]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE-PK: Update design for fingerprint encoding into password
authorJouni Malinen <jouni@codeaurora.org>
Wed, 5 Aug 2020 14:44:32 +0000 (17:44 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 5 Aug 2020 19:05:20 +0000 (22:05 +0300)
Update the SAE-PK implementation to match the changes in the protocol
design:
- allow only Sec values 3 and 5 and encode this as a single bit field
  with multiple copies
- add a checksum character

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
hostapd/sae_pk_gen.c
src/common/common_module_tests.c
src/common/sae.c
src/common/sae.h
src/common/sae_pk.c
tests/hwsim/test_sae_pk.py
tests/hwsim/test_sigma_dut.py

index 6570e9ed99230b1bf7cab20f1044fa1b285d8b2a..c31eff75b538a00a9d6ba476a5c67198fed152db 100644 (file)
@@ -25,11 +25,15 @@ int main(int argc, char *argv[])
        char *b64 = NULL, *pw = NULL, *pos, *src;
        int sec, j;
        int ret = -1;
-       u8 hash[SAE_MAX_HASH_LEN], fingerprint[SAE_MAX_HASH_LEN];
+       u8 hash[SAE_MAX_HASH_LEN];
+       char hash_hex[2 * SAE_MAX_HASH_LEN + 1];
+       u8 pw_base_bin[SAE_MAX_HASH_LEN];
+       u8 *dst;
        int group;
        size_t hash_len;
        unsigned long long i, expected;
        char m_hex[2 * SAE_PK_M_LEN + 1];
+       u32 sec_1b, val20;
 
        wpa_debug_level = MSG_INFO;
        if (os_program_init() < 0)
@@ -37,15 +41,17 @@ int main(int argc, char *argv[])
 
        if (argc != 4) {
                fprintf(stderr,
-                       "usage: sae_pk_gen <DER ECPrivateKey file> <Sec:2..5> <SSID>\n");
+                       "usage: sae_pk_gen <DER ECPrivateKey file> <Sec:3|5> <SSID>\n");
                goto fail;
        }
 
        sec = atoi(argv[2]);
