Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / mbedtls / repo / library / x509write_crt.c
1 /*
2  *  X.509 certificate writing
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  * References:
23  * - certificates: RFC 5280, updated by RFC 6818
24  * - CSRs: PKCS#10 v1.7 aka RFC 2986
25  * - attributes: PKCS#9 v2.0 aka RFC 2985
26  */
27
28 #if !defined(MBEDTLS_CONFIG_FILE)
29 #include "mbedtls/config.h"
30 #else
31 #include MBEDTLS_CONFIG_FILE
32 #endif
33
34 #if defined(MBEDTLS_X509_CRT_WRITE_C)
35
36 #include "mbedtls/x509_crt.h"
37 #include "mbedtls/oid.h"
38 #include "mbedtls/asn1write.h"
39 #include "mbedtls/sha1.h"
40 #include "mbedtls/platform_util.h"
41
42 #include <string.h>
43
44 #if defined(MBEDTLS_PEM_WRITE_C)
45 #include "mbedtls/pem.h"
46 #endif /* MBEDTLS_PEM_WRITE_C */
47
48 void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
49 {
50     memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
51
52     mbedtls_mpi_init( &ctx->serial );
53     ctx->version = MBEDTLS_X509_CRT_VERSION_3;
54 }
55
56 void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx )
57 {
58     mbedtls_mpi_free( &ctx->serial );
59
60     mbedtls_asn1_free_named_data_list( &ctx->subject );
61     mbedtls_asn1_free_named_data_list( &ctx->issuer );
62     mbedtls_asn1_free_named_data_list( &ctx->extensions );
63
64     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) );
65 }
66
67 void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version )
68 {
69     ctx->version = version;
70 }
71
72 void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg )
73 {
74     ctx->md_alg = md_alg;
75 }
76
77 void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
78 {
79     ctx->subject_key = key;
80 }
81
82 void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key )
83 {
84     ctx->issuer_key = key;
85 }
86
87 int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx,
88                                     const char *subject_name )
89 {
90     return mbedtls_x509_string_to_names( &ctx->subject, subject_name );
91 }
92
93 int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx,
94                                    const char *issuer_name )
95 {
96     return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name );
97 }
98
99 int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial )
100 {
101     int ret;
102
103     if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
104         return( ret );
105
106     return( 0 );
107 }
108
109 int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before,
110                                 const char *not_after )
111 {
112     if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
113         strlen( not_after )  != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 )
114     {
115         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
116     }
117     strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
118     strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN );
119     ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
120     ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
121
122     return( 0 );
123 }
124
125 int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
126                                  const char *oid, size_t oid_len,
127                                  int critical,
128                                  const unsigned char *val, size_t val_len )
129 {
130     return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,
131                                critical, val, val_len );
132 }
133
134 int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
135                                          int is_ca, int max_pathlen )
136 {
137     int ret;
138     unsigned char buf[9];
139     unsigned char *c = buf + sizeof(buf);
140     size_t len = 0;
141
142     memset( buf, 0, sizeof(buf) );
143
144     if( is_ca && max_pathlen > 127 )
145         return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
146
147     if( is_ca )
148     {
149         if( max_pathlen >= 0 )
150         {
151             MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) );
152         }
153         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) );
154     }
155
156     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
157     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
158                                                 MBEDTLS_ASN1_SEQUENCE ) );
159
160     return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
161                                         MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ),
162                                         0, buf + sizeof(buf) - len, len );
163 }
164
165 #if defined(MBEDTLS_SHA1_C)
166 int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
167 {
168     int ret;
169     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
170     unsigned char *c = buf + sizeof(buf);
171     size_t len = 0;
172
173     memset( buf, 0, sizeof(buf) );
174     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) );
175
176     ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
177                             buf + sizeof( buf ) - 20 );
178     if( ret != 0 )
179         return( ret );
180     c = buf + sizeof( buf ) - 20;
181     len = 20;
182
183     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
184     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) );
185
186     return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
187                                         MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
188                                         0, buf + sizeof(buf) - len, len );
189 }
190
191 int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
192 {
193     int ret;
194     unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
195     unsigned char *c = buf + sizeof( buf );
196     size_t len = 0;
197
198     memset( buf, 0, sizeof(buf) );
199     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) );
200
201     ret = mbedtls_sha1_ret( buf + sizeof( buf ) - len, len,
202                             buf + sizeof( buf ) - 20 );
203     if( ret != 0 )
204         return( ret );
205     c = buf + sizeof( buf ) - 20;
206     len = 20;
207
208     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
209     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) );
210
211     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
212     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
213                                                 MBEDTLS_ASN1_SEQUENCE ) );
214
215     return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
216                                    MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
217                                    0, buf + sizeof( buf ) - len, len );
218 }
219 #endif /* MBEDTLS_SHA1_C */
220
221 int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
222                                          unsigned int key_usage )
223 {
224     unsigned char buf[5], ku[2];
225     unsigned char *c;
226     int ret;
227     const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
228         MBEDTLS_X509_KU_NON_REPUDIATION   |
229         MBEDTLS_X509_KU_KEY_ENCIPHERMENT  |
230         MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
231         MBEDTLS_X509_KU_KEY_AGREEMENT     |
232         MBEDTLS_X509_KU_KEY_CERT_SIGN     |
233         MBEDTLS_X509_KU_CRL_SIGN          |
234         MBEDTLS_X509_KU_ENCIPHER_ONLY     |
235         MBEDTLS_X509_KU_DECIPHER_ONLY;
236
237     /* Check that nothing other than the allowed flags is set */
238     if( ( key_usage & ~allowed_bits ) != 0 )
239         return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE );
240
241     c = buf + 5;
242     ku[0] = (unsigned char)( key_usage      );
243     ku[1] = (unsigned char)( key_usage >> 8 );
244     ret = mbedtls_asn1_write_named_bitstring( &c, buf, ku, 9 );
245
246     if( ret < 0 )
247         return( ret );
248     else if( ret < 3 || ret > 5 )
249         return( MBEDTLS_ERR_X509_INVALID_FORMAT );
250
251     ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,
252                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),
253                                        1, c, (size_t)ret );
254     if( ret != 0 )
255         return( ret );
256
257     return( 0 );
258 }
259
260 int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
261                                     unsigned char ns_cert_type )
262 {
263     unsigned char buf[4];
264     unsigned char *c;
265     int ret;
266
267     c = buf + 4;
268
269     ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 );
270     if( ret < 3 || ret > 4 )
271         return( ret );
272
273     ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,
274                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),
275                                        0, c, (size_t)ret );
276     if( ret != 0 )
277         return( ret );
278
279     return( 0 );
280 }
281
282 static int x509_write_time( unsigned char **p, unsigned char *start,
283                             const char *t, size_t size )
284 {
285     int ret;
286     size_t len = 0;
287
288     /*
289      * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
290      */
291     if( t[0] == '2' && t[1] == '0' && t[2] < '5' )
292     {
293         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
294                                              (const unsigned char *) t + 2,
295                                              size - 2 ) );
296         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
297         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) );
298     }
299     else
300     {
301         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
302                                                   (const unsigned char *) t,
303                                                   size ) );
304         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
305         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) );
306     }
307
308     return( (int) len );
309 }
310
311 int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size,
312                        int (*f_rng)(void *, unsigned char *, size_t),
313                        void *p_rng )
314 {
315     int ret;
316     const char *sig_oid;
317     size_t sig_oid_len = 0;
318     unsigned char *c, *c2;
319     unsigned char hash[64];
320     unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
321     unsigned char tmp_buf[2048];
322     size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
323     size_t len = 0;
324     mbedtls_pk_type_t pk_alg;
325
326     /*
327      * Prepare data to be signed in tmp_buf
328      */
329     c = tmp_buf + sizeof( tmp_buf );
330
331     /* Signature algorithm needed in TBS, and later for actual signature */
332
333     /* There's no direct way of extracting a signature algorithm
334      * (represented as an element of mbedtls_pk_type_t) from a PK instance. */
335     if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) )
336         pk_alg = MBEDTLS_PK_RSA;
337     else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) )
338         pk_alg = MBEDTLS_PK_ECDSA;
339     else
340         return( MBEDTLS_ERR_X509_INVALID_ALG );
341
342     if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,
343                                           &sig_oid, &sig_oid_len ) ) != 0 )
344     {
345         return( ret );
346     }
347
348     /*
349      *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
350      */
351
352     /* Only for v3 */
353     if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 )
354     {
355         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );
356         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
357         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
358                                                            MBEDTLS_ASN1_SEQUENCE ) );
359         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
360         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
361                                                            MBEDTLS_ASN1_CONSTRUCTED | 3 ) );
362     }
363
364     /*
365      *  SubjectPublicKeyInfo
366      */
367     MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key,
368                                                 tmp_buf, c - tmp_buf ) );
369     c -= pub_len;
370     len += pub_len;
371
372     /*
373      *  Subject  ::=  Name
374      */
375     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) );
376
377     /*
378      *  Validity ::= SEQUENCE {
379      *       notBefore      Time,
380      *       notAfter       Time }
381      */
382     sub_len = 0;
383
384     MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after,
385                                             MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
386
387     MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before,
388                                             MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) );
389
390     len += sub_len;
391     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
392     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
393                                                     MBEDTLS_ASN1_SEQUENCE ) );
394
395     /*
396      *  Issuer  ::=  Name
397      */
398     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) );
399
400     /*
401      *  Signature   ::=  AlgorithmIdentifier
402      */
403     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf,
404                        sig_oid, strlen( sig_oid ), 0 ) );
405
406     /*
407      *  Serial   ::=  INTEGER
408      */
409     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) );
410
411     /*
412      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
413      */
414
415     /* Can be omitted for v1 */
416     if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 )
417     {
418         sub_len = 0;
419         MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) );
420         len += sub_len;
421         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) );
422         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC |
423                                                            MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
424     }
425
426     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );
427     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |
428                                                        MBEDTLS_ASN1_SEQUENCE ) );
429
430     /*
431      * Make signature
432      */
433     if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c,
434                             len, hash ) ) != 0 )
435     {
436         return( ret );
437     }
438
439     if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len,
440                          f_rng, p_rng ) ) != 0 )
441     {
442         return( ret );
443     }
444
445     /*
446      * Write data to output buffer
447      */
448     c2 = buf + size;
449     MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,
450                                         sig_oid, sig_oid_len, sig, sig_len ) );
451
452     if( len > (size_t)( c2 - buf ) )
453         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
454
455     c2 -= len;
456     memcpy( c2, c, len );
457
458     len += sig_and_oid_len;
459     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );
460     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED |
461                                                  MBEDTLS_ASN1_SEQUENCE ) );
462
463     return( (int) len );
464 }
465
466 #define PEM_BEGIN_CRT           "-----BEGIN CERTIFICATE-----\n"
467 #define PEM_END_CRT             "-----END CERTIFICATE-----\n"
468
469 #if defined(MBEDTLS_PEM_WRITE_C)
470 int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size,
471                        int (*f_rng)(void *, unsigned char *, size_t),
472                        void *p_rng )
473 {
474     int ret;
475     unsigned char output_buf[4096];
476     size_t olen = 0;
477
478     if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf),
479                                    f_rng, p_rng ) ) < 0 )
480     {
481         return( ret );
482     }
483
484     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT,
485                                   output_buf + sizeof(output_buf) - ret,
486                                   ret, buf, size, &olen ) ) != 0 )
487     {
488         return( ret );
489     }
490
491     return( 0 );
492 }
493 #endif /* MBEDTLS_PEM_WRITE_C */
494
495 #endif /* MBEDTLS_X509_CRT_WRITE_C */