1 /* 2 * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (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_lcl.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) { 37 PKCS12err(PKCS12_F_PKCS12_NEWPASS, 38 PKCS12_R_INVALID_NULL_PKCS12_POINTER); 39 return 0; 40 } 41 42 /* Check the mac */ 43 44 if (!PKCS12_verify_mac(p12, oldpass, -1)) { 45 PKCS12err(PKCS12_F_PKCS12_NEWPASS, PKCS12_R_MAC_VERIFY_FAILURE); 46 return 0; 47 } 48 49 if (!newpass_p12(p12, oldpass, newpass)) { 50 PKCS12err(PKCS12_F_PKCS12_NEWPASS, PKCS12_R_PARSE_ERROR); 51 return 0; 52 } 53 54 return 1; 55 } 56 57 /* Parse the outer PKCS#12 structure */ 58 59 static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) 60 { 61 STACK_OF(PKCS7) *asafes = NULL, *newsafes = NULL; 62 STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 63 int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0; 64 PKCS7 *p7, *p7new; 65 ASN1_OCTET_STRING *p12_data_tmp = NULL, *macoct = NULL; 66 unsigned char mac[EVP_MAX_MD_SIZE]; 67 unsigned int maclen; 68 int rv = 0; 69 70 if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) 71 goto err; 72 if ((newsafes = sk_PKCS7_new_null()) == NULL) 73 goto err; 74 for (i = 0; i < sk_PKCS7_num(asafes); i++) { 75 p7 = sk_PKCS7_value(asafes, i); 76 bagnid = OBJ_obj2nid(p7->type); 77 if (bagnid == NID_pkcs7_data) { 78 bags = PKCS12_unpack_p7data(p7); 79 } else if (bagnid == NID_pkcs7_encrypted) { 80 bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); 81 if (!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 || !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 return 0; 162 p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen, 163 p8_iter, p8); 164 PKCS8_PRIV_KEY_INFO_free(p8); 165 if (p8new == NULL) 166 return 0; 167 X509_SIG_free(bag->value.shkeybag); 168 bag->value.shkeybag = p8new; 169 return 1; 170 } 171 172 static int alg_get(const X509_ALGOR *alg, int *pnid, int *piter, 173 int *psaltlen) 174 { 175 PBEPARAM *pbe; 176 pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), alg->parameter); 177 if (!pbe) 178 return 0; 179 *pnid = OBJ_obj2nid(alg->algorithm); 180 *piter = ASN1_INTEGER_get(pbe->iter); 181 *psaltlen = pbe->salt->length; 182 PBEPARAM_free(pbe); 183 return 1; 184 } 185