]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/mbedtls/library/x509_create.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / mbedtls / library / x509_create.c
1 /*\r
2  *  X.509 base functions for creating certificates / CSRs\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 #if !defined(MBEDTLS_CONFIG_FILE)\r
23 #include "mbedtls/config.h"\r
24 #else\r
25 #include MBEDTLS_CONFIG_FILE\r
26 #endif\r
27 \r
28 #if defined(MBEDTLS_X509_CREATE_C)\r
29 \r
30 #include "mbedtls/x509.h"\r
31 #include "mbedtls/asn1write.h"\r
32 #include "mbedtls/oid.h"\r
33 \r
34 #include <string.h>\r
35 \r
36 /* Structure linking OIDs for X.509 DN AttributeTypes to their\r
37  * string representations and default string encodings used by Mbed TLS. */\r
38 typedef struct {\r
39    const char *name; /* String representation of AttributeType, e.g.\r
40                       * "CN" or "emailAddress". */\r
41    size_t name_len;  /* Length of 'name', without trailing 0 byte. */\r
42    const char *oid;  /* String representation of OID of AttributeType,\r
43                       * as per RFC 5280, Appendix A.1. */\r
44    int default_tag;  /* The default character encoding used for the\r
45                       * given attribute type, e.g.\r
46                       * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */\r
47 } x509_attr_descriptor_t;\r
48 \r
49 #define ADD_STRLEN( s )     s, sizeof( s ) - 1\r
50 \r
51 /* X.509 DN attributes from RFC 5280, Appendix A.1. */\r
52 static const x509_attr_descriptor_t x509_attrs[] =\r
53 {\r
54     { ADD_STRLEN( "CN" ),\r
55       MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING },\r
56     { ADD_STRLEN( "commonName" ),\r
57       MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING },\r
58     { ADD_STRLEN( "C" ),\r
59       MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING },\r
60     { ADD_STRLEN( "countryName" ),\r
61       MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING },\r
62     { ADD_STRLEN( "O" ),\r
63       MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING },\r
64     { ADD_STRLEN( "organizationName" ),\r
65       MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING },\r
66     { ADD_STRLEN( "L" ),\r
67       MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING },\r
68     { ADD_STRLEN( "locality" ),\r
69       MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING },\r
70     { ADD_STRLEN( "R" ),\r
71       MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING },\r
72     { ADD_STRLEN( "OU" ),\r
73       MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING },\r
74     { ADD_STRLEN( "organizationalUnitName" ),\r
75       MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING },\r
76     { ADD_STRLEN( "ST" ),\r
77       MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING },\r
78     { ADD_STRLEN( "stateOrProvinceName" ),\r
79       MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING },\r
80     { ADD_STRLEN( "emailAddress" ),\r
81       MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING },\r
82     { ADD_STRLEN( "serialNumber" ),\r
83       MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING },\r
84     { ADD_STRLEN( "postalAddress" ),\r
85       MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING },\r
86     { ADD_STRLEN( "postalCode" ),\r
87       MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING },\r
88     { ADD_STRLEN( "dnQualifier" ),\r
89       MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING },\r
90     { ADD_STRLEN( "title" ),\r
91       MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING },\r
92     { ADD_STRLEN( "surName" ),\r
93       MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING },\r
94     { ADD_STRLEN( "SN" ),\r
95       MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING },\r
96     { ADD_STRLEN( "givenName" ),\r
97       MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING },\r
98     { ADD_STRLEN( "GN" ),\r
99       MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING },\r
100     { ADD_STRLEN( "initials" ),\r
101       MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING },\r
102     { ADD_STRLEN( "pseudonym" ),\r
103       MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING },\r
104     { ADD_STRLEN( "generationQualifier" ),\r
105       MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING },\r
106     { ADD_STRLEN( "domainComponent" ),\r
107       MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING },\r
108     { ADD_STRLEN( "DC" ),\r
109       MBEDTLS_OID_DOMAIN_COMPONENT,   MBEDTLS_ASN1_IA5_STRING },\r
110     { NULL, 0, NULL, MBEDTLS_ASN1_NULL }\r
111 };\r
112 \r
113 static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len )\r
114 {\r
115     const x509_attr_descriptor_t *cur;\r
116 \r
117     for( cur = x509_attrs; cur->name != NULL; cur++ )\r
118         if( cur->name_len == name_len &&\r
119             strncmp( cur->name, name, name_len ) == 0 )\r
120             break;\r
121 \r
122     if ( cur->name == NULL )\r
123         return( NULL );\r
124 \r
125     return( cur );\r
126 }\r
127 \r
128 int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name )\r
129 {\r
130     int ret = 0;\r
131     const char *s = name, *c = s;\r
132     const char *end = s + strlen( s );\r
133     const char *oid = NULL;\r
134     const x509_attr_descriptor_t* attr_descr = NULL;\r
135     int in_tag = 1;\r
136     char data[MBEDTLS_X509_MAX_DN_NAME_SIZE];\r
137     char *d = data;\r
138 \r
139     /* Clear existing chain if present */\r
140     mbedtls_asn1_free_named_data_list( head );\r
141 \r
142     while( c <= end )\r
143     {\r
144         if( in_tag && *c == '=' )\r
145         {\r
146             if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL )\r
147             {\r
148                 ret = MBEDTLS_ERR_X509_UNKNOWN_OID;\r
149                 goto exit;\r
150             }\r
151 \r
152             oid = attr_descr->oid;\r
153             s = c + 1;\r
154             in_tag = 0;\r
155             d = data;\r
156         }\r
157 \r
158         if( !in_tag && *c == '\\' && c != end )\r
159         {\r
160             c++;\r
161 \r
162             /* Check for valid escaped characters */\r
163             if( c == end || *c != ',' )\r
164             {\r
165                 ret = MBEDTLS_ERR_X509_INVALID_NAME;\r
166                 goto exit;\r
167             }\r
168         }\r
169         else if( !in_tag && ( *c == ',' || c == end ) )\r
170         {\r
171             mbedtls_asn1_named_data* cur =\r
172                 mbedtls_asn1_store_named_data( head, oid, strlen( oid ),\r
173                                                (unsigned char *) data,\r
174                                                d - data );\r
175 \r
176             if(cur == NULL )\r
177             {\r
178                 return( MBEDTLS_ERR_X509_ALLOC_FAILED );\r
179             }\r
180 \r
181             // set tagType\r
182             cur->val.tag = attr_descr->default_tag;\r
183 \r
184             while( c < end && *(c + 1) == ' ' )\r
185                 c++;\r
186 \r
187             s = c + 1;\r
188             in_tag = 1;\r
189         }\r
190 \r
191         if( !in_tag && s != c + 1 )\r
192         {\r
193             *(d++) = *c;\r
194 \r
195             if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE )\r
196             {\r
197                 ret = MBEDTLS_ERR_X509_INVALID_NAME;\r
198                 goto exit;\r
199             }\r
200         }\r
201 \r
202         c++;\r
203     }\r
204 \r
205 exit:\r
206 \r
207     return( ret );\r
208 }\r
209 \r
210 /* The first byte of the value in the mbedtls_asn1_named_data structure is reserved\r
211  * to store the critical boolean for us\r
212  */\r
213 int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,\r
214                         int critical, const unsigned char *val, size_t val_len )\r
215 {\r
216     mbedtls_asn1_named_data *cur;\r
217 \r
218     if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len,\r
219                                        NULL, val_len + 1 ) ) == NULL )\r
220     {\r
221         return( MBEDTLS_ERR_X509_ALLOC_FAILED );\r
222     }\r
223 \r
224     cur->val.p[0] = critical;\r
225     memcpy( cur->val.p + 1, val, val_len );\r
226 \r
227     return( 0 );\r
228 }\r
229 \r
230 /*\r
231  *  RelativeDistinguishedName ::=\r
232  *    SET OF AttributeTypeAndValue\r
233  *\r
234  *  AttributeTypeAndValue ::= SEQUENCE {\r
235  *    type     AttributeType,\r
236  *    value    AttributeValue }\r
237  *\r
238  *  AttributeType ::= OBJECT IDENTIFIER\r
239  *\r
240  *  AttributeValue ::= ANY DEFINED BY AttributeType\r
241  */\r
242 static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name)\r
243 {\r
244     int ret;\r
245     size_t len = 0;\r
246     const char *oid             = (const char*)cur_name->oid.p;\r
247     size_t oid_len              = cur_name->oid.len;\r
248     const unsigned char *name   = cur_name->val.p;\r
249     size_t name_len             = cur_name->val.len;\r
250 \r
251     // Write correct string tag and value\r
252     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start,\r
253                                                        cur_name->val.tag,\r
254                                                        (const char *) name,\r
255                                                        name_len ) );\r
256     // Write OID\r
257     //\r
258     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid,\r
259                                                        oid_len ) );\r
260 \r
261     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );\r
262     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,\r
263                                                     MBEDTLS_ASN1_CONSTRUCTED |\r
264                                                     MBEDTLS_ASN1_SEQUENCE ) );\r
265 \r
266     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );\r
267     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,\r
268                                                  MBEDTLS_ASN1_CONSTRUCTED |\r
269                                                  MBEDTLS_ASN1_SET ) );\r
270 \r
271     return( (int) len );\r
272 }\r
273 \r
274 int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,\r
275                               mbedtls_asn1_named_data *first )\r
276 {\r
277     int ret;\r
278     size_t len = 0;\r
279     mbedtls_asn1_named_data *cur = first;\r
280 \r
281     while( cur != NULL )\r
282     {\r
283         MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) );\r
284         cur = cur->next;\r
285     }\r
286 \r
287     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );\r
288     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |\r
289                                                  MBEDTLS_ASN1_SEQUENCE ) );\r
290 \r
291     return( (int) len );\r
292 }\r
293 \r
294 int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,\r
295                     const char *oid, size_t oid_len,\r
296                     unsigned char *sig, size_t size )\r
297 {\r
298     int ret;\r
299     size_t len = 0;\r
300 \r
301     if( *p < start || (size_t)( *p - start ) < size )\r
302         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );\r
303 \r
304     len = size;\r
305     (*p) -= len;\r
306     memcpy( *p, sig, len );\r
307 \r
308     if( *p - start < 1 )\r
309         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );\r
310 \r
311     *--(*p) = 0;\r
312     len += 1;\r
313 \r
314     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );\r
315     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );\r
316 \r
317     // Write OID\r
318     //\r
319     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid,\r
320                                                         oid_len, 0 ) );\r
321 \r
322     return( (int) len );\r
323 }\r
324 \r
325 static int x509_write_extension( unsigned char **p, unsigned char *start,\r
326                                  mbedtls_asn1_named_data *ext )\r
327 {\r
328     int ret;\r
329     size_t len = 0;\r
330 \r
331     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1,\r
332                                               ext->val.len - 1 ) );\r
333     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) );\r
334     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );\r
335 \r
336     if( ext->val.p[0] != 0 )\r
337     {\r
338         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) );\r
339     }\r
340 \r
341     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p,\r
342                                               ext->oid.len ) );\r
343     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) );\r
344     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );\r
345 \r
346     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );\r
347     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |\r
348                                                  MBEDTLS_ASN1_SEQUENCE ) );\r
349 \r
350     return( (int) len );\r
351 }\r
352 \r
353 /*\r
354  * Extension  ::=  SEQUENCE  {\r
355  *     extnID      OBJECT IDENTIFIER,\r
356  *     critical    BOOLEAN DEFAULT FALSE,\r
357  *     extnValue   OCTET STRING\r
358  *                 -- contains the DER encoding of an ASN.1 value\r
359  *                 -- corresponding to the extension type identified\r
360  *                 -- by extnID\r
361  *     }\r
362  */\r
363 int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,\r
364                            mbedtls_asn1_named_data *first )\r
365 {\r
366     int ret;\r
367     size_t len = 0;\r
368     mbedtls_asn1_named_data *cur_ext = first;\r
369 \r
370     while( cur_ext != NULL )\r
371     {\r
372         MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );\r
373         cur_ext = cur_ext->next;\r
374     }\r
375 \r
376     return( (int) len );\r
377 }\r
378 \r
379 #endif /* MBEDTLS_X509_CREATE_C */\r