srctree

Gregory Mullen parent 64eddc2a 2166eb83
unworking Finished message :<

inlinesplit
src/cipher.zig added: 74, removed: 63, total 11
@@ -130,7 +130,8 @@ pub const Suites = enum(u16) {
TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAE,
 
/// TODO
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC014,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028,
 
///Current Supported
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9,
@@ -245,7 +246,6 @@ pub const AnyAES = struct {
const seed = "master secret" ++ ctx.cli_random.? ++ ctx.srv_random.?;
 
const PRF = Sha384;
 
var a1: [48]u8 = undefined;
PRF.create(&a1, seed, &premaster);
var p1: [48]u8 = undefined;
@@ -281,7 +281,7 @@ pub const AnyAES = struct {
try r.readNoEof(&ctx.cipher.suite.aes.srv_dh.?.public_key);
 
// TODO verify signature
 
ctx.cipher.suite.aes.cli_dh = try Cipher.X25519.KeyPair.create(null);
ctx.cipher.suite.aes.material = try buildKeyMaterial(ctx);
}
 
@@ -480,6 +480,7 @@ pub const EllipticCurve = struct {
 
// TODO verify signature
 
ctx.cipher.suite.ecc.cli_dh = try Cipher.X25519.KeyPair.create(null);
ctx.cipher.suite.ecc.material = try buildKeyMaterial(ctx);
}
 
 
src/context.zig added: 74, removed: 63, total 11
@@ -51,3 +51,7 @@ pub fn initCrypto(a: Allocator) ConnCtx {
pub fn initServer() ConnCtx {
return .{};
}
 
pub fn raze(ctx: ConnCtx) void {
ctx.handshake_record.deinit();
}
 
src/handshake.zig added: 74, removed: 63, total 11
@@ -30,6 +30,8 @@ const Extension = Extensions.Extension;
const fixedBufferStream = std.io.fixedBufferStream;
const print = std.debug.print;
 
const HmacSha384 = std.crypto.auth.hmac.sha2.HmacSha384;
 
var csprng = std.Random.ChaCha.init([_]u8{0} ** 32);
 
pub const Compression = enum(u8) {
@@ -139,12 +141,14 @@ pub const Finished = struct {
.aes => |aes| aes.material.master,
else => unreachable,
};
var hash: [48]u8 = undefined;
std.crypto.hash.sha2.Sha384.hash(ctx.handshake_record.items, hash[0..], .{});
 
var sha = std.crypto.auth.hmac.sha2.HmacSha384.init(&master);
sha.update("client finished");
sha.update(ctx.handshake_record.items);
var verify: [48]u8 = undefined;
sha.final(&verify);
const seed = "client finished" ++ hash;
var a1: [48]u8 = undefined;
HmacSha384.create(&a1, seed, &master);
var verified: [48]u8 = undefined;
HmacSha384.create(&verified, a1 ++ seed, &master);
 
//sha = std.crypto.auth.hmac.sha2.HmacSha384.init(&master);
//sha.update(&verify);
@@ -152,11 +156,12 @@ pub const Finished = struct {
//sha.update(ctx.handshake_record.items);
//sha.final(&verify);
 
// TODO do I need to zero this struct?
defer ctx.handshake_record.deinit();
print("hash {}\n", .{
std.fmt.fmtSliceHexLower(&verified),
});
 
try w.writeAll(&verify);
return 48;
try w.writeAll(verified[0..12]);
return 12;
}
};
 
@@ -235,11 +240,9 @@ pub const ServerKeyExchange = struct {
pub fn unpack(buffer: []const u8, ctx: *ConnCtx) !ServerKeyExchange {
switch (ctx.cipher.suite) {
.ecc => {
ctx.cipher.suite.ecc.cli_dh = try Cipher.X25519.KeyPair.create(null);
try Cipher.EllipticCurve.unpackKeyExchange(buffer, ctx);
},
.aes => {
ctx.cipher.suite.aes.cli_dh = try Cipher.X25519.KeyPair.create(null);
try Cipher.AnyAES.unpackKeyExchange(buffer, ctx);
},
else => unreachable,
@@ -391,8 +394,8 @@ pub const Handshake = struct {
 
try w.writeByte(@intFromEnum(hs.msg_type));
try w.writeInt(u24, @truncate(len), std.builtin.Endian.big);
if (hs.body == .client_hello)
try ctx.handshake_record.appendSlice(buffer[0 .. len + 4]);
print("pack append\n", .{});
try ctx.handshake_record.appendSlice(buffer[0 .. len + 4]);
return len + 4;
}
 
@@ -402,6 +405,7 @@ pub const Handshake = struct {
 
// TODO choose real assert length
std.debug.assert(len < 1024);
print("unpack append\n", .{});
try ctx.handshake_record.appendSlice(buffer[0 .. len + 4]);
const hsbuf = buffer[4..][0..len];
return .{
 
src/root.zig added: 74, removed: 63, total 11
@@ -76,10 +76,6 @@ pub const TLSRecord = struct {
var clear_text: [0x1000]u8 = undefined;
var len = try record.packFragment(&clear_text, ctx);
 
print("clear buffer {}\n", .{
std.fmt.fmtSliceHexLower(clear_text[0..len]),
});
 
switch (ctx.cipher.suite) {
.ecc => {
const empty: [0]u8 = undefined;
@@ -99,38 +95,40 @@ pub const TLSRecord = struct {
var mac_fba = fixedBufferStream(&mac_buf);
var mac_w = mac_fba.writer().any();
try mac_w.writeInt(u64, @truncate(ctx.cipher.sequence), .big);
try mac_w.writeAll(&[_]u8{ 22, 3, 3 });
try mac_w.writeInt(u16, @truncate(len), .big);
try mac_w.writeAll(clear_text[0..len]);
const mac_len = try mac_fba.getPos();
 
const mac_out: *[48]u8 = clear_text[len..][0..48];
const mac_text = mac_buf[0 .. 8 + len];
const mac_text = mac_buf[0..mac_len];
std.crypto.auth.hmac.sha2.HmacSha384.create(mac_out, mac_text, &aes.material.cli_mac);
print("mac buf {any}\n", .{mac_text});
len += 48;
}
 
var aes_ctx = std.crypto.core.aes.Aes256.initEnc(aes.material.cli_key);
const add = 16 - (len % 16);
if (add != 0) {
@memset(clear_text[len..][0..add], 0);
@memset(clear_text[len..][0..add], @truncate(add - 1));
}
len += add;
try w.writeAll(aes.material.cli_iv[0..]);
 
var xord: [16]u8 = aes.material.cli_iv;
print("xor pre {any}\n", .{xord});
for (0..len / 16) |i| {
var clear: [16]u8 = clear_text[i * 16 ..][0..16].*;
var cipher: [16]u8 = undefined;
for (clear[0..], xord[0..]) |*c, xr| c.* ^= xr;
aes_ctx.encrypt(cipher[0..], clear[0..]);
var xclear: [16]u8 = undefined;
for (xclear[0..], clear[0..], xord[0..]) |*xc, c, xr| xc.* = c ^ xr;
aes_ctx.encrypt(cipher[0..], xclear[0..]);
@memcpy(xord[0..16], cipher[0..16]);
print("{} {any}\n {any}\n", .{ i, clear, cipher });
//print("{} {any}\n {any}\n {any}\n", .{ i, clear, xclear, cipher });
try w.writeAll(cipher[0..]);
}
},
else => unreachable,
}
const enc_len = try fba.getPos();
const enc_len = try fba.getPos() - 5;
return try record.packHeader(buffer, enc_len);
}
 
@@ -192,21 +190,21 @@ pub const ChangeCipherSpec = struct {
}
};
 
test "Handshake ClientHello" {
var buffer = [_]u8{0} ** 0x400;
 
var ctx = ConnCtx.initClient(std.testing.allocator);
const client_hello = Handshake.ClientHello.init(ctx);
const record = TLSRecord{
.kind = .{
.handshake = try Handshake.Handshake.wrap(client_hello),
},
};
 
const len = try record.pack(&buffer, &ctx);
_ = len;
defer ctx.handshake_record.deinit();
}
//test "Handshake ClientHello" {
// var buffer = [_]u8{0} ** 0x400;
//
// var ctx = ConnCtx.initClient(std.testing.allocator);
// const client_hello = Handshake.ClientHello.init(ctx);
// const record = TLSRecord{
// .kind = .{
// .handshake = try Handshake.Handshake.wrap(client_hello),
// },
// };
//
// const len = try record.pack(&buffer, &ctx);
// _ = len;
// defer ctx.handshake_record.deinit();
//}
 
fn startHandshakeCustomSuites(conn: std.net.Stream, suites: []const Cipher.Suites) !ConnCtx {
var buffer = [_]u8{0} ** 0x1000;
@@ -262,7 +260,7 @@ fn buildServer(data: []const u8, ctx: *ConnCtx) !void {
switch (hs.body) {
.server_hello => |hello| {
if (false) print("server hello {}\n", .{@TypeOf(hello)});
if (true) print("srv selected suite {any}\n", .{ctx.cipher});
if (false) print("srv selected suite {any}\n", .{ctx.cipher});
//if (ctx.cipher.suite != .ecc) {
// return error.UnexpectedCipherSuite;
//}
@@ -325,21 +323,23 @@ fn completeClient(conn: std.net.Stream, ctx: *ConnCtx) !void {
},
};
const fin_len = try fin_record.encrypt(&buffer, ctx);
if (true) print("fin: {any}\n", .{
std.fmt.fmtSliceHexLower(buffer[0..fin_len]),
});
print("client key {}\n", .{
std.fmt.fmtSliceHexLower(&ctx.cipher.suite.aes.material.cli_key),
});
print("client mac {}\n", .{
std.fmt.fmtSliceHexLower(&ctx.cipher.suite.aes.material.cli_mac),
});
print("client iv {}\n", .{
std.fmt.fmtSliceHexLower(buffer[5..][0..16]),
});
print("client msg {}\n", .{
std.fmt.fmtSliceHexLower(buffer[5..][16..][0 .. fin_len - 5 - 16]),
});
if (false) {
print("fin: {any}\n", .{
std.fmt.fmtSliceHexLower(buffer[0..fin_len]),
});
print("clientiv='{}'\n", .{
std.fmt.fmtSliceHexLower(buffer[5..][0..16]),
});
print("clientkey='{}'\n", .{
std.fmt.fmtSliceHexLower(&ctx.cipher.suite.aes.material.cli_key),
});
print("clientmac='{}'\n", .{
std.fmt.fmtSliceHexLower(&ctx.cipher.suite.aes.material.cli_mac),
});
print("clientmsg='{}'\n", .{
std.fmt.fmtSliceHexLower(buffer[5..][16..][0 .. fin_len - 5 - 16]),
});
}
const finout = try conn.write(buffer[0..fin_len]);
if (false) print("fin delivered, {}\n", .{finout});
 
@@ -347,6 +347,8 @@ fn completeClient(conn: std.net.Stream, ctx: *ConnCtx) !void {
if (false) print("sin: {any}\n", .{r_buf[0..num2]});
const sin2 = try TLSRecord.unpack(r_buf[0..num2], ctx);
if (false) print("server thing {}\n", .{sin2});
 
ctx.raze();
}
 
fn fullHandshake(conn: std.net.Stream) !void {