2 * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
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
13 #include <openssl/pem.h>
14 #include <openssl/err.h>
15 #include <openssl/pkcs12.h>
18 /* PKCS#12 password change routine */
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
,
23 static int newpass_bag(PKCS12_SAFEBAG
*bag
, const char *oldpass
,
25 static int alg_get(const X509_ALGOR
*alg
, int *pnid
, int *piter
,
29 * Change the password on a PKCS#12 structure.
32 int PKCS12_newpass(PKCS12
*p12
, const char *oldpass
, const char *newpass
)
34 /* Check for NULL PKCS12 structure */
37 PKCS12err(PKCS12_F_PKCS12_NEWPASS
,
38 PKCS12_R_INVALID_NULL_PKCS12_POINTER
);
44 if (!PKCS12_verify_mac(p12
, oldpass
, -1)) {
45 PKCS12err(PKCS12_F_PKCS12_NEWPASS
, PKCS12_R_MAC_VERIFY_FAILURE
);
49 if (!newpass_p12(p12
, oldpass
, newpass
)) {
50 PKCS12err(PKCS12_F_PKCS12_NEWPASS
, PKCS12_R_PARSE_ERROR
);
57 /* Parse the outer PKCS#12 structure */
59 static int newpass_p12(PKCS12
*p12
, const char *oldpass
, const char *newpass
)
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;
65 ASN1_OCTET_STRING
*p12_data_tmp
= NULL
, *macoct
= NULL
;
66 unsigned char mac
[EVP_MAX_MD_SIZE
];
70 if ((asafes
= PKCS12_unpack_authsafes(p12
)) == NULL
)
72 if ((newsafes
= sk_PKCS7_new_null()) == NULL
)
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
))
89 if (!newpass_bags(bags
, oldpass
, newpass
))
91 /* Repack bag in same form with new password */
92 if (bagnid
== NID_pkcs7_data
)
93 p7new
= PKCS12_pack_p7data(bags
);
95 p7new
= PKCS12_pack_p7encdata(pbe_nid
, newpass
, -1, NULL
,
96 pbe_saltlen
, pbe_iter
, bags
);
97 if (!p7new
|| !sk_PKCS7_push(newsafes
, p7new
))
99 sk_PKCS12_SAFEBAG_pop_free(bags
, PKCS12_SAFEBAG_free
);
103 /* Repack safe: save old safe in case of error */
105 p12_data_tmp
= p12
->authsafes
->d
.data
;
106 if ((p12
->authsafes
->d
.data
= ASN1_OCTET_STRING_new()) == NULL
)
108 if (!PKCS12_pack_authsafes(p12
, newsafes
))
111 if (!PKCS12_gen_mac(p12
, newpass
, -1, mac
, &maclen
))
113 X509_SIG_getm(p12
->mac
->dinfo
, NULL
, &macoct
);
114 if (!ASN1_OCTET_STRING_set(macoct
, mac
, maclen
))
120 /* Restore old safe if necessary */
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
;
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
);
133 static int newpass_bags(STACK_OF(PKCS12_SAFEBAG
) *bags
, const char *oldpass
,
137 for (i
= 0; i
< sk_PKCS12_SAFEBAG_num(bags
); i
++) {
138 if (!newpass_bag(sk_PKCS12_SAFEBAG_value(bags
, i
), oldpass
, newpass
))
144 /* Change password of safebag: only needs handle shrouded keybags */
146 static int newpass_bag(PKCS12_SAFEBAG
*bag
, const char *oldpass
,
149 PKCS8_PRIV_KEY_INFO
*p8
;
151 int p8_nid
, p8_saltlen
, p8_iter
;
152 const X509_ALGOR
*shalg
;
154 if (PKCS12_SAFEBAG_get_nid(bag
) != NID_pkcs8ShroudedKeyBag
)
157 if ((p8
= PKCS8_decrypt(bag
->value
.shkeybag
, oldpass
, -1)) == NULL
)
159 X509_SIG_get0(bag
->value
.shkeybag
, &shalg
, NULL
);
160 if (!alg_get(shalg
, &p8_nid
, &p8_iter
, &p8_saltlen
))
162 p8new
= PKCS8_encrypt(p8_nid
, NULL
, newpass
, -1, NULL
, p8_saltlen
,
164 PKCS8_PRIV_KEY_INFO_free(p8
);
167 X509_SIG_free(bag
->value
.shkeybag
);
168 bag
->value
.shkeybag
= p8new
;
172 static int alg_get(const X509_ALGOR
*alg
, int *pnid
, int *piter
,
176 pbe
= ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM
), alg
->parameter
);
179 *pnid
= OBJ_obj2nid(alg
->algorithm
);
180 *piter
= ASN1_INTEGER_get(pbe
->iter
);
181 *psaltlen
= pbe
->salt
->length
;