pkwrite.c 18 KB

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