Home | History | Annotate | Download | only in common
      1 /*
      2  * DPP functionality shared between hostapd and wpa_supplicant
      3  * Copyright (c) 2017, Qualcomm Atheros, Inc.
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "utils/includes.h"
     10 #include <openssl/opensslv.h>
     11 #include <openssl/err.h>
     12 
     13 #include "utils/common.h"
     14 #include "utils/base64.h"
     15 #include "utils/json.h"
     16 #include "common/ieee802_11_common.h"
     17 #include "common/ieee802_11_defs.h"
     18 #include "common/wpa_ctrl.h"
     19 #include "crypto/crypto.h"
     20 #include "crypto/random.h"
     21 #include "crypto/aes.h"
     22 #include "crypto/aes_siv.h"
     23 #include "crypto/sha384.h"
     24 #include "crypto/sha512.h"
     25 #include "dpp.h"
     26 
     27 
     28 #if OPENSSL_VERSION_NUMBER < 0x10100000L
     29 /* Compatibility wrappers for older versions. */
     30 
     31 static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
     32 {
     33 	sig->r = r;
     34 	sig->s = s;
     35 	return 1;
     36 }
     37 
     38 
     39 static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr,
     40 			   const BIGNUM **ps)
     41 {
     42 	if (pr)
     43 		*pr = sig->r;
     44 	if (ps)
     45 		*ps = sig->s;
     46 }
     47 
     48 #endif
     49 
     50 
     51 static const struct dpp_curve_params dpp_curves[] = {
     52 	/* The mandatory to support and the default NIST P-256 curve needs to
     53 	 * be the first entry on this list. */
     54 	{ "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" },
     55 	{ "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" },
     56 	{ "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" },
     57 	{ "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" },
     58 	{ "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" },
     59 	{ "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" },
     60 	{ NULL, 0, 0, 0, 0, NULL, 0, NULL }
     61 };
     62 
     63 
     64 /* Role-specific elements for PKEX */
     65 
     66 /* NIST P-256 */
     67 static const u8 pkex_init_x_p256[32] = {
     68 	0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b,
     69 	0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54,
     70 	0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07,
     71 	0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25
     72  };
     73 static const u8 pkex_init_y_p256[32] = {
     74 	0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b,
     75 	0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc,
     76 	0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45,
     77 	0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4
     78  };
     79 static const u8 pkex_resp_x_p256[32] = {
     80 	0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39,
     81 	0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f,
     82 	0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f,
     83 	0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76
     84 };
     85 static const u8 pkex_resp_y_p256[32] = {
     86 	0x26, 0x04, 0x09, 0x45, 0x0a, 0x05, 0x20, 0xe7,
     87 	0xa7, 0x27, 0xc1, 0x36, 0x76, 0x85, 0xca, 0x3e,
     88 	0x42, 0x16, 0xf4, 0x89, 0x85, 0x34, 0x6e, 0xd5,
     89 	0x17, 0xde, 0xc0, 0xb8, 0xad, 0xfd, 0xb2, 0x98
     90 };
     91 
     92 /* NIST P-384 */
     93 static const u8 pkex_init_x_p384[48] = {
     94 	0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa,
     95 	0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68,
     96 	0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53,
     97 	0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac,
     98 	0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12,
     99 	0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3
    100 };
    101 static const u8 pkex_init_y_p384[48] = {
    102 	0x89, 0xd0, 0x97, 0x7b, 0x59, 0x4f, 0xa6, 0xd6,
    103 	0x7c, 0x5d, 0x93, 0x5b, 0x93, 0xc4, 0x07, 0xa9,
    104 	0x89, 0xee, 0xd5, 0xcd, 0x6f, 0x42, 0xf8, 0x38,
    105 	0xc8, 0xc6, 0x62, 0x24, 0x69, 0x0c, 0xd4, 0x48,
    106 	0xd8, 0x44, 0xd6, 0xc2, 0xe8, 0xcc, 0x62, 0x6b,
    107 	0x3c, 0x25, 0x53, 0xba, 0x4f, 0x71, 0xf8, 0xe7
    108 };
    109 static const u8 pkex_resp_x_p384[48] = {
    110 	0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98,
    111 	0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97,
    112 	0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92,
    113 	0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44,
    114 	0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf,
    115 	0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf
    116 };
    117 static const u8 pkex_resp_y_p384[48] = {
    118 	0x54, 0x58, 0x20, 0xad, 0x55, 0x1d, 0xca, 0xf3,
    119 	0x1c, 0x8a, 0xcd, 0x19, 0x40, 0xf9, 0x37, 0x83,
    120 	0xc7, 0xd6, 0xb3, 0x13, 0x7d, 0x53, 0x28, 0x5c,
    121 	0xf6, 0x2d, 0xf1, 0xdd, 0xa5, 0x8b, 0xad, 0x5d,
    122 	0x81, 0xab, 0xb1, 0x00, 0x39, 0xd6, 0xcc, 0x9c,
    123 	0xea, 0x1e, 0x84, 0x1d, 0xbf, 0xe3, 0x35, 0xf9
    124 };
    125 
    126 /* NIST P-521 */
    127 static const u8 pkex_init_x_p521[66] = {
    128 	0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23,
    129 	0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0,
    130 	0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76,
    131 	0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5,
    132 	0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38,
    133 	0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01,
    134 	0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e,
    135 	0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d,
    136 	0x97, 0x76
    137 };
    138 static const u8 pkex_init_y_p521[66] = {
    139 	0x01, 0x4c, 0x71, 0xfd, 0x1b, 0xd5, 0x9c, 0xa6,
    140 	0xed, 0x39, 0xef, 0x45, 0xc5, 0x06, 0xfd, 0x66,
    141 	0xc0, 0xeb, 0x0f, 0xbf, 0x21, 0xa3, 0x36, 0x74,
    142 	0xfd, 0xaa, 0x05, 0x6e, 0x4e, 0x33, 0x95, 0x42,
    143 	0x1a, 0x9d, 0x3f, 0x3a, 0x1c, 0x5e, 0xa8, 0x60,
    144 	0xf7, 0xe5, 0x59, 0x1d, 0x07, 0xaa, 0x6f, 0x40,
    145 	0x0a, 0x59, 0x3c, 0x27, 0xad, 0xe0, 0x48, 0xfd,
    146 	0xd1, 0x83, 0x37, 0x4c, 0xdf, 0xe1, 0x86, 0x72,
    147 	0xfc, 0x57
    148 };
    149 static const u8 pkex_resp_x_p521[66] = {
    150 	0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a,
    151 	0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44,
    152 	0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f,
    153 	0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb,
    154 	0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48,
    155 	0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e,
    156 	0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a,
    157 	0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97,
    158 	0x84, 0xb4
    159 };
    160 static const u8 pkex_resp_y_p521[66] = {
    161 	0x01, 0xb9, 0x9c, 0xc6, 0x41, 0x32, 0x5b, 0xd2,
    162 	0x35, 0xd8, 0x8b, 0x2b, 0xe4, 0x6e, 0xcc, 0xdf,
    163 	0x7c, 0x38, 0xc4, 0x5b, 0xf6, 0x74, 0x71, 0x5c,
    164 	0x77, 0x16, 0x8a, 0x80, 0xa9, 0x84, 0xc7, 0x7b,
    165 	0x9d, 0xfd, 0x83, 0x6f, 0xae, 0xf8, 0x24, 0x16,
    166 	0x2f, 0x21, 0x25, 0x65, 0xa2, 0x1a, 0x6b, 0x2d,
    167 	0x30, 0x62, 0xb3, 0xcc, 0x6e, 0x59, 0x3c, 0x7f,
    168 	0x58, 0x91, 0x81, 0x72, 0x07, 0x8c, 0x91, 0xac,
    169 	0x31, 0x1e
    170 };
    171 
    172 /* Brainpool P-256r1 */
    173 static const u8 pkex_init_x_bp_p256r1[32] = {
    174 	0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10,
    175 	0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca,
    176 	0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75,
    177 	0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8
    178 };
    179 static const u8 pkex_init_y_bp_p256r1[32] = {
    180 	0x16, 0x30, 0x68, 0x32, 0x3b, 0xb0, 0x21, 0xee,
    181 	0xeb, 0xf7, 0xb6, 0x7c, 0xae, 0x52, 0x26, 0x42,
    182 	0x59, 0x28, 0x58, 0xb6, 0x14, 0x90, 0xed, 0x69,
    183 	0xd0, 0x67, 0xea, 0x25, 0x60, 0x0f, 0xa9, 0x6c
    184 };
    185 static const u8 pkex_resp_x_bp_p256r1[32] = {
    186 	0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f,
    187 	0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a,
    188 	0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a,
    189 	0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3
    190 };
    191 static const u8 pkex_resp_y_bp_p256r1[32] = {
    192 	0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd,
    193 	0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2,
    194 	0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e,
    195 	0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64
    196 };
    197 
    198 /* Brainpool P-384r1 */
    199 static const u8 pkex_init_x_bp_p384r1[48] = {
    200 	0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd,
    201 	0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19,
    202 	0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06,
    203 	0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62,
    204 	0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30,
    205 	0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe
    206 };
    207 static const u8 pkex_init_y_bp_p384r1[48] = {
    208 	0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99,
    209 	0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86,
    210 	0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32,
    211 	0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9,
    212 	0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e,
    213 	0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52
    214 };
    215 static const u8 pkex_resp_x_bp_p384r1[48] = {
    216 	0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0,
    217 	0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25,
    218 	0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b,
    219 	0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71,
    220 	0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce,
    221 	0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c
    222 };
    223 static const u8 pkex_resp_y_bp_p384r1[48] = {
    224 	0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65,
    225 	0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04,
    226 	0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70,
    227 	0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c,
    228 	0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb,
    229 	0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1
    230 };
    231 
    232 /* Brainpool P-512r1 */
    233 static const u8 pkex_init_x_bp_p512r1[64] = {
    234 	0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c,
    235 	0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51,
    236 	0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc,
    237 	0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95,
    238 	0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d,
    239 	0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff,
    240 	0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc,
    241 	0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f
    242 };
    243 static const u8 pkex_init_y_bp_p512r1[64] = {
    244 	0x5a, 0x28, 0x01, 0xbe, 0x96, 0x82, 0x4e, 0xf6,
    245 	0xfa, 0xed, 0x7d, 0xfd, 0x48, 0x8b, 0x48, 0x4e,
    246 	0xd1, 0x97, 0x87, 0xc4, 0x05, 0x5d, 0x15, 0x2a,
    247 	0xf4, 0x91, 0x4b, 0x75, 0x90, 0xd9, 0x34, 0x2c,
    248 	0x3c, 0x12, 0xf2, 0xf5, 0x25, 0x94, 0x24, 0x34,
    249 	0xa7, 0x6d, 0x66, 0xbc, 0x27, 0xa4, 0xa0, 0x8d,
    250 	0xd5, 0xe1, 0x54, 0xa3, 0x55, 0x26, 0xd4, 0x14,
    251 	0x17, 0x0f, 0xc1, 0xc7, 0x3d, 0x68, 0x7f, 0x5a
    252 };
    253 static const u8 pkex_resp_x_bp_p512r1[64] = {
    254 	0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72,
    255 	0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76,
    256 	0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19,
    257 	0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e,
    258 	0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9,
    259 	0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88,
    260 	0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29,
    261 	0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e
    262 };
    263 static const u8 pkex_resp_y_bp_p512r1[64] = {
    264 	0x2a, 0xbe, 0x59, 0xe6, 0xc4, 0xb3, 0xd8, 0x09,
    265 	0x66, 0x89, 0x0a, 0x2d, 0x19, 0xf0, 0x9c, 0x9f,
    266 	0xb4, 0xab, 0x8f, 0x50, 0x68, 0x3c, 0x74, 0x64,
    267 	0x4e, 0x19, 0x55, 0x81, 0x9b, 0x48, 0x5c, 0xf4,
    268 	0x12, 0x8d, 0xb9, 0xd8, 0x02, 0x5b, 0xe1, 0x26,
    269 	0x7e, 0x19, 0x5c, 0xfd, 0x70, 0xf7, 0x4b, 0xdc,
    270 	0xb5, 0x5d, 0xc1, 0x7a, 0xe9, 0xd1, 0x05, 0x2e,
    271 	0xd1, 0xfd, 0x2f, 0xce, 0x63, 0x77, 0x48, 0x2c
    272 };
    273 
    274 
    275 static int dpp_hash_vector(const struct dpp_curve_params *curve,
    276 			   size_t num_elem, const u8 *addr[], const size_t *len,
    277 			   u8 *mac)
    278 {
    279 	if (curve->hash_len == 32)
    280 		return sha256_vector(num_elem, addr, len, mac);
    281 	if (curve->hash_len == 48)
    282 		return sha384_vector(num_elem, addr, len, mac);
    283 	if (curve->hash_len == 64)
    284 		return sha512_vector(num_elem, addr, len, mac);
    285 	return -1;
    286 }
    287 
    288 
    289 static int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len,
    290 			   const char *label, u8 *out, size_t outlen)
    291 {
    292 	if (hash_len == 32)
    293 		return hmac_sha256_kdf(secret, secret_len, NULL,
    294 				       (const u8 *) label, os_strlen(label),
    295 				       out, outlen);
    296 	if (hash_len == 48)
    297 		return hmac_sha384_kdf(secret, secret_len, NULL,
    298 				       (const u8 *) label, os_strlen(label),
    299 				       out, outlen);
    300 	if (hash_len == 64)
    301 		return hmac_sha512_kdf(secret, secret_len, NULL,
    302 				       (const u8 *) label, os_strlen(label),
    303 				       out, outlen);
    304 	return -1;
    305 }
    306 
    307 
    308 static int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len,
    309 			   size_t num_elem, const u8 *addr[],
    310 			   const size_t *len, u8 *mac)
    311 {
    312 	if (hash_len == 32)
    313 		return hmac_sha256_vector(key, key_len, num_elem, addr, len,
    314 					  mac);
    315 	if (hash_len == 48)
    316 		return hmac_sha384_vector(key, key_len, num_elem, addr, len,
    317 					  mac);
    318 	if (hash_len == 64)
    319 		return hmac_sha512_vector(key, key_len, num_elem, addr, len,
    320 					  mac);
    321 	return -1;
    322 }
    323 
    324 
    325 static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len,
    326 		    const u8 *data, size_t data_len, u8 *mac)
    327 {
    328 	if (hash_len == 32)
    329 		return hmac_sha256(key, key_len, data, data_len, mac);
    330 	if (hash_len == 48)
    331 		return hmac_sha384(key, key_len, data, data_len, mac);
    332 	if (hash_len == 64)
    333 		return hmac_sha512(key, key_len, data, data_len, mac);
    334 	return -1;
    335 }
    336 
    337 
    338 static struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix)
    339 {
    340 	int len, res;
    341 	EC_KEY *eckey;
    342 	struct wpabuf *buf;
    343 	unsigned char *pos;
    344 
    345 	eckey = EVP_PKEY_get1_EC_KEY(pkey);
    346 	if (!eckey)
    347 		return NULL;
    348 	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
    349 	len = i2o_ECPublicKey(eckey, NULL);
    350 	if (len <= 0) {
    351 		wpa_printf(MSG_ERROR,
    352 			   "DDP: Failed to determine public key encoding length");
    353 		EC_KEY_free(eckey);
    354 		return NULL;
    355 	}
    356 
    357 	buf = wpabuf_alloc(len);
    358 	if (!buf) {
    359 		EC_KEY_free(eckey);
    360 		return NULL;
    361 	}
    362 
    363 	pos = wpabuf_put(buf, len);
    364 	res = i2o_ECPublicKey(eckey, &pos);
    365 	EC_KEY_free(eckey);
    366 	if (res != len) {
    367 		wpa_printf(MSG_ERROR,
    368 			   "DDP: Failed to encode public key (res=%d/%d)",
    369 			   res, len);
    370 		wpabuf_free(buf);
    371 		return NULL;
    372 	}
    373 
    374 	if (!prefix) {
    375 		/* Remove 0x04 prefix to match DPP definition */
    376 		pos = wpabuf_mhead(buf);
    377 		os_memmove(pos, pos + 1, len - 1);
    378 		buf->used--;
    379 	}
    380 
    381 	return buf;
    382 }
    383 
    384 
    385 static EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group,
    386 					     const u8 *buf_x, const u8 *buf_y,
    387 					     size_t len)
    388 {
    389 	EC_KEY *eckey = NULL;
    390 	BN_CTX *ctx;
    391 	EC_POINT *point = NULL;
    392 	BIGNUM *x = NULL, *y = NULL;
    393 	EVP_PKEY *pkey = NULL;
    394 
    395 	ctx = BN_CTX_new();
    396 	if (!ctx) {
    397 		wpa_printf(MSG_ERROR, "DPP: Out of memory");
    398 		return NULL;
    399 	}
    400 
    401 	point = EC_POINT_new(group);
    402 	x = BN_bin2bn(buf_x, len, NULL);
    403 	y = BN_bin2bn(buf_y, len, NULL);
    404 	if (!point || !x || !y) {
    405 		wpa_printf(MSG_ERROR, "DPP: Out of memory");
    406 		goto fail;
    407 	}
    408 
    409 	if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
    410 		wpa_printf(MSG_ERROR,
    411 			   "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s",
    412 			   ERR_error_string(ERR_get_error(), NULL));
    413 		goto fail;
    414 	}
    415 
    416 	if (!EC_POINT_is_on_curve(group, point, ctx) ||
    417 	    EC_POINT_is_at_infinity(group, point)) {
    418 		wpa_printf(MSG_ERROR, "DPP: Invalid point");
    419 		goto fail;
    420 	}
    421 
    422 	eckey = EC_KEY_new();
    423 	if (!eckey ||
    424 	    EC_KEY_set_group(eckey, group) != 1 ||
    425 	    EC_KEY_set_public_key(eckey, point) != 1) {
    426 		wpa_printf(MSG_ERROR,
    427 			   "DPP: Failed to set EC_KEY: %s",
    428 			   ERR_error_string(ERR_get_error(), NULL));
    429 		goto fail;
    430 	}
    431 	EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
    432 
    433 	pkey = EVP_PKEY_new();
    434 	if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) {
    435 		wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY");
    436 		goto fail;
    437 	}
    438 
    439 out:
    440 	BN_free(x);
    441 	BN_free(y);
    442 	EC_KEY_free(eckey);
    443 	EC_POINT_free(point);
    444 	BN_CTX_free(ctx);
    445 	return pkey;
    446 fail:
    447 	EVP_PKEY_free(pkey);
    448 	pkey = NULL;
    449 	goto out;
    450 }
    451 
    452 
    453 static EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key,
    454 				       const u8 *buf, size_t len)
    455 {
    456 	EC_KEY *eckey;
    457 	const EC_GROUP *group;
    458 	EVP_PKEY *pkey = NULL;
    459 
    460 	if (len & 1)
    461 		return NULL;
    462 
    463 	eckey = EVP_PKEY_get1_EC_KEY(group_key);
    464 	if (!eckey) {
    465 		wpa_printf(MSG_ERROR,
    466 			   "DPP: Could not get EC_KEY from group_key");
    467 		return NULL;
    468 	}
    469 
    470 	group = EC_KEY_get0_group(eckey);
    471 	if (group)
    472 		pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2,
    473 						  len / 2);
    474 	else
    475 		wpa_printf(MSG_ERROR, "DPP: Could not get EC group");
    476 
    477 	EC_KEY_free(eckey);
    478 	return pkey;
    479 }
    480 
    481 
    482 struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type,
    483 			      size_t len)
    484 {
    485 	struct wpabuf *msg;
    486 
    487 	msg = wpabuf_alloc(8 + len);
    488 	if (!msg)
    489 		return NULL;
    490 	wpabuf_put_u8(msg, WLAN_ACTION_PUBLIC);
    491 	wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
    492 	wpabuf_put_be24(msg, OUI_WFA);
    493 	wpabuf_put_u8(msg, DPP_OUI_TYPE);
    494 	wpabuf_put_u8(msg, 1); /* Crypto Suite */
    495 	wpabuf_put_u8(msg, type);
    496 	return msg;
    497 }
    498 
    499 
    500 const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len)
    501 {
    502 	u16 id, alen;
    503 	const u8 *pos = buf, *end = buf + len;
    504 
    505 	while (end - pos >= 4) {
    506 		id = WPA_GET_LE16(pos);
    507 		pos += 2;
    508 		alen = WPA_GET_LE16(pos);
    509 		pos += 2;
    510 		if (alen > end - pos)
    511 			return NULL;
    512 		if (id == req_id) {
    513 			*ret_len = alen;
    514 			return pos;
    515 		}
    516 		pos += alen;
    517 	}
    518 
    519 	return NULL;
    520 }
    521 
    522 
    523 int dpp_check_attrs(const u8 *buf, size_t len)
    524 {
    525 	const u8 *pos, *end;
    526 
    527 	pos = buf;
    528 	end = buf + len;
    529 	while (end - pos >= 4) {
    530 		u16 id, alen;
    531 
    532 		id = WPA_GET_LE16(pos);
    533 		pos += 2;
    534 		alen = WPA_GET_LE16(pos);
    535 		pos += 2;
    536 		wpa_printf(MSG_MSGDUMP, "DPP: Attribute ID %04x len %u",
    537 			   id, alen);
    538 		if (alen > end - pos) {
    539 			wpa_printf(MSG_DEBUG,
    540 				   "DPP: Truncated message - not enough room for the attribute - dropped");
    541 			return -1;
    542 		}
    543 		pos += alen;
    544 	}
    545 
    546 	if (end != pos) {
    547 		wpa_printf(MSG_DEBUG,
    548 			   "DPP: Unexpected octets (%d) after the last attribute",
    549 			   (int) (end - pos));
    550 		return -1;
    551 	}
    552 
    553 	return 0;
    554 }
    555 
    556 
    557 void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info)
    558 {
    559 	if (!info)
    560 		return;
    561 	os_free(info->uri);
    562 	os_free(info->info);
    563 	EVP_PKEY_free(info->pubkey);
    564 	os_free(info);
    565 }
    566 
    567 
    568 const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type)
    569 {
    570 	switch (type) {
    571 	case DPP_BOOTSTRAP_QR_CODE:
    572 		return "QRCODE";
    573 	case DPP_BOOTSTRAP_PKEX:
    574 		return "PKEX";
    575 	}
    576 	return "??";
    577 }
    578 
    579 
    580 static int dpp_uri_valid_info(const char *info)
    581 {
    582 	while (*info) {
    583 		unsigned char val = *info++;
    584 
    585 		if (val < 0x20 || val > 0x7e || val == 0x3b)
    586 			return 0;
    587 	}
    588 
    589 	return 1;
    590 }
    591 
    592 
    593 static int dpp_clone_uri(struct dpp_bootstrap_info *bi, const char *uri)
    594 {
    595 	bi->uri = os_strdup(uri);
    596 	return bi->uri ? 0 : -1;
    597 }
    598 
    599 
    600 int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi,
    601 			    const char *chan_list)
    602 {
    603 	const char *pos = chan_list;
    604 	int opclass, channel, freq;
    605 
    606 	while (pos && *pos && *pos != ';') {
    607 		opclass = atoi(pos);
    608 		if (opclass <= 0)
    609 			goto fail;
    610 		pos = os_strchr(pos, '/');
    611 		if (!pos)
    612 			goto fail;
    613 		pos++;
    614 		channel = atoi(pos);
    615 		if (channel <= 0)
    616 			goto fail;
    617 		while (*pos >= '0' && *pos <= '9')
    618 			pos++;
    619 		freq = ieee80211_chan_to_freq(NULL, opclass, channel);
    620 		wpa_printf(MSG_DEBUG,
    621 			   "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d",
    622 			   opclass, channel, freq);
    623 		if (freq < 0) {
    624 			wpa_printf(MSG_DEBUG,
    625 				   "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)",
    626 				   opclass, channel);
    627 		} else if (bi->num_freq == DPP_BOOTSTRAP_MAX_FREQ) {
    628 			wpa_printf(MSG_DEBUG,
    629 				   "DPP: Too many channels in URI channel-list - ignore list");
    630 			bi->num_freq = 0;
    631 			break;
    632 		} else {
    633 			bi->freq[bi->num_freq++] = freq;
    634 		}
    635 
    636 		if (*pos == ';' || *pos == '\0')
    637 			break;
    638 		if (*pos != ',')
    639 			goto fail;
    640 		pos++;
    641 	}
    642 
    643 	return 0;
    644 fail:
    645 	wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list");
    646 	return -1;
    647 }
    648 
    649 
    650 int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac)
    651 {
    652 	if (!mac)
    653 		return 0;
    654 
    655 	if (hwaddr_aton2(mac, bi->mac_addr) < 0) {
    656 		wpa_printf(MSG_DEBUG, "DPP: Invalid URI mac");
    657 		return -1;
    658 	}
    659 
    660 	wpa_printf(MSG_DEBUG, "DPP: URI mac: " MACSTR, MAC2STR(bi->mac_addr));
    661 
    662 	return 0;
    663 }
    664 
    665 
    666 int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info)
    667 {
    668 	const char *end;
    669 
    670 	if (!info)
    671 		return 0;
    672 
    673 	end = os_strchr(info, ';');
    674 	if (!end)
    675 		end = info + os_strlen(info);
    676 	bi->info = os_malloc(end - info + 1);
    677 	if (!bi->info)
    678 		return -1;
    679 	os_memcpy(bi->info, info, end - info);
    680 	bi->info[end - info] = '\0';
    681 	wpa_printf(MSG_DEBUG, "DPP: URI(information): %s", bi->info);
    682 	if (!dpp_uri_valid_info(bi->info)) {
    683 		wpa_printf(MSG_DEBUG, "DPP: Invalid URI information payload");
    684 		return -1;
    685 	}
    686 
    687 	return 0;
    688 }
    689 
    690 
    691 static const struct dpp_curve_params *
    692 dpp_get_curve_oid(const ASN1_OBJECT *poid)
    693 {
    694 	ASN1_OBJECT *oid;
    695 	int i;
    696 
    697 	for (i = 0; dpp_curves[i].name; i++) {
    698 		oid = OBJ_txt2obj(dpp_curves[i].name, 0);
    699 		if (oid && OBJ_cmp(poid, oid) == 0)
    700 			return &dpp_curves[i];
    701 	}
    702 	return NULL;
    703 }
    704 
    705 
    706 static const struct dpp_curve_params * dpp_get_curve_nid(int nid)
    707 {
    708 	int i, tmp;
    709 
    710 	if (!nid)
    711 		return NULL;
    712 	for (i = 0; dpp_curves[i].name; i++) {
    713 		tmp = OBJ_txt2nid(dpp_curves[i].name);
    714 		if (tmp == nid)
    715 			return &dpp_curves[i];
    716 	}
    717 	return NULL;
    718 }
    719 
    720 
    721 static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info)
    722 {
    723 	const char *end;
    724 	u8 *data;
    725 	size_t data_len;
    726 	EVP_PKEY *pkey;
    727 	const unsigned char *p;
    728 	int res;
    729 	X509_PUBKEY *pub = NULL;
    730 	ASN1_OBJECT *ppkalg;
    731 	const unsigned char *pk;
    732 	int ppklen;
    733 	X509_ALGOR *pa;
    734 #if OPENSSL_VERSION_NUMBER < 0x10100000L
    735 	ASN1_OBJECT *pa_oid;
    736 #else
    737 	const ASN1_OBJECT *pa_oid;
    738 #endif
    739 	const void *pval;
    740 	int ptype;
    741 	const ASN1_OBJECT *poid;
    742 	char buf[100];
    743 
    744 	end = os_strchr(info, ';');
    745 	if (!end)
    746 		return -1;
    747 
    748 	data = base64_decode((const unsigned char *) info, end - info,
    749 			     &data_len);
    750 	if (!data) {
    751 		wpa_printf(MSG_DEBUG,
    752 			   "DPP: Invalid base64 encoding on URI public-key");
    753 		return -1;
    754 	}
    755 	wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key",
    756 		    data, data_len);
    757 
    758 	if (sha256_vector(1, (const u8 **) &data, &data_len,
    759 			  bi->pubkey_hash) < 0) {
    760 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
    761 		return -1;
    762 	}
    763 	wpa_hexdump(MSG_DEBUG, "DPP: Public key hash",
    764 		    bi->pubkey_hash, SHA256_MAC_LEN);
    765 
    766 	/* DER encoded ASN.1 SubjectPublicKeyInfo
    767 	 *
    768 	 * SubjectPublicKeyInfo  ::=  SEQUENCE  {
    769 	 *      algorithm            AlgorithmIdentifier,
    770 	 *      subjectPublicKey     BIT STRING  }
    771 	 *
    772 	 * AlgorithmIdentifier  ::=  SEQUENCE  {
    773 	 *      algorithm               OBJECT IDENTIFIER,
    774 	 *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
    775 	 *
    776 	 * subjectPublicKey = compressed format public key per ANSI X9.63
    777 	 * algorithm = ecPublicKey (1.2.840.10045.2.1)
    778 	 * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g.,
    779 	 *       prime256v1 (1.2.840.10045.3.1.7)
    780 	 */
    781 
    782 	p = data;
    783 	pkey = d2i_PUBKEY(NULL, &p, data_len);
    784 	os_free(data);
    785 
    786 	if (!pkey) {
    787 		wpa_printf(MSG_DEBUG,
    788 			   "DPP: Could not parse URI public-key SubjectPublicKeyInfo");
    789 		return -1;
    790 	}
    791 
    792 	if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
    793 		wpa_printf(MSG_DEBUG,
    794 			   "DPP: SubjectPublicKeyInfo does not describe an EC key");
    795 		EVP_PKEY_free(pkey);
    796 		return -1;
    797 	}
    798 
    799 	res = X509_PUBKEY_set(&pub, pkey);
    800 	if (res != 1) {
    801 		wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey");
    802 		goto fail;
    803 	}
    804 
    805 	res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub);
    806 	if (res != 1) {
    807 		wpa_printf(MSG_DEBUG,
    808 			   "DPP: Could not extract SubjectPublicKeyInfo parameters");
    809 		goto fail;
    810 	}
    811 	res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0);
    812 	if (res < 0 || (size_t) res >= sizeof(buf)) {
    813 		wpa_printf(MSG_DEBUG,
    814 			   "DPP: Could not extract SubjectPublicKeyInfo algorithm");
    815 		goto fail;
    816 	}
    817 	wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf);
    818 	if (os_strcmp(buf, "id-ecPublicKey") != 0) {
    819 		wpa_printf(MSG_DEBUG,
    820 			   "DPP: Unsupported SubjectPublicKeyInfo algorithm");
    821 		goto fail;
    822 	}
    823 
    824 	X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa);
    825 	if (ptype != V_ASN1_OBJECT) {
    826 		wpa_printf(MSG_DEBUG,
    827 			   "DPP: SubjectPublicKeyInfo parameters did not contain an OID");
    828 		goto fail;
    829 	}
    830 	poid = pval;
    831 	res = OBJ_obj2txt(buf, sizeof(buf), poid, 0);
    832 	if (res < 0 || (size_t) res >= sizeof(buf)) {
    833 		wpa_printf(MSG_DEBUG,
    834 			   "DPP: Could not extract SubjectPublicKeyInfo parameters OID");
    835 		goto fail;
    836 	}
    837 	wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf);
    838 	bi->curve = dpp_get_curve_oid(poid);
    839 	if (!bi->curve) {
    840 		wpa_printf(MSG_DEBUG,
    841 			   "DPP: Unsupported SubjectPublicKeyInfo curve: %s",
    842 			   buf);
    843 		goto fail;
    844 	}
    845 
    846 	wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen);
    847 
    848 	X509_PUBKEY_free(pub);
    849 	bi->pubkey = pkey;
    850 	return 0;
    851 fail:
    852 	X509_PUBKEY_free(pub);
    853 	EVP_PKEY_free(pkey);
    854 	return -1;
    855 }
    856 
    857 
    858 static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri)
    859 {
    860 	const char *pos = uri;
    861 	const char *end;
    862 	const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL;
    863 	struct dpp_bootstrap_info *bi;
    864 
    865 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri));
    866 
    867 	if (os_strncmp(pos, "DPP:", 4) != 0) {
    868 		wpa_printf(MSG_INFO, "DPP: Not a DPP URI");
    869 		return NULL;
    870 	}
    871 	pos += 4;
    872 
    873 	for (;;) {
    874 		end = os_strchr(pos, ';');
    875 		if (!end)
    876 			break;
    877 
    878 		if (end == pos) {
    879 			/* Handle terminating ";;" and ignore unexpected ";"
    880 			 * for parsing robustness. */
    881 			pos++;
    882 			continue;
    883 		}
    884 
    885 		if (pos[0] == 'C' && pos[1] == ':' && !chan_list)
    886 			chan_list = pos + 2;
    887 		else if (pos[0] == 'M' && pos[1] == ':' && !mac)
    888 			mac = pos + 2;
    889 		else if (pos[0] == 'I' && pos[1] == ':' && !info)
    890 			info = pos + 2;
    891 		else if (pos[0] == 'K' && pos[1] == ':' && !pk)
    892 			pk = pos + 2;
    893 		else
    894 			wpa_hexdump_ascii(MSG_DEBUG,
    895 					  "DPP: Ignore unrecognized URI parameter",
    896 					  pos, end - pos);
    897 		pos = end + 1;
    898 	}
    899 
    900 	if (!pk) {
    901 		wpa_printf(MSG_INFO, "DPP: URI missing public-key");
    902 		return NULL;
    903 	}
    904 
    905 	bi = os_zalloc(sizeof(*bi));
    906 	if (!bi)
    907 		return NULL;
    908 
    909 	if (dpp_clone_uri(bi, uri) < 0 ||
    910 	    dpp_parse_uri_chan_list(bi, chan_list) < 0 ||
    911 	    dpp_parse_uri_mac(bi, mac) < 0 ||
    912 	    dpp_parse_uri_info(bi, info) < 0 ||
    913 	    dpp_parse_uri_pk(bi, pk) < 0) {
    914 		dpp_bootstrap_info_free(bi);
    915 		bi = NULL;
    916 	}
    917 
    918 	return bi;
    919 }
    920 
    921 
    922 struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri)
    923 {
    924 	struct dpp_bootstrap_info *bi;
    925 
    926 	bi = dpp_parse_uri(uri);
    927 	if (bi)
    928 		bi->type = DPP_BOOTSTRAP_QR_CODE;
    929 	return bi;
    930 }
    931 
    932 
    933 static void dpp_debug_print_key(const char *title, EVP_PKEY *key)
    934 {
    935 	EC_KEY *eckey;
    936 	BIO *out;
    937 	size_t rlen;
    938 	char *txt;
    939 	int res;
    940 	unsigned char *der = NULL;
    941 	int der_len;
    942 
    943 	out = BIO_new(BIO_s_mem());
    944 	if (!out)
    945 		return;
    946 
    947 	EVP_PKEY_print_private(out, key, 0, NULL);
    948 	rlen = BIO_ctrl_pending(out);
    949 	txt = os_malloc(rlen + 1);
    950 	if (txt) {
    951 		res = BIO_read(out, txt, rlen);
    952 		if (res > 0) {
    953 			txt[res] = '\0';
    954 			wpa_printf(MSG_DEBUG, "%s: %s", title, txt);
    955 		}
    956 		os_free(txt);
    957 	}
    958 	BIO_free(out);
    959 
    960 	eckey = EVP_PKEY_get1_EC_KEY(key);
    961 	if (!eckey)
    962 		return;
    963 
    964 	der_len = i2d_ECPrivateKey(eckey, &der);
    965 	if (der_len > 0)
    966 		wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len);
    967 	OPENSSL_free(der);
    968 	if (der_len <= 0) {
    969 		der = NULL;
    970 		der_len = i2d_EC_PUBKEY(eckey, &der);
    971 		if (der_len > 0)
    972 			wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len);
    973 		OPENSSL_free(der);
    974 	}
    975 
    976 	EC_KEY_free(eckey);
    977 }
    978 
    979 
    980 static EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve)
    981 {
    982 #ifdef OPENSSL_IS_BORINGSSL
    983 	EVP_PKEY_CTX *kctx = NULL;
    984 	const EC_GROUP *group;
    985 	EC_KEY *ec_params;
    986 #else
    987 	EVP_PKEY_CTX *pctx, *kctx = NULL;
    988 #endif
    989 	EVP_PKEY *params = NULL, *key = NULL;
    990 	int nid;
    991 
    992 	wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
    993 
    994 	nid = OBJ_txt2nid(curve->name);
    995 	if (nid == NID_undef) {
    996 		wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name);
    997 		return NULL;
    998 	}
    999 #ifdef OPENSSL_IS_BORINGSSL
   1000 	group = EC_GROUP_new_by_curve_name(nid);
   1001 	ec_params = EC_KEY_new();
   1002 	if (!ec_params || EC_KEY_set_group(ec_params, group) != 1) {
   1003 		wpa_printf(MSG_ERROR,
   1004 			   "DPP: Failed to generate EC_KEY parameters");
   1005 		goto fail;
   1006 	}
   1007 	EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE);
   1008 	params = EVP_PKEY_new();
   1009 	if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) {
   1010 		wpa_printf(MSG_ERROR,
   1011 			   "DPP: Failed to generate EVP_PKEY parameters");
   1012 		goto fail;
   1013 	}
   1014 #else
   1015 	pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
   1016 	if (!pctx ||
   1017 	    EVP_PKEY_paramgen_init(pctx) != 1 ||
   1018 	    EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, nid) != 1 ||
   1019 	    EVP_PKEY_CTX_set_ec_param_enc(pctx, OPENSSL_EC_NAMED_CURVE) != 1 ||
   1020 	    EVP_PKEY_paramgen(pctx, &params) != 1) {
   1021 		wpa_printf(MSG_ERROR,
   1022 			   "DPP: Failed to generate EVP_PKEY parameters");
   1023 		EVP_PKEY_CTX_free(pctx);
   1024 		goto fail;
   1025 	}
   1026 	EVP_PKEY_CTX_free(pctx);
   1027 #endif
   1028 
   1029 	kctx = EVP_PKEY_CTX_new(params, NULL);
   1030 	if (!kctx ||
   1031 	    EVP_PKEY_keygen_init(kctx) != 1 ||
   1032 	    EVP_PKEY_keygen(kctx, &key) != 1) {
   1033 		wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key");
   1034 		goto fail;
   1035 	}
   1036 
   1037 	if (wpa_debug_show_keys)
   1038 		dpp_debug_print_key("Own generated key", key);
   1039 
   1040 	EVP_PKEY_free(params);
   1041 	EVP_PKEY_CTX_free(kctx);
   1042 	return key;
   1043 fail:
   1044 	EVP_PKEY_CTX_free(kctx);
   1045 	EVP_PKEY_free(params);
   1046 	return NULL;
   1047 }
   1048 
   1049 
   1050 static const struct dpp_curve_params *
   1051 dpp_get_curve_name(const char *name)
   1052 {
   1053 	int i;
   1054 
   1055 	for (i = 0; dpp_curves[i].name; i++) {
   1056 		if (os_strcmp(name, dpp_curves[i].name) == 0 ||
   1057 		    (dpp_curves[i].jwk_crv &&
   1058 		     os_strcmp(name, dpp_curves[i].jwk_crv) == 0))
   1059 			return &dpp_curves[i];
   1060 	}
   1061 	return NULL;
   1062 }
   1063 
   1064 
   1065 static const struct dpp_curve_params *
   1066 dpp_get_curve_jwk_crv(const char *name)
   1067 {
   1068 	int i;
   1069 
   1070 	for (i = 0; dpp_curves[i].name; i++) {
   1071 		if (dpp_curves[i].jwk_crv &&
   1072 		    os_strcmp(name, dpp_curves[i].jwk_crv) == 0)
   1073 			return &dpp_curves[i];
   1074 	}
   1075 	return NULL;
   1076 }
   1077 
   1078 
   1079 static EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve,
   1080 				  const u8 *privkey, size_t privkey_len)
   1081 {
   1082 	EVP_PKEY *pkey;
   1083 	EC_KEY *eckey;
   1084 	const EC_GROUP *group;
   1085 	int nid;
   1086 
   1087 	pkey = EVP_PKEY_new();
   1088 	if (!pkey)
   1089 		return NULL;
   1090 	eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len);
   1091 	if (!eckey) {
   1092 		wpa_printf(MSG_INFO,
   1093 			   "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s",
   1094 			   ERR_error_string(ERR_get_error(), NULL));
   1095 		EVP_PKEY_free(pkey);
   1096 		return NULL;
   1097 	}
   1098 	group = EC_KEY_get0_group(eckey);
   1099 	if (!group) {
   1100 		EC_KEY_free(eckey);
   1101 		EVP_PKEY_free(pkey);
   1102 		return NULL;
   1103 	}
   1104 	nid = EC_GROUP_get_curve_name(group);
   1105 	*curve = dpp_get_curve_nid(nid);
   1106 	if (!*curve) {
   1107 		wpa_printf(MSG_INFO,
   1108 			   "DPP: Unsupported curve (nid=%d) in pre-assigned key",
   1109 			   nid);
   1110 		EC_KEY_free(eckey);
   1111 		EVP_PKEY_free(pkey);
   1112 		return NULL;
   1113 	}
   1114 
   1115 	if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) {
   1116 		EC_KEY_free(eckey);
   1117 		EVP_PKEY_free(pkey);
   1118 		return NULL;
   1119 	}
   1120 	return pkey;
   1121 }
   1122 
   1123 
   1124 int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
   1125 {
   1126 	unsigned char *der = NULL;
   1127 	int der_len;
   1128 	EC_KEY *eckey;
   1129 	int res;
   1130 	size_t len;
   1131 
   1132 	/* Need to get the compressed form of the public key through EC_KEY, so
   1133 	 * cannot use the simpler i2d_PUBKEY() here. */
   1134 	eckey = EVP_PKEY_get1_EC_KEY(bi->pubkey);
   1135 	if (!eckey)
   1136 		return -1;
   1137 	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
   1138 	der_len = i2d_EC_PUBKEY(eckey, &der);
   1139 	EC_KEY_free(eckey);
   1140 	if (der_len <= 0) {
   1141 		wpa_printf(MSG_ERROR,
   1142 			   "DDP: Failed to build DER encoded public key");
   1143 		OPENSSL_free(der);
   1144 		return -1;
   1145 	}
   1146 
   1147 	len = der_len;
   1148 	res = sha256_vector(1, (const u8 **) &der, &len, bi->pubkey_hash);
   1149 	OPENSSL_free(der);
   1150 	if (res < 0)
   1151 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
   1152 	return res;
   1153 }
   1154 
   1155 
   1156 char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
   1157 		  const u8 *privkey, size_t privkey_len)
   1158 {
   1159 	unsigned char *base64 = NULL;
   1160 	char *pos, *end;
   1161 	size_t len;
   1162 	unsigned char *der = NULL;
   1163 	int der_len;
   1164 	EC_KEY *eckey;
   1165 
   1166 	if (!curve) {
   1167 		bi->curve = &dpp_curves[0];
   1168 	} else {
   1169 		bi->curve = dpp_get_curve_name(curve);
   1170 		if (!bi->curve) {
   1171 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
   1172 				   curve);
   1173 			return NULL;
   1174 		}
   1175 	}
   1176 	if (privkey)
   1177 		bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len);
   1178 	else
   1179 		bi->pubkey = dpp_gen_keypair(bi->curve);
   1180 	if (!bi->pubkey)
   1181 		goto fail;
   1182 	bi->own = 1;
   1183 
   1184 	/* Need to get the compressed form of the public key through EC_KEY, so
   1185 	 * cannot use the simpler i2d_PUBKEY() here. */
   1186 	eckey = EVP_PKEY_get1_EC_KEY(bi->pubkey);
   1187 	if (!eckey)
   1188 		goto fail;
   1189 	EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
   1190 	der_len = i2d_EC_PUBKEY(eckey, &der);
   1191 	EC_KEY_free(eckey);
   1192 	if (der_len <= 0) {
   1193 		wpa_printf(MSG_ERROR,
   1194 			   "DDP: Failed to build DER encoded public key");
   1195 		goto fail;
   1196 	}
   1197 
   1198 	len = der_len;
   1199 	if (sha256_vector(1, (const u8 **) &der, &len, bi->pubkey_hash) < 0) {
   1200 		wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key");
   1201 		goto fail;
   1202 	}
   1203 
   1204 	base64 = base64_encode(der, der_len, &len);
   1205 	OPENSSL_free(der);
   1206 	der = NULL;
   1207 	if (!base64)
   1208 		goto fail;
   1209 	pos = (char *) base64;
   1210 	end = pos + len;
   1211 	for (;;) {
   1212 		pos = os_strchr(pos, '\n');
   1213 		if (!pos)
   1214 			break;
   1215 		os_memmove(pos, pos + 1, end - pos);
   1216 	}
   1217 	return (char *) base64;
   1218 fail:
   1219 	os_free(base64);
   1220 	OPENSSL_free(der);
   1221 	return NULL;
   1222 }
   1223 
   1224 
   1225 static int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1,
   1226 			 unsigned int hash_len)
   1227 {
   1228 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
   1229 	const char *info = "first intermediate key";
   1230 	int res;
   1231 
   1232 	/* k1 = HKDF(<>, "first intermediate key", M.x) */
   1233 
   1234 	/* HKDF-Extract(<>, M.x) */
   1235 	os_memset(salt, 0, hash_len);
   1236 	if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0)
   1237 		return -1;
   1238 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)",
   1239 			prk, hash_len);
   1240 
   1241 	/* HKDF-Expand(PRK, info, L) */
   1242 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len);
   1243 	os_memset(prk, 0, hash_len);
   1244 	if (res < 0)
   1245 		return -1;
   1246 
   1247 	wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)",
   1248 			k1, hash_len);
   1249 	return 0;
   1250 }
   1251 
   1252 
   1253 static int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2,
   1254 			 unsigned int hash_len)
   1255 {
   1256 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
   1257 	const char *info = "second intermediate key";
   1258 	int res;
   1259 
   1260 	/* k2 = HKDF(<>, "second intermediate key", N.x) */
   1261 
   1262 	/* HKDF-Extract(<>, N.x) */
   1263 	os_memset(salt, 0, hash_len);
   1264 	res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk);
   1265 	if (res < 0)
   1266 		return -1;
   1267 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
   1268 			prk, hash_len);
   1269 
   1270 	/* HKDF-Expand(PRK, info, L) */
   1271 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len);
   1272 	os_memset(prk, 0, hash_len);
   1273 	if (res < 0)
   1274 		return -1;
   1275 
   1276 	wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)",
   1277 			k2, hash_len);
   1278 	return 0;
   1279 }
   1280 
   1281 
   1282 static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke,
   1283 			 unsigned int hash_len)
   1284 {
   1285 	size_t nonce_len;
   1286 	u8 nonces[2 * DPP_MAX_NONCE_LEN];
   1287 	const char *info_ke = "DPP Key";
   1288 	u8 prk[DPP_MAX_HASH_LEN];
   1289 	int res;
   1290 	const u8 *addr[3];
   1291 	size_t len[3];
   1292 	size_t num_elem = 0;
   1293 
   1294 	/* ke = HKDF(I-nonce | R-nonce, "DPP Key", M.x | N.x [| L.x]) */
   1295 
   1296 	/* HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */
   1297 	nonce_len = auth->curve->nonce_len;
   1298 	os_memcpy(nonces, auth->i_nonce, nonce_len);
   1299 	os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len);
   1300 	addr[num_elem] = auth->Mx;
   1301 	len[num_elem] = auth->secret_len;
   1302 	num_elem++;
   1303 	addr[num_elem] = auth->Nx;
   1304 	len[num_elem] = auth->secret_len;
   1305 	num_elem++;
   1306 	if (auth->peer_bi && auth->own_bi) {
   1307 		addr[num_elem] = auth->Lx;
   1308 		len[num_elem] = auth->secret_len;
   1309 		num_elem++;
   1310 	}
   1311 	res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len,
   1312 			      num_elem, addr, len, prk);
   1313 	if (res < 0)
   1314 		return -1;
   1315 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
   1316 			prk, hash_len);
   1317 
   1318 	/* HKDF-Expand(PRK, info, L) */
   1319 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info_ke, ke, hash_len);
   1320 	os_memset(prk, 0, hash_len);
   1321 	if (res < 0)
   1322 		return -1;
   1323 
   1324 	wpa_hexdump_key(MSG_DEBUG, "DPP: ke = HKDF-Expand(PRK, info, L)",
   1325 			ke, hash_len);
   1326 	return 0;
   1327 }
   1328 
   1329 
   1330 struct dpp_authentication * dpp_auth_init(void *msg_ctx,
   1331 					  struct dpp_bootstrap_info *peer_bi,
   1332 					  struct dpp_bootstrap_info *own_bi,
   1333 					  int configurator)
   1334 {
   1335 	struct dpp_authentication *auth;
   1336 	size_t nonce_len;
   1337 	EVP_PKEY_CTX *ctx = NULL;
   1338 	size_t secret_len;
   1339 	struct wpabuf *msg, *pi = NULL;
   1340 	u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1];
   1341 	u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE];
   1342 	u8 *pos;
   1343 	const u8 *addr[2];
   1344 	size_t len[2], siv_len, attr_len;
   1345 	u8 *attr_start, *attr_end;
   1346 
   1347 	auth = os_zalloc(sizeof(*auth));
   1348 	if (!auth)
   1349 		return NULL;
   1350 	auth->msg_ctx = msg_ctx;
   1351 	auth->initiator = 1;
   1352 	auth->configurator = configurator;
   1353 	auth->peer_bi = peer_bi;
   1354 	auth->own_bi = own_bi;
   1355 	auth->curve = peer_bi->curve;
   1356 
   1357 	nonce_len = auth->curve->nonce_len;
   1358 	if (random_get_bytes(auth->i_nonce, nonce_len)) {
   1359 		wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce");
   1360 		goto fail;
   1361 	}
   1362 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len);
   1363 
   1364 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
   1365 	if (!auth->own_protocol_key)
   1366 		goto fail;
   1367 
   1368 	pi = dpp_get_pubkey_point(auth->own_protocol_key, 0);
   1369 	if (!pi)
   1370 		goto fail;
   1371 
   1372 	/* ECDH: M = pI * BR */
   1373 	ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
   1374 	if (!ctx ||
   1375 	    EVP_PKEY_derive_init(ctx) != 1 ||
   1376 	    EVP_PKEY_derive_set_peer(ctx, auth->peer_bi->pubkey) != 1 ||
   1377 	    EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
   1378 	    secret_len > DPP_MAX_SHARED_SECRET_LEN ||
   1379 	    EVP_PKEY_derive(ctx, auth->Mx, &secret_len) != 1) {
   1380 		wpa_printf(MSG_ERROR,
   1381 			   "DPP: Failed to derive ECDH shared secret: %s",
   1382 			   ERR_error_string(ERR_get_error(), NULL));
   1383 		goto fail;
   1384 	}
   1385 	auth->secret_len = secret_len;
   1386 	EVP_PKEY_CTX_free(ctx);
   1387 	ctx = NULL;
   1388 
   1389 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
   1390 			auth->Mx, auth->secret_len);
   1391 
   1392 	if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
   1393 			  auth->curve->hash_len) < 0)
   1394 		goto fail;
   1395 
   1396 	/* Build DPP Authentication Request frame attributes */
   1397 	attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + wpabuf_len(pi) +
   1398 		4 + sizeof(wrapped_data);
   1399 	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len);
   1400 	if (!msg)
   1401 		goto fail;
   1402 	auth->req_msg = msg;
   1403 
   1404 	attr_start = wpabuf_put(msg, 0);
   1405 
   1406 	/* Responder Bootstrapping Key Hash */
   1407 	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
   1408 	wpabuf_put_le16(msg, SHA256_MAC_LEN);
   1409 	wpabuf_put_data(msg, auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
   1410 
   1411 	/* Initiator Bootstrapping Key Hash */
   1412 	wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
   1413 	wpabuf_put_le16(msg, SHA256_MAC_LEN);
   1414 	if (auth->own_bi)
   1415 		wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
   1416 	else
   1417 		os_memset(wpabuf_put(msg, SHA256_MAC_LEN), 0, SHA256_MAC_LEN);
   1418 
   1419 	/* Initiator Protocol Key */
   1420 	wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY);
   1421 	wpabuf_put_le16(msg, wpabuf_len(pi));
   1422 	wpabuf_put_buf(msg, pi);
   1423 	wpabuf_free(pi);
   1424 	pi = NULL;
   1425 
   1426 	/* Wrapped data ({I-nonce, I-capabilities}k1) */
   1427 	pos = clear;
   1428 	/* I-nonce */
   1429 	WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
   1430 	pos += 2;
   1431 	WPA_PUT_LE16(pos, nonce_len);
   1432 	pos += 2;
   1433 	os_memcpy(pos, auth->i_nonce, nonce_len);
   1434 	pos += nonce_len;
   1435 	/* I-capabilities */
   1436 	WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES);
   1437 	pos += 2;
   1438 	WPA_PUT_LE16(pos, 1);
   1439 	pos += 2;
   1440 	auth->i_capab = configurator ? DPP_CAPAB_CONFIGURATOR :
   1441 		DPP_CAPAB_ENROLLEE;
   1442 	*pos++ = auth->i_capab;
   1443 
   1444 	attr_end = wpabuf_put(msg, 0);
   1445 
   1446 	/* OUI, OUI type, Crypto Suite, DPP frame type */
   1447 	addr[0] = wpabuf_head_u8(msg) + 2;
   1448 	len[0] = 3 + 1 + 1 + 1;
   1449 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   1450 
   1451 	/* Attributes before Wrapped Data */
   1452 	addr[1] = attr_start;
   1453 	len[1] = attr_end - attr_start;
   1454 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   1455 
   1456 	siv_len = pos - clear;
   1457 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
   1458 	if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len,
   1459 			    2, addr, len, wrapped_data) < 0)
   1460 		goto fail;
   1461 	siv_len += AES_BLOCK_SIZE;
   1462 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   1463 		    wrapped_data, siv_len);
   1464 
   1465 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
   1466 	wpabuf_put_le16(msg, siv_len);
   1467 	wpabuf_put_data(msg, wrapped_data, siv_len);
   1468 
   1469 	wpa_hexdump_buf(MSG_DEBUG,
   1470 			"DPP: Authentication Request frame attributes", msg);
   1471 
   1472 	return auth;
   1473 fail:
   1474 	wpabuf_free(pi);
   1475 	EVP_PKEY_CTX_free(ctx);
   1476 	dpp_auth_deinit(auth);
   1477 	return NULL;
   1478 }
   1479 
   1480 
   1481 struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth,
   1482 				   const char *json)
   1483 {
   1484 	size_t nonce_len;
   1485 	size_t json_len, clear_len;
   1486 	struct wpabuf *clear = NULL, *msg = NULL;
   1487 	u8 *wrapped;
   1488 
   1489 	wpa_printf(MSG_DEBUG, "DPP: Build configuration request");
   1490 
   1491 	nonce_len = auth->curve->nonce_len;
   1492 	if (random_get_bytes(auth->e_nonce, nonce_len)) {
   1493 		wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce");
   1494 		goto fail;
   1495 	}
   1496 	wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", auth->e_nonce, nonce_len);
   1497 	json_len = os_strlen(json);
   1498 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: configAttr JSON", json, json_len);
   1499 
   1500 	/* { E-nonce, configAttrib }ke */
   1501 	clear_len = 4 + nonce_len + 4 + json_len;
   1502 	clear = wpabuf_alloc(clear_len);
   1503 	msg = wpabuf_alloc(4 + clear_len + AES_BLOCK_SIZE);
   1504 	if (!clear || !msg)
   1505 		goto fail;
   1506 
   1507 	/* E-nonce */
   1508 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
   1509 	wpabuf_put_le16(clear, nonce_len);
   1510 	wpabuf_put_data(clear, auth->e_nonce, nonce_len);
   1511 
   1512 	/* configAttrib */
   1513 	wpabuf_put_le16(clear, DPP_ATTR_CONFIG_ATTR_OBJ);
   1514 	wpabuf_put_le16(clear, json_len);
   1515 	wpabuf_put_data(clear, json, json_len);
   1516 
   1517 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
   1518 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
   1519 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
   1520 
   1521 	/* No AES-SIV AD */
   1522 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
   1523 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
   1524 			    wpabuf_head(clear), wpabuf_len(clear),
   1525 			    0, NULL, NULL, wrapped) < 0)
   1526 		goto fail;
   1527 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   1528 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
   1529 
   1530 	wpa_hexdump_buf(MSG_DEBUG,
   1531 			"DPP: Configuration Request frame attributes", msg);
   1532 	wpabuf_free(clear);
   1533 	return msg;
   1534 
   1535 fail:
   1536 	wpabuf_free(clear);
   1537 	wpabuf_free(msg);
   1538 	return NULL;
   1539 }
   1540 
   1541 
   1542 static void dpp_auth_success(struct dpp_authentication *auth)
   1543 {
   1544 	wpa_printf(MSG_DEBUG,
   1545 		   "DPP: Authentication success - clear temporary keys");
   1546 	os_memset(auth->Mx, 0, sizeof(auth->Mx));
   1547 	os_memset(auth->Nx, 0, sizeof(auth->Nx));
   1548 	os_memset(auth->Lx, 0, sizeof(auth->Lx));
   1549 	os_memset(auth->k1, 0, sizeof(auth->k1));
   1550 	os_memset(auth->k2, 0, sizeof(auth->k2));
   1551 
   1552 	auth->auth_success = 1;
   1553 }
   1554 
   1555 
   1556 static int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth)
   1557 {
   1558 	struct wpabuf *pix, *prx, *bix, *brx;
   1559 	const u8 *addr[7];
   1560 	size_t len[7];
   1561 	size_t i, num_elem = 0;
   1562 	size_t nonce_len;
   1563 	u8 zero = 0;
   1564 	int res = -1;
   1565 
   1566 	/* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
   1567 	nonce_len = auth->curve->nonce_len;
   1568 
   1569 	if (auth->initiator) {
   1570 		pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
   1571 		prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
   1572 		if (auth->own_bi)
   1573 			bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
   1574 		else
   1575 			bix = NULL;
   1576 		brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
   1577 	} else {
   1578 		pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
   1579 		prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
   1580 		if (auth->peer_bi)
   1581 			bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
   1582 		else
   1583 			bix = NULL;
   1584 		brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
   1585 	}
   1586 	if (!pix || !prx || !brx)
   1587 		goto fail;
   1588 
   1589 	addr[num_elem] = auth->i_nonce;
   1590 	len[num_elem] = nonce_len;
   1591 	num_elem++;
   1592 
   1593 	addr[num_elem] = auth->r_nonce;
   1594 	len[num_elem] = nonce_len;
   1595 	num_elem++;
   1596 
   1597 	addr[num_elem] = wpabuf_head(pix);
   1598 	len[num_elem] = wpabuf_len(pix) / 2;
   1599 	num_elem++;
   1600 
   1601 	addr[num_elem] = wpabuf_head(prx);
   1602 	len[num_elem] = wpabuf_len(prx) / 2;
   1603 	num_elem++;
   1604 
   1605 	if (bix) {
   1606 		addr[num_elem] = wpabuf_head(bix);
   1607 		len[num_elem] = wpabuf_len(bix) / 2;
   1608 		num_elem++;
   1609 	}
   1610 
   1611 	addr[num_elem] = wpabuf_head(brx);
   1612 	len[num_elem] = wpabuf_len(brx) / 2;
   1613 	num_elem++;
   1614 
   1615 	addr[num_elem] = &zero;
   1616 	len[num_elem] = 1;
   1617 	num_elem++;
   1618 
   1619 	wpa_printf(MSG_DEBUG, "DPP: R-auth hash components");
   1620 	for (i = 0; i < num_elem; i++)
   1621 		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
   1622 	res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth);
   1623 	if (res == 0)
   1624 		wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth,
   1625 			    auth->curve->hash_len);
   1626 fail:
   1627 	wpabuf_free(pix);
   1628 	wpabuf_free(prx);
   1629 	wpabuf_free(bix);
   1630 	wpabuf_free(brx);
   1631 	return res;
   1632 }
   1633 
   1634 
   1635 static int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth)
   1636 {
   1637 	struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL;
   1638 	const u8 *addr[7];
   1639 	size_t len[7];
   1640 	size_t i, num_elem = 0;
   1641 	size_t nonce_len;
   1642 	u8 one = 1;
   1643 	int res = -1;
   1644 
   1645 	/* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
   1646 	nonce_len = auth->curve->nonce_len;
   1647 
   1648 	if (auth->initiator) {
   1649 		pix = dpp_get_pubkey_point(auth->own_protocol_key, 0);
   1650 		prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
   1651 		if (auth->own_bi)
   1652 			bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
   1653 		else
   1654 			bix = NULL;
   1655 		if (!auth->peer_bi)
   1656 			goto fail;
   1657 		brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
   1658 	} else {
   1659 		pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0);
   1660 		prx = dpp_get_pubkey_point(auth->own_protocol_key, 0);
   1661 		if (auth->peer_bi)
   1662 			bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0);
   1663 		else
   1664 			bix = NULL;
   1665 		if (!auth->own_bi)
   1666 			goto fail;
   1667 		brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0);
   1668 	}
   1669 	if (!pix || !prx || !brx)
   1670 		goto fail;
   1671 
   1672 	addr[num_elem] = auth->r_nonce;
   1673 	len[num_elem] = nonce_len;
   1674 	num_elem++;
   1675 
   1676 	addr[num_elem] = auth->i_nonce;
   1677 	len[num_elem] = nonce_len;
   1678 	num_elem++;
   1679 
   1680 	addr[num_elem] = wpabuf_head(prx);
   1681 	len[num_elem] = wpabuf_len(prx) / 2;
   1682 	num_elem++;
   1683 
   1684 	addr[num_elem] = wpabuf_head(pix);
   1685 	len[num_elem] = wpabuf_len(pix) / 2;
   1686 	num_elem++;
   1687 
   1688 	addr[num_elem] = wpabuf_head(brx);
   1689 	len[num_elem] = wpabuf_len(brx) / 2;
   1690 	num_elem++;
   1691 
   1692 	if (bix) {
   1693 		addr[num_elem] = wpabuf_head(bix);
   1694 		len[num_elem] = wpabuf_len(bix) / 2;
   1695 		num_elem++;
   1696 	}
   1697 
   1698 	addr[num_elem] = &one;
   1699 	len[num_elem] = 1;
   1700 	num_elem++;
   1701 
   1702 	wpa_printf(MSG_DEBUG, "DPP: I-auth hash components");
   1703 	for (i = 0; i < num_elem; i++)
   1704 		wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]);
   1705 	res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth);
   1706 	if (res == 0)
   1707 		wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth,
   1708 			    auth->curve->hash_len);
   1709 fail:
   1710 	wpabuf_free(pix);
   1711 	wpabuf_free(prx);
   1712 	wpabuf_free(bix);
   1713 	wpabuf_free(brx);
   1714 	return res;
   1715 }
   1716 
   1717 
   1718 static int dpp_auth_derive_l_responder(struct dpp_authentication *auth)
   1719 {
   1720 	const EC_GROUP *group;
   1721 	EC_POINT *l = NULL;
   1722 	EC_KEY *BI = NULL, *bR = NULL, *pR = NULL;
   1723 	const EC_POINT *BI_point;
   1724 	BN_CTX *bnctx;
   1725 	BIGNUM *lx, *sum, *q;
   1726 	const BIGNUM *bR_bn, *pR_bn;
   1727 	int ret = -1;
   1728 	int num_bytes, offset;
   1729 
   1730 	/* L = ((bR + pR) modulo q) * BI */
   1731 
   1732 	bnctx = BN_CTX_new();
   1733 	sum = BN_new();
   1734 	q = BN_new();
   1735 	lx = BN_new();
   1736 	if (!bnctx || !sum || !q || !lx)
   1737 		goto fail;
   1738 	BI = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey);
   1739 	if (!BI)
   1740 		goto fail;
   1741 	BI_point = EC_KEY_get0_public_key(BI);
   1742 	group = EC_KEY_get0_group(BI);
   1743 	if (!group)
   1744 		goto fail;
   1745 
   1746 	bR = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey);
   1747 	pR = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key);
   1748 	if (!bR || !pR)
   1749 		goto fail;
   1750 	bR_bn = EC_KEY_get0_private_key(bR);
   1751 	pR_bn = EC_KEY_get0_private_key(pR);
   1752 	if (!bR_bn || !pR_bn)
   1753 		goto fail;
   1754 	if (EC_GROUP_get_order(group, q, bnctx) != 1 ||
   1755 	    BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1)
   1756 		goto fail;
   1757 	l = EC_POINT_new(group);
   1758 	if (!l ||
   1759 	    EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 ||
   1760 	    EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
   1761 						bnctx) != 1) {
   1762 		wpa_printf(MSG_ERROR,
   1763 			   "OpenSSL: failed: %s",
   1764 			   ERR_error_string(ERR_get_error(), NULL));
   1765 		goto fail;
   1766 	}
   1767 
   1768 	num_bytes = BN_num_bytes(lx);
   1769 	if ((size_t) num_bytes > auth->secret_len)
   1770 		goto fail;
   1771 	if (auth->secret_len > (size_t) num_bytes)
   1772 		offset = auth->secret_len - num_bytes;
   1773 	else
   1774 		offset = 0;
   1775 
   1776 	os_memset(auth->Lx, 0, offset);
   1777 	BN_bn2bin(lx, auth->Lx + offset);
   1778 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
   1779 	ret = 0;
   1780 fail:
   1781 	EC_POINT_clear_free(l);
   1782 	EC_KEY_free(BI);
   1783 	EC_KEY_free(bR);
   1784 	EC_KEY_free(pR);
   1785 	BN_clear_free(lx);
   1786 	BN_clear_free(sum);
   1787 	BN_free(q);
   1788 	BN_CTX_free(bnctx);
   1789 	return ret;
   1790 }
   1791 
   1792 
   1793 static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth)
   1794 {
   1795 	const EC_GROUP *group;
   1796 	EC_POINT *l = NULL, *sum = NULL;
   1797 	EC_KEY *bI = NULL, *BR = NULL, *PR = NULL;
   1798 	const EC_POINT *BR_point, *PR_point;
   1799 	BN_CTX *bnctx;
   1800 	BIGNUM *lx;
   1801 	const BIGNUM *bI_bn;
   1802 	int ret = -1;
   1803 	int num_bytes, offset;
   1804 
   1805 	/* L = bI * (BR + PR) */
   1806 
   1807 	bnctx = BN_CTX_new();
   1808 	lx = BN_new();
   1809 	if (!bnctx || !lx)
   1810 		goto fail;
   1811 	BR = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey);
   1812 	PR = EVP_PKEY_get1_EC_KEY(auth->peer_protocol_key);
   1813 	if (!BR || !PR)
   1814 		goto fail;
   1815 	BR_point = EC_KEY_get0_public_key(BR);
   1816 	PR_point = EC_KEY_get0_public_key(PR);
   1817 
   1818 	bI = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey);
   1819 	if (!bI)
   1820 		goto fail;
   1821 	group = EC_KEY_get0_group(bI);
   1822 	bI_bn = EC_KEY_get0_private_key(bI);
   1823 	if (!group || !bI_bn)
   1824 		goto fail;
   1825 	sum = EC_POINT_new(group);
   1826 	l = EC_POINT_new(group);
   1827 	if (!sum || !l ||
   1828 	    EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 ||
   1829 	    EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 ||
   1830 	    EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL,
   1831 						bnctx) != 1) {
   1832 		wpa_printf(MSG_ERROR,
   1833 			   "OpenSSL: failed: %s",
   1834 			   ERR_error_string(ERR_get_error(), NULL));
   1835 		goto fail;
   1836 	}
   1837 
   1838 	num_bytes = BN_num_bytes(lx);
   1839 	if ((size_t) num_bytes > auth->secret_len)
   1840 		goto fail;
   1841 	if (auth->secret_len > (size_t) num_bytes)
   1842 		offset = auth->secret_len - num_bytes;
   1843 	else
   1844 		offset = 0;
   1845 
   1846 	os_memset(auth->Lx, 0, offset);
   1847 	BN_bn2bin(lx, auth->Lx + offset);
   1848 	wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len);
   1849 	ret = 0;
   1850 fail:
   1851 	EC_POINT_clear_free(l);
   1852 	EC_KEY_free(bI);
   1853 	EC_KEY_free(BR);
   1854 	EC_KEY_free(PR);
   1855 	BN_clear_free(lx);
   1856 	BN_CTX_free(bnctx);
   1857 	return ret;
   1858 }
   1859 
   1860 
   1861 static int dpp_auth_build_resp(struct dpp_authentication *auth)
   1862 {
   1863 	size_t nonce_len;
   1864 	EVP_PKEY_CTX *ctx = NULL;
   1865 	size_t secret_len;
   1866 	struct wpabuf *msg, *pr = NULL;
   1867 	u8 r_auth[4 + DPP_MAX_HASH_LEN];
   1868 	u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE];
   1869 #define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \
   1870 		4 + sizeof(wrapped_r_auth)
   1871 	size_t wrapped_r_auth_len;
   1872 	u8 clear[DPP_AUTH_RESP_CLEAR_LEN];
   1873 	u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE];
   1874 	u8 *pos;
   1875 	const u8 *addr[2];
   1876 	size_t len[2], siv_len, attr_len;
   1877 	u8 *attr_start, *attr_end;
   1878 
   1879 	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
   1880 
   1881 	nonce_len = auth->curve->nonce_len;
   1882 	if (random_get_bytes(auth->r_nonce, nonce_len)) {
   1883 		wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce");
   1884 		goto fail;
   1885 	}
   1886 	wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len);
   1887 
   1888 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
   1889 	if (!auth->own_protocol_key)
   1890 		goto fail;
   1891 
   1892 	pr = dpp_get_pubkey_point(auth->own_protocol_key, 0);
   1893 	if (!pr)
   1894 		goto fail;
   1895 
   1896 	/* ECDH: N = pR * PI */
   1897 	ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
   1898 	if (!ctx ||
   1899 	    EVP_PKEY_derive_init(ctx) != 1 ||
   1900 	    EVP_PKEY_derive_set_peer(ctx, auth->peer_protocol_key) != 1 ||
   1901 	    EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
   1902 	    secret_len > DPP_MAX_SHARED_SECRET_LEN ||
   1903 	    EVP_PKEY_derive(ctx, auth->Nx, &secret_len) != 1) {
   1904 		wpa_printf(MSG_ERROR,
   1905 			   "DPP: Failed to derive ECDH shared secret: %s",
   1906 			   ERR_error_string(ERR_get_error(), NULL));
   1907 		goto fail;
   1908 	}
   1909 	EVP_PKEY_CTX_free(ctx);
   1910 	ctx = NULL;
   1911 
   1912 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
   1913 			auth->Nx, auth->secret_len);
   1914 
   1915 	if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
   1916 			  auth->curve->hash_len) < 0)
   1917 		goto fail;
   1918 
   1919 	if (auth->own_bi && auth->peer_bi) {
   1920 		/* Mutual authentication */
   1921 		if (dpp_auth_derive_l_responder(auth) < 0)
   1922 			goto fail;
   1923 	}
   1924 
   1925 	if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
   1926 		goto fail;
   1927 
   1928 	/* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
   1929 	WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG);
   1930 	WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len);
   1931 	if (dpp_gen_r_auth(auth, r_auth + 4) < 0 ||
   1932 	    aes_siv_encrypt(auth->ke, auth->curve->hash_len,
   1933 			    r_auth, 4 + auth->curve->hash_len,
   1934 			    0, NULL, NULL, wrapped_r_auth) < 0)
   1935 		goto fail;
   1936 	wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE;
   1937 	wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke",
   1938 		    wrapped_r_auth, wrapped_r_auth_len);
   1939 
   1940 	/* Build DPP Authentication Response frame attributes */
   1941 	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
   1942 		4 + wpabuf_len(pr) + 4 + sizeof(wrapped_data);
   1943 	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len);
   1944 	if (!msg)
   1945 		goto fail;
   1946 	wpabuf_free(auth->resp_msg);
   1947 	auth->resp_msg = msg;
   1948 
   1949 	attr_start = wpabuf_put(msg, 0);
   1950 
   1951 	/* DPP Status */
   1952 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
   1953 	wpabuf_put_le16(msg, 1);
   1954 	wpabuf_put_u8(msg, DPP_STATUS_OK);
   1955 
   1956 	/* Responder Bootstrapping Key Hash */
   1957 	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
   1958 	wpabuf_put_le16(msg, SHA256_MAC_LEN);
   1959 	wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
   1960 
   1961 	if (auth->peer_bi) {
   1962 		/* Mutual authentication */
   1963 		/* Initiator Bootstrapping Key Hash */
   1964 		wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
   1965 		wpabuf_put_le16(msg, SHA256_MAC_LEN);
   1966 		wpabuf_put_data(msg, auth->peer_bi->pubkey_hash,
   1967 				SHA256_MAC_LEN);
   1968 	}
   1969 
   1970 	/* Responder Protocol Key */
   1971 	wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY);
   1972 	wpabuf_put_le16(msg, wpabuf_len(pr));
   1973 	wpabuf_put_buf(msg, pr);
   1974 	wpabuf_free(pr);
   1975 	pr = NULL;
   1976 
   1977 	attr_end = wpabuf_put(msg, 0);
   1978 
   1979 	/* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */
   1980 	pos = clear;
   1981 	/* R-nonce */
   1982 	WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE);
   1983 	pos += 2;
   1984 	WPA_PUT_LE16(pos, nonce_len);
   1985 	pos += 2;
   1986 	os_memcpy(pos, auth->r_nonce, nonce_len);
   1987 	pos += nonce_len;
   1988 	/* I-nonce */
   1989 	WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
   1990 	pos += 2;
   1991 	WPA_PUT_LE16(pos, nonce_len);
   1992 	pos += 2;
   1993 	os_memcpy(pos, auth->i_nonce, nonce_len);
   1994 	pos += nonce_len;
   1995 	/* R-capabilities */
   1996 	WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES);
   1997 	pos += 2;
   1998 	WPA_PUT_LE16(pos, 1);
   1999 	pos += 2;
   2000 	auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR :
   2001 		DPP_CAPAB_ENROLLEE;
   2002 	*pos++ = auth->r_capab;
   2003 	/* {R-auth}ke */
   2004 	WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA);
   2005 	pos += 2;
   2006 	WPA_PUT_LE16(pos, wrapped_r_auth_len);
   2007 	pos += 2;
   2008 	os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len);
   2009 	pos += wrapped_r_auth_len;
   2010 
   2011 	/* OUI, OUI type, Crypto Suite, DPP frame type */
   2012 	addr[0] = wpabuf_head_u8(msg) + 2;
   2013 	len[0] = 3 + 1 + 1 + 1;
   2014 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   2015 
   2016 	/* Attributes before Wrapped Data */
   2017 	addr[1] = attr_start;
   2018 	len[1] = attr_end - attr_start;
   2019 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   2020 
   2021 	siv_len = pos - clear;
   2022 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
   2023 	if (aes_siv_encrypt(auth->k2, auth->curve->hash_len, clear, siv_len,
   2024 			    2, addr, len, wrapped_data) < 0)
   2025 		goto fail;
   2026 	siv_len += AES_BLOCK_SIZE;
   2027 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   2028 		    wrapped_data, siv_len);
   2029 
   2030 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
   2031 	wpabuf_put_le16(msg, siv_len);
   2032 	wpabuf_put_data(msg, wrapped_data, siv_len);
   2033 
   2034 	wpa_hexdump_buf(MSG_DEBUG,
   2035 			"DPP: Authentication Response frame attributes", msg);
   2036 
   2037 	return 0;
   2038 
   2039 fail:
   2040 	wpabuf_free(pr);
   2041 	return -1;
   2042 }
   2043 
   2044 
   2045 static int dpp_auth_build_resp_status(struct dpp_authentication *auth,
   2046 				      enum dpp_status_error status)
   2047 {
   2048 	size_t nonce_len;
   2049 	struct wpabuf *msg;
   2050 #define DPP_AUTH_RESP_CLEAR_LEN2 4 + DPP_MAX_NONCE_LEN + 4 + 1
   2051 	u8 clear[DPP_AUTH_RESP_CLEAR_LEN2];
   2052 	u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN2 + AES_BLOCK_SIZE];
   2053 	u8 *pos;
   2054 	const u8 *addr[2];
   2055 	size_t len[2], siv_len, attr_len;
   2056 	u8 *attr_start, *attr_end;
   2057 
   2058 	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response");
   2059 
   2060 	/* Build DPP Authentication Response frame attributes */
   2061 	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + 4 + sizeof(wrapped_data);
   2062 	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len);
   2063 	if (!msg)
   2064 		goto fail;
   2065 	wpabuf_free(auth->resp_msg);
   2066 	auth->resp_msg = msg;
   2067 
   2068 	attr_start = wpabuf_put(msg, 0);
   2069 
   2070 	/* DPP Status */
   2071 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
   2072 	wpabuf_put_le16(msg, 1);
   2073 	wpabuf_put_u8(msg, status);
   2074 
   2075 	/* Responder Bootstrapping Key Hash */
   2076 	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
   2077 	wpabuf_put_le16(msg, SHA256_MAC_LEN);
   2078 	wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
   2079 
   2080 	if (auth->peer_bi) {
   2081 		/* Mutual authentication */
   2082 		/* Initiator Bootstrapping Key Hash */
   2083 		wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
   2084 		wpabuf_put_le16(msg, SHA256_MAC_LEN);
   2085 		wpabuf_put_data(msg, auth->peer_bi->pubkey_hash,
   2086 				SHA256_MAC_LEN);
   2087 	}
   2088 
   2089 	attr_end = wpabuf_put(msg, 0);
   2090 
   2091 	/* Wrapped data ({I-nonce, R-capabilities}k1) */
   2092 	pos = clear;
   2093 	/* I-nonce */
   2094 	nonce_len = auth->curve->nonce_len;
   2095 	WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE);
   2096 	pos += 2;
   2097 	WPA_PUT_LE16(pos, nonce_len);
   2098 	pos += 2;
   2099 	os_memcpy(pos, auth->i_nonce, nonce_len);
   2100 	pos += nonce_len;
   2101 	/* R-capabilities */
   2102 	WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES);
   2103 	pos += 2;
   2104 	WPA_PUT_LE16(pos, 1);
   2105 	pos += 2;
   2106 	auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR :
   2107 		DPP_CAPAB_ENROLLEE;
   2108 	*pos++ = auth->r_capab;
   2109 
   2110 	/* OUI, OUI type, Crypto Suite, DPP frame type */
   2111 	addr[0] = wpabuf_head_u8(msg) + 2;
   2112 	len[0] = 3 + 1 + 1 + 1;
   2113 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   2114 
   2115 	/* Attributes before Wrapped Data */
   2116 	addr[1] = attr_start;
   2117 	len[1] = attr_end - attr_start;
   2118 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   2119 
   2120 	siv_len = pos - clear;
   2121 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len);
   2122 	if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len,
   2123 			    2, addr, len, wrapped_data) < 0)
   2124 		goto fail;
   2125 	siv_len += AES_BLOCK_SIZE;
   2126 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   2127 		    wrapped_data, siv_len);
   2128 
   2129 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
   2130 	wpabuf_put_le16(msg, siv_len);
   2131 	wpabuf_put_data(msg, wrapped_data, siv_len);
   2132 
   2133 	wpa_hexdump_buf(MSG_DEBUG,
   2134 			"DPP: Authentication Response frame attributes", msg);
   2135 
   2136 	return 0;
   2137 
   2138 fail:
   2139 	return -1;
   2140 }
   2141 
   2142 
   2143 struct dpp_authentication *
   2144 dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
   2145 		struct dpp_bootstrap_info *peer_bi,
   2146 		struct dpp_bootstrap_info *own_bi,
   2147 		unsigned int freq, const u8 *hdr, const u8 *attr_start,
   2148 		const u8 *wrapped_data,	u16 wrapped_data_len)
   2149 {
   2150 	EVP_PKEY *pi = NULL;
   2151 	EVP_PKEY_CTX *ctx = NULL;
   2152 	size_t secret_len;
   2153 	const u8 *addr[2];
   2154 	size_t len[2];
   2155 	u8 *unwrapped = NULL;
   2156 	size_t unwrapped_len = 0;
   2157 	const u8 *i_proto, *i_nonce, *i_capab, *i_bootstrap;
   2158 	u16 i_proto_len, i_nonce_len, i_capab_len, i_bootstrap_len;
   2159 	struct dpp_authentication *auth = NULL;
   2160 	size_t attr_len;
   2161 
   2162 	if (wrapped_data_len < AES_BLOCK_SIZE)
   2163 		return NULL;
   2164 
   2165 	attr_len = wrapped_data - 4 - attr_start;
   2166 
   2167 	auth = os_zalloc(sizeof(*auth));
   2168 	if (!auth)
   2169 		goto fail;
   2170 	auth->msg_ctx = msg_ctx;
   2171 	auth->peer_bi = peer_bi;
   2172 	auth->own_bi = own_bi;
   2173 	auth->curve = own_bi->curve;
   2174 	auth->curr_freq = freq;
   2175 
   2176 	i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY,
   2177 			       &i_proto_len);
   2178 	if (!i_proto) {
   2179 		wpa_printf(MSG_DEBUG,
   2180 			   "DPP: Missing required Initiator Protocol Key attribute");
   2181 		goto fail;
   2182 	}
   2183 	wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key",
   2184 		    i_proto, i_proto_len);
   2185 
   2186 	/* M = bR * PI */
   2187 	pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len);
   2188 	if (!pi) {
   2189 		wpa_printf(MSG_DEBUG, "DPP: Invalid Initiator Protocol Key");
   2190 		goto fail;
   2191 	}
   2192 	dpp_debug_print_key("Peer (Initiator) Protocol Key", pi);
   2193 
   2194 	ctx = EVP_PKEY_CTX_new(own_bi->pubkey, NULL);
   2195 	if (!ctx ||
   2196 	    EVP_PKEY_derive_init(ctx) != 1 ||
   2197 	    EVP_PKEY_derive_set_peer(ctx, pi) != 1 ||
   2198 	    EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
   2199 	    secret_len > DPP_MAX_SHARED_SECRET_LEN ||
   2200 	    EVP_PKEY_derive(ctx, auth->Mx, &secret_len) != 1) {
   2201 		wpa_printf(MSG_ERROR,
   2202 			   "DPP: Failed to derive ECDH shared secret: %s",
   2203 			   ERR_error_string(ERR_get_error(), NULL));
   2204 		goto fail;
   2205 	}
   2206 	auth->secret_len = secret_len;
   2207 	EVP_PKEY_CTX_free(ctx);
   2208 	ctx = NULL;
   2209 
   2210 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)",
   2211 			auth->Mx, auth->secret_len);
   2212 
   2213 	if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1,
   2214 			  auth->curve->hash_len) < 0)
   2215 		goto fail;
   2216 
   2217 	addr[0] = hdr;
   2218 	len[0] = DPP_HDR_LEN;
   2219 	addr[1] = attr_start;
   2220 	len[1] = attr_len;
   2221 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   2222 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   2223 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   2224 		    wrapped_data, wrapped_data_len);
   2225 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
   2226 	unwrapped = os_malloc(unwrapped_len);
   2227 	if (!unwrapped)
   2228 		goto fail;
   2229 	if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
   2230 			    wrapped_data, wrapped_data_len,
   2231 			    2, addr, len, unwrapped) < 0) {
   2232 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
   2233 		goto fail;
   2234 	}
   2235 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
   2236 		    unwrapped, unwrapped_len);
   2237 
   2238 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
   2239 		wpa_printf(MSG_DEBUG,
   2240 			   "DPP: Invalid attribute in unwrapped data");
   2241 		goto fail;
   2242 	}
   2243 
   2244 	i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
   2245 			       &i_nonce_len);
   2246 	if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
   2247 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
   2248 		goto fail;
   2249 	}
   2250 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
   2251 	os_memcpy(auth->i_nonce, i_nonce, i_nonce_len);
   2252 
   2253 	i_capab = dpp_get_attr(unwrapped, unwrapped_len,
   2254 			       DPP_ATTR_I_CAPABILITIES,
   2255 			       &i_capab_len);
   2256 	if (!i_capab || i_capab_len < 1) {
   2257 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-capabilities");
   2258 		goto fail;
   2259 	}
   2260 	auth->i_capab = i_capab[0];
   2261 	wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab);
   2262 
   2263 	bin_clear_free(unwrapped, unwrapped_len);
   2264 	unwrapped = NULL;
   2265 
   2266 	switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) {
   2267 	case DPP_CAPAB_ENROLLEE:
   2268 		if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) {
   2269 			wpa_printf(MSG_DEBUG,
   2270 				   "DPP: Local policy does not allow Configurator role");
   2271 			goto not_compatible;
   2272 		}
   2273 		wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator");
   2274 		auth->configurator = 1;
   2275 		break;
   2276 	case DPP_CAPAB_CONFIGURATOR:
   2277 		if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) {
   2278 			wpa_printf(MSG_DEBUG,
   2279 				   "DPP: Local policy does not allow Enrollee role");
   2280 			goto not_compatible;
   2281 		}
   2282 		wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee");
   2283 		auth->configurator = 0;
   2284 		break;
   2285 	default:
   2286 		wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities");
   2287 		goto not_compatible;
   2288 	}
   2289 
   2290 	auth->peer_protocol_key = pi;
   2291 	pi = NULL;
   2292 	if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) {
   2293 		char hex[SHA256_MAC_LEN * 2 + 1];
   2294 
   2295 		wpa_printf(MSG_DEBUG,
   2296 			   "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time");
   2297 		if (dpp_auth_build_resp_status(auth,
   2298 					       DPP_STATUS_RESPONSE_PENDING) < 0)
   2299 			goto fail;
   2300 		i_bootstrap = dpp_get_attr(attr_start, attr_len,
   2301 					   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
   2302 					   &i_bootstrap_len);
   2303 		if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) {
   2304 			auth->response_pending = 1;
   2305 			os_memcpy(auth->waiting_pubkey_hash,
   2306 				  i_bootstrap, i_bootstrap_len);
   2307 			wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap,
   2308 					 i_bootstrap_len);
   2309 		} else {
   2310 			hex[0] = '\0';
   2311 		}
   2312 
   2313 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE
   2314 			"%s", hex);
   2315 		return auth;
   2316 	}
   2317 	if (dpp_auth_build_resp(auth) < 0)
   2318 		goto fail;
   2319 
   2320 	return auth;
   2321 
   2322 not_compatible:
   2323 	wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
   2324 		"i-capab=0x%02x", auth->i_capab);
   2325 	if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)
   2326 		auth->configurator = 1;
   2327 	else
   2328 		auth->configurator = 0;
   2329 	auth->peer_protocol_key = pi;
   2330 	pi = NULL;
   2331 	if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0)
   2332 		goto fail;
   2333 
   2334 	auth->remove_on_tx_status = 1;
   2335 	return auth;
   2336 fail:
   2337 	bin_clear_free(unwrapped, unwrapped_len);
   2338 	EVP_PKEY_free(pi);
   2339 	EVP_PKEY_CTX_free(ctx);
   2340 	dpp_auth_deinit(auth);
   2341 	return NULL;
   2342 }
   2343 
   2344 
   2345 int dpp_notify_new_qr_code(struct dpp_authentication *auth,
   2346 			   struct dpp_bootstrap_info *peer_bi)
   2347 {
   2348 	if (!auth || !auth->response_pending ||
   2349 	    os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash,
   2350 		      SHA256_MAC_LEN) != 0)
   2351 		return 0;
   2352 
   2353 	wpa_printf(MSG_DEBUG,
   2354 		   "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with "
   2355 		   MACSTR, MAC2STR(auth->peer_mac_addr));
   2356 	auth->peer_bi = peer_bi;
   2357 
   2358 	if (dpp_auth_build_resp(auth) < 0)
   2359 		return -1;
   2360 
   2361 	return 1;
   2362 }
   2363 
   2364 
   2365 static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth)
   2366 {
   2367 	struct wpabuf *msg;
   2368 	u8 i_auth[4 + DPP_MAX_HASH_LEN];
   2369 	size_t i_auth_len;
   2370 	const u8 *addr[2];
   2371 	size_t len[2], attr_len;
   2372 	u8 *wrapped_i_auth;
   2373 	u8 *attr_start, *attr_end;
   2374 
   2375 	wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation");
   2376 
   2377 	i_auth_len = 4 + auth->curve->hash_len;
   2378 	/* Build DPP Authentication Confirmation frame attributes */
   2379 	attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) +
   2380 		4 + i_auth_len + AES_BLOCK_SIZE;
   2381 	msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len);
   2382 	if (!msg)
   2383 		goto fail;
   2384 
   2385 	attr_start = wpabuf_put(msg, 0);
   2386 
   2387 	/* DPP Status */
   2388 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
   2389 	wpabuf_put_le16(msg, 1);
   2390 	wpabuf_put_u8(msg, DPP_STATUS_OK);
   2391 
   2392 	/* Responder Bootstrapping Key Hash */
   2393 	wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH);
   2394 	wpabuf_put_le16(msg, SHA256_MAC_LEN);
   2395 	wpabuf_put_data(msg, auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
   2396 
   2397 	if (auth->own_bi) {
   2398 		/* Mutual authentication */
   2399 		/* Initiator Bootstrapping Key Hash */
   2400 		wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH);
   2401 		wpabuf_put_le16(msg, SHA256_MAC_LEN);
   2402 		wpabuf_put_data(msg, auth->own_bi->pubkey_hash, SHA256_MAC_LEN);
   2403 	}
   2404 
   2405 	attr_end = wpabuf_put(msg, 0);
   2406 
   2407 	/* OUI, OUI type, Crypto Suite, DPP frame type */
   2408 	addr[0] = wpabuf_head_u8(msg) + 2;
   2409 	len[0] = 3 + 1 + 1 + 1;
   2410 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   2411 
   2412 	/* Attributes before Wrapped Data */
   2413 	addr[1] = attr_start;
   2414 	len[1] = attr_end - attr_start;
   2415 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   2416 
   2417 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
   2418 	wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE);
   2419 	wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE);
   2420 	/* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
   2421 	WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG);
   2422 	WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len);
   2423 	if (dpp_gen_i_auth(auth, i_auth + 4) < 0 ||
   2424 	    aes_siv_encrypt(auth->ke, auth->curve->hash_len,
   2425 			    i_auth, i_auth_len,
   2426 			    2, addr, len, wrapped_i_auth) < 0)
   2427 		goto fail;
   2428 	wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke",
   2429 		    wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE);
   2430 
   2431 	wpa_hexdump_buf(MSG_DEBUG,
   2432 			"DPP: Authentication Confirmation frame attributes",
   2433 			msg);
   2434 	dpp_auth_success(auth);
   2435 
   2436 	return msg;
   2437 
   2438 fail:
   2439 	return NULL;
   2440 }
   2441 
   2442 
   2443 static void
   2444 dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr,
   2445 			const u8 *attr_start, size_t attr_len,
   2446 			const u8 *wrapped_data, u16 wrapped_data_len,
   2447 			enum dpp_status_error status)
   2448 {
   2449 	const u8 *addr[2];
   2450 	size_t len[2];
   2451 	u8 *unwrapped = NULL;
   2452 	size_t unwrapped_len = 0;
   2453 	const u8 *i_nonce, *r_capab;
   2454 	u16 i_nonce_len, r_capab_len;
   2455 
   2456 	if (status == DPP_STATUS_NOT_COMPATIBLE) {
   2457 		wpa_printf(MSG_DEBUG,
   2458 			   "DPP: Responder reported incompatible roles");
   2459 	} else if (status == DPP_STATUS_RESPONSE_PENDING) {
   2460 		wpa_printf(MSG_DEBUG,
   2461 			   "DPP: Responder reported more time needed");
   2462 	} else {
   2463 		wpa_printf(MSG_DEBUG,
   2464 			   "DPP: Responder reported failure (status %d)",
   2465 			   status);
   2466 		return;
   2467 	}
   2468 
   2469 	addr[0] = hdr;
   2470 	len[0] = DPP_HDR_LEN;
   2471 	addr[1] = attr_start;
   2472 	len[1] = attr_len;
   2473 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   2474 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   2475 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   2476 		    wrapped_data, wrapped_data_len);
   2477 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
   2478 	unwrapped = os_malloc(unwrapped_len);
   2479 	if (!unwrapped)
   2480 		goto fail;
   2481 	if (aes_siv_decrypt(auth->k1, auth->curve->hash_len,
   2482 			    wrapped_data, wrapped_data_len,
   2483 			    2, addr, len, unwrapped) < 0) {
   2484 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
   2485 		goto fail;
   2486 	}
   2487 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
   2488 		    unwrapped, unwrapped_len);
   2489 
   2490 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
   2491 		wpa_printf(MSG_DEBUG,
   2492 			   "DPP: Invalid attribute in unwrapped data");
   2493 		goto fail;
   2494 	}
   2495 
   2496 	i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
   2497 			       &i_nonce_len);
   2498 	if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
   2499 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
   2500 		goto fail;
   2501 	}
   2502 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
   2503 	if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
   2504 		wpa_printf(MSG_DEBUG, "DPP: I-nonce mismatch");
   2505 		goto fail;
   2506 	}
   2507 
   2508 	r_capab = dpp_get_attr(unwrapped, unwrapped_len,
   2509 			       DPP_ATTR_R_CAPABILITIES,
   2510 			       &r_capab_len);
   2511 	if (!r_capab || r_capab_len < 1) {
   2512 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-capabilities");
   2513 		goto fail;
   2514 	}
   2515 	auth->r_capab = r_capab[0];
   2516 	wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
   2517 	if (status == DPP_STATUS_NOT_COMPATIBLE) {
   2518 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE
   2519 			"r-capab=0x%02x", auth->r_capab);
   2520 	} else if (status == DPP_STATUS_RESPONSE_PENDING) {
   2521 		wpa_printf(MSG_DEBUG,
   2522 			   "DPP: Continue waiting for full DPP Authentication Response");
   2523 		wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_RESPONSE_PENDING);
   2524 	}
   2525 fail:
   2526 	bin_clear_free(unwrapped, unwrapped_len);
   2527 }
   2528 
   2529 
   2530 struct wpabuf *
   2531 dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
   2532 		 const u8 *attr_start, size_t attr_len)
   2533 {
   2534 	EVP_PKEY *pr;
   2535 	EVP_PKEY_CTX *ctx = NULL;
   2536 	size_t secret_len;
   2537 	const u8 *addr[2];
   2538 	size_t len[2];
   2539 	u8 *unwrapped = NULL, *unwrapped2 = NULL;
   2540 	size_t unwrapped_len = 0, unwrapped2_len = 0;
   2541 	const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto,
   2542 		*r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth;
   2543 	u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
   2544 		r_proto_len, r_nonce_len, i_nonce_len, r_capab_len,
   2545 		wrapped2_len, r_auth_len;
   2546 	u8 r_auth2[DPP_MAX_HASH_LEN];
   2547 
   2548 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
   2549 				    &wrapped_data_len);
   2550 	if (!wrapped_data) {
   2551 		wpa_printf(MSG_DEBUG,
   2552 			   "DPP: Missing required Wrapped data attribute");
   2553 		return NULL;
   2554 	}
   2555 	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
   2556 		    wrapped_data, wrapped_data_len);
   2557 
   2558 	if (wrapped_data_len < AES_BLOCK_SIZE)
   2559 		return NULL;
   2560 
   2561 	attr_len = wrapped_data - 4 - attr_start;
   2562 
   2563 	r_bootstrap = dpp_get_attr(attr_start, attr_len,
   2564 				   DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
   2565 				   &r_bootstrap_len);
   2566 	if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
   2567 		wpa_printf(MSG_DEBUG,
   2568 			   "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
   2569 		return NULL;
   2570 	}
   2571 	wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
   2572 		    r_bootstrap, r_bootstrap_len);
   2573 	if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash,
   2574 		      SHA256_MAC_LEN) != 0) {
   2575 		wpa_hexdump(MSG_DEBUG,
   2576 			    "DPP: Expected Responder Bootstrapping Key Hash",
   2577 			    auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
   2578 		return NULL;
   2579 	}
   2580 
   2581 	i_bootstrap = dpp_get_attr(attr_start, attr_len,
   2582 				   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
   2583 				   &i_bootstrap_len);
   2584 	if (i_bootstrap) {
   2585 		if (i_bootstrap_len != SHA256_MAC_LEN) {
   2586 			wpa_printf(MSG_DEBUG,
   2587 				   "DPP: Invalid Initiator Bootstrapping Key Hash attribute");
   2588 			return NULL;
   2589 		}
   2590 		wpa_hexdump(MSG_MSGDUMP,
   2591 			    "DPP: Initiator Bootstrapping Key Hash",
   2592 			    i_bootstrap, i_bootstrap_len);
   2593 		if (!auth->own_bi ||
   2594 		    os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash,
   2595 			      SHA256_MAC_LEN) != 0) {
   2596 			wpa_printf(MSG_DEBUG,
   2597 				   "DPP: Initiator Bootstrapping Key Hash attribute did not match");
   2598 			return NULL;
   2599 		}
   2600 	}
   2601 
   2602 	status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
   2603 			      &status_len);
   2604 	if (!status || status_len < 1) {
   2605 		wpa_printf(MSG_DEBUG,
   2606 			   "DPP: Missing or invalid required DPP Status attribute");
   2607 		return NULL;
   2608 	}
   2609 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
   2610 	auth->auth_resp_status = status[0];
   2611 	if (status[0] != DPP_STATUS_OK) {
   2612 		dpp_auth_resp_rx_status(auth, hdr, attr_start,
   2613 					attr_len, wrapped_data,
   2614 					wrapped_data_len, status[0]);
   2615 		return NULL;
   2616 	}
   2617 
   2618 	r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY,
   2619 			       &r_proto_len);
   2620 	if (!r_proto) {
   2621 		wpa_printf(MSG_DEBUG,
   2622 			   "DPP: Missing required Responder Protocol Key attribute");
   2623 		return NULL;
   2624 	}
   2625 	wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key",
   2626 		    r_proto, r_proto_len);
   2627 
   2628 	/* N = pI * PR */
   2629 	pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len);
   2630 	if (!pr) {
   2631 		wpa_printf(MSG_DEBUG, "DPP: Invalid Responder Protocol Key");
   2632 		return NULL;
   2633 	}
   2634 	dpp_debug_print_key("Peer (Responder) Protocol Key", pr);
   2635 
   2636 	ctx = EVP_PKEY_CTX_new(auth->own_protocol_key, NULL);
   2637 	if (!ctx ||
   2638 	    EVP_PKEY_derive_init(ctx) != 1 ||
   2639 	    EVP_PKEY_derive_set_peer(ctx, pr) != 1 ||
   2640 	    EVP_PKEY_derive(ctx, NULL, &secret_len) != 1 ||
   2641 	    secret_len > DPP_MAX_SHARED_SECRET_LEN ||
   2642 	    EVP_PKEY_derive(ctx, auth->Nx, &secret_len) != 1) {
   2643 		wpa_printf(MSG_ERROR,
   2644 			   "DPP: Failed to derive ECDH shared secret: %s",
   2645 			   ERR_error_string(ERR_get_error(), NULL));
   2646 		goto fail;
   2647 	}
   2648 	EVP_PKEY_CTX_free(ctx);
   2649 	ctx = NULL;
   2650 	auth->peer_protocol_key = pr;
   2651 	pr = NULL;
   2652 
   2653 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
   2654 			auth->Nx, auth->secret_len);
   2655 
   2656 	if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2,
   2657 			  auth->curve->hash_len) < 0)
   2658 		goto fail;
   2659 
   2660 	addr[0] = hdr;
   2661 	len[0] = DPP_HDR_LEN;
   2662 	addr[1] = attr_start;
   2663 	len[1] = attr_len;
   2664 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   2665 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   2666 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   2667 		    wrapped_data, wrapped_data_len);
   2668 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
   2669 	unwrapped = os_malloc(unwrapped_len);
   2670 	if (!unwrapped)
   2671 		goto fail;
   2672 	if (aes_siv_decrypt(auth->k2, auth->curve->hash_len,
   2673 			    wrapped_data, wrapped_data_len,
   2674 			    2, addr, len, unwrapped) < 0) {
   2675 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
   2676 		goto fail;
   2677 	}
   2678 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
   2679 		    unwrapped, unwrapped_len);
   2680 
   2681 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
   2682 		wpa_printf(MSG_DEBUG,
   2683 			   "DPP: Invalid attribute in unwrapped data");
   2684 		goto fail;
   2685 	}
   2686 
   2687 	r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE,
   2688 			       &r_nonce_len);
   2689 	if (!r_nonce || r_nonce_len != auth->curve->nonce_len) {
   2690 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-nonce");
   2691 		goto fail;
   2692 	}
   2693 	wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len);
   2694 	os_memcpy(auth->r_nonce, r_nonce, r_nonce_len);
   2695 
   2696 	i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE,
   2697 			       &i_nonce_len);
   2698 	if (!i_nonce || i_nonce_len != auth->curve->nonce_len) {
   2699 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid I-nonce");
   2700 		goto fail;
   2701 	}
   2702 	wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len);
   2703 	if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) {
   2704 		wpa_printf(MSG_DEBUG, "DPP: I-nonce mismatch");
   2705 		goto fail;
   2706 	}
   2707 
   2708 	if (auth->own_bi && auth->peer_bi) {
   2709 		/* Mutual authentication */
   2710 		if (dpp_auth_derive_l_initiator(auth) < 0)
   2711 			goto fail;
   2712 	}
   2713 
   2714 	if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0)
   2715 		goto fail;
   2716 
   2717 	r_capab = dpp_get_attr(unwrapped, unwrapped_len,
   2718 			       DPP_ATTR_R_CAPABILITIES,
   2719 			       &r_capab_len);
   2720 	if (!r_capab || r_capab_len < 1) {
   2721 		wpa_printf(MSG_DEBUG, "DPP: Missing or invalid R-capabilities");
   2722 		goto fail;
   2723 	}
   2724 	auth->r_capab = r_capab[0];
   2725 	wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab);
   2726 	if ((auth->configurator && (auth->r_capab & DPP_CAPAB_CONFIGURATOR)) ||
   2727 	    (!auth->configurator && (auth->r_capab & DPP_CAPAB_ENROLLEE))) {
   2728 		wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection");
   2729 		goto fail;
   2730 	}
   2731 
   2732 	wrapped2 = dpp_get_attr(unwrapped, unwrapped_len,
   2733 				DPP_ATTR_WRAPPED_DATA, &wrapped2_len);
   2734 	if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) {
   2735 		wpa_printf(MSG_DEBUG,
   2736 			   "DPP: Missing or invalid Secondary Wrapped Data");
   2737 		goto fail;
   2738 	}
   2739 
   2740 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   2741 		    wrapped2, wrapped2_len);
   2742 	unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE;
   2743 	unwrapped2 = os_malloc(unwrapped2_len);
   2744 	if (!unwrapped2)
   2745 		goto fail;
   2746 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
   2747 			    wrapped2, wrapped2_len,
   2748 			    0, NULL, NULL, unwrapped2) < 0) {
   2749 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
   2750 		goto fail;
   2751 	}
   2752 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
   2753 		    unwrapped2, unwrapped2_len);
   2754 
   2755 	if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) {
   2756 		wpa_printf(MSG_DEBUG,
   2757 			   "DPP: Invalid attribute in secondary unwrapped data");
   2758 		goto fail;
   2759 	}
   2760 
   2761 	r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG,
   2762 			       &r_auth_len);
   2763 	if (!r_auth || r_auth_len != auth->curve->hash_len) {
   2764 		wpa_printf(MSG_DEBUG,
   2765 			   "DPP: Missing or invalid Responder Authenticating Tag");
   2766 		goto fail;
   2767 	}
   2768 	wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag",
   2769 		    r_auth, r_auth_len);
   2770 	/* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */
   2771 	if (dpp_gen_r_auth(auth, r_auth2) < 0)
   2772 		goto fail;
   2773 	wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag",
   2774 		    r_auth2, r_auth_len);
   2775 	if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) {
   2776 		wpa_printf(MSG_DEBUG,
   2777 			   "DPP: Mismatching Responder Authenticating Tag");
   2778 		goto fail;
   2779 	}
   2780 
   2781 	bin_clear_free(unwrapped, unwrapped_len);
   2782 	bin_clear_free(unwrapped2, unwrapped2_len);
   2783 
   2784 	return dpp_auth_build_conf(auth);
   2785 
   2786 fail:
   2787 	bin_clear_free(unwrapped, unwrapped_len);
   2788 	bin_clear_free(unwrapped2, unwrapped2_len);
   2789 	EVP_PKEY_free(pr);
   2790 	EVP_PKEY_CTX_free(ctx);
   2791 	return NULL;
   2792 }
   2793 
   2794 
   2795 int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
   2796 		     const u8 *attr_start, size_t attr_len)
   2797 {
   2798 	const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth;
   2799 	u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len,
   2800 		i_auth_len;
   2801 	const u8 *addr[2];
   2802 	size_t len[2];
   2803 	u8 *unwrapped = NULL;
   2804 	size_t unwrapped_len = 0;
   2805 	u8 i_auth2[DPP_MAX_HASH_LEN];
   2806 
   2807 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
   2808 				    &wrapped_data_len);
   2809 	if (!wrapped_data) {
   2810 		wpa_printf(MSG_DEBUG,
   2811 			   "DPP: Missing required Wrapped data attribute");
   2812 		return -1;
   2813 	}
   2814 	wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data",
   2815 		    wrapped_data, wrapped_data_len);
   2816 
   2817 	if (wrapped_data_len < AES_BLOCK_SIZE)
   2818 		return -1;
   2819 
   2820 	attr_len = wrapped_data - 4 - attr_start;
   2821 
   2822 	r_bootstrap = dpp_get_attr(attr_start, attr_len,
   2823 				   DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
   2824 				   &r_bootstrap_len);
   2825 	if (!r_bootstrap || r_bootstrap > wrapped_data ||
   2826 	    r_bootstrap_len != SHA256_MAC_LEN) {
   2827 		wpa_printf(MSG_DEBUG,
   2828 			   "DPP: Missing or invalid required Responder Bootstrapping Key Hash attribute");
   2829 		return -1;
   2830 	}
   2831 	wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash",
   2832 		    r_bootstrap, r_bootstrap_len);
   2833 	if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash,
   2834 		      SHA256_MAC_LEN) != 0) {
   2835 		wpa_hexdump(MSG_DEBUG,
   2836 			    "DPP: Expected Responder Bootstrapping Key Hash",
   2837 			    auth->peer_bi->pubkey_hash, SHA256_MAC_LEN);
   2838 		return -1;
   2839 	}
   2840 
   2841 	i_bootstrap = dpp_get_attr(attr_start, attr_len,
   2842 				   DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
   2843 				   &i_bootstrap_len);
   2844 	if (i_bootstrap) {
   2845 		if (i_bootstrap > wrapped_data ||
   2846 		    i_bootstrap_len != SHA256_MAC_LEN) {
   2847 			wpa_printf(MSG_DEBUG,
   2848 				   "DPP: Invalid Initiator Bootstrapping Key Hash attribute");
   2849 			return -1;
   2850 		}
   2851 		wpa_hexdump(MSG_MSGDUMP,
   2852 			    "DPP: Initiator Bootstrapping Key Hash",
   2853 			    i_bootstrap, i_bootstrap_len);
   2854 		if (!auth->peer_bi ||
   2855 		    os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash,
   2856 			      SHA256_MAC_LEN) != 0) {
   2857 			wpa_printf(MSG_DEBUG,
   2858 				   "DPP: Initiator Bootstrapping Key Hash attribute did not match");
   2859 			return -1;
   2860 		}
   2861 	}
   2862 
   2863 	status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS,
   2864 			      &status_len);
   2865 	if (!status || status_len < 1) {
   2866 		wpa_printf(MSG_DEBUG,
   2867 			   "DPP: Missing or invalid required DPP Status attribute");
   2868 		return -1;
   2869 	}
   2870 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
   2871 	if (status[0] != DPP_STATUS_OK) {
   2872 		wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
   2873 		return -1;
   2874 	}
   2875 
   2876 	addr[0] = hdr;
   2877 	len[0] = DPP_HDR_LEN;
   2878 	addr[1] = attr_start;
   2879 	len[1] = attr_len;
   2880 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   2881 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   2882 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   2883 		    wrapped_data, wrapped_data_len);
   2884 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
   2885 	unwrapped = os_malloc(unwrapped_len);
   2886 	if (!unwrapped)
   2887 		return -1;
   2888 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
   2889 			    wrapped_data, wrapped_data_len,
   2890 			    2, addr, len, unwrapped) < 0) {
   2891 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
   2892 		goto fail;
   2893 	}
   2894 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
   2895 		    unwrapped, unwrapped_len);
   2896 
   2897 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
   2898 		wpa_printf(MSG_DEBUG,
   2899 			   "DPP: Invalid attribute in unwrapped data");
   2900 		goto fail;
   2901 	}
   2902 
   2903 	i_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
   2904 			      &i_auth_len);
   2905 	if (!i_auth || i_auth_len != auth->curve->hash_len) {
   2906 		wpa_printf(MSG_DEBUG,
   2907 			   "DPP: Missing or invalid Initiator Authenticating Tag");
   2908 		goto fail;
   2909 	}
   2910 	wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag",
   2911 		    i_auth, i_auth_len);
   2912 	/* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */
   2913 	if (dpp_gen_i_auth(auth, i_auth2) < 0)
   2914 		goto fail;
   2915 	wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag",
   2916 		    i_auth2, i_auth_len);
   2917 	if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) {
   2918 		wpa_printf(MSG_DEBUG,
   2919 			   "DPP: Mismatching Initiator Authenticating Tag");
   2920 		goto fail;
   2921 	}
   2922 
   2923 	bin_clear_free(unwrapped, unwrapped_len);
   2924 	dpp_auth_success(auth);
   2925 	return 0;
   2926 fail:
   2927 	bin_clear_free(unwrapped, unwrapped_len);
   2928 	return -1;
   2929 }
   2930 
   2931 
   2932 void dpp_configuration_free(struct dpp_configuration *conf)
   2933 {
   2934 	if (!conf)
   2935 		return;
   2936 	str_clear_free(conf->passphrase);
   2937 	bin_clear_free(conf, sizeof(*conf));
   2938 }
   2939 
   2940 
   2941 void dpp_auth_deinit(struct dpp_authentication *auth)
   2942 {
   2943 	if (!auth)
   2944 		return;
   2945 	dpp_configuration_free(auth->conf_ap);
   2946 	dpp_configuration_free(auth->conf_sta);
   2947 	EVP_PKEY_free(auth->own_protocol_key);
   2948 	EVP_PKEY_free(auth->peer_protocol_key);
   2949 	wpabuf_free(auth->req_msg);
   2950 	wpabuf_free(auth->resp_msg);
   2951 	wpabuf_free(auth->conf_req);
   2952 	os_free(auth->connector);
   2953 	wpabuf_free(auth->net_access_key);
   2954 	wpabuf_free(auth->c_sign_key);
   2955 #ifdef CONFIG_TESTING_OPTIONS
   2956 	os_free(auth->config_obj_override);
   2957 	os_free(auth->discovery_override);
   2958 	os_free(auth->groups_override);
   2959 #endif /* CONFIG_TESTING_OPTIONS */
   2960 	bin_clear_free(auth, sizeof(*auth));
   2961 }
   2962 
   2963 
   2964 static struct wpabuf *
   2965 dpp_build_conf_start(struct dpp_authentication *auth,
   2966 		     struct dpp_configuration *conf, size_t tailroom)
   2967 {
   2968 	struct wpabuf *buf;
   2969 	char ssid[6 * sizeof(conf->ssid) + 1];
   2970 
   2971 #ifdef CONFIG_TESTING_OPTIONS
   2972 	if (auth->discovery_override)
   2973 		tailroom += os_strlen(auth->discovery_override);
   2974 #endif /* CONFIG_TESTING_OPTIONS */
   2975 
   2976 	buf = wpabuf_alloc(200 + tailroom);
   2977 	if (!buf)
   2978 		return NULL;
   2979 	wpabuf_put_str(buf, "{\"wi-fi_tech\":\"infra\",\"discovery\":");
   2980 #ifdef CONFIG_TESTING_OPTIONS
   2981 	if (auth->discovery_override) {
   2982 		wpa_printf(MSG_DEBUG, "DPP: TESTING - discovery override: '%s'",
   2983 			   auth->discovery_override);
   2984 		wpabuf_put_str(buf, auth->discovery_override);
   2985 		wpabuf_put_u8(buf, ',');
   2986 		return buf;
   2987 	}
   2988 #endif /* CONFIG_TESTING_OPTIONS */
   2989 	wpabuf_put_str(buf, "{\"ssid\":\"");
   2990 	json_escape_string(ssid, sizeof(ssid),
   2991 			   (const char *) conf->ssid, conf->ssid_len);
   2992 	wpabuf_put_str(buf, ssid);
   2993 	wpabuf_put_str(buf, "\"");
   2994 	/* TODO: optional channel information */
   2995 	wpabuf_put_str(buf, "},");
   2996 
   2997 	return buf;
   2998 }
   2999 
   3000 
   3001 static int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len)
   3002 {
   3003 	int num_bytes, offset;
   3004 
   3005 	num_bytes = BN_num_bytes(bn);
   3006 	if ((size_t) num_bytes > len)
   3007 		return -1;
   3008 	offset = len - num_bytes;
   3009 	os_memset(pos, 0, offset);
   3010 	BN_bn2bin(bn, pos + offset);
   3011 	return 0;
   3012 }
   3013 
   3014 
   3015 static int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key,
   3016 			 const char *kid, const struct dpp_curve_params *curve)
   3017 {
   3018 	struct wpabuf *pub;
   3019 	const u8 *pos;
   3020 	char *x = NULL, *y = NULL;
   3021 	int ret = -1;
   3022 
   3023 	pub = dpp_get_pubkey_point(key, 0);
   3024 	if (!pub)
   3025 		goto fail;
   3026 	pos = wpabuf_head(pub);
   3027 	x = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0);
   3028 	pos += curve->prime_len;
   3029 	y = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0);
   3030 	if (!x || !y)
   3031 		goto fail;
   3032 
   3033 	wpabuf_put_str(buf, "\"");
   3034 	wpabuf_put_str(buf, name);
   3035 	wpabuf_put_str(buf, "\":{\"kty\":\"EC\",\"crv\":\"");
   3036 	wpabuf_put_str(buf, curve->jwk_crv);
   3037 	wpabuf_put_str(buf, "\",\"x\":\"");
   3038 	wpabuf_put_str(buf, x);
   3039 	wpabuf_put_str(buf, "\",\"y\":\"");
   3040 	wpabuf_put_str(buf, y);
   3041 	if (kid) {
   3042 		wpabuf_put_str(buf, "\",\"kid\":\"");
   3043 		wpabuf_put_str(buf, kid);
   3044 	}
   3045 	wpabuf_put_str(buf, "\"}");
   3046 	ret = 0;
   3047 fail:
   3048 	wpabuf_free(pub);
   3049 	os_free(x);
   3050 	os_free(y);
   3051 	return ret;
   3052 }
   3053 
   3054 
   3055 static struct wpabuf *
   3056 dpp_build_conf_obj_dpp(struct dpp_authentication *auth, int ap,
   3057 		       struct dpp_configuration *conf)
   3058 {
   3059 	struct wpabuf *buf = NULL;
   3060 	char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL;
   3061 	size_t tailroom;
   3062 	const struct dpp_curve_params *curve;
   3063 	char jws_prot_hdr[100];
   3064 	size_t signed1_len, signed2_len, signed3_len;
   3065 	struct wpabuf *dppcon = NULL;
   3066 	unsigned char *signature = NULL;
   3067 	const unsigned char *p;
   3068 	size_t signature_len;
   3069 	EVP_MD_CTX *md_ctx = NULL;
   3070 	ECDSA_SIG *sig = NULL;
   3071 	char *dot = ".";
   3072 	const EVP_MD *sign_md;
   3073 	const BIGNUM *r, *s;
   3074 	size_t extra_len = 1000;
   3075 
   3076 	if (!auth->conf) {
   3077 		wpa_printf(MSG_INFO,
   3078 			   "DPP: No configurator specified - cannot generate DPP config object");
   3079 		goto fail;
   3080 	}
   3081 	curve = auth->conf->curve;
   3082 	if (curve->hash_len == SHA256_MAC_LEN) {
   3083 		sign_md = EVP_sha256();
   3084 	} else if (curve->hash_len == SHA384_MAC_LEN) {
   3085 		sign_md = EVP_sha384();
   3086 	} else if (curve->hash_len == SHA512_MAC_LEN) {
   3087 		sign_md = EVP_sha512();
   3088 	} else {
   3089 		wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
   3090 		goto fail;
   3091 	}
   3092 
   3093 #ifdef CONFIG_TESTING_OPTIONS
   3094 	if (auth->groups_override)
   3095 		extra_len += os_strlen(auth->groups_override);
   3096 #endif /* CONFIG_TESTING_OPTIONS */
   3097 
   3098 	/* Connector (JSON dppCon object) */
   3099 	dppcon = wpabuf_alloc(extra_len + 2 * auth->curve->prime_len * 4 / 3);
   3100 	if (!dppcon)
   3101 		goto fail;
   3102 #ifdef CONFIG_TESTING_OPTIONS
   3103 	if (auth->groups_override) {
   3104 		wpabuf_put_u8(dppcon, '{');
   3105 		if (auth->groups_override) {
   3106 			wpa_printf(MSG_DEBUG,
   3107 				   "DPP: TESTING - groups override: '%s'",
   3108 				   auth->groups_override);
   3109 			wpabuf_put_str(dppcon, "\"groups\":");
   3110 			wpabuf_put_str(dppcon, auth->groups_override);
   3111 			wpabuf_put_u8(dppcon, ',');
   3112 		}
   3113 		goto skip_groups;
   3114 	}
   3115 #endif /* CONFIG_TESTING_OPTIONS */
   3116 	wpabuf_put_str(dppcon, "{\"groups\":[{\"groupId\":\"*\",");
   3117 	wpabuf_printf(dppcon, "\"netRole\":\"%s\"}],", ap ? "ap" : "sta");
   3118 #ifdef CONFIG_TESTING_OPTIONS
   3119 skip_groups:
   3120 #endif /* CONFIG_TESTING_OPTIONS */
   3121 	if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL,
   3122 			  auth->curve) < 0) {
   3123 		wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK");
   3124 		goto fail;
   3125 	}
   3126 	if (conf->netaccesskey_expiry) {
   3127 		struct os_tm tm;
   3128 
   3129 		if (os_gmtime(conf->netaccesskey_expiry, &tm) < 0) {
   3130 			wpa_printf(MSG_DEBUG,
   3131 				   "DPP: Failed to generate expiry string");
   3132 			goto fail;
   3133 		}
   3134 		wpabuf_printf(dppcon,
   3135 			      ",\"expiry\":\"%04u-%02u-%02uT%02u:%02u:%02uZ\"",
   3136 			      tm.year, tm.month, tm.day,
   3137 			      tm.hour, tm.min, tm.sec);
   3138 	}
   3139 	wpabuf_put_u8(dppcon, '}');
   3140 	wpa_printf(MSG_DEBUG, "DPP: dppCon: %s",
   3141 		   (const char *) wpabuf_head(dppcon));
   3142 
   3143 	os_snprintf(jws_prot_hdr, sizeof(jws_prot_hdr),
   3144 		    "{\"typ\":\"dppCon\",\"kid\":\"%s\",\"alg\":\"%s\"}",
   3145 		    auth->conf->kid, curve->jws_alg);
   3146 	signed1 = (char *) base64_url_encode((unsigned char *) jws_prot_hdr,
   3147 					     os_strlen(jws_prot_hdr),
   3148 					     &signed1_len, 0);
   3149 	signed2 = (char *) base64_url_encode(wpabuf_head(dppcon),
   3150 					     wpabuf_len(dppcon),
   3151 					     &signed2_len, 0);
   3152 	if (!signed1 || !signed2)
   3153 		goto fail;
   3154 
   3155 	md_ctx = EVP_MD_CTX_create();
   3156 	if (!md_ctx)
   3157 		goto fail;
   3158 
   3159 	ERR_clear_error();
   3160 	if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL,
   3161 			       auth->conf->csign) != 1) {
   3162 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s",
   3163 			   ERR_error_string(ERR_get_error(), NULL));
   3164 		goto fail;
   3165 	}
   3166 	if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 ||
   3167 	    EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 ||
   3168 	    EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) {
   3169 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s",
   3170 			   ERR_error_string(ERR_get_error(), NULL));
   3171 		goto fail;
   3172 	}
   3173 	if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) {
   3174 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
   3175 			   ERR_error_string(ERR_get_error(), NULL));
   3176 		goto fail;
   3177 	}
   3178 	signature = os_malloc(signature_len);
   3179 	if (!signature)
   3180 		goto fail;
   3181 	if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) {
   3182 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s",
   3183 			   ERR_error_string(ERR_get_error(), NULL));
   3184 		goto fail;
   3185 	}
   3186 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)",
   3187 		    signature, signature_len);
   3188 	/* Convert to raw coordinates r,s */
   3189 	p = signature;
   3190 	sig = d2i_ECDSA_SIG(NULL, &p, signature_len);
   3191 	if (!sig)
   3192 		goto fail;
   3193 	ECDSA_SIG_get0(sig, &r, &s);
   3194 	if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 ||
   3195 	    dpp_bn2bin_pad(s, signature + curve->prime_len,
   3196 			   curve->prime_len) < 0)
   3197 		goto fail;
   3198 	signature_len = 2 * curve->prime_len;
   3199 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)",
   3200 		    signature, signature_len);
   3201 	signed3 = (char *) base64_url_encode(signature, signature_len,
   3202 					     &signed3_len, 0);
   3203 	if (!signed3)
   3204 		goto fail;
   3205 
   3206 	tailroom = 1000;
   3207 	tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid);
   3208 	tailroom += signed1_len + signed2_len + signed3_len;
   3209 	buf = dpp_build_conf_start(auth, conf, tailroom);
   3210 	if (!buf)
   3211 		return NULL;
   3212 
   3213 	wpabuf_put_str(buf, "\"cred\":{\"akm\":\"dpp\",\"signedConnector\":\"");
   3214 	wpabuf_put_str(buf, signed1);
   3215 	wpabuf_put_u8(buf, '.');
   3216 	wpabuf_put_str(buf, signed2);
   3217 	wpabuf_put_u8(buf, '.');
   3218 	wpabuf_put_str(buf, signed3);
   3219 	wpabuf_put_str(buf, "\",");
   3220 	if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid,
   3221 			  curve) < 0) {
   3222 		wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK");
   3223 		goto fail;
   3224 	}
   3225 
   3226 	wpabuf_put_str(buf, "}}");
   3227 
   3228 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object",
   3229 			      wpabuf_head(buf), wpabuf_len(buf));
   3230 
   3231 out:
   3232 	EVP_MD_CTX_destroy(md_ctx);
   3233 	ECDSA_SIG_free(sig);
   3234 	os_free(signed1);
   3235 	os_free(signed2);
   3236 	os_free(signed3);
   3237 	os_free(signature);
   3238 	wpabuf_free(dppcon);
   3239 	return buf;
   3240 fail:
   3241 	wpa_printf(MSG_DEBUG, "DPP: Failed to build configuration object");
   3242 	wpabuf_free(buf);
   3243 	buf = NULL;
   3244 	goto out;
   3245 }
   3246 
   3247 
   3248 static struct wpabuf *
   3249 dpp_build_conf_obj_legacy(struct dpp_authentication *auth, int ap,
   3250 			  struct dpp_configuration *conf)
   3251 {
   3252 	struct wpabuf *buf;
   3253 
   3254 	buf = dpp_build_conf_start(auth, conf, 1000);
   3255 	if (!buf)
   3256 		return NULL;
   3257 
   3258 	wpabuf_put_str(buf, "\"cred\":{\"akm\":\"psk\",");
   3259 	if (conf->passphrase) {
   3260 		char pass[63 * 6 + 1];
   3261 
   3262 		if (os_strlen(conf->passphrase) > 63) {
   3263 			wpabuf_free(buf);
   3264 			return NULL;
   3265 		}
   3266 
   3267 		json_escape_string(pass, sizeof(pass), conf->passphrase,
   3268 				   os_strlen(conf->passphrase));
   3269 		wpabuf_put_str(buf, "\"pass\":\"");
   3270 		wpabuf_put_str(buf, pass);
   3271 		wpabuf_put_str(buf, "\"");
   3272 	} else {
   3273 		char psk[2 * sizeof(conf->psk) + 1];
   3274 
   3275 		wpa_snprintf_hex(psk, sizeof(psk),
   3276 				 conf->psk, sizeof(conf->psk));
   3277 		wpabuf_put_str(buf, "\"psk_hex\":\"");
   3278 		wpabuf_put_str(buf, psk);
   3279 		wpabuf_put_str(buf, "\"");
   3280 	}
   3281 	wpabuf_put_str(buf, "}}");
   3282 
   3283 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object (legacy)",
   3284 			      wpabuf_head(buf), wpabuf_len(buf));
   3285 
   3286 	return buf;
   3287 }
   3288 
   3289 
   3290 static struct wpabuf *
   3291 dpp_build_conf_obj(struct dpp_authentication *auth, int ap)
   3292 {
   3293 	struct dpp_configuration *conf;
   3294 
   3295 #ifdef CONFIG_TESTING_OPTIONS
   3296 	if (auth->config_obj_override) {
   3297 		wpa_printf(MSG_DEBUG, "DPP: Testing - Config Object override");
   3298 		return wpabuf_alloc_copy(auth->config_obj_override,
   3299 					 os_strlen(auth->config_obj_override));
   3300 	}
   3301 #endif /* CONFIG_TESTING_OPTIONS */
   3302 
   3303 	conf = ap ? auth->conf_ap : auth->conf_sta;
   3304 	if (!conf) {
   3305 		wpa_printf(MSG_DEBUG,
   3306 			   "DPP: No configuration available for Enrollee(%s) - reject configuration request",
   3307 			   ap ? "ap" : "sta");
   3308 		return NULL;
   3309 	}
   3310 
   3311 	if (conf->dpp)
   3312 		return dpp_build_conf_obj_dpp(auth, ap, conf);
   3313 	return dpp_build_conf_obj_legacy(auth, ap, conf);
   3314 }
   3315 
   3316 
   3317 static struct wpabuf *
   3318 dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
   3319 		    u16 e_nonce_len, int ap)
   3320 {
   3321 	struct wpabuf *conf;
   3322 	size_t clear_len;
   3323 	struct wpabuf *clear = NULL, *msg = NULL;
   3324 	u8 *wrapped;
   3325 	const u8 *addr[1];
   3326 	size_t len[1];
   3327 	enum dpp_status_error status;
   3328 
   3329 	conf = dpp_build_conf_obj(auth, ap);
   3330 	if (conf) {
   3331 		wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
   3332 				  wpabuf_head(conf), wpabuf_len(conf));
   3333 	}
   3334 	status = conf ? DPP_STATUS_OK : DPP_STATUS_CONFIGURE_FAILURE;
   3335 
   3336 	/* { E-nonce, configurationObject}ke */
   3337 	clear_len = 4 + e_nonce_len;
   3338 	if (conf)
   3339 		clear_len += 4 + wpabuf_len(conf);
   3340 	clear = wpabuf_alloc(clear_len);
   3341 	msg = wpabuf_alloc(4 + 1 + 4 + clear_len + AES_BLOCK_SIZE);
   3342 	if (!clear || !msg)
   3343 		goto fail;
   3344 
   3345 	/* E-nonce */
   3346 	wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE);
   3347 	wpabuf_put_le16(clear, e_nonce_len);
   3348 	wpabuf_put_data(clear, e_nonce, e_nonce_len);
   3349 
   3350 	if (conf) {
   3351 		wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ);
   3352 		wpabuf_put_le16(clear, wpabuf_len(conf));
   3353 		wpabuf_put_buf(clear, conf);
   3354 		wpabuf_free(conf);
   3355 		conf = NULL;
   3356 	}
   3357 
   3358 	/* DPP Status */
   3359 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
   3360 	wpabuf_put_le16(msg, 1);
   3361 	wpabuf_put_u8(msg, status);
   3362 
   3363 	addr[0] = wpabuf_head(msg);
   3364 	len[0] = wpabuf_len(msg);
   3365 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
   3366 
   3367 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
   3368 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
   3369 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
   3370 
   3371 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
   3372 	if (aes_siv_encrypt(auth->ke, auth->curve->hash_len,
   3373 			    wpabuf_head(clear), wpabuf_len(clear),
   3374 			    1, addr, len, wrapped) < 0)
   3375 		goto fail;
   3376 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   3377 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
   3378 	wpabuf_free(clear);
   3379 	clear = NULL;
   3380 
   3381 	wpa_hexdump_buf(MSG_DEBUG,
   3382 			"DPP: Configuration Response attributes", msg);
   3383 	return msg;
   3384 fail:
   3385 	wpabuf_free(conf);
   3386 	wpabuf_free(clear);
   3387 	wpabuf_free(msg);
   3388 	return NULL;
   3389 }
   3390 
   3391 
   3392 struct wpabuf *
   3393 dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
   3394 		size_t attr_len)
   3395 {
   3396 	const u8 *wrapped_data, *e_nonce, *config_attr;
   3397 	u16 wrapped_data_len, e_nonce_len, config_attr_len;
   3398 	u8 *unwrapped = NULL;
   3399 	size_t unwrapped_len = 0;
   3400 	struct wpabuf *resp = NULL;
   3401 	struct json_token *root = NULL, *token;
   3402 	int ap;
   3403 
   3404 	if (dpp_check_attrs(attr_start, attr_len) < 0) {
   3405 		wpa_printf(MSG_DEBUG,
   3406 			   "DPP: Invalid attribute in config request");
   3407 		return NULL;
   3408 	}
   3409 
   3410 	wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA,
   3411 				    &wrapped_data_len);
   3412 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
   3413 		wpa_printf(MSG_DEBUG,
   3414 			   "DPP: Missing or invalid required Wrapped data attribute");
   3415 		return NULL;
   3416 	}
   3417 
   3418 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   3419 		    wrapped_data, wrapped_data_len);
   3420 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
   3421 	unwrapped = os_malloc(unwrapped_len);
   3422 	if (!unwrapped)
   3423 		return NULL;
   3424 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
   3425 			    wrapped_data, wrapped_data_len,
   3426 			    0, NULL, NULL, unwrapped) < 0) {
   3427 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
   3428 		goto fail;
   3429 	}
   3430 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
   3431 		    unwrapped, unwrapped_len);
   3432 
   3433 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
   3434 		wpa_printf(MSG_DEBUG,
   3435 			   "DPP: Invalid attribute in unwrapped data");
   3436 		goto fail;
   3437 	}
   3438 
   3439 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
   3440 			       DPP_ATTR_ENROLLEE_NONCE,
   3441 			       &e_nonce_len);
   3442 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
   3443 		wpa_printf(MSG_DEBUG,
   3444 			   "DPP: Missing or invalid Enrollee Nonce attribute");
   3445 		goto fail;
   3446 	}
   3447 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
   3448 
   3449 	config_attr = dpp_get_attr(unwrapped, unwrapped_len,
   3450 				   DPP_ATTR_CONFIG_ATTR_OBJ,
   3451 				   &config_attr_len);
   3452 	if (!config_attr) {
   3453 		wpa_printf(MSG_DEBUG,
   3454 			   "DPP: Missing or invalid Config Attributes attribute");
   3455 		goto fail;
   3456 	}
   3457 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Config Attributes",
   3458 			  config_attr, config_attr_len);
   3459 
   3460 	root = json_parse((const char *) config_attr, config_attr_len);
   3461 	if (!root) {
   3462 		wpa_printf(MSG_DEBUG, "DPP: Could not parse Config Attributes");
   3463 		goto fail;
   3464 	}
   3465 
   3466 	token = json_get_member(root, "name");
   3467 	if (!token || token->type != JSON_STRING) {
   3468 		wpa_printf(MSG_DEBUG, "DPP: No Config Attributes - name");
   3469 		goto fail;
   3470 	}
   3471 	wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string);
   3472 
   3473 	token = json_get_member(root, "wi-fi_tech");
   3474 	if (!token || token->type != JSON_STRING) {
   3475 		wpa_printf(MSG_DEBUG, "DPP: No Config Attributes - wi-fi_tech");
   3476 		goto fail;
   3477 	}
   3478 	wpa_printf(MSG_DEBUG, "DPP: wi-fi_tech = '%s'", token->string);
   3479 	if (os_strcmp(token->string, "infra") != 0) {
   3480 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech '%s'",
   3481 			   token->string);
   3482 		goto fail;
   3483 	}
   3484 
   3485 	token = json_get_member(root, "netRole");
   3486 	if (!token || token->type != JSON_STRING) {
   3487 		wpa_printf(MSG_DEBUG, "DPP: No Config Attributes - netRole");
   3488 		goto fail;
   3489 	}
   3490 	wpa_printf(MSG_DEBUG, "DPP: netRole = '%s'", token->string);
   3491 	if (os_strcmp(token->string, "sta") == 0) {
   3492 		ap = 0;
   3493 	} else if (os_strcmp(token->string, "ap") == 0) {
   3494 		ap = 1;
   3495 	} else {
   3496 		wpa_printf(MSG_DEBUG, "DPP: Unsupported netRole '%s'",
   3497 			   token->string);
   3498 		goto fail;
   3499 	}
   3500 
   3501 	resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, ap);
   3502 
   3503 fail:
   3504 	json_free(root);
   3505 	os_free(unwrapped);
   3506 	return resp;
   3507 }
   3508 
   3509 
   3510 static struct wpabuf *
   3511 dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve,
   3512 		       const u8 *prot_hdr, u16 prot_hdr_len,
   3513 		       const EVP_MD **ret_md)
   3514 {
   3515 	struct json_token *root, *token;
   3516 	struct wpabuf *kid = NULL;
   3517 
   3518 	root = json_parse((const char *) prot_hdr, prot_hdr_len);
   3519 	if (!root) {
   3520 		wpa_printf(MSG_DEBUG,
   3521 			   "DPP: JSON parsing failed for JWS Protected Header");
   3522 		goto fail;
   3523 	}
   3524 
   3525 	if (root->type != JSON_OBJECT) {
   3526 		wpa_printf(MSG_DEBUG,
   3527 			   "DPP: JWS Protected Header root is not an object");
   3528 		goto fail;
   3529 	}
   3530 
   3531 	token = json_get_member(root, "typ");
   3532 	if (!token || token->type != JSON_STRING) {
   3533 		wpa_printf(MSG_DEBUG, "DPP: No typ string value found");
   3534 		goto fail;
   3535 	}
   3536 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s",
   3537 		   token->string);
   3538 	if (os_strcmp(token->string, "dppCon") != 0) {
   3539 		wpa_printf(MSG_DEBUG,
   3540 			   "DPP: Unsupported JWS Protected Header typ=%s",
   3541 			   token->string);
   3542 		goto fail;
   3543 	}
   3544 
   3545 	token = json_get_member(root, "alg");
   3546 	if (!token || token->type != JSON_STRING) {
   3547 		wpa_printf(MSG_DEBUG, "DPP: No alg string value found");
   3548 		goto fail;
   3549 	}
   3550 	wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s",
   3551 		   token->string);
   3552 	if (os_strcmp(token->string, curve->jws_alg) != 0) {
   3553 		wpa_printf(MSG_DEBUG,
   3554 			   "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)",
   3555 			   token->string, curve->jws_alg);
   3556 		goto fail;
   3557 	}
   3558 	if (os_strcmp(token->string, "ES256") == 0 ||
   3559 	    os_strcmp(token->string, "BS256") == 0)
   3560 		*ret_md = EVP_sha256();
   3561 	else if (os_strcmp(token->string, "ES384") == 0 ||
   3562 		 os_strcmp(token->string, "BS384") == 0)
   3563 		*ret_md = EVP_sha384();
   3564 	else if (os_strcmp(token->string, "ES512") == 0 ||
   3565 		 os_strcmp(token->string, "BS512") == 0)
   3566 		*ret_md = EVP_sha512();
   3567 	else
   3568 		*ret_md = NULL;
   3569 	if (!*ret_md) {
   3570 		wpa_printf(MSG_DEBUG,
   3571 			   "DPP: Unsupported JWS Protected Header alg=%s",
   3572 			   token->string);
   3573 		goto fail;
   3574 	}
   3575 
   3576 	kid = json_get_member_base64url(root, "kid");
   3577 	if (!kid) {
   3578 		wpa_printf(MSG_DEBUG, "DPP: No kid string value found");
   3579 		goto fail;
   3580 	}
   3581 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)",
   3582 			kid);
   3583 
   3584 fail:
   3585 	json_free(root);
   3586 	return kid;
   3587 }
   3588 
   3589 
   3590 static int dpp_parse_cred_legacy(struct dpp_authentication *auth,
   3591 				 struct json_token *cred)
   3592 {
   3593 	struct json_token *pass, *psk_hex;
   3594 
   3595 	wpa_printf(MSG_DEBUG, "DPP: Legacy akm=psk credential");
   3596 
   3597 	pass = json_get_member(cred, "pass");
   3598 	psk_hex = json_get_member(cred, "psk_hex");
   3599 
   3600 	if (pass && pass->type == JSON_STRING) {
   3601 		size_t len = os_strlen(pass->string);
   3602 
   3603 		wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase",
   3604 				      pass->string, len);
   3605 		if (len < 8 || len > 63)
   3606 			return -1;
   3607 		os_strlcpy(auth->passphrase, pass->string,
   3608 			   sizeof(auth->passphrase));
   3609 	} else if (psk_hex && psk_hex->type == JSON_STRING) {
   3610 		if (os_strlen(psk_hex->string) != PMK_LEN * 2 ||
   3611 		    hexstr2bin(psk_hex->string, auth->psk, PMK_LEN) < 0) {
   3612 			wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding");
   3613 			return -1;
   3614 		}
   3615 		wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK",
   3616 				auth->psk, PMK_LEN);
   3617 		auth->psk_set = 1;
   3618 	} else {
   3619 		wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found");
   3620 		return -1;
   3621 	}
   3622 
   3623 	return 0;
   3624 }
   3625 
   3626 
   3627 static EVP_PKEY * dpp_parse_jwk(struct json_token *jwk,
   3628 				const struct dpp_curve_params **key_curve)
   3629 {
   3630 	struct json_token *token;
   3631 	const struct dpp_curve_params *curve;
   3632 	struct wpabuf *x = NULL, *y = NULL;
   3633 	EC_GROUP *group;
   3634 	EVP_PKEY *pkey = NULL;
   3635 
   3636 	token = json_get_member(jwk, "kty");
   3637 	if (!token || token->type != JSON_STRING) {
   3638 		wpa_printf(MSG_DEBUG, "DPP: No kty in JWK");
   3639 		goto fail;
   3640 	}
   3641 	if (os_strcmp(token->string, "EC") != 0) {
   3642 		wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s",
   3643 			   token->string);
   3644 		goto fail;
   3645 	}
   3646 
   3647 	token = json_get_member(jwk, "crv");
   3648 	if (!token || token->type != JSON_STRING) {
   3649 		wpa_printf(MSG_DEBUG, "DPP: No crv in JWK");
   3650 		goto fail;
   3651 	}
   3652 	curve = dpp_get_curve_jwk_crv(token->string);
   3653 	if (!curve) {
   3654 		wpa_printf(MSG_DEBUG, "DPP: Unsupported JWK crv '%s'",
   3655 			   token->string);
   3656 		goto fail;
   3657 	}
   3658 
   3659 	x = json_get_member_base64url(jwk, "x");
   3660 	if (!x) {
   3661 		wpa_printf(MSG_DEBUG, "DPP: No x in JWK");
   3662 		goto fail;
   3663 	}
   3664 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK x", x);
   3665 	if (wpabuf_len(x) != curve->prime_len) {
   3666 		wpa_printf(MSG_DEBUG,
   3667 			   "DPP: Unexpected JWK x length %u (expected %u for curve %s)",
   3668 			   (unsigned int) wpabuf_len(x),
   3669 			   (unsigned int) curve->prime_len, curve->name);
   3670 		goto fail;
   3671 	}
   3672 
   3673 	y = json_get_member_base64url(jwk, "y");
   3674 	if (!y) {
   3675 		wpa_printf(MSG_DEBUG, "DPP: No y in JWK");
   3676 		goto fail;
   3677 	}
   3678 	wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK y", y);
   3679 	if (wpabuf_len(y) != curve->prime_len) {
   3680 		wpa_printf(MSG_DEBUG,
   3681 			   "DPP: Unexpected JWK y length %u (expected %u for curve %s)",
   3682 			   (unsigned int) wpabuf_len(y),
   3683 			   (unsigned int) curve->prime_len, curve->name);
   3684 		goto fail;
   3685 	}
   3686 
   3687 	group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
   3688 	if (!group) {
   3689 		wpa_printf(MSG_DEBUG, "DPP: Could not prepare group for JWK");
   3690 		goto fail;
   3691 	}
   3692 
   3693 	pkey = dpp_set_pubkey_point_group(group, wpabuf_head(x), wpabuf_head(y),
   3694 					  wpabuf_len(x));
   3695 	*key_curve = curve;
   3696 
   3697 fail:
   3698 	wpabuf_free(x);
   3699 	wpabuf_free(y);
   3700 
   3701 	return pkey;
   3702 }
   3703 
   3704 
   3705 int dpp_key_expired(const char *timestamp, os_time_t *expiry)
   3706 {
   3707 	struct os_time now;
   3708 	unsigned int year, month, day, hour, min, sec;
   3709 	os_time_t utime;
   3710 	const char *pos;
   3711 
   3712 	/* ISO 8601 date and time:
   3713 	 * <date>T<time>
   3714 	 * YYYY-MM-DDTHH:MM:SSZ
   3715 	 * YYYY-MM-DDTHH:MM:SS+03:00
   3716 	 */
   3717 	if (os_strlen(timestamp) < 19) {
   3718 		wpa_printf(MSG_DEBUG,
   3719 			   "DPP: Too short timestamp - assume expired key");
   3720 		return 1;
   3721 	}
   3722 	if (sscanf(timestamp, "%04u-%02u-%02uT%02u:%02u:%02u",
   3723 		   &year, &month, &day, &hour, &min, &sec) != 6) {
   3724 		wpa_printf(MSG_DEBUG,
   3725 			   "DPP: Failed to parse expiration day - assume expired key");
   3726 		return 1;
   3727 	}
   3728 
   3729 	if (os_mktime(year, month, day, hour, min, sec, &utime) < 0) {
   3730 		wpa_printf(MSG_DEBUG,
   3731 			   "DPP: Invalid date/time information - assume expired key");
   3732 		return 1;
   3733 	}
   3734 
   3735 	pos = timestamp + 19;
   3736 	if (*pos == 'Z' || *pos == '\0') {
   3737 		/* In UTC - no need to adjust */
   3738 	} else if (*pos == '-' || *pos == '+') {
   3739 		int items;
   3740 
   3741 		/* Adjust local time to UTC */
   3742 		items = sscanf(pos + 1, "%02u:%02u", &hour, &min);
   3743 		if (items < 1) {
   3744 			wpa_printf(MSG_DEBUG,
   3745 				   "DPP: Invalid time zone designator (%s) - assume expired key",
   3746 				   pos);
   3747 			return 1;
   3748 		}
   3749 		if (*pos == '-')
   3750 			utime += 3600 * hour;
   3751 		if (*pos == '+')
   3752 			utime -= 3600 * hour;
   3753 		if (items > 1) {
   3754 			if (*pos == '-')
   3755 				utime += 60 * min;
   3756 			if (*pos == '+')
   3757 				utime -= 60 * min;
   3758 		}
   3759 	} else {
   3760 		wpa_printf(MSG_DEBUG,
   3761 			   "DPP: Invalid time zone designator (%s) - assume expired key",
   3762 			   pos);
   3763 		return 1;
   3764 	}
   3765 	if (expiry)
   3766 		*expiry = utime;
   3767 
   3768 	if (os_get_time(&now) < 0) {
   3769 		wpa_printf(MSG_DEBUG,
   3770 			   "DPP: Cannot get current time - assume expired key");
   3771 		return 1;
   3772 	}
   3773 
   3774 	if (now.sec > utime) {
   3775 		wpa_printf(MSG_DEBUG, "DPP: Key has expired (%lu < %lu)",
   3776 			   utime, now.sec);
   3777 		return 1;
   3778 	}
   3779 
   3780 	return 0;
   3781 }
   3782 
   3783 
   3784 static int dpp_parse_connector(struct dpp_authentication *auth,
   3785 			       const unsigned char *payload,
   3786 			       u16 payload_len)
   3787 {
   3788 	struct json_token *root, *groups, *netkey, *token;
   3789 	int ret = -1;
   3790 	EVP_PKEY *key = NULL;
   3791 	const struct dpp_curve_params *curve;
   3792 	unsigned int rules = 0;
   3793 
   3794 	root = json_parse((const char *) payload, payload_len);
   3795 	if (!root) {
   3796 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
   3797 		goto fail;
   3798 	}
   3799 
   3800 	groups = json_get_member(root, "groups");
   3801 	if (!groups || groups->type != JSON_ARRAY) {
   3802 		wpa_printf(MSG_DEBUG, "DPP: No groups array found");
   3803 		goto skip_groups;
   3804 	}
   3805 	for (token = groups->child; token; token = token->sibling) {
   3806 		struct json_token *id, *role;
   3807 
   3808 		id = json_get_member(token, "groupId");
   3809 		if (!id || id->type != JSON_STRING) {
   3810 			wpa_printf(MSG_DEBUG, "DPP: Missing groupId string");
   3811 			goto fail;
   3812 		}
   3813 
   3814 		role = json_get_member(token, "netRole");
   3815 		if (!role || role->type != JSON_STRING) {
   3816 			wpa_printf(MSG_DEBUG, "DPP: Missing netRole string");
   3817 			goto fail;
   3818 		}
   3819 		wpa_printf(MSG_DEBUG,
   3820 			   "DPP: connector group: groupId='%s' netRole='%s'",
   3821 			   id->string, role->string);
   3822 		rules++;
   3823 	}
   3824 skip_groups:
   3825 
   3826 	if (!rules) {
   3827 		wpa_printf(MSG_DEBUG,
   3828 			   "DPP: Connector includes no groups");
   3829 		goto fail;
   3830 	}
   3831 
   3832 	token = json_get_member(root, "expiry");
   3833 	if (!token || token->type != JSON_STRING) {
   3834 		wpa_printf(MSG_DEBUG,
   3835 			   "DPP: No expiry string found - connector does not expire");
   3836 	} else {
   3837 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
   3838 		if (dpp_key_expired(token->string,
   3839 				    &auth->net_access_key_expiry)) {
   3840 			wpa_printf(MSG_DEBUG,
   3841 				   "DPP: Connector (netAccessKey) has expired");
   3842 			goto fail;
   3843 		}
   3844 	}
   3845 
   3846 	netkey = json_get_member(root, "netAccessKey");
   3847 	if (!netkey || netkey->type != JSON_OBJECT) {
   3848 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
   3849 		goto fail;
   3850 	}
   3851 
   3852 	key = dpp_parse_jwk(netkey, &curve);
   3853 	if (!key)
   3854 		goto fail;
   3855 	dpp_debug_print_key("DPP: Received netAccessKey", key);
   3856 
   3857 	if (EVP_PKEY_cmp(key, auth->own_protocol_key) != 1) {
   3858 		wpa_printf(MSG_DEBUG,
   3859 			   "DPP: netAccessKey in connector does not match own protocol key");
   3860 #ifdef CONFIG_TESTING_OPTIONS
   3861 		if (auth->ignore_netaccesskey_mismatch) {
   3862 			wpa_printf(MSG_DEBUG,
   3863 				   "DPP: TESTING - skip netAccessKey mismatch");
   3864 		} else {
   3865 			goto fail;
   3866 		}
   3867 #else /* CONFIG_TESTING_OPTIONS */
   3868 		goto fail;
   3869 #endif /* CONFIG_TESTING_OPTIONS */
   3870 	}
   3871 
   3872 	ret = 0;
   3873 fail:
   3874 	EVP_PKEY_free(key);
   3875 	json_free(root);
   3876 	return ret;
   3877 }
   3878 
   3879 
   3880 static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash)
   3881 {
   3882 	struct wpabuf *uncomp;
   3883 	int res;
   3884 	u8 hash[SHA256_MAC_LEN];
   3885 	const u8 *addr[1];
   3886 	size_t len[1];
   3887 
   3888 	if (wpabuf_len(r_hash) != SHA256_MAC_LEN)
   3889 		return -1;
   3890 	uncomp = dpp_get_pubkey_point(pub, 1);
   3891 	if (!uncomp)
   3892 		return -1;
   3893 	addr[0] = wpabuf_head(uncomp);
   3894 	len[0] = wpabuf_len(uncomp);
   3895 	wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key",
   3896 		    addr[0], len[0]);
   3897 	res = sha256_vector(1, addr, len, hash);
   3898 	wpabuf_free(uncomp);
   3899 	if (res < 0)
   3900 		return -1;
   3901 	if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) {
   3902 		wpa_printf(MSG_DEBUG,
   3903 			   "DPP: Received hash value does not match calculated public key hash value");
   3904 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash",
   3905 			    hash, SHA256_MAC_LEN);
   3906 		return -1;
   3907 	}
   3908 	return 0;
   3909 }
   3910 
   3911 
   3912 static void dpp_copy_csign(struct dpp_authentication *auth, EVP_PKEY *csign)
   3913 {
   3914 	unsigned char *der = NULL;
   3915 	int der_len;
   3916 
   3917 	der_len = i2d_PUBKEY(csign, &der);
   3918 	if (der_len <= 0)
   3919 		return;
   3920 	wpabuf_free(auth->c_sign_key);
   3921 	auth->c_sign_key = wpabuf_alloc_copy(der, der_len);
   3922 	OPENSSL_free(der);
   3923 }
   3924 
   3925 
   3926 static void dpp_copy_netaccesskey(struct dpp_authentication *auth)
   3927 {
   3928 	unsigned char *der = NULL;
   3929 	int der_len;
   3930 	EC_KEY *eckey;
   3931 
   3932 	eckey = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key);
   3933 	if (!eckey)
   3934 		return;
   3935 
   3936 	der_len = i2d_ECPrivateKey(eckey, &der);
   3937 	if (der_len <= 0) {
   3938 		EC_KEY_free(eckey);
   3939 		return;
   3940 	}
   3941 	wpabuf_free(auth->net_access_key);
   3942 	auth->net_access_key = wpabuf_alloc_copy(der, der_len);
   3943 	OPENSSL_free(der);
   3944 	EC_KEY_free(eckey);
   3945 }
   3946 
   3947 
   3948 struct dpp_signed_connector_info {
   3949 	unsigned char *payload;
   3950 	size_t payload_len;
   3951 };
   3952 
   3953 static int
   3954 dpp_process_signed_connector(struct dpp_signed_connector_info *info,
   3955 			     EVP_PKEY *csign_pub, const char *connector)
   3956 {
   3957 	int ret = -1;
   3958 	const char *pos, *end, *signed_start, *signed_end;
   3959 	struct wpabuf *kid = NULL;
   3960 	unsigned char *prot_hdr = NULL, *signature = NULL;
   3961 	size_t prot_hdr_len = 0, signature_len = 0;
   3962 	const EVP_MD *sign_md = NULL;
   3963 	unsigned char *der = NULL;
   3964 	int der_len;
   3965 	int res;
   3966 	EVP_MD_CTX *md_ctx = NULL;
   3967 	ECDSA_SIG *sig = NULL;
   3968 	BIGNUM *r = NULL, *s = NULL;
   3969 	const struct dpp_curve_params *curve;
   3970 	EC_KEY *eckey;
   3971 	const EC_GROUP *group;
   3972 	int nid;
   3973 
   3974 	eckey = EVP_PKEY_get1_EC_KEY(csign_pub);
   3975 	if (!eckey)
   3976 		goto fail;
   3977 	group = EC_KEY_get0_group(eckey);
   3978 	if (!group)
   3979 		goto fail;
   3980 	nid = EC_GROUP_get_curve_name(group);
   3981 	curve = dpp_get_curve_nid(nid);
   3982 	if (!curve)
   3983 		goto fail;
   3984 	wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv);
   3985 	os_memset(info, 0, sizeof(*info));
   3986 
   3987 	signed_start = pos = connector;
   3988 	end = os_strchr(pos, '.');
   3989 	if (!end) {
   3990 		wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector");
   3991 		goto fail;
   3992 	}
   3993 	prot_hdr = base64_url_decode((const unsigned char *) pos,
   3994 				     end - pos, &prot_hdr_len);
   3995 	if (!prot_hdr) {
   3996 		wpa_printf(MSG_DEBUG,
   3997 			   "DPP: Failed to base64url decode signedConnector JWS Protected Header");
   3998 		goto fail;
   3999 	}
   4000 	wpa_hexdump_ascii(MSG_DEBUG,
   4001 			  "DPP: signedConnector - JWS Protected Header",
   4002 			  prot_hdr, prot_hdr_len);
   4003 	kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md);
   4004 	if (!kid)
   4005 		goto fail;
   4006 	if (wpabuf_len(kid) != SHA256_MAC_LEN) {
   4007 		wpa_printf(MSG_DEBUG,
   4008 			   "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)",
   4009 			   (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN);
   4010 		goto fail;
   4011 	}
   4012 
   4013 	pos = end + 1;
   4014 	end = os_strchr(pos, '.');
   4015 	if (!end) {
   4016 		wpa_printf(MSG_DEBUG,
   4017 			   "DPP: Missing dot(2) in signedConnector");
   4018 		goto fail;
   4019 	}
   4020 	signed_end = end - 1;
   4021 	info->payload = base64_url_decode((const unsigned char *) pos,
   4022 					  end - pos, &info->payload_len);
   4023 	if (!info->payload) {
   4024 		wpa_printf(MSG_DEBUG,
   4025 			   "DPP: Failed to base64url decode signedConnector JWS Payload");
   4026 		goto fail;
   4027 	}
   4028 	wpa_hexdump_ascii(MSG_DEBUG,
   4029 			  "DPP: signedConnector - JWS Payload",
   4030 			  info->payload, info->payload_len);
   4031 	pos = end + 1;
   4032 	signature = base64_url_decode((const unsigned char *) pos,
   4033 				      os_strlen(pos), &signature_len);
   4034 	if (!signature) {
   4035 		wpa_printf(MSG_DEBUG,
   4036 			   "DPP: Failed to base64url decode signedConnector signature");
   4037 		goto fail;
   4038 		}
   4039 	wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature",
   4040 		    signature, signature_len);
   4041 
   4042 	if (dpp_check_pubkey_match(csign_pub, kid) < 0)
   4043 		goto fail;
   4044 
   4045 	if (signature_len & 0x01) {
   4046 		wpa_printf(MSG_DEBUG,
   4047 			   "DPP: Unexpected signedConnector signature length (%d)",
   4048 			   (int) signature_len);
   4049 		goto fail;
   4050 	}
   4051 
   4052 	/* JWS Signature encodes the signature (r,s) as two octet strings. Need
   4053 	 * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */
   4054 	r = BN_bin2bn(signature, signature_len / 2, NULL);
   4055 	s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL);
   4056 	sig = ECDSA_SIG_new();
   4057 	if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1)
   4058 		goto fail;
   4059 	r = NULL;
   4060 	s = NULL;
   4061 
   4062 	der_len = i2d_ECDSA_SIG(sig, &der);
   4063 	if (der_len <= 0) {
   4064 		wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature");
   4065 		goto fail;
   4066 	}
   4067 	wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len);
   4068 	md_ctx = EVP_MD_CTX_create();
   4069 	if (!md_ctx)
   4070 		goto fail;
   4071 
   4072 	ERR_clear_error();
   4073 	if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) {
   4074 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s",
   4075 			   ERR_error_string(ERR_get_error(), NULL));
   4076 		goto fail;
   4077 	}
   4078 	if (EVP_DigestVerifyUpdate(md_ctx, signed_start,
   4079 				   signed_end - signed_start + 1) != 1) {
   4080 		wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s",
   4081 			   ERR_error_string(ERR_get_error(), NULL));
   4082 		goto fail;
   4083 	}
   4084 	res = EVP_DigestVerifyFinal(md_ctx, der, der_len);
   4085 	if (res != 1) {
   4086 		wpa_printf(MSG_DEBUG,
   4087 			   "DPP: EVP_DigestVerifyFinal failed (res=%d): %s",
   4088 			   res, ERR_error_string(ERR_get_error(), NULL));
   4089 		goto fail;
   4090 	}
   4091 
   4092 	ret = 0;
   4093 fail:
   4094 	EC_KEY_free(eckey);
   4095 	EVP_MD_CTX_destroy(md_ctx);
   4096 	os_free(prot_hdr);
   4097 	wpabuf_free(kid);
   4098 	os_free(signature);
   4099 	ECDSA_SIG_free(sig);
   4100 	BN_free(r);
   4101 	BN_free(s);
   4102 	OPENSSL_free(der);
   4103 	return ret;
   4104 }
   4105 
   4106 
   4107 static int dpp_parse_cred_dpp(struct dpp_authentication *auth,
   4108 			      struct json_token *cred)
   4109 {
   4110 	struct dpp_signed_connector_info info;
   4111 	struct json_token *token, *csign;
   4112 	int ret = -1;
   4113 	EVP_PKEY *csign_pub = NULL;
   4114 	const struct dpp_curve_params *key_curve = NULL;
   4115 	const char *signed_connector;
   4116 
   4117 	os_memset(&info, 0, sizeof(info));
   4118 
   4119 	wpa_printf(MSG_DEBUG, "DPP: Connector credential");
   4120 
   4121 	csign = json_get_member(cred, "csign");
   4122 	if (!csign || csign->type != JSON_OBJECT) {
   4123 		wpa_printf(MSG_DEBUG, "DPP: No csign JWK in JSON");
   4124 		goto fail;
   4125 	}
   4126 
   4127 	csign_pub = dpp_parse_jwk(csign, &key_curve);
   4128 	if (!csign_pub) {
   4129 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse csign JWK");
   4130 		goto fail;
   4131 	}
   4132 	dpp_debug_print_key("DPP: Received C-sign-key", csign_pub);
   4133 
   4134 	token = json_get_member(cred, "signedConnector");
   4135 	if (!token || token->type != JSON_STRING) {
   4136 		wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found");
   4137 		goto fail;
   4138 	}
   4139 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: signedConnector",
   4140 			  token->string, os_strlen(token->string));
   4141 	signed_connector = token->string;
   4142 
   4143 	if (os_strchr(signed_connector, '"') ||
   4144 	    os_strchr(signed_connector, '\n')) {
   4145 		wpa_printf(MSG_DEBUG,
   4146 			   "DPP: Unexpected character in signedConnector");
   4147 		goto fail;
   4148 	}
   4149 
   4150 	if (dpp_process_signed_connector(&info, csign_pub,
   4151 					 signed_connector) < 0)
   4152 		goto fail;
   4153 
   4154 	if (dpp_parse_connector(auth, info.payload, info.payload_len) < 0) {
   4155 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse connector");
   4156 		goto fail;
   4157 	}
   4158 
   4159 	os_free(auth->connector);
   4160 	auth->connector = os_strdup(signed_connector);
   4161 
   4162 	dpp_copy_csign(auth, csign_pub);
   4163 	dpp_copy_netaccesskey(auth);
   4164 
   4165 	ret = 0;
   4166 fail:
   4167 	EVP_PKEY_free(csign_pub);
   4168 	os_free(info.payload);
   4169 	return ret;
   4170 }
   4171 
   4172 
   4173 static int dpp_parse_conf_obj(struct dpp_authentication *auth,
   4174 			      const u8 *conf_obj, u16 conf_obj_len)
   4175 {
   4176 	int ret = -1;
   4177 	struct json_token *root, *token, *discovery, *cred;
   4178 
   4179 	root = json_parse((const char *) conf_obj, conf_obj_len);
   4180 	if (!root)
   4181 		return -1;
   4182 	if (root->type != JSON_OBJECT) {
   4183 		wpa_printf(MSG_DEBUG, "DPP: JSON root is not an object");
   4184 		goto fail;
   4185 	}
   4186 
   4187 	token = json_get_member(root, "wi-fi_tech");
   4188 	if (!token || token->type != JSON_STRING) {
   4189 		wpa_printf(MSG_DEBUG, "DPP: No wi-fi_tech string value found");
   4190 		goto fail;
   4191 	}
   4192 	if (os_strcmp(token->string, "infra") != 0) {
   4193 		wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech value: '%s'",
   4194 			   token->string);
   4195 		goto fail;
   4196 	}
   4197 
   4198 	discovery = json_get_member(root, "discovery");
   4199 	if (!discovery || discovery->type != JSON_OBJECT) {
   4200 		wpa_printf(MSG_DEBUG, "DPP: No discovery object in JSON");
   4201 		goto fail;
   4202 	}
   4203 
   4204 	token = json_get_member(discovery, "ssid");
   4205 	if (!token || token->type != JSON_STRING) {
   4206 		wpa_printf(MSG_DEBUG,
   4207 			   "DPP: No discovery::ssid string value found");
   4208 		goto fail;
   4209 	}
   4210 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: discovery::ssid",
   4211 			  token->string, os_strlen(token->string));
   4212 	if (os_strlen(token->string) > SSID_MAX_LEN) {
   4213 		wpa_printf(MSG_DEBUG,
   4214 			   "DPP: Too long discovery::ssid string value");
   4215 		goto fail;
   4216 	}
   4217 	auth->ssid_len = os_strlen(token->string);
   4218 	os_memcpy(auth->ssid, token->string, auth->ssid_len);
   4219 
   4220 	cred = json_get_member(root, "cred");
   4221 	if (!cred || cred->type != JSON_OBJECT) {
   4222 		wpa_printf(MSG_DEBUG, "DPP: No cred object in JSON");
   4223 		goto fail;
   4224 	}
   4225 
   4226 	token = json_get_member(cred, "akm");
   4227 	if (!token || token->type != JSON_STRING) {
   4228 		wpa_printf(MSG_DEBUG,
   4229 			   "DPP: No cred::akm string value found");
   4230 		goto fail;
   4231 	}
   4232 	if (os_strcmp(token->string, "psk") == 0) {
   4233 		if (dpp_parse_cred_legacy(auth, cred) < 0)
   4234 			goto fail;
   4235 	} else if (os_strcmp(token->string, "dpp") == 0) {
   4236 		if (dpp_parse_cred_dpp(auth, cred) < 0)
   4237 			goto fail;
   4238 	} else {
   4239 		wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
   4240 			   token->string);
   4241 		goto fail;
   4242 	}
   4243 
   4244 	wpa_printf(MSG_DEBUG, "DPP: JSON parsing completed successfully");
   4245 	ret = 0;
   4246 fail:
   4247 	json_free(root);
   4248 	return ret;
   4249 }
   4250 
   4251 
   4252 int dpp_conf_resp_rx(struct dpp_authentication *auth,
   4253 		     const struct wpabuf *resp)
   4254 {
   4255 	const u8 *wrapped_data, *e_nonce, *status, *conf_obj;
   4256 	u16 wrapped_data_len, e_nonce_len, status_len, conf_obj_len;
   4257 	const u8 *addr[1];
   4258 	size_t len[1];
   4259 	u8 *unwrapped = NULL;
   4260 	size_t unwrapped_len = 0;
   4261 	int ret = -1;
   4262 
   4263 	if (dpp_check_attrs(wpabuf_head(resp), wpabuf_len(resp)) < 0) {
   4264 		wpa_printf(MSG_DEBUG,
   4265 			   "DPP: Invalid attribute in config response");
   4266 		return -1;
   4267 	}
   4268 
   4269 	wrapped_data = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
   4270 				    DPP_ATTR_WRAPPED_DATA,
   4271 				    &wrapped_data_len);
   4272 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
   4273 		wpa_printf(MSG_DEBUG,
   4274 			   "DPP: Missing or invalid required Wrapped data attribute");
   4275 		return -1;
   4276 	}
   4277 
   4278 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   4279 		    wrapped_data, wrapped_data_len);
   4280 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
   4281 	unwrapped = os_malloc(unwrapped_len);
   4282 	if (!unwrapped)
   4283 		return -1;
   4284 
   4285 	addr[0] = wpabuf_head(resp);
   4286 	len[0] = wrapped_data - 4 - (const u8 *) wpabuf_head(resp);
   4287 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]);
   4288 
   4289 	if (aes_siv_decrypt(auth->ke, auth->curve->hash_len,
   4290 			    wrapped_data, wrapped_data_len,
   4291 			    1, addr, len, unwrapped) < 0) {
   4292 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
   4293 		goto fail;
   4294 	}
   4295 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
   4296 		    unwrapped, unwrapped_len);
   4297 
   4298 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
   4299 		wpa_printf(MSG_DEBUG,
   4300 			   "DPP: Invalid attribute in unwrapped data");
   4301 		goto fail;
   4302 	}
   4303 
   4304 	e_nonce = dpp_get_attr(unwrapped, unwrapped_len,
   4305 			       DPP_ATTR_ENROLLEE_NONCE,
   4306 			       &e_nonce_len);
   4307 	if (!e_nonce || e_nonce_len != auth->curve->nonce_len) {
   4308 		wpa_printf(MSG_DEBUG,
   4309 			   "DPP: Missing or invalid Enrollee Nonce attribute");
   4310 		goto fail;
   4311 	}
   4312 	wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len);
   4313 	if (os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) {
   4314 		wpa_printf(MSG_DEBUG, "Enrollee Nonce mismatch");
   4315 		goto fail;
   4316 	}
   4317 
   4318 	status = dpp_get_attr(wpabuf_head(resp), wpabuf_len(resp),
   4319 			      DPP_ATTR_STATUS, &status_len);
   4320 	if (!status || status_len < 1) {
   4321 		wpa_printf(MSG_DEBUG,
   4322 			   "DPP: Missing or invalid required DPP Status attribute");
   4323 		goto fail;
   4324 	}
   4325 	wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
   4326 	if (status[0] != DPP_STATUS_OK) {
   4327 		wpa_printf(MSG_DEBUG, "DPP: Configuration failed");
   4328 		goto fail;
   4329 	}
   4330 
   4331 	conf_obj = dpp_get_attr(unwrapped, unwrapped_len,
   4332 				DPP_ATTR_CONFIG_OBJ, &conf_obj_len);
   4333 	if (!conf_obj) {
   4334 		wpa_printf(MSG_DEBUG,
   4335 			   "DPP: Missing required Configuration Object attribute");
   4336 		goto fail;
   4337 	}
   4338 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON",
   4339 			  conf_obj, conf_obj_len);
   4340 	if (dpp_parse_conf_obj(auth, conf_obj, conf_obj_len) < 0)
   4341 		goto fail;
   4342 
   4343 	ret = 0;
   4344 
   4345 fail:
   4346 	os_free(unwrapped);
   4347 	return ret;
   4348 }
   4349 
   4350 
   4351 void dpp_configurator_free(struct dpp_configurator *conf)
   4352 {
   4353 	if (!conf)
   4354 		return;
   4355 	EVP_PKEY_free(conf->csign);
   4356 	os_free(conf->kid);
   4357 	os_free(conf);
   4358 }
   4359 
   4360 
   4361 struct dpp_configurator *
   4362 dpp_keygen_configurator(const char *curve, const u8 *privkey,
   4363 			size_t privkey_len)
   4364 {
   4365 	struct dpp_configurator *conf;
   4366 	struct wpabuf *csign_pub = NULL;
   4367 	u8 kid_hash[SHA256_MAC_LEN];
   4368 	const u8 *addr[1];
   4369 	size_t len[1];
   4370 
   4371 	conf = os_zalloc(sizeof(*conf));
   4372 	if (!conf)
   4373 		return NULL;
   4374 
   4375 	if (!curve) {
   4376 		conf->curve = &dpp_curves[0];
   4377 	} else {
   4378 		conf->curve = dpp_get_curve_name(curve);
   4379 		if (!conf->curve) {
   4380 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
   4381 				   curve);
   4382 			return NULL;
   4383 		}
   4384 	}
   4385 	if (privkey)
   4386 		conf->csign = dpp_set_keypair(&conf->curve, privkey,
   4387 					      privkey_len);
   4388 	else
   4389 		conf->csign = dpp_gen_keypair(conf->curve);
   4390 	if (!conf->csign)
   4391 		goto fail;
   4392 	conf->own = 1;
   4393 
   4394 	csign_pub = dpp_get_pubkey_point(conf->csign, 1);
   4395 	if (!csign_pub) {
   4396 		wpa_printf(MSG_INFO, "DPP: Failed to extract C-sign-key");
   4397 		goto fail;
   4398 	}
   4399 
   4400 	/* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */
   4401 	addr[0] = wpabuf_head(csign_pub);
   4402 	len[0] = wpabuf_len(csign_pub);
   4403 	if (sha256_vector(1, addr, len, kid_hash) < 0) {
   4404 		wpa_printf(MSG_DEBUG,
   4405 			   "DPP: Failed to derive kid for C-sign-key");
   4406 		goto fail;
   4407 	}
   4408 
   4409 	conf->kid = (char *) base64_url_encode(kid_hash, sizeof(kid_hash),
   4410 					       NULL, 0);
   4411 	if (!conf->kid)
   4412 		goto fail;
   4413 out:
   4414 	wpabuf_free(csign_pub);
   4415 	return conf;
   4416 fail:
   4417 	dpp_configurator_free(conf);
   4418 	conf = NULL;
   4419 	goto out;
   4420 }
   4421 
   4422 
   4423 int dpp_configurator_own_config(struct dpp_authentication *auth,
   4424 				const char *curve)
   4425 {
   4426 	struct wpabuf *conf_obj;
   4427 	int ret = -1;
   4428 
   4429 	if (!auth->conf) {
   4430 		wpa_printf(MSG_DEBUG, "DPP: No configurator specified");
   4431 		return -1;
   4432 	}
   4433 
   4434 	if (!curve) {
   4435 		auth->curve = &dpp_curves[0];
   4436 	} else {
   4437 		auth->curve = dpp_get_curve_name(curve);
   4438 		if (!auth->curve) {
   4439 			wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s",
   4440 				   curve);
   4441 			return -1;
   4442 		}
   4443 	}
   4444 	wpa_printf(MSG_DEBUG,
   4445 		   "DPP: Building own configuration/connector with curve %s",
   4446 		   auth->curve->name);
   4447 
   4448 	auth->own_protocol_key = dpp_gen_keypair(auth->curve);
   4449 	if (!auth->own_protocol_key)
   4450 		return -1;
   4451 	dpp_copy_netaccesskey(auth);
   4452 	auth->peer_protocol_key = auth->own_protocol_key;
   4453 	dpp_copy_csign(auth, auth->conf->csign);
   4454 
   4455 	conf_obj = dpp_build_conf_obj(auth, 0);
   4456 	if (!conf_obj)
   4457 		goto fail;
   4458 	ret = dpp_parse_conf_obj(auth, wpabuf_head(conf_obj),
   4459 				 wpabuf_len(conf_obj));
   4460 fail:
   4461 	wpabuf_free(conf_obj);
   4462 	auth->peer_protocol_key = NULL;
   4463 	return ret;
   4464 }
   4465 
   4466 
   4467 static int dpp_compatible_netrole(const char *role1, const char *role2)
   4468 {
   4469 	return (os_strcmp(role1, "sta") == 0 && os_strcmp(role2, "ap") == 0) ||
   4470 		(os_strcmp(role1, "ap") == 0 && os_strcmp(role2, "sta") == 0);
   4471 }
   4472 
   4473 
   4474 static int dpp_connector_compatible_group(struct json_token *root,
   4475 					  const char *group_id,
   4476 					  const char *net_role)
   4477 {
   4478 	struct json_token *groups, *token;
   4479 
   4480 	groups = json_get_member(root, "groups");
   4481 	if (!groups || groups->type != JSON_ARRAY)
   4482 		return 0;
   4483 
   4484 	for (token = groups->child; token; token = token->sibling) {
   4485 		struct json_token *id, *role;
   4486 
   4487 		id = json_get_member(token, "groupId");
   4488 		if (!id || id->type != JSON_STRING)
   4489 			continue;
   4490 
   4491 		role = json_get_member(token, "netRole");
   4492 		if (!role || role->type != JSON_STRING)
   4493 			continue;
   4494 
   4495 		if (os_strcmp(id->string, "*") != 0 &&
   4496 		    os_strcmp(group_id, "*") != 0 &&
   4497 		    os_strcmp(id->string, group_id) != 0)
   4498 			continue;
   4499 
   4500 		if (dpp_compatible_netrole(role->string, net_role))
   4501 			return 1;
   4502 	}
   4503 
   4504 	return 0;
   4505 }
   4506 
   4507 
   4508 static int dpp_connector_match_groups(struct json_token *own_root,
   4509 				      struct json_token *peer_root)
   4510 {
   4511 	struct json_token *groups, *token;
   4512 
   4513 	groups = json_get_member(peer_root, "groups");
   4514 	if (!groups || groups->type != JSON_ARRAY) {
   4515 		wpa_printf(MSG_DEBUG, "DPP: No peer groups array found");
   4516 		return 0;
   4517 	}
   4518 
   4519 	for (token = groups->child; token; token = token->sibling) {
   4520 		struct json_token *id, *role;
   4521 
   4522 		id = json_get_member(token, "groupId");
   4523 		if (!id || id->type != JSON_STRING) {
   4524 			wpa_printf(MSG_DEBUG,
   4525 				   "DPP: Missing peer groupId string");
   4526 			continue;
   4527 		}
   4528 
   4529 		role = json_get_member(token, "netRole");
   4530 		if (!role || role->type != JSON_STRING) {
   4531 			wpa_printf(MSG_DEBUG,
   4532 				   "DPP: Missing peer groups::netRole string");
   4533 			continue;
   4534 		}
   4535 		wpa_printf(MSG_DEBUG,
   4536 			   "DPP: peer connector group: groupId='%s' netRole='%s'",
   4537 			   id->string, role->string);
   4538 		if (dpp_connector_compatible_group(own_root, id->string,
   4539 						   role->string)) {
   4540 			wpa_printf(MSG_DEBUG,
   4541 				   "DPP: Compatible group/netRole in own connector");
   4542 			return 1;
   4543 		}
   4544 	}
   4545 
   4546 	return 0;
   4547 }
   4548 
   4549 
   4550 static int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk,
   4551 			  unsigned int hash_len)
   4552 {
   4553 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
   4554 	const char *info = "DPP PMK";
   4555 	int res;
   4556 
   4557 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
   4558 
   4559 	/* HKDF-Extract(<>, N.x) */
   4560 	os_memset(salt, 0, hash_len);
   4561 	if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0)
   4562 		return -1;
   4563 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)",
   4564 			prk, hash_len);
   4565 
   4566 	/* HKDF-Expand(PRK, info, L) */
   4567 	res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len);
   4568 	os_memset(prk, 0, hash_len);
   4569 	if (res < 0)
   4570 		return -1;
   4571 
   4572 	wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)",
   4573 			pmk, hash_len);
   4574 	return 0;
   4575 }
   4576 
   4577 
   4578 static int dpp_derive_pmkid(const struct dpp_curve_params *curve,
   4579 			    EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid)
   4580 {
   4581 	struct wpabuf *nkx, *pkx;
   4582 	int ret = -1, res;
   4583 	const u8 *addr[2];
   4584 	size_t len[2];
   4585 	u8 hash[SHA256_MAC_LEN];
   4586 
   4587 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
   4588 	nkx = dpp_get_pubkey_point(own_key, 0);
   4589 	pkx = dpp_get_pubkey_point(peer_key, 0);
   4590 	if (!nkx || !pkx)
   4591 		goto fail;
   4592 	addr[0] = wpabuf_head(nkx);
   4593 	len[0] = wpabuf_len(nkx) / 2;
   4594 	addr[1] = wpabuf_head(pkx);
   4595 	len[1] = wpabuf_len(pkx) / 2;
   4596 	if (len[0] != len[1])
   4597 		goto fail;
   4598 	if (os_memcmp(addr[0], addr[1], len[0]) > 0) {
   4599 		addr[0] = wpabuf_head(pkx);
   4600 		addr[1] = wpabuf_head(nkx);
   4601 	}
   4602 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]);
   4603 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]);
   4604 	res = sha256_vector(2, addr, len, hash);
   4605 	if (res < 0)
   4606 		goto fail;
   4607 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN);
   4608 	os_memcpy(pmkid, hash, PMKID_LEN);
   4609 	wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN);
   4610 	ret = 0;
   4611 fail:
   4612 	wpabuf_free(nkx);
   4613 	wpabuf_free(pkx);
   4614 	return ret;
   4615 }
   4616 
   4617 
   4618 int dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector,
   4619 		   const u8 *net_access_key, size_t net_access_key_len,
   4620 		   const u8 *csign_key, size_t csign_key_len,
   4621 		   const u8 *peer_connector, size_t peer_connector_len,
   4622 		   os_time_t *expiry)
   4623 {
   4624 	struct json_token *root = NULL, *netkey, *token;
   4625 	struct json_token *own_root = NULL;
   4626 	int ret = -1;
   4627 	EVP_PKEY *own_key = NULL, *peer_key = NULL;
   4628 	struct wpabuf *own_key_pub = NULL;
   4629 	const struct dpp_curve_params *curve, *own_curve;
   4630 	struct dpp_signed_connector_info info;
   4631 	const unsigned char *p;
   4632 	EVP_PKEY *csign = NULL;
   4633 	char *signed_connector = NULL;
   4634 	const char *pos, *end;
   4635 	unsigned char *own_conn = NULL;
   4636 	size_t own_conn_len;
   4637 	EVP_PKEY_CTX *ctx = NULL;
   4638 	size_t Nx_len;
   4639 	u8 Nx[DPP_MAX_SHARED_SECRET_LEN];
   4640 
   4641 	os_memset(intro, 0, sizeof(*intro));
   4642 	os_memset(&info, 0, sizeof(info));
   4643 	if (expiry)
   4644 		*expiry = 0;
   4645 
   4646 	p = csign_key;
   4647 	csign = d2i_PUBKEY(NULL, &p, csign_key_len);
   4648 	if (!csign) {
   4649 		wpa_printf(MSG_ERROR,
   4650 			   "DPP: Failed to parse local C-sign-key information");
   4651 		goto fail;
   4652 	}
   4653 
   4654 	own_key = dpp_set_keypair(&own_curve, net_access_key,
   4655 				  net_access_key_len);
   4656 	if (!own_key) {
   4657 		wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey");
   4658 		goto fail;
   4659 	}
   4660 
   4661 	pos = os_strchr(own_connector, '.');
   4662 	if (!pos) {
   4663 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)");
   4664 		goto fail;
   4665 	}
   4666 	pos++;
   4667 	end = os_strchr(pos, '.');
   4668 	if (!end) {
   4669 		wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)");
   4670 		goto fail;
   4671 	}
   4672 	own_conn = base64_url_decode((const unsigned char *) pos,
   4673 				     end - pos, &own_conn_len);
   4674 	if (!own_conn) {
   4675 		wpa_printf(MSG_DEBUG,
   4676 			   "DPP: Failed to base64url decode own signedConnector JWS Payload");
   4677 		goto fail;
   4678 	}
   4679 
   4680 	own_root = json_parse((const char *) own_conn, own_conn_len);
   4681 	if (!own_root) {
   4682 		wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector");
   4683 		goto fail;
   4684 	}
   4685 
   4686 	wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector",
   4687 			  peer_connector, peer_connector_len);
   4688 	signed_connector = os_malloc(peer_connector_len + 1);
   4689 	if (!signed_connector)
   4690 		goto fail;
   4691 	os_memcpy(signed_connector, peer_connector, peer_connector_len);
   4692 	signed_connector[peer_connector_len] = '\0';
   4693 
   4694 	if (dpp_process_signed_connector(&info, csign, signed_connector) < 0)
   4695 		goto fail;
   4696 
   4697 	root = json_parse((const char *) info.payload, info.payload_len);
   4698 	if (!root) {
   4699 		wpa_printf(MSG_DEBUG, "DPP: JSON parsing of connector failed");
   4700 		goto fail;
   4701 	}
   4702 
   4703 	if (!dpp_connector_match_groups(own_root, root)) {
   4704 		wpa_printf(MSG_DEBUG,
   4705 			   "DPP: Peer connector does not include compatible group netrole with own connector");
   4706 		goto fail;
   4707 	}
   4708 
   4709 	token = json_get_member(root, "expiry");
   4710 	if (!token || token->type != JSON_STRING) {
   4711 		wpa_printf(MSG_DEBUG,
   4712 			   "DPP: No expiry string found - connector does not expire");
   4713 	} else {
   4714 		wpa_printf(MSG_DEBUG, "DPP: expiry = %s", token->string);
   4715 		if (dpp_key_expired(token->string, expiry)) {
   4716 			wpa_printf(MSG_DEBUG,
   4717 				   "DPP: Connector (netAccessKey) has expired");
   4718 			goto fail;
   4719 		}
   4720 	}
   4721 
   4722 	netkey = json_get_member(root, "netAccessKey");
   4723 	if (!netkey || netkey->type != JSON_OBJECT) {
   4724 		wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found");
   4725 		goto fail;
   4726 	}
   4727 
   4728 	peer_key = dpp_parse_jwk(netkey, &curve);
   4729 	if (!peer_key)
   4730 		goto fail;
   4731 	dpp_debug_print_key("DPP: Received netAccessKey", peer_key);
   4732 
   4733 	if (own_curve != curve) {
   4734 		wpa_printf(MSG_DEBUG,
   4735 			   "DPP: Mismatching netAccessKey curves (%s != %s)",
   4736 			   own_curve->name, curve->name);
   4737 		goto fail;
   4738 	}
   4739 
   4740 	/* ECDH: N = nk * PK */
   4741 	ctx = EVP_PKEY_CTX_new(own_key, NULL);
   4742 	if (!ctx ||
   4743 	    EVP_PKEY_derive_init(ctx) != 1 ||
   4744 	    EVP_PKEY_derive_set_peer(ctx, peer_key) != 1 ||
   4745 	    EVP_PKEY_derive(ctx, NULL, &Nx_len) != 1 ||
   4746 	    Nx_len > DPP_MAX_SHARED_SECRET_LEN ||
   4747 	    EVP_PKEY_derive(ctx, Nx, &Nx_len) != 1) {
   4748 		wpa_printf(MSG_ERROR,
   4749 			   "DPP: Failed to derive ECDH shared secret: %s",
   4750 			   ERR_error_string(ERR_get_error(), NULL));
   4751 		goto fail;
   4752 	}
   4753 
   4754 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)",
   4755 			Nx, Nx_len);
   4756 
   4757 	/* PMK = HKDF(<>, "DPP PMK", N.x) */
   4758 	if (dpp_derive_pmk(Nx, Nx_len, intro->pmk, curve->hash_len) < 0) {
   4759 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMK");
   4760 		goto fail;
   4761 	}
   4762 	intro->pmk_len = curve->hash_len;
   4763 
   4764 	/* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */
   4765 	if (dpp_derive_pmkid(curve, own_key, peer_key, intro->pmkid) < 0) {
   4766 		wpa_printf(MSG_ERROR, "DPP: Failed to derive PMKID");
   4767 		goto fail;
   4768 	}
   4769 
   4770 	ret = 0;
   4771 fail:
   4772 	if (ret < 0)
   4773 		os_memset(intro, 0, sizeof(*intro));
   4774 	os_memset(Nx, 0, sizeof(Nx));
   4775 	EVP_PKEY_CTX_free(ctx);
   4776 	os_free(own_conn);
   4777 	os_free(signed_connector);
   4778 	os_free(info.payload);
   4779 	EVP_PKEY_free(own_key);
   4780 	wpabuf_free(own_key_pub);
   4781 	EVP_PKEY_free(peer_key);
   4782 	EVP_PKEY_free(csign);
   4783 	json_free(root);
   4784 	json_free(own_root);
   4785 	return ret;
   4786 }
   4787 
   4788 
   4789 static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve,
   4790 					 int init)
   4791 {
   4792 	EC_GROUP *group;
   4793 	size_t len = curve->prime_len;
   4794 	const u8 *x, *y;
   4795 
   4796 	switch (curve->ike_group) {
   4797 	case 19:
   4798 		x = init ? pkex_init_x_p256 : pkex_resp_x_p256;
   4799 		y = init ? pkex_init_y_p256 : pkex_resp_y_p256;
   4800 		break;
   4801 	case 20:
   4802 		x = init ? pkex_init_x_p384 : pkex_resp_x_p384;
   4803 		y = init ? pkex_init_y_p384 : pkex_resp_y_p384;
   4804 		break;
   4805 	case 21:
   4806 		x = init ? pkex_init_x_p521 : pkex_resp_x_p521;
   4807 		y = init ? pkex_init_y_p521 : pkex_resp_y_p521;
   4808 		break;
   4809 	case 28:
   4810 		x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1;
   4811 		y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1;
   4812 		break;
   4813 	case 29:
   4814 		x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1;
   4815 		y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1;
   4816 		break;
   4817 	case 30:
   4818 		x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1;
   4819 		y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1;
   4820 		break;
   4821 	default:
   4822 		return NULL;
   4823 	}
   4824 
   4825 	group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name));
   4826 	if (!group)
   4827 		return NULL;
   4828 	return dpp_set_pubkey_point_group(group, x, y, len);
   4829 }
   4830 
   4831 
   4832 static EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve,
   4833 				     const u8 *mac_init, const char *code,
   4834 				     const char *identifier, BN_CTX *bnctx,
   4835 				     const EC_GROUP **ret_group)
   4836 {
   4837 	u8 hash[DPP_MAX_HASH_LEN];
   4838 	const u8 *addr[3];
   4839 	size_t len[3];
   4840 	unsigned int num_elem = 0;
   4841 	EC_POINT *Qi = NULL;
   4842 	EVP_PKEY *Pi = NULL;
   4843 	EC_KEY *Pi_ec = NULL;
   4844 	const EC_POINT *Pi_point;
   4845 	BIGNUM *hash_bn = NULL;
   4846 	const EC_GROUP *group = NULL;
   4847 	EC_GROUP *group2 = NULL;
   4848 
   4849 	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
   4850 
   4851 	wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init));
   4852 	addr[num_elem] = mac_init;
   4853 	len[num_elem] = ETH_ALEN;
   4854 	num_elem++;
   4855 	if (identifier) {
   4856 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
   4857 			   identifier);
   4858 		addr[num_elem] = (const u8 *) identifier;
   4859 		len[num_elem] = os_strlen(identifier);
   4860 		num_elem++;
   4861 	}
   4862 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
   4863 	addr[num_elem] = (const u8 *) code;
   4864 	len[num_elem] = os_strlen(code);
   4865 	num_elem++;
   4866 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
   4867 		goto fail;
   4868 	wpa_hexdump_key(MSG_DEBUG,
   4869 			"DPP: H(MAC-Initiator | [identifier |] code)",
   4870 			hash, curve->hash_len);
   4871 	Pi = dpp_pkex_get_role_elem(curve, 1);
   4872 	if (!Pi)
   4873 		goto fail;
   4874 	dpp_debug_print_key("DPP: Pi", Pi);
   4875 	Pi_ec = EVP_PKEY_get1_EC_KEY(Pi);
   4876 	if (!Pi_ec)
   4877 		goto fail;
   4878 	Pi_point = EC_KEY_get0_public_key(Pi_ec);
   4879 
   4880 	group = EC_KEY_get0_group(Pi_ec);
   4881 	if (!group)
   4882 		goto fail;
   4883 	group2 = EC_GROUP_dup(group);
   4884 	if (!group2)
   4885 		goto fail;
   4886 	Qi = EC_POINT_new(group2);
   4887 	if (!Qi) {
   4888 		EC_GROUP_free(group2);
   4889 		goto fail;
   4890 	}
   4891 	hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
   4892 	if (!hash_bn ||
   4893 	    EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1)
   4894 		goto fail;
   4895 	if (EC_POINT_is_at_infinity(group, Qi)) {
   4896 		wpa_printf(MSG_INFO, "PDP: Qi is the point-at-infinity");
   4897 		goto fail;
   4898 	}
   4899 out:
   4900 	EC_KEY_free(Pi_ec);
   4901 	EVP_PKEY_free(Pi);
   4902 	BN_clear_free(hash_bn);
   4903 	if (ret_group)
   4904 		*ret_group = group2;
   4905 	return Qi;
   4906 fail:
   4907 	EC_POINT_free(Qi);
   4908 	Qi = NULL;
   4909 	goto out;
   4910 }
   4911 
   4912 
   4913 static EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve,
   4914 				     const u8 *mac_resp, const char *code,
   4915 				     const char *identifier, BN_CTX *bnctx,
   4916 				     const EC_GROUP **ret_group)
   4917 {
   4918 	u8 hash[DPP_MAX_HASH_LEN];
   4919 	const u8 *addr[3];
   4920 	size_t len[3];
   4921 	unsigned int num_elem = 0;
   4922 	EC_POINT *Qr = NULL;
   4923 	EVP_PKEY *Pr = NULL;
   4924 	EC_KEY *Pr_ec = NULL;
   4925 	const EC_POINT *Pr_point;
   4926 	BIGNUM *hash_bn = NULL;
   4927 	const EC_GROUP *group = NULL;
   4928 	EC_GROUP *group2 = NULL;
   4929 
   4930 	/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
   4931 
   4932 	wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp));
   4933 	addr[num_elem] = mac_resp;
   4934 	len[num_elem] = ETH_ALEN;
   4935 	num_elem++;
   4936 	if (identifier) {
   4937 		wpa_printf(MSG_DEBUG, "DPP: code identifier: %s",
   4938 			   identifier);
   4939 		addr[num_elem] = (const u8 *) identifier;
   4940 		len[num_elem] = os_strlen(identifier);
   4941 		num_elem++;
   4942 	}
   4943 	wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code));
   4944 	addr[num_elem] = (const u8 *) code;
   4945 	len[num_elem] = os_strlen(code);
   4946 	num_elem++;
   4947 	if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0)
   4948 		goto fail;
   4949 	wpa_hexdump_key(MSG_DEBUG,
   4950 			"DPP: H(MAC-Responder | [identifier |] code)",
   4951 			hash, curve->hash_len);
   4952 	Pr = dpp_pkex_get_role_elem(curve, 0);
   4953 	if (!Pr)
   4954 		goto fail;
   4955 	dpp_debug_print_key("DPP: Pr", Pr);
   4956 	Pr_ec = EVP_PKEY_get1_EC_KEY(Pr);
   4957 	if (!Pr_ec)
   4958 		goto fail;
   4959 	Pr_point = EC_KEY_get0_public_key(Pr_ec);
   4960 
   4961 	group = EC_KEY_get0_group(Pr_ec);
   4962 	if (!group)
   4963 		goto fail;
   4964 	group2 = EC_GROUP_dup(group);
   4965 	if (!group2)
   4966 		goto fail;
   4967 	Qr = EC_POINT_new(group2);
   4968 	if (!Qr) {
   4969 		EC_GROUP_free(group2);
   4970 		goto fail;
   4971 	}
   4972 	hash_bn = BN_bin2bn(hash, curve->hash_len, NULL);
   4973 	if (!hash_bn ||
   4974 	    EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1)
   4975 		goto fail;
   4976 out:
   4977 	EC_KEY_free(Pr_ec);
   4978 	EVP_PKEY_free(Pr);
   4979 	BN_clear_free(hash_bn);
   4980 	if (ret_group)
   4981 		*ret_group = group2;
   4982 	return Qr;
   4983 fail:
   4984 	EC_POINT_free(Qr);
   4985 	Qr = NULL;
   4986 	goto out;
   4987 }
   4988 
   4989 
   4990 static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex)
   4991 {
   4992 	EC_KEY *X_ec = NULL;
   4993 	const EC_POINT *X_point;
   4994 	BN_CTX *bnctx = NULL;
   4995 	const EC_GROUP *group;
   4996 	EC_POINT *Qi = NULL, *M = NULL;
   4997 	struct wpabuf *M_buf = NULL;
   4998 	BIGNUM *Mx = NULL, *My = NULL;
   4999 	struct wpabuf *msg = NULL;
   5000 	size_t attr_len;
   5001 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
   5002 	int num_bytes, offset;
   5003 
   5004 	wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request");
   5005 
   5006 	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
   5007 	bnctx = BN_CTX_new();
   5008 	if (!bnctx)
   5009 		goto fail;
   5010 	Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code,
   5011 				pkex->identifier, bnctx, &group);
   5012 	if (!Qi)
   5013 		goto fail;
   5014 
   5015 	/* Generate a random ephemeral keypair x/X */
   5016 	pkex->x = dpp_gen_keypair(curve);
   5017 	if (!pkex->x)
   5018 		goto fail;
   5019 
   5020 	/* M = X + Qi */
   5021 	X_ec = EVP_PKEY_get1_EC_KEY(pkex->x);
   5022 	if (!X_ec)
   5023 		goto fail;
   5024 	X_point = EC_KEY_get0_public_key(X_ec);
   5025 	if (!X_point)
   5026 		goto fail;
   5027 	M = EC_POINT_new(group);
   5028 	Mx = BN_new();
   5029 	My = BN_new();
   5030 	if (!M || !Mx || !My ||
   5031 	    EC_POINT_add(group, M, X_point, Qi, bnctx) != 1 ||
   5032 	    EC_POINT_get_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1)
   5033 		goto fail;
   5034 
   5035 	/* Initiator -> Responder: group, [identifier,] M */
   5036 	attr_len = 4 + 2;
   5037 	if (pkex->identifier)
   5038 		attr_len += 4 + os_strlen(pkex->identifier);
   5039 	attr_len += 4 + 2 * curve->prime_len;
   5040 	msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len);
   5041 	if (!msg)
   5042 		goto fail;
   5043 
   5044 	/* Finite Cyclic Group attribute */
   5045 	wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP);
   5046 	wpabuf_put_le16(msg, 2);
   5047 	wpabuf_put_le16(msg, curve->ike_group);
   5048 
   5049 	/* Code Identifier attribute */
   5050 	if (pkex->identifier) {
   5051 		wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
   5052 		wpabuf_put_le16(msg, os_strlen(pkex->identifier));
   5053 		wpabuf_put_str(msg, pkex->identifier);
   5054 	}
   5055 
   5056 	/* M in Encrypted Key attribute */
   5057 	wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
   5058 	wpabuf_put_le16(msg, 2 * curve->prime_len);
   5059 
   5060 	num_bytes = BN_num_bytes(Mx);
   5061 	if ((size_t) num_bytes > curve->prime_len)
   5062 		goto fail;
   5063 	if (curve->prime_len > (size_t) num_bytes)
   5064 		offset = curve->prime_len - num_bytes;
   5065 	else
   5066 		offset = 0;
   5067 	os_memset(wpabuf_put(msg, offset), 0, offset);
   5068 	BN_bn2bin(Mx, wpabuf_put(msg, num_bytes));
   5069 	os_memset(pkex->Mx, 0, offset);
   5070 	BN_bn2bin(Mx, pkex->Mx + offset);
   5071 
   5072 	num_bytes = BN_num_bytes(My);
   5073 	if ((size_t) num_bytes > curve->prime_len)
   5074 		goto fail;
   5075 	if (curve->prime_len > (size_t) num_bytes)
   5076 		offset = curve->prime_len - num_bytes;
   5077 	else
   5078 		offset = 0;
   5079 	os_memset(wpabuf_put(msg, offset), 0, offset);
   5080 	BN_bn2bin(My, wpabuf_put(msg, num_bytes));
   5081 
   5082 out:
   5083 	wpabuf_free(M_buf);
   5084 	EC_KEY_free(X_ec);
   5085 	EC_POINT_free(M);
   5086 	EC_POINT_free(Qi);
   5087 	BN_clear_free(Mx);
   5088 	BN_clear_free(My);
   5089 	BN_CTX_free(bnctx);
   5090 	return msg;
   5091 fail:
   5092 	wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request");
   5093 	wpabuf_free(msg);
   5094 	msg = NULL;
   5095 	goto out;
   5096 }
   5097 
   5098 
   5099 struct dpp_pkex * dpp_pkex_init(struct dpp_bootstrap_info *bi,
   5100 				const u8 *own_mac,
   5101 				const char *identifier,
   5102 				const char *code)
   5103 {
   5104 	struct dpp_pkex *pkex;
   5105 
   5106 	pkex = os_zalloc(sizeof(*pkex));
   5107 	if (!pkex)
   5108 		return NULL;
   5109 	pkex->initiator = 1;
   5110 	pkex->own_bi = bi;
   5111 	os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
   5112 	if (identifier) {
   5113 		pkex->identifier = os_strdup(identifier);
   5114 		if (!pkex->identifier)
   5115 			goto fail;
   5116 	}
   5117 	pkex->code = os_strdup(code);
   5118 	if (!pkex->code)
   5119 		goto fail;
   5120 	pkex->exchange_req = dpp_pkex_build_exchange_req(pkex);
   5121 	if (!pkex->exchange_req)
   5122 		goto fail;
   5123 	return pkex;
   5124 fail:
   5125 	dpp_pkex_free(pkex);
   5126 	return NULL;
   5127 }
   5128 
   5129 
   5130 struct dpp_pkex * dpp_pkex_rx_exchange_req(struct dpp_bootstrap_info *bi,
   5131 					   const u8 *own_mac,
   5132 					   const u8 *peer_mac,
   5133 					   const char *identifier,
   5134 					   const char *code,
   5135 					   const u8 *buf, size_t len)
   5136 {
   5137 	const u8 *attr_group, *attr_id, *attr_key;
   5138 	u16 attr_group_len, attr_id_len, attr_key_len;
   5139 	const struct dpp_curve_params *curve = bi->curve;
   5140 	u16 ike_group;
   5141 	struct dpp_pkex *pkex = NULL;
   5142 	EC_POINT *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL, *N = NULL;
   5143 	BN_CTX *bnctx = NULL;
   5144 	const EC_GROUP *group;
   5145 	BIGNUM *Mx = NULL, *My = NULL;
   5146 	EC_KEY *Y_ec = NULL, *X_ec = NULL;;
   5147 	const EC_POINT *Y_point;
   5148 	BIGNUM *Nx = NULL, *Ny = NULL;
   5149 	struct wpabuf *msg = NULL;
   5150 	size_t attr_len;
   5151 	int num_bytes, offset;
   5152 
   5153 	attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER,
   5154 			       &attr_id_len);
   5155 	if (!attr_id && identifier) {
   5156 		wpa_printf(MSG_DEBUG,
   5157 			   "DPP: No PKEX code identifier received, but expected one");
   5158 		return NULL;
   5159 	}
   5160 	if (attr_id && identifier &&
   5161 	    (os_strlen(identifier) != attr_id_len ||
   5162 	     os_memcmp(identifier, attr_id, attr_id_len) != 0)) {
   5163 		wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch");
   5164 		return NULL;
   5165 	}
   5166 
   5167 	attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
   5168 				  &attr_group_len);
   5169 	if (!attr_group || attr_group_len != 2) {
   5170 		wpa_printf(MSG_DEBUG,
   5171 			   "DPP: Missing or invalid Finite Cyclic Group attribute");
   5172 		return NULL;
   5173 	}
   5174 	ike_group = WPA_GET_LE16(attr_group);
   5175 	if (ike_group != curve->ike_group) {
   5176 		wpa_printf(MSG_DEBUG,
   5177 			   "DPP: Mismatching PKEX curve: peer=%u own=%u",
   5178 			   ike_group, curve->ike_group);
   5179 		/* TODO: error response with suggested curve:
   5180 		 * DPP Status, group */
   5181 		return NULL;
   5182 	}
   5183 
   5184 	/* M in Encrypted Key attribute */
   5185 	attr_key = dpp_get_attr(buf, len, DPP_ATTR_ENCRYPTED_KEY,
   5186 				&attr_key_len);
   5187 	if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2 ||
   5188 	    attr_key_len / 2 > DPP_MAX_SHARED_SECRET_LEN) {
   5189 		wpa_printf(MSG_DEBUG, "DPP: Missing Encrypted Key attribute");
   5190 		return NULL;
   5191 	}
   5192 
   5193 	/* Qi = H(MAC-Initiator | [identifier |] code) * Pi */
   5194 	bnctx = BN_CTX_new();
   5195 	if (!bnctx)
   5196 		goto fail;
   5197 	Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, bnctx,
   5198 				&group);
   5199 	if (!Qi)
   5200 		goto fail;
   5201 
   5202 	/* X' = M - Qi */
   5203 	X = EC_POINT_new(group);
   5204 	M = EC_POINT_new(group);
   5205 	Mx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
   5206 	My = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
   5207 	if (!X || !M || !Mx || !My ||
   5208 	    EC_POINT_set_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1 ||
   5209 	    EC_POINT_is_at_infinity(group, M) ||
   5210 	    !EC_POINT_is_on_curve(group, M, bnctx) ||
   5211 	    EC_POINT_invert(group, Qi, bnctx) != 1 ||
   5212 	    EC_POINT_add(group, X, M, Qi, bnctx) != 1 ||
   5213 	    EC_POINT_is_at_infinity(group, X) ||
   5214 	    !EC_POINT_is_on_curve(group, X, bnctx))
   5215 		goto fail;
   5216 
   5217 	pkex = os_zalloc(sizeof(*pkex));
   5218 	if (!pkex)
   5219 		goto fail;
   5220 	pkex->own_bi = bi;
   5221 	os_memcpy(pkex->own_mac, own_mac, ETH_ALEN);
   5222 	os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN);
   5223 	if (identifier) {
   5224 		pkex->identifier = os_strdup(identifier);
   5225 		if (!pkex->identifier)
   5226 			goto fail;
   5227 	}
   5228 	pkex->code = os_strdup(code);
   5229 	if (!pkex->code)
   5230 		goto fail;
   5231 
   5232 	os_memcpy(pkex->Mx, attr_key, attr_key_len / 2);
   5233 
   5234 	X_ec = EC_KEY_new();
   5235 	if (!X_ec ||
   5236 	    EC_KEY_set_group(X_ec, group) != 1 ||
   5237 	    EC_KEY_set_public_key(X_ec, X) != 1)
   5238 		goto fail;
   5239 	pkex->x = EVP_PKEY_new();
   5240 	if (!pkex->x ||
   5241 	    EVP_PKEY_set1_EC_KEY(pkex->x, X_ec) != 1)
   5242 		goto fail;
   5243 
   5244 	/* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */
   5245 	Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, bnctx, NULL);
   5246 	if (!Qr)
   5247 		goto fail;
   5248 
   5249 	/* Generate a random ephemeral keypair y/Y */
   5250 	pkex->y = dpp_gen_keypair(curve);
   5251 	if (!pkex->y)
   5252 		goto fail;
   5253 
   5254 	/* N = Y + Qr */
   5255 	Y_ec = EVP_PKEY_get1_EC_KEY(pkex->y);
   5256 	if (!Y_ec)
   5257 		goto fail;
   5258 	Y_point = EC_KEY_get0_public_key(Y_ec);
   5259 	if (!Y_point)
   5260 		goto fail;
   5261 	N = EC_POINT_new(group);
   5262 	Nx = BN_new();
   5263 	Ny = BN_new();
   5264 	if (!N || !Nx || !Ny ||
   5265 	    EC_POINT_add(group, N, Y_point, Qr, bnctx) != 1 ||
   5266 	    EC_POINT_get_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1)
   5267 		goto fail;
   5268 
   5269 	/* Initiator -> Responder: DPP Status, [identifier,] N */
   5270 	attr_len = 4 + 1;
   5271 	if (identifier)
   5272 		attr_len += 4 + os_strlen(identifier);
   5273 	attr_len += 4 + 2 * curve->prime_len;
   5274 	msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_RESP, attr_len);
   5275 	if (!msg)
   5276 		goto fail;
   5277 
   5278 	/* DPP Status */
   5279 	wpabuf_put_le16(msg, DPP_ATTR_STATUS);
   5280 	wpabuf_put_le16(msg, 1);
   5281 	wpabuf_put_u8(msg, DPP_STATUS_OK);
   5282 
   5283 	/* Code Identifier attribute */
   5284 	if (pkex->identifier) {
   5285 		wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER);
   5286 		wpabuf_put_le16(msg, os_strlen(pkex->identifier));
   5287 		wpabuf_put_str(msg, pkex->identifier);
   5288 	}
   5289 
   5290 	/* N in Encrypted Key attribute */
   5291 	wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY);
   5292 	wpabuf_put_le16(msg, 2 * curve->prime_len);
   5293 
   5294 	num_bytes = BN_num_bytes(Nx);
   5295 	if ((size_t) num_bytes > curve->prime_len)
   5296 		goto fail;
   5297 	if (curve->prime_len > (size_t) num_bytes)
   5298 		offset = curve->prime_len - num_bytes;
   5299 	else
   5300 		offset = 0;
   5301 	os_memset(wpabuf_put(msg, offset), 0, offset);
   5302 	BN_bn2bin(Nx, wpabuf_put(msg, num_bytes));
   5303 	os_memset(pkex->Nx, 0, offset);
   5304 	BN_bn2bin(Nx, pkex->Nx + offset);
   5305 
   5306 	num_bytes = BN_num_bytes(Ny);
   5307 	if ((size_t) num_bytes > curve->prime_len)
   5308 		goto fail;
   5309 	if (curve->prime_len > (size_t) num_bytes)
   5310 		offset = curve->prime_len - num_bytes;
   5311 	else
   5312 		offset = 0;
   5313 	os_memset(wpabuf_put(msg, offset), 0, offset);
   5314 	BN_bn2bin(Ny, wpabuf_put(msg, num_bytes));
   5315 
   5316 	pkex->exchange_resp = msg;
   5317 	msg = NULL;
   5318 	pkex->exchange_done = 1;
   5319 
   5320 out:
   5321 	wpabuf_free(msg);
   5322 	BN_CTX_free(bnctx);
   5323 	EC_POINT_free(Qi);
   5324 	EC_POINT_free(Qr);
   5325 	BN_free(Mx);
   5326 	BN_free(My);
   5327 	BN_free(Nx);
   5328 	BN_free(Ny);
   5329 	EC_POINT_free(M);
   5330 	EC_POINT_free(N);
   5331 	EC_POINT_free(X);
   5332 	EC_KEY_free(X_ec);
   5333 	EC_KEY_free(Y_ec);
   5334 	return pkex;
   5335 fail:
   5336 	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing faileed");
   5337 	dpp_pkex_free(pkex);
   5338 	pkex = NULL;
   5339 	goto out;
   5340 }
   5341 
   5342 
   5343 static int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
   5344 			     const u8 *Mx, size_t Mx_len,
   5345 			     const u8 *Nx, size_t Nx_len,
   5346 			     const char *code,
   5347 			     const u8 *Kx, size_t Kx_len,
   5348 			     u8 *z, unsigned int hash_len)
   5349 {
   5350 	u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN];
   5351 	int res;
   5352 	u8 *info, *pos;
   5353 	size_t info_len;
   5354 
   5355 	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
   5356 	 */
   5357 
   5358 	/* HKDF-Extract(<>, IKM=K.x) */
   5359 	os_memset(salt, 0, hash_len);
   5360 	if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0)
   5361 		return -1;
   5362 	wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)",
   5363 			prk, hash_len);
   5364 	info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code);
   5365 	info = os_malloc(info_len);
   5366 	if (!info)
   5367 		return -1;
   5368 	pos = info;
   5369 	os_memcpy(pos, mac_init, ETH_ALEN);
   5370 	pos += ETH_ALEN;
   5371 	os_memcpy(pos, mac_resp, ETH_ALEN);
   5372 	pos += ETH_ALEN;
   5373 	os_memcpy(pos, Mx, Mx_len);
   5374 	pos += Mx_len;
   5375 	os_memcpy(pos, Nx, Nx_len);
   5376 	pos += Nx_len;
   5377 	os_memcpy(pos, code, os_strlen(code));
   5378 
   5379 	/* HKDF-Expand(PRK, info, L) */
   5380 	if (hash_len == 32)
   5381 		res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len,
   5382 				      z, hash_len);
   5383 	else if (hash_len == 48)
   5384 		res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len,
   5385 				      z, hash_len);
   5386 	else if (hash_len == 64)
   5387 		res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len,
   5388 				      z, hash_len);
   5389 	else
   5390 		res = -1;
   5391 	os_free(info);
   5392 	os_memset(prk, 0, hash_len);
   5393 	if (res < 0)
   5394 		return -1;
   5395 
   5396 	wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)",
   5397 			z, hash_len);
   5398 	return 0;
   5399 }
   5400 
   5401 
   5402 struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
   5403 					  const u8 *buf, size_t buflen)
   5404 {
   5405 	const u8 *attr_status, *attr_id, *attr_key;
   5406 	u16 attr_status_len, attr_id_len, attr_key_len;
   5407 	const EC_GROUP *group;
   5408 	BN_CTX *bnctx = NULL;
   5409 	size_t clear_len;
   5410 	struct wpabuf *clear = NULL;
   5411 	u8 *wrapped;
   5412 	struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
   5413 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
   5414 	EC_POINT *Qr = NULL, *Y = NULL, *N = NULL;
   5415 	BIGNUM *Nx = NULL, *Ny = NULL;
   5416 	EVP_PKEY_CTX *ctx = NULL;
   5417 	EC_KEY *Y_ec = NULL;
   5418 	size_t Jx_len, Kx_len;
   5419 	u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
   5420 	const u8 *addr[4];
   5421 	size_t len[4];
   5422 	u8 u[DPP_MAX_HASH_LEN];
   5423 	u8 octet;
   5424 	int res;
   5425 
   5426 	attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS,
   5427 				   &attr_status_len);
   5428 	if (!attr_status || attr_status_len != 1) {
   5429 		wpa_printf(MSG_DEBUG, "DPP: No DPP Status attribute");
   5430 		return NULL;
   5431 	}
   5432 	wpa_printf(MSG_DEBUG, "DPP: Status %u", attr_status[0]);
   5433 	if (attr_status[0] != DPP_STATUS_OK) {
   5434 		wpa_printf(MSG_DEBUG, "DPP: PKEX failed");
   5435 		return NULL;
   5436 	}
   5437 
   5438 	attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER,
   5439 			       &attr_id_len);
   5440 	if (!attr_id && pkex->identifier) {
   5441 		wpa_printf(MSG_DEBUG,
   5442 			   "DPP: No PKEX code identifier received, but expected one");
   5443 		return NULL;
   5444 	}
   5445 	if (attr_id && pkex->identifier &&
   5446 	    (os_strlen(pkex->identifier) != attr_id_len ||
   5447 	     os_memcmp(pkex->identifier, attr_id, attr_id_len) != 0)) {
   5448 		wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch");
   5449 		return NULL;
   5450 	}
   5451 
   5452 	/* N in Encrypted Key attribute */
   5453 	attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY,
   5454 				&attr_key_len);
   5455 	if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) {
   5456 		wpa_printf(MSG_DEBUG, "DPP: Missing Encrypted Key attribute");
   5457 		return NULL;
   5458 	}
   5459 
   5460 	/* Qr = H(MAC-Responder | [identifier |] code) * Pr */
   5461 	bnctx = BN_CTX_new();
   5462 	if (!bnctx)
   5463 		goto fail;
   5464 	Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code,
   5465 				pkex->identifier, bnctx, &group);
   5466 	if (!Qr)
   5467 		goto fail;
   5468 
   5469 	/* Y' = N - Qr */
   5470 	Y = EC_POINT_new(group);
   5471 	N = EC_POINT_new(group);
   5472 	Nx = BN_bin2bn(attr_key, attr_key_len / 2, NULL);
   5473 	Ny = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL);
   5474 	if (!Y || !N || !Nx || !Ny ||
   5475 	    EC_POINT_set_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1 ||
   5476 	    EC_POINT_is_at_infinity(group, N) ||
   5477 	    !EC_POINT_is_on_curve(group, N, bnctx) ||
   5478 	    EC_POINT_invert(group, Qr, bnctx) != 1 ||
   5479 	    EC_POINT_add(group, Y, N, Qr, bnctx) != 1 ||
   5480 	    EC_POINT_is_at_infinity(group, Y) ||
   5481 	    !EC_POINT_is_on_curve(group, Y, bnctx))
   5482 		goto fail;
   5483 
   5484 	pkex->exchange_done = 1;
   5485 
   5486 	/* ECDH: J = a * Y */
   5487 	Y_ec = EC_KEY_new();
   5488 	if (!Y_ec ||
   5489 	    EC_KEY_set_group(Y_ec, group) != 1 ||
   5490 	    EC_KEY_set_public_key(Y_ec, Y) != 1)
   5491 		goto fail;
   5492 	pkex->y = EVP_PKEY_new();
   5493 	if (!pkex->y ||
   5494 	    EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1)
   5495 		goto fail;
   5496 	ctx = EVP_PKEY_CTX_new(pkex->own_bi->pubkey, NULL);
   5497 	if (!ctx ||
   5498 	    EVP_PKEY_derive_init(ctx) != 1 ||
   5499 	    EVP_PKEY_derive_set_peer(ctx, pkex->y) != 1 ||
   5500 	    EVP_PKEY_derive(ctx, NULL, &Jx_len) != 1 ||
   5501 	    Jx_len > DPP_MAX_SHARED_SECRET_LEN ||
   5502 	    EVP_PKEY_derive(ctx, Jx, &Jx_len) != 1) {
   5503 		wpa_printf(MSG_ERROR,
   5504 			   "DPP: Failed to derive ECDH shared secret: %s",
   5505 			   ERR_error_string(ERR_get_error(), NULL));
   5506 		goto fail;
   5507 	}
   5508 
   5509 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
   5510 			Jx, Jx_len);
   5511 
   5512 	/* u = HMAC(J.x,  MAC-Initiator | A.x | Y.x | X.x ) */
   5513 	A_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
   5514 	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
   5515 	X_pub = dpp_get_pubkey_point(pkex->x, 0);
   5516 	if (!A_pub || !Y_pub || !X_pub)
   5517 		goto fail;
   5518 	addr[0] = pkex->own_mac;
   5519 	len[0] = ETH_ALEN;
   5520 	addr[1] = wpabuf_head(A_pub);
   5521 	len[1] = wpabuf_len(A_pub) / 2;
   5522 	addr[2] = wpabuf_head(Y_pub);
   5523 	len[2] = wpabuf_len(Y_pub) / 2;
   5524 	addr[3] = wpabuf_head(X_pub);
   5525 	len[3] = wpabuf_len(X_pub) / 2;
   5526 	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
   5527 		goto fail;
   5528 	wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len);
   5529 
   5530 	/* K = x * Y */
   5531 	EVP_PKEY_CTX_free(ctx);
   5532 	ctx = EVP_PKEY_CTX_new(pkex->x, NULL);
   5533 	if (!ctx ||
   5534 	    EVP_PKEY_derive_init(ctx) != 1 ||
   5535 	    EVP_PKEY_derive_set_peer(ctx, pkex->y) != 1 ||
   5536 	    EVP_PKEY_derive(ctx, NULL, &Kx_len) != 1 ||
   5537 	    Kx_len > DPP_MAX_SHARED_SECRET_LEN ||
   5538 	    EVP_PKEY_derive(ctx, Kx, &Kx_len) != 1) {
   5539 		wpa_printf(MSG_ERROR,
   5540 			   "DPP: Failed to derive ECDH shared secret: %s",
   5541 			   ERR_error_string(ERR_get_error(), NULL));
   5542 		goto fail;
   5543 	}
   5544 
   5545 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
   5546 			Kx, Kx_len);
   5547 
   5548 	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
   5549 	 */
   5550 	res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac,
   5551 				pkex->Mx, curve->prime_len,
   5552 				attr_key /* N.x */, attr_key_len / 2,
   5553 				pkex->code, Kx, Kx_len,
   5554 				pkex->z, curve->hash_len);
   5555 	os_memset(Kx, 0, Kx_len);
   5556 	if (res < 0)
   5557 		goto fail;
   5558 
   5559 	/* {A, u, [bootstrapping info]}z */
   5560 	clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
   5561 	clear = wpabuf_alloc(clear_len);
   5562 	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ,
   5563 			    4 + clear_len + AES_BLOCK_SIZE);
   5564 	if (!clear || !msg)
   5565 		goto fail;
   5566 
   5567 	/* A in Bootstrap Key attribute */
   5568 	wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
   5569 	wpabuf_put_le16(clear, wpabuf_len(A_pub));
   5570 	wpabuf_put_buf(clear, A_pub);
   5571 
   5572 	/* u in I-Auth tag attribute */
   5573 	wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG);
   5574 	wpabuf_put_le16(clear, curve->hash_len);
   5575 	wpabuf_put_data(clear, u, curve->hash_len);
   5576 
   5577 	addr[0] = wpabuf_head_u8(msg) + 2;
   5578 	len[0] = DPP_HDR_LEN;
   5579 	octet = 0;
   5580 	addr[1] = &octet;
   5581 	len[1] = sizeof(octet);
   5582 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   5583 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   5584 
   5585 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
   5586 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
   5587 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
   5588 
   5589 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
   5590 	if (aes_siv_encrypt(pkex->z, curve->hash_len,
   5591 			    wpabuf_head(clear), wpabuf_len(clear),
   5592 			    2, addr, len, wrapped) < 0)
   5593 		goto fail;
   5594 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   5595 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
   5596 
   5597 out:
   5598 	wpabuf_free(clear);
   5599 	wpabuf_free(A_pub);
   5600 	wpabuf_free(X_pub);
   5601 	wpabuf_free(Y_pub);
   5602 	EC_POINT_free(Qr);
   5603 	EC_POINT_free(Y);
   5604 	EC_POINT_free(N);
   5605 	BN_free(Nx);
   5606 	BN_free(Ny);
   5607 	EC_KEY_free(Y_ec);
   5608 	EVP_PKEY_CTX_free(ctx);
   5609 	BN_CTX_free(bnctx);
   5610 	return msg;
   5611 fail:
   5612 	wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing faileed");
   5613 	wpabuf_free(msg);
   5614 	msg = NULL;
   5615 	goto out;
   5616 }
   5617 
   5618 
   5619 struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex,
   5620 					      const u8 *hdr,
   5621 					      const u8 *buf, size_t buflen)
   5622 {
   5623 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
   5624 	EVP_PKEY_CTX *ctx;
   5625 	size_t Jx_len, Kx_len, Lx_len;
   5626 	u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN];
   5627 	u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
   5628 	const u8 *wrapped_data, *b_key, *peer_u;
   5629 	u16 wrapped_data_len, b_key_len, peer_u_len = 0;
   5630 	const u8 *addr[4];
   5631 	size_t len[4];
   5632 	u8 octet;
   5633 	u8 *unwrapped = NULL;
   5634 	size_t unwrapped_len = 0;
   5635 	struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
   5636 	struct wpabuf *B_pub = NULL;
   5637 	u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN];
   5638 	size_t clear_len;
   5639 	struct wpabuf *clear = NULL;
   5640 	u8 *wrapped;
   5641 	int res;
   5642 
   5643 	/* K = y * X' */
   5644 	ctx = EVP_PKEY_CTX_new(pkex->y, NULL);
   5645 	if (!ctx ||
   5646 	    EVP_PKEY_derive_init(ctx) != 1 ||
   5647 	    EVP_PKEY_derive_set_peer(ctx, pkex->x) != 1 ||
   5648 	    EVP_PKEY_derive(ctx, NULL, &Kx_len) != 1 ||
   5649 	    Kx_len > DPP_MAX_SHARED_SECRET_LEN ||
   5650 	    EVP_PKEY_derive(ctx, Kx, &Kx_len) != 1) {
   5651 		wpa_printf(MSG_ERROR,
   5652 			   "DPP: Failed to derive ECDH shared secret: %s",
   5653 			   ERR_error_string(ERR_get_error(), NULL));
   5654 		goto fail;
   5655 	}
   5656 
   5657 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)",
   5658 			Kx, Kx_len);
   5659 
   5660 	/* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x)
   5661 	 */
   5662 	res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac,
   5663 				pkex->Mx, curve->prime_len,
   5664 				pkex->Nx, curve->prime_len, pkex->code,
   5665 				Kx, Kx_len, pkex->z, curve->hash_len);
   5666 	os_memset(Kx, 0, Kx_len);
   5667 	if (res < 0)
   5668 		goto fail;
   5669 
   5670 	wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
   5671 				    &wrapped_data_len);
   5672 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
   5673 		wpa_printf(MSG_DEBUG,
   5674 			   "DPP: Missing or invalid required Wrapped data attribute");
   5675 		goto fail;
   5676 	}
   5677 
   5678 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   5679 		    wrapped_data, wrapped_data_len);
   5680 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
   5681 	unwrapped = os_malloc(unwrapped_len);
   5682 	if (!unwrapped)
   5683 		goto fail;
   5684 
   5685 	addr[0] = hdr;
   5686 	len[0] = DPP_HDR_LEN;
   5687 	octet = 0;
   5688 	addr[1] = &octet;
   5689 	len[1] = sizeof(octet);
   5690 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   5691 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   5692 
   5693 	if (aes_siv_decrypt(pkex->z, curve->hash_len,
   5694 			    wrapped_data, wrapped_data_len,
   5695 			    2, addr, len, unwrapped) < 0) {
   5696 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
   5697 		goto fail;
   5698 	}
   5699 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
   5700 		    unwrapped, unwrapped_len);
   5701 
   5702 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
   5703 		wpa_printf(MSG_DEBUG,
   5704 			   "DPP: Invalid attribute in unwrapped data");
   5705 		goto fail;
   5706 	}
   5707 
   5708 	b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
   5709 			     &b_key_len);
   5710 	if (!b_key || b_key_len != 2 * curve->prime_len) {
   5711 		wpa_printf(MSG_DEBUG,
   5712 			   "DPP: No valid peer bootstrapping key found");
   5713 		goto fail;
   5714 	}
   5715 	pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
   5716 							b_key_len);
   5717 	if (!pkex->peer_bootstrap_key)
   5718 		goto fail;
   5719 	dpp_debug_print_key("DPP: Peer bootstrap public key",
   5720 			    pkex->peer_bootstrap_key);
   5721 
   5722 	/* ECDH: J' = y * A' */
   5723 	EVP_PKEY_CTX_free(ctx);
   5724 	ctx = EVP_PKEY_CTX_new(pkex->y, NULL);
   5725 	if (!ctx ||
   5726 	    EVP_PKEY_derive_init(ctx) != 1 ||
   5727 	    EVP_PKEY_derive_set_peer(ctx, pkex->peer_bootstrap_key) != 1 ||
   5728 	    EVP_PKEY_derive(ctx, NULL, &Jx_len) != 1 ||
   5729 	    Jx_len > DPP_MAX_SHARED_SECRET_LEN ||
   5730 	    EVP_PKEY_derive(ctx, Jx, &Jx_len) != 1) {
   5731 		wpa_printf(MSG_ERROR,
   5732 			   "DPP: Failed to derive ECDH shared secret: %s",
   5733 			   ERR_error_string(ERR_get_error(), NULL));
   5734 		goto fail;
   5735 	}
   5736 
   5737 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)",
   5738 			Jx, Jx_len);
   5739 
   5740 	/* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */
   5741 	A_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
   5742 	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
   5743 	X_pub = dpp_get_pubkey_point(pkex->x, 0);
   5744 	if (!A_pub || !Y_pub || !X_pub)
   5745 		goto fail;
   5746 	addr[0] = pkex->peer_mac;
   5747 	len[0] = ETH_ALEN;
   5748 	addr[1] = wpabuf_head(A_pub);
   5749 	len[1] = wpabuf_len(A_pub) / 2;
   5750 	addr[2] = wpabuf_head(Y_pub);
   5751 	len[2] = wpabuf_len(Y_pub) / 2;
   5752 	addr[3] = wpabuf_head(X_pub);
   5753 	len[3] = wpabuf_len(X_pub) / 2;
   5754 	if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0)
   5755 		goto fail;
   5756 
   5757 	peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG,
   5758 			      &peer_u_len);
   5759 	if (!peer_u || peer_u_len != curve->hash_len ||
   5760 	    os_memcmp(peer_u, u, curve->hash_len) != 0) {
   5761 		wpa_printf(MSG_DEBUG, "DPP: No valid u (I-Auth tag) found");
   5762 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated u'",
   5763 			    u, curve->hash_len);
   5764 		wpa_hexdump(MSG_DEBUG, "DPP: Received u", peer_u, peer_u_len);
   5765 		goto fail;
   5766 	}
   5767 	wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received");
   5768 
   5769 	/* ECDH: L = b * X' */
   5770 	EVP_PKEY_CTX_free(ctx);
   5771 	ctx = EVP_PKEY_CTX_new(pkex->own_bi->pubkey, NULL);
   5772 	if (!ctx ||
   5773 	    EVP_PKEY_derive_init(ctx) != 1 ||
   5774 	    EVP_PKEY_derive_set_peer(ctx, pkex->x) != 1 ||
   5775 	    EVP_PKEY_derive(ctx, NULL, &Lx_len) != 1 ||
   5776 	    Lx_len > DPP_MAX_SHARED_SECRET_LEN ||
   5777 	    EVP_PKEY_derive(ctx, Lx, &Lx_len) != 1) {
   5778 		wpa_printf(MSG_ERROR,
   5779 			   "DPP: Failed to derive ECDH shared secret: %s",
   5780 			   ERR_error_string(ERR_get_error(), NULL));
   5781 		goto fail;
   5782 	}
   5783 
   5784 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
   5785 			Lx, Lx_len);
   5786 
   5787 	/* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */
   5788 	B_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0);
   5789 	if (!B_pub)
   5790 		goto fail;
   5791 	addr[0] = pkex->own_mac;
   5792 	len[0] = ETH_ALEN;
   5793 	addr[1] = wpabuf_head(B_pub);
   5794 	len[1] = wpabuf_len(B_pub) / 2;
   5795 	addr[2] = wpabuf_head(X_pub);
   5796 	len[2] = wpabuf_len(X_pub) / 2;
   5797 	addr[3] = wpabuf_head(Y_pub);
   5798 	len[3] = wpabuf_len(Y_pub) / 2;
   5799 	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
   5800 		goto fail;
   5801 	wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len);
   5802 
   5803 	/* {B, v [bootstrapping info]}z */
   5804 	clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len;
   5805 	clear = wpabuf_alloc(clear_len);
   5806 	msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP,
   5807 			    4 + clear_len + AES_BLOCK_SIZE);
   5808 	if (!clear || !msg)
   5809 		goto fail;
   5810 
   5811 	/* A in Bootstrap Key attribute */
   5812 	wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY);
   5813 	wpabuf_put_le16(clear, wpabuf_len(B_pub));
   5814 	wpabuf_put_buf(clear, B_pub);
   5815 
   5816 	/* v in R-Auth tag attribute */
   5817 	wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG);
   5818 	wpabuf_put_le16(clear, curve->hash_len);
   5819 	wpabuf_put_data(clear, v, curve->hash_len);
   5820 
   5821 	addr[0] = wpabuf_head_u8(msg) + 2;
   5822 	len[0] = DPP_HDR_LEN;
   5823 	octet = 1;
   5824 	addr[1] = &octet;
   5825 	len[1] = sizeof(octet);
   5826 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   5827 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   5828 
   5829 	wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA);
   5830 	wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
   5831 	wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE);
   5832 
   5833 	wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear);
   5834 	if (aes_siv_encrypt(pkex->z, curve->hash_len,
   5835 			    wpabuf_head(clear), wpabuf_len(clear),
   5836 			    2, addr, len, wrapped) < 0)
   5837 		goto fail;
   5838 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   5839 		    wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE);
   5840 out:
   5841 	EVP_PKEY_CTX_free(ctx);
   5842 	os_free(unwrapped);
   5843 	wpabuf_free(A_pub);
   5844 	wpabuf_free(B_pub);
   5845 	wpabuf_free(X_pub);
   5846 	wpabuf_free(Y_pub);
   5847 	wpabuf_free(clear);
   5848 	return msg;
   5849 fail:
   5850 	wpabuf_free(msg);
   5851 	msg = NULL;
   5852 	goto out;
   5853 }
   5854 
   5855 
   5856 int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr,
   5857 				   const u8 *buf, size_t buflen)
   5858 {
   5859 	const struct dpp_curve_params *curve = pkex->own_bi->curve;
   5860 	const u8 *wrapped_data, *b_key, *peer_v;
   5861 	u16 wrapped_data_len, b_key_len, peer_v_len = 0;
   5862 	const u8 *addr[4];
   5863 	size_t len[4];
   5864 	u8 octet;
   5865 	u8 *unwrapped = NULL;
   5866 	size_t unwrapped_len = 0;
   5867 	int ret = -1;
   5868 	u8 v[DPP_MAX_HASH_LEN];
   5869 	size_t Lx_len;
   5870 	u8 Lx[DPP_MAX_SHARED_SECRET_LEN];
   5871 	EVP_PKEY_CTX *ctx = NULL;
   5872 	struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL;
   5873 
   5874 	wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA,
   5875 				    &wrapped_data_len);
   5876 	if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) {
   5877 		wpa_printf(MSG_DEBUG,
   5878 			   "DPP: Missing or invalid required Wrapped data attribute");
   5879 		goto fail;
   5880 	}
   5881 
   5882 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext",
   5883 		    wrapped_data, wrapped_data_len);
   5884 	unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE;
   5885 	unwrapped = os_malloc(unwrapped_len);
   5886 	if (!unwrapped)
   5887 		goto fail;
   5888 
   5889 	addr[0] = hdr;
   5890 	len[0] = DPP_HDR_LEN;
   5891 	octet = 1;
   5892 	addr[1] = &octet;
   5893 	len[1] = sizeof(octet);
   5894 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]);
   5895 	wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]);
   5896 
   5897 	if (aes_siv_decrypt(pkex->z, curve->hash_len,
   5898 			    wrapped_data, wrapped_data_len,
   5899 			    2, addr, len, unwrapped) < 0) {
   5900 		wpa_printf(MSG_DEBUG, "DPP: AES-SIV decryption failed");
   5901 		goto fail;
   5902 	}
   5903 	wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext",
   5904 		    unwrapped, unwrapped_len);
   5905 
   5906 	if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) {
   5907 		wpa_printf(MSG_DEBUG,
   5908 			   "DPP: Invalid attribute in unwrapped data");
   5909 		goto fail;
   5910 	}
   5911 
   5912 	b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY,
   5913 			     &b_key_len);
   5914 	if (!b_key || b_key_len != 2 * curve->prime_len) {
   5915 		wpa_printf(MSG_DEBUG,
   5916 			   "DPP: No valid peer bootstrapping key found");
   5917 		goto fail;
   5918 	}
   5919 	pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key,
   5920 							b_key_len);
   5921 	if (!pkex->peer_bootstrap_key)
   5922 		goto fail;
   5923 	dpp_debug_print_key("DPP: Peer bootstrap public key",
   5924 			    pkex->peer_bootstrap_key);
   5925 
   5926 	/* ECDH: L' = x * B' */
   5927 	ctx = EVP_PKEY_CTX_new(pkex->x, NULL);
   5928 	if (!ctx ||
   5929 	    EVP_PKEY_derive_init(ctx) != 1 ||
   5930 	    EVP_PKEY_derive_set_peer(ctx, pkex->peer_bootstrap_key) != 1 ||
   5931 	    EVP_PKEY_derive(ctx, NULL, &Lx_len) != 1 ||
   5932 	    Lx_len > DPP_MAX_SHARED_SECRET_LEN ||
   5933 	    EVP_PKEY_derive(ctx, Lx, &Lx_len) != 1) {
   5934 		wpa_printf(MSG_ERROR,
   5935 			   "DPP: Failed to derive ECDH shared secret: %s",
   5936 			   ERR_error_string(ERR_get_error(), NULL));
   5937 		goto fail;
   5938 	}
   5939 
   5940 	wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)",
   5941 			Lx, Lx_len);
   5942 
   5943 	/* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */
   5944 	B_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0);
   5945 	X_pub = dpp_get_pubkey_point(pkex->x, 0);
   5946 	Y_pub = dpp_get_pubkey_point(pkex->y, 0);
   5947 	if (!B_pub || !X_pub || !Y_pub)
   5948 		goto fail;
   5949 	addr[0] = pkex->peer_mac;
   5950 	len[0] = ETH_ALEN;
   5951 	addr[1] = wpabuf_head(B_pub);
   5952 	len[1] = wpabuf_len(B_pub) / 2;
   5953 	addr[2] = wpabuf_head(X_pub);
   5954 	len[2] = wpabuf_len(X_pub) / 2;
   5955 	addr[3] = wpabuf_head(Y_pub);
   5956 	len[3] = wpabuf_len(Y_pub) / 2;
   5957 	if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0)
   5958 		goto fail;
   5959 
   5960 	peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG,
   5961 			      &peer_v_len);
   5962 	if (!peer_v || peer_v_len != curve->hash_len ||
   5963 	    os_memcmp(peer_v, v, curve->hash_len) != 0) {
   5964 		wpa_printf(MSG_DEBUG, "DPP: No valid v (R-Auth tag) found");
   5965 		wpa_hexdump(MSG_DEBUG, "DPP: Calculated v'",
   5966 			    v, curve->hash_len);
   5967 		wpa_hexdump(MSG_DEBUG, "DPP: Received v", peer_v, peer_v_len);
   5968 		goto fail;
   5969 	}
   5970 	wpa_printf(MSG_DEBUG, "DPP: Valid v (R-Auth tag) received");
   5971 
   5972 	ret = 0;
   5973 out:
   5974 	wpabuf_free(B_pub);
   5975 	wpabuf_free(X_pub);
   5976 	wpabuf_free(Y_pub);
   5977 	EVP_PKEY_CTX_free(ctx);
   5978 	os_free(unwrapped);
   5979 	return ret;
   5980 fail:
   5981 	goto out;
   5982 }
   5983 
   5984 
   5985 void dpp_pkex_free(struct dpp_pkex *pkex)
   5986 {
   5987 	if (!pkex)
   5988 		return;
   5989 
   5990 	os_free(pkex->identifier);
   5991 	os_free(pkex->code);
   5992 	EVP_PKEY_free(pkex->x);
   5993 	EVP_PKEY_free(pkex->y);
   5994 	EVP_PKEY_free(pkex->peer_bootstrap_key);
   5995 	wpabuf_free(pkex->exchange_req);
   5996 	wpabuf_free(pkex->exchange_resp);
   5997 	os_free(pkex);
   5998 }
   5999