]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS: Pad DH Public Key and Shared Key to 192 octets
authorJouni Malinen <jouni.malinen@atheros.com>
Thu, 22 Jan 2009 17:32:58 +0000 (19:32 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 22 Jan 2009 17:32:58 +0000 (19:32 +0200)
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.

src/utils/wpabuf.c
src/utils/wpabuf.h
src/wps/wps_attr_build.c
src/wps/wps_common.c

index 3719aaeedb36548ffa6bd1f8d857c8cc4a59b65b..e809690b9c674b1c6ab9e2aa5379c0b24fe41f4a 100644 (file)
@@ -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;
+}
index 724412e3157ad6e90d05834d6c44c0e606386f24..5d435ab10ebc883085c8ad8c572b7786bf525128 100644 (file)
@@ -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);
 
 
 /**
index c30e17b3d8d11993075d1eb911497b177773230d..edeff5c58df45a0164df9a4b4c9d70806e30debf 100644 (file)
@@ -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");
index 9273d3749d5afe0d9e2685a0fa502ce75f30e949..050f04305533c0e9f5da132698a1c6df2c964ffe 100644 (file)
@@ -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;