mirror of
https://github.com/openssl/openssl.git
synced 2025-04-24 20:51:14 +08:00
Implement i2d_PKCS8PrivateKey
Added `i2d_PKCS8PrivateKey(3)` API to complement `i2d_PrivateKey(3)`, the former always outputs PKCS#8. Extended endecoder_test.c to check that `i2d_PKCS8PrivateKey()` produces the expected PKCS#8 output. Reviewed-by: Shane Lontis <shane.lontis@oracle.com> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/27309)
This commit is contained in:
parent
85a8eba567
commit
8d2e4d6d8c
crypto/asn1
doc/man3
include/openssl
test
util
@ -91,20 +91,25 @@ int i2d_KeyParams_bio(BIO *bp, const EVP_PKEY *pkey)
|
||||
return ASN1_i2d_bio_of(EVP_PKEY, i2d_KeyParams, bp, pkey);
|
||||
}
|
||||
|
||||
int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp)
|
||||
static int
|
||||
i2d_PrivateKey_impl(const EVP_PKEY *a, unsigned char **pp, int traditional)
|
||||
{
|
||||
if (evp_pkey_is_provided(a)) {
|
||||
static const struct type_and_structure_st output_info[] = {
|
||||
static const struct type_and_structure_st trad_output_info[] = {
|
||||
{ "DER", "type-specific" },
|
||||
{ "DER", "PrivateKeyInfo" },
|
||||
{ NULL, }
|
||||
};
|
||||
const struct type_and_structure_st *oi = trad_output_info;
|
||||
|
||||
return i2d_provided(a, EVP_PKEY_KEYPAIR, output_info, pp);
|
||||
if (!traditional)
|
||||
++oi;
|
||||
return i2d_provided(a, EVP_PKEY_KEYPAIR, oi, pp);
|
||||
}
|
||||
if (a->ameth != NULL && a->ameth->old_priv_encode != NULL) {
|
||||
|
||||
if (traditional && a->ameth != NULL && a->ameth->old_priv_encode != NULL)
|
||||
return a->ameth->old_priv_encode(a, pp);
|
||||
}
|
||||
|
||||
if (a->ameth != NULL && a->ameth->priv_encode != NULL) {
|
||||
PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8(a);
|
||||
int ret = 0;
|
||||
@ -119,6 +124,16 @@ int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp)
|
||||
{
|
||||
return i2d_PrivateKey_impl(a, pp, 1);
|
||||
}
|
||||
|
||||
int i2d_PKCS8PrivateKey(const EVP_PKEY *a, unsigned char **pp)
|
||||
{
|
||||
return i2d_PrivateKey_impl(a, pp, 0);
|
||||
}
|
||||
|
||||
int i2d_PublicKey(const EVP_PKEY *a, unsigned char **pp)
|
||||
{
|
||||
if (evp_pkey_is_provided(a)) {
|
||||
|
@ -41,9 +41,12 @@ corresponding B<PEM> function as described in L<PEM_read_PrivateKey(3)>.
|
||||
|
||||
These functions are currently the only way to store encrypted private keys using DER format.
|
||||
|
||||
Currently all the functions use BIOs or FILE pointers, there are no functions which
|
||||
work directly on memory: this can be readily worked around by converting the buffers
|
||||
to memory BIOs, see L<BIO_s_mem(3)> for details.
|
||||
Currently all the functions use BIOs or FILE pointers, there are no functions
|
||||
which support password-protection and work directly on memory: this can be
|
||||
readily worked around by converting the buffers to memory BIOs, see
|
||||
L<BIO_s_mem(3)> for details.
|
||||
If password-protection is not required, the L<i2d_PKCS8PrivateKey(3)> function
|
||||
encodes a private key to an unencrypted DER B<PKCS#8> form.
|
||||
|
||||
These functions make no assumption regarding the pass phrase received from the
|
||||
password callback.
|
||||
@ -59,9 +62,14 @@ and i2d_PKCS8PrivateKey_nid_fp() return 1 on success or 0 on error.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<i2d_PKCS8PrivateKey(3)>,
|
||||
L<PEM_read_PrivateKey(3)>,
|
||||
L<passphrase-encoding(7)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
L<i2d_PKCS8PrivateKey(3)> was added in OpenSSL 3.6.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
@ -3,10 +3,10 @@
|
||||
=head1 NAME
|
||||
|
||||
d2i_PrivateKey_ex, d2i_PrivateKey, d2i_PublicKey, d2i_KeyParams,
|
||||
d2i_AutoPrivateKey_ex, d2i_AutoPrivateKey, i2d_PrivateKey, i2d_PublicKey,
|
||||
i2d_KeyParams, i2d_KeyParams_bio, d2i_PrivateKey_ex_bio, d2i_PrivateKey_bio,
|
||||
d2i_PrivateKey_ex_fp, d2i_PrivateKey_fp, d2i_KeyParams_bio, i2d_PrivateKey_bio,
|
||||
i2d_PrivateKey_fp
|
||||
d2i_AutoPrivateKey_ex, d2i_AutoPrivateKey, i2d_PrivateKey,
|
||||
i2d_PKCS8PrivateKey, i2d_PublicKey, i2d_KeyParams, i2d_KeyParams_bio,
|
||||
d2i_PrivateKey_ex_bio, d2i_PrivateKey_bio, d2i_PrivateKey_ex_fp,
|
||||
d2i_PrivateKey_fp, d2i_KeyParams_bio, i2d_PrivateKey_bio, i2d_PrivateKey_fp
|
||||
- decode and encode functions for reading and saving EVP_PKEY structures
|
||||
|
||||
=head1 SYNOPSIS
|
||||
@ -29,6 +29,7 @@ i2d_PrivateKey_fp
|
||||
long length);
|
||||
|
||||
int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp);
|
||||
int i2d_PKCS8PrivateKey(const EVP_PKEY *a, unsigned char **pp);
|
||||
int i2d_PublicKey(const EVP_PKEY *a, unsigned char **pp);
|
||||
int i2d_KeyParams(const EVP_PKEY *a, unsigned char **pp);
|
||||
int i2d_KeyParams_bio(BIO *bp, const EVP_PKEY *pkey);
|
||||
@ -77,6 +78,8 @@ to automatically detect the private key format.
|
||||
|
||||
i2d_PrivateKey() encodes I<a>. It uses a key specific format or, if none is
|
||||
defined for that key type, PKCS#8 unencrypted PrivateKeyInfo format.
|
||||
i2d_PKCS8PrivateKey() does the same using only the PKCS#8 unencrypted
|
||||
PrivateKeyInfo format.
|
||||
i2d_PublicKey() does the same for public keys.
|
||||
i2d_KeyParams() does the same for key parameters.
|
||||
These functions are similar to the d2i_X509() functions; see L<d2i_X509(3)>.
|
||||
@ -106,9 +109,9 @@ d2i_PrivateKey_ex_fp(), d2i_PrivateKey_fp(), d2i_PublicKey(), d2i_KeyParams()
|
||||
and d2i_KeyParams_bio() functions return a valid B<EVP_PKEY> structure or NULL if
|
||||
an error occurs. The error code can be obtained by calling L<ERR_get_error(3)>.
|
||||
|
||||
i2d_PrivateKey(), i2d_PublicKey() and i2d_KeyParams() return the number of
|
||||
bytes successfully encoded or a negative value if an error occurs. The error
|
||||
code can be obtained by calling L<ERR_get_error(3)>.
|
||||
i2d_PrivateKey(), i2d_PKCS8PrivateKey(), i2d_PublicKey() and i2d_KeyParams()
|
||||
return the number of bytes successfully encoded or a negative value if an error
|
||||
occurs. The error code can be obtained by calling L<ERR_get_error(3)>.
|
||||
|
||||
i2d_PrivateKey_bio(), i2d_PrivateKey_fp() and i2d_KeyParams_bio() return 1 if
|
||||
successfully encoded or zero if an error occurs.
|
||||
@ -123,6 +126,8 @@ L<d2i_PKCS8PrivateKey_bio(3)>
|
||||
d2i_PrivateKey_ex(), d2i_PrivateKey_ex_bio(), d2i_PrivateKey_ex_fp(), and
|
||||
d2i_AutoPrivateKey_ex() were added in OpenSSL 3.0.
|
||||
|
||||
i2d_PKCS8PrivateKey() was added in OpenSSL 3.6.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
@ -1457,6 +1457,7 @@ EVP_PKEY *d2i_AutoPrivateKey_ex(EVP_PKEY **a, const unsigned char **pp,
|
||||
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
|
||||
long length);
|
||||
int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp);
|
||||
int i2d_PKCS8PrivateKey(const EVP_PKEY *a, unsigned char **pp);
|
||||
|
||||
int i2d_KeyParams(const EVP_PKEY *a, unsigned char **pp);
|
||||
EVP_PKEY *d2i_KeyParams(int type, EVP_PKEY **a, const unsigned char **pp,
|
||||
|
@ -286,6 +286,34 @@ static int encode_EVP_PKEY_prov(const char *file, const int line,
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int encode_EVP_PKEY_i2d(const char *unused_file,
|
||||
const int unused_line,
|
||||
void **encoded, long *encoded_len,
|
||||
void *object, int unused_selection,
|
||||
const char *unused_output_type,
|
||||
const char *unused_output_structure,
|
||||
const char *unused_pass,
|
||||
const char *unused_pcipher)
|
||||
{
|
||||
EVP_PKEY *pkey = object;
|
||||
unsigned char *buf = NULL, *p;
|
||||
int len, ok = 0;
|
||||
|
||||
if (!TEST_int_gt((len = i2d_PKCS8PrivateKey(pkey, NULL)), 0)
|
||||
|| !TEST_ptr(p = buf = OPENSSL_malloc(len))
|
||||
|| !TEST_int_eq(i2d_PKCS8PrivateKey(pkey, &p), len)
|
||||
|| !TEST_int_eq((int)(p - buf), len))
|
||||
goto end;
|
||||
|
||||
*encoded = buf;
|
||||
*encoded_len = len;
|
||||
buf = NULL;
|
||||
ok = 1;
|
||||
end:
|
||||
OPENSSL_free(buf);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int decode_EVP_PKEY_prov(const char *file, const int line,
|
||||
void **object, void *encoded, long encoded_len,
|
||||
const char *input_type,
|
||||
@ -567,6 +595,17 @@ static int test_unprotected_via_DER(const char *type, EVP_PKEY *key, int fips)
|
||||
dump_der, fips ? 0 : FLAG_FAIL_IF_FIPS);
|
||||
}
|
||||
|
||||
static int test_unprotected_via_i2d(const char *type, EVP_PKEY *key, int fips)
|
||||
{
|
||||
return test_encode_decode(__FILE__, __LINE__, type, key,
|
||||
OSSL_KEYMGMT_SELECT_KEYPAIR
|
||||
| OSSL_KEYMGMT_SELECT_ALL_PARAMETERS,
|
||||
"DER", "PrivateKeyInfo", NULL, NULL,
|
||||
encode_EVP_PKEY_i2d, decode_EVP_PKEY_prov,
|
||||
test_mem, check_unprotected_PKCS8_DER,
|
||||
dump_der, fips ? 0 : FLAG_FAIL_IF_FIPS);
|
||||
}
|
||||
|
||||
static int check_unprotected_PKCS8_PEM(const char *file, const int line,
|
||||
const char *type,
|
||||
const void *data, size_t data_len)
|
||||
@ -906,6 +945,10 @@ static int test_public_via_MSBLOB(const char *type, EVP_PKEY *key)
|
||||
{ \
|
||||
return test_unprotected_via_DER(KEYTYPEstr, key_##KEYTYPE, fips); \
|
||||
} \
|
||||
static int test_unprotected_##KEYTYPE##_via_i2d(void) \
|
||||
{ \
|
||||
return test_unprotected_via_i2d(KEYTYPEstr, key_##KEYTYPE, fips); \
|
||||
} \
|
||||
static int test_unprotected_##KEYTYPE##_via_PEM(void) \
|
||||
{ \
|
||||
return test_unprotected_via_PEM(KEYTYPEstr, key_##KEYTYPE, fips); \
|
||||
@ -929,6 +972,7 @@ static int test_public_via_MSBLOB(const char *type, EVP_PKEY *key)
|
||||
|
||||
#define ADD_TEST_SUITE(KEYTYPE) \
|
||||
ADD_TEST(test_unprotected_##KEYTYPE##_via_DER); \
|
||||
ADD_TEST(test_unprotected_##KEYTYPE##_via_i2d); \
|
||||
ADD_TEST(test_unprotected_##KEYTYPE##_via_PEM); \
|
||||
ADD_TEST(test_protected_##KEYTYPE##_via_DER); \
|
||||
ADD_TEST(test_protected_##KEYTYPE##_via_PEM); \
|
||||
|
@ -5925,3 +5925,4 @@ OSSL_AA_DIST_POINT_new ? 3_5_0 EXIST::FUNCTION:
|
||||
OSSL_AA_DIST_POINT_it ? 3_5_0 EXIST::FUNCTION:
|
||||
PEM_ASN1_write_bio_ctx ? 3_5_0 EXIST::FUNCTION:
|
||||
OPENSSL_sk_set_thunks ? 3_6_0 EXIST::FUNCTION:
|
||||
i2d_PKCS8PrivateKey ? 3_6_0 EXIST::FUNCTION:
|
||||
|
Loading…
x
Reference in New Issue
Block a user