diff --git a/lib/std/crypto/aes_ocb.zig b/lib/std/crypto/aes_ocb.zig index b5a0e24f1a..44a0fb2430 100644 --- a/lib/std/crypto/aes_ocb.zig +++ b/lib/std/crypto/aes_ocb.zig @@ -155,12 +155,12 @@ fn AesOcb(comptime Aes: anytype) type { xorWith(&offset, lx.star); var pad = offset; aes_enc_ctx.encrypt(&pad, &pad); - for (m[i * 16 ..], 0..) |x, j| { - c[i * 16 + j] = pad[j] ^ x; - } var e = [_]u8{0} ** 16; @memcpy(e[0..leftover], m[i * 16 ..][0..leftover]); e[leftover] = 0x80; + for (m[i * 16 ..], 0..) |x, j| { + c[i * 16 + j] = pad[j] ^ x; + } xorWith(&sum, e); } var e = xorBlocks(xorBlocks(sum, offset), lx.dol); @@ -354,3 +354,32 @@ test "AesOcb test vector 4" { try Aes128Ocb.decrypt(&m2, &c, tag, &ad, nonce, k); assert(mem.eql(u8, &m, &m2)); } + +test "AesOcb in-place encryption-decryption" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + + var k: [Aes128Ocb.key_length]u8 = undefined; + var nonce: [Aes128Ocb.nonce_length]u8 = undefined; + var tag: [Aes128Ocb.tag_length]u8 = undefined; + var m: [40]u8 = undefined; + var original_m: [m.len]u8 = undefined; + _ = try hexToBytes(&k, "000102030405060708090A0B0C0D0E0F"); + _ = try hexToBytes(&m, "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627"); + _ = try hexToBytes(&nonce, "BBAA9988776655443322110D"); + const ad = m; + + @memcpy(&original_m, &m); + + Aes128Ocb.encrypt(&m, &tag, &m, &ad, nonce, k); + + var expected_c: [m.len]u8 = undefined; + var expected_tag: [tag.len]u8 = undefined; + _ = try hexToBytes(&expected_tag, "ED07BA06A4A69483A7035490C5769E60"); + _ = try hexToBytes(&expected_c, "D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7A"); + + try testing.expectEqualSlices(u8, &expected_tag, &tag); + try testing.expectEqualSlices(u8, &expected_c, &m); + try Aes128Ocb.decrypt(&m, &m, tag, &ad, nonce, k); + + try testing.expectEqualSlices(u8, &original_m, &m); +}