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