1 /* 2 * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <openssl/pem.h> 14 #include <openssl/err.h> 15 #include <openssl/pkcs12.h> 16 #include "p12_local.h" 17 18 /* PKCS#12 password change routine */ 19 20 static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass); 21 static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, 22 const char *newpass); 23 static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, 24 const char *newpass); 25 static int alg_get(const X509_ALGOR *alg, int *pnid, int *piter, 26 int *psaltlen); 27 28 /* 29 * Change the password on a PKCS#12 structure. 30 */ 31 32 int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass) 33 { 34 /* Check for NULL PKCS12 structure */ 35 36 if (p12 == NULL) { 37 ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_PKCS12_POINTER); 38 return 0; 39 } 40 41 /* Check the mac */ 42 43 if (!PKCS12_verify_mac(p12, oldpass, -1)) { 44 ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE); 45 return 0; 46 } 47 48 if (!newpass_p12(p12, oldpass, newpass)) { 49 ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR); 50 return 0; 51 } 52 53 return 1; 54 } 55 56 /* Parse the outer PKCS#12 structure */ 57 58 static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) 59 { 60 STACK_OF(PKCS7) *asafes = NULL, *newsafes = NULL; 61 STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 62 int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0; 63 PKCS7 *p7, *p7new; 64 ASN1_OCTET_STRING *p12_data_tmp = NULL, *macoct = NULL; 65 unsigned char mac[EVP_MAX_MD_SIZE]; 66 unsigned int maclen; 67 int rv = 0; 68 69 if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) 70 goto err; 71 if ((newsafes = sk_PKCS7_new_null()) == NULL) 72 goto err; 73 for (i = 0; i < sk_PKCS7_num(asafes); i++) { 74 p7 = sk_PKCS7_value(asafes, i); 75 bagnid = OBJ_obj2nid(p7->type); 76 if (bagnid == NID_pkcs7_data) { 77 bags = PKCS12_unpack_p7data(p7); 78 } else if (bagnid == NID_pkcs7_encrypted) { 79 bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); 80 if (p7->d.encrypted == NULL 81 || !alg_get(p7->d.encrypted->enc_data->algorithm, 82 &pbe_nid, &pbe_iter, &pbe_saltlen)) 83 goto err; 84 } else { 85 continue; 86 } 87 if (bags == NULL) 88 goto err; 89 if (!newpass_bags(bags, oldpass, newpass)) 90 goto err; 91 /* Repack bag in same form with new password */ 92 if (bagnid == NID_pkcs7_data) 93 p7new = PKCS12_pack_p7data(bags); 94 else 95 p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL, 96 pbe_saltlen, pbe_iter, bags); 97 if (p7new == NULL || !sk_PKCS7_push(newsafes, p7new)) 98 goto err; 99 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 100 bags = NULL; 101 } 102 103 /* Repack safe: save old safe in case of error */ 104 105 p12_data_tmp = p12->authsafes->d.data; 106 if ((p12->authsafes->d.data = ASN1_OCTET_STRING_new()) == NULL) 107 goto err; 108 if (!PKCS12_pack_authsafes(p12, newsafes)) 109 goto err; 110 111 if (!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) 112 goto err; 113 X509_SIG_getm(p12->mac->dinfo, NULL, &macoct); 114 if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) 115 goto err; 116 117 rv = 1; 118 119 err: 120 /* Restore old safe if necessary */ 121 if (rv == 1) { 122 ASN1_OCTET_STRING_free(p12_data_tmp); 123 } else if (p12_data_tmp != NULL) { 124 ASN1_OCTET_STRING_free(p12->authsafes->d.data); 125 p12->authsafes->d.data = p12_data_tmp; 126 } 127 sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 128 sk_PKCS7_pop_free(asafes, PKCS7_free); 129 sk_PKCS7_pop_free(newsafes, PKCS7_free); 130 return rv; 131 } 132 133 static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, 134 const char *newpass) 135 { 136 int i; 137 for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { 138 if (!newpass_bag(sk_PKCS12_SAFEBAG_value(bags, i), oldpass, newpass)) 139 return 0; 140 } 141 return 1; 142 } 143 144 /* Change password of safebag: only needs handle shrouded keybags */ 145 146 static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, 147 const char *newpass) 148 { 149 PKCS8_PRIV_KEY_INFO *p8; 150 X509_SIG *p8new; 151 int p8_nid, p8_saltlen, p8_iter; 152 const X509_ALGOR *shalg; 153 154 if (PKCS12_SAFEBAG_get_nid(bag) != NID_pkcs8ShroudedKeyBag) 155 return 1; 156 157 if ((p8 = PKCS8_decrypt(bag->value.shkeybag, oldpass, -1)) == NULL) 158 return 0; 159 X509_SIG_get0(bag->value.shkeybag, &shalg, NULL); 160 if (!alg_get(shalg, &p8_nid, &p8_iter, &p8_saltlen)) { 161 PKCS8_PRIV_KEY_INFO_free(p8); 162 return 0; 163 } 164 p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen, 165 p8_iter, p8); 166 PKCS8_PRIV_KEY_INFO_free(p8); 167 if (p8new == NULL) 168 return 0; 169 X509_SIG_free(bag->value.shkeybag); 170 bag->value.shkeybag = p8new; 171 return 1; 172 } 173 174 static int alg_get(const X509_ALGOR *alg, int *pnid, int *piter, 175 int *psaltlen) 176 { 177 PBEPARAM *pbe; 178 179 pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), alg->parameter); 180 if (pbe == NULL) 181 return 0; 182 *pnid = OBJ_obj2nid(alg->algorithm); 183 *piter = ASN1_INTEGER_get(pbe->iter); 184 *psaltlen = pbe->salt->length; 185 PBEPARAM_free(pbe); 186 return 1; 187 } 188