pkwrite.c 20 KB

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