1c1d255d3SCy Schubert /* 2c1d255d3SCy Schubert * DPP crypto functionality 3c1d255d3SCy Schubert * Copyright (c) 2017, Qualcomm Atheros, Inc. 4c1d255d3SCy Schubert * Copyright (c) 2018-2020, The Linux Foundation 5c1d255d3SCy Schubert * 6c1d255d3SCy Schubert * This software may be distributed under the terms of the BSD license. 7c1d255d3SCy Schubert * See README for more details. 8c1d255d3SCy Schubert */ 9c1d255d3SCy Schubert 10c1d255d3SCy Schubert #include "utils/includes.h" 11c1d255d3SCy Schubert 12c1d255d3SCy Schubert #include "utils/common.h" 13c1d255d3SCy Schubert #include "utils/base64.h" 14c1d255d3SCy Schubert #include "utils/json.h" 15c1d255d3SCy Schubert #include "common/ieee802_11_defs.h" 16c1d255d3SCy Schubert #include "crypto/crypto.h" 17c1d255d3SCy Schubert #include "crypto/random.h" 18c1d255d3SCy Schubert #include "crypto/sha384.h" 19c1d255d3SCy Schubert #include "crypto/sha512.h" 20*266f97b5SCy Schubert #include "tls/asn1.h" 21c1d255d3SCy Schubert #include "dpp.h" 22c1d255d3SCy Schubert #include "dpp_i.h" 23c1d255d3SCy Schubert 24c1d255d3SCy Schubert 25c1d255d3SCy Schubert static const struct dpp_curve_params dpp_curves[] = { 26c1d255d3SCy Schubert /* The mandatory to support and the default NIST P-256 curve needs to 27c1d255d3SCy Schubert * be the first entry on this list. */ 28c1d255d3SCy Schubert { "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" }, 29c1d255d3SCy Schubert { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" }, 30c1d255d3SCy Schubert { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" }, 31c1d255d3SCy Schubert { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" }, 32c1d255d3SCy Schubert { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" }, 33c1d255d3SCy Schubert { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" }, 34c1d255d3SCy Schubert { NULL, 0, 0, 0, 0, NULL, 0, NULL } 35c1d255d3SCy Schubert }; 36c1d255d3SCy Schubert 37c1d255d3SCy Schubert 38c1d255d3SCy Schubert const struct dpp_curve_params * dpp_get_curve_name(const char *name) 39c1d255d3SCy Schubert { 40c1d255d3SCy Schubert int i; 41c1d255d3SCy Schubert 42c1d255d3SCy Schubert if (!name) 43c1d255d3SCy Schubert return &dpp_curves[0]; 44c1d255d3SCy Schubert 45c1d255d3SCy Schubert for (i = 0; dpp_curves[i].name; i++) { 46c1d255d3SCy Schubert if (os_strcmp(name, dpp_curves[i].name) == 0 || 47c1d255d3SCy Schubert (dpp_curves[i].jwk_crv && 48c1d255d3SCy Schubert os_strcmp(name, dpp_curves[i].jwk_crv) == 0)) 49c1d255d3SCy Schubert return &dpp_curves[i]; 50c1d255d3SCy Schubert } 51c1d255d3SCy Schubert return NULL; 52c1d255d3SCy Schubert } 53c1d255d3SCy Schubert 54c1d255d3SCy Schubert 55c1d255d3SCy Schubert const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name) 56c1d255d3SCy Schubert { 57c1d255d3SCy Schubert int i; 58c1d255d3SCy Schubert 59c1d255d3SCy Schubert for (i = 0; dpp_curves[i].name; i++) { 60c1d255d3SCy Schubert if (dpp_curves[i].jwk_crv && 61c1d255d3SCy Schubert os_strcmp(name, dpp_curves[i].jwk_crv) == 0) 62c1d255d3SCy Schubert return &dpp_curves[i]; 63c1d255d3SCy Schubert } 64c1d255d3SCy Schubert return NULL; 65c1d255d3SCy Schubert } 66c1d255d3SCy Schubert 67c1d255d3SCy Schubert 68c1d255d3SCy Schubert const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group) 69c1d255d3SCy Schubert { 70c1d255d3SCy Schubert int i; 71c1d255d3SCy Schubert 72c1d255d3SCy Schubert for (i = 0; dpp_curves[i].name; i++) { 73c1d255d3SCy Schubert if (dpp_curves[i].ike_group == group) 74c1d255d3SCy Schubert return &dpp_curves[i]; 75c1d255d3SCy Schubert } 76c1d255d3SCy Schubert return NULL; 77c1d255d3SCy Schubert } 78c1d255d3SCy Schubert 79c1d255d3SCy Schubert 80*266f97b5SCy Schubert void dpp_debug_print_key(const char *title, struct crypto_ec_key *key) 81c1d255d3SCy Schubert { 82*266f97b5SCy Schubert struct wpabuf *der = NULL; 83c1d255d3SCy Schubert 84*266f97b5SCy Schubert crypto_ec_key_debug_print(key, title); 85c1d255d3SCy Schubert 86*266f97b5SCy Schubert der = crypto_ec_key_get_ecprivate_key(key, true); 87*266f97b5SCy Schubert if (der) { 88*266f97b5SCy Schubert wpa_hexdump_buf_key(MSG_DEBUG, "DPP: ECPrivateKey", der); 89*266f97b5SCy Schubert } else { 90*266f97b5SCy Schubert der = crypto_ec_key_get_subject_public_key(key); 91*266f97b5SCy Schubert if (der) 92*266f97b5SCy Schubert wpa_hexdump_buf_key(MSG_DEBUG, "DPP: EC_PUBKEY", der); 93c1d255d3SCy Schubert } 94c1d255d3SCy Schubert 95*266f97b5SCy Schubert wpabuf_clear_free(der); 96c1d255d3SCy Schubert } 97c1d255d3SCy Schubert 98c1d255d3SCy Schubert 99c1d255d3SCy Schubert static int dpp_hash_vector(const struct dpp_curve_params *curve, 100c1d255d3SCy Schubert size_t num_elem, const u8 *addr[], const size_t *len, 101c1d255d3SCy Schubert u8 *mac) 102c1d255d3SCy Schubert { 103c1d255d3SCy Schubert if (curve->hash_len == 32) 104c1d255d3SCy Schubert return sha256_vector(num_elem, addr, len, mac); 105c1d255d3SCy Schubert if (curve->hash_len == 48) 106c1d255d3SCy Schubert return sha384_vector(num_elem, addr, len, mac); 107c1d255d3SCy Schubert if (curve->hash_len == 64) 108c1d255d3SCy Schubert return sha512_vector(num_elem, addr, len, mac); 109c1d255d3SCy Schubert return -1; 110c1d255d3SCy Schubert } 111c1d255d3SCy Schubert 112c1d255d3SCy Schubert 113c1d255d3SCy Schubert int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, 114c1d255d3SCy Schubert const char *label, u8 *out, size_t outlen) 115c1d255d3SCy Schubert { 116c1d255d3SCy Schubert if (hash_len == 32) 117c1d255d3SCy Schubert return hmac_sha256_kdf(secret, secret_len, NULL, 118c1d255d3SCy Schubert (const u8 *) label, os_strlen(label), 119c1d255d3SCy Schubert out, outlen); 120c1d255d3SCy Schubert if (hash_len == 48) 121c1d255d3SCy Schubert return hmac_sha384_kdf(secret, secret_len, NULL, 122c1d255d3SCy Schubert (const u8 *) label, os_strlen(label), 123c1d255d3SCy Schubert out, outlen); 124c1d255d3SCy Schubert if (hash_len == 64) 125c1d255d3SCy Schubert return hmac_sha512_kdf(secret, secret_len, NULL, 126c1d255d3SCy Schubert (const u8 *) label, os_strlen(label), 127c1d255d3SCy Schubert out, outlen); 128c1d255d3SCy Schubert return -1; 129c1d255d3SCy Schubert } 130c1d255d3SCy Schubert 131c1d255d3SCy Schubert 132c1d255d3SCy Schubert int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, 133c1d255d3SCy Schubert size_t num_elem, const u8 *addr[], const size_t *len, 134c1d255d3SCy Schubert u8 *mac) 135c1d255d3SCy Schubert { 136c1d255d3SCy Schubert if (hash_len == 32) 137c1d255d3SCy Schubert return hmac_sha256_vector(key, key_len, num_elem, addr, len, 138c1d255d3SCy Schubert mac); 139c1d255d3SCy Schubert if (hash_len == 48) 140c1d255d3SCy Schubert return hmac_sha384_vector(key, key_len, num_elem, addr, len, 141c1d255d3SCy Schubert mac); 142c1d255d3SCy Schubert if (hash_len == 64) 143c1d255d3SCy Schubert return hmac_sha512_vector(key, key_len, num_elem, addr, len, 144c1d255d3SCy Schubert mac); 145c1d255d3SCy Schubert return -1; 146c1d255d3SCy Schubert } 147c1d255d3SCy Schubert 148c1d255d3SCy Schubert 149c1d255d3SCy Schubert static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, 150c1d255d3SCy Schubert const u8 *data, size_t data_len, u8 *mac) 151c1d255d3SCy Schubert { 152c1d255d3SCy Schubert if (hash_len == 32) 153c1d255d3SCy Schubert return hmac_sha256(key, key_len, data, data_len, mac); 154c1d255d3SCy Schubert if (hash_len == 48) 155c1d255d3SCy Schubert return hmac_sha384(key, key_len, data, data_len, mac); 156c1d255d3SCy Schubert if (hash_len == 64) 157c1d255d3SCy Schubert return hmac_sha512(key, key_len, data, data_len, mac); 158c1d255d3SCy Schubert return -1; 159c1d255d3SCy Schubert } 160c1d255d3SCy Schubert 161c1d255d3SCy Schubert 162c1d255d3SCy Schubert #ifdef CONFIG_DPP2 163c1d255d3SCy Schubert 164c1d255d3SCy Schubert static int dpp_pbkdf2_f(size_t hash_len, 165c1d255d3SCy Schubert const u8 *password, size_t password_len, 166c1d255d3SCy Schubert const u8 *salt, size_t salt_len, 167c1d255d3SCy Schubert unsigned int iterations, unsigned int count, u8 *digest) 168c1d255d3SCy Schubert { 169c1d255d3SCy Schubert unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN]; 170c1d255d3SCy Schubert unsigned int i; 171c1d255d3SCy Schubert size_t j; 172c1d255d3SCy Schubert u8 count_buf[4]; 173c1d255d3SCy Schubert const u8 *addr[2]; 174c1d255d3SCy Schubert size_t len[2]; 175c1d255d3SCy Schubert 176c1d255d3SCy Schubert addr[0] = salt; 177c1d255d3SCy Schubert len[0] = salt_len; 178c1d255d3SCy Schubert addr[1] = count_buf; 179c1d255d3SCy Schubert len[1] = 4; 180c1d255d3SCy Schubert 181c1d255d3SCy Schubert /* F(P, S, c, i) = U1 xor U2 xor ... Uc 182c1d255d3SCy Schubert * U1 = PRF(P, S || i) 183c1d255d3SCy Schubert * U2 = PRF(P, U1) 184c1d255d3SCy Schubert * Uc = PRF(P, Uc-1) 185c1d255d3SCy Schubert */ 186c1d255d3SCy Schubert 187c1d255d3SCy Schubert WPA_PUT_BE32(count_buf, count); 188c1d255d3SCy Schubert if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len, 189c1d255d3SCy Schubert tmp)) 190c1d255d3SCy Schubert return -1; 191c1d255d3SCy Schubert os_memcpy(digest, tmp, hash_len); 192c1d255d3SCy Schubert 193c1d255d3SCy Schubert for (i = 1; i < iterations; i++) { 194c1d255d3SCy Schubert if (dpp_hmac(hash_len, password, password_len, tmp, hash_len, 195c1d255d3SCy Schubert tmp2)) 196c1d255d3SCy Schubert return -1; 197c1d255d3SCy Schubert os_memcpy(tmp, tmp2, hash_len); 198c1d255d3SCy Schubert for (j = 0; j < hash_len; j++) 199c1d255d3SCy Schubert digest[j] ^= tmp2[j]; 200c1d255d3SCy Schubert } 201c1d255d3SCy Schubert 202c1d255d3SCy Schubert return 0; 203c1d255d3SCy Schubert } 204c1d255d3SCy Schubert 205c1d255d3SCy Schubert 206c1d255d3SCy Schubert int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len, 207c1d255d3SCy Schubert const u8 *salt, size_t salt_len, unsigned int iterations, 208c1d255d3SCy Schubert u8 *buf, size_t buflen) 209c1d255d3SCy Schubert { 210c1d255d3SCy Schubert unsigned int count = 0; 211c1d255d3SCy Schubert unsigned char *pos = buf; 212c1d255d3SCy Schubert size_t left = buflen, plen; 213c1d255d3SCy Schubert unsigned char digest[DPP_MAX_HASH_LEN]; 214c1d255d3SCy Schubert 215c1d255d3SCy Schubert while (left > 0) { 216c1d255d3SCy Schubert count++; 217c1d255d3SCy Schubert if (dpp_pbkdf2_f(hash_len, password, password_len, 218c1d255d3SCy Schubert salt, salt_len, iterations, count, digest)) 219c1d255d3SCy Schubert return -1; 220c1d255d3SCy Schubert plen = left > hash_len ? hash_len : left; 221c1d255d3SCy Schubert os_memcpy(pos, digest, plen); 222c1d255d3SCy Schubert pos += plen; 223c1d255d3SCy Schubert left -= plen; 224c1d255d3SCy Schubert } 225c1d255d3SCy Schubert 226c1d255d3SCy Schubert return 0; 227c1d255d3SCy Schubert } 228c1d255d3SCy Schubert 229c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 230c1d255d3SCy Schubert 231c1d255d3SCy Schubert 232*266f97b5SCy Schubert struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, 233*266f97b5SCy Schubert const u8 *buf, size_t len) 234c1d255d3SCy Schubert { 235*266f97b5SCy Schubert int ike_group = crypto_ec_key_group(group_key); 236c1d255d3SCy Schubert 237c1d255d3SCy Schubert if (len & 1) 238c1d255d3SCy Schubert return NULL; 239c1d255d3SCy Schubert 240*266f97b5SCy Schubert if (ike_group < 0) { 241*266f97b5SCy Schubert wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); 242c1d255d3SCy Schubert return NULL; 243c1d255d3SCy Schubert } 244c1d255d3SCy Schubert 245*266f97b5SCy Schubert return crypto_ec_key_set_pub(ike_group, buf, buf + len / 2, len / 2); 246c1d255d3SCy Schubert } 247c1d255d3SCy Schubert 248c1d255d3SCy Schubert 249*266f97b5SCy Schubert struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve) 250c1d255d3SCy Schubert { 251*266f97b5SCy Schubert struct crypto_ec_key *key; 252c1d255d3SCy Schubert 253c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); 254c1d255d3SCy Schubert 255*266f97b5SCy Schubert key = crypto_ec_key_gen(curve->ike_group); 256*266f97b5SCy Schubert if (key && wpa_debug_show_keys) 257c1d255d3SCy Schubert dpp_debug_print_key("Own generated key", key); 258c1d255d3SCy Schubert 259c1d255d3SCy Schubert return key; 260c1d255d3SCy Schubert } 261c1d255d3SCy Schubert 262c1d255d3SCy Schubert 263*266f97b5SCy Schubert struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve, 264c1d255d3SCy Schubert const u8 *privkey, size_t privkey_len) 265c1d255d3SCy Schubert { 266*266f97b5SCy Schubert struct crypto_ec_key *key; 267*266f97b5SCy Schubert int group; 268c1d255d3SCy Schubert 269*266f97b5SCy Schubert key = crypto_ec_key_parse_priv(privkey, privkey_len); 270*266f97b5SCy Schubert if (!key) { 271*266f97b5SCy Schubert wpa_printf(MSG_INFO, "DPP: Failed to parse private key"); 272c1d255d3SCy Schubert return NULL; 273c1d255d3SCy Schubert } 274*266f97b5SCy Schubert 275*266f97b5SCy Schubert group = crypto_ec_key_group(key); 276*266f97b5SCy Schubert if (group < 0) { 277*266f97b5SCy Schubert crypto_ec_key_deinit(key); 278c1d255d3SCy Schubert return NULL; 279c1d255d3SCy Schubert } 280*266f97b5SCy Schubert 281*266f97b5SCy Schubert *curve = dpp_get_curve_ike_group(group); 282c1d255d3SCy Schubert if (!*curve) { 283c1d255d3SCy Schubert wpa_printf(MSG_INFO, 284*266f97b5SCy Schubert "DPP: Unsupported curve (group=%d) in pre-assigned key", 285*266f97b5SCy Schubert group); 286*266f97b5SCy Schubert crypto_ec_key_deinit(key); 287c1d255d3SCy Schubert return NULL; 288c1d255d3SCy Schubert } 289c1d255d3SCy Schubert 290*266f97b5SCy Schubert return key; 291c1d255d3SCy Schubert } 292c1d255d3SCy Schubert 293c1d255d3SCy Schubert 294c1d255d3SCy Schubert int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) 295c1d255d3SCy Schubert { 296c1d255d3SCy Schubert struct wpabuf *der; 297c1d255d3SCy Schubert int res; 298c1d255d3SCy Schubert 299*266f97b5SCy Schubert der = crypto_ec_key_get_subject_public_key(bi->pubkey); 300c1d255d3SCy Schubert if (!der) 301c1d255d3SCy Schubert return -1; 302c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", 303c1d255d3SCy Schubert der); 304c1d255d3SCy Schubert res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)); 305c1d255d3SCy Schubert if (res < 0) 306c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); 307c1d255d3SCy Schubert wpabuf_free(der); 308c1d255d3SCy Schubert return res; 309c1d255d3SCy Schubert } 310c1d255d3SCy Schubert 311c1d255d3SCy Schubert 312c1d255d3SCy Schubert int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, 313c1d255d3SCy Schubert const u8 *privkey, size_t privkey_len) 314c1d255d3SCy Schubert { 315c1d255d3SCy Schubert char *base64 = NULL; 316c1d255d3SCy Schubert char *pos, *end; 317c1d255d3SCy Schubert size_t len; 318c1d255d3SCy Schubert struct wpabuf *der = NULL; 319c1d255d3SCy Schubert 320c1d255d3SCy Schubert bi->curve = dpp_get_curve_name(curve); 321c1d255d3SCy Schubert if (!bi->curve) { 322c1d255d3SCy Schubert wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); 323c1d255d3SCy Schubert return -1; 324c1d255d3SCy Schubert } 325c1d255d3SCy Schubert 326c1d255d3SCy Schubert if (privkey) 327c1d255d3SCy Schubert bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len); 328c1d255d3SCy Schubert else 329c1d255d3SCy Schubert bi->pubkey = dpp_gen_keypair(bi->curve); 330c1d255d3SCy Schubert if (!bi->pubkey) 331c1d255d3SCy Schubert goto fail; 332c1d255d3SCy Schubert bi->own = 1; 333c1d255d3SCy Schubert 334*266f97b5SCy Schubert der = crypto_ec_key_get_subject_public_key(bi->pubkey); 335c1d255d3SCy Schubert if (!der) 336c1d255d3SCy Schubert goto fail; 337c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", 338c1d255d3SCy Schubert der); 339c1d255d3SCy Schubert 340c1d255d3SCy Schubert if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) { 341c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); 342c1d255d3SCy Schubert goto fail; 343c1d255d3SCy Schubert } 344c1d255d3SCy Schubert 345c1d255d3SCy Schubert base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len); 346c1d255d3SCy Schubert wpabuf_free(der); 347c1d255d3SCy Schubert der = NULL; 348c1d255d3SCy Schubert if (!base64) 349c1d255d3SCy Schubert goto fail; 350c1d255d3SCy Schubert pos = base64; 351c1d255d3SCy Schubert end = pos + len; 352c1d255d3SCy Schubert for (;;) { 353c1d255d3SCy Schubert pos = os_strchr(pos, '\n'); 354c1d255d3SCy Schubert if (!pos) 355c1d255d3SCy Schubert break; 356c1d255d3SCy Schubert os_memmove(pos, pos + 1, end - pos); 357c1d255d3SCy Schubert } 358c1d255d3SCy Schubert os_free(bi->pk); 359c1d255d3SCy Schubert bi->pk = base64; 360c1d255d3SCy Schubert return 0; 361c1d255d3SCy Schubert fail: 362c1d255d3SCy Schubert os_free(base64); 363c1d255d3SCy Schubert wpabuf_free(der); 364c1d255d3SCy Schubert return -1; 365c1d255d3SCy Schubert } 366c1d255d3SCy Schubert 367c1d255d3SCy Schubert 368c1d255d3SCy Schubert int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len) 369c1d255d3SCy Schubert { 370c1d255d3SCy Schubert u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 371c1d255d3SCy Schubert const char *info = "first intermediate key"; 372c1d255d3SCy Schubert int res; 373c1d255d3SCy Schubert 374c1d255d3SCy Schubert /* k1 = HKDF(<>, "first intermediate key", M.x) */ 375c1d255d3SCy Schubert 376c1d255d3SCy Schubert /* HKDF-Extract(<>, M.x) */ 377c1d255d3SCy Schubert os_memset(salt, 0, hash_len); 378c1d255d3SCy Schubert if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0) 379c1d255d3SCy Schubert return -1; 380c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)", 381c1d255d3SCy Schubert prk, hash_len); 382c1d255d3SCy Schubert 383c1d255d3SCy Schubert /* HKDF-Expand(PRK, info, L) */ 384c1d255d3SCy Schubert res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len); 385c1d255d3SCy Schubert os_memset(prk, 0, hash_len); 386c1d255d3SCy Schubert if (res < 0) 387c1d255d3SCy Schubert return -1; 388c1d255d3SCy Schubert 389c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)", 390c1d255d3SCy Schubert k1, hash_len); 391c1d255d3SCy Schubert return 0; 392c1d255d3SCy Schubert } 393c1d255d3SCy Schubert 394c1d255d3SCy Schubert 395c1d255d3SCy Schubert int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len) 396c1d255d3SCy Schubert { 397c1d255d3SCy Schubert u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 398c1d255d3SCy Schubert const char *info = "second intermediate key"; 399c1d255d3SCy Schubert int res; 400c1d255d3SCy Schubert 401c1d255d3SCy Schubert /* k2 = HKDF(<>, "second intermediate key", N.x) */ 402c1d255d3SCy Schubert 403c1d255d3SCy Schubert /* HKDF-Extract(<>, N.x) */ 404c1d255d3SCy Schubert os_memset(salt, 0, hash_len); 405c1d255d3SCy Schubert res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk); 406c1d255d3SCy Schubert if (res < 0) 407c1d255d3SCy Schubert return -1; 408c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", 409c1d255d3SCy Schubert prk, hash_len); 410c1d255d3SCy Schubert 411c1d255d3SCy Schubert /* HKDF-Expand(PRK, info, L) */ 412c1d255d3SCy Schubert res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len); 413c1d255d3SCy Schubert os_memset(prk, 0, hash_len); 414c1d255d3SCy Schubert if (res < 0) 415c1d255d3SCy Schubert return -1; 416c1d255d3SCy Schubert 417c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)", 418c1d255d3SCy Schubert k2, hash_len); 419c1d255d3SCy Schubert return 0; 420c1d255d3SCy Schubert } 421c1d255d3SCy Schubert 422c1d255d3SCy Schubert 423c1d255d3SCy Schubert int dpp_derive_bk_ke(struct dpp_authentication *auth) 424c1d255d3SCy Schubert { 425c1d255d3SCy Schubert unsigned int hash_len = auth->curve->hash_len; 426c1d255d3SCy Schubert size_t nonce_len = auth->curve->nonce_len; 427c1d255d3SCy Schubert u8 nonces[2 * DPP_MAX_NONCE_LEN]; 428c1d255d3SCy Schubert const char *info_ke = "DPP Key"; 429c1d255d3SCy Schubert int res; 430c1d255d3SCy Schubert const u8 *addr[3]; 431c1d255d3SCy Schubert size_t len[3]; 432c1d255d3SCy Schubert size_t num_elem = 0; 433c1d255d3SCy Schubert 434c1d255d3SCy Schubert if (!auth->Mx_len || !auth->Nx_len) { 435c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 436c1d255d3SCy Schubert "DPP: Mx/Nx not available - cannot derive ke"); 437c1d255d3SCy Schubert return -1; 438c1d255d3SCy Schubert } 439c1d255d3SCy Schubert 440c1d255d3SCy Schubert /* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ 441c1d255d3SCy Schubert os_memcpy(nonces, auth->i_nonce, nonce_len); 442c1d255d3SCy Schubert os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len); 443c1d255d3SCy Schubert addr[num_elem] = auth->Mx; 444c1d255d3SCy Schubert len[num_elem] = auth->Mx_len; 445c1d255d3SCy Schubert num_elem++; 446c1d255d3SCy Schubert addr[num_elem] = auth->Nx; 447c1d255d3SCy Schubert len[num_elem] = auth->Nx_len; 448c1d255d3SCy Schubert num_elem++; 449c1d255d3SCy Schubert if (auth->peer_bi && auth->own_bi) { 450c1d255d3SCy Schubert if (!auth->Lx_len) { 451c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 452c1d255d3SCy Schubert "DPP: Lx not available - cannot derive ke"); 453c1d255d3SCy Schubert return -1; 454c1d255d3SCy Schubert } 455c1d255d3SCy Schubert addr[num_elem] = auth->Lx; 456c1d255d3SCy Schubert len[num_elem] = auth->secret_len; 457c1d255d3SCy Schubert num_elem++; 458c1d255d3SCy Schubert } 459c1d255d3SCy Schubert res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len, 460c1d255d3SCy Schubert num_elem, addr, len, auth->bk); 461c1d255d3SCy Schubert if (res < 0) 462c1d255d3SCy Schubert return -1; 463c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 464c1d255d3SCy Schubert "DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])", 465c1d255d3SCy Schubert auth->bk, hash_len); 466c1d255d3SCy Schubert 467c1d255d3SCy Schubert /* ke = HKDF-Expand(bk, "DPP Key", length) */ 468c1d255d3SCy Schubert res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke, 469c1d255d3SCy Schubert hash_len); 470c1d255d3SCy Schubert if (res < 0) 471c1d255d3SCy Schubert return -1; 472c1d255d3SCy Schubert 473c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 474c1d255d3SCy Schubert "DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)", 475c1d255d3SCy Schubert auth->ke, hash_len); 476c1d255d3SCy Schubert 477c1d255d3SCy Schubert return 0; 478c1d255d3SCy Schubert } 479c1d255d3SCy Schubert 480c1d255d3SCy Schubert 481*266f97b5SCy Schubert int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer, 482*266f97b5SCy Schubert u8 *secret, size_t *secret_len) 483c1d255d3SCy Schubert { 484*266f97b5SCy Schubert struct crypto_ecdh *ecdh; 485*266f97b5SCy Schubert struct wpabuf *peer_pub, *secret_buf = NULL; 486c1d255d3SCy Schubert int ret = -1; 487c1d255d3SCy Schubert 488c1d255d3SCy Schubert *secret_len = 0; 489c1d255d3SCy Schubert 490*266f97b5SCy Schubert ecdh = crypto_ecdh_init2(crypto_ec_key_group(own), own); 491*266f97b5SCy Schubert if (!ecdh) { 492*266f97b5SCy Schubert wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_init2() failed"); 493c1d255d3SCy Schubert return -1; 494c1d255d3SCy Schubert } 495c1d255d3SCy Schubert 496*266f97b5SCy Schubert peer_pub = crypto_ec_key_get_pubkey_point(peer, 0); 497*266f97b5SCy Schubert if (!peer_pub) { 498c1d255d3SCy Schubert wpa_printf(MSG_ERROR, 499*266f97b5SCy Schubert "DPP: crypto_ec_key_get_pubkey_point() failed"); 500c1d255d3SCy Schubert goto fail; 501c1d255d3SCy Schubert } 502c1d255d3SCy Schubert 503*266f97b5SCy Schubert secret_buf = crypto_ecdh_set_peerkey(ecdh, 1, wpabuf_head(peer_pub), 504*266f97b5SCy Schubert wpabuf_len(peer_pub)); 505*266f97b5SCy Schubert if (!secret_buf) { 506*266f97b5SCy Schubert wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_set_peerkey() failed"); 507c1d255d3SCy Schubert goto fail; 508c1d255d3SCy Schubert } 509c1d255d3SCy Schubert 510*266f97b5SCy Schubert if (wpabuf_len(secret_buf) > DPP_MAX_SHARED_SECRET_LEN) { 511*266f97b5SCy Schubert wpa_printf(MSG_ERROR, "DPP: ECDH secret longer than expected"); 512c1d255d3SCy Schubert goto fail; 513c1d255d3SCy Schubert } 514c1d255d3SCy Schubert 515*266f97b5SCy Schubert *secret_len = wpabuf_len(secret_buf); 516*266f97b5SCy Schubert os_memcpy(secret, wpabuf_head(secret_buf), wpabuf_len(secret_buf)); 517c1d255d3SCy Schubert ret = 0; 518c1d255d3SCy Schubert 519c1d255d3SCy Schubert fail: 520*266f97b5SCy Schubert wpabuf_clear_free(secret_buf); 521*266f97b5SCy Schubert wpabuf_free(peer_pub); 522*266f97b5SCy Schubert crypto_ecdh_deinit(ecdh); 523c1d255d3SCy Schubert return ret; 524c1d255d3SCy Schubert } 525c1d255d3SCy Schubert 526c1d255d3SCy Schubert 527c1d255d3SCy Schubert int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, 528c1d255d3SCy Schubert const u8 *data, size_t data_len) 529c1d255d3SCy Schubert { 530c1d255d3SCy Schubert const u8 *addr[2]; 531c1d255d3SCy Schubert size_t len[2]; 532c1d255d3SCy Schubert 533c1d255d3SCy Schubert addr[0] = data; 534c1d255d3SCy Schubert len[0] = data_len; 535c1d255d3SCy Schubert if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0) 536c1d255d3SCy Schubert return -1; 537c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", 538c1d255d3SCy Schubert bi->pubkey_hash, SHA256_MAC_LEN); 539c1d255d3SCy Schubert 540c1d255d3SCy Schubert addr[0] = (const u8 *) "chirp"; 541c1d255d3SCy Schubert len[0] = 5; 542c1d255d3SCy Schubert addr[1] = data; 543c1d255d3SCy Schubert len[1] = data_len; 544c1d255d3SCy Schubert if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0) 545c1d255d3SCy Schubert return -1; 546c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)", 547c1d255d3SCy Schubert bi->pubkey_hash_chirp, SHA256_MAC_LEN); 548c1d255d3SCy Schubert 549c1d255d3SCy Schubert return 0; 550c1d255d3SCy Schubert } 551c1d255d3SCy Schubert 552c1d255d3SCy Schubert 553c1d255d3SCy Schubert int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, 554c1d255d3SCy Schubert const u8 *data, size_t data_len) 555c1d255d3SCy Schubert { 556*266f97b5SCy Schubert struct crypto_ec_key *key; 557c1d255d3SCy Schubert 558c1d255d3SCy Schubert if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) { 559c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); 560c1d255d3SCy Schubert return -1; 561c1d255d3SCy Schubert } 562c1d255d3SCy Schubert 563*266f97b5SCy Schubert key = crypto_ec_key_parse_pub(data, data_len); 564*266f97b5SCy Schubert if (!key) { 565c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 566c1d255d3SCy Schubert "DPP: Could not parse URI public-key SubjectPublicKeyInfo"); 567c1d255d3SCy Schubert return -1; 568c1d255d3SCy Schubert } 569c1d255d3SCy Schubert 570*266f97b5SCy Schubert bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(key)); 571c1d255d3SCy Schubert if (!bi->curve) { 572c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 573*266f97b5SCy Schubert "DPP: Unsupported SubjectPublicKeyInfo curve: group %d", 574*266f97b5SCy Schubert crypto_ec_key_group(key)); 575c1d255d3SCy Schubert goto fail; 576c1d255d3SCy Schubert } 577c1d255d3SCy Schubert 578*266f97b5SCy Schubert bi->pubkey = key; 579c1d255d3SCy Schubert return 0; 580c1d255d3SCy Schubert fail: 581*266f97b5SCy Schubert crypto_ec_key_deinit(key); 582c1d255d3SCy Schubert return -1; 583c1d255d3SCy Schubert } 584c1d255d3SCy Schubert 585c1d255d3SCy Schubert 586c1d255d3SCy Schubert static struct wpabuf * 587c1d255d3SCy Schubert dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, 588c1d255d3SCy Schubert const u8 *prot_hdr, u16 prot_hdr_len, 589*266f97b5SCy Schubert int *hash_func) 590c1d255d3SCy Schubert { 591c1d255d3SCy Schubert struct json_token *root, *token; 592c1d255d3SCy Schubert struct wpabuf *kid = NULL; 593c1d255d3SCy Schubert 594c1d255d3SCy Schubert root = json_parse((const char *) prot_hdr, prot_hdr_len); 595c1d255d3SCy Schubert if (!root) { 596c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 597c1d255d3SCy Schubert "DPP: JSON parsing failed for JWS Protected Header"); 598c1d255d3SCy Schubert goto fail; 599c1d255d3SCy Schubert } 600c1d255d3SCy Schubert 601c1d255d3SCy Schubert if (root->type != JSON_OBJECT) { 602c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 603c1d255d3SCy Schubert "DPP: JWS Protected Header root is not an object"); 604c1d255d3SCy Schubert goto fail; 605c1d255d3SCy Schubert } 606c1d255d3SCy Schubert 607c1d255d3SCy Schubert token = json_get_member(root, "typ"); 608c1d255d3SCy Schubert if (!token || token->type != JSON_STRING) { 609c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No typ string value found"); 610c1d255d3SCy Schubert goto fail; 611c1d255d3SCy Schubert } 612c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s", 613c1d255d3SCy Schubert token->string); 614c1d255d3SCy Schubert if (os_strcmp(token->string, "dppCon") != 0) { 615c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 616c1d255d3SCy Schubert "DPP: Unsupported JWS Protected Header typ=%s", 617c1d255d3SCy Schubert token->string); 618c1d255d3SCy Schubert goto fail; 619c1d255d3SCy Schubert } 620c1d255d3SCy Schubert 621c1d255d3SCy Schubert token = json_get_member(root, "alg"); 622c1d255d3SCy Schubert if (!token || token->type != JSON_STRING) { 623c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No alg string value found"); 624c1d255d3SCy Schubert goto fail; 625c1d255d3SCy Schubert } 626c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s", 627c1d255d3SCy Schubert token->string); 628c1d255d3SCy Schubert if (os_strcmp(token->string, curve->jws_alg) != 0) { 629c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 630c1d255d3SCy Schubert "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)", 631c1d255d3SCy Schubert token->string, curve->jws_alg); 632c1d255d3SCy Schubert goto fail; 633c1d255d3SCy Schubert } 634c1d255d3SCy Schubert if (os_strcmp(token->string, "ES256") == 0 || 635*266f97b5SCy Schubert os_strcmp(token->string, "BS256") == 0) { 636*266f97b5SCy Schubert *hash_func = CRYPTO_HASH_ALG_SHA256; 637*266f97b5SCy Schubert } else if (os_strcmp(token->string, "ES384") == 0 || 638*266f97b5SCy Schubert os_strcmp(token->string, "BS384") == 0) { 639*266f97b5SCy Schubert *hash_func = CRYPTO_HASH_ALG_SHA384; 640*266f97b5SCy Schubert } else if (os_strcmp(token->string, "ES512") == 0 || 641*266f97b5SCy Schubert os_strcmp(token->string, "BS512") == 0) { 642*266f97b5SCy Schubert *hash_func = CRYPTO_HASH_ALG_SHA512; 643*266f97b5SCy Schubert } else { 644*266f97b5SCy Schubert *hash_func = -1; 645c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 646c1d255d3SCy Schubert "DPP: Unsupported JWS Protected Header alg=%s", 647c1d255d3SCy Schubert token->string); 648c1d255d3SCy Schubert goto fail; 649c1d255d3SCy Schubert } 650c1d255d3SCy Schubert 651c1d255d3SCy Schubert kid = json_get_member_base64url(root, "kid"); 652c1d255d3SCy Schubert if (!kid) { 653c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No kid string value found"); 654c1d255d3SCy Schubert goto fail; 655c1d255d3SCy Schubert } 656c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)", 657c1d255d3SCy Schubert kid); 658c1d255d3SCy Schubert 659c1d255d3SCy Schubert fail: 660c1d255d3SCy Schubert json_free(root); 661c1d255d3SCy Schubert return kid; 662c1d255d3SCy Schubert } 663c1d255d3SCy Schubert 664c1d255d3SCy Schubert 665*266f97b5SCy Schubert static int dpp_check_pubkey_match(struct crypto_ec_key *pub, 666*266f97b5SCy Schubert struct wpabuf *r_hash) 667c1d255d3SCy Schubert { 668c1d255d3SCy Schubert struct wpabuf *uncomp; 669c1d255d3SCy Schubert int res; 670c1d255d3SCy Schubert u8 hash[SHA256_MAC_LEN]; 671c1d255d3SCy Schubert const u8 *addr[1]; 672c1d255d3SCy Schubert size_t len[1]; 673c1d255d3SCy Schubert 674c1d255d3SCy Schubert if (wpabuf_len(r_hash) != SHA256_MAC_LEN) 675c1d255d3SCy Schubert return -1; 676*266f97b5SCy Schubert uncomp = crypto_ec_key_get_pubkey_point(pub, 1); 677c1d255d3SCy Schubert if (!uncomp) 678c1d255d3SCy Schubert return -1; 679c1d255d3SCy Schubert addr[0] = wpabuf_head(uncomp); 680c1d255d3SCy Schubert len[0] = wpabuf_len(uncomp); 681c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key", 682c1d255d3SCy Schubert addr[0], len[0]); 683c1d255d3SCy Schubert res = sha256_vector(1, addr, len, hash); 684c1d255d3SCy Schubert wpabuf_free(uncomp); 685c1d255d3SCy Schubert if (res < 0) 686c1d255d3SCy Schubert return -1; 687c1d255d3SCy Schubert if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) { 688c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 689c1d255d3SCy Schubert "DPP: Received hash value does not match calculated public key hash value"); 690c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash", 691c1d255d3SCy Schubert hash, SHA256_MAC_LEN); 692c1d255d3SCy Schubert return -1; 693c1d255d3SCy Schubert } 694c1d255d3SCy Schubert return 0; 695c1d255d3SCy Schubert } 696c1d255d3SCy Schubert 697c1d255d3SCy Schubert 698c1d255d3SCy Schubert enum dpp_status_error 699c1d255d3SCy Schubert dpp_process_signed_connector(struct dpp_signed_connector_info *info, 700*266f97b5SCy Schubert struct crypto_ec_key *csign_pub, 701*266f97b5SCy Schubert const char *connector) 702c1d255d3SCy Schubert { 703c1d255d3SCy Schubert enum dpp_status_error ret = 255; 704c1d255d3SCy Schubert const char *pos, *end, *signed_start, *signed_end; 705c1d255d3SCy Schubert struct wpabuf *kid = NULL; 706c1d255d3SCy Schubert unsigned char *prot_hdr = NULL, *signature = NULL; 707*266f97b5SCy Schubert size_t prot_hdr_len = 0, signature_len = 0, signed_len; 708*266f97b5SCy Schubert int res, hash_func = -1; 709c1d255d3SCy Schubert const struct dpp_curve_params *curve; 710*266f97b5SCy Schubert u8 *hash = NULL; 711c1d255d3SCy Schubert 712*266f97b5SCy Schubert curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub)); 713c1d255d3SCy Schubert if (!curve) 714c1d255d3SCy Schubert goto fail; 715c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv); 716c1d255d3SCy Schubert os_memset(info, 0, sizeof(*info)); 717c1d255d3SCy Schubert 718c1d255d3SCy Schubert signed_start = pos = connector; 719c1d255d3SCy Schubert end = os_strchr(pos, '.'); 720c1d255d3SCy Schubert if (!end) { 721c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector"); 722c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 723c1d255d3SCy Schubert goto fail; 724c1d255d3SCy Schubert } 725c1d255d3SCy Schubert prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len); 726c1d255d3SCy Schubert if (!prot_hdr) { 727c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 728c1d255d3SCy Schubert "DPP: Failed to base64url decode signedConnector JWS Protected Header"); 729c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 730c1d255d3SCy Schubert goto fail; 731c1d255d3SCy Schubert } 732c1d255d3SCy Schubert wpa_hexdump_ascii(MSG_DEBUG, 733c1d255d3SCy Schubert "DPP: signedConnector - JWS Protected Header", 734c1d255d3SCy Schubert prot_hdr, prot_hdr_len); 735*266f97b5SCy Schubert kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func); 736c1d255d3SCy Schubert if (!kid) { 737c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 738c1d255d3SCy Schubert goto fail; 739c1d255d3SCy Schubert } 740c1d255d3SCy Schubert if (wpabuf_len(kid) != SHA256_MAC_LEN) { 741c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 742c1d255d3SCy Schubert "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)", 743c1d255d3SCy Schubert (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN); 744c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 745c1d255d3SCy Schubert goto fail; 746c1d255d3SCy Schubert } 747c1d255d3SCy Schubert 748c1d255d3SCy Schubert pos = end + 1; 749c1d255d3SCy Schubert end = os_strchr(pos, '.'); 750c1d255d3SCy Schubert if (!end) { 751c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 752c1d255d3SCy Schubert "DPP: Missing dot(2) in signedConnector"); 753c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 754c1d255d3SCy Schubert goto fail; 755c1d255d3SCy Schubert } 756c1d255d3SCy Schubert signed_end = end - 1; 757c1d255d3SCy Schubert info->payload = base64_url_decode(pos, end - pos, &info->payload_len); 758c1d255d3SCy Schubert if (!info->payload) { 759c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 760c1d255d3SCy Schubert "DPP: Failed to base64url decode signedConnector JWS Payload"); 761c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 762c1d255d3SCy Schubert goto fail; 763c1d255d3SCy Schubert } 764c1d255d3SCy Schubert wpa_hexdump_ascii(MSG_DEBUG, 765c1d255d3SCy Schubert "DPP: signedConnector - JWS Payload", 766c1d255d3SCy Schubert info->payload, info->payload_len); 767c1d255d3SCy Schubert pos = end + 1; 768c1d255d3SCy Schubert signature = base64_url_decode(pos, os_strlen(pos), &signature_len); 769c1d255d3SCy Schubert if (!signature) { 770c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 771c1d255d3SCy Schubert "DPP: Failed to base64url decode signedConnector signature"); 772c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 773c1d255d3SCy Schubert goto fail; 774c1d255d3SCy Schubert } 775c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature", 776c1d255d3SCy Schubert signature, signature_len); 777c1d255d3SCy Schubert 778c1d255d3SCy Schubert if (dpp_check_pubkey_match(csign_pub, kid) < 0) { 779c1d255d3SCy Schubert ret = DPP_STATUS_NO_MATCH; 780c1d255d3SCy Schubert goto fail; 781c1d255d3SCy Schubert } 782c1d255d3SCy Schubert 783c1d255d3SCy Schubert if (signature_len & 0x01) { 784c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 785c1d255d3SCy Schubert "DPP: Unexpected signedConnector signature length (%d)", 786c1d255d3SCy Schubert (int) signature_len); 787c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 788c1d255d3SCy Schubert goto fail; 789c1d255d3SCy Schubert } 790c1d255d3SCy Schubert 791*266f97b5SCy Schubert hash = os_malloc(curve->hash_len); 792*266f97b5SCy Schubert if (!hash) 793c1d255d3SCy Schubert goto fail; 794c1d255d3SCy Schubert 795*266f97b5SCy Schubert signed_len = signed_end - signed_start + 1; 796*266f97b5SCy Schubert if (hash_func == CRYPTO_HASH_ALG_SHA256) 797*266f97b5SCy Schubert res = sha256_vector(1, (const u8 **) &signed_start, &signed_len, 798*266f97b5SCy Schubert hash); 799*266f97b5SCy Schubert else if (hash_func == CRYPTO_HASH_ALG_SHA384) 800*266f97b5SCy Schubert res = sha384_vector(1, (const u8 **) &signed_start, &signed_len, 801*266f97b5SCy Schubert hash); 802*266f97b5SCy Schubert else if (hash_func == CRYPTO_HASH_ALG_SHA512) 803*266f97b5SCy Schubert res = sha512_vector(1, (const u8 **) &signed_start, &signed_len, 804*266f97b5SCy Schubert hash); 805*266f97b5SCy Schubert else 806c1d255d3SCy Schubert goto fail; 807*266f97b5SCy Schubert 808*266f97b5SCy Schubert if (res) 809c1d255d3SCy Schubert goto fail; 810*266f97b5SCy Schubert 811*266f97b5SCy Schubert res = crypto_ec_key_verify_signature_r_s(csign_pub, 812*266f97b5SCy Schubert hash, curve->hash_len, 813*266f97b5SCy Schubert signature, signature_len / 2, 814*266f97b5SCy Schubert signature + signature_len / 2, 815*266f97b5SCy Schubert signature_len / 2); 816c1d255d3SCy Schubert if (res != 1) { 817c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 818*266f97b5SCy Schubert "DPP: signedConnector signature check failed (res=%d)", 819*266f97b5SCy Schubert res); 820c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 821c1d255d3SCy Schubert goto fail; 822c1d255d3SCy Schubert } 823c1d255d3SCy Schubert 824c1d255d3SCy Schubert ret = DPP_STATUS_OK; 825c1d255d3SCy Schubert fail: 826*266f97b5SCy Schubert os_free(hash); 827c1d255d3SCy Schubert os_free(prot_hdr); 828c1d255d3SCy Schubert wpabuf_free(kid); 829c1d255d3SCy Schubert os_free(signature); 830c1d255d3SCy Schubert return ret; 831c1d255d3SCy Schubert } 832c1d255d3SCy Schubert 833c1d255d3SCy Schubert 834c1d255d3SCy Schubert enum dpp_status_error 835c1d255d3SCy Schubert dpp_check_signed_connector(struct dpp_signed_connector_info *info, 836c1d255d3SCy Schubert const u8 *csign_key, size_t csign_key_len, 837c1d255d3SCy Schubert const u8 *peer_connector, size_t peer_connector_len) 838c1d255d3SCy Schubert { 839*266f97b5SCy Schubert struct crypto_ec_key *csign; 840c1d255d3SCy Schubert char *signed_connector = NULL; 841c1d255d3SCy Schubert enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR; 842c1d255d3SCy Schubert 843*266f97b5SCy Schubert csign = crypto_ec_key_parse_pub(csign_key, csign_key_len); 844c1d255d3SCy Schubert if (!csign) { 845c1d255d3SCy Schubert wpa_printf(MSG_ERROR, 846c1d255d3SCy Schubert "DPP: Failed to parse local C-sign-key information"); 847c1d255d3SCy Schubert goto fail; 848c1d255d3SCy Schubert } 849c1d255d3SCy Schubert 850c1d255d3SCy Schubert wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector", 851c1d255d3SCy Schubert peer_connector, peer_connector_len); 852c1d255d3SCy Schubert signed_connector = os_malloc(peer_connector_len + 1); 853c1d255d3SCy Schubert if (!signed_connector) 854c1d255d3SCy Schubert goto fail; 855c1d255d3SCy Schubert os_memcpy(signed_connector, peer_connector, peer_connector_len); 856c1d255d3SCy Schubert signed_connector[peer_connector_len] = '\0'; 857c1d255d3SCy Schubert res = dpp_process_signed_connector(info, csign, signed_connector); 858c1d255d3SCy Schubert fail: 859c1d255d3SCy Schubert os_free(signed_connector); 860*266f97b5SCy Schubert crypto_ec_key_deinit(csign); 861c1d255d3SCy Schubert return res; 862c1d255d3SCy Schubert } 863c1d255d3SCy Schubert 864c1d255d3SCy Schubert 865c1d255d3SCy Schubert int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) 866c1d255d3SCy Schubert { 867c1d255d3SCy Schubert struct wpabuf *pix, *prx, *bix, *brx; 868c1d255d3SCy Schubert const u8 *addr[7]; 869c1d255d3SCy Schubert size_t len[7]; 870c1d255d3SCy Schubert size_t i, num_elem = 0; 871c1d255d3SCy Schubert size_t nonce_len; 872c1d255d3SCy Schubert u8 zero = 0; 873c1d255d3SCy Schubert int res = -1; 874c1d255d3SCy Schubert 875c1d255d3SCy Schubert /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ 876c1d255d3SCy Schubert nonce_len = auth->curve->nonce_len; 877c1d255d3SCy Schubert 878c1d255d3SCy Schubert if (auth->initiator) { 879*266f97b5SCy Schubert pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 880*266f97b5SCy Schubert prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 881*266f97b5SCy Schubert 0); 882c1d255d3SCy Schubert if (auth->own_bi) 883*266f97b5SCy Schubert bix = crypto_ec_key_get_pubkey_point( 884*266f97b5SCy Schubert auth->own_bi->pubkey, 0); 885c1d255d3SCy Schubert else 886c1d255d3SCy Schubert bix = NULL; 887*266f97b5SCy Schubert brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0); 888c1d255d3SCy Schubert } else { 889*266f97b5SCy Schubert pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 890*266f97b5SCy Schubert 0); 891*266f97b5SCy Schubert prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 892c1d255d3SCy Schubert if (auth->peer_bi) 893*266f97b5SCy Schubert bix = crypto_ec_key_get_pubkey_point( 894*266f97b5SCy Schubert auth->peer_bi->pubkey, 0); 895c1d255d3SCy Schubert else 896c1d255d3SCy Schubert bix = NULL; 897*266f97b5SCy Schubert brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0); 898c1d255d3SCy Schubert } 899c1d255d3SCy Schubert if (!pix || !prx || !brx) 900c1d255d3SCy Schubert goto fail; 901c1d255d3SCy Schubert 902c1d255d3SCy Schubert addr[num_elem] = auth->i_nonce; 903c1d255d3SCy Schubert len[num_elem] = nonce_len; 904c1d255d3SCy Schubert num_elem++; 905c1d255d3SCy Schubert 906c1d255d3SCy Schubert addr[num_elem] = auth->r_nonce; 907c1d255d3SCy Schubert len[num_elem] = nonce_len; 908c1d255d3SCy Schubert num_elem++; 909c1d255d3SCy Schubert 910c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(pix); 911c1d255d3SCy Schubert len[num_elem] = wpabuf_len(pix) / 2; 912c1d255d3SCy Schubert num_elem++; 913c1d255d3SCy Schubert 914c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(prx); 915c1d255d3SCy Schubert len[num_elem] = wpabuf_len(prx) / 2; 916c1d255d3SCy Schubert num_elem++; 917c1d255d3SCy Schubert 918c1d255d3SCy Schubert if (bix) { 919c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(bix); 920c1d255d3SCy Schubert len[num_elem] = wpabuf_len(bix) / 2; 921c1d255d3SCy Schubert num_elem++; 922c1d255d3SCy Schubert } 923c1d255d3SCy Schubert 924c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(brx); 925c1d255d3SCy Schubert len[num_elem] = wpabuf_len(brx) / 2; 926c1d255d3SCy Schubert num_elem++; 927c1d255d3SCy Schubert 928c1d255d3SCy Schubert addr[num_elem] = &zero; 929c1d255d3SCy Schubert len[num_elem] = 1; 930c1d255d3SCy Schubert num_elem++; 931c1d255d3SCy Schubert 932c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: R-auth hash components"); 933c1d255d3SCy Schubert for (i = 0; i < num_elem; i++) 934c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); 935c1d255d3SCy Schubert res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth); 936c1d255d3SCy Schubert if (res == 0) 937c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth, 938c1d255d3SCy Schubert auth->curve->hash_len); 939c1d255d3SCy Schubert fail: 940c1d255d3SCy Schubert wpabuf_free(pix); 941c1d255d3SCy Schubert wpabuf_free(prx); 942c1d255d3SCy Schubert wpabuf_free(bix); 943c1d255d3SCy Schubert wpabuf_free(brx); 944c1d255d3SCy Schubert return res; 945c1d255d3SCy Schubert } 946c1d255d3SCy Schubert 947c1d255d3SCy Schubert 948c1d255d3SCy Schubert int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth) 949c1d255d3SCy Schubert { 950c1d255d3SCy Schubert struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL; 951c1d255d3SCy Schubert const u8 *addr[7]; 952c1d255d3SCy Schubert size_t len[7]; 953c1d255d3SCy Schubert size_t i, num_elem = 0; 954c1d255d3SCy Schubert size_t nonce_len; 955c1d255d3SCy Schubert u8 one = 1; 956c1d255d3SCy Schubert int res = -1; 957c1d255d3SCy Schubert 958c1d255d3SCy Schubert /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ 959c1d255d3SCy Schubert nonce_len = auth->curve->nonce_len; 960c1d255d3SCy Schubert 961c1d255d3SCy Schubert if (auth->initiator) { 962*266f97b5SCy Schubert pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 963*266f97b5SCy Schubert prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 964*266f97b5SCy Schubert 0); 965c1d255d3SCy Schubert if (auth->own_bi) 966*266f97b5SCy Schubert bix = crypto_ec_key_get_pubkey_point( 967*266f97b5SCy Schubert auth->own_bi->pubkey, 0); 968c1d255d3SCy Schubert else 969c1d255d3SCy Schubert bix = NULL; 970c1d255d3SCy Schubert if (!auth->peer_bi) 971c1d255d3SCy Schubert goto fail; 972*266f97b5SCy Schubert brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0); 973c1d255d3SCy Schubert } else { 974*266f97b5SCy Schubert pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 975*266f97b5SCy Schubert 0); 976*266f97b5SCy Schubert prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 977c1d255d3SCy Schubert if (auth->peer_bi) 978*266f97b5SCy Schubert bix = crypto_ec_key_get_pubkey_point( 979*266f97b5SCy Schubert auth->peer_bi->pubkey, 0); 980c1d255d3SCy Schubert else 981c1d255d3SCy Schubert bix = NULL; 982c1d255d3SCy Schubert if (!auth->own_bi) 983c1d255d3SCy Schubert goto fail; 984*266f97b5SCy Schubert brx = crypto_ec_key_get_pubkey_point(auth->own_bi->pubkey, 0); 985c1d255d3SCy Schubert } 986c1d255d3SCy Schubert if (!pix || !prx || !brx) 987c1d255d3SCy Schubert goto fail; 988c1d255d3SCy Schubert 989c1d255d3SCy Schubert addr[num_elem] = auth->r_nonce; 990c1d255d3SCy Schubert len[num_elem] = nonce_len; 991c1d255d3SCy Schubert num_elem++; 992c1d255d3SCy Schubert 993c1d255d3SCy Schubert addr[num_elem] = auth->i_nonce; 994c1d255d3SCy Schubert len[num_elem] = nonce_len; 995c1d255d3SCy Schubert num_elem++; 996c1d255d3SCy Schubert 997c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(prx); 998c1d255d3SCy Schubert len[num_elem] = wpabuf_len(prx) / 2; 999c1d255d3SCy Schubert num_elem++; 1000c1d255d3SCy Schubert 1001c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(pix); 1002c1d255d3SCy Schubert len[num_elem] = wpabuf_len(pix) / 2; 1003c1d255d3SCy Schubert num_elem++; 1004c1d255d3SCy Schubert 1005c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(brx); 1006c1d255d3SCy Schubert len[num_elem] = wpabuf_len(brx) / 2; 1007c1d255d3SCy Schubert num_elem++; 1008c1d255d3SCy Schubert 1009c1d255d3SCy Schubert if (bix) { 1010c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(bix); 1011c1d255d3SCy Schubert len[num_elem] = wpabuf_len(bix) / 2; 1012c1d255d3SCy Schubert num_elem++; 1013c1d255d3SCy Schubert } 1014c1d255d3SCy Schubert 1015c1d255d3SCy Schubert addr[num_elem] = &one; 1016c1d255d3SCy Schubert len[num_elem] = 1; 1017c1d255d3SCy Schubert num_elem++; 1018c1d255d3SCy Schubert 1019c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: I-auth hash components"); 1020c1d255d3SCy Schubert for (i = 0; i < num_elem; i++) 1021c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); 1022c1d255d3SCy Schubert res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth); 1023c1d255d3SCy Schubert if (res == 0) 1024c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth, 1025c1d255d3SCy Schubert auth->curve->hash_len); 1026c1d255d3SCy Schubert fail: 1027c1d255d3SCy Schubert wpabuf_free(pix); 1028c1d255d3SCy Schubert wpabuf_free(prx); 1029c1d255d3SCy Schubert wpabuf_free(bix); 1030c1d255d3SCy Schubert wpabuf_free(brx); 1031c1d255d3SCy Schubert return res; 1032c1d255d3SCy Schubert } 1033c1d255d3SCy Schubert 1034c1d255d3SCy Schubert 1035c1d255d3SCy Schubert int dpp_auth_derive_l_responder(struct dpp_authentication *auth) 1036c1d255d3SCy Schubert { 1037*266f97b5SCy Schubert struct crypto_ec *ec; 1038*266f97b5SCy Schubert struct crypto_ec_point *L = NULL; 1039*266f97b5SCy Schubert const struct crypto_ec_point *BI; 1040*266f97b5SCy Schubert const struct crypto_bignum *bR, *pR, *q; 1041*266f97b5SCy Schubert struct crypto_bignum *sum = NULL, *lx = NULL; 1042c1d255d3SCy Schubert int ret = -1; 1043c1d255d3SCy Schubert 1044c1d255d3SCy Schubert /* L = ((bR + pR) modulo q) * BI */ 1045c1d255d3SCy Schubert 1046*266f97b5SCy Schubert ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey)); 1047*266f97b5SCy Schubert if (!ec) 1048c1d255d3SCy Schubert goto fail; 1049c1d255d3SCy Schubert 1050*266f97b5SCy Schubert q = crypto_ec_get_order(ec); 1051*266f97b5SCy Schubert BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey); 1052*266f97b5SCy Schubert bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey); 1053*266f97b5SCy Schubert pR = crypto_ec_key_get_private_key(auth->own_protocol_key); 1054*266f97b5SCy Schubert sum = crypto_bignum_init(); 1055*266f97b5SCy Schubert L = crypto_ec_point_init(ec); 1056*266f97b5SCy Schubert lx = crypto_bignum_init(); 1057*266f97b5SCy Schubert if (!q || !BI || !bR || !pR || !sum || !L || !lx || 1058*266f97b5SCy Schubert crypto_bignum_addmod(bR, pR, q, sum) || 1059*266f97b5SCy Schubert crypto_ec_point_mul(ec, BI, sum, L) || 1060*266f97b5SCy Schubert crypto_ec_point_x(ec, L, lx) || 1061*266f97b5SCy Schubert crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx), 1062*266f97b5SCy Schubert auth->secret_len) < 0) 1063c1d255d3SCy Schubert goto fail; 1064c1d255d3SCy Schubert 1065c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); 1066c1d255d3SCy Schubert auth->Lx_len = auth->secret_len; 1067c1d255d3SCy Schubert ret = 0; 1068c1d255d3SCy Schubert fail: 1069*266f97b5SCy Schubert crypto_bignum_deinit(lx, 1); 1070*266f97b5SCy Schubert crypto_bignum_deinit(sum, 1); 1071*266f97b5SCy Schubert crypto_ec_point_deinit(L, 1); 1072*266f97b5SCy Schubert crypto_ec_deinit(ec); 1073c1d255d3SCy Schubert return ret; 1074c1d255d3SCy Schubert } 1075c1d255d3SCy Schubert 1076c1d255d3SCy Schubert 1077c1d255d3SCy Schubert int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) 1078c1d255d3SCy Schubert { 1079*266f97b5SCy Schubert struct crypto_ec *ec; 1080*266f97b5SCy Schubert struct crypto_ec_point *L = NULL, *sum = NULL; 1081*266f97b5SCy Schubert const struct crypto_ec_point *BR, *PR; 1082*266f97b5SCy Schubert const struct crypto_bignum *bI; 1083*266f97b5SCy Schubert struct crypto_bignum *lx = NULL; 1084c1d255d3SCy Schubert int ret = -1; 1085c1d255d3SCy Schubert 1086c1d255d3SCy Schubert /* L = bI * (BR + PR) */ 1087c1d255d3SCy Schubert 1088*266f97b5SCy Schubert ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey)); 1089*266f97b5SCy Schubert if (!ec) 1090c1d255d3SCy Schubert goto fail; 1091c1d255d3SCy Schubert 1092*266f97b5SCy Schubert BR = crypto_ec_key_get_public_key(auth->peer_bi->pubkey); 1093*266f97b5SCy Schubert PR = crypto_ec_key_get_public_key(auth->peer_protocol_key); 1094*266f97b5SCy Schubert bI = crypto_ec_key_get_private_key(auth->own_bi->pubkey); 1095*266f97b5SCy Schubert sum = crypto_ec_point_init(ec); 1096*266f97b5SCy Schubert L = crypto_ec_point_init(ec); 1097*266f97b5SCy Schubert lx = crypto_bignum_init(); 1098*266f97b5SCy Schubert if (!BR || !PR || !bI || !sum || !L || !lx || 1099*266f97b5SCy Schubert crypto_ec_point_add(ec, BR, PR, sum) || 1100*266f97b5SCy Schubert crypto_ec_point_mul(ec, sum, bI, L) || 1101*266f97b5SCy Schubert crypto_ec_point_x(ec, L, lx) || 1102*266f97b5SCy Schubert crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx), 1103*266f97b5SCy Schubert auth->secret_len) < 0) 1104c1d255d3SCy Schubert goto fail; 1105c1d255d3SCy Schubert 1106c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); 1107c1d255d3SCy Schubert auth->Lx_len = auth->secret_len; 1108c1d255d3SCy Schubert ret = 0; 1109c1d255d3SCy Schubert fail: 1110*266f97b5SCy Schubert crypto_bignum_deinit(lx, 1); 1111*266f97b5SCy Schubert crypto_ec_point_deinit(sum, 1); 1112*266f97b5SCy Schubert crypto_ec_point_deinit(L, 1); 1113*266f97b5SCy Schubert crypto_ec_deinit(ec); 1114c1d255d3SCy Schubert return ret; 1115c1d255d3SCy Schubert } 1116c1d255d3SCy Schubert 1117c1d255d3SCy Schubert 1118c1d255d3SCy Schubert int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len) 1119c1d255d3SCy Schubert { 1120c1d255d3SCy Schubert u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 1121c1d255d3SCy Schubert const char *info = "DPP PMK"; 1122c1d255d3SCy Schubert int res; 1123c1d255d3SCy Schubert 1124c1d255d3SCy Schubert /* PMK = HKDF(<>, "DPP PMK", N.x) */ 1125c1d255d3SCy Schubert 1126c1d255d3SCy Schubert /* HKDF-Extract(<>, N.x) */ 1127c1d255d3SCy Schubert os_memset(salt, 0, hash_len); 1128c1d255d3SCy Schubert if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0) 1129c1d255d3SCy Schubert return -1; 1130c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", 1131c1d255d3SCy Schubert prk, hash_len); 1132c1d255d3SCy Schubert 1133c1d255d3SCy Schubert /* HKDF-Expand(PRK, info, L) */ 1134c1d255d3SCy Schubert res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len); 1135c1d255d3SCy Schubert os_memset(prk, 0, hash_len); 1136c1d255d3SCy Schubert if (res < 0) 1137c1d255d3SCy Schubert return -1; 1138c1d255d3SCy Schubert 1139c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)", 1140c1d255d3SCy Schubert pmk, hash_len); 1141c1d255d3SCy Schubert return 0; 1142c1d255d3SCy Schubert } 1143c1d255d3SCy Schubert 1144c1d255d3SCy Schubert 1145c1d255d3SCy Schubert int dpp_derive_pmkid(const struct dpp_curve_params *curve, 1146*266f97b5SCy Schubert struct crypto_ec_key *own_key, 1147*266f97b5SCy Schubert struct crypto_ec_key *peer_key, u8 *pmkid) 1148c1d255d3SCy Schubert { 1149c1d255d3SCy Schubert struct wpabuf *nkx, *pkx; 1150c1d255d3SCy Schubert int ret = -1, res; 1151c1d255d3SCy Schubert const u8 *addr[2]; 1152c1d255d3SCy Schubert size_t len[2]; 1153c1d255d3SCy Schubert u8 hash[SHA256_MAC_LEN]; 1154c1d255d3SCy Schubert 1155c1d255d3SCy Schubert /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */ 1156*266f97b5SCy Schubert nkx = crypto_ec_key_get_pubkey_point(own_key, 0); 1157*266f97b5SCy Schubert pkx = crypto_ec_key_get_pubkey_point(peer_key, 0); 1158c1d255d3SCy Schubert if (!nkx || !pkx) 1159c1d255d3SCy Schubert goto fail; 1160c1d255d3SCy Schubert addr[0] = wpabuf_head(nkx); 1161c1d255d3SCy Schubert len[0] = wpabuf_len(nkx) / 2; 1162c1d255d3SCy Schubert addr[1] = wpabuf_head(pkx); 1163c1d255d3SCy Schubert len[1] = wpabuf_len(pkx) / 2; 1164c1d255d3SCy Schubert if (len[0] != len[1]) 1165c1d255d3SCy Schubert goto fail; 1166c1d255d3SCy Schubert if (os_memcmp(addr[0], addr[1], len[0]) > 0) { 1167c1d255d3SCy Schubert addr[0] = wpabuf_head(pkx); 1168c1d255d3SCy Schubert addr[1] = wpabuf_head(nkx); 1169c1d255d3SCy Schubert } 1170c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]); 1171c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]); 1172c1d255d3SCy Schubert res = sha256_vector(2, addr, len, hash); 1173c1d255d3SCy Schubert if (res < 0) 1174c1d255d3SCy Schubert goto fail; 1175c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN); 1176c1d255d3SCy Schubert os_memcpy(pmkid, hash, PMKID_LEN); 1177c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN); 1178c1d255d3SCy Schubert ret = 0; 1179c1d255d3SCy Schubert fail: 1180c1d255d3SCy Schubert wpabuf_free(nkx); 1181c1d255d3SCy Schubert wpabuf_free(pkx); 1182c1d255d3SCy Schubert return ret; 1183c1d255d3SCy Schubert } 1184c1d255d3SCy Schubert 1185c1d255d3SCy Schubert 1186c1d255d3SCy Schubert /* Role-specific elements for PKEX */ 1187c1d255d3SCy Schubert 1188c1d255d3SCy Schubert /* NIST P-256 */ 1189c1d255d3SCy Schubert static const u8 pkex_init_x_p256[32] = { 1190c1d255d3SCy Schubert 0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b, 1191c1d255d3SCy Schubert 0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54, 1192c1d255d3SCy Schubert 0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07, 1193c1d255d3SCy Schubert 0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25 1194c1d255d3SCy Schubert }; 1195c1d255d3SCy Schubert static const u8 pkex_init_y_p256[32] = { 1196c1d255d3SCy Schubert 0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b, 1197c1d255d3SCy Schubert 0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc, 1198c1d255d3SCy Schubert 0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45, 1199c1d255d3SCy Schubert 0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4 1200c1d255d3SCy Schubert }; 1201c1d255d3SCy Schubert static const u8 pkex_resp_x_p256[32] = { 1202c1d255d3SCy Schubert 0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39, 1203c1d255d3SCy Schubert 0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f, 1204c1d255d3SCy Schubert 0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f, 1205c1d255d3SCy Schubert 0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76 1206c1d255d3SCy Schubert }; 1207c1d255d3SCy Schubert static const u8 pkex_resp_y_p256[32] = { 1208c1d255d3SCy Schubert 0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19, 1209c1d255d3SCy Schubert 0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1, 1210c1d255d3SCy Schubert 0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a, 1211c1d255d3SCy Schubert 0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67 1212c1d255d3SCy Schubert }; 1213c1d255d3SCy Schubert 1214c1d255d3SCy Schubert /* NIST P-384 */ 1215c1d255d3SCy Schubert static const u8 pkex_init_x_p384[48] = { 1216c1d255d3SCy Schubert 0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa, 1217c1d255d3SCy Schubert 0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68, 1218c1d255d3SCy Schubert 0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53, 1219c1d255d3SCy Schubert 0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac, 1220c1d255d3SCy Schubert 0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12, 1221c1d255d3SCy Schubert 0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3 1222c1d255d3SCy Schubert }; 1223c1d255d3SCy Schubert static const u8 pkex_init_y_p384[48] = { 1224c1d255d3SCy Schubert 0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29, 1225c1d255d3SCy Schubert 0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56, 1226c1d255d3SCy Schubert 0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7, 1227c1d255d3SCy Schubert 0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6, 1228c1d255d3SCy Schubert 0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94, 1229c1d255d3SCy Schubert 0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18 1230c1d255d3SCy Schubert }; 1231c1d255d3SCy Schubert static const u8 pkex_resp_x_p384[48] = { 1232c1d255d3SCy Schubert 0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98, 1233c1d255d3SCy Schubert 0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97, 1234c1d255d3SCy Schubert 0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92, 1235c1d255d3SCy Schubert 0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44, 1236c1d255d3SCy Schubert 0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf, 1237c1d255d3SCy Schubert 0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf 1238c1d255d3SCy Schubert }; 1239c1d255d3SCy Schubert static const u8 pkex_resp_y_p384[48] = { 1240c1d255d3SCy Schubert 0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c, 1241c1d255d3SCy Schubert 0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c, 1242c1d255d3SCy Schubert 0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3, 1243c1d255d3SCy Schubert 0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1, 1244c1d255d3SCy Schubert 0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63, 1245c1d255d3SCy Schubert 0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06 1246c1d255d3SCy Schubert }; 1247c1d255d3SCy Schubert 1248c1d255d3SCy Schubert /* NIST P-521 */ 1249c1d255d3SCy Schubert static const u8 pkex_init_x_p521[66] = { 1250c1d255d3SCy Schubert 0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23, 1251c1d255d3SCy Schubert 0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0, 1252c1d255d3SCy Schubert 0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76, 1253c1d255d3SCy Schubert 0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5, 1254c1d255d3SCy Schubert 0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38, 1255c1d255d3SCy Schubert 0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01, 1256c1d255d3SCy Schubert 0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e, 1257c1d255d3SCy Schubert 0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d, 1258c1d255d3SCy Schubert 0x97, 0x76 1259c1d255d3SCy Schubert }; 1260c1d255d3SCy Schubert static const u8 pkex_init_y_p521[66] = { 1261c1d255d3SCy Schubert 0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59, 1262c1d255d3SCy Schubert 0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99, 1263c1d255d3SCy Schubert 0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b, 1264c1d255d3SCy Schubert 0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd, 1265c1d255d3SCy Schubert 0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f, 1266c1d255d3SCy Schubert 0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf, 1267c1d255d3SCy Schubert 0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02, 1268c1d255d3SCy Schubert 0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d, 1269c1d255d3SCy Schubert 0x03, 0xa8 1270c1d255d3SCy Schubert }; 1271c1d255d3SCy Schubert static const u8 pkex_resp_x_p521[66] = { 1272c1d255d3SCy Schubert 0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a, 1273c1d255d3SCy Schubert 0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44, 1274c1d255d3SCy Schubert 0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f, 1275c1d255d3SCy Schubert 0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb, 1276c1d255d3SCy Schubert 0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48, 1277c1d255d3SCy Schubert 0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e, 1278c1d255d3SCy Schubert 0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a, 1279c1d255d3SCy Schubert 0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97, 1280c1d255d3SCy Schubert 0x84, 0xb4 1281c1d255d3SCy Schubert }; 1282c1d255d3SCy Schubert static const u8 pkex_resp_y_p521[66] = { 1283c1d255d3SCy Schubert 0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d, 1284c1d255d3SCy Schubert 0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20, 1285c1d255d3SCy Schubert 0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3, 1286c1d255d3SCy Schubert 0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84, 1287c1d255d3SCy Schubert 0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9, 1288c1d255d3SCy Schubert 0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2, 1289c1d255d3SCy Schubert 0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80, 1290c1d255d3SCy Schubert 0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53, 1291c1d255d3SCy Schubert 0xce, 0xe1 1292c1d255d3SCy Schubert }; 1293c1d255d3SCy Schubert 1294c1d255d3SCy Schubert /* Brainpool P-256r1 */ 1295c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p256r1[32] = { 1296c1d255d3SCy Schubert 0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10, 1297c1d255d3SCy Schubert 0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca, 1298c1d255d3SCy Schubert 0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75, 1299c1d255d3SCy Schubert 0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8 1300c1d255d3SCy Schubert }; 1301c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p256r1[32] = { 1302c1d255d3SCy Schubert 0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd, 1303c1d255d3SCy Schubert 0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30, 1304c1d255d3SCy Schubert 0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe, 1305c1d255d3SCy Schubert 0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b 1306c1d255d3SCy Schubert }; 1307c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p256r1[32] = { 1308c1d255d3SCy Schubert 0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f, 1309c1d255d3SCy Schubert 0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a, 1310c1d255d3SCy Schubert 0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a, 1311c1d255d3SCy Schubert 0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3 1312c1d255d3SCy Schubert }; 1313c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p256r1[32] = { 1314c1d255d3SCy Schubert 0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd, 1315c1d255d3SCy Schubert 0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2, 1316c1d255d3SCy Schubert 0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e, 1317c1d255d3SCy Schubert 0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64 1318c1d255d3SCy Schubert }; 1319c1d255d3SCy Schubert 1320c1d255d3SCy Schubert /* Brainpool P-384r1 */ 1321c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p384r1[48] = { 1322c1d255d3SCy Schubert 0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd, 1323c1d255d3SCy Schubert 0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19, 1324c1d255d3SCy Schubert 0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06, 1325c1d255d3SCy Schubert 0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62, 1326c1d255d3SCy Schubert 0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30, 1327c1d255d3SCy Schubert 0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe 1328c1d255d3SCy Schubert }; 1329c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p384r1[48] = { 1330c1d255d3SCy Schubert 0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99, 1331c1d255d3SCy Schubert 0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86, 1332c1d255d3SCy Schubert 0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32, 1333c1d255d3SCy Schubert 0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9, 1334c1d255d3SCy Schubert 0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e, 1335c1d255d3SCy Schubert 0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52 1336c1d255d3SCy Schubert }; 1337c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p384r1[48] = { 1338c1d255d3SCy Schubert 0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0, 1339c1d255d3SCy Schubert 0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25, 1340c1d255d3SCy Schubert 0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b, 1341c1d255d3SCy Schubert 0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71, 1342c1d255d3SCy Schubert 0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce, 1343c1d255d3SCy Schubert 0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c 1344c1d255d3SCy Schubert }; 1345c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p384r1[48] = { 1346c1d255d3SCy Schubert 0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65, 1347c1d255d3SCy Schubert 0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04, 1348c1d255d3SCy Schubert 0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70, 1349c1d255d3SCy Schubert 0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c, 1350c1d255d3SCy Schubert 0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb, 1351c1d255d3SCy Schubert 0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1 1352c1d255d3SCy Schubert }; 1353c1d255d3SCy Schubert 1354c1d255d3SCy Schubert /* Brainpool P-512r1 */ 1355c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p512r1[64] = { 1356c1d255d3SCy Schubert 0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c, 1357c1d255d3SCy Schubert 0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51, 1358c1d255d3SCy Schubert 0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc, 1359c1d255d3SCy Schubert 0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95, 1360c1d255d3SCy Schubert 0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d, 1361c1d255d3SCy Schubert 0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff, 1362c1d255d3SCy Schubert 0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc, 1363c1d255d3SCy Schubert 0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f 1364c1d255d3SCy Schubert }; 1365c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p512r1[64] = { 1366c1d255d3SCy Schubert 0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94, 1367c1d255d3SCy Schubert 0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8, 1368c1d255d3SCy Schubert 0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3, 1369c1d255d3SCy Schubert 0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45, 1370c1d255d3SCy Schubert 0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e, 1371c1d255d3SCy Schubert 0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58, 1372c1d255d3SCy Schubert 0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71, 1373c1d255d3SCy Schubert 0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99 1374c1d255d3SCy Schubert }; 1375c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p512r1[64] = { 1376c1d255d3SCy Schubert 0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72, 1377c1d255d3SCy Schubert 0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76, 1378c1d255d3SCy Schubert 0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19, 1379c1d255d3SCy Schubert 0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e, 1380c1d255d3SCy Schubert 0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9, 1381c1d255d3SCy Schubert 0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88, 1382c1d255d3SCy Schubert 0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29, 1383c1d255d3SCy Schubert 0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e 1384c1d255d3SCy Schubert }; 1385c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p512r1[64] = { 1386c1d255d3SCy Schubert 0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81, 1387c1d255d3SCy Schubert 0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68, 1388c1d255d3SCy Schubert 0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa, 1389c1d255d3SCy Schubert 0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d, 1390c1d255d3SCy Schubert 0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c, 1391c1d255d3SCy Schubert 0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09, 1392c1d255d3SCy Schubert 0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56, 1393c1d255d3SCy Schubert 0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7 1394c1d255d3SCy Schubert }; 1395c1d255d3SCy Schubert 1396c1d255d3SCy Schubert 1397*266f97b5SCy Schubert static struct crypto_ec_key * 1398*266f97b5SCy Schubert dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init) 1399c1d255d3SCy Schubert { 1400c1d255d3SCy Schubert const u8 *x, *y; 1401c1d255d3SCy Schubert 1402c1d255d3SCy Schubert switch (curve->ike_group) { 1403c1d255d3SCy Schubert case 19: 1404c1d255d3SCy Schubert x = init ? pkex_init_x_p256 : pkex_resp_x_p256; 1405c1d255d3SCy Schubert y = init ? pkex_init_y_p256 : pkex_resp_y_p256; 1406c1d255d3SCy Schubert break; 1407c1d255d3SCy Schubert case 20: 1408c1d255d3SCy Schubert x = init ? pkex_init_x_p384 : pkex_resp_x_p384; 1409c1d255d3SCy Schubert y = init ? pkex_init_y_p384 : pkex_resp_y_p384; 1410c1d255d3SCy Schubert break; 1411c1d255d3SCy Schubert case 21: 1412c1d255d3SCy Schubert x = init ? pkex_init_x_p521 : pkex_resp_x_p521; 1413c1d255d3SCy Schubert y = init ? pkex_init_y_p521 : pkex_resp_y_p521; 1414c1d255d3SCy Schubert break; 1415c1d255d3SCy Schubert case 28: 1416c1d255d3SCy Schubert x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1; 1417c1d255d3SCy Schubert y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1; 1418c1d255d3SCy Schubert break; 1419c1d255d3SCy Schubert case 29: 1420c1d255d3SCy Schubert x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1; 1421c1d255d3SCy Schubert y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1; 1422c1d255d3SCy Schubert break; 1423c1d255d3SCy Schubert case 30: 1424c1d255d3SCy Schubert x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1; 1425c1d255d3SCy Schubert y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1; 1426c1d255d3SCy Schubert break; 1427c1d255d3SCy Schubert default: 1428c1d255d3SCy Schubert return NULL; 1429c1d255d3SCy Schubert } 1430c1d255d3SCy Schubert 1431*266f97b5SCy Schubert return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len); 1432c1d255d3SCy Schubert } 1433c1d255d3SCy Schubert 1434c1d255d3SCy Schubert 1435*266f97b5SCy Schubert struct crypto_ec_point * 1436*266f97b5SCy Schubert dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init, 1437*266f97b5SCy Schubert const char *code, const char *identifier, 1438*266f97b5SCy Schubert struct crypto_ec **ret_ec) 1439c1d255d3SCy Schubert { 1440c1d255d3SCy Schubert u8 hash[DPP_MAX_HASH_LEN]; 1441c1d255d3SCy Schubert const u8 *addr[3]; 1442c1d255d3SCy Schubert size_t len[3]; 1443c1d255d3SCy Schubert unsigned int num_elem = 0; 1444*266f97b5SCy Schubert struct crypto_ec_point *Qi = NULL; 1445*266f97b5SCy Schubert struct crypto_ec_key *Pi_key = NULL; 1446*266f97b5SCy Schubert const struct crypto_ec_point *Pi = NULL; 1447*266f97b5SCy Schubert struct crypto_bignum *hash_bn = NULL; 1448*266f97b5SCy Schubert struct crypto_ec *ec = NULL; 1449c1d255d3SCy Schubert 1450c1d255d3SCy Schubert /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ 1451c1d255d3SCy Schubert 1452c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init)); 1453c1d255d3SCy Schubert addr[num_elem] = mac_init; 1454c1d255d3SCy Schubert len[num_elem] = ETH_ALEN; 1455c1d255d3SCy Schubert num_elem++; 1456c1d255d3SCy Schubert if (identifier) { 1457c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", 1458c1d255d3SCy Schubert identifier); 1459c1d255d3SCy Schubert addr[num_elem] = (const u8 *) identifier; 1460c1d255d3SCy Schubert len[num_elem] = os_strlen(identifier); 1461c1d255d3SCy Schubert num_elem++; 1462c1d255d3SCy Schubert } 1463c1d255d3SCy Schubert wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); 1464c1d255d3SCy Schubert addr[num_elem] = (const u8 *) code; 1465c1d255d3SCy Schubert len[num_elem] = os_strlen(code); 1466c1d255d3SCy Schubert num_elem++; 1467c1d255d3SCy Schubert if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) 1468c1d255d3SCy Schubert goto fail; 1469c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 1470c1d255d3SCy Schubert "DPP: H(MAC-Initiator | [identifier |] code)", 1471c1d255d3SCy Schubert hash, curve->hash_len); 1472*266f97b5SCy Schubert Pi_key = dpp_pkex_get_role_elem(curve, 1); 1473*266f97b5SCy Schubert if (!Pi_key) 1474c1d255d3SCy Schubert goto fail; 1475*266f97b5SCy Schubert dpp_debug_print_key("DPP: Pi", Pi_key); 1476c1d255d3SCy Schubert 1477*266f97b5SCy Schubert ec = crypto_ec_init(curve->ike_group); 1478*266f97b5SCy Schubert if (!ec) 1479c1d255d3SCy Schubert goto fail; 1480*266f97b5SCy Schubert 1481*266f97b5SCy Schubert Pi = crypto_ec_key_get_public_key(Pi_key); 1482*266f97b5SCy Schubert Qi = crypto_ec_point_init(ec); 1483*266f97b5SCy Schubert hash_bn = crypto_bignum_init_set(hash, curve->hash_len); 1484*266f97b5SCy Schubert if (!Pi || !Qi || !hash_bn || crypto_ec_point_mul(ec, Pi, hash_bn, Qi)) 1485c1d255d3SCy Schubert goto fail; 1486*266f97b5SCy Schubert 1487*266f97b5SCy Schubert if (crypto_ec_point_is_at_infinity(ec, Qi)) { 1488c1d255d3SCy Schubert wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity"); 1489c1d255d3SCy Schubert goto fail; 1490c1d255d3SCy Schubert } 1491*266f97b5SCy Schubert crypto_ec_point_debug_print(ec, Qi, "DPP: Qi"); 1492c1d255d3SCy Schubert out: 1493*266f97b5SCy Schubert crypto_ec_key_deinit(Pi_key); 1494*266f97b5SCy Schubert crypto_bignum_deinit(hash_bn, 1); 1495*266f97b5SCy Schubert if (ret_ec && Qi) 1496*266f97b5SCy Schubert *ret_ec = ec; 1497c1d255d3SCy Schubert else 1498*266f97b5SCy Schubert crypto_ec_deinit(ec); 1499c1d255d3SCy Schubert return Qi; 1500c1d255d3SCy Schubert fail: 1501*266f97b5SCy Schubert crypto_ec_point_deinit(Qi, 1); 1502c1d255d3SCy Schubert Qi = NULL; 1503c1d255d3SCy Schubert goto out; 1504c1d255d3SCy Schubert } 1505c1d255d3SCy Schubert 1506c1d255d3SCy Schubert 1507*266f97b5SCy Schubert struct crypto_ec_point * 1508*266f97b5SCy Schubert dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp, 1509*266f97b5SCy Schubert const char *code, const char *identifier, 1510*266f97b5SCy Schubert struct crypto_ec **ret_ec) 1511c1d255d3SCy Schubert { 1512c1d255d3SCy Schubert u8 hash[DPP_MAX_HASH_LEN]; 1513c1d255d3SCy Schubert const u8 *addr[3]; 1514c1d255d3SCy Schubert size_t len[3]; 1515c1d255d3SCy Schubert unsigned int num_elem = 0; 1516*266f97b5SCy Schubert struct crypto_ec_point *Qr = NULL; 1517*266f97b5SCy Schubert struct crypto_ec_key *Pr_key = NULL; 1518*266f97b5SCy Schubert const struct crypto_ec_point *Pr = NULL; 1519*266f97b5SCy Schubert struct crypto_bignum *hash_bn = NULL; 1520*266f97b5SCy Schubert struct crypto_ec *ec = NULL; 1521c1d255d3SCy Schubert 1522c1d255d3SCy Schubert /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */ 1523c1d255d3SCy Schubert 1524c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp)); 1525c1d255d3SCy Schubert addr[num_elem] = mac_resp; 1526c1d255d3SCy Schubert len[num_elem] = ETH_ALEN; 1527c1d255d3SCy Schubert num_elem++; 1528c1d255d3SCy Schubert if (identifier) { 1529c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", 1530c1d255d3SCy Schubert identifier); 1531c1d255d3SCy Schubert addr[num_elem] = (const u8 *) identifier; 1532c1d255d3SCy Schubert len[num_elem] = os_strlen(identifier); 1533c1d255d3SCy Schubert num_elem++; 1534c1d255d3SCy Schubert } 1535c1d255d3SCy Schubert wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); 1536c1d255d3SCy Schubert addr[num_elem] = (const u8 *) code; 1537c1d255d3SCy Schubert len[num_elem] = os_strlen(code); 1538c1d255d3SCy Schubert num_elem++; 1539c1d255d3SCy Schubert if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) 1540c1d255d3SCy Schubert goto fail; 1541c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 1542c1d255d3SCy Schubert "DPP: H(MAC-Responder | [identifier |] code)", 1543c1d255d3SCy Schubert hash, curve->hash_len); 1544*266f97b5SCy Schubert Pr_key = dpp_pkex_get_role_elem(curve, 0); 1545*266f97b5SCy Schubert if (!Pr_key) 1546c1d255d3SCy Schubert goto fail; 1547*266f97b5SCy Schubert dpp_debug_print_key("DPP: Pr", Pr_key); 1548c1d255d3SCy Schubert 1549*266f97b5SCy Schubert ec = crypto_ec_init(curve->ike_group); 1550*266f97b5SCy Schubert if (!ec) 1551c1d255d3SCy Schubert goto fail; 1552*266f97b5SCy Schubert 1553*266f97b5SCy Schubert Pr = crypto_ec_key_get_public_key(Pr_key); 1554*266f97b5SCy Schubert Qr = crypto_ec_point_init(ec); 1555*266f97b5SCy Schubert hash_bn = crypto_bignum_init_set(hash, curve->hash_len); 1556*266f97b5SCy Schubert if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr)) 1557c1d255d3SCy Schubert goto fail; 1558*266f97b5SCy Schubert 1559*266f97b5SCy Schubert if (crypto_ec_point_is_at_infinity(ec, Qr)) { 1560c1d255d3SCy Schubert wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity"); 1561c1d255d3SCy Schubert goto fail; 1562c1d255d3SCy Schubert } 1563*266f97b5SCy Schubert crypto_ec_point_debug_print(ec, Qr, "DPP: Qr"); 1564*266f97b5SCy Schubert 1565c1d255d3SCy Schubert out: 1566*266f97b5SCy Schubert crypto_ec_key_deinit(Pr_key); 1567*266f97b5SCy Schubert crypto_bignum_deinit(hash_bn, 1); 1568*266f97b5SCy Schubert if (ret_ec && Qr) 1569*266f97b5SCy Schubert *ret_ec = ec; 1570c1d255d3SCy Schubert else 1571*266f97b5SCy Schubert crypto_ec_deinit(ec); 1572c1d255d3SCy Schubert return Qr; 1573c1d255d3SCy Schubert fail: 1574*266f97b5SCy Schubert crypto_ec_point_deinit(Qr, 1); 1575c1d255d3SCy Schubert Qr = NULL; 1576c1d255d3SCy Schubert goto out; 1577c1d255d3SCy Schubert } 1578c1d255d3SCy Schubert 1579c1d255d3SCy Schubert 1580c1d255d3SCy Schubert int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, 1581c1d255d3SCy Schubert const u8 *Mx, size_t Mx_len, 1582c1d255d3SCy Schubert const u8 *Nx, size_t Nx_len, 1583c1d255d3SCy Schubert const char *code, 1584c1d255d3SCy Schubert const u8 *Kx, size_t Kx_len, 1585c1d255d3SCy Schubert u8 *z, unsigned int hash_len) 1586c1d255d3SCy Schubert { 1587c1d255d3SCy Schubert u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 1588c1d255d3SCy Schubert int res; 1589c1d255d3SCy Schubert u8 *info, *pos; 1590c1d255d3SCy Schubert size_t info_len; 1591c1d255d3SCy Schubert 1592c1d255d3SCy Schubert /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) 1593c1d255d3SCy Schubert */ 1594c1d255d3SCy Schubert 1595c1d255d3SCy Schubert /* HKDF-Extract(<>, IKM=K.x) */ 1596c1d255d3SCy Schubert os_memset(salt, 0, hash_len); 1597c1d255d3SCy Schubert if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0) 1598c1d255d3SCy Schubert return -1; 1599c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", 1600c1d255d3SCy Schubert prk, hash_len); 1601c1d255d3SCy Schubert info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code); 1602c1d255d3SCy Schubert info = os_malloc(info_len); 1603c1d255d3SCy Schubert if (!info) 1604c1d255d3SCy Schubert return -1; 1605c1d255d3SCy Schubert pos = info; 1606c1d255d3SCy Schubert os_memcpy(pos, mac_init, ETH_ALEN); 1607c1d255d3SCy Schubert pos += ETH_ALEN; 1608c1d255d3SCy Schubert os_memcpy(pos, mac_resp, ETH_ALEN); 1609c1d255d3SCy Schubert pos += ETH_ALEN; 1610c1d255d3SCy Schubert os_memcpy(pos, Mx, Mx_len); 1611c1d255d3SCy Schubert pos += Mx_len; 1612c1d255d3SCy Schubert os_memcpy(pos, Nx, Nx_len); 1613c1d255d3SCy Schubert pos += Nx_len; 1614c1d255d3SCy Schubert os_memcpy(pos, code, os_strlen(code)); 1615c1d255d3SCy Schubert 1616c1d255d3SCy Schubert /* HKDF-Expand(PRK, info, L) */ 1617c1d255d3SCy Schubert if (hash_len == 32) 1618c1d255d3SCy Schubert res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len, 1619c1d255d3SCy Schubert z, hash_len); 1620c1d255d3SCy Schubert else if (hash_len == 48) 1621c1d255d3SCy Schubert res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len, 1622c1d255d3SCy Schubert z, hash_len); 1623c1d255d3SCy Schubert else if (hash_len == 64) 1624c1d255d3SCy Schubert res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len, 1625c1d255d3SCy Schubert z, hash_len); 1626c1d255d3SCy Schubert else 1627c1d255d3SCy Schubert res = -1; 1628c1d255d3SCy Schubert os_free(info); 1629c1d255d3SCy Schubert os_memset(prk, 0, hash_len); 1630c1d255d3SCy Schubert if (res < 0) 1631c1d255d3SCy Schubert return -1; 1632c1d255d3SCy Schubert 1633c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)", 1634c1d255d3SCy Schubert z, hash_len); 1635c1d255d3SCy Schubert return 0; 1636c1d255d3SCy Schubert } 1637c1d255d3SCy Schubert 1638c1d255d3SCy Schubert 1639c1d255d3SCy Schubert int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, 1640c1d255d3SCy Schubert const u8 *net_access_key, 1641c1d255d3SCy Schubert size_t net_access_key_len, 1642c1d255d3SCy Schubert struct json_token *peer_net_access_key) 1643c1d255d3SCy Schubert { 1644*266f97b5SCy Schubert struct crypto_ec_key *own_key = NULL, *peer_key = NULL; 1645*266f97b5SCy Schubert struct crypto_bignum *sum = NULL; 1646*266f97b5SCy Schubert const struct crypto_bignum *q, *cR, *pR; 1647*266f97b5SCy Schubert struct crypto_ec *ec = NULL; 1648*266f97b5SCy Schubert struct crypto_ec_point *M = NULL; 1649*266f97b5SCy Schubert const struct crypto_ec_point *CI; 1650c1d255d3SCy Schubert u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; 1651c1d255d3SCy Schubert u8 prk[DPP_MAX_HASH_LEN]; 1652c1d255d3SCy Schubert const struct dpp_curve_params *curve; 1653c1d255d3SCy Schubert int res = -1; 1654c1d255d3SCy Schubert u8 nonces[2 * DPP_MAX_NONCE_LEN]; 1655c1d255d3SCy Schubert 1656c1d255d3SCy Schubert own_key = dpp_set_keypair(&auth->curve, net_access_key, 1657c1d255d3SCy Schubert net_access_key_len); 1658c1d255d3SCy Schubert if (!own_key) { 1659c1d255d3SCy Schubert dpp_auth_fail(auth, "Failed to parse own netAccessKey"); 1660c1d255d3SCy Schubert goto fail; 1661c1d255d3SCy Schubert } 1662c1d255d3SCy Schubert 1663c1d255d3SCy Schubert peer_key = dpp_parse_jwk(peer_net_access_key, &curve); 1664c1d255d3SCy Schubert if (!peer_key) 1665c1d255d3SCy Schubert goto fail; 1666c1d255d3SCy Schubert dpp_debug_print_key("DPP: Received netAccessKey", peer_key); 1667c1d255d3SCy Schubert 1668c1d255d3SCy Schubert if (auth->curve != curve) { 1669c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1670c1d255d3SCy Schubert "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", 1671c1d255d3SCy Schubert auth->curve->name, curve->name); 1672c1d255d3SCy Schubert goto fail; 1673c1d255d3SCy Schubert } 1674c1d255d3SCy Schubert 1675c1d255d3SCy Schubert auth->own_protocol_key = dpp_gen_keypair(curve); 1676c1d255d3SCy Schubert if (!auth->own_protocol_key) 1677c1d255d3SCy Schubert goto fail; 1678c1d255d3SCy Schubert 1679c1d255d3SCy Schubert if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) { 1680c1d255d3SCy Schubert wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce"); 1681c1d255d3SCy Schubert goto fail; 1682c1d255d3SCy Schubert } 1683c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce", 1684c1d255d3SCy Schubert auth->e_nonce, auth->curve->nonce_len); 1685c1d255d3SCy Schubert 1686c1d255d3SCy Schubert /* M = { cR + pR } * CI */ 1687*266f97b5SCy Schubert ec = crypto_ec_init(curve->ike_group); 1688*266f97b5SCy Schubert if (!ec) 1689c1d255d3SCy Schubert goto fail; 1690*266f97b5SCy Schubert 1691*266f97b5SCy Schubert sum = crypto_bignum_init(); 1692*266f97b5SCy Schubert q = crypto_ec_get_order(ec); 1693*266f97b5SCy Schubert M = crypto_ec_point_init(ec); 1694*266f97b5SCy Schubert cR = crypto_ec_key_get_private_key(own_key); 1695*266f97b5SCy Schubert pR = crypto_ec_key_get_private_key(auth->own_protocol_key); 1696*266f97b5SCy Schubert CI = crypto_ec_key_get_public_key(peer_key); 1697*266f97b5SCy Schubert if (!sum || !q || !M || !cR || !pR || !CI || 1698*266f97b5SCy Schubert crypto_bignum_addmod(cR, pR, q, sum) || 1699*266f97b5SCy Schubert crypto_ec_point_mul(ec, CI, sum, M) || 1700*266f97b5SCy Schubert crypto_ec_point_to_bin(ec, M, Mx, NULL)) { 1701*266f97b5SCy Schubert wpa_printf(MSG_ERROR, "DPP: Error during M computation"); 1702c1d255d3SCy Schubert goto fail; 1703c1d255d3SCy Schubert } 1704c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); 1705c1d255d3SCy Schubert 1706c1d255d3SCy Schubert /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ 1707c1d255d3SCy Schubert 1708c1d255d3SCy Schubert /* HKDF-Extract(C-nonce | E-nonce, M.x) */ 1709c1d255d3SCy Schubert os_memcpy(nonces, auth->c_nonce, curve->nonce_len); 1710c1d255d3SCy Schubert os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); 1711c1d255d3SCy Schubert if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, 1712c1d255d3SCy Schubert Mx, curve->prime_len, prk) < 0) 1713c1d255d3SCy Schubert goto fail; 1714c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); 1715c1d255d3SCy Schubert 1716c1d255d3SCy Schubert /* HKDF-Expand(PRK, "dpp reconfig key", L) */ 1717c1d255d3SCy Schubert if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, 1718c1d255d3SCy Schubert "dpp reconfig key", auth->ke, curve->hash_len) < 0) 1719c1d255d3SCy Schubert goto fail; 1720c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 1721c1d255d3SCy Schubert "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", 1722c1d255d3SCy Schubert auth->ke, curve->hash_len); 1723c1d255d3SCy Schubert 1724c1d255d3SCy Schubert res = 0; 1725*266f97b5SCy Schubert crypto_ec_key_deinit(auth->reconfig_old_protocol_key); 1726c1d255d3SCy Schubert auth->reconfig_old_protocol_key = own_key; 1727c1d255d3SCy Schubert own_key = NULL; 1728c1d255d3SCy Schubert fail: 1729c1d255d3SCy Schubert forced_memzero(prk, sizeof(prk)); 1730c1d255d3SCy Schubert forced_memzero(Mx, sizeof(Mx)); 1731*266f97b5SCy Schubert crypto_ec_point_deinit(M, 1); 1732*266f97b5SCy Schubert crypto_bignum_deinit(sum, 1); 1733*266f97b5SCy Schubert crypto_ec_key_deinit(own_key); 1734*266f97b5SCy Schubert crypto_ec_key_deinit(peer_key); 1735*266f97b5SCy Schubert crypto_ec_deinit(ec); 1736c1d255d3SCy Schubert return res; 1737c1d255d3SCy Schubert } 1738c1d255d3SCy Schubert 1739c1d255d3SCy Schubert 1740c1d255d3SCy Schubert int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, 1741c1d255d3SCy Schubert const u8 *r_proto, u16 r_proto_len, 1742c1d255d3SCy Schubert struct json_token *net_access_key) 1743c1d255d3SCy Schubert { 1744*266f97b5SCy Schubert struct crypto_ec_key *pr = NULL, *peer_key = NULL; 1745*266f97b5SCy Schubert const struct crypto_ec_point *CR, *PR; 1746*266f97b5SCy Schubert const struct crypto_bignum *cI; 1747*266f97b5SCy Schubert struct crypto_ec *ec = NULL; 1748*266f97b5SCy Schubert struct crypto_ec_point *sum = NULL, *M = NULL; 1749c1d255d3SCy Schubert u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; 1750c1d255d3SCy Schubert u8 prk[DPP_MAX_HASH_LEN]; 1751c1d255d3SCy Schubert int res = -1; 1752c1d255d3SCy Schubert const struct dpp_curve_params *curve; 1753c1d255d3SCy Schubert u8 nonces[2 * DPP_MAX_NONCE_LEN]; 1754c1d255d3SCy Schubert 1755c1d255d3SCy Schubert pr = dpp_set_pubkey_point(auth->conf->connector_key, 1756c1d255d3SCy Schubert r_proto, r_proto_len); 1757c1d255d3SCy Schubert if (!pr) { 1758c1d255d3SCy Schubert dpp_auth_fail(auth, "Invalid Responder Protocol Key"); 1759c1d255d3SCy Schubert goto fail; 1760c1d255d3SCy Schubert } 1761c1d255d3SCy Schubert dpp_debug_print_key("Peer (Responder) Protocol Key", pr); 1762*266f97b5SCy Schubert crypto_ec_key_deinit(auth->peer_protocol_key); 1763c1d255d3SCy Schubert auth->peer_protocol_key = pr; 1764c1d255d3SCy Schubert pr = NULL; 1765c1d255d3SCy Schubert 1766c1d255d3SCy Schubert peer_key = dpp_parse_jwk(net_access_key, &curve); 1767c1d255d3SCy Schubert if (!peer_key) 1768c1d255d3SCy Schubert goto fail; 1769c1d255d3SCy Schubert dpp_debug_print_key("DPP: Received netAccessKey", peer_key); 1770c1d255d3SCy Schubert if (auth->curve != curve) { 1771c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1772c1d255d3SCy Schubert "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", 1773c1d255d3SCy Schubert auth->curve->name, curve->name); 1774c1d255d3SCy Schubert goto fail; 1775c1d255d3SCy Schubert } 1776c1d255d3SCy Schubert 1777c1d255d3SCy Schubert /* M = cI * { CR + PR } */ 1778*266f97b5SCy Schubert ec = crypto_ec_init(curve->ike_group); 1779*266f97b5SCy Schubert if (!ec) 1780c1d255d3SCy Schubert goto fail; 1781c1d255d3SCy Schubert 1782*266f97b5SCy Schubert cI = crypto_ec_key_get_private_key(auth->conf->connector_key); 1783*266f97b5SCy Schubert sum = crypto_ec_point_init(ec); 1784*266f97b5SCy Schubert M = crypto_ec_point_init(ec); 1785*266f97b5SCy Schubert CR = crypto_ec_key_get_public_key(peer_key); 1786*266f97b5SCy Schubert PR = crypto_ec_key_get_public_key(auth->peer_protocol_key); 1787*266f97b5SCy Schubert if (!cI || !sum || !M || !CR || !PR || 1788*266f97b5SCy Schubert crypto_ec_point_add(ec, CR, PR, sum) || 1789*266f97b5SCy Schubert crypto_ec_point_mul(ec, sum, cI, M) || 1790*266f97b5SCy Schubert crypto_ec_point_to_bin(ec, M, Mx, NULL)) { 1791*266f97b5SCy Schubert wpa_printf(MSG_ERROR, "DPP: Error during M computation"); 1792*266f97b5SCy Schubert goto fail; 1793*266f97b5SCy Schubert } 1794*266f97b5SCy Schubert 1795c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); 1796c1d255d3SCy Schubert 1797c1d255d3SCy Schubert /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ 1798c1d255d3SCy Schubert 1799c1d255d3SCy Schubert /* HKDF-Extract(C-nonce | E-nonce, M.x) */ 1800c1d255d3SCy Schubert os_memcpy(nonces, auth->c_nonce, curve->nonce_len); 1801c1d255d3SCy Schubert os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); 1802c1d255d3SCy Schubert if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, 1803c1d255d3SCy Schubert Mx, curve->prime_len, prk) < 0) 1804c1d255d3SCy Schubert goto fail; 1805c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); 1806c1d255d3SCy Schubert 1807c1d255d3SCy Schubert /* HKDF-Expand(PRK, "dpp reconfig key", L) */ 1808c1d255d3SCy Schubert if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, 1809c1d255d3SCy Schubert "dpp reconfig key", auth->ke, curve->hash_len) < 0) 1810c1d255d3SCy Schubert goto fail; 1811c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 1812c1d255d3SCy Schubert "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", 1813c1d255d3SCy Schubert auth->ke, curve->hash_len); 1814c1d255d3SCy Schubert 1815c1d255d3SCy Schubert res = 0; 1816c1d255d3SCy Schubert fail: 1817c1d255d3SCy Schubert forced_memzero(prk, sizeof(prk)); 1818c1d255d3SCy Schubert forced_memzero(Mx, sizeof(Mx)); 1819*266f97b5SCy Schubert crypto_ec_key_deinit(pr); 1820*266f97b5SCy Schubert crypto_ec_key_deinit(peer_key); 1821*266f97b5SCy Schubert crypto_ec_point_deinit(sum, 1); 1822*266f97b5SCy Schubert crypto_ec_point_deinit(M, 1); 1823*266f97b5SCy Schubert crypto_ec_deinit(ec); 1824c1d255d3SCy Schubert return res; 1825c1d255d3SCy Schubert } 1826c1d255d3SCy Schubert 1827c1d255d3SCy Schubert 1828c1d255d3SCy Schubert static char * 1829c1d255d3SCy Schubert dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len) 1830c1d255d3SCy Schubert { 1831c1d255d3SCy Schubert struct wpabuf *jws_prot_hdr; 1832c1d255d3SCy Schubert char *signed1; 1833c1d255d3SCy Schubert 1834c1d255d3SCy Schubert jws_prot_hdr = wpabuf_alloc(100); 1835c1d255d3SCy Schubert if (!jws_prot_hdr) 1836c1d255d3SCy Schubert return NULL; 1837c1d255d3SCy Schubert json_start_object(jws_prot_hdr, NULL); 1838c1d255d3SCy Schubert json_add_string(jws_prot_hdr, "typ", "dppCon"); 1839c1d255d3SCy Schubert json_value_sep(jws_prot_hdr); 1840c1d255d3SCy Schubert json_add_string(jws_prot_hdr, "kid", conf->kid); 1841c1d255d3SCy Schubert json_value_sep(jws_prot_hdr); 1842c1d255d3SCy Schubert json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg); 1843c1d255d3SCy Schubert json_end_object(jws_prot_hdr); 1844c1d255d3SCy Schubert signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr), 1845c1d255d3SCy Schubert wpabuf_len(jws_prot_hdr), 1846c1d255d3SCy Schubert signed1_len); 1847c1d255d3SCy Schubert wpabuf_free(jws_prot_hdr); 1848c1d255d3SCy Schubert return signed1; 1849c1d255d3SCy Schubert } 1850c1d255d3SCy Schubert 1851c1d255d3SCy Schubert 1852c1d255d3SCy Schubert static char * 1853c1d255d3SCy Schubert dpp_build_conn_signature(struct dpp_configurator *conf, 1854c1d255d3SCy Schubert const char *signed1, size_t signed1_len, 1855c1d255d3SCy Schubert const char *signed2, size_t signed2_len, 1856c1d255d3SCy Schubert size_t *signed3_len) 1857c1d255d3SCy Schubert { 1858c1d255d3SCy Schubert const struct dpp_curve_params *curve; 1859*266f97b5SCy Schubert struct wpabuf *sig = NULL; 1860c1d255d3SCy Schubert char *signed3 = NULL; 1861c1d255d3SCy Schubert char *dot = "."; 1862*266f97b5SCy Schubert const u8 *vector[3]; 1863*266f97b5SCy Schubert size_t vector_len[3]; 1864*266f97b5SCy Schubert u8 *hash; 1865*266f97b5SCy Schubert int ret; 1866*266f97b5SCy Schubert 1867*266f97b5SCy Schubert vector[0] = (const u8 *) signed1; 1868*266f97b5SCy Schubert vector[1] = (const u8 *) dot; 1869*266f97b5SCy Schubert vector[2] = (const u8 *) signed2; 1870*266f97b5SCy Schubert vector_len[0] = signed1_len; 1871*266f97b5SCy Schubert vector_len[1] = 1; 1872*266f97b5SCy Schubert vector_len[2] = signed2_len; 1873c1d255d3SCy Schubert 1874c1d255d3SCy Schubert curve = conf->curve; 1875*266f97b5SCy Schubert hash = os_malloc(curve->hash_len); 1876*266f97b5SCy Schubert if (!hash) 1877*266f97b5SCy Schubert goto fail; 1878c1d255d3SCy Schubert if (curve->hash_len == SHA256_MAC_LEN) { 1879*266f97b5SCy Schubert ret = sha256_vector(3, vector, vector_len, hash); 1880c1d255d3SCy Schubert } else if (curve->hash_len == SHA384_MAC_LEN) { 1881*266f97b5SCy Schubert ret = sha384_vector(3, vector, vector_len, hash); 1882c1d255d3SCy Schubert } else if (curve->hash_len == SHA512_MAC_LEN) { 1883*266f97b5SCy Schubert ret = sha512_vector(3, vector, vector_len, hash); 1884c1d255d3SCy Schubert } else { 1885c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); 1886c1d255d3SCy Schubert goto fail; 1887c1d255d3SCy Schubert } 1888*266f97b5SCy Schubert if (ret) { 1889*266f97b5SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Hash computation failed"); 1890*266f97b5SCy Schubert goto fail; 1891*266f97b5SCy Schubert } 1892*266f97b5SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Hash value for Connector signature", 1893*266f97b5SCy Schubert hash, curve->hash_len); 1894c1d255d3SCy Schubert 1895*266f97b5SCy Schubert sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len); 1896*266f97b5SCy Schubert if (!sig) { 1897*266f97b5SCy Schubert wpa_printf(MSG_ERROR, "DPP: Signature computation failed"); 1898c1d255d3SCy Schubert goto fail; 1899*266f97b5SCy Schubert } 1900c1d255d3SCy Schubert 1901c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)", 1902*266f97b5SCy Schubert wpabuf_head(sig), wpabuf_len(sig)); 1903*266f97b5SCy Schubert signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig), 1904*266f97b5SCy Schubert signed3_len); 1905*266f97b5SCy Schubert 1906c1d255d3SCy Schubert fail: 1907*266f97b5SCy Schubert os_free(hash); 1908*266f97b5SCy Schubert wpabuf_free(sig); 1909c1d255d3SCy Schubert return signed3; 1910c1d255d3SCy Schubert } 1911c1d255d3SCy Schubert 1912c1d255d3SCy Schubert char * dpp_sign_connector(struct dpp_configurator *conf, 1913c1d255d3SCy Schubert const struct wpabuf *dppcon) 1914c1d255d3SCy Schubert { 1915c1d255d3SCy Schubert char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL; 1916c1d255d3SCy Schubert char *signed_conn = NULL, *pos; 1917c1d255d3SCy Schubert size_t signed1_len, signed2_len, signed3_len; 1918c1d255d3SCy Schubert 1919c1d255d3SCy Schubert signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len); 1920c1d255d3SCy Schubert signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon), 1921c1d255d3SCy Schubert &signed2_len); 1922c1d255d3SCy Schubert if (!signed1 || !signed2) 1923c1d255d3SCy Schubert goto fail; 1924c1d255d3SCy Schubert 1925c1d255d3SCy Schubert signed3 = dpp_build_conn_signature(conf, signed1, signed1_len, 1926c1d255d3SCy Schubert signed2, signed2_len, &signed3_len); 1927c1d255d3SCy Schubert if (!signed3) 1928c1d255d3SCy Schubert goto fail; 1929c1d255d3SCy Schubert 1930c1d255d3SCy Schubert signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3); 1931c1d255d3SCy Schubert if (!signed_conn) 1932c1d255d3SCy Schubert goto fail; 1933c1d255d3SCy Schubert pos = signed_conn; 1934c1d255d3SCy Schubert os_memcpy(pos, signed1, signed1_len); 1935c1d255d3SCy Schubert pos += signed1_len; 1936c1d255d3SCy Schubert *pos++ = '.'; 1937c1d255d3SCy Schubert os_memcpy(pos, signed2, signed2_len); 1938c1d255d3SCy Schubert pos += signed2_len; 1939c1d255d3SCy Schubert *pos++ = '.'; 1940c1d255d3SCy Schubert os_memcpy(pos, signed3, signed3_len); 1941c1d255d3SCy Schubert pos += signed3_len; 1942c1d255d3SCy Schubert *pos = '\0'; 1943c1d255d3SCy Schubert 1944c1d255d3SCy Schubert fail: 1945c1d255d3SCy Schubert os_free(signed1); 1946c1d255d3SCy Schubert os_free(signed2); 1947c1d255d3SCy Schubert os_free(signed3); 1948c1d255d3SCy Schubert return signed_conn; 1949c1d255d3SCy Schubert } 1950c1d255d3SCy Schubert 1951c1d255d3SCy Schubert 1952c1d255d3SCy Schubert #ifdef CONFIG_DPP2 1953c1d255d3SCy Schubert 1954c1d255d3SCy Schubert struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, 1955c1d255d3SCy Schubert size_t net_access_key_len) 1956c1d255d3SCy Schubert { 1957c1d255d3SCy Schubert struct wpabuf *pub = NULL; 1958*266f97b5SCy Schubert struct crypto_ec_key *own_key; 1959c1d255d3SCy Schubert struct dpp_pfs *pfs; 1960c1d255d3SCy Schubert 1961c1d255d3SCy Schubert pfs = os_zalloc(sizeof(*pfs)); 1962c1d255d3SCy Schubert if (!pfs) 1963c1d255d3SCy Schubert return NULL; 1964c1d255d3SCy Schubert 1965c1d255d3SCy Schubert own_key = dpp_set_keypair(&pfs->curve, net_access_key, 1966c1d255d3SCy Schubert net_access_key_len); 1967c1d255d3SCy Schubert if (!own_key) { 1968c1d255d3SCy Schubert wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); 1969c1d255d3SCy Schubert goto fail; 1970c1d255d3SCy Schubert } 1971*266f97b5SCy Schubert crypto_ec_key_deinit(own_key); 1972c1d255d3SCy Schubert 1973c1d255d3SCy Schubert pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group); 1974c1d255d3SCy Schubert if (!pfs->ecdh) 1975c1d255d3SCy Schubert goto fail; 1976c1d255d3SCy Schubert 1977c1d255d3SCy Schubert pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0); 1978c1d255d3SCy Schubert pub = wpabuf_zeropad(pub, pfs->curve->prime_len); 1979c1d255d3SCy Schubert if (!pub) 1980c1d255d3SCy Schubert goto fail; 1981c1d255d3SCy Schubert 1982c1d255d3SCy Schubert pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub)); 1983c1d255d3SCy Schubert if (!pfs->ie) 1984c1d255d3SCy Schubert goto fail; 1985c1d255d3SCy Schubert wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION); 1986c1d255d3SCy Schubert wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub)); 1987c1d255d3SCy Schubert wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM); 1988c1d255d3SCy Schubert wpabuf_put_le16(pfs->ie, pfs->curve->ike_group); 1989c1d255d3SCy Schubert wpabuf_put_buf(pfs->ie, pub); 1990c1d255d3SCy Schubert wpabuf_free(pub); 1991c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element", 1992c1d255d3SCy Schubert pfs->ie); 1993c1d255d3SCy Schubert 1994c1d255d3SCy Schubert return pfs; 1995c1d255d3SCy Schubert fail: 1996c1d255d3SCy Schubert wpabuf_free(pub); 1997c1d255d3SCy Schubert dpp_pfs_free(pfs); 1998c1d255d3SCy Schubert return NULL; 1999c1d255d3SCy Schubert } 2000c1d255d3SCy Schubert 2001c1d255d3SCy Schubert 2002c1d255d3SCy Schubert int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len) 2003c1d255d3SCy Schubert { 2004c1d255d3SCy Schubert if (peer_ie_len < 2) 2005c1d255d3SCy Schubert return -1; 2006c1d255d3SCy Schubert if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) { 2007c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS"); 2008c1d255d3SCy Schubert return -1; 2009c1d255d3SCy Schubert } 2010c1d255d3SCy Schubert 2011c1d255d3SCy Schubert pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2, 2012c1d255d3SCy Schubert peer_ie_len - 2); 2013c1d255d3SCy Schubert pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len); 2014c1d255d3SCy Schubert if (!pfs->secret) { 2015c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key"); 2016c1d255d3SCy Schubert return -1; 2017c1d255d3SCy Schubert } 2018c1d255d3SCy Schubert wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret); 2019c1d255d3SCy Schubert return 0; 2020c1d255d3SCy Schubert } 2021c1d255d3SCy Schubert 2022c1d255d3SCy Schubert 2023c1d255d3SCy Schubert void dpp_pfs_free(struct dpp_pfs *pfs) 2024c1d255d3SCy Schubert { 2025c1d255d3SCy Schubert if (!pfs) 2026c1d255d3SCy Schubert return; 2027c1d255d3SCy Schubert crypto_ecdh_deinit(pfs->ecdh); 2028c1d255d3SCy Schubert wpabuf_free(pfs->ie); 2029c1d255d3SCy Schubert wpabuf_clear_free(pfs->secret); 2030c1d255d3SCy Schubert os_free(pfs); 2031c1d255d3SCy Schubert } 2032c1d255d3SCy Schubert 2033c1d255d3SCy Schubert 2034c1d255d3SCy Schubert struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name) 2035c1d255d3SCy Schubert { 2036*266f97b5SCy Schubert struct crypto_csr *csr = NULL; 2037c1d255d3SCy Schubert struct wpabuf *buf = NULL; 2038*266f97b5SCy Schubert struct crypto_ec_key *key; 2039c1d255d3SCy Schubert unsigned int hash_len = auth->curve->hash_len; 2040*266f97b5SCy Schubert struct wpabuf *priv_key; 2041c1d255d3SCy Schubert u8 cp[DPP_CP_LEN]; 2042*266f97b5SCy Schubert char *password = NULL; 2043c1d255d3SCy Schubert size_t password_len; 2044*266f97b5SCy Schubert int hash_sign_algo; 2045c1d255d3SCy Schubert 2046c1d255d3SCy Schubert /* TODO: use auth->csrattrs */ 2047c1d255d3SCy Schubert 2048c1d255d3SCy Schubert /* TODO: support generation of a new private key if csrAttrs requests 2049c1d255d3SCy Schubert * a specific group to be used */ 2050c1d255d3SCy Schubert key = auth->own_protocol_key; 2051c1d255d3SCy Schubert 2052*266f97b5SCy Schubert priv_key = crypto_ec_key_get_ecprivate_key(key, true); 2053*266f97b5SCy Schubert if (!priv_key) 2054c1d255d3SCy Schubert goto fail; 2055c1d255d3SCy Schubert wpabuf_free(auth->priv_key); 2056*266f97b5SCy Schubert auth->priv_key = priv_key; 2057*266f97b5SCy Schubert 2058*266f97b5SCy Schubert csr = crypto_csr_init(); 2059*266f97b5SCy Schubert if (!csr || crypto_csr_set_ec_public_key(csr, key)) 2060c1d255d3SCy Schubert goto fail; 2061c1d255d3SCy Schubert 2062*266f97b5SCy Schubert if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name)) 2063c1d255d3SCy Schubert goto fail; 2064c1d255d3SCy Schubert 2065c1d255d3SCy Schubert /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ 2066c1d255d3SCy Schubert if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, 2067c1d255d3SCy Schubert "CSR challengePassword", cp, DPP_CP_LEN) < 0) 2068c1d255d3SCy Schubert goto fail; 2069c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 2070c1d255d3SCy Schubert "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", 2071c1d255d3SCy Schubert cp, DPP_CP_LEN); 2072c1d255d3SCy Schubert password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len); 2073c1d255d3SCy Schubert forced_memzero(cp, DPP_CP_LEN); 2074*266f97b5SCy Schubert if (!password || 2075*266f97b5SCy Schubert crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD, 2076*266f97b5SCy Schubert ASN1_TAG_UTF8STRING, (const u8 *) password, 2077*266f97b5SCy Schubert password_len)) 2078c1d255d3SCy Schubert goto fail; 2079c1d255d3SCy Schubert 2080c1d255d3SCy Schubert /* TODO: hash func selection based on csrAttrs */ 2081c1d255d3SCy Schubert if (hash_len == SHA256_MAC_LEN) { 2082*266f97b5SCy Schubert hash_sign_algo = CRYPTO_HASH_ALG_SHA256; 2083c1d255d3SCy Schubert } else if (hash_len == SHA384_MAC_LEN) { 2084*266f97b5SCy Schubert hash_sign_algo = CRYPTO_HASH_ALG_SHA384; 2085c1d255d3SCy Schubert } else if (hash_len == SHA512_MAC_LEN) { 2086*266f97b5SCy Schubert hash_sign_algo = CRYPTO_HASH_ALG_SHA512; 2087c1d255d3SCy Schubert } else { 2088c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); 2089c1d255d3SCy Schubert goto fail; 2090c1d255d3SCy Schubert } 2091c1d255d3SCy Schubert 2092*266f97b5SCy Schubert buf = crypto_csr_sign(csr, key, hash_sign_algo); 2093*266f97b5SCy Schubert if (!buf) 2094c1d255d3SCy Schubert goto fail; 2095c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf); 2096c1d255d3SCy Schubert 2097c1d255d3SCy Schubert fail: 2098*266f97b5SCy Schubert bin_clear_free(password, password_len); 2099*266f97b5SCy Schubert crypto_csr_deinit(csr); 2100c1d255d3SCy Schubert return buf; 2101c1d255d3SCy Schubert } 2102c1d255d3SCy Schubert 2103c1d255d3SCy Schubert 2104*266f97b5SCy Schubert int dpp_validate_csr(struct dpp_authentication *auth, 2105*266f97b5SCy Schubert const struct wpabuf *csrbuf) 2106c1d255d3SCy Schubert { 2107*266f97b5SCy Schubert struct crypto_csr *csr; 2108*266f97b5SCy Schubert const u8 *attr; 2109*266f97b5SCy Schubert size_t attr_len; 2110*266f97b5SCy Schubert int attr_type; 2111c1d255d3SCy Schubert unsigned char *cp = NULL; 2112c1d255d3SCy Schubert size_t cp_len; 2113c1d255d3SCy Schubert u8 exp_cp[DPP_CP_LEN]; 2114c1d255d3SCy Schubert unsigned int hash_len = auth->curve->hash_len; 2115*266f97b5SCy Schubert int ret = -1; 2116c1d255d3SCy Schubert 2117*266f97b5SCy Schubert csr = crypto_csr_verify(csrbuf); 2118*266f97b5SCy Schubert if (!csr) { 2119c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2120*266f97b5SCy Schubert "DPP: CSR invalid or invalid signature"); 2121c1d255d3SCy Schubert goto fail; 2122c1d255d3SCy Schubert } 2123c1d255d3SCy Schubert 2124*266f97b5SCy Schubert attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD, 2125*266f97b5SCy Schubert &attr_len, &attr_type); 2126*266f97b5SCy Schubert if (!attr) { 2127c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2128c1d255d3SCy Schubert "DPP: CSR does not include challengePassword"); 2129c1d255d3SCy Schubert goto fail; 2130c1d255d3SCy Schubert } 2131c1d255d3SCy Schubert /* This is supposed to be UTF8String, but allow other strings as well 2132c1d255d3SCy Schubert * since challengePassword is using ASCII (base64 encoded). */ 2133*266f97b5SCy Schubert if (attr_type != ASN1_TAG_UTF8STRING && 2134*266f97b5SCy Schubert attr_type != ASN1_TAG_PRINTABLESTRING && 2135*266f97b5SCy Schubert attr_type != ASN1_TAG_IA5STRING) { 2136c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2137c1d255d3SCy Schubert "DPP: Unexpected challengePassword attribute type %d", 2138*266f97b5SCy Schubert attr_type); 2139c1d255d3SCy Schubert goto fail; 2140c1d255d3SCy Schubert } 2141c1d255d3SCy Schubert 2142*266f97b5SCy Schubert cp = base64_decode((const char *) attr, attr_len, &cp_len); 2143c1d255d3SCy Schubert if (!cp) { 2144c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2145c1d255d3SCy Schubert "DPP: Could not base64 decode challengePassword"); 2146c1d255d3SCy Schubert goto fail; 2147c1d255d3SCy Schubert } 2148c1d255d3SCy Schubert if (cp_len != DPP_CP_LEN) { 2149c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2150c1d255d3SCy Schubert "DPP: Unexpected cp length (%zu) in CSR challengePassword", 2151c1d255d3SCy Schubert cp_len); 2152c1d255d3SCy Schubert goto fail; 2153c1d255d3SCy Schubert } 2154c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword", 2155c1d255d3SCy Schubert cp, cp_len); 2156c1d255d3SCy Schubert 2157c1d255d3SCy Schubert /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ 2158c1d255d3SCy Schubert if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, 2159c1d255d3SCy Schubert "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0) 2160c1d255d3SCy Schubert goto fail; 2161c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 2162c1d255d3SCy Schubert "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", 2163c1d255d3SCy Schubert exp_cp, DPP_CP_LEN); 2164c1d255d3SCy Schubert if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) { 2165c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2166c1d255d3SCy Schubert "DPP: CSR challengePassword does not match calculated cp"); 2167c1d255d3SCy Schubert goto fail; 2168c1d255d3SCy Schubert } 2169c1d255d3SCy Schubert 2170c1d255d3SCy Schubert ret = 0; 2171c1d255d3SCy Schubert fail: 2172c1d255d3SCy Schubert os_free(cp); 2173*266f97b5SCy Schubert crypto_csr_deinit(csr); 2174c1d255d3SCy Schubert return ret; 2175c1d255d3SCy Schubert } 2176c1d255d3SCy Schubert 2177c1d255d3SCy Schubert 2178c1d255d3SCy Schubert struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, 2179c1d255d3SCy Schubert size_t csign_key_len, 2180c1d255d3SCy Schubert const u8 *pp_key, 2181c1d255d3SCy Schubert size_t pp_key_len) 2182c1d255d3SCy Schubert { 2183*266f97b5SCy Schubert struct crypto_ec_key *csign = NULL, *ppkey = NULL; 2184c1d255d3SCy Schubert struct dpp_reconfig_id *id = NULL; 2185*266f97b5SCy Schubert struct crypto_ec *ec = NULL; 2186*266f97b5SCy Schubert const struct crypto_bignum *q; 2187*266f97b5SCy Schubert struct crypto_bignum *bn = NULL; 2188*266f97b5SCy Schubert struct crypto_ec_point *e_id = NULL; 2189*266f97b5SCy Schubert const struct crypto_ec_point *generator; 2190c1d255d3SCy Schubert 2191*266f97b5SCy Schubert csign = crypto_ec_key_parse_pub(csign_key, csign_key_len); 2192c1d255d3SCy Schubert if (!csign) 2193c1d255d3SCy Schubert goto fail; 2194c1d255d3SCy Schubert 2195c1d255d3SCy Schubert if (!pp_key) 2196c1d255d3SCy Schubert goto fail; 2197*266f97b5SCy Schubert ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len); 2198c1d255d3SCy Schubert if (!ppkey) 2199c1d255d3SCy Schubert goto fail; 2200c1d255d3SCy Schubert 2201*266f97b5SCy Schubert ec = crypto_ec_init(crypto_ec_key_group(csign)); 2202*266f97b5SCy Schubert if (!ec) 2203c1d255d3SCy Schubert goto fail; 2204c1d255d3SCy Schubert 2205*266f97b5SCy Schubert e_id = crypto_ec_point_init(ec); 2206*266f97b5SCy Schubert bn = crypto_bignum_init(); 2207*266f97b5SCy Schubert q = crypto_ec_get_order(ec); 2208*266f97b5SCy Schubert generator = crypto_ec_get_generator(ec); 2209*266f97b5SCy Schubert if (!e_id || !bn || !q || !generator || 2210*266f97b5SCy Schubert crypto_bignum_rand(bn, q) || 2211*266f97b5SCy Schubert crypto_ec_point_mul(ec, generator, bn, e_id)) 2212c1d255d3SCy Schubert goto fail; 2213c1d255d3SCy Schubert 2214*266f97b5SCy Schubert crypto_ec_point_debug_print(ec, e_id, 2215*266f97b5SCy Schubert "DPP: Generated random point E-id"); 2216c1d255d3SCy Schubert 2217c1d255d3SCy Schubert id = os_zalloc(sizeof(*id)); 2218c1d255d3SCy Schubert if (!id) 2219c1d255d3SCy Schubert goto fail; 2220*266f97b5SCy Schubert 2221*266f97b5SCy Schubert id->ec = ec; 2222*266f97b5SCy Schubert ec = NULL; 2223c1d255d3SCy Schubert id->e_id = e_id; 2224c1d255d3SCy Schubert e_id = NULL; 2225c1d255d3SCy Schubert id->csign = csign; 2226c1d255d3SCy Schubert csign = NULL; 2227c1d255d3SCy Schubert id->pp_key = ppkey; 2228c1d255d3SCy Schubert ppkey = NULL; 2229c1d255d3SCy Schubert fail: 2230*266f97b5SCy Schubert crypto_ec_point_deinit(e_id, 1); 2231*266f97b5SCy Schubert crypto_ec_key_deinit(csign); 2232*266f97b5SCy Schubert crypto_ec_key_deinit(ppkey); 2233*266f97b5SCy Schubert crypto_bignum_deinit(bn, 1); 2234*266f97b5SCy Schubert crypto_ec_deinit(ec); 2235c1d255d3SCy Schubert return id; 2236c1d255d3SCy Schubert } 2237c1d255d3SCy Schubert 2238c1d255d3SCy Schubert 2239c1d255d3SCy Schubert int dpp_update_reconfig_id(struct dpp_reconfig_id *id) 2240c1d255d3SCy Schubert { 2241*266f97b5SCy Schubert const struct crypto_bignum *q; 2242*266f97b5SCy Schubert struct crypto_bignum *bn; 2243*266f97b5SCy Schubert const struct crypto_ec_point *pp, *generator; 2244*266f97b5SCy Schubert struct crypto_ec_point *e_prime_id, *a_nonce; 2245c1d255d3SCy Schubert int ret = -1; 2246c1d255d3SCy Schubert 2247*266f97b5SCy Schubert pp = crypto_ec_key_get_public_key(id->pp_key); 2248*266f97b5SCy Schubert e_prime_id = crypto_ec_point_init(id->ec); 2249*266f97b5SCy Schubert a_nonce = crypto_ec_point_init(id->ec); 2250*266f97b5SCy Schubert bn = crypto_bignum_init(); 2251*266f97b5SCy Schubert q = crypto_ec_get_order(id->ec); 2252*266f97b5SCy Schubert generator = crypto_ec_get_generator(id->ec); 2253*266f97b5SCy Schubert 2254c1d255d3SCy Schubert /* Generate random 0 <= a-nonce < q 2255c1d255d3SCy Schubert * A-NONCE = a-nonce * G 2256c1d255d3SCy Schubert * E'-id = E-id + a-nonce * P_pk */ 2257*266f97b5SCy Schubert if (!pp || !e_prime_id || !a_nonce || !bn || !q || !generator || 2258*266f97b5SCy Schubert crypto_bignum_rand(bn, q) || /* bn = a-nonce */ 2259*266f97b5SCy Schubert crypto_ec_point_mul(id->ec, generator, bn, a_nonce) || 2260*266f97b5SCy Schubert crypto_ec_point_mul(id->ec, pp, bn, e_prime_id) || 2261*266f97b5SCy Schubert crypto_ec_point_add(id->ec, id->e_id, e_prime_id, e_prime_id)) 2262c1d255d3SCy Schubert goto fail; 2263c1d255d3SCy Schubert 2264*266f97b5SCy Schubert crypto_ec_point_debug_print(id->ec, a_nonce, 2265*266f97b5SCy Schubert "DPP: Generated A-NONCE"); 2266*266f97b5SCy Schubert crypto_ec_point_debug_print(id->ec, e_prime_id, 2267*266f97b5SCy Schubert "DPP: Encrypted E-id to E'-id"); 2268c1d255d3SCy Schubert 2269*266f97b5SCy Schubert crypto_ec_key_deinit(id->a_nonce); 2270*266f97b5SCy Schubert crypto_ec_key_deinit(id->e_prime_id); 2271*266f97b5SCy Schubert id->a_nonce = crypto_ec_key_set_pub_point(id->ec, a_nonce); 2272*266f97b5SCy Schubert id->e_prime_id = crypto_ec_key_set_pub_point(id->ec, e_prime_id); 2273c1d255d3SCy Schubert if (!id->a_nonce || !id->e_prime_id) 2274c1d255d3SCy Schubert goto fail; 2275c1d255d3SCy Schubert 2276c1d255d3SCy Schubert ret = 0; 2277c1d255d3SCy Schubert 2278c1d255d3SCy Schubert fail: 2279*266f97b5SCy Schubert crypto_ec_point_deinit(e_prime_id, 1); 2280*266f97b5SCy Schubert crypto_ec_point_deinit(a_nonce, 1); 2281*266f97b5SCy Schubert crypto_bignum_deinit(bn, 1); 2282c1d255d3SCy Schubert return ret; 2283c1d255d3SCy Schubert } 2284c1d255d3SCy Schubert 2285c1d255d3SCy Schubert 2286c1d255d3SCy Schubert void dpp_free_reconfig_id(struct dpp_reconfig_id *id) 2287c1d255d3SCy Schubert { 2288c1d255d3SCy Schubert if (id) { 2289*266f97b5SCy Schubert crypto_ec_point_deinit(id->e_id, 1); 2290*266f97b5SCy Schubert crypto_ec_key_deinit(id->csign); 2291*266f97b5SCy Schubert crypto_ec_key_deinit(id->a_nonce); 2292*266f97b5SCy Schubert crypto_ec_key_deinit(id->e_prime_id); 2293*266f97b5SCy Schubert crypto_ec_key_deinit(id->pp_key); 2294*266f97b5SCy Schubert crypto_ec_deinit(id->ec); 2295c1d255d3SCy Schubert os_free(id); 2296c1d255d3SCy Schubert } 2297c1d255d3SCy Schubert } 2298c1d255d3SCy Schubert 2299c1d255d3SCy Schubert 2300*266f97b5SCy Schubert struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey, 2301*266f97b5SCy Schubert struct crypto_ec_key *a_nonce, 2302*266f97b5SCy Schubert struct crypto_ec_key *e_prime_id) 2303c1d255d3SCy Schubert { 2304*266f97b5SCy Schubert struct crypto_ec *ec; 2305*266f97b5SCy Schubert const struct crypto_bignum *pp; 2306*266f97b5SCy Schubert struct crypto_ec_point *e_id = NULL; 2307*266f97b5SCy Schubert const struct crypto_ec_point *a_nonce_point, *e_prime_id_point; 2308c1d255d3SCy Schubert 2309c1d255d3SCy Schubert if (!ppkey) 2310c1d255d3SCy Schubert return NULL; 2311c1d255d3SCy Schubert 2312c1d255d3SCy Schubert /* E-id = E'-id - s_C * A-NONCE */ 2313*266f97b5SCy Schubert ec = crypto_ec_init(crypto_ec_key_group(ppkey)); 2314*266f97b5SCy Schubert if (!ec) 2315c1d255d3SCy Schubert return NULL; 2316*266f97b5SCy Schubert 2317*266f97b5SCy Schubert pp = crypto_ec_key_get_private_key(ppkey); 2318*266f97b5SCy Schubert a_nonce_point = crypto_ec_key_get_public_key(a_nonce); 2319*266f97b5SCy Schubert e_prime_id_point = crypto_ec_key_get_public_key(e_prime_id); 2320*266f97b5SCy Schubert e_id = crypto_ec_point_init(ec); 2321*266f97b5SCy Schubert if (!pp || !a_nonce_point || !e_prime_id_point || !e_id || 2322*266f97b5SCy Schubert crypto_ec_point_mul(ec, a_nonce_point, pp, e_id) || 2323*266f97b5SCy Schubert crypto_ec_point_invert(ec, e_id) || 2324*266f97b5SCy Schubert crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) { 2325*266f97b5SCy Schubert crypto_ec_point_deinit(e_id, 1); 2326c1d255d3SCy Schubert goto fail; 2327c1d255d3SCy Schubert } 2328c1d255d3SCy Schubert 2329*266f97b5SCy Schubert crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id"); 2330c1d255d3SCy Schubert 2331c1d255d3SCy Schubert fail: 2332*266f97b5SCy Schubert crypto_ec_deinit(ec); 2333c1d255d3SCy Schubert return e_id; 2334c1d255d3SCy Schubert } 2335c1d255d3SCy Schubert 2336c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 2337c1d255d3SCy Schubert 2338c1d255d3SCy Schubert 2339c1d255d3SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 2340c1d255d3SCy Schubert 2341c1d255d3SCy Schubert int dpp_test_gen_invalid_key(struct wpabuf *msg, 2342c1d255d3SCy Schubert const struct dpp_curve_params *curve) 2343c1d255d3SCy Schubert { 2344*266f97b5SCy Schubert struct crypto_ec *ec; 2345*266f97b5SCy Schubert struct crypto_ec_key *key = NULL; 2346*266f97b5SCy Schubert const struct crypto_ec_point *pub_key; 2347*266f97b5SCy Schubert struct crypto_ec_point *p = NULL; 2348*266f97b5SCy Schubert u8 *x, *y; 2349c1d255d3SCy Schubert int ret = -1; 2350c1d255d3SCy Schubert 2351*266f97b5SCy Schubert ec = crypto_ec_init(curve->ike_group); 2352*266f97b5SCy Schubert x = wpabuf_put(msg, curve->prime_len); 2353*266f97b5SCy Schubert y = wpabuf_put(msg, curve->prime_len); 2354*266f97b5SCy Schubert if (!ec) 2355c1d255d3SCy Schubert goto fail; 2356c1d255d3SCy Schubert 2357*266f97b5SCy Schubert retry: 2358*266f97b5SCy Schubert /* Generate valid key pair */ 2359*266f97b5SCy Schubert key = crypto_ec_key_gen(curve->ike_group); 2360*266f97b5SCy Schubert if (!key) 2361c1d255d3SCy Schubert goto fail; 2362c1d255d3SCy Schubert 2363*266f97b5SCy Schubert /* Retrieve public key coordinates */ 2364*266f97b5SCy Schubert pub_key = crypto_ec_key_get_public_key(key); 2365*266f97b5SCy Schubert if (!pub_key) 2366c1d255d3SCy Schubert goto fail; 2367c1d255d3SCy Schubert 2368*266f97b5SCy Schubert crypto_ec_point_to_bin(ec, pub_key, x, y); 2369*266f97b5SCy Schubert 2370*266f97b5SCy Schubert /* And corrupt them */ 2371*266f97b5SCy Schubert y[curve->prime_len - 1] ^= 0x01; 2372*266f97b5SCy Schubert p = crypto_ec_point_from_bin(ec, x); 2373*266f97b5SCy Schubert if (p && crypto_ec_point_is_on_curve(ec, p)) { 2374*266f97b5SCy Schubert crypto_ec_point_deinit(p, 0); 2375*266f97b5SCy Schubert p = NULL; 2376*266f97b5SCy Schubert goto retry; 2377c1d255d3SCy Schubert } 2378c1d255d3SCy Schubert 2379c1d255d3SCy Schubert ret = 0; 2380c1d255d3SCy Schubert fail: 2381*266f97b5SCy Schubert crypto_ec_point_deinit(p, 0); 2382*266f97b5SCy Schubert crypto_ec_key_deinit(key); 2383*266f97b5SCy Schubert crypto_ec_deinit(ec); 2384c1d255d3SCy Schubert return ret; 2385c1d255d3SCy Schubert } 2386c1d255d3SCy Schubert 2387c1d255d3SCy Schubert 2388c1d255d3SCy Schubert char * dpp_corrupt_connector_signature(const char *connector) 2389c1d255d3SCy Schubert { 2390c1d255d3SCy Schubert char *tmp, *pos, *signed3 = NULL; 2391c1d255d3SCy Schubert unsigned char *signature = NULL; 2392c1d255d3SCy Schubert size_t signature_len = 0, signed3_len; 2393c1d255d3SCy Schubert 2394c1d255d3SCy Schubert tmp = os_zalloc(os_strlen(connector) + 5); 2395c1d255d3SCy Schubert if (!tmp) 2396c1d255d3SCy Schubert goto fail; 2397c1d255d3SCy Schubert os_memcpy(tmp, connector, os_strlen(connector)); 2398c1d255d3SCy Schubert 2399c1d255d3SCy Schubert pos = os_strchr(tmp, '.'); 2400c1d255d3SCy Schubert if (!pos) 2401c1d255d3SCy Schubert goto fail; 2402c1d255d3SCy Schubert 2403c1d255d3SCy Schubert pos = os_strchr(pos + 1, '.'); 2404c1d255d3SCy Schubert if (!pos) 2405c1d255d3SCy Schubert goto fail; 2406c1d255d3SCy Schubert pos++; 2407c1d255d3SCy Schubert 2408c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s", 2409c1d255d3SCy Schubert pos); 2410c1d255d3SCy Schubert signature = base64_url_decode(pos, os_strlen(pos), &signature_len); 2411c1d255d3SCy Schubert if (!signature || signature_len == 0) 2412c1d255d3SCy Schubert goto fail; 2413c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature", 2414c1d255d3SCy Schubert signature, signature_len); 2415c1d255d3SCy Schubert signature[signature_len - 1] ^= 0x01; 2416c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature", 2417c1d255d3SCy Schubert signature, signature_len); 2418c1d255d3SCy Schubert signed3 = base64_url_encode(signature, signature_len, &signed3_len); 2419c1d255d3SCy Schubert if (!signed3) 2420c1d255d3SCy Schubert goto fail; 2421c1d255d3SCy Schubert os_memcpy(pos, signed3, signed3_len); 2422c1d255d3SCy Schubert pos[signed3_len] = '\0'; 2423c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s", 2424c1d255d3SCy Schubert pos); 2425c1d255d3SCy Schubert 2426c1d255d3SCy Schubert out: 2427c1d255d3SCy Schubert os_free(signature); 2428c1d255d3SCy Schubert os_free(signed3); 2429c1d255d3SCy Schubert return tmp; 2430c1d255d3SCy Schubert fail: 2431c1d255d3SCy Schubert os_free(tmp); 2432c1d255d3SCy Schubert tmp = NULL; 2433c1d255d3SCy Schubert goto out; 2434c1d255d3SCy Schubert } 2435c1d255d3SCy Schubert 2436c1d255d3SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 2437