authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2023-05-30 12:06:44+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-05-30 10:06:44+00:00
log1ab008d89dbc18cd79abed88f306ad9bd0397622
treef470654f24f59129fab69e92f7a284ce30fd267d
parent9244e4fe2d675c6cda569afc7509349e35199ed5
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

RSA: remove usage of allocators (#15901)

Individual max buffer sizes are well known, now that arithmetic doesn't require allocations any more. Also bump `main_cert_pub_key_buf`, so that e.g. `nodejs.org` public keys can fit.

2 files changed, 24 insertions(+), 21 deletions(-)

lib/std/crypto/Certificate.zig+22-16
...@@ -917,18 +917,20 @@ pub const rsa = struct {...@@ -917,18 +917,20 @@ pub const rsa = struct {
917 return result;917 return result;
918 }918 }
919919
920 pub fn verify(comptime modulus_len: usize, sig: [modulus_len]u8, msg: []const u8, public_key: PublicKey, comptime Hash: type, allocator: std.mem.Allocator) !void {920 pub fn verify(comptime modulus_len: usize, sig: [modulus_len]u8, msg: []const u8, public_key: PublicKey, comptime Hash: type) !void {
921 const mod_bits = public_key.n.bits();921 const mod_bits = public_key.n.bits();
922 const em_dec = try encrypt(modulus_len, sig, public_key);922 const em_dec = try encrypt(modulus_len, sig, public_key);
923923
924 EMSA_PSS_VERIFY(msg, &em_dec, mod_bits - 1, Hash.digest_length, Hash, allocator) catch unreachable;924 EMSA_PSS_VERIFY(msg, &em_dec, mod_bits - 1, Hash.digest_length, Hash) catch unreachable;
925 }925 }
926926
927 fn EMSA_PSS_VERIFY(msg: []const u8, em: []const u8, emBit: usize, sLen: usize, comptime Hash: type, allocator: std.mem.Allocator) !void {927 fn EMSA_PSS_VERIFY(msg: []const u8, em: []const u8, emBit: usize, sLen: usize, comptime Hash: type) !void {
928 // TODO
929 // 1. If the length of M is greater than the input limitation for928 // 1. If the length of M is greater than the input limitation for
930 // the hash function (2^61 - 1 octets for SHA-1), output929 // the hash function (2^61 - 1 octets for SHA-1), output
931 // "inconsistent" and stop.930 // "inconsistent" and stop.
931 // All the cryptographic hash functions in the standard library have a limit of >= 2^61 - 1.
932 // Even then, this check is only there for paranoia. In the context of TLS certifcates, emBit cannot exceed 4096.
933 if (emBit >= 1 << 61) return error.InvalidSignature;
932934
933 // emLen = \ceil(emBits/8)935 // emLen = \ceil(emBits/8)
934 const emLen = ((emBit - 1) / 8) + 1;936 const emLen = ((emBit - 1) / 8) + 1;
...@@ -952,7 +954,7 @@ pub const rsa = struct {...@@ -952,7 +954,7 @@ pub const rsa = struct {
952 // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM,954 // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM,
953 // and let H be the next hLen octets.955 // and let H be the next hLen octets.
954 const maskedDB = em[0..(emLen - Hash.digest_length - 1)];956 const maskedDB = em[0..(emLen - Hash.digest_length - 1)];
955 const h = em[(emLen - Hash.digest_length - 1)..(emLen - 1)];957 const h = em[(emLen - Hash.digest_length - 1)..(emLen - 1)][0..Hash.digest_length];
956958
957 // 6. If the leftmost 8emLen - emBits bits of the leftmost octet in959 // 6. If the leftmost 8emLen - emBits bits of the leftmost octet in
958 // maskedDB are not all equal to zero, output "inconsistent" and960 // maskedDB are not all equal to zero, output "inconsistent" and
...@@ -969,9 +971,12 @@ pub const rsa = struct {...@@ -969,9 +971,12 @@ pub const rsa = struct {
969971
970 // 7. Let dbMask = MGF(H, emLen - hLen - 1).972 // 7. Let dbMask = MGF(H, emLen - hLen - 1).
971 const mgf_len = emLen - Hash.digest_length - 1;973 const mgf_len = emLen - Hash.digest_length - 1;
972 var mgf_out = try allocator.alloc(u8, ((mgf_len - 1) / Hash.digest_length + 1) * Hash.digest_length);974 var mgf_out_buf: [512]u8 = undefined;
973 defer allocator.free(mgf_out);975 if (mgf_len > mgf_out_buf.len) { // Modulus > 4096 bits
974 var dbMask = try MGF1(mgf_out, h, mgf_len, Hash, allocator);976 return error.InvalidSignature;
977 }
978 var mgf_out = mgf_out_buf[0 .. ((mgf_len - 1) / Hash.digest_length + 1) * Hash.digest_length];
979 var dbMask = try MGF1(Hash, mgf_out, h, mgf_len);
975980
976 // 8. Let DB = maskedDB \xor dbMask.981 // 8. Let DB = maskedDB \xor dbMask.
977 i = 0;982 i = 0;
...@@ -1008,8 +1013,11 @@ pub const rsa = struct {...@@ -1008,8 +1013,11 @@ pub const rsa = struct {
1008 // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ;1013 // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ;
1009 // M' is an octet string of length 8 + hLen + sLen with eight1014 // M' is an octet string of length 8 + hLen + sLen with eight
1010 // initial zero octets.1015 // initial zero octets.
1011 var m_p = try allocator.alloc(u8, 8 + Hash.digest_length + sLen);1016 if (sLen > Hash.digest_length) { // A seed larger than the hash length would be useless
1012 defer allocator.free(m_p);1017 return error.InvalidSignature;
1018 }
1019 var m_p_buf: [8 + Hash.digest_length + Hash.digest_length]u8 = undefined;
1020 var m_p = m_p_buf[0 .. 8 + Hash.digest_length + sLen];
1013 std.mem.copyForwards(u8, m_p, &([_]u8{0} ** 8));1021 std.mem.copyForwards(u8, m_p, &([_]u8{0} ** 8));
1014 std.mem.copyForwards(u8, m_p[8..], &mHash);1022 std.mem.copyForwards(u8, m_p[8..], &mHash);
1015 std.mem.copyForwards(u8, m_p[(8 + Hash.digest_length)..], salt);1023 std.mem.copyForwards(u8, m_p[(8 + Hash.digest_length)..], salt);
...@@ -1025,14 +1033,12 @@ pub const rsa = struct {...@@ -1025,14 +1033,12 @@ pub const rsa = struct {
1025 }1033 }
1026 }1034 }
10271035
1028 fn MGF1(out: []u8, seed: []const u8, len: usize, comptime Hash: type, allocator: std.mem.Allocator) ![]u8 {1036 fn MGF1(comptime Hash: type, out: []u8, seed: *const [Hash.digest_length]u8, len: usize) ![]u8 {
1029 var counter: usize = 0;1037 var counter: usize = 0;
1030 var idx: usize = 0;1038 var idx: usize = 0;
1031 var c: [4]u8 = undefined;1039 var c: [4]u8 = undefined;
10321040 var hash: [Hash.digest_length + c.len]u8 = undefined;
1033 var hash = try allocator.alloc(u8, seed.len + c.len);1041 @memcpy(hash[0..Hash.digest_length], seed);
1034 defer allocator.free(hash);
1035 std.mem.copyForwards(u8, hash, seed);
1036 var hashed: [Hash.digest_length]u8 = undefined;1042 var hashed: [Hash.digest_length]u8 = undefined;
10371043
1038 while (idx < len) {1044 while (idx < len) {
...@@ -1042,7 +1048,7 @@ pub const rsa = struct {...@@ -1042,7 +1048,7 @@ pub const rsa = struct {
1042 c[3] = @intCast(u8, counter & 0xFF);1048 c[3] = @intCast(u8, counter & 0xFF);
10431049
1044 std.mem.copyForwards(u8, hash[seed.len..], &c);1050 std.mem.copyForwards(u8, hash[seed.len..], &c);
1045 Hash.hash(hash, &hashed, .{});1051 Hash.hash(&hash, &hashed, .{});
10461052
1047 std.mem.copyForwards(u8, out[idx..], &hashed);1053 std.mem.copyForwards(u8, out[idx..], &hashed);
1048 idx += hashed.len;1054 idx += hashed.len;
lib/std/crypto/tls/Client.zig+2-5
...@@ -424,7 +424,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -424,7 +424,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
424 var handshake_state: HandshakeState = .encrypted_extensions;424 var handshake_state: HandshakeState = .encrypted_extensions;
425 var cleartext_bufs: [2][8000]u8 = undefined;425 var cleartext_bufs: [2][8000]u8 = undefined;
426 var main_cert_pub_key_algo: Certificate.AlgorithmCategory = undefined;426 var main_cert_pub_key_algo: Certificate.AlgorithmCategory = undefined;
427 var main_cert_pub_key_buf: [300]u8 = undefined;427 var main_cert_pub_key_buf: [600]u8 = undefined;
428 var main_cert_pub_key_len: u16 = undefined;428 var main_cert_pub_key_len: u16 = undefined;
429 const now_sec = std.time.timestamp();429 const now_sec = std.time.timestamp();
430430
...@@ -602,14 +602,11 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -602,14 +602,11 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
602 const components = try rsa.PublicKey.parseDer(main_cert_pub_key);602 const components = try rsa.PublicKey.parseDer(main_cert_pub_key);
603 const exponent = components.exponent;603 const exponent = components.exponent;
604 const modulus = components.modulus;604 const modulus = components.modulus;
605 var rsa_mem_buf: [512 * 32]u8 = undefined;
606 var fba = std.heap.FixedBufferAllocator.init(&rsa_mem_buf);
607 const ally = fba.allocator();
608 switch (modulus.len) {605 switch (modulus.len) {
609 inline 128, 256, 512 => |modulus_len| {606 inline 128, 256, 512 => |modulus_len| {
610 const key = try rsa.PublicKey.fromBytes(exponent, modulus);607 const key = try rsa.PublicKey.fromBytes(exponent, modulus);
611 const sig = rsa.PSSSignature.fromBytes(modulus_len, encoded_sig);608 const sig = rsa.PSSSignature.fromBytes(modulus_len, encoded_sig);
612 try rsa.PSSSignature.verify(modulus_len, sig, verify_bytes, key, Hash, ally);609 try rsa.PSSSignature.verify(modulus_len, sig, verify_bytes, key, Hash);
613 },610 },
614 else => {611 else => {
615 return error.TlsBadRsaSignatureBitCount;612 return error.TlsBadRsaSignatureBitCount;