srctree

Gregory Mullen parent 9daaf78c e4a0cb35
refactor into cipher.zig

filename was Deleted added: 202, removed: 197, total 5
@@ -0,0 +1,149 @@
const std = @import("std");
 
const print = std.debug.print;
const fixedBufferStream = std.io.fixedBufferStream;
 
pub const Cipher = @This();
 
suite: union(enum) {
invalid: void,
ecc: EllipticCurve,
} = .{ .invalid = {} },
 
pub const Suites = enum(u16) {
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A,
TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAD,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B,
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAA,
TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D,
TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030,
TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E,
TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036,
TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068,
TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010,
TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031,
TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F,
TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037,
TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069,
TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B,
TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034,
TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C,
TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A,
TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D,
TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018,
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9,
TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAC,
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8,
TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAB,
TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAE,
};
 
pub const EllipticCurve = struct {
curve: Curves = .{ .invalid = {} },
 
clt_key_mat: ?std.crypto.dh.X25519.KeyPair = null,
srv_key_mat: ?std.crypto.dh.X25519.KeyPair = null,
 
pub const Curves = union(CurveType) {
invalid: void,
explicit_prime: ExplicitPrime,
explicit_char2: ExplicitChar2,
named_curve: NamedCurve,
};
 
pub const CurveType = enum(u8) {
invalid = 0,
explicit_prime = 1,
explicit_char2 = 2,
named_curve = 3,
 
pub fn fromByte(t: u8) !CurveType {
return switch (t) {
inline 0...3 => |i| @enumFromInt(i),
else => return error.InvalidECCCurveType,
};
}
};
 
pub const ExplicitPrime = struct {};
pub const ExplicitChar2 = struct {};
pub const NamedCurve = struct {};
 
pub fn init() EllipticCurve {
return .{};
}
 
fn packNamedCurve(_: EllipticCurve, buffer: []u8) !usize {
var fba = fixedBufferStream(buffer);
const w = fba.writer().any();
 
//try w.writeByte(@intFromEnum(ecc.curve));
//// TODO Plz doing the fix here
//try w.writeByte(204);
//try w.writeByte(169);
 
var empty: [32]u8 = std.mem.zeroes([32]u8);
 
@memcpy(&empty, "thisisagoodblob!" ** 2);
@memcpy(&empty, "thisisagoodblob!" ** 2);
var chacha = std.Random.ChaCha.init(empty);
var charand = chacha.random();
charand.bytes(&empty);
 
const key_material = try std.crypto.dh.X25519.KeyPair.create(empty);
 
//try w.writeByte(@intFromEnum(cke.pve));
//try w.writeInt(u16, @truncate(key_material.public_key.len), std.builtin.Endian.big);
try w.writeInt(u8, @truncate(key_material.public_key.len), std.builtin.Endian.big);
try w.writeAll(&key_material.public_key);
return 1 + key_material.public_key.len;
}
 
pub fn packKeyExchange(ecc: EllipticCurve, buffer: []u8) !usize {
return switch (ecc.curve) {
.named_curve => try ecc.packNamedCurve(buffer),
else => unreachable,
};
}
 
pub fn unpackKeyExchange(buffer: []const u8) !EllipticCurve {
var fba = fixedBufferStream(buffer);
const r = fba.reader().any();
 
const curve_type = try CurveType.fromByte(try r.readByte());
//print("named curve {} {}\n", .{ try r.readByte(), try r.readByte() });
//print("full buffer {any}\n", .{buffer[0..4]});
//print("full buffer {any}\n", .{buffer[4..][0..32]});
//print("full buffer {any}\n", .{buffer[36..]});
return .{
.curve = switch (curve_type) {
.named_curve => .{ .named_curve = .{} },
else => return error.UnsupportedCurve,
},
};
}
};
 
pub const Type = enum {
stream,
block,
aead,
};
 
const GenericStreamCipher = struct {};
const GenericBlockCipher = struct {};
const GenericAEADCipher = struct {};
 
const ClientECDH = struct {
_key_material: [255]u8 = [_]u8{8} ** 255,
// 1..255
point: []u8 = &[0]u8{},
};
 
src/extensions.zig added: 202, removed: 197, total 5
@@ -113,6 +113,30 @@ const SignatureAlgos = enum(u8) {
// 224-255 Private Use
};
 
//const HashAlgorithm = enum(u8) {
// none = 0,
// md5 = 1,
// sha1 = 2,
// sha224 = 3,
// sha256 = 4,
// sha384 = 5,
//
// sha512 = 6,
//};
//
//const SignatureAlgorithm = enum(u8) {
// anonymous = 0,
// rsa = 1,
// dsa = 2,
// ecdsa = 3,
//};
//
//const SignatureAndHashAlgorithm = struct {
// hash: HashAlgorithm,
// signature: SignatureAlgorithm,
//};
//
 
