]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
More forceful clearing of stack memory with keys
authorJouni Malinen <j@w1.fi>
Sat, 25 May 2019 21:47:17 +0000 (00:47 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 26 May 2019 13:11:56 +0000 (16:11 +0300)
gcc 8.3.0 was apparently clever enough to optimize away the previously
used os_memset() to explicitly clear a stack buffer that contains keys
when that clearing happened just before returning from the function.
Since memset_s() is not exactly portable (or commonly available yet..),
use a less robust mechanism that is still pretty likely to prevent
current compilers from optimizing the explicit clearing of the memory
away.

Signed-off-by: Jouni Malinen <j@w1.fi>
25 files changed:
src/ap/wpa_auth.c
src/ap/wpa_auth_ft.c
src/crypto/sha1-internal.c
src/crypto/sha1-prf.c
src/crypto/sha1-tlsprf.c
src/crypto/sha1-tprf.c
src/crypto/sha1.c
src/crypto/sha256-kdf.c
src/crypto/sha256-prf.c
src/crypto/sha384-kdf.c
src/crypto/sha384-prf.c
src/crypto/sha512-kdf.c
src/crypto/sha512-prf.c
src/crypto/tls_openssl.c
src/crypto/tls_wolfssl.c
src/eap_peer/eap_eke.c
src/eap_peer/eap_leap.c
src/eap_peer/eap_peap.c
src/eap_peer/eap_pwd.c
src/eap_server/eap_server_peap.c
src/eap_server/eap_server_pwd.c
src/rsn_supp/wpa.c
src/rsn_supp/wpa_ft.c
src/utils/common.c
src/utils/common.h

index f5e5779ab5ff24154de32fce48715ec639cbc99e..e5a777bbbce1f3914254d927bedf31f1c98d0ccf 100644 (file)
@@ -934,6 +934,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data,
 
        os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN);
        os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
+       forced_memzero(&PTK, sizeof(PTK));
        sm->PTK_valid = TRUE;
 
        return 0;
@@ -1407,6 +1408,8 @@ static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
 #endif /* CONFIG_SHA256 */
 #endif /* CONFIG_SHA384 */
 
+       forced_memzero(data, sizeof(data));
+
        return ret;
 }
 
@@ -2046,7 +2049,7 @@ SM_STATE(WPA_PTK, INITPMK)
                sm->Disconnect = TRUE;
                return;
        }
-       os_memset(msk, 0, sizeof(msk));
+       forced_memzero(msk, sizeof(msk));
 
        sm->req_replay_counter_used = 0;
        /* IEEE 802.11i does not set keyRun to FALSE, but not doing this
@@ -2285,12 +2288,12 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
                wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name",
                            pmk_r0_name, WPA_PMK_NAME_LEN);
                wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
-               os_memset(fils_ft, 0, sizeof(fils_ft));
+               forced_memzero(fils_ft, sizeof(fils_ft));
 
                res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
                                             sm->addr, sm->pmk_r1_name,
                                             use_sha384);
-               os_memset(pmk_r0, 0, PMK_LEN_MAX);
+               forced_memzero(pmk_r0, PMK_LEN_MAX);
                if (res < 0)
                        return -1;
                wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
@@ -2308,7 +2311,7 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
                               sm->wpa_key_mgmt, sm->fils_key_auth_sta,
                               sm->fils_key_auth_ap,
                               &sm->fils_key_auth_len);
-       os_memset(ick, 0, sizeof(ick));
+       forced_memzero(ick, sizeof(ick));
 
        /* Store nonces for (Re)Association Request/Response frame processing */
        os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN);
@@ -3030,6 +3033,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
        sm->MICVerified = TRUE;
 
        os_memcpy(&sm->PTK, &PTK, sizeof(PTK));
+       forced_memzero(&PTK, sizeof(PTK));
        sm->PTK_valid = TRUE;
 }
 
index d1a983e0b3ce0dd3dd01d18c9b690d51048a4879..696f8d5fa49ba4fb61dadfd5daae3346c1fee645 100644 (file)
@@ -2226,6 +2226,7 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
                return NULL;
        }
 
