]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
test-aes: Allow NIST key wrap test vectors to be verified
authorJouni Malinen <j@w1.fi>
Tue, 7 Oct 2014 11:53:09 +0000 (14:53 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 7 Oct 2014 11:57:10 +0000 (14:57 +0300)
This allows the aes_wrap() and aes_unwrap() implementation to be
verified against KW_{AE,AD}_{128,192,256}.txt test vectors from
http://csrc.nist.gov/groups/STM/cavp/documents/mac/kwtestvectors.zip

For example:
./test-aes NIST-KW-AE kwtestvectors/KW_AE_128.txt
./test-aes NIST-KW-AE kwtestvectors/KW_AE_192.txt
./test-aes NIST-KW-AE kwtestvectors/KW_AE_256.txt
./test-aes NIST-KW-AD kwtestvectors/KW_AD_128.txt
./test-aes NIST-KW-AD kwtestvectors/KW_AD_192.txt
./test-aes NIST-KW-AD kwtestvectors/KW_AD_256.txt

Signed-off-by: Jouni Malinen <j@w1.fi>
tests/test-aes.c

index 596e38b1d426693e3f357fa9d0ef2ac7fe29eace..20d4b5d043fc940539facc724a9359100a15bc78 100644 (file)
@@ -752,6 +752,281 @@ static int test_key_wrap(void)
 }
 
 
