1 /* $NetBSD: sodium_selftest.c,v 1.2 2024/07/26 18:32:15 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 2024 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifdef _KERNEL 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: sodium_selftest.c,v 1.2 2024/07/26 18:32:15 riastradh Exp $"); 33 34 #include <sys/types.h> 35 36 #include <sys/systm.h> 37 38 #include <lib/libkern/libkern.h> 39 40 #else 41 42 #include <sys/cdefs.h> 43 __RCSID("$NetBSD: sodium_selftest.c,v 1.2 2024/07/26 18:32:15 riastradh Exp $"); 44 45 #include <stdint.h> 46 #include <stdio.h> 47 #include <string.h> 48 49 static void 50 hexdump(int (*prf)(const char *, ...) __printflike(1,2), const char *prefix, 51 const void *buf, size_t len) 52 { 53 const uint8_t *p = buf; 54 size_t i; 55 56 (*prf)("%s (%zu bytes @ %p)\n", prefix, len, buf); 57 for (i = 0; i < len; i++) { 58 if (i % 16 == 8) 59 (*prf)(" "); 60 else 61 (*prf)(" "); 62 (*prf)("%02hhx", p[i]); 63 if ((i + 1) % 16 == 0) 64 (*prf)("\n"); 65 } 66 if (i % 16) 67 (*prf)("\n"); 68 } 69 70 #endif 71 72 #include <crypto/sodium/crypto_aead_chacha20poly1305.h> 73 #include <crypto/sodium/crypto_aead_xchacha20poly1305.h> 74 #include <crypto/sodium/sodium_selftest.h> 75 76 /* 77 * Test misalignments up to and including this. Would be nice to do 78 * this up to, say, 15, but that takes 16^5 = 2^20 ~ 1m trials, which 79 * is a bit steep as a self-test. 80 */ 81 #define TESTALIGN 1 82 83 int 84 crypto_aead_chacha20poly1305_ietf_selftest(void) 85 { 86 /* https://datatracker.ietf.org/doc/html/rfc8439#section-2.8.2 */ 87 static const uint8_t plaintext[] = { 88 0x4c,0x61,0x64,0x69, 0x65,0x73,0x20,0x61, 89 0x6e,0x64,0x20,0x47, 0x65,0x6e,0x74,0x6c, 90 0x65,0x6d,0x65,0x6e, 0x20,0x6f,0x66,0x20, 91 0x74,0x68,0x65,0x20, 0x63,0x6c,0x61,0x73, 92 0x73,0x20,0x6f,0x66, 0x20,0x27,0x39,0x39, 93 0x3a,0x20,0x49,0x66, 0x20,0x49,0x20,0x63, 94 0x6f,0x75,0x6c,0x64, 0x20,0x6f,0x66,0x66, 95 0x65,0x72,0x20,0x79, 0x6f,0x75,0x20,0x6f, 96 0x6e,0x6c,0x79,0x20, 0x6f,0x6e,0x65,0x20, 97 0x74,0x69,0x70,0x20, 0x66,0x6f,0x72,0x20, 98 0x74,0x68,0x65,0x20, 0x66,0x75,0x74,0x75, 99 0x72,0x65,0x2c,0x20, 0x73,0x75,0x6e,0x73, 100 0x63,0x72,0x65,0x65, 0x6e,0x20,0x77,0x6f, 101 0x75,0x6c,0x64,0x20, 0x62,0x65,0x20,0x69, 102 0x74,0x2e, 103 }; 104 static const uint8_t aad[] = { 105 0x50,0x51,0x52,0x53, 0xc0,0xc1,0xc2,0xc3, 106 0xc4,0xc5,0xc6,0xc7, 107 }; 108 static const uint8_t key[] = { 109 0x80,0x81,0x82,0x83, 0x84,0x85,0x86,0x87, 110 0x88,0x89,0x8a,0x8b, 0x8c,0x8d,0x8e,0x8f, 111 0x90,0x91,0x92,0x93, 0x94,0x95,0x96,0x97, 112 0x98,0x99,0x9a,0x9b, 0x9c,0x9d,0x9e,0x9f, 113 }; 114 static const uint8_t nonce[] = { 115 0x07,0x00,0x00,0x00, 116 0x40,0x41,0x42,0x43, 0x44,0x45,0x46,0x47, 117 }; 118 static const uint8_t ciphertext[] = { 119 0xd3,0x1a,0x8d,0x34, 0x64,0x8e,0x60,0xdb, 120 0x7b,0x86,0xaf,0xbc, 0x53,0xef,0x7e,0xc2, 121 0xa4,0xad,0xed,0x51, 0x29,0x6e,0x08,0xfe, 122 0xa9,0xe2,0xb5,0xa7, 0x36,0xee,0x62,0xd6, 123 0x3d,0xbe,0xa4,0x5e, 0x8c,0xa9,0x67,0x12, 124 0x82,0xfa,0xfb,0x69, 0xda,0x92,0x72,0x8b, 125 0x1a,0x71,0xde,0x0a, 0x9e,0x06,0x0b,0x29, 126 0x05,0xd6,0xa5,0xb6, 0x7e,0xcd,0x3b,0x36, 127 0x92,0xdd,0xbd,0x7f, 0x2d,0x77,0x8b,0x8c, 128 0x98,0x03,0xae,0xe3, 0x28,0x09,0x1b,0x58, 129 0xfa,0xb3,0x24,0xe4, 0xfa,0xd6,0x75,0x94, 130 0x55,0x85,0x80,0x8b, 0x48,0x31,0xd7,0xbc, 131 0x3f,0xf4,0xde,0xf0, 0x8e,0x4b,0x7a,0x9d, 132 0xe5,0x76,0xd2,0x65, 0x86,0xce,0xc6,0x4b, 133 0x61,0x16, 134 135 0x1a,0xe1,0x0b,0x59, 0x4f,0x09,0xe2,0x6a, 136 0x7e,0x90,0x2e,0xcb, 0xd0,0x60,0x06,0x91, 137 }; 138 uint8_t inbuf[sizeof(ciphertext) + TESTALIGN]; 139 uint8_t outbuf[sizeof(ciphertext) + TESTALIGN]; 140 uint8_t aadbuf[sizeof(aad) + TESTALIGN]; 141 uint8_t noncebuf[sizeof(nonce) + TESTALIGN]; 142 uint8_t keybuf[sizeof(key) + TESTALIGN]; 143 unsigned i, j, k, L, M; 144 145 /* 146 * Iterate over alignment and misalignment of all four inputs 147 * (plaintext/ciphertext, associated data, nonce, and key), and 148 * the output (ciphertext/plaintext). 149 * 150 * With apologies for the quirky nonindentation here -- it just 151 * gets nested a little too much. 152 */ 153 for (i = 0; i <= TESTALIGN; i++) { 154 for (j = 0; j <= TESTALIGN; j++) { 155 for (k = 0; k <= TESTALIGN; k++) { 156 for (L = 0; L <= TESTALIGN; L++) { 157 for (M = 0; M <= TESTALIGN; M++) { 158 unsigned long long outsize = 0; 159 int error; 160 char t[128]; 161 unsigned u; 162 163 /* 164 * Verify encryption produces the expected ciphertext. 165 */ 166 memset(inbuf, 0, sizeof(inbuf)); 167 memset(aadbuf, 0, sizeof(aadbuf)); 168 memset(noncebuf, 0, sizeof(noncebuf)); 169 memset(keybuf, 0, sizeof(keybuf)); 170 memset(outbuf, 0, sizeof(outbuf)); 171 172 memcpy(inbuf + i, plaintext, sizeof(plaintext)); 173 memcpy(aadbuf + j, aad, sizeof(aad)); 174 memcpy(noncebuf + k, nonce, sizeof(nonce)); 175 memcpy(keybuf + L, key, sizeof(key)); 176 177 error = crypto_aead_chacha20poly1305_ietf_encrypt(outbuf + M, 178 &outsize, 179 inbuf + i, sizeof(plaintext), 180 aadbuf + j, sizeof(aad), 181 NULL, /* secret nonce, not supported */ 182 noncebuf + k, 183 keybuf + L); 184 if (error) { 185 snprintf(t, sizeof(t), 186 "%s: %s i=%u j=%u k=%u L=%u M=%u", 187 __func__, "encrypt", i, j, k, L, M); 188 printf("%s: encrypt error=%d\n", t, error); 189 return -1; 190 } 191 if (outsize != sizeof(ciphertext)) { 192 snprintf(t, sizeof(t), 193 "%s: %s i=%u j=%u k=%u L=%u M=%u", 194 __func__, "encrypt", i, j, k, L, M); 195 printf("%s: outsize=%llu is not %zu\n", t, 196 outsize, sizeof(ciphertext)); 197 return -1; 198 } 199 if (memcmp(outbuf + M, ciphertext, sizeof(ciphertext)) != 0) { 200 snprintf(t, sizeof(t), 201 "%s: %s i=%u j=%u k=%u L=%u M=%u", 202 __func__, "encrypt", i, j, k, L, M); 203 hexdump(printf, t, outbuf + M, sizeof(ciphertext)); 204 return -1; 205 } 206 207 /* 208 * Verify decryption of the valid ciphertext succeeds 209 * and produces the expected plaintext. 210 */ 211 memset(inbuf, 0, sizeof(inbuf)); 212 memset(aadbuf, 0, sizeof(aadbuf)); 213 memset(noncebuf, 0, sizeof(noncebuf)); 214 memset(keybuf, 0, sizeof(keybuf)); 215 memset(outbuf, 0, sizeof(outbuf)); 216 217 memcpy(inbuf + i, ciphertext, sizeof(ciphertext)); 218 memcpy(aadbuf + j, aad, sizeof(aad)); 219 memcpy(noncebuf + k, nonce, sizeof(nonce)); 220 memcpy(keybuf + L, key, sizeof(key)); 221 222 error = crypto_aead_chacha20poly1305_ietf_decrypt(outbuf + M, 223 &outsize, 224 NULL, /* secret nonce, not supported */ 225 inbuf + i, sizeof(ciphertext), 226 aadbuf + j, sizeof(aad), 227 noncebuf + k, 228 keybuf + L); 229 if (error) { 230 snprintf(t, sizeof(t), 231 "%s: %s i=%u j=%u k=%u L=%u M=%u", 232 __func__, "decrypt", i, j, k, L, M); 233 printf("%s: decrypt error=%d\n", t, error); 234 return -1; 235 } 236 if (outsize != sizeof(plaintext)) { 237 snprintf(t, sizeof(t), 238 "%s: %s i=%u j=%u k=%u L=%u M=%u", 239 __func__, "decrypt", i, j, k, L, M); 240 printf("%s: outsize=%llu is not %zu\n", t, 241 outsize, sizeof(plaintext)); 242 return -1; 243 } 244 if (memcmp(outbuf + M, plaintext, sizeof(plaintext)) != 0) { 245 snprintf(t, sizeof(t), 246 "%s: %s i=%u j=%u k=%u L=%u M=%u", 247 __func__, "decrypt", i, j, k, L, M); 248 hexdump(printf, t, outbuf + M, sizeof(ciphertext)); 249 return -1; 250 } 251 252 /* 253 * Verify decryption of a corrupted ciphertext fails 254 * and produces all-zero output. 255 */ 256 memset(outbuf, 0x5a, sizeof(outbuf)); 257 inbuf[i] ^= 0x80; 258 error = crypto_aead_chacha20poly1305_ietf_decrypt(outbuf + M, 259 &outsize, 260 NULL, /* secret nonce, not supported */ 261 inbuf + i, sizeof(ciphertext), 262 aadbuf + j, sizeof(aad), 263 noncebuf + k, 264 keybuf + L); 265 inbuf[i] ^= 0x80; 266 if (error == 0) { 267 snprintf(t, sizeof(t), 268 "%s: %s i=%u j=%u k=%u L=%u M=%u", 269 __func__, "msg forgery", i, j, k, L, M); 270 printf("%s: wrongly accepted\n", t); 271 return -1; 272 } 273 for (u = 0; u < sizeof(plaintext); u++) { 274 if (outbuf[M + u] != 0) { 275 snprintf(t, sizeof(t), 276 "%s: %s i=%u j=%u k=%u L=%u M=%u", 277 __func__, "msg forgery", i, j, k, L, M); 278 hexdump(printf, t, outbuf + M, 279 sizeof(plaintext)); 280 return -1; 281 } 282 } 283 284 /* 285 * Verify decryption with corrupted associated data 286 * fails and produces all-zero output. 287 */ 288 memset(outbuf, 0xac, sizeof(outbuf)); 289 aadbuf[j] ^= 0x80; 290 error = crypto_aead_chacha20poly1305_ietf_decrypt(outbuf + M, 291 &outsize, 292 NULL, /* secret nonce, not supported */ 293 inbuf + i, sizeof(ciphertext), 294 aadbuf + j, sizeof(aad), 295 noncebuf + k, 296 keybuf + L); 297 aadbuf[j] ^= 0x80; 298 if (error == 0) { 299 snprintf(t, sizeof(t), 300 "%s: %s i=%u j=%u k=%u L=%u M=%u", 301 __func__, "aad forgery", i, j, k, L, M); 302 printf("%s: wrongly accepted\n", t); 303 return -1; 304 } 305 for (u = 0; u < sizeof(plaintext); u++) { 306 if (outbuf[M + u] != 0) { 307 snprintf(t, sizeof(t), 308 "%s: %s i=%u j=%u k=%u L=%u M=%u", 309 __func__, "aad forgery", i, j, k, L, M); 310 hexdump(printf, t, outbuf + M, 311 sizeof(plaintext)); 312 return -1; 313 } 314 } 315 } 316 } 317 } 318 } 319 } 320 321 return 0; 322 } 323 324 int 325 crypto_aead_xchacha20poly1305_ietf_selftest(void) 326 { 327 /* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha#appendix-A.3.1 */ 328 static const uint8_t plaintext[] = { 329 0x4c,0x61,0x64,0x69, 0x65,0x73,0x20,0x61, 330 0x6e,0x64,0x20,0x47, 0x65,0x6e,0x74,0x6c, 331 0x65,0x6d,0x65,0x6e, 0x20,0x6f,0x66,0x20, 332 0x74,0x68,0x65,0x20, 0x63,0x6c,0x61,0x73, 333 0x73,0x20,0x6f,0x66, 0x20,0x27,0x39,0x39, 334 0x3a,0x20,0x49,0x66, 0x20,0x49,0x20,0x63, 335 0x6f,0x75,0x6c,0x64, 0x20,0x6f,0x66,0x66, 336 0x65,0x72,0x20,0x79, 0x6f,0x75,0x20,0x6f, 337 0x6e,0x6c,0x79,0x20, 0x6f,0x6e,0x65,0x20, 338 0x74,0x69,0x70,0x20, 0x66,0x6f,0x72,0x20, 339 0x74,0x68,0x65,0x20, 0x66,0x75,0x74,0x75, 340 0x72,0x65,0x2c,0x20, 0x73,0x75,0x6e,0x73, 341 0x63,0x72,0x65,0x65, 0x6e,0x20,0x77,0x6f, 342 0x75,0x6c,0x64,0x20, 0x62,0x65,0x20,0x69, 343 0x74,0x2e, 344 }; 345 static const uint8_t aad[] = { 346 0x50,0x51,0x52,0x53, 0xc0,0xc1,0xc2,0xc3, 347 0xc4,0xc5,0xc6,0xc7, 348 }; 349 static const uint8_t key[] = { 350 0x80,0x81,0x82,0x83, 0x84,0x85,0x86,0x87, 351 0x88,0x89,0x8a,0x8b, 0x8c,0x8d,0x8e,0x8f, 352 0x90,0x91,0x92,0x93, 0x94,0x95,0x96,0x97, 353 0x98,0x99,0x9a,0x9b, 0x9c,0x9d,0x9e,0x9f, 354 }; 355 static const uint8_t nonce[] = { 356 0x40,0x41,0x42,0x43, 0x44,0x45,0x46,0x47, 357 0x48,0x49,0x4a,0x4b, 0x4c,0x4d,0x4e,0x4f, 358 0x50,0x51,0x52,0x53, 0x54,0x55,0x56,0x57, 359 0x00,0x00,0x00,0x00, 360 }; 361 static const uint8_t ciphertext[] = { 362 0xbd,0x6d,0x17,0x9d, 0x3e,0x83,0xd4,0x3b, 363 0x95,0x76,0x57,0x94, 0x93,0xc0,0xe9,0x39, 364 0x57,0x2a,0x17,0x00, 0x25,0x2b,0xfa,0xcc, 365 0xbe,0xd2,0x90,0x2c, 0x21,0x39,0x6c,0xbb, 366 0x73,0x1c,0x7f,0x1b, 0x0b,0x4a,0xa6,0x44, 367 0x0b,0xf3,0xa8,0x2f, 0x4e,0xda,0x7e,0x39, 368 0xae,0x64,0xc6,0x70, 0x8c,0x54,0xc2,0x16, 369 0xcb,0x96,0xb7,0x2e, 0x12,0x13,0xb4,0x52, 370 0x2f,0x8c,0x9b,0xa4, 0x0d,0xb5,0xd9,0x45, 371 0xb1,0x1b,0x69,0xb9, 0x82,0xc1,0xbb,0x9e, 372 0x3f,0x3f,0xac,0x2b, 0xc3,0x69,0x48,0x8f, 373 0x76,0xb2,0x38,0x35, 0x65,0xd3,0xff,0xf9, 374 0x21,0xf9,0x66,0x4c, 0x97,0x63,0x7d,0xa9, 375 0x76,0x88,0x12,0xf6, 0x15,0xc6,0x8b,0x13, 376 0xb5,0x2e, 377 378 0xc0,0x87,0x59,0x24, 0xc1,0xc7,0x98,0x79, 379 0x47,0xde,0xaf,0xd8, 0x78,0x0a,0xcf,0x49, 380 }; 381 uint8_t inbuf[sizeof(ciphertext) + TESTALIGN]; 382 uint8_t outbuf[sizeof(ciphertext) + TESTALIGN]; 383 uint8_t aadbuf[sizeof(aad) + TESTALIGN]; 384 uint8_t noncebuf[sizeof(nonce) + TESTALIGN]; 385 uint8_t keybuf[sizeof(key) + TESTALIGN]; 386 unsigned i, j, k, L, M; 387 388 /* 389 * Iterate over alignment and misalignment of all four inputs 390 * (plaintext/ciphertext, associated data, nonce, and key), and 391 * the output (ciphertext/plaintext). 392 * 393 * With apologies for the quirky nonindentation here -- it just 394 * gets nested a little too much. 395 */ 396 for (i = 0; i <= TESTALIGN; i++) { 397 for (j = 0; j <= TESTALIGN; j++) { 398 for (k = 0; k <= TESTALIGN; k++) { 399 for (L = 0; L <= TESTALIGN; L++) { 400 for (M = 0; M <= TESTALIGN; M++) { 401 unsigned long long outsize = 0; 402 int error; 403 char t[128]; 404 unsigned u; 405 406 /* 407 * Verify encryption produces the expected ciphertext. 408 */ 409 memset(inbuf, 0, sizeof(inbuf)); 410 memset(aadbuf, 0, sizeof(aadbuf)); 411 memset(noncebuf, 0, sizeof(noncebuf)); 412 memset(keybuf, 0, sizeof(keybuf)); 413 memset(outbuf, 0, sizeof(outbuf)); 414 415 memcpy(inbuf + i, plaintext, sizeof(plaintext)); 416 memcpy(aadbuf + j, aad, sizeof(aad)); 417 memcpy(noncebuf + k, nonce, sizeof(nonce)); 418 memcpy(keybuf + L, key, sizeof(key)); 419 420 error = crypto_aead_xchacha20poly1305_ietf_encrypt(outbuf + M, 421 &outsize, 422 inbuf + i, sizeof(plaintext), 423 aadbuf + j, sizeof(aad), 424 NULL, /* secret nonce, not supported */ 425 noncebuf + k, 426 keybuf + L); 427 if (error) { 428 snprintf(t, sizeof(t), 429 "%s: %s i=%u j=%u k=%u L=%u M=%u", 430 __func__, "encrypt", i, j, k, L, M); 431 printf("%s: encrypt error=%d\n", t, error); 432 return -1; 433 } 434 if (outsize != sizeof(ciphertext)) { 435 snprintf(t, sizeof(t), 436 "%s: %s i=%u j=%u k=%u L=%u M=%u", 437 __func__, "encrypt", i, j, k, L, M); 438 printf("%s: outsize=%llu is not %zu\n", t, 439 outsize, sizeof(ciphertext)); 440 return -1; 441 } 442 if (memcmp(outbuf + M, ciphertext, sizeof(ciphertext)) != 0) { 443 snprintf(t, sizeof(t), 444 "%s: %s i=%u j=%u k=%u L=%u M=%u", 445 __func__, "encrypt", i, j, k, L, M); 446 hexdump(printf, t, outbuf + M, sizeof(ciphertext)); 447 return -1; 448 } 449 450 /* 451 * Verify decryption of the valid ciphertext succeeds 452 * and produces the expected plaintext. 453 */ 454 memset(inbuf, 0, sizeof(inbuf)); 455 memset(aadbuf, 0, sizeof(aadbuf)); 456 memset(noncebuf, 0, sizeof(noncebuf)); 457 memset(keybuf, 0, sizeof(keybuf)); 458 memset(outbuf, 0, sizeof(outbuf)); 459 460 memcpy(inbuf + i, ciphertext, sizeof(ciphertext)); 461 memcpy(aadbuf + j, aad, sizeof(aad)); 462 memcpy(noncebuf + k, nonce, sizeof(nonce)); 463 memcpy(keybuf + L, key, sizeof(key)); 464 465 error = crypto_aead_xchacha20poly1305_ietf_decrypt(outbuf + M, 466 &outsize, 467 NULL, /* secret nonce, not supported */ 468 inbuf + i, sizeof(ciphertext), 469 aadbuf + j, sizeof(aad), 470 noncebuf + k, 471 keybuf + L); 472 if (error) { 473 snprintf(t, sizeof(t), 474 "%s: %s i=%u j=%u k=%u L=%u M=%u", 475 __func__, "decrypt", i, j, k, L, M); 476 printf("%s: decrypt error=%d\n", t, error); 477 return -1; 478 } 479 if (outsize != sizeof(plaintext)) { 480 snprintf(t, sizeof(t), 481 "%s: %s i=%u j=%u k=%u L=%u M=%u", 482 __func__, "decrypt", i, j, k, L, M); 483 printf("%s: outsize=%llu is not %zu\n", t, 484 outsize, sizeof(plaintext)); 485 return -1; 486 } 487 if (memcmp(outbuf + M, plaintext, sizeof(plaintext)) != 0) { 488 snprintf(t, sizeof(t), 489 "%s: %s i=%u j=%u k=%u L=%u M=%u", 490 __func__, "decrypt", i, j, k, L, M); 491 hexdump(printf, t, outbuf + M, sizeof(ciphertext)); 492 return -1; 493 } 494 495 /* 496 * Verify decryption of a corrupted ciphertext fails 497 * and produces all-zero output. 498 */ 499 memset(outbuf, 0x5a, sizeof(outbuf)); 500 inbuf[i] ^= 0x80; 501 error = crypto_aead_xchacha20poly1305_ietf_decrypt(outbuf + M, 502 &outsize, 503 NULL, /* secret nonce, not supported */ 504 inbuf + i, sizeof(ciphertext), 505 aadbuf + j, sizeof(aad), 506 noncebuf + k, 507 keybuf + L); 508 inbuf[i] ^= 0x80; 509 if (error == 0) { 510 snprintf(t, sizeof(t), 511 "%s: %s i=%u j=%u k=%u L=%u M=%u", 512 __func__, "msg forgery", i, j, k, L, M); 513 printf("%s: wrongly accepted\n", t); 514 return -1; 515 } 516 for (u = 0; u < sizeof(plaintext); u++) { 517 if (outbuf[M + u] != 0) { 518 snprintf(t, sizeof(t), 519 "%s: %s i=%u j=%u k=%u L=%u M=%u", 520 __func__, "msg forgery", i, j, k, L, M); 521 hexdump(printf, t, outbuf + M, 522 sizeof(plaintext)); 523 return -1; 524 } 525 } 526 527 /* 528 * Verify decryption with corrupted associated data 529 * fails and produces all-zero output. 530 */ 531 memset(outbuf, 0xac, sizeof(outbuf)); 532 aadbuf[j] ^= 0x80; 533 error = crypto_aead_xchacha20poly1305_ietf_decrypt(outbuf + M, 534 &outsize, 535 NULL, /* secret nonce, not supported */ 536 inbuf + i, sizeof(ciphertext), 537 aadbuf + j, sizeof(aad), 538 noncebuf + k, 539 keybuf + L); 540 aadbuf[j] ^= 0x80; 541 if (error == 0) { 542 snprintf(t, sizeof(t), 543 "%s: %s i=%u j=%u k=%u L=%u M=%u", 544 __func__, "aad forgery", i, j, k, L, M); 545 printf("%s: wrongly accepted\n", t); 546 return -1; 547 } 548 for (u = 0; u < sizeof(plaintext); u++) { 549 if (outbuf[M + u] != 0) { 550 snprintf(t, sizeof(t), 551 "%s: %s i=%u j=%u k=%u L=%u M=%u", 552 __func__, "aad forgery", i, j, k, L, M); 553 hexdump(printf, t, outbuf + M, 554 sizeof(plaintext)); 555 return -1; 556 } 557 } 558 } 559 } 560 } 561 } 562 } 563 564 return 0; 565 } 566 567 int 568 sodium_selftest(void) 569 { 570 int result = 0; 571 572 result |= crypto_aead_chacha20poly1305_ietf_selftest(); 573 result |= crypto_aead_xchacha20poly1305_ietf_selftest(); 574 575 return result; 576 } 577 578 #ifdef SODIUM_SELFTEST_MAIN 579 int 580 main(void) 581 { 582 583 return sodium_selftest(); 584 } 585 #endif 586