2 * Public Key layer for writing key files and structures
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: GPL-2.0
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.
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.
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.
21 * This file is part of mbed TLS (https://tls.mbed.org)
24 #if !defined(MBEDTLS_CONFIG_FILE)
25 #include "mbedtls/config.h"
27 #include MBEDTLS_CONFIG_FILE
30 #if defined(MBEDTLS_PK_WRITE_C)
32 #include "mbedtls/pk.h"
33 #include "mbedtls/asn1write.h"
34 #include "mbedtls/oid.h"
38 #if defined(MBEDTLS_RSA_C)
39 #include "mbedtls/rsa.h"
41 #if defined(MBEDTLS_ECP_C)
42 #include "mbedtls/ecp.h"
44 #if defined(MBEDTLS_ECDSA_C)
45 #include "mbedtls/ecdsa.h"
47 #if defined(MBEDTLS_PEM_WRITE_C)
48 #include "mbedtls/pem.h"
51 #if defined(MBEDTLS_PLATFORM_C)
52 #include "mbedtls/platform.h"
55 #define mbedtls_calloc calloc
56 #define mbedtls_free free
59 #if defined(MBEDTLS_RSA_C)
61 * RSAPublicKey ::= SEQUENCE {
62 * modulus INTEGER, -- n
63 * publicExponent INTEGER -- e
66 static int pk_write_rsa_pubkey( unsigned char **p
, unsigned char *start
,
67 mbedtls_rsa_context
*rsa
)
73 mbedtls_mpi_init( &T
);
76 if ( ( ret
= mbedtls_rsa_export( rsa
, NULL
, NULL
, NULL
, NULL
, &T
) ) != 0 ||
77 ( ret
= mbedtls_asn1_write_mpi( p
, start
, &T
) ) < 0 )
82 if ( ( ret
= mbedtls_rsa_export( rsa
, &T
, NULL
, NULL
, NULL
, NULL
) ) != 0 ||
83 ( ret
= mbedtls_asn1_write_mpi( p
, start
, &T
) ) < 0 )
89 mbedtls_mpi_free( &T
);
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
) );
99 #endif /* MBEDTLS_RSA_C */
101 #if defined(MBEDTLS_ECP_C)
103 * EC public key is an EC point
105 static int pk_write_ec_pubkey( unsigned char **p
, unsigned char *start
,
106 mbedtls_ecp_keypair
*ec
)
110 unsigned char buf
[MBEDTLS_ECP_MAX_PT_LEN
];
112 if( ( ret
= mbedtls_ecp_point_write_binary( &ec
->grp
, &ec
->Q
,
113 MBEDTLS_ECP_PF_UNCOMPRESSED
,
114 &len
, buf
, sizeof( buf
) ) ) != 0 )
119 if( *p
< start
|| (size_t)( *p
- start
) < len
)
120 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
123 memcpy( *p
, buf
, len
);
129 * ECParameters ::= CHOICE {
130 * namedCurve OBJECT IDENTIFIER
133 static int pk_write_ec_param( unsigned char **p
, unsigned char *start
,
134 mbedtls_ecp_keypair
*ec
)
141 if( ( ret
= mbedtls_oid_get_oid_by_ec_grp( ec
->grp
.id
, &oid
, &oid_len
) ) != 0 )
144 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_oid( p
, start
, oid
, oid_len
) );
148 #endif /* MBEDTLS_ECP_C */
150 int mbedtls_pk_write_pubkey( unsigned char **p
, unsigned char *start
,
151 const mbedtls_pk_context
*key
)
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
) ) );
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
) ) );
166 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE
);
171 int mbedtls_pk_write_pubkey_der( mbedtls_pk_context
*key
, unsigned char *buf
, size_t size
)
175 size_t len
= 0, par_len
= 0, oid_len
;
180 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_pk_write_pubkey( &c
, buf
, key
) );
183 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
186 * SubjectPublicKeyInfo ::= SEQUENCE {
187 * algorithm AlgorithmIdentifier,
188 * subjectPublicKey BIT STRING }
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
) );
196 if( ( ret
= mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key
),
197 &oid
, &oid_len
) ) != 0 )
202 #if defined(MBEDTLS_ECP_C)
203 if( mbedtls_pk_get_type( key
) == MBEDTLS_PK_ECKEY
)
205 MBEDTLS_ASN1_CHK_ADD( par_len
, pk_write_ec_param( &c
, buf
, mbedtls_pk_ec( *key
) ) );
209 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_algorithm_identifier( &c
, buf
, oid
, oid_len
,
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
) );
219 int mbedtls_pk_write_key_der( mbedtls_pk_context
*key
, unsigned char *buf
, size_t size
)
222 unsigned char *c
= buf
+ size
;
225 #if defined(MBEDTLS_RSA_C)
226 if( mbedtls_pk_get_type( key
) == MBEDTLS_PK_RSA
)
228 mbedtls_mpi T
; /* Temporary holding the exported parameters */
229 mbedtls_rsa_context
*rsa
= mbedtls_pk_rsa( *key
);
232 * Export the parameters one after another to avoid simultaneous copies.
235 mbedtls_mpi_init( &T
);
238 if( ( ret
= mbedtls_rsa_export_crt( rsa
, NULL
, NULL
, &T
) ) != 0 ||
239 ( ret
= mbedtls_asn1_write_mpi( &c
, buf
, &T
) ) < 0 )
244 if( ( ret
= mbedtls_rsa_export_crt( rsa
, NULL
, &T
, NULL
) ) != 0 ||
245 ( ret
= mbedtls_asn1_write_mpi( &c
, buf
, &T
) ) < 0 )
250 if( ( ret
= mbedtls_rsa_export_crt( rsa
, &T
, NULL
, NULL
) ) != 0 ||
251 ( ret
= mbedtls_asn1_write_mpi( &c
, buf
, &T
) ) < 0 )
256 if ( ( ret
= mbedtls_rsa_export( rsa
, NULL
, NULL
,
257 &T
, NULL
, NULL
) ) != 0 ||
258 ( ret
= mbedtls_asn1_write_mpi( &c
, buf
, &T
) ) < 0 )
263 if ( ( ret
= mbedtls_rsa_export( rsa
, NULL
, &T
,
264 NULL
, NULL
, NULL
) ) != 0 ||
265 ( ret
= mbedtls_asn1_write_mpi( &c
, buf
, &T
) ) < 0 )
270 if ( ( ret
= mbedtls_rsa_export( rsa
, NULL
, NULL
,
271 NULL
, &T
, NULL
) ) != 0 ||
272 ( ret
= mbedtls_asn1_write_mpi( &c
, buf
, &T
) ) < 0 )
277 if ( ( ret
= mbedtls_rsa_export( rsa
, NULL
, NULL
,
278 NULL
, NULL
, &T
) ) != 0 ||
279 ( ret
= mbedtls_asn1_write_mpi( &c
, buf
, &T
) ) < 0 )
284 if ( ( ret
= mbedtls_rsa_export( rsa
, &T
, NULL
,
285 NULL
, NULL
, NULL
) ) != 0 ||
286 ( ret
= mbedtls_asn1_write_mpi( &c
, buf
, &T
) ) < 0 )
292 mbedtls_mpi_free( &T
);
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
) );
303 #endif /* MBEDTLS_RSA_C */
304 #if defined(MBEDTLS_ECP_C)
305 if( mbedtls_pk_get_type( key
) == MBEDTLS_PK_ECKEY
)
307 mbedtls_ecp_keypair
*ec
= mbedtls_pk_ec( *key
);
308 size_t pub_len
= 0, par_len
= 0;
311 * RFC 5915, or SEC1 Appendix C.4
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
322 MBEDTLS_ASN1_CHK_ADD( pub_len
, pk_write_ec_pubkey( &c
, buf
, ec
) );
325 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL
);
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
) );
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 ) );
338 MBEDTLS_ASN1_CHK_ADD( par_len
, pk_write_ec_param( &c
, buf
, ec
) );
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 ) );
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
;
350 MBEDTLS_ASN1_CHK_ADD( len
, mbedtls_asn1_write_int( &c
, buf
, 1 ) );
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
) );
357 #endif /* MBEDTLS_ECP_C */
358 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE
);
363 #if defined(MBEDTLS_PEM_WRITE_C)
365 #define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
366 #define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
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"
374 * Max sizes of key per types. Shown as tag + len (+ content).
377 #if defined(MBEDTLS_RSA_C)
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
390 #define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE
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)
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 \
412 #else /* MBEDTLS_RSA_C */
414 #define RSA_PUB_DER_MAX_BYTES 0
415 #define RSA_PRV_DER_MAX_BYTES 0
417 #endif /* MBEDTLS_RSA_C */
419 #if defined(MBEDTLS_ECP_C)
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]
431 #define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES
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
442 #define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES
444 #else /* MBEDTLS_ECP_C */
446 #define ECP_PUB_DER_MAX_BYTES 0
447 #define ECP_PRV_DER_MAX_BYTES 0
449 #endif /* MBEDTLS_ECP_C */
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
456 int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context
*key
, unsigned char *buf
, size_t size
)
459 unsigned char output_buf
[PUB_DER_MAX_BYTES
];
462 if( ( ret
= mbedtls_pk_write_pubkey_der( key
, output_buf
,
463 sizeof(output_buf
) ) ) < 0 )
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 )
478 int mbedtls_pk_write_key_pem( mbedtls_pk_context
*key
, unsigned char *buf
, size_t size
)
481 unsigned char output_buf
[PRV_DER_MAX_BYTES
];
482 const char *begin
, *end
;
485 if( ( ret
= mbedtls_pk_write_key_der( key
, output_buf
, sizeof(output_buf
) ) ) < 0 )
488 #if defined(MBEDTLS_RSA_C)
489 if( mbedtls_pk_get_type( key
) == MBEDTLS_PK_RSA
)
491 begin
= PEM_BEGIN_PRIVATE_KEY_RSA
;
492 end
= PEM_END_PRIVATE_KEY_RSA
;
496 #if defined(MBEDTLS_ECP_C)
497 if( mbedtls_pk_get_type( key
) == MBEDTLS_PK_ECKEY
)
499 begin
= PEM_BEGIN_PRIVATE_KEY_EC
;
500 end
= PEM_END_PRIVATE_KEY_EC
;
504 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE
);
506 if( ( ret
= mbedtls_pem_write_buffer( begin
, end
,
507 output_buf
+ sizeof(output_buf
) - ret
,
508 ret
, buf
, size
, &olen
) ) != 0 )
515 #endif /* MBEDTLS_PEM_WRITE_C */
517 #endif /* MBEDTLS_PK_WRITE_C */