authorgravatar for luke.champine@gmail.comlukechampine <luke.champine@gmail.com> 2019-11-04 17:07:14-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-05 11:33:11-05:00
log3d907b29433bf722f8c0ca188d1144f9ebdbfd55
treefc275c56e1597b740cf1c9e7ef57cd76359cba52
parent1657bead463656a0a38eaf49b60d8c651e5403ae

crypto: Add support for AES-CTR


1 files changed, 47 insertions(+), 0 deletions(-)

lib/std/crypto/aes.zig+47
...@@ -115,6 +115,14 @@ pub fn decryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {...@@ -115,6 +115,14 @@ pub fn decryptBlock(xk: []const u32, dst: []u8, src: []const u8) void {
115 mem.writeIntSliceBig(u32, dst[12..16], s3);115 mem.writeIntSliceBig(u32, dst[12..16], s3);
116}116}
117117
118fn xorBytes(dst: []u8, a: []const u8, b: []const u8) usize {
119 var n = std.math.min(dst.len, std.math.min(a.len, b.len));
120 for (dst[0..n]) |_, i| {
121 dst[i] = a[i] ^ b[i];
122 }
123 return n;
124}
125
118pub const AES128 = AES(128);126pub const AES128 = AES(128);
119pub const AES256 = AES(256);127pub const AES256 = AES(256);
120128
...@@ -138,9 +146,48 @@ fn AES(comptime keysize: usize) type {...@@ -138,9 +146,48 @@ fn AES(comptime keysize: usize) type {
138 pub fn decrypt(ctx: Self, dst: []u8, src: []const u8) void {146 pub fn decrypt(ctx: Self, dst: []u8, src: []const u8) void {
139 decryptBlock(ctx.dec[0..], dst, src);147 decryptBlock(ctx.dec[0..], dst, src);
140 }148 }
149 pub fn ctr(ctx: Self, dst: []u8, src: []const u8, iv: [16]u8) void {
150 std.debug.assert(dst.len >= src.len);
151
152 var keystream: [16]u8 = undefined;
153 var ctrbuf = iv;
154 var n: usize = 0;
155 while (n < src.len) {
156 ctx.encrypt(keystream[0..], ctrbuf[0..]);
157 var ctr_i = std.mem.readIntSliceBig(u128, ctrbuf[0..]);
158 std.mem.writeIntSliceBig(u128, ctrbuf[0..], ctr_i +% 1);
159
160 n += xorBytes(dst[n..], src[n..], keystream);
161 }
162 }
141 };163 };
142}164}
143165
166test "ctr" {
167 // NIST SP 800-38A pp 55-58
168 {
169 const key = [_]u8{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
170 const iv = [_]u8{ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
171 const in = [_]u8{
172 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
173 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
174 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
175 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
176 };
177 const exp_out = [_]u8{
178 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce,
179 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff,
180 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab,
181 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee,
182 };
183
184 var out: [exp_out.len]u8 = undefined;
185 var aes = AES128.init(key);
186 aes.ctr(out[0..], in[0..], iv);
187 testing.expectEqualSlices(u8, exp_out[0..], out[0..]);
188 }
189}
190
144test "encrypt" {191test "encrypt" {
145 // Appendix B192 // Appendix B
146 {193 {