summaryrefslogtreecommitdiff
path: root/tests/crypto-vectors.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/crypto-vectors.c')
-rw-r--r--tests/crypto-vectors.c307
1 files changed, 297 insertions, 10 deletions
diff --git a/tests/crypto-vectors.c b/tests/crypto-vectors.c
index 004e426..ae8dd68 100644
--- a/tests/crypto-vectors.c
+++ b/tests/crypto-vectors.c
@@ -1,7 +1,7 @@
/*
* cryptsetup crypto backend test vectors
*
- * Copyright (C) 2018-2021 Milan Broz
+ * Copyright (C) 2018-2023 Milan Broz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -22,8 +22,10 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
-#include "crypto_backend.h"
+#include "crypto_backend/crypto_backend.h"
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
@@ -40,6 +42,24 @@ static void printhex(const char *s, const char *buf, size_t len)
fflush(stdout);
}
+static bool fips_mode(void)
+{
+ int fd;
+ char buf = 0;
+
+ fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY);
+
+ if (fd < 0)
+ return false;
+
+ if (read(fd, &buf, 1) != 1)
+ buf = '0';
+
+ close(fd);
+
+ return (buf == '1');
+}
+
/*
* KDF tests
*/
@@ -104,6 +124,27 @@ static struct kdf_test_vector kdf_test_vectors[] = {
// "\xd0\x1e\xf0\x45\x2d\x75\xb6\x5e"
// "\xb5\x25\x20\xe9\x6b\x01\xe6\x59", 32
},
+ /* empty password */
+ {
+ "argon2i", NULL, 0, 3, 128, 1,
+ "", 0,
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16,
+ "\xbb\x1f\xf2\xb9\x9f\xd4\x4a\xd9"
+ "\xdf\x7f\xb9\x54\x55\x9e\xb8\xeb"
+ "\xb5\x9d\xab\xce\x2e\x62\x9f\x9b"
+ "\x89\x09\xfe\xde\x57\xcc\x63\x86", 32
+ },
+ {
+ "argon2id", NULL, 0, 3, 128, 1,
+ "", 0,
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16,
+ "\x09\x2f\x38\x35\xac\xb2\x43\x92"
+ "\x93\xeb\xcd\xe8\x04\x16\x6a\x31"
+ "\xce\x14\xd4\x55\xdb\xd8\xf7\xe6"
+ "\xb4\xf5\x9d\x64\x8e\xd0\x3a\xdb", 32
+ },
/* RFC 3962 */
{
"pbkdf2", "sha1", 64, 1, 0, 0,
@@ -912,13 +953,80 @@ static struct cipher_iv_test_vector cipher_iv_test_vectors[] = {
},
}}};
+/* Base64 test vectors */
+struct base64_test_vector {
+ size_t decoded_len;
+ const char *decoded;
+ const char *encoded;
+};
+
+static struct base64_test_vector base64_test_vectors[] = {
+ { 0, "", "" },
+ { 1, "\x00", "AA==" },
+ { 1, "f", "Zg==" },
+ { 2, "fo", "Zm8=" },
+ { 3, "foo", "Zm9v" },
+ { 4, "foob", "Zm9vYg==" },
+ { 5, "fooba", "Zm9vYmE=" },
+ { 6, "foobar", "Zm9vYmFy" },
+ { 11, "Hello world", "SGVsbG8gd29ybGQ=" },
+ { 22, "\x36\x03\x84\xdc\x4e\x03\x46\xa0\xb5\x2d\x03"
+ "\x6e\xd0\x56\xed\xa0\x37\x02\xac\xc6\x65\xd1",
+ "NgOE3E4DRqC1LQNu0FbtoDcCrMZl0Q==" },
+ { 3, "***", "Kioq" },
+ { 4, "\x01\x02\x03\x04", "AQIDBA==" },
+ { 5, "\xAD\xAD\xAD\xAD\xAD", "ra2tra0=" },
+ { 5, "\xFF\xFF\xFF\xFF\xFF", "//////8=" },
+ { 32, "\x40\xC1\x3F\xBD\x05\x4C\x72\x2A\xA3\xC2\xF2"
+ "\x11\x73\xC0\x69\xEA\x49\x7D\x35\x29\x6B\xCC"
+ "\x24\x65\xF6\xF9\xD0\x41\x08\x7B\xD7\xA9",
+ "QME/vQVMciqjwvIRc8Bp6kl9NSlrzCRl9vnQQQh716k=" },
+ { 7, "\x54\x0f\xdc\xf0\x0f\xaf\x4a", "VA/c8A+vSg==" },
+ {179, "blah blah blah blah blah blah blah blah blah "
+ "blah blah blah blah blah blah blah blah blah "
+ "blah blah blah blah blah blah blah blah blah "
+ "blah blah blah blah blah blah blah blah blah",
+ "YmxhaCBibGFoIGJsYWggYmxhaCBibGFoIGJsYWggYmxh"
+ "aCBibGFoIGJsYWggYmxhaCBibGFoIGJsYWggYmxhaCBi"
+ "bGFoIGJsYWggYmxhaCBibGFoIGJsYWggYmxhaCBibGFo"
+ "IGJsYWggYmxhaCBibGFoIGJsYWggYmxhaCBibGFoIGJs"
+ "YWggYmxhaCBibGFoIGJsYWggYmxhaCBibGFoIGJsYWgg"
+ "YmxhaCBibGFoIGJsYWg=" },
+};
+
+/* UTF8 to UTF16LE test vectors */
+struct utf8_16_test_vector {
+ size_t len8;
+ size_t len16;
+ const char *utf8;
+ const char *utf16;
+};
+
+static struct utf8_16_test_vector utf8_16_test_vectors[] = {
+ { 1, 2, "a", "\x61\x00" },
+ { 16, 32, "0123456789abcdef",
+ "\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00"
+ "\x38\x00\x39\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00" },
+ { 77, 78,
+ "\xf2\xa4\xa5\x94\x49\xf2\xa1\x98\x98\xd8\x8a\xe1\xb4\x88\xea\xa7"
+ "\xaa\xde\x95\xe2\x85\xb1\xe7\xb1\x9a\xf2\xb5\xa1\xae\x37\x2d\xd0"
+ "\xa9\xe1\x9a\x9c\xe8\xb0\xb7\xc8\x95\x0a\xf3\xaa\x92\xba\xf2\x83"
+ "\xb0\x99\xf0\x9b\xbe\x8f\x4f\xc8\x86\x30\xe7\xab\xa0\xda\xb9\xd8"
+ "\x89\xd8\xbc\xd7\x8a\xd9\xbc\xc3\x8f\x33\x62\xda\xb7",
+ "\x52\xda\x54\xdd\x49\x00\x45\xda\x18\xde\x0a\x06\x08\x1d\xea\xa9"
+ "\x95\x07\x71\x21\x5a\x7c\x96\xda\x6e\xdc\x37\x00\x2d\x00\x29\x04"
+ "\x9c\x16\x37\x8c\x15\x02\x0a\x00\x69\xdb\xba\xdc\xcf\xd9\x19\xdc"
+ "\x2f\xd8\x8f\xdf\x4f\x00\x06\x02\x30\x00\xe0\x7a\xb9\x06\x09\x06"
+ "\x3c\x06\xca\x05\x7c\x06\xcf\x00\x33\x00\x62\x00\xb7\x06" },
+};
+
static int pbkdf_test_vectors(void)
{
char result[256];
unsigned int i;
const struct kdf_test_vector *vec;
- for (i = 0; i < (sizeof(kdf_test_vectors) / sizeof(*kdf_test_vectors)); i++) {
+ for (i = 0; i < ARRAY_SIZE(kdf_test_vectors); i++) {
crypt_backend_memzero(result, sizeof(result));
vec = &kdf_test_vectors[i];
printf("PBKDF vector %02d %s ", i, vec->type);
@@ -1012,17 +1120,37 @@ static int hash_test(void)
if (!r)
r = crypt_hash_final(h, result, vector->out[j].length);
- crypt_hash_destroy(h);
- if (r)
+ if (r) {
+ crypt_hash_destroy(h);
return EXIT_FAILURE;
+ }
if (memcmp(result, vector->out[j].out, vector->out[j].length)) {
printf("[FAILED]\n");
printhex(" got", result, vector->out[j].length);
printhex("want", vector->out[j].out, vector->out[j].length);
+ crypt_hash_destroy(h);
+ return EXIT_FAILURE;
+ }
+
+ /*
+ * After crypt_hash_final() the context must be reset, repeat
+ */
+ crypt_backend_memzero(result, sizeof(result));
+ r = crypt_hash_write(h, vector->data, vector->data_length);
+ if (!r)
+ r = crypt_hash_final(h, result, vector->out[j].length);
+
+ if (r || memcmp(result, vector->out[j].out, vector->out[j].length)) {
+ printf("[FAILED (RESET CONTEXT)]\n");
+ printhex(" got", result, vector->out[j].length);
+ printhex("want", vector->out[j].out, vector->out[j].length);
+ crypt_hash_destroy(h);
return EXIT_FAILURE;
}
+
+ crypt_hash_destroy(h);
}
printf("\n");
}
@@ -1065,17 +1193,36 @@ static int hmac_test(void)
if (!r)
r = crypt_hmac_final(hmac, result, vector->out[j].length);
- crypt_hmac_destroy(hmac);
-
- if (r)
+ if (r) {
+ crypt_hmac_destroy(hmac);
return EXIT_FAILURE;
+ }
if (memcmp(result, vector->out[j].out, vector->out[j].length)) {
printf("[FAILED]\n");
printhex(" got", result, vector->out[j].length);
printhex("want", vector->out[j].out, vector->out[j].length);
+ crypt_hmac_destroy(hmac);
+ return EXIT_FAILURE;
+ }
+
+ /*
+ * After crypt_hmac_final() the context must be reset, repeat
+ */
+ crypt_backend_memzero(result, sizeof(result));
+ r = crypt_hmac_write(hmac, vector->data, vector->data_length);
+ if (!r)
+ r = crypt_hmac_final(hmac, result, vector->out[j].length);
+
+ if (r || memcmp(result, vector->out[j].out, vector->out[j].length)) {
+ printf("[FAILED (RESET CONTEXT)]\n");
+ printhex(" got", result, vector->out[j].length);
+ printhex("want", vector->out[j].out, vector->out[j].length);
+ crypt_hmac_destroy(hmac);
return EXIT_FAILURE;
}
+
+ crypt_hmac_destroy(hmac);
}
printf("\n");
}
@@ -1182,7 +1329,9 @@ static int cipher_iv_test(void)
if (vector->data_length > sizeof(result))
return EXIT_FAILURE;
- snprintf(mode_iv, sizeof(mode_iv)-2, "%s-%s", vector->cipher_mode, vector->iv_name);
+ if (snprintf(mode_iv, sizeof(mode_iv)-2, "%s-%s", vector->cipher_mode, vector->iv_name) < 0)
+ return EXIT_FAILURE;
+
r = crypt_storage_init(&storage, vector->out[j].sector_size, vector->cipher_name, mode_iv,
vector->key, vector->key_length, vector->out[j].large_iv);
if (r == -ENOENT || r == -ENOTSUP) {
@@ -1231,6 +1380,128 @@ static int cipher_iv_test(void)
return EXIT_SUCCESS;
}
+static int check_hash(const char *hash)
+{
+ struct crypt_hash *h;
+
+ if (crypt_hash_size(hash) < 0)
+ return EXIT_FAILURE;
+
+ if (crypt_hash_init(&h, hash))
+ return EXIT_FAILURE;
+
+ crypt_hash_destroy(h);
+ return EXIT_SUCCESS;
+}
+
+static int base64_test(void)
+{
+ unsigned int i;
+ char *s;
+ size_t s_len;
+
+ for (i = 0; i < ARRAY_SIZE(base64_test_vectors); i++) {
+ printf("BASE64 %02d ", i);
+ s = NULL;
+ s_len = 0;
+ if (crypt_base64_encode(&s, &s_len,
+ base64_test_vectors[i].decoded,
+ base64_test_vectors[i].decoded_len) < 0) {
+ printf("[ENCODE FAILED]\n");
+ return EXIT_FAILURE;
+ } else if (strcmp(s, base64_test_vectors[i].encoded)) {
+ printf("[ENCODE FAILED]\n");
+ free(s);
+ return EXIT_FAILURE;
+ }
+ printf("[encode]");
+ free(s);
+
+ s = NULL;
+ s_len = 0;
+ if (crypt_base64_decode(&s, &s_len,
+ base64_test_vectors[i].encoded,
+ strlen(base64_test_vectors[i].encoded)) < 0) {
+ printf("[DECODE FAILED]\n");
+ return EXIT_FAILURE;
+ } else if (s_len != base64_test_vectors[i].decoded_len ||
+ memcmp(s, base64_test_vectors[i].decoded, s_len)) {
+ printf("[DECODE FAILED]\n");
+ return EXIT_FAILURE;
+ }
+ printf("[decode]\n");
+ free(s);
+ }
+
+ return EXIT_SUCCESS;
+}
+
+static int utf8_16_test(void)
+{
+ unsigned int i;
+ char s8[128], *s;
+ char16_t c16[256], s16[256], *su;
+
+ for (i = 0; i < ARRAY_SIZE(utf8_16_test_vectors); i++) {
+ printf("UTF8/16 %02d ", i);
+ crypt_backend_memzero(s16, sizeof(s16));
+ su = &s16[0];
+ if (crypt_utf8_to_utf16(&su, utf8_16_test_vectors[i].utf8,
+ utf8_16_test_vectors[i].len8) < 0 ||
+ memcmp(utf8_16_test_vectors[i].utf16, s16,
+ utf8_16_test_vectors[i].len16)) {
+ printf("[UTF8_TO_UTF16 FAILED]\n");
+ return EXIT_FAILURE;
+ }
+ printf("[UTF8_TO_UTF16]");
+
+ crypt_backend_memzero(s8, sizeof(s8));
+ s = &s8[0];
+ memcpy(c16, utf8_16_test_vectors[i].utf16, utf8_16_test_vectors[i].len16);
+ if (crypt_utf16_to_utf8(&s, c16, utf8_16_test_vectors[i].len16) < 0 ||
+ utf8_16_test_vectors[i].len8 != strlen(s8) ||
+ memcmp(utf8_16_test_vectors[i].utf8, s8,
+ utf8_16_test_vectors[i].len8)) {
+ printf("[UTF16_TO_UTF8 FAILED]\n");
+ return EXIT_FAILURE;
+ }
+ printf("[UTF16_TO_UTF8]\n");
+ }
+
+ return EXIT_SUCCESS;
+}
+
+static int default_alg_test(void)
+{
+ printf("Defaults: [LUKS1 hash %s] ", DEFAULT_LUKS1_HASH);
+ if (check_hash(DEFAULT_LUKS1_HASH))
+ return EXIT_FAILURE;
+
+ printf("[PLAIN hash %s] ", DEFAULT_PLAIN_HASH);
+ if (check_hash(DEFAULT_PLAIN_HASH))
+ return EXIT_FAILURE;
+
+ printf("[VERITY hash %s] ", DEFAULT_VERITY_HASH);
+ if (check_hash(DEFAULT_VERITY_HASH))
+ return EXIT_FAILURE;
+
+ printf("[OK]\n");
+
+ return EXIT_SUCCESS;
+}
+
+static int memcmp_test(void)
+{
+ printf("MEMEQ ");
+ if (!crypt_backend_memeq("aaaaaaaa", "bbbbbbbb", 8))
+ return EXIT_FAILURE;
+ if (crypt_backend_memeq("aaaaaaaa", "aaaaaaaa", 8))
+ return EXIT_FAILURE;
+ printf("[OK]\n");
+
+ return EXIT_SUCCESS;
+}
+
static void __attribute__((noreturn)) exit_test(const char *msg, int r)
{
if (msg)
@@ -1248,7 +1519,7 @@ int main(__attribute__ ((unused)) int argc, __attribute__ ((unused))char *argv[]
exit(77);
}
- if (crypt_backend_init())
+ if (crypt_backend_init(fips_mode()))
exit_test("Crypto backend init error.", EXIT_FAILURE);
printf("Test vectors using %s crypto backend.\n", crypt_backend_version());
@@ -1268,5 +1539,21 @@ int main(__attribute__ ((unused)) int argc, __attribute__ ((unused))char *argv[]
if (cipher_iv_test())
exit_test("IV test failed.", EXIT_FAILURE);
+ if (base64_test())
+ exit_test("BASE64 test failed.", EXIT_FAILURE);
+
+ if (memcmp_test())
+ exit_test("Memcmp test failed.", EXIT_FAILURE);
+
+ if (utf8_16_test())
+ exit_test("UTF8/16 test failed.", EXIT_FAILURE);
+
+ if (default_alg_test()) {
+ if (fips_mode())
+ printf("\nDefault compiled-in algorithms test ignored (FIPS mode on).\n");
+ else
+ exit_test("\nDefault compiled-in algorithms test failed.", EXIT_FAILURE);
+ }
+
exit_test(NULL, EXIT_SUCCESS);
}