aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-01-22 17:32:58 (GMT)
committerJouni Malinen <j@w1.fi>2009-02-08 10:14:30 (GMT)
commit2e93bf80626fe294015608c6f17a83ca90646b8f (patch)
tree51c1f2cd78c3a096a8294f1d3fc002021f20d94f /src
parent8c64f7fc2a96173316831845adf5e4e656d7b0c6 (diff)
downloadhostap-06-2e93bf80626fe294015608c6f17a83ca90646b8f.zip
hostap-06-2e93bf80626fe294015608c6f17a83ca90646b8f.tar.gz
hostap-06-2e93bf80626fe294015608c6f17a83ca90646b8f.tar.bz2
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. (cherry picked from commit b3ddab21223455c147bb18334745eddc5773b487)
Diffstat (limited to 'src')
-rw-r--r--src/utils/wpabuf.c35
-rw-r--r--src/utils/wpabuf.h1
-rw-r--r--src/wps/wps_attr_build.c1
-rw-r--r--src/wps/wps_common.c1
4 files changed, 38 insertions, 0 deletions
diff --git a/src/utils/wpabuf.c b/src/utils/wpabuf.c
index 3719aae..e809690 100644
--- a/src/utils/wpabuf.c
+++ b/src/utils/wpabuf.c
@@ -160,3 +160,38 @@ struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b)
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;
+}
diff --git a/src/utils/wpabuf.h b/src/utils/wpabuf.h
index 724412e..5d435ab 100644
--- a/src/utils/wpabuf.h
+++ b/src/utils/wpabuf.h
@@ -37,6 +37,7 @@ struct wpabuf * wpabuf_dup(const struct wpabuf *src);
void wpabuf_free(struct wpabuf *buf);
void * wpabuf_put(struct wpabuf *buf, size_t len);
struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b);
+struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len);
/**
diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c
index c30e17b..edeff5c 100644
--- a/src/wps/wps_attr_build.c
+++ b/src/wps/wps_attr_build.c
@@ -27,6 +27,7 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
wpa_printf(MSG_DEBUG, "WPS: * Public Key");
pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), &wps->dh_privkey);
+ pubkey = wpabuf_zeropad(pubkey, 192);
if (pubkey == NULL) {
wpa_printf(MSG_DEBUG, "WPS: Failed to initialize "
"Diffie-Hellman handshake");
diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c
index 9273d37..050f043 100644
--- a/src/wps/wps_common.c
+++ b/src/wps/wps_common.c
@@ -82,6 +82,7 @@ int wps_derive_keys(struct wps_data *wps)
dh_shared = dh_derive_shared(pubkey, wps->dh_privkey,
dh_groups_get(WPS_DH_GROUP));
+ dh_shared = wpabuf_zeropad(dh_shared, 192);
if (dh_shared == NULL) {
wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key");
return -1;