diff --git a/src/utils/wpabuf.c b/src/utils/wpabuf.c index 3719aaeed..e809690b9 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 724412e31..5d435ab10 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 c30e17b3d..edeff5c58 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 9273d3749..050f04305 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;