xref: /reactos/dll/3rdparty/mbedtls/x509_create.c (revision c2c66aff)
1 /*
2  *  X.509 base functions for creating certificates / CSRs
3  *
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5  *  SPDX-License-Identifier: GPL-2.0
6  *
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.
11  *
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.
16  *
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.
20  *
21  *  This file is part of mbed TLS (https://tls.mbed.org)
22  */
23 
24 #if !defined(MBEDTLS_CONFIG_FILE)
25 #include "mbedtls/config.h"
26 #else
27 #include MBEDTLS_CONFIG_FILE
28 #endif
29 
30 #if defined(MBEDTLS_X509_CREATE_C)
31 
32 #include "mbedtls/x509.h"
33 #include "mbedtls/asn1write.h"
34 #include "mbedtls/oid.h"
35 
36 #include <string.h>
37 
38 typedef struct {
39     const char *name;
40     size_t name_len;
41     const char*oid;
42 } x509_attr_descriptor_t;
43 
44 #define ADD_STRLEN( s )     s, sizeof( s ) - 1
45 
46 static const x509_attr_descriptor_t x509_attrs[] =
47 {
48     { ADD_STRLEN( "CN" ),                       MBEDTLS_OID_AT_CN },
49     { ADD_STRLEN( "commonName" ),               MBEDTLS_OID_AT_CN },
50     { ADD_STRLEN( "C" ),                        MBEDTLS_OID_AT_COUNTRY },
51     { ADD_STRLEN( "countryName" ),              MBEDTLS_OID_AT_COUNTRY },
52     { ADD_STRLEN( "O" ),                        MBEDTLS_OID_AT_ORGANIZATION },
53     { ADD_STRLEN( "organizationName" ),         MBEDTLS_OID_AT_ORGANIZATION },
54     { ADD_STRLEN( "L" ),                        MBEDTLS_OID_AT_LOCALITY },
55     { ADD_STRLEN( "locality" ),                 MBEDTLS_OID_AT_LOCALITY },
56     { ADD_STRLEN( "R" ),                        MBEDTLS_OID_PKCS9_EMAIL },
57     { ADD_STRLEN( "OU" ),                       MBEDTLS_OID_AT_ORG_UNIT },
58     { ADD_STRLEN( "organizationalUnitName" ),   MBEDTLS_OID_AT_ORG_UNIT },
59     { ADD_STRLEN( "ST" ),                       MBEDTLS_OID_AT_STATE },
60     { ADD_STRLEN( "stateOrProvinceName" ),      MBEDTLS_OID_AT_STATE },
61     { ADD_STRLEN( "emailAddress" ),             MBEDTLS_OID_PKCS9_EMAIL },
62     { ADD_STRLEN( "serialNumber" ),             MBEDTLS_OID_AT_SERIAL_NUMBER },
63     { ADD_STRLEN( "postalAddress" ),            MBEDTLS_OID_AT_POSTAL_ADDRESS },
64     { ADD_STRLEN( "postalCode" ),               MBEDTLS_OID_AT_POSTAL_CODE },
65     { ADD_STRLEN( "dnQualifier" ),              MBEDTLS_OID_AT_DN_QUALIFIER },
66     { ADD_STRLEN( "title" ),                    MBEDTLS_OID_AT_TITLE },
67     { ADD_STRLEN( "surName" ),                  MBEDTLS_OID_AT_SUR_NAME },
68     { ADD_STRLEN( "SN" ),                       MBEDTLS_OID_AT_SUR_NAME },
69     { ADD_STRLEN( "givenName" ),                MBEDTLS_OID_AT_GIVEN_NAME },
70     { ADD_STRLEN( "GN" ),                       MBEDTLS_OID_AT_GIVEN_NAME },
71     { ADD_STRLEN( "initials" ),                 MBEDTLS_OID_AT_INITIALS },
72     { ADD_STRLEN( "pseudonym" ),                MBEDTLS_OID_AT_PSEUDONYM },
73     { ADD_STRLEN( "generationQualifier" ),      MBEDTLS_OID_AT_GENERATION_QUALIFIER },
74     { ADD_STRLEN( "domainComponent" ),          MBEDTLS_OID_DOMAIN_COMPONENT },
75     { ADD_STRLEN( "DC" ),                       MBEDTLS_OID_DOMAIN_COMPONENT },
76     { NULL, 0, NULL }
77 };
78 
79 static const char *x509_at_oid_from_name( const char *name, size_t name_len )
80 {
81     const x509_attr_descriptor_t *cur;
82 
83     for( cur = x509_attrs; cur->name != NULL; cur++ )
84         if( cur->name_len == name_len &&
85             strncmp( cur->name, name, name_len ) == 0 )
86             break;
87 
88     return( cur->oid );
89 }
90 
91 int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name )
92 {
93     int ret = 0;
94     const char *s = name, *c = s;
95     const char *end = s + strlen( s );
96     const char *oid = NULL;
97     int in_tag = 1;
98     char data[MBEDTLS_X509_MAX_DN_NAME_SIZE];
99     char *d = data;
100 
101     /* Clear existing chain if present */
102     mbedtls_asn1_free_named_data_list( head );
103 
104     while( c <= end )
105     {
106         if( in_tag && *c == '=' )
107         {
108             if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL )
109             {
110                 ret = MBEDTLS_ERR_X509_UNKNOWN_OID;
111                 goto exit;
112             }
113 
114             s = c + 1;
115             in_tag = 0;
116             d = data;
117         }
118 
119         if( !in_tag && *c == '\\' && c != end )
120         {
121             c++;
122 
123             /* Check for valid escaped characters */
124             if( c == end || *c != ',' )
125             {
126                 ret = MBEDTLS_ERR_X509_INVALID_NAME;
127                 goto exit;
128             }
129         }
130         else if( !in_tag && ( *c == ',' || c == end ) )
131         {
132             if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ),
133                                        (unsigned char *) data,
134                                        d - data ) == NULL )
135             {
136                 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
137             }
138 
139             while( c < end && *(c + 1) == ' ' )
140                 c++;
141 
142             s = c + 1;
143             in_tag = 1;
144         }
145 
146         if( !in_tag && s != c + 1 )
147         {
148             *(d++) = *c;
149 
150             if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE )
151             {
152                 ret = MBEDTLS_ERR_X509_INVALID_NAME;
153                 goto exit;
154             }
155         }
156 
157         c++;
158     }
159 
160 exit:
161 
162     return( ret );
163 }
164 
165 /* The first byte of the value in the mbedtls_asn1_named_data structure is reserved
166  * to store the critical boolean for us
167  */
168 int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
169                         int critical, const unsigned char *val, size_t val_len )
170 {
171     mbedtls_asn1_named_data *cur;
172 
173     if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len,
174                                        NULL, val_len + 1 ) ) == NULL )
175     {
176         return( MBEDTLS_ERR_X509_ALLOC_FAILED );
177     }
178 
179     cur->val.p[0] = critical;
180     memcpy( cur->val.p + 1, val, val_len );
181 
182     return( 0 );
183 }
184 
185 /*
186  *  RelativeDistinguishedName ::=
187  *    SET OF AttributeTypeAndValue
188  *
189  *  AttributeTypeAndValue ::= SEQUENCE {
190  *    type     AttributeType,
191  *    value    AttributeValue }
192  *
193  *  AttributeType ::= OBJECT IDENTIFIER
194  *
195  *  AttributeValue ::= ANY DEFINED BY AttributeType
196  */
197 static int x509_write_name( unsigned char **p, unsigned char *start,
198                             const char *oid, size_t oid_len,
199                             const unsigned char *name, size_t name_len )
200 {
201     int ret;
202     size_t len = 0;
203 
204     // Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL
205     //
206     if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len &&
207         memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 )
208     {
209         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start,
210                                                   (const char *) name,
211                                                   name_len ) );
212     }
213     else
214     {
215         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start,
216                                                         (const char *) name,
217                                                         name_len ) );
218     }
219 
220     // Write OID
221     //
222     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
223 
224     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
225     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
226                                                  MBEDTLS_ASN1_SEQUENCE ) );
227 
228     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
229     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
230                                                  MBEDTLS_ASN1_SET ) );
231 
232     return( (int) len );
233 }
234 
235 int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
236                       mbedtls_asn1_named_data *first )
237 {
238     int ret;
239     size_t len = 0;
240     mbedtls_asn1_named_data *cur = first;
241 
242     while( cur != NULL )
243     {
244         MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
245                                             cur->oid.len,
246                                             cur->val.p, cur->val.len ) );
247         cur = cur->next;
248     }
249 
250     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
251     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
252                                                  MBEDTLS_ASN1_SEQUENCE ) );
253 
254     return( (int) len );
255 }
256 
257 int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,
258                     const char *oid, size_t oid_len,
259                     unsigned char *sig, size_t size )
260 {
261     int ret;
262     size_t len = 0;
263 
264     if( *p < start || (size_t)( *p - start ) < size )
265         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
266 
267     len = size;
268     (*p) -= len;
269     memcpy( *p, sig, len );
270 
271     if( *p - start < 1 )
272         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
273 
274     *--(*p) = 0;
275     len += 1;
276 
277     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
278     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
279 
280     // Write OID
281     //
282     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid,
283                                                         oid_len, 0 ) );
284 
285     return( (int) len );
286 }
287 
288 static int x509_write_extension( unsigned char **p, unsigned char *start,
289                                  mbedtls_asn1_named_data *ext )
290 {
291     int ret;
292     size_t len = 0;
293 
294     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1,
295                                               ext->val.len - 1 ) );
296     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) );
297     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
298 
299     if( ext->val.p[0] != 0 )
300     {
301         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) );
302     }
303 
304     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p,
305                                               ext->oid.len ) );
306     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) );
307     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );
308 
309     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
310     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
311                                                  MBEDTLS_ASN1_SEQUENCE ) );
312 
313     return( (int) len );
314 }
315 
316 /*
317  * Extension  ::=  SEQUENCE  {
318  *     extnID      OBJECT IDENTIFIER,
319  *     critical    BOOLEAN DEFAULT FALSE,
320  *     extnValue   OCTET STRING
321  *                 -- contains the DER encoding of an ASN.1 value
322  *                 -- corresponding to the extension type identified
323  *                 -- by extnID
324  *     }
325  */
326 int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,
327                            mbedtls_asn1_named_data *first )
328 {
329     int ret;
330     size_t len = 0;
331     mbedtls_asn1_named_data *cur_ext = first;
332 
333     while( cur_ext != NULL )
334     {
335         MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
336         cur_ext = cur_ext->next;
337     }
338 
339     return( (int) len );
340 }
341 
342 #endif /* MBEDTLS_X509_CREATE_C */
343