Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
x509.c
00001 /* 00002 * X.509 common functions for parsing and verification 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 /* 00022 * The ITU-T X.509 standard defines a certificate format for PKI. 00023 * 00024 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) 00025 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) 00026 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) 00027 * 00028 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf 00029 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf 00030 */ 00031 00032 #if !defined(MBEDTLS_CONFIG_FILE) 00033 #include "mbedtls/config.h" 00034 #else 00035 #include MBEDTLS_CONFIG_FILE 00036 #endif 00037 00038 #if defined(MBEDTLS_X509_USE_C) 00039 00040 #include "mbedtls/x509.h" 00041 #include "mbedtls/asn1.h" 00042 #include "mbedtls/oid.h" 00043 00044 #include <stdio.h> 00045 #include <string.h> 00046 00047 #if defined(MBEDTLS_PEM_PARSE_C) 00048 #include "mbedtls/pem.h" 00049 #endif 00050 00051 #if defined(MBEDTLS_PLATFORM_C) 00052 #include "mbedtls/platform.h" 00053 #else 00054 #include <stdio.h> 00055 #include <stdlib.h> 00056 #define mbedtls_free free 00057 #define mbedtls_calloc calloc 00058 #define mbedtls_printf printf 00059 #define mbedtls_snprintf snprintf 00060 #endif 00061 00062 #if defined(MBEDTLS_HAVE_TIME) 00063 #include "mbedtls/platform_time.h" 00064 #endif 00065 #if defined(MBEDTLS_HAVE_TIME_DATE) 00066 #include "mbedtls/platform_util.h" 00067 #include <time.h> 00068 #endif 00069 00070 #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } 00071 #define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } 00072 00073 /* 00074 * CertificateSerialNumber ::= INTEGER 00075 */ 00076 int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, 00077 mbedtls_x509_buf *serial ) 00078 { 00079 int ret; 00080 00081 if( ( end - *p ) < 1 ) 00082 return( MBEDTLS_ERR_X509_INVALID_SERIAL + 00083 MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 00084 00085 if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && 00086 **p != MBEDTLS_ASN1_INTEGER ) 00087 return( MBEDTLS_ERR_X509_INVALID_SERIAL + 00088 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 00089 00090 serial->tag = *(*p)++; 00091 00092 if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) 00093 return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); 00094 00095 serial->p = *p; 00096 *p += serial->len; 00097 00098 return( 0 ); 00099 } 00100 00101 /* Get an algorithm identifier without parameters (eg for signatures) 00102 * 00103 * AlgorithmIdentifier ::= SEQUENCE { 00104 * algorithm OBJECT IDENTIFIER, 00105 * parameters ANY DEFINED BY algorithm OPTIONAL } 00106 */ 00107 int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, 00108 mbedtls_x509_buf *alg ) 00109 { 00110 int ret; 00111 00112 if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) 00113 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00114 00115 return( 0 ); 00116 } 00117 00118 /* 00119 * Parse an algorithm identifier with (optional) paramaters 00120 */ 00121 int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, 00122 mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) 00123 { 00124 int ret; 00125 00126 if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) 00127 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00128 00129 return( 0 ); 00130 } 00131 00132 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 00133 /* 00134 * HashAlgorithm ::= AlgorithmIdentifier 00135 * 00136 * AlgorithmIdentifier ::= SEQUENCE { 00137 * algorithm OBJECT IDENTIFIER, 00138 * parameters ANY DEFINED BY algorithm OPTIONAL } 00139 * 00140 * For HashAlgorithm, parameters MUST be NULL or absent. 00141 */ 00142 static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) 00143 { 00144 int ret; 00145 unsigned char *p; 00146 const unsigned char *end; 00147 mbedtls_x509_buf md_oid; 00148 size_t len; 00149 00150 /* Make sure we got a SEQUENCE and setup bounds */ 00151 if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) 00152 return( MBEDTLS_ERR_X509_INVALID_ALG + 00153 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 00154 00155 p = (unsigned char *) alg->p; 00156 end = p + alg->len; 00157 00158 if( p >= end ) 00159 return( MBEDTLS_ERR_X509_INVALID_ALG + 00160 MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 00161 00162 /* Parse md_oid */ 00163 md_oid.tag = *p; 00164 00165 if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) 00166 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00167 00168 md_oid.p = p; 00169 p += md_oid.len; 00170 00171 /* Get md_alg from md_oid */ 00172 if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) 00173 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00174 00175 /* Make sure params is absent of NULL */ 00176 if( p == end ) 00177 return( 0 ); 00178 00179 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) 00180 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00181 00182 if( p != end ) 00183 return( MBEDTLS_ERR_X509_INVALID_ALG + 00184 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 00185 00186 return( 0 ); 00187 } 00188 00189 /* 00190 * RSASSA-PSS-params ::= SEQUENCE { 00191 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, 00192 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, 00193 * saltLength [2] INTEGER DEFAULT 20, 00194 * trailerField [3] INTEGER DEFAULT 1 } 00195 * -- Note that the tags in this Sequence are explicit. 00196 * 00197 * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value 00198 * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other 00199 * option. Enfore this at parsing time. 00200 */ 00201 int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, 00202 mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, 00203 int *salt_len ) 00204 { 00205 int ret; 00206 unsigned char *p; 00207 const unsigned char *end, *end2; 00208 size_t len; 00209 mbedtls_x509_buf alg_id, alg_params; 00210 00211 /* First set everything to defaults */ 00212 *md_alg = MBEDTLS_MD_SHA1; 00213 *mgf_md = MBEDTLS_MD_SHA1; 00214 *salt_len = 20; 00215 00216 /* Make sure params is a SEQUENCE and setup bounds */ 00217 if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) 00218 return( MBEDTLS_ERR_X509_INVALID_ALG + 00219 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 00220 00221 p = (unsigned char *) params->p; 00222 end = p + params->len; 00223 00224 if( p == end ) 00225 return( 0 ); 00226 00227 /* 00228 * HashAlgorithm 00229 */ 00230 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 00231 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) 00232 { 00233 end2 = p + len; 00234 00235 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ 00236 if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) 00237 return( ret ); 00238 00239 if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) 00240 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00241 00242 if( p != end2 ) 00243 return( MBEDTLS_ERR_X509_INVALID_ALG + 00244 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 00245 } 00246 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 00247 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00248 00249 if( p == end ) 00250 return( 0 ); 00251 00252 /* 00253 * MaskGenAlgorithm 00254 */ 00255 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 00256 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) 00257 { 00258 end2 = p + len; 00259 00260 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ 00261 if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) 00262 return( ret ); 00263 00264 /* Only MFG1 is recognised for now */ 00265 if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) 00266 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + 00267 MBEDTLS_ERR_OID_NOT_FOUND ); 00268 00269 /* Parse HashAlgorithm */ 00270 if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) 00271 return( ret ); 00272 00273 if( p != end2 ) 00274 return( MBEDTLS_ERR_X509_INVALID_ALG + 00275 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 00276 } 00277 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 00278 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00279 00280 if( p == end ) 00281 return( 0 ); 00282 00283 /* 00284 * salt_len 00285 */ 00286 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 00287 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) 00288 { 00289 end2 = p + len; 00290 00291 if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) 00292 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00293 00294 if( p != end2 ) 00295 return( MBEDTLS_ERR_X509_INVALID_ALG + 00296 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 00297 } 00298 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 00299 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00300 00301 if( p == end ) 00302 return( 0 ); 00303 00304 /* 00305 * trailer_field (if present, must be 1) 00306 */ 00307 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 00308 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) 00309 { 00310 int trailer_field; 00311 00312 end2 = p + len; 00313 00314 if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) 00315 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00316 00317 if( p != end2 ) 00318 return( MBEDTLS_ERR_X509_INVALID_ALG + 00319 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 00320 00321 if( trailer_field != 1 ) 00322 return( MBEDTLS_ERR_X509_INVALID_ALG ); 00323 } 00324 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) 00325 return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); 00326 00327 if( p != end ) 00328 return( MBEDTLS_ERR_X509_INVALID_ALG + 00329 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 00330 00331 return( 0 ); 00332 } 00333 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 00334 00335 /* 00336 * AttributeTypeAndValue ::= SEQUENCE { 00337 * type AttributeType, 00338 * value AttributeValue } 00339 * 00340 * AttributeType ::= OBJECT IDENTIFIER 00341 * 00342 * AttributeValue ::= ANY DEFINED BY AttributeType 00343 */ 00344 static int x509_get_attr_type_value( unsigned char **p, 00345 const unsigned char *end, 00346 mbedtls_x509_name *cur ) 00347 { 00348 int ret; 00349 size_t len; 00350 mbedtls_x509_buf *oid; 00351 mbedtls_x509_buf *val; 00352 00353 if( ( ret = mbedtls_asn1_get_tag( p, end, &len, 00354 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 00355 return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); 00356 00357 if( ( end - *p ) < 1 ) 00358 return( MBEDTLS_ERR_X509_INVALID_NAME + 00359 MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 00360 00361 oid = &cur->oid; 00362 oid->tag = **p; 00363 00364 if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) 00365 return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); 00366 00367 oid->p = *p; 00368 *p += oid->len; 00369 00370 if( ( end - *p ) < 1 ) 00371 return( MBEDTLS_ERR_X509_INVALID_NAME + 00372 MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 00373 00374 if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && 00375 **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && 00376 **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && 00377 **p != MBEDTLS_ASN1_BIT_STRING ) 00378 return( MBEDTLS_ERR_X509_INVALID_NAME + 00379 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 00380 00381 val = &cur->val; 00382 val->tag = *(*p)++; 00383 00384 if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) 00385 return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); 00386 00387 val->p = *p; 00388 *p += val->len; 00389 00390 cur->next = NULL; 00391 00392 return( 0 ); 00393 } 00394 00395 /* 00396 * Name ::= CHOICE { -- only one possibility for now -- 00397 * rdnSequence RDNSequence } 00398 * 00399 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 00400 * 00401 * RelativeDistinguishedName ::= 00402 * SET OF AttributeTypeAndValue 00403 * 00404 * AttributeTypeAndValue ::= SEQUENCE { 00405 * type AttributeType, 00406 * value AttributeValue } 00407 * 00408 * AttributeType ::= OBJECT IDENTIFIER 00409 * 00410 * AttributeValue ::= ANY DEFINED BY AttributeType 00411 * 00412 * The data structure is optimized for the common case where each RDN has only 00413 * one element, which is represented as a list of AttributeTypeAndValue. 00414 * For the general case we still use a flat list, but we mark elements of the 00415 * same set so that they are "merged" together in the functions that consume 00416 * this list, eg mbedtls_x509_dn_gets(). 00417 */ 00418 int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, 00419 mbedtls_x509_name *cur ) 00420 { 00421 int ret; 00422 size_t set_len; 00423 const unsigned char *end_set; 00424 00425 /* don't use recursion, we'd risk stack overflow if not optimized */ 00426 while( 1 ) 00427 { 00428 /* 00429 * parse SET 00430 */ 00431 if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, 00432 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) 00433 return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); 00434 00435 end_set = *p + set_len; 00436 00437 while( 1 ) 00438 { 00439 if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) 00440 return( ret ); 00441 00442 if( *p == end_set ) 00443 break; 00444 00445 /* Mark this item as being no the only one in a set */ 00446 cur->next_merged = 1; 00447 00448 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); 00449 00450 if( cur->next == NULL ) 00451 return( MBEDTLS_ERR_X509_ALLOC_FAILED ); 00452 00453 cur = cur->next; 00454 } 00455 00456 /* 00457 * continue until end of SEQUENCE is reached 00458 */ 00459 if( *p == end ) 00460 return( 0 ); 00461 00462 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); 00463 00464 if( cur->next == NULL ) 00465 return( MBEDTLS_ERR_X509_ALLOC_FAILED ); 00466 00467 cur = cur->next; 00468 } 00469 } 00470 00471 static int x509_parse_int( unsigned char **p, size_t n, int *res ) 00472 { 00473 *res = 0; 00474 00475 for( ; n > 0; --n ) 00476 { 00477 if( ( **p < '0') || ( **p > '9' ) ) 00478 return ( MBEDTLS_ERR_X509_INVALID_DATE ); 00479 00480 *res *= 10; 00481 *res += ( *(*p)++ - '0' ); 00482 } 00483 00484 return( 0 ); 00485 } 00486 00487 static int x509_date_is_valid(const mbedtls_x509_time *t ) 00488 { 00489 int ret = MBEDTLS_ERR_X509_INVALID_DATE; 00490 int month_len; 00491 00492 CHECK_RANGE( 0, 9999, t->year ); 00493 CHECK_RANGE( 0, 23, t->hour ); 00494 CHECK_RANGE( 0, 59, t->min ); 00495 CHECK_RANGE( 0, 59, t->sec ); 00496 00497 switch( t->mon ) 00498 { 00499 case 1: case 3: case 5: case 7: case 8: case 10: case 12: 00500 month_len = 31; 00501 break; 00502 case 4: case 6: case 9: case 11: 00503 month_len = 30; 00504 break; 00505 case 2: 00506 if( ( !( t->year % 4 ) && t->year % 100 ) || 00507 !( t->year % 400 ) ) 00508 month_len = 29; 00509 else 00510 month_len = 28; 00511 break; 00512 default: 00513 return( ret ); 00514 } 00515 CHECK_RANGE( 1, month_len, t->day ); 00516 00517 return( 0 ); 00518 } 00519 00520 /* 00521 * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) 00522 * field. 00523 */ 00524 static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, 00525 mbedtls_x509_time *tm ) 00526 { 00527 int ret; 00528 00529 /* 00530 * Minimum length is 10 or 12 depending on yearlen 00531 */ 00532 if ( len < yearlen + 8 ) 00533 return ( MBEDTLS_ERR_X509_INVALID_DATE ); 00534 len -= yearlen + 8; 00535 00536 /* 00537 * Parse year, month, day, hour, minute 00538 */ 00539 CHECK( x509_parse_int( p, yearlen, &tm->year ) ); 00540 if ( 2 == yearlen ) 00541 { 00542 if ( tm->year < 50 ) 00543 tm->year += 100; 00544 00545 tm->year += 1900; 00546 } 00547 00548 CHECK( x509_parse_int( p, 2, &tm->mon ) ); 00549 CHECK( x509_parse_int( p, 2, &tm->day ) ); 00550 CHECK( x509_parse_int( p, 2, &tm->hour ) ); 00551 CHECK( x509_parse_int( p, 2, &tm->min ) ); 00552 00553 /* 00554 * Parse seconds if present 00555 */ 00556 if ( len >= 2 ) 00557 { 00558 CHECK( x509_parse_int( p, 2, &tm->sec ) ); 00559 len -= 2; 00560 } 00561 else 00562 return ( MBEDTLS_ERR_X509_INVALID_DATE ); 00563 00564 /* 00565 * Parse trailing 'Z' if present 00566 */ 00567 if ( 1 == len && 'Z' == **p ) 00568 { 00569 (*p)++; 00570 len--; 00571 } 00572 00573 /* 00574 * We should have parsed all characters at this point 00575 */ 00576 if ( 0 != len ) 00577 return ( MBEDTLS_ERR_X509_INVALID_DATE ); 00578 00579 CHECK( x509_date_is_valid( tm ) ); 00580 00581 return ( 0 ); 00582 } 00583 00584 /* 00585 * Time ::= CHOICE { 00586 * utcTime UTCTime, 00587 * generalTime GeneralizedTime } 00588 */ 00589 int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, 00590 mbedtls_x509_time *tm ) 00591 { 00592 int ret; 00593 size_t len, year_len; 00594 unsigned char tag; 00595 00596 if( ( end - *p ) < 1 ) 00597 return( MBEDTLS_ERR_X509_INVALID_DATE + 00598 MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 00599 00600 tag = **p; 00601 00602 if( tag == MBEDTLS_ASN1_UTC_TIME ) 00603 year_len = 2; 00604 else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) 00605 year_len = 4; 00606 else 00607 return( MBEDTLS_ERR_X509_INVALID_DATE + 00608 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); 00609 00610 (*p)++; 00611 ret = mbedtls_asn1_get_len( p, end, &len ); 00612 00613 if( ret != 0 ) 00614 return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); 00615 00616 return x509_parse_time( p, len, year_len, tm ); 00617 } 00618 00619 int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) 00620 { 00621 int ret; 00622 size_t len; 00623 int tag_type; 00624 00625 if( ( end - *p ) < 1 ) 00626 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + 00627 MBEDTLS_ERR_ASN1_OUT_OF_DATA ); 00628 00629 tag_type = **p; 00630 00631 if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) 00632 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); 00633 00634 sig->tag = tag_type; 00635 sig->len = len; 00636 sig->p = *p; 00637 00638 *p += len; 00639 00640 return( 0 ); 00641 } 00642 00643 /* 00644 * Get signature algorithm from alg OID and optional parameters 00645 */ 00646 int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, 00647 mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, 00648 void **sig_opts ) 00649 { 00650 int ret; 00651 00652 if( *sig_opts != NULL ) 00653 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); 00654 00655 if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) 00656 return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret ); 00657 00658 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 00659 if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) 00660 { 00661 mbedtls_pk_rsassa_pss_options *pss_opts; 00662 00663 pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); 00664 if( pss_opts == NULL ) 00665 return( MBEDTLS_ERR_X509_ALLOC_FAILED ); 00666 00667 ret = mbedtls_x509_get_rsassa_pss_params( sig_params, 00668 md_alg, 00669 &pss_opts->mgf1_hash_id, 00670 &pss_opts->expected_salt_len ); 00671 if( ret != 0 ) 00672 { 00673 mbedtls_free( pss_opts ); 00674 return( ret ); 00675 } 00676 00677 *sig_opts = (void *) pss_opts; 00678 } 00679 else 00680 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 00681 { 00682 /* Make sure parameters are absent or NULL */ 00683 if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || 00684 sig_params->len != 0 ) 00685 return( MBEDTLS_ERR_X509_INVALID_ALG ); 00686 } 00687 00688 return( 0 ); 00689 } 00690 00691 /* 00692 * X.509 Extensions (No parsing of extensions, pointer should 00693 * be either manually updated or extensions should be parsed!) 00694 */ 00695 int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, 00696 mbedtls_x509_buf *ext, int tag ) 00697 { 00698 int ret; 00699 size_t len; 00700 00701 if( *p == end ) 00702 return( 0 ); 00703 00704 ext->tag = **p; 00705 00706 if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, 00707 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 ) 00708 return( ret ); 00709 00710 ext->p = *p; 00711 end = *p + ext->len; 00712 00713 /* 00714 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 00715 * 00716 * Extension ::= SEQUENCE { 00717 * extnID OBJECT IDENTIFIER, 00718 * critical BOOLEAN DEFAULT FALSE, 00719 * extnValue OCTET STRING } 00720 */ 00721 if( ( ret = mbedtls_asn1_get_tag( p, end, &len, 00722 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 00723 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); 00724 00725 if( end != *p + len ) 00726 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + 00727 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); 00728 00729 return( 0 ); 00730 } 00731 00732 /* 00733 * Store the name in printable form into buf; no more 00734 * than size characters will be written 00735 */ 00736 int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) 00737 { 00738 int ret; 00739 size_t i, n; 00740 unsigned char c, merge = 0; 00741 const mbedtls_x509_name *name; 00742 const char *short_name = NULL; 00743 char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; 00744 00745 memset( s, 0, sizeof( s ) ); 00746 00747 name = dn; 00748 p = buf; 00749 n = size; 00750 00751 while( name != NULL ) 00752 { 00753 if( !name->oid.p ) 00754 { 00755 name = name->next; 00756 continue; 00757 } 00758 00759 if( name != dn ) 00760 { 00761 ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); 00762 MBEDTLS_X509_SAFE_SNPRINTF; 00763 } 00764 00765 ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); 00766 00767 if( ret == 0 ) 00768 ret = mbedtls_snprintf( p, n, "%s=", short_name ); 00769 else 00770 ret = mbedtls_snprintf( p, n, "\?\?=" ); 00771 MBEDTLS_X509_SAFE_SNPRINTF; 00772 00773 for( i = 0; i < name->val.len; i++ ) 00774 { 00775 if( i >= sizeof( s ) - 1 ) 00776 break; 00777 00778 c = name->val.p[i]; 00779 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) 00780 s[i] = '?'; 00781 else s[i] = c; 00782 } 00783 s[i] = '\0'; 00784 ret = mbedtls_snprintf( p, n, "%s", s ); 00785 MBEDTLS_X509_SAFE_SNPRINTF; 00786 00787 merge = name->next_merged; 00788 name = name->next; 00789 } 00790 00791 return( (int) ( size - n ) ); 00792 } 00793 00794 /* 00795 * Store the serial in printable form into buf; no more 00796 * than size characters will be written 00797 */ 00798 int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) 00799 { 00800 int ret; 00801 size_t i, n, nr; 00802 char *p; 00803 00804 p = buf; 00805 n = size; 00806 00807 nr = ( serial->len <= 32 ) 00808 ? serial->len : 28; 00809 00810 for( i = 0; i < nr; i++ ) 00811 { 00812 if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) 00813 continue; 00814 00815 ret = mbedtls_snprintf( p, n, "%02X%s", 00816 serial->p[i], ( i < nr - 1 ) ? ":" : "" ); 00817 MBEDTLS_X509_SAFE_SNPRINTF; 00818 } 00819 00820 if( nr != serial->len ) 00821 { 00822 ret = mbedtls_snprintf( p, n, "...." ); 00823 MBEDTLS_X509_SAFE_SNPRINTF; 00824 } 00825 00826 return( (int) ( size - n ) ); 00827 } 00828 00829 /* 00830 * Helper for writing signature algorithms 00831 */ 00832 int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, 00833 mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, 00834 const void *sig_opts ) 00835 { 00836 int ret; 00837 char *p = buf; 00838 size_t n = size; 00839 const char *desc = NULL; 00840 00841 ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); 00842 if( ret != 0 ) 00843 ret = mbedtls_snprintf( p, n, "???" ); 00844 else 00845 ret = mbedtls_snprintf( p, n, "%s", desc ); 00846 MBEDTLS_X509_SAFE_SNPRINTF; 00847 00848 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) 00849 if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) 00850 { 00851 const mbedtls_pk_rsassa_pss_options *pss_opts; 00852 const mbedtls_md_info_t *md_info, *mgf_md_info; 00853 00854 pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; 00855 00856 md_info = mbedtls_md_info_from_type( md_alg ); 00857 mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); 00858 00859 ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", 00860 md_info ? mbedtls_md_get_name( md_info ) : "???", 00861 mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", 00862 pss_opts->expected_salt_len ); 00863 MBEDTLS_X509_SAFE_SNPRINTF; 00864 } 00865 #else 00866 ((void) pk_alg); 00867 ((void) md_alg); 00868 ((void) sig_opts); 00869 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ 00870 00871 return( (int)( size - n ) ); 00872 } 00873 00874 /* 00875 * Helper for writing "RSA key size", "EC key size", etc 00876 */ 00877 int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) 00878 { 00879 char *p = buf; 00880 size_t n = buf_size; 00881 int ret; 00882 00883 ret = mbedtls_snprintf( p, n, "%s key size", name ); 00884 MBEDTLS_X509_SAFE_SNPRINTF; 00885 00886 return( 0 ); 00887 } 00888 00889 #if defined(MBEDTLS_HAVE_TIME_DATE) 00890 /* 00891 * Set the time structure to the current time. 00892 * Return 0 on success, non-zero on failure. 00893 */ 00894 static int x509_get_current_time( mbedtls_x509_time *now ) 00895 { 00896 struct tm *lt, tm_buf; 00897 mbedtls_time_t tt; 00898 int ret = 0; 00899 00900 tt = mbedtls_time( NULL ); 00901 lt = mbedtls_platform_gmtime_r( &tt, &tm_buf ); 00902 00903 if( lt == NULL ) 00904 ret = -1; 00905 else 00906 { 00907 now->year = lt->tm_year + 1900; 00908 now->mon = lt->tm_mon + 1; 00909 now->day = lt->tm_mday; 00910 now->hour = lt->tm_hour; 00911 now->min = lt->tm_min; 00912 now->sec = lt->tm_sec; 00913 } 00914 00915 return( ret ); 00916 } 00917 00918 /* 00919 * Return 0 if before <= after, 1 otherwise 00920 */ 00921 static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) 00922 { 00923 if( before->year > after->year ) 00924 return( 1 ); 00925 00926 if( before->year == after->year && 00927 before->mon > after->mon ) 00928 return( 1 ); 00929 00930 if( before->year == after->year && 00931 before->mon == after->mon && 00932 before->day > after->day ) 00933 return( 1 ); 00934 00935 if( before->year == after->year && 00936 before->mon == after->mon && 00937 before->day == after->day && 00938 before->hour > after->hour ) 00939 return( 1 ); 00940 00941 if( before->year == after->year && 00942 before->mon == after->mon && 00943 before->day == after->day && 00944 before->hour == after->hour && 00945 before->min > after->min ) 00946 return( 1 ); 00947 00948 if( before->year == after->year && 00949 before->mon == after->mon && 00950 before->day == after->day && 00951 before->hour == after->hour && 00952 before->min == after->min && 00953 before->sec > after->sec ) 00954 return( 1 ); 00955 00956 return( 0 ); 00957 } 00958 00959 int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) 00960 { 00961 mbedtls_x509_time now; 00962 00963 if( x509_get_current_time( &now ) != 0 ) 00964 return( 1 ); 00965 00966 return( x509_check_time( &now, to ) ); 00967 } 00968 00969 int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) 00970 { 00971 mbedtls_x509_time now; 00972 00973 if( x509_get_current_time( &now ) != 0 ) 00974 return( 1 ); 00975 00976 return( x509_check_time( from, &now ) ); 00977 } 00978 00979 #else /* MBEDTLS_HAVE_TIME_DATE */ 00980 00981 int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) 00982 { 00983 ((void) to); 00984 return( 0 ); 00985 } 00986 00987 int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) 00988 { 00989 ((void) from); 00990 return( 0 ); 00991 } 00992 #endif /* MBEDTLS_HAVE_TIME_DATE */ 00993 00994 #if defined(MBEDTLS_SELF_TEST) 00995 00996 #include "mbedtls/x509_crt.h" 00997 #include "mbedtls/certs.h" 00998 00999 /* 01000 * Checkup routine 01001 */ 01002 int mbedtls_x509_self_test( int verbose ) 01003 { 01004 #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) 01005 int ret; 01006 uint32_t flags; 01007 mbedtls_x509_crt cacert; 01008 mbedtls_x509_crt clicert; 01009 01010 if( verbose != 0 ) 01011 mbedtls_printf( " X.509 certificate load: " ); 01012 01013 mbedtls_x509_crt_init( &clicert ); 01014 01015 ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, 01016 mbedtls_test_cli_crt_len ); 01017 if( ret != 0 ) 01018 { 01019 if( verbose != 0 ) 01020 mbedtls_printf( "failed\n" ); 01021 01022 return( ret ); 01023 } 01024 01025 mbedtls_x509_crt_init( &cacert ); 01026 01027 ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, 01028 mbedtls_test_ca_crt_len ); 01029 if( ret != 0 ) 01030 { 01031 if( verbose != 0 ) 01032 mbedtls_printf( "failed\n" ); 01033 01034 return( ret ); 01035 } 01036 01037 if( verbose != 0 ) 01038 mbedtls_printf( "passed\n X.509 signature verify: "); 01039 01040 ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); 01041 if( ret != 0 ) 01042 { 01043 if( verbose != 0 ) 01044 mbedtls_printf( "failed\n" ); 01045 01046 return( ret ); 01047 } 01048 01049 if( verbose != 0 ) 01050 mbedtls_printf( "passed\n\n"); 01051 01052 mbedtls_x509_crt_free( &cacert ); 01053 mbedtls_x509_crt_free( &clicert ); 01054 01055 return( 0 ); 01056 #else 01057 ((void) verbose); 01058 return( 0 ); 01059 #endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */ 01060 } 01061 01062 #endif /* MBEDTLS_SELF_TEST */ 01063 01064 #endif /* MBEDTLS_X509_USE_C */
Generated on Tue Aug 9 2022 00:37:24 by
1.7.2