Skip to content

Commit

Permalink
Add d2i_PUBKEY_ex_fp and d2i_PUBKEY_ex_bio.
Browse files Browse the repository at this point in the history
These functions pass a library content and prop query.
The i2d documentation related to these functions has been corrected since the bio and fp functions always return 0 or 1.

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from #18427)
  • Loading branch information
slontis authored and t8m committed Nov 2, 2022
1 parent 57d2bcc commit 820723d
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 8 deletions.
35 changes: 35 additions & 0 deletions crypto/x509/x_all.c
Expand Up @@ -705,6 +705,22 @@ int i2d_PUBKEY_fp(FILE *fp, const EVP_PKEY *pkey)
return ASN1_i2d_fp_of(EVP_PKEY, i2d_PUBKEY, fp, pkey);
}

EVP_PKEY *d2i_PUBKEY_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
const char *propq)
{
BIO *b;
void *ret;

if ((b = BIO_new(BIO_s_file())) == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB);
return NULL;
}
BIO_set_fp(b, fp, BIO_NOCLOSE);
ret = d2i_PUBKEY_ex_bio(b, a, libctx, propq);
BIO_free(b);
return ret;
}

EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a)
{
return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a);
Expand Down Expand Up @@ -772,6 +788,25 @@ int i2d_PUBKEY_bio(BIO *bp, const EVP_PKEY *pkey)
return ASN1_i2d_bio_of(EVP_PKEY, i2d_PUBKEY, bp, pkey);
}

EVP_PKEY *d2i_PUBKEY_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
const char *propq)
{
BUF_MEM *b = NULL;
const unsigned char *p;
void *ret = NULL;
int len;

len = asn1_d2i_read_bio(bp, &b);
if (len < 0)
goto err;

p = (unsigned char *)b->data;
ret = d2i_PUBKEY_ex(a, &p, len, libctx, propq);
err:
BUF_MEM_free(b);
return ret;
}

EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a)
{
return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a);
Expand Down
30 changes: 23 additions & 7 deletions doc/man3/X509_PUBKEY_new.pod
Expand Up @@ -4,9 +4,9 @@

X509_PUBKEY_new_ex, X509_PUBKEY_new, X509_PUBKEY_free, X509_PUBKEY_dup,
X509_PUBKEY_set, X509_PUBKEY_get0, X509_PUBKEY_get,
d2i_PUBKEY_ex, d2i_PUBKEY, i2d_PUBKEY, d2i_PUBKEY_bio, d2i_PUBKEY_fp,
i2d_PUBKEY_fp, i2d_PUBKEY_bio, X509_PUBKEY_set0_public_key,
X509_PUBKEY_set0_param, X509_PUBKEY_get0_param,
d2i_PUBKEY_ex, d2i_PUBKEY, i2d_PUBKEY, d2i_PUBKEY_ex_bio, d2i_PUBKEY_bio,
d2i_PUBKEY_ex_fp, d2i_PUBKEY_fp, i2d_PUBKEY_fp, i2d_PUBKEY_bio,
X509_PUBKEY_set0_public_key, X509_PUBKEY_set0_param, X509_PUBKEY_get0_param,
X509_PUBKEY_eq - SubjectPublicKeyInfo public key functions

=head1 SYNOPSIS
Expand All @@ -27,7 +27,12 @@ X509_PUBKEY_eq - SubjectPublicKeyInfo public key functions
EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length);
int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp);

EVP_PKEY *d2i_PUBKEY_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
const char *propq);
EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a);

EVP_PKEY *d2i_PUBKEY_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
const char *propq);
EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a);

int i2d_PUBKEY_fp(const FILE *fp, EVP_PKEY *pkey);
Expand Down Expand Up @@ -88,6 +93,9 @@ d2i_PUBKEY_bio(), d2i_PUBKEY_fp(), i2d_PUBKEY_bio() and i2d_PUBKEY_fp() are
similar to d2i_PUBKEY() and i2d_PUBKEY() except they decode or encode using a
B<BIO> or B<FILE> pointer.

d2i_PUBKEY_ex_bio() and d2i_PUBKEY_ex_fp() are similar to d2i_PUBKEY_ex() except
they decode using a B<BIO> or B<FILE> pointer.

X509_PUBKEY_set0_public_key() sets the public-key encoding of I<pub>
to the I<penclen> bytes contained in buffer I<penc>.
Any earlier public-key encoding in I<pub> is freed.
Expand Down Expand Up @@ -129,8 +137,15 @@ Otherwise they return a pointer to the newly allocated structure.

X509_PUBKEY_free() does not return a value.

X509_PUBKEY_get0() and X509_PUBKEY_get() return a pointer to an B<EVP_PKEY>
structure or NULL if an error occurs.
X509_PUBKEY_get0(), X509_PUBKEY_get(), d2i_PUBKEY_ex(), d2i_PUBKEY(),
d2i_PUBKEY_ex_bio(), d2i_PUBKEY_bio(), d2i_PUBKEY_ex_fp() and d2i_PUBKEY_fp()
return a pointer to an B<EVP_PKEY> structure or NULL if an error occurs.

