PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *p8, const char *pass, int passlen) { X509_ALGOR *dalg; ASN1_OCTET_STRING *doct; X509_SIG_get0(&dalg, &doct, p8); return PKCS12_item_decrypt_d2i(dalg, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass, passlen, doct, 1); }
/* * Encrypted PKCS#8 decoder. It operates by just decrypting the given blob * into a new blob, which is returned as an EMBEDDED STORE_INFO. The whole * decoding process will then start over with the new blob. */ static OSSL_STORE_INFO *try_decode_PKCS8Encrypted(const char *pem_name, const char *pem_header, const unsigned char *blob, size_t len, void **pctx, int *matchcount, const UI_METHOD *ui_method, void *ui_data) { X509_SIG *p8 = NULL; char kbuf[PEM_BUFSIZE]; char *pass = NULL; const X509_ALGOR *dalg = NULL; const ASN1_OCTET_STRING *doct = NULL; OSSL_STORE_INFO *store_info = NULL; BUF_MEM *mem = NULL; unsigned char *new_data = NULL; int new_data_len; if (pem_name != NULL) { if (strcmp(pem_name, PEM_STRING_PKCS8) != 0) return NULL; *matchcount = 1; } if ((p8 = d2i_X509_SIG(NULL, &blob, len)) == NULL) return NULL; *matchcount = 1; if ((mem = BUF_MEM_new()) == NULL) { OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, ERR_R_MALLOC_FAILURE); goto nop8; } if ((pass = file_get_pass(ui_method, kbuf, PEM_BUFSIZE, "PKCS8 decrypt password", ui_data)) == NULL) { OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, OSSL_STORE_R_BAD_PASSWORD_READ); goto nop8; } X509_SIG_get0(p8, &dalg, &doct); if (!PKCS12_pbe_crypt(dalg, pass, strlen(pass), doct->data, doct->length, &new_data, &new_data_len, 0)) goto nop8; mem->data = (char *)new_data; mem->max = mem->length = (size_t)new_data_len; X509_SIG_free(p8); store_info = ossl_store_info_new_EMBEDDED(PEM_STRING_PKCS8INF, mem); if (store_info == NULL) { OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS8ENCRYPTED, ERR_R_MALLOC_FAILURE); goto nop8; } return store_info; nop8: X509_SIG_free(p8); BUF_MEM_free(mem); return NULL; }
static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) { STACK_OF(PKCS7) *asafes = NULL, *newsafes = NULL; STACK_OF(PKCS12_SAFEBAG) *bags = NULL; int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0; PKCS7 *p7, *p7new; ASN1_OCTET_STRING *p12_data_tmp = NULL, *macoct = NULL; unsigned char mac[EVP_MAX_MD_SIZE]; unsigned int maclen; int rv = 0; if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) goto err; if ((newsafes = sk_PKCS7_new_null()) == NULL) goto err; for (i = 0; i < sk_PKCS7_num(asafes); i++) { p7 = sk_PKCS7_value(asafes, i); bagnid = OBJ_obj2nid(p7->type); if (bagnid == NID_pkcs7_data) { bags = PKCS12_unpack_p7data(p7); } else if (bagnid == NID_pkcs7_encrypted) { bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); if (!alg_get(p7->d.encrypted->enc_data->algorithm, &pbe_nid, &pbe_iter, &pbe_saltlen)) goto err; } else { continue; } if (bags == NULL) goto err; if (!newpass_bags(bags, oldpass, newpass)) goto err; /* Repack bag in same form with new password */ if (bagnid == NID_pkcs7_data) p7new = PKCS12_pack_p7data(bags); else p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL, pbe_saltlen, pbe_iter, bags); if (!p7new || !sk_PKCS7_push(newsafes, p7new)) goto err; sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); bags = NULL; } /* Repack safe: save old safe in case of error */ p12_data_tmp = p12->authsafes->d.data; if ((p12->authsafes->d.data = ASN1_OCTET_STRING_new()) == NULL) goto err; if (!PKCS12_pack_authsafes(p12, newsafes)) goto err; if (!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) goto err; X509_SIG_get0(NULL, &macoct, p12->mac->dinfo); if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) goto err; rv = 1; err: /* Restore old safe if necessary */ if (rv == 1) { ASN1_OCTET_STRING_free(p12_data_tmp); } else if (p12_data_tmp != NULL) { ASN1_OCTET_STRING_free(p12->authsafes->d.data); p12->authsafes->d.data = p12_data_tmp; } sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); sk_PKCS7_pop_free(asafes, PKCS7_free); sk_PKCS7_pop_free(newsafes, PKCS7_free); return rv; }