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 };