+       forced_memzero(keybuf, sizeof(keybuf));
        *len = subelem_len;
        return subelem;
 }
@@ -3567,7 +3568,7 @@ static int wpa_ft_rrb_build_r0(const u8 *key, const size_t key_len,
                               pmk_r0->vlan, src_addr, type,
                               packet, packet_len);
 
-       os_memset(pmk_r1, 0, sizeof(pmk_r1));
+       forced_memzero(pmk_r1, sizeof(pmk_r1));
 
        return ret;
 }
@@ -3893,10 +3894,7 @@ static int wpa_ft_rrb_rx_r1(struct wpa_authenticator *wpa_auth,
 
        ret = 0;
 out:
-       if (plain) {
-               os_memset(plain, 0, plain_len);
-               os_free(plain);
-       }
+       bin_clear_free(plain, plain_len);
 
        return ret;
 
index a4917070f196b2cbf6b73752d3508298608a83e2..ffa04df017e37817dbf506b45bd989c0c3c61ae8 100644 (file)
@@ -224,7 +224,7 @@ void SHA1Transform(u32 state[5], const unsigned char buffer[64])
        /* Wipe variables */
        a = b = c = d = e = 0;
 #ifdef SHA1HANDSOFF
-       os_memset(block, 0, 64);
+       forced_memzero(block, 64);
 #endif
 }
 
@@ -300,7 +300,7 @@ void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
        os_memset(context->buffer, 0, 64);
        os_memset(context->state, 0, 20);
        os_memset(context->count, 0, 8);
-       os_memset(finalcount, 0, 8);
+       forced_memzero(finalcount, sizeof(finalcount));
 }
 
 /* ===== end - public domain SHA1 implementation ===== */
index 4b2d1373067f8be1c99d8d67bede45df98509690..13851494fb92372f8cb97ae22cd28b9f0cfed4c9 100644 (file)
@@ -61,7 +61,7 @@ int sha1_prf(const u8 *key, size_t key_len, const char *label,
                }
                counter++;
        }
-       os_memset(hash, 0, sizeof(hash));
+       forced_memzero(hash, sizeof(hash));
 
        return 0;
 }
index a11649a933eb373f015a732a0619be153898bb2a..5e8d15920c3d77334b8d5cc2b568e5b11b33e397 100644 (file)
@@ -92,10 +92,10 @@ int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label,
                SHA1_pos++;
        }
 
-       os_memset(A_MD5, 0, MD5_MAC_LEN);
-       os_memset(P_MD5, 0, MD5_MAC_LEN);
-       os_memset(A_SHA1, 0, SHA1_MAC_LEN);
-       os_memset(P_SHA1, 0, SHA1_MAC_LEN);
+       forced_memzero(A_MD5, MD5_MAC_LEN);
+       forced_memzero(P_MD5, MD5_MAC_LEN);
+       forced_memzero(A_SHA1, SHA1_MAC_LEN);
+       forced_memzero(P_SHA1, SHA1_MAC_LEN);
 
        return 0;
 }
index 562510f8937d07b316eed5f78b15cc10542e5b5f..c3acf19750d5a857ccaa28533f1bec3c6cb40ba1 100644 (file)
@@ -66,7 +66,7 @@ int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
                len[0] = SHA1_MAC_LEN;
        }
 
-       os_memset(hash, 0, SHA1_MAC_LEN);
+       forced_memzero(hash, SHA1_MAC_LEN);
 
        return 0;
 }
index 8fce139408f191a77e2ac1fbc4b08a3a81709560..76d7a68f26109155318f3ef136a80170065dde67 100644 (file)
@@ -86,7 +86,8 @@ int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
        _addr[1] = mac;
        _len[1] = SHA1_MAC_LEN;
        ret = sha1_vector(2, _addr, _len, mac);
-       os_memset(k_pad, 0, sizeof(k_pad));
+       forced_memzero(k_pad, sizeof(k_pad));
+       forced_memzero(tk, sizeof(tk));
        return ret;
 }
 