-       if (sec < 2 || sec > 5) {
-               fprintf(stderr, "Invalid Sec value (allowed range: 2..5)\n");
+       if (sec != 3 && sec != 5) {
+               fprintf(stderr,
+                       "Invalid Sec value (allowed values: 3 and 5)\n");
                goto fail;
        }
+       sec_1b = sec == 3;
        expected = 1;
        for (j = 0; j < sec; j++)
                expected *= 256;
@@ -106,7 +112,7 @@ int main(int argc, char *argv[])
                        goto fail;
                }
                if (hash[0] == 0 && hash[1] == 0) {
-                       if (sec == 2 || (hash[2] & 0xf0) == 0)
+                       if ((hash[2] & 0xf0) == 0)
                                fprintf(stderr, "\r%3.2f%%",
                                        100.0 * (double) i / (double) expected);
                        for (j = 2; j < sec; j++) {
@@ -119,18 +125,14 @@ int main(int argc, char *argv[])
                inc_byte_array(m, SAE_PK_M_LEN);
        }
 
-       fprintf(stderr, "\nFound a valid hash in %llu iterations\n", i);
-       wpa_hexdump(MSG_DEBUG, "Valid hash", hash, hash_len);
-       fingerprint[0] = (sec - 2) << 6 | hash[sec] >> 2;
-       for (i = 1; i < hash_len - sec; i++)
-               fingerprint[i] = hash[sec + i - 1] << 6 | hash[sec + i] >> 2;
-       wpa_hexdump(MSG_DEBUG, "Fingerprint part for password",
-                   fingerprint, hash_len - sec);
+       if (wpa_snprintf_hex(m_hex, sizeof(m_hex), m, SAE_PK_M_LEN) < 0 ||
+           wpa_snprintf_hex(hash_hex, sizeof(hash_hex), hash, hash_len) < 0)
+               goto fail;
+       fprintf(stderr, "\nFound a valid hash in %llu iterations: %s\n",
+               i + 1, hash_hex);
 
        b64 = base64_encode(der, der_len, NULL);
-       pw = sae_pk_base32_encode(fingerprint, (hash_len - sec) * 8 - 2);
-       if (!b64 || !pw ||
-           wpa_snprintf_hex(m_hex, sizeof(m_hex), m, SAE_PK_M_LEN) < 0)
+       if (!b64)
                goto fail;
        src = pos = b64;
        while (*src) {
@@ -140,10 +142,44 @@ int main(int argc, char *argv[])
        }
        *pos = '\0';
 
+       /* Skip 8*Sec bits and add Sec_1b as the every 20th bit starting with
+        * one. */
+       os_memset(pw_base_bin, 0, sizeof(pw_base_bin));
+       dst = pw_base_bin;
+       for (j = 0; j < 8 * (int) hash_len / 20; j++) {
+               val20 = sae_pk_get_be19(hash + sec);
+               val20 |= sec_1b << 19;
+               sae_pk_buf_shift_left_19(hash + sec, hash_len - sec);
+
+               if (j & 1) {
+                       *dst |= (val20 >> 16) & 0x0f;
+                       dst++;
+                       *dst++ = (val20 >> 8) & 0xff;
+                       *dst++ = val20 & 0xff;
+               } else {
+                       *dst++ = (val20 >> 12) & 0xff;
+                       *dst++ = (val20 >> 4) & 0xff;
+                       *dst = (val20 << 4) & 0xf0;
+               }
+       }
+       if (wpa_snprintf_hex(hash_hex, sizeof(hash_hex),
+                            pw_base_bin, hash_len - sec) >= 0)
+               fprintf(stderr, "PasswordBase binary data for base32: %s",
+                       hash_hex);
+
+       pw = sae_pk_base32_encode(pw_base_bin, 20 * 3 - 5);
+       if (!pw)
+               goto fail;
+
        printf("# SAE-PK password/M/private key for Sec=%d.\n", sec);
-       printf("# The password can be truncated from right to improve\n");
-       printf("# usability at the cost of security.\n");
        printf("sae_password=%s|pk=%s:%s\n", pw, m_hex, b64);
+       printf("# Longer passwords can be used for improved security at the cost of usability:\n");
+       for (j = 4; j <= ((int) hash_len * 8 + 5 - 8 * sec) / 19; j++) {
+               os_free(pw);
+               pw = sae_pk_base32_encode(pw_base_bin, 20 * j - 5);
+               if (pw)
+                       printf("# %s\n", pw);
+       }
 
        ret = 0;
 fail:
index 2af179b42dc66d566b7c3b243bb22edaf16c3ed9..00308d41e6d288ee1dda0586cb5c847aa0907d76 100644 (file)
@@ -551,19 +551,14 @@ fail:
 static int sae_pk_tests(void)
 {
 #ifdef CONFIG_SAE_PK
-       const char *invalid[] = { "a2bc-de3f-ghi4-", "a2bcde3fghi4", "", NULL };
+       const char *invalid[] = { "a2bc-de3f-ghim-", "a2bcde3fghim", "", NULL };
        struct {
                const char *pw;
                const u8 *val;
        } valid[] = {
-               { "a2bc-de3f-ghi4", (u8 *) "\x06\x82\x21\x93\x65\x31\xd1\xc0" },
-               { "aaaa-aaaa-aaaa-a",
-                 (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
-               { "aaaa-aaaa-aaaa", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x00" },
-               { "7777-7777-777", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe" },
-               { "7777-7777-7777", (u8 *) "\xff\xff\xff\xff\xff\xff\xff\xf0" },
-               { "7777-7777-7777-7",
-                 (u8 *) "\xff\xff\xff\xff\xff\xff\xff\xff\x80" },
+               { "a2bc-de3f-ghim", (u8 *) "\x06\x82\x21\x93\x65\x31\xd0\xc0" },
+               { "aaaa-aaaa-aaaj", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x90" },
+               { "7777-7777-777f", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe\x50" },
                { NULL, NULL }
        };
        int i;
@@ -617,7 +612,7 @@ static int sae_pk_tests(void)
                }
                os_free(res);
 
-               b32 = sae_pk_base32_encode(val, bits);
+               b32 = sae_pk_base32_encode(val, bits - 5);
                if (!b32) {
                        wpa_printf(MSG_ERROR,
                                   "SAE-PK: Failed to encode password '%s'",
index 77f3a0e8c13b15c479928eab2cd5efead99acd97..72b5f3fabc1956a3ead6a5346efc7aa87662cb6e 100644 (file)
@@ -112,9 +112,6 @@ void sae_clear_temp_data(struct sae_data *sae)
        wpabuf_free(tmp->own_rejected_groups);
        wpabuf_free(tmp->peer_rejected_groups);
        os_free(tmp->pw_id);
-#ifdef CONFIG_SAE_PK
-       bin_clear_free(tmp->pw, tmp->pw_len);
-#endif /* CONFIG_SAE_PK */
        bin_clear_free(tmp, sizeof(*tmp));
        sae->tmp = NULL;
 }
index ee3c662c589da8c0141c3cd44b7ebec1fd566788..2243c0f339b0beb3b0b6d8af0bbea8bdb8fe8b68 100644 (file)
@@ -70,9 +70,11 @@ struct sae_temporary_data {
        const struct sae_pk *ap_pk;
        u8 own_addr[ETH_ALEN];
        u8 peer_addr[ETH_ALEN];
-       u8 *pw;
-       size_t pw_len;
+       u8 fingerprint[SAE_MAX_HASH_LEN];
+       size_t fingerprint_bytes;
+       size_t fingerprint_bits;
        size_t lambda;
+       unsigned int sec;
        u8 ssid[32];
        size_t ssid_len;
 #ifdef CONFIG_TESTING_OPTIONS
@@ -164,5 +166,7 @@ struct sae_pk * sae_parse_pk(const char *val);
 int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf);
 int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len);
 int sae_hash(size_t hash_len, const u8 *data, size_t len, u8 *hash);
+u32 sae_pk_get_be19(const u8 *buf);
+void sae_pk_buf_shift_left_19(u8 *buf, size_t len);
 
 #endif /* SAE_H */
index e839bde4e4d7f000b95ab6490ae06696265abf71..df79e5f2c3b0edd8a3a2d4c9794f73c6f9a42505 100644 (file)
 static const char *sae_pk_base32_table = "abcdefghijklmnopqrstuvwxyz234567";
 
 
+static const u8 d_mult_table[] = {
+        0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+       16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+        1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,
+       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16,
+        2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,
+       18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17,
+        3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,
+       19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18,
+        4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,
+       20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19,
+        5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,
+       21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20,
+        6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,
+       22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21,
+        7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,
+       23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22,
+        8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,
+       24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23,
+        9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,
+       25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+       10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+       26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+       11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10,
+       27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+       12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
+       28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+       13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,
+       29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+       14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,
+       30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+       15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+       31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+       16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
+        0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,
+       17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18,
+        1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,
+       18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19,
+        2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,
+       19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20,
+        3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,
+       20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21,
+        4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,
+       21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22,
+        5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,
+       22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23,
+        6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,
+       23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24,
+        7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,
+       24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25,
+        8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,
+       25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26,
+        9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,
+       26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27,
+       10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11,
+       27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28,
+       11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12,
+       28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29,
+       12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13,
+       29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30,
+       13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14,
+       30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31,
+       14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15,
+       31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
+       15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0
+};
+
+static const u8 d_perm_table[] = {
+        7,  2,  1, 30, 16, 20, 27, 11, 31,  6,  8, 13, 29,  5, 10, 21,
+       22,  3, 24,  0, 23, 25, 12,  9, 28, 14,  4, 15, 17, 18, 19, 26
+};
+
+
+static u8 d_permute(u8 val, unsigned int iter)
+{
+       if (iter == 0)
+               return val;
+       return d_permute(d_perm_table[val], iter - 1);
+}
+
+
+static u8 d_invert(u8 val)
+{
+       if (val > 0 && val < 16)
+               return 16 - val;
+       return val;
+}
+
+
+static char d_check_char(const char *str, size_t len)
+{
+       size_t i;
+       u8 val = 0;
+       u8 dtable[256];
+       unsigned int iter = 1;
+       int j;
+
+       os_memset(dtable, 0x80, 256);
+       for (i = 0; sae_pk_base32_table[i]; i++)
+               dtable[(u8) sae_pk_base32_table[i]] = i;
+
+       for (j = len - 1; j >= 0; j--) {
+               u8 c, p;
+
+               c = dtable[(u8) str[j]];
+               if (c == 0x80)
+                       continue;
+               p = d_permute(c, iter);
+               iter++;
+               val = d_mult_table[val * 32 + p];
+       }
+
+       return sae_pk_base32_table[d_invert(val)];
+}
+
+
 bool sae_pk_valid_password(const char *pw)
 {
-       int pos, sec;
-       const char *idx;
-       size_t pw_len = os_strlen(pw);
-
-       /* Check whether the password is long enough to meet the minimum
-        * required resistance to preimage attacks. This makes it less likely to
-        * recognize non-SAE-PK passwords as suitable for SAE-PK. */
-       if (pw_len < 1)
-               return false;
-       /* Fetch Sec from the two MSBs */
-       idx = os_strchr(sae_pk_base32_table, pw[0]);
-       if (!idx)
+       int pos;
+       size_t i, pw_len = os_strlen(pw);
+       u8 sec_1b;
+       u8 dtable[256];
+
+       os_memset(dtable, 0x80, 256);
+       for (i = 0; sae_pk_base32_table[i]; i++)
+               dtable[(u8) sae_pk_base32_table[i]] = i;
+
+       /* SAE-PK password has at least three four character components
+        * separated by hyphens. */
+       if (pw_len < 14 || pw_len % 5 != 4) {
+               wpa_printf(MSG_DEBUG, "SAE-PK: Not a valid password (length)");
                return false;
-       sec = (((u8) ((idx - sae_pk_base32_table) & 0x1f)) >> 3) + 2;
-       if ((sec == 2 && pw_len < 14) ||
-           (sec == 3 && pw_len < 13) ||
-           (sec == 4 && pw_len < 11) ||
-           (sec == 5 && pw_len < 9))
-               return false; /* too short password */
+       }
 
        for (pos = 0; pw[pos]; pos++) {
                if (pos && pos % 5 == 4) {
-                       if (pw[pos] != '-')
+                       if (pw[pos] != '-') {
+                               wpa_printf(MSG_DEBUG,
+                                          "SAE-PK: Not a valid password (separator)");
                                return false;
+                       }
                        continue;
                }
-               if (!os_strchr(sae_pk_base32_table, pw[pos]))
+               if (dtable[(u8) pw[pos]] == 0x80) {
+                       wpa_printf(MSG_DEBUG,
+                                  "SAE-PK: Not a valid password (character)");
                        return false;
+               }
        }
-       if (pos == 0)
+
+       /* Verify that the checksum character is valid */
+       if (pw[pw_len - 1] != d_check_char(pw, pw_len - 1)) {
+               wpa_printf(MSG_DEBUG,
+                          "SAE-PK: Not a valid password (checksum)");
                return false;
-       return pw[pos - 1] != '-';
+       }
+
+       /* Verify that Sec_1b bits match */
+       sec_1b = dtable[(u8) pw[0]] & BIT(4);
+       for (i = 5; i < pw_len; i += 5) {
+               if (sec_1b != (dtable[(u8) pw[i]] & BIT(4))) {
+                       wpa_printf(MSG_DEBUG,
+                                  "SAE-PK: Not a valid password (Sec_1b)");
+                       return false;
+               }
+       }
+       return true;
 }
 
 
@@ -76,6 +209,7 @@ static char * add_char(const char *start, char *pos, u8 idx, size_t *bits)
 }
 
 
+/* Base32 encode a password and add hyper separators and checksum */
 char * sae_pk_base32_encode(const u8 *src, size_t len_bits)
 {
        char *out, *pos;
@@ -90,7 +224,7 @@ char * sae_pk_base32_encode(const u8 *src, size_t len_bits)
                return NULL;
        olen = len * 8 / 5 + 1;
        olen += olen / 4; /* hyphen separators */
-       pos = out = os_zalloc(olen + 1);
+       pos = out = os_zalloc(olen + 2); /* include room for ChkSum and nul */
        if (!out)
                return NULL;
 
@@ -107,6 +241,8 @@ char * sae_pk_base32_encode(const u8 *src, size_t len_bits)
                }
        }
 
+       *pos = d_check_char(out, os_strlen(out));
+
        return out;
 }
 
@@ -178,19 +314,107 @@ u8 * sae_pk_base32_decode(const char *src, size_t len, size_t *out_len)
 }
 
 
+u32 sae_pk_get_be19(const u8 *buf)
+{
+       return (buf[0] << 11) | (buf[1] << 3) | (buf[2] >> 5);
+}
+
+
+/* shift left by two octets and three bits; fill in zeros from right;
+ * len must be at least three */
+void sae_pk_buf_shift_left_19(u8 *buf, size_t len)
+{
+       u8 *dst, *src, *end;
+
+       dst = buf;
+       src = buf + 2;
+       end = buf + len;
+
+       while (src + 1 < end) {
+               *dst++ = (src[0] << 3) | (src[1] >> 5);
+               src++;
+       }
+       *dst++ = *src << 3;
+       *dst++ = 0;
+       *dst++ = 0;
+}
+
+
+static void sae_pk_buf_shift_left_1(u8 *buf, size_t len)
+{
+       u8 *dst, *src, *end;
+
+       dst = buf;
+       src = buf;
+       end = buf + len;
+
+       while (src + 1 < end) {
+               *dst++ = (src[0] << 1) | (src[1] >> 7);
+               src++;
+       }
+       *dst++ = *src << 1;
+}
+
+
 int sae_pk_set_password(struct sae_data *sae, const char *password)
 {
        struct sae_temporary_data *tmp = sae->tmp;
-       size_t len;
+       size_t len, pw_len;
+       u8 *pw, *pos;
+       int bits;
+       u32 val = 0, val19;
+       unsigned int val_bits = 0;
+
+       if (!tmp)
+               return -1;
+
+       os_memset(tmp->fingerprint, 0, sizeof(tmp->fingerprint));
+       tmp->fingerprint_bytes = tmp->fingerprint_bits = 0;
 
        len = os_strlen(password);
-       if (!tmp || len < 1)
+       if (len < 1 || !sae_pk_valid_password(password))
                return -1;
 
-       bin_clear_free(tmp->pw, tmp->pw_len);
-       tmp->pw = sae_pk_base32_decode(password, len, &tmp->pw_len);
+       pw = sae_pk_base32_decode(password, len, &pw_len);
+       if (!pw)
+               return -1;
+
+       tmp->sec = (pw[0] & BIT(7)) ? 3 : 5;
        tmp->lambda = len - len / 5;
-       return tmp->pw ? 0 : -1;
+       tmp->fingerprint_bits = 8 * tmp->sec + 19 * tmp->lambda / 4 - 5;
+       wpa_printf(MSG_DEBUG, "SAE-PK: Sec=%u Lambda=%zu fingerprint_bits=%zu",
+                  tmp->sec, tmp->lambda, tmp->fingerprint_bits);
+
+       /* Construct Fingerprint from PasswordBase by prefixing with Sec zero
+        * octets and skipping the Sec_1b bits */
+       pos = &tmp->fingerprint[tmp->sec];
+       bits = tmp->fingerprint_bits - 8 * tmp->sec;
+       wpa_hexdump_key(MSG_DEBUG, "SAE-PK: PasswordBase", pw, pw_len);
+       while (bits > 0) {
+               if (val_bits < 8) {
+                       sae_pk_buf_shift_left_1(pw, pw_len); /* Sec_1b */
+                       val19 = sae_pk_get_be19(pw);
+                       sae_pk_buf_shift_left_19(pw, pw_len);
+                       val = (val << 19) | val19;
+                       val_bits += 19;
+               }
+               if (val_bits >= 8) {
+                       if (bits < 8)
+                               break;
+                       *pos++ = (val >> (val_bits - 8)) & 0xff;
+                       val_bits -= 8;
+                       bits -= 8;
+               }
+       }
+       if (bits > 0) {
+               val >>= val_bits - bits;
+               *pos++ = val << (8 - bits);
+       }
+       tmp->fingerprint_bytes = pos - tmp->fingerprint;
+       wpa_hexdump_key(MSG_DEBUG, "SAE-PK: Fingerprint",
+                       tmp->fingerprint, tmp->fingerprint_bytes);
+       bin_clear_free(pw, pw_len);
+       return 0;
 }
 
 
@@ -481,19 +705,19 @@ static bool sae_pk_valid_fingerprint(struct sae_data *sae,
                                     const u8 *k_ap, size_t k_ap_len, int group)
 {
        struct sae_temporary_data *tmp = sae->tmp;
-       size_t sec, i;
-       u8 *fingerprint_exp, *hash_data, *pos;
-       size_t hash_len, hash_data_len, fingerprint_bits, fingerprint_bytes;
+       u8 *hash_data, *pos;
+       size_t hash_len, hash_data_len;
        u8 hash[SAE_MAX_HASH_LEN];
        int res;
 
-       if (!tmp->pw || tmp->pw_len < 1) {
+       if (!tmp->fingerprint_bytes) {
                wpa_printf(MSG_DEBUG,
                           "SAE-PK: No PW available for K_AP fingerprint check");
                return false;
        }
 
-       /* Fingerprint = L(Hash(SSID || M || K_AP), 0, 8*Sec + 5*Lambda - 2) */
+       /* Fingerprint = L(Hash(SSID || M || K_AP), 0, 8*Sec + 19*Lambda/4 - 5)
+        */
 
        hash_len = sae_group_2_hash_len(group);
        hash_data_len = tmp->ssid_len + m_len + k_ap_len;
@@ -516,44 +740,26 @@ static bool sae_pk_valid_fingerprint(struct sae_data *sae,
        wpa_hexdump(MSG_DEBUG, "SAE-PK: Hash(SSID || M || K_AP)",
                    hash, hash_len);
 
-       wpa_hexdump_key(MSG_DEBUG, "SAE-PK: PW", tmp->pw, tmp->pw_len);
-       sec = (tmp->pw[0] >> 6) + 2;
-       fingerprint_bits = 8 * sec + 5 * tmp->lambda - 2;
-       wpa_printf(MSG_DEBUG, "SAE-PK: Sec=%zu Lambda=%zu fingerprint_bits=%zu",
-                  sec, tmp->lambda, fingerprint_bits);
-       if (fingerprint_bits > hash_len * 8) {
+       if (tmp->fingerprint_bits > hash_len * 8) {
                wpa_printf(MSG_INFO,
                           "SAE-PK: Not enough hash output bits for the fingerprint");
                return false;
        }
-       fingerprint_bytes = (fingerprint_bits + 7) / 8;
-       if (fingerprint_bits % 8) {
+       if (tmp->fingerprint_bits % 8) {
                size_t extra;
 
                /* Zero out the extra bits in the last octet */
-               extra = 8 - fingerprint_bits % 8;
-               pos = &hash[fingerprint_bits / 8];
+               extra = 8 - tmp->fingerprint_bits % 8;
+               pos = &hash[tmp->fingerprint_bits / 8];
                *pos = (*pos >> extra) << extra;
        }
-       wpa_hexdump(MSG_DEBUG, "SAE-PK: Fingerprint", hash, fingerprint_bytes);
-
-       fingerprint_exp = os_zalloc(sec + tmp->pw_len);
-       if (!fingerprint_exp)
-               return false;
-       pos = fingerprint_exp + sec;
-       for (i = 0; i < tmp->pw_len; i++) {
-               u8 next = i + 1 < tmp->pw_len ? tmp->pw[i + 1] : 0;
-
-               *pos++ = tmp->pw[i] << 2 | next >> 6;
-       }
-
-       wpa_hexdump(MSG_DEBUG, "SAE-PK: Fingerprint_Expected",
-                   fingerprint_exp, fingerprint_bytes);
-       res = os_memcmp_const(hash, fingerprint_exp, fingerprint_bytes);
-       bin_clear_free(fingerprint_exp, tmp->pw_len);
-
+       wpa_hexdump(MSG_DEBUG, "SAE-PK: Fingerprint", hash,
+                   tmp->fingerprint_bytes);
+       res = os_memcmp_const(hash, tmp->fingerprint, tmp->fingerprint_bytes);
        if (res) {
                wpa_printf(MSG_DEBUG, "SAE-PK: K_AP fingerprint mismatch");
+       wpa_hexdump(MSG_DEBUG, "SAE-PK: Expected fingerprint",
+                   tmp->fingerprint, tmp->fingerprint_bytes);
                return false;
        }
 
index 7feee54df05ecd6f43f9f3e869ac567417f640a7..e01b5a3bd43c0edff56dfead20dd0e96bd054931 100644 (file)
@@ -9,18 +9,17 @@ from utils import *
 
 SAE_PK_SSID = "SAE-PK test"
 
-SAE_PK_SEC2_PW = "dwxm-zv66-p5ue"
-SAE_PK_SEC2_PW_FULL = "dwxm-zv66-p5ue-fotp-owjy-lfby-2xpg-vmwq-chtz-hilu-m3t2-qleg"
-SAE_PK_SEC2_M = "431ff8322f93b9dc50ded9f3d14ace22"
+SAE_PK_SEC3_PW = "r6cr-6ksa-56og"
+SAE_PK_SEC3_M = "089ec11475d55f0d38403f5117a6d64d"
 SAE_PK_19_PK = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg=="
 
-SAE_PK_20_PW = "f3bh-5un3-wz7o-al3p"
-SAE_PK_20_M = "50bf37ba0033ed110a74e3a7aa52f4e9"
+SAE_PK_20_PW = "4zsy-uspe-xbfr-3ifo"
+SAE_PK_20_M = "206902f9f09b62e3fafcd487c65f5c64"
 SAE_PK_20_PK = "MIGkAgEBBDA4wpA6w/fK0g3a2V6QmcoxNoFCVuQPyzWvKYimJkgXsVsXt2ERXQ7dGOVXeycM5DqgBwYFK4EEACKhZANiAARTdszGBNe2PGCnc8Wvs+IDvdVEf4PPBrty0meRZf6UTbGouquTHpy6KKTq5sxrulYzsQFimg4op0UJBGxAzqo0EtTgMlLiBvY0I3Nl3N69MhWo8nvnmguvGGN32AAPXpQ="
 
-SAE_PK_21_PW = "a5rp-4rgd-ewum-v4qr-v5jy"
-SAE_PK_21_M = "2bf0a143b158b967a435cf75b07fc9e6"
-SAE_PK_21_PK = "MIHcAgEBBEIBcch+ygKv1uL5344C+8Rt5h8cTYHG++L3/8/hH6I2J3pWboB0jtzTf/zdZVGqkEIi+zZ2O+5g65cS8my1B44n0g+gBwYFK4EEACOhgYkDgYYABAA49TXDQfBgQWuwGrvYSkw9yuLRTn7WKyWcfSqSFfJYY6piGRE0wdKsNsGbuqHsfjn3Jb3LhmPdcnaDXd5z7fhdgAGFaiL+ZtBJCw5LqjW71rb54oy1NookDiNILdZ9i1dwBzE3fpfOWVvfjnXj9weZKUWHLB+2RF2X1qB0mY/G5NuRXA=="
+SAE_PK_21_PW = "vluk-umpa-3mbw-zrhe-s2n2"
+SAE_PK_21_M = "1c63c1b17e9a999f0693b4341a970a63"
+SAE_PK_21_PK = "MIHcAgEBBEIBnFBjU0ywxo1dLTYcg2aZdMfNY7JHt4GTADRTgJ7RRo9qzRIlfmK7p+BP1c8YM8ia8v7YDTut00rDOfzkdmLOi0WgBwYFK4EEACOhgYkDgYYABAD6n3DHI+qaj/lElhe2sUSKqAe4sweckMlr9bhdmwp8Wsx5lKR/Tt7WPexeqFrA47nChw5WMWy6qJanCKNFvGYG0ADUWnxesYczGtCdUYJQgs3X5tHSapMssz6tP8QL0X9adTI/H3tFYhiVIdor03eZDUVnej78/F31CcHcjGBEyItVfw=="
 
 def run_sae_pk(apdev, dev, ssid, pw, m, pk, ap_groups=None,
                confirm_immediate=False):
@@ -54,11 +53,18 @@ def test_sae_pk(dev, apdev):
     dev[0].flush_scan_cache()
     dev[0].set("sae_groups", "")
 
-    for i in range(14, len(SAE_PK_SEC2_PW_FULL) + 1):
-        p = SAE_PK_SEC2_PW_FULL[:i]
-        if p.endswith('-'):
-            continue
-        run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, p, SAE_PK_SEC2_M,
+    passwords = [SAE_PK_SEC3_PW,
+                 "r6cr-6ksa-56oo-5557",
+                 "r6cr-6ksa-56oo-555p-wi44",
+                 "r6cr-6ksa-56oo-555p-wi4b-vghb",
+                 "r6cr-6ksa-56oo-555p-wi4b-vghv-vwro",
+                 "r6cr-6ksa-56oo-555p-wi4b-vghv-vwrp-taqj",
+                 "r6cr-6ksa-56oo-555p-wi4b-vghv-vwrp-taq5-4zfq",
+                 "r6cr-6ksa-56oo-555p-wi4b-vghv-vwrp-taq5-4zfa-ye3x",
+                 "r6cr-6ksa-56oo-555p-wi4b-vghv-vwrp-taq5-4zfa-ye35-4rne",
+                 "r6cr-6ksa-56oo-555p-wi4b-vghv-vwrp-taq5-4zfa-ye35-4rny-5yqz"]
+    for p in passwords:
+        run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, p, SAE_PK_SEC3_M,
                    SAE_PK_19_PK)
 
 def test_sae_pk_group_negotiation(dev, apdev):
@@ -68,39 +74,19 @@ def test_sae_pk_group_negotiation(dev, apdev):
     dev[0].set("sae_groups", "20 19")
 
     try:
-        run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW,
-                   SAE_PK_SEC2_M, SAE_PK_19_PK, ap_groups="19 20")
+        run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC3_PW,
+                   SAE_PK_SEC3_M, SAE_PK_19_PK, ap_groups="19 20")
     finally:
         dev[0].set("sae_groups", "")
 
-def test_sae_pk_sec_2(dev, apdev):
-    """SAE-PK with Sec 2"""
-    check_sae_pk_capab(dev[0])
-    dev[0].flush_scan_cache()
-    dev[0].set("sae_groups", "")
-
-    run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW,
-               SAE_PK_SEC2_M, SAE_PK_19_PK)
-
 def test_sae_pk_sec_3(dev, apdev):
     """SAE-PK with Sec 3"""
     check_sae_pk_capab(dev[0])
     dev[0].flush_scan_cache()
     dev[0].set("sae_groups", "")
 
-    pw = "iian-qey6-pu5t"
-    m = "128e51ddb5e2e24388f9ed14b687e2eb"
-    run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, pw, m, SAE_PK_19_PK)
-
-def test_sae_pk_sec_4(dev, apdev):
-    """SAE-PK with Sec 4"""
-    check_sae_pk_capab(dev[0])
-    dev[0].flush_scan_cache()
-    dev[0].set("sae_groups", "")
-
-    pw = "ssko-2lmu-7hzs-bqct"
-    m = "a5e38c7251ea310cc348fbcdadfa8bcb"
-    run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, pw, m, SAE_PK_19_PK)
+    run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC3_PW, SAE_PK_SEC3_M,
+               SAE_PK_19_PK)
 
 def test_sae_pk_sec_5(dev, apdev):
     """SAE-PK with Sec 5"""
@@ -108,7 +94,7 @@ def test_sae_pk_sec_5(dev, apdev):
     dev[0].flush_scan_cache()
     dev[0].set("sae_groups", "")
 
-    pw = "3qqu-f4xq-dz37-fes3-fbgc"
+    pw = "hbbi-f4xq-b457-jjew-muei"
     m = "d2e5fa27d1be8897f987f2d480d2af6b"
     run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, pw, m, SAE_PK_19_PK)
 
