159191Skris/* p12_npas.c */ 2280304Sjkim/* 3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4280304Sjkim * 1999. 559191Skris */ 659191Skris/* ==================================================================== 759191Skris * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 859191Skris * 959191Skris * Redistribution and use in source and binary forms, with or without 1059191Skris * modification, are permitted provided that the following conditions 1159191Skris * are met: 1259191Skris * 1359191Skris * 1. Redistributions of source code must retain the above copyright 14280304Sjkim * notice, this list of conditions and the following disclaimer. 1559191Skris * 1659191Skris * 2. Redistributions in binary form must reproduce the above copyright 1759191Skris * notice, this list of conditions and the following disclaimer in 1859191Skris * the documentation and/or other materials provided with the 1959191Skris * distribution. 2059191Skris * 2159191Skris * 3. All advertising materials mentioning features or use of this 2259191Skris * software must display the following acknowledgment: 2359191Skris * "This product includes software developed by the OpenSSL Project 2459191Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2559191Skris * 2659191Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2759191Skris * endorse or promote products derived from this software without 2859191Skris * prior written permission. For written permission, please contact 2959191Skris * licensing@OpenSSL.org. 3059191Skris * 3159191Skris * 5. Products derived from this software may not be called "OpenSSL" 3259191Skris * nor may "OpenSSL" appear in their names without prior written 3359191Skris * permission of the OpenSSL Project. 3459191Skris * 3559191Skris * 6. Redistributions of any form whatsoever must retain the following 3659191Skris * acknowledgment: 3759191Skris * "This product includes software developed by the OpenSSL Project 3859191Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3959191Skris * 4059191Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4159191Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4259191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4359191Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4459191Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4559191Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4659191Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4759191Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4859191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4959191Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5059191Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5159191Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5259191Skris * ==================================================================== 5359191Skris * 5459191Skris * This product includes cryptographic software written by Eric Young 5559191Skris * (eay@cryptsoft.com). This product includes software written by Tim 5659191Skris * Hudson (tjh@cryptsoft.com). 5759191Skris * 5859191Skris */ 5959191Skris 6059191Skris#include <stdio.h> 6159191Skris#include <stdlib.h> 6259191Skris#include <string.h> 6359191Skris#include <openssl/pem.h> 6459191Skris#include <openssl/err.h> 6559191Skris#include <openssl/pkcs12.h> 6659191Skris 6759191Skris/* PKCS#12 password change routine */ 6859191Skris 69306196Sjkimstatic int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass); 70306196Sjkimstatic int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, 71306196Sjkim const char *newpass); 72306196Sjkimstatic int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, 73306196Sjkim const char *newpass); 7459191Skrisstatic int alg_get(X509_ALGOR *alg, int *pnid, int *piter, int *psaltlen); 7559191Skris 76280304Sjkim/* 7759191Skris * Change the password on a PKCS#12 structure. 7859191Skris */ 7959191Skris 80306196Sjkimint PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass) 8159191Skris{ 82280304Sjkim /* Check for NULL PKCS12 structure */ 8359191Skris 84280304Sjkim if (!p12) { 85280304Sjkim PKCS12err(PKCS12_F_PKCS12_NEWPASS, 86280304Sjkim PKCS12_R_INVALID_NULL_PKCS12_POINTER); 87280304Sjkim return 0; 88280304Sjkim } 8959191Skris 90280304Sjkim /* Check the mac */ 9159191Skris 92280304Sjkim if (!PKCS12_verify_mac(p12, oldpass, -1)) { 93280304Sjkim PKCS12err(PKCS12_F_PKCS12_NEWPASS, PKCS12_R_MAC_VERIFY_FAILURE); 94280304Sjkim return 0; 95280304Sjkim } 9659191Skris 97280304Sjkim if (!newpass_p12(p12, oldpass, newpass)) { 98280304Sjkim PKCS12err(PKCS12_F_PKCS12_NEWPASS, PKCS12_R_PARSE_ERROR); 99280304Sjkim return 0; 100280304Sjkim } 101280304Sjkim 102280304Sjkim return 1; 10359191Skris} 10459191Skris 10559191Skris/* Parse the outer PKCS#12 structure */ 10659191Skris 107306196Sjkimstatic int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) 10859191Skris{ 109306196Sjkim STACK_OF(PKCS7) *asafes = NULL, *newsafes = NULL; 110306196Sjkim STACK_OF(PKCS12_SAFEBAG) *bags = NULL; 111280304Sjkim int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0; 112280304Sjkim PKCS7 *p7, *p7new; 113306196Sjkim ASN1_OCTET_STRING *p12_data_tmp = NULL; 114280304Sjkim unsigned char mac[EVP_MAX_MD_SIZE]; 115280304Sjkim unsigned int maclen; 116306196Sjkim int rv = 0; 11768651Skris 118306196Sjkim if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) 119306196Sjkim goto err; 120306196Sjkim if ((newsafes = sk_PKCS7_new_null()) == NULL) 121306196Sjkim goto err; 122280304Sjkim for (i = 0; i < sk_PKCS7_num(asafes); i++) { 123280304Sjkim p7 = sk_PKCS7_value(asafes, i); 124280304Sjkim bagnid = OBJ_obj2nid(p7->type); 125280304Sjkim if (bagnid == NID_pkcs7_data) { 126280304Sjkim bags = PKCS12_unpack_p7data(p7); 127280304Sjkim } else if (bagnid == NID_pkcs7_encrypted) { 128280304Sjkim bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); 129280304Sjkim if (!alg_get(p7->d.encrypted->enc_data->algorithm, 130306196Sjkim &pbe_nid, &pbe_iter, &pbe_saltlen)) 131306196Sjkim goto err; 132306196Sjkim } else { 133280304Sjkim continue; 134280304Sjkim } 135306196Sjkim if (bags == NULL) 136306196Sjkim goto err; 137306196Sjkim if (!newpass_bags(bags, oldpass, newpass)) 138306196Sjkim goto err; 139280304Sjkim /* Repack bag in same form with new password */ 140280304Sjkim if (bagnid == NID_pkcs7_data) 141280304Sjkim p7new = PKCS12_pack_p7data(bags); 142280304Sjkim else 143280304Sjkim p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL, 144280304Sjkim pbe_saltlen, pbe_iter, bags); 145306196Sjkim if (!p7new || !sk_PKCS7_push(newsafes, p7new)) 146306196Sjkim goto err; 147280304Sjkim sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 148306196Sjkim bags = NULL; 149280304Sjkim } 15059191Skris 151280304Sjkim /* Repack safe: save old safe in case of error */ 15259191Skris 153280304Sjkim p12_data_tmp = p12->authsafes->d.data; 154306196Sjkim if ((p12->authsafes->d.data = ASN1_OCTET_STRING_new()) == NULL) 155306196Sjkim goto err; 156280304Sjkim if (!PKCS12_pack_authsafes(p12, newsafes)) 157306196Sjkim goto err; 158280304Sjkim if (!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) 159306196Sjkim goto err; 160306196Sjkim if (!ASN1_OCTET_STRING_set(p12->mac->dinfo->digest, mac, maclen)) 161306196Sjkim goto err; 16259191Skris 163306196Sjkim rv = 1; 16459191Skris 165306196Sjkimerr: 166306196Sjkim /* Restore old safe if necessary */ 167306196Sjkim if (rv == 1) { 168306196Sjkim ASN1_OCTET_STRING_free(p12_data_tmp); 169306196Sjkim } else if (p12_data_tmp != NULL) { 170306196Sjkim ASN1_OCTET_STRING_free(p12->authsafes->d.data); 171306196Sjkim p12->authsafes->d.data = p12_data_tmp; 172306196Sjkim } 173306196Sjkim sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 174306196Sjkim sk_PKCS7_pop_free(asafes, PKCS7_free); 175306196Sjkim sk_PKCS7_pop_free(newsafes, PKCS7_free); 176306196Sjkim return rv; 17759191Skris} 17859191Skris 179306196Sjkimstatic int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass, 180306196Sjkim const char *newpass) 18159191Skris{ 182280304Sjkim int i; 183280304Sjkim for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { 184280304Sjkim if (!newpass_bag(sk_PKCS12_SAFEBAG_value(bags, i), oldpass, newpass)) 185280304Sjkim return 0; 186280304Sjkim } 187280304Sjkim return 1; 18859191Skris} 18959191Skris 19059191Skris/* Change password of safebag: only needs handle shrouded keybags */ 19159191Skris 192306196Sjkimstatic int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, 193306196Sjkim const char *newpass) 19459191Skris{ 195280304Sjkim PKCS8_PRIV_KEY_INFO *p8; 196280304Sjkim X509_SIG *p8new; 197280304Sjkim int p8_nid, p8_saltlen, p8_iter; 19859191Skris 199280304Sjkim if (M_PKCS12_bag_type(bag) != NID_pkcs8ShroudedKeyBag) 200280304Sjkim return 1; 20159191Skris 202280304Sjkim if (!(p8 = PKCS8_decrypt(bag->value.shkeybag, oldpass, -1))) 203280304Sjkim return 0; 204280304Sjkim if (!alg_get(bag->value.shkeybag->algor, &p8_nid, &p8_iter, &p8_saltlen)) 205280304Sjkim return 0; 206306196Sjkim p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen, 207306196Sjkim p8_iter, p8); 208306196Sjkim PKCS8_PRIV_KEY_INFO_free(p8); 209306196Sjkim if (p8new == NULL) 210280304Sjkim return 0; 211280304Sjkim X509_SIG_free(bag->value.shkeybag); 212280304Sjkim bag->value.shkeybag = p8new; 213280304Sjkim return 1; 21459191Skris} 21559191Skris 21659191Skrisstatic int alg_get(X509_ALGOR *alg, int *pnid, int *piter, int *psaltlen) 21759191Skris{ 218280304Sjkim PBEPARAM *pbe; 219280304Sjkim const unsigned char *p; 220160814Ssimon 221280304Sjkim p = alg->parameter->value.sequence->data; 222280304Sjkim pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length); 223280304Sjkim if (!pbe) 224280304Sjkim return 0; 225280304Sjkim *pnid = OBJ_obj2nid(alg->algorithm); 226280304Sjkim *piter = ASN1_INTEGER_get(pbe->iter); 227280304Sjkim *psaltlen = pbe->salt->length; 228280304Sjkim PBEPARAM_free(pbe); 229280304Sjkim return 1; 23059191Skris} 231