Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto.ecdsa: the last bits of migration steps #23877

Merged
merged 1 commit into from
Mar 8, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions vlib/crypto/ecdsa/ecdsa.c.v
Original file line number Diff line number Diff line change
@@ -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
12 changes: 8 additions & 4 deletions vlib/crypto/ecdsa/ecdsa.v
Original file line number Diff line number Diff line change
@@ -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
}

56 changes: 16 additions & 40 deletions vlib/crypto/ecdsa/util.v
Original file line number Diff line number Diff line change
@@ -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