@@ -164,8 +150,8 @@ def test_sae_pk_group_19_sae_group_20(dev, apdev):
     dev[0].flush_scan_cache()
     dev[0].set("sae_groups", "20")
     try:
-        run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW,
-                   SAE_PK_SEC2_M, SAE_PK_19_PK, ap_groups="20")
+        run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC3_PW,
+                   SAE_PK_SEC3_M, SAE_PK_19_PK, ap_groups="20")
     finally:
         dev[0].set("sae_groups", "")
 
@@ -176,10 +162,10 @@ def test_sae_pk_password_without_pk(dev, apdev):
 
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
-    params['sae_password'] = SAE_PK_SEC2_PW
+    params['sae_password'] = SAE_PK_SEC3_PW
     hapd = hostapd.add_ap(apdev[0], params)
 
-    dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW,
+    dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW,
                    key_mgmt="SAE", scan_freq="2412")
     if dev[0].get_status_field("sae_pk") != "0":
         raise Exception("Unexpected sae_pk STATUS value")
@@ -191,10 +177,10 @@ def test_sae_pk_only(dev, apdev):
 
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
-    params['sae_password'] = SAE_PK_SEC2_PW
+    params['sae_password'] = SAE_PK_SEC3_PW
     hapd = hostapd.add_ap(apdev[0], params)
 