index af7d954d8a440b102ff6cc4a8c6103c26b972474..5a6b744552d6a7c9e4c5445535d44d32c81c7605 100644 (file)
@@ -69,7 +69,7 @@ int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
 
                if (iter == 255) {
                        os_memset(out, 0, outlen);
-                       os_memset(T, 0, SHA256_MAC_LEN);
+                       forced_memzero(T, SHA256_MAC_LEN);
                        return -1;
                }
                iter++;
@@ -77,11 +77,11 @@ int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
                if (hmac_sha256_vector(secret, secret_len, 4, addr, len, T) < 0)
                {
                        os_memset(out, 0, outlen);
-                       os_memset(T, 0, SHA256_MAC_LEN);
+                       forced_memzero(T, SHA256_MAC_LEN);
                        return -1;
                }
        }
 
-       os_memset(T, 0, SHA256_MAC_LEN);
+       forced_memzero(T, SHA256_MAC_LEN);
        return 0;
 }
index 722cad6bdeb4d1e25837a676ed681422f704b0a0..d665a9983cf8a798cbc86dca8070018f8e9d1402 100644 (file)
@@ -102,7 +102,7 @@ int sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
                buf[pos - 1] &= mask;
        }
 
-       os_memset(hash, 0, sizeof(hash));
+       forced_memzero(hash, sizeof(hash));
 
        return 0;
 }
index 1d196279086e0ee4ca17c9f93e05c555f6bd535b..babcb9ed04c92fd8282ac4b1bbfe580ed1b1e229 100644 (file)
@@ -69,7 +69,7 @@ int hmac_sha384_kdf(const u8 *secret, size_t secret_len,
 
                if (iter == 255) {
                        os_memset(out, 0, outlen);
-                       os_memset(T, 0, SHA384_MAC_LEN);
+                       forced_memzero(T, SHA384_MAC_LEN);
                        return -1;
                }
                iter++;
@@ -77,11 +77,11 @@ int hmac_sha384_kdf(const u8 *secret, size_t secret_len,
                if (hmac_sha384_vector(secret, secret_len, 4, addr, len, T) < 0)
                {
                        os_memset(out, 0, outlen);
-                       os_memset(T, 0, SHA384_MAC_LEN);
+                       forced_memzero(T, SHA384_MAC_LEN);
                        return -1;
                }
        }
 
-       os_memset(T, 0, SHA384_MAC_LEN);
+       forced_memzero(T, SHA384_MAC_LEN);
        return 0;
 }
index 03e3cb353a3d0e92a8297e479faa2311a7604ec5..420e78c380cd918e7c64b5d76ddba8a73ccf91c2 100644 (file)
@@ -102,7 +102,7 @@ int sha384_prf_bits(const u8 *key, size_t key_len, const char *label,
                buf[pos - 1] &= mask;
        }
 
-       os_memset(hash, 0, sizeof(hash));
+       forced_memzero(hash, sizeof(hash));
 
        return 0;
 }
index 8b71f9b0e4f9d04c79bf3752e21607d2fd1bdd85..5bde66485e6d04d3adf8651939e022cdbbd1932d 100644 (file)
@@ -69,7 +69,7 @@ int hmac_sha512_kdf(const u8 *secret, size_t secret_len,
 
                if (iter == 255) {
                        os_memset(out, 0, outlen);
-                       os_memset(T, 0, SHA512_MAC_LEN);
+                       forced_memzero(T, SHA512_MAC_LEN);
                        return -1;
                }
                iter++;
@@ -77,11 +77,11 @@ int hmac_sha512_kdf(const u8 *secret, size_t secret_len,
                if (hmac_sha512_vector(secret, secret_len, 4, addr, len, T) < 0)
                {
                        os_memset(out, 0, outlen);
-                       os_memset(T, 0, SHA512_MAC_LEN);
+                       forced_memzero(T, SHA512_MAC_LEN);
                        return -1;
                }
        }
 
-       os_memset(T, 0, SHA512_MAC_LEN);
+       forced_memzero(T, SHA512_MAC_LEN);
        return 0;
 }