i2d_PUBKEY() returns the number of bytes successfully encoded or a
negative value if an error occurs.

i2d_PUBKEY_fp() and i2d_PUBKEY_bio() return 1 if successfully
encoded or 0 if an error occurs.

X509_PUBKEY_set0_public_key() does not return a value.

Expand All @@ -150,11 +165,12 @@ L<X509_get_pubkey(3)>,
The X509_PUBKEY_new_ex() and X509_PUBKEY_eq() functions were added in OpenSSL
3.0.

X509_PUBKEY_set0_public_key() was added in OpenSSL 3.2.
The X509_PUBKEY_set0_public_key(), d2i_PUBKEY_ex_bio() and d2i_PUBKEY_ex_fp()
functions were added in OpenSSL 3.2.

=head1 COPYRIGHT

Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
Expand Down
4 changes: 4 additions & 0 deletions include/openssl/x509.h.in
Expand Up @@ -412,6 +412,8 @@ EVP_PKEY *d2i_PrivateKey_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
const char *propq);
EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a);
int i2d_PUBKEY_fp(FILE *fp, const EVP_PKEY *pkey);
EVP_PKEY *d2i_PUBKEY_ex_fp(FILE *fp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
const char *propq);
EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a);
# endif

Expand Down Expand Up @@ -460,6 +462,8 @@ EVP_PKEY *d2i_PrivateKey_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
const char *propq);
EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a);
int i2d_PUBKEY_bio(BIO *bp, const EVP_PKEY *pkey);
EVP_PKEY *d2i_PUBKEY_ex_bio(BIO *bp, EVP_PKEY **a, OSSL_LIB_CTX *libctx,
const char *propq);
EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a);

DECLARE_ASN1_DUP_FUNCTION(X509)
Expand Down
2 changes: 1 addition & 1 deletion test/build.info
Expand Up @@ -184,7 +184,7 @@ IF[{- !$disabled{tests} -}]
INCLUDE[evp_extra_test]=../include ../apps/include
DEPEND[evp_extra_test]=../libcrypto.a libtestutil.a

SOURCE[evp_extra_test2]=evp_extra_test2.c
SOURCE[evp_extra_test2]=evp_extra_test2.c $INITSRC
INCLUDE[evp_extra_test2]=../include ../apps/include
DEPEND[evp_extra_test2]=../libcrypto libtestutil.a

Expand Down
30 changes: 30 additions & 0 deletions test/evp_extra_test2.c
Expand Up @@ -359,6 +359,35 @@ static int test_dh_tofrom_data_select(void)
#endif

#ifndef OPENSSL_NO_EC

static int test_ec_d2i_i2d_pubkey(void)
{
int ret = 0;
FILE *fp = NULL;
EVP_PKEY *key = NULL, *outkey = NULL;
static const char *filename = "pubkey.der";

if (!TEST_ptr(fp = fopen(filename, "wb"))
|| !TEST_ptr(key = EVP_PKEY_Q_keygen(mainctx, NULL, "EC", "P-256"))
|| !TEST_true(i2d_PUBKEY_fp(fp, key))
|| !TEST_int_eq(fclose(fp), 0))
goto err;
fp = NULL;

if (!TEST_ptr(fp = fopen(filename, "rb"))
|| !TEST_ptr(outkey = d2i_PUBKEY_ex_fp(fp, NULL, mainctx, NULL))
|| !TEST_int_eq(EVP_PKEY_eq(key, outkey), 1))
goto err;

ret = 1;

err:
EVP_PKEY_free(outkey);
EVP_PKEY_free(key);
fclose(fp);
return ret;
}

static int test_ec_tofrom_data_select(void)
{
int ret;
Expand Down Expand Up @@ -1117,6 +1146,7 @@ int setup_tests(void)
ADD_ALL_TESTS(test_d2i_PrivateKey_ex, 2);
ADD_TEST(test_ec_tofrom_data_select);
ADD_TEST(test_ecx_tofrom_data_select);
ADD_TEST(test_ec_d2i_i2d_pubkey);
#else
ADD_ALL_TESTS(test_d2i_PrivateKey_ex, 1);
#endif
Expand Down
2 changes: 2 additions & 0 deletions util/libcrypto.num
Expand Up @@ -5478,3 +5478,5 @@ BIO_f_brotli ? 3_2_0 EXIST::FUNCTION:COMP
COMP_zstd ? 3_2_0 EXIST::FUNCTION:COMP
COMP_zstd_oneshot ? 3_2_0 EXIST::FUNCTION:COMP
BIO_f_zstd ? 3_2_0 EXIST::FUNCTION:COMP
d2i_PUBKEY_ex_fp ? 3_2_0 EXIST::FUNCTION:STDIO
d2i_PUBKEY_ex_bio ? 3_2_0 EXIST::FUNCTION:

0 comments on commit 820723d

Please sign in to comment.