1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <stdio.h> 11e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 12e1051a39Sopenharmony_ci#include <openssl/pkcs12.h> 13e1051a39Sopenharmony_ci#include "p12_local.h" 14e1051a39Sopenharmony_ci 15e1051a39Sopenharmony_cistatic int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, 16e1051a39Sopenharmony_ci PKCS12_SAFEBAG *bag); 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_cistatic int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid) 19e1051a39Sopenharmony_ci{ 20e1051a39Sopenharmony_ci int idx; 21e1051a39Sopenharmony_ci X509_ATTRIBUTE *attr; 22e1051a39Sopenharmony_ci idx = EVP_PKEY_get_attr_by_NID(pkey, nid, -1); 23e1051a39Sopenharmony_ci if (idx < 0) 24e1051a39Sopenharmony_ci return 1; 25e1051a39Sopenharmony_ci attr = EVP_PKEY_get_attr(pkey, idx); 26e1051a39Sopenharmony_ci if (!X509at_add1_attr(&bag->attrib, attr)) 27e1051a39Sopenharmony_ci return 0; 28e1051a39Sopenharmony_ci return 1; 29e1051a39Sopenharmony_ci} 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_ciPKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey, 32e1051a39Sopenharmony_ci X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, 33e1051a39Sopenharmony_ci int iter, int mac_iter, int keytype, 34e1051a39Sopenharmony_ci OSSL_LIB_CTX *ctx, const char *propq) 35e1051a39Sopenharmony_ci{ 36e1051a39Sopenharmony_ci PKCS12 *p12 = NULL; 37e1051a39Sopenharmony_ci STACK_OF(PKCS7) *safes = NULL; 38e1051a39Sopenharmony_ci STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 39e1051a39Sopenharmony_ci PKCS12_SAFEBAG *bag = NULL; 40e1051a39Sopenharmony_ci int i; 41e1051a39Sopenharmony_ci unsigned char keyid[EVP_MAX_MD_SIZE]; 42e1051a39Sopenharmony_ci unsigned int keyidlen = 0; 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_ci /* Set defaults */ 45e1051a39Sopenharmony_ci if (nid_cert == NID_undef) 46e1051a39Sopenharmony_ci nid_cert = NID_aes_256_cbc; 47e1051a39Sopenharmony_ci if (nid_key == NID_undef) 48e1051a39Sopenharmony_ci nid_key = NID_aes_256_cbc; 49e1051a39Sopenharmony_ci if (!iter) 50e1051a39Sopenharmony_ci iter = PKCS12_DEFAULT_ITER; 51e1051a39Sopenharmony_ci if (!mac_iter) 52e1051a39Sopenharmony_ci mac_iter = PKCS12_DEFAULT_ITER; 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_ci if (pkey == NULL && cert == NULL && ca == NULL) { 55e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_ARGUMENT); 56e1051a39Sopenharmony_ci return NULL; 57e1051a39Sopenharmony_ci } 58e1051a39Sopenharmony_ci 59e1051a39Sopenharmony_ci if (pkey && cert) { 60e1051a39Sopenharmony_ci if (!X509_check_private_key(cert, pkey)) 61e1051a39Sopenharmony_ci return NULL; 62e1051a39Sopenharmony_ci if (!X509_digest(cert, EVP_sha1(), keyid, &keyidlen)) 63e1051a39Sopenharmony_ci return NULL; 64e1051a39Sopenharmony_ci } 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_ci if (cert) { 67e1051a39Sopenharmony_ci bag = PKCS12_add_cert(&bags, cert); 68e1051a39Sopenharmony_ci if (name && !PKCS12_add_friendlyname(bag, name, -1)) 69e1051a39Sopenharmony_ci goto err; 70e1051a39Sopenharmony_ci if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) 71e1051a39Sopenharmony_ci goto err; 72e1051a39Sopenharmony_ci } 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_ci /* Add all other certificates */ 75e1051a39Sopenharmony_ci for (i = 0; i < sk_X509_num(ca); i++) { 76e1051a39Sopenharmony_ci if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i))) 77e1051a39Sopenharmony_ci goto err; 78e1051a39Sopenharmony_ci } 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_ci if (bags && !PKCS12_add_safe_ex(&safes, bags, nid_cert, iter, pass, 81e1051a39Sopenharmony_ci ctx, propq)) 82e1051a39Sopenharmony_ci goto err; 83e1051a39Sopenharmony_ci 84e1051a39Sopenharmony_ci sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 85e1051a39Sopenharmony_ci bags = NULL; 86e1051a39Sopenharmony_ci 87e1051a39Sopenharmony_ci if (pkey) { 88e1051a39Sopenharmony_ci bag = PKCS12_add_key_ex(&bags, pkey, keytype, iter, nid_key, pass, 89e1051a39Sopenharmony_ci ctx, propq); 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci if (!bag) 92e1051a39Sopenharmony_ci goto err; 93e1051a39Sopenharmony_ci 94e1051a39Sopenharmony_ci if (!copy_bag_attr(bag, pkey, NID_ms_csp_name)) 95e1051a39Sopenharmony_ci goto err; 96e1051a39Sopenharmony_ci if (!copy_bag_attr(bag, pkey, NID_LocalKeySet)) 97e1051a39Sopenharmony_ci goto err; 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci if (name && !PKCS12_add_friendlyname(bag, name, -1)) 100e1051a39Sopenharmony_ci goto err; 101e1051a39Sopenharmony_ci if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) 102e1051a39Sopenharmony_ci goto err; 103e1051a39Sopenharmony_ci } 104e1051a39Sopenharmony_ci 105e1051a39Sopenharmony_ci if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL)) 106e1051a39Sopenharmony_ci goto err; 107e1051a39Sopenharmony_ci 108e1051a39Sopenharmony_ci sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 109e1051a39Sopenharmony_ci bags = NULL; 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_ci p12 = PKCS12_add_safes_ex(safes, 0, ctx, propq); 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ci if (p12 == NULL) 114e1051a39Sopenharmony_ci goto err; 115e1051a39Sopenharmony_ci 116e1051a39Sopenharmony_ci sk_PKCS7_pop_free(safes, PKCS7_free); 117e1051a39Sopenharmony_ci 118e1051a39Sopenharmony_ci safes = NULL; 119e1051a39Sopenharmony_ci 120e1051a39Sopenharmony_ci if ((mac_iter != -1) && 121e1051a39Sopenharmony_ci !PKCS12_set_mac(p12, pass, -1, NULL, 0, mac_iter, NULL)) 122e1051a39Sopenharmony_ci goto err; 123e1051a39Sopenharmony_ci 124e1051a39Sopenharmony_ci return p12; 125e1051a39Sopenharmony_ci 126e1051a39Sopenharmony_ci err: 127e1051a39Sopenharmony_ci PKCS12_free(p12); 128e1051a39Sopenharmony_ci sk_PKCS7_pop_free(safes, PKCS7_free); 129e1051a39Sopenharmony_ci sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 130e1051a39Sopenharmony_ci return NULL; 131e1051a39Sopenharmony_ci 132e1051a39Sopenharmony_ci} 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ciPKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert, 135e1051a39Sopenharmony_ci STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, 136e1051a39Sopenharmony_ci int mac_iter, int keytype) 137e1051a39Sopenharmony_ci{ 138e1051a39Sopenharmony_ci return PKCS12_create_ex(pass, name, pkey, cert, ca, nid_key, nid_cert, 139e1051a39Sopenharmony_ci iter, mac_iter, keytype, NULL, NULL); 140e1051a39Sopenharmony_ci} 141e1051a39Sopenharmony_ci 142e1051a39Sopenharmony_ciPKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert) 143e1051a39Sopenharmony_ci{ 144e1051a39Sopenharmony_ci PKCS12_SAFEBAG *bag = NULL; 145e1051a39Sopenharmony_ci char *name; 146e1051a39Sopenharmony_ci int namelen = -1; 147e1051a39Sopenharmony_ci unsigned char *keyid; 148e1051a39Sopenharmony_ci int keyidlen = -1; 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_ci /* Add user certificate */ 151e1051a39Sopenharmony_ci if ((bag = PKCS12_SAFEBAG_create_cert(cert)) == NULL) 152e1051a39Sopenharmony_ci goto err; 153e1051a39Sopenharmony_ci 154e1051a39Sopenharmony_ci /* 155e1051a39Sopenharmony_ci * Use friendlyName and localKeyID in certificate. (if present) 156e1051a39Sopenharmony_ci */ 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_ci name = (char *)X509_alias_get0(cert, &namelen); 159e1051a39Sopenharmony_ci 160e1051a39Sopenharmony_ci if (name && !PKCS12_add_friendlyname(bag, name, namelen)) 161e1051a39Sopenharmony_ci goto err; 162e1051a39Sopenharmony_ci 163e1051a39Sopenharmony_ci keyid = X509_keyid_get0(cert, &keyidlen); 164e1051a39Sopenharmony_ci 165e1051a39Sopenharmony_ci if (keyid && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) 166e1051a39Sopenharmony_ci goto err; 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_ci if (!pkcs12_add_bag(pbags, bag)) 169e1051a39Sopenharmony_ci goto err; 170e1051a39Sopenharmony_ci 171e1051a39Sopenharmony_ci return bag; 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci err: 174e1051a39Sopenharmony_ci PKCS12_SAFEBAG_free(bag); 175e1051a39Sopenharmony_ci return NULL; 176e1051a39Sopenharmony_ci 177e1051a39Sopenharmony_ci} 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ciPKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags, 180e1051a39Sopenharmony_ci EVP_PKEY *key, int key_usage, int iter, 181e1051a39Sopenharmony_ci int nid_key, const char *pass, 182e1051a39Sopenharmony_ci OSSL_LIB_CTX *ctx, const char *propq) 183e1051a39Sopenharmony_ci{ 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ci PKCS12_SAFEBAG *bag = NULL; 186e1051a39Sopenharmony_ci PKCS8_PRIV_KEY_INFO *p8 = NULL; 187e1051a39Sopenharmony_ci 188e1051a39Sopenharmony_ci /* Make a PKCS#8 structure */ 189e1051a39Sopenharmony_ci if ((p8 = EVP_PKEY2PKCS8(key)) == NULL) 190e1051a39Sopenharmony_ci goto err; 191e1051a39Sopenharmony_ci if (key_usage && !PKCS8_add_keyusage(p8, key_usage)) 192e1051a39Sopenharmony_ci goto err; 193e1051a39Sopenharmony_ci if (nid_key != -1) { 194e1051a39Sopenharmony_ci /* This call does not take ownership of p8 */ 195e1051a39Sopenharmony_ci bag = PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(nid_key, pass, -1, NULL, 0, 196e1051a39Sopenharmony_ci iter, p8, ctx, propq); 197e1051a39Sopenharmony_ci } else { 198e1051a39Sopenharmony_ci bag = PKCS12_SAFEBAG_create0_p8inf(p8); 199e1051a39Sopenharmony_ci if (bag != NULL) 200e1051a39Sopenharmony_ci p8 = NULL; /* bag takes ownership of p8 */ 201e1051a39Sopenharmony_ci } 202e1051a39Sopenharmony_ci /* This does not need to be in the error path */ 203e1051a39Sopenharmony_ci if (p8 != NULL) 204e1051a39Sopenharmony_ci PKCS8_PRIV_KEY_INFO_free(p8); 205e1051a39Sopenharmony_ci 206e1051a39Sopenharmony_ci if (bag == NULL || !pkcs12_add_bag(pbags, bag)) 207e1051a39Sopenharmony_ci goto err; 208e1051a39Sopenharmony_ci 209e1051a39Sopenharmony_ci return bag; 210e1051a39Sopenharmony_ci 211e1051a39Sopenharmony_ci err: 212e1051a39Sopenharmony_ci PKCS12_SAFEBAG_free(bag); 213e1051a39Sopenharmony_ci return NULL; 214e1051a39Sopenharmony_ci 215e1051a39Sopenharmony_ci} 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ciPKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, 218e1051a39Sopenharmony_ci EVP_PKEY *key, int key_usage, int iter, 219e1051a39Sopenharmony_ci int nid_key, const char *pass) 220e1051a39Sopenharmony_ci{ 221e1051a39Sopenharmony_ci return PKCS12_add_key_ex(pbags, key, key_usage, iter, nid_key, pass, 222e1051a39Sopenharmony_ci NULL, NULL); 223e1051a39Sopenharmony_ci} 224e1051a39Sopenharmony_ci 225e1051a39Sopenharmony_ciPKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags, 226e1051a39Sopenharmony_ci int nid_type, const unsigned char *value, int len) 227e1051a39Sopenharmony_ci{ 228e1051a39Sopenharmony_ci PKCS12_SAFEBAG *bag = NULL; 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ci /* Add secret, storing the value as an octet string */ 231e1051a39Sopenharmony_ci if ((bag = PKCS12_SAFEBAG_create_secret(nid_type, V_ASN1_OCTET_STRING, value, len)) == NULL) 232e1051a39Sopenharmony_ci goto err; 233e1051a39Sopenharmony_ci 234e1051a39Sopenharmony_ci if (!pkcs12_add_bag(pbags, bag)) 235e1051a39Sopenharmony_ci goto err; 236e1051a39Sopenharmony_ci 237e1051a39Sopenharmony_ci return bag; 238e1051a39Sopenharmony_ci err: 239e1051a39Sopenharmony_ci PKCS12_SAFEBAG_free(bag); 240e1051a39Sopenharmony_ci return NULL; 241e1051a39Sopenharmony_ci} 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_ciint PKCS12_add_safe_ex(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags, 244e1051a39Sopenharmony_ci int nid_safe, int iter, const char *pass, 245e1051a39Sopenharmony_ci OSSL_LIB_CTX *ctx, const char *propq) 246e1051a39Sopenharmony_ci{ 247e1051a39Sopenharmony_ci PKCS7 *p7 = NULL; 248e1051a39Sopenharmony_ci int free_safes = 0; 249e1051a39Sopenharmony_ci 250e1051a39Sopenharmony_ci if (*psafes == NULL) { 251e1051a39Sopenharmony_ci *psafes = sk_PKCS7_new_null(); 252e1051a39Sopenharmony_ci if (*psafes == NULL) 253e1051a39Sopenharmony_ci return 0; 254e1051a39Sopenharmony_ci free_safes = 1; 255e1051a39Sopenharmony_ci } 256e1051a39Sopenharmony_ci 257e1051a39Sopenharmony_ci if (nid_safe == 0) 258e1051a39Sopenharmony_ci#ifdef OPENSSL_NO_RC2 259e1051a39Sopenharmony_ci nid_safe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; 260e1051a39Sopenharmony_ci#else 261e1051a39Sopenharmony_ci nid_safe = NID_pbe_WithSHA1And40BitRC2_CBC; 262e1051a39Sopenharmony_ci#endif 263e1051a39Sopenharmony_ci 264e1051a39Sopenharmony_ci if (nid_safe == -1) 265e1051a39Sopenharmony_ci p7 = PKCS12_pack_p7data(bags); 266e1051a39Sopenharmony_ci else 267e1051a39Sopenharmony_ci p7 = PKCS12_pack_p7encdata_ex(nid_safe, pass, -1, NULL, 0, iter, bags, ctx, propq); 268e1051a39Sopenharmony_ci if (p7 == NULL) 269e1051a39Sopenharmony_ci goto err; 270e1051a39Sopenharmony_ci 271e1051a39Sopenharmony_ci if (!sk_PKCS7_push(*psafes, p7)) 272e1051a39Sopenharmony_ci goto err; 273e1051a39Sopenharmony_ci 274e1051a39Sopenharmony_ci return 1; 275e1051a39Sopenharmony_ci 276e1051a39Sopenharmony_ci err: 277e1051a39Sopenharmony_ci if (free_safes) { 278e1051a39Sopenharmony_ci sk_PKCS7_free(*psafes); 279e1051a39Sopenharmony_ci *psafes = NULL; 280e1051a39Sopenharmony_ci } 281e1051a39Sopenharmony_ci PKCS7_free(p7); 282e1051a39Sopenharmony_ci return 0; 283e1051a39Sopenharmony_ci} 284e1051a39Sopenharmony_ci 285e1051a39Sopenharmony_ciint PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags, 286e1051a39Sopenharmony_ci int nid_safe, int iter, const char *pass) 287e1051a39Sopenharmony_ci{ 288e1051a39Sopenharmony_ci return PKCS12_add_safe_ex(psafes, bags, nid_safe, iter, pass, NULL, NULL); 289e1051a39Sopenharmony_ci} 290e1051a39Sopenharmony_ci 291e1051a39Sopenharmony_cistatic int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, 292e1051a39Sopenharmony_ci PKCS12_SAFEBAG *bag) 293e1051a39Sopenharmony_ci{ 294e1051a39Sopenharmony_ci int free_bags = 0; 295e1051a39Sopenharmony_ci 296e1051a39Sopenharmony_ci if (pbags == NULL) 297e1051a39Sopenharmony_ci return 1; 298e1051a39Sopenharmony_ci if (*pbags == NULL) { 299e1051a39Sopenharmony_ci *pbags = sk_PKCS12_SAFEBAG_new_null(); 300e1051a39Sopenharmony_ci if (*pbags == NULL) 301e1051a39Sopenharmony_ci return 0; 302e1051a39Sopenharmony_ci free_bags = 1; 303e1051a39Sopenharmony_ci } 304e1051a39Sopenharmony_ci 305e1051a39Sopenharmony_ci if (!sk_PKCS12_SAFEBAG_push(*pbags, bag)) { 306e1051a39Sopenharmony_ci if (free_bags) { 307e1051a39Sopenharmony_ci sk_PKCS12_SAFEBAG_free(*pbags); 308e1051a39Sopenharmony_ci *pbags = NULL; 309e1051a39Sopenharmony_ci } 310e1051a39Sopenharmony_ci return 0; 311e1051a39Sopenharmony_ci } 312e1051a39Sopenharmony_ci 313e1051a39Sopenharmony_ci return 1; 314e1051a39Sopenharmony_ci 315e1051a39Sopenharmony_ci} 316e1051a39Sopenharmony_ci 317e1051a39Sopenharmony_ciPKCS12 *PKCS12_add_safes_ex(STACK_OF(PKCS7) *safes, int nid_p7, 318e1051a39Sopenharmony_ci OSSL_LIB_CTX *ctx, const char *propq) 319e1051a39Sopenharmony_ci{ 320e1051a39Sopenharmony_ci PKCS12 *p12; 321e1051a39Sopenharmony_ci 322e1051a39Sopenharmony_ci if (nid_p7 <= 0) 323e1051a39Sopenharmony_ci nid_p7 = NID_pkcs7_data; 324e1051a39Sopenharmony_ci p12 = PKCS12_init_ex(nid_p7, ctx, propq); 325e1051a39Sopenharmony_ci if (p12 == NULL) 326e1051a39Sopenharmony_ci return NULL; 327e1051a39Sopenharmony_ci 328e1051a39Sopenharmony_ci if (!PKCS12_pack_authsafes(p12, safes)) { 329e1051a39Sopenharmony_ci PKCS12_free(p12); 330e1051a39Sopenharmony_ci return NULL; 331e1051a39Sopenharmony_ci } 332e1051a39Sopenharmony_ci 333e1051a39Sopenharmony_ci return p12; 334e1051a39Sopenharmony_ci 335e1051a39Sopenharmony_ci} 336e1051a39Sopenharmony_ci 337e1051a39Sopenharmony_ciPKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7) 338e1051a39Sopenharmony_ci{ 339e1051a39Sopenharmony_ci return PKCS12_add_safes_ex(safes, nid_p7, NULL, NULL); 340e1051a39Sopenharmony_ci} 341