mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-25 00:38:24 -05:00
DPP2: Validate CSR on Configurator before forwarding to CA/RA
Parse the received CSR, verify that it has been signed correctly, and verify that the challengePassword is present and matches the derived cp. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
c98db9f1f8
commit
3b60f11741
@ -1694,6 +1694,11 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
|
||||
size_t len[1];
|
||||
enum dpp_status_error status;
|
||||
|
||||
if (auth->force_conf_resp_status != DPP_STATUS_OK) {
|
||||
status = auth->force_conf_resp_status;
|
||||
goto forced_status;
|
||||
}
|
||||
|
||||
if (netrole == DPP_NETROLE_CONFIGURATOR) {
|
||||
#ifdef CONFIG_DPP2
|
||||
env_data = dpp_build_enveloped_data(auth);
|
||||
@ -1715,6 +1720,7 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce,
|
||||
status = DPP_STATUS_CSR_NEEDED;
|
||||
else
|
||||
status = DPP_STATUS_CONFIGURE_FAILURE;
|
||||
forced_status:
|
||||
auth->conf_resp_status = status;
|
||||
|
||||
/* { E-nonce, configurationObject[, sendConnStatus]}ke */
|
||||
@ -2040,6 +2046,12 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
||||
char *txt;
|
||||
|
||||
wpa_hexdump_buf(MSG_DEBUG, "DPP: CertificateRequest", cert_req);
|
||||
if (dpp_validate_csr(auth, cert_req) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: CSR is not valid");
|
||||
auth->force_conf_resp_status = DPP_STATUS_CSR_BAD;
|
||||
goto cont;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA");
|
||||
txt = base64_encode_no_lf(wpabuf_head(cert_req),
|
||||
wpabuf_len(cert_req), NULL);
|
||||
if (!txt)
|
||||
@ -2051,6 +2063,7 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start,
|
||||
auth->waiting_cert = true;
|
||||
goto fail;
|
||||
}
|
||||
cont:
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole,
|
||||
|
@ -250,6 +250,7 @@ struct dpp_authentication {
|
||||
enum dpp_connector_key reconfig_connector_key;
|
||||
enum dpp_status_error auth_resp_status;
|
||||
enum dpp_status_error conf_resp_status;
|
||||
enum dpp_status_error force_conf_resp_status;
|
||||
u8 peer_mac_addr[ETH_ALEN];
|
||||
u8 i_nonce[DPP_MAX_NONCE_LEN];
|
||||
u8 r_nonce[DPP_MAX_NONCE_LEN];
|
||||
@ -617,6 +618,7 @@ 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);
|
||||
int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr);
|
||||
|
||||
struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp,
|
||||
const char *uri);
|
||||
|
@ -2844,6 +2844,125 @@ fail:
|
||||
return pem;
|
||||
}
|
||||
|
||||
|
||||
int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr)
|
||||
{
|
||||
X509_REQ *req;
|
||||
const unsigned char *pos;
|
||||
EVP_PKEY *pkey;
|
||||
int res, loc, ret = -1;
|
||||
X509_ATTRIBUTE *attr;
|
||||
ASN1_TYPE *type;
|
||||
ASN1_STRING *str;
|
||||
unsigned char *utf8 = NULL;
|
||||
unsigned char *cp = NULL;
|
||||
size_t cp_len;
|
||||
u8 exp_cp[DPP_CP_LEN];
|
||||
unsigned int hash_len = auth->curve->hash_len;
|
||||
|
||||
pos = wpabuf_head(csr);
|
||||
req = d2i_X509_REQ(NULL, &pos, wpabuf_len(csr));
|
||||
if (!req) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Failed to parse CSR");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pkey = X509_REQ_get_pubkey(req);
|
||||
if (!pkey) {
|
||||
wpa_printf(MSG_DEBUG, "DPP: Failed to get public key from CSR");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = X509_REQ_verify(req, pkey);
|
||||
EVP_PKEY_free(pkey);
|
||||
if (res != 1) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: CSR does not have a valid signature");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
loc = X509_REQ_get_attr_by_NID(req, NID_pkcs9_challengePassword, -1);
|
||||
if (loc < 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: CSR does not include challengePassword");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
attr = X509_REQ_get_attr(req, loc);
|
||||
if (!attr) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Could not get challengePassword attribute");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
type = X509_ATTRIBUTE_get0_type(attr, 0);
|
||||
if (!type) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Could not get challengePassword attribute type");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = ASN1_TYPE_get(type);
|
||||
/* This is supposed to be UTF8String, but allow other strings as well
|
||||
* since challengePassword is using ASCII (base64 encoded). */
|
||||
if (res != V_ASN1_UTF8STRING && res != V_ASN1_PRINTABLESTRING &&
|
||||
res != V_ASN1_IA5STRING) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Unexpected challengePassword attribute type %d",
|
||||
res);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
str = X509_ATTRIBUTE_get0_data(attr, 0, res, NULL);
|
||||
if (!str) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Could not get ASN.1 string for challengePassword");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = ASN1_STRING_to_UTF8(&utf8, str);
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Could not get UTF8 version of challengePassword");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cp = base64_decode((const char *) utf8, res, &cp_len);
|
||||
OPENSSL_free(utf8);
|
||||
if (!cp) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Could not base64 decode challengePassword");
|
||||
goto fail;
|
||||
}
|
||||
if (cp_len != DPP_CP_LEN) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: Unexpected cp length (%zu) in CSR challengePassword",
|
||||
cp_len);
|
||||
goto fail;
|
||||
}
|
||||
wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword",
|
||||
cp, cp_len);
|
||||
|
||||
/* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */
|
||||
if (dpp_hkdf_expand(hash_len, auth->bk, hash_len,
|
||||
"CSR challengePassword", exp_cp, DPP_CP_LEN) < 0)
|
||||
goto fail;
|
||||
wpa_hexdump_key(MSG_DEBUG,
|
||||
"DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)",
|
||||
exp_cp, DPP_CP_LEN);
|
||||
if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"DPP: CSR challengePassword does not match calculated cp");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
os_free(cp);
|
||||
X509_REQ_free(req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DPP2 */
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user