Cybersecurity-Projects/PROJECTS/advanced/hsm-emulator/src/crypto/mac.zig

77 lines
2.3 KiB
Zig

// ©AngelaMos | 2026
// mac.zig
const std = @import("std");
const ck = @import("../ck.zig");
const hmac = std.crypto.auth.hmac.sha2;
pub const max_mac_len = hmac.HmacSha512.mac_length;
pub const Mac = union(enum) {
sha256: hmac.HmacSha256,
sha384: hmac.HmacSha384,
sha512: hmac.HmacSha512,
pub fn init(mech: ck.CK_MECHANISM_TYPE, key: []const u8) ?Mac {
return switch (mech) {
ck.CKM_SHA256_HMAC => .{ .sha256 = hmac.HmacSha256.init(key) },
ck.CKM_SHA384_HMAC => .{ .sha384 = hmac.HmacSha384.init(key) },
ck.CKM_SHA512_HMAC => .{ .sha512 = hmac.HmacSha512.init(key) },
else => null,
};
}
pub fn update(self: *Mac, data: []const u8) void {
switch (self.*) {
inline else => |*m| m.update(data),
}
}
pub fn macLen(self: *const Mac) usize {
return switch (self.*) {
inline else => |m| @TypeOf(m).mac_length,
};
}
pub fn finalInto(self: *Mac, out: []u8) void {
switch (self.*) {
inline else => |*m| {
const M = @TypeOf(m.*);
m.final(out[0..M.mac_length]);
},
}
}
};
pub fn macLenOf(mech: ck.CK_MECHANISM_TYPE) ?usize {
return switch (mech) {
ck.CKM_SHA256_HMAC => hmac.HmacSha256.mac_length,
ck.CKM_SHA384_HMAC => hmac.HmacSha384.mac_length,
ck.CKM_SHA512_HMAC => hmac.HmacSha512.mac_length,
else => null,
};
}
test "HMAC-SHA256 matches RFC 4231 test case 2" {
var m = Mac.init(ck.CKM_SHA256_HMAC, "Jefe").?;
m.update("what do ya want ");
m.update("for nothing?");
var out: [max_mac_len]u8 = undefined;
m.finalInto(&out);
const expect = [_]u8{
0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43,
};
try std.testing.expectEqual(@as(usize, 32), m.macLen());
try std.testing.expectEqualSlices(u8, &expect, out[0..32]);
}
test "macLenOf maps mechanisms and rejects non-HMAC" {
try std.testing.expectEqual(@as(?usize, 48), macLenOf(ck.CKM_SHA384_HMAC));
try std.testing.expectEqual(@as(?usize, 64), macLenOf(ck.CKM_SHA512_HMAC));
try std.testing.expect(macLenOf(ck.CKM_SHA256) == null);
}