From b1f4015cf518e07ca1204b6d942565c9ad63cc0c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 7 Oct 2014 14:53:09 +0300 Subject: [PATCH] test-aes: Allow NIST key wrap test vectors to be verified 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 --- tests/test-aes.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) diff --git a/tests/test-aes.c b/tests/test-aes.c index 596e38b1d..20d4b5d04 100644 --- a/tests/test-aes.c +++ b/tests/test-aes.c @@ -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();