+static int test_nist_key_wrap_ae(const char *fname)
+{
+       FILE *f;
+       int ret = 0;
+       char buf[15000], *pos, *pos2;
+       u8 bin[2000], k[32], p[1024], c[1024 + 8], result[1024 + 8];
+       size_t bin_len, k_len = 0, p_len = 0, c_len = 0;
+       int ok = 0;
+
+       printf("NIST KW AE tests from %s\n", fname);
+
+       f = fopen(fname, "r");
+       if (f == NULL) {
+               printf("%s does not exist - cannot validate test vectors\n",
+                      fname);
+               return 1;
+       }
+
+       while (fgets(buf, sizeof(buf), f)) {
+               if (buf[0] == '#')
+                       continue;
+               pos = os_strchr(buf, '=');
+               if (pos == NULL)
+                       continue;
+               pos2 = pos - 1;
+               while (pos2 >= buf && *pos2 == ' ')
+                       *pos2-- = '\0';
+               *pos++ = '\0';
+               while (*pos == ' ')
+                       *pos++ = '\0';
+               pos2 = os_strchr(pos, '\r');
+               if (!pos2)
+                       pos2 = os_strchr(pos, '\n');
+               if (pos2)
+                       *pos2 = '\0';
+               else
+                       pos2 = pos + os_strlen(pos);
+
+               if (buf[0] == '[') {
+                       printf("%s = %s\n", buf, pos);
+                       continue;
+               }
+
+               if (os_strcmp(buf, "COUNT") == 0) {
+                       printf("Test %s - ", pos);
+                       continue;
+               }
+
+               bin_len = os_strlen(pos);
+               if (bin_len > sizeof(bin) * 2) {
+                       printf("Too long binary data (%s)\n", buf);
+                       return 1;
+               }
+               if (bin_len & 0x01) {
+                       printf("Odd number of hexstring values (%s)\n",
+                               buf);
+                       return 1;
+               }
+               bin_len /= 2;
+               if (hexstr2bin(pos, bin, bin_len) < 0) {
+                       printf("Invalid hex string '%s' (%s)\n", pos, buf);
+                       return 1;
+               }
+
+               if (os_strcmp(buf, "K") == 0) {
+                       if (bin_len > sizeof(k)) {
+                               printf("Too long K (%u)\n", (unsigned) bin_len);
+                               return 1;
+                       }
+                       os_memcpy(k, bin, bin_len);
+                       k_len = bin_len;
+                       continue;
+               }
+
+               if (os_strcmp(buf, "P") == 0) {
+                       if (bin_len > sizeof(p)) {
+                               printf("Too long P (%u)\n", (unsigned) bin_len);
+                               return 1;
+                       }
+                       os_memcpy(p, bin, bin_len);
+                       p_len = bin_len;
+                       continue;
+               }
+
+               if (os_strcmp(buf, "C") != 0) {
+                       printf("Unexpected field '%s'\n", buf);
+                       continue;
+               }
+
+               if (bin_len > sizeof(c)) {
+                       printf("Too long C (%u)\n", (unsigned) bin_len);
+                       return 1;
+               }
+               os_memcpy(c, bin, bin_len);
+               c_len = bin_len;
+
+               if (p_len % 8 != 0 || c_len % 8 != 0 || c_len - p_len != 8) {
+                       printf("invalid parameter length (p_len=%u c_len=%u)\n",
+                              (unsigned) p_len, (unsigned) c_len);
+                       continue;
+               }
+
+               if (aes_wrap(k, k_len, p_len / 8, p, result)) {
+                       printf("aes_wrap() failed\n");
+                       ret++;
+                       continue;
+               }
+
+               if (os_memcmp(c, result, c_len) == 0) {
+                       printf("OK\n");
+                       ok++;
+               } else {
+                       printf("FAIL\n");
+                       ret++;
+               }
+       }
+
+       fclose(f);
+
+       if (ret)
+               printf("Test case failed\n");
+       else
+               printf("%d test vectors OK\n", ok);
+
+       return ret;
+}
+
+
+static int test_nist_key_wrap_ad(const char *fname)
+{
+       FILE *f;
+       int ret = 0;
+       char buf[15000], *pos, *pos2;
+       u8 bin[2000], k[32], p[1024], c[1024 + 8], result[1024 + 8];
+       size_t bin_len, k_len = 0, p_len = 0, c_len = 0;
+       int ok = 0;
+       int fail;
+
+       printf("NIST KW AD tests from %s\n", fname);
+
+       f = fopen(fname, "r");
+       if (f == NULL) {
+               printf("%s does not exist - cannot validate test vectors\n",
+                      fname);
+               return 1;
+       }
+
+       while (fgets(buf, sizeof(buf), f)) {
+               if (buf[0] == '#')
+                       continue;
+               fail = 0;
+               pos = os_strchr(buf, '=');
+               if (pos == NULL) {
+                       if (os_strncmp(buf, "FAIL", 4) == 0) {
+                               fail = 1;
+                               goto skip_val_parse;
+                       }
+                       continue;
+               }
+               pos2 = pos - 1;
+               while (pos2 >= buf && *pos2 == ' ')
+                       *pos2-- = '\0';
+               *pos++ = '\0';
+               while (*pos == ' ')
+                       *pos++ = '\0';
+               pos2 = os_strchr(pos, '\r');
+               if (!pos2)
+                       pos2 = os_strchr(pos, '\n');
+               if (pos2)
+                       *pos2 = '\0';
+               else
+                       pos2 = pos + os_strlen(pos);
+
+               if (buf[0] == '[') {
+                       printf("%s = %s\n", buf, pos);
+                       continue;
+               }
+
+               if (os_strcmp(buf, "COUNT") == 0) {
+                       printf("Test %s - ", pos);
+                       continue;
+               }
+
+               bin_len = os_strlen(pos);
+               if (bin_len > sizeof(bin) * 2) {
+                       printf("Too long binary data (%s)\n", buf);
+                       return 1;
+               }
+               if (bin_len & 0x01) {
+                       printf("Odd number of hexstring values (%s)\n",
+                               buf);
+                       return 1;
+               }
+               bin_len /= 2;
+               if (hexstr2bin(pos, bin, bin_len) < 0) {
+                       printf("Invalid hex string '%s' (%s)\n", pos, buf);
+                       return 1;
+               }
+
+               if (os_strcmp(buf, "K") == 0) {
+                       if (bin_len > sizeof(k)) {
+                               printf("Too long K (%u)\n", (unsigned) bin_len);
+                               return 1;
+                       }
+                       os_memcpy(k, bin, bin_len);
+                       k_len = bin_len;
+                       continue;
+               }
+
+               if (os_strcmp(buf, "C") == 0) {
+                       if (bin_len > sizeof(c)) {
+                               printf("Too long C (%u)\n", (unsigned) bin_len);
+                               return 1;
+                       }
+                       os_memcpy(c, bin, bin_len);
+                       c_len = bin_len;
+                       continue;
+               }
+
+       skip_val_parse:
+               if (!fail) {
+                       if (os_strcmp(buf, "P") != 0) {
+                               printf("Unexpected field '%s'\n", buf);
+                               continue;
+                       }
+
+                       if (bin_len > sizeof(p)) {
+                               printf("Too long P (%u)\n", (unsigned) bin_len);
+                               return 1;
+                       }
+                       os_memcpy(p, bin, bin_len);
+                       p_len = bin_len;
+
+                       if (p_len % 8 != 0 || c_len % 8 != 0 ||
+                           c_len - p_len != 8) {
+                               printf("invalid parameter length (p_len=%u c_len=%u)\n",
+                                      (unsigned) p_len, (unsigned) c_len);
+                               continue;
+                       }
+               }
+
+               if (aes_unwrap(k, k_len, (c_len / 8) - 1, c, result)) {
+                       if (fail) {
+                               printf("OK (fail reported)\n");
+                               ok++;
+                               continue;
+                       }
+                       printf("aes_unwrap() failed\n");
+                       ret++;
+                       continue;
+               }
+
+               if (fail) {
+                       printf("FAIL (mismatch not reported)\n");
+                       ret++;
+               } else if (os_memcmp(p, result, p_len) == 0) {
+                       printf("OK\n");
+                       ok++;
+               } else {
+                       printf("FAIL\n");
+                       ret++;
+               }
+       }
+
+       fclose(f);
+
+       if (ret)
+               printf("Test case failed\n");
+       else
+               printf("%d test vectors OK\n", ok);
+
+       return ret;
+}
+
+
 int main(int argc, char *argv[])
 {
        u8 result[24];
@@ -759,6 +1034,11 @@ int main(int argc, char *argv[])
        unsigned int i;
        struct omac1_test_vector *tv;
 
+       if (argc >= 3 && os_strcmp(argv[1], "NIST-KW-AE") == 0)
+               ret += test_nist_key_wrap_ae(argv[2]);
+       else if (argc >= 3 && os_strcmp(argv[1], "NIST-KW-AD") == 0)
+               ret += test_nist_key_wrap_ad(argv[2]);
+
        ret += test_key_wrap();
 
        test_aes_perf();