New function PKC12_newpass()
authorDr. Stephen Henson <steve@openssl.org>
Fri, 3 Dec 1999 03:46:18 +0000 (03:46 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 3 Dec 1999 03:46:18 +0000 (03:46 +0000)
CHANGES
crypto/pkcs12/Makefile.ssl
crypto/pkcs12/p12_npas.c [new file with mode: 0644]
crypto/pkcs12/pk12err.c
crypto/pkcs12/pkcs12.h
doc/openssl.txt
util/libeay.num

diff --git a/CHANGES b/CHANGES
index d7970a3..5dcd6d8 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,10 @@
 
  Changes between 0.9.4 and 0.9.5  [xx XXX 1999]
 
 
  Changes between 0.9.4 and 0.9.5  [xx XXX 1999]
 
+  *) New function PKCS12_newpass() which changes the password of a
+     PKCS12 structure.
+     [Steve Henson]
+
   *) Modify X509_TRUST and X509_PURPOSE so it also uses a static and
      dynamic mix. In both cases the ids can be used as an index into the
      table. Also modified the X509_TRUST_add() and X509_PURPOSE_add()
   *) Modify X509_TRUST and X509_PURPOSE so it also uses a static and
      dynamic mix. In both cases the ids can be used as an index into the
      table. Also modified the X509_TRUST_add() and X509_PURPOSE_add()
index 7b3e9fd..ea97ab0 100644 (file)
@@ -24,10 +24,10 @@ APPS=
 LIB=$(TOP)/libcrypto.a
 LIBSRC= p12_add.c p12_attr.c p12_bags.c p12_crpt.c p12_crt.c p12_decr.c \
        p12_init.c p12_key.c p12_kiss.c p12_lib.c p12_mac.c p12_mutl.c\
 LIB=$(TOP)/libcrypto.a
 LIBSRC= p12_add.c p12_attr.c p12_bags.c p12_crpt.c p12_crt.c p12_decr.c \
        p12_init.c p12_key.c p12_kiss.c p12_lib.c p12_mac.c p12_mutl.c\
-       p12_sbag.c p12_utl.c pk12err.c
+       p12_sbag.c p12_utl.c p12_npas.c pk12err.c
 LIBOBJ= p12_add.o p12_attr.o p12_bags.o p12_crpt.o p12_crt.o p12_decr.o \
        p12_init.o p12_key.o p12_kiss.o p12_lib.o p12_mac.o p12_mutl.o\
 LIBOBJ= p12_add.o p12_attr.o p12_bags.o p12_crpt.o p12_crt.o p12_decr.o \
        p12_init.o p12_key.o p12_kiss.o p12_lib.o p12_mac.o p12_mutl.o\
-       p12_sbag.o p12_utl.o pk12err.o
+       p12_sbag.o p12_utl.o p12_npas.o pk12err.o
 
 SRC= $(LIBSRC)
 
 
 SRC= $(LIBSRC)
 
@@ -293,6 +293,23 @@ p12_mutl.o: ../../include/openssl/rsa.h ../../include/openssl/safestack.h
 p12_mutl.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
 p12_mutl.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
 p12_mutl.o: ../cryptlib.h
 p12_mutl.o: ../../include/openssl/sha.h ../../include/openssl/stack.h
 p12_mutl.o: ../../include/openssl/x509.h ../../include/openssl/x509_vfy.h
 p12_mutl.o: ../cryptlib.h
