| ... | @@ -130,21 +130,55 @@ fn AES(comptime keysize: usize) type { | ... | @@ -130,21 +130,55 @@ fn AES(comptime keysize: usize) type { |
| 130 | return struct { | 130 | return struct { |
| 131 | const Self = @This(); | 131 | const Self = @This(); |
| 132 | | 132 | |
| | 133 | pub const Encrypt = AESEncrypt(keysize); |
| | 134 | pub const Decrypt = AESDecrypt(keysize); |
| | 135 | |
| 133 | const nn = (keysize / 8) + 28; | 136 | const nn = (keysize / 8) + 28; |
| 134 | enc: [nn]u32, | 137 | enc: Encrypt, |
| 135 | dec: [nn]u32, | 138 | dec: Decrypt, |
| 136 | | 139 | |
| 137 | pub fn init(key: [keysize / 8]u8) Self { | 140 | pub fn init(key: [keysize / 8]u8) Self { |
| 138 | var ctx: Self = undefined; | 141 | var ctx: Self = undefined; |
| 139 | expandKey(&key, ctx.enc[0..], ctx.dec[0..]); | 142 | ctx.enc = Encrypt.init(key); |
| | 143 | ctx.dec = ctx.enc.toDecrypt(); |
| 140 | return ctx; | 144 | return ctx; |
| 141 | } | 145 | } |
| 142 | | 146 | |
| 143 | pub fn encrypt(ctx: Self, dst: []u8, src: []const u8) void { | 147 | pub fn encrypt(ctx: Self, dst: []u8, src: []const u8) void { |
| 144 | encryptBlock(ctx.enc[0..], dst, src); | 148 | ctx.enc.encrypt(dst, src); |
| 145 | } | 149 | } |
| 146 | pub fn decrypt(ctx: Self, dst: []u8, src: []const u8) void { | 150 | pub fn decrypt(ctx: Self, dst: []u8, src: []const u8) void { |
| 147 | decryptBlock(ctx.dec[0..], dst, src); | 151 | ctx.dec.decrypt(dst, src); |
| | 152 | } |
| | 153 | pub fn ctr(ctx: Self, dst: []u8, src: []const u8, iv: [16]u8) void { |
| | 154 | ctx.enc.ctr(dst, src, iv); |
| | 155 | } |
| | 156 | }; |
| | 157 | } |
| | 158 | |
| | 159 | fn AESEncrypt(comptime keysize: usize) type { |
| | 160 | return struct { |
| | 161 | const Self = @This(); |
| | 162 | |
| | 163 | const Decrypt = AESDecrypt(keysize); |
| | 164 | |
| | 165 | const nn = (keysize / 8) + 28; |
| | 166 | enc: [nn]u32, |
| | 167 | |
| | 168 | pub fn init(key: [keysize / 8]u8) Self { |
| | 169 | var ctx: Self = undefined; |
| | 170 | expandKeyEncrypt(&key, ctx.enc[0..]); |
| | 171 | return ctx; |
| | 172 | } |
| | 173 | |
| | 174 | pub fn toDecrypt(ctx: Self) Decrypt { |
| | 175 | var dec: Decrypt = undefined; |
| | 176 | expandKeyDecrypt(ctx.enc[0..], dec.dec[0..]); |
| | 177 | return dec; |
| | 178 | } |
| | 179 | |
| | 180 | pub fn encrypt(ctx: Self, dst: []u8, src: []const u8) void { |
| | 181 | encryptBlock(ctx.enc[0..], dst, src); |
| 148 | } | 182 | } |
| 149 | pub fn ctr(ctx: Self, dst: []u8, src: []const u8, iv: [16]u8) void { | 183 | pub fn ctr(ctx: Self, dst: []u8, src: []const u8, iv: [16]u8) void { |
| 150 | std.debug.assert(dst.len >= src.len); | 184 | std.debug.assert(dst.len >= src.len); |
| ... | @@ -163,6 +197,27 @@ fn AES(comptime keysize: usize) type { | ... | @@ -163,6 +197,27 @@ fn AES(comptime keysize: usize) type { |
| 163 | }; | 197 | }; |
| 164 | } | 198 | } |
| 165 | | 199 | |
| | 200 | fn AESDecrypt(comptime keysize: usize) type { |
| | 201 | return struct { |
| | 202 | const Self = @This(); |
| | 203 | |
| | 204 | const nn = (keysize / 8) + 28; |
| | 205 | dec: [nn]u32, |
| | 206 | |
| | 207 | pub fn init(key: [keysize / 8]u8) Self { |
| | 208 | var ctx: Self = undefined; |
| | 209 | var enc: [nn]u32 = undefined; |
| | 210 | expandKeyEncrypt(key[0..], enc[0..]); |
| | 211 | expandKeyDecrypt(enc[0..], ctx.dec[0..]); |
| | 212 | return ctx; |
| | 213 | } |
| | 214 | |
| | 215 | pub fn decrypt(ctx: Self, dst: []u8, src: []const u8) void { |
| | 216 | decryptBlock(ctx.dec[0..], dst, src); |
| | 217 | } |
| | 218 | }; |
| | 219 | } |
| | 220 | |
| 166 | test "ctr" { | 221 | test "ctr" { |
| 167 | // NIST SP 800-38A pp 55-58 | 222 | // NIST SP 800-38A pp 55-58 |
| 168 | { | 223 | { |
| ... | @@ -247,7 +302,7 @@ test "decrypt" { | ... | @@ -247,7 +302,7 @@ test "decrypt" { |
| 247 | } | 302 | } |
| 248 | | 303 | |
| 249 | // Key expansion algorithm. See FIPS-197, Figure 11. | 304 | // Key expansion algorithm. See FIPS-197, Figure 11. |
| 250 | fn expandKey(key: []const u8, enc: []u32, dec: []u32) void { | 305 | fn expandKeyEncrypt(key: []const u8, enc: []u32) void { |
| 251 | var i: usize = 0; | 306 | var i: usize = 0; |
| 252 | var nk = key.len / 4; | 307 | var nk = key.len / 4; |
| 253 | while (i < nk) : (i += 1) { | 308 | while (i < nk) : (i += 1) { |
| ... | @@ -262,9 +317,11 @@ fn expandKey(key: []const u8, enc: []u32, dec: []u32) void { | ... | @@ -262,9 +317,11 @@ fn expandKey(key: []const u8, enc: []u32, dec: []u32) void { |
| 262 | } | 317 | } |
| 263 | enc[i] = enc[i - nk] ^ t; | 318 | enc[i] = enc[i - nk] ^ t; |
| 264 | } | 319 | } |
| | 320 | } |
| 265 | | 321 | |
| | 322 | fn expandKeyDecrypt(enc: []const u32, dec: []u32) void { |
| | 323 | var i: usize = 0; |
| 266 | var n = enc.len; | 324 | var n = enc.len; |
| 267 | i = 0; | | |
| 268 | while (i < n) : (i += 4) { | 325 | while (i < n) : (i += 4) { |
| 269 | var ei = n - i - 4; | 326 | var ei = n - i - 4; |
| 270 | var j: usize = 0; | 327 | var j: usize = 0; |
| ... | @@ -308,7 +365,8 @@ test "expand key" { | ... | @@ -308,7 +365,8 @@ test "expand key" { |
| 308 | }; | 365 | }; |
| 309 | var enc: [exp_enc.len]u32 = undefined; | 366 | var enc: [exp_enc.len]u32 = undefined; |
| 310 | var dec: [exp_dec.len]u32 = undefined; | 367 | var dec: [exp_dec.len]u32 = undefined; |
| 311 | expandKey(key[0..], enc[0..], dec[0..]); | 368 | expandKeyEncrypt(key[0..], enc[0..]); |
| | 369 | expandKeyDecrypt(enc[0..], dec[0..]); |
| 312 | testing.expectEqualSlices(u32, exp_enc[0..], enc[0..]); | 370 | testing.expectEqualSlices(u32, exp_enc[0..], enc[0..]); |
| 313 | testing.expectEqualSlices(u32, exp_dec[0..], dec[0..]); | 371 | testing.expectEqualSlices(u32, exp_dec[0..], dec[0..]); |
| 314 | } | 372 | } |