A context to perform encryption using the standard AES key schedule.
pub fn AesEncryptCtx(comptime Aes: type) type
pub fn AesEncryptCtx(comptime Aes: type) type {
std.debug.assert(Aes.key_bits == 128 or Aes.key_bits == 256);
const rounds = Aes.rounds;
return struct {
const Self = @This();
pub const block = Aes.block;
pub const block_length = block.block_length;
key_schedule: KeySchedule(Aes),
/// Create a new encryption context with the given key.
pub fn init(key: [Aes.key_bits / 8]u8) Self {
const key_schedule = KeySchedule(Aes).expandKey(key);
return Self{
.key_schedule = key_schedule,
};
}
/// Encrypt a single block.
pub fn encrypt(ctx: Self, dst: *[16]u8, src: *const [16]u8) void {
const round_keys = ctx.key_schedule.round_keys;
var t = Block.fromBytes(src).xorBlocks(round_keys[0]);
comptime var i = 1;
if (side_channels_mitigations == .full) {
inline while (i < rounds) : (i += 1) {
t = t.encrypt(round_keys[i]);
}
} else {
inline while (i < 5) : (i += 1) {
t = t.encrypt(round_keys[i]);
}
inline while (i < rounds - 1) : (i += 1) {
t = t.encryptUnprotected(round_keys[i]);
}
t = t.encrypt(round_keys[i]);
}
t = t.encryptLast(round_keys[rounds]);
dst.* = t.toBytes();
}
/// Encrypt+XOR a single block.
pub fn xor(ctx: Self, dst: *[16]u8, src: *const [16]u8, counter: [16]u8) void {
const round_keys = ctx.key_schedule.round_keys;
var t = Block.fromBytes(&counter).xorBlocks(round_keys[0]);
comptime var i = 1;
if (side_channels_mitigations == .full) {
inline while (i < rounds) : (i += 1) {
t = t.encrypt(round_keys[i]);
}
} else {
inline while (i < 5) : (i += 1) {
t = t.encrypt(round_keys[i]);
}
inline while (i < rounds - 1) : (i += 1) {
t = t.encryptUnprotected(round_keys[i]);
}
t = t.encrypt(round_keys[i]);
}
t = t.encryptLast(round_keys[rounds]);
dst.* = t.xorBytes(src);
}
/// Encrypt multiple blocks, possibly leveraging parallelization.
pub fn encryptWide(ctx: Self, comptime count: usize, dst: *[16 * count]u8, src: *const [16 * count]u8) void {
var i: usize = 0;
while (i < count) : (i += 1) {
ctx.encrypt(dst[16 * i .. 16 * i + 16][0..16], src[16 * i .. 16 * i + 16][0..16]);
}
}
/// Encrypt+XOR multiple blocks, possibly leveraging parallelization.
pub fn xorWide(ctx: Self, comptime count: usize, dst: *[16 * count]u8, src: *const [16 * count]u8, counters: [16 * count]u8) void {
var i: usize = 0;
while (i < count) : (i += 1) {
ctx.xor(dst[16 * i .. 16 * i + 16][0..16], src[16 * i .. 16 * i + 16][0..16], counters[16 * i .. 16 * i + 16][0..16].*);
}
}
};
}