| ... | @@ -161,7 +161,7 @@ fn State128X(comptime degree: u7) type { | ... | @@ -161,7 +161,7 @@ fn State128X(comptime degree: u7) type { |
| 161 | state.update(msg0, msg1); | 161 | state.update(msg0, msg1); |
| 162 | } | 162 | } |
| 163 | | 163 | |
| 164 | fn mac(state: *State, comptime tag_bits: u9, adlen: usize, mlen: usize) [tag_bits / 8]u8 { | 164 | fn finalize(state: *State, comptime tag_bits: u9, adlen: usize, mlen: usize) [tag_bits / 8]u8 { |
| 165 | const blocks = &state.blocks; | 165 | const blocks = &state.blocks; |
| 166 | var sizes: [aes_block_length]u8 = undefined; | 166 | var sizes: [aes_block_length]u8 = undefined; |
| 167 | mem.writeInt(u64, sizes[0..8], @as(u64, adlen) * 8, .little); | 167 | mem.writeInt(u64, sizes[0..8], @as(u64, adlen) * 8, .little); |
| ... | @@ -200,6 +200,59 @@ fn State128X(comptime degree: u7) type { | ... | @@ -200,6 +200,59 @@ fn State128X(comptime degree: u7) type { |
| 200 | else => unreachable, | 200 | else => unreachable, |
| 201 | } | 201 | } |
| 202 | } | 202 | } |
| | 203 | |
| | 204 | fn finalizeMac(state: *State, comptime tag_bits: u9, datalen: usize) [tag_bits / 8]u8 { |
| | 205 | const blocks = &state.blocks; |
| | 206 | var sizes: [aes_block_length]u8 = undefined; |
| | 207 | mem.writeInt(u64, sizes[0..8], @as(u64, datalen) * 8, .little); |
| | 208 | mem.writeInt(u64, sizes[8..16], tag_bits, .little); |
| | 209 | for (1..degree) |i| { |
| | 210 | @memcpy(sizes[i * 16 ..][0..16], sizes[0..16]); |
| | 211 | } |
| | 212 | var t = blocks[2].xorBlocks(AesBlockVec.fromBytes(&sizes)); |
| | 213 | for (0..7) |_| { |
| | 214 | state.update(t, t); |
| | 215 | } |
| | 216 | if (degree > 1) { |
| | 217 | var v = [_]u8{0} ** rate; |
| | 218 | switch (tag_bits) { |
| | 219 | 128 => { |
| | 220 | const tags = blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).xorBlocks(blocks[3]).xorBlocks(blocks[4]).xorBlocks(blocks[5]).xorBlocks(blocks[6]).toBytes(); |
| | 221 | for (0..degree / 2) |d| { |
| | 222 | v[0..32].* = tags[d * 32 ..][0..32].*; |
| | 223 | state.absorb(&v); |
| | 224 | } |
| | 225 | }, |
| | 226 | 256 => { |
| | 227 | const tags_0 = blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).xorBlocks(blocks[3]).toBytes(); |
| | 228 | const tags_1 = blocks[4].xorBlocks(blocks[5]).xorBlocks(blocks[6]).xorBlocks(blocks[7]).toBytes(); |
| | 229 | for (1..degree) |d| { |
| | 230 | v[0..32].* = tags_0[d * 16 ..][0..16].* ++ tags_1[d * 16 ..][0..16].*; |
| | 231 | state.absorb(&v); |
| | 232 | } |
| | 233 | }, |
| | 234 | else => unreachable, |
| | 235 | } |
| | 236 | mem.writeInt(u64, sizes[0..8], degree, .little); |
| | 237 | mem.writeInt(u64, sizes[8..16], tag_bits, .little); |
| | 238 | t = blocks[2].xorBlocks(AesBlockVec.fromBytes(&sizes)); |
| | 239 | for (0..7) |_| { |
| | 240 | state.update(t, t); |
| | 241 | } |
| | 242 | } |
| | 243 | switch (tag_bits) { |
| | 244 | 128 => { |
| | 245 | const tags = blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).xorBlocks(blocks[3]).xorBlocks(blocks[4]).xorBlocks(blocks[5]).xorBlocks(blocks[6]).toBytes(); |
| | 246 | return tags[0..16].*; |
| | 247 | }, |
| | 248 | 256 => { |
| | 249 | const tags_0 = blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).xorBlocks(blocks[3]).toBytes(); |
| | 250 | const tags_1 = blocks[4].xorBlocks(blocks[5]).xorBlocks(blocks[6]).xorBlocks(blocks[7]).toBytes(); |
| | 251 | return tags_0[0..16].* ++ tags_1[0..16].*; |
| | 252 | }, |
| | 253 | else => unreachable, |
| | 254 | } |
| | 255 | } |
| 203 | }; | 256 | }; |
| 204 | } | 257 | } |
| 205 | | 258 | |
| ... | @@ -252,7 +305,7 @@ fn Aegis128XGeneric(comptime degree: u7, comptime tag_bits: u9) type { | ... | @@ -252,7 +305,7 @@ fn Aegis128XGeneric(comptime degree: u7, comptime tag_bits: u9) type { |
| 252 | state.enc(&dst, &src); | 305 | state.enc(&dst, &src); |
| 253 | @memcpy(c[i..][0 .. m.len % block_length], dst[0 .. m.len % block_length]); | 306 | @memcpy(c[i..][0 .. m.len % block_length], dst[0 .. m.len % block_length]); |
| 254 | } | 307 | } |
| 255 | tag.* = state.mac(tag_bits, ad.len, m.len); | 308 | tag.* = state.finalize(tag_bits, ad.len, m.len); |
| 256 | } | 309 | } |
| 257 | | 310 | |
| 258 | /// `m`: Message | 311 | /// `m`: Message |
| ... | @@ -284,7 +337,7 @@ fn Aegis128XGeneric(comptime degree: u7, comptime tag_bits: u9) type { | ... | @@ -284,7 +337,7 @@ fn Aegis128XGeneric(comptime degree: u7, comptime tag_bits: u9) type { |
| 284 | if (m.len % block_length != 0) { | 337 | if (m.len % block_length != 0) { |
| 285 | state.decLast(m[i..], c[i..]); | 338 | state.decLast(m[i..], c[i..]); |
| 286 | } | 339 | } |
| 287 | var computed_tag = state.mac(tag_bits, ad.len, m.len); | 340 | var computed_tag = state.finalize(tag_bits, ad.len, m.len); |
| 288 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); | 341 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 289 | if (!verify) { | 342 | if (!verify) { |
| 290 | crypto.secureZero(u8, &computed_tag); | 343 | crypto.secureZero(u8, &computed_tag); |
| ... | @@ -401,7 +454,7 @@ fn State256X(comptime degree: u7) type { | ... | @@ -401,7 +454,7 @@ fn State256X(comptime degree: u7) type { |
| 401 | state.update(msg); | 454 | state.update(msg); |
| 402 | } | 455 | } |
| 403 | | 456 | |
| 404 | fn mac(state: *State, comptime tag_bits: u9, adlen: usize, mlen: usize) [tag_bits / 8]u8 { | 457 | fn finalize(state: *State, comptime tag_bits: u9, adlen: usize, mlen: usize) [tag_bits / 8]u8 { |
| 405 | const blocks = &state.blocks; | 458 | const blocks = &state.blocks; |
| 406 | var sizes: [aes_block_length]u8 = undefined; | 459 | var sizes: [aes_block_length]u8 = undefined; |
| 407 | mem.writeInt(u64, sizes[0..8], @as(u64, adlen) * 8, .little); | 460 | mem.writeInt(u64, sizes[0..8], @as(u64, adlen) * 8, .little); |
| ... | @@ -440,6 +493,61 @@ fn State256X(comptime degree: u7) type { | ... | @@ -440,6 +493,61 @@ fn State256X(comptime degree: u7) type { |
| 440 | else => unreachable, | 493 | else => unreachable, |
| 441 | } | 494 | } |
| 442 | } | 495 | } |
| | 496 | |
| | 497 | fn finalizeMac(state: *State, comptime tag_bits: u9, datalen: usize) [tag_bits / 8]u8 { |
| | 498 | const blocks = &state.blocks; |
| | 499 | var sizes: [aes_block_length]u8 = undefined; |
| | 500 | mem.writeInt(u64, sizes[0..8], @as(u64, datalen) * 8, .little); |
| | 501 | mem.writeInt(u64, sizes[8..16], tag_bits, .little); |
| | 502 | for (1..degree) |i| { |
| | 503 | @memcpy(sizes[i * 16 ..][0..16], sizes[0..16]); |
| | 504 | } |
| | 505 | var t = blocks[3].xorBlocks(AesBlockVec.fromBytes(&sizes)); |
| | 506 | for (0..7) |_| { |
| | 507 | state.update(t); |
| | 508 | } |
| | 509 | if (degree > 1) { |
| | 510 | var v = [_]u8{0} ** rate; |
| | 511 | switch (tag_bits) { |
| | 512 | 128 => { |
| | 513 | const tags = blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).xorBlocks(blocks[3]).xorBlocks(blocks[4]).xorBlocks(blocks[5]).toBytes(); |
| | 514 | for (1..degree) |d| { |
| | 515 | v[0..16].* = tags[d * 16 ..][0..16].*; |
| | 516 | state.absorb(&v); |
| | 517 | } |
| | 518 | }, |
| | 519 | 256 => { |
| | 520 | const tags_0 = blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).toBytes(); |
| | 521 | const tags_1 = blocks[3].xorBlocks(blocks[4]).xorBlocks(blocks[5]).toBytes(); |
| | 522 | for (1..degree) |d| { |
| | 523 | v[0..16].* = tags_0[d * 16 ..][0..16].*; |
| | 524 | state.absorb(&v); |
| | 525 | v[0..16].* = tags_1[d * 16 ..][0..16].*; |
| | 526 | state.absorb(&v); |
| | 527 | } |
| | 528 | }, |
| | 529 | else => unreachable, |
| | 530 | } |
| | 531 | mem.writeInt(u64, sizes[0..8], degree, .little); |
| | 532 | mem.writeInt(u64, sizes[8..16], tag_bits, .little); |
| | 533 | t = blocks[3].xorBlocks(AesBlockVec.fromBytes(&sizes)); |
| | 534 | for (0..7) |_| { |
| | 535 | state.update(t); |
| | 536 | } |
| | 537 | } |
| | 538 | switch (tag_bits) { |
| | 539 | 128 => { |
| | 540 | const tags = blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).xorBlocks(blocks[3]).xorBlocks(blocks[4]).xorBlocks(blocks[5]).toBytes(); |
| | 541 | return tags[0..16].*; |
| | 542 | }, |
| | 543 | 256 => { |
| | 544 | const tags_0 = blocks[0].xorBlocks(blocks[1]).xorBlocks(blocks[2]).toBytes(); |
| | 545 | const tags_1 = blocks[3].xorBlocks(blocks[4]).xorBlocks(blocks[5]).toBytes(); |
| | 546 | return tags_0[0..16].* ++ tags_1[0..16].*; |
| | 547 | }, |
| | 548 | else => unreachable, |
| | 549 | } |
| | 550 | } |
| 443 | }; | 551 | }; |
| 444 | } | 552 | } |
| 445 | | 553 | |
| ... | @@ -492,7 +600,7 @@ fn Aegis256XGeneric(comptime degree: u7, comptime tag_bits: u9) type { | ... | @@ -492,7 +600,7 @@ fn Aegis256XGeneric(comptime degree: u7, comptime tag_bits: u9) type { |
| 492 | state.enc(&dst, &src); | 600 | state.enc(&dst, &src); |
| 493 | @memcpy(c[i..][0 .. m.len % block_length], dst[0 .. m.len % block_length]); | 601 | @memcpy(c[i..][0 .. m.len % block_length], dst[0 .. m.len % block_length]); |
| 494 | } | 602 | } |
| 495 | tag.* = state.mac(tag_bits, ad.len, m.len); | 603 | tag.* = state.finalize(tag_bits, ad.len, m.len); |
| 496 | } | 604 | } |
| 497 | | 605 | |
| 498 | /// `m`: Message | 606 | /// `m`: Message |
| ... | @@ -524,7 +632,7 @@ fn Aegis256XGeneric(comptime degree: u7, comptime tag_bits: u9) type { | ... | @@ -524,7 +632,7 @@ fn Aegis256XGeneric(comptime degree: u7, comptime tag_bits: u9) type { |
| 524 | if (m.len % block_length != 0) { | 632 | if (m.len % block_length != 0) { |
| 525 | state.decLast(m[i..], c[i..]); | 633 | state.decLast(m[i..], c[i..]); |
| 526 | } | 634 | } |
| 527 | var computed_tag = state.mac(tag_bits, ad.len, m.len); | 635 | var computed_tag = state.finalize(tag_bits, ad.len, m.len); |
| 528 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); | 636 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 529 | if (!verify) { | 637 | if (!verify) { |
| 530 | crypto.secureZero(u8, &computed_tag); | 638 | crypto.secureZero(u8, &computed_tag); |
| ... | @@ -562,9 +670,31 @@ pub const Aegis128X2Mac = AegisMac(Aegis128X2_256); | ... | @@ -562,9 +670,31 @@ pub const Aegis128X2Mac = AegisMac(Aegis128X2_256); |
| 562 | /// - It has a large security margin against internal collisions. | 670 | /// - It has a large security margin against internal collisions. |
| 563 | pub const Aegis128LMac = AegisMac(Aegis128L_256); | 671 | pub const Aegis128LMac = AegisMac(Aegis128L_256); |
| 564 | | 672 | |
| | 673 | /// The `Aegis256X4Mac` message authentication function has a 256-bit key size, |
| | 674 | /// and outputs 256 bit tags. |
| | 675 | /// The key size is the main practical difference with `Aegis128X4Mac`. |
| | 676 | /// AEGIS' large state, non-linearity and non-invertibility provides the |
| | 677 | /// following properties: |
| | 678 | /// - 256 bit security against forgery. |
| | 679 | /// - Recovering the secret key from the state would require ~2^256 attempts, |
| | 680 | /// which is infeasible for any practical adversary. |
| | 681 | /// - It has a large security margin against internal collisions. |
| | 682 | pub const Aegis256X4Mac = AegisMac(Aegis256X4_256); |
| | 683 | |
| | 684 | /// The `Aegis256X2Mac` message authentication function has a 256-bit key size, |
| | 685 | /// and outputs 256 bit tags. |
| | 686 | /// The key size is the main practical difference with `Aegis128X2Mac`. |
| | 687 | /// AEGIS' large state, non-linearity and non-invertibility provides the |
| | 688 | /// following properties: |
| | 689 | /// - 256 bit security against forgery. |
| | 690 | /// - Recovering the secret key from the state would require ~2^256 attempts, |
| | 691 | /// which is infeasible for any practical adversary. |
| | 692 | /// - It has a large security margin against internal collisions. |
| | 693 | pub const Aegis256X2Mac = AegisMac(Aegis256X2_256); |
| | 694 | |
| 565 | /// The `Aegis256Mac` message authentication function has a 256-bit key size, | 695 | /// The `Aegis256Mac` message authentication function has a 256-bit key size, |
| 566 | /// and outputs 256 bit tags. Unless theoretical multi-target attacks are a | 696 | /// and outputs 256 bit tags. |
| 567 | /// concern, the AEGIS-128L variant should be preferred. | 697 | /// The key size is the main practical difference with `Aegis128LMac`. |
| 568 | /// AEGIS' large state, non-linearity and non-invertibility provides the | 698 | /// AEGIS' large state, non-linearity and non-invertibility provides the |
| 569 | /// following properties: | 699 | /// following properties: |
| 570 | /// - 256 bit security against forgery. | 700 | /// - 256 bit security against forgery. |
| ... | @@ -573,9 +703,21 @@ pub const Aegis128LMac = AegisMac(Aegis128L_256); | ... | @@ -573,9 +703,21 @@ pub const Aegis128LMac = AegisMac(Aegis128L_256); |
| 573 | /// - It has a large security margin against internal collisions. | 703 | /// - It has a large security margin against internal collisions. |
| 574 | pub const Aegis256Mac = AegisMac(Aegis256_256); | 704 | pub const Aegis256Mac = AegisMac(Aegis256_256); |
| 575 | | 705 | |
| | 706 | /// AEGIS-128X4 MAC with 128-bit tags |
| | 707 | pub const Aegis128X4Mac_128 = AegisMac(Aegis128X4); |
| | 708 | |
| | 709 | /// AEGIS-128X2 MAC with 128-bit tags |
| | 710 | pub const Aegis128X2Mac_128 = AegisMac(Aegis128X2); |
| | 711 | |
| 576 | /// AEGIS-128L MAC with 128-bit tags | 712 | /// AEGIS-128L MAC with 128-bit tags |
| 577 | pub const Aegis128LMac_128 = AegisMac(Aegis128L); | 713 | pub const Aegis128LMac_128 = AegisMac(Aegis128L); |
| 578 | | 714 | |
| | 715 | /// AEGIS-256X4 MAC with 128-bit tags |
| | 716 | pub const Aegis256X4Mac_128 = AegisMac(Aegis256X4); |
| | 717 | |
| | 718 | /// AEGIS-256X2 MAC with 128-bit tags |
| | 719 | pub const Aegis256X2Mac_128 = AegisMac(Aegis256X2); |
| | 720 | |
| 579 | /// AEGIS-256 MAC with 128-bit tags | 721 | /// AEGIS-256 MAC with 128-bit tags |
| 580 | pub const Aegis256Mac_128 = AegisMac(Aegis256); | 722 | pub const Aegis256Mac_128 = AegisMac(Aegis256); |
| 581 | | 723 | |
| ... | @@ -585,6 +727,7 @@ fn AegisMac(comptime T: type) type { | ... | @@ -585,6 +727,7 @@ fn AegisMac(comptime T: type) type { |
| 585 | | 727 | |
| 586 | pub const mac_length = T.tag_length; | 728 | pub const mac_length = T.tag_length; |
| 587 | pub const key_length = T.key_length; | 729 | pub const key_length = T.key_length; |
| | 730 | pub const nonce_length = T.nonce_length; |
| 588 | pub const block_length = T.block_length; | 731 | pub const block_length = T.block_length; |
| 589 | | 732 | |
| 590 | state: T.State, | 733 | state: T.State, |
| ... | @@ -592,11 +735,17 @@ fn AegisMac(comptime T: type) type { | ... | @@ -592,11 +735,17 @@ fn AegisMac(comptime T: type) type { |
| 592 | off: usize = 0, | 735 | off: usize = 0, |
| 593 | msg_len: usize = 0, | 736 | msg_len: usize = 0, |
| 594 | | 737 | |
| 595 | /// Initialize a state for the MAC function | 738 | /// Initialize a state for the MAC function, with a key and a nonce |
| | 739 | pub fn initWithNonce(key: *const [key_length]u8, nonce: *const [nonce_length]u8) Mac { |
| | 740 | return Mac{ |
| | 741 | .state = T.State.init(key.*, nonce.*), |
| | 742 | }; |
| | 743 | } |
| | 744 | |
| | 745 | /// Initialize a state for the MAC function, with a default nonce |
| 596 | pub fn init(key: *const [key_length]u8) Mac { | 746 | pub fn init(key: *const [key_length]u8) Mac { |
| 597 | const nonce = [_]u8{0} ** T.nonce_length; | | |
| 598 | return Mac{ | 747 | return Mac{ |
| 599 | .state = T.State.init(key.*, nonce), | 748 | .state = T.State.init(key.*, [_]u8{0} ** nonce_length), |
| 600 | }; | 749 | }; |
| 601 | } | 750 | } |
| 602 | | 751 | |
| ... | @@ -634,7 +783,14 @@ fn AegisMac(comptime T: type) type { | ... | @@ -634,7 +783,14 @@ fn AegisMac(comptime T: type) type { |
| 634 | @memcpy(pad[0..self.off], self.buf[0..self.off]); | 783 | @memcpy(pad[0..self.off], self.buf[0..self.off]); |
| 635 | self.state.absorb(&pad); | 784 | self.state.absorb(&pad); |
| 636 | } | 785 | } |
| 637 | out.* = self.state.mac(T.tag_length * 8, self.msg_len, 0); | 786 | out.* = self.state.finalizeMac(T.tag_length * 8, self.msg_len); |
| | 787 | } |
| | 788 | |
| | 789 | /// Return an authentication tag for a message, a key and a nonce |
| | 790 | pub fn createWithNonce(out: *[mac_length]u8, msg: []const u8, key: *const [key_length]u8, nonce: *const [nonce_length]u8) void { |
| | 791 | var ctx = Mac.initWithNonce(key, nonce); |
| | 792 | ctx.update(msg); |
| | 793 | ctx.final(out); |
| 638 | } | 794 | } |
| 639 | | 795 | |
| 640 | /// Return an authentication tag for a message and a key | 796 | /// Return an authentication tag for a message and a key |
| ... | @@ -820,29 +976,72 @@ test "Aegis MAC" { | ... | @@ -820,29 +976,72 @@ test "Aegis MAC" { |
| 820 | st.update(msg[0..32]); | 976 | st.update(msg[0..32]); |
| 821 | st.update(msg[32..]); | 977 | st.update(msg[32..]); |
| 822 | st.final(&tag); | 978 | st.final(&tag); |
| 823 | try htest.assertEqual("f8840849602738d81037cbaa0f584ea95759e2ac60263ce77346bcdc79fe4319", &tag); | 979 | try htest.assertEqual("f5eb88d90b7d31c9a679eb94ed1374cd14816b19cdb77930d1a5158f8595983b", &tag); |
| 824 | | 980 | |
| 825 | st = st_init; | 981 | st = st_init; |
| 826 | st.update(msg[0..31]); | 982 | st.update(msg[0..31]); |
| 827 | st.update(msg[31..]); | 983 | st.update(msg[31..]); |
| 828 | st.final(&tag); | 984 | st.final(&tag); |
| 829 | try htest.assertEqual("f8840849602738d81037cbaa0f584ea95759e2ac60263ce77346bcdc79fe4319", &tag); | 985 | try htest.assertEqual("f5eb88d90b7d31c9a679eb94ed1374cd14816b19cdb77930d1a5158f8595983b", &tag); |
| 830 | | 986 | |
| 831 | st = st_init; | 987 | st = st_init; |
| 832 | st.update(msg[0..14]); | 988 | st.update(msg[0..14]); |
| 833 | st.update(msg[14..30]); | 989 | st.update(msg[14..30]); |
| 834 | st.update(msg[30..]); | 990 | st.update(msg[30..]); |
| 835 | st.final(&tag); | 991 | st.final(&tag); |
| 836 | try htest.assertEqual("f8840849602738d81037cbaa0f584ea95759e2ac60263ce77346bcdc79fe4319", &tag); | 992 | try htest.assertEqual("f5eb88d90b7d31c9a679eb94ed1374cd14816b19cdb77930d1a5158f8595983b", &tag); |
| 837 | | | |
| 838 | var empty: [0]u8 = undefined; | | |
| 839 | const nonce = [_]u8{0x00} ** Aegis128L_256.nonce_length; | | |
| 840 | Aegis128L_256.encrypt(&empty, &tag, &empty, &msg, nonce, key); | | |
| 841 | try htest.assertEqual("f8840849602738d81037cbaa0f584ea95759e2ac60263ce77346bcdc79fe4319", &tag); | | |
| 842 | | 993 | |
| 843 | // An update whose size is not a multiple of the block size | 994 | // An update whose size is not a multiple of the block size |
| 844 | st = st_init; | 995 | st = st_init; |
| 845 | st.update(msg[0..33]); | 996 | st.update(msg[0..33]); |
| 846 | st.final(&tag); | 997 | st.final(&tag); |
| 847 | try htest.assertEqual("c7cf649a844c1a6676cf6d91b1658e0aee54a4da330b0a8d3bc7ea4067551d1b", &tag); | 998 | try htest.assertEqual("07b3ba5ad9ceee5ef1906e3396f0fa540fbcd2f33833ef97c35bdc2ae9ae0535", &tag); |
| | 999 | } |
| | 1000 | |
| | 1001 | test "AEGISMAC-128* test vectors" { |
| | 1002 | const key = [_]u8{ 0x10, 0x01 } ++ [_]u8{0x00} ** (16 - 2); |
| | 1003 | const nonce = [_]u8{ 0x10, 0x00, 0x02 } ++ [_]u8{0x00} ** (16 - 3); |
| | 1004 | var msg: [35]u8 = undefined; |
| | 1005 | for (&msg, 0..) |*byte, i| byte.* = @truncate(i); |
| | 1006 | var mac128: [16]u8 = undefined; |
| | 1007 | var mac256: [32]u8 = undefined; |
| | 1008 | |
| | 1009 | Aegis128LMac.createWithNonce(&mac256, &msg, &key, &nonce); |
| | 1010 | Aegis128LMac_128.createWithNonce(&mac128, &msg, &key, &nonce); |
| | 1011 | try htest.assertEqual("d3f09b2842ad301687d6902c921d7818", &mac128); |
| | 1012 | try htest.assertEqual("9490e7c89d420c9f37417fa625eb38e8cad53c5cbec55285e8499ea48377f2a3", &mac256); |
| | 1013 | |
| | 1014 | Aegis128X2Mac.createWithNonce(&mac256, &msg, &key, &nonce); |
| | 1015 | Aegis128X2Mac_128.createWithNonce(&mac128, &msg, &key, &nonce); |
| | 1016 | try htest.assertEqual("7aa41edfd57a95c1108d83c63b8d4d01", &mac128); |
| | 1017 | try htest.assertEqual("55b6449929cd2b01d04786e57698b3ddfb5cbf6e421bbd022637a33d60f40294", &mac256); |
| | 1018 | |
| | 1019 | Aegis128X4Mac.createWithNonce(&mac256, &msg, &key, &nonce); |
| | 1020 | Aegis128X4Mac_128.createWithNonce(&mac128, &msg, &key, &nonce); |
| | 1021 | try htest.assertEqual("46a194ea4337bb32c2186a99e312f3a7", &mac128); |
| | 1022 | try htest.assertEqual("ea884072699569532fb68ae9fb2653c9ffef3e974333d3a17d77be02453cc12f", &mac256); |
| | 1023 | } |
| | 1024 | |
| | 1025 | test "AEGISMAC-256* test vectors" { |
| | 1026 | const key = [_]u8{ 0x10, 0x01 } ++ [_]u8{0x00} ** (32 - 2); |
| | 1027 | const nonce = [_]u8{ 0x10, 0x00, 0x02 } ++ [_]u8{0x00} ** (32 - 3); |
| | 1028 | var msg: [35]u8 = undefined; |
| | 1029 | for (&msg, 0..) |*byte, i| byte.* = @truncate(i); |
| | 1030 | var mac128: [16]u8 = undefined; |
| | 1031 | var mac256: [32]u8 = undefined; |
| | 1032 | |
| | 1033 | Aegis256Mac.createWithNonce(&mac256, &msg, &key, &nonce); |
| | 1034 | Aegis256Mac_128.createWithNonce(&mac128, &msg, &key, &nonce); |
| | 1035 | try htest.assertEqual("c08e20cfc56f27195a46c9cef5c162d4", &mac128); |
| | 1036 | try htest.assertEqual("a5c906ede3d69545c11e20afa360b221f936e946ed2dba3d7c75ad6dc2784126", &mac256); |
| | 1037 | |
| | 1038 | Aegis256X2Mac.createWithNonce(&mac256, &msg, &key, &nonce); |
| | 1039 | Aegis256X2Mac_128.createWithNonce(&mac128, &msg, &key, &nonce); |
| | 1040 | try htest.assertEqual("fb319cb6dd728a764606fb14d37f2a5e", &mac128); |
| | 1041 | try htest.assertEqual("0844b20ed5147ceae89c7a160263afd4b1382d6b154ecf560ce8a342cb6a8fd1", &mac256); |
| | 1042 | |
| | 1043 | Aegis256X4Mac.createWithNonce(&mac256, &msg, &key, &nonce); |
| | 1044 | Aegis256X4Mac_128.createWithNonce(&mac128, &msg, &key, &nonce); |
| | 1045 | try htest.assertEqual("a51f9bc5beae60cce77f0dbc60761edd", &mac128); |
| | 1046 | try htest.assertEqual("b36a16ef07c36d75a91f437502f24f545b8dfa88648ed116943c29fead3bf10c", &mac256); |
| 848 | } | 1047 | } |