psa_pkcbs.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. /* psa_pkcbs.c
  2. *
  3. * Copyright (C) 2006-2023 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL.
  6. *
  7. * wolfSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * wolfSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #include <wolfssl/wolfcrypt/settings.h>
  25. #if defined(WOLFSSL_HAVE_PSA)
  26. #if defined(HAVE_PK_CALLBACKS)
  27. #if !defined(WOLFSSL_PSA_NO_PKCBS)
  28. #include <psa/crypto.h>
  29. #include <wolfssl/wolfcrypt/port/psa/psa.h>
  30. #include <wolfssl/wolfcrypt/error-crypt.h>
  31. #include <wolfssl/internal.h>
  32. #include <wolfssl/wolfcrypt/asn.h>
  33. #include <wolfssl/wolfcrypt/logging.h>
  34. #ifdef HAVE_ECC
  35. #include <wolfssl/wolfcrypt/ecc.h>
  36. static int psa_ecc_get_curve_info_from_curve_id(int ecc_curve,
  37. psa_ecc_family_t *family,
  38. size_t *key_size)
  39. {
  40. if (ecc_curve != ECC_SECP256R1)
  41. return NOT_COMPILED_IN;
  42. *family = PSA_ECC_FAMILY_SECP_R1;
  43. if (key_size != NULL)
  44. *key_size = 32;
  45. return 0;
  46. }
  47. /**
  48. * psa_ecc_export_to_wc_key() - export psa @key_id into ecc_key @key
  49. * @key: already initialized ecc_key to export the key into [out]
  50. * @key_id: key to export [in]
  51. * @key_size: size of the key [in]
  52. * @curve_id: wc id of the curve [in]
  53. *
  54. * returns 0 on success
  55. */
  56. static int psa_ecc_export_to_wc_key(struct ecc_key *key,
  57. psa_key_id_t key_id,
  58. int curve_id)
  59. {
  60. uint8_t raw[(MAX_ECC_BYTES * 2) + 1];
  61. psa_status_t status;
  62. size_t length;
  63. int ret;
  64. PSA_LOCK();
  65. status = psa_export_public_key(key_id,
  66. raw, sizeof(raw), &length);
  67. PSA_UNLOCK();
  68. if (status != PSA_SUCCESS) {
  69. WOLFSSL_MSG("PSA: export key error");
  70. return WC_HW_E;
  71. }
  72. ret = wc_ecc_import_x963_ex(raw, (word32)length, key, curve_id);
  73. if (ret != 0) {
  74. WOLFSSL_MSG("PSA: import key error");
  75. return WC_HW_E;
  76. }
  77. return 0;
  78. }
  79. static int psa_ecc_keygen(int ecc_curve, unsigned key_size,
  80. psa_key_id_t *key_id)
  81. {
  82. psa_key_attributes_t key_attr = { 0 };
  83. size_t ecc_curve_key_size;
  84. psa_ecc_family_t family;
  85. psa_status_t status;
  86. int ret;
  87. ret = psa_ecc_get_curve_info_from_curve_id(ecc_curve, &family,
  88. &ecc_curve_key_size);
  89. if (ret != 0)
  90. return ret;
  91. if (key_size != 0 && key_size != ecc_curve_key_size)
  92. return BAD_FUNC_ARG;
  93. psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(family));
  94. psa_set_key_bits(&key_attr, ecc_curve_key_size * 8);
  95. psa_set_key_algorithm(&key_attr, PSA_ALG_ECDH);
  96. psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  97. PSA_LOCK();
  98. status = psa_generate_key(&key_attr, key_id);
  99. PSA_UNLOCK();
  100. if (status != PSA_SUCCESS)
  101. return WC_HW_E;
  102. return 0;
  103. }
  104. static int psa_ecc_keygen_cb(WOLFSSL* ssl, struct ecc_key* key,
  105. unsigned int key_size, int ecc_curve, void* ctx)
  106. {
  107. struct psa_ssl_ctx *psa_ctx = (struct psa_ssl_ctx *)ctx;
  108. psa_key_id_t psa_key_id;
  109. int ret;
  110. (void)ssl;
  111. WOLFSSL_ENTER("psa_ecc_keygen_cb");
  112. if (psa_ctx == NULL)
  113. return BAD_FUNC_ARG;
  114. ret = psa_ecc_keygen(ecc_curve, key_size, &psa_key_id);
  115. if (ret != 0)
  116. return WC_HW_E;
  117. ret = psa_ecc_export_to_wc_key(key, psa_key_id, ecc_curve);
  118. if (ret != 0) {
  119. PSA_LOCK();
  120. psa_destroy_key(psa_key_id);
  121. PSA_UNLOCK();
  122. return WC_HW_E;
  123. }
  124. psa_ctx->dh_key = psa_key_id;
  125. return 0;
  126. }
  127. static int psa_ecc_shared_secret_tls12_client(struct ecc_key* other_key,
  128. unsigned char* pubKeyDer,
  129. word32* pubKeySz,
  130. unsigned char* out,
  131. word32* output_size)
  132. {
  133. uint8_t raw[(MAX_ECC_BYTES * 2) + 1];
  134. psa_status_t status;
  135. word32 raw_length;
  136. psa_key_id_t key;
  137. size_t length;
  138. int ret;
  139. ret = psa_ecc_keygen(other_key->dp->id, 0, &key);
  140. if (ret != 0)
  141. return ret;
  142. PSA_LOCK();
  143. status = psa_export_public_key(key, pubKeyDer, *pubKeySz, &length);
  144. PSA_UNLOCK();
  145. if (status != PSA_SUCCESS) {
  146. ret = WC_HW_E;
  147. goto exit;
  148. }
  149. *pubKeySz = (word32)length;
  150. raw_length = (word32)sizeof(raw);
  151. ret = wc_ecc_export_x963_ex(other_key, raw, &raw_length, 0);
  152. if (ret != 0)
  153. goto exit;
  154. PSA_LOCK();
  155. status = psa_raw_key_agreement(PSA_ALG_ECDH, key,
  156. raw, raw_length,
  157. out, *output_size,
  158. &length);
  159. PSA_UNLOCK();
  160. if (status != PSA_SUCCESS) {
  161. ret = WC_HW_E;
  162. goto exit;
  163. }
  164. *output_size = (word32)length;
  165. ret = 0;
  166. exit:
  167. PSA_LOCK();
  168. psa_destroy_key(key);
  169. PSA_UNLOCK();
  170. return ret;
  171. }
  172. static int psa_ecc_shared_secret_cb(WOLFSSL* ssl, struct ecc_key* other_key,
  173. unsigned char* pubKeyDer, word32* pubKeySz,
  174. unsigned char* out, word32* output_size,
  175. int side, void* ctx)
  176. {
  177. struct psa_ssl_ctx *psa_ctx = (struct psa_ssl_ctx *)ctx;
  178. size_t output_length;
  179. psa_status_t status;
  180. if (psa_ctx == NULL)
  181. return BAD_FUNC_ARG;
  182. WOLFSSL_ENTER("psa_ecc_shared_secret_cb");
  183. /* client before tls13 must create the key and export it in pubkeyDer. The
  184. server key is stored in other_key */
  185. if (side == WOLFSSL_CLIENT_END &&
  186. wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) {
  187. return psa_ecc_shared_secret_tls12_client(other_key,
  188. pubKeyDer, pubKeySz,
  189. out, output_size);
  190. }
  191. PSA_LOCK();
  192. status = psa_raw_key_agreement(PSA_ALG_ECDH,
  193. psa_ctx->dh_key,
  194. pubKeyDer,
  195. *pubKeySz,
  196. out, *output_size,
  197. &output_length);
  198. PSA_UNLOCK();
  199. if (status != PSA_SUCCESS) {
  200. WOLFSSL_MSG("PSA: error raw_key_agreement");
  201. return WC_HW_E;
  202. }
  203. *output_size = (word32)output_length;
  204. PSA_LOCK();
  205. psa_destroy_key(psa_ctx->dh_key);
  206. PSA_UNLOCK();
  207. psa_ctx->dh_key = PSA_KEY_ID_NULL;
  208. return 0;
  209. }
  210. /* Map hash length to equivalent psa_algorithm_t type.
  211. *
  212. * hash_len - length of hash
  213. *
  214. * Return psa_algorithm_t representing hash algorithm for hash length, or
  215. * PSA_ALG_NONE if no match.
  216. */
  217. static int psa_map_hash_alg(int hash_len)
  218. {
  219. switch (hash_len) {
  220. case 20:
  221. return PSA_ALG_SHA_1;
  222. case 28:
  223. return PSA_ALG_SHA_224;
  224. case 32:
  225. return PSA_ALG_SHA_256;
  226. case 48:
  227. return PSA_ALG_SHA_384;
  228. case 64:
  229. return PSA_ALG_SHA_512;
  230. default:
  231. return PSA_ALG_NONE;
  232. }
  233. }
  234. static int psa_ecc_sign_cb(WOLFSSL* ssl, const unsigned char* input,
  235. unsigned int input_length,
  236. unsigned char* signature, word32* signature_size,
  237. const unsigned char* keyDer, unsigned int keySz,
  238. void* ctx)
  239. {
  240. struct psa_ssl_ctx *psa_ctx = (struct psa_ssl_ctx*)ctx;
  241. uint8_t rs[MAX_ECC_BYTES * 2];
  242. psa_status_t status;
  243. size_t rs_length;
  244. word32 point_len;
  245. psa_algorithm_t hash_algo;
  246. int ret;
  247. (void)ssl;
  248. (void)keyDer;
  249. (void)keySz;
  250. WOLFSSL_ENTER("psa_ecc_sign_cb");
  251. if (psa_ctx == NULL)
  252. return BAD_FUNC_ARG;
  253. /* Get correct hash algorithm that matches input hash length */
  254. hash_algo = psa_map_hash_alg(input_length);
  255. status = psa_sign_hash(psa_ctx->private_key,
  256. PSA_ALG_ECDSA(hash_algo), input,
  257. input_length, rs, sizeof(rs),
  258. &rs_length);
  259. if (status != PSA_SUCCESS)
  260. return WC_HW_E;
  261. point_len = (word32)(rs_length / 2);
  262. ret = wc_ecc_rs_raw_to_sig(rs, point_len, rs + point_len, point_len,
  263. signature, signature_size);
  264. if (ret != 0)
  265. return -1;
  266. return 0;
  267. }
  268. static int psa_ecc_decode_public_key(const uint8_t *key, word32 key_length,
  269. psa_key_id_t *key_id,
  270. psa_algorithm_t hash_algo)
  271. {
  272. uint8_t raw_key[(MAX_ECC_BYTES * 2) + 1];
  273. psa_key_attributes_t attr = { 0 };
  274. word32 raw_key_length, idx;
  275. psa_ecc_family_t ecc_curve;
  276. size_t ecc_curve_size;
  277. psa_status_t status;
  278. ecc_key tmp_key;
  279. int ret;
  280. ret = wc_ecc_init(&tmp_key);
  281. if (ret != 0 )
  282. return ret;
  283. idx = 0;
  284. ret = wc_EccPublicKeyDecode(key, &idx, &tmp_key, key_length);
  285. if (ret != 0 )
  286. goto exit;
  287. raw_key_length = (word32)sizeof(raw_key);
  288. ret = wc_ecc_export_x963_ex(&tmp_key, raw_key, &raw_key_length, 0);
  289. if (ret != 0 )
  290. goto exit;
  291. ret = psa_ecc_get_curve_info_from_curve_id(tmp_key.dp->id,
  292. &ecc_curve, &ecc_curve_size);
  293. if (ret != 0 )
  294. goto exit;
  295. psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(ecc_curve));
  296. psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_VERIFY_HASH);
  297. psa_set_key_bits(&attr, ecc_curve_size * 8);
  298. psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(hash_algo));
  299. PSA_LOCK();
  300. status = psa_import_key(&attr, raw_key, raw_key_length, key_id);
  301. PSA_UNLOCK();
  302. if (status != PSA_SUCCESS) {
  303. WOLFSSL_MSG("psa_ecc_decode_public_key: can't import the key");
  304. ret = WC_HW_E;
  305. goto exit;
  306. }
  307. ret = 0;
  308. exit:
  309. wc_ecc_free(&tmp_key);
  310. return ret;
  311. }
  312. static int psa_ecc_verify_cb(WOLFSSL* ssl, const byte* sig, word32 sig_length,
  313. const byte* hash, word32 hash_length,
  314. const byte* key, word32 key_length,
  315. int* result, void* ctx)
  316. {
  317. uint8_t raw_signature[MAX_ECC_BYTES * 2], *s;
  318. psa_key_id_t tmp_key;
  319. word32 r_len, s_len;
  320. psa_status_t status;
  321. psa_algorithm_t hash_algo;
  322. int ret;
  323. (void)ssl;
  324. (void)ctx;
  325. WOLFSSL_ENTER("psa_ecc_verify_cb");
  326. /* Get correct hash algorithm that matches input hash length */
  327. hash_algo = psa_map_hash_alg(hash_length);
  328. ret = psa_ecc_decode_public_key(key, key_length, &tmp_key, hash_algo);
  329. if (ret != 0)
  330. return ret;
  331. r_len = s_len = MAX_ECC_BYTES;
  332. s = raw_signature + r_len;
  333. ret = wc_ecc_sig_to_rs(sig, sig_length, raw_signature, &r_len,
  334. s, &s_len);
  335. if (ret != 0)
  336. goto exit;
  337. /* coalescence of r and s in the buffer */
  338. XMEMCPY(raw_signature + r_len, s, s_len);
  339. PSA_LOCK();
  340. status = psa_verify_hash(tmp_key, PSA_ALG_ECDSA(hash_algo), hash,
  341. hash_length, raw_signature, r_len + s_len);
  342. PSA_UNLOCK();
  343. if (status == PSA_SUCCESS) {
  344. *result = 1;
  345. } else {
  346. *result = 0;
  347. if (status != PSA_ERROR_INVALID_SIGNATURE) {
  348. WOLFSSL_MSG("psa_ecc_verify_cb: can't verify hash");
  349. ret = WC_HW_E;
  350. }
  351. /* returns 0 for invalid signature as well */
  352. }
  353. exit:
  354. PSA_LOCK();
  355. psa_destroy_key(tmp_key);
  356. PSA_UNLOCK();
  357. return ret;
  358. }
  359. #endif /* HAVE_ECC */
  360. #ifdef HAVE_HKDF
  361. static int psa_hkdf_extract_cb(byte* prk, const byte* salt,
  362. word32 salt_length, byte* ikm,
  363. word32 ikm_length, int digest,
  364. void* ctx)
  365. {
  366. psa_key_attributes_t attr = { 0 };
  367. psa_algorithm_t hash;
  368. psa_key_id_t tmp_key;
  369. psa_status_t status;
  370. size_t digest_len;
  371. (void)ctx;
  372. WOLFSSL_ENTER("psa hkdf cb");
  373. if (salt_length != 0 && salt == NULL)
  374. return BAD_FUNC_ARG;
  375. switch (digest) {
  376. #ifndef NO_SHA256
  377. case WC_SHA256:
  378. digest_len = WC_SHA256_DIGEST_SIZE;
  379. hash = PSA_ALG_SHA_256;
  380. break;
  381. #endif
  382. #ifdef WOLFSSL_SHA384
  383. case WC_SHA384:
  384. digest_len = WC_SHA384_DIGEST_SIZE;
  385. hash = PSA_ALG_SHA_384;
  386. break;
  387. #endif
  388. default:
  389. return BAD_FUNC_ARG;
  390. }
  391. psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
  392. psa_set_key_algorithm(&attr, PSA_ALG_HMAC(hash));
  393. psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_MESSAGE);
  394. /* salt not provided, use zeroed digest len string. Use temporarily the prk
  395. buffer as we are sure is big enough */
  396. if (salt == NULL) {
  397. XMEMSET(prk, 0, digest_len);
  398. salt = prk;
  399. salt_length = (word32)digest_len;
  400. }
  401. /* When length is 0 then use zeroed data of digest length. */
  402. if (ikm_length == 0) {
  403. ikm_length = (word32)digest_len;
  404. XMEMSET(ikm, 0, digest_len);
  405. }
  406. PSA_LOCK();
  407. status = psa_import_key(&attr, salt, salt_length, &tmp_key);
  408. PSA_UNLOCK();
  409. if (status != PSA_SUCCESS) {
  410. WOLFSSL_MSG("psa_hkdf_cb: failed to import tmp key");
  411. return WC_HW_E;
  412. }
  413. PSA_LOCK();
  414. status = psa_mac_compute(tmp_key, PSA_ALG_HMAC(hash),
  415. ikm, ikm_length, prk, digest_len,
  416. &digest_len);
  417. PSA_UNLOCK();
  418. if (status != PSA_SUCCESS) {
  419. WOLFSSL_MSG("psa_hkdf_cb: failed to compute hashed mac");
  420. PSA_LOCK();
  421. psa_destroy_key(tmp_key);
  422. PSA_UNLOCK();
  423. return WC_HW_E;
  424. }
  425. PSA_LOCK();
  426. psa_destroy_key(tmp_key);
  427. PSA_UNLOCK();
  428. return 0;
  429. }
  430. #endif /* HAVE_HKDF */
  431. int wolfSSL_psa_set_private_key_id(struct psa_ssl_ctx *ctx, psa_key_id_t id)
  432. {
  433. if (ctx == NULL)
  434. return BAD_FUNC_ARG;
  435. if (id == PSA_KEY_ID_NULL)
  436. return BAD_FUNC_ARG;
  437. ctx->private_key = id;
  438. return WOLFSSL_SUCCESS;
  439. }
  440. void wolfSSL_free_psa_ctx(struct psa_ssl_ctx *ctx)
  441. {
  442. if (ctx->dh_key != PSA_KEY_ID_NULL) {
  443. PSA_LOCK();
  444. psa_destroy_key(ctx->dh_key);
  445. PSA_UNLOCK();
  446. ctx->dh_key = PSA_KEY_ID_NULL;
  447. }
  448. }
  449. int wolfSSL_set_psa_ctx(WOLFSSL *ssl, struct psa_ssl_ctx *ctx)
  450. {
  451. if (ctx == NULL || ssl == NULL)
  452. return BAD_FUNC_ARG;
  453. #ifdef HAVE_ECC
  454. wolfSSL_SetEccSignCtx(ssl, ctx);
  455. wolfSSL_SetEccKeyGenCtx(ssl, ctx);
  456. wolfSSL_SetEccSharedSecretCtx(ssl, ctx);
  457. wolfSSL_SetEccVerifyCtx(ssl, ctx);
  458. #endif
  459. #ifdef HAVE_HKDF
  460. wolfSSL_SetHKDFExtractCtx(ssl, ctx);
  461. #endif
  462. return WOLFSSL_SUCCESS;
  463. }
  464. int wolfSSL_CTX_psa_enable(WOLFSSL_CTX *ctx)
  465. {
  466. if (ctx == NULL)
  467. return BAD_FUNC_ARG;
  468. #ifdef HAVE_ECC
  469. wolfSSL_CTX_SetEccSignCb(ctx, psa_ecc_sign_cb);
  470. wolfSSL_CTX_SetEccKeyGenCb(ctx, psa_ecc_keygen_cb);
  471. wolfSSL_CTX_SetEccSharedSecretCb(ctx, psa_ecc_shared_secret_cb);
  472. wolfSSL_CTX_SetEccVerifyCb(ctx, psa_ecc_verify_cb);
  473. #endif
  474. #ifdef HAVE_HKDF
  475. wolfSSL_CTX_SetHKDFExtractCb(ctx, psa_hkdf_extract_cb);
  476. #endif
  477. return WOLFSSL_SUCCESS;
  478. }
  479. #endif /* !WOLFSSL_PSA_NO_PKCBS */
  480. #endif /* HAVE_PK_CALLBACKS */
  481. #endif /* WOLFSSL_HAVE_PSA */