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;
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)) {
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.
=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.
=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
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);
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)>.
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.
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.
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,
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,
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)
{ \
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); \
#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); \
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: