2 * X.509 common functions for parsing and verification
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: GPL-2.0
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * This file is part of mbed TLS (https://tls.mbed.org)
24 * The ITU-T X.509 standard defines a certificate format for PKI.
26 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
27 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
28 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
30 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
31 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
34 /* Ensure gmtime_r is available even with -std=c99; must be included before
35 * config.h, which pulls in glibc's features.h. Harmless on other platforms. */
36 #define _POSIX_C_SOURCE 200112L
38 #if !defined(MBEDTLS_CONFIG_FILE)
39 #include "mbedtls/config.h"
41 #include MBEDTLS_CONFIG_FILE
44 #if defined(MBEDTLS_X509_USE_C)
46 #include "mbedtls/x509.h"
47 #include "mbedtls/asn1.h"
48 #include "mbedtls/oid.h"
53 #if defined(MBEDTLS_PEM_PARSE_C)
54 #include "mbedtls/pem.h"
57 #if defined(MBEDTLS_PLATFORM_C)
58 #include "mbedtls/platform.h"
62 #define mbedtls_free free
63 #define mbedtls_calloc calloc
64 #define mbedtls_printf printf
65 #define mbedtls_snprintf snprintf
68 #if defined(MBEDTLS_HAVE_TIME)
69 #include "mbedtls/platform_time.h"
71 #if defined(MBEDTLS_HAVE_TIME_DATE)
75 #define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); }
76 #define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); }
79 * CertificateSerialNumber ::= INTEGER
81 int mbedtls_x509_get_serial( unsigned char **p
, const unsigned char *end
,
82 mbedtls_x509_buf
*serial
)
86 if( ( end
- *p
) < 1 )
87 return( MBEDTLS_ERR_X509_INVALID_SERIAL
+
88 MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
90 if( **p
!= ( MBEDTLS_ASN1_CONTEXT_SPECIFIC
| MBEDTLS_ASN1_PRIMITIVE
| 2 ) &&
91 **p
!= MBEDTLS_ASN1_INTEGER
)
92 return( MBEDTLS_ERR_X509_INVALID_SERIAL
+
93 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
);
95 serial
->tag
= *(*p
)++;
97 if( ( ret
= mbedtls_asn1_get_len( p
, end
, &serial
->len
) ) != 0 )
98 return( MBEDTLS_ERR_X509_INVALID_SERIAL
+ ret
);
106 /* Get an algorithm identifier without parameters (eg for signatures)
108 * AlgorithmIdentifier ::= SEQUENCE {
109 * algorithm OBJECT IDENTIFIER,
110 * parameters ANY DEFINED BY algorithm OPTIONAL }
112 int mbedtls_x509_get_alg_null( unsigned char **p
, const unsigned char *end
,
113 mbedtls_x509_buf
*alg
)
117 if( ( ret
= mbedtls_asn1_get_alg_null( p
, end
, alg
) ) != 0 )
118 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
124 * Parse an algorithm identifier with (optional) paramaters
126 int mbedtls_x509_get_alg( unsigned char **p
, const unsigned char *end
,
127 mbedtls_x509_buf
*alg
, mbedtls_x509_buf
*params
)
131 if( ( ret
= mbedtls_asn1_get_alg( p
, end
, alg
, params
) ) != 0 )
132 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
137 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
139 * HashAlgorithm ::= AlgorithmIdentifier
141 * AlgorithmIdentifier ::= SEQUENCE {
142 * algorithm OBJECT IDENTIFIER,
143 * parameters ANY DEFINED BY algorithm OPTIONAL }
145 * For HashAlgorithm, parameters MUST be NULL or absent.
147 static int x509_get_hash_alg( const mbedtls_x509_buf
*alg
, mbedtls_md_type_t
*md_alg
)
151 const unsigned char *end
;
152 mbedtls_x509_buf md_oid
;
155 /* Make sure we got a SEQUENCE and setup bounds */
156 if( alg
->tag
!= ( MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) )
157 return( MBEDTLS_ERR_X509_INVALID_ALG
+
158 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
);
160 p
= (unsigned char *) alg
->p
;
164 return( MBEDTLS_ERR_X509_INVALID_ALG
+
165 MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
170 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &md_oid
.len
, MBEDTLS_ASN1_OID
) ) != 0 )
171 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
176 /* Get md_alg from md_oid */
177 if( ( ret
= mbedtls_oid_get_md_alg( &md_oid
, md_alg
) ) != 0 )
178 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
180 /* Make sure params is absent of NULL */
184 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &len
, MBEDTLS_ASN1_NULL
) ) != 0 || len
!= 0 )
185 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
188 return( MBEDTLS_ERR_X509_INVALID_ALG
+
189 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
195 * RSASSA-PSS-params ::= SEQUENCE {
196 * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
197 * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
198 * saltLength [2] INTEGER DEFAULT 20,
199 * trailerField [3] INTEGER DEFAULT 1 }
200 * -- Note that the tags in this Sequence are explicit.
202 * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
203 * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
204 * option. Enfore this at parsing time.
206 int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf
*params
,
207 mbedtls_md_type_t
*md_alg
, mbedtls_md_type_t
*mgf_md
,
212 const unsigned char *end
, *end2
;
214 mbedtls_x509_buf alg_id
, alg_params
;
216 /* First set everything to defaults */
217 *md_alg
= MBEDTLS_MD_SHA1
;
218 *mgf_md
= MBEDTLS_MD_SHA1
;
221 /* Make sure params is a SEQUENCE and setup bounds */
222 if( params
->tag
!= ( MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) )
223 return( MBEDTLS_ERR_X509_INVALID_ALG
+
224 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
);
226 p
= (unsigned char *) params
->p
;
227 end
= p
+ params
->len
;
235 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &len
,
236 MBEDTLS_ASN1_CONTEXT_SPECIFIC
| MBEDTLS_ASN1_CONSTRUCTED
| 0 ) ) == 0 )
240 /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
241 if( ( ret
= mbedtls_x509_get_alg_null( &p
, end2
, &alg_id
) ) != 0 )
244 if( ( ret
= mbedtls_oid_get_md_alg( &alg_id
, md_alg
) ) != 0 )
245 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
248 return( MBEDTLS_ERR_X509_INVALID_ALG
+
249 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
251 else if( ret
!= MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
252 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
260 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &len
,
261 MBEDTLS_ASN1_CONTEXT_SPECIFIC
| MBEDTLS_ASN1_CONSTRUCTED
| 1 ) ) == 0 )
265 /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
266 if( ( ret
= mbedtls_x509_get_alg( &p
, end2
, &alg_id
, &alg_params
) ) != 0 )
269 /* Only MFG1 is recognised for now */
270 if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1
, &alg_id
) != 0 )
271 return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE
+
272 MBEDTLS_ERR_OID_NOT_FOUND
);
274 /* Parse HashAlgorithm */
275 if( ( ret
= x509_get_hash_alg( &alg_params
, mgf_md
) ) != 0 )
279 return( MBEDTLS_ERR_X509_INVALID_ALG
+
280 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
282 else if( ret
!= MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
283 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
291 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &len
,
292 MBEDTLS_ASN1_CONTEXT_SPECIFIC
| MBEDTLS_ASN1_CONSTRUCTED
| 2 ) ) == 0 )
296 if( ( ret
= mbedtls_asn1_get_int( &p
, end2
, salt_len
) ) != 0 )
297 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
300 return( MBEDTLS_ERR_X509_INVALID_ALG
+
301 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
303 else if( ret
!= MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
304 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
310 * trailer_field (if present, must be 1)
312 if( ( ret
= mbedtls_asn1_get_tag( &p
, end
, &len
,
313 MBEDTLS_ASN1_CONTEXT_SPECIFIC
| MBEDTLS_ASN1_CONSTRUCTED
| 3 ) ) == 0 )
319 if( ( ret
= mbedtls_asn1_get_int( &p
, end2
, &trailer_field
) ) != 0 )
320 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
323 return( MBEDTLS_ERR_X509_INVALID_ALG
+
324 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
326 if( trailer_field
!= 1 )
327 return( MBEDTLS_ERR_X509_INVALID_ALG
);
329 else if( ret
!= MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
)
330 return( MBEDTLS_ERR_X509_INVALID_ALG
+ ret
);
333 return( MBEDTLS_ERR_X509_INVALID_ALG
+
334 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
338 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
341 * AttributeTypeAndValue ::= SEQUENCE {
342 * type AttributeType,
343 * value AttributeValue }
345 * AttributeType ::= OBJECT IDENTIFIER
347 * AttributeValue ::= ANY DEFINED BY AttributeType
349 static int x509_get_attr_type_value( unsigned char **p
,
350 const unsigned char *end
,
351 mbedtls_x509_name
*cur
)
355 mbedtls_x509_buf
*oid
;
356 mbedtls_x509_buf
*val
;
358 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &len
,
359 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
360 return( MBEDTLS_ERR_X509_INVALID_NAME
+ ret
);
362 if( ( end
- *p
) < 1 )
363 return( MBEDTLS_ERR_X509_INVALID_NAME
+
364 MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
369 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &oid
->len
, MBEDTLS_ASN1_OID
) ) != 0 )
370 return( MBEDTLS_ERR_X509_INVALID_NAME
+ ret
);
375 if( ( end
- *p
) < 1 )
376 return( MBEDTLS_ERR_X509_INVALID_NAME
+
377 MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
379 if( **p
!= MBEDTLS_ASN1_BMP_STRING
&& **p
!= MBEDTLS_ASN1_UTF8_STRING
&&
380 **p
!= MBEDTLS_ASN1_T61_STRING
&& **p
!= MBEDTLS_ASN1_PRINTABLE_STRING
&&
381 **p
!= MBEDTLS_ASN1_IA5_STRING
&& **p
!= MBEDTLS_ASN1_UNIVERSAL_STRING
&&
382 **p
!= MBEDTLS_ASN1_BIT_STRING
)
383 return( MBEDTLS_ERR_X509_INVALID_NAME
+
384 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
);
389 if( ( ret
= mbedtls_asn1_get_len( p
, end
, &val
->len
) ) != 0 )
390 return( MBEDTLS_ERR_X509_INVALID_NAME
+ ret
);
401 * Name ::= CHOICE { -- only one possibility for now --
402 * rdnSequence RDNSequence }
404 * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
406 * RelativeDistinguishedName ::=
407 * SET OF AttributeTypeAndValue
409 * AttributeTypeAndValue ::= SEQUENCE {
410 * type AttributeType,
411 * value AttributeValue }
413 * AttributeType ::= OBJECT IDENTIFIER
415 * AttributeValue ::= ANY DEFINED BY AttributeType
417 * The data structure is optimized for the common case where each RDN has only
418 * one element, which is represented as a list of AttributeTypeAndValue.
419 * For the general case we still use a flat list, but we mark elements of the
420 * same set so that they are "merged" together in the functions that consume
421 * this list, eg mbedtls_x509_dn_gets().
423 int mbedtls_x509_get_name( unsigned char **p
, const unsigned char *end
,
424 mbedtls_x509_name
*cur
)
428 const unsigned char *end_set
;
430 /* don't use recursion, we'd risk stack overflow if not optimized */
436 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &set_len
,
437 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SET
) ) != 0 )
438 return( MBEDTLS_ERR_X509_INVALID_NAME
+ ret
);
440 end_set
= *p
+ set_len
;
444 if( ( ret
= x509_get_attr_type_value( p
, end_set
, cur
) ) != 0 )
450 /* Mark this item as being no the only one in a set */
451 cur
->next_merged
= 1;
453 cur
->next
= mbedtls_calloc( 1, sizeof( mbedtls_x509_name
) );
455 if( cur
->next
== NULL
)
456 return( MBEDTLS_ERR_X509_ALLOC_FAILED
);
462 * continue until end of SEQUENCE is reached
467 cur
->next
= mbedtls_calloc( 1, sizeof( mbedtls_x509_name
) );
469 if( cur
->next
== NULL
)
470 return( MBEDTLS_ERR_X509_ALLOC_FAILED
);
476 static int x509_parse_int( unsigned char **p
, size_t n
, int *res
)
482 if( ( **p
< '0') || ( **p
> '9' ) )
483 return ( MBEDTLS_ERR_X509_INVALID_DATE
);
486 *res
+= ( *(*p
)++ - '0' );
492 static int x509_date_is_valid(const mbedtls_x509_time
*t
)
494 int ret
= MBEDTLS_ERR_X509_INVALID_DATE
;
497 CHECK_RANGE( 0, 9999, t
->year
);
498 CHECK_RANGE( 0, 23, t
->hour
);
499 CHECK_RANGE( 0, 59, t
->min
);
500 CHECK_RANGE( 0, 59, t
->sec
);
504 case 1: case 3: case 5: case 7: case 8: case 10: case 12:
507 case 4: case 6: case 9: case 11:
511 if( ( !( t
->year
% 4 ) && t
->year
% 100 ) ||
520 CHECK_RANGE( 1, month_len
, t
->day
);
526 * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
529 static int x509_parse_time( unsigned char **p
, size_t len
, size_t yearlen
,
530 mbedtls_x509_time
*tm
)
535 * Minimum length is 10 or 12 depending on yearlen
537 if ( len
< yearlen
+ 8 )
538 return ( MBEDTLS_ERR_X509_INVALID_DATE
);
542 * Parse year, month, day, hour, minute
544 CHECK( x509_parse_int( p
, yearlen
, &tm
->year
) );
553 CHECK( x509_parse_int( p
, 2, &tm
->mon
) );
554 CHECK( x509_parse_int( p
, 2, &tm
->day
) );
555 CHECK( x509_parse_int( p
, 2, &tm
->hour
) );
556 CHECK( x509_parse_int( p
, 2, &tm
->min
) );
559 * Parse seconds if present
563 CHECK( x509_parse_int( p
, 2, &tm
->sec
) );
567 return ( MBEDTLS_ERR_X509_INVALID_DATE
);
570 * Parse trailing 'Z' if present
572 if ( 1 == len
&& 'Z' == **p
)
579 * We should have parsed all characters at this point
582 return ( MBEDTLS_ERR_X509_INVALID_DATE
);
584 CHECK( x509_date_is_valid( tm
) );
592 * generalTime GeneralizedTime }
594 int mbedtls_x509_get_time( unsigned char **p
, const unsigned char *end
,
595 mbedtls_x509_time
*tm
)
598 size_t len
, year_len
;
601 if( ( end
- *p
) < 1 )
602 return( MBEDTLS_ERR_X509_INVALID_DATE
+
603 MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
607 if( tag
== MBEDTLS_ASN1_UTC_TIME
)
609 else if( tag
== MBEDTLS_ASN1_GENERALIZED_TIME
)
612 return( MBEDTLS_ERR_X509_INVALID_DATE
+
613 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
);
616 ret
= mbedtls_asn1_get_len( p
, end
, &len
);
619 return( MBEDTLS_ERR_X509_INVALID_DATE
+ ret
);
621 return x509_parse_time( p
, len
, year_len
, tm
);
624 int mbedtls_x509_get_sig( unsigned char **p
, const unsigned char *end
, mbedtls_x509_buf
*sig
)
630 if( ( end
- *p
) < 1 )
631 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE
+
632 MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
636 if( ( ret
= mbedtls_asn1_get_bitstring_null( p
, end
, &len
) ) != 0 )
637 return( MBEDTLS_ERR_X509_INVALID_SIGNATURE
+ ret
);
649 * Get signature algorithm from alg OID and optional parameters
651 int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf
*sig_oid
, const mbedtls_x509_buf
*sig_params
,
652 mbedtls_md_type_t
*md_alg
, mbedtls_pk_type_t
*pk_alg
,
657 if( *sig_opts
!= NULL
)
658 return( MBEDTLS_ERR_X509_BAD_INPUT_DATA
);
660 if( ( ret
= mbedtls_oid_get_sig_alg( sig_oid
, md_alg
, pk_alg
) ) != 0 )
661 return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG
+ ret
);
663 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
664 if( *pk_alg
== MBEDTLS_PK_RSASSA_PSS
)
666 mbedtls_pk_rsassa_pss_options
*pss_opts
;
668 pss_opts
= mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options
) );
669 if( pss_opts
== NULL
)
670 return( MBEDTLS_ERR_X509_ALLOC_FAILED
);
672 ret
= mbedtls_x509_get_rsassa_pss_params( sig_params
,
674 &pss_opts
->mgf1_hash_id
,
675 &pss_opts
->expected_salt_len
);
678 mbedtls_free( pss_opts
);
682 *sig_opts
= (void *) pss_opts
;
685 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
687 /* Make sure parameters are absent or NULL */
688 if( ( sig_params
->tag
!= MBEDTLS_ASN1_NULL
&& sig_params
->tag
!= 0 ) ||
689 sig_params
->len
!= 0 )
690 return( MBEDTLS_ERR_X509_INVALID_ALG
);
697 * X.509 Extensions (No parsing of extensions, pointer should
698 * be either manually updated or extensions should be parsed!)
700 int mbedtls_x509_get_ext( unsigned char **p
, const unsigned char *end
,
701 mbedtls_x509_buf
*ext
, int tag
)
711 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &ext
->len
,
712 MBEDTLS_ASN1_CONTEXT_SPECIFIC
| MBEDTLS_ASN1_CONSTRUCTED
| tag
) ) != 0 )
719 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
721 * Extension ::= SEQUENCE {
722 * extnID OBJECT IDENTIFIER,
723 * critical BOOLEAN DEFAULT FALSE,
724 * extnValue OCTET STRING }
726 if( ( ret
= mbedtls_asn1_get_tag( p
, end
, &len
,
727 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
) ) != 0 )
728 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+ ret
);
730 if( end
!= *p
+ len
)
731 return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS
+
732 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
738 * Store the name in printable form into buf; no more
739 * than size characters will be written
741 int mbedtls_x509_dn_gets( char *buf
, size_t size
, const mbedtls_x509_name
*dn
)
745 unsigned char c
, merge
= 0;
746 const mbedtls_x509_name
*name
;
747 const char *short_name
= NULL
;
748 char s
[MBEDTLS_X509_MAX_DN_NAME_SIZE
], *p
;
750 memset( s
, 0, sizeof( s
) );
756 while( name
!= NULL
)
766 ret
= mbedtls_snprintf( p
, n
, merge
? " + " : ", " );
767 MBEDTLS_X509_SAFE_SNPRINTF
;
770 ret
= mbedtls_oid_get_attr_short_name( &name
->oid
, &short_name
);
773 ret
= mbedtls_snprintf( p
, n
, "%s=", short_name
);
775 ret
= mbedtls_snprintf( p
, n
, "\?\?=" );
776 MBEDTLS_X509_SAFE_SNPRINTF
;
778 for( i
= 0; i
< name
->val
.len
; i
++ )
780 if( i
>= sizeof( s
) - 1 )
784 if( c
< 32 || c
== 127 || ( c
> 128 && c
< 160 ) )
789 ret
= mbedtls_snprintf( p
, n
, "%s", s
);
790 MBEDTLS_X509_SAFE_SNPRINTF
;
792 merge
= name
->next_merged
;
796 return( (int) ( size
- n
) );
800 * Store the serial in printable form into buf; no more
801 * than size characters will be written
803 int mbedtls_x509_serial_gets( char *buf
, size_t size
, const mbedtls_x509_buf
*serial
)
812 nr
= ( serial
->len
<= 32 )
815 for( i
= 0; i
< nr
; i
++ )
817 if( i
== 0 && nr
> 1 && serial
->p
[i
] == 0x0 )
820 ret
= mbedtls_snprintf( p
, n
, "%02X%s",
821 serial
->p
[i
], ( i
< nr
- 1 ) ? ":" : "" );
822 MBEDTLS_X509_SAFE_SNPRINTF
;
825 if( nr
!= serial
->len
)
827 ret
= mbedtls_snprintf( p
, n
, "...." );
828 MBEDTLS_X509_SAFE_SNPRINTF
;
831 return( (int) ( size
- n
) );
835 * Helper for writing signature algorithms
837 int mbedtls_x509_sig_alg_gets( char *buf
, size_t size
, const mbedtls_x509_buf
*sig_oid
,
838 mbedtls_pk_type_t pk_alg
, mbedtls_md_type_t md_alg
,
839 const void *sig_opts
)
844 const char *desc
= NULL
;
846 ret
= mbedtls_oid_get_sig_alg_desc( sig_oid
, &desc
);
848 ret
= mbedtls_snprintf( p
, n
, "???" );
850 ret
= mbedtls_snprintf( p
, n
, "%s", desc
);
851 MBEDTLS_X509_SAFE_SNPRINTF
;
853 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
854 if( pk_alg
== MBEDTLS_PK_RSASSA_PSS
)
856 const mbedtls_pk_rsassa_pss_options
*pss_opts
;
857 const mbedtls_md_info_t
*md_info
, *mgf_md_info
;
859 pss_opts
= (const mbedtls_pk_rsassa_pss_options
*) sig_opts
;
861 md_info
= mbedtls_md_info_from_type( md_alg
);
862 mgf_md_info
= mbedtls_md_info_from_type( pss_opts
->mgf1_hash_id
);
864 ret
= mbedtls_snprintf( p
, n
, " (%s, MGF1-%s, 0x%02X)",
865 md_info
? mbedtls_md_get_name( md_info
) : "???",
866 mgf_md_info
? mbedtls_md_get_name( mgf_md_info
) : "???",
867 pss_opts
->expected_salt_len
);
868 MBEDTLS_X509_SAFE_SNPRINTF
;
874 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
876 return( (int)( size
- n
) );
880 * Helper for writing "RSA key size", "EC key size", etc
882 int mbedtls_x509_key_size_helper( char *buf
, size_t buf_size
, const char *name
)
888 ret
= mbedtls_snprintf( p
, n
, "%s key size", name
);
889 MBEDTLS_X509_SAFE_SNPRINTF
;
894 #if defined(MBEDTLS_HAVE_TIME_DATE)
896 * Set the time structure to the current time.
897 * Return 0 on success, non-zero on failure.
899 static int x509_get_current_time( mbedtls_x509_time
*now
)
901 struct tm
*lt
, tm_buf
;
905 tt
= mbedtls_time( NULL
);
906 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
907 lt
= gmtime_s( &tm_buf
, &tt
) == 0 ? &tm_buf
: NULL
;
909 lt
= gmtime_r( &tt
, &tm_buf
);
916 now
->year
= lt
->tm_year
+ 1900;
917 now
->mon
= lt
->tm_mon
+ 1;
918 now
->day
= lt
->tm_mday
;
919 now
->hour
= lt
->tm_hour
;
920 now
->min
= lt
->tm_min
;
921 now
->sec
= lt
->tm_sec
;
928 * Return 0 if before <= after, 1 otherwise
930 static int x509_check_time( const mbedtls_x509_time
*before
, const mbedtls_x509_time
*after
)
932 if( before
->year
> after
->year
)
935 if( before
->year
== after
->year
&&
936 before
->mon
> after
->mon
)
939 if( before
->year
== after
->year
&&
940 before
->mon
== after
->mon
&&
941 before
->day
> after
->day
)
944 if( before
->year
== after
->year
&&
945 before
->mon
== after
->mon
&&
946 before
->day
== after
->day
&&
947 before
->hour
> after
->hour
)
950 if( before
->year
== after
->year
&&
951 before
->mon
== after
->mon
&&
952 before
->day
== after
->day
&&
953 before
->hour
== after
->hour
&&
954 before
->min
> after
->min
)
957 if( before
->year
== after
->year
&&
958 before
->mon
== after
->mon
&&
959 before
->day
== after
->day
&&
960 before
->hour
== after
->hour
&&
961 before
->min
== after
->min
&&
962 before
->sec
> after
->sec
)
968 int mbedtls_x509_time_is_past( const mbedtls_x509_time
*to
)
970 mbedtls_x509_time now
;
972 if( x509_get_current_time( &now
) != 0 )
975 return( x509_check_time( &now
, to
) );
978 int mbedtls_x509_time_is_future( const mbedtls_x509_time
*from
)
980 mbedtls_x509_time now
;
982 if( x509_get_current_time( &now
) != 0 )
985 return( x509_check_time( from
, &now
) );
988 #else /* MBEDTLS_HAVE_TIME_DATE */
990 int mbedtls_x509_time_is_past( const mbedtls_x509_time
*to
)
996 int mbedtls_x509_time_is_future( const mbedtls_x509_time
*from
)
1001 #endif /* MBEDTLS_HAVE_TIME_DATE */
1003 #if defined(MBEDTLS_SELF_TEST)
1005 #include "mbedtls/x509_crt.h"
1006 #include "mbedtls/certs.h"
1011 int mbedtls_x509_self_test( int verbose
)
1013 #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C)
1016 mbedtls_x509_crt cacert
;
1017 mbedtls_x509_crt clicert
;
1020 mbedtls_printf( " X.509 certificate load: " );
1022 mbedtls_x509_crt_init( &clicert
);
1024 ret
= mbedtls_x509_crt_parse( &clicert
, (const unsigned char *) mbedtls_test_cli_crt
,
1025 mbedtls_test_cli_crt_len
);
1029 mbedtls_printf( "failed\n" );
1034 mbedtls_x509_crt_init( &cacert
);
1036 ret
= mbedtls_x509_crt_parse( &cacert
, (const unsigned char *) mbedtls_test_ca_crt
,
1037 mbedtls_test_ca_crt_len
);
1041 mbedtls_printf( "failed\n" );
1047 mbedtls_printf( "passed\n X.509 signature verify: ");
1049 ret
= mbedtls_x509_crt_verify( &clicert
, &cacert
, NULL
, NULL
, &flags
, NULL
, NULL
);
1053 mbedtls_printf( "failed\n" );
1059 mbedtls_printf( "passed\n\n");
1061 mbedtls_x509_crt_free( &cacert
);
1062 mbedtls_x509_crt_free( &clicert
);
1068 #endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */
1071 #endif /* MBEDTLS_SELF_TEST */
1073 #endif /* MBEDTLS_X509_USE_C */