Lines Matching +full:concat +full:- +full:map
2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
25 #include "private-lib-core.h"
26 #include "private-lib-jose-jwe.h"
31 * 4.6. Key Agreement with Elliptic Curve Diffie-Hellman Ephemeral Static
32 * (ECDH-ES)
35 * Curve Diffie-Hellman Ephemeral Static [RFC6090], in combination with
36 * the Concat KDF, as defined in Section 5.8.1 of [NIST.800-56A]. The
49 * In Direct Key Agreement mode, the output of the Concat KDF MUST be a
52 * value. The "alg" (algorithm) Header Parameter value "ECDH-ES" is
55 * In Key Agreement with Key Wrapping mode, the output of the Concat KDF
58 * with the agreed-upon key.
65 * +-----------------+-------------------------------------------------+
68 * +-----------------+-------------------------------------------------+
69 * | ECDH-ES+A128KW | ECDH-ES using Concat KDF and CEK wrapped with |
71 * | ECDH-ES+A192KW | ECDH-ES using Concat KDF and CEK wrapped with |
73 * | ECDH-ES+A256KW | ECDH-ES using Concat KDF and CEK wrapped with |
75 * +-----------------+-------------------------------------------------+
96 * using it (such as "ECDH-ES"), represented as a base64url-encoded
105 * using it (such as "ECDH-ES"), represented as a base64url encoded
113 * The key derivation process derives the agreed-upon key from the
115 * Section 6.2.2.2 of [NIST.800-56A].
117 * Key derivation is performed using the Concat KDF, as defined in
118 * Section 5.8.1 of [NIST.800-56A], where the Digest Method is SHA-256.
119 * The Concat KDF parameters are set as follows:
127 * "ECDH-ES", this is length of the key used by the "enc" algorithm.
128 * For "ECDH-ES+A128KW", "ECDH-ES+A192KW", and "ECDH-ES+A256KW", this
133 * is a variable-length string of zero or more octets, and Datalen is
134 * a fixed-length, big-endian 32-bit counter that indicates the
143 * a variable-length string of zero or more octets, and Datalen is a
144 * fixed-length, big-endian 32-bit counter that indicates the length
153 * a variable-length string of zero or more octets, and Datalen is a
154 * fixed-length, big-endian 32-bit counter that indicates the length
162 * This is set to the keydatalen represented as a 32-bit big-endian
171 * [NIST.800-56A] need to provide values that meet the requirements of
174 * a manner similar to "Diffie-Hellman Key Agreement Method" [RFC2631]:
176 * a random 512-bit value (analogous to PartyAInfo in Ephemeral-Static
183 * - ECDH-ES[-variant] comes in the jose "alg" and just covers key agreement.
187 * - The jwe->jws.jwk is the PEER - the encryption consumer's - public key.
189 * - The public part of the ephemeral key comes out in jose.jwk_ephemeral
191 * - Return shared secret length or < 0 for error
193 * - Unwrapped CEK in EKEY. If any, wrapped CEK in "wrapped".
195 * - Caller responsibility to cleanse EKEY.
204 int m, n, ret = -1, ot = *temp_len, ss_len = sizeof(shared_secret), in lws_jwe_encrypt_ecdh()
205 // kw_hlen = lws_genhash_size(jwe->jose.alg->hash_type), in lws_jwe_encrypt_ecdh()
206 enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type), in lws_jwe_encrypt_ecdh()
207 ekbytes = 32; //jwe->jose.alg->keybits_fixed / 8; in lws_jwe_encrypt_ecdh()
209 struct lws_jwk *ephem = &jwe->jose.recipient[jwe->recip].jwk_ephemeral; in lws_jwe_encrypt_ecdh()
211 if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_EC) { in lws_jwe_encrypt_ecdh()
212 lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty); in lws_jwe_encrypt_ecdh()
214 return -1; in lws_jwe_encrypt_ecdh()
217 ephem->kty = LWS_GENCRYPTO_KTY_EC; in lws_jwe_encrypt_ecdh()
218 ephem->private_key = 1; in lws_jwe_encrypt_ecdh()
222 if (lws_genecdh_create(&ecctx, jwe->jws.context, NULL)) in lws_jwe_encrypt_ecdh()
227 jwe->jws.jwk->e[LWS_GENCRYPTO_EC_KEYEL_CRV].buf, in lws_jwe_encrypt_ecdh()
228 ephem->e)) in lws_jwe_encrypt_ecdh()
231 /* peer context gets js->jwk key */ in lws_jwe_encrypt_ecdh()
232 if (lws_genecdh_set_key(&ecctx, jwe->jws.jwk->e, LDHS_THEIRS)) { in lws_jwe_encrypt_ecdh()
252 lws_explicit_bzero(ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].buf, in lws_jwe_encrypt_ecdh()
253 ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].len); in lws_jwe_encrypt_ecdh()
254 lws_free_set_NULL(ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].buf); in lws_jwe_encrypt_ecdh()
255 ephem->e[LWS_GENCRYPTO_EC_KEYEL_D].len = 0; in lws_jwe_encrypt_ecdh()
256 ephem->private_key = 0; in lws_jwe_encrypt_ecdh()
260 * derived matches bitcount in jwe->jose.enc_alg->keybits_fixed in lws_jwe_encrypt_ecdh()
262 * In Direct Key Agreement mode, the output of the Concat KDF MUST be a in lws_jwe_encrypt_ecdh()
267 jwe->jose.alg->algtype_crypto == LWS_JOSE_ENCTYPE_NONE, in lws_jwe_encrypt_ecdh()
274 /* in P-521 case, we get a 66-byte shared secret for a 64-byte key */ in lws_jwe_encrypt_ecdh()
276 lwsl_err("%s: concat KDF bad derived key len %d\n", __func__, in lws_jwe_encrypt_ecdh()
282 * For "ECDH-ES", that was it, and we use what we just wrapped in in lws_jwe_encrypt_ecdh()
285 * For "ECDH-ES-AES[128,192,256]KW", we generate a new, random CEK and in lws_jwe_encrypt_ecdh()
290 if (jwe->jose.alg->algtype_crypto != LWS_JOSE_ENCTYPE_NONE) { in lws_jwe_encrypt_ecdh()
296 if (lws_get_random(jwe->jws.context, cek, (unsigned int)enc_hlen) != in lws_jwe_encrypt_ecdh()
317 (void *)jwe->jws.map.buf[LJWE_EKEY], in lws_jwe_encrypt_ecdh()
329 jwe->jws.map.len[LJWE_EKEY] = (unsigned int)enc_hlen + 8; in lws_jwe_encrypt_ecdh()
338 jwe->jws.map.buf[LJWE_JOSE] = temp; in lws_jwe_encrypt_ecdh()
342 jwe->jose.alg->alg, jwe->jose.enc_alg->alg); in lws_jwe_encrypt_ecdh()
343 *temp_len -= n; in lws_jwe_encrypt_ecdh()
345 n = lws_jwk_export(ephem, 0, temp + (ot - *temp_len), temp_len); in lws_jwe_encrypt_ecdh()
352 n = lws_snprintf(temp + (ot - *temp_len), (size_t)*temp_len, "}"); in lws_jwe_encrypt_ecdh()
353 *temp_len -= n + 1; in lws_jwe_encrypt_ecdh()
355 jwe->jws.map.len[LJWE_JOSE] = (unsigned int)m; in lws_jwe_encrypt_ecdh()
359 if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE, in lws_jwe_encrypt_ecdh()
360 temp + (ot - *temp_len), temp_len, in lws_jwe_encrypt_ecdh()
361 jwe->jws.map.buf[LJWE_JOSE], in lws_jwe_encrypt_ecdh()
362 jwe->jws.map.len[LJWE_JOSE])) in lws_jwe_encrypt_ecdh()
363 return -1; in lws_jwe_encrypt_ecdh()
380 int ss_len, // kw_hlen = lws_genhash_size(jwe->jose.alg->hash_type), in lws_jwe_encrypt_ecdh_cbc_hs()
381 enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type); in lws_jwe_encrypt_ecdh_cbc_hs()
383 int ekbytes = jwe->jose.alg->keybits_fixed / 8; in lws_jwe_encrypt_ecdh_cbc_hs()
384 int n, ot = *temp_len, ret = -1; in lws_jwe_encrypt_ecdh_cbc_hs()
388 if (jwe->jose.alg->algtype_crypto != LWS_JOSE_ENCTYPE_NONE) { in lws_jwe_encrypt_ecdh_cbc_hs()
389 if (lws_jws_alloc_element(&jwe->jws.map, LJWE_EKEY, in lws_jwe_encrypt_ecdh_cbc_hs()
390 temp + (ot - *temp_len), temp_len, in lws_jwe_encrypt_ecdh_cbc_hs()
397 ss_len = lws_jwe_encrypt_ecdh(jwe, temp + (ot - *temp_len), temp_len, cek); in lws_jwe_encrypt_ecdh_cbc_hs()
400 return -1; in lws_jwe_encrypt_ecdh_cbc_hs()
407 if (lws_jws_alloc_element(&jwe->jws.map, LJWE_ATAG, in lws_jwe_encrypt_ecdh_cbc_hs()
408 temp + (ot - *temp_len), in lws_jwe_encrypt_ecdh_cbc_hs()
412 if (lws_jws_alloc_element(&jwe->jws.map, LJWE_IV, in lws_jwe_encrypt_ecdh_cbc_hs()
413 temp + (ot - *temp_len), in lws_jwe_encrypt_ecdh_cbc_hs()
421 (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE], in lws_jwe_encrypt_ecdh_cbc_hs()
422 (int)jwe->jws.map_b64.len[LJWE_JOSE]); in lws_jwe_encrypt_ecdh_cbc_hs()
432 if (ret || jwe->jose.enc_alg->algtype_crypto == LWS_JOSE_ENCTYPE_NONE) { in lws_jwe_encrypt_ecdh_cbc_hs()
433 if (jwe->jws.map.len[LJWE_EKEY]) in lws_jwe_encrypt_ecdh_cbc_hs()
434 lws_explicit_bzero((void *)jwe->jws.map.buf[LJWE_EKEY], in lws_jwe_encrypt_ecdh_cbc_hs()
435 jwe->jws.map.len[LJWE_EKEY]); in lws_jwe_encrypt_ecdh_cbc_hs()
436 jwe->jws.map.len[LJWE_EKEY] = 0; in lws_jwe_encrypt_ecdh_cbc_hs()
445 * jwe->jws.jwk is recipient private key
457 int ekbytes = jwe->jose.enc_alg->keybits_fixed / 8, in lws_jwe_auth_and_decrypt_ecdh()
458 enc_hlen = (int)lws_genhmac_size(jwe->jose.enc_alg->hmac_type); in lws_jwe_auth_and_decrypt_ecdh()
460 int n, ret = -1, ss_len = sizeof(shared_secret); in lws_jwe_auth_and_decrypt_ecdh()
462 if (jwe->jws.jwk->kty != LWS_GENCRYPTO_KTY_EC) { in lws_jwe_auth_and_decrypt_ecdh()
463 lwsl_err("%s: unexpected kty %d\n", __func__, jwe->jws.jwk->kty); in lws_jwe_auth_and_decrypt_ecdh()
465 return -1; in lws_jwe_auth_and_decrypt_ecdh()
468 if (jwe->jose.recipient[jwe->recip].jwk_ephemeral.kty != in lws_jwe_auth_and_decrypt_ecdh()
472 return -1; in lws_jwe_auth_and_decrypt_ecdh()
478 * - direct: it's the CEK in lws_jwe_auth_and_decrypt_ecdh()
480 * - aeskw: apply it as AES keywrap to EKEY to get the CEK in lws_jwe_auth_and_decrypt_ecdh()
485 if (lws_genecdh_create(&ecctx, jwe->jws.context, NULL)) in lws_jwe_auth_and_decrypt_ecdh()
490 if (lws_genecdh_set_key(&ecctx, jwe->jws.jwk->e, LDHS_OURS)) { in lws_jwe_auth_and_decrypt_ecdh()
497 jwe->jose.recipient[jwe->recip].jwk_ephemeral.e, in lws_jwe_auth_and_decrypt_ecdh()
521 * cek[] matches bitcount in jwe->jose.enc_alg->keybits_fixed in lws_jwe_auth_and_decrypt_ecdh()
525 jwe->jose.alg->algtype_crypto == LWS_JOSE_ENCTYPE_NONE, in lws_jwe_auth_and_decrypt_ecdh()
533 * "ECDH-ES": derived is the CEK in lws_jwe_auth_and_decrypt_ecdh()
534 * "ECDH-ES-AES[128,192,256]KW": wrapped key is in EKEY, in lws_jwe_auth_and_decrypt_ecdh()
538 if (jwe->jose.alg->algtype_crypto != LWS_JOSE_ENCTYPE_NONE) { in lws_jwe_auth_and_decrypt_ecdh()
545 if (jwe->jws.map.len[LJWE_EKEY] < (unsigned int)enc_hlen) { in lws_jwe_auth_and_decrypt_ecdh()
566 (const uint8_t *)jwe->jws.map.buf[LJWE_EKEY], in lws_jwe_auth_and_decrypt_ecdh()
567 jwe->jws.map.len[LJWE_EKEY], in lws_jwe_auth_and_decrypt_ecdh()
585 (uint8_t *)jwe->jws.map_b64.buf[LJWE_JOSE], in lws_jwe_auth_and_decrypt_ecdh()
586 (int)jwe->jws.map_b64.len[LJWE_JOSE]) < 0) { in lws_jwe_auth_and_decrypt_ecdh()
609 if (lws_jws_encode_b64_element(&jwe->jws.map_b64, LJWE_JOSE, in lws_jwe_auth_and_decrypt_ecdh_cbc_hs()
611 jwe->jws.map.buf[LJWE_JOSE], in lws_jwe_auth_and_decrypt_ecdh_cbc_hs()
612 jwe->jws.map.len[LJWE_JOSE])) in lws_jwe_auth_and_decrypt_ecdh_cbc_hs()
613 return -1; in lws_jwe_auth_and_decrypt_ecdh_cbc_hs()