xref: /reactos/dll/3rdparty/mbedtls/pkwrite.c (revision 02e84521)
1 /*
2  *  Public Key layer for writing key files and structures
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_PK_WRITE_C)
31 
32 #include "mbedtls/pk.h"
33 #include "mbedtls/asn1write.h"
34 #include "mbedtls/oid.h"
35 
36 #include <string.h>
37 
38 #if defined(MBEDTLS_RSA_C)
39 #include "mbedtls/rsa.h"
40 #endif
41 #if defined(MBEDTLS_ECP_C)
42 #include "mbedtls/ecp.h"
43 #endif
44 #if defined(MBEDTLS_ECDSA_C)
45 #include "mbedtls/ecdsa.h"
46 #endif
47 #if defined(MBEDTLS_PEM_WRITE_C)
48 #include "mbedtls/pem.h"
49 #endif
50 
51 #if defined(MBEDTLS_PLATFORM_C)
52 #include "mbedtls/platform.h"
53 #else
54 #include <stdlib.h>
55 #define mbedtls_calloc    calloc
56 #define mbedtls_free       free
57 #endif
58 
59 #if defined(MBEDTLS_RSA_C)
60 /*
61  *  RSAPublicKey ::= SEQUENCE {
62  *      modulus           INTEGER,  -- n
63  *      publicExponent    INTEGER   -- e
64  *  }
65  */
66 static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
67                                 mbedtls_rsa_context *rsa )
68 {
69     int ret;
70     size_t len = 0;
71     mbedtls_mpi T;
72 
73     mbedtls_mpi_init( &T );
74 
75     /* Export E */
76     if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 ||
77          ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
78         goto end_of_export;
79     len += ret;
80 
81     /* Export N */
82     if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 ||
83          ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
84         goto end_of_export;
85     len += ret;
86 
87 end_of_export:
88 
89     mbedtls_mpi_free( &T );
90     if( ret < 0 )
91         return( ret );
92 
93     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
94     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
95                                                  MBEDTLS_ASN1_SEQUENCE ) );
96 
97     return( (int) len );
98 }
99 #endif /* MBEDTLS_RSA_C */
100 
101 #if defined(MBEDTLS_ECP_C)
102 /*
103  * EC public key is an EC point
104  */
105 static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
106                                mbedtls_ecp_keypair *ec )
107 {
108     int ret;
109     size_t len = 0;
110     unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
111 
112     if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q,
113                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
114                                         &len, buf, sizeof( buf ) ) ) != 0 )
115     {
116         return( ret );
117     }
118 
119     if( *p < start || (size_t)( *p - start ) < len )
120         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
121 
122     *p -= len;
123     memcpy( *p, buf, len );
124 
125     return( (int) len );
126 }
127 
128 /*
129  * ECParameters ::= CHOICE {
130  *   namedCurve         OBJECT IDENTIFIER
131  * }
132  */
133 static int pk_write_ec_param( unsigned char **p, unsigned char *start,
134                               mbedtls_ecp_keypair *ec )
135 {
136     int ret;
137     size_t len = 0;
138     const char *oid;
139     size_t oid_len;
140 
141     if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )
142         return( ret );
143 
144     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
145 
146     return( (int) len );
147 }
148 #endif /* MBEDTLS_ECP_C */
149 
150 int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
151                              const mbedtls_pk_context *key )
152 {
153     int ret;
154     size_t len = 0;
155 
156 #if defined(MBEDTLS_RSA_C)
157     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
158         MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) );
159     else
160 #endif
161 #if defined(MBEDTLS_ECP_C)
162     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
163         MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) );
164     else
165 #endif
166         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
167 
168     return( (int) len );
169 }
170 
171 int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
172 {
173     int ret;
174     unsigned char *c;
175     size_t len = 0, par_len = 0, oid_len;
176     const char *oid;
177 
178     c = buf + size;
179 
180     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) );
181 
182     if( c - buf < 1 )
183         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
184 
185     /*
186      *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
187      *       algorithm            AlgorithmIdentifier,
188      *       subjectPublicKey     BIT STRING }
189      */
190     *--c = 0;
191     len += 1;
192 
193     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
194     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
195 
196     if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ),
197                                        &oid, &oid_len ) ) != 0 )
198     {
199         return( ret );
200     }
201 
202 #if defined(MBEDTLS_ECP_C)
203     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
204     {
205         MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) );
206     }
207 #endif
208 
209     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len,
210                                                         par_len ) );
211 
212     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
213     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
214                                                 MBEDTLS_ASN1_SEQUENCE ) );
215 
216     return( (int) len );
217 }
218 
219 int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
220 {
221     int ret;
222     unsigned char *c = buf + size;
223     size_t len = 0;
224 
225 #if defined(MBEDTLS_RSA_C)
226     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
227     {
228         mbedtls_mpi T; /* Temporary holding the exported parameters */
229         mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key );
230 
231         /*
232          * Export the parameters one after another to avoid simultaneous copies.
233          */
234 
235         mbedtls_mpi_init( &T );
236 
237         /* Export QP */
238         if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 ||
239             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
240             goto end_of_export;
241         len += ret;
242 
243         /* Export DQ */
244         if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 ||
245             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
246             goto end_of_export;
247         len += ret;
248 
249         /* Export DP */
250         if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 ||
251             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
252             goto end_of_export;
253         len += ret;
254 
255         /* Export Q */
256         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
257                                          &T, NULL, NULL ) ) != 0 ||
258              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
259             goto end_of_export;
260         len += ret;
261 
262         /* Export P */
263         if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T,
264                                          NULL, NULL, NULL ) ) != 0 ||
265              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
266             goto end_of_export;
267         len += ret;
268 
269         /* Export D */
270         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
271                                          NULL, &T, NULL ) ) != 0 ||
272              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
273             goto end_of_export;
274         len += ret;
275 
276         /* Export E */
277         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
278                                          NULL, NULL, &T ) ) != 0 ||
279              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
280             goto end_of_export;
281         len += ret;
282 
283         /* Export N */
284         if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL,
285                                          NULL, NULL, NULL ) ) != 0 ||
286              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
287             goto end_of_export;
288         len += ret;
289 
290     end_of_export:
291 
292         mbedtls_mpi_free( &T );
293         if( ret < 0 )
294             return( ret );
295 
296         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );
297         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
298         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c,
299                                                buf, MBEDTLS_ASN1_CONSTRUCTED |
300                                                MBEDTLS_ASN1_SEQUENCE ) );
301     }
302     else
303 #endif /* MBEDTLS_RSA_C */
304 #if defined(MBEDTLS_ECP_C)
305     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
306     {
307         mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key );
308         size_t pub_len = 0, par_len = 0;
309 
310         /*
311          * RFC 5915, or SEC1 Appendix C.4
312          *
313          * ECPrivateKey ::= SEQUENCE {
314          *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
315          *      privateKey     OCTET STRING,
316          *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
317          *      publicKey  [1] BIT STRING OPTIONAL
318          *    }
319          */
320 
321         /* publicKey */
322         MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );
323 
324         if( c - buf < 1 )
325             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
326         *--c = 0;
327         pub_len += 1;
328 
329         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
330         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );
331 
332         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );
333         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf,
334                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) );
335         len += pub_len;
336 
337         /* parameters */
338         MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );
339 
340         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) );
341         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf,
342                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
343         len += par_len;
344 
345         /* privateKey: write as MPI then fix tag */
346         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) );
347         *c = MBEDTLS_ASN1_OCTET_STRING;
348 
349         /* version */
350         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) );
351 
352         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
353         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |
354                                                     MBEDTLS_ASN1_SEQUENCE ) );
355     }
356     else
357 #endif /* MBEDTLS_ECP_C */
358         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
359 
360     return( (int) len );
361 }
362 
363 #if defined(MBEDTLS_PEM_WRITE_C)
364 
365 #define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----\n"
366 #define PEM_END_PUBLIC_KEY      "-----END PUBLIC KEY-----\n"
367 
368 #define PEM_BEGIN_PRIVATE_KEY_RSA   "-----BEGIN RSA PRIVATE KEY-----\n"
369 #define PEM_END_PRIVATE_KEY_RSA     "-----END RSA PRIVATE KEY-----\n"
370 #define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----\n"
371 #define PEM_END_PRIVATE_KEY_EC      "-----END EC PRIVATE KEY-----\n"
372 
373 /*
374  * Max sizes of key per types. Shown as tag + len (+ content).
375  */
376 
377 #if defined(MBEDTLS_RSA_C)
378 /*
379  * RSA public keys:
380  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3
381  *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)
382  *                                                + 1 + 1 + 9 (rsa oid)
383  *                                                + 1 + 1 (params null)
384  *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)
385  *  RSAPublicKey ::= SEQUENCE {                     1 + 3
386  *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1
387  *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1
388  *  }
389  */
390 #define RSA_PUB_DER_MAX_BYTES   38 + 2 * MBEDTLS_MPI_MAX_SIZE
391 
392 /*
393  * RSA private keys:
394  *  RSAPrivateKey ::= SEQUENCE {                    1 + 3
395  *      version           Version,                  1 + 1 + 1
396  *      modulus           INTEGER,                  1 + 3 + MPI_MAX + 1
397  *      publicExponent    INTEGER,                  1 + 3 + MPI_MAX + 1
398  *      privateExponent   INTEGER,                  1 + 3 + MPI_MAX + 1
399  *      prime1            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
400  *      prime2            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
401  *      exponent1         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
402  *      exponent2         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
403  *      coefficient       INTEGER,                  1 + 3 + MPI_MAX / 2 + 1
404  *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)
405  *  }
406  */
407 #define MPI_MAX_SIZE_2          MBEDTLS_MPI_MAX_SIZE / 2 + \
408                                 MBEDTLS_MPI_MAX_SIZE % 2
409 #define RSA_PRV_DER_MAX_BYTES   47 + 3 * MBEDTLS_MPI_MAX_SIZE \
410                                    + 5 * MPI_MAX_SIZE_2
411 
412 #else /* MBEDTLS_RSA_C */
413 
414 #define RSA_PUB_DER_MAX_BYTES   0
415 #define RSA_PRV_DER_MAX_BYTES   0
416 
417 #endif /* MBEDTLS_RSA_C */
418 
419 #if defined(MBEDTLS_ECP_C)
420 /*
421  * EC public keys:
422  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {      1 + 2
423  *    algorithm         AlgorithmIdentifier,    1 + 1 (sequence)
424  *                                            + 1 + 1 + 7 (ec oid)
425  *                                            + 1 + 1 + 9 (namedCurve oid)
426  *    subjectPublicKey  BIT STRING              1 + 2 + 1               [1]
427  *                                            + 1 (point format)        [1]
428  *                                            + 2 * ECP_MAX (coords)    [1]
429  *  }
430  */
431 #define ECP_PUB_DER_MAX_BYTES   30 + 2 * MBEDTLS_ECP_MAX_BYTES
432 
433 /*
434  * EC private keys:
435  * ECPrivateKey ::= SEQUENCE {                  1 + 2
436  *      version        INTEGER ,                1 + 1 + 1
437  *      privateKey     OCTET STRING,            1 + 1 + ECP_MAX
438  *      parameters [0] ECParameters OPTIONAL,   1 + 1 + (1 + 1 + 9)
439  *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
440  *    }
441  */
442 #define ECP_PRV_DER_MAX_BYTES   29 + 3 * MBEDTLS_ECP_MAX_BYTES
443 
444 #else /* MBEDTLS_ECP_C */
445 
446 #define ECP_PUB_DER_MAX_BYTES   0
447 #define ECP_PRV_DER_MAX_BYTES   0
448 
449 #endif /* MBEDTLS_ECP_C */
450 
451 #define PUB_DER_MAX_BYTES   RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
452                             RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES
453 #define PRV_DER_MAX_BYTES   RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \
454                             RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES
455 
456 int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
457 {
458     int ret;
459     unsigned char output_buf[PUB_DER_MAX_BYTES];
460     size_t olen = 0;
461 
462     if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf,
463                                      sizeof(output_buf) ) ) < 0 )
464     {
465         return( ret );
466     }
467 
468     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
469                                   output_buf + sizeof(output_buf) - ret,
470                                   ret, buf, size, &olen ) ) != 0 )
471     {
472         return( ret );
473     }
474 
475     return( 0 );
476 }
477 
478 int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
479 {
480     int ret;
481     unsigned char output_buf[PRV_DER_MAX_BYTES];
482     const char *begin, *end;
483     size_t olen = 0;
484 
485     if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )
486         return( ret );
487 
488 #if defined(MBEDTLS_RSA_C)
489     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
490     {
491         begin = PEM_BEGIN_PRIVATE_KEY_RSA;
492         end = PEM_END_PRIVATE_KEY_RSA;
493     }
494     else
495 #endif
496 #if defined(MBEDTLS_ECP_C)
497     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )
498     {
499         begin = PEM_BEGIN_PRIVATE_KEY_EC;
500         end = PEM_END_PRIVATE_KEY_EC;
501     }
502     else
503 #endif
504         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
505 
506     if( ( ret = mbedtls_pem_write_buffer( begin, end,
507                                   output_buf + sizeof(output_buf) - ret,
508                                   ret, buf, size, &olen ) ) != 0 )
509     {
510         return( ret );
511     }
512 
513     return( 0 );
514 }
515 #endif /* MBEDTLS_PEM_WRITE_C */
516 
517 #endif /* MBEDTLS_PK_WRITE_C */
518