]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/mbedtls/library/pkwrite.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / mbedtls / library / pkwrite.c
1 /*\r
2  *  Public Key layer for writing key files and structures\r
3  *\r
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved\r
5  *  SPDX-License-Identifier: Apache-2.0\r
6  *\r
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may\r
8  *  not use this file except in compliance with the License.\r
9  *  You may obtain a copy of the License at\r
10  *\r
11  *  http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  *  Unless required by applicable law or agreed to in writing, software\r
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  *  See the License for the specific language governing permissions and\r
17  *  limitations under the License.\r
18  *\r
19  *  This file is part of mbed TLS (https://tls.mbed.org)\r
20  */\r
21 \r
22 #if !defined(MBEDTLS_CONFIG_FILE)\r
23 #include "mbedtls/config.h"\r
24 #else\r
25 #include MBEDTLS_CONFIG_FILE\r
26 #endif\r
27 \r
28 #if defined(MBEDTLS_PK_WRITE_C)\r
29 \r
30 #include "mbedtls/pk.h"\r
31 #include "mbedtls/asn1write.h"\r
32 #include "mbedtls/oid.h"\r
33 #include "mbedtls/platform_util.h"\r
34 \r
35 #include <string.h>\r
36 \r
37 #if defined(MBEDTLS_RSA_C)\r
38 #include "mbedtls/rsa.h"\r
39 #endif\r
40 #if defined(MBEDTLS_ECP_C)\r
41 #include "mbedtls/ecp.h"\r
42 #endif\r
43 #if defined(MBEDTLS_ECDSA_C)\r
44 #include "mbedtls/ecdsa.h"\r
45 #endif\r
46 #if defined(MBEDTLS_PEM_WRITE_C)\r
47 #include "mbedtls/pem.h"\r
48 #endif\r
49 \r
50 #if defined(MBEDTLS_USE_PSA_CRYPTO)\r
51 #include "psa/crypto.h"\r
52 #include "mbedtls/psa_util.h"\r
53 #endif\r
54 #if defined(MBEDTLS_PLATFORM_C)\r
55 #include "mbedtls/platform.h"\r
56 #else\r
57 #include <stdlib.h>\r
58 #define mbedtls_calloc    calloc\r
59 #define mbedtls_free       free\r
60 #endif\r
61 \r
62 /* Parameter validation macros based on platform_util.h */\r
63 #define PK_VALIDATE_RET( cond )    \\r
64     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )\r
65 #define PK_VALIDATE( cond )        \\r
66     MBEDTLS_INTERNAL_VALIDATE( cond )\r
67 \r
68 #if defined(MBEDTLS_RSA_C)\r
69 /*\r
70  *  RSAPublicKey ::= SEQUENCE {\r
71  *      modulus           INTEGER,  -- n\r
72  *      publicExponent    INTEGER   -- e\r
73  *  }\r
74  */\r
75 static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,\r
76                                 mbedtls_rsa_context *rsa )\r
77 {\r
78     int ret;\r
79     size_t len = 0;\r
80     mbedtls_mpi T;\r
81 \r
82     mbedtls_mpi_init( &T );\r
83 \r
84     /* Export E */\r
85     if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 ||\r
86          ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )\r
87         goto end_of_export;\r
88     len += ret;\r
89 \r
90     /* Export N */\r
91     if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 ||\r
92          ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )\r
93         goto end_of_export;\r
94     len += ret;\r
95 \r
96 end_of_export:\r
97 \r
98     mbedtls_mpi_free( &T );\r
99     if( ret < 0 )\r
100         return( ret );\r
101 \r
102     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );\r
103     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |\r
104                                                  MBEDTLS_ASN1_SEQUENCE ) );\r
105 \r
106     return( (int) len );\r
107 }\r
108 #endif /* MBEDTLS_RSA_C */\r
109 \r
110 #if defined(MBEDTLS_ECP_C)\r
111 /*\r
112  * EC public key is an EC point\r
113  */\r
114 static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,\r
115                                mbedtls_ecp_keypair *ec )\r
116 {\r
117     int ret;\r
118     size_t len = 0;\r
119     unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];\r
120 \r
121     if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q,\r
122                                         MBEDTLS_ECP_PF_UNCOMPRESSED,\r
123                                         &len, buf, sizeof( buf ) ) ) != 0 )\r
124     {\r
125         return( ret );\r
126     }\r
127 \r
128     if( *p < start || (size_t)( *p - start ) < len )\r
129         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );\r
130 \r
131     *p -= len;\r
132     memcpy( *p, buf, len );\r
133 \r
134     return( (int) len );\r
135 }\r
136 \r
137 /*\r
138  * ECParameters ::= CHOICE {\r
139  *   namedCurve         OBJECT IDENTIFIER\r
140  * }\r
141  */\r
142 static int pk_write_ec_param( unsigned char **p, unsigned char *start,\r
143                               mbedtls_ecp_keypair *ec )\r
144 {\r
145     int ret;\r
146     size_t len = 0;\r
147     const char *oid;\r
148     size_t oid_len;\r
149 \r
150     if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 )\r
151         return( ret );\r
152 \r
153     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );\r
154 \r
155     return( (int) len );\r
156 }\r
157 #endif /* MBEDTLS_ECP_C */\r
158 \r
159 int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,\r
160                              const mbedtls_pk_context *key )\r
161 {\r
162     int ret;\r
163     size_t len = 0;\r
164 \r
165     PK_VALIDATE_RET( p != NULL );\r
166     PK_VALIDATE_RET( *p != NULL );\r
167     PK_VALIDATE_RET( start != NULL );\r
168     PK_VALIDATE_RET( key != NULL );\r
169 \r
170 #if defined(MBEDTLS_RSA_C)\r
171     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )\r
172         MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) );\r
173     else\r
174 #endif\r
175 #if defined(MBEDTLS_ECP_C)\r
176     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )\r
177         MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) );\r
178     else\r
179 #endif\r
180 #if defined(MBEDTLS_USE_PSA_CRYPTO)\r
181     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE )\r
182     {\r
183         size_t buffer_size;\r
184         psa_key_handle_t* key_slot = (psa_key_handle_t*) key->pk_ctx;\r
185 \r
186         if ( *p < start )\r
187             return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );\r
188 \r
189         buffer_size = (size_t)( *p - start );\r
190         if ( psa_export_public_key( *key_slot, start, buffer_size, &len )\r
191              != PSA_SUCCESS )\r
192         {\r
193             return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );\r
194         }\r
195         else\r
196         {\r
197             *p -= len;\r
198             memmove( *p, start, len );\r
199         }\r
200     }\r
201     else\r
202 #endif /* MBEDTLS_USE_PSA_CRYPTO */\r
203         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );\r
204 \r
205     return( (int) len );\r
206 }\r
207 \r
208 int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )\r
209 {\r
210     int ret;\r
211     unsigned char *c;\r
212     size_t len = 0, par_len = 0, oid_len;\r
213     mbedtls_pk_type_t pk_type;\r
214     const char *oid;\r
215 \r
216     PK_VALIDATE_RET( key != NULL );\r
217     if( size == 0 )\r
218         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );\r
219     PK_VALIDATE_RET( buf != NULL );\r
220 \r
221     c = buf + size;\r
222 \r
223     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) );\r
224 \r
225     if( c - buf < 1 )\r
226         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );\r
227 \r
228     /*\r
229      *  SubjectPublicKeyInfo  ::=  SEQUENCE  {\r
230      *       algorithm            AlgorithmIdentifier,\r
231      *       subjectPublicKey     BIT STRING }\r
232      */\r
233     *--c = 0;\r
234     len += 1;\r
235 \r
236     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );\r
237     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );\r
238 \r
239     pk_type = mbedtls_pk_get_type( key );\r
240 #if defined(MBEDTLS_ECP_C)\r
241     if( pk_type == MBEDTLS_PK_ECKEY )\r
242     {\r
243         MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) );\r
244     }\r
245 #endif\r
246 #if defined(MBEDTLS_USE_PSA_CRYPTO)\r
247     if( pk_type == MBEDTLS_PK_OPAQUE )\r
248     {\r
249         psa_status_t status;\r
250         psa_key_type_t key_type;\r
251         psa_key_handle_t handle;\r
252         psa_ecc_curve_t curve;\r
253 \r
254         handle = *((psa_key_handle_t*) key->pk_ctx );\r
255 \r
256         status = psa_get_key_information( handle, &key_type,\r
257                                           NULL /* bitsize not needed */ );\r
258         if( status != PSA_SUCCESS )\r
259             return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );\r
260 \r
261         curve = PSA_KEY_TYPE_GET_CURVE( key_type );\r
262         if( curve == 0 )\r
263             return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );\r
264 \r
265         ret = mbedtls_psa_get_ecc_oid_from_id( curve, &oid, &oid_len );\r
266         if( ret != 0 )\r
267             return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );\r
268 \r
269         /* Write EC algorithm parameters; that's akin\r
270          * to pk_write_ec_param() above. */\r
271         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_oid( &c, buf,\r
272                                                                oid, oid_len ) );\r
273 \r
274         /* The rest of the function works as for legacy EC contexts. */\r
275         pk_type = MBEDTLS_PK_ECKEY;\r
276     }\r
277 #endif /* MBEDTLS_USE_PSA_CRYPTO */\r
278 \r
279     if( ( ret = mbedtls_oid_get_oid_by_pk_alg( pk_type, &oid,\r
280                                                &oid_len ) ) != 0 )\r
281     {\r
282         return( ret );\r
283     }\r
284 \r
285     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len,\r
286                                                         par_len ) );\r
287 \r
288     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );\r
289     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |\r
290                                                 MBEDTLS_ASN1_SEQUENCE ) );\r
291 \r
292     return( (int) len );\r
293 }\r
294 \r
295 int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )\r
296 {\r
297     int ret;\r
298     unsigned char *c;\r
299     size_t len = 0;\r
300 \r
301     PK_VALIDATE_RET( key != NULL );\r
302     if( size == 0 )\r
303         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );\r
304     PK_VALIDATE_RET( buf != NULL );\r
305 \r
306     c = buf + size;\r
307 \r
308 #if defined(MBEDTLS_RSA_C)\r
309     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )\r
310     {\r
311         mbedtls_mpi T; /* Temporary holding the exported parameters */\r
312         mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key );\r
313 \r
314         /*\r
315          * Export the parameters one after another to avoid simultaneous copies.\r
316          */\r
317 \r
318         mbedtls_mpi_init( &T );\r
319 \r
320         /* Export QP */\r
321         if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 ||\r
322             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )\r
323             goto end_of_export;\r
324         len += ret;\r
325 \r
326         /* Export DQ */\r
327         if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 ||\r
328             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )\r
329             goto end_of_export;\r
330         len += ret;\r
331 \r
332         /* Export DP */\r
333         if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 ||\r
334             ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )\r
335             goto end_of_export;\r
336         len += ret;\r
337 \r
338         /* Export Q */\r
339         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,\r
340                                          &T, NULL, NULL ) ) != 0 ||\r
341              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )\r
342             goto end_of_export;\r
343         len += ret;\r
344 \r
345         /* Export P */\r
346         if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T,\r
347                                          NULL, NULL, NULL ) ) != 0 ||\r
348              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )\r
349             goto end_of_export;\r
350         len += ret;\r
351 \r
352         /* Export D */\r
353         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,\r
354                                          NULL, &T, NULL ) ) != 0 ||\r
355              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )\r
356             goto end_of_export;\r
357         len += ret;\r
358 \r
359         /* Export E */\r
360         if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,\r
361                                          NULL, NULL, &T ) ) != 0 ||\r
362              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )\r
363             goto end_of_export;\r
364         len += ret;\r
365 \r
366         /* Export N */\r
367         if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL,\r
368                                          NULL, NULL, NULL ) ) != 0 ||\r
369              ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )\r
370             goto end_of_export;\r
371         len += ret;\r
372 \r
373     end_of_export:\r
374 \r
375         mbedtls_mpi_free( &T );\r
376         if( ret < 0 )\r
377             return( ret );\r
378 \r
379         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );\r
380         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );\r
381         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c,\r
382                                                buf, MBEDTLS_ASN1_CONSTRUCTED |\r
383                                                MBEDTLS_ASN1_SEQUENCE ) );\r
384     }\r
385     else\r
386 #endif /* MBEDTLS_RSA_C */\r
387 #if defined(MBEDTLS_ECP_C)\r
388     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )\r
389     {\r
390         mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key );\r
391         size_t pub_len = 0, par_len = 0;\r
392 \r
393         /*\r
394          * RFC 5915, or SEC1 Appendix C.4\r
395          *\r
396          * ECPrivateKey ::= SEQUENCE {\r
397          *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),\r
398          *      privateKey     OCTET STRING,\r
399          *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,\r
400          *      publicKey  [1] BIT STRING OPTIONAL\r
401          *    }\r
402          */\r
403 \r
404         /* publicKey */\r
405         MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) );\r
406 \r
407         if( c - buf < 1 )\r
408             return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );\r
409         *--c = 0;\r
410         pub_len += 1;\r
411 \r
412         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );\r
413         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) );\r
414 \r
415         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) );\r
416         MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf,\r
417                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) );\r
418         len += pub_len;\r
419 \r
420         /* parameters */\r
421         MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) );\r
422 \r
423         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) );\r
424         MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf,\r
425                             MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) );\r
426         len += par_len;\r
427 \r
428         /* privateKey: write as MPI then fix tag */\r
429         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) );\r
430         *c = MBEDTLS_ASN1_OCTET_STRING;\r
431 \r
432         /* version */\r
433         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) );\r
434 \r
435         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );\r
436         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED |\r
437                                                     MBEDTLS_ASN1_SEQUENCE ) );\r
438     }\r
439     else\r
440 #endif /* MBEDTLS_ECP_C */\r
441         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );\r
442 \r
443     return( (int) len );\r
444 }\r
445 \r
446 #if defined(MBEDTLS_PEM_WRITE_C)\r
447 \r
448 #define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----\n"\r
449 #define PEM_END_PUBLIC_KEY      "-----END PUBLIC KEY-----\n"\r
450 \r
451 #define PEM_BEGIN_PRIVATE_KEY_RSA   "-----BEGIN RSA PRIVATE KEY-----\n"\r
452 #define PEM_END_PRIVATE_KEY_RSA     "-----END RSA PRIVATE KEY-----\n"\r
453 #define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----\n"\r
454 #define PEM_END_PRIVATE_KEY_EC      "-----END EC PRIVATE KEY-----\n"\r
455 \r
456 /*\r
457  * Max sizes of key per types. Shown as tag + len (+ content).\r
458  */\r
459 \r
460 #if defined(MBEDTLS_RSA_C)\r
461 /*\r
462  * RSA public keys:\r
463  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {          1 + 3\r
464  *       algorithm            AlgorithmIdentifier,  1 + 1 (sequence)\r
465  *                                                + 1 + 1 + 9 (rsa oid)\r
466  *                                                + 1 + 1 (params null)\r
467  *       subjectPublicKey     BIT STRING }          1 + 3 + (1 + below)\r
468  *  RSAPublicKey ::= SEQUENCE {                     1 + 3\r
469  *      modulus           INTEGER,  -- n            1 + 3 + MPI_MAX + 1\r
470  *      publicExponent    INTEGER   -- e            1 + 3 + MPI_MAX + 1\r
471  *  }\r
472  */\r
473 #define RSA_PUB_DER_MAX_BYTES   38 + 2 * MBEDTLS_MPI_MAX_SIZE\r
474 \r
475 /*\r
476  * RSA private keys:\r
477  *  RSAPrivateKey ::= SEQUENCE {                    1 + 3\r
478  *      version           Version,                  1 + 1 + 1\r
479  *      modulus           INTEGER,                  1 + 3 + MPI_MAX + 1\r
480  *      publicExponent    INTEGER,                  1 + 3 + MPI_MAX + 1\r
481  *      privateExponent   INTEGER,                  1 + 3 + MPI_MAX + 1\r
482  *      prime1            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1\r
483  *      prime2            INTEGER,                  1 + 3 + MPI_MAX / 2 + 1\r
484  *      exponent1         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1\r
485  *      exponent2         INTEGER,                  1 + 3 + MPI_MAX / 2 + 1\r
486  *      coefficient       INTEGER,                  1 + 3 + MPI_MAX / 2 + 1\r
487  *      otherPrimeInfos   OtherPrimeInfos OPTIONAL  0 (not supported)\r
488  *  }\r
489  */\r
490 #define MPI_MAX_SIZE_2          MBEDTLS_MPI_MAX_SIZE / 2 + \\r
491                                 MBEDTLS_MPI_MAX_SIZE % 2\r
492 #define RSA_PRV_DER_MAX_BYTES   47 + 3 * MBEDTLS_MPI_MAX_SIZE \\r
493                                    + 5 * MPI_MAX_SIZE_2\r
494 \r
495 #else /* MBEDTLS_RSA_C */\r
496 \r
497 #define RSA_PUB_DER_MAX_BYTES   0\r
498 #define RSA_PRV_DER_MAX_BYTES   0\r
499 \r
500 #endif /* MBEDTLS_RSA_C */\r
501 \r
502 #if defined(MBEDTLS_ECP_C)\r
503 /*\r
504  * EC public keys:\r
505  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {      1 + 2\r
506  *    algorithm         AlgorithmIdentifier,    1 + 1 (sequence)\r
507  *                                            + 1 + 1 + 7 (ec oid)\r
508  *                                            + 1 + 1 + 9 (namedCurve oid)\r
509  *    subjectPublicKey  BIT STRING              1 + 2 + 1               [1]\r
510  *                                            + 1 (point format)        [1]\r
511  *                                            + 2 * ECP_MAX (coords)    [1]\r
512  *  }\r
513  */\r
514 #define ECP_PUB_DER_MAX_BYTES   30 + 2 * MBEDTLS_ECP_MAX_BYTES\r
515 \r
516 /*\r
517  * EC private keys:\r
518  * ECPrivateKey ::= SEQUENCE {                  1 + 2\r
519  *      version        INTEGER ,                1 + 1 + 1\r
520  *      privateKey     OCTET STRING,            1 + 1 + ECP_MAX\r
521  *      parameters [0] ECParameters OPTIONAL,   1 + 1 + (1 + 1 + 9)\r
522  *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above\r
523  *    }\r
524  */\r
525 #define ECP_PRV_DER_MAX_BYTES   29 + 3 * MBEDTLS_ECP_MAX_BYTES\r
526 \r
527 #else /* MBEDTLS_ECP_C */\r
528 \r
529 #define ECP_PUB_DER_MAX_BYTES   0\r
530 #define ECP_PRV_DER_MAX_BYTES   0\r
531 \r
532 #endif /* MBEDTLS_ECP_C */\r
533 \r
534 #define PUB_DER_MAX_BYTES   RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \\r
535                             RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES\r
536 #define PRV_DER_MAX_BYTES   RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \\r
537                             RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES\r
538 \r
539 int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )\r
540 {\r
541     int ret;\r
542     unsigned char output_buf[PUB_DER_MAX_BYTES];\r
543     size_t olen = 0;\r
544 \r
545     PK_VALIDATE_RET( key != NULL );\r
546     PK_VALIDATE_RET( buf != NULL || size == 0 );\r
547 \r
548     if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf,\r
549                                      sizeof(output_buf) ) ) < 0 )\r
550     {\r
551         return( ret );\r
552     }\r
553 \r
554     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,\r
555                                   output_buf + sizeof(output_buf) - ret,\r
556                                   ret, buf, size, &olen ) ) != 0 )\r
557     {\r
558         return( ret );\r
559     }\r
560 \r
561     return( 0 );\r
562 }\r
563 \r
564 int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )\r
565 {\r
566     int ret;\r
567     unsigned char output_buf[PRV_DER_MAX_BYTES];\r
568     const char *begin, *end;\r
569     size_t olen = 0;\r
570 \r
571     PK_VALIDATE_RET( key != NULL );\r
572     PK_VALIDATE_RET( buf != NULL || size == 0 );\r
573 \r
574     if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 )\r
575         return( ret );\r
576 \r
577 #if defined(MBEDTLS_RSA_C)\r
578     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )\r
579     {\r
580         begin = PEM_BEGIN_PRIVATE_KEY_RSA;\r
581         end = PEM_END_PRIVATE_KEY_RSA;\r
582     }\r
583     else\r
584 #endif\r
585 #if defined(MBEDTLS_ECP_C)\r
586     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY )\r
587     {\r
588         begin = PEM_BEGIN_PRIVATE_KEY_EC;\r
589         end = PEM_END_PRIVATE_KEY_EC;\r
590     }\r
591     else\r
592 #endif\r
593         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );\r
594 \r
595     if( ( ret = mbedtls_pem_write_buffer( begin, end,\r
596                                   output_buf + sizeof(output_buf) - ret,\r
597                                   ret, buf, size, &olen ) ) != 0 )\r
598     {\r
599         return( ret );\r
600     }\r
601 \r
602     return( 0 );\r
603 }\r
604 #endif /* MBEDTLS_PEM_WRITE_C */\r
605 \r
606 #endif /* MBEDTLS_PK_WRITE_C */\r