Browse Source

WPS: Use os_memcmp_const() for hash/password comparisons

This makes the implementation less likely to provide useful timing
information to potential attackers from comparisons of information
received from a remote device and private material known only by the
authorized devices.

Signed-off-by: Jouni Malinen <j@w1.fi>
Jouni Malinen 10 years ago
parent
commit
ce9c9bcc38
3 changed files with 12 additions and 11 deletions
  1. 2 2
      src/wps/wps_attr_process.c
  2. 4 4
      src/wps/wps_enrollee.c
  3. 6 5
      src/wps/wps_registrar.c

+ 2 - 2
src/wps/wps_attr_process.c

@@ -41,7 +41,7 @@ int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator,
 	len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN;
 	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash);
 
-	if (os_memcmp(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) {
+	if (os_memcmp_const(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator");
 		return -1;
 	}
@@ -71,7 +71,7 @@ int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg,
 	}
 
 	hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash);
-	if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) {
+	if (os_memcmp_const(hash, key_wrap_auth, WPS_KWA_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: Invalid KWA");
 		return -1;
 	}

+ 4 - 4
src/wps/wps_enrollee.c

@@ -525,8 +525,8 @@ static int wps_process_pubkey(struct wps_data *wps, const u8 *pk,
 	if (wps->peer_pubkey_hash_set) {
 		u8 hash[WPS_HASH_LEN];
 		sha256_vector(1, &pk, &pk_len, hash);
-		if (os_memcmp(hash, wps->peer_pubkey_hash,
-			      WPS_OOB_PUBKEY_HASH_LEN) != 0) {
+		if (os_memcmp_const(hash, wps->peer_pubkey_hash,
+				    WPS_OOB_PUBKEY_HASH_LEN) != 0) {
 			wpa_printf(MSG_ERROR, "WPS: Public Key hash mismatch");
 			wpa_hexdump(MSG_DEBUG, "WPS: Received public key",
 				    pk, pk_len);
@@ -605,7 +605,7 @@ static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1)
 	len[3] = wpabuf_len(wps->dh_pubkey_r);
 	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
 
-	if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
+	if (os_memcmp_const(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does "
 			   "not match with the pre-committed value");
 		wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
@@ -645,7 +645,7 @@ static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2)
 	len[3] = wpabuf_len(wps->dh_pubkey_r);
 	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
 
-	if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
+	if (os_memcmp_const(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does "
 			   "not match with the pre-committed value");
 		wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;

+ 6 - 5
src/wps/wps_registrar.c

@@ -826,7 +826,7 @@ static int wps_registrar_invalidate_wildcard_pin(struct wps_registrar *reg,
 	{
 		if (dev_pw && pin->pin &&
 		    (dev_pw_len != pin->pin_len ||
-		     os_memcmp(dev_pw, pin->pin, dev_pw_len) != 0))
+		     os_memcmp_const(dev_pw, pin->pin, dev_pw_len) != 0))
 			continue; /* different PIN */
 		if (pin->wildcard_uuid) {
 			wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID",
@@ -2211,7 +2211,7 @@ static int wps_process_e_snonce1(struct wps_data *wps, const u8 *e_snonce1)
 	len[3] = wpabuf_len(wps->dh_pubkey_r);
 	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
 
-	if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
+	if (os_memcmp_const(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does "
 			   "not match with the pre-committed value");
 		wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE;
@@ -2251,7 +2251,7 @@ static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2)
 	len[3] = wpabuf_len(wps->dh_pubkey_r);
 	hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash);
 
-	if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
+	if (os_memcmp_const(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) {
 		wpa_printf(MSG_DEBUG, "WPS: E-Hash2 derived from E-S2 does "
 			   "not match with the pre-committed value");
 		wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e);
@@ -2591,8 +2591,9 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
 
 			addr[0] = attr->public_key;
 			sha256_vector(1, addr, &attr->public_key_len, hash);
-			if (os_memcmp(hash, wps->nfc_pw_token->pubkey_hash,
-				      WPS_OOB_PUBKEY_HASH_LEN) != 0) {
+			if (os_memcmp_const(hash,
+					    wps->nfc_pw_token->pubkey_hash,
+					    WPS_OOB_PUBKEY_HASH_LEN) != 0) {
 				wpa_printf(MSG_ERROR, "WPS: Public Key hash "
 					   "mismatch");
 				wps->state = SEND_M2D;