Home | History | Annotate | Line # | Download | only in chacha
      1 /*	$NetBSD: chacha_selftest.c,v 1.1 2020/07/25 22:46:34 riastradh Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2020 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 #include "chacha_impl.h"
     30 
     31 #ifdef _KERNEL
     33 
     34 #include <lib/libkern/libkern.h>
     35 
     36 #else
     37 
     38 #include <stdio.h>
     39 #include <string.h>
     40 
     41 static void
     42 hexdump(int (*prf)(const char *, ...) __printflike(1,2), const char *prefix,
     43     const void *buf, size_t len)
     44 {
     45 	const uint8_t *p = buf;
     46 	size_t i;
     47 
     48 	(*prf)("%s (%zu bytes @ %p)\n", prefix, len, buf);
     49 	for (i = 0; i < len; i++) {
     50 		if (i % 16 == 8)
     51 			(*prf)("  ");
     52 		else
     53 			(*prf)(" ");
     54 		(*prf)("%02hhx", p[i]);
     55 		if ((i + 1) % 16 == 0)
     56 			(*prf)("\n");
     57 	}
     58 	if (i % 16)
     59 		(*prf)("\n");
     60 }
     61 
     62 #endif
     63 
     64 /* https://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-00 */
     66 static int
     67 chacha_core_selftest(const struct chacha_impl *ci)
     68 {
     69 	/* TC1, 32-byte key, rounds=12, keystream block 1 */
     70 	static const uint8_t zero[32];
     71 	static const uint8_t expected0[64] = {
     72 		0x9b,0xf4,0x9a,0x6a, 0x07,0x55,0xf9,0x53,
     73 		0x81,0x1f,0xce,0x12, 0x5f,0x26,0x83,0xd5,
     74 		0x04,0x29,0xc3,0xbb, 0x49,0xe0,0x74,0x14,
     75 		0x7e,0x00,0x89,0xa5, 0x2e,0xae,0x15,0x5f,
     76 		0x05,0x64,0xf8,0x79, 0xd2,0x7a,0xe3,0xc0,
     77 		0x2c,0xe8,0x28,0x34, 0xac,0xfa,0x8c,0x79,
     78 		0x3a,0x62,0x9f,0x2c, 0xa0,0xde,0x69,0x19,
     79 		0x61,0x0b,0xe8,0x2f, 0x41,0x13,0x26,0xbe,
     80 	};
     81 	/* TC7, 32-byte key, rounds=12, keystream block 2 */
     82 	static const uint8_t k1[32] = {
     83 		0x00,0x11,0x22,0x33, 0x44,0x55,0x66,0x77,
     84 		0x88,0x99,0xaa,0xbb, 0xcc,0xdd,0xee,0xff,
     85 		0xff,0xee,0xdd,0xcc, 0xbb,0xaa,0x99,0x88,
     86 		0x77,0x66,0x55,0x44, 0x33,0x22,0x11,0x00,
     87 	};
     88 	static const uint8_t in1[16] = {
     89 		0x01,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,
     90 		0x0f,0x1e,0x2d,0x3c, 0x4b,0x59,0x68,0x77,
     91 	};
     92 	static const uint8_t expected1[64] = {
     93 		0xcd,0x9a,0x2a,0xa9, 0xea,0x93,0xc2,0x67,
     94 		0x5e,0x82,0x88,0x14, 0x08,0xde,0x85,0x2c,
     95 		0x62,0xfa,0x74,0x6a, 0x30,0xe5,0x2b,0x45,
     96 		0xa2,0x69,0x62,0xcf, 0x43,0x51,0xe3,0x04,
     97 		0xd3,0x13,0x20,0xbb, 0xd6,0xaa,0x6c,0xc8,
     98 		0xf3,0x26,0x37,0xf9, 0x59,0x34,0xe4,0xc1,
     99 		0x45,0xef,0xd5,0x62, 0x31,0xef,0x31,0x61,
    100 		0x03,0x28,0x36,0xf4, 0x96,0x71,0x83,0x3e,
    101 	};
    102 	uint8_t out[64];
    103 	int result = 0;
    104 
    105 	(*ci->ci_chacha_core)(out, zero, zero, chacha_const32, 12);
    106 	if (memcmp(out, expected0, 64)) {
    107 		hexdump(printf, "chacha core 1", out, sizeof out);
    108 		result = -1;
    109 	}
    110 
    111 	(*ci->ci_chacha_core)(out, in1, k1, chacha_const32, 12);
    112 	if (memcmp(out, expected1, 64)) {
    113 		hexdump(printf, "chacha core 2", out, sizeof out);
    114 		result = -1;
    115 	}
    116 
    117 	return result;
    118 }
    119 
    120 static int
    122 hchacha_selftest(const struct chacha_impl *ci)
    123 {
    124 	/* https://tools.ietf.org/html/draft-irtf-cfrg-xchacha-03, 2.2.1 */
    125 	static const uint8_t k[32] = {
    126 		0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
    127 		0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
    128 		0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
    129 		0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
    130 	};
    131 	static const uint8_t in[16] = {
    132 		0x00,0x00,0x00,0x09, 0x00,0x00,0x00,0x4a,
    133 		0x00,0x00,0x00,0x00, 0x31,0x41,0x59,0x27,
    134 	};
    135 	static const uint8_t expected[32] = {
    136 		0x82,0x41,0x3b,0x42, 0x27,0xb2,0x7b,0xfe,
    137 		0xd3,0x0e,0x42,0x50, 0x8a,0x87,0x7d,0x73,
    138 		0xa0,0xf9,0xe4,0xd5, 0x8a,0x74,0xa8,0x53,
    139 		0xc1,0x2e,0xc4,0x13, 0x26,0xd3,0xec,0xdc,
    140 	};
    141 	uint8_t out[32];
    142 	int result = 0;
    143 
    144 	(*ci->ci_hchacha)(out, in, k, chacha_const32, 20);
    145 	if (memcmp(out, expected, 32)) {
    146 		hexdump(printf, "hchacha", out, sizeof out);
    147 		result = -1;
    148 	}
    149 
    150 	return result;
    151 }
    152 
    153 static int
    155 chacha_stream_selftest(const struct chacha_impl *ci)
    156 {
    157 
    158 	/* XXX */
    159 	return 0;
    160 }
    161 
    162 static int
    164 xchacha_stream_selftest(const struct chacha_impl *ci)
    165 {
    166 	/* https://tools.ietf.org/html/draft-irtf-cfrg-xchacha-03, A.2.1 */
    167 	static const uint8_t k[32] = {
    168 		0x80,0x81,0x82,0x83, 0x84,0x85,0x86,0x87,
    169 		0x88,0x89,0x8a,0x8b, 0x8c,0x8d,0x8e,0x8f,
    170 		0x90,0x91,0x92,0x93, 0x94,0x95,0x96,0x97,
    171 		0x98,0x99,0x9a,0x9b, 0x9c,0x9d,0x9e,0x9f,
    172 	};
    173 	static const uint8_t nonce[24] = {
    174 		0x40,0x41,0x42,0x43, 0x44,0x45,0x46,0x47,
    175 		0x48,0x49,0x4a,0x4b, 0x4c,0x4d,0x4e,0x4f,
    176 		0x50,0x51,0x52,0x53, 0x54,0x55,0x56,0x58,
    177 	};
    178 	static const uint8_t p[608] = {
    179 		0x54,0x68,0x65,0x20, 0x64,0x68,0x6f,0x6c,
    180 		0x65,0x20,0x28,0x70, 0x72,0x6f,0x6e,0x6f,
    181 		0x75,0x6e,0x63,0x65, 0x64,0x20,0x22,0x64,
    182 		0x6f,0x6c,0x65,0x22, 0x29,0x20,0x69,0x73,
    183 		0x20,0x61,0x6c,0x73, 0x6f,0x20,0x6b,0x6e,
    184 		0x6f,0x77,0x6e,0x20, 0x61,0x73,0x20,0x74,
    185 		0x68,0x65,0x20,0x41, 0x73,0x69,0x61,0x74,
    186 		0x69,0x63,0x20,0x77, 0x69,0x6c,0x64,0x20,
    187 		0x64,0x6f,0x67,0x2c, 0x20,0x72,0x65,0x64,
    188 		0x20,0x64,0x6f,0x67, 0x2c,0x20,0x61,0x6e,
    189 		0x64,0x20,0x77,0x68, 0x69,0x73,0x74,0x6c,
    190 		0x69,0x6e,0x67,0x20, 0x64,0x6f,0x67,0x2e,
    191 		0x20,0x49,0x74,0x20, 0x69,0x73,0x20,0x61,
    192 		0x62,0x6f,0x75,0x74, 0x20,0x74,0x68,0x65,
    193 		0x20,0x73,0x69,0x7a, 0x65,0x20,0x6f,0x66,
    194 		0x20,0x61,0x20,0x47, 0x65,0x72,0x6d,0x61,
    195 		0x6e,0x20,0x73,0x68, 0x65,0x70,0x68,0x65,
    196 		0x72,0x64,0x20,0x62, 0x75,0x74,0x20,0x6c,
    197 		0x6f,0x6f,0x6b,0x73, 0x20,0x6d,0x6f,0x72,
    198 		0x65,0x20,0x6c,0x69, 0x6b,0x65,0x20,0x61,
    199 		0x20,0x6c,0x6f,0x6e, 0x67,0x2d,0x6c,0x65,
    200 		0x67,0x67,0x65,0x64, 0x20,0x66,0x6f,0x78,
    201 		0x2e,0x20,0x54,0x68, 0x69,0x73,0x20,0x68,
    202 		0x69,0x67,0x68,0x6c, 0x79,0x20,0x65,0x6c,
    203 		0x75,0x73,0x69,0x76, 0x65,0x20,0x61,0x6e,
    204 		0x64,0x20,0x73,0x6b, 0x69,0x6c,0x6c,0x65,
    205 		0x64,0x20,0x6a,0x75, 0x6d,0x70,0x65,0x72,
    206 		0x20,0x69,0x73,0x20, 0x63,0x6c,0x61,0x73,
    207 		0x73,0x69,0x66,0x69, 0x65,0x64,0x20,0x77,
    208 		0x69,0x74,0x68,0x20, 0x77,0x6f,0x6c,0x76,
    209 		0x65,0x73,0x2c,0x20, 0x63,0x6f,0x79,0x6f,
    210 		0x74,0x65,0x73,0x2c, 0x20,0x6a,0x61,0x63,
    211 		0x6b,0x61,0x6c,0x73, 0x2c,0x20,0x61,0x6e,
    212 		0x64,0x20,0x66,0x6f, 0x78,0x65,0x73,0x20,
    213 		0x69,0x6e,0x20,0x74, 0x68,0x65,0x20,0x74,
    214 		0x61,0x78,0x6f,0x6e, 0x6f,0x6d,0x69,0x63,
    215 		0x20,0x66,0x61,0x6d, 0x69,0x6c,0x79,0x20,
    216 		0x43,0x61,0x6e,0x69, 0x64,0x61,0x65,0x2e,
    217 
    218 		0x54,0x68,0x65,0x20, 0x64,0x68,0x6f,0x6c,
    219 		0x65,0x20,0x28,0x70, 0x72,0x6f,0x6e,0x6f,
    220 		0x75,0x6e,0x63,0x65, 0x64,0x20,0x22,0x64,
    221 		0x6f,0x6c,0x65,0x22, 0x29,0x20,0x69,0x73,
    222 		0x20,0x61,0x6c,0x73, 0x6f,0x20,0x6b,0x6e,
    223 		0x6f,0x77,0x6e,0x20, 0x61,0x73,0x20,0x74,
    224 		0x68,0x65,0x20,0x41, 0x73,0x69,0x61,0x74,
    225 		0x69,0x63,0x20,0x77, 0x69,0x6c,0x64,0x20,
    226 		0x64,0x6f,0x67,0x2c, 0x20,0x72,0x65,0x64,
    227 		0x20,0x64,0x6f,0x67, 0x2c,0x20,0x61,0x6e,
    228 		0x64,0x20,0x77,0x68, 0x69,0x73,0x74,0x6c,
    229 		0x69,0x6e,0x67,0x20, 0x64,0x6f,0x67,0x2e,
    230 		0x20,0x49,0x74,0x20, 0x69,0x73,0x20,0x61,
    231 		0x62,0x6f,0x75,0x74, 0x20,0x74,0x68,0x65,
    232 		0x20,0x73,0x69,0x7a, 0x65,0x20,0x6f,0x66,
    233 		0x20,0x61,0x20,0x47, 0x65,0x72,0x6d,0x61,
    234 		0x6e,0x20,0x73,0x68, 0x65,0x70,0x68,0x65,
    235 		0x72,0x64,0x20,0x62, 0x75,0x74,0x20,0x6c,
    236 		0x6f,0x6f,0x6b,0x73, 0x20,0x6d,0x6f,0x72,
    237 		0x65,0x20,0x6c,0x69, 0x6b,0x65,0x20,0x61,
    238 		0x20,0x6c,0x6f,0x6e, 0x67,0x2d,0x6c,0x65,
    239 		0x67,0x67,0x65,0x64, 0x20,0x66,0x6f,0x78,
    240 		0x2e,0x20,0x54,0x68, 0x69,0x73,0x20,0x68,
    241 		0x69,0x67,0x68,0x6c, 0x79,0x20,0x65,0x6c,
    242 		0x75,0x73,0x69,0x76, 0x65,0x20,0x61,0x6e,
    243 		0x64,0x20,0x73,0x6b, 0x69,0x6c,0x6c,0x65,
    244 		0x64,0x20,0x6a,0x75, 0x6d,0x70,0x65,0x72,
    245 		0x20,0x69,0x73,0x20, 0x63,0x6c,0x61,0x73,
    246 		0x73,0x69,0x66,0x69, 0x65,0x64,0x20,0x77,
    247 		0x69,0x74,0x68,0x20, 0x77,0x6f,0x6c,0x76,
    248 		0x65,0x73,0x2c,0x20, 0x63,0x6f,0x79,0x6f,
    249 		0x74,0x65,0x73,0x2c, 0x20,0x6a,0x61,0x63,
    250 		0x6b,0x61,0x6c,0x73, 0x2c,0x20,0x61,0x6e,
    251 		0x64,0x20,0x66,0x6f, 0x78,0x65,0x73,0x20,
    252 		0x69,0x6e,0x20,0x74, 0x68,0x65,0x20,0x74,
    253 		0x61,0x78,0x6f,0x6e, 0x6f,0x6d,0x69,0x63,
    254 		0x20,0x66,0x61,0x6d, 0x69,0x6c,0x79,0x20,
    255 		0x43,0x61,0x6e,0x69, 0x64,0x61,0x65,0x2e,
    256 	};
    257 	static const uint8_t expected[608] = {
    258 		0x45,0x59,0xab,0xba, 0x4e,0x48,0xc1,0x61,
    259 		0x02,0xe8,0xbb,0x2c, 0x05,0xe6,0x94,0x7f,
    260 		0x50,0xa7,0x86,0xde, 0x16,0x2f,0x9b,0x0b,
    261 		0x7e,0x59,0x2a,0x9b, 0x53,0xd0,0xd4,0xe9,
    262 		0x8d,0x8d,0x64,0x10, 0xd5,0x40,0xa1,0xa6,
    263 		0x37,0x5b,0x26,0xd8, 0x0d,0xac,0xe4,0xfa,
    264 		0xb5,0x23,0x84,0xc7, 0x31,0xac,0xbf,0x16,
    265 		0xa5,0x92,0x3c,0x0c, 0x48,0xd3,0x57,0x5d,
    266 		0x4d,0x0d,0x2c,0x67, 0x3b,0x66,0x6f,0xaa,
    267 		0x73,0x10,0x61,0x27, 0x77,0x01,0x09,0x3a,
    268 		0x6b,0xf7,0xa1,0x58, 0xa8,0x86,0x42,0x92,
    269 		0xa4,0x1c,0x48,0xe3, 0xa9,0xb4,0xc0,0xda,
    270 		0xec,0xe0,0xf8,0xd9, 0x8d,0x0d,0x7e,0x05,
    271 		0xb3,0x7a,0x30,0x7b, 0xbb,0x66,0x33,0x31,
    272 		0x64,0xec,0x9e,0x1b, 0x24,0xea,0x0d,0x6c,
    273 		0x3f,0xfd,0xdc,0xec, 0x4f,0x68,0xe7,0x44,
    274 		0x30,0x56,0x19,0x3a, 0x03,0xc8,0x10,0xe1,
    275 		0x13,0x44,0xca,0x06, 0xd8,0xed,0x8a,0x2b,
    276 		0xfb,0x1e,0x8d,0x48, 0xcf,0xa6,0xbc,0x0e,
    277 		0xb4,0xe2,0x46,0x4b, 0x74,0x81,0x42,0x40,
    278 		0x7c,0x9f,0x43,0x1a, 0xee,0x76,0x99,0x60,
    279 		0xe1,0x5b,0xa8,0xb9, 0x68,0x90,0x46,0x6e,
    280 		0xf2,0x45,0x75,0x99, 0x85,0x23,0x85,0xc6,
    281 		0x61,0xf7,0x52,0xce, 0x20,0xf9,0xda,0x0c,
    282 		0x09,0xab,0x6b,0x19, 0xdf,0x74,0xe7,0x6a,
    283 		0x95,0x96,0x74,0x46, 0xf8,0xd0,0xfd,0x41,
    284 		0x5e,0x7b,0xee,0x2a, 0x12,0xa1,0x14,0xc2,
    285 		0x0e,0xb5,0x29,0x2a, 0xe7,0xa3,0x49,0xae,
    286 		0x57,0x78,0x20,0xd5, 0x52,0x0a,0x1f,0x3f,
    287 		0xb6,0x2a,0x17,0xce, 0x6a,0x7e,0x68,0xfa,
    288 		0x7c,0x79,0x11,0x1d, 0x88,0x60,0x92,0x0b,
    289 		0xc0,0x48,0xef,0x43, 0xfe,0x84,0x48,0x6c,
    290 		0xcb,0x87,0xc2,0x5f, 0x0a,0xe0,0x45,0xf0,
    291 		0xcc,0xe1,0xe7,0x98, 0x9a,0x9a,0xa2,0x20,
    292 		0xa2,0x8b,0xdd,0x48, 0x27,0xe7,0x51,0xa2,
    293 		0x4a,0x6d,0x5c,0x62, 0xd7,0x90,0xa6,0x63,
    294 		0x93,0xb9,0x31,0x11, 0xc1,0xa5,0x5d,0xd7,
    295 		0x42,0x1a,0x10,0x18, 0x49,0x74,0xc7,0xc5,
    296 
    297 		0x08,0x38,0x2d,0x64, 0x35,0x8d,0x21,0x77,
    298 		0x2e,0xb9,0x73,0xa8, 0x8f,0xb6,0x2b,0xf8,
    299 		0xce,0xfa,0xb4,0xca, 0x6f,0x0c,0x26,0xbb,
    300 		0x7f,0xd6,0x6d,0xb2, 0xa0,0xbe,0xb0,0x5a,
    301 		0x1a,0x6e,0x39,0xcb, 0xd5,0xda,0xf2,0xfc,
    302 		0x0b,0x74,0x31,0x3d, 0x2e,0xcd,0x5f,0x94,
    303 		0xc2,0x9f,0x30,0xdb, 0x11,0x5e,0x41,0x53,
    304 		0x8c,0x6d,0x30,0xba, 0x97,0xa0,0xc5,0x07,
    305 		0x70,0x78,0x02,0x5a, 0xc1,0x69,0x70,0x8f,
    306 		0x22,0x85,0xcb,0x98, 0xbc,0x6a,0x51,0xfb,
    307 		0xc6,0xa7,0xc3,0x3d, 0x76,0xe4,0x93,0x9a,
    308 		0x21,0xe2,0xc6,0x12, 0xe1,0x3a,0xcc,0xfb,
    309 		0x6f,0xa6,0x57,0xc0, 0x09,0x8c,0x6f,0xf3,
    310 		0x8d,0x83,0x21,0x1b, 0x71,0xa9,0xc1,0x93,
    311 		0x88,0x35,0xfc,0x18, 0x1f,0x94,0xa2,0x57,
    312 		0x3a,0x4e,0xd0,0xc0, 0xbc,0x92,0xa7,0x9c,
    313 		0x52,0x8a,0x82,0x9d, 0x44,0x75,0x7b,0xa0,
    314 		0xcf,0x3d,0x2d,0xbf, 0xf9,0x6f,0x71,0x56,
    315 		0x38,0xb0,0x63,0x5e, 0x55,0xcd,0x28,0x12,
    316 		0xc5,0xea,0x52,0xf4, 0xdc,0xf7,0xdc,0x3d,
    317 		0xd8,0x96,0x09,0xe8, 0x2a,0xcc,0x00,0x16,
    318 		0x88,0x77,0x82,0x10, 0xed,0x7d,0xd8,0x8b,
    319 		0xf5,0xd3,0xe1,0xfc, 0x49,0x66,0x36,0x8d,
    320 		0x55,0xd2,0x33,0xb8, 0x6d,0xff,0xe3,0xd3,
    321 		0x55,0x80,0x0e,0xd8, 0x95,0x32,0x32,0x55,
    322 		0x83,0xe7,0x58,0x6f, 0xec,0xc3,0x8c,0xf8,
    323 		0x52,0x16,0xdc,0x0d, 0x29,0x02,0xe5,0x27,
    324 		0x35,0xc2,0xbb,0xe2, 0xe2,0x3b,0xf5,0x19,
    325 		0xcd,0x44,0x83,0xe8, 0x21,0x55,0xd0,0x10,
    326 		0x15,0x68,0x8e,0x46, 0xa3,0x2f,0xa5,0x7c,
    327 		0xa8,0x2c,0xc6,0x8f, 0x14,0xcd,0xb3,0x79,
    328 		0x92,0x32,0x71,0xac, 0xd9,0xaf,0x9c,0x4d,
    329 		0x00,0x88,0xd1,0x42, 0xd5,0x23,0xfa,0xe6,
    330 		0x7f,0x38,0xa2,0x56, 0x99,0xbe,0x6f,0xcf,
    331 		0xe0,0xaa,0x44,0x11, 0x8a,0xc8,0x3a,0x99,
    332 		0x48,0x6d,0x33,0x0e, 0x94,0xf2,0xb9,0x87,
    333 		0xed,0x4f,0x6a,0x9c, 0x33,0x93,0x6d,0xe4,
    334 		0x92,0x76,0xab,0xfa, 0xce,0x5b,0x17,0x14,
    335 	};
    336 	uint8_t c[608];
    337 	unsigned i;
    338 	int result = 0;
    339 
    340 	/*
    341 	 * 608 = 96 (mod 256)
    342 	 * 607 = 95 (mod 256), = 7 (mod 8)
    343 	 * 543 = 31 (mod 256), = 7 (mod 8)
    344 	 * 511 = 255 (mod 256), = 7 (mod 8)
    345 	 *
    346 	 * This exercises several branches when there are special cases
    347 	 * for integral numbers of 4-byte words, integral numbers of
    348 	 * 64-byte blocks, and integral numbers of 256-byte chunks.
    349 	 */
    350 
    351 	(*ci->ci_xchacha_stream)(c, 608, 0, nonce, k, 20);
    352 	for (i = 0; i < 608; i++)
    353 		c[i] ^= p[i];
    354 	if (memcmp(c, expected, 608)) {
    355 		for (i = 0; i < 608; i++)
    356 			c[i] ^= p[i];
    357 		hexdump(printf, "xchacha_stream", c, 608);
    358 		for (i = 0; i < 608; i++)
    359 			c[i] = expected[i] ^ p[i];
    360 		hexdump(printf, "expected", c, 608);
    361 		result = -1;
    362 	}
    363 
    364 	(*ci->ci_xchacha_stream)(c, 607, 0, nonce, k, 20);
    365 	for (i = 0; i < 607; i++)
    366 		c[i] ^= p[i];
    367 	if (memcmp(c, expected, 607)) {
    368 		for (i = 0; i < 607; i++)
    369 			c[i] ^= p[i];
    370 		hexdump(printf, "xchacha_stream", c, 607);
    371 		for (i = 0; i < 607; i++)
    372 			c[i] = expected[i] ^ p[i];
    373 		hexdump(printf, "expected", c, 607);
    374 		result = -1;
    375 	}
    376 
    377 	(*ci->ci_xchacha_stream)(c, 543, 0, nonce, k, 20);
    378 	for (i = 0; i < 543; i++)
    379 		c[i] ^= p[i];
    380 	if (memcmp(c, expected, 543)) {
    381 		for (i = 0; i < 543; i++)
    382 			c[i] ^= p[i];
    383 		hexdump(printf, "xchacha_stream", c, 543);
    384 		for (i = 0; i < 543; i++)
    385 			c[i] = expected[i] ^ p[i];
    386 		hexdump(printf, "expected", c, 543);
    387 		result = -1;
    388 	}
    389 
    390 	(*ci->ci_xchacha_stream)(c, 511, 0, nonce, k, 20);
    391 	for (i = 0; i < 511; i++)
    392 		c[i] ^= p[i];
    393 	if (memcmp(c, expected, 511)) {
    394 		for (i = 0; i < 511; i++)
    395 			c[i] ^= p[i];
    396 		hexdump(printf, "xchacha_stream", c, 511);
    397 		for (i = 0; i < 511; i++)
    398 			c[i] = expected[i] ^ p[i];
    399 		hexdump(printf, "expected", c, 511);
    400 		result = -1;
    401 	}
    402 
    403 	(*ci->ci_xchacha_stream)(c, 63, 0, nonce, k, 20);
    404 	for (i = 0; i < 63; i++)
    405 		c[i] ^= p[i];
    406 	if (memcmp(c, expected, 63)) {
    407 		for (i = 0; i < 63; i++)
    408 			c[i] ^= p[i];
    409 		hexdump(printf, "xchacha_stream", c, 63);
    410 		for (i = 0; i < 63; i++)
    411 			c[i] = expected[i] ^ p[i];
    412 		hexdump(printf, "expected", c, 63);
    413 		result = -1;
    414 	}
    415 
    416 	(*ci->ci_xchacha_stream_xor)(c, p, 608, 0, nonce, k, 20);
    417 	if (memcmp(c, expected, 608)) {
    418 		hexdump(printf, "xchacha_stream_xor", c, 608);
    419 		hexdump(printf, "expected", expected, 608);
    420 		result = -1;
    421 	}
    422 
    423 	memset(c, 0, sizeof c);
    424 	(*ci->ci_xchacha_stream_xor)(c, p, 607, 0, nonce, k, 20);
    425 	if (memcmp(c, expected, 607)) {
    426 		hexdump(printf, "xchacha_stream_xor", c, 607);
    427 		hexdump(printf, "expected", expected, 607);
    428 		result = -1;
    429 	}
    430 
    431 	memset(c, 0, sizeof c);
    432 	(*ci->ci_xchacha_stream_xor)(c, p, 543, 0, nonce, k, 20);
    433 	if (memcmp(c, expected, 543)) {
    434 		hexdump(printf, "xchacha_stream_xor", c, 543);
    435 		hexdump(printf, "expected", expected, 543);
    436 		result = -1;
    437 	}
    438 
    439 	memset(c, 0, sizeof c);
    440 	(*ci->ci_xchacha_stream_xor)(c, p, 511, 0, nonce, k, 20);
    441 	if (memcmp(c, expected, 511)) {
    442 		hexdump(printf, "xchacha_stream_xor", c, 511);
    443 		hexdump(printf, "expected", expected, 511);
    444 		result = -1;
    445 	}
    446 
    447 	memset(c, 0, sizeof c);
    448 	(*ci->ci_xchacha_stream_xor)(c, p, 63, 0, nonce, k, 20);
    449 	if (memcmp(c, expected, 63)) {
    450 		hexdump(printf, "xchacha_stream_xor", c, 63);
    451 		hexdump(printf, "expected", expected, 63);
    452 		result = -1;
    453 	}
    454 
    455 	return result;
    456 }
    457 
    458 int
    460 chacha_selftest(const struct chacha_impl *ci)
    461 {
    462 	int result = 0;
    463 
    464 	result |= chacha_core_selftest(ci);
    465 	result |= chacha_stream_selftest(ci);
    466 	result |= hchacha_selftest(ci);
    467 	result |= xchacha_stream_selftest(ci);
    468 
    469 	return result;
    470 }
    471