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" 11*db0ac6deSCy Schubert #include <openssl/opensslv.h> 12*db0ac6deSCy Schubert #include <openssl/err.h> 13*db0ac6deSCy Schubert #include <openssl/asn1.h> 14*db0ac6deSCy Schubert #include <openssl/asn1t.h> 15*db0ac6deSCy Schubert #include <openssl/pem.h> 16c1d255d3SCy Schubert 17c1d255d3SCy Schubert #include "utils/common.h" 18c1d255d3SCy Schubert #include "utils/base64.h" 19c1d255d3SCy Schubert #include "utils/json.h" 20c1d255d3SCy Schubert #include "common/ieee802_11_defs.h" 21c1d255d3SCy Schubert #include "crypto/crypto.h" 22c1d255d3SCy Schubert #include "crypto/random.h" 23c1d255d3SCy Schubert #include "crypto/sha384.h" 24c1d255d3SCy Schubert #include "crypto/sha512.h" 25c1d255d3SCy Schubert #include "dpp.h" 26c1d255d3SCy Schubert #include "dpp_i.h" 27c1d255d3SCy Schubert 28c1d255d3SCy Schubert 29*db0ac6deSCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ 30*db0ac6deSCy Schubert (defined(LIBRESSL_VERSION_NUMBER) && \ 31*db0ac6deSCy Schubert LIBRESSL_VERSION_NUMBER < 0x20700000L) 32*db0ac6deSCy Schubert /* Compatibility wrappers for older versions. */ 33*db0ac6deSCy Schubert 34*db0ac6deSCy Schubert static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) 35*db0ac6deSCy Schubert { 36*db0ac6deSCy Schubert sig->r = r; 37*db0ac6deSCy Schubert sig->s = s; 38*db0ac6deSCy Schubert return 1; 39*db0ac6deSCy Schubert } 40*db0ac6deSCy Schubert 41*db0ac6deSCy Schubert 42*db0ac6deSCy Schubert static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, 43*db0ac6deSCy Schubert const BIGNUM **ps) 44*db0ac6deSCy Schubert { 45*db0ac6deSCy Schubert if (pr) 46*db0ac6deSCy Schubert *pr = sig->r; 47*db0ac6deSCy Schubert if (ps) 48*db0ac6deSCy Schubert *ps = sig->s; 49*db0ac6deSCy Schubert } 50*db0ac6deSCy Schubert 51*db0ac6deSCy Schubert 52*db0ac6deSCy Schubert static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) 53*db0ac6deSCy Schubert { 54*db0ac6deSCy Schubert if (pkey->type != EVP_PKEY_EC) 55*db0ac6deSCy Schubert return NULL; 56*db0ac6deSCy Schubert return pkey->pkey.ec; 57*db0ac6deSCy Schubert } 58*db0ac6deSCy Schubert 59*db0ac6deSCy Schubert #endif 60*db0ac6deSCy Schubert 61c1d255d3SCy Schubert static const struct dpp_curve_params dpp_curves[] = { 62c1d255d3SCy Schubert /* The mandatory to support and the default NIST P-256 curve needs to 63c1d255d3SCy Schubert * be the first entry on this list. */ 64c1d255d3SCy Schubert { "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" }, 65c1d255d3SCy Schubert { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" }, 66c1d255d3SCy Schubert { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" }, 67c1d255d3SCy Schubert { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" }, 68c1d255d3SCy Schubert { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" }, 69c1d255d3SCy Schubert { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" }, 70c1d255d3SCy Schubert { NULL, 0, 0, 0, 0, NULL, 0, NULL } 71c1d255d3SCy Schubert }; 72c1d255d3SCy Schubert 73c1d255d3SCy Schubert 74c1d255d3SCy Schubert const struct dpp_curve_params * dpp_get_curve_name(const char *name) 75c1d255d3SCy Schubert { 76c1d255d3SCy Schubert int i; 77c1d255d3SCy Schubert 78c1d255d3SCy Schubert if (!name) 79c1d255d3SCy Schubert return &dpp_curves[0]; 80c1d255d3SCy Schubert 81c1d255d3SCy Schubert for (i = 0; dpp_curves[i].name; i++) { 82c1d255d3SCy Schubert if (os_strcmp(name, dpp_curves[i].name) == 0 || 83c1d255d3SCy Schubert (dpp_curves[i].jwk_crv && 84c1d255d3SCy Schubert os_strcmp(name, dpp_curves[i].jwk_crv) == 0)) 85c1d255d3SCy Schubert return &dpp_curves[i]; 86c1d255d3SCy Schubert } 87c1d255d3SCy Schubert return NULL; 88c1d255d3SCy Schubert } 89c1d255d3SCy Schubert 90c1d255d3SCy Schubert 91c1d255d3SCy Schubert const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name) 92c1d255d3SCy Schubert { 93c1d255d3SCy Schubert int i; 94c1d255d3SCy Schubert 95c1d255d3SCy Schubert for (i = 0; dpp_curves[i].name; i++) { 96c1d255d3SCy Schubert if (dpp_curves[i].jwk_crv && 97c1d255d3SCy Schubert os_strcmp(name, dpp_curves[i].jwk_crv) == 0) 98c1d255d3SCy Schubert return &dpp_curves[i]; 99c1d255d3SCy Schubert } 100c1d255d3SCy Schubert return NULL; 101c1d255d3SCy Schubert } 102c1d255d3SCy Schubert 103c1d255d3SCy Schubert 104*db0ac6deSCy Schubert static const struct dpp_curve_params * 105*db0ac6deSCy Schubert dpp_get_curve_oid(const ASN1_OBJECT *poid) 106*db0ac6deSCy Schubert { 107*db0ac6deSCy Schubert ASN1_OBJECT *oid; 108*db0ac6deSCy Schubert int i; 109*db0ac6deSCy Schubert 110*db0ac6deSCy Schubert for (i = 0; dpp_curves[i].name; i++) { 111*db0ac6deSCy Schubert oid = OBJ_txt2obj(dpp_curves[i].name, 0); 112*db0ac6deSCy Schubert if (oid && OBJ_cmp(poid, oid) == 0) 113*db0ac6deSCy Schubert return &dpp_curves[i]; 114*db0ac6deSCy Schubert } 115*db0ac6deSCy Schubert return NULL; 116*db0ac6deSCy Schubert } 117*db0ac6deSCy Schubert 118*db0ac6deSCy Schubert 119*db0ac6deSCy Schubert const struct dpp_curve_params * dpp_get_curve_nid(int nid) 120*db0ac6deSCy Schubert { 121*db0ac6deSCy Schubert int i, tmp; 122*db0ac6deSCy Schubert 123*db0ac6deSCy Schubert if (!nid) 124*db0ac6deSCy Schubert return NULL; 125*db0ac6deSCy Schubert for (i = 0; dpp_curves[i].name; i++) { 126*db0ac6deSCy Schubert tmp = OBJ_txt2nid(dpp_curves[i].name); 127*db0ac6deSCy Schubert if (tmp == nid) 128*db0ac6deSCy Schubert return &dpp_curves[i]; 129*db0ac6deSCy Schubert } 130*db0ac6deSCy Schubert return NULL; 131*db0ac6deSCy Schubert } 132*db0ac6deSCy Schubert 133*db0ac6deSCy Schubert 134c1d255d3SCy Schubert const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group) 135c1d255d3SCy Schubert { 136c1d255d3SCy Schubert int i; 137c1d255d3SCy Schubert 138c1d255d3SCy Schubert for (i = 0; dpp_curves[i].name; i++) { 139c1d255d3SCy Schubert if (dpp_curves[i].ike_group == group) 140c1d255d3SCy Schubert return &dpp_curves[i]; 141c1d255d3SCy Schubert } 142c1d255d3SCy Schubert return NULL; 143c1d255d3SCy Schubert } 144c1d255d3SCy Schubert 145c1d255d3SCy Schubert 146*db0ac6deSCy Schubert void dpp_debug_print_point(const char *title, const EC_GROUP *group, 147*db0ac6deSCy Schubert const EC_POINT *point) 148c1d255d3SCy Schubert { 149*db0ac6deSCy Schubert BIGNUM *x, *y; 150*db0ac6deSCy Schubert BN_CTX *ctx; 151*db0ac6deSCy Schubert char *x_str = NULL, *y_str = NULL; 152c1d255d3SCy Schubert 153*db0ac6deSCy Schubert if (!wpa_debug_show_keys) 154*db0ac6deSCy Schubert return; 155c1d255d3SCy Schubert 156*db0ac6deSCy Schubert ctx = BN_CTX_new(); 157*db0ac6deSCy Schubert x = BN_new(); 158*db0ac6deSCy Schubert y = BN_new(); 159*db0ac6deSCy Schubert if (!ctx || !x || !y || 160*db0ac6deSCy Schubert EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) != 1) 161*db0ac6deSCy Schubert goto fail; 162*db0ac6deSCy Schubert 163*db0ac6deSCy Schubert x_str = BN_bn2hex(x); 164*db0ac6deSCy Schubert y_str = BN_bn2hex(y); 165*db0ac6deSCy Schubert if (!x_str || !y_str) 166*db0ac6deSCy Schubert goto fail; 167*db0ac6deSCy Schubert 168*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str); 169*db0ac6deSCy Schubert 170*db0ac6deSCy Schubert fail: 171*db0ac6deSCy Schubert OPENSSL_free(x_str); 172*db0ac6deSCy Schubert OPENSSL_free(y_str); 173*db0ac6deSCy Schubert BN_free(x); 174*db0ac6deSCy Schubert BN_free(y); 175*db0ac6deSCy Schubert BN_CTX_free(ctx); 176c1d255d3SCy Schubert } 177c1d255d3SCy Schubert 178*db0ac6deSCy Schubert 179*db0ac6deSCy Schubert void dpp_debug_print_key(const char *title, EVP_PKEY *key) 180*db0ac6deSCy Schubert { 181*db0ac6deSCy Schubert EC_KEY *eckey; 182*db0ac6deSCy Schubert BIO *out; 183*db0ac6deSCy Schubert size_t rlen; 184*db0ac6deSCy Schubert char *txt; 185*db0ac6deSCy Schubert int res; 186*db0ac6deSCy Schubert unsigned char *der = NULL; 187*db0ac6deSCy Schubert int der_len; 188*db0ac6deSCy Schubert const EC_GROUP *group; 189*db0ac6deSCy Schubert const EC_POINT *point; 190*db0ac6deSCy Schubert 191*db0ac6deSCy Schubert out = BIO_new(BIO_s_mem()); 192*db0ac6deSCy Schubert if (!out) 193*db0ac6deSCy Schubert return; 194*db0ac6deSCy Schubert 195*db0ac6deSCy Schubert EVP_PKEY_print_private(out, key, 0, NULL); 196*db0ac6deSCy Schubert rlen = BIO_ctrl_pending(out); 197*db0ac6deSCy Schubert txt = os_malloc(rlen + 1); 198*db0ac6deSCy Schubert if (txt) { 199*db0ac6deSCy Schubert res = BIO_read(out, txt, rlen); 200*db0ac6deSCy Schubert if (res > 0) { 201*db0ac6deSCy Schubert txt[res] = '\0'; 202*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "%s: %s", title, txt); 203*db0ac6deSCy Schubert } 204*db0ac6deSCy Schubert os_free(txt); 205*db0ac6deSCy Schubert } 206*db0ac6deSCy Schubert BIO_free(out); 207*db0ac6deSCy Schubert 208*db0ac6deSCy Schubert eckey = EVP_PKEY_get1_EC_KEY(key); 209*db0ac6deSCy Schubert if (!eckey) 210*db0ac6deSCy Schubert return; 211*db0ac6deSCy Schubert 212*db0ac6deSCy Schubert group = EC_KEY_get0_group(eckey); 213*db0ac6deSCy Schubert point = EC_KEY_get0_public_key(eckey); 214*db0ac6deSCy Schubert if (group && point) 215*db0ac6deSCy Schubert dpp_debug_print_point(title, group, point); 216*db0ac6deSCy Schubert 217*db0ac6deSCy Schubert der_len = i2d_ECPrivateKey(eckey, &der); 218*db0ac6deSCy Schubert if (der_len > 0) 219*db0ac6deSCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len); 220*db0ac6deSCy Schubert OPENSSL_free(der); 221*db0ac6deSCy Schubert if (der_len <= 0) { 222*db0ac6deSCy Schubert der = NULL; 223*db0ac6deSCy Schubert der_len = i2d_EC_PUBKEY(eckey, &der); 224*db0ac6deSCy Schubert if (der_len > 0) 225*db0ac6deSCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len); 226*db0ac6deSCy Schubert OPENSSL_free(der); 227*db0ac6deSCy Schubert } 228*db0ac6deSCy Schubert 229*db0ac6deSCy Schubert EC_KEY_free(eckey); 230c1d255d3SCy Schubert } 231c1d255d3SCy Schubert 232c1d255d3SCy Schubert 233c1d255d3SCy Schubert static int dpp_hash_vector(const struct dpp_curve_params *curve, 234c1d255d3SCy Schubert size_t num_elem, const u8 *addr[], const size_t *len, 235c1d255d3SCy Schubert u8 *mac) 236c1d255d3SCy Schubert { 237c1d255d3SCy Schubert if (curve->hash_len == 32) 238c1d255d3SCy Schubert return sha256_vector(num_elem, addr, len, mac); 239c1d255d3SCy Schubert if (curve->hash_len == 48) 240c1d255d3SCy Schubert return sha384_vector(num_elem, addr, len, mac); 241c1d255d3SCy Schubert if (curve->hash_len == 64) 242c1d255d3SCy Schubert return sha512_vector(num_elem, addr, len, mac); 243c1d255d3SCy Schubert return -1; 244c1d255d3SCy Schubert } 245c1d255d3SCy Schubert 246c1d255d3SCy Schubert 247c1d255d3SCy Schubert int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, 248c1d255d3SCy Schubert const char *label, u8 *out, size_t outlen) 249c1d255d3SCy Schubert { 250c1d255d3SCy Schubert if (hash_len == 32) 251c1d255d3SCy Schubert return hmac_sha256_kdf(secret, secret_len, NULL, 252c1d255d3SCy Schubert (const u8 *) label, os_strlen(label), 253c1d255d3SCy Schubert out, outlen); 254c1d255d3SCy Schubert if (hash_len == 48) 255c1d255d3SCy Schubert return hmac_sha384_kdf(secret, secret_len, NULL, 256c1d255d3SCy Schubert (const u8 *) label, os_strlen(label), 257c1d255d3SCy Schubert out, outlen); 258c1d255d3SCy Schubert if (hash_len == 64) 259c1d255d3SCy Schubert return hmac_sha512_kdf(secret, secret_len, NULL, 260c1d255d3SCy Schubert (const u8 *) label, os_strlen(label), 261c1d255d3SCy Schubert out, outlen); 262c1d255d3SCy Schubert return -1; 263c1d255d3SCy Schubert } 264c1d255d3SCy Schubert 265c1d255d3SCy Schubert 266c1d255d3SCy Schubert int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, 267c1d255d3SCy Schubert size_t num_elem, const u8 *addr[], const size_t *len, 268c1d255d3SCy Schubert u8 *mac) 269c1d255d3SCy Schubert { 270c1d255d3SCy Schubert if (hash_len == 32) 271c1d255d3SCy Schubert return hmac_sha256_vector(key, key_len, num_elem, addr, len, 272c1d255d3SCy Schubert mac); 273c1d255d3SCy Schubert if (hash_len == 48) 274c1d255d3SCy Schubert return hmac_sha384_vector(key, key_len, num_elem, addr, len, 275c1d255d3SCy Schubert mac); 276c1d255d3SCy Schubert if (hash_len == 64) 277c1d255d3SCy Schubert return hmac_sha512_vector(key, key_len, num_elem, addr, len, 278c1d255d3SCy Schubert mac); 279c1d255d3SCy Schubert return -1; 280c1d255d3SCy Schubert } 281c1d255d3SCy Schubert 282c1d255d3SCy Schubert 283c1d255d3SCy Schubert static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, 284c1d255d3SCy Schubert const u8 *data, size_t data_len, u8 *mac) 285c1d255d3SCy Schubert { 286c1d255d3SCy Schubert if (hash_len == 32) 287c1d255d3SCy Schubert return hmac_sha256(key, key_len, data, data_len, mac); 288c1d255d3SCy Schubert if (hash_len == 48) 289c1d255d3SCy Schubert return hmac_sha384(key, key_len, data, data_len, mac); 290c1d255d3SCy Schubert if (hash_len == 64) 291c1d255d3SCy Schubert return hmac_sha512(key, key_len, data, data_len, mac); 292c1d255d3SCy Schubert return -1; 293c1d255d3SCy Schubert } 294c1d255d3SCy Schubert 295c1d255d3SCy Schubert 296c1d255d3SCy Schubert #ifdef CONFIG_DPP2 297c1d255d3SCy Schubert 298c1d255d3SCy Schubert static int dpp_pbkdf2_f(size_t hash_len, 299c1d255d3SCy Schubert const u8 *password, size_t password_len, 300c1d255d3SCy Schubert const u8 *salt, size_t salt_len, 301c1d255d3SCy Schubert unsigned int iterations, unsigned int count, u8 *digest) 302c1d255d3SCy Schubert { 303c1d255d3SCy Schubert unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN]; 304c1d255d3SCy Schubert unsigned int i; 305c1d255d3SCy Schubert size_t j; 306c1d255d3SCy Schubert u8 count_buf[4]; 307c1d255d3SCy Schubert const u8 *addr[2]; 308c1d255d3SCy Schubert size_t len[2]; 309c1d255d3SCy Schubert 310c1d255d3SCy Schubert addr[0] = salt; 311c1d255d3SCy Schubert len[0] = salt_len; 312c1d255d3SCy Schubert addr[1] = count_buf; 313c1d255d3SCy Schubert len[1] = 4; 314c1d255d3SCy Schubert 315c1d255d3SCy Schubert /* F(P, S, c, i) = U1 xor U2 xor ... Uc 316c1d255d3SCy Schubert * U1 = PRF(P, S || i) 317c1d255d3SCy Schubert * U2 = PRF(P, U1) 318c1d255d3SCy Schubert * Uc = PRF(P, Uc-1) 319c1d255d3SCy Schubert */ 320c1d255d3SCy Schubert 321c1d255d3SCy Schubert WPA_PUT_BE32(count_buf, count); 322c1d255d3SCy Schubert if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len, 323c1d255d3SCy Schubert tmp)) 324c1d255d3SCy Schubert return -1; 325c1d255d3SCy Schubert os_memcpy(digest, tmp, hash_len); 326c1d255d3SCy Schubert 327c1d255d3SCy Schubert for (i = 1; i < iterations; i++) { 328c1d255d3SCy Schubert if (dpp_hmac(hash_len, password, password_len, tmp, hash_len, 329c1d255d3SCy Schubert tmp2)) 330c1d255d3SCy Schubert return -1; 331c1d255d3SCy Schubert os_memcpy(tmp, tmp2, hash_len); 332c1d255d3SCy Schubert for (j = 0; j < hash_len; j++) 333c1d255d3SCy Schubert digest[j] ^= tmp2[j]; 334c1d255d3SCy Schubert } 335c1d255d3SCy Schubert 336c1d255d3SCy Schubert return 0; 337c1d255d3SCy Schubert } 338c1d255d3SCy Schubert 339c1d255d3SCy Schubert 340c1d255d3SCy Schubert int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len, 341c1d255d3SCy Schubert const u8 *salt, size_t salt_len, unsigned int iterations, 342c1d255d3SCy Schubert u8 *buf, size_t buflen) 343c1d255d3SCy Schubert { 344c1d255d3SCy Schubert unsigned int count = 0; 345c1d255d3SCy Schubert unsigned char *pos = buf; 346c1d255d3SCy Schubert size_t left = buflen, plen; 347c1d255d3SCy Schubert unsigned char digest[DPP_MAX_HASH_LEN]; 348c1d255d3SCy Schubert 349c1d255d3SCy Schubert while (left > 0) { 350c1d255d3SCy Schubert count++; 351c1d255d3SCy Schubert if (dpp_pbkdf2_f(hash_len, password, password_len, 352c1d255d3SCy Schubert salt, salt_len, iterations, count, digest)) 353c1d255d3SCy Schubert return -1; 354c1d255d3SCy Schubert plen = left > hash_len ? hash_len : left; 355c1d255d3SCy Schubert os_memcpy(pos, digest, plen); 356c1d255d3SCy Schubert pos += plen; 357c1d255d3SCy Schubert left -= plen; 358c1d255d3SCy Schubert } 359c1d255d3SCy Schubert 360c1d255d3SCy Schubert return 0; 361c1d255d3SCy Schubert } 362c1d255d3SCy Schubert 363c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 364c1d255d3SCy Schubert 365c1d255d3SCy Schubert 366*db0ac6deSCy Schubert int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len) 367c1d255d3SCy Schubert { 368*db0ac6deSCy Schubert int num_bytes, offset; 369*db0ac6deSCy Schubert 370*db0ac6deSCy Schubert num_bytes = BN_num_bytes(bn); 371*db0ac6deSCy Schubert if ((size_t) num_bytes > len) 372*db0ac6deSCy Schubert return -1; 373*db0ac6deSCy Schubert offset = len - num_bytes; 374*db0ac6deSCy Schubert os_memset(pos, 0, offset); 375*db0ac6deSCy Schubert BN_bn2bin(bn, pos + offset); 376*db0ac6deSCy Schubert return 0; 377*db0ac6deSCy Schubert } 378*db0ac6deSCy Schubert 379*db0ac6deSCy Schubert 380*db0ac6deSCy Schubert struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix) 381*db0ac6deSCy Schubert { 382*db0ac6deSCy Schubert int len, res; 383*db0ac6deSCy Schubert EC_KEY *eckey; 384*db0ac6deSCy Schubert struct wpabuf *buf; 385*db0ac6deSCy Schubert unsigned char *pos; 386*db0ac6deSCy Schubert 387*db0ac6deSCy Schubert eckey = EVP_PKEY_get1_EC_KEY(pkey); 388*db0ac6deSCy Schubert if (!eckey) 389*db0ac6deSCy Schubert return NULL; 390*db0ac6deSCy Schubert EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED); 391*db0ac6deSCy Schubert len = i2o_ECPublicKey(eckey, NULL); 392*db0ac6deSCy Schubert if (len <= 0) { 393*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 394*db0ac6deSCy Schubert "DDP: Failed to determine public key encoding length"); 395*db0ac6deSCy Schubert EC_KEY_free(eckey); 396*db0ac6deSCy Schubert return NULL; 397*db0ac6deSCy Schubert } 398*db0ac6deSCy Schubert 399*db0ac6deSCy Schubert buf = wpabuf_alloc(len); 400*db0ac6deSCy Schubert if (!buf) { 401*db0ac6deSCy Schubert EC_KEY_free(eckey); 402*db0ac6deSCy Schubert return NULL; 403*db0ac6deSCy Schubert } 404*db0ac6deSCy Schubert 405*db0ac6deSCy Schubert pos = wpabuf_put(buf, len); 406*db0ac6deSCy Schubert res = i2o_ECPublicKey(eckey, &pos); 407*db0ac6deSCy Schubert EC_KEY_free(eckey); 408*db0ac6deSCy Schubert if (res != len) { 409*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 410*db0ac6deSCy Schubert "DDP: Failed to encode public key (res=%d/%d)", 411*db0ac6deSCy Schubert res, len); 412*db0ac6deSCy Schubert wpabuf_free(buf); 413*db0ac6deSCy Schubert return NULL; 414*db0ac6deSCy Schubert } 415*db0ac6deSCy Schubert 416*db0ac6deSCy Schubert if (!prefix) { 417*db0ac6deSCy Schubert /* Remove 0x04 prefix to match DPP definition */ 418*db0ac6deSCy Schubert pos = wpabuf_mhead(buf); 419*db0ac6deSCy Schubert os_memmove(pos, pos + 1, len - 1); 420*db0ac6deSCy Schubert buf->used--; 421*db0ac6deSCy Schubert } 422*db0ac6deSCy Schubert 423*db0ac6deSCy Schubert return buf; 424*db0ac6deSCy Schubert } 425*db0ac6deSCy Schubert 426*db0ac6deSCy Schubert 427*db0ac6deSCy Schubert EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group, 428*db0ac6deSCy Schubert const u8 *buf_x, const u8 *buf_y, 429*db0ac6deSCy Schubert size_t len) 430*db0ac6deSCy Schubert { 431*db0ac6deSCy Schubert EC_KEY *eckey = NULL; 432*db0ac6deSCy Schubert BN_CTX *ctx; 433*db0ac6deSCy Schubert EC_POINT *point = NULL; 434*db0ac6deSCy Schubert BIGNUM *x = NULL, *y = NULL; 435*db0ac6deSCy Schubert EVP_PKEY *pkey = NULL; 436*db0ac6deSCy Schubert 437*db0ac6deSCy Schubert ctx = BN_CTX_new(); 438*db0ac6deSCy Schubert if (!ctx) { 439*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: Out of memory"); 440*db0ac6deSCy Schubert return NULL; 441*db0ac6deSCy Schubert } 442*db0ac6deSCy Schubert 443*db0ac6deSCy Schubert point = EC_POINT_new(group); 444*db0ac6deSCy Schubert x = BN_bin2bn(buf_x, len, NULL); 445*db0ac6deSCy Schubert y = BN_bin2bn(buf_y, len, NULL); 446*db0ac6deSCy Schubert if (!point || !x || !y) { 447*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: Out of memory"); 448*db0ac6deSCy Schubert goto fail; 449*db0ac6deSCy Schubert } 450*db0ac6deSCy Schubert 451*db0ac6deSCy Schubert if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { 452*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 453*db0ac6deSCy Schubert "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s", 454*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 455*db0ac6deSCy Schubert goto fail; 456*db0ac6deSCy Schubert } 457*db0ac6deSCy Schubert 458*db0ac6deSCy Schubert if (!EC_POINT_is_on_curve(group, point, ctx) || 459*db0ac6deSCy Schubert EC_POINT_is_at_infinity(group, point)) { 460*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: Invalid point"); 461*db0ac6deSCy Schubert goto fail; 462*db0ac6deSCy Schubert } 463*db0ac6deSCy Schubert dpp_debug_print_point("DPP: dpp_set_pubkey_point_group", group, point); 464*db0ac6deSCy Schubert 465*db0ac6deSCy Schubert eckey = EC_KEY_new(); 466*db0ac6deSCy Schubert if (!eckey || 467*db0ac6deSCy Schubert EC_KEY_set_group(eckey, group) != 1 || 468*db0ac6deSCy Schubert EC_KEY_set_public_key(eckey, point) != 1) { 469*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 470*db0ac6deSCy Schubert "DPP: Failed to set EC_KEY: %s", 471*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 472*db0ac6deSCy Schubert goto fail; 473*db0ac6deSCy Schubert } 474*db0ac6deSCy Schubert EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); 475*db0ac6deSCy Schubert 476*db0ac6deSCy Schubert pkey = EVP_PKEY_new(); 477*db0ac6deSCy Schubert if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) { 478*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY"); 479*db0ac6deSCy Schubert goto fail; 480*db0ac6deSCy Schubert } 481*db0ac6deSCy Schubert 482*db0ac6deSCy Schubert out: 483*db0ac6deSCy Schubert BN_free(x); 484*db0ac6deSCy Schubert BN_free(y); 485*db0ac6deSCy Schubert EC_KEY_free(eckey); 486*db0ac6deSCy Schubert EC_POINT_free(point); 487*db0ac6deSCy Schubert BN_CTX_free(ctx); 488*db0ac6deSCy Schubert return pkey; 489*db0ac6deSCy Schubert fail: 490*db0ac6deSCy Schubert EVP_PKEY_free(pkey); 491*db0ac6deSCy Schubert pkey = NULL; 492*db0ac6deSCy Schubert goto out; 493*db0ac6deSCy Schubert } 494*db0ac6deSCy Schubert 495*db0ac6deSCy Schubert 496*db0ac6deSCy Schubert EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len) 497*db0ac6deSCy Schubert { 498*db0ac6deSCy Schubert const EC_KEY *eckey; 499*db0ac6deSCy Schubert const EC_GROUP *group; 500*db0ac6deSCy Schubert EVP_PKEY *pkey = NULL; 501c1d255d3SCy Schubert 502c1d255d3SCy Schubert if (len & 1) 503c1d255d3SCy Schubert return NULL; 504c1d255d3SCy Schubert 505*db0ac6deSCy Schubert eckey = EVP_PKEY_get0_EC_KEY(group_key); 506*db0ac6deSCy Schubert if (!eckey) { 507*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 508*db0ac6deSCy Schubert "DPP: Could not get EC_KEY from group_key"); 509c1d255d3SCy Schubert return NULL; 510c1d255d3SCy Schubert } 511c1d255d3SCy Schubert 512*db0ac6deSCy Schubert group = EC_KEY_get0_group(eckey); 513*db0ac6deSCy Schubert if (group) 514*db0ac6deSCy Schubert pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2, 515*db0ac6deSCy Schubert len / 2); 516*db0ac6deSCy Schubert else 517*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); 518*db0ac6deSCy Schubert 519*db0ac6deSCy Schubert return pkey; 520c1d255d3SCy Schubert } 521c1d255d3SCy Schubert 522c1d255d3SCy Schubert 523*db0ac6deSCy Schubert EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve) 524c1d255d3SCy Schubert { 525*db0ac6deSCy Schubert EVP_PKEY_CTX *kctx = NULL; 526*db0ac6deSCy Schubert EC_KEY *ec_params = NULL; 527*db0ac6deSCy Schubert EVP_PKEY *params = NULL, *key = NULL; 528*db0ac6deSCy Schubert int nid; 529c1d255d3SCy Schubert 530c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); 531c1d255d3SCy Schubert 532*db0ac6deSCy Schubert nid = OBJ_txt2nid(curve->name); 533*db0ac6deSCy Schubert if (nid == NID_undef) { 534*db0ac6deSCy Schubert wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name); 535*db0ac6deSCy Schubert return NULL; 536*db0ac6deSCy Schubert } 537*db0ac6deSCy Schubert 538*db0ac6deSCy Schubert ec_params = EC_KEY_new_by_curve_name(nid); 539*db0ac6deSCy Schubert if (!ec_params) { 540*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 541*db0ac6deSCy Schubert "DPP: Failed to generate EC_KEY parameters"); 542*db0ac6deSCy Schubert goto fail; 543*db0ac6deSCy Schubert } 544*db0ac6deSCy Schubert EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE); 545*db0ac6deSCy Schubert params = EVP_PKEY_new(); 546*db0ac6deSCy Schubert if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) { 547*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 548*db0ac6deSCy Schubert "DPP: Failed to generate EVP_PKEY parameters"); 549*db0ac6deSCy Schubert goto fail; 550*db0ac6deSCy Schubert } 551*db0ac6deSCy Schubert 552*db0ac6deSCy Schubert kctx = EVP_PKEY_CTX_new(params, NULL); 553*db0ac6deSCy Schubert if (!kctx || 554*db0ac6deSCy Schubert EVP_PKEY_keygen_init(kctx) != 1 || 555*db0ac6deSCy Schubert EVP_PKEY_keygen(kctx, &key) != 1) { 556*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key"); 557*db0ac6deSCy Schubert key = NULL; 558*db0ac6deSCy Schubert goto fail; 559*db0ac6deSCy Schubert } 560*db0ac6deSCy Schubert 561*db0ac6deSCy Schubert if (wpa_debug_show_keys) 562c1d255d3SCy Schubert dpp_debug_print_key("Own generated key", key); 563c1d255d3SCy Schubert 564*db0ac6deSCy Schubert fail: 565*db0ac6deSCy Schubert EC_KEY_free(ec_params); 566*db0ac6deSCy Schubert EVP_PKEY_free(params); 567*db0ac6deSCy Schubert EVP_PKEY_CTX_free(kctx); 568c1d255d3SCy Schubert return key; 569c1d255d3SCy Schubert } 570c1d255d3SCy Schubert 571c1d255d3SCy Schubert 572*db0ac6deSCy Schubert EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve, 573c1d255d3SCy Schubert const u8 *privkey, size_t privkey_len) 574c1d255d3SCy Schubert { 575*db0ac6deSCy Schubert EVP_PKEY *pkey; 576*db0ac6deSCy Schubert EC_KEY *eckey; 577*db0ac6deSCy Schubert const EC_GROUP *group; 578*db0ac6deSCy Schubert int nid; 579c1d255d3SCy Schubert 580*db0ac6deSCy Schubert pkey = EVP_PKEY_new(); 581*db0ac6deSCy Schubert if (!pkey) 582*db0ac6deSCy Schubert return NULL; 583*db0ac6deSCy Schubert eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len); 584*db0ac6deSCy Schubert if (!eckey) { 585*db0ac6deSCy Schubert wpa_printf(MSG_INFO, 586*db0ac6deSCy Schubert "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", 587*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 588*db0ac6deSCy Schubert EVP_PKEY_free(pkey); 589c1d255d3SCy Schubert return NULL; 590c1d255d3SCy Schubert } 591*db0ac6deSCy Schubert group = EC_KEY_get0_group(eckey); 592*db0ac6deSCy Schubert if (!group) { 593*db0ac6deSCy Schubert EC_KEY_free(eckey); 594*db0ac6deSCy Schubert EVP_PKEY_free(pkey); 595c1d255d3SCy Schubert return NULL; 596c1d255d3SCy Schubert } 597*db0ac6deSCy Schubert nid = EC_GROUP_get_curve_name(group); 598*db0ac6deSCy Schubert *curve = dpp_get_curve_nid(nid); 599c1d255d3SCy Schubert if (!*curve) { 600c1d255d3SCy Schubert wpa_printf(MSG_INFO, 601*db0ac6deSCy Schubert "DPP: Unsupported curve (nid=%d) in pre-assigned key", 602*db0ac6deSCy Schubert nid); 603*db0ac6deSCy Schubert EC_KEY_free(eckey); 604*db0ac6deSCy Schubert EVP_PKEY_free(pkey); 605c1d255d3SCy Schubert return NULL; 606c1d255d3SCy Schubert } 607c1d255d3SCy Schubert 608*db0ac6deSCy Schubert if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { 609*db0ac6deSCy Schubert EC_KEY_free(eckey); 610*db0ac6deSCy Schubert EVP_PKEY_free(pkey); 611*db0ac6deSCy Schubert return NULL; 612*db0ac6deSCy Schubert } 613*db0ac6deSCy Schubert return pkey; 614*db0ac6deSCy Schubert } 615*db0ac6deSCy Schubert 616*db0ac6deSCy Schubert 617*db0ac6deSCy Schubert typedef struct { 618*db0ac6deSCy Schubert /* AlgorithmIdentifier ecPublicKey with optional parameters present 619*db0ac6deSCy Schubert * as an OID identifying the curve */ 620*db0ac6deSCy Schubert X509_ALGOR *alg; 621*db0ac6deSCy Schubert /* Compressed format public key per ANSI X9.63 */ 622*db0ac6deSCy Schubert ASN1_BIT_STRING *pub_key; 623*db0ac6deSCy Schubert } DPP_BOOTSTRAPPING_KEY; 624*db0ac6deSCy Schubert 625*db0ac6deSCy Schubert ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = { 626*db0ac6deSCy Schubert ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR), 627*db0ac6deSCy Schubert ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING) 628*db0ac6deSCy Schubert } ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY); 629*db0ac6deSCy Schubert 630*db0ac6deSCy Schubert IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY); 631*db0ac6deSCy Schubert 632*db0ac6deSCy Schubert 633*db0ac6deSCy Schubert static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key) 634*db0ac6deSCy Schubert { 635*db0ac6deSCy Schubert unsigned char *der = NULL; 636*db0ac6deSCy Schubert int der_len; 637*db0ac6deSCy Schubert const EC_KEY *eckey; 638*db0ac6deSCy Schubert struct wpabuf *ret = NULL; 639*db0ac6deSCy Schubert size_t len; 640*db0ac6deSCy Schubert const EC_GROUP *group; 641*db0ac6deSCy Schubert const EC_POINT *point; 642*db0ac6deSCy Schubert BN_CTX *ctx; 643*db0ac6deSCy Schubert DPP_BOOTSTRAPPING_KEY *bootstrap = NULL; 644*db0ac6deSCy Schubert int nid; 645*db0ac6deSCy Schubert 646*db0ac6deSCy Schubert ctx = BN_CTX_new(); 647*db0ac6deSCy Schubert eckey = EVP_PKEY_get0_EC_KEY(key); 648*db0ac6deSCy Schubert if (!ctx || !eckey) 649*db0ac6deSCy Schubert goto fail; 650*db0ac6deSCy Schubert 651*db0ac6deSCy Schubert group = EC_KEY_get0_group(eckey); 652*db0ac6deSCy Schubert point = EC_KEY_get0_public_key(eckey); 653*db0ac6deSCy Schubert if (!group || !point) 654*db0ac6deSCy Schubert goto fail; 655*db0ac6deSCy Schubert dpp_debug_print_point("DPP: bootstrap public key", group, point); 656*db0ac6deSCy Schubert nid = EC_GROUP_get_curve_name(group); 657*db0ac6deSCy Schubert 658*db0ac6deSCy Schubert bootstrap = DPP_BOOTSTRAPPING_KEY_new(); 659*db0ac6deSCy Schubert if (!bootstrap || 660*db0ac6deSCy Schubert X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC), 661*db0ac6deSCy Schubert V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1) 662*db0ac6deSCy Schubert goto fail; 663*db0ac6deSCy Schubert 664*db0ac6deSCy Schubert len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, 665*db0ac6deSCy Schubert NULL, 0, ctx); 666*db0ac6deSCy Schubert if (len == 0) 667*db0ac6deSCy Schubert goto fail; 668*db0ac6deSCy Schubert 669*db0ac6deSCy Schubert der = OPENSSL_malloc(len); 670*db0ac6deSCy Schubert if (!der) 671*db0ac6deSCy Schubert goto fail; 672*db0ac6deSCy Schubert len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, 673*db0ac6deSCy Schubert der, len, ctx); 674*db0ac6deSCy Schubert 675*db0ac6deSCy Schubert OPENSSL_free(bootstrap->pub_key->data); 676*db0ac6deSCy Schubert bootstrap->pub_key->data = der; 677*db0ac6deSCy Schubert der = NULL; 678*db0ac6deSCy Schubert bootstrap->pub_key->length = len; 679*db0ac6deSCy Schubert /* No unused bits */ 680*db0ac6deSCy Schubert bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); 681*db0ac6deSCy Schubert bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; 682*db0ac6deSCy Schubert 683*db0ac6deSCy Schubert der_len = i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der); 684*db0ac6deSCy Schubert if (der_len <= 0) { 685*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 686*db0ac6deSCy Schubert "DDP: Failed to build DER encoded public key"); 687*db0ac6deSCy Schubert goto fail; 688*db0ac6deSCy Schubert } 689*db0ac6deSCy Schubert 690*db0ac6deSCy Schubert ret = wpabuf_alloc_copy(der, der_len); 691*db0ac6deSCy Schubert fail: 692*db0ac6deSCy Schubert DPP_BOOTSTRAPPING_KEY_free(bootstrap); 693*db0ac6deSCy Schubert OPENSSL_free(der); 694*db0ac6deSCy Schubert BN_CTX_free(ctx); 695*db0ac6deSCy Schubert return ret; 696c1d255d3SCy Schubert } 697c1d255d3SCy Schubert 698c1d255d3SCy Schubert 699c1d255d3SCy Schubert int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) 700c1d255d3SCy Schubert { 701c1d255d3SCy Schubert struct wpabuf *der; 702c1d255d3SCy Schubert int res; 703c1d255d3SCy Schubert 704*db0ac6deSCy Schubert der = dpp_bootstrap_key_der(bi->pubkey); 705c1d255d3SCy Schubert if (!der) 706c1d255d3SCy Schubert return -1; 707c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", 708c1d255d3SCy Schubert der); 709c1d255d3SCy Schubert res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)); 710c1d255d3SCy Schubert if (res < 0) 711c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); 712c1d255d3SCy Schubert wpabuf_free(der); 713c1d255d3SCy Schubert return res; 714c1d255d3SCy Schubert } 715c1d255d3SCy Schubert 716c1d255d3SCy Schubert 717c1d255d3SCy Schubert int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, 718c1d255d3SCy Schubert const u8 *privkey, size_t privkey_len) 719c1d255d3SCy Schubert { 720c1d255d3SCy Schubert char *base64 = NULL; 721c1d255d3SCy Schubert char *pos, *end; 722c1d255d3SCy Schubert size_t len; 723c1d255d3SCy Schubert struct wpabuf *der = NULL; 724c1d255d3SCy Schubert 725c1d255d3SCy Schubert bi->curve = dpp_get_curve_name(curve); 726c1d255d3SCy Schubert if (!bi->curve) { 727c1d255d3SCy Schubert wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); 728c1d255d3SCy Schubert return -1; 729c1d255d3SCy Schubert } 730c1d255d3SCy Schubert 731c1d255d3SCy Schubert if (privkey) 732c1d255d3SCy Schubert bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len); 733c1d255d3SCy Schubert else 734c1d255d3SCy Schubert bi->pubkey = dpp_gen_keypair(bi->curve); 735c1d255d3SCy Schubert if (!bi->pubkey) 736c1d255d3SCy Schubert goto fail; 737c1d255d3SCy Schubert bi->own = 1; 738c1d255d3SCy Schubert 739*db0ac6deSCy Schubert der = dpp_bootstrap_key_der(bi->pubkey); 740c1d255d3SCy Schubert if (!der) 741c1d255d3SCy Schubert goto fail; 742c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", 743c1d255d3SCy Schubert der); 744c1d255d3SCy Schubert 745c1d255d3SCy Schubert if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) { 746c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); 747c1d255d3SCy Schubert goto fail; 748c1d255d3SCy Schubert } 749c1d255d3SCy Schubert 750c1d255d3SCy Schubert base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len); 751c1d255d3SCy Schubert wpabuf_free(der); 752c1d255d3SCy Schubert der = NULL; 753c1d255d3SCy Schubert if (!base64) 754c1d255d3SCy Schubert goto fail; 755c1d255d3SCy Schubert pos = base64; 756c1d255d3SCy Schubert end = pos + len; 757c1d255d3SCy Schubert for (;;) { 758c1d255d3SCy Schubert pos = os_strchr(pos, '\n'); 759c1d255d3SCy Schubert if (!pos) 760c1d255d3SCy Schubert break; 761c1d255d3SCy Schubert os_memmove(pos, pos + 1, end - pos); 762c1d255d3SCy Schubert } 763c1d255d3SCy Schubert os_free(bi->pk); 764c1d255d3SCy Schubert bi->pk = base64; 765c1d255d3SCy Schubert return 0; 766c1d255d3SCy Schubert fail: 767c1d255d3SCy Schubert os_free(base64); 768c1d255d3SCy Schubert wpabuf_free(der); 769c1d255d3SCy Schubert return -1; 770c1d255d3SCy Schubert } 771c1d255d3SCy Schubert 772c1d255d3SCy Schubert 773c1d255d3SCy Schubert int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len) 774c1d255d3SCy Schubert { 775c1d255d3SCy Schubert u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 776c1d255d3SCy Schubert const char *info = "first intermediate key"; 777c1d255d3SCy Schubert int res; 778c1d255d3SCy Schubert 779c1d255d3SCy Schubert /* k1 = HKDF(<>, "first intermediate key", M.x) */ 780c1d255d3SCy Schubert 781c1d255d3SCy Schubert /* HKDF-Extract(<>, M.x) */ 782c1d255d3SCy Schubert os_memset(salt, 0, hash_len); 783c1d255d3SCy Schubert if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0) 784c1d255d3SCy Schubert return -1; 785c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)", 786c1d255d3SCy Schubert prk, hash_len); 787c1d255d3SCy Schubert 788c1d255d3SCy Schubert /* HKDF-Expand(PRK, info, L) */ 789c1d255d3SCy Schubert res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len); 790c1d255d3SCy Schubert os_memset(prk, 0, hash_len); 791c1d255d3SCy Schubert if (res < 0) 792c1d255d3SCy Schubert return -1; 793c1d255d3SCy Schubert 794c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)", 795c1d255d3SCy Schubert k1, hash_len); 796c1d255d3SCy Schubert return 0; 797c1d255d3SCy Schubert } 798c1d255d3SCy Schubert 799c1d255d3SCy Schubert 800c1d255d3SCy Schubert int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len) 801c1d255d3SCy Schubert { 802c1d255d3SCy Schubert u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 803c1d255d3SCy Schubert const char *info = "second intermediate key"; 804c1d255d3SCy Schubert int res; 805c1d255d3SCy Schubert 806c1d255d3SCy Schubert /* k2 = HKDF(<>, "second intermediate key", N.x) */ 807c1d255d3SCy Schubert 808c1d255d3SCy Schubert /* HKDF-Extract(<>, N.x) */ 809c1d255d3SCy Schubert os_memset(salt, 0, hash_len); 810c1d255d3SCy Schubert res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk); 811c1d255d3SCy Schubert if (res < 0) 812c1d255d3SCy Schubert return -1; 813c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", 814c1d255d3SCy Schubert prk, hash_len); 815c1d255d3SCy Schubert 816c1d255d3SCy Schubert /* HKDF-Expand(PRK, info, L) */ 817c1d255d3SCy Schubert res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len); 818c1d255d3SCy Schubert os_memset(prk, 0, hash_len); 819c1d255d3SCy Schubert if (res < 0) 820c1d255d3SCy Schubert return -1; 821c1d255d3SCy Schubert 822c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)", 823c1d255d3SCy Schubert k2, hash_len); 824c1d255d3SCy Schubert return 0; 825c1d255d3SCy Schubert } 826c1d255d3SCy Schubert 827c1d255d3SCy Schubert 828c1d255d3SCy Schubert int dpp_derive_bk_ke(struct dpp_authentication *auth) 829c1d255d3SCy Schubert { 830c1d255d3SCy Schubert unsigned int hash_len = auth->curve->hash_len; 831c1d255d3SCy Schubert size_t nonce_len = auth->curve->nonce_len; 832c1d255d3SCy Schubert u8 nonces[2 * DPP_MAX_NONCE_LEN]; 833c1d255d3SCy Schubert const char *info_ke = "DPP Key"; 834c1d255d3SCy Schubert int res; 835c1d255d3SCy Schubert const u8 *addr[3]; 836c1d255d3SCy Schubert size_t len[3]; 837c1d255d3SCy Schubert size_t num_elem = 0; 838c1d255d3SCy Schubert 839c1d255d3SCy Schubert if (!auth->Mx_len || !auth->Nx_len) { 840c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 841c1d255d3SCy Schubert "DPP: Mx/Nx not available - cannot derive ke"); 842c1d255d3SCy Schubert return -1; 843c1d255d3SCy Schubert } 844c1d255d3SCy Schubert 845c1d255d3SCy Schubert /* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ 846c1d255d3SCy Schubert os_memcpy(nonces, auth->i_nonce, nonce_len); 847c1d255d3SCy Schubert os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len); 848c1d255d3SCy Schubert addr[num_elem] = auth->Mx; 849c1d255d3SCy Schubert len[num_elem] = auth->Mx_len; 850c1d255d3SCy Schubert num_elem++; 851c1d255d3SCy Schubert addr[num_elem] = auth->Nx; 852c1d255d3SCy Schubert len[num_elem] = auth->Nx_len; 853c1d255d3SCy Schubert num_elem++; 854c1d255d3SCy Schubert if (auth->peer_bi && auth->own_bi) { 855c1d255d3SCy Schubert if (!auth->Lx_len) { 856c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 857c1d255d3SCy Schubert "DPP: Lx not available - cannot derive ke"); 858c1d255d3SCy Schubert return -1; 859c1d255d3SCy Schubert } 860c1d255d3SCy Schubert addr[num_elem] = auth->Lx; 861c1d255d3SCy Schubert len[num_elem] = auth->secret_len; 862c1d255d3SCy Schubert num_elem++; 863c1d255d3SCy Schubert } 864c1d255d3SCy Schubert res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len, 865c1d255d3SCy Schubert num_elem, addr, len, auth->bk); 866c1d255d3SCy Schubert if (res < 0) 867c1d255d3SCy Schubert return -1; 868c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 869c1d255d3SCy Schubert "DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])", 870c1d255d3SCy Schubert auth->bk, hash_len); 871c1d255d3SCy Schubert 872c1d255d3SCy Schubert /* ke = HKDF-Expand(bk, "DPP Key", length) */ 873c1d255d3SCy Schubert res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke, 874c1d255d3SCy Schubert hash_len); 875c1d255d3SCy Schubert if (res < 0) 876c1d255d3SCy Schubert return -1; 877c1d255d3SCy Schubert 878c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 879c1d255d3SCy Schubert "DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)", 880c1d255d3SCy Schubert auth->ke, hash_len); 881c1d255d3SCy Schubert 882c1d255d3SCy Schubert return 0; 883c1d255d3SCy Schubert } 884c1d255d3SCy Schubert 885c1d255d3SCy Schubert 886*db0ac6deSCy Schubert int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, u8 *secret, size_t *secret_len) 887c1d255d3SCy Schubert { 888*db0ac6deSCy Schubert EVP_PKEY_CTX *ctx; 889c1d255d3SCy Schubert int ret = -1; 890c1d255d3SCy Schubert 891*db0ac6deSCy Schubert ERR_clear_error(); 892c1d255d3SCy Schubert *secret_len = 0; 893c1d255d3SCy Schubert 894*db0ac6deSCy Schubert ctx = EVP_PKEY_CTX_new(own, NULL); 895*db0ac6deSCy Schubert if (!ctx) { 896*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s", 897*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 898c1d255d3SCy Schubert return -1; 899c1d255d3SCy Schubert } 900c1d255d3SCy Schubert 901*db0ac6deSCy Schubert if (EVP_PKEY_derive_init(ctx) != 1) { 902*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive_init failed: %s", 903*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 904*db0ac6deSCy Schubert goto fail; 905*db0ac6deSCy Schubert } 906*db0ac6deSCy Schubert 907*db0ac6deSCy Schubert if (EVP_PKEY_derive_set_peer(ctx, peer) != 1) { 908c1d255d3SCy Schubert wpa_printf(MSG_ERROR, 909*db0ac6deSCy Schubert "DPP: EVP_PKEY_derive_set_peet failed: %s", 910*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 911c1d255d3SCy Schubert goto fail; 912c1d255d3SCy Schubert } 913c1d255d3SCy Schubert 914*db0ac6deSCy Schubert if (EVP_PKEY_derive(ctx, NULL, secret_len) != 1) { 915*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive(NULL) failed: %s", 916*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 917c1d255d3SCy Schubert goto fail; 918c1d255d3SCy Schubert } 919c1d255d3SCy Schubert 920*db0ac6deSCy Schubert if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { 921*db0ac6deSCy Schubert u8 buf[200]; 922*db0ac6deSCy Schubert int level = *secret_len > 200 ? MSG_ERROR : MSG_DEBUG; 923*db0ac6deSCy Schubert 924*db0ac6deSCy Schubert /* It looks like OpenSSL can return unexpectedly large buffer 925*db0ac6deSCy Schubert * need for shared secret from EVP_PKEY_derive(NULL) in some 926*db0ac6deSCy Schubert * cases. For example, group 19 has shown cases where secret_len 927*db0ac6deSCy Schubert * is set to 72 even though the actual length ends up being 928*db0ac6deSCy Schubert * updated to 32 when EVP_PKEY_derive() is called with a buffer 929*db0ac6deSCy Schubert * for the value. Work around this by trying to fetch the value 930*db0ac6deSCy Schubert * and continue if it is within supported range even when the 931*db0ac6deSCy Schubert * initial buffer need is claimed to be larger. */ 932*db0ac6deSCy Schubert wpa_printf(level, 933*db0ac6deSCy Schubert "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", 934*db0ac6deSCy Schubert (int) *secret_len); 935*db0ac6deSCy Schubert if (*secret_len > 200) 936*db0ac6deSCy Schubert goto fail; 937*db0ac6deSCy Schubert if (EVP_PKEY_derive(ctx, buf, secret_len) != 1) { 938*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", 939*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 940*db0ac6deSCy Schubert goto fail; 941*db0ac6deSCy Schubert } 942*db0ac6deSCy Schubert if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { 943*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 944*db0ac6deSCy Schubert "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", 945*db0ac6deSCy Schubert (int) *secret_len); 946*db0ac6deSCy Schubert goto fail; 947*db0ac6deSCy Schubert } 948*db0ac6deSCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: Unexpected secret_len change", 949*db0ac6deSCy Schubert buf, *secret_len); 950*db0ac6deSCy Schubert os_memcpy(secret, buf, *secret_len); 951*db0ac6deSCy Schubert forced_memzero(buf, sizeof(buf)); 952*db0ac6deSCy Schubert goto done; 953*db0ac6deSCy Schubert } 954*db0ac6deSCy Schubert 955*db0ac6deSCy Schubert if (EVP_PKEY_derive(ctx, secret, secret_len) != 1) { 956*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", 957*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 958c1d255d3SCy Schubert goto fail; 959c1d255d3SCy Schubert } 960c1d255d3SCy Schubert 961*db0ac6deSCy Schubert done: 962c1d255d3SCy Schubert ret = 0; 963c1d255d3SCy Schubert 964c1d255d3SCy Schubert fail: 965*db0ac6deSCy Schubert EVP_PKEY_CTX_free(ctx); 966c1d255d3SCy Schubert return ret; 967c1d255d3SCy Schubert } 968c1d255d3SCy Schubert 969c1d255d3SCy Schubert 970c1d255d3SCy Schubert int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, 971c1d255d3SCy Schubert const u8 *data, size_t data_len) 972c1d255d3SCy Schubert { 973c1d255d3SCy Schubert const u8 *addr[2]; 974c1d255d3SCy Schubert size_t len[2]; 975c1d255d3SCy Schubert 976c1d255d3SCy Schubert addr[0] = data; 977c1d255d3SCy Schubert len[0] = data_len; 978c1d255d3SCy Schubert if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0) 979c1d255d3SCy Schubert return -1; 980c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", 981c1d255d3SCy Schubert bi->pubkey_hash, SHA256_MAC_LEN); 982c1d255d3SCy Schubert 983c1d255d3SCy Schubert addr[0] = (const u8 *) "chirp"; 984c1d255d3SCy Schubert len[0] = 5; 985c1d255d3SCy Schubert addr[1] = data; 986c1d255d3SCy Schubert len[1] = data_len; 987c1d255d3SCy Schubert if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0) 988c1d255d3SCy Schubert return -1; 989c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)", 990c1d255d3SCy Schubert bi->pubkey_hash_chirp, SHA256_MAC_LEN); 991c1d255d3SCy Schubert 992c1d255d3SCy Schubert return 0; 993c1d255d3SCy Schubert } 994c1d255d3SCy Schubert 995c1d255d3SCy Schubert 996c1d255d3SCy Schubert int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, 997c1d255d3SCy Schubert const u8 *data, size_t data_len) 998c1d255d3SCy Schubert { 999*db0ac6deSCy Schubert EVP_PKEY *pkey; 1000*db0ac6deSCy Schubert const unsigned char *p; 1001*db0ac6deSCy Schubert int res; 1002*db0ac6deSCy Schubert X509_PUBKEY *pub = NULL; 1003*db0ac6deSCy Schubert ASN1_OBJECT *ppkalg; 1004*db0ac6deSCy Schubert const unsigned char *pk; 1005*db0ac6deSCy Schubert int ppklen; 1006*db0ac6deSCy Schubert X509_ALGOR *pa; 1007*db0ac6deSCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ 1008*db0ac6deSCy Schubert (defined(LIBRESSL_VERSION_NUMBER) && \ 1009*db0ac6deSCy Schubert LIBRESSL_VERSION_NUMBER < 0x20800000L) 1010*db0ac6deSCy Schubert ASN1_OBJECT *pa_oid; 1011*db0ac6deSCy Schubert #else 1012*db0ac6deSCy Schubert const ASN1_OBJECT *pa_oid; 1013*db0ac6deSCy Schubert #endif 1014*db0ac6deSCy Schubert const void *pval; 1015*db0ac6deSCy Schubert int ptype; 1016*db0ac6deSCy Schubert const ASN1_OBJECT *poid; 1017*db0ac6deSCy Schubert char buf[100]; 1018c1d255d3SCy Schubert 1019c1d255d3SCy Schubert if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) { 1020c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); 1021c1d255d3SCy Schubert return -1; 1022c1d255d3SCy Schubert } 1023c1d255d3SCy Schubert 1024*db0ac6deSCy Schubert /* DER encoded ASN.1 SubjectPublicKeyInfo 1025*db0ac6deSCy Schubert * 1026*db0ac6deSCy Schubert * SubjectPublicKeyInfo ::= SEQUENCE { 1027*db0ac6deSCy Schubert * algorithm AlgorithmIdentifier, 1028*db0ac6deSCy Schubert * subjectPublicKey BIT STRING } 1029*db0ac6deSCy Schubert * 1030*db0ac6deSCy Schubert * AlgorithmIdentifier ::= SEQUENCE { 1031*db0ac6deSCy Schubert * algorithm OBJECT IDENTIFIER, 1032*db0ac6deSCy Schubert * parameters ANY DEFINED BY algorithm OPTIONAL } 1033*db0ac6deSCy Schubert * 1034*db0ac6deSCy Schubert * subjectPublicKey = compressed format public key per ANSI X9.63 1035*db0ac6deSCy Schubert * algorithm = ecPublicKey (1.2.840.10045.2.1) 1036*db0ac6deSCy Schubert * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g., 1037*db0ac6deSCy Schubert * prime256v1 (1.2.840.10045.3.1.7) 1038*db0ac6deSCy Schubert */ 1039*db0ac6deSCy Schubert 1040*db0ac6deSCy Schubert p = data; 1041*db0ac6deSCy Schubert pkey = d2i_PUBKEY(NULL, &p, data_len); 1042*db0ac6deSCy Schubert 1043*db0ac6deSCy Schubert if (!pkey) { 1044c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1045c1d255d3SCy Schubert "DPP: Could not parse URI public-key SubjectPublicKeyInfo"); 1046c1d255d3SCy Schubert return -1; 1047c1d255d3SCy Schubert } 1048c1d255d3SCy Schubert 1049*db0ac6deSCy Schubert if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) { 1050c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1051*db0ac6deSCy Schubert "DPP: SubjectPublicKeyInfo does not describe an EC key"); 1052*db0ac6deSCy Schubert EVP_PKEY_free(pkey); 1053*db0ac6deSCy Schubert return -1; 1054*db0ac6deSCy Schubert } 1055*db0ac6deSCy Schubert 1056*db0ac6deSCy Schubert res = X509_PUBKEY_set(&pub, pkey); 1057*db0ac6deSCy Schubert if (res != 1) { 1058*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey"); 1059c1d255d3SCy Schubert goto fail; 1060c1d255d3SCy Schubert } 1061c1d255d3SCy Schubert 1062*db0ac6deSCy Schubert res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub); 1063*db0ac6deSCy Schubert if (res != 1) { 1064*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 1065*db0ac6deSCy Schubert "DPP: Could not extract SubjectPublicKeyInfo parameters"); 1066*db0ac6deSCy Schubert goto fail; 1067*db0ac6deSCy Schubert } 1068*db0ac6deSCy Schubert res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0); 1069*db0ac6deSCy Schubert if (res < 0 || (size_t) res >= sizeof(buf)) { 1070*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 1071*db0ac6deSCy Schubert "DPP: Could not extract SubjectPublicKeyInfo algorithm"); 1072*db0ac6deSCy Schubert goto fail; 1073*db0ac6deSCy Schubert } 1074*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf); 1075*db0ac6deSCy Schubert if (os_strcmp(buf, "id-ecPublicKey") != 0) { 1076*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 1077*db0ac6deSCy Schubert "DPP: Unsupported SubjectPublicKeyInfo algorithm"); 1078*db0ac6deSCy Schubert goto fail; 1079*db0ac6deSCy Schubert } 1080*db0ac6deSCy Schubert 1081*db0ac6deSCy Schubert X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa); 1082*db0ac6deSCy Schubert if (ptype != V_ASN1_OBJECT) { 1083*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 1084*db0ac6deSCy Schubert "DPP: SubjectPublicKeyInfo parameters did not contain an OID"); 1085*db0ac6deSCy Schubert goto fail; 1086*db0ac6deSCy Schubert } 1087*db0ac6deSCy Schubert poid = pval; 1088*db0ac6deSCy Schubert res = OBJ_obj2txt(buf, sizeof(buf), poid, 0); 1089*db0ac6deSCy Schubert if (res < 0 || (size_t) res >= sizeof(buf)) { 1090*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 1091*db0ac6deSCy Schubert "DPP: Could not extract SubjectPublicKeyInfo parameters OID"); 1092*db0ac6deSCy Schubert goto fail; 1093*db0ac6deSCy Schubert } 1094*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf); 1095*db0ac6deSCy Schubert bi->curve = dpp_get_curve_oid(poid); 1096*db0ac6deSCy Schubert if (!bi->curve) { 1097*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 1098*db0ac6deSCy Schubert "DPP: Unsupported SubjectPublicKeyInfo curve: %s", 1099*db0ac6deSCy Schubert buf); 1100*db0ac6deSCy Schubert goto fail; 1101*db0ac6deSCy Schubert } 1102*db0ac6deSCy Schubert 1103*db0ac6deSCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen); 1104*db0ac6deSCy Schubert 1105*db0ac6deSCy Schubert X509_PUBKEY_free(pub); 1106*db0ac6deSCy Schubert bi->pubkey = pkey; 1107c1d255d3SCy Schubert return 0; 1108c1d255d3SCy Schubert fail: 1109*db0ac6deSCy Schubert X509_PUBKEY_free(pub); 1110*db0ac6deSCy Schubert EVP_PKEY_free(pkey); 1111c1d255d3SCy Schubert return -1; 1112c1d255d3SCy Schubert } 1113c1d255d3SCy Schubert 1114c1d255d3SCy Schubert 1115c1d255d3SCy Schubert static struct wpabuf * 1116c1d255d3SCy Schubert dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, 1117c1d255d3SCy Schubert const u8 *prot_hdr, u16 prot_hdr_len, 1118*db0ac6deSCy Schubert const EVP_MD **ret_md) 1119c1d255d3SCy Schubert { 1120c1d255d3SCy Schubert struct json_token *root, *token; 1121c1d255d3SCy Schubert struct wpabuf *kid = NULL; 1122c1d255d3SCy Schubert 1123c1d255d3SCy Schubert root = json_parse((const char *) prot_hdr, prot_hdr_len); 1124c1d255d3SCy Schubert if (!root) { 1125c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1126c1d255d3SCy Schubert "DPP: JSON parsing failed for JWS Protected Header"); 1127c1d255d3SCy Schubert goto fail; 1128c1d255d3SCy Schubert } 1129c1d255d3SCy Schubert 1130c1d255d3SCy Schubert if (root->type != JSON_OBJECT) { 1131c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1132c1d255d3SCy Schubert "DPP: JWS Protected Header root is not an object"); 1133c1d255d3SCy Schubert goto fail; 1134c1d255d3SCy Schubert } 1135c1d255d3SCy Schubert 1136c1d255d3SCy Schubert token = json_get_member(root, "typ"); 1137c1d255d3SCy Schubert if (!token || token->type != JSON_STRING) { 1138c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No typ string value found"); 1139c1d255d3SCy Schubert goto fail; 1140c1d255d3SCy Schubert } 1141c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s", 1142c1d255d3SCy Schubert token->string); 1143c1d255d3SCy Schubert if (os_strcmp(token->string, "dppCon") != 0) { 1144c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1145c1d255d3SCy Schubert "DPP: Unsupported JWS Protected Header typ=%s", 1146c1d255d3SCy Schubert token->string); 1147c1d255d3SCy Schubert goto fail; 1148c1d255d3SCy Schubert } 1149c1d255d3SCy Schubert 1150c1d255d3SCy Schubert token = json_get_member(root, "alg"); 1151c1d255d3SCy Schubert if (!token || token->type != JSON_STRING) { 1152c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No alg string value found"); 1153c1d255d3SCy Schubert goto fail; 1154c1d255d3SCy Schubert } 1155c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s", 1156c1d255d3SCy Schubert token->string); 1157c1d255d3SCy Schubert if (os_strcmp(token->string, curve->jws_alg) != 0) { 1158c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1159c1d255d3SCy Schubert "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)", 1160c1d255d3SCy Schubert token->string, curve->jws_alg); 1161c1d255d3SCy Schubert goto fail; 1162c1d255d3SCy Schubert } 1163c1d255d3SCy Schubert if (os_strcmp(token->string, "ES256") == 0 || 1164*db0ac6deSCy Schubert os_strcmp(token->string, "BS256") == 0) 1165*db0ac6deSCy Schubert *ret_md = EVP_sha256(); 1166*db0ac6deSCy Schubert else if (os_strcmp(token->string, "ES384") == 0 || 1167*db0ac6deSCy Schubert os_strcmp(token->string, "BS384") == 0) 1168*db0ac6deSCy Schubert *ret_md = EVP_sha384(); 1169*db0ac6deSCy Schubert else if (os_strcmp(token->string, "ES512") == 0 || 1170*db0ac6deSCy Schubert os_strcmp(token->string, "BS512") == 0) 1171*db0ac6deSCy Schubert *ret_md = EVP_sha512(); 1172*db0ac6deSCy Schubert else 1173*db0ac6deSCy Schubert *ret_md = NULL; 1174*db0ac6deSCy Schubert if (!*ret_md) { 1175c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1176c1d255d3SCy Schubert "DPP: Unsupported JWS Protected Header alg=%s", 1177c1d255d3SCy Schubert token->string); 1178c1d255d3SCy Schubert goto fail; 1179c1d255d3SCy Schubert } 1180c1d255d3SCy Schubert 1181c1d255d3SCy Schubert kid = json_get_member_base64url(root, "kid"); 1182c1d255d3SCy Schubert if (!kid) { 1183c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: No kid string value found"); 1184c1d255d3SCy Schubert goto fail; 1185c1d255d3SCy Schubert } 1186c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)", 1187c1d255d3SCy Schubert kid); 1188c1d255d3SCy Schubert 1189c1d255d3SCy Schubert fail: 1190c1d255d3SCy Schubert json_free(root); 1191c1d255d3SCy Schubert return kid; 1192c1d255d3SCy Schubert } 1193c1d255d3SCy Schubert 1194c1d255d3SCy Schubert 1195*db0ac6deSCy Schubert static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash) 1196c1d255d3SCy Schubert { 1197c1d255d3SCy Schubert struct wpabuf *uncomp; 1198c1d255d3SCy Schubert int res; 1199c1d255d3SCy Schubert u8 hash[SHA256_MAC_LEN]; 1200c1d255d3SCy Schubert const u8 *addr[1]; 1201c1d255d3SCy Schubert size_t len[1]; 1202c1d255d3SCy Schubert 1203c1d255d3SCy Schubert if (wpabuf_len(r_hash) != SHA256_MAC_LEN) 1204c1d255d3SCy Schubert return -1; 1205*db0ac6deSCy Schubert uncomp = dpp_get_pubkey_point(pub, 1); 1206c1d255d3SCy Schubert if (!uncomp) 1207c1d255d3SCy Schubert return -1; 1208c1d255d3SCy Schubert addr[0] = wpabuf_head(uncomp); 1209c1d255d3SCy Schubert len[0] = wpabuf_len(uncomp); 1210c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key", 1211c1d255d3SCy Schubert addr[0], len[0]); 1212c1d255d3SCy Schubert res = sha256_vector(1, addr, len, hash); 1213c1d255d3SCy Schubert wpabuf_free(uncomp); 1214c1d255d3SCy Schubert if (res < 0) 1215c1d255d3SCy Schubert return -1; 1216c1d255d3SCy Schubert if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) { 1217c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1218c1d255d3SCy Schubert "DPP: Received hash value does not match calculated public key hash value"); 1219c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash", 1220c1d255d3SCy Schubert hash, SHA256_MAC_LEN); 1221c1d255d3SCy Schubert return -1; 1222c1d255d3SCy Schubert } 1223c1d255d3SCy Schubert return 0; 1224c1d255d3SCy Schubert } 1225c1d255d3SCy Schubert 1226c1d255d3SCy Schubert 1227c1d255d3SCy Schubert enum dpp_status_error 1228c1d255d3SCy Schubert dpp_process_signed_connector(struct dpp_signed_connector_info *info, 1229*db0ac6deSCy Schubert EVP_PKEY *csign_pub, const char *connector) 1230c1d255d3SCy Schubert { 1231c1d255d3SCy Schubert enum dpp_status_error ret = 255; 1232c1d255d3SCy Schubert const char *pos, *end, *signed_start, *signed_end; 1233c1d255d3SCy Schubert struct wpabuf *kid = NULL; 1234c1d255d3SCy Schubert unsigned char *prot_hdr = NULL, *signature = NULL; 1235*db0ac6deSCy Schubert size_t prot_hdr_len = 0, signature_len = 0; 1236*db0ac6deSCy Schubert const EVP_MD *sign_md = NULL; 1237*db0ac6deSCy Schubert unsigned char *der = NULL; 1238*db0ac6deSCy Schubert int der_len; 1239*db0ac6deSCy Schubert int res; 1240*db0ac6deSCy Schubert EVP_MD_CTX *md_ctx = NULL; 1241*db0ac6deSCy Schubert ECDSA_SIG *sig = NULL; 1242*db0ac6deSCy Schubert BIGNUM *r = NULL, *s = NULL; 1243c1d255d3SCy Schubert const struct dpp_curve_params *curve; 1244*db0ac6deSCy Schubert const EC_KEY *eckey; 1245*db0ac6deSCy Schubert const EC_GROUP *group; 1246*db0ac6deSCy Schubert int nid; 1247c1d255d3SCy Schubert 1248*db0ac6deSCy Schubert eckey = EVP_PKEY_get0_EC_KEY(csign_pub); 1249*db0ac6deSCy Schubert if (!eckey) 1250*db0ac6deSCy Schubert goto fail; 1251*db0ac6deSCy Schubert group = EC_KEY_get0_group(eckey); 1252*db0ac6deSCy Schubert if (!group) 1253*db0ac6deSCy Schubert goto fail; 1254*db0ac6deSCy Schubert nid = EC_GROUP_get_curve_name(group); 1255*db0ac6deSCy Schubert curve = dpp_get_curve_nid(nid); 1256c1d255d3SCy Schubert if (!curve) 1257c1d255d3SCy Schubert goto fail; 1258c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv); 1259c1d255d3SCy Schubert os_memset(info, 0, sizeof(*info)); 1260c1d255d3SCy Schubert 1261c1d255d3SCy Schubert signed_start = pos = connector; 1262c1d255d3SCy Schubert end = os_strchr(pos, '.'); 1263c1d255d3SCy Schubert if (!end) { 1264c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector"); 1265c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 1266c1d255d3SCy Schubert goto fail; 1267c1d255d3SCy Schubert } 1268c1d255d3SCy Schubert prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len); 1269c1d255d3SCy Schubert if (!prot_hdr) { 1270c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1271c1d255d3SCy Schubert "DPP: Failed to base64url decode signedConnector JWS Protected Header"); 1272c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 1273c1d255d3SCy Schubert goto fail; 1274c1d255d3SCy Schubert } 1275c1d255d3SCy Schubert wpa_hexdump_ascii(MSG_DEBUG, 1276c1d255d3SCy Schubert "DPP: signedConnector - JWS Protected Header", 1277c1d255d3SCy Schubert prot_hdr, prot_hdr_len); 1278*db0ac6deSCy Schubert kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md); 1279c1d255d3SCy Schubert if (!kid) { 1280c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 1281c1d255d3SCy Schubert goto fail; 1282c1d255d3SCy Schubert } 1283c1d255d3SCy Schubert if (wpabuf_len(kid) != SHA256_MAC_LEN) { 1284c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1285c1d255d3SCy Schubert "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)", 1286c1d255d3SCy Schubert (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN); 1287c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 1288c1d255d3SCy Schubert goto fail; 1289c1d255d3SCy Schubert } 1290c1d255d3SCy Schubert 1291c1d255d3SCy Schubert pos = end + 1; 1292c1d255d3SCy Schubert end = os_strchr(pos, '.'); 1293c1d255d3SCy Schubert if (!end) { 1294c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1295c1d255d3SCy Schubert "DPP: Missing dot(2) in signedConnector"); 1296c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 1297c1d255d3SCy Schubert goto fail; 1298c1d255d3SCy Schubert } 1299c1d255d3SCy Schubert signed_end = end - 1; 1300c1d255d3SCy Schubert info->payload = base64_url_decode(pos, end - pos, &info->payload_len); 1301c1d255d3SCy Schubert if (!info->payload) { 1302c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1303c1d255d3SCy Schubert "DPP: Failed to base64url decode signedConnector JWS Payload"); 1304c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 1305c1d255d3SCy Schubert goto fail; 1306c1d255d3SCy Schubert } 1307c1d255d3SCy Schubert wpa_hexdump_ascii(MSG_DEBUG, 1308c1d255d3SCy Schubert "DPP: signedConnector - JWS Payload", 1309c1d255d3SCy Schubert info->payload, info->payload_len); 1310c1d255d3SCy Schubert pos = end + 1; 1311c1d255d3SCy Schubert signature = base64_url_decode(pos, os_strlen(pos), &signature_len); 1312c1d255d3SCy Schubert if (!signature) { 1313c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1314c1d255d3SCy Schubert "DPP: Failed to base64url decode signedConnector signature"); 1315c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 1316c1d255d3SCy Schubert goto fail; 1317c1d255d3SCy Schubert } 1318c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature", 1319c1d255d3SCy Schubert signature, signature_len); 1320c1d255d3SCy Schubert 1321c1d255d3SCy Schubert if (dpp_check_pubkey_match(csign_pub, kid) < 0) { 1322c1d255d3SCy Schubert ret = DPP_STATUS_NO_MATCH; 1323c1d255d3SCy Schubert goto fail; 1324c1d255d3SCy Schubert } 1325c1d255d3SCy Schubert 1326c1d255d3SCy Schubert if (signature_len & 0x01) { 1327c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1328c1d255d3SCy Schubert "DPP: Unexpected signedConnector signature length (%d)", 1329c1d255d3SCy Schubert (int) signature_len); 1330c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 1331c1d255d3SCy Schubert goto fail; 1332c1d255d3SCy Schubert } 1333c1d255d3SCy Schubert 1334*db0ac6deSCy Schubert /* JWS Signature encodes the signature (r,s) as two octet strings. Need 1335*db0ac6deSCy Schubert * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */ 1336*db0ac6deSCy Schubert r = BN_bin2bn(signature, signature_len / 2, NULL); 1337*db0ac6deSCy Schubert s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL); 1338*db0ac6deSCy Schubert sig = ECDSA_SIG_new(); 1339*db0ac6deSCy Schubert if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1) 1340*db0ac6deSCy Schubert goto fail; 1341*db0ac6deSCy Schubert r = NULL; 1342*db0ac6deSCy Schubert s = NULL; 1343*db0ac6deSCy Schubert 1344*db0ac6deSCy Schubert der_len = i2d_ECDSA_SIG(sig, &der); 1345*db0ac6deSCy Schubert if (der_len <= 0) { 1346*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature"); 1347*db0ac6deSCy Schubert goto fail; 1348*db0ac6deSCy Schubert } 1349*db0ac6deSCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len); 1350*db0ac6deSCy Schubert md_ctx = EVP_MD_CTX_create(); 1351*db0ac6deSCy Schubert if (!md_ctx) 1352c1d255d3SCy Schubert goto fail; 1353c1d255d3SCy Schubert 1354*db0ac6deSCy Schubert ERR_clear_error(); 1355*db0ac6deSCy Schubert if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) { 1356*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s", 1357*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 1358c1d255d3SCy Schubert goto fail; 1359*db0ac6deSCy Schubert } 1360*db0ac6deSCy Schubert if (EVP_DigestVerifyUpdate(md_ctx, signed_start, 1361*db0ac6deSCy Schubert signed_end - signed_start + 1) != 1) { 1362*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s", 1363*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 1364c1d255d3SCy Schubert goto fail; 1365*db0ac6deSCy Schubert } 1366*db0ac6deSCy Schubert res = EVP_DigestVerifyFinal(md_ctx, der, der_len); 1367c1d255d3SCy Schubert if (res != 1) { 1368c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 1369*db0ac6deSCy Schubert "DPP: EVP_DigestVerifyFinal failed (res=%d): %s", 1370*db0ac6deSCy Schubert res, ERR_error_string(ERR_get_error(), NULL)); 1371c1d255d3SCy Schubert ret = DPP_STATUS_INVALID_CONNECTOR; 1372c1d255d3SCy Schubert goto fail; 1373c1d255d3SCy Schubert } 1374c1d255d3SCy Schubert 1375c1d255d3SCy Schubert ret = DPP_STATUS_OK; 1376c1d255d3SCy Schubert fail: 1377*db0ac6deSCy Schubert EVP_MD_CTX_destroy(md_ctx); 1378c1d255d3SCy Schubert os_free(prot_hdr); 1379c1d255d3SCy Schubert wpabuf_free(kid); 1380c1d255d3SCy Schubert os_free(signature); 1381*db0ac6deSCy Schubert ECDSA_SIG_free(sig); 1382*db0ac6deSCy Schubert BN_free(r); 1383*db0ac6deSCy Schubert BN_free(s); 1384*db0ac6deSCy Schubert OPENSSL_free(der); 1385c1d255d3SCy Schubert return ret; 1386c1d255d3SCy Schubert } 1387c1d255d3SCy Schubert 1388c1d255d3SCy Schubert 1389c1d255d3SCy Schubert enum dpp_status_error 1390c1d255d3SCy Schubert dpp_check_signed_connector(struct dpp_signed_connector_info *info, 1391c1d255d3SCy Schubert const u8 *csign_key, size_t csign_key_len, 1392c1d255d3SCy Schubert const u8 *peer_connector, size_t peer_connector_len) 1393c1d255d3SCy Schubert { 1394*db0ac6deSCy Schubert const unsigned char *p; 1395*db0ac6deSCy Schubert EVP_PKEY *csign = NULL; 1396c1d255d3SCy Schubert char *signed_connector = NULL; 1397c1d255d3SCy Schubert enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR; 1398c1d255d3SCy Schubert 1399*db0ac6deSCy Schubert p = csign_key; 1400*db0ac6deSCy Schubert csign = d2i_PUBKEY(NULL, &p, csign_key_len); 1401c1d255d3SCy Schubert if (!csign) { 1402c1d255d3SCy Schubert wpa_printf(MSG_ERROR, 1403c1d255d3SCy Schubert "DPP: Failed to parse local C-sign-key information"); 1404c1d255d3SCy Schubert goto fail; 1405c1d255d3SCy Schubert } 1406c1d255d3SCy Schubert 1407c1d255d3SCy Schubert wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector", 1408c1d255d3SCy Schubert peer_connector, peer_connector_len); 1409c1d255d3SCy Schubert signed_connector = os_malloc(peer_connector_len + 1); 1410c1d255d3SCy Schubert if (!signed_connector) 1411c1d255d3SCy Schubert goto fail; 1412c1d255d3SCy Schubert os_memcpy(signed_connector, peer_connector, peer_connector_len); 1413c1d255d3SCy Schubert signed_connector[peer_connector_len] = '\0'; 1414c1d255d3SCy Schubert res = dpp_process_signed_connector(info, csign, signed_connector); 1415c1d255d3SCy Schubert fail: 1416c1d255d3SCy Schubert os_free(signed_connector); 1417*db0ac6deSCy Schubert EVP_PKEY_free(csign); 1418c1d255d3SCy Schubert return res; 1419c1d255d3SCy Schubert } 1420c1d255d3SCy Schubert 1421c1d255d3SCy Schubert 1422c1d255d3SCy Schubert int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) 1423c1d255d3SCy Schubert { 1424c1d255d3SCy Schubert struct wpabuf *pix, *prx, *bix, *brx; 1425c1d255d3SCy Schubert const u8 *addr[7]; 1426c1d255d3SCy Schubert size_t len[7]; 1427c1d255d3SCy Schubert size_t i, num_elem = 0; 1428c1d255d3SCy Schubert size_t nonce_len; 1429c1d255d3SCy Schubert u8 zero = 0; 1430c1d255d3SCy Schubert int res = -1; 1431c1d255d3SCy Schubert 1432c1d255d3SCy Schubert /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ 1433c1d255d3SCy Schubert nonce_len = auth->curve->nonce_len; 1434c1d255d3SCy Schubert 1435c1d255d3SCy Schubert if (auth->initiator) { 1436*db0ac6deSCy Schubert pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); 1437*db0ac6deSCy Schubert prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); 1438c1d255d3SCy Schubert if (auth->own_bi) 1439*db0ac6deSCy Schubert bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); 1440c1d255d3SCy Schubert else 1441c1d255d3SCy Schubert bix = NULL; 1442*db0ac6deSCy Schubert brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); 1443c1d255d3SCy Schubert } else { 1444*db0ac6deSCy Schubert pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); 1445*db0ac6deSCy Schubert prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); 1446c1d255d3SCy Schubert if (auth->peer_bi) 1447*db0ac6deSCy Schubert bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); 1448c1d255d3SCy Schubert else 1449c1d255d3SCy Schubert bix = NULL; 1450*db0ac6deSCy Schubert brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); 1451c1d255d3SCy Schubert } 1452c1d255d3SCy Schubert if (!pix || !prx || !brx) 1453c1d255d3SCy Schubert goto fail; 1454c1d255d3SCy Schubert 1455c1d255d3SCy Schubert addr[num_elem] = auth->i_nonce; 1456c1d255d3SCy Schubert len[num_elem] = nonce_len; 1457c1d255d3SCy Schubert num_elem++; 1458c1d255d3SCy Schubert 1459c1d255d3SCy Schubert addr[num_elem] = auth->r_nonce; 1460c1d255d3SCy Schubert len[num_elem] = nonce_len; 1461c1d255d3SCy Schubert num_elem++; 1462c1d255d3SCy Schubert 1463c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(pix); 1464c1d255d3SCy Schubert len[num_elem] = wpabuf_len(pix) / 2; 1465c1d255d3SCy Schubert num_elem++; 1466c1d255d3SCy Schubert 1467c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(prx); 1468c1d255d3SCy Schubert len[num_elem] = wpabuf_len(prx) / 2; 1469c1d255d3SCy Schubert num_elem++; 1470c1d255d3SCy Schubert 1471c1d255d3SCy Schubert if (bix) { 1472c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(bix); 1473c1d255d3SCy Schubert len[num_elem] = wpabuf_len(bix) / 2; 1474c1d255d3SCy Schubert num_elem++; 1475c1d255d3SCy Schubert } 1476c1d255d3SCy Schubert 1477c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(brx); 1478c1d255d3SCy Schubert len[num_elem] = wpabuf_len(brx) / 2; 1479c1d255d3SCy Schubert num_elem++; 1480c1d255d3SCy Schubert 1481c1d255d3SCy Schubert addr[num_elem] = &zero; 1482c1d255d3SCy Schubert len[num_elem] = 1; 1483c1d255d3SCy Schubert num_elem++; 1484c1d255d3SCy Schubert 1485c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: R-auth hash components"); 1486c1d255d3SCy Schubert for (i = 0; i < num_elem; i++) 1487c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); 1488c1d255d3SCy Schubert res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth); 1489c1d255d3SCy Schubert if (res == 0) 1490c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth, 1491c1d255d3SCy Schubert auth->curve->hash_len); 1492c1d255d3SCy Schubert fail: 1493c1d255d3SCy Schubert wpabuf_free(pix); 1494c1d255d3SCy Schubert wpabuf_free(prx); 1495c1d255d3SCy Schubert wpabuf_free(bix); 1496c1d255d3SCy Schubert wpabuf_free(brx); 1497c1d255d3SCy Schubert return res; 1498c1d255d3SCy Schubert } 1499c1d255d3SCy Schubert 1500c1d255d3SCy Schubert 1501c1d255d3SCy Schubert int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth) 1502c1d255d3SCy Schubert { 1503c1d255d3SCy Schubert struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL; 1504c1d255d3SCy Schubert const u8 *addr[7]; 1505c1d255d3SCy Schubert size_t len[7]; 1506c1d255d3SCy Schubert size_t i, num_elem = 0; 1507c1d255d3SCy Schubert size_t nonce_len; 1508c1d255d3SCy Schubert u8 one = 1; 1509c1d255d3SCy Schubert int res = -1; 1510c1d255d3SCy Schubert 1511c1d255d3SCy Schubert /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ 1512c1d255d3SCy Schubert nonce_len = auth->curve->nonce_len; 1513c1d255d3SCy Schubert 1514c1d255d3SCy Schubert if (auth->initiator) { 1515*db0ac6deSCy Schubert pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); 1516*db0ac6deSCy Schubert prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); 1517c1d255d3SCy Schubert if (auth->own_bi) 1518*db0ac6deSCy Schubert bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); 1519c1d255d3SCy Schubert else 1520c1d255d3SCy Schubert bix = NULL; 1521c1d255d3SCy Schubert if (!auth->peer_bi) 1522c1d255d3SCy Schubert goto fail; 1523*db0ac6deSCy Schubert brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); 1524c1d255d3SCy Schubert } else { 1525*db0ac6deSCy Schubert pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); 1526*db0ac6deSCy Schubert prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); 1527c1d255d3SCy Schubert if (auth->peer_bi) 1528*db0ac6deSCy Schubert bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); 1529c1d255d3SCy Schubert else 1530c1d255d3SCy Schubert bix = NULL; 1531c1d255d3SCy Schubert if (!auth->own_bi) 1532c1d255d3SCy Schubert goto fail; 1533*db0ac6deSCy Schubert brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); 1534c1d255d3SCy Schubert } 1535c1d255d3SCy Schubert if (!pix || !prx || !brx) 1536c1d255d3SCy Schubert goto fail; 1537c1d255d3SCy Schubert 1538c1d255d3SCy Schubert addr[num_elem] = auth->r_nonce; 1539c1d255d3SCy Schubert len[num_elem] = nonce_len; 1540c1d255d3SCy Schubert num_elem++; 1541c1d255d3SCy Schubert 1542c1d255d3SCy Schubert addr[num_elem] = auth->i_nonce; 1543c1d255d3SCy Schubert len[num_elem] = nonce_len; 1544c1d255d3SCy Schubert num_elem++; 1545c1d255d3SCy Schubert 1546c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(prx); 1547c1d255d3SCy Schubert len[num_elem] = wpabuf_len(prx) / 2; 1548c1d255d3SCy Schubert num_elem++; 1549c1d255d3SCy Schubert 1550c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(pix); 1551c1d255d3SCy Schubert len[num_elem] = wpabuf_len(pix) / 2; 1552c1d255d3SCy Schubert num_elem++; 1553c1d255d3SCy Schubert 1554c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(brx); 1555c1d255d3SCy Schubert len[num_elem] = wpabuf_len(brx) / 2; 1556c1d255d3SCy Schubert num_elem++; 1557c1d255d3SCy Schubert 1558c1d255d3SCy Schubert if (bix) { 1559c1d255d3SCy Schubert addr[num_elem] = wpabuf_head(bix); 1560c1d255d3SCy Schubert len[num_elem] = wpabuf_len(bix) / 2; 1561c1d255d3SCy Schubert num_elem++; 1562c1d255d3SCy Schubert } 1563c1d255d3SCy Schubert 1564c1d255d3SCy Schubert addr[num_elem] = &one; 1565c1d255d3SCy Schubert len[num_elem] = 1; 1566c1d255d3SCy Schubert num_elem++; 1567c1d255d3SCy Schubert 1568c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: I-auth hash components"); 1569c1d255d3SCy Schubert for (i = 0; i < num_elem; i++) 1570c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); 1571c1d255d3SCy Schubert res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth); 1572c1d255d3SCy Schubert if (res == 0) 1573c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth, 1574c1d255d3SCy Schubert auth->curve->hash_len); 1575c1d255d3SCy Schubert fail: 1576c1d255d3SCy Schubert wpabuf_free(pix); 1577c1d255d3SCy Schubert wpabuf_free(prx); 1578c1d255d3SCy Schubert wpabuf_free(bix); 1579c1d255d3SCy Schubert wpabuf_free(brx); 1580c1d255d3SCy Schubert return res; 1581c1d255d3SCy Schubert } 1582c1d255d3SCy Schubert 1583c1d255d3SCy Schubert 1584c1d255d3SCy Schubert int dpp_auth_derive_l_responder(struct dpp_authentication *auth) 1585c1d255d3SCy Schubert { 1586*db0ac6deSCy Schubert const EC_GROUP *group; 1587*db0ac6deSCy Schubert EC_POINT *l = NULL; 1588*db0ac6deSCy Schubert const EC_KEY *BI, *bR, *pR; 1589*db0ac6deSCy Schubert const EC_POINT *BI_point; 1590*db0ac6deSCy Schubert BN_CTX *bnctx; 1591*db0ac6deSCy Schubert BIGNUM *lx, *sum, *q; 1592*db0ac6deSCy Schubert const BIGNUM *bR_bn, *pR_bn; 1593c1d255d3SCy Schubert int ret = -1; 1594c1d255d3SCy Schubert 1595c1d255d3SCy Schubert /* L = ((bR + pR) modulo q) * BI */ 1596c1d255d3SCy Schubert 1597*db0ac6deSCy Schubert bnctx = BN_CTX_new(); 1598*db0ac6deSCy Schubert sum = BN_new(); 1599*db0ac6deSCy Schubert q = BN_new(); 1600*db0ac6deSCy Schubert lx = BN_new(); 1601*db0ac6deSCy Schubert if (!bnctx || !sum || !q || !lx) 1602*db0ac6deSCy Schubert goto fail; 1603*db0ac6deSCy Schubert BI = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey); 1604*db0ac6deSCy Schubert if (!BI) 1605*db0ac6deSCy Schubert goto fail; 1606*db0ac6deSCy Schubert BI_point = EC_KEY_get0_public_key(BI); 1607*db0ac6deSCy Schubert group = EC_KEY_get0_group(BI); 1608*db0ac6deSCy Schubert if (!group) 1609c1d255d3SCy Schubert goto fail; 1610c1d255d3SCy Schubert 1611*db0ac6deSCy Schubert bR = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey); 1612*db0ac6deSCy Schubert pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key); 1613*db0ac6deSCy Schubert if (!bR || !pR) 1614c1d255d3SCy Schubert goto fail; 1615*db0ac6deSCy Schubert bR_bn = EC_KEY_get0_private_key(bR); 1616*db0ac6deSCy Schubert pR_bn = EC_KEY_get0_private_key(pR); 1617*db0ac6deSCy Schubert if (!bR_bn || !pR_bn) 1618*db0ac6deSCy Schubert goto fail; 1619*db0ac6deSCy Schubert if (EC_GROUP_get_order(group, q, bnctx) != 1 || 1620*db0ac6deSCy Schubert BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1) 1621*db0ac6deSCy Schubert goto fail; 1622*db0ac6deSCy Schubert l = EC_POINT_new(group); 1623*db0ac6deSCy Schubert if (!l || 1624*db0ac6deSCy Schubert EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 || 1625*db0ac6deSCy Schubert EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, 1626*db0ac6deSCy Schubert bnctx) != 1) { 1627*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 1628*db0ac6deSCy Schubert "OpenSSL: failed: %s", 1629*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 1630*db0ac6deSCy Schubert goto fail; 1631*db0ac6deSCy Schubert } 1632c1d255d3SCy Schubert 1633*db0ac6deSCy Schubert if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) 1634*db0ac6deSCy Schubert goto fail; 1635c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); 1636c1d255d3SCy Schubert auth->Lx_len = auth->secret_len; 1637c1d255d3SCy Schubert ret = 0; 1638c1d255d3SCy Schubert fail: 1639*db0ac6deSCy Schubert EC_POINT_clear_free(l); 1640*db0ac6deSCy Schubert BN_clear_free(lx); 1641*db0ac6deSCy Schubert BN_clear_free(sum); 1642*db0ac6deSCy Schubert BN_free(q); 1643*db0ac6deSCy Schubert BN_CTX_free(bnctx); 1644c1d255d3SCy Schubert return ret; 1645c1d255d3SCy Schubert } 1646c1d255d3SCy Schubert 1647c1d255d3SCy Schubert 1648c1d255d3SCy Schubert int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) 1649c1d255d3SCy Schubert { 1650*db0ac6deSCy Schubert const EC_GROUP *group; 1651*db0ac6deSCy Schubert EC_POINT *l = NULL, *sum = NULL; 1652*db0ac6deSCy Schubert const EC_KEY *bI, *BR, *PR; 1653*db0ac6deSCy Schubert const EC_POINT *BR_point, *PR_point; 1654*db0ac6deSCy Schubert BN_CTX *bnctx; 1655*db0ac6deSCy Schubert BIGNUM *lx; 1656*db0ac6deSCy Schubert const BIGNUM *bI_bn; 1657c1d255d3SCy Schubert int ret = -1; 1658c1d255d3SCy Schubert 1659c1d255d3SCy Schubert /* L = bI * (BR + PR) */ 1660c1d255d3SCy Schubert 1661*db0ac6deSCy Schubert bnctx = BN_CTX_new(); 1662*db0ac6deSCy Schubert lx = BN_new(); 1663*db0ac6deSCy Schubert if (!bnctx || !lx) 1664c1d255d3SCy Schubert goto fail; 1665*db0ac6deSCy Schubert BR = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey); 1666*db0ac6deSCy Schubert PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key); 1667*db0ac6deSCy Schubert if (!BR || !PR) 1668c1d255d3SCy Schubert goto fail; 1669*db0ac6deSCy Schubert BR_point = EC_KEY_get0_public_key(BR); 1670*db0ac6deSCy Schubert PR_point = EC_KEY_get0_public_key(PR); 1671c1d255d3SCy Schubert 1672*db0ac6deSCy Schubert bI = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey); 1673*db0ac6deSCy Schubert if (!bI) 1674*db0ac6deSCy Schubert goto fail; 1675*db0ac6deSCy Schubert group = EC_KEY_get0_group(bI); 1676*db0ac6deSCy Schubert bI_bn = EC_KEY_get0_private_key(bI); 1677*db0ac6deSCy Schubert if (!group || !bI_bn) 1678*db0ac6deSCy Schubert goto fail; 1679*db0ac6deSCy Schubert sum = EC_POINT_new(group); 1680*db0ac6deSCy Schubert l = EC_POINT_new(group); 1681*db0ac6deSCy Schubert if (!sum || !l || 1682*db0ac6deSCy Schubert EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 || 1683*db0ac6deSCy Schubert EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 || 1684*db0ac6deSCy Schubert EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, 1685*db0ac6deSCy Schubert bnctx) != 1) { 1686*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 1687*db0ac6deSCy Schubert "OpenSSL: failed: %s", 1688*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 1689*db0ac6deSCy Schubert goto fail; 1690*db0ac6deSCy Schubert } 1691*db0ac6deSCy Schubert 1692*db0ac6deSCy Schubert if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) 1693*db0ac6deSCy Schubert goto fail; 1694c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); 1695c1d255d3SCy Schubert auth->Lx_len = auth->secret_len; 1696c1d255d3SCy Schubert ret = 0; 1697c1d255d3SCy Schubert fail: 1698*db0ac6deSCy Schubert EC_POINT_clear_free(l); 1699*db0ac6deSCy Schubert EC_POINT_clear_free(sum); 1700*db0ac6deSCy Schubert BN_clear_free(lx); 1701*db0ac6deSCy Schubert BN_CTX_free(bnctx); 1702c1d255d3SCy Schubert return ret; 1703c1d255d3SCy Schubert } 1704c1d255d3SCy Schubert 1705c1d255d3SCy Schubert 1706c1d255d3SCy Schubert int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len) 1707c1d255d3SCy Schubert { 1708c1d255d3SCy Schubert u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 1709c1d255d3SCy Schubert const char *info = "DPP PMK"; 1710c1d255d3SCy Schubert int res; 1711c1d255d3SCy Schubert 1712c1d255d3SCy Schubert /* PMK = HKDF(<>, "DPP PMK", N.x) */ 1713c1d255d3SCy Schubert 1714c1d255d3SCy Schubert /* HKDF-Extract(<>, N.x) */ 1715c1d255d3SCy Schubert os_memset(salt, 0, hash_len); 1716c1d255d3SCy Schubert if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0) 1717c1d255d3SCy Schubert return -1; 1718c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", 1719c1d255d3SCy Schubert prk, hash_len); 1720c1d255d3SCy Schubert 1721c1d255d3SCy Schubert /* HKDF-Expand(PRK, info, L) */ 1722c1d255d3SCy Schubert res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len); 1723c1d255d3SCy Schubert os_memset(prk, 0, hash_len); 1724c1d255d3SCy Schubert if (res < 0) 1725c1d255d3SCy Schubert return -1; 1726c1d255d3SCy Schubert 1727c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)", 1728c1d255d3SCy Schubert pmk, hash_len); 1729c1d255d3SCy Schubert return 0; 1730c1d255d3SCy Schubert } 1731c1d255d3SCy Schubert 1732c1d255d3SCy Schubert 1733c1d255d3SCy Schubert int dpp_derive_pmkid(const struct dpp_curve_params *curve, 1734*db0ac6deSCy Schubert EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid) 1735c1d255d3SCy Schubert { 1736c1d255d3SCy Schubert struct wpabuf *nkx, *pkx; 1737c1d255d3SCy Schubert int ret = -1, res; 1738c1d255d3SCy Schubert const u8 *addr[2]; 1739c1d255d3SCy Schubert size_t len[2]; 1740c1d255d3SCy Schubert u8 hash[SHA256_MAC_LEN]; 1741c1d255d3SCy Schubert 1742c1d255d3SCy Schubert /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */ 1743*db0ac6deSCy Schubert nkx = dpp_get_pubkey_point(own_key, 0); 1744*db0ac6deSCy Schubert pkx = dpp_get_pubkey_point(peer_key, 0); 1745c1d255d3SCy Schubert if (!nkx || !pkx) 1746c1d255d3SCy Schubert goto fail; 1747c1d255d3SCy Schubert addr[0] = wpabuf_head(nkx); 1748c1d255d3SCy Schubert len[0] = wpabuf_len(nkx) / 2; 1749c1d255d3SCy Schubert addr[1] = wpabuf_head(pkx); 1750c1d255d3SCy Schubert len[1] = wpabuf_len(pkx) / 2; 1751c1d255d3SCy Schubert if (len[0] != len[1]) 1752c1d255d3SCy Schubert goto fail; 1753c1d255d3SCy Schubert if (os_memcmp(addr[0], addr[1], len[0]) > 0) { 1754c1d255d3SCy Schubert addr[0] = wpabuf_head(pkx); 1755c1d255d3SCy Schubert addr[1] = wpabuf_head(nkx); 1756c1d255d3SCy Schubert } 1757c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]); 1758c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]); 1759c1d255d3SCy Schubert res = sha256_vector(2, addr, len, hash); 1760c1d255d3SCy Schubert if (res < 0) 1761c1d255d3SCy Schubert goto fail; 1762c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN); 1763c1d255d3SCy Schubert os_memcpy(pmkid, hash, PMKID_LEN); 1764c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN); 1765c1d255d3SCy Schubert ret = 0; 1766c1d255d3SCy Schubert fail: 1767c1d255d3SCy Schubert wpabuf_free(nkx); 1768c1d255d3SCy Schubert wpabuf_free(pkx); 1769c1d255d3SCy Schubert return ret; 1770c1d255d3SCy Schubert } 1771c1d255d3SCy Schubert 1772c1d255d3SCy Schubert 1773c1d255d3SCy Schubert /* Role-specific elements for PKEX */ 1774c1d255d3SCy Schubert 1775c1d255d3SCy Schubert /* NIST P-256 */ 1776c1d255d3SCy Schubert static const u8 pkex_init_x_p256[32] = { 1777c1d255d3SCy Schubert 0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b, 1778c1d255d3SCy Schubert 0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54, 1779c1d255d3SCy Schubert 0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07, 1780c1d255d3SCy Schubert 0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25 1781c1d255d3SCy Schubert }; 1782c1d255d3SCy Schubert static const u8 pkex_init_y_p256[32] = { 1783c1d255d3SCy Schubert 0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b, 1784c1d255d3SCy Schubert 0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc, 1785c1d255d3SCy Schubert 0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45, 1786c1d255d3SCy Schubert 0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4 1787c1d255d3SCy Schubert }; 1788c1d255d3SCy Schubert static const u8 pkex_resp_x_p256[32] = { 1789c1d255d3SCy Schubert 0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39, 1790c1d255d3SCy Schubert 0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f, 1791c1d255d3SCy Schubert 0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f, 1792c1d255d3SCy Schubert 0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76 1793c1d255d3SCy Schubert }; 1794c1d255d3SCy Schubert static const u8 pkex_resp_y_p256[32] = { 1795c1d255d3SCy Schubert 0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19, 1796c1d255d3SCy Schubert 0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1, 1797c1d255d3SCy Schubert 0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a, 1798c1d255d3SCy Schubert 0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67 1799c1d255d3SCy Schubert }; 1800c1d255d3SCy Schubert 1801c1d255d3SCy Schubert /* NIST P-384 */ 1802c1d255d3SCy Schubert static const u8 pkex_init_x_p384[48] = { 1803c1d255d3SCy Schubert 0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa, 1804c1d255d3SCy Schubert 0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68, 1805c1d255d3SCy Schubert 0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53, 1806c1d255d3SCy Schubert 0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac, 1807c1d255d3SCy Schubert 0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12, 1808c1d255d3SCy Schubert 0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3 1809c1d255d3SCy Schubert }; 1810c1d255d3SCy Schubert static const u8 pkex_init_y_p384[48] = { 1811c1d255d3SCy Schubert 0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29, 1812c1d255d3SCy Schubert 0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56, 1813c1d255d3SCy Schubert 0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7, 1814c1d255d3SCy Schubert 0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6, 1815c1d255d3SCy Schubert 0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94, 1816c1d255d3SCy Schubert 0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18 1817c1d255d3SCy Schubert }; 1818c1d255d3SCy Schubert static const u8 pkex_resp_x_p384[48] = { 1819c1d255d3SCy Schubert 0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98, 1820c1d255d3SCy Schubert 0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97, 1821c1d255d3SCy Schubert 0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92, 1822c1d255d3SCy Schubert 0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44, 1823c1d255d3SCy Schubert 0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf, 1824c1d255d3SCy Schubert 0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf 1825c1d255d3SCy Schubert }; 1826c1d255d3SCy Schubert static const u8 pkex_resp_y_p384[48] = { 1827c1d255d3SCy Schubert 0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c, 1828c1d255d3SCy Schubert 0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c, 1829c1d255d3SCy Schubert 0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3, 1830c1d255d3SCy Schubert 0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1, 1831c1d255d3SCy Schubert 0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63, 1832c1d255d3SCy Schubert 0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06 1833c1d255d3SCy Schubert }; 1834c1d255d3SCy Schubert 1835c1d255d3SCy Schubert /* NIST P-521 */ 1836c1d255d3SCy Schubert static const u8 pkex_init_x_p521[66] = { 1837c1d255d3SCy Schubert 0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23, 1838c1d255d3SCy Schubert 0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0, 1839c1d255d3SCy Schubert 0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76, 1840c1d255d3SCy Schubert 0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5, 1841c1d255d3SCy Schubert 0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38, 1842c1d255d3SCy Schubert 0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01, 1843c1d255d3SCy Schubert 0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e, 1844c1d255d3SCy Schubert 0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d, 1845c1d255d3SCy Schubert 0x97, 0x76 1846c1d255d3SCy Schubert }; 1847c1d255d3SCy Schubert static const u8 pkex_init_y_p521[66] = { 1848c1d255d3SCy Schubert 0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59, 1849c1d255d3SCy Schubert 0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99, 1850c1d255d3SCy Schubert 0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b, 1851c1d255d3SCy Schubert 0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd, 1852c1d255d3SCy Schubert 0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f, 1853c1d255d3SCy Schubert 0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf, 1854c1d255d3SCy Schubert 0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02, 1855c1d255d3SCy Schubert 0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d, 1856c1d255d3SCy Schubert 0x03, 0xa8 1857c1d255d3SCy Schubert }; 1858c1d255d3SCy Schubert static const u8 pkex_resp_x_p521[66] = { 1859c1d255d3SCy Schubert 0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a, 1860c1d255d3SCy Schubert 0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44, 1861c1d255d3SCy Schubert 0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f, 1862c1d255d3SCy Schubert 0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb, 1863c1d255d3SCy Schubert 0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48, 1864c1d255d3SCy Schubert 0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e, 1865c1d255d3SCy Schubert 0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a, 1866c1d255d3SCy Schubert 0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97, 1867c1d255d3SCy Schubert 0x84, 0xb4 1868c1d255d3SCy Schubert }; 1869c1d255d3SCy Schubert static const u8 pkex_resp_y_p521[66] = { 1870c1d255d3SCy Schubert 0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d, 1871c1d255d3SCy Schubert 0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20, 1872c1d255d3SCy Schubert 0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3, 1873c1d255d3SCy Schubert 0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84, 1874c1d255d3SCy Schubert 0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9, 1875c1d255d3SCy Schubert 0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2, 1876c1d255d3SCy Schubert 0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80, 1877c1d255d3SCy Schubert 0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53, 1878c1d255d3SCy Schubert 0xce, 0xe1 1879c1d255d3SCy Schubert }; 1880c1d255d3SCy Schubert 1881c1d255d3SCy Schubert /* Brainpool P-256r1 */ 1882c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p256r1[32] = { 1883c1d255d3SCy Schubert 0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10, 1884c1d255d3SCy Schubert 0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca, 1885c1d255d3SCy Schubert 0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75, 1886c1d255d3SCy Schubert 0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8 1887c1d255d3SCy Schubert }; 1888c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p256r1[32] = { 1889c1d255d3SCy Schubert 0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd, 1890c1d255d3SCy Schubert 0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30, 1891c1d255d3SCy Schubert 0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe, 1892c1d255d3SCy Schubert 0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b 1893c1d255d3SCy Schubert }; 1894c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p256r1[32] = { 1895c1d255d3SCy Schubert 0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f, 1896c1d255d3SCy Schubert 0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a, 1897c1d255d3SCy Schubert 0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a, 1898c1d255d3SCy Schubert 0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3 1899c1d255d3SCy Schubert }; 1900c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p256r1[32] = { 1901c1d255d3SCy Schubert 0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd, 1902c1d255d3SCy Schubert 0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2, 1903c1d255d3SCy Schubert 0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e, 1904c1d255d3SCy Schubert 0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64 1905c1d255d3SCy Schubert }; 1906c1d255d3SCy Schubert 1907c1d255d3SCy Schubert /* Brainpool P-384r1 */ 1908c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p384r1[48] = { 1909c1d255d3SCy Schubert 0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd, 1910c1d255d3SCy Schubert 0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19, 1911c1d255d3SCy Schubert 0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06, 1912c1d255d3SCy Schubert 0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62, 1913c1d255d3SCy Schubert 0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30, 1914c1d255d3SCy Schubert 0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe 1915c1d255d3SCy Schubert }; 1916c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p384r1[48] = { 1917c1d255d3SCy Schubert 0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99, 1918c1d255d3SCy Schubert 0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86, 1919c1d255d3SCy Schubert 0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32, 1920c1d255d3SCy Schubert 0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9, 1921c1d255d3SCy Schubert 0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e, 1922c1d255d3SCy Schubert 0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52 1923c1d255d3SCy Schubert }; 1924c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p384r1[48] = { 1925c1d255d3SCy Schubert 0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0, 1926c1d255d3SCy Schubert 0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25, 1927c1d255d3SCy Schubert 0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b, 1928c1d255d3SCy Schubert 0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71, 1929c1d255d3SCy Schubert 0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce, 1930c1d255d3SCy Schubert 0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c 1931c1d255d3SCy Schubert }; 1932c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p384r1[48] = { 1933c1d255d3SCy Schubert 0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65, 1934c1d255d3SCy Schubert 0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04, 1935c1d255d3SCy Schubert 0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70, 1936c1d255d3SCy Schubert 0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c, 1937c1d255d3SCy Schubert 0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb, 1938c1d255d3SCy Schubert 0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1 1939c1d255d3SCy Schubert }; 1940c1d255d3SCy Schubert 1941c1d255d3SCy Schubert /* Brainpool P-512r1 */ 1942c1d255d3SCy Schubert static const u8 pkex_init_x_bp_p512r1[64] = { 1943c1d255d3SCy Schubert 0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c, 1944c1d255d3SCy Schubert 0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51, 1945c1d255d3SCy Schubert 0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc, 1946c1d255d3SCy Schubert 0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95, 1947c1d255d3SCy Schubert 0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d, 1948c1d255d3SCy Schubert 0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff, 1949c1d255d3SCy Schubert 0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc, 1950c1d255d3SCy Schubert 0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f 1951c1d255d3SCy Schubert }; 1952c1d255d3SCy Schubert static const u8 pkex_init_y_bp_p512r1[64] = { 1953c1d255d3SCy Schubert 0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94, 1954c1d255d3SCy Schubert 0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8, 1955c1d255d3SCy Schubert 0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3, 1956c1d255d3SCy Schubert 0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45, 1957c1d255d3SCy Schubert 0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e, 1958c1d255d3SCy Schubert 0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58, 1959c1d255d3SCy Schubert 0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71, 1960c1d255d3SCy Schubert 0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99 1961c1d255d3SCy Schubert }; 1962c1d255d3SCy Schubert static const u8 pkex_resp_x_bp_p512r1[64] = { 1963c1d255d3SCy Schubert 0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72, 1964c1d255d3SCy Schubert 0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76, 1965c1d255d3SCy Schubert 0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19, 1966c1d255d3SCy Schubert 0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e, 1967c1d255d3SCy Schubert 0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9, 1968c1d255d3SCy Schubert 0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88, 1969c1d255d3SCy Schubert 0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29, 1970c1d255d3SCy Schubert 0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e 1971c1d255d3SCy Schubert }; 1972c1d255d3SCy Schubert static const u8 pkex_resp_y_bp_p512r1[64] = { 1973c1d255d3SCy Schubert 0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81, 1974c1d255d3SCy Schubert 0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68, 1975c1d255d3SCy Schubert 0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa, 1976c1d255d3SCy Schubert 0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d, 1977c1d255d3SCy Schubert 0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c, 1978c1d255d3SCy Schubert 0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09, 1979c1d255d3SCy Schubert 0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56, 1980c1d255d3SCy Schubert 0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7 1981c1d255d3SCy Schubert }; 1982c1d255d3SCy Schubert 1983c1d255d3SCy Schubert 1984*db0ac6deSCy Schubert static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, 1985*db0ac6deSCy Schubert int init) 1986c1d255d3SCy Schubert { 1987*db0ac6deSCy Schubert EC_GROUP *group; 1988*db0ac6deSCy Schubert size_t len = curve->prime_len; 1989c1d255d3SCy Schubert const u8 *x, *y; 1990*db0ac6deSCy Schubert EVP_PKEY *res; 1991c1d255d3SCy Schubert 1992c1d255d3SCy Schubert switch (curve->ike_group) { 1993c1d255d3SCy Schubert case 19: 1994c1d255d3SCy Schubert x = init ? pkex_init_x_p256 : pkex_resp_x_p256; 1995c1d255d3SCy Schubert y = init ? pkex_init_y_p256 : pkex_resp_y_p256; 1996c1d255d3SCy Schubert break; 1997c1d255d3SCy Schubert case 20: 1998c1d255d3SCy Schubert x = init ? pkex_init_x_p384 : pkex_resp_x_p384; 1999c1d255d3SCy Schubert y = init ? pkex_init_y_p384 : pkex_resp_y_p384; 2000c1d255d3SCy Schubert break; 2001c1d255d3SCy Schubert case 21: 2002c1d255d3SCy Schubert x = init ? pkex_init_x_p521 : pkex_resp_x_p521; 2003c1d255d3SCy Schubert y = init ? pkex_init_y_p521 : pkex_resp_y_p521; 2004c1d255d3SCy Schubert break; 2005c1d255d3SCy Schubert case 28: 2006c1d255d3SCy Schubert x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1; 2007c1d255d3SCy Schubert y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1; 2008c1d255d3SCy Schubert break; 2009c1d255d3SCy Schubert case 29: 2010c1d255d3SCy Schubert x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1; 2011c1d255d3SCy Schubert y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1; 2012c1d255d3SCy Schubert break; 2013c1d255d3SCy Schubert case 30: 2014c1d255d3SCy Schubert x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1; 2015c1d255d3SCy Schubert y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1; 2016c1d255d3SCy Schubert break; 2017c1d255d3SCy Schubert default: 2018c1d255d3SCy Schubert return NULL; 2019c1d255d3SCy Schubert } 2020c1d255d3SCy Schubert 2021*db0ac6deSCy Schubert group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); 2022*db0ac6deSCy Schubert if (!group) 2023*db0ac6deSCy Schubert return NULL; 2024*db0ac6deSCy Schubert res = dpp_set_pubkey_point_group(group, x, y, len); 2025*db0ac6deSCy Schubert EC_GROUP_free(group); 2026*db0ac6deSCy Schubert return res; 2027c1d255d3SCy Schubert } 2028c1d255d3SCy Schubert 2029c1d255d3SCy Schubert 2030*db0ac6deSCy Schubert EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, 2031*db0ac6deSCy Schubert const u8 *mac_init, const char *code, 2032*db0ac6deSCy Schubert const char *identifier, BN_CTX *bnctx, 2033*db0ac6deSCy Schubert EC_GROUP **ret_group) 2034c1d255d3SCy Schubert { 2035c1d255d3SCy Schubert u8 hash[DPP_MAX_HASH_LEN]; 2036c1d255d3SCy Schubert const u8 *addr[3]; 2037c1d255d3SCy Schubert size_t len[3]; 2038c1d255d3SCy Schubert unsigned int num_elem = 0; 2039*db0ac6deSCy Schubert EC_POINT *Qi = NULL; 2040*db0ac6deSCy Schubert EVP_PKEY *Pi = NULL; 2041*db0ac6deSCy Schubert const EC_KEY *Pi_ec; 2042*db0ac6deSCy Schubert const EC_POINT *Pi_point; 2043*db0ac6deSCy Schubert BIGNUM *hash_bn = NULL; 2044*db0ac6deSCy Schubert const EC_GROUP *group = NULL; 2045*db0ac6deSCy Schubert EC_GROUP *group2 = NULL; 2046c1d255d3SCy Schubert 2047c1d255d3SCy Schubert /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ 2048c1d255d3SCy Schubert 2049c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init)); 2050c1d255d3SCy Schubert addr[num_elem] = mac_init; 2051c1d255d3SCy Schubert len[num_elem] = ETH_ALEN; 2052c1d255d3SCy Schubert num_elem++; 2053c1d255d3SCy Schubert if (identifier) { 2054c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", 2055c1d255d3SCy Schubert identifier); 2056c1d255d3SCy Schubert addr[num_elem] = (const u8 *) identifier; 2057c1d255d3SCy Schubert len[num_elem] = os_strlen(identifier); 2058c1d255d3SCy Schubert num_elem++; 2059c1d255d3SCy Schubert } 2060c1d255d3SCy Schubert wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); 2061c1d255d3SCy Schubert addr[num_elem] = (const u8 *) code; 2062c1d255d3SCy Schubert len[num_elem] = os_strlen(code); 2063c1d255d3SCy Schubert num_elem++; 2064c1d255d3SCy Schubert if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) 2065c1d255d3SCy Schubert goto fail; 2066c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 2067c1d255d3SCy Schubert "DPP: H(MAC-Initiator | [identifier |] code)", 2068c1d255d3SCy Schubert hash, curve->hash_len); 2069*db0ac6deSCy Schubert Pi = dpp_pkex_get_role_elem(curve, 1); 2070*db0ac6deSCy Schubert if (!Pi) 2071c1d255d3SCy Schubert goto fail; 2072*db0ac6deSCy Schubert dpp_debug_print_key("DPP: Pi", Pi); 2073*db0ac6deSCy Schubert Pi_ec = EVP_PKEY_get0_EC_KEY(Pi); 2074*db0ac6deSCy Schubert if (!Pi_ec) 2075c1d255d3SCy Schubert goto fail; 2076*db0ac6deSCy Schubert Pi_point = EC_KEY_get0_public_key(Pi_ec); 2077266f97b5SCy Schubert 2078*db0ac6deSCy Schubert group = EC_KEY_get0_group(Pi_ec); 2079*db0ac6deSCy Schubert if (!group) 2080c1d255d3SCy Schubert goto fail; 2081*db0ac6deSCy Schubert group2 = EC_GROUP_dup(group); 2082*db0ac6deSCy Schubert if (!group2) 2083*db0ac6deSCy Schubert goto fail; 2084*db0ac6deSCy Schubert Qi = EC_POINT_new(group2); 2085*db0ac6deSCy Schubert if (!Qi) { 2086*db0ac6deSCy Schubert EC_GROUP_free(group2); 2087*db0ac6deSCy Schubert goto fail; 2088*db0ac6deSCy Schubert } 2089*db0ac6deSCy Schubert hash_bn = BN_bin2bn(hash, curve->hash_len, NULL); 2090*db0ac6deSCy Schubert if (!hash_bn || 2091*db0ac6deSCy Schubert EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1) 2092*db0ac6deSCy Schubert goto fail; 2093*db0ac6deSCy Schubert if (EC_POINT_is_at_infinity(group, Qi)) { 2094c1d255d3SCy Schubert wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity"); 2095c1d255d3SCy Schubert goto fail; 2096c1d255d3SCy Schubert } 2097*db0ac6deSCy Schubert dpp_debug_print_point("DPP: Qi", group, Qi); 2098c1d255d3SCy Schubert out: 2099*db0ac6deSCy Schubert EVP_PKEY_free(Pi); 2100*db0ac6deSCy Schubert BN_clear_free(hash_bn); 2101*db0ac6deSCy Schubert if (ret_group && Qi) 2102*db0ac6deSCy Schubert *ret_group = group2; 2103c1d255d3SCy Schubert else 2104*db0ac6deSCy Schubert EC_GROUP_free(group2); 2105c1d255d3SCy Schubert return Qi; 2106c1d255d3SCy Schubert fail: 2107*db0ac6deSCy Schubert EC_POINT_free(Qi); 2108c1d255d3SCy Schubert Qi = NULL; 2109c1d255d3SCy Schubert goto out; 2110c1d255d3SCy Schubert } 2111c1d255d3SCy Schubert 2112c1d255d3SCy Schubert 2113*db0ac6deSCy Schubert EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, 2114*db0ac6deSCy Schubert const u8 *mac_resp, const char *code, 2115*db0ac6deSCy Schubert const char *identifier, BN_CTX *bnctx, 2116*db0ac6deSCy Schubert EC_GROUP **ret_group) 2117c1d255d3SCy Schubert { 2118c1d255d3SCy Schubert u8 hash[DPP_MAX_HASH_LEN]; 2119c1d255d3SCy Schubert const u8 *addr[3]; 2120c1d255d3SCy Schubert size_t len[3]; 2121c1d255d3SCy Schubert unsigned int num_elem = 0; 2122*db0ac6deSCy Schubert EC_POINT *Qr = NULL; 2123*db0ac6deSCy Schubert EVP_PKEY *Pr = NULL; 2124*db0ac6deSCy Schubert const EC_KEY *Pr_ec; 2125*db0ac6deSCy Schubert const EC_POINT *Pr_point; 2126*db0ac6deSCy Schubert BIGNUM *hash_bn = NULL; 2127*db0ac6deSCy Schubert const EC_GROUP *group = NULL; 2128*db0ac6deSCy Schubert EC_GROUP *group2 = NULL; 2129c1d255d3SCy Schubert 2130c1d255d3SCy Schubert /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */ 2131c1d255d3SCy Schubert 2132c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp)); 2133c1d255d3SCy Schubert addr[num_elem] = mac_resp; 2134c1d255d3SCy Schubert len[num_elem] = ETH_ALEN; 2135c1d255d3SCy Schubert num_elem++; 2136c1d255d3SCy Schubert if (identifier) { 2137c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", 2138c1d255d3SCy Schubert identifier); 2139c1d255d3SCy Schubert addr[num_elem] = (const u8 *) identifier; 2140c1d255d3SCy Schubert len[num_elem] = os_strlen(identifier); 2141c1d255d3SCy Schubert num_elem++; 2142c1d255d3SCy Schubert } 2143c1d255d3SCy Schubert wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); 2144c1d255d3SCy Schubert addr[num_elem] = (const u8 *) code; 2145c1d255d3SCy Schubert len[num_elem] = os_strlen(code); 2146c1d255d3SCy Schubert num_elem++; 2147c1d255d3SCy Schubert if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) 2148c1d255d3SCy Schubert goto fail; 2149c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 2150c1d255d3SCy Schubert "DPP: H(MAC-Responder | [identifier |] code)", 2151c1d255d3SCy Schubert hash, curve->hash_len); 2152*db0ac6deSCy Schubert Pr = dpp_pkex_get_role_elem(curve, 0); 2153*db0ac6deSCy Schubert if (!Pr) 2154c1d255d3SCy Schubert goto fail; 2155*db0ac6deSCy Schubert dpp_debug_print_key("DPP: Pr", Pr); 2156*db0ac6deSCy Schubert Pr_ec = EVP_PKEY_get0_EC_KEY(Pr); 2157*db0ac6deSCy Schubert if (!Pr_ec) 2158c1d255d3SCy Schubert goto fail; 2159*db0ac6deSCy Schubert Pr_point = EC_KEY_get0_public_key(Pr_ec); 2160266f97b5SCy Schubert 2161*db0ac6deSCy Schubert group = EC_KEY_get0_group(Pr_ec); 2162*db0ac6deSCy Schubert if (!group) 2163c1d255d3SCy Schubert goto fail; 2164*db0ac6deSCy Schubert group2 = EC_GROUP_dup(group); 2165*db0ac6deSCy Schubert if (!group2) 2166*db0ac6deSCy Schubert goto fail; 2167*db0ac6deSCy Schubert Qr = EC_POINT_new(group2); 2168*db0ac6deSCy Schubert if (!Qr) { 2169*db0ac6deSCy Schubert EC_GROUP_free(group2); 2170*db0ac6deSCy Schubert goto fail; 2171*db0ac6deSCy Schubert } 2172*db0ac6deSCy Schubert hash_bn = BN_bin2bn(hash, curve->hash_len, NULL); 2173*db0ac6deSCy Schubert if (!hash_bn || 2174*db0ac6deSCy Schubert EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1) 2175*db0ac6deSCy Schubert goto fail; 2176*db0ac6deSCy Schubert if (EC_POINT_is_at_infinity(group, Qr)) { 2177c1d255d3SCy Schubert wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity"); 2178c1d255d3SCy Schubert goto fail; 2179c1d255d3SCy Schubert } 2180*db0ac6deSCy Schubert dpp_debug_print_point("DPP: Qr", group, Qr); 2181c1d255d3SCy Schubert out: 2182*db0ac6deSCy Schubert EVP_PKEY_free(Pr); 2183*db0ac6deSCy Schubert BN_clear_free(hash_bn); 2184*db0ac6deSCy Schubert if (ret_group && Qr) 2185*db0ac6deSCy Schubert *ret_group = group2; 2186c1d255d3SCy Schubert else 2187*db0ac6deSCy Schubert EC_GROUP_free(group2); 2188c1d255d3SCy Schubert return Qr; 2189c1d255d3SCy Schubert fail: 2190*db0ac6deSCy Schubert EC_POINT_free(Qr); 2191c1d255d3SCy Schubert Qr = NULL; 2192c1d255d3SCy Schubert goto out; 2193c1d255d3SCy Schubert } 2194c1d255d3SCy Schubert 2195c1d255d3SCy Schubert 2196c1d255d3SCy Schubert int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, 2197c1d255d3SCy Schubert const u8 *Mx, size_t Mx_len, 2198c1d255d3SCy Schubert const u8 *Nx, size_t Nx_len, 2199c1d255d3SCy Schubert const char *code, 2200c1d255d3SCy Schubert const u8 *Kx, size_t Kx_len, 2201c1d255d3SCy Schubert u8 *z, unsigned int hash_len) 2202c1d255d3SCy Schubert { 2203c1d255d3SCy Schubert u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; 2204c1d255d3SCy Schubert int res; 2205c1d255d3SCy Schubert u8 *info, *pos; 2206c1d255d3SCy Schubert size_t info_len; 2207c1d255d3SCy Schubert 2208c1d255d3SCy Schubert /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) 2209c1d255d3SCy Schubert */ 2210c1d255d3SCy Schubert 2211c1d255d3SCy Schubert /* HKDF-Extract(<>, IKM=K.x) */ 2212c1d255d3SCy Schubert os_memset(salt, 0, hash_len); 2213c1d255d3SCy Schubert if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0) 2214c1d255d3SCy Schubert return -1; 2215c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", 2216c1d255d3SCy Schubert prk, hash_len); 2217c1d255d3SCy Schubert info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code); 2218c1d255d3SCy Schubert info = os_malloc(info_len); 2219c1d255d3SCy Schubert if (!info) 2220c1d255d3SCy Schubert return -1; 2221c1d255d3SCy Schubert pos = info; 2222c1d255d3SCy Schubert os_memcpy(pos, mac_init, ETH_ALEN); 2223c1d255d3SCy Schubert pos += ETH_ALEN; 2224c1d255d3SCy Schubert os_memcpy(pos, mac_resp, ETH_ALEN); 2225c1d255d3SCy Schubert pos += ETH_ALEN; 2226c1d255d3SCy Schubert os_memcpy(pos, Mx, Mx_len); 2227c1d255d3SCy Schubert pos += Mx_len; 2228c1d255d3SCy Schubert os_memcpy(pos, Nx, Nx_len); 2229c1d255d3SCy Schubert pos += Nx_len; 2230c1d255d3SCy Schubert os_memcpy(pos, code, os_strlen(code)); 2231c1d255d3SCy Schubert 2232c1d255d3SCy Schubert /* HKDF-Expand(PRK, info, L) */ 2233c1d255d3SCy Schubert if (hash_len == 32) 2234c1d255d3SCy Schubert res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len, 2235c1d255d3SCy Schubert z, hash_len); 2236c1d255d3SCy Schubert else if (hash_len == 48) 2237c1d255d3SCy Schubert res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len, 2238c1d255d3SCy Schubert z, hash_len); 2239c1d255d3SCy Schubert else if (hash_len == 64) 2240c1d255d3SCy Schubert res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len, 2241c1d255d3SCy Schubert z, hash_len); 2242c1d255d3SCy Schubert else 2243c1d255d3SCy Schubert res = -1; 2244c1d255d3SCy Schubert os_free(info); 2245c1d255d3SCy Schubert os_memset(prk, 0, hash_len); 2246c1d255d3SCy Schubert if (res < 0) 2247c1d255d3SCy Schubert return -1; 2248c1d255d3SCy Schubert 2249c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)", 2250c1d255d3SCy Schubert z, hash_len); 2251c1d255d3SCy Schubert return 0; 2252c1d255d3SCy Schubert } 2253c1d255d3SCy Schubert 2254c1d255d3SCy Schubert 2255c1d255d3SCy Schubert int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, 2256c1d255d3SCy Schubert const u8 *net_access_key, 2257c1d255d3SCy Schubert size_t net_access_key_len, 2258c1d255d3SCy Schubert struct json_token *peer_net_access_key) 2259c1d255d3SCy Schubert { 2260*db0ac6deSCy Schubert BN_CTX *bnctx = NULL; 2261*db0ac6deSCy Schubert EVP_PKEY *own_key = NULL, *peer_key = NULL; 2262*db0ac6deSCy Schubert BIGNUM *sum = NULL, *q = NULL, *mx = NULL; 2263*db0ac6deSCy Schubert EC_POINT *m = NULL; 2264*db0ac6deSCy Schubert const EC_KEY *cR, *pR; 2265*db0ac6deSCy Schubert const EC_GROUP *group; 2266*db0ac6deSCy Schubert const BIGNUM *cR_bn, *pR_bn; 2267*db0ac6deSCy Schubert const EC_POINT *CI_point; 2268*db0ac6deSCy Schubert const EC_KEY *CI; 2269c1d255d3SCy Schubert u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; 2270c1d255d3SCy Schubert u8 prk[DPP_MAX_HASH_LEN]; 2271c1d255d3SCy Schubert const struct dpp_curve_params *curve; 2272c1d255d3SCy Schubert int res = -1; 2273c1d255d3SCy Schubert u8 nonces[2 * DPP_MAX_NONCE_LEN]; 2274c1d255d3SCy Schubert 2275c1d255d3SCy Schubert own_key = dpp_set_keypair(&auth->curve, net_access_key, 2276c1d255d3SCy Schubert net_access_key_len); 2277c1d255d3SCy Schubert if (!own_key) { 2278c1d255d3SCy Schubert dpp_auth_fail(auth, "Failed to parse own netAccessKey"); 2279c1d255d3SCy Schubert goto fail; 2280c1d255d3SCy Schubert } 2281c1d255d3SCy Schubert 2282c1d255d3SCy Schubert peer_key = dpp_parse_jwk(peer_net_access_key, &curve); 2283c1d255d3SCy Schubert if (!peer_key) 2284c1d255d3SCy Schubert goto fail; 2285c1d255d3SCy Schubert dpp_debug_print_key("DPP: Received netAccessKey", peer_key); 2286c1d255d3SCy Schubert 2287c1d255d3SCy Schubert if (auth->curve != curve) { 2288c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2289c1d255d3SCy Schubert "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", 2290c1d255d3SCy Schubert auth->curve->name, curve->name); 2291c1d255d3SCy Schubert goto fail; 2292c1d255d3SCy Schubert } 2293c1d255d3SCy Schubert 2294c1d255d3SCy Schubert auth->own_protocol_key = dpp_gen_keypair(curve); 2295c1d255d3SCy Schubert if (!auth->own_protocol_key) 2296c1d255d3SCy Schubert goto fail; 2297c1d255d3SCy Schubert 2298c1d255d3SCy Schubert if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) { 2299c1d255d3SCy Schubert wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce"); 2300c1d255d3SCy Schubert goto fail; 2301c1d255d3SCy Schubert } 2302c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce", 2303c1d255d3SCy Schubert auth->e_nonce, auth->curve->nonce_len); 2304c1d255d3SCy Schubert 2305c1d255d3SCy Schubert /* M = { cR + pR } * CI */ 2306*db0ac6deSCy Schubert cR = EVP_PKEY_get0_EC_KEY(own_key); 2307*db0ac6deSCy Schubert pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key); 2308*db0ac6deSCy Schubert if (!pR) 2309c1d255d3SCy Schubert goto fail; 2310*db0ac6deSCy Schubert group = EC_KEY_get0_group(pR); 2311*db0ac6deSCy Schubert bnctx = BN_CTX_new(); 2312*db0ac6deSCy Schubert sum = BN_new(); 2313*db0ac6deSCy Schubert mx = BN_new(); 2314*db0ac6deSCy Schubert q = BN_new(); 2315*db0ac6deSCy Schubert m = EC_POINT_new(group); 2316*db0ac6deSCy Schubert if (!cR || !bnctx || !sum || !mx || !q || !m) 2317*db0ac6deSCy Schubert goto fail; 2318*db0ac6deSCy Schubert cR_bn = EC_KEY_get0_private_key(cR); 2319*db0ac6deSCy Schubert pR_bn = EC_KEY_get0_private_key(pR); 2320*db0ac6deSCy Schubert if (!cR_bn || !pR_bn) 2321*db0ac6deSCy Schubert goto fail; 2322*db0ac6deSCy Schubert CI = EVP_PKEY_get0_EC_KEY(peer_key); 2323*db0ac6deSCy Schubert CI_point = EC_KEY_get0_public_key(CI); 2324*db0ac6deSCy Schubert if (EC_GROUP_get_order(group, q, bnctx) != 1 || 2325*db0ac6deSCy Schubert BN_mod_add(sum, cR_bn, pR_bn, q, bnctx) != 1 || 2326*db0ac6deSCy Schubert EC_POINT_mul(group, m, NULL, CI_point, sum, bnctx) != 1 || 2327*db0ac6deSCy Schubert EC_POINT_get_affine_coordinates_GFp(group, m, mx, NULL, 2328*db0ac6deSCy Schubert bnctx) != 1) { 2329*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 2330*db0ac6deSCy Schubert "OpenSSL: failed: %s", 2331*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 2332c1d255d3SCy Schubert goto fail; 2333c1d255d3SCy Schubert } 2334*db0ac6deSCy Schubert 2335*db0ac6deSCy Schubert if (dpp_bn2bin_pad(mx, Mx, curve->prime_len) < 0) 2336*db0ac6deSCy Schubert goto fail; 2337c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); 2338c1d255d3SCy Schubert 2339c1d255d3SCy Schubert /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ 2340c1d255d3SCy Schubert 2341c1d255d3SCy Schubert /* HKDF-Extract(C-nonce | E-nonce, M.x) */ 2342c1d255d3SCy Schubert os_memcpy(nonces, auth->c_nonce, curve->nonce_len); 2343c1d255d3SCy Schubert os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); 2344c1d255d3SCy Schubert if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, 2345c1d255d3SCy Schubert Mx, curve->prime_len, prk) < 0) 2346c1d255d3SCy Schubert goto fail; 2347c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); 2348c1d255d3SCy Schubert 2349c1d255d3SCy Schubert /* HKDF-Expand(PRK, "dpp reconfig key", L) */ 2350c1d255d3SCy Schubert if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, 2351c1d255d3SCy Schubert "dpp reconfig key", auth->ke, curve->hash_len) < 0) 2352c1d255d3SCy Schubert goto fail; 2353c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 2354c1d255d3SCy Schubert "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", 2355c1d255d3SCy Schubert auth->ke, curve->hash_len); 2356c1d255d3SCy Schubert 2357c1d255d3SCy Schubert res = 0; 2358*db0ac6deSCy Schubert EVP_PKEY_free(auth->reconfig_old_protocol_key); 2359c1d255d3SCy Schubert auth->reconfig_old_protocol_key = own_key; 2360c1d255d3SCy Schubert own_key = NULL; 2361c1d255d3SCy Schubert fail: 2362c1d255d3SCy Schubert forced_memzero(prk, sizeof(prk)); 2363c1d255d3SCy Schubert forced_memzero(Mx, sizeof(Mx)); 2364*db0ac6deSCy Schubert EC_POINT_clear_free(m); 2365*db0ac6deSCy Schubert BN_free(q); 2366*db0ac6deSCy Schubert BN_clear_free(mx); 2367*db0ac6deSCy Schubert BN_clear_free(sum); 2368*db0ac6deSCy Schubert EVP_PKEY_free(own_key); 2369*db0ac6deSCy Schubert EVP_PKEY_free(peer_key); 2370*db0ac6deSCy Schubert BN_CTX_free(bnctx); 2371c1d255d3SCy Schubert return res; 2372c1d255d3SCy Schubert } 2373c1d255d3SCy Schubert 2374c1d255d3SCy Schubert 2375c1d255d3SCy Schubert int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, 2376c1d255d3SCy Schubert const u8 *r_proto, u16 r_proto_len, 2377c1d255d3SCy Schubert struct json_token *net_access_key) 2378c1d255d3SCy Schubert { 2379*db0ac6deSCy Schubert BN_CTX *bnctx = NULL; 2380*db0ac6deSCy Schubert EVP_PKEY *pr = NULL, *peer_key = NULL; 2381*db0ac6deSCy Schubert EC_POINT *sum = NULL, *m = NULL; 2382*db0ac6deSCy Schubert BIGNUM *mx = NULL; 2383*db0ac6deSCy Schubert const EC_KEY *cI, *CR, *PR; 2384*db0ac6deSCy Schubert const EC_GROUP *group; 2385*db0ac6deSCy Schubert const EC_POINT *CR_point, *PR_point; 2386*db0ac6deSCy Schubert const BIGNUM *cI_bn; 2387c1d255d3SCy Schubert u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; 2388c1d255d3SCy Schubert u8 prk[DPP_MAX_HASH_LEN]; 2389c1d255d3SCy Schubert int res = -1; 2390c1d255d3SCy Schubert const struct dpp_curve_params *curve; 2391c1d255d3SCy Schubert u8 nonces[2 * DPP_MAX_NONCE_LEN]; 2392c1d255d3SCy Schubert 2393c1d255d3SCy Schubert pr = dpp_set_pubkey_point(auth->conf->connector_key, 2394c1d255d3SCy Schubert r_proto, r_proto_len); 2395c1d255d3SCy Schubert if (!pr) { 2396c1d255d3SCy Schubert dpp_auth_fail(auth, "Invalid Responder Protocol Key"); 2397c1d255d3SCy Schubert goto fail; 2398c1d255d3SCy Schubert } 2399c1d255d3SCy Schubert dpp_debug_print_key("Peer (Responder) Protocol Key", pr); 2400*db0ac6deSCy Schubert EVP_PKEY_free(auth->peer_protocol_key); 2401c1d255d3SCy Schubert auth->peer_protocol_key = pr; 2402c1d255d3SCy Schubert pr = NULL; 2403c1d255d3SCy Schubert 2404c1d255d3SCy Schubert peer_key = dpp_parse_jwk(net_access_key, &curve); 2405c1d255d3SCy Schubert if (!peer_key) 2406c1d255d3SCy Schubert goto fail; 2407c1d255d3SCy Schubert dpp_debug_print_key("DPP: Received netAccessKey", peer_key); 2408c1d255d3SCy Schubert if (auth->curve != curve) { 2409c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2410c1d255d3SCy Schubert "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", 2411c1d255d3SCy Schubert auth->curve->name, curve->name); 2412c1d255d3SCy Schubert goto fail; 2413c1d255d3SCy Schubert } 2414c1d255d3SCy Schubert 2415c1d255d3SCy Schubert /* M = cI * { CR + PR } */ 2416*db0ac6deSCy Schubert cI = EVP_PKEY_get0_EC_KEY(auth->conf->connector_key); 2417*db0ac6deSCy Schubert cI_bn = EC_KEY_get0_private_key(cI); 2418*db0ac6deSCy Schubert group = EC_KEY_get0_group(cI); 2419*db0ac6deSCy Schubert bnctx = BN_CTX_new(); 2420*db0ac6deSCy Schubert sum = EC_POINT_new(group); 2421*db0ac6deSCy Schubert m = EC_POINT_new(group); 2422*db0ac6deSCy Schubert mx = BN_new(); 2423*db0ac6deSCy Schubert CR = EVP_PKEY_get0_EC_KEY(peer_key); 2424*db0ac6deSCy Schubert PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key); 2425*db0ac6deSCy Schubert CR_point = EC_KEY_get0_public_key(CR); 2426*db0ac6deSCy Schubert PR_point = EC_KEY_get0_public_key(PR); 2427*db0ac6deSCy Schubert if (!bnctx || !sum || !m || !mx || 2428*db0ac6deSCy Schubert EC_POINT_add(group, sum, CR_point, PR_point, bnctx) != 1 || 2429*db0ac6deSCy Schubert EC_POINT_mul(group, m, NULL, sum, cI_bn, bnctx) != 1 || 2430*db0ac6deSCy Schubert EC_POINT_get_affine_coordinates_GFp(group, m, mx, NULL, 2431*db0ac6deSCy Schubert bnctx) != 1 || 2432*db0ac6deSCy Schubert dpp_bn2bin_pad(mx, Mx, curve->prime_len) < 0) 2433c1d255d3SCy Schubert goto fail; 2434c1d255d3SCy Schubert 2435c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); 2436c1d255d3SCy Schubert 2437c1d255d3SCy Schubert /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ 2438c1d255d3SCy Schubert 2439c1d255d3SCy Schubert /* HKDF-Extract(C-nonce | E-nonce, M.x) */ 2440c1d255d3SCy Schubert os_memcpy(nonces, auth->c_nonce, curve->nonce_len); 2441c1d255d3SCy Schubert os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); 2442c1d255d3SCy Schubert if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, 2443c1d255d3SCy Schubert Mx, curve->prime_len, prk) < 0) 2444c1d255d3SCy Schubert goto fail; 2445c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); 2446c1d255d3SCy Schubert 2447c1d255d3SCy Schubert /* HKDF-Expand(PRK, "dpp reconfig key", L) */ 2448c1d255d3SCy Schubert if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, 2449c1d255d3SCy Schubert "dpp reconfig key", auth->ke, curve->hash_len) < 0) 2450c1d255d3SCy Schubert goto fail; 2451c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 2452c1d255d3SCy Schubert "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", 2453c1d255d3SCy Schubert auth->ke, curve->hash_len); 2454c1d255d3SCy Schubert 2455c1d255d3SCy Schubert res = 0; 2456c1d255d3SCy Schubert fail: 2457c1d255d3SCy Schubert forced_memzero(prk, sizeof(prk)); 2458c1d255d3SCy Schubert forced_memzero(Mx, sizeof(Mx)); 2459*db0ac6deSCy Schubert EVP_PKEY_free(pr); 2460*db0ac6deSCy Schubert EVP_PKEY_free(peer_key); 2461*db0ac6deSCy Schubert EC_POINT_clear_free(sum); 2462*db0ac6deSCy Schubert EC_POINT_clear_free(m); 2463*db0ac6deSCy Schubert BN_clear_free(mx); 2464*db0ac6deSCy Schubert BN_CTX_free(bnctx); 2465c1d255d3SCy Schubert return res; 2466c1d255d3SCy Schubert } 2467c1d255d3SCy Schubert 2468c1d255d3SCy Schubert 2469c1d255d3SCy Schubert static char * 2470c1d255d3SCy Schubert dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len) 2471c1d255d3SCy Schubert { 2472c1d255d3SCy Schubert struct wpabuf *jws_prot_hdr; 2473c1d255d3SCy Schubert char *signed1; 2474c1d255d3SCy Schubert 2475c1d255d3SCy Schubert jws_prot_hdr = wpabuf_alloc(100); 2476c1d255d3SCy Schubert if (!jws_prot_hdr) 2477c1d255d3SCy Schubert return NULL; 2478c1d255d3SCy Schubert json_start_object(jws_prot_hdr, NULL); 2479c1d255d3SCy Schubert json_add_string(jws_prot_hdr, "typ", "dppCon"); 2480c1d255d3SCy Schubert json_value_sep(jws_prot_hdr); 2481c1d255d3SCy Schubert json_add_string(jws_prot_hdr, "kid", conf->kid); 2482c1d255d3SCy Schubert json_value_sep(jws_prot_hdr); 2483c1d255d3SCy Schubert json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg); 2484c1d255d3SCy Schubert json_end_object(jws_prot_hdr); 2485c1d255d3SCy Schubert signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr), 2486c1d255d3SCy Schubert wpabuf_len(jws_prot_hdr), 2487c1d255d3SCy Schubert signed1_len); 2488c1d255d3SCy Schubert wpabuf_free(jws_prot_hdr); 2489c1d255d3SCy Schubert return signed1; 2490c1d255d3SCy Schubert } 2491c1d255d3SCy Schubert 2492c1d255d3SCy Schubert 2493c1d255d3SCy Schubert static char * 2494c1d255d3SCy Schubert dpp_build_conn_signature(struct dpp_configurator *conf, 2495c1d255d3SCy Schubert const char *signed1, size_t signed1_len, 2496c1d255d3SCy Schubert const char *signed2, size_t signed2_len, 2497c1d255d3SCy Schubert size_t *signed3_len) 2498c1d255d3SCy Schubert { 2499c1d255d3SCy Schubert const struct dpp_curve_params *curve; 2500c1d255d3SCy Schubert char *signed3 = NULL; 2501*db0ac6deSCy Schubert unsigned char *signature = NULL; 2502*db0ac6deSCy Schubert const unsigned char *p; 2503*db0ac6deSCy Schubert size_t signature_len; 2504*db0ac6deSCy Schubert EVP_MD_CTX *md_ctx = NULL; 2505*db0ac6deSCy Schubert ECDSA_SIG *sig = NULL; 2506c1d255d3SCy Schubert char *dot = "."; 2507*db0ac6deSCy Schubert const EVP_MD *sign_md; 2508*db0ac6deSCy Schubert const BIGNUM *r, *s; 2509c1d255d3SCy Schubert 2510c1d255d3SCy Schubert curve = conf->curve; 2511c1d255d3SCy Schubert if (curve->hash_len == SHA256_MAC_LEN) { 2512*db0ac6deSCy Schubert sign_md = EVP_sha256(); 2513c1d255d3SCy Schubert } else if (curve->hash_len == SHA384_MAC_LEN) { 2514*db0ac6deSCy Schubert sign_md = EVP_sha384(); 2515c1d255d3SCy Schubert } else if (curve->hash_len == SHA512_MAC_LEN) { 2516*db0ac6deSCy Schubert sign_md = EVP_sha512(); 2517c1d255d3SCy Schubert } else { 2518c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); 2519c1d255d3SCy Schubert goto fail; 2520c1d255d3SCy Schubert } 2521*db0ac6deSCy Schubert 2522*db0ac6deSCy Schubert md_ctx = EVP_MD_CTX_create(); 2523*db0ac6deSCy Schubert if (!md_ctx) 2524*db0ac6deSCy Schubert goto fail; 2525*db0ac6deSCy Schubert 2526*db0ac6deSCy Schubert ERR_clear_error(); 2527*db0ac6deSCy Schubert if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL, conf->csign) != 1) { 2528*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s", 2529*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 2530266f97b5SCy Schubert goto fail; 2531266f97b5SCy Schubert } 2532*db0ac6deSCy Schubert if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 || 2533*db0ac6deSCy Schubert EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 || 2534*db0ac6deSCy Schubert EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) { 2535*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s", 2536*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 2537c1d255d3SCy Schubert goto fail; 2538266f97b5SCy Schubert } 2539*db0ac6deSCy Schubert if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) { 2540*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", 2541*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 2542*db0ac6deSCy Schubert goto fail; 2543*db0ac6deSCy Schubert } 2544*db0ac6deSCy Schubert signature = os_malloc(signature_len); 2545*db0ac6deSCy Schubert if (!signature) 2546*db0ac6deSCy Schubert goto fail; 2547*db0ac6deSCy Schubert if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) { 2548*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", 2549*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 2550*db0ac6deSCy Schubert goto fail; 2551*db0ac6deSCy Schubert } 2552*db0ac6deSCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)", 2553*db0ac6deSCy Schubert signature, signature_len); 2554*db0ac6deSCy Schubert /* Convert to raw coordinates r,s */ 2555*db0ac6deSCy Schubert p = signature; 2556*db0ac6deSCy Schubert sig = d2i_ECDSA_SIG(NULL, &p, signature_len); 2557*db0ac6deSCy Schubert if (!sig) 2558*db0ac6deSCy Schubert goto fail; 2559*db0ac6deSCy Schubert ECDSA_SIG_get0(sig, &r, &s); 2560*db0ac6deSCy Schubert if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 || 2561*db0ac6deSCy Schubert dpp_bn2bin_pad(s, signature + curve->prime_len, 2562*db0ac6deSCy Schubert curve->prime_len) < 0) 2563*db0ac6deSCy Schubert goto fail; 2564*db0ac6deSCy Schubert signature_len = 2 * curve->prime_len; 2565c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)", 2566*db0ac6deSCy Schubert signature, signature_len); 2567*db0ac6deSCy Schubert signed3 = base64_url_encode(signature, signature_len, signed3_len); 2568c1d255d3SCy Schubert fail: 2569*db0ac6deSCy Schubert EVP_MD_CTX_destroy(md_ctx); 2570*db0ac6deSCy Schubert ECDSA_SIG_free(sig); 2571*db0ac6deSCy Schubert os_free(signature); 2572c1d255d3SCy Schubert return signed3; 2573c1d255d3SCy Schubert } 2574c1d255d3SCy Schubert 2575c1d255d3SCy Schubert char * dpp_sign_connector(struct dpp_configurator *conf, 2576c1d255d3SCy Schubert const struct wpabuf *dppcon) 2577c1d255d3SCy Schubert { 2578c1d255d3SCy Schubert char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL; 2579c1d255d3SCy Schubert char *signed_conn = NULL, *pos; 2580c1d255d3SCy Schubert size_t signed1_len, signed2_len, signed3_len; 2581c1d255d3SCy Schubert 2582c1d255d3SCy Schubert signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len); 2583c1d255d3SCy Schubert signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon), 2584c1d255d3SCy Schubert &signed2_len); 2585c1d255d3SCy Schubert if (!signed1 || !signed2) 2586c1d255d3SCy Schubert goto fail; 2587c1d255d3SCy Schubert 2588c1d255d3SCy Schubert signed3 = dpp_build_conn_signature(conf, signed1, signed1_len, 2589c1d255d3SCy Schubert signed2, signed2_len, &signed3_len); 2590c1d255d3SCy Schubert if (!signed3) 2591c1d255d3SCy Schubert goto fail; 2592c1d255d3SCy Schubert 2593c1d255d3SCy Schubert signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3); 2594c1d255d3SCy Schubert if (!signed_conn) 2595c1d255d3SCy Schubert goto fail; 2596c1d255d3SCy Schubert pos = signed_conn; 2597c1d255d3SCy Schubert os_memcpy(pos, signed1, signed1_len); 2598c1d255d3SCy Schubert pos += signed1_len; 2599c1d255d3SCy Schubert *pos++ = '.'; 2600c1d255d3SCy Schubert os_memcpy(pos, signed2, signed2_len); 2601c1d255d3SCy Schubert pos += signed2_len; 2602c1d255d3SCy Schubert *pos++ = '.'; 2603c1d255d3SCy Schubert os_memcpy(pos, signed3, signed3_len); 2604c1d255d3SCy Schubert pos += signed3_len; 2605c1d255d3SCy Schubert *pos = '\0'; 2606c1d255d3SCy Schubert 2607c1d255d3SCy Schubert fail: 2608c1d255d3SCy Schubert os_free(signed1); 2609c1d255d3SCy Schubert os_free(signed2); 2610c1d255d3SCy Schubert os_free(signed3); 2611c1d255d3SCy Schubert return signed_conn; 2612c1d255d3SCy Schubert } 2613c1d255d3SCy Schubert 2614c1d255d3SCy Schubert 2615c1d255d3SCy Schubert #ifdef CONFIG_DPP2 2616c1d255d3SCy Schubert 2617c1d255d3SCy Schubert struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, 2618c1d255d3SCy Schubert size_t net_access_key_len) 2619c1d255d3SCy Schubert { 2620c1d255d3SCy Schubert struct wpabuf *pub = NULL; 2621*db0ac6deSCy Schubert EVP_PKEY *own_key; 2622c1d255d3SCy Schubert struct dpp_pfs *pfs; 2623c1d255d3SCy Schubert 2624c1d255d3SCy Schubert pfs = os_zalloc(sizeof(*pfs)); 2625c1d255d3SCy Schubert if (!pfs) 2626c1d255d3SCy Schubert return NULL; 2627c1d255d3SCy Schubert 2628c1d255d3SCy Schubert own_key = dpp_set_keypair(&pfs->curve, net_access_key, 2629c1d255d3SCy Schubert net_access_key_len); 2630c1d255d3SCy Schubert if (!own_key) { 2631c1d255d3SCy Schubert wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); 2632c1d255d3SCy Schubert goto fail; 2633c1d255d3SCy Schubert } 2634*db0ac6deSCy Schubert EVP_PKEY_free(own_key); 2635c1d255d3SCy Schubert 2636c1d255d3SCy Schubert pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group); 2637c1d255d3SCy Schubert if (!pfs->ecdh) 2638c1d255d3SCy Schubert goto fail; 2639c1d255d3SCy Schubert 2640c1d255d3SCy Schubert pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0); 2641c1d255d3SCy Schubert pub = wpabuf_zeropad(pub, pfs->curve->prime_len); 2642c1d255d3SCy Schubert if (!pub) 2643c1d255d3SCy Schubert goto fail; 2644c1d255d3SCy Schubert 2645c1d255d3SCy Schubert pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub)); 2646c1d255d3SCy Schubert if (!pfs->ie) 2647c1d255d3SCy Schubert goto fail; 2648c1d255d3SCy Schubert wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION); 2649c1d255d3SCy Schubert wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub)); 2650c1d255d3SCy Schubert wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM); 2651c1d255d3SCy Schubert wpabuf_put_le16(pfs->ie, pfs->curve->ike_group); 2652c1d255d3SCy Schubert wpabuf_put_buf(pfs->ie, pub); 2653c1d255d3SCy Schubert wpabuf_free(pub); 2654c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element", 2655c1d255d3SCy Schubert pfs->ie); 2656c1d255d3SCy Schubert 2657c1d255d3SCy Schubert return pfs; 2658c1d255d3SCy Schubert fail: 2659c1d255d3SCy Schubert wpabuf_free(pub); 2660c1d255d3SCy Schubert dpp_pfs_free(pfs); 2661c1d255d3SCy Schubert return NULL; 2662c1d255d3SCy Schubert } 2663c1d255d3SCy Schubert 2664c1d255d3SCy Schubert 2665c1d255d3SCy Schubert int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len) 2666c1d255d3SCy Schubert { 2667c1d255d3SCy Schubert if (peer_ie_len < 2) 2668c1d255d3SCy Schubert return -1; 2669c1d255d3SCy Schubert if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) { 2670c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS"); 2671c1d255d3SCy Schubert return -1; 2672c1d255d3SCy Schubert } 2673c1d255d3SCy Schubert 2674c1d255d3SCy Schubert pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2, 2675c1d255d3SCy Schubert peer_ie_len - 2); 2676c1d255d3SCy Schubert pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len); 2677c1d255d3SCy Schubert if (!pfs->secret) { 2678c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key"); 2679c1d255d3SCy Schubert return -1; 2680c1d255d3SCy Schubert } 2681c1d255d3SCy Schubert wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret); 2682c1d255d3SCy Schubert return 0; 2683c1d255d3SCy Schubert } 2684c1d255d3SCy Schubert 2685c1d255d3SCy Schubert 2686c1d255d3SCy Schubert void dpp_pfs_free(struct dpp_pfs *pfs) 2687c1d255d3SCy Schubert { 2688c1d255d3SCy Schubert if (!pfs) 2689c1d255d3SCy Schubert return; 2690c1d255d3SCy Schubert crypto_ecdh_deinit(pfs->ecdh); 2691c1d255d3SCy Schubert wpabuf_free(pfs->ie); 2692c1d255d3SCy Schubert wpabuf_clear_free(pfs->secret); 2693c1d255d3SCy Schubert os_free(pfs); 2694c1d255d3SCy Schubert } 2695c1d255d3SCy Schubert 2696c1d255d3SCy Schubert 2697c1d255d3SCy Schubert struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name) 2698c1d255d3SCy Schubert { 2699*db0ac6deSCy Schubert X509_REQ *req = NULL; 2700c1d255d3SCy Schubert struct wpabuf *buf = NULL; 2701*db0ac6deSCy Schubert unsigned char *der; 2702*db0ac6deSCy Schubert int der_len; 2703*db0ac6deSCy Schubert EVP_PKEY *key; 2704*db0ac6deSCy Schubert const EVP_MD *sign_md; 2705c1d255d3SCy Schubert unsigned int hash_len = auth->curve->hash_len; 2706*db0ac6deSCy Schubert EC_KEY *eckey; 2707*db0ac6deSCy Schubert BIO *out = NULL; 2708c1d255d3SCy Schubert u8 cp[DPP_CP_LEN]; 2709*db0ac6deSCy Schubert char *password; 2710c1d255d3SCy Schubert size_t password_len; 2711*db0ac6deSCy Schubert int res; 2712c1d255d3SCy Schubert 2713c1d255d3SCy Schubert /* TODO: use auth->csrattrs */ 2714c1d255d3SCy Schubert 2715c1d255d3SCy Schubert /* TODO: support generation of a new private key if csrAttrs requests 2716c1d255d3SCy Schubert * a specific group to be used */ 2717c1d255d3SCy Schubert key = auth->own_protocol_key; 2718c1d255d3SCy Schubert 2719*db0ac6deSCy Schubert eckey = EVP_PKEY_get1_EC_KEY(key); 2720*db0ac6deSCy Schubert if (!eckey) 2721*db0ac6deSCy Schubert goto fail; 2722*db0ac6deSCy Schubert der = NULL; 2723*db0ac6deSCy Schubert der_len = i2d_ECPrivateKey(eckey, &der); 2724*db0ac6deSCy Schubert if (der_len <= 0) 2725c1d255d3SCy Schubert goto fail; 2726c1d255d3SCy Schubert wpabuf_free(auth->priv_key); 2727*db0ac6deSCy Schubert auth->priv_key = wpabuf_alloc_copy(der, der_len); 2728*db0ac6deSCy Schubert OPENSSL_free(der); 2729*db0ac6deSCy Schubert if (!auth->priv_key) 2730c1d255d3SCy Schubert goto fail; 2731c1d255d3SCy Schubert 2732*db0ac6deSCy Schubert req = X509_REQ_new(); 2733*db0ac6deSCy Schubert if (!req || !X509_REQ_set_pubkey(req, key)) 2734c1d255d3SCy Schubert goto fail; 2735c1d255d3SCy Schubert 2736*db0ac6deSCy Schubert if (name) { 2737*db0ac6deSCy Schubert X509_NAME *n; 2738*db0ac6deSCy Schubert 2739*db0ac6deSCy Schubert n = X509_REQ_get_subject_name(req); 2740*db0ac6deSCy Schubert if (!n) 2741*db0ac6deSCy Schubert goto fail; 2742*db0ac6deSCy Schubert 2743*db0ac6deSCy Schubert if (X509_NAME_add_entry_by_txt( 2744*db0ac6deSCy Schubert n, "CN", MBSTRING_UTF8, 2745*db0ac6deSCy Schubert (const unsigned char *) name, -1, -1, 0) != 1) 2746*db0ac6deSCy Schubert goto fail; 2747*db0ac6deSCy Schubert } 2748*db0ac6deSCy Schubert 2749c1d255d3SCy Schubert /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ 2750c1d255d3SCy Schubert if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, 2751c1d255d3SCy Schubert "CSR challengePassword", cp, DPP_CP_LEN) < 0) 2752c1d255d3SCy Schubert goto fail; 2753c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 2754c1d255d3SCy Schubert "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", 2755c1d255d3SCy Schubert cp, DPP_CP_LEN); 2756c1d255d3SCy Schubert password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len); 2757c1d255d3SCy Schubert forced_memzero(cp, DPP_CP_LEN); 2758*db0ac6deSCy Schubert if (!password) 2759c1d255d3SCy Schubert goto fail; 2760c1d255d3SCy Schubert 2761*db0ac6deSCy Schubert res = X509_REQ_add1_attr_by_NID(req, NID_pkcs9_challengePassword, 2762*db0ac6deSCy Schubert V_ASN1_UTF8STRING, 2763*db0ac6deSCy Schubert (const unsigned char *) password, 2764*db0ac6deSCy Schubert password_len); 2765*db0ac6deSCy Schubert bin_clear_free(password, password_len); 2766*db0ac6deSCy Schubert if (!res) 2767*db0ac6deSCy Schubert goto fail; 2768*db0ac6deSCy Schubert 2769*db0ac6deSCy Schubert /* TODO */ 2770*db0ac6deSCy Schubert 2771c1d255d3SCy Schubert /* TODO: hash func selection based on csrAttrs */ 2772c1d255d3SCy Schubert if (hash_len == SHA256_MAC_LEN) { 2773*db0ac6deSCy Schubert sign_md = EVP_sha256(); 2774c1d255d3SCy Schubert } else if (hash_len == SHA384_MAC_LEN) { 2775*db0ac6deSCy Schubert sign_md = EVP_sha384(); 2776c1d255d3SCy Schubert } else if (hash_len == SHA512_MAC_LEN) { 2777*db0ac6deSCy Schubert sign_md = EVP_sha512(); 2778c1d255d3SCy Schubert } else { 2779c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); 2780c1d255d3SCy Schubert goto fail; 2781c1d255d3SCy Schubert } 2782c1d255d3SCy Schubert 2783*db0ac6deSCy Schubert if (!X509_REQ_sign(req, key, sign_md)) 2784c1d255d3SCy Schubert goto fail; 2785*db0ac6deSCy Schubert 2786*db0ac6deSCy Schubert der = NULL; 2787*db0ac6deSCy Schubert der_len = i2d_X509_REQ(req, &der); 2788*db0ac6deSCy Schubert if (der_len < 0) 2789*db0ac6deSCy Schubert goto fail; 2790*db0ac6deSCy Schubert buf = wpabuf_alloc_copy(der, der_len); 2791*db0ac6deSCy Schubert OPENSSL_free(der); 2792*db0ac6deSCy Schubert 2793c1d255d3SCy Schubert wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf); 2794c1d255d3SCy Schubert 2795c1d255d3SCy Schubert fail: 2796*db0ac6deSCy Schubert BIO_free_all(out); 2797*db0ac6deSCy Schubert X509_REQ_free(req); 2798c1d255d3SCy Schubert return buf; 2799c1d255d3SCy Schubert } 2800c1d255d3SCy Schubert 2801c1d255d3SCy Schubert 2802*db0ac6deSCy Schubert struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7) 2803c1d255d3SCy Schubert { 2804*db0ac6deSCy Schubert #ifdef OPENSSL_IS_BORINGSSL 2805*db0ac6deSCy Schubert CBS pkcs7_cbs; 2806*db0ac6deSCy Schubert #else /* OPENSSL_IS_BORINGSSL */ 2807*db0ac6deSCy Schubert PKCS7 *p7 = NULL; 2808*db0ac6deSCy Schubert const unsigned char *p = wpabuf_head(pkcs7); 2809*db0ac6deSCy Schubert #endif /* OPENSSL_IS_BORINGSSL */ 2810*db0ac6deSCy Schubert STACK_OF(X509) *certs; 2811*db0ac6deSCy Schubert int i, num; 2812*db0ac6deSCy Schubert BIO *out = NULL; 2813*db0ac6deSCy Schubert size_t rlen; 2814*db0ac6deSCy Schubert struct wpabuf *pem = NULL; 2815*db0ac6deSCy Schubert int res; 2816*db0ac6deSCy Schubert 2817*db0ac6deSCy Schubert #ifdef OPENSSL_IS_BORINGSSL 2818*db0ac6deSCy Schubert certs = sk_X509_new_null(); 2819*db0ac6deSCy Schubert if (!certs) 2820*db0ac6deSCy Schubert goto fail; 2821*db0ac6deSCy Schubert CBS_init(&pkcs7_cbs, wpabuf_head(pkcs7), wpabuf_len(pkcs7)); 2822*db0ac6deSCy Schubert if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) { 2823*db0ac6deSCy Schubert wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s", 2824*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 2825*db0ac6deSCy Schubert goto fail; 2826*db0ac6deSCy Schubert } 2827*db0ac6deSCy Schubert #else /* OPENSSL_IS_BORINGSSL */ 2828*db0ac6deSCy Schubert p7 = d2i_PKCS7(NULL, &p, wpabuf_len(pkcs7)); 2829*db0ac6deSCy Schubert if (!p7) { 2830*db0ac6deSCy Schubert wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s", 2831*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 2832*db0ac6deSCy Schubert goto fail; 2833*db0ac6deSCy Schubert } 2834*db0ac6deSCy Schubert 2835*db0ac6deSCy Schubert switch (OBJ_obj2nid(p7->type)) { 2836*db0ac6deSCy Schubert case NID_pkcs7_signed: 2837*db0ac6deSCy Schubert certs = p7->d.sign->cert; 2838*db0ac6deSCy Schubert break; 2839*db0ac6deSCy Schubert case NID_pkcs7_signedAndEnveloped: 2840*db0ac6deSCy Schubert certs = p7->d.signed_and_enveloped->cert; 2841*db0ac6deSCy Schubert break; 2842*db0ac6deSCy Schubert default: 2843*db0ac6deSCy Schubert certs = NULL; 2844*db0ac6deSCy Schubert break; 2845*db0ac6deSCy Schubert } 2846*db0ac6deSCy Schubert #endif /* OPENSSL_IS_BORINGSSL */ 2847*db0ac6deSCy Schubert 2848*db0ac6deSCy Schubert if (!certs || ((num = sk_X509_num(certs)) == 0)) { 2849*db0ac6deSCy Schubert wpa_printf(MSG_INFO, 2850*db0ac6deSCy Schubert "DPP: No certificates found in PKCS#7 object"); 2851*db0ac6deSCy Schubert goto fail; 2852*db0ac6deSCy Schubert } 2853*db0ac6deSCy Schubert 2854*db0ac6deSCy Schubert out = BIO_new(BIO_s_mem()); 2855*db0ac6deSCy Schubert if (!out) 2856*db0ac6deSCy Schubert goto fail; 2857*db0ac6deSCy Schubert 2858*db0ac6deSCy Schubert for (i = 0; i < num; i++) { 2859*db0ac6deSCy Schubert X509 *cert = sk_X509_value(certs, i); 2860*db0ac6deSCy Schubert 2861*db0ac6deSCy Schubert PEM_write_bio_X509(out, cert); 2862*db0ac6deSCy Schubert } 2863*db0ac6deSCy Schubert 2864*db0ac6deSCy Schubert rlen = BIO_ctrl_pending(out); 2865*db0ac6deSCy Schubert pem = wpabuf_alloc(rlen); 2866*db0ac6deSCy Schubert if (!pem) 2867*db0ac6deSCy Schubert goto fail; 2868*db0ac6deSCy Schubert res = BIO_read(out, wpabuf_put(pem, 0), rlen); 2869*db0ac6deSCy Schubert if (res <= 0) { 2870*db0ac6deSCy Schubert wpabuf_free(pem); 2871*db0ac6deSCy Schubert pem = NULL; 2872*db0ac6deSCy Schubert goto fail; 2873*db0ac6deSCy Schubert } 2874*db0ac6deSCy Schubert wpabuf_put(pem, res); 2875*db0ac6deSCy Schubert 2876*db0ac6deSCy Schubert fail: 2877*db0ac6deSCy Schubert #ifdef OPENSSL_IS_BORINGSSL 2878*db0ac6deSCy Schubert if (certs) 2879*db0ac6deSCy Schubert sk_X509_pop_free(certs, X509_free); 2880*db0ac6deSCy Schubert #else /* OPENSSL_IS_BORINGSSL */ 2881*db0ac6deSCy Schubert PKCS7_free(p7); 2882*db0ac6deSCy Schubert #endif /* OPENSSL_IS_BORINGSSL */ 2883*db0ac6deSCy Schubert if (out) 2884*db0ac6deSCy Schubert BIO_free_all(out); 2885*db0ac6deSCy Schubert 2886*db0ac6deSCy Schubert return pem; 2887*db0ac6deSCy Schubert } 2888*db0ac6deSCy Schubert 2889*db0ac6deSCy Schubert 2890*db0ac6deSCy Schubert int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr) 2891*db0ac6deSCy Schubert { 2892*db0ac6deSCy Schubert X509_REQ *req; 2893*db0ac6deSCy Schubert const unsigned char *pos; 2894*db0ac6deSCy Schubert EVP_PKEY *pkey; 2895*db0ac6deSCy Schubert int res, loc, ret = -1; 2896*db0ac6deSCy Schubert X509_ATTRIBUTE *attr; 2897*db0ac6deSCy Schubert ASN1_TYPE *type; 2898*db0ac6deSCy Schubert ASN1_STRING *str; 2899*db0ac6deSCy Schubert unsigned char *utf8 = NULL; 2900c1d255d3SCy Schubert unsigned char *cp = NULL; 2901c1d255d3SCy Schubert size_t cp_len; 2902c1d255d3SCy Schubert u8 exp_cp[DPP_CP_LEN]; 2903c1d255d3SCy Schubert unsigned int hash_len = auth->curve->hash_len; 2904c1d255d3SCy Schubert 2905*db0ac6deSCy Schubert pos = wpabuf_head(csr); 2906*db0ac6deSCy Schubert req = d2i_X509_REQ(NULL, &pos, wpabuf_len(csr)); 2907*db0ac6deSCy Schubert if (!req) { 2908*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to parse CSR"); 2909*db0ac6deSCy Schubert return -1; 2910*db0ac6deSCy Schubert } 2911*db0ac6deSCy Schubert 2912*db0ac6deSCy Schubert pkey = X509_REQ_get_pubkey(req); 2913*db0ac6deSCy Schubert if (!pkey) { 2914*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, "DPP: Failed to get public key from CSR"); 2915c1d255d3SCy Schubert goto fail; 2916c1d255d3SCy Schubert } 2917c1d255d3SCy Schubert 2918*db0ac6deSCy Schubert res = X509_REQ_verify(req, pkey); 2919*db0ac6deSCy Schubert EVP_PKEY_free(pkey); 2920*db0ac6deSCy Schubert if (res != 1) { 2921*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 2922*db0ac6deSCy Schubert "DPP: CSR does not have a valid signature"); 2923*db0ac6deSCy Schubert goto fail; 2924*db0ac6deSCy Schubert } 2925*db0ac6deSCy Schubert 2926*db0ac6deSCy Schubert loc = X509_REQ_get_attr_by_NID(req, NID_pkcs9_challengePassword, -1); 2927*db0ac6deSCy Schubert if (loc < 0) { 2928c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2929c1d255d3SCy Schubert "DPP: CSR does not include challengePassword"); 2930c1d255d3SCy Schubert goto fail; 2931c1d255d3SCy Schubert } 2932*db0ac6deSCy Schubert 2933*db0ac6deSCy Schubert attr = X509_REQ_get_attr(req, loc); 2934*db0ac6deSCy Schubert if (!attr) { 2935c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2936*db0ac6deSCy Schubert "DPP: Could not get challengePassword attribute"); 2937c1d255d3SCy Schubert goto fail; 2938c1d255d3SCy Schubert } 2939c1d255d3SCy Schubert 2940*db0ac6deSCy Schubert type = X509_ATTRIBUTE_get0_type(attr, 0); 2941*db0ac6deSCy Schubert if (!type) { 2942*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 2943*db0ac6deSCy Schubert "DPP: Could not get challengePassword attribute type"); 2944*db0ac6deSCy Schubert goto fail; 2945*db0ac6deSCy Schubert } 2946*db0ac6deSCy Schubert 2947*db0ac6deSCy Schubert res = ASN1_TYPE_get(type); 2948*db0ac6deSCy Schubert /* This is supposed to be UTF8String, but allow other strings as well 2949*db0ac6deSCy Schubert * since challengePassword is using ASCII (base64 encoded). */ 2950*db0ac6deSCy Schubert if (res != V_ASN1_UTF8STRING && res != V_ASN1_PRINTABLESTRING && 2951*db0ac6deSCy Schubert res != V_ASN1_IA5STRING) { 2952*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 2953*db0ac6deSCy Schubert "DPP: Unexpected challengePassword attribute type %d", 2954*db0ac6deSCy Schubert res); 2955*db0ac6deSCy Schubert goto fail; 2956*db0ac6deSCy Schubert } 2957*db0ac6deSCy Schubert 2958*db0ac6deSCy Schubert str = X509_ATTRIBUTE_get0_data(attr, 0, res, NULL); 2959*db0ac6deSCy Schubert if (!str) { 2960*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 2961*db0ac6deSCy Schubert "DPP: Could not get ASN.1 string for challengePassword"); 2962*db0ac6deSCy Schubert goto fail; 2963*db0ac6deSCy Schubert } 2964*db0ac6deSCy Schubert 2965*db0ac6deSCy Schubert res = ASN1_STRING_to_UTF8(&utf8, str); 2966*db0ac6deSCy Schubert if (res < 0) { 2967*db0ac6deSCy Schubert wpa_printf(MSG_DEBUG, 2968*db0ac6deSCy Schubert "DPP: Could not get UTF8 version of challengePassword"); 2969*db0ac6deSCy Schubert goto fail; 2970*db0ac6deSCy Schubert } 2971*db0ac6deSCy Schubert 2972*db0ac6deSCy Schubert cp = base64_decode((const char *) utf8, res, &cp_len); 2973*db0ac6deSCy Schubert OPENSSL_free(utf8); 2974c1d255d3SCy Schubert if (!cp) { 2975c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2976c1d255d3SCy Schubert "DPP: Could not base64 decode challengePassword"); 2977c1d255d3SCy Schubert goto fail; 2978c1d255d3SCy Schubert } 2979c1d255d3SCy Schubert if (cp_len != DPP_CP_LEN) { 2980c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2981c1d255d3SCy Schubert "DPP: Unexpected cp length (%zu) in CSR challengePassword", 2982c1d255d3SCy Schubert cp_len); 2983c1d255d3SCy Schubert goto fail; 2984c1d255d3SCy Schubert } 2985c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword", 2986c1d255d3SCy Schubert cp, cp_len); 2987c1d255d3SCy Schubert 2988c1d255d3SCy Schubert /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ 2989c1d255d3SCy Schubert if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, 2990c1d255d3SCy Schubert "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0) 2991c1d255d3SCy Schubert goto fail; 2992c1d255d3SCy Schubert wpa_hexdump_key(MSG_DEBUG, 2993c1d255d3SCy Schubert "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", 2994c1d255d3SCy Schubert exp_cp, DPP_CP_LEN); 2995c1d255d3SCy Schubert if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) { 2996c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, 2997c1d255d3SCy Schubert "DPP: CSR challengePassword does not match calculated cp"); 2998c1d255d3SCy Schubert goto fail; 2999c1d255d3SCy Schubert } 3000c1d255d3SCy Schubert 3001c1d255d3SCy Schubert ret = 0; 3002c1d255d3SCy Schubert fail: 3003c1d255d3SCy Schubert os_free(cp); 3004*db0ac6deSCy Schubert X509_REQ_free(req); 3005c1d255d3SCy Schubert return ret; 3006c1d255d3SCy Schubert } 3007c1d255d3SCy Schubert 3008c1d255d3SCy Schubert 3009c1d255d3SCy Schubert struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, 3010c1d255d3SCy Schubert size_t csign_key_len, 3011c1d255d3SCy Schubert const u8 *pp_key, 3012c1d255d3SCy Schubert size_t pp_key_len) 3013c1d255d3SCy Schubert { 3014*db0ac6deSCy Schubert const unsigned char *p; 3015*db0ac6deSCy Schubert EVP_PKEY *csign = NULL, *ppkey = NULL; 3016c1d255d3SCy Schubert struct dpp_reconfig_id *id = NULL; 3017*db0ac6deSCy Schubert BN_CTX *ctx = NULL; 3018*db0ac6deSCy Schubert BIGNUM *bn = NULL, *q = NULL; 3019*db0ac6deSCy Schubert const EC_KEY *eckey; 3020*db0ac6deSCy Schubert const EC_GROUP *group; 3021*db0ac6deSCy Schubert EC_POINT *e_id = NULL; 3022c1d255d3SCy Schubert 3023*db0ac6deSCy Schubert p = csign_key; 3024*db0ac6deSCy Schubert csign = d2i_PUBKEY(NULL, &p, csign_key_len); 3025c1d255d3SCy Schubert if (!csign) 3026c1d255d3SCy Schubert goto fail; 3027c1d255d3SCy Schubert 3028c1d255d3SCy Schubert if (!pp_key) 3029c1d255d3SCy Schubert goto fail; 3030*db0ac6deSCy Schubert p = pp_key; 3031*db0ac6deSCy Schubert ppkey = d2i_PUBKEY(NULL, &p, pp_key_len); 3032c1d255d3SCy Schubert if (!ppkey) 3033c1d255d3SCy Schubert goto fail; 3034c1d255d3SCy Schubert 3035*db0ac6deSCy Schubert eckey = EVP_PKEY_get0_EC_KEY(csign); 3036*db0ac6deSCy Schubert if (!eckey) 3037*db0ac6deSCy Schubert goto fail; 3038*db0ac6deSCy Schubert group = EC_KEY_get0_group(eckey); 3039*db0ac6deSCy Schubert if (!group) 3040c1d255d3SCy Schubert goto fail; 3041c1d255d3SCy Schubert 3042*db0ac6deSCy Schubert e_id = EC_POINT_new(group); 3043*db0ac6deSCy Schubert ctx = BN_CTX_new(); 3044*db0ac6deSCy Schubert bn = BN_new(); 3045*db0ac6deSCy Schubert q = BN_new(); 3046*db0ac6deSCy Schubert if (!e_id || !ctx || !bn || !q || 3047*db0ac6deSCy Schubert !EC_GROUP_get_order(group, q, ctx) || 3048*db0ac6deSCy Schubert !BN_rand_range(bn, q) || 3049*db0ac6deSCy Schubert !EC_POINT_mul(group, e_id, bn, NULL, NULL, ctx)) 3050c1d255d3SCy Schubert goto fail; 3051c1d255d3SCy Schubert 3052*db0ac6deSCy Schubert dpp_debug_print_point("DPP: Generated random point E-id", group, e_id); 3053c1d255d3SCy Schubert 3054c1d255d3SCy Schubert id = os_zalloc(sizeof(*id)); 3055c1d255d3SCy Schubert if (!id) 3056c1d255d3SCy Schubert goto fail; 3057*db0ac6deSCy Schubert id->group = group; 3058c1d255d3SCy Schubert id->e_id = e_id; 3059c1d255d3SCy Schubert e_id = NULL; 3060c1d255d3SCy Schubert id->csign = csign; 3061c1d255d3SCy Schubert csign = NULL; 3062c1d255d3SCy Schubert id->pp_key = ppkey; 3063c1d255d3SCy Schubert ppkey = NULL; 3064c1d255d3SCy Schubert fail: 3065*db0ac6deSCy Schubert EC_POINT_free(e_id); 3066*db0ac6deSCy Schubert EVP_PKEY_free(csign); 3067*db0ac6deSCy Schubert EVP_PKEY_free(ppkey); 3068*db0ac6deSCy Schubert BN_clear_free(bn); 3069*db0ac6deSCy Schubert BN_CTX_free(ctx); 3070c1d255d3SCy Schubert return id; 3071c1d255d3SCy Schubert } 3072c1d255d3SCy Schubert 3073c1d255d3SCy Schubert 3074*db0ac6deSCy Schubert static EVP_PKEY * dpp_pkey_from_point(const EC_GROUP *group, 3075*db0ac6deSCy Schubert const EC_POINT *point) 3076*db0ac6deSCy Schubert { 3077*db0ac6deSCy Schubert EC_KEY *eckey; 3078*db0ac6deSCy Schubert EVP_PKEY *pkey = NULL; 3079*db0ac6deSCy Schubert 3080*db0ac6deSCy Schubert eckey = EC_KEY_new(); 3081*db0ac6deSCy Schubert if (!eckey || 3082*db0ac6deSCy Schubert EC_KEY_set_group(eckey, group) != 1 || 3083*db0ac6deSCy Schubert EC_KEY_set_public_key(eckey, point) != 1) { 3084*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, 3085*db0ac6deSCy Schubert "DPP: Failed to set EC_KEY: %s", 3086*db0ac6deSCy Schubert ERR_error_string(ERR_get_error(), NULL)); 3087*db0ac6deSCy Schubert goto fail; 3088*db0ac6deSCy Schubert } 3089*db0ac6deSCy Schubert EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); 3090*db0ac6deSCy Schubert 3091*db0ac6deSCy Schubert pkey = EVP_PKEY_new(); 3092*db0ac6deSCy Schubert if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) { 3093*db0ac6deSCy Schubert wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY"); 3094*db0ac6deSCy Schubert EVP_PKEY_free(pkey); 3095*db0ac6deSCy Schubert pkey = NULL; 3096*db0ac6deSCy Schubert goto fail; 3097*db0ac6deSCy Schubert } 3098*db0ac6deSCy Schubert 3099*db0ac6deSCy Schubert fail: 3100*db0ac6deSCy Schubert EC_KEY_free(eckey); 3101*db0ac6deSCy Schubert return pkey; 3102*db0ac6deSCy Schubert } 3103*db0ac6deSCy Schubert 3104*db0ac6deSCy Schubert 3105c1d255d3SCy Schubert int dpp_update_reconfig_id(struct dpp_reconfig_id *id) 3106c1d255d3SCy Schubert { 3107*db0ac6deSCy Schubert BN_CTX *ctx = NULL; 3108*db0ac6deSCy Schubert BIGNUM *bn = NULL, *q = NULL; 3109*db0ac6deSCy Schubert EC_POINT *e_prime_id = NULL, *a_nonce = NULL; 3110c1d255d3SCy Schubert int ret = -1; 3111*db0ac6deSCy Schubert const EC_KEY *pp; 3112*db0ac6deSCy Schubert const EC_POINT *pp_point; 3113c1d255d3SCy Schubert 3114*db0ac6deSCy Schubert pp = EVP_PKEY_get0_EC_KEY(id->pp_key); 3115*db0ac6deSCy Schubert if (!pp) 3116*db0ac6deSCy Schubert goto fail; 3117*db0ac6deSCy Schubert pp_point = EC_KEY_get0_public_key(pp); 3118*db0ac6deSCy Schubert e_prime_id = EC_POINT_new(id->group); 3119*db0ac6deSCy Schubert a_nonce = EC_POINT_new(id->group); 3120*db0ac6deSCy Schubert ctx = BN_CTX_new(); 3121*db0ac6deSCy Schubert bn = BN_new(); 3122*db0ac6deSCy Schubert q = BN_new(); 3123c1d255d3SCy Schubert /* Generate random 0 <= a-nonce < q 3124c1d255d3SCy Schubert * A-NONCE = a-nonce * G 3125c1d255d3SCy Schubert * E'-id = E-id + a-nonce * P_pk */ 3126*db0ac6deSCy Schubert if (!pp_point || !e_prime_id || !a_nonce || !ctx || !bn || !q || 3127*db0ac6deSCy Schubert !EC_GROUP_get_order(id->group, q, ctx) || 3128*db0ac6deSCy Schubert !BN_rand_range(bn, q) || /* bn = a-nonce */ 3129*db0ac6deSCy Schubert !EC_POINT_mul(id->group, a_nonce, bn, NULL, NULL, ctx) || 3130*db0ac6deSCy Schubert !EC_POINT_mul(id->group, e_prime_id, NULL, pp_point, bn, ctx) || 3131*db0ac6deSCy Schubert !EC_POINT_add(id->group, e_prime_id, id->e_id, e_prime_id, ctx)) 3132c1d255d3SCy Schubert goto fail; 3133c1d255d3SCy Schubert 3134*db0ac6deSCy Schubert dpp_debug_print_point("DPP: Generated A-NONCE", id->group, a_nonce); 3135*db0ac6deSCy Schubert dpp_debug_print_point("DPP: Encrypted E-id to E'-id", 3136*db0ac6deSCy Schubert id->group, e_prime_id); 3137c1d255d3SCy Schubert 3138*db0ac6deSCy Schubert EVP_PKEY_free(id->a_nonce); 3139*db0ac6deSCy Schubert EVP_PKEY_free(id->e_prime_id); 3140*db0ac6deSCy Schubert id->a_nonce = dpp_pkey_from_point(id->group, a_nonce); 3141*db0ac6deSCy Schubert id->e_prime_id = dpp_pkey_from_point(id->group, e_prime_id); 3142c1d255d3SCy Schubert if (!id->a_nonce || !id->e_prime_id) 3143c1d255d3SCy Schubert goto fail; 3144c1d255d3SCy Schubert 3145c1d255d3SCy Schubert ret = 0; 3146c1d255d3SCy Schubert 3147c1d255d3SCy Schubert fail: 3148*db0ac6deSCy Schubert EC_POINT_free(e_prime_id); 3149*db0ac6deSCy Schubert EC_POINT_free(a_nonce); 3150*db0ac6deSCy Schubert BN_clear_free(bn); 3151*db0ac6deSCy Schubert BN_CTX_free(ctx); 3152c1d255d3SCy Schubert return ret; 3153c1d255d3SCy Schubert } 3154c1d255d3SCy Schubert 3155c1d255d3SCy Schubert 3156c1d255d3SCy Schubert void dpp_free_reconfig_id(struct dpp_reconfig_id *id) 3157c1d255d3SCy Schubert { 3158c1d255d3SCy Schubert if (id) { 3159*db0ac6deSCy Schubert EC_POINT_clear_free(id->e_id); 3160*db0ac6deSCy Schubert EVP_PKEY_free(id->csign); 3161*db0ac6deSCy Schubert EVP_PKEY_free(id->a_nonce); 3162*db0ac6deSCy Schubert EVP_PKEY_free(id->e_prime_id); 3163*db0ac6deSCy Schubert EVP_PKEY_free(id->pp_key); 3164c1d255d3SCy Schubert os_free(id); 3165c1d255d3SCy Schubert } 3166c1d255d3SCy Schubert } 3167c1d255d3SCy Schubert 3168c1d255d3SCy Schubert 3169*db0ac6deSCy Schubert EC_POINT * dpp_decrypt_e_id(EVP_PKEY *ppkey, EVP_PKEY *a_nonce, 3170*db0ac6deSCy Schubert EVP_PKEY *e_prime_id) 3171c1d255d3SCy Schubert { 3172*db0ac6deSCy Schubert const EC_KEY *pp_ec, *a_nonce_ec, *e_prime_id_ec; 3173*db0ac6deSCy Schubert const BIGNUM *pp_bn; 3174*db0ac6deSCy Schubert const EC_GROUP *group; 3175*db0ac6deSCy Schubert EC_POINT *e_id = NULL; 3176*db0ac6deSCy Schubert const EC_POINT *a_nonce_point, *e_prime_id_point; 3177*db0ac6deSCy Schubert BN_CTX *ctx = NULL; 3178c1d255d3SCy Schubert 3179c1d255d3SCy Schubert if (!ppkey) 3180c1d255d3SCy Schubert return NULL; 3181c1d255d3SCy Schubert 3182c1d255d3SCy Schubert /* E-id = E'-id - s_C * A-NONCE */ 3183*db0ac6deSCy Schubert pp_ec = EVP_PKEY_get0_EC_KEY(ppkey); 3184*db0ac6deSCy Schubert a_nonce_ec = EVP_PKEY_get0_EC_KEY(a_nonce); 3185*db0ac6deSCy Schubert e_prime_id_ec = EVP_PKEY_get0_EC_KEY(e_prime_id); 3186*db0ac6deSCy Schubert if (!pp_ec || !a_nonce_ec || !e_prime_id_ec) 3187c1d255d3SCy Schubert return NULL; 3188*db0ac6deSCy Schubert pp_bn = EC_KEY_get0_private_key(pp_ec); 3189*db0ac6deSCy Schubert group = EC_KEY_get0_group(pp_ec); 3190*db0ac6deSCy Schubert a_nonce_point = EC_KEY_get0_public_key(a_nonce_ec); 3191*db0ac6deSCy Schubert e_prime_id_point = EC_KEY_get0_public_key(e_prime_id_ec); 3192*db0ac6deSCy Schubert ctx = BN_CTX_new(); 3193*db0ac6deSCy Schubert if (!pp_bn || !group || !a_nonce_point || !e_prime_id_point || !ctx) 3194*db0ac6deSCy Schubert goto fail; 3195*db0ac6deSCy Schubert e_id = EC_POINT_new(group); 3196*db0ac6deSCy Schubert if (!e_id || 3197*db0ac6deSCy Schubert !EC_POINT_mul(group, e_id, NULL, a_nonce_point, pp_bn, ctx) || 3198*db0ac6deSCy Schubert !EC_POINT_invert(group, e_id, ctx) || 3199*db0ac6deSCy Schubert !EC_POINT_add(group, e_id, e_prime_id_point, e_id, ctx)) { 3200*db0ac6deSCy Schubert EC_POINT_clear_free(e_id); 3201c1d255d3SCy Schubert goto fail; 3202c1d255d3SCy Schubert } 3203c1d255d3SCy Schubert 3204*db0ac6deSCy Schubert dpp_debug_print_point("DPP: Decrypted E-id", group, e_id); 3205c1d255d3SCy Schubert 3206c1d255d3SCy Schubert fail: 3207*db0ac6deSCy Schubert BN_CTX_free(ctx); 3208c1d255d3SCy Schubert return e_id; 3209c1d255d3SCy Schubert } 3210c1d255d3SCy Schubert 3211c1d255d3SCy Schubert #endif /* CONFIG_DPP2 */ 3212c1d255d3SCy Schubert 3213c1d255d3SCy Schubert 3214c1d255d3SCy Schubert #ifdef CONFIG_TESTING_OPTIONS 3215c1d255d3SCy Schubert 3216c1d255d3SCy Schubert int dpp_test_gen_invalid_key(struct wpabuf *msg, 3217c1d255d3SCy Schubert const struct dpp_curve_params *curve) 3218c1d255d3SCy Schubert { 3219*db0ac6deSCy Schubert BN_CTX *ctx; 3220*db0ac6deSCy Schubert BIGNUM *x, *y; 3221c1d255d3SCy Schubert int ret = -1; 3222*db0ac6deSCy Schubert EC_GROUP *group; 3223*db0ac6deSCy Schubert EC_POINT *point; 3224c1d255d3SCy Schubert 3225*db0ac6deSCy Schubert group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); 3226*db0ac6deSCy Schubert if (!group) 3227*db0ac6deSCy Schubert return -1; 3228*db0ac6deSCy Schubert 3229*db0ac6deSCy Schubert ctx = BN_CTX_new(); 3230*db0ac6deSCy Schubert point = EC_POINT_new(group); 3231*db0ac6deSCy Schubert x = BN_new(); 3232*db0ac6deSCy Schubert y = BN_new(); 3233*db0ac6deSCy Schubert if (!ctx || !point || !x || !y) 3234c1d255d3SCy Schubert goto fail; 3235c1d255d3SCy Schubert 3236*db0ac6deSCy Schubert if (BN_rand(x, curve->prime_len * 8, 0, 0) != 1) 3237c1d255d3SCy Schubert goto fail; 3238c1d255d3SCy Schubert 3239*db0ac6deSCy Schubert /* Generate a random y coordinate that results in a point that is not 3240*db0ac6deSCy Schubert * on the curve. */ 3241*db0ac6deSCy Schubert for (;;) { 3242*db0ac6deSCy Schubert if (BN_rand(y, curve->prime_len * 8, 0, 0) != 1) 3243c1d255d3SCy Schubert goto fail; 3244c1d255d3SCy Schubert 3245*db0ac6deSCy Schubert if (EC_POINT_set_affine_coordinates_GFp(group, point, x, y, 3246*db0ac6deSCy Schubert ctx) != 1) { 3247*db0ac6deSCy Schubert #if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL) 3248*db0ac6deSCy Schubert /* Unlike older OpenSSL versions, OpenSSL 1.1.1 and BoringSSL 3249*db0ac6deSCy Schubert * return an error from EC_POINT_set_affine_coordinates_GFp() 3250*db0ac6deSCy Schubert * when the point is not on the curve. */ 3251*db0ac6deSCy Schubert break; 3252*db0ac6deSCy Schubert #else /* >=1.1.0 or OPENSSL_IS_BORINGSSL */ 3253*db0ac6deSCy Schubert goto fail; 3254*db0ac6deSCy Schubert #endif /* >= 1.1.0 or OPENSSL_IS_BORINGSSL */ 3255c1d255d3SCy Schubert } 3256c1d255d3SCy Schubert 3257*db0ac6deSCy Schubert if (!EC_POINT_is_on_curve(group, point, ctx)) 3258*db0ac6deSCy Schubert break; 3259*db0ac6deSCy Schubert } 3260*db0ac6deSCy Schubert 3261*db0ac6deSCy Schubert if (dpp_bn2bin_pad(x, wpabuf_put(msg, curve->prime_len), 3262*db0ac6deSCy Schubert curve->prime_len) < 0 || 3263*db0ac6deSCy Schubert dpp_bn2bin_pad(y, wpabuf_put(msg, curve->prime_len), 3264*db0ac6deSCy Schubert curve->prime_len) < 0) 3265*db0ac6deSCy Schubert goto fail; 3266*db0ac6deSCy Schubert 3267c1d255d3SCy Schubert ret = 0; 3268c1d255d3SCy Schubert fail: 3269*db0ac6deSCy Schubert if (ret < 0) 3270*db0ac6deSCy Schubert wpa_printf(MSG_INFO, "DPP: Failed to generate invalid key"); 3271*db0ac6deSCy Schubert BN_free(x); 3272*db0ac6deSCy Schubert BN_free(y); 3273*db0ac6deSCy Schubert EC_POINT_free(point); 3274*db0ac6deSCy Schubert BN_CTX_free(ctx); 3275*db0ac6deSCy Schubert EC_GROUP_free(group); 3276*db0ac6deSCy Schubert 3277c1d255d3SCy Schubert return ret; 3278c1d255d3SCy Schubert } 3279c1d255d3SCy Schubert 3280c1d255d3SCy Schubert 3281c1d255d3SCy Schubert char * dpp_corrupt_connector_signature(const char *connector) 3282c1d255d3SCy Schubert { 3283c1d255d3SCy Schubert char *tmp, *pos, *signed3 = NULL; 3284c1d255d3SCy Schubert unsigned char *signature = NULL; 3285c1d255d3SCy Schubert size_t signature_len = 0, signed3_len; 3286c1d255d3SCy Schubert 3287c1d255d3SCy Schubert tmp = os_zalloc(os_strlen(connector) + 5); 3288c1d255d3SCy Schubert if (!tmp) 3289c1d255d3SCy Schubert goto fail; 3290c1d255d3SCy Schubert os_memcpy(tmp, connector, os_strlen(connector)); 3291c1d255d3SCy Schubert 3292c1d255d3SCy Schubert pos = os_strchr(tmp, '.'); 3293c1d255d3SCy Schubert if (!pos) 3294c1d255d3SCy Schubert goto fail; 3295c1d255d3SCy Schubert 3296c1d255d3SCy Schubert pos = os_strchr(pos + 1, '.'); 3297c1d255d3SCy Schubert if (!pos) 3298c1d255d3SCy Schubert goto fail; 3299c1d255d3SCy Schubert pos++; 3300c1d255d3SCy Schubert 3301c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s", 3302c1d255d3SCy Schubert pos); 3303c1d255d3SCy Schubert signature = base64_url_decode(pos, os_strlen(pos), &signature_len); 3304c1d255d3SCy Schubert if (!signature || signature_len == 0) 3305c1d255d3SCy Schubert goto fail; 3306c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature", 3307c1d255d3SCy Schubert signature, signature_len); 3308c1d255d3SCy Schubert signature[signature_len - 1] ^= 0x01; 3309c1d255d3SCy Schubert wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature", 3310c1d255d3SCy Schubert signature, signature_len); 3311c1d255d3SCy Schubert signed3 = base64_url_encode(signature, signature_len, &signed3_len); 3312c1d255d3SCy Schubert if (!signed3) 3313c1d255d3SCy Schubert goto fail; 3314c1d255d3SCy Schubert os_memcpy(pos, signed3, signed3_len); 3315c1d255d3SCy Schubert pos[signed3_len] = '\0'; 3316c1d255d3SCy Schubert wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s", 3317c1d255d3SCy Schubert pos); 3318c1d255d3SCy Schubert 3319c1d255d3SCy Schubert out: 3320c1d255d3SCy Schubert os_free(signature); 3321c1d255d3SCy Schubert os_free(signed3); 3322c1d255d3SCy Schubert return tmp; 3323c1d255d3SCy Schubert fail: 3324c1d255d3SCy Schubert os_free(tmp); 3325c1d255d3SCy Schubert tmp = NULL; 3326c1d255d3SCy Schubert goto out; 3327c1d255d3SCy Schubert } 3328c1d255d3SCy Schubert 3329c1d255d3SCy Schubert #endif /* CONFIG_TESTING_OPTIONS */ 3330