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