std.crypto.tls: avoid heap allocation

The code we are borrowing from https://github.com/shiguredo/tls13-zig
requires an Allocator for doing RSA certificate verification. As a
stopgap measure, this commit uses a FixedBufferAllocator to avoid heap
allocation for these functions.

Thank you to @naoki9911 for providing this great resource which has been
extremely helpful for me when working on this standard library TLS
implementation. Until Zig has std.crypto.rsa officially, we will borrow
this implementation of RSA. 🙏
This commit is contained in:
Andrew Kelley 2022-12-29 20:49:56 -07:00
parent 2d090f61be
commit 79b41dbdbf
2 changed files with 13 additions and 9 deletions

View file

@ -511,6 +511,10 @@ fn verifyRsa(
var msg_hashed: [Hash.digest_length]u8 = undefined;
Hash.hash(message, &msg_hashed, .{});
var rsa_mem_buf: [512 * 32]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&rsa_mem_buf);
const ally = fba.allocator();
switch (modulus.len) {
inline 128, 256, 512 => |modulus_len| {
const ps_len = modulus_len - (hash_der.len + msg_hashed.len) - 3;
@ -521,11 +525,11 @@ fn verifyRsa(
hash_der ++
msg_hashed;
const public_key = rsa.PublicKey.fromBytes(exponent, modulus, rsa.poop) catch |err| switch (err) {
error.OutOfMemory => @panic("TODO don't heap allocate"),
const public_key = rsa.PublicKey.fromBytes(exponent, modulus, ally) catch |err| switch (err) {
error.OutOfMemory => unreachable, // rsa_mem_buf is big enough
};
const em_dec = rsa.encrypt(modulus_len, sig[0..modulus_len].*, public_key, rsa.poop) catch |err| switch (err) {
error.OutOfMemory => @panic("TODO don't heap allocate"),
const em_dec = rsa.encrypt(modulus_len, sig[0..modulus_len].*, public_key, ally) catch |err| switch (err) {
error.OutOfMemory => unreachable, // rsa_mem_buf is big enough
error.MessageTooLong => unreachable,
error.NegativeIntoUnsigned => @panic("TODO make RSA not emit this error"),
@ -977,7 +981,4 @@ pub const rsa = struct {
return i;
}
// TODO: flush the toilet
pub const poop = std.heap.page_allocator;
};

View file

@ -544,11 +544,14 @@ pub fn init(stream: net.Stream, ca_bundle: Certificate.Bundle, host: []const u8)
const components = try rsa.PublicKey.parseDer(main_cert_pub_key);
const exponent = components.exponent;
const modulus = components.modulus;
var rsa_mem_buf: [512 * 32]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&rsa_mem_buf);
const ally = fba.allocator();
switch (modulus.len) {
inline 128, 256, 512 => |modulus_len| {
const key = try rsa.PublicKey.fromBytes(exponent, modulus, rsa.poop);
const key = try rsa.PublicKey.fromBytes(exponent, modulus, ally);
const sig = rsa.PSSSignature.fromBytes(modulus_len, encoded_sig);
try rsa.PSSSignature.verify(modulus_len, sig, verify_bytes, key, Hash, rsa.poop);
try rsa.PSSSignature.verify(modulus_len, sig, verify_bytes, key, Hash, ally);
},
else => {
return error.TlsBadRsaSignatureBitCount;