hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

ctr+test.ha (11410B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use bytes;
      5 use crypto::cipher;
      6 use errors;
      7 use io;
      8 use memio;
      9 
     10 @test fn ctr_zero_iv() void = {
     11 	const key: [_]u8 = [
     12 		0xc3, 0x43, 0x2a, 0xf7, 0xcf, 0x56, 0x72, 0xad,
     13 		0x0f, 0x4d, 0xab, 0xee, 0xf5, 0x32, 0x0e, 0x33,
     14 	];
     15 
     16 	const iv: [_]u8 = [
     17 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     18 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     19 	];
     20 
     21 	const plain: [_]u8 = [
     22 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     23 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     24 	];
     25 
     26 	const cipher: [_]u8 = [
     27 		0xda, 0xe1, 0x45, 0xd6, 0xe8, 0x6a, 0xc0, 0x4b,
     28 		0xb8, 0x68, 0xf0, 0xdb, 0xcd, 0x8a, 0x22, 0x80,
     29 	];
     30 
     31 	let result: [16]u8 = [0...];
     32 	let buf: [CTR_BUFSZ]u8 = [0...];
     33 	let resultbuf = memio::fixed(result);
     34 
     35 	let b = ct64();
     36 	ct64_init(&b, key);
     37 
     38 	let ctr = cipher::ctr(&resultbuf, &b, iv[..], buf[..]);
     39 
     40 	const s = io::writeall(&ctr, plain)!;
     41 	assert(s == len(plain));
     42 	assert(bytes::equal(cipher, result));
     43 	io::close(&ctr)!;
     44 
     45 	const zero: [CTR_BUFSZ]u8 = [0...];
     46 	const bsz = cipher::blocksz(&b);
     47 	assert(bytes::equal(ctr.xorbuf, zero[bsz..]));
     48 
     49 	let b = ct64();
     50 	ct64_init(&b, key);
     51 
     52 	result = [0...];
     53 	buf = [0...];
     54 	let cipherbuf = memio::fixed(cipher);
     55 	let ctr = cipher::ctr(&cipherbuf, &b, iv[..], buf[..]);
     56 	const s = io::readall(&ctr, result)!;
     57 	assert(s as size == len(plain));
     58 	assert(bytes::equal(plain, result));
     59 };
     60 
     61 @test fn ctr_encrypt_max_iv() void = {
     62 	const key: [_]u8 = [
     63 		0xc3, 0x43, 0x2a, 0xf7, 0xcf, 0x56, 0x72, 0xad,
     64 		0x0f, 0x4d, 0xab, 0xee, 0xf5, 0x32, 0x0e, 0x33,
     65 	];
     66 
     67 	const iv: [_]u8 = [
     68 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     69 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
     70 	];
     71 
     72 	const plain: [_]u8 = [
     73 		0x1f, 0x03, 0x62, 0xb4, 0xb6, 0xd3, 0xc9, 0xc1,
     74 		0xfa, 0x12, 0xa1, 0x1f, 0xa5, 0x6a, 0xbe, 0x46,
     75 		0x85, 0xea,
     76 	];
     77 
     78 	const cipher: [_]u8 = [
     79 		0x3d, 0x31, 0x42, 0x04, 0xf5, 0x1d, 0x04, 0x4c,
     80 		0x3e, 0xb1, 0xa5, 0xf8, 0x18, 0x79, 0x87, 0x41,
     81 		0x5f, 0x0b,
     82 	];
     83 
     84 	let result: [18]u8 = [0...];
     85 	let resultbuf = memio::fixed(result);
     86 	let buf: [CTR_BUFSZ]u8 = [0...];
     87 
     88 	let b = ct64();
     89 	ct64_init(&b, key);
     90 
     91 	let ctr = cipher::ctr(&resultbuf, &b, iv[..], buf[..]);
     92 	defer io::close(&ctr)!;
     93 
     94 	io::write(&ctr, plain)!;
     95 	assert(bytes::equal(cipher, result));
     96 };
     97 
     98 @test fn ctr_test_multiple_blocks() void = {
     99 	const key: [_]u8 = [
    100 		0xae, 0x0c, 0x47, 0x6d, 0xce, 0x69, 0xdf, 0x52,
    101 		0xf7, 0x5e, 0x1f, 0x16, 0x7e, 0xea, 0x1c, 0xf0,
    102 	];
    103 
    104 	const iv: [_]u8 = [
    105 		0x9a, 0x11, 0xd7, 0x24, 0x43, 0x86, 0x50, 0xf0,
    106 		0xd9, 0x8c, 0x0d, 0x0d, 0x7a, 0x2e, 0x95, 0x72,
    107 	];
    108 
    109 	const plain: [_]u8 = [
    110 		0x05, 0xc8, 0x4a, 0xf7, 0xba, 0x4b, 0xc2, 0x4f,
    111 		0xd3, 0x63, 0xf3, 0x20, 0x51, 0x2b, 0x65, 0xec,
    112 		0x4c, 0xe7, 0x7f, 0x78, 0x17, 0x45, 0x0c, 0x6e,
    113 		0xff, 0xf1, 0x73, 0x97, 0x42, 0x4d, 0x4a, 0x30,
    114 		0x5d, 0xb2, 0x79, 0x45, 0xca, 0x20, 0x10, 0x5b,
    115 		0x2c, 0x34, 0x4c, 0xed, 0x42, 0x59, 0x61, 0x3a,
    116 		0x66, 0xa3, 0x2e, 0x74, 0xa8, 0xbb, 0x9c, 0xe9,
    117 		0x4e, 0xda, 0x33, 0x97, 0x98, 0x41, 0x9a, 0xf0,
    118 		0xbb, 0x6d, 0xcb, 0x5d, 0x15, 0x60, 0x26, 0x7c,
    119 		0x6c, 0xe5, 0xa4, 0xaf, 0x52, 0x14, 0x29, 0x2f,
    120 	];
    121 
    122 	const cipher: [_]u8 = [
    123 		0xc1, 0xe5, 0x15, 0x76, 0x5b, 0xb2, 0x3a, 0xbc,
    124 		0xc4, 0x71, 0xdf, 0xcc, 0x20, 0xe0, 0x63, 0xd6,
    125 		0xb3, 0x7d, 0x48, 0x51, 0xe0, 0xd1, 0xcb, 0x07,
    126 		0xa3, 0xc8, 0xc6, 0xb9, 0x43, 0xa9, 0x1e, 0x70,
    127 		0xb2, 0x1e, 0xbe, 0xc3, 0x11, 0x36, 0xb2, 0x64,
    128 		0x7c, 0xaf, 0x89, 0x46, 0x17, 0x60, 0x90, 0x19,
    129 		0x23, 0x53, 0xd1, 0xce, 0xc6, 0x5c, 0x50, 0x9c,
    130 		0x8c, 0x1d, 0xa8, 0xee, 0x44, 0x9c, 0xa2, 0xb2,
    131 		0x97, 0x62, 0x39, 0xcc, 0x91, 0xb0, 0xcc, 0x2c,
    132 		0x1b, 0x4c, 0xc3, 0x5d, 0xc3, 0xfa, 0xe9, 0x98,
    133 	];
    134 
    135 	let result: [80]u8 = [0...];
    136 	let resultbuf = memio::fixed(result);
    137 	let buf: [CTR_BUFSZ]u8 = [0...];
    138 
    139 	let b = ct64();
    140 	ct64_init(&b, key);
    141 
    142 	let ctr = cipher::ctr(&resultbuf, &b, iv[..], buf[..]);
    143 	const n = io::writeall(&ctr, plain)!;
    144 	assert(n == len(cipher));
    145 	assert(bytes::equal(cipher, result));
    146 	io::close(&ctr)!;
    147 
    148 	let b = ct64();
    149 	ct64_init(&b, key);
    150 
    151 	let cipherbuf = memio::fixed(cipher);
    152 	let ctr = cipher::ctr(&cipherbuf, &b, iv[..], buf[..]);
    153 	const n = io::readall(&ctr, result)!;
    154 	assert(n as size == len(plain));
    155 	assert(bytes::equal(plain, result));
    156 	io::close(&ctr)!;
    157 };
    158 
    159 @test fn ctr_test_multiple_calls() void = {
    160 	const key: [_]u8 = [
    161 		0xae, 0x0c, 0x47, 0x6d, 0xce, 0x69, 0xdf, 0x52,
    162 		0xf7, 0x5e, 0x1f, 0x16, 0x7e, 0xea, 0x1c, 0xf0,
    163 	];
    164 
    165 	const iv: [_]u8 = [
    166 		0x9a, 0x11, 0xd7, 0x24, 0x43, 0x86, 0x50, 0xf0,
    167 		0xd9, 0x8c, 0x0d, 0x0d, 0x7a, 0x2e, 0x95, 0x72,
    168 	];
    169 
    170 	const plain: [_]u8 = [
    171 		0x05, 0xc8, 0x4a, 0xf7, 0xba, 0x4b, 0xc2, 0x4f,
    172 		0xd3, 0x63, 0xf3, 0x20, 0x51, 0x2b, 0x65, 0xec,
    173 		0x4c, 0xe7, 0x7f, 0x78, 0x17, 0x45, 0x0c, 0x6e,
    174 		0xff, 0xf1, 0x73, 0x97, 0x42, 0x4d, 0x4a, 0x30,
    175 		0x5d, 0xb2, 0x79, 0x45, 0xca, 0x20, 0x10, 0x5b,
    176 		0x2c, 0x34, 0x4c, 0xed, 0x42, 0x59, 0x61, 0x3a,
    177 		0x66, 0xa3, 0x2e, 0x74, 0xa8, 0xbb, 0x9c, 0xe9,
    178 		0x4e, 0xda, 0x33, 0x97, 0x98, 0x41, 0x9a, 0xf0,
    179 		0xbb, 0x6d, 0xcb, 0x5d, 0x15, 0x60, 0x26, 0x7c,
    180 		0x6c, 0xe5, 0xa4, 0xaf, 0x52, 0x14, 0x29, 0x2f,
    181 	];
    182 
    183 	const cipher: [_]u8 = [
    184 		0xc1, 0xe5, 0x15, 0x76, 0x5b, 0xb2, 0x3a, 0xbc,
    185 		0xc4, 0x71, 0xdf, 0xcc, 0x20, 0xe0, 0x63, 0xd6,
    186 		0xb3, 0x7d, 0x48, 0x51, 0xe0, 0xd1, 0xcb, 0x07,
    187 		0xa3, 0xc8, 0xc6, 0xb9, 0x43, 0xa9, 0x1e, 0x70,
    188 		0xb2, 0x1e, 0xbe, 0xc3, 0x11, 0x36, 0xb2, 0x64,
    189 		0x7c, 0xaf, 0x89, 0x46, 0x17, 0x60, 0x90, 0x19,
    190 		0x23, 0x53, 0xd1, 0xce, 0xc6, 0x5c, 0x50, 0x9c,
    191 		0x8c, 0x1d, 0xa8, 0xee, 0x44, 0x9c, 0xa2, 0xb2,
    192 		0x97, 0x62, 0x39, 0xcc, 0x91, 0xb0, 0xcc, 0x2c,
    193 		0x1b, 0x4c, 0xc3, 0x5d, 0xc3, 0xfa, 0xe9, 0x98,
    194 	];
    195 
    196 	let result: [80]u8 = [0...];
    197 	let resultbuf = memio::fixed(result);
    198 	let buf: [CTR_BUFSZ]u8 = [0...];
    199 
    200 	let b = ct64();
    201 	ct64_init(&b, key);
    202 
    203 	let ctr = cipher::ctr(&resultbuf, &b, iv[..], buf[..]);
    204 	defer io::close(&ctr)!;
    205 	let n = 0z;
    206 	n += io::write(&ctr, plain[0..32])!;
    207 	n += io::write(&ctr, plain[32..])!;
    208 	// previous call only writes 32 bytes. Write remaining here.
    209 	n += io::write(&ctr, plain[64..])!;
    210 	assert(n == len(plain));
    211 	assert(bytes::equal(cipher, result));
    212 
    213 	let cipherbuf = memio::fixed(cipher);
    214 	let ctr = cipher::ctr(&cipherbuf, &b, iv[..], buf[..]);
    215 	const n = io::readall(&ctr, result)!;
    216 	assert(n as size == len(plain));
    217 	assert(bytes::equal(plain, result));
    218 };
    219 
    220 @test fn ctr_encrypt_in_place() void = {
    221 	const key: [_]u8 = [
    222 		0x3f, 0xf8, 0x68, 0x06, 0xe4, 0xcc, 0x88, 0x11,
    223 		0xa6, 0xba, 0x14, 0xb6, 0x0b, 0x4c, 0x5a, 0xef,
    224 	];
    225 
    226 	const iv: [_]u8 = [
    227 		0xc5, 0x4c, 0x99, 0xd2, 0xd0, 0xef, 0xf5, 0xde,
    228 		0x95, 0x38, 0x45, 0x34, 0xeb, 0xa2, 0xad, 0xa0,
    229 	];
    230 
    231 	let result: [_]u8 = [
    232 		0x65, 0x60, 0x3b, 0x9a, 0x07, 0x56, 0xb1, 0x96,
    233 		0x3b, 0xd8, 0x8d, 0x84, 0x20, 0x29, 0xec, 0x7f,
    234 		0xa6, 0xe9, 0xf8, 0xdf, 0xa3, 0x37, 0xf3, 0x8f,
    235 	];
    236 
    237 	const cipher: [_]u8 = [
    238 		0x14, 0xfd, 0x4b, 0x5b, 0x4a, 0x11, 0xd3, 0xdf,
    239 		0x6e, 0x02, 0x61, 0x09, 0x64, 0x1f, 0xa1, 0x86,
    240 		0xb1, 0xa6, 0xd9, 0x40, 0xaf, 0x1b, 0x02, 0xe1,
    241 	];
    242 
    243 	let b = ct64();
    244 	ct64_init(&b, key);
    245 	defer cipher::finish(&b);
    246 
    247 	let buf: [CTR_BUFSZ]u8 = [0...];
    248 	let resultbuf = memio::fixed(result);
    249 	let ctr = cipher::ctr(&resultbuf, &b, iv[..], buf[..]);
    250 	defer io::close(&ctr)!;
    251 
    252 	io::write(&ctr, result)!;
    253 	assert(bytes::equal(cipher, result));
    254 };
    255 
    256 @test fn ctr_encrypt_smaller_buf() void = {
    257 	const key: [_]u8 = [
    258 		0x3f, 0xf8, 0x68, 0x06, 0xe4, 0xcc, 0x88, 0x11,
    259 		0xa6, 0xba, 0x14, 0xb6, 0x0b, 0x4c, 0x5a, 0xef,
    260 	];
    261 
    262 	const iv: [_]u8 = [
    263 		0xc5, 0x4c, 0x99, 0xd2, 0xd0, 0xef, 0xf5, 0xde,
    264 		0x95, 0x38, 0x45, 0x34, 0xeb, 0xa2, 0xad, 0xa0,
    265 	];
    266 
    267 	let result: [_]u8 = [
    268 		0x65, 0x60, 0x3b, 0x9a, 0x07, 0x56, 0xb1, 0x96,
    269 		0x3b, 0xd8, 0x8d, 0x84, 0x20, 0x29, 0xec, 0x7f,
    270 		0xa6, 0xe9, 0xf8, 0xdf, 0xa3, 0x37, 0xf3, 0x8f,
    271 	];
    272 
    273 	const cipher: [_]u8 = [
    274 		0x14, 0xfd, 0x4b, 0x5b, 0x4a, 0x11, 0xd3, 0xdf,
    275 		0x6e, 0x02, 0x61, 0x09, 0x64, 0x1f, 0xa1, 0x86,
    276 		0xb1, 0xa6, 0xd9, 0x40, 0xaf, 0x1b, 0x02, 0xe1,
    277 	];
    278 
    279 	let b = ct64();
    280 	ct64_init(&b, key);
    281 	defer cipher::finish(&b);
    282 
    283 	let buf: [64]u8 = [0...];
    284 	let resultbuf = memio::fixed(result);
    285 
    286 	let ctr = cipher::ctr(&resultbuf, &b, iv[..], buf[..]);
    287 	defer io::close(&ctr)!;
    288 
    289 	io::write(&ctr, result)!;
    290 	assert(bytes::equal(cipher, result));
    291 };
    292 
    293 @test fn empty_write() void = {
    294 	const key: [_]u8 = [
    295 		0x3f, 0xf8, 0x68, 0x06, 0xe4, 0xcc, 0x88, 0x11,
    296 		0xa6, 0xba, 0x14, 0xb6, 0x0b, 0x4c, 0x5a, 0xef,
    297 	];
    298 
    299 	const iv: [_]u8 = [
    300 		0xc5, 0x4c, 0x99, 0xd2, 0xd0, 0xef, 0xf5, 0xde,
    301 		0x95, 0x38, 0x45, 0x34, 0xeb, 0xa2, 0xad, 0xa0,
    302 	];
    303 
    304 	let b = ct64();
    305 	ct64_init(&b, key);
    306 	defer cipher::finish(&b);
    307 
    308 	let buf: [64]u8 = [0...];
    309 	let result: [1]u8 = [0];
    310 	let resultbuf = memio::fixed(result);
    311 
    312 	let ctr = cipher::ctr(&resultbuf, &b, iv[..], buf[..]);
    313 	defer io::close(&ctr)!;
    314 
    315 	const n = io::write(&ctr, [])!;
    316 	assert(n == 0);
    317 };
    318 
    319 type err_stream = struct {
    320 	stream: io::stream,
    321 	out: io::handle,
    322 	err: io::error,
    323 	limit: size,
    324 };
    325 
    326 const err_stream_vtable: io::vtable = io::vtable {
    327 	writer = &err_writer,
    328 	...
    329 };
    330 
    331 fn err_writer(s: *io::stream, buf: const []u8) (size | io::error) = {
    332 	let s = s: *err_stream;
    333 
    334 	if (s.limit == 0) {
    335 		return s.err;
    336 	};
    337 
    338 	const n = if (len(buf) < s.limit) {
    339 		yield len(buf);
    340 	} else {
    341 		return s.err;
    342 	};
    343 
    344 	match(io::write(s.out, buf[..n])) {
    345 	case let z: size =>
    346 		s.limit -= z;
    347 		return n;
    348 	case let e: io::error =>
    349 		return e;
    350 	};
    351 };
    352 
    353 fn errwriter(out: io::handle, limit: size, err: io::error) err_stream = {
    354 	return err_stream {
    355 		stream = &err_stream_vtable,
    356 		out = out,
    357 		limit = limit,
    358 		err = err,
    359 	};
    360 };
    361 
    362 @test fn ctr_test_retry() void = {
    363 	const key: [_]u8 = [
    364 		0xae, 0x0c, 0x47, 0x6d, 0xce, 0x69, 0xdf, 0x52,
    365 		0xf7, 0x5e, 0x1f, 0x16, 0x7e, 0xea, 0x1c, 0xf0,
    366 	];
    367 
    368 	const iv: [_]u8 = [
    369 		0x9a, 0x11, 0xd7, 0x24, 0x43, 0x86, 0x50, 0xf0,
    370 		0xd9, 0x8c, 0x0d, 0x0d, 0x7a, 0x2e, 0x95, 0x72,
    371 	];
    372 
    373 	const plain: [_]u8 = [
    374 		0x05, 0xc8, 0x4a, 0xf7, 0xba, 0x4b, 0xc2, 0x4f,
    375 		0xd3, 0x63, 0xf3, 0x20, 0x51, 0x2b, 0x65, 0xec,
    376 		0x4c, 0xe7, 0x7f, 0x78, 0x17, 0x45, 0x0c, 0x6e,
    377 		0xff, 0xf1, 0x73, 0x97, 0x42, 0x4d, 0x4a, 0x30,
    378 		0x5d, 0xb2, 0x79, 0x45, 0xca, 0x20, 0x10, 0x5b,
    379 		0x2c, 0x34, 0x4c, 0xed, 0x42, 0x59, 0x61, 0x3a,
    380 		0x66, 0xa3, 0x2e, 0x74, 0xa8, 0xbb, 0x9c, 0xe9,
    381 		0x4e, 0xda, 0x33, 0x97, 0x98, 0x41, 0x9a, 0xf0,
    382 		0xbb, 0x6d, 0xcb, 0x5d, 0x15, 0x60, 0x26, 0x7c,
    383 		0x6c, 0xe5, 0xa4, 0xaf, 0x52, 0x14, 0x29, 0x2f,
    384 	];
    385 
    386 	const cipher: [_]u8 = [
    387 		0xc1, 0xe5, 0x15, 0x76, 0x5b, 0xb2, 0x3a, 0xbc,
    388 		0xc4, 0x71, 0xdf, 0xcc, 0x20, 0xe0, 0x63, 0xd6,
    389 		0xb3, 0x7d, 0x48, 0x51, 0xe0, 0xd1, 0xcb, 0x07,
    390 		0xa3, 0xc8, 0xc6, 0xb9, 0x43, 0xa9, 0x1e, 0x70,
    391 		0xb2, 0x1e, 0xbe, 0xc3, 0x11, 0x36, 0xb2, 0x64,
    392 		0x7c, 0xaf, 0x89, 0x46, 0x17, 0x60, 0x90, 0x19,
    393 		0x23, 0x53, 0xd1, 0xce, 0xc6, 0x5c, 0x50, 0x9c,
    394 		0x8c, 0x1d, 0xa8, 0xee, 0x44, 0x9c, 0xa2, 0xb2,
    395 		0x97, 0x62, 0x39, 0xcc, 0x91, 0xb0, 0xcc, 0x2c,
    396 		0x1b, 0x4c, 0xc3, 0x5d, 0xc3, 0xfa, 0xe9, 0x98,
    397 	];
    398 
    399 	let result: [80]u8 = [0...];
    400 	let resultbuf = memio::fixed(result);
    401 	let errw = errwriter(&resultbuf, 20, errors::again);
    402 	let buf: [CTR_BUFSZ]u8 = [0...];
    403 
    404 	let b = ct64();
    405 	ct64_init(&b, key);
    406 	defer cipher::finish(&b);
    407 
    408 	let ctr = cipher::ctr(&errw, &b, iv[..], buf[..]);
    409 	defer io::close(&ctr)!;
    410 	let n = 0z;
    411 	match (io::write(&ctr, plain[..64])) {
    412 	case errors::again => void;
    413 	case size =>
    414 		assert(false);
    415 	};
    416 
    417 	errw.limit = 999;
    418 
    419 	// try again
    420 	n += io::write(&ctr, plain[..64])!;
    421 	n += io::write(&ctr, plain[64..])!;
    422 	assert(n == len(plain));
    423 	assert(bytes::equal(cipher, result));
    424 };