-    dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW,
+    dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW,
                    key_mgmt="SAE", sae_pk="1",
                    scan_freq="2412", wait_connect=False)
     ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
@@ -208,7 +194,7 @@ def test_sae_pk_only(dev, apdev):
 
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
-    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M,
+    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M,
                                                SAE_PK_19_PK)]
     hapd2 = hostapd.add_ap(apdev[1], params)
     bssid2 = hapd2.own_addr()
@@ -229,13 +215,13 @@ def test_sae_pk_modes(dev, apdev):
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
     params["ieee80211w"] = "2"
-    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M,
+    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M,
                                                SAE_PK_19_PK)]
     hapd = hostapd.add_ap(apdev[0], params)
 
     tests = [(2, 0), (1, 1), (0, 1)]
     for sae_pk, expected in tests:
-        dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW,
+        dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW,
                        key_mgmt="SAE", sae_pk=str(sae_pk), ieee80211w="2",
                        scan_freq="2412")
         val = dev[0].get_status_field("sae_pk")
@@ -252,10 +238,10 @@ def test_sae_pk_not_on_ap(dev, apdev):
 
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
-    params['sae_password'] = SAE_PK_SEC2_PW
+    params['sae_password'] = SAE_PK_SEC3_PW
     hapd = hostapd.add_ap(apdev[0], params)
 