+p12_npas.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
+p12_npas.o: ../../include/openssl/blowfish.h ../../include/openssl/bn.h
+p12_npas.o: ../../include/openssl/cast.h ../../include/openssl/crypto.h
+p12_npas.o: ../../include/openssl/des.h ../../include/openssl/dh.h
+p12_npas.o: ../../include/openssl/dsa.h ../../include/openssl/e_os2.h
+p12_npas.o: ../../include/openssl/err.h ../../include/openssl/evp.h
+p12_npas.o: ../../include/openssl/idea.h ../../include/openssl/md2.h
+p12_npas.o: ../../include/openssl/md5.h ../../include/openssl/mdc2.h
+p12_npas.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+p12_npas.o: ../../include/openssl/opensslv.h ../../include/openssl/pem.h
+p12_npas.o: ../../include/openssl/pem2.h ../../include/openssl/pkcs12.h
+p12_npas.o: ../../include/openssl/pkcs7.h ../../include/openssl/rc2.h
+p12_npas.o: ../../include/openssl/rc4.h ../../include/openssl/rc5.h
+p12_npas.o: ../../include/openssl/ripemd.h ../../include/openssl/rsa.h
+p12_npas.o: ../../include/openssl/safestack.h ../../include/openssl/sha.h
+p12_npas.o: ../../include/openssl/stack.h ../../include/openssl/x509.h
+p12_npas.o: ../../include/openssl/x509_vfy.h
 p12_sbag.o: ../../include/openssl/asn1.h ../../include/openssl/asn1_mac.h
 p12_sbag.o: ../../include/openssl/bio.h ../../include/openssl/blowfish.h
 p12_sbag.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
 p12_sbag.o: ../../include/openssl/asn1.h ../../include/openssl/asn1_mac.h
 p12_sbag.o: ../../include/openssl/bio.h ../../include/openssl/blowfish.h
 p12_sbag.o: ../../include/openssl/bn.h ../../include/openssl/buffer.h
