Module Name: src
Committed By: riastradh
Date: Fri Jul 26 18:32:15 UTC 2024
Modified Files:
src/sys/crypto/sodium: sodium_selftest.h
src/sys/external/isc/libsodium/src: sodium_selftest.c
Log Message:
sys/crypto/sodium: Add self-test for XChaCha20/Poly1305 AEAD.
PR kern/58468
To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/crypto/sodium/sodium_selftest.h
cvs rdiff -u -r1.1 -r1.2 src/sys/external/isc/libsodium/src/sodium_selftest.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/crypto/sodium/sodium_selftest.h
diff -u src/sys/crypto/sodium/sodium_selftest.h:1.1 src/sys/crypto/sodium/sodium_selftest.h:1.2
--- src/sys/crypto/sodium/sodium_selftest.h:1.1 Fri Jul 26 18:25:03 2024
+++ src/sys/crypto/sodium/sodium_selftest.h Fri Jul 26 18:32:15 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: sodium_selftest.h,v 1.1 2024/07/26 18:25:03 riastradh Exp $ */
+/* $NetBSD: sodium_selftest.h,v 1.2 2024/07/26 18:32:15 riastradh Exp $ */
/*-
* Copyright (c) 2024 The NetBSD Foundation, Inc.
@@ -30,6 +30,7 @@
#define _SYS_CRYPTO_SODIUM_SODIUM_SELFTEST_H_
int crypto_aead_chacha20poly1305_ietf_selftest(void);
+int crypto_aead_xchacha20poly1305_ietf_selftest(void);
int sodium_selftest(void);
Index: src/sys/external/isc/libsodium/src/sodium_selftest.c
diff -u src/sys/external/isc/libsodium/src/sodium_selftest.c:1.1 src/sys/external/isc/libsodium/src/sodium_selftest.c:1.2
--- src/sys/external/isc/libsodium/src/sodium_selftest.c:1.1 Fri Jul 26 18:25:03 2024
+++ src/sys/external/isc/libsodium/src/sodium_selftest.c Fri Jul 26 18:32:15 2024
@@ -1,4 +1,4 @@
-/* $NetBSD: sodium_selftest.c,v 1.1 2024/07/26 18:25:03 riastradh Exp $ */
+/* $NetBSD: sodium_selftest.c,v 1.2 2024/07/26 18:32:15 riastradh Exp $ */
/*-
* Copyright (c) 2024 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
#ifdef _KERNEL
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sodium_selftest.c,v 1.1 2024/07/26 18:25:03 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sodium_selftest.c,v 1.2 2024/07/26 18:32:15 riastradh Exp $");
#include <sys/types.h>
@@ -40,7 +40,7 @@ __KERNEL_RCSID(0, "$NetBSD: sodium_selft
#else
#include <sys/cdefs.h>
-__RCSID("$NetBSD: sodium_selftest.c,v 1.1 2024/07/26 18:25:03 riastradh Exp $");
+__RCSID("$NetBSD: sodium_selftest.c,v 1.2 2024/07/26 18:32:15 riastradh Exp $");
#include <stdint.h>
#include <stdio.h>
@@ -70,6 +70,7 @@ hexdump(int (*prf)(const char *, ...) __
#endif
#include <crypto/sodium/crypto_aead_chacha20poly1305.h>
+#include <crypto/sodium/crypto_aead_xchacha20poly1305.h>
#include <crypto/sodium/sodium_selftest.h>
/*
@@ -321,11 +322,255 @@ crypto_aead_chacha20poly1305_ietf_selfte
}
int
+crypto_aead_xchacha20poly1305_ietf_selftest(void)
+{
+ /* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha#appendix-A.3.1 */
+ static const uint8_t plaintext[] = {
+ 0x4c,0x61,0x64,0x69, 0x65,0x73,0x20,0x61,
+ 0x6e,0x64,0x20,0x47, 0x65,0x6e,0x74,0x6c,
+ 0x65,0x6d,0x65,0x6e, 0x20,0x6f,0x66,0x20,
+ 0x74,0x68,0x65,0x20, 0x63,0x6c,0x61,0x73,
+ 0x73,0x20,0x6f,0x66, 0x20,0x27,0x39,0x39,
+ 0x3a,0x20,0x49,0x66, 0x20,0x49,0x20,0x63,
+ 0x6f,0x75,0x6c,0x64, 0x20,0x6f,0x66,0x66,
+ 0x65,0x72,0x20,0x79, 0x6f,0x75,0x20,0x6f,
+ 0x6e,0x6c,0x79,0x20, 0x6f,0x6e,0x65,0x20,
+ 0x74,0x69,0x70,0x20, 0x66,0x6f,0x72,0x20,
+ 0x74,0x68,0x65,0x20, 0x66,0x75,0x74,0x75,
+ 0x72,0x65,0x2c,0x20, 0x73,0x75,0x6e,0x73,
+ 0x63,0x72,0x65,0x65, 0x6e,0x20,0x77,0x6f,
+ 0x75,0x6c,0x64,0x20, 0x62,0x65,0x20,0x69,
+ 0x74,0x2e,
+ };
+ static const uint8_t aad[] = {
+ 0x50,0x51,0x52,0x53, 0xc0,0xc1,0xc2,0xc3,
+ 0xc4,0xc5,0xc6,0xc7,
+ };
+ static const uint8_t key[] = {
+ 0x80,0x81,0x82,0x83, 0x84,0x85,0x86,0x87,
+ 0x88,0x89,0x8a,0x8b, 0x8c,0x8d,0x8e,0x8f,
+ 0x90,0x91,0x92,0x93, 0x94,0x95,0x96,0x97,
+ 0x98,0x99,0x9a,0x9b, 0x9c,0x9d,0x9e,0x9f,
+ };
+ static const uint8_t nonce[] = {
+ 0x40,0x41,0x42,0x43, 0x44,0x45,0x46,0x47,
+ 0x48,0x49,0x4a,0x4b, 0x4c,0x4d,0x4e,0x4f,
+ 0x50,0x51,0x52,0x53, 0x54,0x55,0x56,0x57,
+ 0x00,0x00,0x00,0x00,
+ };
+ static const uint8_t ciphertext[] = {
+ 0xbd,0x6d,0x17,0x9d, 0x3e,0x83,0xd4,0x3b,
+ 0x95,0x76,0x57,0x94, 0x93,0xc0,0xe9,0x39,
+ 0x57,0x2a,0x17,0x00, 0x25,0x2b,0xfa,0xcc,
+ 0xbe,0xd2,0x90,0x2c, 0x21,0x39,0x6c,0xbb,
+ 0x73,0x1c,0x7f,0x1b, 0x0b,0x4a,0xa6,0x44,
+ 0x0b,0xf3,0xa8,0x2f, 0x4e,0xda,0x7e,0x39,
+ 0xae,0x64,0xc6,0x70, 0x8c,0x54,0xc2,0x16,
+ 0xcb,0x96,0xb7,0x2e, 0x12,0x13,0xb4,0x52,
+ 0x2f,0x8c,0x9b,0xa4, 0x0d,0xb5,0xd9,0x45,
+ 0xb1,0x1b,0x69,0xb9, 0x82,0xc1,0xbb,0x9e,
+ 0x3f,0x3f,0xac,0x2b, 0xc3,0x69,0x48,0x8f,
+ 0x76,0xb2,0x38,0x35, 0x65,0xd3,0xff,0xf9,
+ 0x21,0xf9,0x66,0x4c, 0x97,0x63,0x7d,0xa9,
+ 0x76,0x88,0x12,0xf6, 0x15,0xc6,0x8b,0x13,
+ 0xb5,0x2e,
+
+ 0xc0,0x87,0x59,0x24, 0xc1,0xc7,0x98,0x79,
+ 0x47,0xde,0xaf,0xd8, 0x78,0x0a,0xcf,0x49,
+ };
+ uint8_t inbuf[sizeof(ciphertext) + TESTALIGN];
+ uint8_t outbuf[sizeof(ciphertext) + TESTALIGN];
+ uint8_t aadbuf[sizeof(aad) + TESTALIGN];
+ uint8_t noncebuf[sizeof(nonce) + TESTALIGN];
+ uint8_t keybuf[sizeof(key) + TESTALIGN];
+ unsigned i, j, k, L, M;
+
+ /*
+ * Iterate over alignment and misalignment of all four inputs
+ * (plaintext/ciphertext, associated data, nonce, and key), and
+ * the output (ciphertext/plaintext).
+ *
+ * With apologies for the quirky nonindentation here -- it just
+ * gets nested a little too much.
+ */
+ for (i = 0; i <= TESTALIGN; i++) {
+ for (j = 0; j <= TESTALIGN; j++) {
+ for (k = 0; k <= TESTALIGN; k++) {
+ for (L = 0; L <= TESTALIGN; L++) {
+ for (M = 0; M <= TESTALIGN; M++) {
+ unsigned long long outsize = 0;
+ int error;
+ char t[128];
+ unsigned u;
+
+ /*
+ * Verify encryption produces the expected ciphertext.
+ */
+ memset(inbuf, 0, sizeof(inbuf));
+ memset(aadbuf, 0, sizeof(aadbuf));
+ memset(noncebuf, 0, sizeof(noncebuf));
+ memset(keybuf, 0, sizeof(keybuf));
+ memset(outbuf, 0, sizeof(outbuf));
+
+ memcpy(inbuf + i, plaintext, sizeof(plaintext));
+ memcpy(aadbuf + j, aad, sizeof(aad));
+ memcpy(noncebuf + k, nonce, sizeof(nonce));
+ memcpy(keybuf + L, key, sizeof(key));
+
+ error = crypto_aead_xchacha20poly1305_ietf_encrypt(outbuf + M,
+ &outsize,
+ inbuf + i, sizeof(plaintext),
+ aadbuf + j, sizeof(aad),
+ NULL, /* secret nonce, not supported */
+ noncebuf + k,
+ keybuf + L);
+ if (error) {
+ snprintf(t, sizeof(t),
+ "%s: %s i=%u j=%u k=%u L=%u M=%u",
+ __func__, "encrypt", i, j, k, L, M);
+ printf("%s: encrypt error=%d\n", t, error);
+ return -1;
+ }
+ if (outsize != sizeof(ciphertext)) {
+ snprintf(t, sizeof(t),
+ "%s: %s i=%u j=%u k=%u L=%u M=%u",
+ __func__, "encrypt", i, j, k, L, M);
+ printf("%s: outsize=%llu is not %zu\n", t,
+ outsize, sizeof(ciphertext));
+ return -1;
+ }
+ if (memcmp(outbuf + M, ciphertext, sizeof(ciphertext)) != 0) {
+ snprintf(t, sizeof(t),
+ "%s: %s i=%u j=%u k=%u L=%u M=%u",
+ __func__, "encrypt", i, j, k, L, M);
+ hexdump(printf, t, outbuf + M, sizeof(ciphertext));
+ return -1;
+ }
+
+ /*
+ * Verify decryption of the valid ciphertext succeeds
+ * and produces the expected plaintext.
+ */
+ memset(inbuf, 0, sizeof(inbuf));
+ memset(aadbuf, 0, sizeof(aadbuf));
+ memset(noncebuf, 0, sizeof(noncebuf));
+ memset(keybuf, 0, sizeof(keybuf));
+ memset(outbuf, 0, sizeof(outbuf));
+
+ memcpy(inbuf + i, ciphertext, sizeof(ciphertext));
+ memcpy(aadbuf + j, aad, sizeof(aad));
+ memcpy(noncebuf + k, nonce, sizeof(nonce));
+ memcpy(keybuf + L, key, sizeof(key));
+
+ error = crypto_aead_xchacha20poly1305_ietf_decrypt(outbuf + M,
+ &outsize,
+ NULL, /* secret nonce, not supported */
+ inbuf + i, sizeof(ciphertext),
+ aadbuf + j, sizeof(aad),
+ noncebuf + k,
+ keybuf + L);
+ if (error) {
+ snprintf(t, sizeof(t),
+ "%s: %s i=%u j=%u k=%u L=%u M=%u",
+ __func__, "decrypt", i, j, k, L, M);
+ printf("%s: decrypt error=%d\n", t, error);
+ return -1;
+ }
+ if (outsize != sizeof(plaintext)) {
+ snprintf(t, sizeof(t),
+ "%s: %s i=%u j=%u k=%u L=%u M=%u",
+ __func__, "decrypt", i, j, k, L, M);
+ printf("%s: outsize=%llu is not %zu\n", t,
+ outsize, sizeof(plaintext));
+ return -1;
+ }
+ if (memcmp(outbuf + M, plaintext, sizeof(plaintext)) != 0) {
+ snprintf(t, sizeof(t),
+ "%s: %s i=%u j=%u k=%u L=%u M=%u",
+ __func__, "decrypt", i, j, k, L, M);
+ hexdump(printf, t, outbuf + M, sizeof(ciphertext));
+ return -1;
+ }
+
+ /*
+ * Verify decryption of a corrupted ciphertext fails
+ * and produces all-zero output.
+ */
+ memset(outbuf, 0x5a, sizeof(outbuf));
+ inbuf[i] ^= 0x80;
+ error = crypto_aead_xchacha20poly1305_ietf_decrypt(outbuf + M,
+ &outsize,
+ NULL, /* secret nonce, not supported */
+ inbuf + i, sizeof(ciphertext),
+ aadbuf + j, sizeof(aad),
+ noncebuf + k,
+ keybuf + L);
+ inbuf[i] ^= 0x80;
+ if (error == 0) {
+ snprintf(t, sizeof(t),
+ "%s: %s i=%u j=%u k=%u L=%u M=%u",
+ __func__, "msg forgery", i, j, k, L, M);
+ printf("%s: wrongly accepted\n", t);
+ return -1;
+ }
+ for (u = 0; u < sizeof(plaintext); u++) {
+ if (outbuf[M + u] != 0) {
+ snprintf(t, sizeof(t),
+ "%s: %s i=%u j=%u k=%u L=%u M=%u",
+ __func__, "msg forgery", i, j, k, L, M);
+ hexdump(printf, t, outbuf + M,
+ sizeof(plaintext));
+ return -1;
+ }
+ }
+
+ /*
+ * Verify decryption with corrupted associated data
+ * fails and produces all-zero output.
+ */
+ memset(outbuf, 0xac, sizeof(outbuf));
+ aadbuf[j] ^= 0x80;
+ error = crypto_aead_xchacha20poly1305_ietf_decrypt(outbuf + M,
+ &outsize,
+ NULL, /* secret nonce, not supported */
+ inbuf + i, sizeof(ciphertext),
+ aadbuf + j, sizeof(aad),
+ noncebuf + k,
+ keybuf + L);
+ aadbuf[j] ^= 0x80;
+ if (error == 0) {
+ snprintf(t, sizeof(t),
+ "%s: %s i=%u j=%u k=%u L=%u M=%u",
+ __func__, "aad forgery", i, j, k, L, M);
+ printf("%s: wrongly accepted\n", t);
+ return -1;
+ }
+ for (u = 0; u < sizeof(plaintext); u++) {
+ if (outbuf[M + u] != 0) {
+ snprintf(t, sizeof(t),
+ "%s: %s i=%u j=%u k=%u L=%u M=%u",
+ __func__, "aad forgery", i, j, k, L, M);
+ hexdump(printf, t, outbuf + M,
+ sizeof(plaintext));
+ return -1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
sodium_selftest(void)
{
int result = 0;
result |= crypto_aead_chacha20poly1305_ietf_selftest();
+ result |= crypto_aead_xchacha20poly1305_ietf_selftest();
return result;
}