-    dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW,
+    dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW,
                    key_mgmt="SAE", scan_freq="2412")
     if dev[0].get_status_field("sae_pk") == "1":
         raise Exception("SAE-PK was claimed to be used")
@@ -267,12 +253,12 @@ def test_sae_pk_transition_disable(dev, apdev):
 
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
-    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M,
+    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M,
                                                SAE_PK_19_PK)]
     params['transition_disable'] = '0x02'
     hapd = hostapd.add_ap(apdev[0], params)
 
-    id = dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW,
+    id = dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW,
                         key_mgmt="SAE", scan_freq="2412")
     ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1)
     if ev is None:
@@ -298,7 +284,7 @@ def run_sae_pk_mixed(dev, apdev, confirm_immediate=False):
 
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
-    params['sae_password'] = SAE_PK_SEC2_PW
+    params['sae_password'] = SAE_PK_SEC3_PW
     if confirm_immediate:
         params['sae_confirm_immediate'] = '1'
     hapd = hostapd.add_ap(apdev[0], params)
@@ -306,7 +292,7 @@ def run_sae_pk_mixed(dev, apdev, confirm_immediate=False):
 
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
-    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M,
+    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M,
                                                SAE_PK_19_PK)]
     # Disable HT from the SAE-PK BSS to make the station prefer the other BSS
     # by default.
