pkwrite.c 17 KB

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