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" 204b72b91aSCy 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 804b72b91aSCy Schubert void dpp_debug_print_key(const char *title, struct crypto_ec_key *key) 81c1d255d3SCy Schubert { 824b72b91aSCy Schubert struct wpabuf *der = NULL; 83c1d255d3SCy Schubert 844b72b91aSCy Schubert crypto_ec_key_debug_print(key, title); 85c1d255d3SCy Schubert 864b72b91aSCy Schubert der = crypto_ec_key_get_ecprivate_key(key, true); 874b72b91aSCy Schubert if (der) { 884b72b91aSCy Schubert wpa_hexdump_buf_key(MSG_DEBUG, "DPP: ECPrivateKey", der); 894b72b91aSCy Schubert } else { 904b72b91aSCy Schubert der = crypto_ec_key_get_subject_public_key(key); 914b72b91aSCy Schubert if (der) 924b72b91aSCy Schubert wpa_hexdump_buf_key(MSG_DEBUG, "DPP: EC_PUBKEY", der); 93c1d255d3SCy Schubert } 94c1d255d3SCy Schubert 954b72b91aSCy 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 2324b72b91aSCy Schubert struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, 2334b72b91aSCy Schubert const u8 *buf, size_t len) 234c1d255d3SCy Schubert { 2354b72b91aSCy Schubert int ike_group = crypto_ec_key_group(group_key); 236c1d255d3SCy Schubert 237c1d255d3SCy Schubert if (len & 1) 238c1d255d3SCy Schubert return NULL; 239c1d255d3SCy Schubert 2404b72b91aSCy Schubert if (ike_group < 0) { 2414b72b91aSCy Schubert wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); 242c1d255d3SCy Schubert return NULL; 243c1d255d3SCy Schubert } 244c1d255d3SCy Schubert 2454b72b91aSCy Schubert return crypto_ec_key_set_pub(ike_group, buf, buf + len / 2, len / 2); 246c1d255d3SCy Schubert } 247c1d255d3SCy Schubert 248c1d255d3SCy Schubert 2494b72b91aSCy Schubert struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve) 250c1d255d3SCy Schubert { 2514b72b91aSCy Schubert struct crypto_ec_key *key; 252c1d255d3SCy Schubert 253c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); 254c1d255d3SCy Schubert 2554b72b91aSCy Schubert key = crypto_ec_key_gen(curve->ike_group); 2564b72b91aSCy 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 2634b72b91aSCy 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 { 2664b72b91aSCy Schubert struct crypto_ec_key *key; 2674b72b91aSCy Schubert int group; 268c1d255d3SCy Schubert 2694b72b91aSCy Schubert key = crypto_ec_key_parse_priv(privkey, privkey_len); 2704b72b91aSCy Schubert if (!key) { 2714b72b91aSCy Schubert wpa_printf(MSG_INFO, "DPP: Failed to parse private key"); 272c1d255d3SCy Schubert return NULL; 273c1d255d3SCy Schubert } 2744b72b91aSCy Schubert 2754b72b91aSCy Schubert group = crypto_ec_key_group(key); 2764b72b91aSCy Schubert if (group < 0) { 2774b72b91aSCy Schubert crypto_ec_key_deinit(key); 278c1d255d3SCy Schubert return NULL; 279c1d255d3SCy Schubert } 2804b72b91aSCy Schubert 2814b72b91aSCy Schubert *curve = dpp_get_curve_ike_group(group); 282c1d255d3SCy Schubert if (!*curve) { 283c1d255d3SCy Schubert wpa_printf(MSG_INFO, 2844b72b91aSCy Schubert "DPP: Unsupported curve (group=%d) in pre-assigned key", 2854b72b91aSCy Schubert group); 2864b72b91aSCy Schubert crypto_ec_key_deinit(key); 287c1d255d3SCy Schubert return NULL; 288c1d255d3SCy Schubert } 289c1d255d3SCy Schubert 2904b72b91aSCy 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 2994b72b91aSCy 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 3344b72b91aSCy 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 4814b72b91aSCy Schubert int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer, 4824b72b91aSCy Schubert u8 *secret, size_t *secret_len) 483c1d255d3SCy Schubert { 4844b72b91aSCy Schubert struct crypto_ecdh *ecdh; 4854b72b91aSCy Schubert struct wpabuf *peer_pub, *secret_buf = NULL; 486c1d255d3SCy Schubert int ret = -1; 487c1d255d3SCy Schubert 488c1d255d3SCy Schubert *secret_len = 0; 489c1d255d3SCy Schubert 4904b72b91aSCy Schubert ecdh = crypto_ecdh_init2(crypto_ec_key_group(own), own); 4914b72b91aSCy Schubert if (!ecdh) { 4924b72b91aSCy Schubert wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_init2() failed"); 493c1d255d3SCy Schubert return -1; 494c1d255d3SCy Schubert } 495c1d255d3SCy Schubert 4964b72b91aSCy Schubert peer_pub = crypto_ec_key_get_pubkey_point(peer, 0); 4974b72b91aSCy Schubert if (!peer_pub) { 498c1d255d3SCy Schubert wpa_printf(MSG_ERROR, 4994b72b91aSCy Schubert "DPP: crypto_ec_key_get_pubkey_point() failed"); 500c1d255d3SCy Schubert goto fail; 501c1d255d3SCy Schubert } 502c1d255d3SCy Schubert 5034b72b91aSCy Schubert secret_buf = crypto_ecdh_set_peerkey(ecdh, 1, wpabuf_head(peer_pub), 5044b72b91aSCy Schubert wpabuf_len(peer_pub)); 5054b72b91aSCy Schubert if (!secret_buf) { 5064b72b91aSCy Schubert wpa_printf(MSG_ERROR, "DPP: crypto_ecdh_set_peerkey() failed"); 507c1d255d3SCy Schubert goto fail; 508c1d255d3SCy Schubert } 509c1d255d3SCy Schubert 5104b72b91aSCy Schubert if (wpabuf_len(secret_buf) > DPP_MAX_SHARED_SECRET_LEN) { 5114b72b91aSCy Schubert wpa_printf(MSG_ERROR, "DPP: ECDH secret longer than expected"); 512c1d255d3SCy Schubert goto fail; 513c1d255d3SCy Schubert } 514c1d255d3SCy Schubert 5154b72b91aSCy Schubert *secret_len = wpabuf_len(secret_buf); 5164b72b91aSCy Schubert os_memcpy(secret, wpabuf_head(secret_buf), wpabuf_len(secret_buf)); 517c1d255d3SCy Schubert ret = 0; 518c1d255d3SCy Schubert 519c1d255d3SCy Schubert fail: 5204b72b91aSCy Schubert wpabuf_clear_free(secret_buf); 5214b72b91aSCy Schubert wpabuf_free(peer_pub); 5224b72b91aSCy 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 { 5564b72b91aSCy 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 5634b72b91aSCy Schubert key = crypto_ec_key_parse_pub(data, data_len); 5644b72b91aSCy 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 5704b72b91aSCy Schubert bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(key)); 571db0ac6deSCy Schubert if (!bi->curve) { 572db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 5734b72b91aSCy Schubert "DPP: Unsupported SubjectPublicKeyInfo curve: group %d", 5744b72b91aSCy Schubert crypto_ec_key_group(key)); 575db0ac6deSCy Schubert goto fail; 576db0ac6deSCy Schubert } 577db0ac6deSCy Schubert 5784b72b91aSCy Schubert bi->pubkey = key; 579c1d255d3SCy Schubert return 0; 580c1d255d3SCy Schubert fail: 5814b72b91aSCy 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, 5894b72b91aSCy 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 || 6354b72b91aSCy Schubert os_strcmp(token->string, "BS256") == 0) { 6364b72b91aSCy Schubert *hash_func = CRYPTO_HASH_ALG_SHA256; 6374b72b91aSCy Schubert } else if (os_strcmp(token->string, "ES384") == 0 || 6384b72b91aSCy Schubert os_strcmp(token->string, "BS384") == 0) { 6394b72b91aSCy Schubert *hash_func = CRYPTO_HASH_ALG_SHA384; 6404b72b91aSCy Schubert } else if (os_strcmp(token->string, "ES512") == 0 || 6414b72b91aSCy Schubert os_strcmp(token->string, "BS512") == 0) { 6424b72b91aSCy Schubert *hash_func = CRYPTO_HASH_ALG_SHA512; 6434b72b91aSCy Schubert } else { 6444b72b91aSCy 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 6654b72b91aSCy Schubert static int dpp_check_pubkey_match(struct crypto_ec_key *pub, 6664b72b91aSCy 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; 6764b72b91aSCy 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, 7004b72b91aSCy Schubert struct crypto_ec_key *csign_pub, 7014b72b91aSCy 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; 7074b72b91aSCy Schubert size_t prot_hdr_len = 0, signature_len = 0, signed_len; 7084b72b91aSCy Schubert int res, hash_func = -1; 709c1d255d3SCy Schubert const struct dpp_curve_params *curve; 7104b72b91aSCy Schubert u8 *hash = NULL; 711c1d255d3SCy Schubert 7124b72b91aSCy 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); 7354b72b91aSCy 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 7914b72b91aSCy Schubert hash = os_malloc(curve->hash_len); 7924b72b91aSCy Schubert if (!hash) 793c1d255d3SCy Schubert goto fail; 794c1d255d3SCy Schubert 7954b72b91aSCy Schubert signed_len = signed_end - signed_start + 1; 7964b72b91aSCy Schubert if (hash_func == CRYPTO_HASH_ALG_SHA256) 7974b72b91aSCy Schubert res = sha256_vector(1, (const u8 **) &signed_start, &signed_len, 7984b72b91aSCy Schubert hash); 7994b72b91aSCy Schubert else if (hash_func == CRYPTO_HASH_ALG_SHA384) 8004b72b91aSCy Schubert res = sha384_vector(1, (const u8 **) &signed_start, &signed_len, 8014b72b91aSCy Schubert hash); 8024b72b91aSCy Schubert else if (hash_func == CRYPTO_HASH_ALG_SHA512) 8034b72b91aSCy Schubert res = sha512_vector(1, (const u8 **) &signed_start, &signed_len, 8044b72b91aSCy Schubert hash); 8054b72b91aSCy Schubert else 806c1d255d3SCy Schubert goto fail; 8074b72b91aSCy Schubert 8084b72b91aSCy Schubert if (res) 809c1d255d3SCy Schubert goto fail; 8104b72b91aSCy Schubert 8114b72b91aSCy Schubert res = crypto_ec_key_verify_signature_r_s(csign_pub, 8124b72b91aSCy Schubert hash, curve->hash_len, 8134b72b91aSCy Schubert signature, signature_len / 2, 8144b72b91aSCy Schubert signature + signature_len / 2, 8154b72b91aSCy Schubert signature_len / 2); 816c1d255d3SCy Schubert if (res != 1) { 817c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 8184b72b91aSCy Schubert "DPP: signedConnector signature check failed (res=%d)", 8194b72b91aSCy 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: 8264b72b91aSCy 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 { 8394b72b91aSCy 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 8434b72b91aSCy 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); 8604b72b91aSCy 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) { 8794b72b91aSCy Schubert pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 8804b72b91aSCy Schubert prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 8814b72b91aSCy Schubert 0); 882c1d255d3SCy Schubert if (auth->own_bi) 8834b72b91aSCy Schubert bix = crypto_ec_key_get_pubkey_point( 8844b72b91aSCy Schubert auth->own_bi->pubkey, 0); 885c1d255d3SCy Schubert else 886c1d255d3SCy Schubert bix = NULL; 8874b72b91aSCy Schubert brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0); 888c1d255d3SCy Schubert } else { 8894b72b91aSCy Schubert pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 8904b72b91aSCy Schubert 0); 8914b72b91aSCy Schubert prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 892c1d255d3SCy Schubert if (auth->peer_bi) 8934b72b91aSCy Schubert bix = crypto_ec_key_get_pubkey_point( 8944b72b91aSCy Schubert auth->peer_bi->pubkey, 0); 895c1d255d3SCy Schubert else 896c1d255d3SCy Schubert bix = NULL; 8974b72b91aSCy 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) { 9624b72b91aSCy Schubert pix = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 9634b72b91aSCy Schubert prx = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 9644b72b91aSCy Schubert 0); 965c1d255d3SCy Schubert if (auth->own_bi) 9664b72b91aSCy Schubert bix = crypto_ec_key_get_pubkey_point( 9674b72b91aSCy Schubert auth->own_bi->pubkey, 0); 968c1d255d3SCy Schubert else 969c1d255d3SCy Schubert bix = NULL; 970c1d255d3SCy Schubert if (!auth->peer_bi) 971c1d255d3SCy Schubert goto fail; 9724b72b91aSCy Schubert brx = crypto_ec_key_get_pubkey_point(auth->peer_bi->pubkey, 0); 973c1d255d3SCy Schubert } else { 9744b72b91aSCy Schubert pix = crypto_ec_key_get_pubkey_point(auth->peer_protocol_key, 9754b72b91aSCy Schubert 0); 9764b72b91aSCy Schubert prx = crypto_ec_key_get_pubkey_point(auth->own_protocol_key, 0); 977c1d255d3SCy Schubert if (auth->peer_bi) 9784b72b91aSCy Schubert bix = crypto_ec_key_get_pubkey_point( 9794b72b91aSCy Schubert auth->peer_bi->pubkey, 0); 980c1d255d3SCy Schubert else 981c1d255d3SCy Schubert bix = NULL; 982c1d255d3SCy Schubert if (!auth->own_bi) 983c1d255d3SCy Schubert goto fail; 9844b72b91aSCy 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 { 10374b72b91aSCy Schubert struct crypto_ec *ec; 10384b72b91aSCy Schubert struct crypto_ec_point *L = NULL; 10394b72b91aSCy Schubert const struct crypto_ec_point *BI; 10404b72b91aSCy Schubert const struct crypto_bignum *bR, *pR, *q; 10414b72b91aSCy 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 10464b72b91aSCy Schubert ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey)); 10474b72b91aSCy Schubert if (!ec) 1048c1d255d3SCy Schubert goto fail; 1049c1d255d3SCy Schubert 10504b72b91aSCy Schubert q = crypto_ec_get_order(ec); 10514b72b91aSCy Schubert BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey); 10524b72b91aSCy Schubert bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey); 10534b72b91aSCy Schubert pR = crypto_ec_key_get_private_key(auth->own_protocol_key); 10544b72b91aSCy Schubert sum = crypto_bignum_init(); 10554b72b91aSCy Schubert L = crypto_ec_point_init(ec); 10564b72b91aSCy Schubert lx = crypto_bignum_init(); 10574b72b91aSCy Schubert if (!q || !BI || !bR || !pR || !sum || !L || !lx || 10584b72b91aSCy Schubert crypto_bignum_addmod(bR, pR, q, sum) || 10594b72b91aSCy Schubert crypto_ec_point_mul(ec, BI, sum, L) || 10604b72b91aSCy Schubert crypto_ec_point_x(ec, L, lx) || 10614b72b91aSCy Schubert crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx), 10624b72b91aSCy 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: 10694b72b91aSCy Schubert crypto_bignum_deinit(lx, 1); 10704b72b91aSCy Schubert crypto_bignum_deinit(sum, 1); 10714b72b91aSCy Schubert crypto_ec_point_deinit(L, 1); 10724b72b91aSCy 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 { 10794b72b91aSCy Schubert struct crypto_ec *ec; 10804b72b91aSCy Schubert struct crypto_ec_point *L = NULL, *sum = NULL; 10814b72b91aSCy Schubert const struct crypto_ec_point *BR, *PR; 10824b72b91aSCy Schubert const struct crypto_bignum *bI; 10834b72b91aSCy Schubert struct crypto_bignum *lx = NULL; 1084c1d255d3SCy Schubert int ret = -1; 1085c1d255d3SCy Schubert 1086c1d255d3SCy Schubert /* L = bI * (BR + PR) */ 1087c1d255d3SCy Schubert 10884b72b91aSCy Schubert ec = crypto_ec_init(crypto_ec_key_group(auth->peer_bi->pubkey)); 10894b72b91aSCy Schubert if (!ec) 1090c1d255d3SCy Schubert goto fail; 1091c1d255d3SCy Schubert 10924b72b91aSCy Schubert BR = crypto_ec_key_get_public_key(auth->peer_bi->pubkey); 10934b72b91aSCy Schubert PR = crypto_ec_key_get_public_key(auth->peer_protocol_key); 10944b72b91aSCy Schubert bI = crypto_ec_key_get_private_key(auth->own_bi->pubkey); 10954b72b91aSCy Schubert sum = crypto_ec_point_init(ec); 10964b72b91aSCy Schubert L = crypto_ec_point_init(ec); 10974b72b91aSCy Schubert lx = crypto_bignum_init(); 10984b72b91aSCy Schubert if (!BR || !PR || !bI || !sum || !L || !lx || 10994b72b91aSCy Schubert crypto_ec_point_add(ec, BR, PR, sum) || 11004b72b91aSCy Schubert crypto_ec_point_mul(ec, sum, bI, L) || 11014b72b91aSCy Schubert crypto_ec_point_x(ec, L, lx) || 11024b72b91aSCy Schubert crypto_bignum_to_bin(lx, auth->Lx, sizeof(auth->Lx), 11034b72b91aSCy Schubert auth->secret_len) < 0) 1104db0ac6deSCy Schubert goto fail; 1105db0ac6deSCy 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: 11104b72b91aSCy Schubert crypto_bignum_deinit(lx, 1); 11114b72b91aSCy Schubert crypto_ec_point_deinit(sum, 1); 11124b72b91aSCy Schubert crypto_ec_point_deinit(L, 1); 11134b72b91aSCy 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, 11464b72b91aSCy Schubert struct crypto_ec_key *own_key, 11474b72b91aSCy 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))) */ 11564b72b91aSCy Schubert nkx = crypto_ec_key_get_pubkey_point(own_key, 0); 11574b72b91aSCy 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 13974b72b91aSCy Schubert static struct crypto_ec_key * 13984b72b91aSCy 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 14314b72b91aSCy Schubert return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len); 1432c1d255d3SCy Schubert } 1433c1d255d3SCy Schubert 1434c1d255d3SCy Schubert 14354b72b91aSCy Schubert struct crypto_ec_point * 14364b72b91aSCy Schubert dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, const u8 *mac_init, 14374b72b91aSCy Schubert const char *code, const char *identifier, 14384b72b91aSCy 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; 14444b72b91aSCy Schubert struct crypto_ec_point *Qi = NULL; 14454b72b91aSCy Schubert struct crypto_ec_key *Pi_key = NULL; 14464b72b91aSCy Schubert const struct crypto_ec_point *Pi = NULL; 14474b72b91aSCy Schubert struct crypto_bignum *hash_bn = NULL; 14484b72b91aSCy Schubert struct crypto_ec *ec = NULL; 1449c1d255d3SCy Schubert 1450*32a95656SCy Schubert /* Qi = H([MAC-Initiator |] [identifier |] code) * Pi */ 1451c1d255d3SCy Schubert 1452*32a95656SCy Schubert if (mac_init) { 1453*32a95656SCy Schubert wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, 1454*32a95656SCy Schubert MAC2STR(mac_init)); 1455c1d255d3SCy Schubert addr[num_elem] = mac_init; 1456c1d255d3SCy Schubert len[num_elem] = ETH_ALEN; 1457c1d255d3SCy Schubert num_elem++; 1458*32a95656SCy Schubert } 1459c1d255d3SCy Schubert if (identifier) { 1460c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", 1461c1d255d3SCy Schubert identifier); 1462c1d255d3SCy Schubert addr[num_elem] = (const u8 *) identifier; 1463c1d255d3SCy Schubert len[num_elem] = os_strlen(identifier); 1464c1d255d3SCy Schubert num_elem++; 1465c1d255d3SCy Schubert } 1466c1d255d3SCy Schubert wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); 1467c1d255d3SCy Schubert addr[num_elem] = (const u8 *) code; 1468c1d255d3SCy Schubert len[num_elem] = os_strlen(code); 1469c1d255d3SCy Schubert num_elem++; 1470c1d255d3SCy Schubert if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) 1471c1d255d3SCy Schubert goto fail; 1472c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 1473*32a95656SCy Schubert "DPP: H([MAC-Initiator |] [identifier |] code)", 1474c1d255d3SCy Schubert hash, curve->hash_len); 14754b72b91aSCy Schubert Pi_key = dpp_pkex_get_role_elem(curve, 1); 14764b72b91aSCy Schubert if (!Pi_key) 1477c1d255d3SCy Schubert goto fail; 14784b72b91aSCy Schubert dpp_debug_print_key("DPP: Pi", Pi_key); 1479266f97b5SCy Schubert 14804b72b91aSCy Schubert ec = crypto_ec_init(curve->ike_group); 14814b72b91aSCy Schubert if (!ec) 1482c1d255d3SCy Schubert goto fail; 14834b72b91aSCy Schubert 14844b72b91aSCy Schubert Pi = crypto_ec_key_get_public_key(Pi_key); 14854b72b91aSCy Schubert Qi = crypto_ec_point_init(ec); 14864b72b91aSCy Schubert hash_bn = crypto_bignum_init_set(hash, curve->hash_len); 14874b72b91aSCy Schubert if (!Pi || !Qi || !hash_bn || crypto_ec_point_mul(ec, Pi, hash_bn, Qi)) 1488db0ac6deSCy Schubert goto fail; 14894b72b91aSCy Schubert 14904b72b91aSCy Schubert if (crypto_ec_point_is_at_infinity(ec, Qi)) { 1491c1d255d3SCy Schubert wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity"); 1492c1d255d3SCy Schubert goto fail; 1493c1d255d3SCy Schubert } 14944b72b91aSCy Schubert crypto_ec_point_debug_print(ec, Qi, "DPP: Qi"); 1495c1d255d3SCy Schubert out: 14964b72b91aSCy Schubert crypto_ec_key_deinit(Pi_key); 14974b72b91aSCy Schubert crypto_bignum_deinit(hash_bn, 1); 14984b72b91aSCy Schubert if (ret_ec && Qi) 14994b72b91aSCy Schubert *ret_ec = ec; 1500c1d255d3SCy Schubert else 15014b72b91aSCy Schubert crypto_ec_deinit(ec); 1502c1d255d3SCy Schubert return Qi; 1503c1d255d3SCy Schubert fail: 15044b72b91aSCy Schubert crypto_ec_point_deinit(Qi, 1); 1505c1d255d3SCy Schubert Qi = NULL; 1506c1d255d3SCy Schubert goto out; 1507c1d255d3SCy Schubert } 1508c1d255d3SCy Schubert 1509c1d255d3SCy Schubert 15104b72b91aSCy Schubert struct crypto_ec_point * 15114b72b91aSCy Schubert dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, const u8 *mac_resp, 15124b72b91aSCy Schubert const char *code, const char *identifier, 15134b72b91aSCy Schubert struct crypto_ec **ret_ec) 1514c1d255d3SCy Schubert { 1515c1d255d3SCy Schubert u8 hash[DPP_MAX_HASH_LEN]; 1516c1d255d3SCy Schubert const u8 *addr[3]; 1517c1d255d3SCy Schubert size_t len[3]; 1518c1d255d3SCy Schubert unsigned int num_elem = 0; 15194b72b91aSCy Schubert struct crypto_ec_point *Qr = NULL; 15204b72b91aSCy Schubert struct crypto_ec_key *Pr_key = NULL; 15214b72b91aSCy Schubert const struct crypto_ec_point *Pr = NULL; 15224b72b91aSCy Schubert struct crypto_bignum *hash_bn = NULL; 15234b72b91aSCy Schubert struct crypto_ec *ec = NULL; 1524c1d255d3SCy Schubert 1525*32a95656SCy Schubert /* Qr = H([MAC-Responder |] [identifier |] code) * Pr */ 1526c1d255d3SCy Schubert 1527*32a95656SCy Schubert if (mac_resp) { 1528*32a95656SCy Schubert wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, 1529*32a95656SCy Schubert MAC2STR(mac_resp)); 1530c1d255d3SCy Schubert addr[num_elem] = mac_resp; 1531c1d255d3SCy Schubert len[num_elem] = ETH_ALEN; 1532c1d255d3SCy Schubert num_elem++; 1533*32a95656SCy Schubert } 1534c1d255d3SCy Schubert if (identifier) { 1535c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", 1536c1d255d3SCy Schubert identifier); 1537c1d255d3SCy Schubert addr[num_elem] = (const u8 *) identifier; 1538c1d255d3SCy Schubert len[num_elem] = os_strlen(identifier); 1539c1d255d3SCy Schubert num_elem++; 1540c1d255d3SCy Schubert } 1541c1d255d3SCy Schubert wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); 1542c1d255d3SCy Schubert addr[num_elem] = (const u8 *) code; 1543c1d255d3SCy Schubert len[num_elem] = os_strlen(code); 1544c1d255d3SCy Schubert num_elem++; 1545c1d255d3SCy Schubert if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) 1546c1d255d3SCy Schubert goto fail; 1547c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 1548*32a95656SCy Schubert "DPP: H([MAC-Responder |] [identifier |] code)", 1549c1d255d3SCy Schubert hash, curve->hash_len); 15504b72b91aSCy Schubert Pr_key = dpp_pkex_get_role_elem(curve, 0); 15514b72b91aSCy Schubert if (!Pr_key) 1552c1d255d3SCy Schubert goto fail; 15534b72b91aSCy Schubert dpp_debug_print_key("DPP: Pr", Pr_key); 1554266f97b5SCy Schubert 15554b72b91aSCy Schubert ec = crypto_ec_init(curve->ike_group); 15564b72b91aSCy Schubert if (!ec) 1557c1d255d3SCy Schubert goto fail; 15584b72b91aSCy Schubert 15594b72b91aSCy Schubert Pr = crypto_ec_key_get_public_key(Pr_key); 15604b72b91aSCy Schubert Qr = crypto_ec_point_init(ec); 15614b72b91aSCy Schubert hash_bn = crypto_bignum_init_set(hash, curve->hash_len); 15624b72b91aSCy Schubert if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr)) 1563db0ac6deSCy Schubert goto fail; 15644b72b91aSCy Schubert 15654b72b91aSCy Schubert if (crypto_ec_point_is_at_infinity(ec, Qr)) { 1566c1d255d3SCy Schubert wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity"); 1567c1d255d3SCy Schubert goto fail; 1568c1d255d3SCy Schubert } 15694b72b91aSCy Schubert crypto_ec_point_debug_print(ec, Qr, "DPP: Qr"); 15704b72b91aSCy Schubert 1571c1d255d3SCy Schubert out: 15724b72b91aSCy Schubert crypto_ec_key_deinit(Pr_key); 15734b72b91aSCy Schubert crypto_bignum_deinit(hash_bn, 1); 15744b72b91aSCy Schubert if (ret_ec && Qr) 15754b72b91aSCy Schubert *ret_ec = ec; 1576c1d255d3SCy Schubert else 15774b72b91aSCy Schubert crypto_ec_deinit(ec); 1578c1d255d3SCy Schubert return Qr; 1579c1d255d3SCy Schubert fail: 15804b72b91aSCy Schubert crypto_ec_point_deinit(Qr, 1); 1581c1d255d3SCy Schubert Qr = NULL; 1582c1d255d3SCy Schubert goto out; 1583c1d255d3SCy Schubert } 1584c1d255d3SCy Schubert 1585c1d255d3SCy Schubert 1586c1d255d3SCy Schubert int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, 1587*32a95656SCy Schubert u8 ver_init, u8 ver_resp, 1588c1d255d3SCy Schubert const u8 *Mx, size_t Mx_len, 1589c1d255d3SCy Schubert const u8 *Nx, size_t Nx_len, 1590c1d255d3SCy Schubert const char *code, 1591c1d255d3SCy Schubert const u8 *Kx, size_t Kx_len, 1592c1d255d3SCy Schubert u8 *z, unsigned int hash_len) 1593c1d255d3SCy Schubert { 1594c1d255d3SCy Schubert u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 1595c1d255d3SCy Schubert int res; 1596c1d255d3SCy Schubert u8 *info, *pos; 1597c1d255d3SCy Schubert size_t info_len; 1598c1d255d3SCy Schubert 1599*32a95656SCy Schubert /* 1600*32a95656SCy Schubert * v1: info = MAC-Initiator | MAC-Responder 1601*32a95656SCy Schubert * v2: info = Protocol Version-Initiator | Protocol Version-Responder 1602*32a95656SCy Schubert * z = HKDF(<>, info | M.x | N.x | code, K.x) 1603c1d255d3SCy Schubert */ 1604c1d255d3SCy Schubert 1605c1d255d3SCy Schubert /* HKDF-Extract(<>, IKM=K.x) */ 1606c1d255d3SCy Schubert os_memset(salt, 0, hash_len); 1607c1d255d3SCy Schubert if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0) 1608c1d255d3SCy Schubert return -1; 1609c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", 1610c1d255d3SCy Schubert prk, hash_len); 1611*32a95656SCy Schubert if (mac_init && mac_resp) 1612*32a95656SCy Schubert info_len = 2 * ETH_ALEN; 1613*32a95656SCy Schubert else 1614*32a95656SCy Schubert info_len = 2; 1615*32a95656SCy Schubert info_len += Mx_len + Nx_len + os_strlen(code); 1616c1d255d3SCy Schubert info = os_malloc(info_len); 1617c1d255d3SCy Schubert if (!info) 1618c1d255d3SCy Schubert return -1; 1619c1d255d3SCy Schubert pos = info; 1620*32a95656SCy Schubert if (mac_init && mac_resp) { 1621c1d255d3SCy Schubert os_memcpy(pos, mac_init, ETH_ALEN); 1622c1d255d3SCy Schubert pos += ETH_ALEN; 1623c1d255d3SCy Schubert os_memcpy(pos, mac_resp, ETH_ALEN); 1624c1d255d3SCy Schubert pos += ETH_ALEN; 1625*32a95656SCy Schubert } else { 1626*32a95656SCy Schubert *pos++ = ver_init; 1627*32a95656SCy Schubert *pos++ = ver_resp; 1628*32a95656SCy Schubert } 1629c1d255d3SCy Schubert os_memcpy(pos, Mx, Mx_len); 1630c1d255d3SCy Schubert pos += Mx_len; 1631c1d255d3SCy Schubert os_memcpy(pos, Nx, Nx_len); 1632c1d255d3SCy Schubert pos += Nx_len; 1633c1d255d3SCy Schubert os_memcpy(pos, code, os_strlen(code)); 1634c1d255d3SCy Schubert 1635c1d255d3SCy Schubert /* HKDF-Expand(PRK, info, L) */ 1636c1d255d3SCy Schubert if (hash_len == 32) 1637c1d255d3SCy Schubert res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len, 1638c1d255d3SCy Schubert z, hash_len); 1639c1d255d3SCy Schubert else if (hash_len == 48) 1640c1d255d3SCy Schubert res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len, 1641c1d255d3SCy Schubert z, hash_len); 1642c1d255d3SCy Schubert else if (hash_len == 64) 1643c1d255d3SCy Schubert res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len, 1644c1d255d3SCy Schubert z, hash_len); 1645c1d255d3SCy Schubert else 1646c1d255d3SCy Schubert res = -1; 1647c1d255d3SCy Schubert os_free(info); 1648c1d255d3SCy Schubert os_memset(prk, 0, hash_len); 1649c1d255d3SCy Schubert if (res < 0) 1650c1d255d3SCy Schubert return -1; 1651c1d255d3SCy Schubert 1652c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)", 1653c1d255d3SCy Schubert z, hash_len); 1654c1d255d3SCy Schubert return 0; 1655c1d255d3SCy Schubert } 1656c1d255d3SCy Schubert 1657c1d255d3SCy Schubert 1658c1d255d3SCy Schubert int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, 1659c1d255d3SCy Schubert const u8 *net_access_key, 1660c1d255d3SCy Schubert size_t net_access_key_len, 1661c1d255d3SCy Schubert struct json_token *peer_net_access_key) 1662c1d255d3SCy Schubert { 16634b72b91aSCy Schubert struct crypto_ec_key *own_key = NULL, *peer_key = NULL; 16644b72b91aSCy Schubert struct crypto_bignum *sum = NULL; 16654b72b91aSCy Schubert const struct crypto_bignum *q, *cR, *pR; 16664b72b91aSCy Schubert struct crypto_ec *ec = NULL; 16674b72b91aSCy Schubert struct crypto_ec_point *M = NULL; 16684b72b91aSCy Schubert const struct crypto_ec_point *CI; 1669c1d255d3SCy Schubert u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; 1670c1d255d3SCy Schubert u8 prk[DPP_MAX_HASH_LEN]; 1671c1d255d3SCy Schubert const struct dpp_curve_params *curve; 1672c1d255d3SCy Schubert int res = -1; 1673c1d255d3SCy Schubert u8 nonces[2 * DPP_MAX_NONCE_LEN]; 1674c1d255d3SCy Schubert 1675c1d255d3SCy Schubert own_key = dpp_set_keypair(&auth->curve, net_access_key, 1676c1d255d3SCy Schubert net_access_key_len); 1677c1d255d3SCy Schubert if (!own_key) { 1678c1d255d3SCy Schubert dpp_auth_fail(auth, "Failed to parse own netAccessKey"); 1679c1d255d3SCy Schubert goto fail; 1680c1d255d3SCy Schubert } 1681c1d255d3SCy Schubert 1682c1d255d3SCy Schubert peer_key = dpp_parse_jwk(peer_net_access_key, &curve); 1683c1d255d3SCy Schubert if (!peer_key) 1684c1d255d3SCy Schubert goto fail; 1685c1d255d3SCy Schubert dpp_debug_print_key("DPP: Received netAccessKey", peer_key); 1686c1d255d3SCy Schubert 1687c1d255d3SCy Schubert if (auth->curve != curve) { 1688c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1689c1d255d3SCy Schubert "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", 1690c1d255d3SCy Schubert auth->curve->name, curve->name); 1691c1d255d3SCy Schubert goto fail; 1692c1d255d3SCy Schubert } 1693c1d255d3SCy Schubert 1694c1d255d3SCy Schubert auth->own_protocol_key = dpp_gen_keypair(curve); 1695c1d255d3SCy Schubert if (!auth->own_protocol_key) 1696c1d255d3SCy Schubert goto fail; 1697c1d255d3SCy Schubert 1698c1d255d3SCy Schubert if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) { 1699c1d255d3SCy Schubert wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce"); 1700c1d255d3SCy Schubert goto fail; 1701c1d255d3SCy Schubert } 1702c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce", 1703c1d255d3SCy Schubert auth->e_nonce, auth->curve->nonce_len); 1704c1d255d3SCy Schubert 1705c1d255d3SCy Schubert /* M = { cR + pR } * CI */ 17064b72b91aSCy Schubert ec = crypto_ec_init(curve->ike_group); 17074b72b91aSCy Schubert if (!ec) 1708c1d255d3SCy Schubert goto fail; 17094b72b91aSCy Schubert 17104b72b91aSCy Schubert sum = crypto_bignum_init(); 17114b72b91aSCy Schubert q = crypto_ec_get_order(ec); 17124b72b91aSCy Schubert M = crypto_ec_point_init(ec); 17134b72b91aSCy Schubert cR = crypto_ec_key_get_private_key(own_key); 17144b72b91aSCy Schubert pR = crypto_ec_key_get_private_key(auth->own_protocol_key); 17154b72b91aSCy Schubert CI = crypto_ec_key_get_public_key(peer_key); 17164b72b91aSCy Schubert if (!sum || !q || !M || !cR || !pR || !CI || 17174b72b91aSCy Schubert crypto_bignum_addmod(cR, pR, q, sum) || 17184b72b91aSCy Schubert crypto_ec_point_mul(ec, CI, sum, M) || 17194b72b91aSCy Schubert crypto_ec_point_to_bin(ec, M, Mx, NULL)) { 17204b72b91aSCy Schubert wpa_printf(MSG_ERROR, "DPP: Error during M computation"); 1721c1d255d3SCy Schubert goto fail; 1722c1d255d3SCy Schubert } 1723c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); 1724c1d255d3SCy Schubert 1725c1d255d3SCy Schubert /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ 1726c1d255d3SCy Schubert 1727c1d255d3SCy Schubert /* HKDF-Extract(C-nonce | E-nonce, M.x) */ 1728c1d255d3SCy Schubert os_memcpy(nonces, auth->c_nonce, curve->nonce_len); 1729c1d255d3SCy Schubert os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); 1730c1d255d3SCy Schubert if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, 1731c1d255d3SCy Schubert Mx, curve->prime_len, prk) < 0) 1732c1d255d3SCy Schubert goto fail; 1733c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); 1734c1d255d3SCy Schubert 1735c1d255d3SCy Schubert /* HKDF-Expand(PRK, "dpp reconfig key", L) */ 1736c1d255d3SCy Schubert if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, 1737c1d255d3SCy Schubert "dpp reconfig key", auth->ke, curve->hash_len) < 0) 1738c1d255d3SCy Schubert goto fail; 1739c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 1740c1d255d3SCy Schubert "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", 1741c1d255d3SCy Schubert auth->ke, curve->hash_len); 1742c1d255d3SCy Schubert 1743c1d255d3SCy Schubert res = 0; 17444b72b91aSCy Schubert crypto_ec_key_deinit(auth->reconfig_old_protocol_key); 1745c1d255d3SCy Schubert auth->reconfig_old_protocol_key = own_key; 1746c1d255d3SCy Schubert own_key = NULL; 1747c1d255d3SCy Schubert fail: 1748c1d255d3SCy Schubert forced_memzero(prk, sizeof(prk)); 1749c1d255d3SCy Schubert forced_memzero(Mx, sizeof(Mx)); 17504b72b91aSCy Schubert crypto_ec_point_deinit(M, 1); 17514b72b91aSCy Schubert crypto_bignum_deinit(sum, 1); 17524b72b91aSCy Schubert crypto_ec_key_deinit(own_key); 17534b72b91aSCy Schubert crypto_ec_key_deinit(peer_key); 17544b72b91aSCy Schubert crypto_ec_deinit(ec); 1755c1d255d3SCy Schubert return res; 1756c1d255d3SCy Schubert } 1757c1d255d3SCy Schubert 1758c1d255d3SCy Schubert 1759c1d255d3SCy Schubert int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, 1760c1d255d3SCy Schubert const u8 *r_proto, u16 r_proto_len, 1761c1d255d3SCy Schubert struct json_token *net_access_key) 1762c1d255d3SCy Schubert { 17634b72b91aSCy Schubert struct crypto_ec_key *pr = NULL, *peer_key = NULL; 17644b72b91aSCy Schubert const struct crypto_ec_point *CR, *PR; 17654b72b91aSCy Schubert const struct crypto_bignum *cI; 17664b72b91aSCy Schubert struct crypto_ec *ec = NULL; 17674b72b91aSCy Schubert struct crypto_ec_point *sum = NULL, *M = NULL; 1768c1d255d3SCy Schubert u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; 1769c1d255d3SCy Schubert u8 prk[DPP_MAX_HASH_LEN]; 1770c1d255d3SCy Schubert int res = -1; 1771c1d255d3SCy Schubert const struct dpp_curve_params *curve; 1772c1d255d3SCy Schubert u8 nonces[2 * DPP_MAX_NONCE_LEN]; 1773c1d255d3SCy Schubert 1774c1d255d3SCy Schubert pr = dpp_set_pubkey_point(auth->conf->connector_key, 1775c1d255d3SCy Schubert r_proto, r_proto_len); 1776c1d255d3SCy Schubert if (!pr) { 1777c1d255d3SCy Schubert dpp_auth_fail(auth, "Invalid Responder Protocol Key"); 1778c1d255d3SCy Schubert goto fail; 1779c1d255d3SCy Schubert } 1780c1d255d3SCy Schubert dpp_debug_print_key("Peer (Responder) Protocol Key", pr); 17814b72b91aSCy Schubert crypto_ec_key_deinit(auth->peer_protocol_key); 1782c1d255d3SCy Schubert auth->peer_protocol_key = pr; 1783c1d255d3SCy Schubert pr = NULL; 1784c1d255d3SCy Schubert 1785c1d255d3SCy Schubert peer_key = dpp_parse_jwk(net_access_key, &curve); 1786c1d255d3SCy Schubert if (!peer_key) 1787c1d255d3SCy Schubert goto fail; 1788c1d255d3SCy Schubert dpp_debug_print_key("DPP: Received netAccessKey", peer_key); 1789c1d255d3SCy Schubert if (auth->curve != curve) { 1790c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1791c1d255d3SCy Schubert "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", 1792c1d255d3SCy Schubert auth->curve->name, curve->name); 1793c1d255d3SCy Schubert goto fail; 1794c1d255d3SCy Schubert } 1795c1d255d3SCy Schubert 1796c1d255d3SCy Schubert /* M = cI * { CR + PR } */ 17974b72b91aSCy Schubert ec = crypto_ec_init(curve->ike_group); 17984b72b91aSCy Schubert if (!ec) 1799c1d255d3SCy Schubert goto fail; 1800c1d255d3SCy Schubert 18014b72b91aSCy Schubert cI = crypto_ec_key_get_private_key(auth->conf->connector_key); 18024b72b91aSCy Schubert sum = crypto_ec_point_init(ec); 18034b72b91aSCy Schubert M = crypto_ec_point_init(ec); 18044b72b91aSCy Schubert CR = crypto_ec_key_get_public_key(peer_key); 18054b72b91aSCy Schubert PR = crypto_ec_key_get_public_key(auth->peer_protocol_key); 18064b72b91aSCy Schubert if (!cI || !sum || !M || !CR || !PR || 18074b72b91aSCy Schubert crypto_ec_point_add(ec, CR, PR, sum) || 18084b72b91aSCy Schubert crypto_ec_point_mul(ec, sum, cI, M) || 18094b72b91aSCy Schubert crypto_ec_point_to_bin(ec, M, Mx, NULL)) { 18104b72b91aSCy Schubert wpa_printf(MSG_ERROR, "DPP: Error during M computation"); 18114b72b91aSCy Schubert goto fail; 18124b72b91aSCy Schubert } 18134b72b91aSCy Schubert 1814c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); 1815c1d255d3SCy Schubert 1816c1d255d3SCy Schubert /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ 1817c1d255d3SCy Schubert 1818c1d255d3SCy Schubert /* HKDF-Extract(C-nonce | E-nonce, M.x) */ 1819c1d255d3SCy Schubert os_memcpy(nonces, auth->c_nonce, curve->nonce_len); 1820c1d255d3SCy Schubert os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); 1821c1d255d3SCy Schubert if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, 1822c1d255d3SCy Schubert Mx, curve->prime_len, prk) < 0) 1823c1d255d3SCy Schubert goto fail; 1824c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); 1825c1d255d3SCy Schubert 1826c1d255d3SCy Schubert /* HKDF-Expand(PRK, "dpp reconfig key", L) */ 1827c1d255d3SCy Schubert if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, 1828c1d255d3SCy Schubert "dpp reconfig key", auth->ke, curve->hash_len) < 0) 1829c1d255d3SCy Schubert goto fail; 1830c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 1831c1d255d3SCy Schubert "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", 1832c1d255d3SCy Schubert auth->ke, curve->hash_len); 1833c1d255d3SCy Schubert 1834c1d255d3SCy Schubert res = 0; 1835c1d255d3SCy Schubert fail: 1836c1d255d3SCy Schubert forced_memzero(prk, sizeof(prk)); 1837c1d255d3SCy Schubert forced_memzero(Mx, sizeof(Mx)); 18384b72b91aSCy Schubert crypto_ec_key_deinit(pr); 18394b72b91aSCy Schubert crypto_ec_key_deinit(peer_key); 18404b72b91aSCy Schubert crypto_ec_point_deinit(sum, 1); 18414b72b91aSCy Schubert crypto_ec_point_deinit(M, 1); 18424b72b91aSCy Schubert crypto_ec_deinit(ec); 1843c1d255d3SCy Schubert return res; 1844c1d255d3SCy Schubert } 1845c1d255d3SCy Schubert 1846c1d255d3SCy Schubert 1847c1d255d3SCy Schubert static char * 1848c1d255d3SCy Schubert dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len) 1849c1d255d3SCy Schubert { 1850c1d255d3SCy Schubert struct wpabuf *jws_prot_hdr; 1851c1d255d3SCy Schubert char *signed1; 1852c1d255d3SCy Schubert 1853c1d255d3SCy Schubert jws_prot_hdr = wpabuf_alloc(100); 1854c1d255d3SCy Schubert if (!jws_prot_hdr) 1855c1d255d3SCy Schubert return NULL; 1856c1d255d3SCy Schubert json_start_object(jws_prot_hdr, NULL); 1857c1d255d3SCy Schubert json_add_string(jws_prot_hdr, "typ", "dppCon"); 1858c1d255d3SCy Schubert json_value_sep(jws_prot_hdr); 1859c1d255d3SCy Schubert json_add_string(jws_prot_hdr, "kid", conf->kid); 1860c1d255d3SCy Schubert json_value_sep(jws_prot_hdr); 1861c1d255d3SCy Schubert json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg); 1862c1d255d3SCy Schubert json_end_object(jws_prot_hdr); 1863c1d255d3SCy Schubert signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr), 1864c1d255d3SCy Schubert wpabuf_len(jws_prot_hdr), 1865c1d255d3SCy Schubert signed1_len); 1866c1d255d3SCy Schubert wpabuf_free(jws_prot_hdr); 1867c1d255d3SCy Schubert return signed1; 1868c1d255d3SCy Schubert } 1869c1d255d3SCy Schubert 1870c1d255d3SCy Schubert 1871c1d255d3SCy Schubert static char * 1872c1d255d3SCy Schubert dpp_build_conn_signature(struct dpp_configurator *conf, 1873c1d255d3SCy Schubert const char *signed1, size_t signed1_len, 1874c1d255d3SCy Schubert const char *signed2, size_t signed2_len, 1875c1d255d3SCy Schubert size_t *signed3_len) 1876c1d255d3SCy Schubert { 1877c1d255d3SCy Schubert const struct dpp_curve_params *curve; 18784b72b91aSCy Schubert struct wpabuf *sig = NULL; 1879c1d255d3SCy Schubert char *signed3 = NULL; 1880c1d255d3SCy Schubert char *dot = "."; 18814b72b91aSCy Schubert const u8 *vector[3]; 18824b72b91aSCy Schubert size_t vector_len[3]; 18834b72b91aSCy Schubert u8 *hash; 18844b72b91aSCy Schubert int ret; 18854b72b91aSCy Schubert 18864b72b91aSCy Schubert vector[0] = (const u8 *) signed1; 18874b72b91aSCy Schubert vector[1] = (const u8 *) dot; 18884b72b91aSCy Schubert vector[2] = (const u8 *) signed2; 18894b72b91aSCy Schubert vector_len[0] = signed1_len; 18904b72b91aSCy Schubert vector_len[1] = 1; 18914b72b91aSCy Schubert vector_len[2] = signed2_len; 1892c1d255d3SCy Schubert 1893c1d255d3SCy Schubert curve = conf->curve; 18944b72b91aSCy Schubert hash = os_malloc(curve->hash_len); 18954b72b91aSCy Schubert if (!hash) 18964b72b91aSCy Schubert goto fail; 1897c1d255d3SCy Schubert if (curve->hash_len == SHA256_MAC_LEN) { 18984b72b91aSCy Schubert ret = sha256_vector(3, vector, vector_len, hash); 1899c1d255d3SCy Schubert } else if (curve->hash_len == SHA384_MAC_LEN) { 19004b72b91aSCy Schubert ret = sha384_vector(3, vector, vector_len, hash); 1901c1d255d3SCy Schubert } else if (curve->hash_len == SHA512_MAC_LEN) { 19024b72b91aSCy Schubert ret = sha512_vector(3, vector, vector_len, hash); 1903c1d255d3SCy Schubert } else { 1904c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); 1905c1d255d3SCy Schubert goto fail; 1906c1d255d3SCy Schubert } 19074b72b91aSCy Schubert if (ret) { 19084b72b91aSCy Schubert wpa_printf(MSG_DEBUG, "DPP: Hash computation failed"); 19094b72b91aSCy Schubert goto fail; 19104b72b91aSCy Schubert } 19114b72b91aSCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Hash value for Connector signature", 19124b72b91aSCy Schubert hash, curve->hash_len); 1913db0ac6deSCy Schubert 19144b72b91aSCy Schubert sig = crypto_ec_key_sign_r_s(conf->csign, hash, curve->hash_len); 19154b72b91aSCy Schubert if (!sig) { 19164b72b91aSCy Schubert wpa_printf(MSG_ERROR, "DPP: Signature computation failed"); 1917db0ac6deSCy Schubert goto fail; 19184b72b91aSCy Schubert } 1919db0ac6deSCy Schubert 1920c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)", 19214b72b91aSCy Schubert wpabuf_head(sig), wpabuf_len(sig)); 19224b72b91aSCy Schubert signed3 = base64_url_encode(wpabuf_head(sig), wpabuf_len(sig), 19234b72b91aSCy Schubert signed3_len); 19244b72b91aSCy Schubert 1925c1d255d3SCy Schubert fail: 19264b72b91aSCy Schubert os_free(hash); 19274b72b91aSCy Schubert wpabuf_free(sig); 1928c1d255d3SCy Schubert return signed3; 1929c1d255d3SCy Schubert } 1930c1d255d3SCy Schubert 1931c1d255d3SCy Schubert char * dpp_sign_connector(struct dpp_configurator *conf, 1932c1d255d3SCy Schubert const struct wpabuf *dppcon) 1933c1d255d3SCy Schubert { 1934c1d255d3SCy Schubert char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL; 1935c1d255d3SCy Schubert char *signed_conn = NULL, *pos; 1936c1d255d3SCy Schubert size_t signed1_len, signed2_len, signed3_len; 1937c1d255d3SCy Schubert 1938c1d255d3SCy Schubert signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len); 1939c1d255d3SCy Schubert signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon), 1940c1d255d3SCy Schubert &signed2_len); 1941c1d255d3SCy Schubert if (!signed1 || !signed2) 1942c1d255d3SCy Schubert goto fail; 1943c1d255d3SCy Schubert 1944c1d255d3SCy Schubert signed3 = dpp_build_conn_signature(conf, signed1, signed1_len, 1945c1d255d3SCy Schubert signed2, signed2_len, &signed3_len); 1946c1d255d3SCy Schubert if (!signed3) 1947c1d255d3SCy Schubert goto fail; 1948c1d255d3SCy Schubert 1949c1d255d3SCy Schubert signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3); 1950c1d255d3SCy Schubert if (!signed_conn) 1951c1d255d3SCy Schubert goto fail; 1952c1d255d3SCy Schubert pos = signed_conn; 1953c1d255d3SCy Schubert os_memcpy(pos, signed1, signed1_len); 1954c1d255d3SCy Schubert pos += signed1_len; 1955c1d255d3SCy Schubert *pos++ = '.'; 1956c1d255d3SCy Schubert os_memcpy(pos, signed2, signed2_len); 1957c1d255d3SCy Schubert pos += signed2_len; 1958c1d255d3SCy Schubert *pos++ = '.'; 1959c1d255d3SCy Schubert os_memcpy(pos, signed3, signed3_len); 1960c1d255d3SCy Schubert pos += signed3_len; 1961c1d255d3SCy Schubert *pos = '\0'; 1962c1d255d3SCy Schubert 1963c1d255d3SCy Schubert fail: 1964c1d255d3SCy Schubert os_free(signed1); 1965c1d255d3SCy Schubert os_free(signed2); 1966c1d255d3SCy Schubert os_free(signed3); 1967c1d255d3SCy Schubert return signed_conn; 1968c1d255d3SCy Schubert } 1969c1d255d3SCy Schubert 1970c1d255d3SCy Schubert 1971c1d255d3SCy Schubert #ifdef CONFIG_DPP2 1972c1d255d3SCy Schubert 1973c1d255d3SCy Schubert struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, 1974c1d255d3SCy Schubert size_t net_access_key_len) 1975c1d255d3SCy Schubert { 1976c1d255d3SCy Schubert struct wpabuf *pub = NULL; 19774b72b91aSCy Schubert struct crypto_ec_key *own_key; 1978c1d255d3SCy Schubert struct dpp_pfs *pfs; 1979c1d255d3SCy Schubert 1980c1d255d3SCy Schubert pfs = os_zalloc(sizeof(*pfs)); 1981c1d255d3SCy Schubert if (!pfs) 1982c1d255d3SCy Schubert return NULL; 1983c1d255d3SCy Schubert 1984c1d255d3SCy Schubert own_key = dpp_set_keypair(&pfs->curve, net_access_key, 1985c1d255d3SCy Schubert net_access_key_len); 1986c1d255d3SCy Schubert if (!own_key) { 1987c1d255d3SCy Schubert wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); 1988c1d255d3SCy Schubert goto fail; 1989c1d255d3SCy Schubert } 19904b72b91aSCy Schubert crypto_ec_key_deinit(own_key); 1991c1d255d3SCy Schubert 1992c1d255d3SCy Schubert pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group); 1993c1d255d3SCy Schubert if (!pfs->ecdh) 1994c1d255d3SCy Schubert goto fail; 1995c1d255d3SCy Schubert 1996c1d255d3SCy Schubert pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0); 1997c1d255d3SCy Schubert pub = wpabuf_zeropad(pub, pfs->curve->prime_len); 1998c1d255d3SCy Schubert if (!pub) 1999c1d255d3SCy Schubert goto fail; 2000c1d255d3SCy Schubert 2001c1d255d3SCy Schubert pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub)); 2002c1d255d3SCy Schubert if (!pfs->ie) 2003c1d255d3SCy Schubert goto fail; 2004c1d255d3SCy Schubert wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION); 2005c1d255d3SCy Schubert wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub)); 2006c1d255d3SCy Schubert wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM); 2007c1d255d3SCy Schubert wpabuf_put_le16(pfs->ie, pfs->curve->ike_group); 2008c1d255d3SCy Schubert wpabuf_put_buf(pfs->ie, pub); 2009c1d255d3SCy Schubert wpabuf_free(pub); 2010c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element", 2011c1d255d3SCy Schubert pfs->ie); 2012c1d255d3SCy Schubert 2013c1d255d3SCy Schubert return pfs; 2014c1d255d3SCy Schubert fail: 2015c1d255d3SCy Schubert wpabuf_free(pub); 2016c1d255d3SCy Schubert dpp_pfs_free(pfs); 2017c1d255d3SCy Schubert return NULL; 2018c1d255d3SCy Schubert } 2019c1d255d3SCy Schubert 2020c1d255d3SCy Schubert 2021c1d255d3SCy Schubert int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len) 2022c1d255d3SCy Schubert { 2023c1d255d3SCy Schubert if (peer_ie_len < 2) 2024c1d255d3SCy Schubert return -1; 2025c1d255d3SCy Schubert if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) { 2026c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS"); 2027c1d255d3SCy Schubert return -1; 2028c1d255d3SCy Schubert } 2029c1d255d3SCy Schubert 2030c1d255d3SCy Schubert pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2, 2031c1d255d3SCy Schubert peer_ie_len - 2); 2032c1d255d3SCy Schubert pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len); 2033c1d255d3SCy Schubert if (!pfs->secret) { 2034c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key"); 2035c1d255d3SCy Schubert return -1; 2036c1d255d3SCy Schubert } 2037c1d255d3SCy Schubert wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret); 2038c1d255d3SCy Schubert return 0; 2039c1d255d3SCy Schubert } 2040c1d255d3SCy Schubert 2041c1d255d3SCy Schubert 2042c1d255d3SCy Schubert void dpp_pfs_free(struct dpp_pfs *pfs) 2043c1d255d3SCy Schubert { 2044c1d255d3SCy Schubert if (!pfs) 2045c1d255d3SCy Schubert return; 2046c1d255d3SCy Schubert crypto_ecdh_deinit(pfs->ecdh); 2047c1d255d3SCy Schubert wpabuf_free(pfs->ie); 2048c1d255d3SCy Schubert wpabuf_clear_free(pfs->secret); 2049c1d255d3SCy Schubert os_free(pfs); 2050c1d255d3SCy Schubert } 2051c1d255d3SCy Schubert 2052c1d255d3SCy Schubert 2053c1d255d3SCy Schubert struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name) 2054c1d255d3SCy Schubert { 20554b72b91aSCy Schubert struct crypto_csr *csr = NULL; 2056c1d255d3SCy Schubert struct wpabuf *buf = NULL; 20574b72b91aSCy Schubert struct crypto_ec_key *key; 2058c1d255d3SCy Schubert unsigned int hash_len = auth->curve->hash_len; 20594b72b91aSCy Schubert struct wpabuf *priv_key; 2060c1d255d3SCy Schubert u8 cp[DPP_CP_LEN]; 20614b72b91aSCy Schubert char *password = NULL; 2062c1d255d3SCy Schubert size_t password_len; 20634b72b91aSCy Schubert int hash_sign_algo; 2064c1d255d3SCy Schubert 2065c1d255d3SCy Schubert /* TODO: use auth->csrattrs */ 2066c1d255d3SCy Schubert 2067c1d255d3SCy Schubert /* TODO: support generation of a new private key if csrAttrs requests 2068c1d255d3SCy Schubert * a specific group to be used */ 2069c1d255d3SCy Schubert key = auth->own_protocol_key; 2070c1d255d3SCy Schubert 20714b72b91aSCy Schubert priv_key = crypto_ec_key_get_ecprivate_key(key, true); 20724b72b91aSCy Schubert if (!priv_key) 2073c1d255d3SCy Schubert goto fail; 2074c1d255d3SCy Schubert wpabuf_free(auth->priv_key); 20754b72b91aSCy Schubert auth->priv_key = priv_key; 20764b72b91aSCy Schubert 20774b72b91aSCy Schubert csr = crypto_csr_init(); 20784b72b91aSCy Schubert if (!csr || crypto_csr_set_ec_public_key(csr, key)) 2079c1d255d3SCy Schubert goto fail; 2080c1d255d3SCy Schubert 20814b72b91aSCy Schubert if (name && crypto_csr_set_name(csr, CSR_NAME_CN, name)) 2082c1d255d3SCy Schubert goto fail; 2083c1d255d3SCy Schubert 2084c1d255d3SCy Schubert /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ 2085c1d255d3SCy Schubert if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, 2086c1d255d3SCy Schubert "CSR challengePassword", cp, DPP_CP_LEN) < 0) 2087c1d255d3SCy Schubert goto fail; 2088c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 2089c1d255d3SCy Schubert "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", 2090c1d255d3SCy Schubert cp, DPP_CP_LEN); 2091c1d255d3SCy Schubert password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len); 2092c1d255d3SCy Schubert forced_memzero(cp, DPP_CP_LEN); 20934b72b91aSCy Schubert if (!password || 20944b72b91aSCy Schubert crypto_csr_set_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD, 20954b72b91aSCy Schubert ASN1_TAG_UTF8STRING, (const u8 *) password, 20964b72b91aSCy Schubert password_len)) 2097c1d255d3SCy Schubert goto fail; 2098c1d255d3SCy Schubert 2099c1d255d3SCy Schubert /* TODO: hash func selection based on csrAttrs */ 2100c1d255d3SCy Schubert if (hash_len == SHA256_MAC_LEN) { 21014b72b91aSCy Schubert hash_sign_algo = CRYPTO_HASH_ALG_SHA256; 2102c1d255d3SCy Schubert } else if (hash_len == SHA384_MAC_LEN) { 21034b72b91aSCy Schubert hash_sign_algo = CRYPTO_HASH_ALG_SHA384; 2104c1d255d3SCy Schubert } else if (hash_len == SHA512_MAC_LEN) { 21054b72b91aSCy Schubert hash_sign_algo = CRYPTO_HASH_ALG_SHA512; 2106c1d255d3SCy Schubert } else { 2107c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); 2108c1d255d3SCy Schubert goto fail; 2109c1d255d3SCy Schubert } 2110c1d255d3SCy Schubert 21114b72b91aSCy Schubert buf = crypto_csr_sign(csr, key, hash_sign_algo); 21124b72b91aSCy Schubert if (!buf) 2113c1d255d3SCy Schubert goto fail; 2114c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf); 2115c1d255d3SCy Schubert 2116c1d255d3SCy Schubert fail: 21174b72b91aSCy Schubert bin_clear_free(password, password_len); 21184b72b91aSCy Schubert crypto_csr_deinit(csr); 2119c1d255d3SCy Schubert return buf; 2120c1d255d3SCy Schubert } 2121c1d255d3SCy Schubert 2122c1d255d3SCy Schubert 21234b72b91aSCy Schubert int dpp_validate_csr(struct dpp_authentication *auth, 21244b72b91aSCy Schubert const struct wpabuf *csrbuf) 2125c1d255d3SCy Schubert { 21264b72b91aSCy Schubert struct crypto_csr *csr; 21274b72b91aSCy Schubert const u8 *attr; 21284b72b91aSCy Schubert size_t attr_len; 21294b72b91aSCy Schubert int attr_type; 2130c1d255d3SCy Schubert unsigned char *cp = NULL; 2131c1d255d3SCy Schubert size_t cp_len; 2132c1d255d3SCy Schubert u8 exp_cp[DPP_CP_LEN]; 2133c1d255d3SCy Schubert unsigned int hash_len = auth->curve->hash_len; 21344b72b91aSCy Schubert int ret = -1; 2135c1d255d3SCy Schubert 21364b72b91aSCy Schubert csr = crypto_csr_verify(csrbuf); 21374b72b91aSCy Schubert if (!csr) { 2138db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 21394b72b91aSCy Schubert "DPP: CSR invalid or invalid signature"); 2140db0ac6deSCy Schubert goto fail; 2141db0ac6deSCy Schubert } 2142db0ac6deSCy Schubert 21434b72b91aSCy Schubert attr = crypto_csr_get_attribute(csr, CSR_ATTR_CHALLENGE_PASSWORD, 21444b72b91aSCy Schubert &attr_len, &attr_type); 21454b72b91aSCy Schubert if (!attr) { 2146c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2147c1d255d3SCy Schubert "DPP: CSR does not include challengePassword"); 2148c1d255d3SCy Schubert goto fail; 2149c1d255d3SCy Schubert } 2150db0ac6deSCy Schubert /* This is supposed to be UTF8String, but allow other strings as well 2151db0ac6deSCy Schubert * since challengePassword is using ASCII (base64 encoded). */ 21524b72b91aSCy Schubert if (attr_type != ASN1_TAG_UTF8STRING && 21534b72b91aSCy Schubert attr_type != ASN1_TAG_PRINTABLESTRING && 21544b72b91aSCy Schubert attr_type != ASN1_TAG_IA5STRING) { 2155db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 2156db0ac6deSCy Schubert "DPP: Unexpected challengePassword attribute type %d", 21574b72b91aSCy Schubert attr_type); 2158db0ac6deSCy Schubert goto fail; 2159db0ac6deSCy Schubert } 2160db0ac6deSCy Schubert 21614b72b91aSCy Schubert cp = base64_decode((const char *) attr, attr_len, &cp_len); 2162c1d255d3SCy Schubert if (!cp) { 2163c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2164c1d255d3SCy Schubert "DPP: Could not base64 decode challengePassword"); 2165c1d255d3SCy Schubert goto fail; 2166c1d255d3SCy Schubert } 2167c1d255d3SCy Schubert if (cp_len != DPP_CP_LEN) { 2168c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2169c1d255d3SCy Schubert "DPP: Unexpected cp length (%zu) in CSR challengePassword", 2170c1d255d3SCy Schubert cp_len); 2171c1d255d3SCy Schubert goto fail; 2172c1d255d3SCy Schubert } 2173c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword", 2174c1d255d3SCy Schubert cp, cp_len); 2175c1d255d3SCy Schubert 2176c1d255d3SCy Schubert /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ 2177c1d255d3SCy Schubert if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, 2178c1d255d3SCy Schubert "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0) 2179c1d255d3SCy Schubert goto fail; 2180c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 2181c1d255d3SCy Schubert "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", 2182c1d255d3SCy Schubert exp_cp, DPP_CP_LEN); 2183c1d255d3SCy Schubert if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) { 2184c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2185c1d255d3SCy Schubert "DPP: CSR challengePassword does not match calculated cp"); 2186c1d255d3SCy Schubert goto fail; 2187c1d255d3SCy Schubert } 2188c1d255d3SCy Schubert 2189c1d255d3SCy Schubert ret = 0; 2190c1d255d3SCy Schubert fail: 2191c1d255d3SCy Schubert os_free(cp); 21924b72b91aSCy Schubert crypto_csr_deinit(csr); 2193c1d255d3SCy Schubert return ret; 2194c1d255d3SCy Schubert } 2195c1d255d3SCy Schubert 2196c1d255d3SCy Schubert 2197c1d255d3SCy Schubert struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, 2198c1d255d3SCy Schubert size_t csign_key_len, 2199c1d255d3SCy Schubert const u8 *pp_key, 2200c1d255d3SCy Schubert size_t pp_key_len) 2201c1d255d3SCy Schubert { 22024b72b91aSCy Schubert struct crypto_ec_key *csign = NULL, *ppkey = NULL; 2203c1d255d3SCy Schubert struct dpp_reconfig_id *id = NULL; 22044b72b91aSCy Schubert struct crypto_ec *ec = NULL; 22054b72b91aSCy Schubert const struct crypto_bignum *q; 22064b72b91aSCy Schubert struct crypto_bignum *bn = NULL; 22074b72b91aSCy Schubert struct crypto_ec_point *e_id = NULL; 22084b72b91aSCy Schubert const struct crypto_ec_point *generator; 2209c1d255d3SCy Schubert 22104b72b91aSCy Schubert csign = crypto_ec_key_parse_pub(csign_key, csign_key_len); 2211c1d255d3SCy Schubert if (!csign) 2212c1d255d3SCy Schubert goto fail; 2213c1d255d3SCy Schubert 2214c1d255d3SCy Schubert if (!pp_key) 2215c1d255d3SCy Schubert goto fail; 22164b72b91aSCy Schubert ppkey = crypto_ec_key_parse_pub(pp_key, pp_key_len); 2217c1d255d3SCy Schubert if (!ppkey) 2218c1d255d3SCy Schubert goto fail; 2219c1d255d3SCy Schubert 22204b72b91aSCy Schubert ec = crypto_ec_init(crypto_ec_key_group(csign)); 22214b72b91aSCy Schubert if (!ec) 2222c1d255d3SCy Schubert goto fail; 2223c1d255d3SCy Schubert 22244b72b91aSCy Schubert e_id = crypto_ec_point_init(ec); 22254b72b91aSCy Schubert bn = crypto_bignum_init(); 22264b72b91aSCy Schubert q = crypto_ec_get_order(ec); 22274b72b91aSCy Schubert generator = crypto_ec_get_generator(ec); 22284b72b91aSCy Schubert if (!e_id || !bn || !q || !generator || 22294b72b91aSCy Schubert crypto_bignum_rand(bn, q) || 22304b72b91aSCy Schubert crypto_ec_point_mul(ec, generator, bn, e_id)) 2231c1d255d3SCy Schubert goto fail; 2232c1d255d3SCy Schubert 22334b72b91aSCy Schubert crypto_ec_point_debug_print(ec, e_id, 22344b72b91aSCy Schubert "DPP: Generated random point E-id"); 2235c1d255d3SCy Schubert 2236c1d255d3SCy Schubert id = os_zalloc(sizeof(*id)); 2237c1d255d3SCy Schubert if (!id) 2238c1d255d3SCy Schubert goto fail; 22394b72b91aSCy Schubert 22404b72b91aSCy Schubert id->ec = ec; 22414b72b91aSCy Schubert ec = NULL; 2242c1d255d3SCy Schubert id->e_id = e_id; 2243c1d255d3SCy Schubert e_id = NULL; 2244c1d255d3SCy Schubert id->csign = csign; 2245c1d255d3SCy Schubert csign = NULL; 2246c1d255d3SCy Schubert id->pp_key = ppkey; 2247c1d255d3SCy Schubert ppkey = NULL; 2248c1d255d3SCy Schubert fail: 22494b72b91aSCy Schubert crypto_ec_point_deinit(e_id, 1); 22504b72b91aSCy Schubert crypto_ec_key_deinit(csign); 22514b72b91aSCy Schubert crypto_ec_key_deinit(ppkey); 22524b72b91aSCy Schubert crypto_bignum_deinit(bn, 1); 22534b72b91aSCy Schubert crypto_ec_deinit(ec); 2254c1d255d3SCy Schubert return id; 2255c1d255d3SCy Schubert } 2256c1d255d3SCy Schubert 2257c1d255d3SCy Schubert 2258c1d255d3SCy Schubert int dpp_update_reconfig_id(struct dpp_reconfig_id *id) 2259c1d255d3SCy Schubert { 22604b72b91aSCy Schubert const struct crypto_bignum *q; 22614b72b91aSCy Schubert struct crypto_bignum *bn; 22624b72b91aSCy Schubert const struct crypto_ec_point *pp, *generator; 22634b72b91aSCy Schubert struct crypto_ec_point *e_prime_id, *a_nonce; 2264c1d255d3SCy Schubert int ret = -1; 2265c1d255d3SCy Schubert 22664b72b91aSCy Schubert pp = crypto_ec_key_get_public_key(id->pp_key); 22674b72b91aSCy Schubert e_prime_id = crypto_ec_point_init(id->ec); 22684b72b91aSCy Schubert a_nonce = crypto_ec_point_init(id->ec); 22694b72b91aSCy Schubert bn = crypto_bignum_init(); 22704b72b91aSCy Schubert q = crypto_ec_get_order(id->ec); 22714b72b91aSCy Schubert generator = crypto_ec_get_generator(id->ec); 22724b72b91aSCy Schubert 2273c1d255d3SCy Schubert /* Generate random 0 <= a-nonce < q 2274c1d255d3SCy Schubert * A-NONCE = a-nonce * G 2275c1d255d3SCy Schubert * E'-id = E-id + a-nonce * P_pk */ 22764b72b91aSCy Schubert if (!pp || !e_prime_id || !a_nonce || !bn || !q || !generator || 22774b72b91aSCy Schubert crypto_bignum_rand(bn, q) || /* bn = a-nonce */ 22784b72b91aSCy Schubert crypto_ec_point_mul(id->ec, generator, bn, a_nonce) || 22794b72b91aSCy Schubert crypto_ec_point_mul(id->ec, pp, bn, e_prime_id) || 22804b72b91aSCy Schubert crypto_ec_point_add(id->ec, id->e_id, e_prime_id, e_prime_id)) 2281c1d255d3SCy Schubert goto fail; 2282c1d255d3SCy Schubert 22834b72b91aSCy Schubert crypto_ec_point_debug_print(id->ec, a_nonce, 22844b72b91aSCy Schubert "DPP: Generated A-NONCE"); 22854b72b91aSCy Schubert crypto_ec_point_debug_print(id->ec, e_prime_id, 22864b72b91aSCy Schubert "DPP: Encrypted E-id to E'-id"); 2287c1d255d3SCy Schubert 22884b72b91aSCy Schubert crypto_ec_key_deinit(id->a_nonce); 22894b72b91aSCy Schubert crypto_ec_key_deinit(id->e_prime_id); 22904b72b91aSCy Schubert id->a_nonce = crypto_ec_key_set_pub_point(id->ec, a_nonce); 22914b72b91aSCy Schubert id->e_prime_id = crypto_ec_key_set_pub_point(id->ec, e_prime_id); 2292c1d255d3SCy Schubert if (!id->a_nonce || !id->e_prime_id) 2293c1d255d3SCy Schubert goto fail; 2294c1d255d3SCy Schubert 2295c1d255d3SCy Schubert ret = 0; 2296c1d255d3SCy Schubert 2297c1d255d3SCy Schubert fail: 22984b72b91aSCy Schubert crypto_ec_point_deinit(e_prime_id, 1); 22994b72b91aSCy Schubert crypto_ec_point_deinit(a_nonce, 1); 23004b72b91aSCy Schubert crypto_bignum_deinit(bn, 1); 2301c1d255d3SCy Schubert return ret; 2302c1d255d3SCy Schubert } 2303c1d255d3SCy Schubert 2304c1d255d3SCy Schubert 2305c1d255d3SCy Schubert void dpp_free_reconfig_id(struct dpp_reconfig_id *id) 2306c1d255d3SCy Schubert { 2307c1d255d3SCy Schubert if (id) { 23084b72b91aSCy Schubert crypto_ec_point_deinit(id->e_id, 1); 23094b72b91aSCy Schubert crypto_ec_key_deinit(id->csign); 23104b72b91aSCy Schubert crypto_ec_key_deinit(id->a_nonce); 23114b72b91aSCy Schubert crypto_ec_key_deinit(id->e_prime_id); 23124b72b91aSCy Schubert crypto_ec_key_deinit(id->pp_key); 23134b72b91aSCy Schubert crypto_ec_deinit(id->ec); 2314c1d255d3SCy Schubert os_free(id); 2315c1d255d3SCy Schubert } 2316c1d255d3SCy Schubert } 2317c1d255d3SCy Schubert 2318c1d255d3SCy Schubert 23194b72b91aSCy Schubert struct crypto_ec_point * dpp_decrypt_e_id(struct crypto_ec_key *ppkey, 23204b72b91aSCy Schubert struct crypto_ec_key *a_nonce, 23214b72b91aSCy Schubert struct crypto_ec_key *e_prime_id) 2322c1d255d3SCy Schubert { 23234b72b91aSCy Schubert struct crypto_ec *ec; 23244b72b91aSCy Schubert const struct crypto_bignum *pp; 23254b72b91aSCy Schubert struct crypto_ec_point *e_id = NULL; 23264b72b91aSCy Schubert const struct crypto_ec_point *a_nonce_point, *e_prime_id_point; 2327c1d255d3SCy Schubert 2328c1d255d3SCy Schubert if (!ppkey) 2329c1d255d3SCy Schubert return NULL; 2330c1d255d3SCy Schubert 2331c1d255d3SCy Schubert /* E-id = E'-id - s_C * A-NONCE */ 23324b72b91aSCy Schubert ec = crypto_ec_init(crypto_ec_key_group(ppkey)); 23334b72b91aSCy Schubert if (!ec) 2334c1d255d3SCy Schubert return NULL; 23354b72b91aSCy Schubert 23364b72b91aSCy Schubert pp = crypto_ec_key_get_private_key(ppkey); 23374b72b91aSCy Schubert a_nonce_point = crypto_ec_key_get_public_key(a_nonce); 23384b72b91aSCy Schubert e_prime_id_point = crypto_ec_key_get_public_key(e_prime_id); 23394b72b91aSCy Schubert e_id = crypto_ec_point_init(ec); 23404b72b91aSCy Schubert if (!pp || !a_nonce_point || !e_prime_id_point || !e_id || 23414b72b91aSCy Schubert crypto_ec_point_mul(ec, a_nonce_point, pp, e_id) || 23424b72b91aSCy Schubert crypto_ec_point_invert(ec, e_id) || 23434b72b91aSCy Schubert crypto_ec_point_add(ec, e_id, e_prime_id_point, e_id)) { 23444b72b91aSCy Schubert crypto_ec_point_deinit(e_id, 1); 2345c1d255d3SCy Schubert goto fail; 2346c1d255d3SCy Schubert } 2347c1d255d3SCy Schubert 23484b72b91aSCy Schubert crypto_ec_point_debug_print(ec, e_id, "DPP: Decrypted E-id"); 2349c1d255d3SCy Schubert 2350c1d255d3SCy Schubert fail: 23514b72b91aSCy Schubert crypto_ec_deinit(ec); 2352c1d255d3SCy Schubert return e_id; 2353c1d255d3SCy Schubert } 2354c1d255d3SCy Schubert 2355c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 2356c1d255d3SCy Schubert 2357c1d255d3SCy Schubert 2358c1d255d3SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 2359c1d255d3SCy Schubert 2360c1d255d3SCy Schubert int dpp_test_gen_invalid_key(struct wpabuf *msg, 2361c1d255d3SCy Schubert const struct dpp_curve_params *curve) 2362c1d255d3SCy Schubert { 23634b72b91aSCy Schubert struct crypto_ec *ec; 23644b72b91aSCy Schubert struct crypto_ec_key *key = NULL; 23654b72b91aSCy Schubert const struct crypto_ec_point *pub_key; 23664b72b91aSCy Schubert struct crypto_ec_point *p = NULL; 23674b72b91aSCy Schubert u8 *x, *y; 2368c1d255d3SCy Schubert int ret = -1; 2369c1d255d3SCy Schubert 23704b72b91aSCy Schubert ec = crypto_ec_init(curve->ike_group); 23714b72b91aSCy Schubert x = wpabuf_put(msg, curve->prime_len); 23724b72b91aSCy Schubert y = wpabuf_put(msg, curve->prime_len); 23734b72b91aSCy Schubert if (!ec) 2374c1d255d3SCy Schubert goto fail; 2375c1d255d3SCy Schubert 23764b72b91aSCy Schubert retry: 23774b72b91aSCy Schubert /* Generate valid key pair */ 23784b72b91aSCy Schubert key = crypto_ec_key_gen(curve->ike_group); 23794b72b91aSCy Schubert if (!key) 2380c1d255d3SCy Schubert goto fail; 2381c1d255d3SCy Schubert 23824b72b91aSCy Schubert /* Retrieve public key coordinates */ 23834b72b91aSCy Schubert pub_key = crypto_ec_key_get_public_key(key); 23844b72b91aSCy Schubert if (!pub_key) 2385c1d255d3SCy Schubert goto fail; 2386c1d255d3SCy Schubert 23874b72b91aSCy Schubert crypto_ec_point_to_bin(ec, pub_key, x, y); 23884b72b91aSCy Schubert 23894b72b91aSCy Schubert /* And corrupt them */ 23904b72b91aSCy Schubert y[curve->prime_len - 1] ^= 0x01; 23914b72b91aSCy Schubert p = crypto_ec_point_from_bin(ec, x); 23924b72b91aSCy Schubert if (p && crypto_ec_point_is_on_curve(ec, p)) { 23934b72b91aSCy Schubert crypto_ec_point_deinit(p, 0); 23944b72b91aSCy Schubert p = NULL; 23954b72b91aSCy Schubert goto retry; 2396c1d255d3SCy Schubert } 2397c1d255d3SCy Schubert 2398c1d255d3SCy Schubert ret = 0; 2399c1d255d3SCy Schubert fail: 24004b72b91aSCy Schubert crypto_ec_point_deinit(p, 0); 24014b72b91aSCy Schubert crypto_ec_key_deinit(key); 24024b72b91aSCy Schubert crypto_ec_deinit(ec); 2403c1d255d3SCy Schubert return ret; 2404c1d255d3SCy Schubert } 2405c1d255d3SCy Schubert 2406c1d255d3SCy Schubert 2407c1d255d3SCy Schubert char * dpp_corrupt_connector_signature(const char *connector) 2408c1d255d3SCy Schubert { 2409c1d255d3SCy Schubert char *tmp, *pos, *signed3 = NULL; 2410c1d255d3SCy Schubert unsigned char *signature = NULL; 2411c1d255d3SCy Schubert size_t signature_len = 0, signed3_len; 2412c1d255d3SCy Schubert 2413c1d255d3SCy Schubert tmp = os_zalloc(os_strlen(connector) + 5); 2414c1d255d3SCy Schubert if (!tmp) 2415c1d255d3SCy Schubert goto fail; 2416c1d255d3SCy Schubert os_memcpy(tmp, connector, os_strlen(connector)); 2417c1d255d3SCy Schubert 2418c1d255d3SCy Schubert pos = os_strchr(tmp, '.'); 2419c1d255d3SCy Schubert if (!pos) 2420c1d255d3SCy Schubert goto fail; 2421c1d255d3SCy Schubert 2422c1d255d3SCy Schubert pos = os_strchr(pos + 1, '.'); 2423c1d255d3SCy Schubert if (!pos) 2424c1d255d3SCy Schubert goto fail; 2425c1d255d3SCy Schubert pos++; 2426c1d255d3SCy Schubert 2427c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s", 2428c1d255d3SCy Schubert pos); 2429c1d255d3SCy Schubert signature = base64_url_decode(pos, os_strlen(pos), &signature_len); 2430c1d255d3SCy Schubert if (!signature || signature_len == 0) 2431c1d255d3SCy Schubert goto fail; 2432c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature", 2433c1d255d3SCy Schubert signature, signature_len); 2434c1d255d3SCy Schubert signature[signature_len - 1] ^= 0x01; 2435c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature", 2436c1d255d3SCy Schubert signature, signature_len); 2437c1d255d3SCy Schubert signed3 = base64_url_encode(signature, signature_len, &signed3_len); 2438c1d255d3SCy Schubert if (!signed3) 2439c1d255d3SCy Schubert goto fail; 2440c1d255d3SCy Schubert os_memcpy(pos, signed3, signed3_len); 2441c1d255d3SCy Schubert pos[signed3_len] = '\0'; 2442c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s", 2443c1d255d3SCy Schubert pos); 2444c1d255d3SCy Schubert 2445c1d255d3SCy Schubert out: 2446c1d255d3SCy Schubert os_free(signature); 2447c1d255d3SCy Schubert os_free(signed3); 2448c1d255d3SCy Schubert return tmp; 2449c1d255d3SCy Schubert fail: 2450c1d255d3SCy Schubert os_free(tmp); 2451c1d255d3SCy Schubert tmp = NULL; 2452c1d255d3SCy Schubert goto out; 2453c1d255d3SCy Schubert } 2454c1d255d3SCy Schubert 2455c1d255d3SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 2456