@@ -317,7 +303,7 @@ def run_sae_pk_mixed(dev, apdev, confirm_immediate=False):
     dev[0].scan_for_bss(bssid, freq=2412)
     dev[0].scan_for_bss(bssid2, freq=2412)
 
-    dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW,
+    dev[0].connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW,
                    key_mgmt="SAE", scan_freq="2412")
 
     if dev[0].get_status_field("sae_pk") != "1":
@@ -326,7 +312,7 @@ def run_sae_pk_mixed(dev, apdev, confirm_immediate=False):
         raise Exception("Unexpected BSSID selected")
 
 def check_sae_pk_sta_connect_failure(dev):
-    dev.connect(SAE_PK_SSID, sae_password=SAE_PK_SEC2_PW,
+    dev.connect(SAE_PK_SSID, sae_password=SAE_PK_SEC3_PW,
                 key_mgmt="SAE", scan_freq="2412", wait_connect=False)
     ev = dev.wait_event(["CTRL-EVENT-CONNECTED",
                          "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10)
@@ -342,7 +328,7 @@ def test_sae_pk_missing_ie(dev, apdev):
 
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
-    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M,
+    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M,
                                                SAE_PK_19_PK)]
     params['sae_pk_omit'] = '1'
     hapd = hostapd.add_ap(apdev[0], params)
@@ -355,7 +341,7 @@ def test_sae_pk_unexpected_status(dev, apdev):
 
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
-    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M,
+    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M,
                                                SAE_PK_19_PK)]
     params['sae_commit_status'] = '126'
     hapd = hostapd.add_ap(apdev[0], params)
