jwe-ecdh-es-aeskw.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #include "private-lib-core.h"
  25. #include "private-lib-jose-jwe.h"
  26. /*
  27. * From RFC7518 JWA
  28. *
  29. * 4.6. Key Agreement with Elliptic Curve Diffie-Hellman Ephemeral Static
  30. * (ECDH-ES)
  31. *
  32. * This section defines the specifics of key agreement with Elliptic
  33. * Curve Diffie-Hellman Ephemeral Static [RFC6090], in combination with
  34. * the Concat KDF, as defined in Section 5.8.1 of [NIST.800-56A]. The
  35. * key agreement result can be used in one of two ways:
  36. *
  37. * 1. directly as the Content Encryption Key (CEK) for the "enc"
  38. * algorithm, in the Direct Key Agreement mode, or
  39. *
  40. * 2. as a symmetric key used to wrap the CEK with the "A128KW",
  41. * "A192KW", or "A256KW" algorithms, in the Key Agreement with Key
  42. * Wrapping mode.
  43. *
  44. * A new ephemeral public key value MUST be generated for each key
  45. * agreement operation.
  46. *
  47. * In Direct Key Agreement mode, the output of the Concat KDF MUST be a
  48. * key of the same length as that used by the "enc" algorithm. In this
  49. * case, the empty octet sequence is used as the JWE Encrypted Key
  50. * value. The "alg" (algorithm) Header Parameter value "ECDH-ES" is
  51. * used in the Direct Key Agreement mode.
  52. *
  53. * In Key Agreement with Key Wrapping mode, the output of the Concat KDF
  54. * MUST be a key of the length needed for the specified key wrapping
  55. * algorithm. In this case, the JWE Encrypted Key is the CEK wrapped
  56. * with the agreed-upon key.
  57. *
  58. * The following "alg" (algorithm) Header Parameter values are used to
  59. * indicate that the JWE Encrypted Key is the result of encrypting the
  60. * CEK using the result of the key agreement algorithm as the key
  61. * encryption key for the corresponding key wrapping algorithm:
  62. *
  63. * +-----------------+-------------------------------------------------+
  64. * | "alg" Param | Key Management Algorithm |
  65. * | Value | |
  66. * +-----------------+-------------------------------------------------+
  67. * | ECDH-ES+A128KW | ECDH-ES using Concat KDF and CEK wrapped with |
  68. * | | "A128KW" |
  69. * | ECDH-ES+A192KW | ECDH-ES using Concat KDF and CEK wrapped with |
  70. * | | "A192KW" |
  71. * | ECDH-ES+A256KW | ECDH-ES using Concat KDF and CEK wrapped with |
  72. * | | "A256KW" |
  73. * +-----------------+-------------------------------------------------+
  74. *
  75. * 4.6.1. Header Parameters Used for ECDH Key Agreement
  76. *
  77. * The following Header Parameter names are used for key agreement as
  78. * defined below.
  79. *
  80. * 4.6.1.1. "epk" (Ephemeral Public Key) Header Parameter
  81. *
  82. * The "epk" (ephemeral public key) value created by the originator for
  83. * the use in key agreement algorithms. This key is represented as a
  84. * JSON Web Key [JWK] public key value. It MUST contain only public key
  85. * parameters and SHOULD contain only the minimum JWK parameters
  86. * necessary to represent the key; other JWK parameters included can be
  87. * checked for consistency and honored, or they can be ignored. This
  88. * Header Parameter MUST be present and MUST be understood and processed
  89. * by implementations when these algorithms are used.
  90. *
  91. * 4.6.1.2. "apu" (Agreement PartyUInfo) Header Parameter
  92. *
  93. * The "apu" (agreement PartyUInfo) value for key agreement algorithms
  94. * using it (such as "ECDH-ES"), represented as a base64url-encoded
  95. * string. When used, the PartyUInfo value contains information about
  96. * the producer. Use of this Header Parameter is OPTIONAL. This Header
  97. * Parameter MUST be understood and processed by implementations when
  98. * these algorithms are used.
  99. *
  100. * 4.6.1.3. "apv" (Agreement PartyVInfo) Header Parameter
  101. *
  102. * The "apv" (agreement PartyVInfo) value for key agreement algorithms
  103. * using it (such as "ECDH-ES"), represented as a base64url encoded
  104. * string. When used, the PartyVInfo value contains information about
  105. * the recipient. Use of this Header Parameter is OPTIONAL. This
  106. * Header Parameter MUST be understood and processed by implementations
  107. * when these algorithms are used.
  108. *
  109. * 4.6.2. Key Derivation for ECDH Key Agreement
  110. *
  111. * The key derivation process derives the agreed-upon key from the
  112. * shared secret Z established through the ECDH algorithm, per
  113. * Section 6.2.2.2 of [NIST.800-56A].
  114. *
  115. * Key derivation is performed using the Concat KDF, as defined in
  116. * Section 5.8.1 of [NIST.800-56A], where the Digest Method is SHA-256.
  117. * The Concat KDF parameters are set as follows:
  118. *
  119. * Z
  120. * This is set to the representation of the shared secret Z as an
  121. * octet sequence.
  122. *
  123. * keydatalen
  124. * This is set to the number of bits in the desired output key. For
  125. * "ECDH-ES", this is length of the key used by the "enc" algorithm.
  126. * For "ECDH-ES+A128KW", "ECDH-ES+A192KW", and "ECDH-ES+A256KW", this
  127. * is 128, 192, and 256, respectively.
  128. *
  129. * AlgorithmID
  130. * The AlgorithmID value is of the form Datalen || Data, where Data
  131. * is a variable-length string of zero or more octets, and Datalen is
  132. * a fixed-length, big-endian 32-bit counter that indicates the
  133. * length (in octets) of Data. In the Direct Key Agreement case,
  134. * Data is set to the octets of the ASCII representation of the "enc"
  135. * Header Parameter value. In the Key Agreement with Key Wrapping
  136. * case, Data is set to the octets of the ASCII representation of the
  137. * "alg" (algorithm) Header Parameter value.
  138. *
  139. * PartyUInfo
  140. * The PartyUInfo value is of the form Datalen || Data, where Data is
  141. * a variable-length string of zero or more octets, and Datalen is a
  142. * fixed-length, big-endian 32-bit counter that indicates the length
  143. * (in octets) of Data. If an "apu" (agreement PartyUInfo) Header
  144. * Parameter is present, Data is set to the result of base64url
  145. * decoding the "apu" value and Datalen is set to the number of
  146. * octets in Data. Otherwise, Datalen is set to 0 and Data is set to
  147. * the empty octet sequence.
  148. *
  149. * PartyVInfo
  150. * The PartyVInfo value is of the form Datalen || Data, where Data is
  151. * a variable-length string of zero or more octets, and Datalen is a
  152. * fixed-length, big-endian 32-bit counter that indicates the length
  153. * (in octets) of Data. If an "apv" (agreement PartyVInfo) Header
  154. * Parameter is present, Data is set to the result of base64url
  155. * decoding the "apv" value and Datalen is set to the number of
  156. * octets in Data. Otherwise, Datalen is set to 0 and Data is set to
  157. * the empty octet sequence.
  158. *
  159. * SuppPubInfo
  160. * This is set to the keydatalen represented as a 32-bit big-endian
  161. * integer.
  162. *
  163. * SuppPrivInfo
  164. * This is set to the empty octet sequence.
  165. *
  166. * Applications need to specify how the "apu" and "apv" Header
  167. * Parameters are used for that application. The "apu" and "apv" values
  168. * MUST be distinct, when used. Applications wishing to conform to
  169. * [NIST.800-56A] need to provide values that meet the requirements of
  170. * that document, e.g., by using values that identify the producer and
  171. * consumer. Alternatively, applications MAY conduct key derivation in
  172. * a manner similar to "Diffie-Hellman Key Agreement Method" [RFC2631]:
  173. * in that case, the "apu" parameter MAY either be omitted or represent
  174. * a random 512-bit value (analogous to PartyAInfo in Ephemeral-Static
  175. * mode in RFC 2631) and the "apv" parameter SHOULD NOT be present.
  176. *
  177. */
  178. /*
  179. * - ECDH-ES[-variant] comes in the jose "alg" and just covers key agreement.
  180. * The "enc" action is completely separate and handled elsewhere. However
  181. * the key size throughout is determined by the needs of the "enc" action.
  182. *
  183. * - The jwe->jws.jwk is the PEER - the encryption consumer's - public key.
  184. *
  185. * - The public part of the ephemeral key comes out in jose.jwk_ephemeral
  186. *
  187. * - Return shared secret length or < 0 for error
  188. *
  189. * - Unwrapped CEK in EKEY. If any, wrapped CEK in "wrapped".
  190. *
  191. * - Caller responsibility to cleanse EKEY.
  192. */
  193. static int
  194. lws_jwe_encrypt_ecdh(struct lws_jwe *jwe, char *temp, int *temp_len,
  195. uint8_t *cek)
  196. {
  197. uint8_t shared_secret[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES],
  198. derived[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES];
  199. int m, n, ret = -1, ot = *temp_len, ss_len = sizeof(shared_secret),
  200. // kw_hlen = lws_genhash_size(jwe->jose.alg->hash_type),
  201. enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type),
  202. ekbytes = 32; //jwe->jose.alg->keybits_fixed / 8;
  203. struct lws_genec_ctx ecctx;
  204. struct lws_jwk *ephem = &jwe->jose.recipient[jwe->recip].jwk_ephemeral;
  205. if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_EC) {
  206. lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
  207. return -1;
  208. }
  209. ephem->kty = LWS_GENCRYPTO_KTY_EC;
  210. ephem->private_key = 1;
  211. /* Generate jose.jwk_ephemeral on the peer public key curve */
  212. if (lws_genecdh_create(&ecctx, jwe->jws.context, NULL))
  213. goto bail;
  214. /* ephemeral context gets random key on same curve as recip pubkey */
  215. if (lws_genecdh_new_keypair(&ecctx, LDHS_OURS, (const char *)
  216. jwe->jws.jwk->e[LWS_GENCRYPTO_EC_KEYEL_CRV].buf,
  217. ephem->e))
  218. goto bail;
  219. /* peer context gets js->jwk key */
  220. if (lws_genecdh_set_key(&ecctx, jwe->jws.jwk->e, LDHS_THEIRS)) {
  221. lwsl_err("%s: setting peer pubkey failed\n", __func__);
  222. goto bail;
  223. }
  224. /* combine our ephemeral key and the peer pubkey to get the secret */
  225. if (lws_genecdh_compute_shared_secret(&ecctx, shared_secret, &ss_len)) {
  226. lwsl_notice("%s: lws_genecdh_compute_shared_secret failed\n",
  227. __func__);
  228. goto bail;
  229. }
  230. /*
  231. * The private part of the ephemeral key is finished with...
  232. * cleanse and free it. We need to keep the public part around so we
  233. * can publish it with the JWE as "epk".
  234. */
  235. lws_explicit_bzero(ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].buf,
  236. ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].len);
  237. lws_free_set_NULL(ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].buf);
  238. ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].len = 0;
  239. ephem->private_key = 0;
  240. /*
  241. * Derive the CEK from the shared secret... amount of bytes written to
  242. * derived matches bitcount in jwe->jose.enc_alg->keybits_fixed
  243. *
  244. * In Direct Key Agreement mode, the output of the Concat KDF MUST be a
  245. * key of the same length as that used by the "enc" algorithm.
  246. */
  247. if (lws_jwa_concat_kdf(jwe,
  248. jwe->jose.alg->algtype_crypto == LWS_JOSE_ENCTYPE_NONE,
  249. derived, shared_secret, ss_len)) {
  250. lwsl_notice("%s: lws_jwa_concat_kdf failed\n", __func__);
  251. goto bail;
  252. }
  253. /* in P-521 case, we get a 66-byte shared secret for a 64-byte key */
  254. if (ss_len < enc_hlen) {
  255. lwsl_err("%s: concat KDF bad derived key len %d\n", __func__,
  256. ss_len);
  257. goto bail;
  258. }
  259. /*
  260. * For "ECDH-ES", that was it, and we use what we just wrapped in
  261. * wrapped as the CEK without publishing it.
  262. *
  263. * For "ECDH-ES-AES[128,192,256]KW", we generate a new, random CEK and
  264. * then wrap it using the key we just wrapped, and make the wrapped
  265. * version available in EKEY.
  266. */
  267. if (jwe->jose.alg->algtype_crypto != LWS_JOSE_ENCTYPE_NONE) {
  268. struct lws_gencrypto_keyelem el;
  269. struct lws_genaes_ctx aesctx;
  270. /* generate the actual CEK in cek */
  271. if (lws_get_random(jwe->jws.context, cek, enc_hlen) !=
  272. (size_t)enc_hlen) {
  273. lwsl_err("Problem getting random\n");
  274. goto bail;
  275. }
  276. /* wrap with the derived key */
  277. el.buf = derived;
  278. el.len = enc_hlen / 2;
  279. if (lws_genaes_create(&aesctx, LWS_GAESO_ENC, LWS_GAESM_KW, &el,
  280. 1, NULL)) {
  281. lwsl_notice("%s: lws_genaes_create\n", __func__);
  282. goto bail;
  283. }
  284. /* wrap CEK into EKEY */
  285. n = lws_genaes_crypt(&aesctx, cek, enc_hlen,
  286. (void *)jwe->jws.map.buf[LJWE_EKEY],
  287. NULL, NULL, NULL, 0);
  288. m = lws_genaes_destroy(&aesctx, NULL, 0);
  289. if (n < 0) {
  290. lwsl_err("%s: encrypt cek fail\n", __func__);
  291. goto bail;
  292. }
  293. if (m < 0) {
  294. lwsl_err("%s: lws_genaes_destroy fail\n", __func__);
  295. goto bail;
  296. }
  297. jwe->jws.map.len[LJWE_EKEY] = enc_hlen + 8;
  298. /* Wrapped CEK is in EKEY. Random CEK is in cek. */
  299. } else /* direct derived CEK is in cek */
  300. memcpy(cek, derived, enc_hlen);
  301. /* rewrite the protected JOSE header to have the epk pieces */
  302. jwe->jws.map.buf[LJWE_JOSE] = temp;
  303. m = n = lws_snprintf(temp, *temp_len,
  304. "{\"alg\":\"%s\", \"enc\":\"%s\", \"epk\":",
  305. jwe->jose.alg->alg, jwe->jose.enc_alg->alg);
  306. *temp_len -= n;
  307. n = lws_jwk_export(ephem, 0, temp + (ot - *temp_len), temp_len);
  308. if (n < 0) {
  309. lwsl_err("%s: ephemeral export failed\n", __func__);
  310. goto bail;
  311. }
  312. m += n;
  313. n = lws_snprintf(temp + (ot - *temp_len), *temp_len, "}");
  314. *temp_len -= n + 1;
  315. m += n;
  316. jwe->jws.map.len[LJWE_JOSE] = m;
  317. /* create a b64 version of the JOSE header, needed later for AAD */
  318. if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE,
  319. temp + (ot - *temp_len), temp_len,
  320. jwe->jws.map.buf[LJWE_JOSE],
  321. jwe->jws.map.len[LJWE_JOSE]))
  322. return -1;
  323. ret = enc_hlen;
  324. bail:
  325. lws_genec_destroy(&ecctx);
  326. /* cleanse the shared secret (watch out for cek at parent too) */
  327. lws_explicit_bzero(shared_secret, ekbytes);
  328. lws_explicit_bzero(derived, ekbytes);
  329. return ret;
  330. }
  331. int
  332. lws_jwe_encrypt_ecdh_cbc_hs(struct lws_jwe *jwe, char *temp, int *temp_len)
  333. {
  334. int ss_len, // kw_hlen = lws_genhash_size(jwe->jose.alg->hash_type),
  335. enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type);
  336. uint8_t cek[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES];
  337. int ekbytes = jwe->jose.alg->keybits_fixed / 8;
  338. int n, ot = *temp_len, ret = -1;
  339. /* if we will produce an EKEY, make space for it */
  340. if (jwe->jose.alg->algtype_crypto != LWS_JOSE_ENCTYPE_NONE) {
  341. if (lws_jws_alloc_element(&jwe->jws.map, LJWE_EKEY,
  342. temp + (ot - *temp_len), temp_len,
  343. enc_hlen + 8, 0))
  344. goto bail;
  345. }
  346. /* decrypt the CEK */
  347. ss_len = lws_jwe_encrypt_ecdh(jwe, temp + (ot - *temp_len), temp_len, cek);
  348. if (ss_len < 0) {
  349. lwsl_err("%s: lws_jwe_encrypt_ecdh failed\n", __func__);
  350. return -1;
  351. }
  352. /* cek contains the unwrapped CEK. EKEY may contain wrapped CEK */
  353. /* make space for the payload encryption pieces */
  354. if (lws_jws_alloc_element(&jwe->jws.map, LJWE_ATAG,
  355. temp + (ot - *temp_len),
  356. temp_len, enc_hlen / 2, 0))
  357. goto bail;
  358. if (lws_jws_alloc_element(&jwe->jws.map, LJWE_IV,
  359. temp + (ot - *temp_len),
  360. temp_len, LWS_JWE_AES_IV_BYTES, 0))
  361. goto bail;
  362. /* Perform the authenticated encryption on CTXT...
  363. * ...the AAD is b64u(protected JOSE header) */
  364. n = lws_jwe_encrypt_cbc_hs(jwe, cek,
  365. (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
  366. jwe->jws.map_b64.len[LJWE_JOSE]);
  367. if (n < 0) {
  368. lwsl_notice("%s: lws_jwe_encrypt_cbc_hs failed\n", __func__);
  369. goto bail;
  370. }
  371. ret = 0;
  372. bail:
  373. /* if fail or direct CEK, cleanse and remove EKEY */
  374. if (ret || jwe->jose.enc_alg->algtype_crypto == LWS_JOSE_ENCTYPE_NONE) {
  375. if (jwe->jws.map.len[LJWE_EKEY])
  376. lws_explicit_bzero((void *)jwe->jws.map.buf[LJWE_EKEY],
  377. jwe->jws.map.len[LJWE_EKEY]);
  378. jwe->jws.map.len[LJWE_EKEY] = 0;
  379. }
  380. lws_explicit_bzero(cek, ekbytes);
  381. return ret;
  382. }
  383. /*
  384. * jwe->jws.jwk is recipient private key
  385. *
  386. * If kw mode, then EKEY is the wrapped CEK
  387. *
  388. *
  389. */
  390. static int
  391. lws_jwe_auth_and_decrypt_ecdh(struct lws_jwe *jwe)
  392. {
  393. uint8_t shared_secret[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES],
  394. derived[LWS_JWE_LIMIT_KEY_ELEMENT_BYTES];
  395. int ekbytes = jwe->jose.enc_alg->keybits_fixed / 8,
  396. enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type);
  397. struct lws_genec_ctx ecctx;
  398. int n, ret = -1, ss_len = sizeof(shared_secret);
  399. if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_EC) {
  400. lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty);
  401. return -1;
  402. }
  403. if (jwe->jose.recipient[jwe->recip].jwk_ephemeral.kty !=
  404. LWS_GENCRYPTO_KTY_EC) {
  405. lwsl_err("%s: missing epk\n", __func__);
  406. return -1;
  407. }
  408. /*
  409. * Recompute the shared secret...
  410. *
  411. * - direct: it's the CEK
  412. *
  413. * - aeskw: apply it as AES keywrap to EKEY to get the CEK
  414. */
  415. /* Generate jose.jwk_ephemeral on the peer public key curve */
  416. if (lws_genecdh_create(&ecctx, jwe->jws.context, NULL))
  417. goto bail;
  418. /* Load our private key into our side of the ecdh context */
  419. if (lws_genecdh_set_key(&ecctx, jwe->jws.jwk->e, LDHS_OURS)) {
  420. lwsl_err("%s: setting our private key failed\n", __func__);
  421. goto bail;
  422. }
  423. /* Import the ephemeral public key into the peer side */
  424. if (lws_genecdh_set_key(&ecctx,
  425. jwe->jose.recipient[jwe->recip].jwk_ephemeral.e,
  426. LDHS_THEIRS)) {
  427. lwsl_err("%s: setting epk pubkey failed\n", __func__);
  428. goto bail;
  429. }
  430. /* combine their ephemeral key and our private key to get the secret */
  431. if (lws_genecdh_compute_shared_secret(&ecctx, shared_secret, &ss_len)) {
  432. lwsl_notice("%s: lws_genecdh_compute_shared_secret failed\n",
  433. __func__);
  434. goto bail;
  435. }
  436. lws_genec_destroy(&ecctx);
  437. if (ss_len < enc_hlen) {
  438. lwsl_err("%s: ss_len %d ekbytes %d\n", __func__, ss_len, enc_hlen);
  439. goto bail;
  440. }
  441. /*
  442. * Derive the CEK from the shared secret... amount of bytes written to
  443. * cek[] matches bitcount in jwe->jose.enc_alg->keybits_fixed
  444. */
  445. if (lws_jwa_concat_kdf(jwe,
  446. jwe->jose.alg->algtype_crypto == LWS_JOSE_ENCTYPE_NONE,
  447. derived, shared_secret, ss_len)) {
  448. lwsl_notice("%s: lws_jwa_concat_kdf failed\n", __func__);
  449. goto bail;
  450. }
  451. /*
  452. * "ECDH-ES": derived is the CEK
  453. * "ECDH-ES-AES[128,192,256]KW": wrapped key is in EKEY,
  454. * "derived" contains KEK
  455. */
  456. if (jwe->jose.alg->algtype_crypto != LWS_JOSE_ENCTYPE_NONE) {
  457. struct lws_gencrypto_keyelem el;
  458. struct lws_genaes_ctx aesctx;
  459. int m;
  460. /* Confirm space for EKEY */
  461. if (jwe->jws.map.len[LJWE_EKEY] < (unsigned int)enc_hlen) {
  462. lwsl_err("%s: missing EKEY\n", __func__);
  463. goto bail;
  464. }
  465. /* unwrap with the KEK we derived */
  466. el.buf = derived;
  467. el.len = enc_hlen / 2;
  468. if (lws_genaes_create(&aesctx, LWS_GAESO_DEC, LWS_GAESM_KW,
  469. &el, 1, NULL)) {
  470. lwsl_notice("%s: lws_genaes_create\n", __func__);
  471. goto bail;
  472. }
  473. /* decrypt the EKEY to end up with CEK in "shared_secret" */
  474. n = lws_genaes_crypt(&aesctx,
  475. (const uint8_t *)jwe->jws.map.buf[LJWE_EKEY],
  476. jwe->jws.map.len[LJWE_EKEY],
  477. (uint8_t *)shared_secret,
  478. NULL, NULL, NULL, 0);
  479. m = lws_genaes_destroy(&aesctx, NULL, 0);
  480. if (n < 0) {
  481. lwsl_err("%s: decrypt cek fail\n", __func__);
  482. goto bail;
  483. }
  484. if (m < 0) {
  485. lwsl_err("%s: lws_genaes_destroy fail\n", __func__);
  486. goto bail;
  487. }
  488. } else
  489. memcpy(shared_secret, derived, enc_hlen);
  490. /* either way, the recovered CEK is in shared_secret */
  491. if (lws_jwe_auth_and_decrypt_cbc_hs(jwe, shared_secret,
  492. (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE],
  493. jwe->jws.map_b64.len[LJWE_JOSE]) < 0) {
  494. lwsl_err("%s: lws_jwe_auth_and_decrypt_cbc_hs fail\n", __func__);
  495. goto bail;
  496. }
  497. /* if all went well, then CTXT is now the plaintext */
  498. ret = 0;
  499. bail:
  500. /* cleanse wrapped on stack that contained the CEK / wrapped key */
  501. lws_explicit_bzero(derived, ekbytes);
  502. /* cleanse the shared secret */
  503. lws_explicit_bzero(shared_secret, ekbytes);
  504. return ret;
  505. }
  506. int
  507. lws_jwe_auth_and_decrypt_ecdh_cbc_hs(struct lws_jwe *jwe,
  508. char *temp, int *temp_len)
  509. {
  510. /* create a b64 version of the JOSE header, needed later for AAD */
  511. if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE,
  512. temp, temp_len,
  513. jwe->jws.map.buf[LJWE_JOSE],
  514. jwe->jws.map.len[LJWE_JOSE]))
  515. return -1;
  516. return lws_jwe_auth_and_decrypt_ecdh(jwe);
  517. }