index 3b2ad889d6efbf38df92c57d92b529dc80246a6c..e48cf5f0566260ff715c699120b501051b6773e3 100644 (file)
@@ -102,7 +102,7 @@ int sha512_prf_bits(const u8 *key, size_t key_len, const char *label,
                buf[pos - 1] &= mask;
        }
 
-       os_memset(hash, 0, sizeof(hash));
+       forced_memzero(hash, sizeof(hash));
 
        return 0;
 }
index bf24074215c3359aeb58e47a45b07da41b39aa08..c71979f8bf39a79ff544021bc1361b0e792c3c97 100644 (file)
@@ -3999,7 +3999,7 @@ int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
                                    _out, skip + out_len) == 0) {
                ret = 0;
        }
-       os_memset(master_key, 0, sizeof(master_key));
+       forced_memzero(master_key, sizeof(master_key));
        os_free(rnd);
        if (ret == 0)
                os_memcpy(out, _out + skip, out_len);
index e9cb425c115a0270046da6dfcf549e597b5d61b8..83704fffa4114a49dd1410d7b4a35479202273c7 100644 (file)
@@ -2044,7 +2044,7 @@ int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
                                       _out, skip + out_len);
        }
 
-       os_memset(master_key, 0, master_key_len);
+       forced_memzero(master_key, master_key_len);
        if (ret == 0)
                os_memcpy(out, _out + skip, out_len);
        bin_clear_free(tmp_out, skip + out_len);
index 0de7d6cbf49bd069e1709f51bc37f5d31a9175ff..534af262e88a3fc36e057a72bb3618d1e4feded1 100644 (file)
@@ -414,7 +414,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm,
         */
        if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) {
                wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH");
-               os_memset(key, 0, sizeof(key));
+               forced_memzero(key, sizeof(key));
                return eap_eke_build_fail(data, ret, id,
                                          EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
        }
@@ -422,7 +422,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm,
        if (eap_eke_shared_secret(&data->sess, key, data->dh_priv, dhcomp) < 0)
        {
                wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret");
-               os_memset(key, 0, sizeof(key));
+               forced_memzero(key, sizeof(key));
                return eap_eke_build_fail(data, ret, id,
                                          EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
        }
@@ -431,7 +431,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm,
                                 data->serverid, data->serverid_len,
                                 data->peerid, data->peerid_len) < 0) {
                wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki");
-               os_memset(key, 0, sizeof(key));
+               forced_memzero(key, sizeof(key));
                return eap_eke_build_fail(data, ret, id,
                                          EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
        }
@@ -442,7 +442,7 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm,
                                 data->sess.dhcomp_len + data->sess.pnonce_len,
                                 EAP_EKE_COMMIT);
        if (resp == NULL) {
-               os_memset(key, 0, sizeof(key));
+               forced_memzero(key, sizeof(key));
                return eap_eke_build_fail(data, ret, id,
                                          EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
        }
@@ -452,11 +452,11 @@ static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm,
        if (eap_eke_dhcomp(&data->sess, key, pub, rpos) < 0) {
                wpabuf_free(resp);
                wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_P");
-               os_memset(key, 0, sizeof(key));
+               forced_memzero(key, sizeof(key));
                return eap_eke_build_fail(data, ret, id,
                                          EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
        }
-       os_memset(key, 0, sizeof(key));
+       forced_memzero(key, sizeof(key));
 
        wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_P",
                    rpos, data->sess.dhcomp_len);
index 233b9eeb1f83ffb16c6ec8e456d0544388baeb96..34758e02114998e37f2fe9534a1250d0b09b9ba0 100644 (file)
@@ -390,8 +390,8 @@ static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len)
        wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN);
        *len = LEAP_KEY_LEN;
 
-       os_memset(pw_hash, 0, sizeof(pw_hash));
-       os_memset(pw_hash_hash, 0, sizeof(pw_hash_hash));
+       forced_memzero(pw_hash, sizeof(pw_hash));
+       forced_memzero(pw_hash_hash, sizeof(pw_hash_hash));
 
        return key;
 }
index 8dcf7cc2926f88e70a112586b4b1472178f6a2d2..6453afe2fc57fabab7d51f4ae3e79bc3fd1a3c15 100644 (file)
@@ -295,7 +295,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
        res = peap_prfplus(data->peap_version, tk, 40,
                           "Inner Methods Compound Keys",
                           isk, sizeof(isk), imck, sizeof(imck));