diff --git a/crypto/pkcs12/p12_npas.c b/crypto/pkcs12/p12_npas.c
new file mode 100644 (file)
index 0000000..ee71707
--- /dev/null
@@ -0,0 +1,212 @@
+/* p12_npas.c */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+
+/* PKCS#12 password change routine */
+
+static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass);
+static int newpass_bags(STACK *bags, char *oldpass,  char *newpass);
+static int newpass_bag(PKCS12_SAFEBAG *bag, char *oldpass, char *newpass);
+static int alg_get(X509_ALGOR *alg, int *pnid, int *piter, int *psaltlen);
+
+/* 
+ * Change the password on a PKCS#12 structure.
+ */
+
+int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass)
+{
+
+/* Check for NULL PKCS12 structure */
+
+if(!p12) {
+       PKCS12err(PKCS12_F_PKCS12_NEWPASS,PKCS12_R_INVALID_NULL_PKCS12_POINTER);
+       return 0;
+}
+
+/* Check the mac */
+
+if (!PKCS12_verify_mac(p12, oldpass, -1)) {
+       PKCS12err(PKCS12_F_PKCS12_NEWPASS,PKCS12_R_MAC_VERIFY_FAILURE);
+       return 0;
+}
+
+if (!newpass_p12(p12, oldpass, newpass)) {
+       PKCS12err(PKCS12_F_PKCS12_NEWPASS,PKCS12_R_PARSE_ERROR);
+       return 0;
+}
+
+return 1;
+
+}
+
+/* Parse the outer PKCS#12 structure */
+
+static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass)
+{
+       STACK *asafes, *newsafes, *bags;
+       int i, bagnid, pbe_nid, pbe_iter, pbe_saltlen;
+       PKCS7 *p7, *p7new;
+       ASN1_OCTET_STRING *p12_data_tmp = NULL, *macnew = NULL;
+       unsigned char mac[EVP_MAX_MD_SIZE];
+       unsigned int maclen;
+       if (!(asafes = M_PKCS12_unpack_authsafes(p12))) return 0;
+       if(!(newsafes = sk_new(NULL))) return 0;
+       for (i = 0; i < sk_num (asafes); i++) {
+               p7 = (PKCS7 *) sk_value(asafes, i);
+               bagnid = OBJ_obj2nid(p7->type);
+               if (bagnid == NID_pkcs7_data) {
+                       bags = M_PKCS12_unpack_p7data(p7);
+               } else if (bagnid == NID_pkcs7_encrypted) {
+                       bags = M_PKCS12_unpack_p7encdata(p7, oldpass, -1);
+                       alg_get(p7->d.encrypted->enc_data->algorithm,
+                               &pbe_nid, &pbe_iter, &pbe_saltlen);
+               } else continue;
+               if (!bags) {
+                       sk_pop_free(asafes, PKCS7_free);
+                       return 0;
+               }
+               if (!newpass_bags(bags, oldpass, newpass)) {
+                       sk_pop_free(bags, PKCS12_SAFEBAG_free);
+                       sk_pop_free(asafes, PKCS7_free);
+                       return 0;
+               }
+               /* 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);
+               sk_pop_free(bags, PKCS12_SAFEBAG_free);
+               if(!p7new) {
+                       sk_pop_free(asafes, PKCS7_free);
+                       return 0;
+               }
+               sk_push(newsafes, (char *)p7new);
+       }
+       sk_pop_free(asafes, PKCS7_free);
+
+       /* 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())) goto saferr;
+       if(!M_PKCS12_pack_authsafes(p12, newsafes)) goto saferr;
+
+       if(!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) goto saferr;
+       if(!(macnew = ASN1_OCTET_STRING_new())) goto saferr;
+       if(!ASN1_OCTET_STRING_set(macnew, mac, maclen)) goto saferr;
+       ASN1_OCTET_STRING_free(p12->mac->dinfo->digest);
+       p12->mac->dinfo->digest = macnew;
+       ASN1_OCTET_STRING_free(p12_data_tmp);
+
+       return 1;
+
+       saferr:
+       /* Restore old safe */
+       ASN1_OCTET_STRING_free(p12->authsafes->d.data);
+       ASN1_OCTET_STRING_free(macnew);
+       p12->authsafes->d.data = p12_data_tmp;
+       return 0;
+
+}
+
+
+static int newpass_bags(STACK *bags, char *oldpass,  char *newpass)
+{
+       int i;
+       for (i = 0; i < sk_num(bags); i++) {
+               if (!newpass_bag((PKCS12_SAFEBAG *)sk_value(bags, i),
+                                                oldpass, newpass)) return 0;
+       }
+       return 1;
+}
+
+/* Change password of safebag: only needs handle shrouded keybags */
+
+static int newpass_bag(PKCS12_SAFEBAG *bag, char *oldpass, char *newpass)
+{
+       PKCS8_PRIV_KEY_INFO *p8;
+       X509_SIG *p8new;
+       int p8_nid, p8_saltlen, p8_iter;
+
+       if(M_PKCS12_bag_type(bag) != NID_pkcs8ShroudedKeyBag) return 1;
+
+       if (!(p8 = M_PKCS12_decrypt_skey(bag, oldpass, -1))) return 0;
+       alg_get(bag->value.shkeybag->algor, &p8_nid, &p8_iter, &p8_saltlen);
+       if(!(p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen,
+                                                    p8_iter, p8))) return 0;
+       X509_SIG_free(bag->value.shkeybag);
+       bag->value.shkeybag = p8new;
+       return 1;
+}
+
+static int alg_get(X509_ALGOR *alg, int *pnid, int *piter, int *psaltlen)
+{
+        PBEPARAM *pbe;
+        unsigned char *p;
+        p = alg->parameter->value.sequence->data;
+        pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length);
+        *pnid = OBJ_obj2nid(alg->algorithm);
+       *piter = ASN1_INTEGER_get(pbe->iter);
+       *psaltlen = pbe->salt->length;
+        PBEPARAM_free(pbe);
+        return 0;
+}
index 5bbe2fa..00140a4 100644 (file)
@@ -79,6 +79,7 @@ static ERR_STRING_DATA PKCS12_str_functs[]=
 {ERR_PACK(0,PKCS12_F_PKCS12_KEY_GEN_UNI,0),    "PKCS12_key_gen_uni"},
 {ERR_PACK(0,PKCS12_F_PKCS12_MAKE_KEYBAG,0),    "PKCS12_MAKE_KEYBAG"},
 {ERR_PACK(0,PKCS12_F_PKCS12_MAKE_SHKEYBAG,0),  "PKCS12_MAKE_SHKEYBAG"},
 {ERR_PACK(0,PKCS12_F_PKCS12_KEY_GEN_UNI,0),    "PKCS12_key_gen_uni"},
 {ERR_PACK(0,PKCS12_F_PKCS12_MAKE_KEYBAG,0),    "PKCS12_MAKE_KEYBAG"},
 {ERR_PACK(0,PKCS12_F_PKCS12_MAKE_SHKEYBAG,0),  "PKCS12_MAKE_SHKEYBAG"},
+{ERR_PACK(0,PKCS12_F_PKCS12_NEWPASS,0),        "PKCS12_NEWPASS"},
 {ERR_PACK(0,PKCS12_F_PKCS12_PACK_P7DATA,0),    "PKCS12_pack_p7data"},
 {ERR_PACK(0,PKCS12_F_PKCS12_PACK_P7ENCDATA,0), "PKCS12_pack_p7encdata"},
 {ERR_PACK(0,PKCS12_F_PKCS12_PACK_SAFEBAG,0),   "PKCS12_pack_safebag"},
 {ERR_PACK(0,PKCS12_F_PKCS12_PACK_P7DATA,0),    "PKCS12_pack_p7data"},
 {ERR_PACK(0,PKCS12_F_PKCS12_PACK_P7ENCDATA,0), "PKCS12_pack_p7encdata"},
 {ERR_PACK(0,PKCS12_F_PKCS12_PACK_SAFEBAG,0),   "PKCS12_pack_safebag"},
