pkwrite.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  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 OR GPL-2.0-or-later
  6. */
  7. #include "common.h"
  8. #if defined(MBEDTLS_PK_WRITE_C)
  9. #include "mbedtls/pk.h"
  10. #include "mbedtls/asn1write.h"
  11. #include "mbedtls/oid.h"
  12. #include "mbedtls/platform_util.h"
  13. #include "mbedtls/error.h"
  14. #include "pk_internal.h"
  15. #include <string.h>
  16. #if defined(MBEDTLS_ECP_C)
  17. #include "mbedtls/bignum.h"
  18. #include "mbedtls/ecp.h"
  19. #include "mbedtls/platform_util.h"
  20. #endif
  21. #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
  22. #include "pk_internal.h"
  23. #endif
  24. #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS)
  25. #include "pkwrite.h"
  26. #endif
  27. #if defined(MBEDTLS_PEM_WRITE_C)
  28. #include "mbedtls/pem.h"
  29. #endif
  30. #if defined(MBEDTLS_RSA_C)
  31. #include "rsa_internal.h"
  32. #endif
  33. #if defined(MBEDTLS_USE_PSA_CRYPTO)
  34. #include "psa/crypto.h"
  35. #include "psa_util_internal.h"
  36. #endif
  37. #include "mbedtls/platform.h"
  38. /* Helpers for properly sizing buffers aimed at holding public keys or
  39. * key-pairs based on build symbols. */
  40. #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
  41. #define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
  42. #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
  43. #elif defined(MBEDTLS_USE_PSA_CRYPTO)
  44. #define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
  45. #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
  46. #else
  47. #define PK_MAX_EC_PUBLIC_KEY_SIZE MBEDTLS_ECP_MAX_PT_LEN
  48. #define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_ECP_MAX_BYTES
  49. #endif
  50. /******************************************************************************
  51. * Internal functions for RSA keys.
  52. ******************************************************************************/
  53. #if defined(MBEDTLS_RSA_C)
  54. static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
  55. const mbedtls_pk_context *pk)
  56. {
  57. #if defined(MBEDTLS_USE_PSA_CRYPTO)
  58. if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
  59. uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
  60. size_t tmp_len = 0;
  61. if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
  62. return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
  63. }
  64. /* Ensure there's enough space in the provided buffer before copying data into it. */
  65. if (tmp_len > (size_t) (*p - buf)) {
  66. mbedtls_platform_zeroize(tmp, sizeof(tmp));
  67. return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
  68. }
  69. *p -= tmp_len;
  70. memcpy(*p, tmp, tmp_len);
  71. mbedtls_platform_zeroize(tmp, sizeof(tmp));
  72. return (int) tmp_len;
  73. }
  74. #endif /* MBEDTLS_USE_PSA_CRYPTO */
  75. return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);
  76. }
  77. #endif /* MBEDTLS_RSA_C */
  78. /******************************************************************************
  79. * Internal functions for EC keys.
  80. ******************************************************************************/
  81. #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
  82. #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
  83. static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
  84. const mbedtls_pk_context *pk)
  85. {
  86. size_t len = 0;
  87. uint8_t buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
  88. if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
  89. if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
  90. return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
  91. }
  92. } else {
  93. len = pk->pub_raw_len;
  94. memcpy(buf, pk->pub_raw, len);
  95. }
  96. if (*p < start || (size_t) (*p - start) < len) {
  97. return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
  98. }
  99. *p -= len;
  100. memcpy(*p, buf, len);
  101. return (int) len;
  102. }
  103. #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
  104. static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
  105. const mbedtls_pk_context *pk)
  106. {
  107. size_t len = 0;
  108. unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
  109. mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
  110. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  111. #if defined(MBEDTLS_USE_PSA_CRYPTO)
  112. if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
  113. if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
  114. return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
  115. }
  116. /* Ensure there's enough space in the provided buffer before copying data into it. */
  117. if (len > (size_t) (*p - start)) {
  118. return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
  119. }
  120. *p -= len;
  121. memcpy(*p, buf, len);
  122. return (int) len;
  123. } else
  124. #endif /* MBEDTLS_USE_PSA_CRYPTO */
  125. {
  126. if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
  127. MBEDTLS_ECP_PF_UNCOMPRESSED,
  128. &len, buf, sizeof(buf))) != 0) {
  129. return ret;
  130. }
  131. }
  132. if (*p < start || (size_t) (*p - start) < len) {
  133. return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
  134. }
  135. *p -= len;
  136. memcpy(*p, buf, len);
  137. return (int) len;
  138. }
  139. #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
  140. /*
  141. * privateKey OCTET STRING -- always of length ceil(log2(n)/8)
  142. */
  143. #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
  144. static int pk_write_ec_private(unsigned char **p, unsigned char *start,
  145. const mbedtls_pk_context *pk)
  146. {
  147. size_t byte_length;
  148. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  149. unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
  150. psa_status_t status;
  151. if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
  152. status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
  153. if (status != PSA_SUCCESS) {
  154. ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
  155. return ret;
  156. }
  157. } else {
  158. status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
  159. if (status != PSA_SUCCESS) {
  160. ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
  161. goto exit;
  162. }
  163. }
  164. ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
  165. exit:
  166. mbedtls_platform_zeroize(tmp, sizeof(tmp));
  167. return ret;
  168. }
  169. #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
  170. static int pk_write_ec_private(unsigned char **p, unsigned char *start,
  171. const mbedtls_pk_context *pk)
  172. {
  173. size_t byte_length;
  174. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  175. unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
  176. #if defined(MBEDTLS_USE_PSA_CRYPTO)
  177. psa_status_t status;
  178. if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
  179. status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
  180. if (status != PSA_SUCCESS) {
  181. ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
  182. return ret;
  183. }
  184. } else
  185. #endif /* MBEDTLS_USE_PSA_CRYPTO */
  186. {
  187. mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
  188. byte_length = (ec->grp.pbits + 7) / 8;
  189. ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp));
  190. if (ret != 0) {
  191. goto exit;
  192. }
  193. }
  194. ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
  195. exit:
  196. mbedtls_platform_zeroize(tmp, sizeof(tmp));
  197. return ret;
  198. }
  199. #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
  200. /*
  201. * ECParameters ::= CHOICE {
  202. * namedCurve OBJECT IDENTIFIER
  203. * }
  204. */
  205. static int pk_write_ec_param(unsigned char **p, unsigned char *start,
  206. mbedtls_ecp_group_id grp_id)
  207. {
  208. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  209. size_t len = 0;
  210. const char *oid;
  211. size_t oid_len;
  212. if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) {
  213. return ret;
  214. }
  215. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
  216. return (int) len;
  217. }
  218. #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
  219. /*
  220. * RFC8410 section 7
  221. *
  222. * OneAsymmetricKey ::= SEQUENCE {
  223. * version Version,
  224. * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
  225. * privateKey PrivateKey,
  226. * attributes [0] IMPLICIT Attributes OPTIONAL,
  227. * ...,
  228. * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],
  229. * ...
  230. * }
  231. * ...
  232. * CurvePrivateKey ::= OCTET STRING
  233. */
  234. static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,
  235. const mbedtls_pk_context *pk)
  236. {
  237. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  238. size_t len = 0;
  239. size_t oid_len = 0;
  240. const char *oid;
  241. mbedtls_ecp_group_id grp_id;
  242. /* privateKey */
  243. MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
  244. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
  245. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING));
  246. grp_id = mbedtls_pk_get_ec_group_id(pk);
  247. /* privateKeyAlgorithm */
  248. if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) {
  249. return ret;
  250. }
  251. MBEDTLS_ASN1_CHK_ADD(len,
  252. mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));
  253. /* version */
  254. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
  255. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
  256. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
  257. MBEDTLS_ASN1_SEQUENCE));
  258. return (int) len;
  259. }
  260. #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
  261. /*
  262. * RFC 5915, or SEC1 Appendix C.4
  263. *
  264. * ECPrivateKey ::= SEQUENCE {
  265. * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
  266. * privateKey OCTET STRING,
  267. * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
  268. * publicKey [1] BIT STRING OPTIONAL
  269. * }
  270. */
  271. static int pk_write_ec_der(unsigned char **p, unsigned char *buf,
  272. const mbedtls_pk_context *pk)
  273. {
  274. size_t len = 0;
  275. int ret;
  276. size_t pub_len = 0, par_len = 0;
  277. mbedtls_ecp_group_id grp_id;
  278. /* publicKey */
  279. MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk));
  280. if (*p - buf < 1) {
  281. return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
  282. }
  283. (*p)--;
  284. **p = 0;
  285. pub_len += 1;
  286. MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
  287. MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING));
  288. MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
  289. MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf,
  290. MBEDTLS_ASN1_CONTEXT_SPECIFIC |
  291. MBEDTLS_ASN1_CONSTRUCTED | 1));
  292. len += pub_len;
  293. /* parameters */
  294. grp_id = mbedtls_pk_get_ec_group_id(pk);
  295. MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id));
  296. MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len));
  297. MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf,
  298. MBEDTLS_ASN1_CONTEXT_SPECIFIC |
  299. MBEDTLS_ASN1_CONSTRUCTED | 0));
  300. len += par_len;
  301. /* privateKey */
  302. MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
  303. /* version */
  304. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1));
  305. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
  306. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
  307. MBEDTLS_ASN1_SEQUENCE));
  308. return (int) len;
  309. }
  310. #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
  311. /******************************************************************************
  312. * Internal functions for Opaque keys.
  313. ******************************************************************************/
  314. #if defined(MBEDTLS_USE_PSA_CRYPTO)
  315. static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start,
  316. const mbedtls_pk_context *pk)
  317. {
  318. size_t buffer_size;
  319. size_t len = 0;
  320. if (*p < start) {
  321. return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
  322. }
  323. buffer_size = (size_t) (*p - start);
  324. if (psa_export_public_key(pk->priv_id, start, buffer_size,
  325. &len) != PSA_SUCCESS) {
  326. return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
  327. }
  328. *p -= len;
  329. memmove(*p, start, len);
  330. return (int) len;
  331. }
  332. #endif /* MBEDTLS_USE_PSA_CRYPTO */
  333. /******************************************************************************
  334. * Generic helpers
  335. ******************************************************************************/
  336. /* Extend the public mbedtls_pk_get_type() by getting key type also in case of
  337. * opaque keys. */
  338. static mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk)
  339. {
  340. mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
  341. #if defined(MBEDTLS_USE_PSA_CRYPTO)
  342. if (pk_type == MBEDTLS_PK_OPAQUE) {
  343. psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;
  344. psa_key_type_t opaque_key_type;
  345. if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {
  346. return MBEDTLS_PK_NONE;
  347. }
  348. opaque_key_type = psa_get_key_type(&opaque_attrs);
  349. psa_reset_key_attributes(&opaque_attrs);
  350. if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) {
  351. return MBEDTLS_PK_ECKEY;
  352. } else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) {
  353. return MBEDTLS_PK_RSA;
  354. } else {
  355. return MBEDTLS_PK_NONE;
  356. }
  357. } else
  358. #endif
  359. return pk_type;
  360. }
  361. /******************************************************************************
  362. * Public functions for writing private/public DER keys.
  363. ******************************************************************************/
  364. int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
  365. const mbedtls_pk_context *key)
  366. {
  367. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  368. size_t len = 0;
  369. #if defined(MBEDTLS_RSA_C)
  370. if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
  371. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p));
  372. } else
  373. #endif
  374. #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
  375. if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
  376. MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key));
  377. } else
  378. #endif
  379. #if defined(MBEDTLS_USE_PSA_CRYPTO)
  380. if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
  381. MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key));
  382. } else
  383. #endif /* MBEDTLS_USE_PSA_CRYPTO */
  384. return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
  385. return (int) len;
  386. }
  387. int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
  388. {
  389. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  390. unsigned char *c;
  391. int has_par = 1;
  392. size_t len = 0, par_len = 0, oid_len = 0;
  393. mbedtls_pk_type_t pk_type;
  394. const char *oid = NULL;
  395. if (size == 0) {
  396. return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
  397. }
  398. c = buf + size;
  399. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));
  400. if (c - buf < 1) {
  401. return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
  402. }
  403. /*
  404. * SubjectPublicKeyInfo ::= SEQUENCE {
  405. * algorithm AlgorithmIdentifier,
  406. * subjectPublicKey BIT STRING }
  407. */
  408. *--c = 0;
  409. len += 1;
  410. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
  411. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
  412. pk_type = pk_get_type_ext(key);
  413. #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
  414. if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
  415. mbedtls_ecp_group_id ec_grp_id = mbedtls_pk_get_ec_group_id(key);
  416. if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
  417. ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);
  418. if (ret != 0) {
  419. return ret;
  420. }
  421. has_par = 0;
  422. } else {
  423. MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));
  424. }
  425. }
  426. #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
  427. /* At this point oid_len is not null only for EC Montgomery keys. */
  428. if (oid_len == 0) {
  429. ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len);
  430. if (ret != 0) {
  431. return ret;
  432. }
  433. }
  434. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len,
  435. par_len, has_par));
  436. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
  437. MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
  438. MBEDTLS_ASN1_SEQUENCE));
  439. return (int) len;
  440. }
  441. int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
  442. {
  443. unsigned char *c;
  444. if (size == 0) {
  445. return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
  446. }
  447. c = buf + size;
  448. #if defined(MBEDTLS_RSA_C)
  449. if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
  450. return pk_write_rsa_der(&c, buf, key);
  451. } else
  452. #endif /* MBEDTLS_RSA_C */
  453. #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
  454. if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
  455. #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
  456. if (mbedtls_pk_is_rfc8410(key)) {
  457. return pk_write_ec_rfc8410_der(&c, buf, key);
  458. }
  459. #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
  460. return pk_write_ec_der(&c, buf, key);
  461. } else
  462. #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
  463. return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
  464. }
  465. /******************************************************************************
  466. * Public functions for wrinting private/public PEM keys.
  467. ******************************************************************************/
  468. #if defined(MBEDTLS_PEM_WRITE_C)
  469. #define PUB_DER_MAX_BYTES \
  470. (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
  471. MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
  472. #define PRV_DER_MAX_BYTES \
  473. (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \
  474. MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES)
  475. int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
  476. {
  477. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  478. unsigned char *output_buf = NULL;
  479. output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES);
  480. if (output_buf == NULL) {
  481. return MBEDTLS_ERR_PK_ALLOC_FAILED;
  482. }
  483. size_t olen = 0;
  484. if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
  485. PUB_DER_MAX_BYTES)) < 0) {
  486. goto cleanup;
  487. }
  488. if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY "\n", PEM_END_PUBLIC_KEY "\n",
  489. output_buf + PUB_DER_MAX_BYTES - ret,
  490. ret, buf, size, &olen)) != 0) {
  491. goto cleanup;
  492. }
  493. ret = 0;
  494. cleanup:
  495. mbedtls_free(output_buf);
  496. return ret;
  497. }
  498. int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
  499. {
  500. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  501. unsigned char *output_buf = NULL;
  502. output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES);
  503. if (output_buf == NULL) {
  504. return MBEDTLS_ERR_PK_ALLOC_FAILED;
  505. }
  506. const char *begin, *end;
  507. size_t olen = 0;
  508. if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) {
  509. goto cleanup;
  510. }
  511. #if defined(MBEDTLS_RSA_C)
  512. if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
  513. begin = PEM_BEGIN_PRIVATE_KEY_RSA "\n";
  514. end = PEM_END_PRIVATE_KEY_RSA "\n";
  515. } else
  516. #endif
  517. #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
  518. if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
  519. if (mbedtls_pk_is_rfc8410(key)) {
  520. begin = PEM_BEGIN_PRIVATE_KEY_PKCS8 "\n";
  521. end = PEM_END_PRIVATE_KEY_PKCS8 "\n";
  522. } else {
  523. begin = PEM_BEGIN_PRIVATE_KEY_EC "\n";
  524. end = PEM_END_PRIVATE_KEY_EC "\n";
  525. }
  526. } else
  527. #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
  528. {
  529. ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
  530. goto cleanup;
  531. }
  532. if ((ret = mbedtls_pem_write_buffer(begin, end,
  533. output_buf + PRV_DER_MAX_BYTES - ret,
  534. ret, buf, size, &olen)) != 0) {
  535. goto cleanup;
  536. }
  537. ret = 0;
  538. cleanup:
  539. mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES);
  540. return ret;
  541. }
  542. #endif /* MBEDTLS_PEM_WRITE_C */
  543. #endif /* MBEDTLS_PK_WRITE_C */