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