authenc_test.ha (13525B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use bytes; 5 use errors; 6 7 type sample = struct { 8 msg: []u8, 9 cipher: []u8, 10 additional: []u8, 11 key: sessionkey, 12 nonce: nonce, 13 mac: mac, 14 }; 15 16 // test vector taken from the XChacha20-Poly1305-AEAD draft rfc 17 const rfcsample: sample = sample { 18 msg = [ 19 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 20 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 21 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 22 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 23 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x75, 24 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 25 0x6f, 0x75, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 26 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 27 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 28 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, 0x63, 0x72, 0x65, 0x65, 29 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 30 0x20, 0x69, 0x74, 0x2e, 31 ], 32 additional = [ 33 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 34 0xc6, 0xc7, 35 ], 36 key = [ 37 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 38 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 39 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 40 0x9e, 0x9f, 41 ], 42 nonce = [ 43 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 44 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 45 0x54, 0x55, 0x56, 0x57, 46 ], 47 cipher = [ 48 0xbd, 0x6d, 0x17, 0x9d, 0x3e, 0x83, 0xd4, 0x3b, 0x95, 0x76, 49 0x57, 0x94, 0x93, 0xc0, 0xe9, 0x39, 0x57, 0x2a, 0x17, 0x00, 50 0x25, 0x2b, 0xfa, 0xcc, 0xbe, 0xd2, 0x90, 0x2c, 0x21, 0x39, 51 0x6c, 0xbb, 0x73, 0x1c, 0x7f, 0x1b, 0x0b, 0x4a, 0xa6, 0x44, 52 0x0b, 0xf3, 0xa8, 0x2f, 0x4e, 0xda, 0x7e, 0x39, 0xae, 0x64, 53 0xc6, 0x70, 0x8c, 0x54, 0xc2, 0x16, 0xcb, 0x96, 0xb7, 0x2e, 54 0x12, 0x13, 0xb4, 0x52, 0x2f, 0x8c, 0x9b, 0xa4, 0x0d, 0xb5, 55 0xd9, 0x45, 0xb1, 0x1b, 0x69, 0xb9, 0x82, 0xc1, 0xbb, 0x9e, 56 0x3f, 0x3f, 0xac, 0x2b, 0xc3, 0x69, 0x48, 0x8f, 0x76, 0xb2, 57 0x38, 0x35, 0x65, 0xd3, 0xff, 0xf9, 0x21, 0xf9, 0x66, 0x4c, 58 0x97, 0x63, 0x7d, 0xa9, 0x76, 0x88, 0x12, 0xf6, 0x15, 0xc6, 59 0x8b, 0x13, 0xb5, 0x2e, 60 ], 61 mac = [ 62 0xc0, 0x87, 0x59, 0x24, 0xc1, 0xc7, 0x98, 0x79, 0x47, 0xde, 63 0xaf, 0xd8, 0x78, 0x0a, 0xcf, 0x49, 64 ], 65 }; 66 67 68 const noadsample: sample = sample { 69 key = [ 70 0xdf, 0x23, 0xf4, 0xad, 0xe4, 0x6f, 0xc1, 0x41, 0x36, 0xe6, 71 0x63, 0x48, 0x3c, 0xcd, 0x74, 0x56, 0x44, 0x6a, 0x56, 0x56, 72 0xd8, 0xb4, 0x34, 0x30, 0xd4, 0xfd, 0x7b, 0xa8, 0x2c, 0x60, 73 0xf7, 0x62, 74 ], 75 msg = [ 76 0x9b, 0x0e, 0x38, 0x4b, 0x29, 0x09, 0x8e, 0xa3, 0xb4, 0x37, 77 0x7c, 0x81, 0xba, 0xc0, 0xbf, 0x7e, 0x59, 0xc2, 0xdc, 0x0f, 78 0x43, 0x03, 0x40, 0x1f, 0xd4, 0x1b, 0xae, 0x69, 0xfd, 0x0f, 79 0x0f, 0x49, 0xc8, 0xef, 0xa2, 0x30, 0x21, 0x53, 0x4a, 0xfc, 80 0x0c, 0xa6, 0xef, 0x3c, 0x34, 0xe9, 0x9c, 0xc7, 0x8b, 0xd7, 81 0xe6, 0x02, 0xcd, 0xc5, 0x28, 0x43, 0x42, 0xe3, 0xdf, 0x32, 82 0xf2, 0x28, 0xd9, 0x09, 0xca, 0xa4, 0x45, 0x19, 0x2a, 0x9e, 83 0x2d, 0x99, 0xf1, 0x40, 0x55, 0x2f, 0xb4, 0xe0, 0x04, 0xd8, 84 0x3b, 0x2e, 0x1e, 0xed, 0xff, 0xa6, 0x51, 0xd2, 0xe1, 0x22, 85 ], 86 nonce = [ 87 0xe2, 0x5b, 0x34, 0x1f, 0xc2, 0x8b, 0x6e, 0xc3, 0x37, 0xa0, 88 0x92, 0x45, 0xa8, 0xcb, 0x4b, 0x40, 0x3f, 0x24, 0x1c, 0x95, 89 0xff, 0x72, 0xea, 0x1d, 90 ], 91 cipher = [ 92 0x0b, 0xec, 0x57, 0xc8, 0x58, 0xf0, 0xc6, 0xb3, 0x42, 0x94, 93 0x86, 0xce, 0xf3, 0x3f, 0x04, 0x19, 0x41, 0xc2, 0xf7, 0xc9, 94 0x1f, 0x12, 0x9c, 0xbd, 0x68, 0xa8, 0xf2, 0xbe, 0xd3, 0xf3, 95 0x11, 0xea, 0x6e, 0xae, 0x39, 0xca, 0x93, 0x06, 0x99, 0x70, 96 0x67, 0xd6, 0xfa, 0xd8, 0x16, 0x4b, 0x2d, 0xf3, 0xb4, 0x73, 97 0x22, 0x36, 0x4b, 0x2d, 0xac, 0xd2, 0xaa, 0xab, 0x13, 0x2a, 98 0xd7, 0x05, 0x15, 0xbf, 0x18, 0x56, 0x20, 0xdb, 0xa4, 0xbb, 99 0x38, 0xa8, 0x8b, 0x0d, 0x12, 0xcc, 0x3b, 0x47, 0x4c, 0xba, 100 0x5f, 0x11, 0x75, 0x4e, 0x34, 0x87, 0x14, 0xe9, 0xb1, 0x23, 101 ], 102 mac = [ 103 0x07, 0x92, 0x76, 0xd8, 0x7c, 0x77, 0x71, 0x4b, 0xa4, 0xf2, 104 0x27, 0x66, 0x79, 0xeb, 0x38, 0xc1, 105 ], 106 ... 107 }; 108 109 const nomsg: sample = sample { 110 key = [ 111 0x10, 0x28, 0xbe, 0x0e, 0x0e, 0x46, 0x38, 0x0f, 0x12, 0x9f, 112 0x56, 0x17, 0x21, 0xb8, 0x65, 0x44, 0x49, 0x0d, 0x48, 0x7a, 113 0x46, 0x79, 0x5b, 0x9c, 0x54, 0xfd, 0x42, 0xc4, 0x53, 0x82, 114 0x51, 0x14, 115 ], 116 nonce = [ 117 0x35, 0x54, 0xec, 0x93, 0x4d, 0xd5, 0xdc, 0x90, 0xa2, 0xd3, 118 0x72, 0xdc, 0xff, 0x0a, 0x73, 0x32, 0x5f, 0xbd, 0xcc, 0x36, 119 0xab, 0x3f, 0x47, 0x1c, 120 ], 121 additional = [ 122 0xbe, 0x71, 0xf2, 0x86, 0x5a, 0xb9, 0x1b, 0x3c, 0x07, 0x9b, 123 0xa3, 0x3a, 0x34, 0xa3, 0x5e, 0x4a, 0x51, 0x34, 0xf5, 0x02, 124 0x55, 0xb1, 0x97, 0x1d, 0xd8, 0xb8, 0xb0, 0x63, 0x07, 0x98, 125 0x11, 0x7c, 0x4e, 0x40, 0xd1, 0xfe, 0xf7, 0x8d, 0xc8, 0xbc, 126 0x45, 0x3c, 0x1f, 0x81, 0x2d, 0xf2, 0x98, 0x88, 0x36, 0x9d, 127 0x0d, 0x2f, 0x71, 0xf5, 0xdb, 0x9d, 0x05, 0x5e, 0xc5, 0x4d, 128 0x6d, 0xe3, 0xca, 0xbb, 0x46, 0xda, 0x99, 0x41, 0xb1, 0xcd, 129 0x4e, 0xdc, 0xa3, 0x82, 0xc1, 0xb7, 0xd3, 0x5b, 0xae, 0x41, 130 0x60, 0x6a, 0x59, 0x2e, 0xf9, 0xd3, 0xbf, 0x44, 0x95, 0xbd, 131 ], 132 mac = [ 133 0xe9, 0x50, 0xd4, 0x3f, 0x0a, 0x84, 0x69, 0x24, 0xa3, 0x9a, 134 0xe6, 0x06, 0x29, 0xf8, 0x16, 0xcf, 135 ], 136 ... 137 }; 138 139 const nothing: sample = sample { 140 key = [ 141 0xbb, 0xf5, 0xf5, 0x40, 0xd7, 0x21, 0x38, 0x22, 0xe2, 0x82, 142 0x34, 0x0e, 0x26, 0xaa, 0x0a, 0xce, 0x94, 0x76, 0xb1, 0xac, 143 0x62, 0x50, 0x3f, 0x1a, 0x7c, 0x66, 0x78, 0xb3, 0x86, 0x3e, 144 0x4d, 0x4f, 145 ], 146 nonce = [ 147 0x54, 0xe3, 0xf0, 0xa8, 0x06, 0x86, 0x26, 0xd8, 0xd7, 0x7e, 148 0x26, 0x23, 0x3b, 0x95, 0xbf, 0x44, 0x30, 0x9e, 0xf6, 0xe4, 149 0x00, 0x65, 0xff, 0x1a, 150 ], 151 mac = [ 152 0x14, 0x23, 0x9b, 0xb3, 0xa3, 0x35, 0x9a, 0x11, 0x9c, 0x1d, 153 0x79, 0x65, 0x4b, 0xe2, 0x2f, 0xaf, 154 ], 155 ... 156 }; 157 158 const polyaligned: sample = sample { 159 key = [ 160 0x8a, 0x67, 0xe3, 0x6c, 0x24, 0xbd, 0x05, 0x7f, 0x53, 0x7d, 161 0x3b, 0x2d, 0x25, 0x98, 0x7c, 0x21, 0xb1, 0x51, 0x90, 0xdd, 162 0x7a, 0x4a, 0x52, 0x49, 0x12, 0x22, 0x3e, 0x7e, 0x2e, 0x0d, 163 0x8a, 0x15, 164 ], 165 msg = [ 166 0xa1, 0x9c, 0x40, 0xbe, 0x6e, 0xf7, 0x43, 0x66, 0xcf, 0xe1, 167 0x15, 0xce, 0x0c, 0x90, 0x7c, 0x1f, 0x35, 0xfb, 0x03, 0x7f, 168 0x96, 0x62, 0x53, 0xa6, 0xfa, 0xf1, 0x31, 0x39, 0xae, 0x69, 169 0x0e, 0xf7, 170 ], 171 nonce = [ 172 0xc2, 0x16, 0x80, 0x49, 0xd1, 0x82, 0x04, 0xc5, 0x89, 0xee, 173 0xbc, 0x24, 0xa0, 0x37, 0x6f, 0xbb, 0x44, 0x09, 0x49, 0x8e, 174 0xe2, 0x73, 0x33, 0x4d, 175 ], 176 additional = [ 177 0xc1, 0xf7, 0xa5, 0xcf, 0x2f, 0xc0, 0x21, 0x55, 0x74, 0xfb, 178 0x75, 0xcd, 0x8b, 0x9e, 0xe2, 0x2a, 179 ], 180 cipher = [ 181 0xfe, 0xe1, 0xb9, 0xff, 0xc5, 0x03, 0x38, 0x73, 0xbb, 0x1c, 182 0x90, 0x7b, 0x53, 0x39, 0x65, 0xd7, 0x64, 0x12, 0xe4, 0x88, 183 0xa0, 0xaa, 0x8e, 0x11, 0x23, 0xd0, 0x20, 0x8a, 0x54, 0x76, 184 0x12, 0x75, 185 ], 186 mac = [ 187 0x7e, 0x80, 0x2c, 0x34, 0x45, 0x04, 0x5b, 0xff, 0x04, 0x58, 188 0x36, 0xef, 0xe2, 0x55, 0xc8, 0x45, 189 ], 190 }; 191 192 @test fn rfc() void = { 193 let result: []u8 = alloc(rfcsample.msg...); 194 defer free(result); 195 196 let b = encrypt(&rfcsample.key, &rfcsample.nonce, result[..], 197 rfcsample.additional[..]); 198 199 assert(bytes::equal(rfcsample.cipher, b.2)); 200 assert(bytes::equal(rfcsample.nonce, b.1)); 201 assert(bytes::equal(rfcsample.mac, b.0)); 202 203 const plain = decrypt(&rfcsample.key, &b, rfcsample.additional); 204 205 assert(plain is []u8); 206 assert(bytes::equal(rfcsample.msg, plain as []u8)); 207 }; 208 209 @test fn rfcmultiadditonals() void = { 210 let result: []u8 = alloc(rfcsample.msg...); 211 defer free(result); 212 213 let b = encrypt(&rfcsample.key, &rfcsample.nonce, result[..], 214 rfcsample.additional[..4], rfcsample.additional[4..]); 215 216 assert(bytes::equal(rfcsample.cipher, b.2)); 217 assert(bytes::equal(rfcsample.nonce, b.1)); 218 assert(bytes::equal(rfcsample.mac, b.0)); 219 220 const plain = decrypt(&rfcsample.key, &b, rfcsample.additional); 221 222 assert(plain is []u8); 223 assert(bytes::equal(rfcsample.msg, plain as []u8)); 224 }; 225 226 @test fn noadditional() void = { 227 let result: []u8 = alloc(noadsample.msg...); 228 defer free(result); 229 230 let b = encrypt(&noadsample.key, &noadsample.nonce, result[..]); 231 232 assert(bytes::equal(noadsample.cipher, b.2)); 233 assert(bytes::equal(noadsample.nonce, b.1)); 234 assert(bytes::equal(noadsample.mac, b.0)); 235 236 const plain = decrypt(&noadsample.key, &b); 237 238 assert(plain is []u8); 239 assert(bytes::equal(noadsample.msg, plain as []u8)); 240 }; 241 242 @test fn nomsg() void = { 243 let result: []u8 = []; 244 defer free(result); 245 246 let b = encrypt(&nomsg.key, &nomsg.nonce, result[..], nomsg.additional); 247 248 assert(bytes::equal([], b.2)); 249 assert(bytes::equal(nomsg.nonce, b.1)); 250 assert(bytes::equal(nomsg.mac, b.0)); 251 252 const plain = decrypt(&nomsg.key, &b, nomsg.additional); 253 254 assert(plain is []u8); 255 assert(bytes::equal([], plain as []u8)); 256 }; 257 258 @test fn nothing() void = { 259 let result: []u8 = []; 260 defer free(result); 261 262 let b = encrypt(¬hing.key, ¬hing.nonce, result[..]); 263 264 assert(bytes::equal([], b.2)); 265 assert(bytes::equal(nothing.nonce, b.1)); 266 assert(bytes::equal(nothing.mac, b.0)); 267 268 const plain = decrypt(¬hing.key, &b); 269 270 assert(plain is []u8); 271 assert(bytes::equal([], plain as []u8)); 272 }; 273 274 @test fn polyaligned() void = { 275 let result: []u8 = alloc(polyaligned.msg...); 276 defer free(result); 277 278 let b = encrypt(&polyaligned.key, &polyaligned.nonce, result[..], 279 polyaligned.additional[..]); 280 281 assert(bytes::equal(polyaligned.cipher, b.2)); 282 assert(bytes::equal(polyaligned.nonce, b.1)); 283 assert(bytes::equal(polyaligned.mac, b.0)); 284 285 const plain = decrypt(&polyaligned.key, &b, polyaligned.additional); 286 287 assert(plain is []u8); 288 assert(bytes::equal(polyaligned.msg, plain as []u8)); 289 }; 290 291 292 @test fn invalidkey() void = { 293 const zero: [114]u8 = [0...]; 294 295 let key = rfcsample.key; 296 key[0] = 0x00; 297 298 let cipher: []u8 = alloc(rfcsample.cipher...); 299 defer free(cipher); 300 301 let b: box = (rfcsample.mac, rfcsample.nonce, cipher[..]); 302 303 const plain = decrypt(&key, &b, rfcsample.additional); 304 305 assert(plain is errors::invalid); 306 assert(bytes::equal(zero, cipher)); 307 }; 308 309 @test fn invalidcipher() void = { 310 const zero: [114]u8 = [0...]; 311 312 let cipher: []u8 = alloc(rfcsample.cipher...); 313 defer free(cipher); 314 cipher[0] = 0x00; 315 316 let b: box = (rfcsample.mac, rfcsample.nonce, cipher[..]); 317 318 const plain = decrypt(&rfcsample.key, &b, rfcsample.additional); 319 320 assert(plain is errors::invalid); 321 assert(bytes::equal(zero, cipher)); 322 }; 323 324 @test fn invalidcipher2() void = { 325 326 let cipher: []u8 = alloc(rfcsample.cipher...); 327 defer free(cipher); 328 append(cipher, 0xff); 329 330 let b: box = (rfcsample.mac, rfcsample.nonce, cipher[..]); 331 332 const plain = decrypt(&rfcsample.key, &b, rfcsample.additional); 333 334 assert(plain is errors::invalid); 335 336 const zero: [115]u8 = [0...]; 337 assert(bytes::equal(zero, cipher)); 338 }; 339 340 @test fn invalidcipher3() void = { 341 let cipher: []u8 = alloc(rfcsample.cipher...); 342 defer free(cipher); 343 delete(cipher[len(cipher) - 1]); 344 345 let b: box = (rfcsample.mac, rfcsample.nonce, cipher[..]); 346 347 const plain = decrypt(&rfcsample.key, &b, rfcsample.additional); 348 349 assert(plain is errors::invalid); 350 351 const zero: [113]u8 = [0...]; 352 assert(bytes::equal(zero, cipher)); 353 }; 354 355 @test fn invalidaddition() void = { 356 const zero: [114]u8 = [0...]; 357 358 let cipher: []u8 = alloc(rfcsample.cipher...); 359 defer free(cipher); 360 361 let ad: []u8 = alloc(rfcsample.additional...); 362 defer free(ad); 363 ad[0] = 0x00; 364 365 let b: box = (rfcsample.mac, rfcsample.nonce, cipher[..]); 366 367 const plain = decrypt(&rfcsample.key, &b, ad); 368 369 assert(plain is errors::invalid); 370 assert(bytes::equal(zero, cipher)); 371 }; 372 373 @test fn invalidaddition2() void = { 374 const zero: [114]u8 = [0...]; 375 376 let cipher: []u8 = alloc(rfcsample.cipher...); 377 defer free(cipher); 378 379 let ad: []u8 = alloc(rfcsample.additional...); 380 defer free(ad); 381 append(ad, 0xff); 382 383 let b: box = (rfcsample.mac, rfcsample.nonce, cipher[..]); 384 385 const plain = decrypt(&rfcsample.key, &b, ad); 386 387 assert(plain is errors::invalid); 388 assert(bytes::equal(zero, cipher)); 389 }; 390 391 @test fn invalidaddition3() void = { 392 const zero: [114]u8 = [0...]; 393 394 let cipher: []u8 = alloc(rfcsample.cipher...); 395 defer free(cipher); 396 397 let ad: []u8 = alloc(rfcsample.additional...); 398 defer free(ad); 399 delete(ad[len(ad) - 1]); 400 401 let b: box = (rfcsample.mac, rfcsample.nonce, cipher[..]); 402 403 const plain = decrypt(&rfcsample.key, &b, ad); 404 405 assert(plain is errors::invalid); 406 assert(bytes::equal(zero, cipher)); 407 }; 408 409 @test fn invalidaddition4() void = { 410 const zero: [114]u8 = [0...]; 411 412 let cipher: []u8 = alloc(rfcsample.cipher...); 413 defer free(cipher); 414 415 let b: box = (rfcsample.mac, rfcsample.nonce, cipher[..]); 416 417 const plain = decrypt(&rfcsample.key, &b); 418 419 assert(plain is errors::invalid); 420 assert(bytes::equal(zero, cipher)); 421 }; 422 423 @test fn invalidaddition5() void = { 424 const zero: [114]u8 = [0...]; 425 426 let cipher: []u8 = alloc(rfcsample.cipher...); 427 defer free(cipher); 428 429 let b: box = (rfcsample.mac, rfcsample.nonce, cipher[..]); 430 431 const plain = decrypt(&rfcsample.key, &b, rfcsample.additional, [0xff]); 432 433 assert(plain is errors::invalid); 434 assert(bytes::equal(zero, cipher)); 435 }; 436 437 @test fn cipheradditionswap() void = { 438 let additional: []u8 = alloc(rfcsample.additional...); 439 defer free(additional); 440 441 let b: box = (rfcsample.mac, rfcsample.nonce, additional); 442 443 const plain = decrypt(&rfcsample.key, &b, rfcsample.cipher); 444 445 assert(plain is errors::invalid); 446 447 const zero: [12]u8 = [0...]; 448 assert(bytes::equal(zero, additional)); 449 }; 450 451 @test fn invalidmac() void = { 452 const zero: [114]u8 = [0...]; 453 454 let cipher: []u8 = alloc(rfcsample.cipher...); 455 defer free(cipher); 456 457 let mac: mac = rfcsample.mac; 458 mac[0] = 0xff; 459 460 let b: box = (mac, rfcsample.nonce, cipher[..]); 461 462 const plain = decrypt(&rfcsample.key, &b, rfcsample.additional); 463 464 assert(plain is errors::invalid); 465 assert(bytes::equal(zero, cipher)); 466 };