Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

Committer:
glebiuskv
Date:
Fri Apr 13 08:53:46 2018 +0000
Revision:
0:2f0e1e23c242
initial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
glebiuskv 0:2f0e1e23c242 1 /*
glebiuskv 0:2f0e1e23c242 2 * X.509 common functions for parsing and verification
glebiuskv 0:2f0e1e23c242 3 *
glebiuskv 0:2f0e1e23c242 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
glebiuskv 0:2f0e1e23c242 5 * SPDX-License-Identifier: Apache-2.0
glebiuskv 0:2f0e1e23c242 6 *
glebiuskv 0:2f0e1e23c242 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
glebiuskv 0:2f0e1e23c242 8 * not use this file except in compliance with the License.
glebiuskv 0:2f0e1e23c242 9 * You may obtain a copy of the License at
glebiuskv 0:2f0e1e23c242 10 *
glebiuskv 0:2f0e1e23c242 11 * http://www.apache.org/licenses/LICENSE-2.0
glebiuskv 0:2f0e1e23c242 12 *
glebiuskv 0:2f0e1e23c242 13 * Unless required by applicable law or agreed to in writing, software
glebiuskv 0:2f0e1e23c242 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
glebiuskv 0:2f0e1e23c242 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
glebiuskv 0:2f0e1e23c242 16 * See the License for the specific language governing permissions and
glebiuskv 0:2f0e1e23c242 17 * limitations under the License.
glebiuskv 0:2f0e1e23c242 18 *
glebiuskv 0:2f0e1e23c242 19 * This file is part of mbed TLS (https://tls.mbed.org)
glebiuskv 0:2f0e1e23c242 20 */
glebiuskv 0:2f0e1e23c242 21 /*
glebiuskv 0:2f0e1e23c242 22 * The ITU-T X.509 standard defines a certificate format for PKI.
glebiuskv 0:2f0e1e23c242 23 *
glebiuskv 0:2f0e1e23c242 24 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
glebiuskv 0:2f0e1e23c242 25 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
glebiuskv 0:2f0e1e23c242 26 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
glebiuskv 0:2f0e1e23c242 27 *
glebiuskv 0:2f0e1e23c242 28 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
glebiuskv 0:2f0e1e23c242 29 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
glebiuskv 0:2f0e1e23c242 30 */
glebiuskv 0:2f0e1e23c242 31
glebiuskv 0:2f0e1e23c242 32 #if !defined(MBEDTLS_CONFIG_FILE)
glebiuskv 0:2f0e1e23c242 33 #include "mbedtls/config.h"
glebiuskv 0:2f0e1e23c242 34 #else
glebiuskv 0:2f0e1e23c242 35 #include MBEDTLS_CONFIG_FILE
glebiuskv 0:2f0e1e23c242 36 #endif
glebiuskv 0:2f0e1e23c242 37
glebiuskv 0:2f0e1e23c242 38 #if defined(MBEDTLS_X509_USE_C)
glebiuskv 0:2f0e1e23c242 39
glebiuskv 0:2f0e1e23c242 40 #include "mbedtls/x509.h"
glebiuskv 0:2f0e1e23c242 41 #include "mbedtls/asn1.h"
glebiuskv 0:2f0e1e23c242 42 #include "mbedtls/oid.h"
glebiuskv 0:2f0e1e23c242 43
glebiuskv 0:2f0e1e23c242 44 #include <stdio.h>
glebiuskv 0:2f0e1e23c242 45 #include <string.h>
glebiuskv 0:2f0e1e23c242 46
glebiuskv 0:2f0e1e23c242 47 #if defined(MBEDTLS_PEM_PARSE_C)
glebiuskv 0:2f0e1e23c242 48 #include "mbedtls/pem.h"
glebiuskv 0:2f0e1e23c242 49 #endif
glebiuskv 0:2f0e1e23c242 50
glebiuskv 0:2f0e1e23c242 51 #if defined(MBEDTLS_PLATFORM_C)
glebiuskv 0:2f0e1e23c242 52 #include "mbedtls/platform.h"
glebiuskv 0:2f0e1e23c242 53 #else
glebiuskv 0:2f0e1e23c242 54 #include <stdio.h>
glebiuskv 0:2f0e1e23c242 55 #include <stdlib.h>
glebiuskv 0:2f0e1e23c242 56 #define mbedtls_free free
glebiuskv 0:2f0e1e23c242 57 #define mbedtls_calloc calloc
glebiuskv 0:2f0e1e23c242 58 #define mbedtls_printf printf
glebiuskv 0:2f0e1e23c242 59 #define mbedtls_snprintf snprintf
glebiuskv 0:2f0e1e23c242 60 #endif
glebiuskv 0:2f0e1e23c242 61
glebiuskv 0:2f0e1e23c242 62
glebiuskv 0:2f0e1e23c242 63 #if defined(MBEDTLS_HAVE_TIME)
glebiuskv 0:2f0e1e23c242 64 #include "mbedtls/platform_time.h"
glebiuskv 0:2f0e1e23c242 65 #endif
glebiuskv 0:2f0e1e23c242 66
glebiuskv 0:2f0e1e23c242 67 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
glebiuskv 0:2f0e1e23c242 68 #include <windows.h>
glebiuskv 0:2f0e1e23c242 69 #else
glebiuskv 0:2f0e1e23c242 70 #include <time.h>
glebiuskv 0:2f0e1e23c242 71 #endif
glebiuskv 0:2f0e1e23c242 72
glebiuskv 0:2f0e1e23c242 73 #if defined(MBEDTLS_FS_IO)
glebiuskv 0:2f0e1e23c242 74 #include <stdio.h>
glebiuskv 0:2f0e1e23c242 75 #if !defined(_WIN32)
glebiuskv 0:2f0e1e23c242 76 #include <sys/types.h>
glebiuskv 0:2f0e1e23c242 77 #include <sys/stat.h>
glebiuskv 0:2f0e1e23c242 78 #include <dirent.h>
glebiuskv 0:2f0e1e23c242 79 #endif
glebiuskv 0:2f0e1e23c242 80 #endif
glebiuskv 0:2f0e1e23c242 81
glebiuskv 0:2f0e1e23c242 82 #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); }
glebiuskv 0:2f0e1e23c242 83 #define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); }
glebiuskv 0:2f0e1e23c242 84
glebiuskv 0:2f0e1e23c242 85 /*
glebiuskv 0:2f0e1e23c242 86 * CertificateSerialNumber ::= INTEGER
glebiuskv 0:2f0e1e23c242 87 */
glebiuskv 0:2f0e1e23c242 88 int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
glebiuskv 0:2f0e1e23c242 89 mbedtls_x509_buf *serial )
glebiuskv 0:2f0e1e23c242 90 {
glebiuskv 0:2f0e1e23c242 91 int ret;
glebiuskv 0:2f0e1e23c242 92
glebiuskv 0:2f0e1e23c242 93 if( ( end - *p ) < 1 )
glebiuskv 0:2f0e1e23c242 94 return( MBEDTLS_ERR_X509_INVALID_SERIAL +
glebiuskv 0:2f0e1e23c242 95 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
glebiuskv 0:2f0e1e23c242 96
glebiuskv 0:2f0e1e23c242 97 if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) &&
glebiuskv 0:2f0e1e23c242 98 **p != MBEDTLS_ASN1_INTEGER )
glebiuskv 0:2f0e1e23c242 99 return( MBEDTLS_ERR_X509_INVALID_SERIAL +
glebiuskv 0:2f0e1e23c242 100 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
glebiuskv 0:2f0e1e23c242 101
glebiuskv 0:2f0e1e23c242 102 serial->tag = *(*p)++;
glebiuskv 0:2f0e1e23c242 103
glebiuskv 0:2f0e1e23c242 104 if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 )
glebiuskv 0:2f0e1e23c242 105 return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret );
glebiuskv 0:2f0e1e23c242 106
glebiuskv 0:2f0e1e23c242 107 serial->p = *p;
glebiuskv 0:2f0e1e23c242 108 *p += serial->len;
glebiuskv 0:2f0e1e23c242 109
glebiuskv 0:2f0e1e23c242 110 return( 0 );
glebiuskv 0:2f0e1e23c242 111 }
glebiuskv 0:2f0e1e23c242 112
glebiuskv 0:2f0e1e23c242 113 /* Get an algorithm identifier without parameters (eg for signatures)
glebiuskv 0:2f0e1e23c242 114 *
glebiuskv 0:2f0e1e23c242 115 * AlgorithmIdentifier ::= SEQUENCE {
glebiuskv 0:2f0e1e23c242 116 * algorithm OBJECT IDENTIFIER,
glebiuskv 0:2f0e1e23c242 117 * parameters ANY DEFINED BY algorithm OPTIONAL }
glebiuskv 0:2f0e1e23c242 118 */
glebiuskv 0:2f0e1e23c242 119 int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
glebiuskv 0:2f0e1e23c242 120 mbedtls_x509_buf *alg )
glebiuskv 0:2f0e1e23c242 121 {
glebiuskv 0:2f0e1e23c242 122 int ret;
glebiuskv 0:2f0e1e23c242 123
glebiuskv 0:2f0e1e23c242 124 if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
glebiuskv 0:2f0e1e23c242 125 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 126
glebiuskv 0:2f0e1e23c242 127 return( 0 );
glebiuskv 0:2f0e1e23c242 128 }
glebiuskv 0:2f0e1e23c242 129
glebiuskv 0:2f0e1e23c242 130 /*
glebiuskv 0:2f0e1e23c242 131 * Parse an algorithm identifier with (optional) paramaters
glebiuskv 0:2f0e1e23c242 132 */
glebiuskv 0:2f0e1e23c242 133 int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
glebiuskv 0:2f0e1e23c242 134 mbedtls_x509_buf *alg, mbedtls_x509_buf *params )
glebiuskv 0:2f0e1e23c242 135 {
glebiuskv 0:2f0e1e23c242 136 int ret;
glebiuskv 0:2f0e1e23c242 137
glebiuskv 0:2f0e1e23c242 138 if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 )
glebiuskv 0:2f0e1e23c242 139 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 140
glebiuskv 0:2f0e1e23c242 141 return( 0 );
glebiuskv 0:2f0e1e23c242 142 }
glebiuskv 0:2f0e1e23c242 143
glebiuskv 0:2f0e1e23c242 144 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
glebiuskv 0:2f0e1e23c242 145 /*
glebiuskv 0:2f0e1e23c242 146 * HashAlgorithm ::= AlgorithmIdentifier
glebiuskv 0:2f0e1e23c242 147 *
glebiuskv 0:2f0e1e23c242 148 * AlgorithmIdentifier ::= SEQUENCE {
glebiuskv 0:2f0e1e23c242 149 * algorithm OBJECT IDENTIFIER,
glebiuskv 0:2f0e1e23c242 150 * parameters ANY DEFINED BY algorithm OPTIONAL }
glebiuskv 0:2f0e1e23c242 151 *
glebiuskv 0:2f0e1e23c242 152 * For HashAlgorithm, parameters MUST be NULL or absent.
glebiuskv 0:2f0e1e23c242 153 */
glebiuskv 0:2f0e1e23c242 154 static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg )
glebiuskv 0:2f0e1e23c242 155 {
glebiuskv 0:2f0e1e23c242 156 int ret;
glebiuskv 0:2f0e1e23c242 157 unsigned char *p;
glebiuskv 0:2f0e1e23c242 158 const unsigned char *end;
glebiuskv 0:2f0e1e23c242 159 mbedtls_x509_buf md_oid;
glebiuskv 0:2f0e1e23c242 160 size_t len;
glebiuskv 0:2f0e1e23c242 161
glebiuskv 0:2f0e1e23c242 162 /* Make sure we got a SEQUENCE and setup bounds */
glebiuskv 0:2f0e1e23c242 163 if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
glebiuskv 0:2f0e1e23c242 164 return( MBEDTLS_ERR_X509_INVALID_ALG +
glebiuskv 0:2f0e1e23c242 165 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
glebiuskv 0:2f0e1e23c242 166
glebiuskv 0:2f0e1e23c242 167 p = (unsigned char *) alg->p;
glebiuskv 0:2f0e1e23c242 168 end = p + alg->len;
glebiuskv 0:2f0e1e23c242 169
glebiuskv 0:2f0e1e23c242 170 if( p >= end )
glebiuskv 0:2f0e1e23c242 171 return( MBEDTLS_ERR_X509_INVALID_ALG +
glebiuskv 0:2f0e1e23c242 172 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
glebiuskv 0:2f0e1e23c242 173
glebiuskv 0:2f0e1e23c242 174 /* Parse md_oid */
glebiuskv 0:2f0e1e23c242 175 md_oid.tag = *p;
glebiuskv 0:2f0e1e23c242 176
glebiuskv 0:2f0e1e23c242 177 if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
glebiuskv 0:2f0e1e23c242 178 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 179
glebiuskv 0:2f0e1e23c242 180 md_oid.p = p;
glebiuskv 0:2f0e1e23c242 181 p += md_oid.len;
glebiuskv 0:2f0e1e23c242 182
glebiuskv 0:2f0e1e23c242 183 /* Get md_alg from md_oid */
glebiuskv 0:2f0e1e23c242 184 if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
glebiuskv 0:2f0e1e23c242 185 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 186
glebiuskv 0:2f0e1e23c242 187 /* Make sure params is absent of NULL */
glebiuskv 0:2f0e1e23c242 188 if( p == end )
glebiuskv 0:2f0e1e23c242 189 return( 0 );
glebiuskv 0:2f0e1e23c242 190
glebiuskv 0:2f0e1e23c242 191 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 )
glebiuskv 0:2f0e1e23c242 192 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 193
glebiuskv 0:2f0e1e23c242 194 if( p != end )
glebiuskv 0:2f0e1e23c242 195 return( MBEDTLS_ERR_X509_INVALID_ALG +
glebiuskv 0:2f0e1e23c242 196 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
glebiuskv 0:2f0e1e23c242 197
glebiuskv 0:2f0e1e23c242 198 return( 0 );
glebiuskv 0:2f0e1e23c242 199 }
glebiuskv 0:2f0e1e23c242 200
glebiuskv 0:2f0e1e23c242 201 /*
glebiuskv 0:2f0e1e23c242 202 * RSASSA-PSS-params ::= SEQUENCE {
glebiuskv 0:2f0e1e23c242 203 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
glebiuskv 0:2f0e1e23c242 204 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
glebiuskv 0:2f0e1e23c242 205 * saltLength [2] INTEGER DEFAULT 20,
glebiuskv 0:2f0e1e23c242 206 * trailerField [3] INTEGER DEFAULT 1 }
glebiuskv 0:2f0e1e23c242 207 * -- Note that the tags in this Sequence are explicit.
glebiuskv 0:2f0e1e23c242 208 *
glebiuskv 0:2f0e1e23c242 209 * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
glebiuskv 0:2f0e1e23c242 210 * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
glebiuskv 0:2f0e1e23c242 211 * option. Enfore this at parsing time.
glebiuskv 0:2f0e1e23c242 212 */
glebiuskv 0:2f0e1e23c242 213 int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
glebiuskv 0:2f0e1e23c242 214 mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
glebiuskv 0:2f0e1e23c242 215 int *salt_len )
glebiuskv 0:2f0e1e23c242 216 {
glebiuskv 0:2f0e1e23c242 217 int ret;
glebiuskv 0:2f0e1e23c242 218 unsigned char *p;
glebiuskv 0:2f0e1e23c242 219 const unsigned char *end, *end2;
glebiuskv 0:2f0e1e23c242 220 size_t len;
glebiuskv 0:2f0e1e23c242 221 mbedtls_x509_buf alg_id, alg_params;
glebiuskv 0:2f0e1e23c242 222
glebiuskv 0:2f0e1e23c242 223 /* First set everything to defaults */
glebiuskv 0:2f0e1e23c242 224 *md_alg = MBEDTLS_MD_SHA1;
glebiuskv 0:2f0e1e23c242 225 *mgf_md = MBEDTLS_MD_SHA1;
glebiuskv 0:2f0e1e23c242 226 *salt_len = 20;
glebiuskv 0:2f0e1e23c242 227
glebiuskv 0:2f0e1e23c242 228 /* Make sure params is a SEQUENCE and setup bounds */
glebiuskv 0:2f0e1e23c242 229 if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
glebiuskv 0:2f0e1e23c242 230 return( MBEDTLS_ERR_X509_INVALID_ALG +
glebiuskv 0:2f0e1e23c242 231 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
glebiuskv 0:2f0e1e23c242 232
glebiuskv 0:2f0e1e23c242 233 p = (unsigned char *) params->p;
glebiuskv 0:2f0e1e23c242 234 end = p + params->len;
glebiuskv 0:2f0e1e23c242 235
glebiuskv 0:2f0e1e23c242 236 if( p == end )
glebiuskv 0:2f0e1e23c242 237 return( 0 );
glebiuskv 0:2f0e1e23c242 238
glebiuskv 0:2f0e1e23c242 239 /*
glebiuskv 0:2f0e1e23c242 240 * HashAlgorithm
glebiuskv 0:2f0e1e23c242 241 */
glebiuskv 0:2f0e1e23c242 242 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
glebiuskv 0:2f0e1e23c242 243 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 )
glebiuskv 0:2f0e1e23c242 244 {
glebiuskv 0:2f0e1e23c242 245 end2 = p + len;
glebiuskv 0:2f0e1e23c242 246
glebiuskv 0:2f0e1e23c242 247 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
glebiuskv 0:2f0e1e23c242 248 if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 )
glebiuskv 0:2f0e1e23c242 249 return( ret );
glebiuskv 0:2f0e1e23c242 250
glebiuskv 0:2f0e1e23c242 251 if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
glebiuskv 0:2f0e1e23c242 252 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 253
glebiuskv 0:2f0e1e23c242 254 if( p != end2 )
glebiuskv 0:2f0e1e23c242 255 return( MBEDTLS_ERR_X509_INVALID_ALG +
glebiuskv 0:2f0e1e23c242 256 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
glebiuskv 0:2f0e1e23c242 257 }
glebiuskv 0:2f0e1e23c242 258 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
glebiuskv 0:2f0e1e23c242 259 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 260
glebiuskv 0:2f0e1e23c242 261 if( p == end )
glebiuskv 0:2f0e1e23c242 262 return( 0 );
glebiuskv 0:2f0e1e23c242 263
glebiuskv 0:2f0e1e23c242 264 /*
glebiuskv 0:2f0e1e23c242 265 * MaskGenAlgorithm
glebiuskv 0:2f0e1e23c242 266 */
glebiuskv 0:2f0e1e23c242 267 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
glebiuskv 0:2f0e1e23c242 268 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 )
glebiuskv 0:2f0e1e23c242 269 {
glebiuskv 0:2f0e1e23c242 270 end2 = p + len;
glebiuskv 0:2f0e1e23c242 271
glebiuskv 0:2f0e1e23c242 272 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
glebiuskv 0:2f0e1e23c242 273 if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 )
glebiuskv 0:2f0e1e23c242 274 return( ret );
glebiuskv 0:2f0e1e23c242 275
glebiuskv 0:2f0e1e23c242 276 /* Only MFG1 is recognised for now */
glebiuskv 0:2f0e1e23c242 277 if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 )
glebiuskv 0:2f0e1e23c242 278 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +
glebiuskv 0:2f0e1e23c242 279 MBEDTLS_ERR_OID_NOT_FOUND );
glebiuskv 0:2f0e1e23c242 280
glebiuskv 0:2f0e1e23c242 281 /* Parse HashAlgorithm */
glebiuskv 0:2f0e1e23c242 282 if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
glebiuskv 0:2f0e1e23c242 283 return( ret );
glebiuskv 0:2f0e1e23c242 284
glebiuskv 0:2f0e1e23c242 285 if( p != end2 )
glebiuskv 0:2f0e1e23c242 286 return( MBEDTLS_ERR_X509_INVALID_ALG +
glebiuskv 0:2f0e1e23c242 287 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
glebiuskv 0:2f0e1e23c242 288 }
glebiuskv 0:2f0e1e23c242 289 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
glebiuskv 0:2f0e1e23c242 290 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 291
glebiuskv 0:2f0e1e23c242 292 if( p == end )
glebiuskv 0:2f0e1e23c242 293 return( 0 );
glebiuskv 0:2f0e1e23c242 294
glebiuskv 0:2f0e1e23c242 295 /*
glebiuskv 0:2f0e1e23c242 296 * salt_len
glebiuskv 0:2f0e1e23c242 297 */
glebiuskv 0:2f0e1e23c242 298 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
glebiuskv 0:2f0e1e23c242 299 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 )
glebiuskv 0:2f0e1e23c242 300 {
glebiuskv 0:2f0e1e23c242 301 end2 = p + len;
glebiuskv 0:2f0e1e23c242 302
glebiuskv 0:2f0e1e23c242 303 if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 )
glebiuskv 0:2f0e1e23c242 304 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 305
glebiuskv 0:2f0e1e23c242 306 if( p != end2 )
glebiuskv 0:2f0e1e23c242 307 return( MBEDTLS_ERR_X509_INVALID_ALG +
glebiuskv 0:2f0e1e23c242 308 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
glebiuskv 0:2f0e1e23c242 309 }
glebiuskv 0:2f0e1e23c242 310 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
glebiuskv 0:2f0e1e23c242 311 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 312
glebiuskv 0:2f0e1e23c242 313 if( p == end )
glebiuskv 0:2f0e1e23c242 314 return( 0 );
glebiuskv 0:2f0e1e23c242 315
glebiuskv 0:2f0e1e23c242 316 /*
glebiuskv 0:2f0e1e23c242 317 * trailer_field (if present, must be 1)
glebiuskv 0:2f0e1e23c242 318 */
glebiuskv 0:2f0e1e23c242 319 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
glebiuskv 0:2f0e1e23c242 320 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 )
glebiuskv 0:2f0e1e23c242 321 {
glebiuskv 0:2f0e1e23c242 322 int trailer_field;
glebiuskv 0:2f0e1e23c242 323
glebiuskv 0:2f0e1e23c242 324 end2 = p + len;
glebiuskv 0:2f0e1e23c242 325
glebiuskv 0:2f0e1e23c242 326 if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 )
glebiuskv 0:2f0e1e23c242 327 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 328
glebiuskv 0:2f0e1e23c242 329 if( p != end2 )
glebiuskv 0:2f0e1e23c242 330 return( MBEDTLS_ERR_X509_INVALID_ALG +
glebiuskv 0:2f0e1e23c242 331 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
glebiuskv 0:2f0e1e23c242 332
glebiuskv 0:2f0e1e23c242 333 if( trailer_field != 1 )
glebiuskv 0:2f0e1e23c242 334 return( MBEDTLS_ERR_X509_INVALID_ALG );
glebiuskv 0:2f0e1e23c242 335 }
glebiuskv 0:2f0e1e23c242 336 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
glebiuskv 0:2f0e1e23c242 337 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
glebiuskv 0:2f0e1e23c242 338
glebiuskv 0:2f0e1e23c242 339 if( p != end )
glebiuskv 0:2f0e1e23c242 340 return( MBEDTLS_ERR_X509_INVALID_ALG +
glebiuskv 0:2f0e1e23c242 341 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
glebiuskv 0:2f0e1e23c242 342
glebiuskv 0:2f0e1e23c242 343 return( 0 );
glebiuskv 0:2f0e1e23c242 344 }
glebiuskv 0:2f0e1e23c242 345 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
glebiuskv 0:2f0e1e23c242 346
glebiuskv 0:2f0e1e23c242 347 /*
glebiuskv 0:2f0e1e23c242 348 * AttributeTypeAndValue ::= SEQUENCE {
glebiuskv 0:2f0e1e23c242 349 * type AttributeType,
glebiuskv 0:2f0e1e23c242 350 * value AttributeValue }
glebiuskv 0:2f0e1e23c242 351 *
glebiuskv 0:2f0e1e23c242 352 * AttributeType ::= OBJECT IDENTIFIER
glebiuskv 0:2f0e1e23c242 353 *
glebiuskv 0:2f0e1e23c242 354 * AttributeValue ::= ANY DEFINED BY AttributeType
glebiuskv 0:2f0e1e23c242 355 */
glebiuskv 0:2f0e1e23c242 356 static int x509_get_attr_type_value( unsigned char **p,
glebiuskv 0:2f0e1e23c242 357 const unsigned char *end,
glebiuskv 0:2f0e1e23c242 358 mbedtls_x509_name *cur )
glebiuskv 0:2f0e1e23c242 359 {
glebiuskv 0:2f0e1e23c242 360 int ret;
glebiuskv 0:2f0e1e23c242 361 size_t len;
glebiuskv 0:2f0e1e23c242 362 mbedtls_x509_buf *oid;
glebiuskv 0:2f0e1e23c242 363 mbedtls_x509_buf *val;
glebiuskv 0:2f0e1e23c242 364
glebiuskv 0:2f0e1e23c242 365 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
glebiuskv 0:2f0e1e23c242 366 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
glebiuskv 0:2f0e1e23c242 367 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
glebiuskv 0:2f0e1e23c242 368
glebiuskv 0:2f0e1e23c242 369 if( ( end - *p ) < 1 )
glebiuskv 0:2f0e1e23c242 370 return( MBEDTLS_ERR_X509_INVALID_NAME +
glebiuskv 0:2f0e1e23c242 371 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
glebiuskv 0:2f0e1e23c242 372
glebiuskv 0:2f0e1e23c242 373 oid = &cur->oid;
glebiuskv 0:2f0e1e23c242 374 oid->tag = **p;
glebiuskv 0:2f0e1e23c242 375
glebiuskv 0:2f0e1e23c242 376 if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 )
glebiuskv 0:2f0e1e23c242 377 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
glebiuskv 0:2f0e1e23c242 378
glebiuskv 0:2f0e1e23c242 379 oid->p = *p;
glebiuskv 0:2f0e1e23c242 380 *p += oid->len;
glebiuskv 0:2f0e1e23c242 381
glebiuskv 0:2f0e1e23c242 382 if( ( end - *p ) < 1 )
glebiuskv 0:2f0e1e23c242 383 return( MBEDTLS_ERR_X509_INVALID_NAME +
glebiuskv 0:2f0e1e23c242 384 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
glebiuskv 0:2f0e1e23c242 385
glebiuskv 0:2f0e1e23c242 386 if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING &&
glebiuskv 0:2f0e1e23c242 387 **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
glebiuskv 0:2f0e1e23c242 388 **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
glebiuskv 0:2f0e1e23c242 389 **p != MBEDTLS_ASN1_BIT_STRING )
glebiuskv 0:2f0e1e23c242 390 return( MBEDTLS_ERR_X509_INVALID_NAME +
glebiuskv 0:2f0e1e23c242 391 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
glebiuskv 0:2f0e1e23c242 392
glebiuskv 0:2f0e1e23c242 393 val = &cur->val;
glebiuskv 0:2f0e1e23c242 394 val->tag = *(*p)++;
glebiuskv 0:2f0e1e23c242 395
glebiuskv 0:2f0e1e23c242 396 if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 )
glebiuskv 0:2f0e1e23c242 397 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
glebiuskv 0:2f0e1e23c242 398
glebiuskv 0:2f0e1e23c242 399 val->p = *p;
glebiuskv 0:2f0e1e23c242 400 *p += val->len;
glebiuskv 0:2f0e1e23c242 401
glebiuskv 0:2f0e1e23c242 402 cur->next = NULL;
glebiuskv 0:2f0e1e23c242 403
glebiuskv 0:2f0e1e23c242 404 return( 0 );
glebiuskv 0:2f0e1e23c242 405 }
glebiuskv 0:2f0e1e23c242 406
glebiuskv 0:2f0e1e23c242 407 /*
glebiuskv 0:2f0e1e23c242 408 * Name ::= CHOICE { -- only one possibility for now --
glebiuskv 0:2f0e1e23c242 409 * rdnSequence RDNSequence }
glebiuskv 0:2f0e1e23c242 410 *
glebiuskv 0:2f0e1e23c242 411 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
glebiuskv 0:2f0e1e23c242 412 *
glebiuskv 0:2f0e1e23c242 413 * RelativeDistinguishedName ::=
glebiuskv 0:2f0e1e23c242 414 * SET OF AttributeTypeAndValue
glebiuskv 0:2f0e1e23c242 415 *
glebiuskv 0:2f0e1e23c242 416 * AttributeTypeAndValue ::= SEQUENCE {
glebiuskv 0:2f0e1e23c242 417 * type AttributeType,
glebiuskv 0:2f0e1e23c242 418 * value AttributeValue }
glebiuskv 0:2f0e1e23c242 419 *
glebiuskv 0:2f0e1e23c242 420 * AttributeType ::= OBJECT IDENTIFIER
glebiuskv 0:2f0e1e23c242 421 *
glebiuskv 0:2f0e1e23c242 422 * AttributeValue ::= ANY DEFINED BY AttributeType
glebiuskv 0:2f0e1e23c242 423 *
glebiuskv 0:2f0e1e23c242 424 * The data structure is optimized for the common case where each RDN has only
glebiuskv 0:2f0e1e23c242 425 * one element, which is represented as a list of AttributeTypeAndValue.
glebiuskv 0:2f0e1e23c242 426 * For the general case we still use a flat list, but we mark elements of the
glebiuskv 0:2f0e1e23c242 427 * same set so that they are "merged" together in the functions that consume
glebiuskv 0:2f0e1e23c242 428 * this list, eg mbedtls_x509_dn_gets().
glebiuskv 0:2f0e1e23c242 429 */
glebiuskv 0:2f0e1e23c242 430 int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
glebiuskv 0:2f0e1e23c242 431 mbedtls_x509_name *cur )
glebiuskv 0:2f0e1e23c242 432 {
glebiuskv 0:2f0e1e23c242 433 int ret;
glebiuskv 0:2f0e1e23c242 434 size_t set_len;
glebiuskv 0:2f0e1e23c242 435 const unsigned char *end_set;
glebiuskv 0:2f0e1e23c242 436
glebiuskv 0:2f0e1e23c242 437 /* don't use recursion, we'd risk stack overflow if not optimized */
glebiuskv 0:2f0e1e23c242 438 while( 1 )
glebiuskv 0:2f0e1e23c242 439 {
glebiuskv 0:2f0e1e23c242 440 /*
glebiuskv 0:2f0e1e23c242 441 * parse SET
glebiuskv 0:2f0e1e23c242 442 */
glebiuskv 0:2f0e1e23c242 443 if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len,
glebiuskv 0:2f0e1e23c242 444 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 )
glebiuskv 0:2f0e1e23c242 445 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
glebiuskv 0:2f0e1e23c242 446
glebiuskv 0:2f0e1e23c242 447 end_set = *p + set_len;
glebiuskv 0:2f0e1e23c242 448
glebiuskv 0:2f0e1e23c242 449 while( 1 )
glebiuskv 0:2f0e1e23c242 450 {
glebiuskv 0:2f0e1e23c242 451 if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
glebiuskv 0:2f0e1e23c242 452 return( ret );
glebiuskv 0:2f0e1e23c242 453
glebiuskv 0:2f0e1e23c242 454 if( *p == end_set )
glebiuskv 0:2f0e1e23c242 455 break;
glebiuskv 0:2f0e1e23c242 456
glebiuskv 0:2f0e1e23c242 457 /* Mark this item as being no the only one in a set */
glebiuskv 0:2f0e1e23c242 458 cur->next_merged = 1;
glebiuskv 0:2f0e1e23c242 459
glebiuskv 0:2f0e1e23c242 460 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
glebiuskv 0:2f0e1e23c242 461
glebiuskv 0:2f0e1e23c242 462 if( cur->next == NULL )
glebiuskv 0:2f0e1e23c242 463 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
glebiuskv 0:2f0e1e23c242 464
glebiuskv 0:2f0e1e23c242 465 cur = cur->next;
glebiuskv 0:2f0e1e23c242 466 }
glebiuskv 0:2f0e1e23c242 467
glebiuskv 0:2f0e1e23c242 468 /*
glebiuskv 0:2f0e1e23c242 469 * continue until end of SEQUENCE is reached
glebiuskv 0:2f0e1e23c242 470 */
glebiuskv 0:2f0e1e23c242 471 if( *p == end )
glebiuskv 0:2f0e1e23c242 472 return( 0 );
glebiuskv 0:2f0e1e23c242 473
glebiuskv 0:2f0e1e23c242 474 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
glebiuskv 0:2f0e1e23c242 475
glebiuskv 0:2f0e1e23c242 476 if( cur->next == NULL )
glebiuskv 0:2f0e1e23c242 477 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
glebiuskv 0:2f0e1e23c242 478
glebiuskv 0:2f0e1e23c242 479 cur = cur->next;
glebiuskv 0:2f0e1e23c242 480 }
glebiuskv 0:2f0e1e23c242 481 }
glebiuskv 0:2f0e1e23c242 482
glebiuskv 0:2f0e1e23c242 483 static int x509_parse_int( unsigned char **p, size_t n, int *res )
glebiuskv 0:2f0e1e23c242 484 {
glebiuskv 0:2f0e1e23c242 485 *res = 0;
glebiuskv 0:2f0e1e23c242 486
glebiuskv 0:2f0e1e23c242 487 for( ; n > 0; --n )
glebiuskv 0:2f0e1e23c242 488 {
glebiuskv 0:2f0e1e23c242 489 if( ( **p < '0') || ( **p > '9' ) )
glebiuskv 0:2f0e1e23c242 490 return ( MBEDTLS_ERR_X509_INVALID_DATE );
glebiuskv 0:2f0e1e23c242 491
glebiuskv 0:2f0e1e23c242 492 *res *= 10;
glebiuskv 0:2f0e1e23c242 493 *res += ( *(*p)++ - '0' );
glebiuskv 0:2f0e1e23c242 494 }
glebiuskv 0:2f0e1e23c242 495
glebiuskv 0:2f0e1e23c242 496 return( 0 );
glebiuskv 0:2f0e1e23c242 497 }
glebiuskv 0:2f0e1e23c242 498
glebiuskv 0:2f0e1e23c242 499 static int x509_date_is_valid(const mbedtls_x509_time *t )
glebiuskv 0:2f0e1e23c242 500 {
glebiuskv 0:2f0e1e23c242 501 int ret = MBEDTLS_ERR_X509_INVALID_DATE;
glebiuskv 0:2f0e1e23c242 502 int month_len;
glebiuskv 0:2f0e1e23c242 503
glebiuskv 0:2f0e1e23c242 504 CHECK_RANGE( 0, 9999, t->year );
glebiuskv 0:2f0e1e23c242 505 CHECK_RANGE( 0, 23, t->hour );
glebiuskv 0:2f0e1e23c242 506 CHECK_RANGE( 0, 59, t->min );
glebiuskv 0:2f0e1e23c242 507 CHECK_RANGE( 0, 59, t->sec );
glebiuskv 0:2f0e1e23c242 508
glebiuskv 0:2f0e1e23c242 509 switch( t->mon )
glebiuskv 0:2f0e1e23c242 510 {
glebiuskv 0:2f0e1e23c242 511 case 1: case 3: case 5: case 7: case 8: case 10: case 12:
glebiuskv 0:2f0e1e23c242 512 month_len = 31;
glebiuskv 0:2f0e1e23c242 513 break;
glebiuskv 0:2f0e1e23c242 514 case 4: case 6: case 9: case 11:
glebiuskv 0:2f0e1e23c242 515 month_len = 30;
glebiuskv 0:2f0e1e23c242 516 break;
glebiuskv 0:2f0e1e23c242 517 case 2:
glebiuskv 0:2f0e1e23c242 518 if( ( !( t->year % 4 ) && t->year % 100 ) ||
glebiuskv 0:2f0e1e23c242 519 !( t->year % 400 ) )
glebiuskv 0:2f0e1e23c242 520 month_len = 29;
glebiuskv 0:2f0e1e23c242 521 else
glebiuskv 0:2f0e1e23c242 522 month_len = 28;
glebiuskv 0:2f0e1e23c242 523 break;
glebiuskv 0:2f0e1e23c242 524 default:
glebiuskv 0:2f0e1e23c242 525 return( ret );
glebiuskv 0:2f0e1e23c242 526 }
glebiuskv 0:2f0e1e23c242 527 CHECK_RANGE( 1, month_len, t->day );
glebiuskv 0:2f0e1e23c242 528
glebiuskv 0:2f0e1e23c242 529 return( 0 );
glebiuskv 0:2f0e1e23c242 530 }
glebiuskv 0:2f0e1e23c242 531
glebiuskv 0:2f0e1e23c242 532 /*
glebiuskv 0:2f0e1e23c242 533 * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
glebiuskv 0:2f0e1e23c242 534 * field.
glebiuskv 0:2f0e1e23c242 535 */
glebiuskv 0:2f0e1e23c242 536 static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen,
glebiuskv 0:2f0e1e23c242 537 mbedtls_x509_time *tm )
glebiuskv 0:2f0e1e23c242 538 {
glebiuskv 0:2f0e1e23c242 539 int ret;
glebiuskv 0:2f0e1e23c242 540
glebiuskv 0:2f0e1e23c242 541 /*
glebiuskv 0:2f0e1e23c242 542 * Minimum length is 10 or 12 depending on yearlen
glebiuskv 0:2f0e1e23c242 543 */
glebiuskv 0:2f0e1e23c242 544 if ( len < yearlen + 8 )
glebiuskv 0:2f0e1e23c242 545 return ( MBEDTLS_ERR_X509_INVALID_DATE );
glebiuskv 0:2f0e1e23c242 546 len -= yearlen + 8;
glebiuskv 0:2f0e1e23c242 547
glebiuskv 0:2f0e1e23c242 548 /*
glebiuskv 0:2f0e1e23c242 549 * Parse year, month, day, hour, minute
glebiuskv 0:2f0e1e23c242 550 */
glebiuskv 0:2f0e1e23c242 551 CHECK( x509_parse_int( p, yearlen, &tm->year ) );
glebiuskv 0:2f0e1e23c242 552 if ( 2 == yearlen )
glebiuskv 0:2f0e1e23c242 553 {
glebiuskv 0:2f0e1e23c242 554 if ( tm->year < 50 )
glebiuskv 0:2f0e1e23c242 555 tm->year += 100;
glebiuskv 0:2f0e1e23c242 556
glebiuskv 0:2f0e1e23c242 557 tm->year += 1900;
glebiuskv 0:2f0e1e23c242 558 }
glebiuskv 0:2f0e1e23c242 559
glebiuskv 0:2f0e1e23c242 560 CHECK( x509_parse_int( p, 2, &tm->mon ) );
glebiuskv 0:2f0e1e23c242 561 CHECK( x509_parse_int( p, 2, &tm->day ) );
glebiuskv 0:2f0e1e23c242 562 CHECK( x509_parse_int( p, 2, &tm->hour ) );
glebiuskv 0:2f0e1e23c242 563 CHECK( x509_parse_int( p, 2, &tm->min ) );
glebiuskv 0:2f0e1e23c242 564
glebiuskv 0:2f0e1e23c242 565 /*
glebiuskv 0:2f0e1e23c242 566 * Parse seconds if present
glebiuskv 0:2f0e1e23c242 567 */
glebiuskv 0:2f0e1e23c242 568 if ( len >= 2 )
glebiuskv 0:2f0e1e23c242 569 {
glebiuskv 0:2f0e1e23c242 570 CHECK( x509_parse_int( p, 2, &tm->sec ) );
glebiuskv 0:2f0e1e23c242 571 len -= 2;
glebiuskv 0:2f0e1e23c242 572 }
glebiuskv 0:2f0e1e23c242 573 else
glebiuskv 0:2f0e1e23c242 574 return ( MBEDTLS_ERR_X509_INVALID_DATE );
glebiuskv 0:2f0e1e23c242 575
glebiuskv 0:2f0e1e23c242 576 /*
glebiuskv 0:2f0e1e23c242 577 * Parse trailing 'Z' if present
glebiuskv 0:2f0e1e23c242 578 */
glebiuskv 0:2f0e1e23c242 579 if ( 1 == len && 'Z' == **p )
glebiuskv 0:2f0e1e23c242 580 {
glebiuskv 0:2f0e1e23c242 581 (*p)++;
glebiuskv 0:2f0e1e23c242 582 len--;
glebiuskv 0:2f0e1e23c242 583 }
glebiuskv 0:2f0e1e23c242 584
glebiuskv 0:2f0e1e23c242 585 /*
glebiuskv 0:2f0e1e23c242 586 * We should have parsed all characters at this point
glebiuskv 0:2f0e1e23c242 587 */
glebiuskv 0:2f0e1e23c242 588 if ( 0 != len )
glebiuskv 0:2f0e1e23c242 589 return ( MBEDTLS_ERR_X509_INVALID_DATE );
glebiuskv 0:2f0e1e23c242 590
glebiuskv 0:2f0e1e23c242 591 CHECK( x509_date_is_valid( tm ) );
glebiuskv 0:2f0e1e23c242 592
glebiuskv 0:2f0e1e23c242 593 return ( 0 );
glebiuskv 0:2f0e1e23c242 594 }
glebiuskv 0:2f0e1e23c242 595
glebiuskv 0:2f0e1e23c242 596 /*
glebiuskv 0:2f0e1e23c242 597 * Time ::= CHOICE {
glebiuskv 0:2f0e1e23c242 598 * utcTime UTCTime,
glebiuskv 0:2f0e1e23c242 599 * generalTime GeneralizedTime }
glebiuskv 0:2f0e1e23c242 600 */
glebiuskv 0:2f0e1e23c242 601 int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
glebiuskv 0:2f0e1e23c242 602 mbedtls_x509_time *tm )
glebiuskv 0:2f0e1e23c242 603 {
glebiuskv 0:2f0e1e23c242 604 int ret;
glebiuskv 0:2f0e1e23c242 605 size_t len, year_len;
glebiuskv 0:2f0e1e23c242 606 unsigned char tag;
glebiuskv 0:2f0e1e23c242 607
glebiuskv 0:2f0e1e23c242 608 if( ( end - *p ) < 1 )
glebiuskv 0:2f0e1e23c242 609 return( MBEDTLS_ERR_X509_INVALID_DATE +
glebiuskv 0:2f0e1e23c242 610 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
glebiuskv 0:2f0e1e23c242 611
glebiuskv 0:2f0e1e23c242 612 tag = **p;
glebiuskv 0:2f0e1e23c242 613
glebiuskv 0:2f0e1e23c242 614 if( tag == MBEDTLS_ASN1_UTC_TIME )
glebiuskv 0:2f0e1e23c242 615 year_len = 2;
glebiuskv 0:2f0e1e23c242 616 else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME )
glebiuskv 0:2f0e1e23c242 617 year_len = 4;
glebiuskv 0:2f0e1e23c242 618 else
glebiuskv 0:2f0e1e23c242 619 return( MBEDTLS_ERR_X509_INVALID_DATE +
glebiuskv 0:2f0e1e23c242 620 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
glebiuskv 0:2f0e1e23c242 621
glebiuskv 0:2f0e1e23c242 622 (*p)++;
glebiuskv 0:2f0e1e23c242 623 ret = mbedtls_asn1_get_len( p, end, &len );
glebiuskv 0:2f0e1e23c242 624
glebiuskv 0:2f0e1e23c242 625 if( ret != 0 )
glebiuskv 0:2f0e1e23c242 626 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
glebiuskv 0:2f0e1e23c242 627
glebiuskv 0:2f0e1e23c242 628 return x509_parse_time( p, len, year_len, tm );
glebiuskv 0:2f0e1e23c242 629 }
glebiuskv 0:2f0e1e23c242 630
glebiuskv 0:2f0e1e23c242 631 int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig )
glebiuskv 0:2f0e1e23c242 632 {
glebiuskv 0:2f0e1e23c242 633 int ret;
glebiuskv 0:2f0e1e23c242 634 size_t len;
glebiuskv 0:2f0e1e23c242 635 int tag_type;
glebiuskv 0:2f0e1e23c242 636
glebiuskv 0:2f0e1e23c242 637 if( ( end - *p ) < 1 )
glebiuskv 0:2f0e1e23c242 638 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE +
glebiuskv 0:2f0e1e23c242 639 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
glebiuskv 0:2f0e1e23c242 640
glebiuskv 0:2f0e1e23c242 641 tag_type = **p;
glebiuskv 0:2f0e1e23c242 642
glebiuskv 0:2f0e1e23c242 643 if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
glebiuskv 0:2f0e1e23c242 644 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret );
glebiuskv 0:2f0e1e23c242 645
glebiuskv 0:2f0e1e23c242 646 sig->tag = tag_type;
glebiuskv 0:2f0e1e23c242 647 sig->len = len;
glebiuskv 0:2f0e1e23c242 648 sig->p = *p;
glebiuskv 0:2f0e1e23c242 649
glebiuskv 0:2f0e1e23c242 650 *p += len;
glebiuskv 0:2f0e1e23c242 651
glebiuskv 0:2f0e1e23c242 652 return( 0 );
glebiuskv 0:2f0e1e23c242 653 }
glebiuskv 0:2f0e1e23c242 654
glebiuskv 0:2f0e1e23c242 655 /*
glebiuskv 0:2f0e1e23c242 656 * Get signature algorithm from alg OID and optional parameters
glebiuskv 0:2f0e1e23c242 657 */
glebiuskv 0:2f0e1e23c242 658 int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
glebiuskv 0:2f0e1e23c242 659 mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
glebiuskv 0:2f0e1e23c242 660 void **sig_opts )
glebiuskv 0:2f0e1e23c242 661 {
glebiuskv 0:2f0e1e23c242 662 int ret;
glebiuskv 0:2f0e1e23c242 663
glebiuskv 0:2f0e1e23c242 664 if( *sig_opts != NULL )
glebiuskv 0:2f0e1e23c242 665 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
glebiuskv 0:2f0e1e23c242 666
glebiuskv 0:2f0e1e23c242 667 if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 )
glebiuskv 0:2f0e1e23c242 668 return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret );
glebiuskv 0:2f0e1e23c242 669
glebiuskv 0:2f0e1e23c242 670 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
glebiuskv 0:2f0e1e23c242 671 if( *pk_alg == MBEDTLS_PK_RSASSA_PSS )
glebiuskv 0:2f0e1e23c242 672 {
glebiuskv 0:2f0e1e23c242 673 mbedtls_pk_rsassa_pss_options *pss_opts;
glebiuskv 0:2f0e1e23c242 674
glebiuskv 0:2f0e1e23c242 675 pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) );
glebiuskv 0:2f0e1e23c242 676 if( pss_opts == NULL )
glebiuskv 0:2f0e1e23c242 677 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
glebiuskv 0:2f0e1e23c242 678
glebiuskv 0:2f0e1e23c242 679 ret = mbedtls_x509_get_rsassa_pss_params( sig_params,
glebiuskv 0:2f0e1e23c242 680 md_alg,
glebiuskv 0:2f0e1e23c242 681 &pss_opts->mgf1_hash_id,
glebiuskv 0:2f0e1e23c242 682 &pss_opts->expected_salt_len );
glebiuskv 0:2f0e1e23c242 683 if( ret != 0 )
glebiuskv 0:2f0e1e23c242 684 {
glebiuskv 0:2f0e1e23c242 685 mbedtls_free( pss_opts );
glebiuskv 0:2f0e1e23c242 686 return( ret );
glebiuskv 0:2f0e1e23c242 687 }
glebiuskv 0:2f0e1e23c242 688
glebiuskv 0:2f0e1e23c242 689 *sig_opts = (void *) pss_opts;
glebiuskv 0:2f0e1e23c242 690 }
glebiuskv 0:2f0e1e23c242 691 else
glebiuskv 0:2f0e1e23c242 692 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
glebiuskv 0:2f0e1e23c242 693 {
glebiuskv 0:2f0e1e23c242 694 /* Make sure parameters are absent or NULL */
glebiuskv 0:2f0e1e23c242 695 if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) ||
glebiuskv 0:2f0e1e23c242 696 sig_params->len != 0 )
glebiuskv 0:2f0e1e23c242 697 return( MBEDTLS_ERR_X509_INVALID_ALG );
glebiuskv 0:2f0e1e23c242 698 }
glebiuskv 0:2f0e1e23c242 699
glebiuskv 0:2f0e1e23c242 700 return( 0 );
glebiuskv 0:2f0e1e23c242 701 }
glebiuskv 0:2f0e1e23c242 702
glebiuskv 0:2f0e1e23c242 703 /*
glebiuskv 0:2f0e1e23c242 704 * X.509 Extensions (No parsing of extensions, pointer should
glebiuskv 0:2f0e1e23c242 705 * be either manually updated or extensions should be parsed!)
glebiuskv 0:2f0e1e23c242 706 */
glebiuskv 0:2f0e1e23c242 707 int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
glebiuskv 0:2f0e1e23c242 708 mbedtls_x509_buf *ext, int tag )
glebiuskv 0:2f0e1e23c242 709 {
glebiuskv 0:2f0e1e23c242 710 int ret;
glebiuskv 0:2f0e1e23c242 711 size_t len;
glebiuskv 0:2f0e1e23c242 712
glebiuskv 0:2f0e1e23c242 713 if( *p == end )
glebiuskv 0:2f0e1e23c242 714 return( 0 );
glebiuskv 0:2f0e1e23c242 715
glebiuskv 0:2f0e1e23c242 716 ext->tag = **p;
glebiuskv 0:2f0e1e23c242 717
glebiuskv 0:2f0e1e23c242 718 if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len,
glebiuskv 0:2f0e1e23c242 719 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 )
glebiuskv 0:2f0e1e23c242 720 return( ret );
glebiuskv 0:2f0e1e23c242 721
glebiuskv 0:2f0e1e23c242 722 ext->p = *p;
glebiuskv 0:2f0e1e23c242 723 end = *p + ext->len;
glebiuskv 0:2f0e1e23c242 724
glebiuskv 0:2f0e1e23c242 725 /*
glebiuskv 0:2f0e1e23c242 726 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
glebiuskv 0:2f0e1e23c242 727 *
glebiuskv 0:2f0e1e23c242 728 * Extension ::= SEQUENCE {
glebiuskv 0:2f0e1e23c242 729 * extnID OBJECT IDENTIFIER,
glebiuskv 0:2f0e1e23c242 730 * critical BOOLEAN DEFAULT FALSE,
glebiuskv 0:2f0e1e23c242 731 * extnValue OCTET STRING }
glebiuskv 0:2f0e1e23c242 732 */
glebiuskv 0:2f0e1e23c242 733 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
glebiuskv 0:2f0e1e23c242 734 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
glebiuskv 0:2f0e1e23c242 735 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
glebiuskv 0:2f0e1e23c242 736
glebiuskv 0:2f0e1e23c242 737 if( end != *p + len )
glebiuskv 0:2f0e1e23c242 738 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
glebiuskv 0:2f0e1e23c242 739 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
glebiuskv 0:2f0e1e23c242 740
glebiuskv 0:2f0e1e23c242 741 return( 0 );
glebiuskv 0:2f0e1e23c242 742 }
glebiuskv 0:2f0e1e23c242 743
glebiuskv 0:2f0e1e23c242 744 /*
glebiuskv 0:2f0e1e23c242 745 * Store the name in printable form into buf; no more
glebiuskv 0:2f0e1e23c242 746 * than size characters will be written
glebiuskv 0:2f0e1e23c242 747 */
glebiuskv 0:2f0e1e23c242 748 int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
glebiuskv 0:2f0e1e23c242 749 {
glebiuskv 0:2f0e1e23c242 750 int ret;
glebiuskv 0:2f0e1e23c242 751 size_t i, n;
glebiuskv 0:2f0e1e23c242 752 unsigned char c, merge = 0;
glebiuskv 0:2f0e1e23c242 753 const mbedtls_x509_name *name;
glebiuskv 0:2f0e1e23c242 754 const char *short_name = NULL;
glebiuskv 0:2f0e1e23c242 755 char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
glebiuskv 0:2f0e1e23c242 756
glebiuskv 0:2f0e1e23c242 757 memset( s, 0, sizeof( s ) );
glebiuskv 0:2f0e1e23c242 758
glebiuskv 0:2f0e1e23c242 759 name = dn;
glebiuskv 0:2f0e1e23c242 760 p = buf;
glebiuskv 0:2f0e1e23c242 761 n = size;
glebiuskv 0:2f0e1e23c242 762
glebiuskv 0:2f0e1e23c242 763 while( name != NULL )
glebiuskv 0:2f0e1e23c242 764 {
glebiuskv 0:2f0e1e23c242 765 if( !name->oid.p )
glebiuskv 0:2f0e1e23c242 766 {
glebiuskv 0:2f0e1e23c242 767 name = name->next;
glebiuskv 0:2f0e1e23c242 768 continue;
glebiuskv 0:2f0e1e23c242 769 }
glebiuskv 0:2f0e1e23c242 770
glebiuskv 0:2f0e1e23c242 771 if( name != dn )
glebiuskv 0:2f0e1e23c242 772 {
glebiuskv 0:2f0e1e23c242 773 ret = mbedtls_snprintf( p, n, merge ? " + " : ", " );
glebiuskv 0:2f0e1e23c242 774 MBEDTLS_X509_SAFE_SNPRINTF;
glebiuskv 0:2f0e1e23c242 775 }
glebiuskv 0:2f0e1e23c242 776
glebiuskv 0:2f0e1e23c242 777 ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name );
glebiuskv 0:2f0e1e23c242 778
glebiuskv 0:2f0e1e23c242 779 if( ret == 0 )
glebiuskv 0:2f0e1e23c242 780 ret = mbedtls_snprintf( p, n, "%s=", short_name );
glebiuskv 0:2f0e1e23c242 781 else
glebiuskv 0:2f0e1e23c242 782 ret = mbedtls_snprintf( p, n, "\?\?=" );
glebiuskv 0:2f0e1e23c242 783 MBEDTLS_X509_SAFE_SNPRINTF;
glebiuskv 0:2f0e1e23c242 784
glebiuskv 0:2f0e1e23c242 785 for( i = 0; i < name->val.len; i++ )
glebiuskv 0:2f0e1e23c242 786 {
glebiuskv 0:2f0e1e23c242 787 if( i >= sizeof( s ) - 1 )
glebiuskv 0:2f0e1e23c242 788 break;
glebiuskv 0:2f0e1e23c242 789
glebiuskv 0:2f0e1e23c242 790 c = name->val.p[i];
glebiuskv 0:2f0e1e23c242 791 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
glebiuskv 0:2f0e1e23c242 792 s[i] = '?';
glebiuskv 0:2f0e1e23c242 793 else s[i] = c;
glebiuskv 0:2f0e1e23c242 794 }
glebiuskv 0:2f0e1e23c242 795 s[i] = '\0';
glebiuskv 0:2f0e1e23c242 796 ret = mbedtls_snprintf( p, n, "%s", s );
glebiuskv 0:2f0e1e23c242 797 MBEDTLS_X509_SAFE_SNPRINTF;
glebiuskv 0:2f0e1e23c242 798
glebiuskv 0:2f0e1e23c242 799 merge = name->next_merged;
glebiuskv 0:2f0e1e23c242 800 name = name->next;
glebiuskv 0:2f0e1e23c242 801 }
glebiuskv 0:2f0e1e23c242 802
glebiuskv 0:2f0e1e23c242 803 return( (int) ( size - n ) );
glebiuskv 0:2f0e1e23c242 804 }
glebiuskv 0:2f0e1e23c242 805
glebiuskv 0:2f0e1e23c242 806 /*
glebiuskv 0:2f0e1e23c242 807 * Store the serial in printable form into buf; no more
glebiuskv 0:2f0e1e23c242 808 * than size characters will be written
glebiuskv 0:2f0e1e23c242 809 */
glebiuskv 0:2f0e1e23c242 810 int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial )
glebiuskv 0:2f0e1e23c242 811 {
glebiuskv 0:2f0e1e23c242 812 int ret;
glebiuskv 0:2f0e1e23c242 813 size_t i, n, nr;
glebiuskv 0:2f0e1e23c242 814 char *p;
glebiuskv 0:2f0e1e23c242 815
glebiuskv 0:2f0e1e23c242 816 p = buf;
glebiuskv 0:2f0e1e23c242 817 n = size;
glebiuskv 0:2f0e1e23c242 818
glebiuskv 0:2f0e1e23c242 819 nr = ( serial->len <= 32 )
glebiuskv 0:2f0e1e23c242 820 ? serial->len : 28;
glebiuskv 0:2f0e1e23c242 821
glebiuskv 0:2f0e1e23c242 822 for( i = 0; i < nr; i++ )
glebiuskv 0:2f0e1e23c242 823 {
glebiuskv 0:2f0e1e23c242 824 if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
glebiuskv 0:2f0e1e23c242 825 continue;
glebiuskv 0:2f0e1e23c242 826
glebiuskv 0:2f0e1e23c242 827 ret = mbedtls_snprintf( p, n, "%02X%s",
glebiuskv 0:2f0e1e23c242 828 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
glebiuskv 0:2f0e1e23c242 829 MBEDTLS_X509_SAFE_SNPRINTF;
glebiuskv 0:2f0e1e23c242 830 }
glebiuskv 0:2f0e1e23c242 831
glebiuskv 0:2f0e1e23c242 832 if( nr != serial->len )
glebiuskv 0:2f0e1e23c242 833 {
glebiuskv 0:2f0e1e23c242 834 ret = mbedtls_snprintf( p, n, "...." );
glebiuskv 0:2f0e1e23c242 835 MBEDTLS_X509_SAFE_SNPRINTF;
glebiuskv 0:2f0e1e23c242 836 }
glebiuskv 0:2f0e1e23c242 837
glebiuskv 0:2f0e1e23c242 838 return( (int) ( size - n ) );
glebiuskv 0:2f0e1e23c242 839 }
glebiuskv 0:2f0e1e23c242 840
glebiuskv 0:2f0e1e23c242 841 /*
glebiuskv 0:2f0e1e23c242 842 * Helper for writing signature algorithms
glebiuskv 0:2f0e1e23c242 843 */
glebiuskv 0:2f0e1e23c242 844 int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
glebiuskv 0:2f0e1e23c242 845 mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
glebiuskv 0:2f0e1e23c242 846 const void *sig_opts )
glebiuskv 0:2f0e1e23c242 847 {
glebiuskv 0:2f0e1e23c242 848 int ret;
glebiuskv 0:2f0e1e23c242 849 char *p = buf;
glebiuskv 0:2f0e1e23c242 850 size_t n = size;
glebiuskv 0:2f0e1e23c242 851 const char *desc = NULL;
glebiuskv 0:2f0e1e23c242 852
glebiuskv 0:2f0e1e23c242 853 ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc );
glebiuskv 0:2f0e1e23c242 854 if( ret != 0 )
glebiuskv 0:2f0e1e23c242 855 ret = mbedtls_snprintf( p, n, "???" );
glebiuskv 0:2f0e1e23c242 856 else
glebiuskv 0:2f0e1e23c242 857 ret = mbedtls_snprintf( p, n, "%s", desc );
glebiuskv 0:2f0e1e23c242 858 MBEDTLS_X509_SAFE_SNPRINTF;
glebiuskv 0:2f0e1e23c242 859
glebiuskv 0:2f0e1e23c242 860 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
glebiuskv 0:2f0e1e23c242 861 if( pk_alg == MBEDTLS_PK_RSASSA_PSS )
glebiuskv 0:2f0e1e23c242 862 {
glebiuskv 0:2f0e1e23c242 863 const mbedtls_pk_rsassa_pss_options *pss_opts;
glebiuskv 0:2f0e1e23c242 864 const mbedtls_md_info_t *md_info, *mgf_md_info;
glebiuskv 0:2f0e1e23c242 865
glebiuskv 0:2f0e1e23c242 866 pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
glebiuskv 0:2f0e1e23c242 867
glebiuskv 0:2f0e1e23c242 868 md_info = mbedtls_md_info_from_type( md_alg );
glebiuskv 0:2f0e1e23c242 869 mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id );
glebiuskv 0:2f0e1e23c242 870
glebiuskv 0:2f0e1e23c242 871 ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)",
glebiuskv 0:2f0e1e23c242 872 md_info ? mbedtls_md_get_name( md_info ) : "???",
glebiuskv 0:2f0e1e23c242 873 mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???",
glebiuskv 0:2f0e1e23c242 874 pss_opts->expected_salt_len );
glebiuskv 0:2f0e1e23c242 875 MBEDTLS_X509_SAFE_SNPRINTF;
glebiuskv 0:2f0e1e23c242 876 }
glebiuskv 0:2f0e1e23c242 877 #else
glebiuskv 0:2f0e1e23c242 878 ((void) pk_alg);
glebiuskv 0:2f0e1e23c242 879 ((void) md_alg);
glebiuskv 0:2f0e1e23c242 880 ((void) sig_opts);
glebiuskv 0:2f0e1e23c242 881 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
glebiuskv 0:2f0e1e23c242 882
glebiuskv 0:2f0e1e23c242 883 return( (int)( size - n ) );
glebiuskv 0:2f0e1e23c242 884 }
glebiuskv 0:2f0e1e23c242 885
glebiuskv 0:2f0e1e23c242 886 /*
glebiuskv 0:2f0e1e23c242 887 * Helper for writing "RSA key size", "EC key size", etc
glebiuskv 0:2f0e1e23c242 888 */
glebiuskv 0:2f0e1e23c242 889 int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name )
glebiuskv 0:2f0e1e23c242 890 {
glebiuskv 0:2f0e1e23c242 891 char *p = buf;
glebiuskv 0:2f0e1e23c242 892 size_t n = buf_size;
glebiuskv 0:2f0e1e23c242 893 int ret;
glebiuskv 0:2f0e1e23c242 894
glebiuskv 0:2f0e1e23c242 895 ret = mbedtls_snprintf( p, n, "%s key size", name );
glebiuskv 0:2f0e1e23c242 896 MBEDTLS_X509_SAFE_SNPRINTF;
glebiuskv 0:2f0e1e23c242 897
glebiuskv 0:2f0e1e23c242 898 return( 0 );
glebiuskv 0:2f0e1e23c242 899 }
glebiuskv 0:2f0e1e23c242 900
glebiuskv 0:2f0e1e23c242 901 #if defined(MBEDTLS_HAVE_TIME_DATE)
glebiuskv 0:2f0e1e23c242 902 /*
glebiuskv 0:2f0e1e23c242 903 * Set the time structure to the current time.
glebiuskv 0:2f0e1e23c242 904 * Return 0 on success, non-zero on failure.
glebiuskv 0:2f0e1e23c242 905 */
glebiuskv 0:2f0e1e23c242 906 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
glebiuskv 0:2f0e1e23c242 907 static int x509_get_current_time( mbedtls_x509_time *now )
glebiuskv 0:2f0e1e23c242 908 {
glebiuskv 0:2f0e1e23c242 909 SYSTEMTIME st;
glebiuskv 0:2f0e1e23c242 910
glebiuskv 0:2f0e1e23c242 911 GetSystemTime( &st );
glebiuskv 0:2f0e1e23c242 912
glebiuskv 0:2f0e1e23c242 913 now->year = st.wYear;
glebiuskv 0:2f0e1e23c242 914 now->mon = st.wMonth;
glebiuskv 0:2f0e1e23c242 915 now->day = st.wDay;
glebiuskv 0:2f0e1e23c242 916 now->hour = st.wHour;
glebiuskv 0:2f0e1e23c242 917 now->min = st.wMinute;
glebiuskv 0:2f0e1e23c242 918 now->sec = st.wSecond;
glebiuskv 0:2f0e1e23c242 919
glebiuskv 0:2f0e1e23c242 920 return( 0 );
glebiuskv 0:2f0e1e23c242 921 }
glebiuskv 0:2f0e1e23c242 922 #else
glebiuskv 0:2f0e1e23c242 923 static int x509_get_current_time( mbedtls_x509_time *now )
glebiuskv 0:2f0e1e23c242 924 {
glebiuskv 0:2f0e1e23c242 925 struct tm *lt;
glebiuskv 0:2f0e1e23c242 926 mbedtls_time_t tt;
glebiuskv 0:2f0e1e23c242 927 int ret = 0;
glebiuskv 0:2f0e1e23c242 928
glebiuskv 0:2f0e1e23c242 929 #if defined(MBEDTLS_THREADING_C)
glebiuskv 0:2f0e1e23c242 930 if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
glebiuskv 0:2f0e1e23c242 931 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
glebiuskv 0:2f0e1e23c242 932 #endif
glebiuskv 0:2f0e1e23c242 933
glebiuskv 0:2f0e1e23c242 934 tt = mbedtls_time( NULL );
glebiuskv 0:2f0e1e23c242 935 lt = gmtime( &tt );
glebiuskv 0:2f0e1e23c242 936
glebiuskv 0:2f0e1e23c242 937 if( lt == NULL )
glebiuskv 0:2f0e1e23c242 938 ret = -1;
glebiuskv 0:2f0e1e23c242 939 else
glebiuskv 0:2f0e1e23c242 940 {
glebiuskv 0:2f0e1e23c242 941 now->year = lt->tm_year + 1900;
glebiuskv 0:2f0e1e23c242 942 now->mon = lt->tm_mon + 1;
glebiuskv 0:2f0e1e23c242 943 now->day = lt->tm_mday;
glebiuskv 0:2f0e1e23c242 944 now->hour = lt->tm_hour;
glebiuskv 0:2f0e1e23c242 945 now->min = lt->tm_min;
glebiuskv 0:2f0e1e23c242 946 now->sec = lt->tm_sec;
glebiuskv 0:2f0e1e23c242 947 }
glebiuskv 0:2f0e1e23c242 948
glebiuskv 0:2f0e1e23c242 949 #if defined(MBEDTLS_THREADING_C)
glebiuskv 0:2f0e1e23c242 950 if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
glebiuskv 0:2f0e1e23c242 951 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
glebiuskv 0:2f0e1e23c242 952 #endif
glebiuskv 0:2f0e1e23c242 953
glebiuskv 0:2f0e1e23c242 954 return( ret );
glebiuskv 0:2f0e1e23c242 955 }
glebiuskv 0:2f0e1e23c242 956 #endif /* _WIN32 && !EFIX64 && !EFI32 */
glebiuskv 0:2f0e1e23c242 957
glebiuskv 0:2f0e1e23c242 958 /*
glebiuskv 0:2f0e1e23c242 959 * Return 0 if before <= after, 1 otherwise
glebiuskv 0:2f0e1e23c242 960 */
glebiuskv 0:2f0e1e23c242 961 static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after )
glebiuskv 0:2f0e1e23c242 962 {
glebiuskv 0:2f0e1e23c242 963 if( before->year > after->year )
glebiuskv 0:2f0e1e23c242 964 return( 1 );
glebiuskv 0:2f0e1e23c242 965
glebiuskv 0:2f0e1e23c242 966 if( before->year == after->year &&
glebiuskv 0:2f0e1e23c242 967 before->mon > after->mon )
glebiuskv 0:2f0e1e23c242 968 return( 1 );
glebiuskv 0:2f0e1e23c242 969
glebiuskv 0:2f0e1e23c242 970 if( before->year == after->year &&
glebiuskv 0:2f0e1e23c242 971 before->mon == after->mon &&
glebiuskv 0:2f0e1e23c242 972 before->day > after->day )
glebiuskv 0:2f0e1e23c242 973 return( 1 );
glebiuskv 0:2f0e1e23c242 974
glebiuskv 0:2f0e1e23c242 975 if( before->year == after->year &&
glebiuskv 0:2f0e1e23c242 976 before->mon == after->mon &&
glebiuskv 0:2f0e1e23c242 977 before->day == after->day &&
glebiuskv 0:2f0e1e23c242 978 before->hour > after->hour )
glebiuskv 0:2f0e1e23c242 979 return( 1 );
glebiuskv 0:2f0e1e23c242 980
glebiuskv 0:2f0e1e23c242 981 if( before->year == after->year &&
glebiuskv 0:2f0e1e23c242 982 before->mon == after->mon &&
glebiuskv 0:2f0e1e23c242 983 before->day == after->day &&
glebiuskv 0:2f0e1e23c242 984 before->hour == after->hour &&
glebiuskv 0:2f0e1e23c242 985 before->min > after->min )
glebiuskv 0:2f0e1e23c242 986 return( 1 );
glebiuskv 0:2f0e1e23c242 987
glebiuskv 0:2f0e1e23c242 988 if( before->year == after->year &&
glebiuskv 0:2f0e1e23c242 989 before->mon == after->mon &&
glebiuskv 0:2f0e1e23c242 990 before->day == after->day &&
glebiuskv 0:2f0e1e23c242 991 before->hour == after->hour &&
glebiuskv 0:2f0e1e23c242 992 before->min == after->min &&
glebiuskv 0:2f0e1e23c242 993 before->sec > after->sec )
glebiuskv 0:2f0e1e23c242 994 return( 1 );
glebiuskv 0:2f0e1e23c242 995
glebiuskv 0:2f0e1e23c242 996 return( 0 );
glebiuskv 0:2f0e1e23c242 997 }
glebiuskv 0:2f0e1e23c242 998
glebiuskv 0:2f0e1e23c242 999 int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
glebiuskv 0:2f0e1e23c242 1000 {
glebiuskv 0:2f0e1e23c242 1001 mbedtls_x509_time now;
glebiuskv 0:2f0e1e23c242 1002
glebiuskv 0:2f0e1e23c242 1003 if( x509_get_current_time( &now ) != 0 )
glebiuskv 0:2f0e1e23c242 1004 return( 1 );
glebiuskv 0:2f0e1e23c242 1005
glebiuskv 0:2f0e1e23c242 1006 return( x509_check_time( &now, to ) );
glebiuskv 0:2f0e1e23c242 1007 }
glebiuskv 0:2f0e1e23c242 1008
glebiuskv 0:2f0e1e23c242 1009 int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
glebiuskv 0:2f0e1e23c242 1010 {
glebiuskv 0:2f0e1e23c242 1011 mbedtls_x509_time now;
glebiuskv 0:2f0e1e23c242 1012
glebiuskv 0:2f0e1e23c242 1013 if( x509_get_current_time( &now ) != 0 )
glebiuskv 0:2f0e1e23c242 1014 return( 1 );
glebiuskv 0:2f0e1e23c242 1015
glebiuskv 0:2f0e1e23c242 1016 return( x509_check_time( from, &now ) );
glebiuskv 0:2f0e1e23c242 1017 }
glebiuskv 0:2f0e1e23c242 1018
glebiuskv 0:2f0e1e23c242 1019 #else /* MBEDTLS_HAVE_TIME_DATE */
glebiuskv 0:2f0e1e23c242 1020
glebiuskv 0:2f0e1e23c242 1021 int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
glebiuskv 0:2f0e1e23c242 1022 {
glebiuskv 0:2f0e1e23c242 1023 ((void) to);
glebiuskv 0:2f0e1e23c242 1024 return( 0 );
glebiuskv 0:2f0e1e23c242 1025 }
glebiuskv 0:2f0e1e23c242 1026
glebiuskv 0:2f0e1e23c242 1027 int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
glebiuskv 0:2f0e1e23c242 1028 {
glebiuskv 0:2f0e1e23c242 1029 ((void) from);
glebiuskv 0:2f0e1e23c242 1030 return( 0 );
glebiuskv 0:2f0e1e23c242 1031 }
glebiuskv 0:2f0e1e23c242 1032 #endif /* MBEDTLS_HAVE_TIME_DATE */
glebiuskv 0:2f0e1e23c242 1033
glebiuskv 0:2f0e1e23c242 1034 #if defined(MBEDTLS_SELF_TEST)
glebiuskv 0:2f0e1e23c242 1035
glebiuskv 0:2f0e1e23c242 1036 #include "mbedtls/x509_crt.h"
glebiuskv 0:2f0e1e23c242 1037 #include "mbedtls/certs.h"
glebiuskv 0:2f0e1e23c242 1038
glebiuskv 0:2f0e1e23c242 1039 /*
glebiuskv 0:2f0e1e23c242 1040 * Checkup routine
glebiuskv 0:2f0e1e23c242 1041 */
glebiuskv 0:2f0e1e23c242 1042 int mbedtls_x509_self_test( int verbose )
glebiuskv 0:2f0e1e23c242 1043 {
glebiuskv 0:2f0e1e23c242 1044 #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C)
glebiuskv 0:2f0e1e23c242 1045 int ret;
glebiuskv 0:2f0e1e23c242 1046 uint32_t flags;
glebiuskv 0:2f0e1e23c242 1047 mbedtls_x509_crt cacert;
glebiuskv 0:2f0e1e23c242 1048 mbedtls_x509_crt clicert;
glebiuskv 0:2f0e1e23c242 1049
glebiuskv 0:2f0e1e23c242 1050 if( verbose != 0 )
glebiuskv 0:2f0e1e23c242 1051 mbedtls_printf( " X.509 certificate load: " );
glebiuskv 0:2f0e1e23c242 1052
glebiuskv 0:2f0e1e23c242 1053 mbedtls_x509_crt_init( &clicert );
glebiuskv 0:2f0e1e23c242 1054
glebiuskv 0:2f0e1e23c242 1055 ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
glebiuskv 0:2f0e1e23c242 1056 mbedtls_test_cli_crt_len );
glebiuskv 0:2f0e1e23c242 1057 if( ret != 0 )
glebiuskv 0:2f0e1e23c242 1058 {
glebiuskv 0:2f0e1e23c242 1059 if( verbose != 0 )
glebiuskv 0:2f0e1e23c242 1060 mbedtls_printf( "failed\n" );
glebiuskv 0:2f0e1e23c242 1061
glebiuskv 0:2f0e1e23c242 1062 return( ret );
glebiuskv 0:2f0e1e23c242 1063 }
glebiuskv 0:2f0e1e23c242 1064
glebiuskv 0:2f0e1e23c242 1065 mbedtls_x509_crt_init( &cacert );
glebiuskv 0:2f0e1e23c242 1066
glebiuskv 0:2f0e1e23c242 1067 ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt,
glebiuskv 0:2f0e1e23c242 1068 mbedtls_test_ca_crt_len );
glebiuskv 0:2f0e1e23c242 1069 if( ret != 0 )
glebiuskv 0:2f0e1e23c242 1070 {
glebiuskv 0:2f0e1e23c242 1071 if( verbose != 0 )
glebiuskv 0:2f0e1e23c242 1072 mbedtls_printf( "failed\n" );
glebiuskv 0:2f0e1e23c242 1073
glebiuskv 0:2f0e1e23c242 1074 return( ret );
glebiuskv 0:2f0e1e23c242 1075 }
glebiuskv 0:2f0e1e23c242 1076
glebiuskv 0:2f0e1e23c242 1077 if( verbose != 0 )
glebiuskv 0:2f0e1e23c242 1078 mbedtls_printf( "passed\n X.509 signature verify: ");
glebiuskv 0:2f0e1e23c242 1079
glebiuskv 0:2f0e1e23c242 1080 ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
glebiuskv 0:2f0e1e23c242 1081 if( ret != 0 )
glebiuskv 0:2f0e1e23c242 1082 {
glebiuskv 0:2f0e1e23c242 1083 if( verbose != 0 )
glebiuskv 0:2f0e1e23c242 1084 mbedtls_printf( "failed\n" );
glebiuskv 0:2f0e1e23c242 1085
glebiuskv 0:2f0e1e23c242 1086 return( ret );
glebiuskv 0:2f0e1e23c242 1087 }
glebiuskv 0:2f0e1e23c242 1088
glebiuskv 0:2f0e1e23c242 1089 if( verbose != 0 )
glebiuskv 0:2f0e1e23c242 1090 mbedtls_printf( "passed\n\n");
glebiuskv 0:2f0e1e23c242 1091
glebiuskv 0:2f0e1e23c242 1092 mbedtls_x509_crt_free( &cacert );
glebiuskv 0:2f0e1e23c242 1093 mbedtls_x509_crt_free( &clicert );
glebiuskv 0:2f0e1e23c242 1094
glebiuskv 0:2f0e1e23c242 1095 return( 0 );
glebiuskv 0:2f0e1e23c242 1096 #else
glebiuskv 0:2f0e1e23c242 1097 ((void) verbose);
glebiuskv 0:2f0e1e23c242 1098 return( 0 );
glebiuskv 0:2f0e1e23c242 1099 #endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */
glebiuskv 0:2f0e1e23c242 1100 }
glebiuskv 0:2f0e1e23c242 1101
glebiuskv 0:2f0e1e23c242 1102 #endif /* MBEDTLS_SELF_TEST */
glebiuskv 0:2f0e1e23c242 1103
glebiuskv 0:2f0e1e23c242 1104 #endif /* MBEDTLS_X509_USE_C */