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
Show file tree
Hide file tree
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
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
12 changes: 8 additions & 4 deletions vlib/crypto/ecdsa/ecdsa.v
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
}

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

Expand Down Expand Up @@ -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
Expand Down
Loading