| author | |
| committer | |
| log | 1d1e2b77802c75b3abb793599aefe4c772a7cfb8 |
| tree | 12a4aa03dc649a9d9448285328ecdc1f121b914d |
| parent | bfe3317059131ab552f7583b88d6bc82609d198c |
| parent | 5e00a0c9b5627195ae9b6e09a9be3e186d4f76d5 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/300524 files changed, 101 insertions(+), 0 deletions(-)
lib/std/crypto/aes.zig+30| ... | @@ -108,6 +108,36 @@ test "expand 128-bit key" { | ... | @@ -108,6 +108,36 @@ test "expand 128-bit key" { |
| 108 | } | 108 | } |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | test "invMixColumns" { | ||
| 112 | const key = [_]u8{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; | ||
| 113 | const enc_ctx = Aes128.initEnc(key); | ||
| 114 | const dec_ctx = Aes128.initDec(key); | ||
| 115 | |||
| 116 | for (1..10) |i| { | ||
| 117 | const enc_rk = enc_ctx.key_schedule.round_keys[10 - i]; | ||
| 118 | const dec_rk = dec_ctx.key_schedule.round_keys[i]; | ||
| 119 | const computed = enc_rk.invMixColumns(); | ||
| 120 | try testing.expectEqualSlices(u8, &dec_rk.toBytes(), &computed.toBytes()); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | test "BlockVec invMixColumns" { | ||
| 125 | const input = [_]u8{ | ||
| 126 | 0x5f, 0x57, 0xf7, 0x1d, 0x72, 0xf5, 0xbe, 0xb9, 0x64, 0xbc, 0x3b, 0xf9, 0x15, 0x92, 0x29, 0x1a, | ||
| 127 | 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, | ||
| 128 | }; | ||
| 129 | |||
| 130 | const vec2 = BlockVec(2).fromBytes(&input); | ||
| 131 | const result_vec = vec2.invMixColumns(); | ||
| 132 | const result_bytes = result_vec.toBytes(); | ||
| 133 | |||
| 134 | for (0..2) |i| { | ||
| 135 | const block = Block.fromBytes(input[i * 16 ..][0..16]); | ||
| 136 | const expected = block.invMixColumns().toBytes(); | ||
| 137 | try testing.expectEqualSlices(u8, &expected, result_bytes[i * 16 ..][0..16]); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 111 | test "expand 256-bit key" { | 141 | test "expand 256-bit key" { |
| 112 | const key = [_]u8{ | 142 | const key = [_]u8{ |
| 113 | 0x60, 0x3d, 0xeb, 0x10, | 143 | 0x60, 0x3d, 0xeb, 0x10, |
lib/std/crypto/aes/aesni.zig+22| ... | @@ -96,6 +96,17 @@ pub const Block = struct { | ... | @@ -96,6 +96,17 @@ pub const Block = struct { |
| 96 | return Block{ .repr = block1.repr | block2.repr }; | 96 | return Block{ .repr = block1.repr | block2.repr }; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | /// Apply the inverse MixColumns operation to a block. | ||
| 100 | pub fn invMixColumns(block: Block) Block { | ||
| 101 | return Block{ | ||
| 102 | .repr = asm ( | ||
| 103 | \\ vaesimc %[in], %[out] | ||
| 104 | : [out] "=x" (-> Repr), | ||
| 105 | : [in] "x" (block.repr), | ||
| 106 | ), | ||
| 107 | }; | ||
| 108 | } | ||
| 109 | |||
| 99 | /// Perform operations on multiple blocks in parallel. | 110 | /// Perform operations on multiple blocks in parallel. |
| 100 | pub const parallel = struct { | 111 | pub const parallel = struct { |
| 101 | const cpu = std.Target.x86.cpu; | 112 | const cpu = std.Target.x86.cpu; |
| ... | @@ -308,6 +319,17 @@ pub fn BlockVec(comptime blocks_count: comptime_int) type { | ... | @@ -308,6 +319,17 @@ pub fn BlockVec(comptime blocks_count: comptime_int) type { |
| 308 | } | 319 | } |
| 309 | return out; | 320 | return out; |
| 310 | } | 321 | } |
| 322 | |||
| 323 | /// Apply the inverse MixColumns operation to each block in the vector. | ||
| 324 | pub fn invMixColumns(block_vec: Self) Self { | ||
| 325 | var out_bytes: [blocks_count * 16]u8 = undefined; | ||
| 326 | const in_bytes = block_vec.toBytes(); | ||
| 327 | inline for (0..blocks_count) |i| { | ||
| 328 | const block = Block.fromBytes(in_bytes[i * 16 ..][0..16]); | ||
| 329 | out_bytes[i * 16 ..][0..16].* = block.invMixColumns().toBytes(); | ||
| 330 | } | ||
| 331 | return fromBytes(&out_bytes); | ||
| 332 | } | ||
| 311 | }; | 333 | }; |
| 312 | } | 334 | } |
| 313 | 335 |
lib/std/crypto/aes/armcrypto.zig+20| ... | @@ -99,6 +99,17 @@ pub const Block = struct { | ... | @@ -99,6 +99,17 @@ pub const Block = struct { |
| 99 | return Block{ .repr = block1.repr | block2.repr }; | 99 | return Block{ .repr = block1.repr | block2.repr }; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | /// Apply the inverse MixColumns operation to a block. | ||
| 103 | pub fn invMixColumns(block: Block) Block { | ||
| 104 | return Block{ | ||
| 105 | .repr = asm ( | ||
| 106 | \\ aesimc %[out].16b, %[in].16b | ||
| 107 | : [out] "=x" (-> Repr), | ||
| 108 | : [in] "x" (block.repr), | ||
| 109 | ), | ||
| 110 | }; | ||
| 111 | } | ||
| 112 | |||
| 102 | /// Perform operations on multiple blocks in parallel. | 113 | /// Perform operations on multiple blocks in parallel. |
| 103 | pub const parallel = struct { | 114 | pub const parallel = struct { |
| 104 | /// The recommended number of AES encryption/decryption to perform in parallel for the chosen implementation. | 115 | /// The recommended number of AES encryption/decryption to perform in parallel for the chosen implementation. |
| ... | @@ -275,6 +286,15 @@ pub fn BlockVec(comptime blocks_count: comptime_int) type { | ... | @@ -275,6 +286,15 @@ pub fn BlockVec(comptime blocks_count: comptime_int) type { |
| 275 | } | 286 | } |
| 276 | return out; | 287 | return out; |
| 277 | } | 288 | } |
| 289 | |||
| 290 | /// Apply the inverse MixColumns operation to each block in the vector. | ||
| 291 | pub fn invMixColumns(block_vec: Self) Self { | ||
| 292 | var out: Self = undefined; | ||
| 293 | inline for (0..native_words) |i| { | ||
| 294 | out.repr[i] = block_vec.repr[i].invMixColumns(); | ||
| 295 | } | ||
| 296 | return out; | ||
| 297 | } | ||
| 278 | }; | 298 | }; |
| 279 | } | 299 | } |
| 280 | 300 |
lib/std/crypto/aes/soft.zig+29| ... | @@ -265,6 +265,26 @@ pub const Block = struct { | ... | @@ -265,6 +265,26 @@ pub const Block = struct { |
| 265 | return Block{ .repr = x }; | 265 | return Block{ .repr = x }; |
| 266 | } | 266 | } |
| 267 | 267 | ||
| 268 | /// Apply the inverse MixColumns operation to a block. | ||
| 269 | pub fn invMixColumns(block: Block) Block { | ||
| 270 | var out: Repr = undefined; | ||
| 271 | inline for (0..4) |i| { | ||
| 272 | const col = block.repr[i]; | ||
| 273 | const b0: u8 = @truncate(col); | ||
| 274 | const b1: u8 = @truncate(col >> 8); | ||
| 275 | const b2: u8 = @truncate(col >> 16); | ||
| 276 | const b3: u8 = @truncate(col >> 24); | ||
| 277 | |||
| 278 | const r0 = mul(0x0e, b0) ^ mul(0x0b, b1) ^ mul(0x0d, b2) ^ mul(0x09, b3); | ||
| 279 | const r1 = mul(0x09, b0) ^ mul(0x0e, b1) ^ mul(0x0b, b2) ^ mul(0x0d, b3); | ||
| 280 | const r2 = mul(0x0d, b0) ^ mul(0x09, b1) ^ mul(0x0e, b2) ^ mul(0x0b, b3); | ||
| 281 | const r3 = mul(0x0b, b0) ^ mul(0x0d, b1) ^ mul(0x09, b2) ^ mul(0x0e, b3); | ||
| 282 | |||
| 283 | out[i] = @as(u32, r0) | (@as(u32, r1) << 8) | (@as(u32, r2) << 16) | (@as(u32, r3) << 24); | ||
| 284 | } | ||
| 285 | return Block{ .repr = out }; | ||
| 286 | } | ||
| 287 | |||
| 268 | /// Perform operations on multiple blocks in parallel. | 288 | /// Perform operations on multiple blocks in parallel. |
| 269 | pub const parallel = struct { | 289 | pub const parallel = struct { |
| 270 | /// The recommended number of AES encryption/decryption to perform in parallel for the chosen implementation. | 290 | /// The recommended number of AES encryption/decryption to perform in parallel for the chosen implementation. |
| ... | @@ -441,6 +461,15 @@ pub fn BlockVec(comptime blocks_count: comptime_int) type { | ... | @@ -441,6 +461,15 @@ pub fn BlockVec(comptime blocks_count: comptime_int) type { |
| 441 | } | 461 | } |
| 442 | return out; | 462 | return out; |
| 443 | } | 463 | } |
| 464 | |||
| 465 | /// Apply the inverse MixColumns operation to each block in the vector. | ||
| 466 | pub fn invMixColumns(block_vec: Self) Self { | ||
| 467 | var out: Self = undefined; | ||
| 468 | for (0..native_words) |i| { | ||
| 469 | out.repr[i] = block_vec.repr[i].invMixColumns(); | ||
| 470 | } | ||
| 471 | return out; | ||
| 472 | } | ||
| 444 | }; | 473 | }; |
| 445 | } | 474 | } |
| 446 | 475 |