mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-25 00:38:24 -05:00
DPP2: Enterprise provisioning (Enrollee)
Add initial Enrollee functionality for provisioning enterprise (EAP-TLS) configuration object. This commit is handling only the most basic case and a number of TODO items remains to handle more complete CSR generation and config object processing. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
6568e5d203
commit
ace3723d98
121
src/common/dpp.c
121
src/common/dpp.c
@ -829,6 +829,7 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
|
|||||||
const char *tech = "infra";
|
const char *tech = "infra";
|
||||||
const char *dpp_name;
|
const char *dpp_name;
|
||||||
struct wpabuf *buf, *json;
|
struct wpabuf *buf, *json;
|
||||||
|
char *csr = NULL;
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_OPTIONS
|
#ifdef CONFIG_TESTING_OPTIONS
|
||||||
if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) {
|
if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) {
|
||||||
@ -845,6 +846,17 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
|
|||||||
len = 100 + name_len * 6 + 1 + int_array_len(opclasses) * 4;
|
len = 100 + name_len * 6 + 1 + int_array_len(opclasses) * 4;
|
||||||
if (mud_url && mud_url[0])
|
if (mud_url && mud_url[0])
|
||||||
len += 10 + os_strlen(mud_url);
|
len += 10 + os_strlen(mud_url);
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (auth->csr) {
|
||||||
|
size_t csr_len;
|
||||||
|
|
||||||
|
csr = base64_encode_no_lf(wpabuf_head(auth->csr),
|
||||||
|
wpabuf_len(auth->csr), &csr_len);
|
||||||
|
if (!csr)
|
||||||
|
return NULL;
|
||||||
|
len += 30 + csr_len;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
json = wpabuf_alloc(len);
|
json = wpabuf_alloc(len);
|
||||||
if (!json)
|
if (!json)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -871,10 +883,15 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth,
|
|||||||
wpabuf_printf(json, "%s%u", i ? "," : "", opclasses[i]);
|
wpabuf_printf(json, "%s%u", i ? "," : "", opclasses[i]);
|
||||||
json_end_array(json);
|
json_end_array(json);
|
||||||
}
|
}
|
||||||
|
if (csr) {
|
||||||
|
json_value_sep(json);
|
||||||
|
json_add_string(json, "pkcs10", csr);
|
||||||
|
}
|
||||||
json_end_object(json);
|
json_end_object(json);
|
||||||
|
|
||||||
buf = dpp_build_conf_req(auth, wpabuf_head(json));
|
buf = dpp_build_conf_req(auth, wpabuf_head(json));
|
||||||
wpabuf_free(json);
|
wpabuf_free(json);
|
||||||
|
os_free(csr);
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@ -1263,9 +1280,19 @@ void dpp_auth_deinit(struct dpp_authentication *auth)
|
|||||||
|
|
||||||
os_free(conf->connector);
|
os_free(conf->connector);
|
||||||
wpabuf_free(conf->c_sign_key);
|
wpabuf_free(conf->c_sign_key);
|
||||||
|
wpabuf_free(conf->certbag);
|
||||||
|
wpabuf_free(conf->certs);
|
||||||
|
wpabuf_free(conf->cacert);
|
||||||
|
os_free(conf->server_name);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
dpp_free_asymmetric_key(auth->conf_key_pkg);
|
dpp_free_asymmetric_key(auth->conf_key_pkg);
|
||||||
|
os_free(auth->csrattrs);
|
||||||
|
wpabuf_free(auth->csr);
|
||||||
|
wpabuf_free(auth->priv_key);
|
||||||
|
wpabuf_free(auth->cacert);
|
||||||
|
wpabuf_free(auth->certbag);
|
||||||
|
os_free(auth->trusted_eap_server_name);
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
wpabuf_free(auth->net_access_key);
|
wpabuf_free(auth->net_access_key);
|
||||||
dpp_bootstrap_info_free(auth->tmp_own_bi);
|
dpp_bootstrap_info_free(auth->tmp_own_bi);
|
||||||
@ -2459,6 +2486,58 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
static int dpp_parse_cred_dot1x(struct dpp_authentication *auth,
|
||||||
|
struct dpp_config_obj *conf,
|
||||||
|
struct json_token *cred)
|
||||||
|
{
|
||||||
|
struct json_token *ent, *name;
|
||||||
|
|
||||||
|
ent = json_get_member(cred, "entCreds");
|
||||||
|
if (!ent || ent->type != JSON_OBJECT) {
|
||||||
|
dpp_auth_fail(auth, "No entCreds in JSON");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf->certbag = json_get_member_base64(ent, "certBag");
|
||||||
|
if (!conf->certbag) {
|
||||||
|
dpp_auth_fail(auth, "No certBag in JSON");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received certBag", conf->certbag);
|
||||||
|
conf->certs = dpp_pkcs7_certs(conf->certbag);
|
||||||
|
if (!conf->certs) {
|
||||||
|
dpp_auth_fail(auth, "No certificates in certBag");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf->cacert = json_get_member_base64(ent, "caCert");
|
||||||
|
if (conf->cacert)
|
||||||
|
wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received caCert",
|
||||||
|
conf->cacert);
|
||||||
|
|
||||||
|
name = json_get_member(ent, "trustedEapServerName");
|
||||||
|
if (name &&
|
||||||
|
(name->type != JSON_STRING ||
|
||||||
|
has_ctrl_char((const u8 *) name->string,
|
||||||
|
os_strlen(name->string)))) {
|
||||||
|
dpp_auth_fail(auth,
|
||||||
|
"Invalid trustedEapServerName type in JSON");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (name->string) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Received trustedEapServerName: %s",
|
||||||
|
name->string);
|
||||||
|
conf->server_name = os_strdup(name->string);
|
||||||
|
if (!conf->server_name)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
|
||||||
const char * dpp_akm_str(enum dpp_akm akm)
|
const char * dpp_akm_str(enum dpp_akm akm)
|
||||||
{
|
{
|
||||||
switch (akm) {
|
switch (akm) {
|
||||||
@ -2678,6 +2757,12 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth,
|
|||||||
(auth->peer_version >= 2 && dpp_akm_legacy(conf->akm))) {
|
(auth->peer_version >= 2 && dpp_akm_legacy(conf->akm))) {
|
||||||
if (dpp_parse_cred_dpp(auth, conf, cred) < 0)
|
if (dpp_parse_cred_dpp(auth, conf, cred) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
} else if (conf->akm == DPP_AKM_DOT1X) {
|
||||||
|
if (dpp_parse_cred_dot1x(auth, conf, cred) < 0 ||
|
||||||
|
dpp_parse_cred_dpp(auth, conf, cred) < 0)
|
||||||
|
goto fail;
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
} else {
|
} else {
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
|
wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s",
|
||||||
token->string);
|
token->string);
|
||||||
@ -2694,6 +2779,20 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
static u8 * dpp_get_csr_attrs(const u8 *attrs, size_t attrs_len, size_t *len)
|
||||||
|
{
|
||||||
|
const u8 *b64;
|
||||||
|
u16 b64_len;
|
||||||
|
|
||||||
|
b64 = dpp_get_attr(attrs, attrs_len, DPP_ATTR_CSR_ATTR_REQ, &b64_len);
|
||||||
|
if (!b64)
|
||||||
|
return NULL;
|
||||||
|
return base64_decode((const char *) b64, b64_len, len);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
|
||||||
int dpp_conf_resp_rx(struct dpp_authentication *auth,
|
int dpp_conf_resp_rx(struct dpp_authentication *auth,
|
||||||
const struct wpabuf *resp)
|
const struct wpabuf *resp)
|
||||||
{
|
{
|
||||||
@ -2771,6 +2870,28 @@ int dpp_conf_resp_rx(struct dpp_authentication *auth,
|
|||||||
}
|
}
|
||||||
auth->conf_resp_status = status[0];
|
auth->conf_resp_status = status[0];
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
|
wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]);
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (status[0] == DPP_STATUS_CSR_NEEDED) {
|
||||||
|
u8 *csrattrs;
|
||||||
|
size_t csrattrs_len;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Configurator requested CSR");
|
||||||
|
|
||||||
|
csrattrs = dpp_get_csr_attrs(unwrapped, unwrapped_len,
|
||||||
|
&csrattrs_len);
|
||||||
|
if (!csrattrs) {
|
||||||
|
dpp_auth_fail(auth,
|
||||||
|
"Missing or invalid CSR Attributes Request attribute");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpa_hexdump(MSG_DEBUG, "DPP: CsrAttrs", csrattrs, csrattrs_len);
|
||||||
|
os_free(auth->csrattrs);
|
||||||
|
auth->csrattrs = csrattrs;
|
||||||
|
auth->csrattrs_len = csrattrs_len;
|
||||||
|
ret = -2;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
if (status[0] != DPP_STATUS_OK) {
|
if (status[0] != DPP_STATUS_OK) {
|
||||||
dpp_auth_fail(auth, "Configurator rejected configuration");
|
dpp_auth_fail(auth, "Configurator rejected configuration");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -312,6 +312,10 @@ struct dpp_authentication {
|
|||||||
int psk_set;
|
int psk_set;
|
||||||
enum dpp_akm akm;
|
enum dpp_akm akm;
|
||||||
struct wpabuf *c_sign_key;
|
struct wpabuf *c_sign_key;
|
||||||
|
struct wpabuf *certbag;
|
||||||
|
struct wpabuf *certs;
|
||||||
|
struct wpabuf *cacert;
|
||||||
|
char *server_name;
|
||||||
} conf_obj[DPP_MAX_CONF_OBJ];
|
} conf_obj[DPP_MAX_CONF_OBJ];
|
||||||
unsigned int num_conf_obj;
|
unsigned int num_conf_obj;
|
||||||
struct dpp_asymmetric_key *conf_key_pkg;
|
struct dpp_asymmetric_key *conf_key_pkg;
|
||||||
@ -322,7 +326,11 @@ struct dpp_authentication {
|
|||||||
int akm_use_selector;
|
int akm_use_selector;
|
||||||
int configurator_set;
|
int configurator_set;
|
||||||
u8 transaction_id;
|
u8 transaction_id;
|
||||||
|
u8 *csrattrs;
|
||||||
|
size_t csrattrs_len;
|
||||||
bool waiting_csr;
|
bool waiting_csr;
|
||||||
|
struct wpabuf *csr;
|
||||||
|
struct wpabuf *priv_key; /* DER-encoded private key used for csr */
|
||||||
bool waiting_cert;
|
bool waiting_cert;
|
||||||
char *trusted_eap_server_name;
|
char *trusted_eap_server_name;
|
||||||
struct wpabuf *cacert;
|
struct wpabuf *cacert;
|
||||||
@ -606,6 +614,9 @@ struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key,
|
|||||||
int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len);
|
int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len);
|
||||||
void dpp_pfs_free(struct dpp_pfs *pfs);
|
void dpp_pfs_free(struct dpp_pfs *pfs);
|
||||||
|
|
||||||
|
struct wpabuf * dpp_build_csr(struct dpp_authentication *auth);
|
||||||
|
struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7);
|
||||||
|
|
||||||
struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
|
struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
|
||||||
const char *uri);
|
const char *uri);
|
||||||
struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
|
struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp,
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/asn1.h>
|
#include <openssl/asn1.h>
|
||||||
#include <openssl/asn1t.h>
|
#include <openssl/asn1t.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
|
||||||
#include "utils/common.h"
|
#include "utils/common.h"
|
||||||
#include "utils/base64.h"
|
#include "utils/base64.h"
|
||||||
@ -2664,6 +2665,161 @@ void dpp_pfs_free(struct dpp_pfs *pfs)
|
|||||||
os_free(pfs);
|
os_free(pfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct wpabuf * dpp_build_csr(struct dpp_authentication *auth)
|
||||||
|
{
|
||||||
|
X509_REQ *req = NULL;
|
||||||
|
struct wpabuf *buf = NULL;
|
||||||
|
unsigned char *der;
|
||||||
|
int der_len;
|
||||||
|
EVP_PKEY *key;
|
||||||
|
const EVP_MD *sign_md;
|
||||||
|
unsigned int hash_len = auth->curve->hash_len;
|
||||||
|
EC_KEY *eckey;
|
||||||
|
BIO *out = NULL;
|
||||||
|
|
||||||
|
/* TODO: use auth->csrattrs */
|
||||||
|
|
||||||
|
/* TODO: support generation of a new private key if csrAttrs requests
|
||||||
|
* a specific group to be used */
|
||||||
|
key = auth->own_protocol_key;
|
||||||
|
|
||||||
|
eckey = EVP_PKEY_get1_EC_KEY(key);
|
||||||
|
if (!eckey)
|
||||||
|
goto fail;
|
||||||
|
der = NULL;
|
||||||
|
der_len = i2d_ECPrivateKey(eckey, &der);
|
||||||
|
if (der_len <= 0)
|
||||||
|
goto fail;
|
||||||
|
wpabuf_free(auth->priv_key);
|
||||||
|
auth->priv_key = wpabuf_alloc_copy(der, der_len);
|
||||||
|
OPENSSL_free(der);
|
||||||
|
if (!auth->priv_key)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
req = X509_REQ_new();
|
||||||
|
if (!req || !X509_REQ_set_pubkey(req, key))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
/* TODO: hash func selection based on csrAttrs */
|
||||||
|
if (hash_len == SHA256_MAC_LEN) {
|
||||||
|
sign_md = EVP_sha256();
|
||||||
|
} else if (hash_len == SHA384_MAC_LEN) {
|
||||||
|
sign_md = EVP_sha384();
|
||||||
|
} else if (hash_len == SHA512_MAC_LEN) {
|
||||||
|
sign_md = EVP_sha512();
|
||||||
|
} else {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!X509_REQ_sign(req, key, sign_md))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
der = NULL;
|
||||||
|
der_len = i2d_X509_REQ(req, &der);
|
||||||
|
if (der_len < 0)
|
||||||
|
goto fail;
|
||||||
|
buf = wpabuf_alloc_copy(der, der_len);
|
||||||
|
OPENSSL_free(der);
|
||||||
|
|
||||||
|
wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
BIO_free_all(out);
|
||||||
|
X509_REQ_free(req);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7)
|
||||||
|
{
|
||||||
|
#ifdef OPENSSL_IS_BORINGSSL
|
||||||
|
CBS pkcs7_cbs;
|
||||||
|
#else /* OPENSSL_IS_BORINGSSL */
|
||||||
|
PKCS7 *p7 = NULL;
|
||||||
|
const unsigned char *p = wpabuf_head(pkcs7);
|
||||||
|
#endif /* OPENSSL_IS_BORINGSSL */
|
||||||
|
STACK_OF(X509) *certs;
|
||||||
|
int i, num;
|
||||||
|
BIO *out = NULL;
|
||||||
|
size_t rlen;
|
||||||
|
struct wpabuf *pem = NULL;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
#ifdef OPENSSL_IS_BORINGSSL
|
||||||
|
certs = sk_X509_new_null();
|
||||||
|
if (!certs)
|
||||||
|
goto fail;
|
||||||
|
CBS_init(&pkcs7_cbs, wpabuf_head(pkcs7), wpabuf_len(pkcs7));
|
||||||
|
if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s",
|
||||||
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#else /* OPENSSL_IS_BORINGSSL */
|
||||||
|
p7 = d2i_PKCS7(NULL, &p, wpabuf_len(pkcs7));
|
||||||
|
if (!p7) {
|
||||||
|
wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s",
|
||||||
|
ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (OBJ_obj2nid(p7->type)) {
|
||||||
|
case NID_pkcs7_signed:
|
||||||
|
certs = p7->d.sign->cert;
|
||||||
|
break;
|
||||||
|
case NID_pkcs7_signedAndEnveloped:
|
||||||
|
certs = p7->d.signed_and_enveloped->cert;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
certs = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* OPENSSL_IS_BORINGSSL */
|
||||||
|
|
||||||
|
if (!certs || ((num = sk_X509_num(certs)) == 0)) {
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"DPP: No certificates found in PKCS#7 object");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
out = BIO_new(BIO_s_mem());
|
||||||
|
if (!out)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
X509 *cert = sk_X509_value(certs, i);
|
||||||
|
|
||||||
|
PEM_write_bio_X509(out, cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
rlen = BIO_ctrl_pending(out);
|
||||||
|
pem = wpabuf_alloc(rlen);
|
||||||
|
if (!pem)
|
||||||
|
goto fail;
|
||||||
|
res = BIO_read(out, wpabuf_put(pem, 0), rlen);
|
||||||
|
if (res <= 0) {
|
||||||
|
wpabuf_free(pem);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
wpabuf_put(pem, res);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
#ifdef OPENSSL_IS_BORINGSSL
|
||||||
|
if (certs)
|
||||||
|
sk_X509_pop_free(certs, X509_free);
|
||||||
|
#else /* OPENSSL_IS_BORINGSSL */
|
||||||
|
PKCS7_free(p7);
|
||||||
|
#endif /* OPENSSL_IS_BORINGSSL */
|
||||||
|
if (out)
|
||||||
|
BIO_free_all(out);
|
||||||
|
|
||||||
|
return pem;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,6 +179,9 @@ extern "C" {
|
|||||||
#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
|
#define DPP_EVENT_CONNECTOR "DPP-CONNECTOR "
|
||||||
#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY "
|
#define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY "
|
||||||
#define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY "
|
#define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY "
|
||||||
|
#define DPP_EVENT_SERVER_NAME "DPP-SERVER-NAME "
|
||||||
|
#define DPP_EVENT_CERTBAG "DPP-CERTBAG "
|
||||||
|
#define DPP_EVENT_CACERT "DPP-CACERT "
|
||||||
#define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR "
|
#define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR "
|
||||||
#define DPP_EVENT_NETWORK_ID "DPP-NETWORK-ID "
|
#define DPP_EVENT_NETWORK_ID "DPP-NETWORK-ID "
|
||||||
#define DPP_EVENT_CONFIGURATOR_ID "DPP-CONFIGURATOR-ID "
|
#define DPP_EVENT_CONFIGURATOR_ID "DPP-CONFIGURATOR-ID "
|
||||||
|
@ -49,6 +49,7 @@ wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s,
|
|||||||
#ifdef CONFIG_DPP2
|
#ifdef CONFIG_DPP2
|
||||||
static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
|
static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx,
|
||||||
void *timeout_ctx);
|
void *timeout_ctx);
|
||||||
|
static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s);
|
||||||
#endif /* CONFIG_DPP2 */
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||||
@ -1218,6 +1219,106 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (conf->akm == DPP_AKM_DOT1X) {
|
||||||
|
int i;
|
||||||
|
char name[100], blobname[128];
|
||||||
|
struct wpa_config_blob *blob;
|
||||||
|
|
||||||
|
ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X |
|
||||||
|
WPA_KEY_MGMT_IEEE8021X_SHA256 |
|
||||||
|
WPA_KEY_MGMT_IEEE8021X_SHA256;
|
||||||
|
ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL;
|
||||||
|
|
||||||
|
if (conf->cacert) {
|
||||||
|
/* caCert is DER-encoded X.509v3 certificate for the
|
||||||
|
* server certificate if that is different from the
|
||||||
|
* trust root included in certBag. */
|
||||||
|
/* TODO: ssid->eap.cert.ca_cert */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf->certs) {
|
||||||
|
wpa_hexdump_buf(MSG_INFO, "JKM:certs",
|
||||||
|
conf->certs);
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
os_snprintf(name, sizeof(name), "dpp-certs-%d",
|
||||||
|
i);
|
||||||
|
if (!wpa_config_get_blob(wpa_s->conf, name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
blob = os_zalloc(sizeof(*blob));
|
||||||
|
if (!blob)
|
||||||
|
goto fail;
|
||||||
|
blob->len = wpabuf_len(conf->certs);
|
||||||
|
blob->name = os_strdup(name);
|
||||||
|
blob->data = os_malloc(blob->len);
|
||||||
|
if (!blob->name || !blob->data) {
|
||||||
|
wpa_config_free_blob(blob);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
os_memcpy(blob->data, wpabuf_head(conf->certs),
|
||||||
|
blob->len);
|
||||||
|
os_snprintf(blobname, sizeof(blobname), "blob://%s",
|
||||||
|
name);
|
||||||
|
wpa_config_set_blob(wpa_s->conf, blob);
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s",
|
||||||
|
name);
|
||||||
|
ssid->eap.cert.client_cert = os_strdup(blobname);
|
||||||
|
if (!ssid->eap.cert.client_cert)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* TODO: ssid->eap.identity from own certificate */
|
||||||
|
if (wpa_config_set(ssid, "identity", "\"dpp-ent\"",
|
||||||
|
0) < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auth->priv_key) {
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
os_snprintf(name, sizeof(name), "dpp-key-%d",
|
||||||
|
i);
|
||||||
|
if (!wpa_config_get_blob(wpa_s->conf, name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_hexdump_buf(MSG_INFO, "JKM:privkey",
|
||||||
|
auth->priv_key);
|
||||||
|
blob = os_zalloc(sizeof(*blob));
|
||||||
|
if (!blob)
|
||||||
|
goto fail;
|
||||||
|
blob->len = wpabuf_len(auth->priv_key);
|
||||||
|
blob->name = os_strdup(name);
|
||||||
|
blob->data = os_malloc(blob->len);
|
||||||
|
if (!blob->name || !blob->data) {
|
||||||
|
wpa_config_free_blob(blob);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
os_memcpy(blob->data, wpabuf_head(auth->priv_key),
|
||||||
|
blob->len);
|
||||||
|
os_snprintf(blobname, sizeof(blobname), "blob://%s",
|
||||||
|
name);
|
||||||
|
wpa_config_set_blob(wpa_s->conf, blob);
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s",
|
||||||
|
name);
|
||||||
|
ssid->eap.cert.private_key = os_strdup(blobname);
|
||||||
|
if (!ssid->eap.cert.private_key)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf->server_name) {
|
||||||
|
ssid->eap.cert.domain_suffix_match =
|
||||||
|
os_strdup(conf->server_name);
|
||||||
|
if (!ssid->eap.cert.domain_suffix_match)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Use entCreds::eapMethods */
|
||||||
|
if (wpa_config_set(ssid, "eap", "TLS", 0) < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
|
os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len);
|
||||||
wpa_s->dpp_last_ssid_len = conf->ssid_len;
|
wpa_s->dpp_last_ssid_len = conf->ssid_len;
|
||||||
|
|
||||||
@ -1346,6 +1447,32 @@ static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (conf->certbag) {
|
||||||
|
char *b64;
|
||||||
|
|
||||||
|
b64 = base64_encode_no_lf(wpabuf_head(conf->certbag),
|
||||||
|
wpabuf_len(conf->certbag), NULL);
|
||||||
|
if (b64)
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64);
|
||||||
|
os_free(b64);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf->cacert) {
|
||||||
|
char *b64;
|
||||||
|
|
||||||
|
b64 = base64_encode_no_lf(wpabuf_head(conf->cacert),
|
||||||
|
wpabuf_len(conf->cacert), NULL);
|
||||||
|
if (b64)
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64);
|
||||||
|
os_free(b64);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf->server_name)
|
||||||
|
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s",
|
||||||
|
conf->server_name);
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
return wpas_dpp_process_config(wpa_s, auth, conf);
|
return wpas_dpp_process_config(wpa_s, auth, conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1376,6 +1503,29 @@ static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s = eloop_ctx;
|
||||||
|
struct dpp_authentication *auth = wpa_s->dpp_auth;
|
||||||
|
|
||||||
|
if (!auth || !auth->csrattrs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: Build CSR");
|
||||||
|
wpabuf_free(auth->csr);
|
||||||
|
/* TODO: Additional information needed for CSR based on csrAttrs */
|
||||||
|
auth->csr = dpp_build_csr(auth);
|
||||||
|
if (!auth->csr) {
|
||||||
|
dpp_auth_deinit(wpa_s->dpp_auth);
|
||||||
|
wpa_s->dpp_auth = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpas_dpp_start_gas_client(wpa_s);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
|
||||||
|
|
||||||
static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
||||||
enum gas_query_result result,
|
enum gas_query_result result,
|
||||||
const struct wpabuf *adv_proto,
|
const struct wpabuf *adv_proto,
|
||||||
@ -1420,7 +1570,15 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dpp_conf_resp_rx(auth, resp) < 0) {
|
res = dpp_conf_resp_rx(auth, resp);
|
||||||
|
#ifdef CONFIG_DPP2
|
||||||
|
if (res == -2) {
|
||||||
|
wpa_printf(MSG_DEBUG, "DPP: CSR needed");
|
||||||
|
eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_DPP2 */
|
||||||
|
if (res < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
|
wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -3115,6 +3273,7 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
|
|||||||
eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
|
eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL);
|
||||||
eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
|
eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout,
|
||||||
wpa_s, NULL);
|
wpa_s, NULL);
|
||||||
|
eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL);
|
||||||
dpp_pfs_free(wpa_s->dpp_pfs);
|
dpp_pfs_free(wpa_s->dpp_pfs);
|
||||||
wpa_s->dpp_pfs = NULL;
|
wpa_s->dpp_pfs = NULL;
|
||||||
wpas_dpp_chirp_stop(wpa_s);
|
wpas_dpp_chirp_stop(wpa_s);
|
||||||
|
Loading…
Reference in New Issue
Block a user