| ... | @@ -49,54 +49,47 @@ fn AesGcmSiv(comptime Aes: anytype) type { | ... | @@ -49,54 +49,47 @@ fn AesGcmSiv(comptime Aes: anytype) type { |
| 49 | | 49 | |
| 50 | // Derive authentication and message keys per RFC 8452 Section 4 | 50 | // Derive authentication and message keys per RFC 8452 Section 4 |
| 51 | // Each encryption produces 16 bytes, but we only use first 8 bytes of each block | 51 | // Each encryption produces 16 bytes, but we only use first 8 bytes of each block |
| 52 | var key_block: [16]u8 = undefined; | 52 | |
| 53 | var cipher_out: [16]u8 = undefined; | | |
| 54 | | | |
| 55 | // Generate authentication key (128 bits = 2 * 8 bytes) | | |
| 56 | // Block 0: counter = 0 with nonce | | |
| 57 | mem.writeInt(u32, key_block[0..4], 0, .little); | | |
| 58 | key_block[4..16].* = nonce; | | |
| 59 | aes.encrypt(&cipher_out, &key_block); | | |
| 60 | @memcpy(auth_key[0..8], cipher_out[0..8]); | | |
| 61 | | | |
| 62 | // Block 1: counter = 1 with nonce | | |
| 63 | mem.writeInt(u32, key_block[0..4], 1, .little); | | |
| 64 | aes.encrypt(&cipher_out, &key_block); | | |
| 65 | @memcpy(auth_key[8..16], cipher_out[0..8]); | | |
| 66 | | | |
| 67 | // Generate message encryption key | | |
| 68 | if (key_length == 16) { | 53 | if (key_length == 16) { |
| 69 | // AES-128-GCM-SIV: 128-bit message key = 2 * 8 bytes | 54 | // AES-128-GCM-SIV: Process 4 blocks in parallel |
| 70 | // Block 2: counter = 2 with nonce | 55 | var key_blocks: [4 * 16]u8 = undefined; |
| 71 | mem.writeInt(u32, key_block[0..4], 2, .little); | 56 | var cipher_outs: [4 * 16]u8 = undefined; |
| 72 | aes.encrypt(&cipher_out, &key_block); | 57 | |
| 73 | @memcpy(message_key[0..8], cipher_out[0..8]); | 58 | // Set up all 4 blocks with counters 0-3 and nonce |
| 74 | | 59 | inline for (0..4) |i| { |
| 75 | // Block 3: counter = 3 with nonce | 60 | mem.writeInt(u32, key_blocks[i * 16 ..][0..4], @intCast(i), .little); |
| 76 | mem.writeInt(u32, key_block[0..4], 3, .little); | 61 | key_blocks[i * 16 + 4 .. i * 16 + 16].* = nonce; |
| 77 | aes.encrypt(&cipher_out, &key_block); | 62 | } |
| 78 | @memcpy(message_key[8..16], cipher_out[0..8]); | 63 | |
| | 64 | // Encrypt all 4 blocks in parallel |
| | 65 | aes.encryptWide(4, &cipher_outs, &key_blocks); |
| | 66 | |
| | 67 | // Extract the key material (first 8 bytes of each block) |
| | 68 | @memcpy(auth_key[0..8], cipher_outs[0..8]); |
| | 69 | @memcpy(auth_key[8..16], cipher_outs[16..24]); |
| | 70 | @memcpy(message_key[0..8], cipher_outs[32..40]); |
| | 71 | @memcpy(message_key[8..16], cipher_outs[48..56]); |
| 79 | } else { | 72 | } else { |
| 80 | // AES-256-GCM-SIV: 256-bit message key = 4 * 8 bytes | 73 | // AES-256-GCM-SIV: Process 6 blocks in parallel |
| 81 | // Block 2: counter = 2 with nonce | 74 | var key_blocks: [6 * 16]u8 = undefined; |
| 82 | mem.writeInt(u32, key_block[0..4], 2, .little); | 75 | var cipher_outs: [6 * 16]u8 = undefined; |
| 83 | aes.encrypt(&cipher_out, &key_block); | 76 | |
| 84 | @memcpy(message_key[0..8], cipher_out[0..8]); | 77 | // Set up all 6 blocks with counters 0-5 and nonce |
| 85 | | 78 | inline for (0..6) |i| { |
| 86 | // Block 3: counter = 3 with nonce | 79 | mem.writeInt(u32, key_blocks[i * 16 ..][0..4], @intCast(i), .little); |
| 87 | mem.writeInt(u32, key_block[0..4], 3, .little); | 80 | key_blocks[i * 16 + 4 .. i * 16 + 16].* = nonce; |
| 88 | aes.encrypt(&cipher_out, &key_block); | 81 | } |
| 89 | @memcpy(message_key[8..16], cipher_out[0..8]); | 82 | |
| 90 | | 83 | // Encrypt all 6 blocks in parallel |
| 91 | // Block 4: counter = 4 with nonce | 84 | aes.encryptWide(6, &cipher_outs, &key_blocks); |
| 92 | mem.writeInt(u32, key_block[0..4], 4, .little); | 85 | |
| 93 | aes.encrypt(&cipher_out, &key_block); | 86 | // Extract the key material (first 8 bytes of each block) |
| 94 | @memcpy(message_key[16..24], cipher_out[0..8]); | 87 | @memcpy(auth_key[0..8], cipher_outs[0..8]); |
| 95 | | 88 | @memcpy(auth_key[8..16], cipher_outs[16..24]); |
| 96 | // Block 5: counter = 5 with nonce | 89 | @memcpy(message_key[0..8], cipher_outs[32..40]); |
| 97 | mem.writeInt(u32, key_block[0..4], 5, .little); | 90 | @memcpy(message_key[8..16], cipher_outs[48..56]); |
| 98 | aes.encrypt(&cipher_out, &key_block); | 91 | @memcpy(message_key[16..24], cipher_outs[64..72]); |
| 99 | @memcpy(message_key[24..32], cipher_out[0..8]); | 92 | @memcpy(message_key[24..32], cipher_outs[80..88]); |
| 100 | } | 93 | } |
| 101 | } | 94 | } |
| 102 | | 95 | |