2 * X.509 common functions for parsing and verification
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * This file is part of mbed TLS (https://tls.mbed.org)
22 * The ITU-T X.509 standard defines a certificate format for PKI.
24 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
25 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
26 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
28 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
29 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
32 #if !defined(MBEDTLS_CONFIG_FILE)
33 #include "mbedtls/config.h"
35 #include MBEDTLS_CONFIG_FILE
38 #if defined(MBEDTLS_X509_USE_C)
40 #include "mbedtls/x509.h"
41 #include "mbedtls/asn1.h"
42 #include "mbedtls/oid.h"
47 #if defined(MBEDTLS_PEM_PARSE_C)
48 #include "mbedtls/pem.h"
51 #if defined(MBEDTLS_PLATFORM_C)
52 #include "mbedtls/platform.h"
56 #define mbedtls_free free
57 #define mbedtls_calloc calloc
58 #define mbedtls_printf printf
59 #define mbedtls_snprintf snprintf
63 #if defined(MBEDTLS_HAVE_TIME)
64 #include "mbedtls/platform_time.h"
67 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
73 #if defined(MBEDTLS_FS_IO)
76 #include <sys/types.h>
82 #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); }
83 #define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); }
86 * CertificateSerialNumber ::= INTEGER
88 int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
89 mbedtls_x509_buf *serial )
93 if( ( end - *p ) < 1 )
94 return( MBEDTLS_ERR_X509_INVALID_SERIAL +
95 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
97 if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) &&
98 **p != MBEDTLS_ASN1_INTEGER )
99 return( MBEDTLS_ERR_X509_INVALID_SERIAL +
100 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
102 serial->tag = *(*p)++;
104 if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 )
105 return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret );
113 /* Get an algorithm identifier without parameters (eg for signatures)
115 * AlgorithmIdentifier ::= SEQUENCE {
116 * algorithm OBJECT IDENTIFIER,
117 * parameters ANY DEFINED BY algorithm OPTIONAL }
119 int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
120 mbedtls_x509_buf *alg )
124 if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
125 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
131 * Parse an algorithm identifier with (optional) paramaters
133 int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
134 mbedtls_x509_buf *alg, mbedtls_x509_buf *params )
138 if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 )
139 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
144 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
146 * HashAlgorithm ::= AlgorithmIdentifier
148 * AlgorithmIdentifier ::= SEQUENCE {
149 * algorithm OBJECT IDENTIFIER,
150 * parameters ANY DEFINED BY algorithm OPTIONAL }
152 * For HashAlgorithm, parameters MUST be NULL or absent.
154 static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg )
158 const unsigned char *end;
159 mbedtls_x509_buf md_oid;
162 /* Make sure we got a SEQUENCE and setup bounds */
163 if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
164 return( MBEDTLS_ERR_X509_INVALID_ALG +
165 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
167 p = (unsigned char *) alg->p;
171 return( MBEDTLS_ERR_X509_INVALID_ALG +
172 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
177 if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
178 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
183 /* Get md_alg from md_oid */
184 if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 )
185 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
187 /* Make sure params is absent of NULL */
191 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 )
192 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
195 return( MBEDTLS_ERR_X509_INVALID_ALG +
196 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
202 * RSASSA-PSS-params ::= SEQUENCE {
203 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
204 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
205 * saltLength [2] INTEGER DEFAULT 20,
206 * trailerField [3] INTEGER DEFAULT 1 }
207 * -- Note that the tags in this Sequence are explicit.
209 * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
210 * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
211 * option. Enfore this at parsing time.
213 int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
214 mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
219 const unsigned char *end, *end2;
221 mbedtls_x509_buf alg_id, alg_params;
223 /* First set everything to defaults */
224 *md_alg = MBEDTLS_MD_SHA1;
225 *mgf_md = MBEDTLS_MD_SHA1;
228 /* Make sure params is a SEQUENCE and setup bounds */
229 if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) )
230 return( MBEDTLS_ERR_X509_INVALID_ALG +
231 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
233 p = (unsigned char *) params->p;
234 end = p + params->len;
242 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
243 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 )
247 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
248 if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 )
251 if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 )
252 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
255 return( MBEDTLS_ERR_X509_INVALID_ALG +
256 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
258 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
259 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
267 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
268 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 )
272 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
273 if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 )
276 /* Only MFG1 is recognised for now */
277 if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 )
278 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +
279 MBEDTLS_ERR_OID_NOT_FOUND );
281 /* Parse HashAlgorithm */
282 if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 )
286 return( MBEDTLS_ERR_X509_INVALID_ALG +
287 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
289 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
290 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
298 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
299 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 )
303 if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 )
304 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
307 return( MBEDTLS_ERR_X509_INVALID_ALG +
308 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
310 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
311 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
317 * trailer_field (if present, must be 1)
319 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
320 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 )
326 if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 )
327 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
330 return( MBEDTLS_ERR_X509_INVALID_ALG +
331 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
333 if( trailer_field != 1 )
334 return( MBEDTLS_ERR_X509_INVALID_ALG );
336 else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
337 return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
340 return( MBEDTLS_ERR_X509_INVALID_ALG +
341 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
345 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
348 * AttributeTypeAndValue ::= SEQUENCE {
349 * type AttributeType,
350 * value AttributeValue }
352 * AttributeType ::= OBJECT IDENTIFIER
354 * AttributeValue ::= ANY DEFINED BY AttributeType
356 static int x509_get_attr_type_value( unsigned char **p,
357 const unsigned char *end,
358 mbedtls_x509_name *cur )
362 mbedtls_x509_buf *oid;
363 mbedtls_x509_buf *val;
365 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
366 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
367 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
369 if( ( end - *p ) < 1 )
370 return( MBEDTLS_ERR_X509_INVALID_NAME +
371 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
376 if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 )
377 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
382 if( ( end - *p ) < 1 )
383 return( MBEDTLS_ERR_X509_INVALID_NAME +
384 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
386 if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING &&
387 **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
388 **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
389 **p != MBEDTLS_ASN1_BIT_STRING )
390 return( MBEDTLS_ERR_X509_INVALID_NAME +
391 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
396 if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 )
397 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
408 * Name ::= CHOICE { -- only one possibility for now --
409 * rdnSequence RDNSequence }
411 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
413 * RelativeDistinguishedName ::=
414 * SET OF AttributeTypeAndValue
416 * AttributeTypeAndValue ::= SEQUENCE {
417 * type AttributeType,
418 * value AttributeValue }
420 * AttributeType ::= OBJECT IDENTIFIER
422 * AttributeValue ::= ANY DEFINED BY AttributeType
424 * The data structure is optimized for the common case where each RDN has only
425 * one element, which is represented as a list of AttributeTypeAndValue.
426 * For the general case we still use a flat list, but we mark elements of the
427 * same set so that they are "merged" together in the functions that consume
428 * this list, eg mbedtls_x509_dn_gets().
430 int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
431 mbedtls_x509_name *cur )
435 const unsigned char *end_set;
437 /* don't use recursion, we'd risk stack overflow if not optimized */
443 if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len,
444 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 )
445 return( MBEDTLS_ERR_X509_INVALID_NAME + ret );
447 end_set = *p + set_len;
451 if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 )
457 /* Mark this item as being no the only one in a set */
458 cur->next_merged = 1;
460 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
462 if( cur->next == NULL )
463 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
469 * continue until end of SEQUENCE is reached
474 cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) );
476 if( cur->next == NULL )
477 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
483 static int x509_parse_int(unsigned char **p, unsigned n, int *res){
486 if( ( **p < '0') || ( **p > '9' ) ) return MBEDTLS_ERR_X509_INVALID_DATE;
488 *res += (*(*p)++ - '0');
493 static int x509_date_is_valid(const mbedtls_x509_time *time)
495 int ret = MBEDTLS_ERR_X509_INVALID_DATE;
497 CHECK_RANGE( 0, 9999, time->year );
498 CHECK_RANGE( 0, 23, time->hour );
499 CHECK_RANGE( 0, 59, time->min );
500 CHECK_RANGE( 0, 59, time->sec );
504 case 1: case 3: case 5: case 7: case 8: case 10: case 12:
505 CHECK_RANGE( 1, 31, time->day );
507 case 4: case 6: case 9: case 11:
508 CHECK_RANGE( 1, 30, time->day );
511 CHECK_RANGE( 1, 28 + (time->year % 4 == 0), time->day );
523 * generalTime GeneralizedTime }
525 int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
526 mbedtls_x509_time *time )
532 if( ( end - *p ) < 1 )
533 return( MBEDTLS_ERR_X509_INVALID_DATE +
534 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
538 if( tag == MBEDTLS_ASN1_UTC_TIME )
541 ret = mbedtls_asn1_get_len( p, end, &len );
544 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
546 CHECK( x509_parse_int( p, 2, &time->year ) );
547 CHECK( x509_parse_int( p, 2, &time->mon ) );
548 CHECK( x509_parse_int( p, 2, &time->day ) );
549 CHECK( x509_parse_int( p, 2, &time->hour ) );
550 CHECK( x509_parse_int( p, 2, &time->min ) );
552 CHECK( x509_parse_int( p, 2, &time->sec ) );
553 if( len > 12 && *(*p)++ != 'Z' )
554 return( MBEDTLS_ERR_X509_INVALID_DATE );
556 time->year += 100 * ( time->year < 50 );
559 CHECK( x509_date_is_valid( time ) );
563 else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME )
566 ret = mbedtls_asn1_get_len( p, end, &len );
569 return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
571 CHECK( x509_parse_int( p, 4, &time->year ) );
572 CHECK( x509_parse_int( p, 2, &time->mon ) );
573 CHECK( x509_parse_int( p, 2, &time->day ) );
574 CHECK( x509_parse_int( p, 2, &time->hour ) );
575 CHECK( x509_parse_int( p, 2, &time->min ) );
577 CHECK( x509_parse_int( p, 2, &time->sec ) );
578 if( len > 14 && *(*p)++ != 'Z' )
579 return( MBEDTLS_ERR_X509_INVALID_DATE );
581 CHECK( x509_date_is_valid( time ) );
586 return( MBEDTLS_ERR_X509_INVALID_DATE +
587 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
590 int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig )
596 if( ( end - *p ) < 1 )
597 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE +
598 MBEDTLS_ERR_ASN1_OUT_OF_DATA );
602 if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 )
603 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret );
615 * Get signature algorithm from alg OID and optional parameters
617 int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
618 mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
623 if( *sig_opts != NULL )
624 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
626 if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 )
627 return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret );
629 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
630 if( *pk_alg == MBEDTLS_PK_RSASSA_PSS )
632 mbedtls_pk_rsassa_pss_options *pss_opts;
634 pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) );
635 if( pss_opts == NULL )
636 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
638 ret = mbedtls_x509_get_rsassa_pss_params( sig_params,
640 &pss_opts->mgf1_hash_id,
641 &pss_opts->expected_salt_len );
644 mbedtls_free( pss_opts );
648 *sig_opts = (void *) pss_opts;
651 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
653 /* Make sure parameters are absent or NULL */
654 if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) ||
655 sig_params->len != 0 )
656 return( MBEDTLS_ERR_X509_INVALID_ALG );
663 * X.509 Extensions (No parsing of extensions, pointer should
664 * be either manually updated or extensions should be parsed!
666 int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
667 mbedtls_x509_buf *ext, int tag )
677 if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len,
678 MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 )
685 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
687 * Extension ::= SEQUENCE {
688 * extnID OBJECT IDENTIFIER,
689 * critical BOOLEAN DEFAULT FALSE,
690 * extnValue OCTET STRING }
692 if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
693 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
694 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
696 if( end != *p + len )
697 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
698 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
704 * Store the name in printable form into buf; no more
705 * than size characters will be written
707 int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
711 unsigned char c, merge = 0;
712 const mbedtls_x509_name *name;
713 const char *short_name = NULL;
714 char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
716 memset( s, 0, sizeof( s ) );
722 while( name != NULL )
732 ret = mbedtls_snprintf( p, n, merge ? " + " : ", " );
733 MBEDTLS_X509_SAFE_SNPRINTF;
736 ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name );
739 ret = mbedtls_snprintf( p, n, "%s=", short_name );
741 ret = mbedtls_snprintf( p, n, "\?\?=" );
742 MBEDTLS_X509_SAFE_SNPRINTF;
744 for( i = 0; i < name->val.len; i++ )
746 if( i >= sizeof( s ) - 1 )
750 if( c < 32 || c == 127 || ( c > 128 && c < 160 ) )
755 ret = mbedtls_snprintf( p, n, "%s", s );
756 MBEDTLS_X509_SAFE_SNPRINTF;
758 merge = name->next_merged;
762 return( (int) ( size - n ) );
766 * Store the serial in printable form into buf; no more
767 * than size characters will be written
769 int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial )
778 nr = ( serial->len <= 32 )
781 for( i = 0; i < nr; i++ )
783 if( i == 0 && nr > 1 && serial->p[i] == 0x0 )
786 ret = mbedtls_snprintf( p, n, "%02X%s",
787 serial->p[i], ( i < nr - 1 ) ? ":" : "" );
788 MBEDTLS_X509_SAFE_SNPRINTF;
791 if( nr != serial->len )
793 ret = mbedtls_snprintf( p, n, "...." );
794 MBEDTLS_X509_SAFE_SNPRINTF;
797 return( (int) ( size - n ) );
801 * Helper for writing signature algorithms
803 int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
804 mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
805 const void *sig_opts )
810 const char *desc = NULL;
812 ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc );
814 ret = mbedtls_snprintf( p, n, "???" );
816 ret = mbedtls_snprintf( p, n, "%s", desc );
817 MBEDTLS_X509_SAFE_SNPRINTF;
819 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
820 if( pk_alg == MBEDTLS_PK_RSASSA_PSS )
822 const mbedtls_pk_rsassa_pss_options *pss_opts;
823 const mbedtls_md_info_t *md_info, *mgf_md_info;
825 pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
827 md_info = mbedtls_md_info_from_type( md_alg );
828 mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id );
830 ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)",
831 md_info ? mbedtls_md_get_name( md_info ) : "???",
832 mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???",
833 pss_opts->expected_salt_len );
834 MBEDTLS_X509_SAFE_SNPRINTF;
840 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
842 return( (int)( size - n ) );
846 * Helper for writing "RSA key size", "EC key size", etc
848 int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name )
854 ret = mbedtls_snprintf( p, n, "%s key size", name );
855 MBEDTLS_X509_SAFE_SNPRINTF;
860 #if defined(MBEDTLS_HAVE_TIME_DATE)
862 * Set the time structure to the current time.
863 * Return 0 on success, non-zero on failure.
865 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
866 static int x509_get_current_time( mbedtls_x509_time *now )
870 GetSystemTime( &st );
872 now->year = st.wYear;
873 now->mon = st.wMonth;
875 now->hour = st.wHour;
876 now->min = st.wMinute;
877 now->sec = st.wSecond;
882 static int x509_get_current_time( mbedtls_x509_time *now )
888 #if defined(MBEDTLS_THREADING_C)
889 if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 )
890 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
893 tt = mbedtls_time( NULL );
900 now->year = lt->tm_year + 1900;
901 now->mon = lt->tm_mon + 1;
902 now->day = lt->tm_mday;
903 now->hour = lt->tm_hour;
904 now->min = lt->tm_min;
905 now->sec = lt->tm_sec;
908 #if defined(MBEDTLS_THREADING_C)
909 if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 )
910 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
915 #endif /* _WIN32 && !EFIX64 && !EFI32 */
918 * Return 0 if before <= after, 1 otherwise
920 static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after )
922 if( before->year > after->year )
925 if( before->year == after->year &&
926 before->mon > after->mon )
929 if( before->year == after->year &&
930 before->mon == after->mon &&
931 before->day > after->day )
934 if( before->year == after->year &&
935 before->mon == after->mon &&
936 before->day == after->day &&
937 before->hour > after->hour )
940 if( before->year == after->year &&
941 before->mon == after->mon &&
942 before->day == after->day &&
943 before->hour == after->hour &&
944 before->min > after->min )
947 if( before->year == after->year &&
948 before->mon == after->mon &&
949 before->day == after->day &&
950 before->hour == after->hour &&
951 before->min == after->min &&
952 before->sec > after->sec )
958 int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
960 mbedtls_x509_time now;
962 if( x509_get_current_time( &now ) != 0 )
965 return( x509_check_time( &now, to ) );
968 int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
970 mbedtls_x509_time now;
972 if( x509_get_current_time( &now ) != 0 )
975 return( x509_check_time( from, &now ) );
978 #else /* MBEDTLS_HAVE_TIME_DATE */
980 int mbedtls_x509_time_is_past( const mbedtls_x509_time *to )
986 int mbedtls_x509_time_is_future( const mbedtls_x509_time *from )
991 #endif /* MBEDTLS_HAVE_TIME_DATE */
993 #if defined(MBEDTLS_SELF_TEST)
995 #include "mbedtls/x509_crt.h"
996 #include "mbedtls/certs.h"
1001 int mbedtls_x509_self_test( int verbose )
1003 #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA1_C)
1006 mbedtls_x509_crt cacert;
1007 mbedtls_x509_crt clicert;
1010 mbedtls_printf( " X.509 certificate load: " );
1012 mbedtls_x509_crt_init( &clicert );
1014 ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
1015 mbedtls_test_cli_crt_len );
1019 mbedtls_printf( "failed\n" );
1024 mbedtls_x509_crt_init( &cacert );
1026 ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt,
1027 mbedtls_test_ca_crt_len );
1031 mbedtls_printf( "failed\n" );
1037 mbedtls_printf( "passed\n X.509 signature verify: ");
1039 ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL );
1043 mbedtls_printf( "failed\n" );
1049 mbedtls_printf( "passed\n\n");
1051 mbedtls_x509_crt_free( &cacert );
1052 mbedtls_x509_crt_free( &clicert );
1058 #endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */
1061 #endif /* MBEDTLS_SELF_TEST */
1063 #endif /* MBEDTLS_X509_USE_C */