From ddedadf38b88db515c9402f6ac04aa056a6d4424 Mon Sep 17 00:00:00 2001 From: blackshirt muslim Date: Sat, 8 Mar 2025 01:20:45 +0000 Subject: [PATCH] crypto.ecdsa: the last bits of migration steps --- vlib/crypto/ecdsa/ecdsa.c.v | 3 ++ vlib/crypto/ecdsa/ecdsa.v | 12 +++++--- vlib/crypto/ecdsa/util.v | 56 +++++++++++-------------------------- 3 files changed, 27 insertions(+), 44 deletions(-) diff --git a/vlib/crypto/ecdsa/ecdsa.c.v b/vlib/crypto/ecdsa/ecdsa.c.v index cac79949ccd39e..a785f75c269a17 100644 --- a/vlib/crypto/ecdsa/ecdsa.c.v +++ b/vlib/crypto/ecdsa/ecdsa.c.v @@ -44,6 +44,8 @@ fn C.EVP_PKEY_bits(pkey &C.EVP_PKEY) int fn C.EVP_PKEY_size(key &C.EVP_PKEY) int fn C.EVP_PKEY_eq(a &C.EVP_PKEY, b &C.EVP_PKEY) int +fn C.EVP_PKEY_get1_encoded_public_key(pkey &C.EVP_PKEY, ppub &&u8) int +fn C.EVP_PKEY_get_bn_param(pkey &C.EVP_PKEY, key_name &u8, bn &&C.BIGNUM) int fn C.EVP_PKEY_fromdata_init(ctx &C.EVP_PKEY_CTX) int fn C.EVP_PKEY_fromdata(ctx &C.EVP_PKEY_CTX, ppkey &&C.EVP_PKEY, selection int, params &C.OSSL_PARAM) int @@ -143,6 +145,7 @@ fn C.EC_GROUP_new_by_curve_name(nid int) &C.EC_GROUP @[typedef] struct C.BIGNUM {} +fn C.BN_new() &C.BIGNUM fn C.BN_num_bits(a &C.BIGNUM) int fn C.BN_bn2bin(a &C.BIGNUM, to &u8) int fn C.BN_bn2binpad(a &C.BIGNUM, to &u8, tolen int) int diff --git a/vlib/crypto/ecdsa/ecdsa.v b/vlib/crypto/ecdsa/ecdsa.v index 75c6d3b19ddaf1..acd649f9aa7bb2 100644 --- a/vlib/crypto/ecdsa/ecdsa.v +++ b/vlib/crypto/ecdsa/ecdsa.v @@ -289,10 +289,12 @@ fn (pv PrivateKey) sign_digest(digest []u8) ![]u8 { // bytes represent private key as bytes. pub fn (pv PrivateKey) bytes() ![]u8 { - // This is the old one - bn := voidptr(C.EC_KEY_get0_private_key(pv.key)) - if bn == 0 { - return error('Failed to get private key BIGNUM') + bn := C.BN_new() + // retrieves a BIGNUM value associated with a 'priv' key name + n := C.EVP_PKEY_get_bn_param(pv.evpkey, c'priv', &bn) + if n <= 0 { + C.BN_free(bn) + return error('EVP_PKEY_get_bn_param failed') } num_bytes := (C.BN_num_bits(bn) + 7) / 8 // Get the buffer size to store the seed. @@ -305,8 +307,10 @@ pub fn (pv PrivateKey) bytes() ![]u8 { mut buf := []u8{len: int(size)} res := C.BN_bn2binpad(bn, buf.data, size) if res == 0 { + C.BN_free(bn) return error('Failed to convert BIGNUM to bytes') } + C.BN_free(bn) return buf } diff --git a/vlib/crypto/ecdsa/util.v b/vlib/crypto/ecdsa/util.v index b804460598b83d..fa645d6ea2861b 100644 --- a/vlib/crypto/ecdsa/util.v +++ b/vlib/crypto/ecdsa/util.v @@ -62,45 +62,17 @@ pub fn pubkey_from_bytes(bytes []u8) !PublicKey { // bytes gets the bytes of public key. pub fn (pbk PublicKey) bytes() ![]u8 { - point := voidptr(C.EC_KEY_get0_public_key(pbk.key)) - // defer { C.EC_POINT_free(point)} - if point == 0 { - C.EC_POINT_free(point) - return error('Failed to get public key BIGNUM') - } - - group := voidptr(C.EC_KEY_get0_group(pbk.key)) - num_bits := C.EC_GROUP_get_degree(group) - // 1 byte of conversion format || x || y of EC_POINT - num_bytes := 1 + 2 * ((num_bits + 7) / 8) - - ctx := C.BN_CTX_new() - defer { - C.BN_CTX_free(ctx) - } - - if ctx == 0 { - C.EC_POINT_free(point) - C.BN_CTX_free(ctx) - return error('Failed to create BN_CTX') + ppub := []u8{len: default_point_bufsize} + n := C.EVP_PKEY_get1_encoded_public_key(pbk.evpkey, voidptr(&ppub.data)) + if n <= 0 { + C.OPENSSL_free(voidptr(ppub.data)) + return error('EVP_PKEY_get1_encoded_public_key failed') } - mut buf := []u8{len: num_bytes} + out := ppub[..n].clone() + // ppub should be freed by calling `OPENSSL_free` or memleak happens. + C.OPENSSL_free(voidptr(ppub.data)) - // Get conversion format. - // - // The uncompressed form is indicated by 0x04 and the compressed form is indicated - // by either 0x02 or 0x03, hybrid 0x06 - // The public key MUST be rejected if any other value is included in the first octet. - conv_form := C.EC_KEY_get_conv_form(pbk.key) - if conv_form !in [2, 3, 4, 6] { - return error('bad conversion format') - } - n := C.EC_POINT_point2oct(group, point, conv_form, buf.data, buf.len, ctx) - if n == 0 { - return error('EC_POINT_point2oct failed') - } - // returns the clone of the buffer[..n] - return buf[..n].clone() + return out } // pubkey_from_string loads a PublicKey from valid PEM-formatted string in s. @@ -149,14 +121,16 @@ pub fn pubkey_from_string(s string) !PublicKey { } chk := C.EC_KEY_check_key(eckey) if chk == 0 { + C.BIO_free_all(bo) C.EC_KEY_free(eckey) + C.EVP_PKEY_free(evpkey) return error('EC_KEY_check_key failed') } - C.EVP_PKEY_free(evpkey) C.BIO_free_all(bo) // Its OK to return return PublicKey{ - key: eckey + evpkey: evpkey + key: eckey } } @@ -212,16 +186,18 @@ pub fn privkey_from_string(s string) !PrivateKey { chk := C.EC_KEY_check_key(eckey) if chk == 0 { + C.BIO_free_all(bo) C.EC_KEY_free(eckey) + C.EVP_PKEY_free(evpkey) return error('EC_KEY_check_key failed') } ksize := ec_key_size(eckey)! - C.EVP_PKEY_free(evpkey) C.BIO_free_all(bo) // Its OK to return return PrivateKey{ + evpkey: evpkey key: eckey ks_flag: .fixed ks_size: ksize