xref: /reactos/dll/3rdparty/mbedtls/x509_create.c (revision 7b1049c8)
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 OR GPL-2.0-or-later
6  *
7  *  This file is provided under the Apache License 2.0, or the
8  *  GNU General Public License v2.0 or later.
9  *
10  *  **********
11  *  Apache License 2.0:
12  *
13  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
14  *  not use this file except in compliance with the License.
15  *  You may obtain a copy of the License at
16  *
17  *  http://www.apache.org/licenses/LICENSE-2.0
18  *
19  *  Unless required by applicable law or agreed to in writing, software
20  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22  *  See the License for the specific language governing permissions and
23  *  limitations under the License.
24  *
25  *  **********
26  *
27  *  **********
28  *  GNU General Public License v2.0 or later:
29  *
30  *  This program is free software; you can redistribute it and/or modify
31  *  it under the terms of the GNU General Public License as published by
32  *  the Free Software Foundation; either version 2 of the License, or
33  *  (at your option) any later version.
34  *
35  *  This program is distributed in the hope that it will be useful,
36  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
37  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  *  GNU General Public License for more details.
39  *
40  *  You should have received a copy of the GNU General Public License along
41  *  with this program; if not, write to the Free Software Foundation, Inc.,
42  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43  *
44  *  **********
45  *
46  *  This file is part of mbed TLS (https://tls.mbed.org)
47  */
48 
49 #if !defined(MBEDTLS_CONFIG_FILE)
50 #include "mbedtls/config.h"
51 #else
52 #include MBEDTLS_CONFIG_FILE
53 #endif
54 
55 #if defined(MBEDTLS_X509_CREATE_C)
56 
57 #include "mbedtls/x509.h"
58 #include "mbedtls/asn1write.h"
59 #include "mbedtls/oid.h"
60 
61 #include <string.h>
62 
63 typedef struct {
64     const char *name;
65     size_t name_len;
66     const char*oid;
67 } x509_attr_descriptor_t;
68 
69 #define ADD_STRLEN( s )     s, sizeof( s ) - 1
70 
71 static const x509_attr_descriptor_t x509_attrs[] =
72 {
73     { ADD_STRLEN( "CN" ),                       MBEDTLS_OID_AT_CN },
74     { ADD_STRLEN( "commonName" ),               MBEDTLS_OID_AT_CN },
75     { ADD_STRLEN( "C" ),                        MBEDTLS_OID_AT_COUNTRY },
76     { ADD_STRLEN( "countryName" ),              MBEDTLS_OID_AT_COUNTRY },
77     { ADD_STRLEN( "O" ),                        MBEDTLS_OID_AT_ORGANIZATION },
78     { ADD_STRLEN( "organizationName" ),         MBEDTLS_OID_AT_ORGANIZATION },
79     { ADD_STRLEN( "L" ),                        MBEDTLS_OID_AT_LOCALITY },
80     { ADD_STRLEN( "locality" ),                 MBEDTLS_OID_AT_LOCALITY },
81     { ADD_STRLEN( "R" ),                        MBEDTLS_OID_PKCS9_EMAIL },
82     { ADD_STRLEN( "OU" ),                       MBEDTLS_OID_AT_ORG_UNIT },
83     { ADD_STRLEN( "organizationalUnitName" ),   MBEDTLS_OID_AT_ORG_UNIT },
84     { ADD_STRLEN( "ST" ),                       MBEDTLS_OID_AT_STATE },
85     { ADD_STRLEN( "stateOrProvinceName" ),      MBEDTLS_OID_AT_STATE },
86     { ADD_STRLEN( "emailAddress" ),             MBEDTLS_OID_PKCS9_EMAIL },
87     { ADD_STRLEN( "serialNumber" ),             MBEDTLS_OID_AT_SERIAL_NUMBER },
88     { ADD_STRLEN( "postalAddress" ),            MBEDTLS_OID_AT_POSTAL_ADDRESS },
89     { ADD_STRLEN( "postalCode" ),               MBEDTLS_OID_AT_POSTAL_CODE },
90     { ADD_STRLEN( "dnQualifier" ),              MBEDTLS_OID_AT_DN_QUALIFIER },
91     { ADD_STRLEN( "title" ),                    MBEDTLS_OID_AT_TITLE },
92     { ADD_STRLEN( "surName" ),                  MBEDTLS_OID_AT_SUR_NAME },
93     { ADD_STRLEN( "SN" ),                       MBEDTLS_OID_AT_SUR_NAME },
94     { ADD_STRLEN( "givenName" ),                MBEDTLS_OID_AT_GIVEN_NAME },
95     { ADD_STRLEN( "GN" ),                       MBEDTLS_OID_AT_GIVEN_NAME },
96     { ADD_STRLEN( "initials" ),                 MBEDTLS_OID_AT_INITIALS },
97     { ADD_STRLEN( "pseudonym" ),                MBEDTLS_OID_AT_PSEUDONYM },
98     { ADD_STRLEN( "generationQualifier" ),      MBEDTLS_OID_AT_GENERATION_QUALIFIER },
99     { ADD_STRLEN( "domainComponent" ),          MBEDTLS_OID_DOMAIN_COMPONENT },
100     { ADD_STRLEN( "DC" ),                       MBEDTLS_OID_DOMAIN_COMPONENT },
101     { NULL, 0, NULL }
102 };
103 
104 static const char *x509_at_oid_from_name( const char *name, size_t name_len )
105 {
106     const x509_attr_descriptor_t *cur;
107 
108     for( cur = x509_attrs; cur->name != NULL; cur++ )
109         if( cur->name_len == name_len &&
110             strncmp( cur->name, name, name_len ) == 0 )
111             break;
112 
113     return( cur->oid );
114 }
115 
116 int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name )
117 {
118     int ret = 0;
119     const char *s = name, *c = s;
120     const char *end = s + strlen( s );
121     const char *oid = NULL;
122     int in_tag = 1;
123     char data[MBEDTLS_X509_MAX_DN_NAME_SIZE];
124     char *d = data;
125 
126     /* Clear existing chain if present */
127     mbedtls_asn1_free_named_data_list( head );
128 
129     while( c <= end )
130     {
131         if( in_tag && *c == '=' )
132         {
133             if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL )
134             {
135                 ret = MBEDTLS_ERR_X509_UNKNOWN_OID;
136                 goto exit;
137             }
138 
139             s = c + 1;
140             in_tag = 0;
141             d = data;
142         }
143 
144         if( !in_tag && *c == '\\' && c != end )
145         {
146             c++;
147 
148             /* Check for valid escaped characters */
149             if( c == end || *c != ',' )
150             {
151                 ret = MBEDTLS_ERR_X509_INVALID_NAME;
152                 goto exit;
153             }
154         }
155         else if( !in_tag && ( *c == ',' || c == end ) )
156         {
157             if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ),
158                                        (unsigned char *) data,
159                                        d - data ) == NULL )
160             {
161                 return( MBEDTLS_ERR_X509_ALLOC_FAILED );
162             }
163 
164             while( c < end && *(c + 1) == ' ' )
165                 c++;
166 
167             s = c + 1;
168             in_tag = 1;
169         }
170 
171         if( !in_tag && s != c + 1 )
172         {
173             *(d++) = *c;
174 
175             if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE )
176             {
177                 ret = MBEDTLS_ERR_X509_INVALID_NAME;
178                 goto exit;
179             }
180         }
181 
182         c++;
183     }
184 
185 exit:
186 
187     return( ret );
188 }
189 
190 /* The first byte of the value in the mbedtls_asn1_named_data structure is reserved
191  * to store the critical boolean for us
192  */
193 int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
194                         int critical, const unsigned char *val, size_t val_len )
195 {
196     mbedtls_asn1_named_data *cur;
197 
198     if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len,
199                                        NULL, val_len + 1 ) ) == NULL )
200     {
201         return( MBEDTLS_ERR_X509_ALLOC_FAILED );
202     }
203 
204     cur->val.p[0] = critical;
205     memcpy( cur->val.p + 1, val, val_len );
206 
207     return( 0 );
208 }
209 
210 /*
211  *  RelativeDistinguishedName ::=
212  *    SET OF AttributeTypeAndValue
213  *
214  *  AttributeTypeAndValue ::= SEQUENCE {
215  *    type     AttributeType,
216  *    value    AttributeValue }
217  *
218  *  AttributeType ::= OBJECT IDENTIFIER
219  *
220  *  AttributeValue ::= ANY DEFINED BY AttributeType
221  */
222 static int x509_write_name( unsigned char **p, unsigned char *start,
223                             const char *oid, size_t oid_len,
224                             const unsigned char *name, size_t name_len )
225 {
226     int ret;
227     size_t len = 0;
228 
229     // Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL
230     //
231     if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len &&
232         memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 )
233     {
234         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start,
235                                                   (const char *) name,
236                                                   name_len ) );
237     }
238     else
239     {
240         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start,
241                                                         (const char *) name,
242                                                         name_len ) );
243     }
244 
245     // Write OID
246     //
247     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
248 
249     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
250     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
251                                                  MBEDTLS_ASN1_SEQUENCE ) );
252 
253     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
254     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
255                                                  MBEDTLS_ASN1_SET ) );
256 
257     return( (int) len );
258 }
259 
260 int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
261                       mbedtls_asn1_named_data *first )
262 {
263     int ret;
264     size_t len = 0;
265     mbedtls_asn1_named_data *cur = first;
266 
267     while( cur != NULL )
268     {
269         MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p,
270                                             cur->oid.len,
271                                             cur->val.p, cur->val.len ) );
272         cur = cur->next;
273     }
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_CONSTRUCTED |
277                                                  MBEDTLS_ASN1_SEQUENCE ) );
278 
279     return( (int) len );
280 }
281 
282 int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,
283                     const char *oid, size_t oid_len,
284                     unsigned char *sig, size_t size )
285 {
286     int ret;
287     size_t len = 0;
288 
289     if( *p < start || (size_t)( *p - start ) < size )
290         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
291 
292     len = size;
293     (*p) -= len;
294     memcpy( *p, sig, len );
295 
296     if( *p - start < 1 )
297         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
298 
299     *--(*p) = 0;
300     len += 1;
301 
302     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
303     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
304 
305     // Write OID
306     //
307     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid,
308                                                         oid_len, 0 ) );
309 
310     return( (int) len );
311 }
312 
313 static int x509_write_extension( unsigned char **p, unsigned char *start,
314                                  mbedtls_asn1_named_data *ext )
315 {
316     int ret;
317     size_t len = 0;
318 
319     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1,
320                                               ext->val.len - 1 ) );
321     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) );
322     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
323 
324     if( ext->val.p[0] != 0 )
325     {
326         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) );
327     }
328 
329     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p,
330                                               ext->oid.len ) );
331     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) );
332     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );
333 
334     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
335     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
336                                                  MBEDTLS_ASN1_SEQUENCE ) );
337 
338     return( (int) len );
339 }
340 
341 /*
342  * Extension  ::=  SEQUENCE  {
343  *     extnID      OBJECT IDENTIFIER,
344  *     critical    BOOLEAN DEFAULT FALSE,
345  *     extnValue   OCTET STRING
346  *                 -- contains the DER encoding of an ASN.1 value
347  *                 -- corresponding to the extension type identified
348  *                 -- by extnID
349  *     }
350  */
351 int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,
352                            mbedtls_asn1_named_data *first )
353 {
354     int ret;
355     size_t len = 0;
356     mbedtls_asn1_named_data *cur_ext = first;
357 
358     while( cur_ext != NULL )
359     {
360         MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) );
361         cur_ext = cur_ext->next;
362     }
363 
364     return( (int) len );
365 }
366 
367 #endif /* MBEDTLS_X509_CREATE_C */
368