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:
Jouni Malinen 2009-01-22 19:32:58 +02:00 committed by Jouni Malinen
parent 96fa129da9
commit b3ddab2122
4 changed files with 38 additions and 0 deletions

View file

@ -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;
}

View file

@ -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);
/** /**

View file

@ -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");

View file

@ -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;