index f79cc23..254000f 100644 (file)
@@ -273,6 +273,7 @@ int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12);
 int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12);
 PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12);
 PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12);
 int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12);
 PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12);
 PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12);
+int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass);
 
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
 
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
@@ -296,6 +297,7 @@ PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12);
 #define PKCS12_F_PKCS12_KEY_GEN_UNI                     111
 #define PKCS12_F_PKCS12_MAKE_KEYBAG                     112
 #define PKCS12_F_PKCS12_MAKE_SHKEYBAG                   113
 #define PKCS12_F_PKCS12_KEY_GEN_UNI                     111
 #define PKCS12_F_PKCS12_MAKE_KEYBAG                     112
 #define PKCS12_F_PKCS12_MAKE_SHKEYBAG                   113
+#define PKCS12_F_PKCS12_NEWPASS                                 128
 #define PKCS12_F_PKCS12_PACK_P7DATA                     114
 #define PKCS12_F_PKCS12_PACK_P7ENCDATA                  115
 #define PKCS12_F_PKCS12_PACK_SAFEBAG                    117
 #define PKCS12_F_PKCS12_PACK_P7DATA                     114
 #define PKCS12_F_PKCS12_PACK_P7ENCDATA                  115
 #define PKCS12_F_PKCS12_PACK_SAFEBAG                    117
index 08e2476..cae41f0 100644 (file)
@@ -494,16 +494,16 @@ extension in a human or machine readable form.
 
 1. Initialisation and cleanup.
 
 
 1. Initialisation and cleanup.
 
-X509V3_add_standard_extensions();
-
-This function should be called before any other extension code. It adds support
-for some common PKIX and Netscape extensions. Additional custom extensions can
-be added as well (see later).
+No special initialisation is needed before calling the extension functions.
+You used to have to call X509V3_add_standard_extensions(); but this is no longer
+required and this function no longer does anything.
 
 void X509V3_EXT_cleanup(void);
 
 
 void X509V3_EXT_cleanup(void);
 
-This function should be called last to cleanup the extension code. After this
-call no other extension calls should be made.
+This function should be called to cleanup the extension code if any custom
+extensions have been added. If no custom extensions have been added then this
+call does nothing. After this call all custom extension code is freed up but
+you can still use the standard extensions.
 
 2. Printing and parsing extensions.
 
 
 2. Printing and parsing extensions.
 
@@ -917,7 +917,7 @@ d2i_PKCS12_fp(fp, p12)
 
 This is the same but for a FILE pointer.
 
 
 This is the same but for a FILE pointer.
 
-3. Parsing and creation functions.
+3. High level functions.
 
 3.1 Parsing with PKCS12_parse().
 
 
 3.1 Parsing with PKCS12_parse().
 
@@ -955,6 +955,14 @@ p12 = PKCS12_create(pass, "My Certificate", pkey, cert, NULL, 0,0,0,0,0);
 i2d_PKCS12_fp(fp, p12);
 PKCS12_free(p12);
 
 i2d_PKCS12_fp(fp, p12);
 PKCS12_free(p12);
 
+3.3 Changing a PKCS#12 structure password.
+
+int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass);
+
+This changes the password of an already existing PKCS#12 structure. oldpass
+is the old password and newpass is the new one. An error occurs if the old
+password is incorrect.
+
 LOW LEVEL FUNCTIONS.
 
 In some cases the high level functions do not provide the necessary
 LOW LEVEL FUNCTIONS.
 
 In some cases the high level functions do not provide the necessary
index bf3d063..3a0562e 100755 (executable)
@@ -2113,3 +2113,4 @@ DIRECTORYSTRING_new                     2137
 sk_ASN1_STRING_TABLE_new                2138
 sk_X509_TRUST_delete                    2139
 X509_add_trust_object                   2140
 sk_ASN1_STRING_TABLE_new                2138
 sk_X509_TRUST_delete                    2139
 X509_add_trust_object                   2140
+PKCS12_newpass                          2141