Fix PKCS#12 creation error when certificate contains auxiliary data
Prefer friendly name passed by the caller and calculated local key id to ones found in certificate auxiliary data when creating PKCS#12. Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/21675)
This commit is contained in:
parent
ed4a71d18d
commit
388a8e7314
@ -16,6 +16,12 @@ static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
|
||||
PKCS12_SAFEBAG *bag);
|
||||
static int pkcs12_remove_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
|
||||
PKCS12_SAFEBAG *bag);
|
||||
static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
|
||||
X509 *cert,
|
||||
const char *name,
|
||||
int namelen,
|
||||
unsigned char *keyid,
|
||||
int keyidlen);
|
||||
|
||||
static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
|
||||
{
|
||||
@ -39,6 +45,9 @@ PKCS12 *PKCS12_create_ex2(const char *pass, const char *name, EVP_PKEY *pkey,
|
||||
int i, cbret;
|
||||
unsigned char keyid[EVP_MAX_MD_SIZE];
|
||||
unsigned int keyidlen = 0;
|
||||
int namelen = -1;
|
||||
unsigned char *pkeyid = NULL;
|
||||
int pkeyidlen = -1;
|
||||
|
||||
/* Set defaults */
|
||||
if (nid_cert == NID_undef)
|
||||
@ -63,11 +72,16 @@ PKCS12 *PKCS12_create_ex2(const char *pass, const char *name, EVP_PKEY *pkey,
|
||||
}
|
||||
|
||||
if (cert) {
|
||||
bag = PKCS12_add_cert(&bags, cert);
|
||||
if (name && !PKCS12_add_friendlyname(bag, name, -1))
|
||||
goto err;
|
||||
if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
|
||||
goto err;
|
||||
if (name == NULL)
|
||||
name = (char *)X509_alias_get0(cert, &namelen);
|
||||
if (keyidlen > 0) {
|
||||
pkeyid = keyid;
|
||||
pkeyidlen = keyidlen;
|
||||
} else {
|
||||
pkeyid = X509_keyid_get0(cert, &pkeyidlen);
|
||||
}
|
||||
|
||||
bag = pkcs12_add_cert_bag(&bags, cert, name, namelen, pkeyid, pkeyidlen);
|
||||
if (cb != NULL) {
|
||||
cbret = cb(bag, cbarg);
|
||||
if (cbret == -1) {
|
||||
@ -175,30 +189,23 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
|
||||
iter, mac_iter, keytype, NULL, NULL);
|
||||
}
|
||||
|
||||
PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
|
||||
static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
|
||||
X509 *cert,
|
||||
const char *name,
|
||||
int namelen,
|
||||
unsigned char *keyid,
|
||||
int keyidlen)
|
||||
{
|
||||
PKCS12_SAFEBAG *bag = NULL;
|
||||
char *name;
|
||||
int namelen = -1;
|
||||
unsigned char *keyid;
|
||||
int keyidlen = -1;
|
||||
|
||||
/* Add user certificate */
|
||||
if ((bag = PKCS12_SAFEBAG_create_cert(cert)) == NULL)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Use friendlyName and localKeyID in certificate. (if present)
|
||||
*/
|
||||
|
||||
name = (char *)X509_alias_get0(cert, &namelen);
|
||||
|
||||
if (name && !PKCS12_add_friendlyname(bag, name, namelen))
|
||||
if (name != NULL && !PKCS12_add_friendlyname(bag, name, namelen))
|
||||
goto err;
|
||||
|
||||
keyid = X509_keyid_get0(cert, &keyidlen);
|
||||
|
||||
if (keyid && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
|
||||
if (keyid != NULL && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
|
||||
goto err;
|
||||
|
||||
if (!pkcs12_add_bag(pbags, bag))
|
||||
@ -209,7 +216,22 @@ PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
|
||||
err:
|
||||
PKCS12_SAFEBAG_free(bag);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
|
||||
{
|
||||
char *name = NULL;
|
||||
int namelen = -1;
|
||||
unsigned char *keyid = NULL;
|
||||
int keyidlen = -1;
|
||||
|
||||
/*
|
||||
* Use friendlyName and localKeyID in certificate. (if present)
|
||||
*/
|
||||
name = (char *)X509_alias_get0(cert, &namelen);
|
||||
keyid = X509_keyid_get0(cert, &keyidlen);
|
||||
|
||||
return pkcs12_add_cert_bag(pbags, cert, name, namelen, keyid, keyidlen);
|
||||
}
|
||||
|
||||
PKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags,
|
||||
|
@ -882,6 +882,70 @@ err:
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pkcs12_recreate_test(void)
|
||||
{
|
||||
int ret = 0;
|
||||
X509 *cert = NULL;
|
||||
X509 *cert_parsed = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_PKEY *pkey_parsed = NULL;
|
||||
PKCS12 *p12 = NULL;
|
||||
PKCS12 *p12_parsed = NULL;
|
||||
PKCS12 *p12_recreated = NULL;
|
||||
const unsigned char *cert_bytes = CERT1;
|
||||
const unsigned char *key_bytes = KEY1;
|
||||
BIO *bio = NULL;
|
||||
|
||||
cert = d2i_X509(NULL, &cert_bytes, sizeof(CERT1));
|
||||
if (!TEST_ptr(cert))
|
||||
goto err;
|
||||
pkey = d2i_AutoPrivateKey(NULL, &key_bytes, sizeof(KEY1));
|
||||
if (!TEST_ptr(pkey))
|
||||
goto err;
|
||||
p12 = PKCS12_create("pass", NULL, pkey, cert, NULL, NID_aes_256_cbc,
|
||||
NID_aes_256_cbc, 2, 1, 0);
|
||||
if (!TEST_ptr(p12))
|
||||
goto err;
|
||||
if (!TEST_int_eq(ERR_peek_error(), 0))
|
||||
goto err;
|
||||
|
||||
bio = BIO_new(BIO_s_mem());
|
||||
if (!TEST_ptr(bio))
|
||||
goto err;
|
||||
if (!TEST_int_eq(i2d_PKCS12_bio(bio, p12), 1))
|
||||
goto err;
|
||||
p12_parsed = PKCS12_init_ex(NID_pkcs7_data, testctx, NULL);
|
||||
if (!TEST_ptr(p12_parsed))
|
||||
goto err;
|
||||
p12_parsed = d2i_PKCS12_bio(bio, &p12_parsed);
|
||||
if (!TEST_ptr(p12_parsed))
|
||||
goto err;
|
||||
if (!TEST_int_eq(PKCS12_parse(p12_parsed, "pass", &pkey_parsed,
|
||||
&cert_parsed, NULL), 1))
|
||||
goto err;
|
||||
|
||||
/* cert_parsed also contains auxiliary data */
|
||||
p12_recreated = PKCS12_create("new_pass", NULL, pkey_parsed, cert_parsed,
|
||||
NULL, NID_aes_256_cbc, NID_aes_256_cbc,
|
||||
2, 1, 0);
|
||||
if (!TEST_ptr(p12_recreated))
|
||||
goto err;
|
||||
if (!TEST_int_eq(ERR_peek_error(), 0))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
BIO_free(bio);
|
||||
PKCS12_free(p12);
|
||||
PKCS12_free(p12_parsed);
|
||||
PKCS12_free(p12_recreated);
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_free(pkey_parsed);
|
||||
X509_free(cert);
|
||||
X509_free(cert_parsed);
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef enum OPTION_choice {
|
||||
OPT_ERR = -1,
|
||||
OPT_EOF = 0,
|
||||
@ -963,6 +1027,8 @@ int setup_tests(void)
|
||||
if (default_libctx)
|
||||
ADD_TEST(pkcs12_create_test);
|
||||
#endif
|
||||
if (default_libctx)
|
||||
ADD_TEST(pkcs12_recreate_test);
|
||||
ADD_ALL_TESTS(test_single_key_enc_pass, OSSL_NELEM(passwords));
|
||||
ADD_ALL_TESTS(test_single_key_enc_iter, OSSL_NELEM(iters));
|
||||
ADD_TEST(test_single_key_with_attrs);
|
||||
|
Loading…
x
Reference in New Issue
Block a user