mbedtls.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. /*
  2. * Copyright (c) 2023, Christian Huitema
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to
  6. * deal in the Software without restriction, including without limitation the
  7. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. * sell copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. * IN THE SOFTWARE.
  21. */
  22. #ifdef _WINDOWS
  23. #include "wincompat.h"
  24. #endif
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <psa/crypto.h>
  29. #include <mbedtls/chacha20.h>
  30. #include <mbedtls/ecdh.h>
  31. #include "picotls.h"
  32. #define PSA_FUNC_FAILED(fn, ret) \
  33. do { \
  34. fprintf(stderr, "in %s at line %d, " PTLS_TO_STR(fn) " failed (%d)\n", __FUNCTION__, __LINE__, (int)ret); \
  35. abort(); \
  36. } while (0)
  37. #define CALL_WITH_CHECK(fn, ...) \
  38. do { \
  39. psa_status_t ret; \
  40. if ((ret = fn(__VA_ARGS__)) != PSA_SUCCESS) \
  41. PSA_FUNC_FAILED(fn, ret); \
  42. } while (0)
  43. void ptls_mbedtls_random_bytes(void *buf, size_t len)
  44. {
  45. CALL_WITH_CHECK(psa_generate_random, buf, len);
  46. }
  47. #define DEFINE_HASH(name, name_upcase, psa_alg) \
  48. static void name##_do_init(psa_hash_operation_t *op) \
  49. { \
  50. *op = psa_hash_operation_init(); \
  51. CALL_WITH_CHECK(psa_hash_setup, op, psa_alg); \
  52. } \
  53. static void name##_do_update(psa_hash_operation_t *op, const void *src, size_t len) \
  54. { \
  55. CALL_WITH_CHECK(psa_hash_update, op, src, len); \
  56. } \
  57. static void name##_do_final(psa_hash_operation_t *op, void *md) \
  58. { \
  59. size_t unused; \
  60. CALL_WITH_CHECK(psa_hash_finish, op, md, PTLS_##name_upcase##_DIGEST_SIZE, &unused); \
  61. } \
  62. static void name##_do_clone(psa_hash_operation_t *dst, psa_hash_operation_t *src, size_t unused) \
  63. { \
  64. CALL_WITH_CHECK(psa_hash_clone, src, dst); \
  65. } \
  66. ptls_define_hash6(name, psa_hash_operation_t, name##_do_init, name##_do_update, name##_do_final, name##_do_clone); \
  67. ptls_hash_algorithm_t ptls_mbedtls_##name = {PTLS_TO_STR(name), PTLS_##name_upcase##_BLOCK_SIZE, \
  68. PTLS_##name_upcase##_DIGEST_SIZE, name##_create, PTLS_ZERO_DIGEST_##name_upcase};
  69. DEFINE_HASH(sha256, SHA256, PSA_ALG_SHA_256);
  70. DEFINE_HASH(sha512, SHA512, PSA_ALG_SHA_512);
  71. #if defined(MBEDTLS_SHA384_C)
  72. DEFINE_HASH(sha384, SHA384, PSA_ALG_SHA_384);
  73. #endif
  74. /**
  75. * Generic implementation of a cipher using the PSA API
  76. */
  77. struct st_ptls_mbedtls_cipher_context_t {
  78. ptls_cipher_context_t super;
  79. psa_algorithm_t alg;
  80. unsigned is_enc : 1;
  81. unsigned is_op_in_progress : 1;
  82. mbedtls_svc_key_id_t key;
  83. psa_cipher_operation_t op;
  84. };
  85. static void cipher_init(ptls_cipher_context_t *_ctx, const void *iv)
  86. {
  87. struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx;
  88. if (ctx->is_op_in_progress) {
  89. psa_cipher_abort(&ctx->op);
  90. ctx->is_op_in_progress = 0;
  91. }
  92. ctx->op = psa_cipher_operation_init();
  93. if (ctx->is_enc) {
  94. CALL_WITH_CHECK(psa_cipher_encrypt_setup, &ctx->op, ctx->key, ctx->alg);
  95. } else {
  96. CALL_WITH_CHECK(psa_cipher_decrypt_setup, &ctx->op, ctx->key, ctx->alg);
  97. }
  98. ctx->is_op_in_progress = 1;
  99. if (ctx->super.algo->iv_size > 0)
  100. CALL_WITH_CHECK(psa_cipher_set_iv, &ctx->op, iv, ctx->super.algo->iv_size);
  101. }
  102. static void cipher_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
  103. {
  104. struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx;
  105. size_t unused = 0;
  106. CALL_WITH_CHECK(psa_cipher_update, &ctx->op, input, len, output, len, &unused);
  107. }
  108. static void cipher_dispose(ptls_cipher_context_t *_ctx)
  109. {
  110. struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx;
  111. if (ctx->is_op_in_progress)
  112. psa_cipher_abort(&ctx->op);
  113. psa_destroy_key(ctx->key);
  114. }
  115. static int cipher_setup(ptls_cipher_context_t *_ctx, int is_enc, const void *key_bytes, psa_algorithm_t alg,
  116. psa_key_type_t key_type)
  117. {
  118. struct st_ptls_mbedtls_cipher_context_t *ctx = (struct st_ptls_mbedtls_cipher_context_t *)_ctx;
  119. { /* import key or fail immediately */
  120. psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
  121. psa_set_key_usage_flags(&attributes, is_enc ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT);
  122. psa_set_key_algorithm(&attributes, alg);
  123. psa_set_key_type(&attributes, key_type);
  124. psa_set_key_bits(&attributes, ctx->super.algo->key_size * 8);
  125. if (psa_import_key(&attributes, key_bytes, ctx->super.algo->key_size, &ctx->key) != PSA_SUCCESS)
  126. return PTLS_ERROR_LIBRARY;
  127. }
  128. /* init the rest that are guaranteed to succeed */
  129. ctx->super.do_dispose = cipher_dispose;
  130. ctx->super.do_init = cipher_init;
  131. ctx->super.do_transform = cipher_transform;
  132. ctx->alg = alg;
  133. ctx->is_enc = is_enc;
  134. ctx->is_op_in_progress = 0;
  135. ctx->op = psa_cipher_operation_init();
  136. return 0;
  137. }
  138. static int ecb_setup(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes, psa_key_type_t key_type)
  139. {
  140. int ret;
  141. if ((ret = cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_ECB_NO_PADDING, key_type)) != 0)
  142. return ret;
  143. /* ECB mode does not necessary call `ptls_cipher_init` */
  144. cipher_init(ctx, NULL);
  145. return 0;
  146. }
  147. static int setup_aes128ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes)
  148. {
  149. return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES);
  150. }
  151. ptls_cipher_algorithm_t ptls_mbedtls_aes128ecb = {
  152. "AES128-ECB", PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t),
  153. setup_aes128ecb};
  154. static int setup_aes256ecb(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes)
  155. {
  156. return ecb_setup(ctx, is_enc, key_bytes, PSA_KEY_TYPE_AES);
  157. }
  158. ptls_cipher_algorithm_t ptls_mbedtls_aes256ecb = {
  159. "AES256-ECB", PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 0 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t),
  160. setup_aes256ecb};
  161. static int setup_aes128ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes)
  162. {
  163. return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_AES);
  164. }
  165. ptls_cipher_algorithm_t ptls_mbedtls_aes128ctr = {
  166. "AES128-CTR", PTLS_AES128_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 16 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t),
  167. setup_aes128ctr};
  168. static int setup_aes256ctr(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes)
  169. {
  170. return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_AES);
  171. }
  172. ptls_cipher_algorithm_t ptls_mbedtls_aes256ctr = {
  173. "AES128-CTR", PTLS_AES256_KEY_SIZE, PTLS_AES_BLOCK_SIZE, 16 /* iv size */, sizeof(struct st_ptls_mbedtls_cipher_context_t),
  174. setup_aes256ctr};
  175. #if 0
  176. /* CHACHA20 backend using PSA API is disabled for now, as there seems to be an issue when setting the 16 bytes long IV that we
  177. * need. */
  178. static int setup_chacha20(ptls_cipher_context_t *ctx, int is_enc, const void *key_bytes)
  179. {
  180. return cipher_setup(ctx, is_enc, key_bytes, PSA_ALG_CTR, PSA_KEY_TYPE_CHACHA20);
  181. }
  182. ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = {
  183. "CHACHA20", PTLS_CHACHA20_KEY_SIZE, 1 /* block size */, PTLS_CHACHA20_IV_SIZE, sizeof(struct st_ptls_mbedtls_cipher_context_t),
  184. setup_chacha20};
  185. #else
  186. /* Implementation of ChaCha20 using the low level ChaCha20 API.
  187. * TODO: remove this and the reference to chacha20.h as soon as the IV bug in the generic implementation is fixed. */
  188. struct st_ptls_mbedtls_chacha20_context_t {
  189. ptls_cipher_context_t super;
  190. mbedtls_chacha20_context mctx;
  191. };
  192. static void chacha20_init(ptls_cipher_context_t *_ctx, const void *v_iv)
  193. {
  194. struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx;
  195. const uint8_t *iv = (const uint8_t *)v_iv;
  196. uint32_t ctr = iv[0] | ((uint32_t)iv[1] << 8) | ((uint32_t)iv[2] << 16) | ((uint32_t)iv[3] << 24);
  197. int ret = mbedtls_chacha20_starts(&ctx->mctx, (const uint8_t *)(iv + 4), ctr);
  198. if (ret != 0)
  199. PSA_FUNC_FAILED(mbedtls_chacha20_starts, ret);
  200. }
  201. static void chacha20_transform(ptls_cipher_context_t *_ctx, void *output, const void *input, size_t len)
  202. {
  203. struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx;
  204. int ret = mbedtls_chacha20_update(&ctx->mctx, len, (const uint8_t *)input, (uint8_t *)output);
  205. if (ret != 0)
  206. PSA_FUNC_FAILED(mbedtls_chacha20_update, ret);
  207. }
  208. static void chacha20_dispose(ptls_cipher_context_t *_ctx)
  209. {
  210. struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx;
  211. mbedtls_chacha20_free(&ctx->mctx);
  212. }
  213. static int setup_chacha20(ptls_cipher_context_t *_ctx, int is_enc, const void *key)
  214. {
  215. struct st_ptls_mbedtls_chacha20_context_t *ctx = (struct st_ptls_mbedtls_chacha20_context_t *)_ctx;
  216. mbedtls_chacha20_init(&ctx->mctx);
  217. if (mbedtls_chacha20_setkey(&ctx->mctx, key) != 0)
  218. return PTLS_ERROR_LIBRARY;
  219. ctx->super.do_dispose = chacha20_dispose;
  220. ctx->super.do_init = chacha20_init;
  221. ctx->super.do_transform = chacha20_transform;
  222. return 0;
  223. }
  224. ptls_cipher_algorithm_t ptls_mbedtls_chacha20 = {"CHACHA20",
  225. PTLS_CHACHA20_KEY_SIZE,
  226. 1 /* block size */,
  227. PTLS_CHACHA20_IV_SIZE,
  228. sizeof(struct st_ptls_mbedtls_chacha20_context_t),
  229. setup_chacha20};
  230. #endif
  231. struct ptls_mbedtls_aead_context_t {
  232. struct st_ptls_aead_context_t super;
  233. uint8_t static_iv[PTLS_MAX_IV_SIZE];
  234. psa_algorithm_t alg;
  235. psa_key_id_t key;
  236. };
  237. static void aead_dispose_crypto(struct st_ptls_aead_context_t *_ctx)
  238. {
  239. struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx;
  240. psa_destroy_key(ctx->key);
  241. }
  242. static void aead_get_iv(ptls_aead_context_t *_ctx, void *iv)
  243. {
  244. struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx;
  245. memcpy(iv, ctx->static_iv, ctx->super.algo->iv_size);
  246. }
  247. static void aead_set_iv(ptls_aead_context_t *_ctx, const void *iv)
  248. {
  249. struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx;
  250. memcpy(ctx->static_iv, iv, ctx->super.algo->iv_size);
  251. }
  252. static void aead_encrypt_v(struct st_ptls_aead_context_t *_ctx, void *output, ptls_iovec_t *input, size_t incnt, uint64_t seq,
  253. const void *aad, size_t aadlen)
  254. {
  255. struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx;
  256. psa_aead_operation_t op = psa_aead_operation_init();
  257. uint8_t *dst = output, iv[PTLS_MAX_IV_SIZE], tag[PSA_AEAD_TAG_MAX_SIZE];
  258. size_t outlen, taglen;
  259. /* setup op */
  260. CALL_WITH_CHECK(psa_aead_encrypt_setup, &op, ctx->key, ctx->alg);
  261. ptls_aead__build_iv(ctx->super.algo, iv, ctx->static_iv, seq);
  262. CALL_WITH_CHECK(psa_aead_set_nonce, &op, iv, ctx->super.algo->iv_size);
  263. CALL_WITH_CHECK(psa_aead_update_ad, &op, aad, aadlen);
  264. /* encrypt */
  265. for (size_t i = 0; i < incnt; i++) {
  266. CALL_WITH_CHECK(psa_aead_update, &op, input[i].base, input[i].len, dst, SIZE_MAX, &outlen);
  267. dst += outlen;
  268. }
  269. CALL_WITH_CHECK(psa_aead_finish, &op, dst, SIZE_MAX, &outlen, tag, sizeof(tag), &taglen);
  270. dst += outlen;
  271. memcpy(dst, tag, taglen);
  272. /* destroy op */
  273. psa_aead_abort(&op);
  274. }
  275. static size_t aead_decrypt(struct st_ptls_aead_context_t *_ctx, void *output, const void *input, size_t inlen, uint64_t seq,
  276. const void *aad, size_t aadlen)
  277. {
  278. struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx;
  279. uint8_t iv[PTLS_MAX_IV_SIZE];
  280. size_t outlen;
  281. ptls_aead__build_iv(ctx->super.algo, iv, ctx->static_iv, seq);
  282. psa_status_t ret =
  283. psa_aead_decrypt(ctx->key, ctx->alg, iv, ctx->super.algo->iv_size, aad, aadlen, input, inlen, output, inlen, &outlen);
  284. switch (ret) {
  285. case PSA_SUCCESS:
  286. break;
  287. case PSA_ERROR_INVALID_SIGNATURE:
  288. outlen = SIZE_MAX;
  289. break;
  290. default:
  291. PSA_FUNC_FAILED(psa_aead_decrypt, ret);
  292. break;
  293. }
  294. return outlen;
  295. }
  296. static int aead_setup(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv, psa_algorithm_t psa_alg,
  297. size_t key_bits, psa_key_type_t key_type)
  298. {
  299. struct ptls_mbedtls_aead_context_t *ctx = (struct ptls_mbedtls_aead_context_t *)_ctx;
  300. { /* setup key */
  301. psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
  302. psa_set_key_usage_flags(&attributes, is_enc ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT);
  303. psa_set_key_algorithm(&attributes, psa_alg);
  304. psa_set_key_type(&attributes, key_type);
  305. psa_set_key_bits(&attributes, key_bits);
  306. if (psa_import_key(&attributes, key_bytes, key_bits / 8, &ctx->key) != PSA_SUCCESS)
  307. return PTLS_ERROR_LIBRARY;
  308. }
  309. /* setup the rest */
  310. ctx->super.dispose_crypto = aead_dispose_crypto;
  311. ctx->super.do_get_iv = aead_get_iv;
  312. ctx->super.do_set_iv = aead_set_iv;
  313. if (is_enc) {
  314. ctx->super.do_encrypt = ptls_aead__do_encrypt;
  315. ctx->super.do_encrypt_v = aead_encrypt_v;
  316. } else {
  317. ctx->super.do_decrypt = aead_decrypt;
  318. }
  319. memcpy(ctx->static_iv, iv, ctx->super.algo->iv_size);
  320. ctx->alg = psa_alg;
  321. return 0;
  322. }
  323. static int aead_setup_aes128gcm(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv)
  324. {
  325. return aead_setup(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 128, PSA_KEY_TYPE_AES);
  326. }
  327. ptls_aead_algorithm_t ptls_mbedtls_aes128gcm = {"AES128-GCM",
  328. PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
  329. PTLS_AESGCM_INTEGRITY_LIMIT,
  330. &ptls_mbedtls_aes128ctr,
  331. &ptls_mbedtls_aes128ecb,
  332. PTLS_AES128_KEY_SIZE,
  333. PTLS_AESGCM_IV_SIZE,
  334. PTLS_AESGCM_TAG_SIZE,
  335. {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE},
  336. 0,
  337. 0,
  338. sizeof(struct ptls_mbedtls_aead_context_t),
  339. aead_setup_aes128gcm};
  340. ptls_cipher_suite_t ptls_mbedtls_aes128gcmsha256 = {.id = PTLS_CIPHER_SUITE_AES_128_GCM_SHA256,
  341. .name = PTLS_CIPHER_SUITE_NAME_AES_128_GCM_SHA256,
  342. .aead = &ptls_mbedtls_aes128gcm,
  343. .hash = &ptls_mbedtls_sha256};
  344. static int aead_setup_aes256gcm(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv)
  345. {
  346. return aead_setup(_ctx, is_enc, key_bytes, iv, PSA_ALG_GCM, 256, PSA_KEY_TYPE_AES);
  347. }
  348. ptls_aead_algorithm_t ptls_mbedtls_aes256gcm = {"AES256-GCM",
  349. PTLS_AESGCM_CONFIDENTIALITY_LIMIT,
  350. PTLS_AESGCM_INTEGRITY_LIMIT,
  351. &ptls_mbedtls_aes256ctr,
  352. &ptls_mbedtls_aes256ecb,
  353. PTLS_AES256_KEY_SIZE,
  354. PTLS_AESGCM_IV_SIZE,
  355. PTLS_AESGCM_TAG_SIZE,
  356. {PTLS_TLS12_AESGCM_FIXED_IV_SIZE, PTLS_TLS12_AESGCM_RECORD_IV_SIZE},
  357. 0,
  358. 0,
  359. sizeof(struct ptls_mbedtls_aead_context_t),
  360. aead_setup_aes256gcm};
  361. #if defined(MBEDTLS_SHA384_C)
  362. ptls_cipher_suite_t ptls_mbedtls_aes256gcmsha384 = {.id = PTLS_CIPHER_SUITE_AES_256_GCM_SHA384,
  363. .name = PTLS_CIPHER_SUITE_NAME_AES_256_GCM_SHA384,
  364. .aead = &ptls_mbedtls_aes256gcm,
  365. .hash = &ptls_mbedtls_sha384};
  366. #endif
  367. static int aead_setup_chacha20poly1305(ptls_aead_context_t *_ctx, int is_enc, const void *key_bytes, const void *iv)
  368. {
  369. return aead_setup(_ctx, is_enc, key_bytes, iv, PSA_ALG_CHACHA20_POLY1305, 256, PSA_KEY_TYPE_CHACHA20);
  370. }
  371. ptls_aead_algorithm_t ptls_mbedtls_chacha20poly1305 = {"CHACHA20-POLY1305",
  372. PTLS_CHACHA20POLY1305_CONFIDENTIALITY_LIMIT,
  373. PTLS_CHACHA20POLY1305_INTEGRITY_LIMIT,
  374. &ptls_mbedtls_chacha20,
  375. NULL,
  376. PTLS_CHACHA20_KEY_SIZE,
  377. PTLS_CHACHA20POLY1305_IV_SIZE,
  378. PTLS_CHACHA20POLY1305_TAG_SIZE,
  379. {PTLS_TLS12_CHACHAPOLY_FIXED_IV_SIZE, PTLS_TLS12_CHACHAPOLY_RECORD_IV_SIZE},
  380. 0,
  381. 0,
  382. sizeof(struct ptls_mbedtls_aead_context_t),
  383. aead_setup_chacha20poly1305};
  384. ptls_cipher_suite_t ptls_mbedtls_chacha20poly1305sha256 = {.id = PTLS_CIPHER_SUITE_CHACHA20_POLY1305_SHA256,
  385. .name = PTLS_CIPHER_SUITE_NAME_CHACHA20_POLY1305_SHA256,
  386. .aead = &ptls_mbedtls_chacha20poly1305,
  387. .hash = &ptls_mbedtls_sha256};
  388. ptls_cipher_suite_t *ptls_mbedtls_cipher_suites[] = {
  389. #if defined(MBEDTLS_SHA384_C)
  390. &ptls_mbedtls_aes256gcmsha384,
  391. #endif
  392. &ptls_mbedtls_aes128gcmsha256, &ptls_mbedtls_chacha20poly1305sha256, NULL};
  393. #define PTLS_MBEDTLS_ECDH_PUBKEY_MAX 129
  394. static const struct ptls_mbedtls_key_exchange_params_t {
  395. psa_algorithm_t alg;
  396. psa_ecc_family_t curve;
  397. size_t curve_bits;
  398. size_t secret_size;
  399. } secp256r1_params = {PSA_ALG_ECDH, PSA_ECC_FAMILY_SECP_R1, 256, 32},
  400. x25519_params = {PSA_ALG_ECDH, PSA_ECC_FAMILY_MONTGOMERY, 255, 32};
  401. struct ptls_mbedtls_key_exchange_context_t {
  402. ptls_key_exchange_context_t super;
  403. const struct ptls_mbedtls_key_exchange_params_t *params;
  404. psa_key_id_t private_key;
  405. uint8_t pubkeybuf[PTLS_MBEDTLS_ECDH_PUBKEY_MAX];
  406. };
  407. /**
  408. * Generates a private key. For now, we only support ECC.
  409. */
  410. static int generate_private_key(psa_key_id_t *private_key, const struct ptls_mbedtls_key_exchange_params_t *params)
  411. {
  412. psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
  413. int ret = 0;
  414. psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
  415. psa_set_key_algorithm(&attributes, params->alg);
  416. psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(params->curve));
  417. psa_set_key_bits(&attributes, params->curve_bits);
  418. if (psa_generate_key(&attributes, private_key) != 0) {
  419. ret = -1;
  420. }
  421. return ret;
  422. }
  423. static int key_exchange_on_exchange(struct st_ptls_key_exchange_context_t **_keyex, int release, ptls_iovec_t *secret,
  424. ptls_iovec_t peerkey)
  425. {
  426. struct ptls_mbedtls_key_exchange_context_t *keyex = (struct ptls_mbedtls_key_exchange_context_t *)*_keyex;
  427. int ret = 0;
  428. if (secret == NULL)
  429. goto Exit;
  430. /* derive shared secret */
  431. if ((secret->base = malloc(keyex->params->secret_size)) == NULL) {
  432. ret = PTLS_ERROR_NO_MEMORY;
  433. goto Exit;
  434. }
  435. if (psa_raw_key_agreement(keyex->params->alg, keyex->private_key, peerkey.base, peerkey.len, secret->base,
  436. keyex->params->secret_size, &secret->len) != 0) {
  437. ret = PTLS_ERROR_LIBRARY;
  438. goto Exit;
  439. }
  440. assert(keyex->params->secret_size == secret->len);
  441. ret = 0;
  442. Exit:
  443. if (ret != 0 && secret != NULL) {
  444. free(secret->base);
  445. *secret = ptls_iovec_init(NULL, 0);
  446. }
  447. if (release) {
  448. psa_destroy_key(keyex->private_key);
  449. free(keyex);
  450. *_keyex = NULL;
  451. }
  452. return ret;
  453. }
  454. static int key_exchange_create(ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx,
  455. const struct ptls_mbedtls_key_exchange_params_t *params)
  456. {
  457. struct ptls_mbedtls_key_exchange_context_t *keyex;
  458. *ctx = NULL;
  459. /* setup context */
  460. if ((keyex = malloc(sizeof(*keyex))) == NULL)
  461. return PTLS_ERROR_NO_MEMORY;
  462. *keyex = (struct ptls_mbedtls_key_exchange_context_t){
  463. .super.algo = algo,
  464. .super.pubkey.base = keyex->pubkeybuf,
  465. .super.on_exchange = key_exchange_on_exchange,
  466. .params = params,
  467. };
  468. /* generate private key */
  469. if (generate_private_key(&keyex->private_key, keyex->params) != 0) {
  470. free(keyex);
  471. return PTLS_ERROR_LIBRARY;
  472. }
  473. { /* export public key */
  474. psa_status_t ret =
  475. psa_export_public_key(keyex->private_key, keyex->pubkeybuf, sizeof(keyex->pubkeybuf), &keyex->super.pubkey.len);
  476. if (ret != 0)
  477. PSA_FUNC_FAILED(psa_export_public_key, ret);
  478. }
  479. *ctx = &keyex->super;
  480. return 0;
  481. }
  482. static int key_exchange_exchange(ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret,
  483. ptls_iovec_t peerkey, const struct ptls_mbedtls_key_exchange_params_t *params)
  484. {
  485. psa_key_id_t private_key;
  486. int ret;
  487. *pubkey = ptls_iovec_init(NULL, 0);
  488. *secret = ptls_iovec_init(NULL, 0);
  489. /* generate private key (and return immediately upon failure) */
  490. if (generate_private_key(&private_key, params) != 0)
  491. return PTLS_ERROR_LIBRARY;
  492. /* allocate buffers */
  493. if ((secret->base = malloc(params->secret_size)) == NULL) {
  494. ret = PTLS_ERROR_NO_MEMORY;
  495. goto Exit;
  496. }
  497. if ((pubkey->base = malloc(PTLS_MBEDTLS_ECDH_PUBKEY_MAX)) == NULL) {
  498. ret = PTLS_ERROR_NO_MEMORY;
  499. goto Exit;
  500. }
  501. /* export public key and call key agrement function */
  502. if (psa_export_public_key(private_key, pubkey->base, PTLS_MBEDTLS_ECDH_PUBKEY_MAX, &pubkey->len) != 0 ||
  503. psa_raw_key_agreement(params->alg, private_key, peerkey.base, peerkey.len, secret->base, params->secret_size,
  504. &secret->len) != 0) {
  505. ret = PTLS_ERROR_LIBRARY;
  506. goto Exit;
  507. }
  508. ret = 0;
  509. Exit:
  510. if (ret != 0) {
  511. free(pubkey->base);
  512. *pubkey = ptls_iovec_init(NULL, 0);
  513. free(secret->base);
  514. *secret = ptls_iovec_init(NULL, 0);
  515. }
  516. psa_destroy_key(private_key);
  517. return ret;
  518. }
  519. static int secp256r1_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx)
  520. {
  521. return key_exchange_create(algo, ctx, &secp256r1_params);
  522. }
  523. static int secp256r1_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret,
  524. ptls_iovec_t peerkey)
  525. {
  526. return key_exchange_exchange(algo, pubkey, secret, peerkey, &secp256r1_params);
  527. }
  528. ptls_key_exchange_algorithm_t ptls_mbedtls_secp256r1 = {
  529. .id = PTLS_GROUP_SECP256R1, .name = PTLS_GROUP_NAME_SECP256R1, .create = secp256r1_create, .exchange = secp256r1_exchange};
  530. static int x25519_create(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_key_exchange_context_t **ctx)
  531. {
  532. return key_exchange_create(algo, ctx, &x25519_params);
  533. }
  534. static int x25519_exchange(const struct st_ptls_key_exchange_algorithm_t *algo, ptls_iovec_t *pubkey, ptls_iovec_t *secret,
  535. ptls_iovec_t peerkey)
  536. {
  537. return key_exchange_exchange(algo, pubkey, secret, peerkey, &x25519_params);
  538. }
  539. ptls_key_exchange_algorithm_t ptls_mbedtls_x25519 = {
  540. .id = PTLS_GROUP_X25519, .name = PTLS_GROUP_NAME_X25519, .create = x25519_create, .exchange = x25519_exchange};
  541. ptls_key_exchange_algorithm_t *ptls_mbedtls_key_exchanges[] = {&ptls_mbedtls_secp256r1, NULL};