-       os_memset(isk, 0, sizeof(isk));
+       forced_memzero(isk, sizeof(isk));
        if (res < 0)
                return -1;
        wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
@@ -305,7 +305,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
        wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
        os_memcpy(data->cmk, imck + 40, 20);
        wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
-       os_memset(imck, 0, sizeof(imck));
+       forced_memzero(imck, sizeof(imck));
 
        return 0;
 }
@@ -1267,7 +1267,7 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
                os_memcpy(key, csk, EAP_TLS_KEY_LEN);
                wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
                            key, EAP_TLS_KEY_LEN);
-               os_memset(csk, 0, sizeof(csk));
+               forced_memzero(csk, sizeof(csk));
        } else
                os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
 
index 76fcad4a50e0d6dcf8abef6f47bac0c47b9a7284..6cd72e0c13916a905f35d6b25ea1283b3f5b9a4f 100644 (file)
@@ -362,7 +362,7 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
                                               data->password_len, pwhash);
                        if (res == 0)
                                res = hash_nt_password_hash(pwhash, pwhashhash);
-                       os_memset(pwhash, 0, sizeof(pwhash));
+                       forced_memzero(pwhash, sizeof(pwhash));
                }
 
                if (res) {
@@ -514,8 +514,8 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
                                       data->id_server, data->id_server_len,
                                       data->id_peer, data->id_peer_len,
                                       data->token);
-       os_memset(pwhashhash, 0, sizeof(pwhashhash));
-       os_memset(salthashpwd, 0, sizeof(salthashpwd));
+       forced_memzero(pwhashhash, sizeof(pwhashhash));
+       forced_memzero(salthashpwd, sizeof(salthashpwd));
        if (res) {
                wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute PWE");
                eap_pwd_state(data, FAILURE);
index 92c0e5ec971633214ddfea5316dc80ee56015e16..5e125acf7f932960f3f04497539723085b8994c5 100644 (file)
@@ -362,7 +362,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
        res = peap_prfplus(data->peap_version, tk, 40,
                           "Inner Methods Compound Keys",
                           isk, sizeof(isk), imck, sizeof(imck));
-       os_memset(isk, 0, sizeof(isk));
+       forced_memzero(isk, sizeof(isk));
        if (res < 0) {
                os_free(tk);
                return -1;
@@ -376,7 +376,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
        wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
        os_memcpy(data->cmk, imck + 40, 20);
        wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
-       os_memset(imck, 0, sizeof(imck));
+       forced_memzero(imck, sizeof(imck));
 
        return 0;
 }
@@ -1326,7 +1326,7 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
                                   "key");
                }
 
-               os_memset(csk, 0, sizeof(csk));
+               forced_memzero(csk, sizeof(csk));
 
                return eapKeyData;
        }
index e720a28c85bac6838cb52fd5a4c574b890055675..a8087c1d8a639690bb5371bde1fbd95cf0edf842 100644 (file)
@@ -632,7 +632,7 @@ static void eap_pwd_process_id_resp(struct eap_sm *sm,
                                       data->id_server, data->id_server_len,
                                       data->id_peer, data->id_peer_len,
                                       (u8 *) &data->token);
-       os_memset(pwhashhash, 0, sizeof(pwhashhash));
+       forced_memzero(pwhashhash, sizeof(pwhashhash));
        if (res) {
                wpa_printf(MSG_INFO, "EAP-PWD (server): unable to compute "
                           "PWE");
index 8accb9c80d9ee47d033c2539a30c57325d415bb6..c929e8194a03270d0cc614c42e06a330aefd6df3 100644 (file)
@@ -334,7 +334,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
                                os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN);
                                sm->xxkey_len = PMK_LEN;
                        }
