WPS: Pad DH Public Key and Shared Key to 192 octets
WPS spec is not very specific on the presentation used for the DH values. The Public Key attribute is described to be 192 octets long, so that could be interpreted to imply that other places use fixed length presentation for the DH keys. Change the DH derivation to use fixed length bufferd by zero padding them from beginning if needed. This can resolve infrequent (about 1/256 chance for both Public Key and Shared Key being shorter) interop issues.
This commit is contained in:
parent
96fa129da9
commit
b3ddab2122
4 changed files with 38 additions and 0 deletions
|
@ -160,3 +160,38 @@ struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b)
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* wpabuf_zeropad - Pad buffer with 0x00 octets (prefix) to specified length
|
||||||
|
* @buf: Buffer to be padded
|
||||||
|
* @len: Length for the padded buffer
|
||||||
|
* Returns: wpabuf padded to len octets or %NULL on failure
|
||||||
|
*
|
||||||
|
* If buf is longer than len octets or of same size, it will be returned as-is.
|
||||||
|
* Otherwise a new buffer is allocated and prefixed with 0x00 octets followed
|
||||||
|
* by the source data. The source buffer will be freed on error, i.e., caller
|
||||||
|
* will only be responsible on freeing the returned buffer. If buf is %NULL,
|
||||||
|
* %NULL will be returned.
|
||||||
|
*/
|
||||||
|
struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct wpabuf *ret;
|
||||||
|
size_t blen;
|
||||||
|
|
||||||
|
if (buf == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
blen = wpabuf_len(buf);
|
||||||
|
if (blen >= len)
|
||||||
|
return buf;
|
||||||
|
|
||||||
|
ret = wpabuf_alloc(len);
|
||||||
|
if (ret) {
|
||||||
|
os_memset(wpabuf_put(ret, len - blen), 0, len - blen);
|
||||||
|
wpabuf_put_buf(ret, buf);
|
||||||
|
}
|
||||||
|
wpabuf_free(buf);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ struct wpabuf * wpabuf_dup(const struct wpabuf *src);
|
||||||
void wpabuf_free(struct wpabuf *buf);
|
void wpabuf_free(struct wpabuf *buf);
|
||||||
void * wpabuf_put(struct wpabuf *buf, size_t len);
|
void * wpabuf_put(struct wpabuf *buf, size_t len);
|
||||||
struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b);
|
struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b);
|
||||||
|
struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -27,6 +27,7 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WPS: * Public Key");
|
wpa_printf(MSG_DEBUG, "WPS: * Public Key");
|
||||||
pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), &wps->dh_privkey);
|
pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), &wps->dh_privkey);
|
||||||
|
pubkey = wpabuf_zeropad(pubkey, 192);
|
||||||
if (pubkey == NULL) {
|
if (pubkey == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
|
wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
|
||||||
"Diffie-Hellman handshake");
|
"Diffie-Hellman handshake");
|
||||||
|
|
|
@ -82,6 +82,7 @@ int wps_derive_keys(struct wps_data *wps)
|
||||||
|
|
||||||
dh_shared = dh_derive_shared(pubkey, wps->dh_privkey,
|
dh_shared = dh_derive_shared(pubkey, wps->dh_privkey,
|
||||||
dh_groups_get(WPS_DH_GROUP));
|
dh_groups_get(WPS_DH_GROUP));
|
||||||
|
dh_shared = wpabuf_zeropad(dh_shared, 192);
|
||||||
if (dh_shared == NULL) {
|
if (dh_shared == NULL) {
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key");
|
wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in a new issue