@@ -369,7 +355,7 @@ def test_sae_pk_invalid_signature(dev, apdev):
     other = "MHcCAQEEILw+nTjFzRyhVea0G6KbwZu18oWrfhzppxj+MceUO3YLoAoGCCqGSM49AwEHoUQDQgAELdou6LuTDNiMVlMB65KsWhQFbPXR9url0EA6luWzUfAuGoDXYJUBTVz6Nv3mz6oQcDrSiDmz/LejndJ0YHGgfQ=="
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
-    params['sae_password'] = ['%s|pk=%s:%s:%s' % (SAE_PK_SEC2_PW, SAE_PK_SEC2_M,
+    params['sae_password'] = ['%s|pk=%s:%s:%s' % (SAE_PK_SEC3_PW, SAE_PK_SEC3_M,
                                                   SAE_PK_19_PK, other)]
     hapd = hostapd.add_ap(apdev[0], params)
     check_sae_pk_sta_connect_failure(dev[0])
@@ -382,43 +368,16 @@ def test_sae_pk_invalid_fingerprint(dev, apdev):
     other = "431ff8322f93b9dc50ded9f3d14ace21"
     params = hostapd.wpa2_params(ssid=SAE_PK_SSID)
     params['wpa_key_mgmt'] = 'SAE'
-    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC2_PW, other,
+    params['sae_password'] = ['%s|pk=%s:%s' % (SAE_PK_SEC3_PW, other,
                                                SAE_PK_19_PK)]
     hapd = hostapd.add_ap(apdev[0], params)
     check_sae_pk_sta_connect_failure(dev[0])
 
-def test_sae_pk_password_min_len(dev, apdev):
-    """SAE-PK password minimum length"""
-    check_sae_pk_capab(dev[0])
-    ssid = SAE_PK_SSID
-    pk = SAE_PK_19_PK
-    tests = [("dwxm-zv66-p5u", "431ff8322f93b9dc50ded9f3d14ace22", False),
-             ("dwxm-zv66-p5ue", "431ff8322f93b9dc50ded9f3d14ace22", True),
-             ("iian-qey6-pu", "128e51ddb5e2e24388f9ed14b687e2eb", False),
-             ("iian-qey6-pu5", "128e51ddb5e2e24388f9ed14b687e2eb", True),
-             ("ssko-2lmu", "a5e38c7251ea310cc348fbcdadfa8bcb", False),
-             ("ssko-2lmu-7", "a5e38c7251ea310cc348fbcdadfa8bcb", True),
-             ("3qqu-f4x", "d2e5fa27d1be8897f987f2d480d2af6b", False),
-             ("3qqu-f4xq", "d2e5fa27d1be8897f987f2d480d2af6b", True)]
-    for pw, m, success in tests:
-        params = hostapd.wpa2_params(ssid=ssid)
-        params['wpa_key_mgmt'] = 'SAE'
-        params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)]
-        try:
-            hapd = hostapd.add_ap(apdev[0], params, no_enable=True)
-            if not success:
-                raise Exception("Unexpected success with password %s" % pw)
-        except Exception as e:
-            if str(e).startswith("Unexpected success with password"):
-                raise
-            if success:
-                raise Exception("Unexpected failure with password %s" % pw)
-
 def test_sae_pk_confirm_immediate(dev, apdev):
     """SAE-PK with immediate confirm on AP"""
     check_sae_pk_capab(dev[0])
     dev[0].flush_scan_cache()
     dev[0].set("sae_groups", "")
 
-    run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC2_PW,
-               SAE_PK_SEC2_M, SAE_PK_19_PK, confirm_immediate=True)
+    run_sae_pk(apdev[0], dev[0], SAE_PK_SSID, SAE_PK_SEC3_PW,
+               SAE_PK_SEC3_M, SAE_PK_19_PK, confirm_immediate=True)
index 58143d5604e20b7282c7c621b4424123998c881b..f12b6c0dbd81207bae2b4f66df4d23985ee670c4 100644 (file)
@@ -4930,8 +4930,8 @@ def test_sigma_dut_sae_pk(dev, apdev):
     sigma = start_sigma_dut(ifname)
 
     ssid = "SAE-PK test"
-    pw = "dwxm-zv66-p5ue"
-    m = "431ff8322f93b9dc50ded9f3d14ace22"
+    pw = "hbbi-f4xq-b45g"
+    m = "d2e5fa27d1be8897f987f2d480d2af6b"
     pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg=="
 
     try:
@@ -5012,32 +5012,50 @@ def test_sigma_dut_ap_sae_pk(dev, apdev, params):
     conffile = params['prefix'] + ".sigma-conf"
     if "SAE" not in dev[0].get_capability("auth_alg"):
         raise HwsimSkip("SAE not supported")