-                       os_memset(buf, 0, sizeof(buf));
+                       forced_memzero(buf, sizeof(buf));
                        if (sm->proto == WPA_PROTO_RSN &&
                            wpa_key_mgmt_ft(sm->key_mgmt)) {
                                struct rsn_pmksa_cache_entry *sa = NULL;
@@ -649,7 +649,7 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
                os_memcpy(buf, &ptk->tk[16], 8);
                os_memcpy(&ptk->tk[16], &ptk->tk[24], 8);
                os_memcpy(&ptk->tk[24], buf, 8);
-               os_memset(buf, 0, sizeof(buf));
+               forced_memzero(buf, sizeof(buf));
        }
        sm->tptk_set = 1;
 
@@ -923,7 +923,7 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
                        wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
                                "WPA: Failed to set GTK to the driver "
                                "(Group only)");
-                       os_memset(gtk_buf, 0, sizeof(gtk_buf));
+                       forced_memzero(gtk_buf, sizeof(gtk_buf));
                        return -1;
                }
        } else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr,
@@ -933,10 +933,10 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
                        "WPA: Failed to set GTK to "
                        "the driver (alg=%d keylen=%d keyidx=%d)",
                        gd->alg, gd->gtk_len, gd->keyidx);
-               os_memset(gtk_buf, 0, sizeof(gtk_buf));
+               forced_memzero(gtk_buf, sizeof(gtk_buf));
                return -1;
        }
-       os_memset(gtk_buf, 0, sizeof(gtk_buf));
+       forced_memzero(gtk_buf, sizeof(gtk_buf));
 
        if (wnm_sleep) {
                sm->gtk_wnm_sleep.gtk_len = gd->gtk_len;
@@ -1042,10 +1042,10 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
             wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0))) {
                wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
                        "RSN: Failed to install GTK");
-               os_memset(&gd, 0, sizeof(gd));
+               forced_memzero(&gd, sizeof(gd));
                return -1;
        }
-       os_memset(&gd, 0, sizeof(gd));
+       forced_memzero(&gd, sizeof(gd));
 
        return 0;
 }
@@ -1714,12 +1714,12 @@ static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
                os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len);
                os_memcpy(gd->gtk, key_data, key_data_len);
                if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) {
-                       os_memset(ek, 0, sizeof(ek));
+                       forced_memzero(ek, sizeof(ek));
                        wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
                                "WPA: RC4 failed");
                        return -1;
                }
-               os_memset(ek, 0, sizeof(ek));
+               forced_memzero(ek, sizeof(ek));
 #endif /* CONFIG_NO_RC4 */
        } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
                if (maxkeylen % 8) {
@@ -1868,7 +1868,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
        if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0) ||
            wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
                goto failed;
-       os_memset(&gd, 0, sizeof(gd));
+       forced_memzero(&gd, sizeof(gd));
 
        if (rekey) {
                wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying "
@@ -1887,7 +1887,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
        return;
 
 failed:
-       os_memset(&gd, 0, sizeof(gd));
+       forced_memzero(&gd, sizeof(gd));
        wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
 }
 
@@ -2001,12 +2001,12 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
                os_memcpy(ek, key->key_iv, 16);
                os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len);
                if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) {
-                       os_memset(ek, 0, sizeof(ek));
+                       forced_memzero(ek, sizeof(ek));
                        wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
                                "WPA: RC4 failed");
                        return -1;
                }
-               os_memset(ek, 0, sizeof(ek));
+               forced_memzero(ek, sizeof(ek));
 #endif /* CONFIG_NO_RC4 */
        } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
                   ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
@@ -3446,12 +3446,12 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
                wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
                                gd.gtk, gd.gtk_len);
                if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 1)) {
-                       os_memset(&gd, 0, sizeof(gd));
+                       forced_memzero(&gd, sizeof(gd));
                        wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
                                   "WNM mode");
                        return -1;
                }
-               os_memset(&gd, 0, sizeof(gd));
+               forced_memzero(&gd, sizeof(gd));
 #ifdef CONFIG_IEEE80211W
        } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
                const struct wpa_igtk_kde *igtk;
@@ -3881,7 +3881,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
                                       dh_ss ? wpabuf_head(dh_ss) : NULL,
                                       dh_ss ? wpabuf_len(dh_ss) : 0,
                                       sm->pmk, &sm->pmk_len);