pub const SignatureAlgorithms = struct {
const EXT_TYPE: u16 = 0x000D;
pub fn packUntyped(ptr: *anyopaque, buffer: []u8) !usize {
 
src/handshake.zig added: 202, removed: 197, total 5
@@ -16,13 +16,15 @@
///
///
const std = @import("std");
 
const State = @import("state.zig");
const Protocol = @import("protocol.zig");
const root = @import("root.zig");
const Extensions = @import("extensions.zig");
const Cipher = @import("cipher.zig");
 
const Random = root.Random;
const SessionID = root.SessionID;
const CipherSuites = root.CipherSuites;
const Extensions = @import("extensions.zig");
const Extension = Extensions.Extension;
 
const fixedBufferStream = std.io.fixedBufferStream;
@@ -34,12 +36,14 @@ pub const Compression = enum(u8) {
null = 0,
};
 
const HelloRequest = struct {};
 
/// Client Section
pub const ClientHello = struct {
version: Protocol.Version,
random: Random,
session_id: SessionID,
ciphers: []const CipherSuites = &[0]CipherSuites{},
ciphers: []const Cipher.Suites = &[0]Cipher.Suites{},
compression: Compression,
extensions: []const Extension = &[0]Extension{},
 
@@ -48,11 +52,11 @@ pub const ClientHello = struct {
Extensions.SignatureAlgorithms,
};
 
pub const SupportedSuiteList = [_]CipherSuites{
CipherSuites.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
CipherSuites.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
//CipherSuites.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
//CipherSuites.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
pub const SupportedSuiteList = [_]Cipher.Suites{
Cipher.Suites.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
Cipher.Suites.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
//Cipher.Suites.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
//Cipher.Suites.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
};
pub const length = @sizeOf(ClientHello);
 
@@ -116,12 +120,12 @@ pub const ClientKeyExchange = struct {
/// specified next
explicit = 1,
} = .explicit,
cipher: *const root.Cipher,
cipher: *const Cipher,
 
pub fn init() !ClientKeyExchange {
const cke = ClientKeyExchange{
.cipher = &.{
.suite = .{ .ecc = root.EllipticCurveCipher{
.suite = .{ .ecc = Cipher.EllipticCurve{
.curve = .{ .named_curve = .{} },
} },
},
@@ -159,7 +163,7 @@ pub const ServerHello = struct {
version: Protocol.Version,
random: Random,
session_id: SessionID,
cipher: CipherSuites,
cipher: Cipher.Suites,
compression: Compression,
extensions: []const Extension,
 
@@ -183,7 +187,8 @@ pub const ServerHello = struct {
 
// cipers
//const cbytes: u16 = try r.readInt(u16, std.builtin.Endian.big);
const cipher: CipherSuites = @enumFromInt(try r.readInt(u16, .big));
// FIXME
const cipher: Cipher.Suites = @enumFromInt(try r.readInt(u16, .big));
 
// compression
if (try r.readByte() != 0) return error.InvalidCompression;
@@ -210,7 +215,7 @@ pub const ServerHello = struct {
 
pub const ServerKeyExchange = struct {
buffer: []const u8,
cipher: *const root.Cipher,
cipher: *const Cipher,
 
pub fn pack(_: ServerKeyExchange, _: []u8) !usize {
return 0;
@@ -220,7 +225,7 @@ pub const ServerKeyExchange = struct {
pub fn unpack(buffer: []const u8, sess: *State) !ServerKeyExchange {
switch (sess.cipher.suite) {
.ecc => {
sess.cipher.suite.ecc = try root.EllipticCurveCipher.unpackKeyExchange(buffer);
sess.cipher.suite.ecc = try Cipher.EllipticCurve.unpackKeyExchange(buffer);
},
else => unreachable,
}
@@ -255,6 +260,7 @@ pub const Certificate = struct {
};
}
};
 
pub const CertificateRequest = struct {
buffer: []const u8,
session: *State,
 
src/root.zig added: 202, removed: 197, total 5
@@ -13,6 +13,7 @@ const Extension = Extensions.Extension;
const Protocol = @import("protocol.zig");
const State = @import("state.zig");
const Handshake = @import("handshake.zig");
const Cipher = @import("cipher.zig");
 
var csprng = std.Random.ChaCha.init([_]u8{0} ** 32);
 
@@ -109,134 +110,6 @@ pub const BulkCipherAlgorithm = struct {};
pub const MACAlgorithm = struct {};
pub const CompressionMethod = ?void;
 
pub const EllipticCurveCipher = struct {
curve: Curves = .{ .invalid = {} },
key_material: ?std.crypto.dh.X25519.KeyPair = null,
 
pub const Curves = union(CurveType) {
invalid: void,
explicit_prime: ExplicitPrime,
explicit_char2: ExplicitChar2,
named_curve: NamedCurve,
};
 
pub const CurveType = enum(u8) {
invalid = 0,
explicit_prime = 1,
explicit_char2 = 2,
named_curve = 3,
 
pub fn fromByte(t: u8) !CurveType {
return switch (t) {
inline 0...3 => |i| @enumFromInt(i),
else => return error.InvalidECCCurveType,
};
}
};
 
pub const ExplicitPrime = struct {};
pub const ExplicitChar2 = struct {};
pub const NamedCurve = struct {};
 
fn packNamedCurve(_: EllipticCurveCipher, buffer: []u8) !usize {
var fba = fixedBufferStream(buffer);
const w = fba.writer().any();
 
//try w.writeByte(@intFromEnum(ecc.curve));
//// TODO Plz doing the fix here
//try w.writeByte(204);
//try w.writeByte(169);
 
var empty: [32]u8 = std.mem.zeroes([32]u8);
 
@memcpy(&empty, "thisisagoodblob!" ** 2);
@memcpy(&empty, "thisisagoodblob!" ** 2);
var chacha = std.Random.ChaCha.init(empty);
var charand = chacha.random();
charand.bytes(&empty);
 
const key_material = try std.crypto.dh.X25519.KeyPair.create(empty);
 
//try w.writeByte(@intFromEnum(cke.pve));
//try w.writeInt(u16, @truncate(key_material.public_key.len), std.builtin.Endian.big);
try w.writeInt(u8, @truncate(key_material.public_key.len), std.builtin.Endian.big);
try w.writeAll(&key_material.public_key);
return 1 + key_material.public_key.len;
}
 
pub fn packKeyExchange(ecc: EllipticCurveCipher, buffer: []u8) !usize {
return switch (ecc.curve) {
.named_curve => try ecc.packNamedCurve(buffer),
else => unreachable,
};
}
 
pub fn unpackKeyExchange(buffer: []const u8) !EllipticCurveCipher {
var fba = fixedBufferStream(buffer);
const r = fba.reader().any();
 
const curve_type = try CurveType.fromByte(try r.readByte());
//print("named curve {} {}\n", .{ try r.readByte(), try r.readByte() });
//print("full buffer {any}\n", .{buffer[0..4]});
//print("full buffer {any}\n", .{buffer[4..][0..32]});
//print("full buffer {any}\n", .{buffer[36..]});
return .{
.curve = switch (curve_type) {
.named_curve => .{ .named_curve = .{} },
else => return error.UnsupportedCurve,
},
};
}
};
 
pub const Cipher = struct {
suite: union(enum) {
invalid: void,
ecc: EllipticCurveCipher,
} = .{ .invalid = {} },
};
 
pub const CipherType = enum {
stream,
block,
aead,
};
 
const GenericStreamCipher = struct {};
const GenericBlockCipher = struct {};
const GenericAEADCipher = struct {};
 
const HelloRequest = struct {};
 
const ClientECDH = struct {
_key_material: [255]u8 = [_]u8{8} ** 255,
// 1..255
point: []u8 = &[0]u8{},
};
 
const HashAlgorithm = enum(u8) {
none = 0,
md5 = 1,
sha1 = 2,
sha224 = 3,
sha256 = 4,
sha384 = 5,
 
sha512 = 6,
};
 
const SignatureAlgorithm = enum(u8) {
anonymous = 0,
rsa = 1,
dsa = 2,
ecdsa = 3,
};
 
const SignatureAndHashAlgorithm = struct {
hash: HashAlgorithm,
signature: SignatureAlgorithm,
};
 
pub const ChangeCipherSpec = struct {
pub fn unpack(_: []const u8) !ChangeCipherSpec {
unreachable;
@@ -520,39 +393,3 @@ test "mock server response" {
//try std.testing.expectEqual(43, len);
//print("CKE: {any}\n", .{buffer[0..43]});
}
 
pub const CipherSuites = enum(u16) {
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A,
TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAD,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B,
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAA,
TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D,
TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030,
TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E,
TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036,
TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068,
TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010,
TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031,
TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F,
TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037,
TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069,
TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B,
TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034,
TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C,
TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A,
TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D,
TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018,
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9,
TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAC,
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8,
TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAB,
TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAE,
};
 
src/state.zig added: 202, removed: 197, total 5
@@ -1,12 +1,12 @@
// TODO refactor more
const std = @import("std");
const root = @import("root.zig");
 
const Cipher = root.Cipher;
const root = @import("root.zig");
const Cipher = @import("cipher.zig");
 
const ConnectionEnd = root.ConnectionEnd;
const PRFAlgorithm = root.PRFAlgorithm;
const BulkCipherAlgorithm = root.BulkCipherAlgorithm;
const CipherType = root.CipherType;
const MACAlgorithm = root.MACAlgorithm;
const CompressionMethod = root.CompressionMethod;
 
@@ -15,17 +15,6 @@ pub const State = @This();
cipher: Cipher = .{},
entity: ConnectionEnd = .{},
prf_algorithm: PRFAlgorithm = .{},
bulk_cipher_algorithm: BulkCipherAlgorithm = .{},
cipher_type: ?CipherType = null,
enc_key_length: u8 = 0,
block_length: u8 = 0,
fixed_iv_length: u8 = 0,
record_iv_length: u8 = 0,
mac_algorithm: MACAlgorithm = .{},
mac_length: u8 = 0,
mac_key_length: u8 = 0,
/// Compressed encryption is a mistake...
compression_algorithm: CompressionMethod = null,
master_secret: [48]u8 = std.mem.zeroes([48]u8),
client_random: [32]u8 = std.mem.zeroes([32]u8),
server_random: [32]u8 = std.mem.zeroes([32]u8),