-    tests = [("SAEPK-4.7.1", "fb4c-zpqh-bhdc", "saepk.pem",
-              "2ec1f37b47b402252e9dc5001e81fd1c", False),
-             ("SAEPK-5.7.1.1", "amro-yjrs-zzda", "saepk1.pem",
-              "f42baa90420032486b3229ab0890878a", False),
-             ("SAEPK-5.7.1.2", "eh56-tjce-cnzg-ymhq", "saepk2.pem",
-              "efb8b7a87e0638a93b056cb4aadf4a71", False),
-             ("SAEPK-5.7.1.3", "knny-r45l-ww3w", "saepk3.pem",
-              "6502721b2c2dfea3c9aefc5324eee9c9", False),
-             ("SAEPK-5.7.2.1", "fvys-4brw-d67c", "saepk4.pem",
-              "b63662c6f0bdd12bf5a2075ccfd7e132", False),
-             ("SAEPK-5.7.2.2", "cnj6-khsf-dgzh", "saepk5.pem",
-              "126d37fae167a53d4ebb08a235cef1da", False),
-             ("SAEPK-5.7.2.3", "hr7j-3cdr-wtq6", "saepk6.pem",
-              "61a84a86ffb1b9e23f576a0275ddcc78", True),
-             ("SAEPK-5.7.2.4", "geoh-2rvn-ivwu", "saepk7.pem",
-              "61a84a86ffb1b9e23f576a0275ddcc78", False),
-             ("SAEPK-5.7.2.4", "geoh-2rvn-ivwu", "saepk8_sig.pem",
-              "61a84a86ffb1b9e23f576a0275ddcc78", True),
-             ("SAEPK-5.7.3", "hbhh-r4um-jzjs", "saepk9.pem",
-              "af9b55bce52040892634bb3e41d557ee", False),
-             ("SAE-PK-5.7.1.13", "dop4-pi5w-72g2", "saepk13.pem",
-              "c269116268faaa6728fccd27fa5e9003", False),
-             ("SAE-PK test", "ssko-2lmu-7", "saepk5.7.1Run4thru12.pem",
-              "a5e38c7251ea310cc348fbcdadfa8bcb", False),
-             ("SAE-PK test", "3qqu-f4xq", "saepk5.7.1Run4thru12.pem",
-              "d2e5fa27d1be8897f987f2d480d2af6b", False)]
+    tests = [("SAEPK-4.7.1.1", "ya3o-zvm2-r4so", "saepk1.pem",
+              "faa1ef5094bdb4cb2836332ca2c09839", False),
+             ("SAEPK-4.7.1.2", "xcc2-qwru-yg23", "saepk1.pem",
+              "b1b30107eb74de2f25afd079bb4196c1", False),
+             ("SAEPK-4.7.1.3", "skqz-6scq-zcqv", "saepk1.pem",
+              "4c0ff61465e0f298510254ff54916c71", False),
+             ("SAEPK-4.7.1.4", "r6em-rya4-tqfa", "saepkP384.pem",
+              "fb811655209e9edf347a675ddd3e9c82", False),
+             ("SAEPK-4.7.1.5", "6kjo-umvi-7x3w", "saepkP521.pem",
+              "cccb76bc0f113ab754826ba9538d66f5", False),
+             ("SAEPK-5.7.1.1", "sw4h-re63-wgqg", "saepk1.pem",
+              "0d126f302d85ac809a6a4229dbbe3c75", False),
+             ("SAEPK-5.7.1.2", "wewq-r4kg-4ioz-xb2p", "saepk1.pem",
+              "d6b1d8924b1a462677e67b3bbfe73977", False),
+             ("SAEPK-5.7.1.3", "vb3v-5skk-5eft-v4hu-w2c5", "saepk1.pem",
+              "41f8cfceb96ebc5c8af9677d22749fad", False),
+             ("SAEPK-5.7.1.4", "2qsw-6tgy-xnwa-s7lo-75tq-qggr", "saepk1.pem",
+              "089e8d4a3a79ec637c54dd7bd61972f2", False),
+             ("SAE-PK test", "hbbi-f4xq-b45g", "saepkP256.pem",
+              "d2e5fa27d1be8897f987f2d480d2af6b", False),
+             ("SAE-PK test", "hbbi-f4xq-b457-jje4", "saepkP256.pem",
+              "d2e5fa27d1be8897f987f2d480d2af6b", False),
+             ("SAE-PK test", "hbbi-f4xq-b457-jjew-muei", "saepkP256.pem",
+              "d2e5fa27d1be8897f987f2d480d2af6b", False),
+             ("SAE-PK test", "hbbi-f4xq-b457-jjew-muey-fod3", "saepkP256.pem",
+              "d2e5fa27d1be8897f987f2d480d2af6b", False),
+             ("SAEPK-5.7.1.1", "sw4h-re63-wgqg", "saepk1.pem",
+              "0d126f302d85ac809a6a4229dbbe3c75", False),
+             ("SAEPK-5.7.1.10", "tkor-7nb3-r7tv", "saepkP384.pem",
+              "af1a3df913fc0103f65f105ed1472277", False),
+             ("SAEPK-5.7.1.11", "yjl3-vfvu-w6r3", "saepkP521.pem",
+              "24dadf9d253c4169c9647a21cb54fc57", False),
+             ("SAEPK-5.7.2.1", "rntm-tkrp-xgke", "saepk1.pem",
+              "cd38ccce3baff627d09bee7b9530d6ce", False),
+             ("SAEPK-5.7.2.2", "7lt7-7dqt-6abk", "saepk1.pem",
+              "a22fc8489932597c9e83de62dec02b21", False),
+             ("SAEPK-5.7.2.3", "sw4h-re63-wgqg", "saepk2.pem",
+              "1f4a4c7d290d97e0b6ab0cbbbfa0726d", True),
+             ("SAEPK-5.7.2.4", "rmj3-ya7b-42k4", "saepk1.pem",
+              "5f65e2bc37f8494de7a605ff615c8b6a", False),
+             ("SAEPK-5.7.2.4", "rmj3-ya7b-42k4", "saepk2.pem",
+              "5f65e2bc37f8494de7a605ff615c8b6a", True),
+             ("SAEPK-5.7.3", "4322-ufus-4bhm", "saepk1.pem",
+              "21ede99abc46679646693cafe4677d4e", False)]
 
     with HWSimRadio() as (radio, iface):
         sigma = start_sigma_dut(iface, hostapd_logdir=logdir)
@@ -5054,10 +5072,10 @@ def test_sigma_dut_ap_sae_pk_misbehavior(dev, apdev, params):
     conffile = params['prefix'] + ".sigma-conf"
     if "SAE" not in dev[0].get_capability("auth_alg"):
         raise HwsimSkip("SAE not supported")
-    ssid = "SAEPK-4.7.1"
-    pw = "fb4c-zpqh-bhdc"
-    keypair = "saepk.pem"
-    m = "2ec1f37b47b402252e9dc5001e81fd1c"
+    ssid = "SAEPK-4.7.1.1"
+    pw = "rmj3-ya7b-42k4"
+    keypair = "saepk1.pem"
+    m = "faa1ef5094bdb4cb2836332ca2c09839"
 
     with HWSimRadio() as (radio, iface):
         sigma = start_sigma_dut(iface, hostapd_logdir=logdir)
@@ -5069,7 +5087,7 @@ def test_sigma_dut_ap_sae_pk_misbehavior(dev, apdev, params):
             run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m,
                                     True, status=126, omit=True, immediate=True)
             run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m,
-                                    True, sig="saepk8_sig.pem")
+                                    True, sig="saepk2.pem")
         finally:
             stop_sigma_dut(sigma)