-               os_memset(rmsk, 0, sizeof(rmsk));
+               forced_memzero(rmsk, sizeof(rmsk));
 
                /* Don't use DHss in PTK derivation if PMKSA caching is not
                 * used. */
@@ -3956,7 +3956,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
                               sm->fils_key_auth_ap,
                               &sm->fils_key_auth_len);
        wpabuf_free(pub);
-       os_memset(ick, 0, sizeof(ick));
+       forced_memzero(ick, sizeof(ick));
        return res;
 fail:
        wpabuf_free(pub);
@@ -4480,9 +4480,11 @@ int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
 
        wpa_printf(MSG_DEBUG, "FILS: Auth+Assoc completed successfully");
        sm->fils_completed = 1;
+       forced_memzero(&gd, sizeof(gd));
 
        return 0;
 fail:
+       forced_memzero(&gd, sizeof(gd));
        return -1;
 }
 
@@ -4694,7 +4696,7 @@ int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid,
        else if (group == 21)
                res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info,
                                      os_strlen(info), sm->pmk, hash_len);
-       os_memset(prk, 0, SHA512_MAC_LEN);
+       forced_memzero(prk, SHA512_MAC_LEN);
        if (res < 0) {
                sm->pmk_len = 0;
                return -1;
index 41592511ed198655054d0172214ea65aca3320fb..46ffdca67a774405c7ba47a64a5fca14ea5f2f53 100644 (file)
@@ -828,10 +828,10 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem,
                           igtk_elem + 2, 6, igtk, igtk_len) < 0) {
                wpa_printf(MSG_WARNING, "WPA: Failed to set IGTK to the "
                           "driver.");
-               os_memset(igtk, 0, sizeof(igtk));
+               forced_memzero(igtk, sizeof(igtk));
                return -1;
        }
-       os_memset(igtk, 0, sizeof(igtk));
+       forced_memzero(igtk, sizeof(igtk));
 
        return 0;
 }
index 836fef190c54e0aedc344d2073c46eecf487c49b..27bf435d96910f56cedf505d88b5aa3f8fb7ba63 100644 (file)
@@ -970,7 +970,7 @@ void str_clear_free(char *str)
 {
        if (str) {
                size_t len = os_strlen(str);
-               os_memset(str, 0, len);
+               forced_memzero(str, len);
                os_free(str);
        }
 }
@@ -979,7 +979,7 @@ void str_clear_free(char *str)
 void bin_clear_free(void *bin, size_t len)
 {
        if (bin) {
-               os_memset(bin, 0, len);
+               forced_memzero(bin, len);
                os_free(bin);
        }
 }
@@ -1259,3 +1259,22 @@ char * get_param(const char *cmd, const char *param)
        val[len] = '\0';
        return val;
 }
+
+
+/* Try to prevent most compilers from optimizing out clearing of memory that
+ * becomes unaccessible after this function is called. This is mostly the case
+ * for clearing local stack variables at the end of a function. This is not
+ * exactly perfect, i.e., someone could come up with a compiler that figures out
+ * the pointer is pointing to memset and then end up optimizing the call out, so
+ * try go a bit further by storing the first octet (now zero) to make this even
+ * a bit more difficult to optimize out. Once memset_s() is available, that
+ * could be used here instead. */
+static void * (* const volatile memset_func)(void *, int, size_t) = memset;
+static u8 forced_memzero_val;
+
+void forced_memzero(void *ptr, size_t len)
+{
+       memset_func(ptr, 0, len);
+       if (len)
+               forced_memzero_val = ((u8 *) ptr)[0];
+}
index 36f67fa7171e1d75abce3a5020957051daa3aaf1..17411451d2ed385478974df3551e63eb3324fd1a 100644 (file)
@@ -570,6 +570,8 @@ int str_starts(const char *str, const char *start);
 u8 rssi_to_rcpi(int rssi);
 char * get_param(const char *cmd, const char *param);
 
+void forced_memzero(void *ptr, size_t len);
+
 /*
  * gcc 4.4 ends up generating strict-aliasing warnings about some very common
  * networking socket uses that do not really result in a real problem and