authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-18 18:51:28-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-02 16:57:15-07:00
loge2c16d03abae01538ec8ca65e6dc1ecc6f6ec420
tree98ffce6763c2a964a9bff59e2aa649bd18cc29cd
parentf460c2170504ce94471b16631c43638f50735241

std.crypto.tls.Client: support secp256r1 for handshake


1 files changed, 31 insertions(+), 15 deletions(-)

lib/std/crypto/tls/Client.zig+31-15
......@@ -46,7 +46,6 @@ pub fn init(stream: net.Stream, host: []const u8) !Client {
4646 // Only possible to happen if the private key is all zeroes.
4747 error.IdentityElement => return error.InsufficientEntropy,
4848 };
49 _ = secp256r1_kp;
5049
5150 const extensions_payload =
5251 tls.extension(.supported_versions, [_]u8{
......@@ -70,11 +69,14 @@ pub fn init(stream: net.Stream, host: []const u8) !Client {
7069 .rsa_pkcs1_sha1,
7170 .ecdsa_sha1,
7271 })) ++ tls.extension(.supported_groups, enum_array(tls.NamedGroup, &.{
73 //.secp256r1,
72 .secp256r1,
7473 .x25519,
7574 })) ++ tls.extension(
7675 .key_share,
77 array(1, int2(@enumToInt(tls.NamedGroup.x25519)) ++ array(1, x25519_kp.public_key)),
76 array(1, int2(@enumToInt(tls.NamedGroup.x25519)) ++
77 array(1, x25519_kp.public_key) ++
78 int2(@enumToInt(tls.NamedGroup.secp256r1)) ++
79 array(1, secp256r1_kp.public_key.toUncompressedSec1())),
7880 ) ++
7981 int2(@enumToInt(tls.ExtensionType.server_name)) ++
8082 int2(host_len + 5) ++ // byte length of this extension payload
......@@ -182,7 +184,8 @@ pub fn init(stream: net.Stream, host: []const u8) !Client {
182184 i += 2;
183185 if (i + extensions_size != frag.len) return error.TlsBadLength;
184186 var supported_version: u16 = 0;
185 var opt_x25519_server_pub_key: ?*[32]u8 = null;
187 var shared_key: [32]u8 = undefined;
188 var have_shared_key = false;
186189 while (i < frag.len) {
187190 const et = mem.readIntBig(u16, frag[i..][0..2]);
188191 i += 2;
......@@ -196,15 +199,34 @@ pub fn init(stream: net.Stream, host: []const u8) !Client {
196199 supported_version = mem.readIntBig(u16, frag[i..][0..2]);
197200 },
198201 @enumToInt(tls.ExtensionType.key_share) => {
199 if (opt_x25519_server_pub_key != null) return error.TlsIllegalParameter;
202 if (have_shared_key) return error.TlsIllegalParameter;
203 have_shared_key = true;
200204 const named_group = mem.readIntBig(u16, frag[i..][0..2]);
201205 i += 2;
206 const key_size = mem.readIntBig(u16, frag[i..][0..2]);
207 i += 2;
208
202209 switch (named_group) {
203210 @enumToInt(tls.NamedGroup.x25519) => {
204 const key_size = mem.readIntBig(u16, frag[i..][0..2]);
205 i += 2;
206211 if (key_size != 32) return error.TlsBadLength;
207 opt_x25519_server_pub_key = frag[i..][0..32];
212 const server_pub_key = frag[i..][0..32];
213
214 shared_key = crypto.dh.X25519.scalarmult(
215 x25519_kp.secret_key,
216 server_pub_key.*,
217 ) catch return error.TlsDecryptFailure;
218 },
219 @enumToInt(tls.NamedGroup.secp256r1) => {
220 const server_pub_key = frag[i..][0..key_size];
221
222 const PublicKey = crypto.sign.ecdsa.EcdsaP256Sha256.PublicKey;
223 const pk = PublicKey.fromSec1(server_pub_key) catch {
224 return error.TlsDecryptFailure;
225 };
226 const mul = pk.p.mulPublic(secp256r1_kp.secret_key.bytes, .Big) catch {
227 return error.TlsDecryptFailure;
228 };
229 shared_key = mul.affineCoordinates().x.toBytes(.Big);
208230 },
209231 else => {
210232 std.debug.print("named group: {x}\n", .{named_group});
......@@ -218,8 +240,7 @@ pub fn init(stream: net.Stream, host: []const u8) !Client {
218240 }
219241 i = next_i;
220242 }
221 const x25519_server_pub_key = opt_x25519_server_pub_key orelse
222 return error.TlsIllegalParameter;
243 if (!have_shared_key) return error.TlsIllegalParameter;
223244 const tls_version = if (supported_version == 0) legacy_version else supported_version;
224245 switch (tls_version) {
225246 @enumToInt(tls.ProtocolVersion.tls_1_2) => {
......@@ -231,11 +252,6 @@ pub fn init(stream: net.Stream, host: []const u8) !Client {
231252 else => return error.TlsIllegalParameter,
232253 }
233254
234 const shared_key = crypto.dh.X25519.scalarmult(
235 x25519_kp.secret_key,
236 x25519_server_pub_key.*,
237 ) catch return error.TlsDecryptFailure;
238
239255 switch (cipher_suite_tag) {
240256 inline .AES_128_GCM_SHA256,
241257 .AES_256_GCM_SHA384,