diff options
author | cvs2hg <devnull@localhost> | 2005-11-15 18:19:19 +0000 |
---|---|---|
committer | cvs2hg <devnull@localhost> | 2005-11-15 18:19:19 +0000 |
commit | 18c92e41a5b4a92c2b8a876f02348b58c8ff7b05 (patch) | |
tree | 5270801605a7bfd0559bf4cbfa3bec42a4136adb /security/nss/lib/pkcs12 | |
parent | 415c3e0a7c1c85b6aa5563eaac9dd5d6bedbc750 (diff) | |
download | nss-hg-JSS_4_2_BETA1.tar.gz |
fixup commit for tag 'JSS_4_2_BETA1'JSS_4_2_BETA1
Diffstat (limited to 'security/nss/lib/pkcs12')
-rw-r--r-- | security/nss/lib/pkcs12/Makefile | 81 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/config.mk | 48 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/manifest.mn | 62 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12.h | 208 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12creat.c | 254 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12d.c | 3473 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12dec.c | 696 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12e.c | 2368 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12exp.c | 1410 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12local.c | 1371 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12local.h | 91 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12plcy.c | 201 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12plcy.h | 63 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12t.h | 187 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/p12tmpl.c | 323 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/pkcs12.h | 74 | ||||
-rw-r--r-- | security/nss/lib/pkcs12/pkcs12t.h | 398 |
17 files changed, 0 insertions, 11308 deletions
diff --git a/security/nss/lib/pkcs12/Makefile b/security/nss/lib/pkcs12/Makefile deleted file mode 100644 index 09182f0ea..000000000 --- a/security/nss/lib/pkcs12/Makefile +++ /dev/null @@ -1,81 +0,0 @@ -#! gmake -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is the Netscape security libraries. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1994-2000 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - - -####################################################################### -# (1) Include initial platform-independent assignments (MANDATORY). # -####################################################################### - -include manifest.mn - -####################################################################### -# (2) Include "global" configuration information. (OPTIONAL) # -####################################################################### - -include $(CORE_DEPTH)/coreconf/config.mk - -####################################################################### -# (3) Include "component" configuration information. (OPTIONAL) # -####################################################################### - - - -####################################################################### -# (4) Include "local" platform-dependent assignments (OPTIONAL). # -####################################################################### - -include config.mk - -####################################################################### -# (5) Execute "global" rules. (OPTIONAL) # -####################################################################### - -include $(CORE_DEPTH)/coreconf/rules.mk - -####################################################################### -# (6) Execute "component" rules. (OPTIONAL) # -####################################################################### - - - -####################################################################### -# (7) Execute "local" rules. (OPTIONAL). # -####################################################################### - - - diff --git a/security/nss/lib/pkcs12/config.mk b/security/nss/lib/pkcs12/config.mk deleted file mode 100644 index 9554ab4a5..000000000 --- a/security/nss/lib/pkcs12/config.mk +++ /dev/null @@ -1,48 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is the Netscape security libraries. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1994-2000 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - - -# -# Override TARGETS variable so that only static libraries -# are specifed as dependencies within rules.mk. -# - -TARGETS = $(LIBRARY) -SHARED_LIBRARY = -IMPORT_LIBRARY = -PROGRAM = - diff --git a/security/nss/lib/pkcs12/manifest.mn b/security/nss/lib/pkcs12/manifest.mn deleted file mode 100644 index af76ca2ed..000000000 --- a/security/nss/lib/pkcs12/manifest.mn +++ /dev/null @@ -1,62 +0,0 @@ -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is the Netscape security libraries. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1994-2000 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -CORE_DEPTH = ../../.. - -EXPORTS = \ - pkcs12t.h \ - pkcs12.h \ - p12plcy.h \ - p12.h \ - p12t.h \ - $(NULL) - -MODULE = nss - -CSRCS = \ - p12local.c \ - p12creat.c \ - p12dec.c \ - p12plcy.c \ - p12tmpl.c \ - p12e.c \ - p12d.c \ - $(NULL) - -REQUIRES = dbm - -LIBRARY_NAME = pkcs12 diff --git a/security/nss/lib/pkcs12/p12.h b/security/nss/lib/pkcs12/p12.h deleted file mode 100644 index 6eb6ecfed..000000000 --- a/security/nss/lib/pkcs12/p12.h +++ /dev/null @@ -1,208 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -#ifndef _P12_H_ -#define _P12_H_ - -#include "secoid.h" -#include "key.h" -#include "secpkcs7.h" -#include "p12t.h" - -typedef int (PR_CALLBACK * PKCS12OpenFunction)(void *arg); -typedef int (PR_CALLBACK * PKCS12ReadFunction)(void *arg, - unsigned char *buffer, - unsigned int *lenRead, - unsigned int maxLen); -typedef int (PR_CALLBACK * PKCS12WriteFunction)(void *arg, - unsigned char *buffer, - unsigned int *bufLen, - unsigned int *lenWritten); -typedef int (PR_CALLBACK * PKCS12CloseFunction)(void *arg); -typedef SECStatus (PR_CALLBACK * PKCS12UnicodeConvertFunction)( - PRArenaPool *arena, - SECItem *dest, SECItem *src, - PRBool toUnicode, - PRBool swapBytes); -typedef void (PR_CALLBACK * SEC_PKCS12EncoderOutputCallback)( - void *arg, const char *buf, - unsigned long len); -typedef void (PR_CALLBACK * SEC_PKCS12DecoderOutputCallback)( - void *arg, const char *buf, - unsigned long len); -typedef SECItem * (PR_CALLBACK * SEC_PKCS12NicknameCollisionCallback)( - SECItem *old_nickname, - PRBool *cancel, - void *arg); - - - - -typedef SECStatus (PR_CALLBACK *digestOpenFn)(void *arg, PRBool readData); -typedef SECStatus (PR_CALLBACK *digestCloseFn)(void *arg, PRBool removeFile); -typedef int (PR_CALLBACK *digestIOFn)(void *arg, unsigned char *buf, - unsigned long len); - -typedef struct SEC_PKCS12ExportContextStr SEC_PKCS12ExportContext; -typedef struct SEC_PKCS12SafeInfoStr SEC_PKCS12SafeInfo; -typedef struct SEC_PKCS12DecoderContextStr SEC_PKCS12DecoderContext; -typedef struct SEC_PKCS12DecoderItemStr SEC_PKCS12DecoderItem; - -struct sec_PKCS12PasswordModeInfo { - SECItem *password; - SECOidTag algorithm; -}; - -struct sec_PKCS12PublicKeyModeInfo { - CERTCertificate *cert; - CERTCertDBHandle *certDb; - SECOidTag algorithm; - int keySize; -}; - -struct SEC_PKCS12DecoderItemStr { - SECItem *der; - SECOidTag type; - PRBool hasKey; - SECItem *friendlyName; /* UTF-8 string */ -}; - - -SEC_BEGIN_PROTOS - -SEC_PKCS12SafeInfo * -SEC_PKCS12CreatePubKeyEncryptedSafe(SEC_PKCS12ExportContext *p12ctxt, - CERTCertDBHandle *certDb, - CERTCertificate *signer, - CERTCertificate **recipients, - SECOidTag algorithm, int keysize); - -extern SEC_PKCS12SafeInfo * -SEC_PKCS12CreatePasswordPrivSafe(SEC_PKCS12ExportContext *p12ctxt, - SECItem *pwitem, SECOidTag privAlg); - -extern SEC_PKCS12SafeInfo * -SEC_PKCS12CreateUnencryptedSafe(SEC_PKCS12ExportContext *p12ctxt); - -extern SECStatus -SEC_PKCS12AddPasswordIntegrity(SEC_PKCS12ExportContext *p12ctxt, - SECItem *pwitem, SECOidTag integAlg); -extern SECStatus -SEC_PKCS12AddPublicKeyIntegrity(SEC_PKCS12ExportContext *p12ctxt, - CERTCertificate *cert, CERTCertDBHandle *certDb, - SECOidTag algorithm, int keySize); - -extern SEC_PKCS12ExportContext * -SEC_PKCS12CreateExportContext(SECKEYGetPasswordKey pwfn, void *pwfnarg, - PK11SlotInfo *slot, void *wincx); - -extern SECStatus -SEC_PKCS12AddCert(SEC_PKCS12ExportContext *p12ctxt, - SEC_PKCS12SafeInfo *safe, void *nestedDest, - CERTCertificate *cert, CERTCertDBHandle *certDb, - SECItem *keyId, PRBool includeCertChain); - -extern SECStatus -SEC_PKCS12AddKeyForCert(SEC_PKCS12ExportContext *p12ctxt, - SEC_PKCS12SafeInfo *safe, - void *nestedDest, CERTCertificate *cert, - PRBool shroudKey, SECOidTag algorithm, SECItem *pwitem, - SECItem *keyId, SECItem *nickName); - -extern SECStatus -SEC_PKCS12AddCertAndKey(SEC_PKCS12ExportContext *p12ctxt, - void *certSafe, void *certNestedDest, - CERTCertificate *cert, CERTCertDBHandle *certDb, - void *keySafe, void *keyNestedDest, - PRBool shroudKey, SECItem *pwitem, SECOidTag algorithm); - -extern SECStatus -SEC_PKCS12AddDERCertAndEncryptedKey(SEC_PKCS12ExportContext *p12ctxt, - void *certSafe, void *certNestedDest, SECItem *derCert, - void *keySafe, void *keyNestedDest, - SECKEYEncryptedPrivateKeyInfo *epki, char *nickname); - -extern void * -SEC_PKCS12CreateNestedSafeContents(SEC_PKCS12ExportContext *p12ctxt, - void *baseSafe, void *nestedDest); - -extern SECStatus -SEC_PKCS12Encode(SEC_PKCS12ExportContext *p12exp, - SEC_PKCS12EncoderOutputCallback output, void *outputarg); - -extern void -SEC_PKCS12DestroyExportContext(SEC_PKCS12ExportContext *p12exp); - -extern SEC_PKCS12DecoderContext * -SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx, - digestOpenFn dOpen, digestCloseFn dClose, - digestIOFn dRead, digestIOFn dWrite, void *dArg); - -extern SECStatus -SEC_PKCS12DecoderSetTargetTokenCAs(SEC_PKCS12DecoderContext *p12dcx, - SECPKCS12TargetTokenCAs tokenCAs); - -extern SECStatus -SEC_PKCS12DecoderUpdate(SEC_PKCS12DecoderContext *p12dcx, unsigned char *data, - unsigned long len); - -extern void -SEC_PKCS12DecoderFinish(SEC_PKCS12DecoderContext *p12dcx); - -extern SECStatus -SEC_PKCS12DecoderVerify(SEC_PKCS12DecoderContext *p12dcx); - -extern SECStatus -SEC_PKCS12DecoderValidateBags(SEC_PKCS12DecoderContext *p12dcx, - SEC_PKCS12NicknameCollisionCallback nicknameCb); - -extern SECStatus -SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx); - -CERTCertList * -SEC_PKCS12DecoderGetCerts(SEC_PKCS12DecoderContext *p12dcx); - -SECStatus -SEC_PKCS12DecoderIterateInit(SEC_PKCS12DecoderContext *p12dcx); - -SECStatus -SEC_PKCS12DecoderIterateNext(SEC_PKCS12DecoderContext *p12dcx, - const SEC_PKCS12DecoderItem **ipp); - -SEC_END_PROTOS - -#endif diff --git a/security/nss/lib/pkcs12/p12creat.c b/security/nss/lib/pkcs12/p12creat.c deleted file mode 100644 index 29b0892f3..000000000 --- a/security/nss/lib/pkcs12/p12creat.c +++ /dev/null @@ -1,254 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "pkcs12.h" -#include "secitem.h" -#include "secport.h" -#include "secder.h" -#include "secoid.h" -#include "p12local.h" -#include "secerr.h" - - -/* allocate space for a PFX structure and set up initial - * arena pool. pfx structure is cleared and a pointer to - * the new structure is returned. - */ -SEC_PKCS12PFXItem * -sec_pkcs12_new_pfx(void) -{ - SEC_PKCS12PFXItem *pfx = NULL; - PRArenaPool *poolp = NULL; - - poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); /* XXX Different size? */ - if(poolp == NULL) - goto loser; - - pfx = (SEC_PKCS12PFXItem *)PORT_ArenaZAlloc(poolp, - sizeof(SEC_PKCS12PFXItem)); - if(pfx == NULL) - goto loser; - pfx->poolp = poolp; - - return pfx; - -loser: - PORT_FreeArena(poolp, PR_TRUE); - return NULL; -} - -/* allocate space for a PFX structure and set up initial - * arena pool. pfx structure is cleared and a pointer to - * the new structure is returned. - */ -SEC_PKCS12AuthenticatedSafe * -sec_pkcs12_new_asafe(PRArenaPool *poolp) -{ - SEC_PKCS12AuthenticatedSafe *asafe = NULL; - void *mark; - - mark = PORT_ArenaMark(poolp); - asafe = (SEC_PKCS12AuthenticatedSafe *)PORT_ArenaZAlloc(poolp, - sizeof(SEC_PKCS12AuthenticatedSafe)); - if(asafe == NULL) - goto loser; - asafe->poolp = poolp; - PORT_Memset(&asafe->old_baggage, 0, sizeof(SEC_PKCS7ContentInfo)); - - PORT_ArenaUnmark(poolp, mark); - return asafe; - -loser: - PORT_ArenaRelease(poolp, mark); - return NULL; -} - -/* create a safe contents structure with a list of - * length 0 with the first element being NULL - */ -SEC_PKCS12SafeContents * -sec_pkcs12_create_safe_contents(PRArenaPool *poolp) -{ - SEC_PKCS12SafeContents *safe; - void *mark; - - if(poolp == NULL) - return NULL; - - /* allocate structure */ - mark = PORT_ArenaMark(poolp); - safe = (SEC_PKCS12SafeContents *)PORT_ArenaZAlloc(poolp, - sizeof(SEC_PKCS12SafeContents)); - if(safe == NULL) - { - PORT_SetError(SEC_ERROR_NO_MEMORY); - PORT_ArenaRelease(poolp, mark); - return NULL; - } - - /* init list */ - safe->contents = (SEC_PKCS12SafeBag**)PORT_ArenaZAlloc(poolp, - sizeof(SEC_PKCS12SafeBag *)); - if(safe->contents == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - PORT_ArenaRelease(poolp, mark); - return NULL; - } - safe->contents[0] = NULL; - safe->poolp = poolp; - safe->safe_size = 0; - PORT_ArenaUnmark(poolp, mark); - return safe; -} - -/* create a new external bag which is appended onto the list - * of bags in baggage. the bag is created in the same arena - * as baggage - */ -SEC_PKCS12BaggageItem * -sec_pkcs12_create_external_bag(SEC_PKCS12Baggage *luggage) -{ - void *dummy, *mark; - SEC_PKCS12BaggageItem *bag; - - if(luggage == NULL) { - return NULL; - } - - mark = PORT_ArenaMark(luggage->poolp); - - /* allocate space for null terminated bag list */ - if(luggage->bags == NULL) { - luggage->bags=(SEC_PKCS12BaggageItem**)PORT_ArenaZAlloc(luggage->poolp, - sizeof(SEC_PKCS12BaggageItem *)); - if(luggage->bags == NULL) { - goto loser; - } - luggage->luggage_size = 0; - } - - /* grow the list */ - dummy = PORT_ArenaGrow(luggage->poolp, luggage->bags, - sizeof(SEC_PKCS12BaggageItem *) * (luggage->luggage_size + 1), - sizeof(SEC_PKCS12BaggageItem *) * (luggage->luggage_size + 2)); - if(dummy == NULL) { - goto loser; - } - luggage->bags = (SEC_PKCS12BaggageItem**)dummy; - - luggage->bags[luggage->luggage_size] = - (SEC_PKCS12BaggageItem *)PORT_ArenaZAlloc(luggage->poolp, - sizeof(SEC_PKCS12BaggageItem)); - if(luggage->bags[luggage->luggage_size] == NULL) { - goto loser; - } - - /* create new bag and append it to the end */ - bag = luggage->bags[luggage->luggage_size]; - bag->espvks = (SEC_PKCS12ESPVKItem **)PORT_ArenaZAlloc( - luggage->poolp, - sizeof(SEC_PKCS12ESPVKItem *)); - bag->unencSecrets = (SEC_PKCS12SafeBag **)PORT_ArenaZAlloc( - luggage->poolp, - sizeof(SEC_PKCS12SafeBag *)); - if((bag->espvks == NULL) || (bag->unencSecrets == NULL)) { - goto loser; - } - - bag->poolp = luggage->poolp; - luggage->luggage_size++; - luggage->bags[luggage->luggage_size] = NULL; - bag->espvks[0] = NULL; - bag->unencSecrets[0] = NULL; - bag->nEspvks = bag->nSecrets = 0; - - PORT_ArenaUnmark(luggage->poolp, mark); - return bag; - -loser: - PORT_ArenaRelease(luggage->poolp, mark); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; -} - -/* creates a baggage witha NULL terminated 0 length list */ -SEC_PKCS12Baggage * -sec_pkcs12_create_baggage(PRArenaPool *poolp) -{ - SEC_PKCS12Baggage *luggage; - void *mark; - - if(poolp == NULL) - return NULL; - - mark = PORT_ArenaMark(poolp); - - /* allocate bag */ - luggage = (SEC_PKCS12Baggage *)PORT_ArenaZAlloc(poolp, - sizeof(SEC_PKCS12Baggage)); - if(luggage == NULL) - { - PORT_SetError(SEC_ERROR_NO_MEMORY); - PORT_ArenaRelease(poolp, mark); - return NULL; - } - - /* init list */ - luggage->bags = (SEC_PKCS12BaggageItem **)PORT_ArenaZAlloc(poolp, - sizeof(SEC_PKCS12BaggageItem *)); - if(luggage->bags == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - PORT_ArenaRelease(poolp, mark); - return NULL; - } - - luggage->bags[0] = NULL; - luggage->luggage_size = 0; - luggage->poolp = poolp; - - PORT_ArenaUnmark(poolp, mark); - return luggage; -} - -/* free pfx structure and associated items in the arena */ -void -SEC_PKCS12DestroyPFX(SEC_PKCS12PFXItem *pfx) -{ - if (pfx != NULL && pfx->poolp != NULL) - { - PORT_FreeArena(pfx->poolp, PR_TRUE); - } -} diff --git a/security/nss/lib/pkcs12/p12d.c b/security/nss/lib/pkcs12/p12d.c deleted file mode 100644 index 2d4d29cae..000000000 --- a/security/nss/lib/pkcs12/p12d.c +++ /dev/null @@ -1,3473 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -#include "nssrenam.h" -#include "p12t.h" -#include "p12.h" -#include "plarena.h" -#include "secitem.h" -#include "secoid.h" -#include "seccomon.h" -#include "secport.h" -#include "cert.h" -#include "secpkcs7.h" -#include "secasn1.h" -#include "secerr.h" -#include "pk11func.h" -#include "p12plcy.h" -#include "p12local.h" -#include "secder.h" -#include "secport.h" - -#include "certdb.h" - -#include "prcpucfg.h" - -typedef struct sec_PKCS12SafeContentsContextStr sec_PKCS12SafeContentsContext; - -/* Opaque structure for decoding SafeContents. These are used - * for each authenticated safe as well as any nested safe contents. - */ -struct sec_PKCS12SafeContentsContextStr { - /* the parent decoder context */ - SEC_PKCS12DecoderContext *p12dcx; - - /* memory arena to allocate space from */ - PRArenaPool *arena; - - /* decoder context and destination for decoding safe contents */ - SEC_ASN1DecoderContext *safeContentsDcx; - sec_PKCS12SafeContents safeContents; - - /* information for decoding safe bags within the safe contents. - * these variables are updated for each safe bag decoded. - */ - SEC_ASN1DecoderContext *currentSafeBagDcx; - sec_PKCS12SafeBag *currentSafeBag; - PRBool skipCurrentSafeBag; - - /* if the safe contents is nested, the parent is pointed to here. */ - sec_PKCS12SafeContentsContext *nestedCtx; -}; - -/* opaque decoder context structure. information for decoding a pkcs 12 - * PDU are stored here as well as decoding pointers for intermediary - * structures which are part of the PKCS 12 PDU. Upon a successful - * decode, the safe bags containing certificates and keys encountered. - */ -struct SEC_PKCS12DecoderContextStr { - PRArenaPool *arena; - PK11SlotInfo *slot; - void *wincx; - PRBool error; - int errorValue; - - /* password */ - SECItem *pwitem; - - /* used for decoding the PFX structure */ - SEC_ASN1DecoderContext *pfxDcx; - sec_PKCS12PFXItem pfx; - - /* safe bags found during decoding */ - sec_PKCS12SafeBag **safeBags; - unsigned int safeBagCount; - - /* state variables for decoding authenticated safes. */ - SEC_PKCS7DecoderContext *currentASafeP7Dcx; - SEC_ASN1DecoderContext *aSafeDcx; - SEC_PKCS7DecoderContext *aSafeP7Dcx; - sec_PKCS12AuthenticatedSafe authSafe; - SEC_PKCS7ContentInfo *aSafeCinfo; - sec_PKCS12SafeContents safeContents; - - /* safe contents info */ - unsigned int safeContentsCnt; - sec_PKCS12SafeContentsContext **safeContentsList; - - /* HMAC info */ - sec_PKCS12MacData macData; - SEC_ASN1DecoderContext *hmacDcx; - - /* routines for reading back the data to be hmac'd */ - digestOpenFn dOpen; - digestCloseFn dClose; - digestIOFn dRead, dWrite; - void *dArg; - - /* helper functions */ - SECKEYGetPasswordKey pwfn; - void *pwfnarg; - PRBool swapUnicodeBytes; - - /* import information */ - PRBool bagsVerified; - - /* buffer management for the default callbacks implementation */ - void *buffer; /* storage area */ - PRInt32 filesize; /* actual data size */ - PRInt32 allocated; /* total buffer size allocated */ - PRInt32 currentpos; /* position counter */ - SECPKCS12TargetTokenCAs tokenCAs; - sec_PKCS12SafeBag **keyList;/* used by ...IterateNext() */ - unsigned int iteration; - SEC_PKCS12DecoderItem decitem; -}; - - -/* make sure that the PFX version being decoded is a version - * which we support. - */ -static PRBool -sec_pkcs12_proper_version(sec_PKCS12PFXItem *pfx) -{ - /* if no version, assume it is not supported */ - if(pfx->version.len == 0) { - return PR_FALSE; - } - - if(DER_GetInteger(&pfx->version) > SEC_PKCS12_VERSION) { - return PR_FALSE; - } - - return PR_TRUE; -} - -/* retrieve the key for decrypting the safe contents */ -static PK11SymKey * -sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid) -{ - SEC_PKCS12DecoderContext *p12dcx = - (SEC_PKCS12DecoderContext *) arg; - PK11SlotInfo *slot; - PK11SymKey *bulkKey; - - if(!p12dcx) { - return NULL; - } - - /* if no slot specified, use the internal key slot */ - if(p12dcx->slot) { - slot = PK11_ReferenceSlot(p12dcx->slot); - } else { - slot = PK11_GetInternalKeySlot(); - } - - bulkKey = PK11_PBEKeyGen(slot, algid, p12dcx->pwitem, - PR_FALSE, p12dcx->wincx); - /* some tokens can't generate PBE keys on their own, generate the - * key in the internal slot, and let the Import code deal with it, - * (if the slot can't generate PBEs, then we need to use the internal - * slot anyway to unwrap). */ - if (!bulkKey && !PK11_IsInternal(slot)) { - PK11_FreeSlot(slot); - slot = PK11_GetInternalKeySlot(); - bulkKey = PK11_PBEKeyGen(slot, algid, p12dcx->pwitem, - PR_FALSE, p12dcx->wincx); - } - PK11_FreeSlot(slot); - - /* set the password data on the key */ - if (bulkKey) { - PK11_SetSymKeyUserData(bulkKey,p12dcx->pwitem, NULL); - } - - - return bulkKey; -} - -/* XXX this needs to be modified to handle enveloped data. most - * likely, it should mirror the routines for SMIME in that regard. - */ -static PRBool -sec_pkcs12_decoder_decryption_allowed(SECAlgorithmID *algid, - PK11SymKey *bulkkey) -{ - PRBool decryptionAllowed = SEC_PKCS12DecryptionAllowed(algid); - - if(!decryptionAllowed) { - return PR_FALSE; - } - - return PR_TRUE; -} - -/* when we encounter a new safe bag during the decoding, we need - * to allocate space for the bag to be decoded to and set the - * state variables appropriately. all of the safe bags are allocated - * in a buffer in the outer SEC_PKCS12DecoderContext, however, - * a pointer to the safeBag is also used in the sec_PKCS12SafeContentsContext - * for the current bag. - */ -static SECStatus -sec_pkcs12_decoder_init_new_safe_bag(sec_PKCS12SafeContentsContext - *safeContentsCtx) -{ - void *mark = NULL; - SEC_PKCS12DecoderContext *p12dcx; - - /* make sure that the structures are defined, and there has - * not been an error in the decoding - */ - if(!safeContentsCtx || !safeContentsCtx->p12dcx - || safeContentsCtx->p12dcx->error) { - return SECFailure; - } - - p12dcx = safeContentsCtx->p12dcx; - mark = PORT_ArenaMark(p12dcx->arena); - - /* allocate a new safe bag, if bags already exist, grow the - * list of bags, otherwise allocate a new list. the list is - * NULL terminated. - */ - if(p12dcx->safeBagCount) { - p12dcx->safeBags = - (sec_PKCS12SafeBag**)PORT_ArenaGrow(p12dcx->arena,p12dcx->safeBags, - (p12dcx->safeBagCount + 1) * sizeof(sec_PKCS12SafeBag *), - (p12dcx->safeBagCount + 2) * sizeof(sec_PKCS12SafeBag *)); - } else { - p12dcx->safeBags = (sec_PKCS12SafeBag**)PORT_ArenaZAlloc(p12dcx->arena, - 2 * sizeof(sec_PKCS12SafeBag *)); - } - if(!p12dcx->safeBags) { - p12dcx->errorValue = SEC_ERROR_NO_MEMORY; - goto loser; - } - - /* append the bag to the end of the list and update the reference - * in the safeContentsCtx. - */ - p12dcx->safeBags[p12dcx->safeBagCount] = - (sec_PKCS12SafeBag*)PORT_ArenaZAlloc(p12dcx->arena, - sizeof(sec_PKCS12SafeBag)); - safeContentsCtx->currentSafeBag = p12dcx->safeBags[p12dcx->safeBagCount]; - p12dcx->safeBags[++p12dcx->safeBagCount] = NULL; - if(!safeContentsCtx->currentSafeBag) { - p12dcx->errorValue = SEC_ERROR_NO_MEMORY; - goto loser; - } - - safeContentsCtx->currentSafeBag->slot = safeContentsCtx->p12dcx->slot; - safeContentsCtx->currentSafeBag->pwitem = safeContentsCtx->p12dcx->pwitem; - safeContentsCtx->currentSafeBag->swapUnicodeBytes = - safeContentsCtx->p12dcx->swapUnicodeBytes; - safeContentsCtx->currentSafeBag->arena = safeContentsCtx->p12dcx->arena; - safeContentsCtx->currentSafeBag->tokenCAs = - safeContentsCtx->p12dcx->tokenCAs; - - PORT_ArenaUnmark(p12dcx->arena, mark); - return SECSuccess; - -loser: - - /* if an error occurred, release the memory and set the error flag - * the only possible errors triggered by this function are memory - * related. - */ - if(mark) { - PORT_ArenaRelease(p12dcx->arena, mark); - } - - p12dcx->error = PR_TRUE; - return SECFailure; -} - -/* A wrapper for updating the ASN1 context in which a safeBag is - * being decoded. This function is called as a callback from - * secasn1d when decoding SafeContents structures. - */ -static void -sec_pkcs12_decoder_safe_bag_update(void *arg, const char *data, - unsigned long len, int depth, - SEC_ASN1EncodingPart data_kind) -{ - sec_PKCS12SafeContentsContext *safeContentsCtx = - (sec_PKCS12SafeContentsContext *)arg; - SEC_PKCS12DecoderContext *p12dcx; - SECStatus rv; - - /* make sure that we are not skipping the current safeBag, - * and that there are no errors. If so, just return rather - * than continuing to process. - */ - if(!safeContentsCtx || !safeContentsCtx->p12dcx - || safeContentsCtx->p12dcx->error - || safeContentsCtx->skipCurrentSafeBag) { - return; - } - p12dcx = safeContentsCtx->p12dcx; - - rv = SEC_ASN1DecoderUpdate(safeContentsCtx->currentSafeBagDcx, data, len); - if(rv != SECSuccess) { - p12dcx->errorValue = SEC_ERROR_NO_MEMORY; - goto loser; - } - - return; - -loser: - /* set the error, and finish the decoder context. because there - * is not a way of returning an error message, it may be worth - * while to do a check higher up and finish any decoding contexts - * that are still open. - */ - p12dcx->error = PR_TRUE; - SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagDcx); - safeContentsCtx->currentSafeBagDcx = NULL; - return; -} - -/* forward declarations of functions that are used when decoding - * safeContents bags which are nested and when decoding the - * authenticatedSafes. - */ -static SECStatus -sec_pkcs12_decoder_begin_nested_safe_contents(sec_PKCS12SafeContentsContext - *safeContentsCtx); -static SECStatus -sec_pkcs12_decoder_finish_nested_safe_contents(sec_PKCS12SafeContentsContext - *safeContentsCtx); -static void -sec_pkcs12_decoder_safe_bag_update(void *arg, const char *data, - unsigned long len, int depth, - SEC_ASN1EncodingPart data_kind); - -/* notify function for decoding safeBags. This function is - * used to filter safeBag types which are not supported, - * initiate the decoding of nested safe contents, and decode - * safeBags in general. this function is set when the decoder - * context for the safeBag is first created. - */ -static void -sec_pkcs12_decoder_safe_bag_notify(void *arg, PRBool before, - void *dest, int real_depth) -{ - sec_PKCS12SafeContentsContext *safeContentsCtx = - (sec_PKCS12SafeContentsContext *)arg; - SEC_PKCS12DecoderContext *p12dcx; - sec_PKCS12SafeBag *bag; - PRBool after; - - /* if an error is encountered, return */ - if(!safeContentsCtx || !safeContentsCtx->p12dcx || - safeContentsCtx->p12dcx->error) { - return; - } - p12dcx = safeContentsCtx->p12dcx; - - /* to make things more readable */ - if(before) - after = PR_FALSE; - else - after = PR_TRUE; - - /* have we determined the safeBagType yet? */ - bag = safeContentsCtx->currentSafeBag; - if(bag->bagTypeTag == NULL) { - if(after && (dest == &(bag->safeBagType))) { - bag->bagTypeTag = SECOID_FindOID(&(bag->safeBagType)); - if(bag->bagTypeTag == NULL) { - p12dcx->error = PR_TRUE; - p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE; - } - } - return; - } - - /* process the safeBag depending on it's type. those - * which we do not support, are ignored. we start a decoding - * context for a nested safeContents. - */ - switch(bag->bagTypeTag->offset) { - case SEC_OID_PKCS12_V1_KEY_BAG_ID: - case SEC_OID_PKCS12_V1_CERT_BAG_ID: - case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: - break; - case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID: - /* if we are just starting to decode the safeContents, initialize - * a new safeContentsCtx to process it. - */ - if(before && (dest == &(bag->safeBagContent))) { - sec_pkcs12_decoder_begin_nested_safe_contents(safeContentsCtx); - } else if(after && (dest == &(bag->safeBagContent))) { - /* clean up the nested decoding */ - sec_pkcs12_decoder_finish_nested_safe_contents(safeContentsCtx); - } - break; - case SEC_OID_PKCS12_V1_CRL_BAG_ID: - case SEC_OID_PKCS12_V1_SECRET_BAG_ID: - default: - /* skip any safe bag types we don't understand or handle */ - safeContentsCtx->skipCurrentSafeBag = PR_TRUE; - break; - } - - return; -} - -/* notify function for decoding safe contents. each entry in the - * safe contents is a safeBag which needs to be allocated and - * the decoding context initialized at the beginning and then - * the context needs to be closed and finished at the end. - * - * this function is set when the safeContents decode context is - * initialized. - */ -static void -sec_pkcs12_decoder_safe_contents_notify(void *arg, PRBool before, - void *dest, int real_depth) -{ - sec_PKCS12SafeContentsContext *safeContentsCtx = - (sec_PKCS12SafeContentsContext*)arg; - SEC_PKCS12DecoderContext *p12dcx; - SECStatus rv; - - /* if there is an error we don't want to continue processing, - * just return and keep going. - */ - if(!safeContentsCtx || !safeContentsCtx->p12dcx - || safeContentsCtx->p12dcx->error) { - return; - } - p12dcx = safeContentsCtx->p12dcx; - - /* if we are done with the current safeBag, then we need to - * finish the context and set the state variables appropriately. - */ - if(!before) { - SEC_ASN1DecoderClearFilterProc(safeContentsCtx->safeContentsDcx); - SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagDcx); - safeContentsCtx->currentSafeBagDcx = NULL; - safeContentsCtx->skipCurrentSafeBag = PR_FALSE; - } else { - /* we are starting a new safe bag. we need to allocate space - * for the bag and initialize the decoding context. - */ - rv = sec_pkcs12_decoder_init_new_safe_bag(safeContentsCtx); - if(rv != SECSuccess) { - goto loser; - } - - /* set up the decoder context */ - safeContentsCtx->currentSafeBagDcx = SEC_ASN1DecoderStart(p12dcx->arena, - safeContentsCtx->currentSafeBag, - sec_PKCS12SafeBagTemplate); - if(!safeContentsCtx->currentSafeBagDcx) { - p12dcx->errorValue = SEC_ERROR_NO_MEMORY; - goto loser; - } - - /* set the notify and filter procs so that the safe bag - * data gets sent to the proper location when decoding. - */ - SEC_ASN1DecoderSetNotifyProc(safeContentsCtx->currentSafeBagDcx, - sec_pkcs12_decoder_safe_bag_notify, - safeContentsCtx); - SEC_ASN1DecoderSetFilterProc(safeContentsCtx->safeContentsDcx, - sec_pkcs12_decoder_safe_bag_update, - safeContentsCtx, PR_TRUE); - } - - return; - -loser: - /* in the event of an error, we want to close the decoding - * context and clear the filter and notify procedures. - */ - p12dcx->error = PR_TRUE; - - if(safeContentsCtx->currentSafeBagDcx) { - SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagDcx); - safeContentsCtx->currentSafeBagDcx = NULL; - } - - SEC_ASN1DecoderClearNotifyProc(safeContentsCtx->safeContentsDcx); - SEC_ASN1DecoderClearFilterProc(safeContentsCtx->safeContentsDcx); - - return; -} - -/* initialize the safeContents for decoding. this routine - * is used for authenticatedSafes as well as nested safeContents. - */ -static sec_PKCS12SafeContentsContext * -sec_pkcs12_decoder_safe_contents_init_decode(SEC_PKCS12DecoderContext *p12dcx, - PRBool nestedSafe) -{ - sec_PKCS12SafeContentsContext *safeContentsCtx = NULL; - const SEC_ASN1Template *theTemplate; - - if(!p12dcx || p12dcx->error) { - return NULL; - } - - /* allocate a new safeContents list or grow the existing list and - * append the new safeContents onto the end. - */ - if(!p12dcx->safeContentsCnt) { - p12dcx->safeContentsList = - (sec_PKCS12SafeContentsContext**)PORT_ArenaZAlloc(p12dcx->arena, - sizeof(sec_PKCS12SafeContentsContext *)); - } else { - p12dcx->safeContentsList = - (sec_PKCS12SafeContentsContext **) PORT_ArenaGrow(p12dcx->arena, - p12dcx->safeContentsList, - (p12dcx->safeContentsCnt * - sizeof(sec_PKCS12SafeContentsContext *)), - (1 + p12dcx->safeContentsCnt * - sizeof(sec_PKCS12SafeContentsContext *))); - } - if(!p12dcx->safeContentsList) { - p12dcx->errorValue = SEC_ERROR_NO_MEMORY; - goto loser; - } - - p12dcx->safeContentsList[p12dcx->safeContentsCnt] = - (sec_PKCS12SafeContentsContext*)PORT_ArenaZAlloc( - p12dcx->arena, - sizeof(sec_PKCS12SafeContentsContext)); - p12dcx->safeContentsList[p12dcx->safeContentsCnt+1] = NULL; - if(!p12dcx->safeContentsList[p12dcx->safeContentsCnt]) { - p12dcx->errorValue = SEC_ERROR_NO_MEMORY; - goto loser; - } - - /* set up the state variables */ - safeContentsCtx = p12dcx->safeContentsList[p12dcx->safeContentsCnt]; - p12dcx->safeContentsCnt++; - safeContentsCtx->p12dcx = p12dcx; - safeContentsCtx->arena = p12dcx->arena; - - /* begin the decoding -- the template is based on whether we are - * decoding a nested safeContents or not. - */ - if(nestedSafe == PR_TRUE) { - theTemplate = sec_PKCS12NestedSafeContentsDecodeTemplate; - } else { - theTemplate = sec_PKCS12SafeContentsDecodeTemplate; - } - - /* start the decoder context */ - safeContentsCtx->safeContentsDcx = SEC_ASN1DecoderStart(p12dcx->arena, - &safeContentsCtx->safeContents, - theTemplate); - - if(!safeContentsCtx->safeContentsDcx) { - p12dcx->errorValue = SEC_ERROR_NO_MEMORY; - goto loser; - } - - /* set the safeContents notify procedure to look for - * and start the decode of safeBags. - */ - SEC_ASN1DecoderSetNotifyProc(safeContentsCtx->safeContentsDcx, - sec_pkcs12_decoder_safe_contents_notify, - safeContentsCtx); - - return safeContentsCtx; - -loser: - /* in the case of an error, we want to finish the decoder - * context and set the error flag. - */ - if(safeContentsCtx && safeContentsCtx->safeContentsDcx) { - SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsDcx); - safeContentsCtx->safeContentsDcx = NULL; - } - - p12dcx->error = PR_TRUE; - - return NULL; -} - -/* wrapper for updating safeContents. this is set as the filter of - * safeBag when there is a nested safeContents. - */ -static void -sec_pkcs12_decoder_nested_safe_contents_update(void *arg, const char *buf, - unsigned long len, int depth, - SEC_ASN1EncodingPart data_kind) -{ - sec_PKCS12SafeContentsContext *safeContentsCtx = - (sec_PKCS12SafeContentsContext *)arg; - SEC_PKCS12DecoderContext *p12dcx; - SECStatus rv; - - /* check for an error */ - if(!safeContentsCtx || !safeContentsCtx->p12dcx - || safeContentsCtx->p12dcx->error) { - return; - } - - /* no need to update if no data sent in */ - if(!len || !buf) { - return; - } - - /* update the decoding context */ - p12dcx = safeContentsCtx->p12dcx; - rv = SEC_ASN1DecoderUpdate(safeContentsCtx->safeContentsDcx, buf, len); - if(rv != SECSuccess) { - p12dcx->errorValue = SEC_ERROR_NO_MEMORY; - goto loser; - } - - return; - -loser: - /* handle any errors. If a decoding context is open, close it. */ - p12dcx->error = PR_TRUE; - if(safeContentsCtx->safeContentsDcx) { - SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsDcx); - safeContentsCtx->safeContentsDcx = NULL; - } -} - -/* whenever a new safeContentsSafeBag is encountered, we need - * to init a safeContentsContext. - */ -static SECStatus -sec_pkcs12_decoder_begin_nested_safe_contents(sec_PKCS12SafeContentsContext - *safeContentsCtx) -{ - /* check for an error */ - if(!safeContentsCtx || !safeContentsCtx->p12dcx || - safeContentsCtx->p12dcx->error) { - return SECFailure; - } - - safeContentsCtx->nestedCtx = sec_pkcs12_decoder_safe_contents_init_decode( - safeContentsCtx->p12dcx, - PR_TRUE); - if(!safeContentsCtx->nestedCtx) { - return SECFailure; - } - - /* set up new filter proc */ - SEC_ASN1DecoderSetNotifyProc(safeContentsCtx->nestedCtx->safeContentsDcx, - sec_pkcs12_decoder_safe_contents_notify, - safeContentsCtx->nestedCtx); - SEC_ASN1DecoderSetFilterProc(safeContentsCtx->currentSafeBagDcx, - sec_pkcs12_decoder_nested_safe_contents_update, - safeContentsCtx->nestedCtx, PR_TRUE); - - return SECSuccess; -} - -/* when the safeContents is done decoding, we need to reset the - * proper filter and notify procs and close the decoding context - */ -static SECStatus -sec_pkcs12_decoder_finish_nested_safe_contents(sec_PKCS12SafeContentsContext - *safeContentsCtx) -{ - /* check for error */ - if(!safeContentsCtx || !safeContentsCtx->p12dcx || - safeContentsCtx->p12dcx->error) { - return SECFailure; - } - - /* clean up */ - SEC_ASN1DecoderClearFilterProc(safeContentsCtx->currentSafeBagDcx); - SEC_ASN1DecoderClearNotifyProc(safeContentsCtx->nestedCtx->safeContentsDcx); - SEC_ASN1DecoderFinish(safeContentsCtx->nestedCtx->safeContentsDcx); - safeContentsCtx->nestedCtx->safeContentsDcx = NULL; - safeContentsCtx->nestedCtx = NULL; - - return SECSuccess; -} - -/* wrapper for updating safeContents. This is used when decoding - * the nested safeContents and any authenticatedSafes. - */ -static void -sec_pkcs12_decoder_safe_contents_callback(void *arg, const char *buf, - unsigned long len) -{ - SECStatus rv; - sec_PKCS12SafeContentsContext *safeContentsCtx = - (sec_PKCS12SafeContentsContext *)arg; - SEC_PKCS12DecoderContext *p12dcx; - - /* check for error */ - if(!safeContentsCtx || !safeContentsCtx->p12dcx - || safeContentsCtx->p12dcx->error) { - return; - } - p12dcx = safeContentsCtx->p12dcx; - - /* update the decoder */ - rv = SEC_ASN1DecoderUpdate(safeContentsCtx->safeContentsDcx, buf, len); - if(rv != SECSuccess) { - /* if we fail while trying to decode a 'safe', it's probably because - * we didn't have the correct password. */ - PORT_SetError(SEC_ERROR_BAD_PASSWORD); - p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE; - SEC_PKCS7DecoderAbort(p12dcx->currentASafeP7Dcx,SEC_ERROR_BAD_PASSWORD); - goto loser; - } - - return; - -loser: - /* set the error and finish the context */ - p12dcx->error = PR_TRUE; - if(safeContentsCtx->safeContentsDcx) { - SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsDcx); - safeContentsCtx->safeContentsDcx = NULL; - } - - return; -} - -/* this is a wrapper for the ASN1 decoder to call SEC_PKCS7DecoderUpdate - */ -static void -sec_pkcs12_decoder_wrap_p7_update(void *arg, const char *data, - unsigned long len, int depth, - SEC_ASN1EncodingPart data_kind) -{ - SEC_PKCS7DecoderContext *p7dcx = (SEC_PKCS7DecoderContext *)arg; - - SEC_PKCS7DecoderUpdate(p7dcx, data, len); -} - -/* notify function for decoding aSafes. at the beginning, - * of an authenticatedSafe, we start a decode of a safeContents. - * at the end, we clean up the safeContents decoder context and - * reset state variables - */ -static void -sec_pkcs12_decoder_asafes_notify(void *arg, PRBool before, void *dest, - int real_depth) -{ - SEC_PKCS12DecoderContext *p12dcx; - sec_PKCS12SafeContentsContext *safeContentsCtx; - - /* make sure no error occurred. */ - p12dcx = (SEC_PKCS12DecoderContext *)arg; - if(!p12dcx || p12dcx->error) { - return; - } - - if(before) { - - /* init a new safeContentsContext */ - safeContentsCtx = sec_pkcs12_decoder_safe_contents_init_decode(p12dcx, - PR_FALSE); - if(!safeContentsCtx) { - goto loser; - } - - /* initiate the PKCS7ContentInfo decode */ - p12dcx->currentASafeP7Dcx = SEC_PKCS7DecoderStart( - sec_pkcs12_decoder_safe_contents_callback, - safeContentsCtx, - p12dcx->pwfn, p12dcx->pwfnarg, - sec_pkcs12_decoder_get_decrypt_key, p12dcx, - sec_pkcs12_decoder_decryption_allowed); - if(!p12dcx->currentASafeP7Dcx) { - p12dcx->errorValue = PORT_GetError(); - goto loser; - } - SEC_ASN1DecoderSetFilterProc(p12dcx->aSafeDcx, - sec_pkcs12_decoder_wrap_p7_update, - p12dcx->currentASafeP7Dcx, PR_TRUE); - } - - if(!before) { - /* if one is being decoded, finish the decode */ - if(p12dcx->currentASafeP7Dcx != NULL) { - if(!SEC_PKCS7DecoderFinish(p12dcx->currentASafeP7Dcx)) { - p12dcx->currentASafeP7Dcx = NULL; - p12dcx->errorValue = PORT_GetError(); - goto loser; - } - p12dcx->currentASafeP7Dcx = NULL; - } - p12dcx->currentASafeP7Dcx = NULL; - } - - - return; - -loser: - /* set the error flag */ - p12dcx->error = PR_TRUE; - return; -} - -/* wrapper for updating asafes decoding context. this function - * writes data being decoded to disk, so that a mac can be computed - * later. - */ -static void -sec_pkcs12_decoder_asafes_callback(void *arg, const char *buf, - unsigned long len) -{ - SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg; - SECStatus rv; - - if(!p12dcx || p12dcx->error) { - return; - } - - /* update the context */ - rv = SEC_ASN1DecoderUpdate(p12dcx->aSafeDcx, buf, len); - if(rv != SECSuccess) { - p12dcx->error = (PRBool)SEC_ERROR_NO_MEMORY; - goto loser; - } - - /* if we are writing to a file, write out the new information */ - if(p12dcx->dWrite) { - unsigned long writeLen = (*p12dcx->dWrite)(p12dcx->dArg, - (unsigned char *)buf, len); - if(writeLen != len) { - p12dcx->errorValue = PORT_GetError(); - goto loser; - } - } - - return; - -loser: - /* set the error flag */ - p12dcx->error = PR_TRUE; - SEC_ASN1DecoderFinish(p12dcx->aSafeDcx); - p12dcx->aSafeDcx = NULL; - - return; -} - -/* start the decode of an authenticatedSafe contentInfo. - */ -static SECStatus -sec_pkcs12_decode_start_asafes_cinfo(SEC_PKCS12DecoderContext *p12dcx) -{ - if(!p12dcx || p12dcx->error) { - return SECFailure; - } - - /* start the decode context */ - p12dcx->aSafeDcx = SEC_ASN1DecoderStart(p12dcx->arena, - &p12dcx->authSafe, - sec_PKCS12AuthenticatedSafeTemplate); - if(!p12dcx->aSafeDcx) { - p12dcx->errorValue = SEC_ERROR_NO_MEMORY; - goto loser; - } - - /* set the notify function */ - SEC_ASN1DecoderSetNotifyProc(p12dcx->aSafeDcx, - sec_pkcs12_decoder_asafes_notify, p12dcx); - - /* begin the authSafe decoder context */ - p12dcx->aSafeP7Dcx = SEC_PKCS7DecoderStart( - sec_pkcs12_decoder_asafes_callback, p12dcx, - p12dcx->pwfn, p12dcx->pwfnarg, NULL, NULL, NULL); - if(!p12dcx->aSafeP7Dcx) { - p12dcx->errorValue = SEC_ERROR_NO_MEMORY; - goto loser; - } - - /* open the temp file for writing, if the filter functions were set */ - if(p12dcx->dOpen && (*p12dcx->dOpen)(p12dcx->dArg, PR_FALSE) - != SECSuccess) { - p12dcx->errorValue = PORT_GetError(); - goto loser; - } - - return SECSuccess; - -loser: - p12dcx->error = PR_TRUE; - - if(p12dcx->aSafeDcx) { - SEC_ASN1DecoderFinish(p12dcx->aSafeDcx); - p12dcx->aSafeDcx = NULL; - } - - if(p12dcx->aSafeP7Dcx) { - SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx); - p12dcx->aSafeP7Dcx = NULL; - } - - return SECFailure; -} - -/* wrapper for updating the safeContents. this function is used as - * a filter for the pfx when decoding the authenticated safes - */ -static void -sec_pkcs12_decode_asafes_cinfo_update(void *arg, const char *buf, - unsigned long len, int depth, - SEC_ASN1EncodingPart data_kind) -{ - SEC_PKCS12DecoderContext *p12dcx; - SECStatus rv; - - p12dcx = (SEC_PKCS12DecoderContext*)arg; - if(!p12dcx || p12dcx->error) { - return; - } - - /* update the safeContents decoder */ - rv = SEC_PKCS7DecoderUpdate(p12dcx->aSafeP7Dcx, buf, len); - if(rv != SECSuccess) { - p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE; - goto loser; - } - - return; - -loser: - - /* did we find an error? if so, close the context and set the - * error flag. - */ - SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx); - p12dcx->aSafeP7Dcx = NULL; - p12dcx->error = PR_TRUE; -} - -/* notify procedure used while decoding the pfx. When we encounter - * the authSafes, we want to trigger the decoding of authSafes as well - * as when we encounter the macData, trigger the decoding of it. we do - * this because we we are streaming the decoder and not decoding in place. - * the pfx which is the destination, only has the version decoded into it. - */ -static void -sec_pkcs12_decoder_pfx_notify_proc(void *arg, PRBool before, void *dest, - int real_depth) -{ - SECStatus rv; - SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext*)arg; - - /* if an error occurrs, clear the notifyProc and the filterProc - * and continue. - */ - if(p12dcx->error) { - SEC_ASN1DecoderClearNotifyProc(p12dcx->pfxDcx); - SEC_ASN1DecoderClearFilterProc(p12dcx->pfxDcx); - return; - } - - if(before && (dest == &p12dcx->pfx.encodedAuthSafe)) { - - /* we want to make sure this is a version we support */ - if(!sec_pkcs12_proper_version(&p12dcx->pfx)) { - p12dcx->errorValue = SEC_ERROR_PKCS12_UNSUPPORTED_VERSION; - goto loser; - } - - /* start the decode of the aSafes cinfo... */ - rv = sec_pkcs12_decode_start_asafes_cinfo(p12dcx); - if(rv != SECSuccess) { - goto loser; - } - - /* set the filter proc to update the authenticated safes. */ - SEC_ASN1DecoderSetFilterProc(p12dcx->pfxDcx, - sec_pkcs12_decode_asafes_cinfo_update, - p12dcx, PR_TRUE); - } - - if(!before && (dest == &p12dcx->pfx.encodedAuthSafe)) { - - /* we are done decoding the authenticatedSafes, so we need to - * finish the decoderContext and clear the filter proc - * and close the hmac callback, if present - */ - p12dcx->aSafeCinfo = SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx); - p12dcx->aSafeP7Dcx = NULL; - if(!p12dcx->aSafeCinfo) { - p12dcx->errorValue = PORT_GetError(); - goto loser; - } - SEC_ASN1DecoderClearFilterProc(p12dcx->pfxDcx); - if(p12dcx->dClose && ((*p12dcx->dClose)(p12dcx->dArg, PR_FALSE) - != SECSuccess)) { - p12dcx->errorValue = PORT_GetError(); - goto loser; - } - - } - - return; - -loser: - p12dcx->error = PR_TRUE; -} - -/* default implementations of the open/close/read/write functions for - SEC_PKCS12DecoderStart -*/ - -#define DEFAULT_TEMP_SIZE 4096 - -static SECStatus -p12u_DigestOpen(void *arg, PRBool readData) -{ - SEC_PKCS12DecoderContext* p12cxt = arg; - - p12cxt->currentpos = 0; - - if (PR_FALSE == readData) { - /* allocate an initial buffer */ - p12cxt->filesize = 0; - p12cxt->allocated = DEFAULT_TEMP_SIZE; - p12cxt->buffer = PORT_Alloc(DEFAULT_TEMP_SIZE); - PR_ASSERT(p12cxt->buffer); - } - else - { - PR_ASSERT(p12cxt->buffer); - if (!p12cxt->buffer) { - return SECFailure; /* no data to read */ - } - } - - return SECSuccess; -} - -static SECStatus -p12u_DigestClose(void *arg, PRBool removeFile) -{ - SEC_PKCS12DecoderContext* p12cxt = arg; - - PR_ASSERT(p12cxt); - if (!p12cxt) { - return SECFailure; - } - p12cxt->currentpos = 0; - - if (PR_TRUE == removeFile) { - PR_ASSERT(p12cxt->buffer); - if (!p12cxt->buffer) { - return SECFailure; - } - if (p12cxt->buffer) { - PORT_Free(p12cxt->buffer); - p12cxt->buffer = NULL; - p12cxt->allocated = 0; - p12cxt->filesize = 0; - } - } - - return SECSuccess; -} - -static int -p12u_DigestRead(void *arg, unsigned char *buf, unsigned long len) -{ - int toread = len; - SEC_PKCS12DecoderContext* p12cxt = arg; - - if(!buf || len == 0 || !p12cxt->buffer) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return -1; - } - - if ((p12cxt->filesize - p12cxt->currentpos) < (long)len) { - /* trying to read past the end of the buffer */ - toread = p12cxt->filesize - p12cxt->currentpos; - } - memcpy(buf, (char*)p12cxt->buffer + p12cxt->currentpos, toread); - p12cxt->currentpos += toread; - return toread; -} - -static int -p12u_DigestWrite(void *arg, unsigned char *buf, unsigned long len) -{ - SEC_PKCS12DecoderContext* p12cxt = arg; - - if(!buf || len == 0) { - return -1; - } - - if (p12cxt->currentpos+(long)len > p12cxt->filesize) { - p12cxt->filesize = p12cxt->currentpos + len; - } - else { - p12cxt->filesize += len; - } - if (p12cxt->filesize > p12cxt->allocated) { - void* newbuffer; - size_t newsize = p12cxt->filesize + DEFAULT_TEMP_SIZE; - newbuffer = PORT_Realloc(p12cxt->buffer, newsize); - if (NULL == newbuffer) { - return -1; /* can't extend the buffer */ - } - p12cxt->buffer = newbuffer; - p12cxt->allocated = newsize; - } - PR_ASSERT(p12cxt->buffer); - memcpy((char*)p12cxt->buffer + p12cxt->currentpos, buf, len); - p12cxt->currentpos += len; - return len; -} - -/* SEC_PKCS12DecoderStart - * Creates a decoder context for decoding a PKCS 12 PDU objct. - * This function sets up the initial decoding context for the - * PFX and sets the needed state variables. - * - * pwitem - the password for the hMac and any encoded safes. - * this should be changed to take a callback which retrieves - * the password. it may be possible for different safes to - * have different passwords. also, the password is already - * in unicode. it should probably be converted down below via - * a unicode conversion callback. - * slot - the slot to import the dataa into should multiple slots - * be supported based on key type and cert type? - * dOpen, dClose, dRead, dWrite - digest routines for writing data - * to a file so it could be read back and the hmack recomputed - * and verified. doesn't seem to be away for both encoding - * and decoding to be single pass, thus the need for these - * routines. - * dArg - the argument for dOpen, etc. - * - * if NULL == dOpen == dClose == dRead == dWrite == dArg, then default - * implementations using a memory buffer are used - * - * This function returns the decoder context, if it was successful. - * Otherwise, null is returned. - */ -SEC_PKCS12DecoderContext * -SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx, - digestOpenFn dOpen, digestCloseFn dClose, - digestIOFn dRead, digestIOFn dWrite, void *dArg) -{ - SEC_PKCS12DecoderContext *p12dcx; - PRArenaPool *arena; - - arena = PORT_NewArena(2048); /* different size? */ - if(!arena) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - /* allocate the decoder context and set the state variables */ - p12dcx = (SEC_PKCS12DecoderContext*)PORT_ArenaZAlloc(arena, sizeof(SEC_PKCS12DecoderContext)); - if(!p12dcx) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - if (!dOpen && !dClose && !dRead && !dWrite && !dArg) { - /* use default implementations */ - dOpen = p12u_DigestOpen; - dClose = p12u_DigestClose; - dRead = p12u_DigestRead; - dWrite = p12u_DigestWrite; - dArg = (void*)p12dcx; - } - - p12dcx->arena = arena; - p12dcx->pwitem = pwitem; - p12dcx->slot = (slot ? PK11_ReferenceSlot(slot) - : PK11_GetInternalKeySlot()); - p12dcx->wincx = wincx; - p12dcx->tokenCAs = SECPKCS12TargetTokenNoCAs; -#ifdef IS_LITTLE_ENDIAN - p12dcx->swapUnicodeBytes = PR_TRUE; -#else - p12dcx->swapUnicodeBytes = PR_FALSE; -#endif - p12dcx->errorValue = 0; - p12dcx->error = PR_FALSE; - - /* start the decoding of the PFX and set the notify proc - * for the PFX item. - */ - p12dcx->pfxDcx = SEC_ASN1DecoderStart(p12dcx->arena, &p12dcx->pfx, - sec_PKCS12PFXItemTemplate); - if(!p12dcx->pfxDcx) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - PK11_FreeSlot(p12dcx->slot); - goto loser; - } - - SEC_ASN1DecoderSetNotifyProc(p12dcx->pfxDcx, - sec_pkcs12_decoder_pfx_notify_proc, - p12dcx); - - /* set up digest functions */ - p12dcx->dOpen = dOpen; - p12dcx->dWrite = dWrite; - p12dcx->dClose = dClose; - p12dcx->dRead = dRead; - p12dcx->dArg = dArg; - - p12dcx->keyList = NULL; - p12dcx->decitem.type = 0; - p12dcx->decitem.der = NULL; - p12dcx->decitem.hasKey = PR_FALSE; - p12dcx->decitem.friendlyName = NULL; - p12dcx->iteration = 0; - - return p12dcx; - -loser: - PORT_FreeArena(arena, PR_TRUE); - return NULL; -} - -SECStatus -SEC_PKCS12DecoderSetTargetTokenCAs(SEC_PKCS12DecoderContext *p12dcx, - SECPKCS12TargetTokenCAs tokenCAs) -{ - if (!p12dcx || p12dcx->error) { - return SECFailure; - } - p12dcx->tokenCAs = tokenCAs; - return SECSuccess; -} - - -/* SEC_PKCS12DecoderUpdate - * Streaming update sending more data to the decoder. If - * an error occurs, SECFailure is returned. - * - * p12dcx - the decoder context - * data, len - the data buffer and length of data to send to - * the update functions. - */ -SECStatus -SEC_PKCS12DecoderUpdate(SEC_PKCS12DecoderContext *p12dcx, - unsigned char *data, unsigned long len) -{ - SECStatus rv; - - if(!p12dcx || p12dcx->error) { - return SECFailure; - } - - /* update the PFX decoder context */ - rv = SEC_ASN1DecoderUpdate(p12dcx->pfxDcx, (const char *)data, len); - if(rv != SECSuccess) { - p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE; - goto loser; - } - - return SECSuccess; - -loser: - - p12dcx->error = PR_TRUE; - return SECFailure; -} - -/* This should be a nice sized buffer for reading in data (potentially large -** amounts) to be MACed. It should be MUCH larger than HASH_LENGTH_MAX. -*/ -#define IN_BUF_LEN 1024 -#ifdef DEBUG -static const char bufferEnd[] = { "BufferEnd" } ; -#endif -#define FUDGE 128 /* must be as large as bufferEnd or more. */ - -/* verify the hmac by reading the data from the temporary file - * using the routines specified when the decodingContext was - * created and return SECSuccess if the hmac matches. - */ -static SECStatus -sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx) -{ - PK11Context * pk11cx = NULL; - PK11SymKey * symKey = NULL; - SECItem * params = NULL; - unsigned char * buf; - SECStatus rv = SECFailure; - SECStatus lrv; - unsigned int bufLen; - int iteration; - int bytesRead; - SECOidTag algtag; - SECItem hmacRes; - SECItem ignore = {0}; - CK_MECHANISM_TYPE integrityMech; - - if(!p12dcx || p12dcx->error) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - buf = (unsigned char *)PORT_Alloc(IN_BUF_LEN + FUDGE); - if (!buf) - return SECFailure; /* error code has been set. */ - -#ifdef DEBUG - memcpy(buf + IN_BUF_LEN, bufferEnd, sizeof bufferEnd); -#endif - - /* generate hmac key */ - if(p12dcx->macData.iter.data) { - iteration = (int)DER_GetInteger(&p12dcx->macData.iter); - } else { - iteration = 1; - } - - params = PK11_CreatePBEParams(&p12dcx->macData.macSalt, p12dcx->pwitem, - iteration); - - algtag = SECOID_GetAlgorithmTag(&p12dcx->macData.safeMac.digestAlgorithm); - switch (algtag) { - case SEC_OID_SHA1: - integrityMech = CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN; break; - case SEC_OID_MD5: - integrityMech = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN; break; - case SEC_OID_MD2: - integrityMech = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN; break; - default: - goto loser; - } - - symKey = PK11_KeyGen(NULL, integrityMech, params, 20, NULL); - PK11_DestroyPBEParams(params); - params = NULL; - if (!symKey) goto loser; - /* init hmac */ - pk11cx = PK11_CreateContextBySymKey(sec_pkcs12_algtag_to_mech(algtag), - CKA_SIGN, symKey, &ignore); - if(!pk11cx) { - goto loser; - } - lrv = PK11_DigestBegin(pk11cx); - if (lrv == SECFailure ) { - goto loser; - } - - /* try to open the data for readback */ - if(p12dcx->dOpen && ((*p12dcx->dOpen)(p12dcx->dArg, PR_TRUE) - != SECSuccess)) { - goto loser; - } - - /* read the data back IN_BUF_LEN bytes at a time and recompute - * the hmac. if fewer bytes are read than are requested, it is - * assumed that the end of file has been reached. if bytesRead - * is returned as -1, then an error occured reading from the - * file. - */ - do { - bytesRead = (*p12dcx->dRead)(p12dcx->dArg, buf, IN_BUF_LEN); - if (bytesRead < 0) { - PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_READ); - goto loser; - } - PORT_Assert(bytesRead <= IN_BUF_LEN); - PORT_Assert(!memcmp(buf + IN_BUF_LEN, bufferEnd, sizeof bufferEnd)); - - if (bytesRead > IN_BUF_LEN) { - /* dRead callback overflowed buffer. */ - PORT_SetError(SEC_ERROR_INPUT_LEN); - goto loser; - } - - if (bytesRead) { - lrv = PK11_DigestOp(pk11cx, buf, bytesRead); - if (lrv == SECFailure) { - goto loser; - } - } - } while (bytesRead == IN_BUF_LEN); - - /* finish the hmac context */ - lrv = PK11_DigestFinal(pk11cx, buf, &bufLen, IN_BUF_LEN); - if (lrv == SECFailure ) { - goto loser; - } - - hmacRes.data = buf; - hmacRes.len = bufLen; - - /* is the hmac computed the same as the hmac which was decoded? */ - rv = SECSuccess; - if(SECITEM_CompareItem(&hmacRes, &p12dcx->macData.safeMac.digest) - != SECEqual) { - PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC); - rv = SECFailure; - } - -loser: - /* close the file and remove it */ - if(p12dcx->dClose) { - (*p12dcx->dClose)(p12dcx->dArg, PR_TRUE); - } - - if(pk11cx) { - PK11_DestroyContext(pk11cx, PR_TRUE); - } - if (params) { - PK11_DestroyPBEParams(params); - } - if (symKey) { - PK11_FreeSymKey(symKey); - } - PORT_ZFree(buf, IN_BUF_LEN + FUDGE); - - return rv; -} - -/* SEC_PKCS12DecoderVerify - * Verify the macData or the signature of the decoded PKCS 12 PDU. - * If the signature or the macData do not match, SECFailure is - * returned. - * - * p12dcx - the decoder context - */ -SECStatus -SEC_PKCS12DecoderVerify(SEC_PKCS12DecoderContext *p12dcx) -{ - SECStatus rv = SECSuccess; - - /* make sure that no errors have occured... */ - if(!p12dcx || p12dcx->error) { - return SECFailure; - } - - rv = SEC_ASN1DecoderFinish(p12dcx->pfxDcx); - p12dcx->pfxDcx = NULL; - if(rv != SECSuccess) { - return rv; - } - - /* check the signature or the mac depending on the type of - * integrity used. - */ - if(p12dcx->pfx.encodedMacData.len) { - rv = SEC_ASN1DecodeItem(p12dcx->arena, &p12dcx->macData, - sec_PKCS12MacDataTemplate, - &p12dcx->pfx.encodedMacData); - if(rv == SECSuccess) { - return sec_pkcs12_decoder_verify_mac(p12dcx); - } else { - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - } else { - if(SEC_PKCS7VerifySignature(p12dcx->aSafeCinfo, certUsageEmailSigner, - PR_FALSE)) { - return SECSuccess; - } else { - PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC); - } - } - - return SECFailure; -} - -/* SEC_PKCS12DecoderFinish - * Free any open ASN1 or PKCS7 decoder contexts and then - * free the arena pool which everything should be allocated - * from. This function should be called upon completion of - * decoding and installing of a pfx pdu. This should be - * called even if an error occurs. - * - * p12dcx - the decoder context - */ -void -SEC_PKCS12DecoderFinish(SEC_PKCS12DecoderContext *p12dcx) -{ - if(!p12dcx) { - return; - } - - if(p12dcx->pfxDcx) { - SEC_ASN1DecoderFinish(p12dcx->pfxDcx); - p12dcx->pfxDcx = NULL; - } - - if(p12dcx->aSafeDcx) { - SEC_ASN1DecoderFinish(p12dcx->aSafeDcx); - p12dcx->aSafeDcx = NULL; - } - - if(p12dcx->currentASafeP7Dcx) { - SEC_PKCS7DecoderFinish(p12dcx->currentASafeP7Dcx); - p12dcx->currentASafeP7Dcx = NULL; - } - - if(p12dcx->aSafeP7Dcx) { - SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx); - } - - if(p12dcx->hmacDcx) { - SEC_ASN1DecoderFinish(p12dcx->hmacDcx); - p12dcx->hmacDcx = NULL; - } - - if (p12dcx->decitem.type != 0 && p12dcx->decitem.der != NULL) { - SECITEM_FreeItem(p12dcx->decitem.der, PR_TRUE); - } - if (p12dcx->decitem.friendlyName != NULL) { - SECITEM_FreeItem(p12dcx->decitem.friendlyName, PR_TRUE); - } - - if(p12dcx->slot) { - PK11_FreeSlot(p12dcx->slot); - p12dcx->slot = NULL; - } - - if(p12dcx->arena) { - PORT_FreeArena(p12dcx->arena, PR_TRUE); - } -} - -static SECStatus -sec_pkcs12_decoder_set_attribute_value(sec_PKCS12SafeBag *bag, - SECOidTag attributeType, - SECItem *attrValue) -{ - int i = 0; - SECOidData *oid; - - if(!bag || !attrValue) { - return SECFailure; - } - - oid = SECOID_FindOIDByTag(attributeType); - if(!oid) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - - if(!bag->attribs) { - bag->attribs = (sec_PKCS12Attribute**)PORT_ArenaZAlloc(bag->arena, - sizeof(sec_PKCS12Attribute *) * 2); - } else { - while(bag->attribs[i]) i++; - bag->attribs = (sec_PKCS12Attribute **)PORT_ArenaGrow(bag->arena, - bag->attribs, - (i + 1) * sizeof(sec_PKCS12Attribute *), - (i + 2) * sizeof(sec_PKCS12Attribute *)); - } - - if(!bag->attribs) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - - bag->attribs[i] = (sec_PKCS12Attribute*)PORT_ArenaZAlloc(bag->arena, - sizeof(sec_PKCS12Attribute)); - if(!bag->attribs) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - - bag->attribs[i]->attrValue = (SECItem**)PORT_ArenaZAlloc(bag->arena, - sizeof(SECItem *) * 2); - if(!bag->attribs[i]->attrValue) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - - bag->attribs[i+1] = NULL; - bag->attribs[i]->attrValue[0] = attrValue; - bag->attribs[i]->attrValue[1] = NULL; - - if(SECITEM_CopyItem(bag->arena, &bag->attribs[i]->attrType, &oid->oid) - != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - - return SECSuccess; -} - -static SECItem * -sec_pkcs12_get_attribute_value(sec_PKCS12SafeBag *bag, - SECOidTag attributeType) -{ - int i = 0; - - if(!bag->attribs) { - return NULL; - } - - while(bag->attribs[i] != NULL) { - if(SECOID_FindOIDTag(&bag->attribs[i]->attrType) - == attributeType) { - return bag->attribs[i]->attrValue[0]; - } - i++; - } - - return NULL; -} - -/* For now, this function will merely remove any ":" - * in the nickname which the PK11 functions may have - * placed there. This will keep dual certs from appearing - * twice under "Your" certificates when imported onto smart - * cards. Once with the name "Slot:Cert" and another with - * the nickname "Slot:Slot:Cert" - */ -static void -sec_pkcs12_sanitize_nickname(PK11SlotInfo *slot, SECItem *nick) -{ - char *nickname; - char *delimit; - int delimitlen; - - nickname = (char*)nick->data; /*Mac breaks without this type cast*/ - if ((delimit = PORT_Strchr(nickname, ':')) != NULL) { - char *slotName; - int slotNameLen; - - slotNameLen = delimit-nickname; - slotName = PORT_NewArray(char, (slotNameLen+1)); - PORT_Assert(slotName); - if (slotName == NULL) { - /* What else can we do?*/ - return; - } - PORT_Memcpy(slotName, nickname, slotNameLen); - slotName[slotNameLen] = '\0'; - if (PORT_Strcmp(PK11_GetTokenName(slot), slotName) == 0) { - delimitlen = PORT_Strlen(delimit+1); - PORT_Memmove(nickname, delimit+1, delimitlen+1); - nick->len = delimitlen; - } - PORT_Free(slotName); - } - -} - -static SECItem * -sec_pkcs12_get_nickname(sec_PKCS12SafeBag *bag) -{ - SECItem *src, *dest; - - if(!bag) { - bag->problem = PR_TRUE; - bag->error = SEC_ERROR_NO_MEMORY; - return NULL; - } - - src = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_FRIENDLY_NAME); - if(!src) { - return NULL; - } - - dest = (SECItem*)PORT_ZAlloc(sizeof(SECItem)); - if(!dest) { - goto loser; - } - if(!sec_pkcs12_convert_item_to_unicode(NULL, dest, src, PR_FALSE, - PR_FALSE, PR_FALSE)) { - goto loser; - } - - sec_pkcs12_sanitize_nickname(bag->slot, dest); - - return dest; - -loser: - if(dest) { - SECITEM_ZfreeItem(dest, PR_TRUE); - } - - bag->problem = PR_TRUE; - bag->error = PORT_GetError(); - return NULL; -} - -static SECStatus -sec_pkcs12_set_nickname(sec_PKCS12SafeBag *bag, SECItem *name) -{ - int i = 0; - sec_PKCS12Attribute *attr = NULL; - SECOidData *oid = SECOID_FindOIDByTag(SEC_OID_PKCS9_FRIENDLY_NAME); - - if(!bag || !bag->arena || !name) { - return SECFailure; - } - - if(!bag->attribs) { - if(!oid) { - goto loser; - } - - bag->attribs = (sec_PKCS12Attribute**)PORT_ArenaZAlloc(bag->arena, - sizeof(sec_PKCS12Attribute *)*2); - if(!bag->attribs) { - goto loser; - } - bag->attribs[0] = (sec_PKCS12Attribute*)PORT_ArenaZAlloc(bag->arena, - sizeof(sec_PKCS12Attribute)); - if(!bag->attribs[0]) { - goto loser; - } - bag->attribs[1] = NULL; - - attr = bag->attribs[0]; - if(SECITEM_CopyItem(bag->arena, &attr->attrType, &oid->oid) - != SECSuccess) { - goto loser; - } - } else { - while(bag->attribs[i]) { - if(SECOID_FindOIDTag(&bag->attribs[i]->attrType) - == SEC_OID_PKCS9_FRIENDLY_NAME) { - attr = bag->attribs[i]; - goto have_attrib; - - } - i++; - } - if(!attr) { - bag->attribs = (sec_PKCS12Attribute **)PORT_ArenaGrow(bag->arena, - bag->attribs, - (i+1) * sizeof(sec_PKCS12Attribute *), - (i+2) * sizeof(sec_PKCS12Attribute *)); - if(!bag->attribs) { - goto loser; - } - bag->attribs[i] = - (sec_PKCS12Attribute *)PORT_ArenaZAlloc(bag->arena, - sizeof(sec_PKCS12Attribute)); - if(!bag->attribs[i]) { - goto loser; - } - bag->attribs[i+1] = NULL; - attr = bag->attribs[i]; - if(SECITEM_CopyItem(bag->arena, &attr->attrType, &oid->oid) - != SECSuccess) { - goto loser; - } - } - } -have_attrib: - PORT_Assert(attr); - if(!attr->attrValue) { - attr->attrValue = (SECItem **)PORT_ArenaZAlloc(bag->arena, - sizeof(SECItem *) * 2); - if(!attr->attrValue) { - goto loser; - } - attr->attrValue[0] = (SECItem*)PORT_ArenaZAlloc(bag->arena, - sizeof(SECItem)); - if(!attr->attrValue[0]) { - goto loser; - } - attr->attrValue[1] = NULL; - } - - name->len = PORT_Strlen((char *)name->data); - if(!sec_pkcs12_convert_item_to_unicode(bag->arena, attr->attrValue[0], - name, PR_FALSE, PR_FALSE, PR_TRUE)) { - goto loser; - } - - return SECSuccess; - -loser: - bag->problem = PR_TRUE; - bag->error = SEC_ERROR_NO_MEMORY; - return SECFailure; -} - -static SECStatus -sec_pkcs12_get_key_info(sec_PKCS12SafeBag *key) -{ - int i = 0; - SECKEYPrivateKeyInfo *pki = NULL; - - if(!key) { - return SECFailure; - } - - /* if the bag does *not* contain an unencrypted PrivateKeyInfo - * then we cannot convert the attributes. We are propagating - * attributes within the PrivateKeyInfo to the SafeBag level. - */ - if(SECOID_FindOIDTag(&(key->safeBagType)) != - SEC_OID_PKCS12_V1_KEY_BAG_ID) { - return SECSuccess; - } - - pki = key->safeBagContent.pkcs8KeyBag; - - if(!pki || !pki->attributes) { - return SECSuccess; - } - - while(pki->attributes[i]) { - SECItem *attrValue = NULL; - - if(SECOID_FindOIDTag(&pki->attributes[i]->attrType) == - SEC_OID_PKCS9_LOCAL_KEY_ID) { - attrValue = sec_pkcs12_get_attribute_value(key, - SEC_OID_PKCS9_LOCAL_KEY_ID); - if(!attrValue) { - if(sec_pkcs12_decoder_set_attribute_value(key, - SEC_OID_PKCS9_LOCAL_KEY_ID, - pki->attributes[i]->attrValue[0]) - != SECSuccess) { - key->problem = PR_TRUE; - key->error = SEC_ERROR_NO_MEMORY; - return SECFailure; - } - } - } - - if(SECOID_FindOIDTag(&pki->attributes[i]->attrType) == - SEC_OID_PKCS9_FRIENDLY_NAME) { - attrValue = sec_pkcs12_get_attribute_value(key, - SEC_OID_PKCS9_FRIENDLY_NAME); - if(!attrValue) { - if(sec_pkcs12_decoder_set_attribute_value(key, - SEC_OID_PKCS9_FRIENDLY_NAME, - pki->attributes[i]->attrValue[0]) - != SECSuccess) { - key->problem = PR_TRUE; - key->error = SEC_ERROR_NO_MEMORY; - return SECFailure; - } - } - } - - i++; - } - - return SECSuccess; -} - -/* retrieve the nickname for the certificate bag. first look - * in the cert bag, otherwise get it from the key. - */ -static SECItem * -sec_pkcs12_get_nickname_for_cert(sec_PKCS12SafeBag *cert, - sec_PKCS12SafeBag *key, - void *wincx) -{ - SECItem *nickname; - - if(!cert) { - return NULL; - } - - nickname = sec_pkcs12_get_nickname(cert); - if(nickname) { - return nickname; - } - - if(key) { - nickname = sec_pkcs12_get_nickname(key); - - if(nickname && sec_pkcs12_set_nickname(cert, nickname) - != SECSuccess) { - cert->error = SEC_ERROR_NO_MEMORY; - cert->problem = PR_TRUE; - if(nickname) { - SECITEM_ZfreeItem(nickname, PR_TRUE); - } - return NULL; - } - } - - return nickname; -} - -/* set the nickname for the certificate */ -static SECStatus -sec_pkcs12_set_nickname_for_cert(sec_PKCS12SafeBag *cert, - sec_PKCS12SafeBag *key, - SECItem *nickname, - void *wincx) -{ - if(!nickname || !cert) { - return SECFailure; - } - - if(sec_pkcs12_set_nickname(cert, nickname) != SECSuccess) { - cert->error = SEC_ERROR_NO_MEMORY; - cert->problem = PR_TRUE; - return SECFailure; - } - - if(key) { - if(sec_pkcs12_set_nickname(key, nickname) != SECSuccess) { - cert->error = SEC_ERROR_NO_MEMORY; - cert->problem = PR_TRUE; - return SECFailure; - } - } - - return SECSuccess; -} - -/* retrieve the DER cert from the cert bag */ -static SECItem * -sec_pkcs12_get_der_cert(sec_PKCS12SafeBag *cert) -{ - if(!cert) { - return NULL; - } - - if(SECOID_FindOIDTag(&cert->safeBagType) != SEC_OID_PKCS12_V1_CERT_BAG_ID) { - return NULL; - } - - /* only support X509 certs not SDSI */ - if(SECOID_FindOIDTag(&cert->safeBagContent.certBag->bagID) - != SEC_OID_PKCS9_X509_CERT) { - return NULL; - } - - return SECITEM_DupItem(&(cert->safeBagContent.certBag->value.x509Cert)); -} - -struct certNickInfo { - PRArenaPool *arena; - unsigned int nNicks; - SECItem **nickList; - unsigned int error; -}; - -/* callback for traversing certificates to gather the nicknames - * used in a particular traversal. for instance, when using - * CERT_TraversePermCertsForSubject, gather the nicknames and - * store them in the certNickInfo for a particular DN. - * - * this handles the case where multiple nicknames are allowed - * for the same dn, which is not currently allowed, but may be - * in the future. - */ -static SECStatus -gatherNicknames(CERTCertificate *cert, void *arg) -{ - struct certNickInfo *nickArg = (struct certNickInfo *)arg; - SECItem tempNick; - unsigned int i; - - if(!cert || !nickArg || nickArg->error) { - return SECFailure; - } - - if(!cert->nickname) { - return SECSuccess; - } - - tempNick.data = (unsigned char *)cert->nickname; - tempNick.len = PORT_Strlen(cert->nickname) + 1; - - /* do we already have the nickname in the list? */ - if(nickArg->nNicks > 0) { - - /* nicknames have been encountered, but there is no list -- bad */ - if(!nickArg->nickList) { - nickArg->error = SEC_ERROR_NO_MEMORY; - return SECFailure; - } - - for(i = 0; i < nickArg->nNicks; i++) { - if(SECITEM_CompareItem(nickArg->nickList[i], &tempNick) - == SECEqual) { - return SECSuccess; - } - } - } - - /* add the nickname to the list */ - if(nickArg->nNicks == 0) { - nickArg->nickList = (SECItem **)PORT_ArenaZAlloc(nickArg->arena, - 2 * sizeof(SECItem *)); - } else { - nickArg->nickList = (SECItem **)PORT_ArenaGrow(nickArg->arena, - nickArg->nickList, - (nickArg->nNicks + 1) * sizeof(SECItem *), - (nickArg->nNicks + 2) * sizeof(SECItem *)); - } - if(!nickArg->nickList) { - nickArg->error = SEC_ERROR_NO_MEMORY; - return SECFailure; - } - - nickArg->nickList[nickArg->nNicks] = - (SECItem *)PORT_ArenaZAlloc(nickArg->arena, sizeof(SECItem)); - if(!nickArg->nickList[nickArg->nNicks]) { - nickArg->error = SEC_ERROR_NO_MEMORY; - return SECFailure; - } - - - if(SECITEM_CopyItem(nickArg->arena, nickArg->nickList[nickArg->nNicks], - &tempNick) != SECSuccess) { - nickArg->error = SEC_ERROR_NO_MEMORY; - return SECFailure; - } - - nickArg->nNicks++; - - return SECSuccess; -} - -/* traverses the certs in the data base or in the token for the - * DN to see if any certs currently have a nickname set. - * If so, return it. - */ -static SECItem * -sec_pkcs12_get_existing_nick_for_dn(sec_PKCS12SafeBag *cert, void *wincx) -{ - struct certNickInfo *nickArg = NULL; - SECItem *derCert, *returnDn = NULL; - PRArenaPool *arena = NULL; - CERTCertificate *tempCert; - - if(!cert) { - return NULL; - } - - derCert = sec_pkcs12_get_der_cert(cert); - if(!derCert) { - return NULL; - } - - tempCert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); - if(!tempCert) { - returnDn = NULL; - goto loser; - } - - arena = PORT_NewArena(1024); - if(!arena) { - returnDn = NULL; - goto loser; - } - nickArg = (struct certNickInfo *)PORT_ArenaZAlloc(arena, - sizeof(struct certNickInfo)); - if(!nickArg) { - returnDn = NULL; - goto loser; - } - nickArg->error = 0; - nickArg->nNicks = 0; - nickArg->nickList = NULL; - nickArg->arena = arena; - - /* if the token is local, first traverse the cert database - * then traverse the token. - */ - if(PK11_TraverseCertsForSubjectInSlot(tempCert, cert->slot, gatherNicknames, - (void *)nickArg) != SECSuccess) { - returnDn = NULL; - goto loser; - } - - if(nickArg->error) { - /* XXX do we want to set the error? */ - returnDn = NULL; - goto loser; - } - - if(nickArg->nNicks == 0) { - returnDn = NULL; - goto loser; - } - - /* set it to the first name, for now. handle multiple names? */ - returnDn = SECITEM_DupItem(nickArg->nickList[0]); - -loser: - if(arena) { - PORT_FreeArena(arena, PR_TRUE); - } - - if(tempCert) { - CERT_DestroyCertificate(tempCert); - } - - if(derCert) { - SECITEM_FreeItem(derCert, PR_TRUE); - } - - return (returnDn); -} - -/* counts certificates found for a given traversal function */ -static SECStatus -countCertificate(CERTCertificate *cert, void *arg) -{ - unsigned int *nCerts = (unsigned int *)arg; - - if(!cert || !arg) { - return SECFailure; - } - - (*nCerts)++; - return SECSuccess; -} - -static PRBool -sec_pkcs12_certs_for_nickname_exist(SECItem *nickname, PK11SlotInfo *slot) -{ - unsigned int nCerts = 0; - - if(!nickname || !slot) { - return PR_TRUE; - } - - /* we want to check the local database first if we are importing to it */ - PK11_TraverseCertsForNicknameInSlot(nickname, slot, countCertificate, - (void *)&nCerts); - if(nCerts) return PR_TRUE; - - return PR_FALSE; -} - -/* validate cert nickname such that there is a one-to-one relation - * between nicknames and dn's. we want to enforce the case that the - * nickname is non-NULL and that there is only one nickname per DN. - * - * if there is a problem with a nickname or the nickname is not present, - * the user will be prompted for it. - */ -static void -sec_pkcs12_validate_cert_nickname(sec_PKCS12SafeBag *cert, - sec_PKCS12SafeBag *key, - SEC_PKCS12NicknameCollisionCallback nicknameCb, - void *wincx) -{ - SECItem *certNickname, *existingDNNick; - PRBool setNickname = PR_FALSE, cancel = PR_FALSE; - SECItem *newNickname = NULL; - - if(!cert || !cert->hasKey) { - return; - } - - if(!nicknameCb) { - cert->problem = PR_TRUE; - cert->error = SEC_ERROR_NO_MEMORY; - return; - } - - if(cert->hasKey && !key) { - cert->problem = PR_TRUE; - cert->error = SEC_ERROR_NO_MEMORY; - return; - } - - certNickname = sec_pkcs12_get_nickname_for_cert(cert, key, wincx); - existingDNNick = sec_pkcs12_get_existing_nick_for_dn(cert, wincx); - - /* nickname is already used w/ this dn, so it is safe to return */ - if(certNickname && existingDNNick && - SECITEM_CompareItem(certNickname, existingDNNick) == SECEqual) { - goto loser; - } - - /* nickname not set in pkcs 12 bags, but a nick is already used for - * this dn. set the nicks in the p12 bags and finish. - */ - if(existingDNNick) { - if(sec_pkcs12_set_nickname_for_cert(cert, key, existingDNNick, wincx) - != SECSuccess) { - cert->problem = PR_TRUE; - cert->error = SEC_ERROR_NO_MEMORY; - } - goto loser; - } - - /* at this point, we have a certificate for which the DN is not located - * on the token. the nickname specified may or may not be NULL. if it - * is not null, we need to make sure that there are no other certificates - * with this nickname in the token for it to be valid. this imposes a - * one to one relationship between DN and nickname. - * - * if the nickname is null, we need the user to enter a nickname for - * the certificate. - * - * once we have a nickname, we make sure that the nickname is unique - * for the DN. if it is not, the user is reprompted to enter a new - * nickname. - * - * in order to exit this loop, the nickname entered is either unique - * or the user hits cancel and the certificate is not imported. - */ - setNickname = PR_FALSE; - while(1) { - if(certNickname && certNickname->data) { - /* we will use the nickname so long as no other certs have the - * same nickname. and the nickname is not NULL. - */ - if(!sec_pkcs12_certs_for_nickname_exist(certNickname, cert->slot)) { - if(setNickname) { - if(sec_pkcs12_set_nickname_for_cert(cert, key, certNickname, - wincx) != SECSuccess) { - cert->problem = PR_TRUE; - cert->error = SEC_ERROR_NO_MEMORY; - } - } - goto loser; - } - } - - setNickname = PR_FALSE; - newNickname = (*nicknameCb)(certNickname, &cancel, wincx); - if(cancel) { - cert->problem = PR_TRUE; - cert->error = SEC_ERROR_USER_CANCELLED; - goto loser; - } - - if(!newNickname) { - cert->problem = PR_TRUE; - cert->error = SEC_ERROR_NO_MEMORY; - goto loser; - } - - /* at this point we have a new nickname, if we have an existing - * certNickname, we need to free it and assign the new nickname - * to it to avoid a memory leak. happy? - */ - if(certNickname) { - SECITEM_ZfreeItem(certNickname, PR_TRUE); - certNickname = NULL; - } - - certNickname = newNickname; - setNickname = PR_TRUE; - /* go back and recheck the new nickname */ - } - -loser: - if(certNickname) { - SECITEM_ZfreeItem(certNickname, PR_TRUE); - } - - if(existingDNNick) { - SECITEM_ZfreeItem(existingDNNick, PR_TRUE); - } -} - -static void -sec_pkcs12_validate_cert(sec_PKCS12SafeBag *cert, - sec_PKCS12SafeBag *key, - SEC_PKCS12NicknameCollisionCallback nicknameCb, - void *wincx) -{ - CERTCertificate *leafCert; - - if(!cert) { - return; - } - - cert->validated = PR_TRUE; - - if(!nicknameCb) { - cert->problem = PR_TRUE; - cert->error = SEC_ERROR_NO_MEMORY; - cert->noInstall = PR_TRUE; - return; - } - - if(!cert->safeBagContent.certBag) { - cert->noInstall = PR_TRUE; - cert->problem = PR_TRUE; - cert->error = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE; - return; - } - - cert->noInstall = PR_FALSE; - cert->unused = PR_FALSE; - cert->problem = PR_FALSE; - cert->error = 0; - - leafCert = CERT_DecodeDERCertificate( - &cert->safeBagContent.certBag->value.x509Cert, PR_FALSE, NULL); - if(!leafCert) { - cert->noInstall = PR_TRUE; - cert->problem = PR_TRUE; - cert->error = SEC_ERROR_NO_MEMORY; - return; - } - - CERT_DestroyCertificate(leafCert); - - sec_pkcs12_validate_cert_nickname(cert, key, nicknameCb, wincx); -} - -static void -sec_pkcs12_validate_key_by_cert(sec_PKCS12SafeBag *cert, sec_PKCS12SafeBag *key, - void *wincx) -{ - CERTCertificate *leafCert; - SECKEYPrivateKey *privk; - - if(!key) { - return; - } - - key->validated = PR_TRUE; - - if(!cert) { - key->problem = PR_TRUE; - key->noInstall = PR_TRUE; - key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY; - return; - } - - leafCert = CERT_DecodeDERCertificate( - &(cert->safeBagContent.certBag->value.x509Cert), PR_FALSE, NULL); - if(!leafCert) { - key->problem = PR_TRUE; - key->noInstall = PR_TRUE; - key->error = SEC_ERROR_NO_MEMORY; - return; - } - - privk = PK11_FindPrivateKeyFromCert(key->slot, leafCert, wincx); - if(!privk) { - privk = PK11_FindKeyByDERCert(key->slot, leafCert, wincx); - } - - if(privk) { - SECKEY_DestroyPrivateKey(privk); - key->noInstall = PR_TRUE; - } - - CERT_DestroyCertificate(leafCert); -} - -static SECStatus -sec_pkcs12_add_cert(sec_PKCS12SafeBag *cert, PRBool keyExists, void *wincx) -{ - SECItem *derCert, *nickName; - char *nickData = NULL; - PRBool isIntermediateCA; - SECStatus rv; - - if(!cert) { - return SECFailure; - } - - if(cert->problem || cert->noInstall || cert->installed) { - return SECSuccess; - } - - derCert = &cert->safeBagContent.certBag->value.x509Cert; - - PORT_Assert(!cert->problem && !cert->noInstall); - - nickName = sec_pkcs12_get_nickname(cert); - if(nickName) { - nickData = (char *)nickName->data; - } - - isIntermediateCA = CERT_IsCADERCert(derCert, NULL) && - !CERT_IsRootDERCert(derCert); - - if(keyExists) { - CERTCertificate *newCert; - - newCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), - derCert, NULL, PR_FALSE, PR_FALSE); - if(!newCert) { - if(nickName) SECITEM_ZfreeItem(nickName, PR_TRUE); - cert->error = PORT_GetError(); - cert->problem = PR_TRUE; - return SECFailure; - } - - rv = PK11_ImportCertForKeyToSlot(cert->slot, newCert, nickData, - PR_TRUE, wincx); - CERT_DestroyCertificate(newCert); - } else if ((cert->tokenCAs == SECPKCS12TargetTokenNoCAs) || - ((cert->tokenCAs == SECPKCS12TargetTokenIntermediateCAs) && - !isIntermediateCA)) { - SECItem *certList[2]; - certList[0] = derCert; - certList[1] = NULL; - - rv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageUserCertImport, - 1, certList, NULL, PR_TRUE, PR_FALSE, nickData); - } else { - rv = PK11_ImportDERCert(cert->slot, derCert, CK_INVALID_HANDLE, - nickData, PR_FALSE); - } - - cert->installed = PR_TRUE; - if(nickName) SECITEM_ZfreeItem(nickName, PR_TRUE); - return rv; -} - -static SECStatus -sec_pkcs12_add_key(sec_PKCS12SafeBag *key, SECItem *publicValue, - KeyType keyType, unsigned int keyUsage, void *wincx) -{ - SECStatus rv; - SECItem *nickName; - - if(!key) { - return SECFailure; - } - - if(key->problem || key->noInstall) { - return SECSuccess; - } - - nickName = sec_pkcs12_get_nickname(key); - - switch(SECOID_FindOIDTag(&key->safeBagType)) - { - case SEC_OID_PKCS12_V1_KEY_BAG_ID: - rv = PK11_ImportPrivateKeyInfo(key->slot, - key->safeBagContent.pkcs8KeyBag, - nickName, publicValue, PR_TRUE, PR_TRUE, - keyUsage, wincx); - break; - case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: - rv = PK11_ImportEncryptedPrivateKeyInfo(key->slot, - key->safeBagContent.pkcs8ShroudedKeyBag, - key->pwitem, nickName, publicValue, - PR_TRUE, PR_TRUE, keyType, keyUsage, - wincx); - break; - default: - key->error = SEC_ERROR_PKCS12_UNSUPPORTED_VERSION; - key->problem = PR_TRUE; - if(nickName) { - SECITEM_ZfreeItem(nickName, PR_TRUE); - } - return SECFailure; - } - - key->installed = PR_TRUE; - - if(nickName) { - SECITEM_ZfreeItem(nickName, PR_TRUE); - } - - if(rv != SECSuccess) { - key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY; - key->problem = PR_TRUE; - } else { - key->installed = PR_TRUE; - } - - return rv; -} - -static SECStatus -sec_pkcs12_add_item_to_bag_list(sec_PKCS12SafeBag ***bagList, - sec_PKCS12SafeBag *bag) -{ - int i = 0; - - if(!bagList || !bag) { - return SECFailure; - } - - if(!(*bagList)) { - (*bagList) = (sec_PKCS12SafeBag **)PORT_ArenaZAlloc(bag->arena, - sizeof(sec_PKCS12SafeBag *) * 2); - } else { - while((*bagList)[i]) i++; - (*bagList) = (sec_PKCS12SafeBag **)PORT_ArenaGrow(bag->arena, *bagList, - sizeof(sec_PKCS12SafeBag *) * (i + 1), - sizeof(sec_PKCS12SafeBag *) * (i + 2)); - } - - if(!(*bagList)) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - - (*bagList)[i] = bag; - (*bagList)[i+1] = NULL; - - return SECSuccess; -} - -static sec_PKCS12SafeBag ** -sec_pkcs12_find_certs_for_key(sec_PKCS12SafeBag **safeBags, sec_PKCS12SafeBag *key ) -{ - sec_PKCS12SafeBag **certList = NULL; - SECItem *keyId; - int i; - - if(!safeBags || !safeBags[0]) { - return NULL; - } - - keyId = sec_pkcs12_get_attribute_value(key, SEC_OID_PKCS9_LOCAL_KEY_ID); - if(!keyId) { - return NULL; - } - - i = 0; - certList = NULL; - while(safeBags[i]) { - if(SECOID_FindOIDTag(&(safeBags[i]->safeBagType)) - == SEC_OID_PKCS12_V1_CERT_BAG_ID) { - SECItem *certKeyId = sec_pkcs12_get_attribute_value(safeBags[i], - SEC_OID_PKCS9_LOCAL_KEY_ID); - - if(certKeyId && (SECITEM_CompareItem(certKeyId, keyId) - == SECEqual)) { - if(sec_pkcs12_add_item_to_bag_list(&certList, safeBags[i]) - != SECSuccess) { - return NULL; - } - } - } - i++; - } - - return certList; -} - -CERTCertList * -SEC_PKCS12DecoderGetCerts(SEC_PKCS12DecoderContext *p12dcx) -{ - CERTCertList *certList = NULL; - sec_PKCS12SafeBag **safeBags = p12dcx->safeBags; - int i; - - if (!p12dcx || !p12dcx->safeBags || !p12dcx->safeBags[0]) { - return NULL; - } - - safeBags = p12dcx->safeBags; - i = 0; - certList = CERT_NewCertList(); - - if (certList == NULL) { - return NULL; - } - - while(safeBags[i]) { - if (SECOID_FindOIDTag(&(safeBags[i]->safeBagType)) - == SEC_OID_PKCS12_V1_CERT_BAG_ID) { - SECItem *derCert = sec_pkcs12_get_der_cert(safeBags[i]) ; - CERTCertificate *tempCert = NULL; - - if (derCert == NULL) continue; - tempCert=CERT_NewTempCertificate(CERT_GetDefaultCertDB(), - derCert, NULL, - PR_FALSE, PR_TRUE); - - if (tempCert) { - CERT_AddCertToListTail(certList,tempCert); - } - SECITEM_FreeItem(derCert,PR_TRUE); - } - i++; - } - - return certList; -} -static sec_PKCS12SafeBag ** -sec_pkcs12_get_key_bags(sec_PKCS12SafeBag **safeBags) -{ - int i; - sec_PKCS12SafeBag **keyList = NULL; - SECOidTag bagType; - - if(!safeBags || !safeBags[0]) { - return NULL; - } - - i = 0; - while(safeBags[i]) { - bagType = SECOID_FindOIDTag(&(safeBags[i]->safeBagType)); - switch(bagType) { - case SEC_OID_PKCS12_V1_KEY_BAG_ID: - case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: - if(sec_pkcs12_add_item_to_bag_list(&keyList, safeBags[i]) - != SECSuccess) { - return NULL; - } - break; - default: - break; - } - i++; - } - - return keyList; -} - -static SECStatus -sec_pkcs12_validate_bags(sec_PKCS12SafeBag **safeBags, - SEC_PKCS12NicknameCollisionCallback nicknameCb, - void *wincx) -{ - sec_PKCS12SafeBag **keyList; - int i; - - if(!safeBags || !nicknameCb) { - return SECFailure; - } - - if(!safeBags[0]) { - return SECSuccess; - } - - keyList = sec_pkcs12_get_key_bags(safeBags); - if(keyList) { - i = 0; - - while(keyList[i]) { - sec_PKCS12SafeBag **certList = sec_pkcs12_find_certs_for_key( - safeBags, keyList[i]); - if(certList) { - int j = 0; - - if(SECOID_FindOIDTag(&(keyList[i]->safeBagType)) == - SEC_OID_PKCS12_V1_KEY_BAG_ID) { - /* if it is an unencrypted private key then make sure - * the attributes are propageted to the appropriate - * level - */ - if(sec_pkcs12_get_key_info(keyList[i]) != SECSuccess) { - keyList[i]->problem = PR_TRUE; - keyList[i]->error = SEC_ERROR_NO_MEMORY; - return SECFailure; - } - } - - sec_pkcs12_validate_key_by_cert(certList[0], keyList[i], wincx); - while(certList[j]) { - certList[j]->hasKey = PR_TRUE; - if(keyList[i]->problem) { - certList[j]->problem = PR_TRUE; - certList[j]->error = keyList[i]->error; - } else { - sec_pkcs12_validate_cert(certList[j], keyList[i], - nicknameCb, wincx); - if(certList[j]->problem) { - keyList[i]->problem = certList[j]->problem; - keyList[i]->error = certList[j]->error; - } - } - j++; - } - } - - i++; - } - } - - i = 0; - while(safeBags[i]) { - if(!safeBags[i]->validated) { - SECOidTag bagType = SECOID_FindOIDTag(&safeBags[i]->safeBagType); - - switch(bagType) { - case SEC_OID_PKCS12_V1_CERT_BAG_ID: - sec_pkcs12_validate_cert(safeBags[i], NULL, nicknameCb, - wincx); - break; - case SEC_OID_PKCS12_V1_KEY_BAG_ID: - case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: - safeBags[i]->noInstall = PR_TRUE; - safeBags[i]->problem = PR_TRUE; - safeBags[i]->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY; - break; - default: - safeBags[i]->noInstall = PR_TRUE; - } - } - i++; - } - - return SECSuccess; -} - -SECStatus -SEC_PKCS12DecoderValidateBags(SEC_PKCS12DecoderContext *p12dcx, - SEC_PKCS12NicknameCollisionCallback nicknameCb) -{ - SECStatus rv; - int i, noInstallCnt, probCnt, bagCnt, errorVal = 0; - if(!p12dcx || p12dcx->error) { - return SECFailure; - } - - rv = sec_pkcs12_validate_bags(p12dcx->safeBags, nicknameCb, p12dcx->wincx); - if(rv == SECSuccess) { - p12dcx->bagsVerified = PR_TRUE; - } - - noInstallCnt = probCnt = bagCnt = 0; - i = 0; - while(p12dcx->safeBags[i]) { - bagCnt++; - if(p12dcx->safeBags[i]->noInstall) noInstallCnt++; - if(p12dcx->safeBags[i]->problem) { - probCnt++; - errorVal = p12dcx->safeBags[i]->error; - } - i++; - } - - if(bagCnt == noInstallCnt) { - PORT_SetError(SEC_ERROR_PKCS12_DUPLICATE_DATA); - return SECFailure; - } - - if(probCnt) { - PORT_SetError(errorVal); - return SECFailure; - } - - return rv; -} - -static SECItem * -sec_pkcs12_get_public_value_and_type(sec_PKCS12SafeBag *certBag, - KeyType *type, unsigned int *usage) -{ - SECKEYPublicKey *pubKey = NULL; - CERTCertificate *cert = NULL; - SECItem *pubValue; - - *type = nullKey; - *usage = 0; - - if(!certBag) { - return NULL; - } - - cert = CERT_DecodeDERCertificate( - &certBag->safeBagContent.certBag->value.x509Cert, PR_FALSE, NULL); - if(!cert) { - return NULL; - } - - *usage = cert->keyUsage; - pubKey = CERT_ExtractPublicKey(cert); - CERT_DestroyCertificate(cert); - if(!pubKey) { - return NULL; - } - - *type = pubKey->keyType; - switch(pubKey->keyType) { - case dsaKey: - pubValue = SECITEM_DupItem(&pubKey->u.dsa.publicValue); - break; - case dhKey: - pubValue = SECITEM_DupItem(&pubKey->u.dh.publicValue); - break; - case rsaKey: - pubValue = SECITEM_DupItem(&pubKey->u.rsa.modulus); - break; - case ecKey: - pubValue = SECITEM_DupItem(&pubKey->u.ec.publicValue); - break; - default: - pubValue = NULL; - } - - SECKEY_DestroyPublicKey(pubKey); - - return pubValue; -} - -static SECStatus -sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, - void *wincx) -{ - sec_PKCS12SafeBag **keyList, **certList; - int i; - - if(!safeBags) { - return SECFailure; - } - - if(!safeBags[0]) { - return SECSuccess; - } - - keyList = sec_pkcs12_get_key_bags(safeBags); - if(keyList) { - i = 0; - - while(keyList[i]) { - SECStatus rv; - SECItem *publicValue = NULL; - KeyType keyType; - unsigned int keyUsage; - - if(keyList[i]->problem) { - goto next_key_bag; - } - - certList = sec_pkcs12_find_certs_for_key(safeBags, - keyList[i]); - if(certList) { - publicValue = sec_pkcs12_get_public_value_and_type(certList[0], - &keyType, &keyUsage); - } - rv = sec_pkcs12_add_key(keyList[i], publicValue, keyType, keyUsage, - wincx); - if(publicValue) { - SECITEM_FreeItem(publicValue, PR_TRUE); - } - if(rv != SECSuccess) { - PORT_SetError(keyList[i]->error); - return SECFailure; - } - - if(certList) { - int j = 0; - - while(certList[j]) { - SECStatus certRv; - - if(rv != SECSuccess) { - certList[j]->problem = keyList[i]->problem; - certList[j]->error = keyList[i]->error; - certList[j]->noInstall = PR_TRUE; - goto next_cert_bag; - } - - certRv = sec_pkcs12_add_cert(certList[j], - certList[j]->hasKey, wincx); - if(certRv != SECSuccess) { - keyList[i]->problem = certList[j]->problem; - keyList[i]->error = certList[j]->error; - PORT_SetError(certList[j]->error); - return SECFailure; - } -next_cert_bag: - j++; - } - } - -next_key_bag: - i++; - } - } - - i = 0; - while(safeBags[i]) { - if(!safeBags[i]->installed) { - SECStatus rv; - SECOidTag bagType = SECOID_FindOIDTag(&(safeBags[i]->safeBagType)); - - switch(bagType) { - case SEC_OID_PKCS12_V1_CERT_BAG_ID: - rv = sec_pkcs12_add_cert(safeBags[i], safeBags[i]->hasKey, - wincx); - if(rv != SECSuccess) { - PORT_SetError(safeBags[i]->error); - return SECFailure; - } - break; - case SEC_OID_PKCS12_V1_KEY_BAG_ID: - case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: - default: - break; - } - } - i++; - } - - return SECSuccess; -} - -SECStatus -SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx) -{ - if(!p12dcx || p12dcx->error) { - return SECFailure; - } - - if(!p12dcx->bagsVerified) { - return SECFailure; - } - - return sec_pkcs12_install_bags(p12dcx->safeBags, p12dcx->wincx); -} - -PRBool -sec_pkcs12_bagHasKey(SEC_PKCS12DecoderContext *p12dcx, sec_PKCS12SafeBag *bag) -{ - int i; - SECItem *keyId; - SECItem *certKeyId; - - certKeyId = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_LOCAL_KEY_ID); - if (certKeyId == NULL) { - return PR_FALSE; - } - - for (i=0; p12dcx->keyList && p12dcx->keyList[i]; i++) { - keyId = sec_pkcs12_get_attribute_value(p12dcx->keyList[i], - SEC_OID_PKCS9_LOCAL_KEY_ID); - if(!keyId) { - continue; - } - if(SECITEM_CompareItem(certKeyId, keyId) == SECEqual) { - return PR_TRUE; - } - } - return PR_FALSE; -} - -SECItem * -sec_pkcs12_get_friendlyName(sec_PKCS12SafeBag *bag) -{ - SECItem *friendlyName; - SECItem *tempnm; - - tempnm = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_FRIENDLY_NAME); - friendlyName = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if (friendlyName) { - if (!sec_pkcs12_convert_item_to_unicode(NULL, friendlyName, - tempnm, PR_TRUE, PR_FALSE, PR_FALSE)) { - SECITEM_FreeItem(friendlyName, PR_TRUE); - friendlyName = NULL; - } - } - return friendlyName; -} - -/* Following two functions provide access to selected portions of the safe bags. - * Iteration is implemented per decoder context and may be accessed after - * SEC_PKCS12DecoderVerify() returns success. - * When ...DecoderIterateNext() returns SUCCESS a decoder item has been returned - * where item.type is always set; item.friendlyName is set if it is non-null; - * item.der, item.hasKey are set only for SEC_OID_PKCS12_V1_CERT_BAG_ID items. - * ...DecoderIterateNext() returns FAILURE when the list is exhausted or when - * arguments are invalid; PORT_GetError() is 0 at end-of-list. - * Caller has read-only access to decoder items. Any SECItems generated are - * owned by the decoder context and are freed by ...DecoderFinish(). - */ -SECStatus -SEC_PKCS12DecoderIterateInit(SEC_PKCS12DecoderContext *p12dcx) -{ - if(!p12dcx || p12dcx->error) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - p12dcx->iteration = 0; - return SECSuccess; -} - -SECStatus -SEC_PKCS12DecoderIterateNext(SEC_PKCS12DecoderContext *p12dcx, - const SEC_PKCS12DecoderItem **ipp) -{ - sec_PKCS12SafeBag *bag; - - if(!p12dcx || p12dcx->error) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - if (p12dcx->decitem.type != 0 && p12dcx->decitem.der != NULL) { - SECITEM_FreeItem(p12dcx->decitem.der, PR_TRUE); - } - if (p12dcx->decitem.friendlyName != NULL) { - SECITEM_FreeItem(p12dcx->decitem.friendlyName, PR_TRUE); - } - p12dcx->decitem.type = 0; - p12dcx->decitem.der = NULL; - p12dcx->decitem.friendlyName = NULL; - p12dcx->decitem.hasKey = PR_FALSE; - *ipp = NULL; - if (p12dcx->keyList == NULL) { - p12dcx->keyList = sec_pkcs12_get_key_bags(p12dcx->safeBags); - } - - - for (; p12dcx->iteration < p12dcx->safeBagCount; p12dcx->iteration++) { - bag = p12dcx->safeBags[p12dcx->iteration]; - if(bag == NULL || bag->problem) { - continue; - } - p12dcx->decitem.type = SECOID_FindOIDTag(&(bag->safeBagType)); - switch(p12dcx->decitem.type) { - case SEC_OID_PKCS12_V1_CERT_BAG_ID: - p12dcx->decitem.der = sec_pkcs12_get_der_cert(bag); - p12dcx->decitem.friendlyName = sec_pkcs12_get_friendlyName(bag); - p12dcx->decitem.hasKey = sec_pkcs12_bagHasKey(p12dcx, bag); - break; - case SEC_OID_PKCS12_V1_KEY_BAG_ID: - case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: - p12dcx->decitem.friendlyName = sec_pkcs12_get_friendlyName(bag); - break; - default: - /* return these even though we don't expect them */ - break; - case SEC_OID_UNKNOWN: - /* ignore these */ - continue; - } - *ipp = &p12dcx->decitem; - p12dcx->iteration++; - break; /* end for() */ - } - - PORT_SetError(0); /* end-of-list is SECFailure with no PORT error */ - return ((p12dcx->decitem.type == 0) ? SECFailure : SECSuccess); -} - -static SECStatus -sec_pkcs12_decoder_append_bag_to_context(SEC_PKCS12DecoderContext *p12dcx, - sec_PKCS12SafeBag *bag) -{ - if(!p12dcx || p12dcx->error) { - return SECFailure; - } - - if(!p12dcx->safeBagCount) { - p12dcx->safeBags = (sec_PKCS12SafeBag **)PORT_ArenaZAlloc(p12dcx->arena, - sizeof(sec_PKCS12SafeBag *) * 2); - } else { - p12dcx->safeBags = - (sec_PKCS12SafeBag **)PORT_ArenaGrow(p12dcx->arena, p12dcx->safeBags, - (p12dcx->safeBagCount + 1) * sizeof(sec_PKCS12SafeBag *), - (p12dcx->safeBagCount + 2) * sizeof(sec_PKCS12SafeBag *)); - } - - if(!p12dcx->safeBags) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - - p12dcx->safeBags[p12dcx->safeBagCount] = bag; - p12dcx->safeBags[p12dcx->safeBagCount+1] = NULL; - p12dcx->safeBagCount++; - - return SECSuccess; -} - -static sec_PKCS12SafeBag * -sec_pkcs12_decoder_convert_old_key(SEC_PKCS12DecoderContext *p12dcx, - void *key, PRBool isEspvk) -{ - sec_PKCS12SafeBag *keyBag; - SECOidData *oid; - SECOidTag keyTag; - SECItem *keyID, *nickName, *newNickName; - - if(!p12dcx || p12dcx->error || !key) { - return NULL; - } - - newNickName =(SECItem *)PORT_ArenaZAlloc(p12dcx->arena, sizeof(SECItem)); - keyBag = (sec_PKCS12SafeBag *)PORT_ArenaZAlloc(p12dcx->arena, - sizeof(sec_PKCS12SafeBag)); - if(!keyBag || !newNickName) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - keyBag->swapUnicodeBytes = p12dcx->swapUnicodeBytes; - keyBag->slot = p12dcx->slot; - keyBag->arena = p12dcx->arena; - keyBag->pwitem = p12dcx->pwitem; - keyBag->tokenCAs = p12dcx->tokenCAs; - keyBag->oldBagType = PR_TRUE; - - keyTag = (isEspvk) ? SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID : - SEC_OID_PKCS12_V1_KEY_BAG_ID; - oid = SECOID_FindOIDByTag(keyTag); - if(!oid) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - if(SECITEM_CopyItem(p12dcx->arena, &keyBag->safeBagType, &oid->oid) - != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - if(isEspvk) { - SEC_PKCS12ESPVKItem *espvk = (SEC_PKCS12ESPVKItem *)key; - keyBag->safeBagContent.pkcs8ShroudedKeyBag = - espvk->espvkCipherText.pkcs8KeyShroud; - nickName = &(espvk->espvkData.uniNickName); - if(!espvk->espvkData.assocCerts || !espvk->espvkData.assocCerts[0]) { - PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); - return NULL; - } - keyID = &espvk->espvkData.assocCerts[0]->digest; - } else { - SEC_PKCS12PrivateKey *pk = (SEC_PKCS12PrivateKey *)key; - keyBag->safeBagContent.pkcs8KeyBag = &pk->pkcs8data; - nickName= &(pk->pvkData.uniNickName); - if(!pk->pvkData.assocCerts || !pk->pvkData.assocCerts[0]) { - PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); - return NULL; - } - keyID = &pk->pvkData.assocCerts[0]->digest; - } - - if(nickName->len) { - if(nickName->len >= 2) { - if(nickName->data[0] && nickName->data[1]) { - if(!sec_pkcs12_convert_item_to_unicode(p12dcx->arena, newNickName, - nickName, PR_FALSE, PR_FALSE, PR_TRUE)) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - nickName = newNickName; - } else if(nickName->data[0] && !nickName->data[1]) { - unsigned int j = 0; - unsigned char t; - for(j = 0; j < nickName->len; j+=2) { - t = nickName->data[j+1]; - nickName->data[j+1] = nickName->data[j]; - nickName->data[j] = t; - } - } - } else { - if(!sec_pkcs12_convert_item_to_unicode(p12dcx->arena, newNickName, - nickName, PR_FALSE, PR_FALSE, PR_TRUE)) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - nickName = newNickName; - } - } - - if(sec_pkcs12_decoder_set_attribute_value(keyBag, - SEC_OID_PKCS9_FRIENDLY_NAME, - nickName) != SECSuccess) { - return NULL; - } - - if(sec_pkcs12_decoder_set_attribute_value(keyBag,SEC_OID_PKCS9_LOCAL_KEY_ID, - keyID) != SECSuccess) { - return NULL; - } - - return keyBag; -} - -static sec_PKCS12SafeBag * -sec_pkcs12_decoder_create_cert(SEC_PKCS12DecoderContext *p12dcx, - SECItem *derCert) -{ - sec_PKCS12SafeBag *certBag; - SECOidData *oid; - SGNDigestInfo *digest; - SECItem *keyId; - SECStatus rv; - - if(!p12dcx || p12dcx->error || !derCert) { - return NULL; - } - - keyId = (SECItem *)PORT_ArenaZAlloc(p12dcx->arena, sizeof(SECItem)); - if(!keyId) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - digest = sec_pkcs12_compute_thumbprint(derCert); - if(!digest) { - return NULL; - } - - rv = SECITEM_CopyItem(p12dcx->arena, keyId, &digest->digest); - SGN_DestroyDigestInfo(digest); - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - oid = SECOID_FindOIDByTag(SEC_OID_PKCS12_V1_CERT_BAG_ID); - certBag = (sec_PKCS12SafeBag *)PORT_ArenaZAlloc(p12dcx->arena, - sizeof(sec_PKCS12SafeBag)); - if(!certBag || !oid || (SECITEM_CopyItem(p12dcx->arena, - &certBag->safeBagType, &oid->oid) != SECSuccess)) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - certBag->slot = p12dcx->slot; - certBag->pwitem = p12dcx->pwitem; - certBag->swapUnicodeBytes = p12dcx->swapUnicodeBytes; - certBag->arena = p12dcx->arena; - certBag->tokenCAs = p12dcx->tokenCAs; - - oid = SECOID_FindOIDByTag(SEC_OID_PKCS9_X509_CERT); - certBag->safeBagContent.certBag = - (sec_PKCS12CertBag *)PORT_ArenaZAlloc(p12dcx->arena, - sizeof(sec_PKCS12CertBag)); - if(!certBag->safeBagContent.certBag || !oid || - (SECITEM_CopyItem(p12dcx->arena, - &certBag->safeBagContent.certBag->bagID, - &oid->oid) != SECSuccess)) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - if(SECITEM_CopyItem(p12dcx->arena, - &(certBag->safeBagContent.certBag->value.x509Cert), - derCert) != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - if(sec_pkcs12_decoder_set_attribute_value(certBag, SEC_OID_PKCS9_LOCAL_KEY_ID, - keyId) != SECSuccess) { - return NULL; - } - - return certBag; -} - -static sec_PKCS12SafeBag ** -sec_pkcs12_decoder_convert_old_cert(SEC_PKCS12DecoderContext *p12dcx, - SEC_PKCS12CertAndCRL *oldCert) -{ - sec_PKCS12SafeBag **certList; - SECItem **derCertList; - int i, j; - - if(!p12dcx || p12dcx->error || !oldCert) { - return NULL; - } - - derCertList = SEC_PKCS7GetCertificateList(&oldCert->value.x509->certOrCRL); - if(!derCertList) { - return NULL; - } - - i = 0; - while(derCertList[i]) i++; - - certList = (sec_PKCS12SafeBag **)PORT_ArenaZAlloc(p12dcx->arena, - (i + 1) * sizeof(sec_PKCS12SafeBag *)); - if(!certList) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - for(j = 0; j < i; j++) { - certList[j] = sec_pkcs12_decoder_create_cert(p12dcx, derCertList[j]); - if(!certList[j]) { - return NULL; - } - } - - return certList; -} - -static SECStatus -sec_pkcs12_decoder_convert_old_key_and_certs(SEC_PKCS12DecoderContext *p12dcx, - void *oldKey, PRBool isEspvk, - SEC_PKCS12SafeContents *safe, - SEC_PKCS12Baggage *baggage) -{ - sec_PKCS12SafeBag *key, **certList; - SEC_PKCS12CertAndCRL *oldCert; - SEC_PKCS12PVKSupportingData *pvkData; - int i; - SECItem *keyName; - - if(!p12dcx || !oldKey) { - return SECFailure; - } - - if(isEspvk) { - pvkData = &((SEC_PKCS12ESPVKItem *)(oldKey))->espvkData; - } else { - pvkData = &((SEC_PKCS12PrivateKey *)(oldKey))->pvkData; - } - - if(!pvkData->assocCerts || !pvkData->assocCerts[0]) { - PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); - return SECFailure; - } - - oldCert = (SEC_PKCS12CertAndCRL *)sec_pkcs12_find_object(safe, baggage, - SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID, NULL, - pvkData->assocCerts[0]); - if(!oldCert) { - PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); - return SECFailure; - } - - key = sec_pkcs12_decoder_convert_old_key(p12dcx,oldKey, isEspvk); - certList = sec_pkcs12_decoder_convert_old_cert(p12dcx, oldCert); - if(!key || !certList) { - return SECFailure; - } - - if(sec_pkcs12_decoder_append_bag_to_context(p12dcx, key) != SECSuccess) { - return SECFailure; - } - - keyName = sec_pkcs12_get_nickname(key); - if(!keyName) { - return SECFailure; - } - - i = 0; - while(certList[i]) { - if(sec_pkcs12_decoder_append_bag_to_context(p12dcx, certList[i]) - != SECSuccess) { - return SECFailure; - } - i++; - } - - certList = sec_pkcs12_find_certs_for_key(p12dcx->safeBags, key); - if(!certList) { - return SECFailure; - } - - i = 0; - while(certList[i] != 0) { - if(sec_pkcs12_set_nickname(certList[i], keyName) != SECSuccess) { - return SECFailure; - } - i++; - } - - return SECSuccess; -} - -static SECStatus -sec_pkcs12_decoder_convert_old_safe_to_bags(SEC_PKCS12DecoderContext *p12dcx, - SEC_PKCS12SafeContents *safe, - SEC_PKCS12Baggage *baggage) -{ - SECStatus rv; - - if(!p12dcx || p12dcx->error) { - return SECFailure; - } - - if(safe && safe->contents) { - int i = 0; - while(safe->contents[i] != NULL) { - if(SECOID_FindOIDTag(&safe->contents[i]->safeBagType) - == SEC_OID_PKCS12_KEY_BAG_ID) { - int j = 0; - SEC_PKCS12PrivateKeyBag *privBag = - safe->contents[i]->safeContent.keyBag; - - while(privBag->privateKeys[j] != NULL) { - SEC_PKCS12PrivateKey *pk = privBag->privateKeys[j]; - rv = sec_pkcs12_decoder_convert_old_key_and_certs(p12dcx,pk, - PR_FALSE, safe, baggage); - if(rv != SECSuccess) { - goto loser; - } - j++; - } - } - i++; - } - } - - if(baggage && baggage->bags) { - int i = 0; - while(baggage->bags[i] != NULL) { - SEC_PKCS12BaggageItem *bag = baggage->bags[i]; - int j = 0; - - if(!bag->espvks) { - i++; - continue; - } - - while(bag->espvks[j] != NULL) { - SEC_PKCS12ESPVKItem *espvk = bag->espvks[j]; - rv = sec_pkcs12_decoder_convert_old_key_and_certs(p12dcx, espvk, - PR_TRUE, safe, baggage); - if(rv != SECSuccess) { - goto loser; - } - j++; - } - i++; - } - } - - return SECSuccess; - -loser: - return SECFailure; -} - -SEC_PKCS12DecoderContext * -sec_PKCS12ConvertOldSafeToNew(PRArenaPool *arena, PK11SlotInfo *slot, - PRBool swapUnicode, SECItem *pwitem, - void *wincx, SEC_PKCS12SafeContents *safe, - SEC_PKCS12Baggage *baggage) -{ - SEC_PKCS12DecoderContext *p12dcx; - - if(!arena || !slot || !pwitem) { - return NULL; - } - - if(!safe && !baggage) { - return NULL; - } - - p12dcx = (SEC_PKCS12DecoderContext *)PORT_ArenaZAlloc(arena, - sizeof(SEC_PKCS12DecoderContext)); - if(!p12dcx) { - return NULL; - } - - p12dcx->arena = arena; - p12dcx->slot = PK11_ReferenceSlot(slot); - p12dcx->wincx = wincx; - p12dcx->error = PR_FALSE; - p12dcx->swapUnicodeBytes = swapUnicode; - p12dcx->pwitem = pwitem; - p12dcx->tokenCAs = SECPKCS12TargetTokenNoCAs; - - if(sec_pkcs12_decoder_convert_old_safe_to_bags(p12dcx, safe, baggage) - != SECSuccess) { - p12dcx->error = PR_TRUE; - return NULL; - } - - return p12dcx; -} diff --git a/security/nss/lib/pkcs12/p12dec.c b/security/nss/lib/pkcs12/p12dec.c deleted file mode 100644 index 8124a01ed..000000000 --- a/security/nss/lib/pkcs12/p12dec.c +++ /dev/null @@ -1,696 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "pkcs12.h" -#include "plarena.h" -#include "secpkcs7.h" -#include "p12local.h" -#include "secoid.h" -#include "secitem.h" -#include "secport.h" -#include "secasn1.h" -#include "secder.h" -#include "secerr.h" -#include "cert.h" -#include "certdb.h" -#include "p12plcy.h" -#include "p12.h" -#include "secpkcs5.h" - -/* PFX extraction and validation routines */ - -/* decode the DER encoded PFX item. if unable to decode, check to see if it - * is an older PFX item. If that fails, assume the file was not a valid - * pfx file. - * the returned pfx structure should be destroyed using SEC_PKCS12DestroyPFX - */ -static SEC_PKCS12PFXItem * -sec_pkcs12_decode_pfx(SECItem *der_pfx) -{ - SEC_PKCS12PFXItem *pfx; - SECStatus rv; - - if(der_pfx == NULL) { - return NULL; - } - - /* allocate the space for a new PFX item */ - pfx = sec_pkcs12_new_pfx(); - if(pfx == NULL) { - return NULL; - } - - rv = SEC_ASN1DecodeItem(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate, - der_pfx); - - /* if a failure occurred, check for older version... - * we also get rid of the old pfx structure, because we don't - * know where it failed and what data in may contain - */ - if(rv != SECSuccess) { - SEC_PKCS12DestroyPFX(pfx); - pfx = sec_pkcs12_new_pfx(); - if(pfx == NULL) { - return NULL; - } - rv = SEC_ASN1DecodeItem(pfx->poolp, pfx, SEC_PKCS12PFXItemTemplate_OLD, - der_pfx); - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_PKCS12_DECODING_PFX); - PORT_FreeArena(pfx->poolp, PR_TRUE); - return NULL; - } - pfx->old = PR_TRUE; - SGN_CopyDigestInfo(pfx->poolp, &pfx->macData.safeMac, &pfx->old_safeMac); - SECITEM_CopyItem(pfx->poolp, &pfx->macData.macSalt, &pfx->old_macSalt); - } else { - pfx->old = PR_FALSE; - } - - /* convert bit string from bits to bytes */ - pfx->macData.macSalt.len /= 8; - - return pfx; -} - -/* validate the integrity MAC used in the PFX. The MAC is generated - * per the PKCS 12 document. If the MAC is incorrect, it is most likely - * due to an invalid password. - * pwitem is the integrity password - * pfx is the decoded pfx item - */ -static PRBool -sec_pkcs12_check_pfx_mac(SEC_PKCS12PFXItem *pfx, - SECItem *pwitem) -{ - SECItem *key = NULL, *mac = NULL, *data = NULL; - SECItem *vpwd = NULL; - SECOidTag algorithm; - PRBool ret = PR_FALSE; - - if(pfx == NULL) { - return PR_FALSE; - } - - algorithm = SECOID_GetAlgorithmTag(&pfx->macData.safeMac.digestAlgorithm); - switch(algorithm) { - /* only SHA1 hashing supported as a MACing algorithm */ - case SEC_OID_SHA1: - if(pfx->old == PR_FALSE) { - pfx->swapUnicode = PR_FALSE; - } - -recheckUnicodePassword: - vpwd = sec_pkcs12_create_virtual_password(pwitem, - &pfx->macData.macSalt, - pfx->swapUnicode); - if(vpwd == NULL) { - return PR_FALSE; - } - - key = sec_pkcs12_generate_key_from_password(algorithm, - &pfx->macData.macSalt, - (pfx->old ? pwitem : vpwd)); - /* free vpwd only for newer PFX */ - if(vpwd) { - SECITEM_ZfreeItem(vpwd, PR_TRUE); - } - if(key == NULL) { - return PR_FALSE; - } - - data = SEC_PKCS7GetContent(&pfx->authSafe); - if(data == NULL) { - break; - } - - /* check MAC */ - mac = sec_pkcs12_generate_mac(key, data, pfx->old); - ret = PR_TRUE; - if(mac) { - SECItem *safeMac = &pfx->macData.safeMac.digest; - if(SECITEM_CompareItem(mac, safeMac) != SECEqual) { - - /* if we encounter an invalid mac, lets invert the - * password in case of unicode changes - */ - if(((!pfx->old) && pfx->swapUnicode) || (pfx->old)){ - PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC); - ret = PR_FALSE; - } else { - SECITEM_ZfreeItem(mac, PR_TRUE); - pfx->swapUnicode = PR_TRUE; - goto recheckUnicodePassword; - } - } - SECITEM_ZfreeItem(mac, PR_TRUE); - } else { - ret = PR_FALSE; - } - break; - default: - PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM); - ret = PR_FALSE; - break; - } - - /* let success fall through */ - if(key != NULL) - SECITEM_ZfreeItem(key, PR_TRUE); - - return ret; -} - -/* check the validity of the pfx structure. we currently only support - * password integrity mode, so we check the MAC. - */ -static PRBool -sec_pkcs12_validate_pfx(SEC_PKCS12PFXItem *pfx, - SECItem *pwitem) -{ - SECOidTag contentType; - - contentType = SEC_PKCS7ContentType(&pfx->authSafe); - switch(contentType) - { - case SEC_OID_PKCS7_DATA: - return sec_pkcs12_check_pfx_mac(pfx, pwitem); - break; - case SEC_OID_PKCS7_SIGNED_DATA: - default: - PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE); - break; - } - - return PR_FALSE; -} - -/* decode and return the valid PFX. if the PFX item is not valid, - * NULL is returned. - */ -static SEC_PKCS12PFXItem * -sec_pkcs12_get_pfx(SECItem *pfx_data, - SECItem *pwitem) -{ - SEC_PKCS12PFXItem *pfx; - PRBool valid_pfx; - - if((pfx_data == NULL) || (pwitem == NULL)) { - return NULL; - } - - pfx = sec_pkcs12_decode_pfx(pfx_data); - if(pfx == NULL) { - return NULL; - } - - valid_pfx = sec_pkcs12_validate_pfx(pfx, pwitem); - if(valid_pfx != PR_TRUE) { - SEC_PKCS12DestroyPFX(pfx); - pfx = NULL; - } - - return pfx; -} - -/* authenticated safe decoding, validation, and access routines - */ - -/* convert dogbert beta 3 authenticated safe structure to a post - * beta three structure, so that we don't have to change more routines. - */ -static SECStatus -sec_pkcs12_convert_old_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe) -{ - SEC_PKCS12Baggage *baggage; - SEC_PKCS12BaggageItem *bag; - SECStatus rv = SECSuccess; - - if(asafe->old_baggage.espvks == NULL) { - /* XXX should the ASN1 engine produce a single NULL element list - * rather than setting the pointer to NULL? - * There is no need to return an error -- assume that the list - * was empty. - */ - return SECSuccess; - } - - baggage = sec_pkcs12_create_baggage(asafe->poolp); - if(!baggage) { - return SECFailure; - } - bag = sec_pkcs12_create_external_bag(baggage); - if(!bag) { - return SECFailure; - } - - PORT_Memcpy(&asafe->baggage, baggage, sizeof(SEC_PKCS12Baggage)); - - /* if there are shrouded keys, append them to the bag */ - rv = SECSuccess; - if(asafe->old_baggage.espvks[0] != NULL) { - int nEspvk = 0; - rv = SECSuccess; - while((asafe->old_baggage.espvks[nEspvk] != NULL) && - (rv == SECSuccess)) { - rv = sec_pkcs12_append_shrouded_key(bag, - asafe->old_baggage.espvks[nEspvk]); - nEspvk++; - } - } - - return rv; -} - -/* decodes the authenticated safe item. a return of NULL indicates - * an error. however, the error will have occured either in memory - * allocation or in decoding the authenticated safe. - * - * if an old PFX item has been found, we want to convert the - * old authenticated safe to the new one. - */ -static SEC_PKCS12AuthenticatedSafe * -sec_pkcs12_decode_authenticated_safe(SEC_PKCS12PFXItem *pfx) -{ - SECItem *der_asafe = NULL; - SEC_PKCS12AuthenticatedSafe *asafe = NULL; - SECStatus rv; - - if(pfx == NULL) { - return NULL; - } - - der_asafe = SEC_PKCS7GetContent(&pfx->authSafe); - if(der_asafe == NULL) { - /* XXX set error ? */ - goto loser; - } - - asafe = sec_pkcs12_new_asafe(pfx->poolp); - if(asafe == NULL) { - goto loser; - } - - if(pfx->old == PR_FALSE) { - rv = SEC_ASN1DecodeItem(pfx->poolp, asafe, - SEC_PKCS12AuthenticatedSafeTemplate, - der_asafe); - asafe->old = PR_FALSE; - asafe->swapUnicode = pfx->swapUnicode; - } else { - /* handle beta exported files */ - rv = SEC_ASN1DecodeItem(pfx->poolp, asafe, - SEC_PKCS12AuthenticatedSafeTemplate_OLD, - der_asafe); - asafe->safe = &(asafe->old_safe); - rv = sec_pkcs12_convert_old_auth_safe(asafe); - asafe->old = PR_TRUE; - } - - if(rv != SECSuccess) { - goto loser; - } - - asafe->poolp = pfx->poolp; - - return asafe; - -loser: - return NULL; -} - -/* validates the safe within the authenticated safe item. - * in order to be valid: - * 1. the privacy salt must be present - * 2. the encryption algorithm must be supported (including - * export policy) - * PR_FALSE indicates an error, PR_TRUE indicates a valid safe - */ -static PRBool -sec_pkcs12_validate_encrypted_safe(SEC_PKCS12AuthenticatedSafe *asafe) -{ - PRBool valid = PR_FALSE; - SECAlgorithmID *algid; - - if(asafe == NULL) { - return PR_FALSE; - } - - /* if mode is password privacy, then privacySalt is assumed - * to be non-zero. - */ - if(asafe->privacySalt.len != 0) { - valid = PR_TRUE; - asafe->privacySalt.len /= 8; - } else { - PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); - return PR_FALSE; - } - - /* until spec changes, content will have between 2 and 8 bytes depending - * upon the algorithm used if certs are unencrypted... - * also want to support case where content is empty -- which we produce - */ - if(SEC_PKCS7IsContentEmpty(asafe->safe, 8) == PR_TRUE) { - asafe->emptySafe = PR_TRUE; - return PR_TRUE; - } - - asafe->emptySafe = PR_FALSE; - - /* make sure that a pbe algorithm is being used */ - algid = SEC_PKCS7GetEncryptionAlgorithm(asafe->safe); - if(algid != NULL) { - if(SEC_PKCS5IsAlgorithmPBEAlg(algid)) { - valid = SEC_PKCS12DecryptionAllowed(algid); - - if(valid == PR_FALSE) { - PORT_SetError(SEC_ERROR_BAD_EXPORT_ALGORITHM); - } - } else { - PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM); - valid = PR_FALSE; - } - } else { - valid = PR_FALSE; - PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM); - } - - return valid; -} - -/* validates authenticates safe: - * 1. checks that the version is supported - * 2. checks that only password privacy mode is used (currently) - * 3. further, makes sure safe has appropriate policies per above function - * PR_FALSE indicates failure. - */ -static PRBool -sec_pkcs12_validate_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe) -{ - PRBool valid = PR_TRUE; - SECOidTag safe_type; - int version; - - if(asafe == NULL) { - return PR_FALSE; - } - - /* check version, since it is default it may not be present. - * therefore, assume ok - */ - if((asafe->version.len > 0) && (asafe->old == PR_FALSE)) { - version = DER_GetInteger(&asafe->version); - if(version > SEC_PKCS12_PFX_VERSION) { - PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION); - return PR_FALSE; - } - } - - /* validate password mode is being used */ - safe_type = SEC_PKCS7ContentType(asafe->safe); - switch(safe_type) - { - case SEC_OID_PKCS7_ENCRYPTED_DATA: - valid = sec_pkcs12_validate_encrypted_safe(asafe); - break; - case SEC_OID_PKCS7_ENVELOPED_DATA: - default: - PORT_SetError(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE); - valid = PR_FALSE; - break; - } - - return valid; -} - -/* retrieves the authenticated safe item from the PFX item - * before returning the authenticated safe, the validity of the - * authenticated safe is checked and if valid, returned. - * a return of NULL indicates that an error occured. - */ -static SEC_PKCS12AuthenticatedSafe * -sec_pkcs12_get_auth_safe(SEC_PKCS12PFXItem *pfx) -{ - SEC_PKCS12AuthenticatedSafe *asafe; - PRBool valid_safe; - - if(pfx == NULL) { - return NULL; - } - - asafe = sec_pkcs12_decode_authenticated_safe(pfx); - if(asafe == NULL) { - return NULL; - } - - valid_safe = sec_pkcs12_validate_auth_safe(asafe); - if(valid_safe != PR_TRUE) { - asafe = NULL; - } else if(asafe) { - asafe->baggage.poolp = asafe->poolp; - } - - return asafe; -} - -/* decrypts the authenticated safe. - * a return of anything but SECSuccess indicates an error. the - * password is not known to be valid until the call to the - * function sec_pkcs12_get_safe_contents. If decoding the safe - * fails, it is assumed the password was incorrect and the error - * is set then. any failure here is assumed to be due to - * internal problems in SEC_PKCS7DecryptContents or below. - */ -static SECStatus -sec_pkcs12_decrypt_auth_safe(SEC_PKCS12AuthenticatedSafe *asafe, - SECItem *pwitem, - void *wincx) -{ - SECStatus rv = SECFailure; - SECItem *vpwd = NULL; - - if((asafe == NULL) || (pwitem == NULL)) { - return SECFailure; - } - - if(asafe->old == PR_FALSE) { - vpwd = sec_pkcs12_create_virtual_password(pwitem, &asafe->privacySalt, - asafe->swapUnicode); - if(vpwd == NULL) { - return SECFailure; - } - } - - rv = SEC_PKCS7DecryptContents(asafe->poolp, asafe->safe, - (asafe->old ? pwitem : vpwd), wincx); - - if(asafe->old == PR_FALSE) { - SECITEM_ZfreeItem(vpwd, PR_TRUE); - } - - return rv; -} - -/* extract the safe from the authenticated safe. - * if we are unable to decode the safe, then it is likely that the - * safe has not been decrypted or the password used to decrypt - * the safe was invalid. we assume that the password was invalid and - * set an error accordingly. - * a return of NULL indicates that an error occurred. - */ -static SEC_PKCS12SafeContents * -sec_pkcs12_get_safe_contents(SEC_PKCS12AuthenticatedSafe *asafe) -{ - SECItem *src = NULL; - SEC_PKCS12SafeContents *safe = NULL; - SECStatus rv = SECFailure; - - if(asafe == NULL) { - return NULL; - } - - safe = (SEC_PKCS12SafeContents *)PORT_ArenaZAlloc(asafe->poolp, - sizeof(SEC_PKCS12SafeContents)); - if(safe == NULL) { - return NULL; - } - safe->poolp = asafe->poolp; - safe->old = asafe->old; - safe->swapUnicode = asafe->swapUnicode; - - src = SEC_PKCS7GetContent(asafe->safe); - if(src != NULL) { - const SEC_ASN1Template *theTemplate; - if(asafe->old != PR_TRUE) { - theTemplate = SEC_PKCS12SafeContentsTemplate; - } else { - theTemplate = SEC_PKCS12SafeContentsTemplate_OLD; - } - - rv = SEC_ASN1DecodeItem(asafe->poolp, safe, theTemplate, src); - - /* if we could not decode the item, password was probably invalid */ - if(rv != SECSuccess) { - safe = NULL; - PORT_SetError(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT); - } - } else { - PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE); - rv = SECFailure; - } - - return safe; -} - -/* import PFX item - * der_pfx is the der encoded pfx structure - * pbef and pbearg are the integrity/encryption password call back - * ncCall is the nickname collision calllback - * slot is the destination token - * wincx window handler - * - * on error, error code set and SECFailure returned - */ -SECStatus -SEC_PKCS12PutPFX(SECItem *der_pfx, SECItem *pwitem, - SEC_PKCS12NicknameCollisionCallback ncCall, - PK11SlotInfo *slot, - void *wincx) -{ - SEC_PKCS12PFXItem *pfx; - SEC_PKCS12AuthenticatedSafe *asafe; - SEC_PKCS12SafeContents *safe_contents = NULL; - SECStatus rv; - - if(!der_pfx || !pwitem || !slot) { - return SECFailure; - } - - /* decode and validate each section */ - rv = SECFailure; - - pfx = sec_pkcs12_get_pfx(der_pfx, pwitem); - if(pfx != NULL) { - asafe = sec_pkcs12_get_auth_safe(pfx); - if(asafe != NULL) { - - /* decrypt safe -- only if not empty */ - if(asafe->emptySafe != PR_TRUE) { - rv = sec_pkcs12_decrypt_auth_safe(asafe, pwitem, wincx); - if(rv == SECSuccess) { - safe_contents = sec_pkcs12_get_safe_contents(asafe); - if(safe_contents == NULL) { - rv = SECFailure; - } - } - } else { - safe_contents = sec_pkcs12_create_safe_contents(asafe->poolp); - safe_contents->swapUnicode = pfx->swapUnicode; - if(safe_contents == NULL) { - rv = SECFailure; - } else { - rv = SECSuccess; - } - } - - /* get safe contents and begin import */ - if(rv == SECSuccess) { - SEC_PKCS12DecoderContext *p12dcx; - - p12dcx = sec_PKCS12ConvertOldSafeToNew(pfx->poolp, slot, - pfx->swapUnicode, - pwitem, wincx, safe_contents, - &asafe->baggage); - if(!p12dcx) { - rv = SECFailure; - goto loser; - } - - if(SEC_PKCS12DecoderValidateBags(p12dcx, ncCall) - != SECSuccess) { - rv = SECFailure; - goto loser; - } - - rv = SEC_PKCS12DecoderImportBags(p12dcx); - } - - } - } - -loser: - - if(pfx) { - SEC_PKCS12DestroyPFX(pfx); - } - - return rv; -} - -PRBool -SEC_PKCS12ValidData(char *buf, int bufLen, long int totalLength) -{ - int lengthLength; - - PRBool valid = PR_FALSE; - - if(buf == NULL) { - return PR_FALSE; - } - - /* check for constructed sequence identifier tag */ - if(*buf == (SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE)) { - totalLength--; /* header byte taken care of */ - buf++; - - lengthLength = (long int)SEC_ASN1LengthLength(totalLength - 1); - if(totalLength > 0x7f) { - lengthLength--; - *buf &= 0x7f; /* remove bit 8 indicator */ - if((*buf - (char)lengthLength) == 0) { - valid = PR_TRUE; - } - } else { - lengthLength--; - if((*buf - (char)lengthLength) == 0) { - valid = PR_TRUE; - } - } - } - - return valid; -} diff --git a/security/nss/lib/pkcs12/p12e.c b/security/nss/lib/pkcs12/p12e.c deleted file mode 100644 index f0fbbcb2e..000000000 --- a/security/nss/lib/pkcs12/p12e.c +++ /dev/null @@ -1,2368 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nssrenam.h" -#include "p12t.h" -#include "p12.h" -#include "plarena.h" -#include "secitem.h" -#include "secoid.h" -#include "seccomon.h" -#include "secport.h" -#include "cert.h" -#include "secpkcs7.h" -#include "secasn1.h" -#include "secerr.h" -#include "pk11func.h" -#include "p12plcy.h" -#include "p12local.h" -#include "prcpucfg.h" - -/* -** This PKCS12 file encoder uses numerous nested ASN.1 and PKCS7 encoder -** contexts. It can be difficult to keep straight. Here's a picture: -** -** "outer" ASN.1 encoder. The output goes to the library caller's CB. -** "middle" PKCS7 encoder. Feeds the "outer" ASN.1 encoder. -** "middle" ASN1 encoder. Encodes the encrypted aSafes. -** Feeds the "middle" P7 encoder above. -** "inner" PKCS7 encoder. Encrypts the "authenticated Safes" (aSafes) -** Feeds the "middle" ASN.1 encoder above. -** "inner" ASN.1 encoder. Encodes the unencrypted aSafes. -** Feeds the "inner" P7 enocder above. -** -** Buffering has been added at each point where the output of an ASN.1 -** encoder feeds the input of a PKCS7 encoder. -*/ - -/********************************* - * Output buffer object, used to buffer output from ASN.1 encoder - * before passing data on down to the next PKCS7 encoder. - *********************************/ - -#define PK12_OUTPUT_BUFFER_SIZE 8192 - -struct sec_pkcs12OutputBufferStr { - SEC_PKCS7EncoderContext * p7eCx; - PK11Context * hmacCx; - unsigned int numBytes; - unsigned int bufBytes; - char buf[PK12_OUTPUT_BUFFER_SIZE]; -}; -typedef struct sec_pkcs12OutputBufferStr sec_pkcs12OutputBuffer; - -/********************************* - * Structures used in exporting the PKCS 12 blob - *********************************/ - -/* A SafeInfo is used for each ContentInfo which makes up the - * sequence of safes in the AuthenticatedSafe portion of the - * PFX structure. - */ -struct SEC_PKCS12SafeInfoStr { - PRArenaPool *arena; - - /* information for setting up password encryption */ - SECItem pwitem; - SECOidTag algorithm; - PK11SymKey *encryptionKey; - - /* how many items have been stored in this safe, - * we will skip any safe which does not contain any - * items - */ - unsigned int itemCount; - - /* the content info for the safe */ - SEC_PKCS7ContentInfo *cinfo; - - sec_PKCS12SafeContents *safe; -}; - -/* An opaque structure which contains information needed for exporting - * certificates and keys through PKCS 12. - */ -struct SEC_PKCS12ExportContextStr { - PRArenaPool *arena; - PK11SlotInfo *slot; - void *wincx; - - /* integrity information */ - PRBool integrityEnabled; - PRBool pwdIntegrity; - union { - struct sec_PKCS12PasswordModeInfo pwdInfo; - struct sec_PKCS12PublicKeyModeInfo pubkeyInfo; - } integrityInfo; - - /* helper functions */ - /* retrieve the password call back */ - SECKEYGetPasswordKey pwfn; - void *pwfnarg; - - /* safe contents bags */ - SEC_PKCS12SafeInfo **safeInfos; - unsigned int safeInfoCount; - - /* the sequence of safes */ - sec_PKCS12AuthenticatedSafe authSafe; - - /* information needing deletion */ - CERTCertificate **certList; -}; - -/* structures for passing information to encoder callbacks when processing - * data through the ASN1 engine. - */ -struct sec_pkcs12_encoder_output { - SEC_PKCS12EncoderOutputCallback outputfn; - void *outputarg; -}; - -struct sec_pkcs12_hmac_and_output_info { - void *arg; - struct sec_pkcs12_encoder_output output; -}; - -/* An encoder context which is used for the actual encoding - * portion of PKCS 12. - */ -typedef struct sec_PKCS12EncoderContextStr { - PRArenaPool *arena; - SEC_PKCS12ExportContext *p12exp; - PK11SymKey *encryptionKey; - - /* encoder information - this is set up based on whether - * password based or public key pased privacy is being used - */ - SEC_ASN1EncoderContext *outerA1ecx; - union { - struct sec_pkcs12_hmac_and_output_info hmacAndOutputInfo; - struct sec_pkcs12_encoder_output encOutput; - } output; - - /* structures for encoding of PFX and MAC */ - sec_PKCS12PFXItem pfx; - sec_PKCS12MacData mac; - - /* authenticated safe encoding tracking information */ - SEC_PKCS7ContentInfo *aSafeCinfo; - SEC_PKCS7EncoderContext *middleP7ecx; - SEC_ASN1EncoderContext *middleA1ecx; - unsigned int currentSafe; - - /* hmac context */ - PK11Context *hmacCx; - - /* output buffers */ - sec_pkcs12OutputBuffer middleBuf; - sec_pkcs12OutputBuffer innerBuf; - -} sec_PKCS12EncoderContext; - - -/********************************* - * Export setup routines - *********************************/ - -/* SEC_PKCS12CreateExportContext - * Creates an export context and sets the unicode and password retrieval - * callbacks. This is the first call which must be made when exporting - * a PKCS 12 blob. - * - * pwfn, pwfnarg - password retrieval callback and argument. these are - * required for password-authentication mode. - */ -SEC_PKCS12ExportContext * -SEC_PKCS12CreateExportContext(SECKEYGetPasswordKey pwfn, void *pwfnarg, - PK11SlotInfo *slot, void *wincx) -{ - PRArenaPool *arena = NULL; - SEC_PKCS12ExportContext *p12ctxt = NULL; - - /* allocate the arena and create the context */ - arena = PORT_NewArena(4096); - if(!arena) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - p12ctxt = (SEC_PKCS12ExportContext *)PORT_ArenaZAlloc(arena, - sizeof(SEC_PKCS12ExportContext)); - if(!p12ctxt) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* password callback for key retrieval */ - p12ctxt->pwfn = pwfn; - p12ctxt->pwfnarg = pwfnarg; - - p12ctxt->integrityEnabled = PR_FALSE; - p12ctxt->arena = arena; - p12ctxt->wincx = wincx; - p12ctxt->slot = (slot) ? PK11_ReferenceSlot(slot) : PK11_GetInternalSlot(); - - return p12ctxt; - -loser: - if(arena) { - PORT_FreeArena(arena, PR_TRUE); - } - - return NULL; -} - -/* - * Adding integrity mode - */ - -/* SEC_PKCS12AddPasswordIntegrity - * Add password integrity to the exported data. If an integrity method - * has already been set, then return an error. - * - * p12ctxt - the export context - * pwitem - the password for integrity mode - * integAlg - the integrity algorithm to use for authentication. - */ -SECStatus -SEC_PKCS12AddPasswordIntegrity(SEC_PKCS12ExportContext *p12ctxt, - SECItem *pwitem, SECOidTag integAlg) -{ - if(!p12ctxt || p12ctxt->integrityEnabled) { - return SECFailure; - } - - /* set up integrity information */ - p12ctxt->pwdIntegrity = PR_TRUE; - p12ctxt->integrityInfo.pwdInfo.password = - (SECItem*)PORT_ArenaZAlloc(p12ctxt->arena, sizeof(SECItem)); - if(!p12ctxt->integrityInfo.pwdInfo.password) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - if(SECITEM_CopyItem(p12ctxt->arena, - p12ctxt->integrityInfo.pwdInfo.password, pwitem) - != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - p12ctxt->integrityInfo.pwdInfo.algorithm = integAlg; - p12ctxt->integrityEnabled = PR_TRUE; - - return SECSuccess; -} - -/* SEC_PKCS12AddPublicKeyIntegrity - * Add public key integrity to the exported data. If an integrity method - * has already been set, then return an error. The certificate must be - * allowed to be used as a signing cert. - * - * p12ctxt - the export context - * cert - signer certificate - * certDb - the certificate database - * algorithm - signing algorithm - * keySize - size of the signing key (?) - */ -SECStatus -SEC_PKCS12AddPublicKeyIntegrity(SEC_PKCS12ExportContext *p12ctxt, - CERTCertificate *cert, CERTCertDBHandle *certDb, - SECOidTag algorithm, int keySize) -{ - if(!p12ctxt) { - return SECFailure; - } - - p12ctxt->integrityInfo.pubkeyInfo.cert = cert; - p12ctxt->integrityInfo.pubkeyInfo.certDb = certDb; - p12ctxt->integrityInfo.pubkeyInfo.algorithm = algorithm; - p12ctxt->integrityInfo.pubkeyInfo.keySize = keySize; - p12ctxt->integrityEnabled = PR_TRUE; - - return SECSuccess; -} - - -/* - * Adding safes - encrypted (password/public key) or unencrypted - * Each of the safe creation routines return an opaque pointer which - * are later passed into the routines for exporting certificates and - * keys. - */ - -/* append the newly created safeInfo to list of safeInfos in the export - * context. - */ -static SECStatus -sec_pkcs12_append_safe_info(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *info) -{ - void *mark = NULL, *dummy1 = NULL, *dummy2 = NULL; - - if(!p12ctxt || !info) { - return SECFailure; - } - - mark = PORT_ArenaMark(p12ctxt->arena); - - /* if no safeInfos have been set, create the list, otherwise expand it. */ - if(!p12ctxt->safeInfoCount) { - p12ctxt->safeInfos = (SEC_PKCS12SafeInfo **)PORT_ArenaZAlloc(p12ctxt->arena, - 2 * sizeof(SEC_PKCS12SafeInfo *)); - dummy1 = p12ctxt->safeInfos; - p12ctxt->authSafe.encodedSafes = (SECItem **)PORT_ArenaZAlloc(p12ctxt->arena, - 2 * sizeof(SECItem *)); - dummy2 = p12ctxt->authSafe.encodedSafes; - } else { - dummy1 = PORT_ArenaGrow(p12ctxt->arena, p12ctxt->safeInfos, - (p12ctxt->safeInfoCount + 1) * sizeof(SEC_PKCS12SafeInfo *), - (p12ctxt->safeInfoCount + 2) * sizeof(SEC_PKCS12SafeInfo *)); - p12ctxt->safeInfos = (SEC_PKCS12SafeInfo **)dummy1; - dummy2 = PORT_ArenaGrow(p12ctxt->arena, p12ctxt->authSafe.encodedSafes, - (p12ctxt->authSafe.safeCount + 1) * sizeof(SECItem *), - (p12ctxt->authSafe.safeCount + 2) * sizeof(SECItem *)); - p12ctxt->authSafe.encodedSafes = (SECItem**)dummy2; - } - if(!dummy1 || !dummy2) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* append the new safeInfo and null terminate the list */ - p12ctxt->safeInfos[p12ctxt->safeInfoCount] = info; - p12ctxt->safeInfos[++p12ctxt->safeInfoCount] = NULL; - p12ctxt->authSafe.encodedSafes[p12ctxt->authSafe.safeCount] = - (SECItem*)PORT_ArenaZAlloc(p12ctxt->arena, sizeof(SECItem)); - if(!p12ctxt->authSafe.encodedSafes[p12ctxt->authSafe.safeCount]) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - p12ctxt->authSafe.encodedSafes[++p12ctxt->authSafe.safeCount] = NULL; - - PORT_ArenaUnmark(p12ctxt->arena, mark); - return SECSuccess; - -loser: - PORT_ArenaRelease(p12ctxt->arena, mark); - return SECFailure; -} - -/* SEC_PKCS12CreatePasswordPrivSafe - * Create a password privacy safe to store exported information in. - * - * p12ctxt - export context - * pwitem - password for encryption - * privAlg - pbe algorithm through which encryption is done. - */ -SEC_PKCS12SafeInfo * -SEC_PKCS12CreatePasswordPrivSafe(SEC_PKCS12ExportContext *p12ctxt, - SECItem *pwitem, SECOidTag privAlg) -{ - SEC_PKCS12SafeInfo *safeInfo = NULL; - void *mark = NULL; - PK11SlotInfo *slot = NULL; - SECAlgorithmID *algId; - SECItem uniPwitem = {siBuffer, NULL, 0}; - - if(!p12ctxt) { - return NULL; - } - - /* allocate the safe info */ - mark = PORT_ArenaMark(p12ctxt->arena); - safeInfo = (SEC_PKCS12SafeInfo *)PORT_ArenaZAlloc(p12ctxt->arena, - sizeof(SEC_PKCS12SafeInfo)); - if(!safeInfo) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - PORT_ArenaRelease(p12ctxt->arena, mark); - return NULL; - } - - safeInfo->itemCount = 0; - - /* create the encrypted safe */ - safeInfo->cinfo = SEC_PKCS7CreateEncryptedData(privAlg, 0, p12ctxt->pwfn, - p12ctxt->pwfnarg); - if(!safeInfo->cinfo) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - safeInfo->arena = p12ctxt->arena; - - /* convert the password to unicode */ - if(!sec_pkcs12_convert_item_to_unicode(NULL, &uniPwitem, pwitem, - PR_TRUE, PR_TRUE, PR_TRUE)) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - if(SECITEM_CopyItem(p12ctxt->arena, &safeInfo->pwitem, &uniPwitem) != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* generate the encryption key */ - slot = PK11_ReferenceSlot(p12ctxt->slot); - if(!slot) { - slot = PK11_GetInternalKeySlot(); - if(!slot) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - } - - algId = SEC_PKCS7GetEncryptionAlgorithm(safeInfo->cinfo); - safeInfo->encryptionKey = PK11_PBEKeyGen(slot, algId, &uniPwitem, - PR_FALSE, p12ctxt->wincx); - if(!safeInfo->encryptionKey) { - goto loser; - } - - safeInfo->arena = p12ctxt->arena; - safeInfo->safe = NULL; - if(sec_pkcs12_append_safe_info(p12ctxt, safeInfo) != SECSuccess) { - goto loser; - } - - if(uniPwitem.data) { - SECITEM_ZfreeItem(&uniPwitem, PR_FALSE); - } - PORT_ArenaUnmark(p12ctxt->arena, mark); - - if (slot) { - PK11_FreeSlot(slot); - } - return safeInfo; - -loser: - if (slot) { - PK11_FreeSlot(slot); - } - if(safeInfo->cinfo) { - SEC_PKCS7DestroyContentInfo(safeInfo->cinfo); - } - - if(uniPwitem.data) { - SECITEM_ZfreeItem(&uniPwitem, PR_FALSE); - } - - PORT_ArenaRelease(p12ctxt->arena, mark); - return NULL; -} - -/* SEC_PKCS12CreateUnencryptedSafe - * Creates an unencrypted safe within the export context. - * - * p12ctxt - the export context - */ -SEC_PKCS12SafeInfo * -SEC_PKCS12CreateUnencryptedSafe(SEC_PKCS12ExportContext *p12ctxt) -{ - SEC_PKCS12SafeInfo *safeInfo = NULL; - void *mark = NULL; - - if(!p12ctxt) { - return NULL; - } - - /* create the safe info */ - mark = PORT_ArenaMark(p12ctxt->arena); - safeInfo = (SEC_PKCS12SafeInfo *)PORT_ArenaZAlloc(p12ctxt->arena, - sizeof(SEC_PKCS12SafeInfo)); - if(!safeInfo) { - PORT_ArenaRelease(p12ctxt->arena, mark); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - safeInfo->itemCount = 0; - - /* create the safe content */ - safeInfo->cinfo = SEC_PKCS7CreateData(); - if(!safeInfo->cinfo) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - if(sec_pkcs12_append_safe_info(p12ctxt, safeInfo) != SECSuccess) { - goto loser; - } - - PORT_ArenaUnmark(p12ctxt->arena, mark); - return safeInfo; - -loser: - if(safeInfo->cinfo) { - SEC_PKCS7DestroyContentInfo(safeInfo->cinfo); - } - - PORT_ArenaRelease(p12ctxt->arena, mark); - return NULL; -} - -/* SEC_PKCS12CreatePubKeyEncryptedSafe - * Creates a safe which is protected by public key encryption. - * - * p12ctxt - the export context - * certDb - the certificate database - * signer - the signer's certificate - * recipients - the list of recipient certificates. - * algorithm - the encryption algorithm to use - * keysize - the algorithms key size (?) - */ -SEC_PKCS12SafeInfo * -SEC_PKCS12CreatePubKeyEncryptedSafe(SEC_PKCS12ExportContext *p12ctxt, - CERTCertDBHandle *certDb, - CERTCertificate *signer, - CERTCertificate **recipients, - SECOidTag algorithm, int keysize) -{ - SEC_PKCS12SafeInfo *safeInfo = NULL; - void *mark = NULL; - - if(!p12ctxt || !signer || !recipients || !(*recipients)) { - return NULL; - } - - /* allocate the safeInfo */ - mark = PORT_ArenaMark(p12ctxt->arena); - safeInfo = (SEC_PKCS12SafeInfo *)PORT_ArenaZAlloc(p12ctxt->arena, - sizeof(SEC_PKCS12SafeInfo)); - if(!safeInfo) { - PORT_ArenaRelease(p12ctxt->arena, mark); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - safeInfo->itemCount = 0; - safeInfo->arena = p12ctxt->arena; - - /* create the enveloped content info using certUsageEmailSigner currently. - * XXX We need to eventually use something other than certUsageEmailSigner - */ - safeInfo->cinfo = SEC_PKCS7CreateEnvelopedData(signer, certUsageEmailSigner, - certDb, algorithm, keysize, - p12ctxt->pwfn, p12ctxt->pwfnarg); - if(!safeInfo->cinfo) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* add recipients */ - if(recipients) { - unsigned int i = 0; - while(recipients[i] != NULL) { - SECStatus rv = SEC_PKCS7AddRecipient(safeInfo->cinfo, recipients[i], - certUsageEmailRecipient, certDb); - if(rv != SECSuccess) { - goto loser; - } - i++; - } - } - - if(sec_pkcs12_append_safe_info(p12ctxt, safeInfo) != SECSuccess) { - goto loser; - } - - PORT_ArenaUnmark(p12ctxt->arena, mark); - return safeInfo; - -loser: - if(safeInfo->cinfo) { - SEC_PKCS7DestroyContentInfo(safeInfo->cinfo); - safeInfo->cinfo = NULL; - } - - PORT_ArenaRelease(p12ctxt->arena, mark); - return NULL; -} - -/********************************* - * Routines to handle the exporting of the keys and certificates - *********************************/ - -/* creates a safe contents which safeBags will be appended to */ -sec_PKCS12SafeContents * -sec_PKCS12CreateSafeContents(PRArenaPool *arena) -{ - sec_PKCS12SafeContents *safeContents; - - if(arena == NULL) { - return NULL; - } - - /* create the safe contents */ - safeContents = (sec_PKCS12SafeContents *)PORT_ArenaZAlloc(arena, - sizeof(sec_PKCS12SafeContents)); - if(!safeContents) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* set up the internal contents info */ - safeContents->safeBags = NULL; - safeContents->arena = arena; - safeContents->bagCount = 0; - - return safeContents; - -loser: - return NULL; -} - -/* appends a safe bag to a safeContents using the specified arena. - */ -SECStatus -sec_pkcs12_append_bag_to_safe_contents(PRArenaPool *arena, - sec_PKCS12SafeContents *safeContents, - sec_PKCS12SafeBag *safeBag) -{ - void *mark = NULL, *dummy = NULL; - - if(!arena || !safeBag || !safeContents) { - return SECFailure; - } - - mark = PORT_ArenaMark(arena); - if(!mark) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - - /* allocate space for the list, or reallocate to increase space */ - if(!safeContents->safeBags) { - safeContents->safeBags = (sec_PKCS12SafeBag **)PORT_ArenaZAlloc(arena, - (2 * sizeof(sec_PKCS12SafeBag *))); - dummy = safeContents->safeBags; - safeContents->bagCount = 0; - } else { - dummy = PORT_ArenaGrow(arena, safeContents->safeBags, - (safeContents->bagCount + 1) * sizeof(sec_PKCS12SafeBag *), - (safeContents->bagCount + 2) * sizeof(sec_PKCS12SafeBag *)); - safeContents->safeBags = (sec_PKCS12SafeBag **)dummy; - } - - if(!dummy) { - PORT_ArenaRelease(arena, mark); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - - /* append the bag at the end and null terminate the list */ - safeContents->safeBags[safeContents->bagCount++] = safeBag; - safeContents->safeBags[safeContents->bagCount] = NULL; - - PORT_ArenaUnmark(arena, mark); - - return SECSuccess; -} - -/* appends a safeBag to a specific safeInfo. - */ -SECStatus -sec_pkcs12_append_bag(SEC_PKCS12ExportContext *p12ctxt, - SEC_PKCS12SafeInfo *safeInfo, sec_PKCS12SafeBag *safeBag) -{ - sec_PKCS12SafeContents *dest; - SECStatus rv = SECFailure; - - if(!p12ctxt || !safeBag || !safeInfo) { - return SECFailure; - } - - if(!safeInfo->safe) { - safeInfo->safe = sec_PKCS12CreateSafeContents(p12ctxt->arena); - if(!safeInfo->safe) { - return SECFailure; - } - } - - dest = safeInfo->safe; - rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, dest, safeBag); - if(rv == SECSuccess) { - safeInfo->itemCount++; - } - - return rv; -} - -/* Creates a safeBag of the specified type, and if bagData is specified, - * the contents are set. The contents could be set later by the calling - * routine. - */ -sec_PKCS12SafeBag * -sec_PKCS12CreateSafeBag(SEC_PKCS12ExportContext *p12ctxt, SECOidTag bagType, - void *bagData) -{ - sec_PKCS12SafeBag *safeBag; - PRBool setName = PR_TRUE; - void *mark = NULL; - SECStatus rv = SECSuccess; - SECOidData *oidData = NULL; - - if(!p12ctxt) { - return NULL; - } - - mark = PORT_ArenaMark(p12ctxt->arena); - if(!mark) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - safeBag = (sec_PKCS12SafeBag *)PORT_ArenaZAlloc(p12ctxt->arena, - sizeof(sec_PKCS12SafeBag)); - if(!safeBag) { - PORT_ArenaRelease(p12ctxt->arena, mark); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - /* set the bags content based upon bag type */ - switch(bagType) { - case SEC_OID_PKCS12_V1_KEY_BAG_ID: - safeBag->safeBagContent.pkcs8KeyBag = - (SECKEYPrivateKeyInfo *)bagData; - break; - case SEC_OID_PKCS12_V1_CERT_BAG_ID: - safeBag->safeBagContent.certBag = (sec_PKCS12CertBag *)bagData; - break; - case SEC_OID_PKCS12_V1_CRL_BAG_ID: - safeBag->safeBagContent.crlBag = (sec_PKCS12CRLBag *)bagData; - break; - case SEC_OID_PKCS12_V1_SECRET_BAG_ID: - safeBag->safeBagContent.secretBag = (sec_PKCS12SecretBag *)bagData; - break; - case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: - safeBag->safeBagContent.pkcs8ShroudedKeyBag = - (SECKEYEncryptedPrivateKeyInfo *)bagData; - break; - case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID: - safeBag->safeBagContent.safeContents = - (sec_PKCS12SafeContents *)bagData; - setName = PR_FALSE; - break; - default: - goto loser; - } - - oidData = SECOID_FindOIDByTag(bagType); - if(oidData) { - rv = SECITEM_CopyItem(p12ctxt->arena, &safeBag->safeBagType, &oidData->oid); - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - } else { - goto loser; - } - - safeBag->arena = p12ctxt->arena; - PORT_ArenaUnmark(p12ctxt->arena, mark); - - return safeBag; - -loser: - if(mark) { - PORT_ArenaRelease(p12ctxt->arena, mark); - } - - return NULL; -} - -/* Creates a new certificate bag and returns a pointer to it. If an error - * occurs NULL is returned. - */ -sec_PKCS12CertBag * -sec_PKCS12NewCertBag(PRArenaPool *arena, SECOidTag certType) -{ - sec_PKCS12CertBag *certBag = NULL; - SECOidData *bagType = NULL; - SECStatus rv; - void *mark = NULL; - - if(!arena) { - return NULL; - } - - mark = PORT_ArenaMark(arena); - certBag = (sec_PKCS12CertBag *)PORT_ArenaZAlloc(arena, - sizeof(sec_PKCS12CertBag)); - if(!certBag) { - PORT_ArenaRelease(arena, mark); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - bagType = SECOID_FindOIDByTag(certType); - if(!bagType) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - rv = SECITEM_CopyItem(arena, &certBag->bagID, &bagType->oid); - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - PORT_ArenaUnmark(arena, mark); - return certBag; - -loser: - PORT_ArenaRelease(arena, mark); - return NULL; -} - -/* Creates a new CRL bag and returns a pointer to it. If an error - * occurs NULL is returned. - */ -sec_PKCS12CRLBag * -sec_PKCS12NewCRLBag(PRArenaPool *arena, SECOidTag crlType) -{ - sec_PKCS12CRLBag *crlBag = NULL; - SECOidData *bagType = NULL; - SECStatus rv; - void *mark = NULL; - - if(!arena) { - return NULL; - } - - mark = PORT_ArenaMark(arena); - crlBag = (sec_PKCS12CRLBag *)PORT_ArenaZAlloc(arena, - sizeof(sec_PKCS12CRLBag)); - if(!crlBag) { - PORT_ArenaRelease(arena, mark); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - bagType = SECOID_FindOIDByTag(crlType); - if(!bagType) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - rv = SECITEM_CopyItem(arena, &crlBag->bagID, &bagType->oid); - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - PORT_ArenaUnmark(arena, mark); - return crlBag; - -loser: - PORT_ArenaRelease(arena, mark); - return NULL; -} - -/* sec_PKCS12AddAttributeToBag - * adds an attribute to a safeBag. currently, the only attributes supported - * are those which are specified within PKCS 12. - * - * p12ctxt - the export context - * safeBag - the safeBag to which attributes are appended - * attrType - the attribute type - * attrData - the attribute data - */ -SECStatus -sec_PKCS12AddAttributeToBag(SEC_PKCS12ExportContext *p12ctxt, - sec_PKCS12SafeBag *safeBag, SECOidTag attrType, - SECItem *attrData) -{ - sec_PKCS12Attribute *attribute; - void *mark = NULL, *dummy = NULL; - SECOidData *oiddata = NULL; - SECItem unicodeName = { siBuffer, NULL, 0}; - void *src = NULL; - unsigned int nItems = 0; - SECStatus rv; - - if(!safeBag || !p12ctxt) { - return SECFailure; - } - - mark = PORT_ArenaMark(safeBag->arena); - - /* allocate the attribute */ - attribute = (sec_PKCS12Attribute *)PORT_ArenaZAlloc(safeBag->arena, - sizeof(sec_PKCS12Attribute)); - if(!attribute) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* set up the attribute */ - oiddata = SECOID_FindOIDByTag(attrType); - if(!oiddata) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - if(SECITEM_CopyItem(p12ctxt->arena, &attribute->attrType, &oiddata->oid) != - SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - nItems = 1; - switch(attrType) { - case SEC_OID_PKCS9_LOCAL_KEY_ID: - { - src = attrData; - break; - } - case SEC_OID_PKCS9_FRIENDLY_NAME: - { - if(!sec_pkcs12_convert_item_to_unicode(p12ctxt->arena, - &unicodeName, attrData, PR_FALSE, - PR_FALSE, PR_TRUE)) { - goto loser; - } - src = &unicodeName; - break; - } - default: - goto loser; - } - - /* append the attribute to the attribute value list */ - attribute->attrValue = (SECItem **)PORT_ArenaZAlloc(p12ctxt->arena, - ((nItems + 1) * sizeof(SECItem *))); - if(!attribute->attrValue) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* XXX this will need to be changed if attributes requiring more than - * one element are ever used. - */ - attribute->attrValue[0] = (SECItem *)PORT_ArenaZAlloc(p12ctxt->arena, - sizeof(SECItem)); - if(!attribute->attrValue[0]) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - attribute->attrValue[1] = NULL; - - rv = SECITEM_CopyItem(p12ctxt->arena, attribute->attrValue[0], - (SECItem*)src); - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* append the attribute to the safeBag attributes */ - if(safeBag->nAttribs) { - dummy = PORT_ArenaGrow(p12ctxt->arena, safeBag->attribs, - ((safeBag->nAttribs + 1) * sizeof(sec_PKCS12Attribute *)), - ((safeBag->nAttribs + 2) * sizeof(sec_PKCS12Attribute *))); - safeBag->attribs = (sec_PKCS12Attribute **)dummy; - } else { - safeBag->attribs = (sec_PKCS12Attribute **)PORT_ArenaZAlloc(p12ctxt->arena, - 2 * sizeof(sec_PKCS12Attribute *)); - dummy = safeBag->attribs; - } - if(!dummy) { - goto loser; - } - - safeBag->attribs[safeBag->nAttribs] = attribute; - safeBag->attribs[++safeBag->nAttribs] = NULL; - - PORT_ArenaUnmark(p12ctxt->arena, mark); - return SECSuccess; - -loser: - if(mark) { - PORT_ArenaRelease(p12ctxt->arena, mark); - } - - return SECFailure; -} - -/* SEC_PKCS12AddCert - * Adds a certificate to the data being exported. - * - * p12ctxt - the export context - * safe - the safeInfo to which the certificate is placed - * nestedDest - if the cert is to be placed within a nested safeContents then, - * this value is to be specified with the destination - * cert - the cert to export - * certDb - the certificate database handle - * keyId - a unique identifier to associate a certificate/key pair - * includeCertChain - PR_TRUE if the certificate chain is to be included. - */ -SECStatus -SEC_PKCS12AddCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *safe, - void *nestedDest, CERTCertificate *cert, - CERTCertDBHandle *certDb, SECItem *keyId, - PRBool includeCertChain) -{ - sec_PKCS12CertBag *certBag; - sec_PKCS12SafeBag *safeBag; - void *mark; - SECStatus rv; - SECItem nick = {siBuffer, NULL,0}; - - if(!p12ctxt || !cert) { - return SECFailure; - } - mark = PORT_ArenaMark(p12ctxt->arena); - - /* allocate the cert bag */ - certBag = sec_PKCS12NewCertBag(p12ctxt->arena, - SEC_OID_PKCS9_X509_CERT); - if(!certBag) { - goto loser; - } - - if(SECITEM_CopyItem(p12ctxt->arena, &certBag->value.x509Cert, - &cert->derCert) != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* if the cert chain is to be included, we should only be exporting - * the cert from our internal database. - */ - if(includeCertChain) { - CERTCertificateList *certList = CERT_CertChainFromCert(cert, - certUsageSSLClient, - PR_TRUE); - unsigned int count = 0; - if(!certList) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* add cert chain */ - for(count = 0; count < (unsigned int)certList->len; count++) { - if(SECITEM_CompareItem(&certList->certs[count], &cert->derCert) - != SECEqual) { - CERTCertificate *tempCert; - - /* decode the certificate */ - /* XXX - * This was rather silly. The chain is constructed above - * by finding all of the CERTCertificate's in the database. - * Then the chain is put into a CERTCertificateList, which only - * contains the DER. Finally, the DER was decoded, and the - * decoded cert was sent recursively back to this function. - * Beyond being inefficent, this causes data loss (specifically, - * the nickname). Instead, for 3.4, we'll do a lookup by the - * DER, which should return the cached entry. - */ - tempCert = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), - &certList->certs[count]); - if(!tempCert) { - CERT_DestroyCertificateList(certList); - goto loser; - } - - /* add the certificate */ - if(SEC_PKCS12AddCert(p12ctxt, safe, nestedDest, tempCert, - certDb, NULL, PR_FALSE) != SECSuccess) { - CERT_DestroyCertificate(tempCert); - CERT_DestroyCertificateList(certList); - goto loser; - } - CERT_DestroyCertificate(tempCert); - } - } - CERT_DestroyCertificateList(certList); - } - - /* if the certificate has a nickname, we will set the friendly name - * to that. - */ - if(cert->nickname) { - if (cert->slot && !PK11_IsInternal(cert->slot)) { - /* - * The cert is coming off of an external token, - * let's strip the token name from the nickname - * and only add what comes after the colon as the - * nickname. -javi - */ - char *delimit; - - delimit = PORT_Strchr(cert->nickname,':'); - if (delimit == NULL) { - nick.data = (unsigned char *)cert->nickname; - nick.len = PORT_Strlen(cert->nickname); - } else { - delimit++; - nick.data = (unsigned char *)PORT_ArenaStrdup(p12ctxt->arena, - delimit); - nick.len = PORT_Strlen(delimit); - } - } else { - nick.data = (unsigned char *)cert->nickname; - nick.len = PORT_Strlen(cert->nickname); - } - } - - safeBag = sec_PKCS12CreateSafeBag(p12ctxt, SEC_OID_PKCS12_V1_CERT_BAG_ID, - certBag); - if(!safeBag) { - goto loser; - } - - /* add the friendly name and keyId attributes, if necessary */ - if(nick.data) { - if(sec_PKCS12AddAttributeToBag(p12ctxt, safeBag, - SEC_OID_PKCS9_FRIENDLY_NAME, &nick) - != SECSuccess) { - goto loser; - } - } - - if(keyId) { - if(sec_PKCS12AddAttributeToBag(p12ctxt, safeBag, SEC_OID_PKCS9_LOCAL_KEY_ID, - keyId) != SECSuccess) { - goto loser; - } - } - - /* append the cert safeBag */ - if(nestedDest) { - rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, - (sec_PKCS12SafeContents*)nestedDest, - safeBag); - } else { - rv = sec_pkcs12_append_bag(p12ctxt, safe, safeBag); - } - - if(rv != SECSuccess) { - goto loser; - } - - PORT_ArenaUnmark(p12ctxt->arena, mark); - return SECSuccess; - -loser: - if(mark) { - PORT_ArenaRelease(p12ctxt->arena, mark); - } - - return SECFailure; -} - -/* SEC_PKCS12AddEncryptedKey - * Extracts the key associated with a particular certificate and exports - * it. - * - * p12ctxt - the export context - * safe - the safeInfo to place the key in - * nestedDest - the nested safeContents to place a key - * cert - the certificate which the key belongs to - * shroudKey - encrypt the private key for export. This value should - * always be true. lower level code will not allow the export - * of unencrypted private keys. - * algorithm - the algorithm with which to encrypt the private key - * pwitem - the password to encrypted the private key with - * keyId - the keyID attribute - * nickName - the nickname attribute - */ -static SECStatus -SEC_PKCS12AddEncryptedKey(SEC_PKCS12ExportContext *p12ctxt, - SECKEYEncryptedPrivateKeyInfo *epki, SEC_PKCS12SafeInfo *safe, - void *nestedDest, SECItem *keyId, SECItem *nickName) -{ - void *mark; - void *keyItem; - SECOidTag keyType; - SECStatus rv = SECFailure; - sec_PKCS12SafeBag *returnBag; - - if(!p12ctxt || !safe || !epki) { - return SECFailure; - } - - mark = PORT_ArenaMark(p12ctxt->arena); - - keyItem = PORT_ArenaZAlloc(p12ctxt->arena, - sizeof(SECKEYEncryptedPrivateKeyInfo)); - if(!keyItem) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - rv = SECKEY_CopyEncryptedPrivateKeyInfo(p12ctxt->arena, - (SECKEYEncryptedPrivateKeyInfo *)keyItem, - epki); - keyType = SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID; - - if(rv != SECSuccess) { - goto loser; - } - - /* create the safe bag and set any attributes */ - returnBag = sec_PKCS12CreateSafeBag(p12ctxt, keyType, keyItem); - if(!returnBag) { - rv = SECFailure; - goto loser; - } - - if(nickName) { - if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, - SEC_OID_PKCS9_FRIENDLY_NAME, nickName) - != SECSuccess) { - goto loser; - } - } - - if(keyId) { - if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, - SEC_OID_PKCS9_LOCAL_KEY_ID, - keyId) != SECSuccess) { - goto loser; - } - } - - if(nestedDest) { - rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, - (sec_PKCS12SafeContents*)nestedDest, - returnBag); - } else { - rv = sec_pkcs12_append_bag(p12ctxt, safe, returnBag); - } - -loser: - - if (rv != SECSuccess) { - PORT_ArenaRelease(p12ctxt->arena, mark); - } else { - PORT_ArenaUnmark(p12ctxt->arena, mark); - } - - return rv; -} - -/* SEC_PKCS12AddKeyForCert - * Extracts the key associated with a particular certificate and exports - * it. - * - * p12ctxt - the export context - * safe - the safeInfo to place the key in - * nestedDest - the nested safeContents to place a key - * cert - the certificate which the key belongs to - * shroudKey - encrypt the private key for export. This value should - * always be true. lower level code will not allow the export - * of unencrypted private keys. - * algorithm - the algorithm with which to encrypt the private key - * pwitem - the password to encrypt the private key with - * keyId - the keyID attribute - * nickName - the nickname attribute - */ -SECStatus -SEC_PKCS12AddKeyForCert(SEC_PKCS12ExportContext *p12ctxt, SEC_PKCS12SafeInfo *safe, - void *nestedDest, CERTCertificate *cert, - PRBool shroudKey, SECOidTag algorithm, SECItem *pwitem, - SECItem *keyId, SECItem *nickName) -{ - void *mark; - void *keyItem; - SECOidTag keyType; - SECStatus rv = SECFailure; - SECItem nickname = {siBuffer,NULL,0}, uniPwitem = {siBuffer, NULL, 0}; - sec_PKCS12SafeBag *returnBag; - - if(!p12ctxt || !cert || !safe) { - return SECFailure; - } - - mark = PORT_ArenaMark(p12ctxt->arena); - - /* retrieve the key based upon the type that it is and - * specify the type of safeBag to store the key in - */ - if(!shroudKey) { - - /* extract the key unencrypted. this will most likely go away */ - SECKEYPrivateKeyInfo *pki = PK11_ExportPrivateKeyInfo(cert, - p12ctxt->wincx); - if(!pki) { - PORT_ArenaRelease(p12ctxt->arena, mark); - PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY); - return SECFailure; - } - keyItem = PORT_ArenaZAlloc(p12ctxt->arena, sizeof(SECKEYPrivateKeyInfo)); - if(!keyItem) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - rv = SECKEY_CopyPrivateKeyInfo(p12ctxt->arena, - (SECKEYPrivateKeyInfo *)keyItem, pki); - keyType = SEC_OID_PKCS12_V1_KEY_BAG_ID; - SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE); - } else { - - /* extract the key encrypted */ - SECKEYEncryptedPrivateKeyInfo *epki = NULL; - PK11SlotInfo *slot = NULL; - - if(!sec_pkcs12_convert_item_to_unicode(p12ctxt->arena, &uniPwitem, - pwitem, PR_TRUE, PR_TRUE, PR_TRUE)) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* we want to make sure to take the key out of the key slot */ - if(PK11_IsInternal(p12ctxt->slot)) { - slot = PK11_GetInternalKeySlot(); - } else { - slot = PK11_ReferenceSlot(p12ctxt->slot); - } - - epki = PK11_ExportEncryptedPrivateKeyInfo(slot, algorithm, - &uniPwitem, cert, 1, - p12ctxt->wincx); - PK11_FreeSlot(slot); - - keyItem = PORT_ArenaZAlloc(p12ctxt->arena, - sizeof(SECKEYEncryptedPrivateKeyInfo)); - if(!keyItem) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - if(!epki) { - PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY); - return SECFailure; - } - rv = SECKEY_CopyEncryptedPrivateKeyInfo(p12ctxt->arena, - (SECKEYEncryptedPrivateKeyInfo *)keyItem, - epki); - keyType = SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID; - SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE); - } - - if(rv != SECSuccess) { - goto loser; - } - - /* if no nickname specified, let's see if the certificate has a - * nickname. - */ - if(!nickName) { - if(cert->nickname) { - nickname.data = (unsigned char *)cert->nickname; - nickname.len = PORT_Strlen(cert->nickname); - nickName = &nickname; - } - } - - /* create the safe bag and set any attributes */ - returnBag = sec_PKCS12CreateSafeBag(p12ctxt, keyType, keyItem); - if(!returnBag) { - rv = SECFailure; - goto loser; - } - - if(nickName) { - if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, - SEC_OID_PKCS9_FRIENDLY_NAME, nickName) - != SECSuccess) { - goto loser; - } - } - - if(keyId) { - if(sec_PKCS12AddAttributeToBag(p12ctxt, returnBag, SEC_OID_PKCS9_LOCAL_KEY_ID, - keyId) != SECSuccess) { - goto loser; - } - } - - if(nestedDest) { - rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, - (sec_PKCS12SafeContents*)nestedDest, - returnBag); - } else { - rv = sec_pkcs12_append_bag(p12ctxt, safe, returnBag); - } - -loser: - - if (rv != SECSuccess) { - PORT_ArenaRelease(p12ctxt->arena, mark); - } else { - PORT_ArenaUnmark(p12ctxt->arena, mark); - } - - return rv; -} - -/* SEC_PKCS12AddCertAndEncryptedKey - * Add a certificate and key pair to be exported. - * - * p12ctxt - the export context - * certSafe - the safeInfo where the cert is stored - * certNestedDest - the nested safeContents to store the cert - * keySafe - the safeInfo where the key is stored - * keyNestedDest - the nested safeContents to store the key - * shroudKey - extract the private key encrypted? - * pwitem - the password with which the key is encrypted - * algorithm - the algorithm with which the key is encrypted - */ -SECStatus -SEC_PKCS12AddDERCertAndEncryptedKey(SEC_PKCS12ExportContext *p12ctxt, - void *certSafe, void *certNestedDest, - SECItem *derCert, void *keySafe, - void *keyNestedDest, SECKEYEncryptedPrivateKeyInfo *epki, - char *nickname) -{ - SECStatus rv = SECFailure; - SGNDigestInfo *digest = NULL; - void *mark = NULL; - CERTCertificate *cert; - SECItem nick = {siBuffer, NULL,0}, *nickPtr = NULL; - - if(!p12ctxt || !certSafe || !keySafe || !derCert) { - return SECFailure; - } - - mark = PORT_ArenaMark(p12ctxt->arena); - - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), - derCert, NULL, PR_FALSE, PR_FALSE); - if(!cert) { - PORT_ArenaRelease(p12ctxt->arena, mark); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - cert->nickname = nickname; - - /* generate the thumbprint of the cert to use as a keyId */ - digest = sec_pkcs12_compute_thumbprint(&cert->derCert); - if(!digest) { - CERT_DestroyCertificate(cert); - return SECFailure; - } - - /* add the certificate */ - rv = SEC_PKCS12AddCert(p12ctxt, (SEC_PKCS12SafeInfo*)certSafe, - certNestedDest, cert, NULL, - &digest->digest, PR_FALSE); - if(rv != SECSuccess) { - goto loser; - } - - if(nickname) { - nick.data = (unsigned char *)nickname; - nick.len = PORT_Strlen(nickname); - nickPtr = &nick; - } else { - nickPtr = NULL; - } - - /* add the key */ - rv = SEC_PKCS12AddEncryptedKey(p12ctxt, epki, (SEC_PKCS12SafeInfo*)keySafe, - keyNestedDest, &digest->digest, nickPtr ); - if(rv != SECSuccess) { - goto loser; - } - - SGN_DestroyDigestInfo(digest); - - PORT_ArenaUnmark(p12ctxt->arena, mark); - return SECSuccess; - -loser: - SGN_DestroyDigestInfo(digest); - CERT_DestroyCertificate(cert); - PORT_ArenaRelease(p12ctxt->arena, mark); - - return SECFailure; -} - -/* SEC_PKCS12AddCertAndKey - * Add a certificate and key pair to be exported. - * - * p12ctxt - the export context - * certSafe - the safeInfo where the cert is stored - * certNestedDest - the nested safeContents to store the cert - * keySafe - the safeInfo where the key is stored - * keyNestedDest - the nested safeContents to store the key - * shroudKey - extract the private key encrypted? - * pwitem - the password with which the key is encrypted - * algorithm - the algorithm with which the key is encrypted - */ -SECStatus -SEC_PKCS12AddCertAndKey(SEC_PKCS12ExportContext *p12ctxt, - void *certSafe, void *certNestedDest, - CERTCertificate *cert, CERTCertDBHandle *certDb, - void *keySafe, void *keyNestedDest, - PRBool shroudKey, SECItem *pwitem, SECOidTag algorithm) -{ - SECStatus rv = SECFailure; - SGNDigestInfo *digest = NULL; - void *mark = NULL; - - if(!p12ctxt || !certSafe || !keySafe || !cert) { - return SECFailure; - } - - mark = PORT_ArenaMark(p12ctxt->arena); - - /* generate the thumbprint of the cert to use as a keyId */ - digest = sec_pkcs12_compute_thumbprint(&cert->derCert); - if(!digest) { - PORT_ArenaRelease(p12ctxt->arena, mark); - return SECFailure; - } - - /* add the certificate */ - rv = SEC_PKCS12AddCert(p12ctxt, (SEC_PKCS12SafeInfo*)certSafe, - (SEC_PKCS12SafeInfo*)certNestedDest, cert, certDb, - &digest->digest, PR_TRUE); - if(rv != SECSuccess) { - goto loser; - } - - /* add the key */ - rv = SEC_PKCS12AddKeyForCert(p12ctxt, (SEC_PKCS12SafeInfo*)keySafe, - keyNestedDest, cert, - shroudKey, algorithm, pwitem, - &digest->digest, NULL ); - if(rv != SECSuccess) { - goto loser; - } - - SGN_DestroyDigestInfo(digest); - - PORT_ArenaUnmark(p12ctxt->arena, mark); - return SECSuccess; - -loser: - SGN_DestroyDigestInfo(digest); - PORT_ArenaRelease(p12ctxt->arena, mark); - - return SECFailure; -} - -/* SEC_PKCS12CreateNestedSafeContents - * Allows nesting of safe contents to be implemented. No limit imposed on - * depth. - * - * p12ctxt - the export context - * baseSafe - the base safeInfo - * nestedDest - a parent safeContents (?) - */ -void * -SEC_PKCS12CreateNestedSafeContents(SEC_PKCS12ExportContext *p12ctxt, - void *baseSafe, void *nestedDest) -{ - sec_PKCS12SafeContents *newSafe; - sec_PKCS12SafeBag *safeContentsBag; - void *mark; - SECStatus rv; - - if(!p12ctxt || !baseSafe) { - return NULL; - } - - mark = PORT_ArenaMark(p12ctxt->arena); - - newSafe = sec_PKCS12CreateSafeContents(p12ctxt->arena); - if(!newSafe) { - PORT_ArenaRelease(p12ctxt->arena, mark); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - /* create the safeContents safeBag */ - safeContentsBag = sec_PKCS12CreateSafeBag(p12ctxt, - SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID, - newSafe); - if(!safeContentsBag) { - goto loser; - } - - /* append the safeContents to the appropriate area */ - if(nestedDest) { - rv = sec_pkcs12_append_bag_to_safe_contents(p12ctxt->arena, - (sec_PKCS12SafeContents*)nestedDest, - safeContentsBag); - } else { - rv = sec_pkcs12_append_bag(p12ctxt, (SEC_PKCS12SafeInfo*)baseSafe, - safeContentsBag); - } - if(rv != SECSuccess) { - goto loser; - } - - PORT_ArenaUnmark(p12ctxt->arena, mark); - return newSafe; - -loser: - PORT_ArenaRelease(p12ctxt->arena, mark); - return NULL; -} - -/********************************* - * Encoding routines - *********************************/ - -/* set up the encoder context based on information in the export context - * and return the newly allocated enocoder context. A return of NULL - * indicates an error occurred. - */ -sec_PKCS12EncoderContext * -sec_pkcs12_encoder_start_context(SEC_PKCS12ExportContext *p12exp) -{ - sec_PKCS12EncoderContext *p12enc = NULL; - unsigned int i, nonEmptyCnt; - SECStatus rv; - SECItem ignore = {0}; - void *mark; - - if(!p12exp || !p12exp->safeInfos) { - return NULL; - } - - /* check for any empty safes and skip them */ - i = nonEmptyCnt = 0; - while(p12exp->safeInfos[i]) { - if(p12exp->safeInfos[i]->itemCount) { - nonEmptyCnt++; - } - i++; - } - if(nonEmptyCnt == 0) { - return NULL; - } - p12exp->authSafe.encodedSafes[nonEmptyCnt] = NULL; - - /* allocate the encoder context */ - mark = PORT_ArenaMark(p12exp->arena); - p12enc = PORT_ArenaZNew(p12exp->arena, sec_PKCS12EncoderContext); - if(!p12enc) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - p12enc->arena = p12exp->arena; - p12enc->p12exp = p12exp; - - /* set up the PFX version and information */ - PORT_Memset(&p12enc->pfx, 0, sizeof(sec_PKCS12PFXItem)); - if(!SEC_ASN1EncodeInteger(p12exp->arena, &(p12enc->pfx.version), - SEC_PKCS12_VERSION) ) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* set up the authenticated safe content info based on the - * type of integrity being used. this should be changed to - * enforce integrity mode, but will not be implemented until - * it is confirmed that integrity must be in place - */ - if(p12exp->integrityEnabled && !p12exp->pwdIntegrity) { - SECStatus rv; - - /* create public key integrity mode */ - p12enc->aSafeCinfo = SEC_PKCS7CreateSignedData( - p12exp->integrityInfo.pubkeyInfo.cert, - certUsageEmailSigner, - p12exp->integrityInfo.pubkeyInfo.certDb, - p12exp->integrityInfo.pubkeyInfo.algorithm, - NULL, - p12exp->pwfn, - p12exp->pwfnarg); - if(!p12enc->aSafeCinfo) { - goto loser; - } - if(SEC_PKCS7IncludeCertChain(p12enc->aSafeCinfo,NULL) != SECSuccess) { - goto loser; - } - rv = SEC_PKCS7AddSigningTime(p12enc->aSafeCinfo); - PORT_Assert(rv == SECSuccess); - } else { - p12enc->aSafeCinfo = SEC_PKCS7CreateData(); - - /* init password pased integrity mode */ - if(p12exp->integrityEnabled) { - SECItem pwd = {siBuffer,NULL, 0}; - SECItem *salt = sec_pkcs12_generate_salt(); - PK11SymKey *symKey; - SECItem *params; - CK_MECHANISM_TYPE integrityMech; - CK_MECHANISM_TYPE hmacMech; - - /* zero out macData and set values */ - PORT_Memset(&p12enc->mac, 0, sizeof(sec_PKCS12MacData)); - - if(!salt) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - if(SECITEM_CopyItem(p12exp->arena, &(p12enc->mac.macSalt), salt) - != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* generate HMAC key */ - if(!sec_pkcs12_convert_item_to_unicode(NULL, &pwd, - p12exp->integrityInfo.pwdInfo.password, PR_TRUE, - PR_TRUE, PR_TRUE)) { - goto loser; - } - - params = PK11_CreatePBEParams(salt, &pwd, 1); - SECITEM_ZfreeItem(salt, PR_TRUE); - SECITEM_ZfreeItem(&pwd, PR_FALSE); - - switch (p12exp->integrityInfo.pwdInfo.algorithm) { - case SEC_OID_SHA1: - integrityMech = CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN; break; - case SEC_OID_MD5: - integrityMech = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN; break; - case SEC_OID_MD2: - integrityMech = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN; break; - default: - goto loser; - } - - symKey = PK11_KeyGen(NULL, integrityMech, params, 20, NULL); - PK11_DestroyPBEParams(params); - if(!symKey) { - goto loser; - } - - /* initialize hmac */ - /* XXX NBB, why is this mech different than the one above? */ - hmacMech = sec_pkcs12_algtag_to_mech( - p12exp->integrityInfo.pwdInfo.algorithm); - - p12enc->hmacCx = PK11_CreateContextBySymKey( hmacMech, CKA_SIGN, - symKey, &ignore); - - PK11_FreeSymKey(symKey); - if(!p12enc->hmacCx) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - rv = PK11_DigestBegin(p12enc->hmacCx); - if (rv != SECSuccess) - goto loser; - } - } - - if(!p12enc->aSafeCinfo) { - goto loser; - } - - PORT_ArenaUnmark(p12exp->arena, mark); - - return p12enc; - -loser: - if(p12enc) { - if(p12enc->aSafeCinfo) { - SEC_PKCS7DestroyContentInfo(p12enc->aSafeCinfo); - } - if(p12enc->hmacCx) { - PK11_DestroyContext(p12enc->hmacCx, PR_TRUE); - } - } - if (p12exp->arena != NULL) - PORT_ArenaRelease(p12exp->arena, mark); - - return NULL; -} - -/* The outermost ASN.1 encoder calls this function for output. -** This function calls back to the library caller's output routine, -** which typically writes to a PKCS12 file. - */ -static void -sec_P12A1OutputCB_Outer(void *arg, const char *buf, unsigned long len, - int depth, SEC_ASN1EncodingPart data_kind) -{ - struct sec_pkcs12_encoder_output *output; - - output = (struct sec_pkcs12_encoder_output*)arg; - (* output->outputfn)(output->outputarg, buf, len); -} - -/* The "middle" and "inner" ASN.1 encoders call this function to output. -** This function does HMACing, if appropriate, and then buffers the data. -** The buffered data is eventually passed down to the underlying PKCS7 encoder. - */ -static void -sec_P12A1OutputCB_HmacP7Update(void *arg, const char *buf, - unsigned long len, - int depth, - SEC_ASN1EncodingPart data_kind) -{ - sec_pkcs12OutputBuffer * bufcx = (sec_pkcs12OutputBuffer *)arg; - - if(!buf || !len) - return; - - if (bufcx->hmacCx) { - PK11_DigestOp(bufcx->hmacCx, (unsigned char *)buf, len); - } - - /* buffer */ - if (bufcx->numBytes > 0) { - int toCopy; - if (len + bufcx->numBytes <= bufcx->bufBytes) { - memcpy(bufcx->buf + bufcx->numBytes, buf, len); - bufcx->numBytes += len; - if (bufcx->numBytes < bufcx->bufBytes) - return; - SEC_PKCS7EncoderUpdate(bufcx->p7eCx, bufcx->buf, bufcx->bufBytes); - bufcx->numBytes = 0; - return; - } - toCopy = bufcx->bufBytes - bufcx->numBytes; - memcpy(bufcx->buf + bufcx->numBytes, buf, toCopy); - SEC_PKCS7EncoderUpdate(bufcx->p7eCx, bufcx->buf, bufcx->bufBytes); - bufcx->numBytes = 0; - len -= toCopy; - buf += toCopy; - } - /* buffer is presently empty */ - if (len >= bufcx->bufBytes) { - /* Just pass it through */ - SEC_PKCS7EncoderUpdate(bufcx->p7eCx, buf, len); - } else { - /* copy it all into the buffer, and return */ - memcpy(bufcx->buf, buf, len); - bufcx->numBytes = len; - } -} - -void -sec_FlushPkcs12OutputBuffer( sec_pkcs12OutputBuffer * bufcx) -{ - if (bufcx->numBytes > 0) { - SEC_PKCS7EncoderUpdate(bufcx->p7eCx, bufcx->buf, bufcx->numBytes); - bufcx->numBytes = 0; - } -} - -/* Feeds the output of a PKCS7 encoder into the next outward ASN.1 encoder. -** This function is used by both the inner and middle PCS7 encoders. -*/ -static void -sec_P12P7OutputCB_CallA1Update(void *arg, const char *buf, unsigned long len) -{ - SEC_ASN1EncoderContext *cx = (SEC_ASN1EncoderContext*)arg; - - if (!buf || !len) - return; - - SEC_ASN1EncoderUpdate(cx, buf, len); -} - - -/* this function encodes content infos which are part of the - * sequence of content infos labeled AuthenticatedSafes - */ -static SECStatus -sec_pkcs12_encoder_asafe_process(sec_PKCS12EncoderContext *p12ecx) -{ - SEC_PKCS7EncoderContext *innerP7ecx; - SEC_PKCS7ContentInfo *cinfo; - PK11SymKey *bulkKey = NULL; - SEC_ASN1EncoderContext *innerA1ecx = NULL; - SECStatus rv = SECSuccess; - - if(p12ecx->currentSafe < p12ecx->p12exp->authSafe.safeCount) { - SEC_PKCS12SafeInfo *safeInfo; - SECOidTag cinfoType; - - safeInfo = p12ecx->p12exp->safeInfos[p12ecx->currentSafe]; - - /* skip empty safes */ - if(safeInfo->itemCount == 0) { - return SECSuccess; - } - - cinfo = safeInfo->cinfo; - cinfoType = SEC_PKCS7ContentType(cinfo); - - /* determine the safe type and set the appropriate argument */ - switch(cinfoType) { - case SEC_OID_PKCS7_DATA: - case SEC_OID_PKCS7_ENVELOPED_DATA: - break; - case SEC_OID_PKCS7_ENCRYPTED_DATA: - bulkKey = safeInfo->encryptionKey; - PK11_SetSymKeyUserData(bulkKey, &safeInfo->pwitem, NULL); - break; - default: - return SECFailure; - - } - - /* start the PKCS7 encoder */ - innerP7ecx = SEC_PKCS7EncoderStart(cinfo, - sec_P12P7OutputCB_CallA1Update, - p12ecx->middleA1ecx, bulkKey); - if(!innerP7ecx) { - goto loser; - } - - /* encode safe contents */ - p12ecx->innerBuf.p7eCx = innerP7ecx; - p12ecx->innerBuf.hmacCx = NULL; - p12ecx->innerBuf.numBytes = 0; - p12ecx->innerBuf.bufBytes = sizeof p12ecx->innerBuf.buf; - - innerA1ecx = SEC_ASN1EncoderStart(safeInfo->safe, - sec_PKCS12SafeContentsTemplate, - sec_P12A1OutputCB_HmacP7Update, - &p12ecx->innerBuf); - if(!innerA1ecx) { - goto loser; - } - rv = SEC_ASN1EncoderUpdate(innerA1ecx, NULL, 0); - SEC_ASN1EncoderFinish(innerA1ecx); - sec_FlushPkcs12OutputBuffer( &p12ecx->innerBuf); - innerA1ecx = NULL; - if(rv != SECSuccess) { - goto loser; - } - - - /* finish up safe content info */ - rv = SEC_PKCS7EncoderFinish(innerP7ecx, p12ecx->p12exp->pwfn, - p12ecx->p12exp->pwfnarg); - } - memset(&p12ecx->innerBuf, 0, sizeof p12ecx->innerBuf); - return SECSuccess; - -loser: - if(innerP7ecx) { - SEC_PKCS7EncoderFinish(innerP7ecx, p12ecx->p12exp->pwfn, - p12ecx->p12exp->pwfnarg); - } - - if(innerA1ecx) { - SEC_ASN1EncoderFinish(innerA1ecx); - } - memset(&p12ecx->innerBuf, 0, sizeof p12ecx->innerBuf); - return SECFailure; -} - -/* finish the HMAC and encode the macData so that it can be - * encoded. - */ -static SECStatus -sec_Pkcs12FinishMac(sec_PKCS12EncoderContext *p12ecx) -{ - SECItem hmac = { siBuffer, NULL, 0 }; - SECStatus rv; - SGNDigestInfo *di = NULL; - void *dummy; - - if(!p12ecx) { - return SECFailure; - } - - /* make sure we are using password integrity mode */ - if(!p12ecx->p12exp->integrityEnabled) { - return SECSuccess; - } - - if(!p12ecx->p12exp->pwdIntegrity) { - return SECSuccess; - } - - /* finish the hmac */ - hmac.data = (unsigned char *)PORT_ZAlloc(SHA1_LENGTH); - if(!hmac.data) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - - rv = PK11_DigestFinal(p12ecx->hmacCx, hmac.data, &hmac.len, SHA1_LENGTH); - - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* create the digest info */ - di = SGN_CreateDigestInfo(p12ecx->p12exp->integrityInfo.pwdInfo.algorithm, - hmac.data, hmac.len); - if(!di) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - rv = SECFailure; - goto loser; - } - - rv = SGN_CopyDigestInfo(p12ecx->arena, &p12ecx->mac.safeMac, di); - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - /* encode the mac data */ - dummy = SEC_ASN1EncodeItem(p12ecx->arena, &p12ecx->pfx.encodedMacData, - &p12ecx->mac, sec_PKCS12MacDataTemplate); - if(!dummy) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - rv = SECFailure; - } - -loser: - if(di) { - SGN_DestroyDigestInfo(di); - } - if(hmac.data) { - SECITEM_ZfreeItem(&hmac, PR_FALSE); - } - PK11_DestroyContext(p12ecx->hmacCx, PR_TRUE); - p12ecx->hmacCx = NULL; - - return rv; -} - -/* pfx notify function for ASN1 encoder. - * We want to stop encoding once we reach the authenticated safe. - * At that point, the encoder will be updated via streaming - * as the authenticated safe is encoded. - */ -static void -sec_pkcs12_encoder_pfx_notify(void *arg, PRBool before, void *dest, int real_depth) -{ - sec_PKCS12EncoderContext *p12ecx; - - if(!before) { - return; - } - - /* look for authenticated safe */ - p12ecx = (sec_PKCS12EncoderContext*)arg; - if(dest != &p12ecx->pfx.encodedAuthSafe) { - return; - } - - SEC_ASN1EncoderSetTakeFromBuf(p12ecx->outerA1ecx); - SEC_ASN1EncoderSetStreaming(p12ecx->outerA1ecx); - SEC_ASN1EncoderClearNotifyProc(p12ecx->outerA1ecx); -} - -/* SEC_PKCS12Encode - * Encodes the PFX item and returns it to the output function, via - * callback. the output function must be capable of multiple updates. - * - * p12exp - the export context - * output - the output function callback, will be called more than once, - * must be able to accept streaming data. - * outputarg - argument for the output callback. - */ -SECStatus -SEC_PKCS12Encode(SEC_PKCS12ExportContext *p12exp, - SEC_PKCS12EncoderOutputCallback output, void *outputarg) -{ - sec_PKCS12EncoderContext *p12enc; - struct sec_pkcs12_encoder_output outInfo; - SECStatus rv; - - if(!p12exp || !output) { - return SECFailure; - } - - /* get the encoder context */ - p12enc = sec_pkcs12_encoder_start_context(p12exp); - if(!p12enc) { - return SECFailure; - } - - outInfo.outputfn = output; - outInfo.outputarg = outputarg; - - /* set up PFX encoder, the "outer" encoder. Set it for streaming */ - p12enc->outerA1ecx = SEC_ASN1EncoderStart(&p12enc->pfx, - sec_PKCS12PFXItemTemplate, - sec_P12A1OutputCB_Outer, - &outInfo); - if(!p12enc->outerA1ecx) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - rv = SECFailure; - goto loser; - } - SEC_ASN1EncoderSetStreaming(p12enc->outerA1ecx); - SEC_ASN1EncoderSetNotifyProc(p12enc->outerA1ecx, - sec_pkcs12_encoder_pfx_notify, p12enc); - rv = SEC_ASN1EncoderUpdate(p12enc->outerA1ecx, NULL, 0); - if(rv != SECSuccess) { - rv = SECFailure; - goto loser; - } - - /* set up asafe cinfo - the output of the encoder feeds the PFX encoder */ - p12enc->middleP7ecx = SEC_PKCS7EncoderStart(p12enc->aSafeCinfo, - sec_P12P7OutputCB_CallA1Update, - p12enc->outerA1ecx, NULL); - if(!p12enc->middleP7ecx) { - rv = SECFailure; - goto loser; - } - - /* encode asafe */ - p12enc->middleBuf.p7eCx = p12enc->middleP7ecx; - p12enc->middleBuf.hmacCx = NULL; - p12enc->middleBuf.numBytes = 0; - p12enc->middleBuf.bufBytes = sizeof p12enc->middleBuf.buf; - - /* Setup the "inner ASN.1 encoder for Authenticated Safes. */ - if(p12enc->p12exp->integrityEnabled && - p12enc->p12exp->pwdIntegrity) { - p12enc->middleBuf.hmacCx = p12enc->hmacCx; - } - p12enc->middleA1ecx = SEC_ASN1EncoderStart(&p12enc->p12exp->authSafe, - sec_PKCS12AuthenticatedSafeTemplate, - sec_P12A1OutputCB_HmacP7Update, - &p12enc->middleBuf); - if(!p12enc->middleA1ecx) { - rv = SECFailure; - goto loser; - } - SEC_ASN1EncoderSetStreaming(p12enc->middleA1ecx); - SEC_ASN1EncoderSetTakeFromBuf(p12enc->middleA1ecx); - - /* encode each of the safes */ - while(p12enc->currentSafe != p12enc->p12exp->safeInfoCount) { - sec_pkcs12_encoder_asafe_process(p12enc); - p12enc->currentSafe++; - } - SEC_ASN1EncoderClearTakeFromBuf(p12enc->middleA1ecx); - SEC_ASN1EncoderClearStreaming(p12enc->middleA1ecx); - SEC_ASN1EncoderUpdate(p12enc->middleA1ecx, NULL, 0); - SEC_ASN1EncoderFinish(p12enc->middleA1ecx); - - sec_FlushPkcs12OutputBuffer( &p12enc->middleBuf); - - /* finish the encoding of the authenticated safes */ - rv = SEC_PKCS7EncoderFinish(p12enc->middleP7ecx, p12exp->pwfn, - p12exp->pwfnarg); - if(rv != SECSuccess) { - goto loser; - } - - SEC_ASN1EncoderClearTakeFromBuf(p12enc->outerA1ecx); - SEC_ASN1EncoderClearStreaming(p12enc->outerA1ecx); - - /* update the mac, if necessary */ - rv = sec_Pkcs12FinishMac(p12enc); - if(rv != SECSuccess) { - goto loser; - } - - /* finish encoding the pfx */ - rv = SEC_ASN1EncoderUpdate(p12enc->outerA1ecx, NULL, 0); - - SEC_ASN1EncoderFinish(p12enc->outerA1ecx); - -loser: - return rv; -} - -void -SEC_PKCS12DestroyExportContext(SEC_PKCS12ExportContext *p12ecx) -{ - int i = 0; - - if(!p12ecx) { - return; - } - - if(p12ecx->safeInfos) { - i = 0; - while(p12ecx->safeInfos[i] != NULL) { - if(p12ecx->safeInfos[i]->encryptionKey) { - PK11_FreeSymKey(p12ecx->safeInfos[i]->encryptionKey); - } - if(p12ecx->safeInfos[i]->cinfo) { - SEC_PKCS7DestroyContentInfo(p12ecx->safeInfos[i]->cinfo); - } - i++; - } - } - - PK11_FreeSlot(p12ecx->slot); - - PORT_FreeArena(p12ecx->arena, PR_TRUE); -} - - -/********************************* - * All-in-one routines for exporting certificates - *********************************/ -struct inPlaceEncodeInfo { - PRBool error; - SECItem outItem; -}; - -static void -sec_pkcs12_in_place_encoder_output(void *arg, const char *buf, unsigned long len) -{ - struct inPlaceEncodeInfo *outInfo = (struct inPlaceEncodeInfo*)arg; - - if(!outInfo || !len || outInfo->error) { - return; - } - - if(!outInfo->outItem.data) { - outInfo->outItem.data = (unsigned char*)PORT_ZAlloc(len); - outInfo->outItem.len = 0; - } else { - if(!PORT_Realloc(&(outInfo->outItem.data), (outInfo->outItem.len + len))) { - SECITEM_ZfreeItem(&(outInfo->outItem), PR_FALSE); - outInfo->outItem.data = NULL; - PORT_SetError(SEC_ERROR_NO_MEMORY); - outInfo->error = PR_TRUE; - return; - } - } - - PORT_Memcpy(&(outInfo->outItem.data[outInfo->outItem.len]), buf, len); - outInfo->outItem.len += len; - - return; -} - -/* - * SEC_PKCS12ExportCertifcateAndKeyUsingPassword - * Exports a certificate/key pair using password-based encryption and - * authentication. - * - * pwfn, pwfnarg - password function and argument for the key database - * cert - the certificate to export - * certDb - certificate database - * pwitem - the password to use - * shroudKey - encrypt the key externally, - * keyShroudAlg - encryption algorithm for key - * encryptionAlg - the algorithm with which data is encrypted - * integrityAlg - the algorithm for integrity - */ -SECItem * -SEC_PKCS12ExportCertificateAndKeyUsingPassword( - SECKEYGetPasswordKey pwfn, void *pwfnarg, - CERTCertificate *cert, PK11SlotInfo *slot, - CERTCertDBHandle *certDb, SECItem *pwitem, - PRBool shroudKey, SECOidTag shroudAlg, - PRBool encryptCert, SECOidTag certEncAlg, - SECOidTag integrityAlg, void *wincx) -{ - struct inPlaceEncodeInfo outInfo; - SEC_PKCS12ExportContext *p12ecx = NULL; - SEC_PKCS12SafeInfo *keySafe, *certSafe; - SECItem *returnItem = NULL; - - if(!cert || !pwitem || !slot) { - return NULL; - } - - outInfo.error = PR_FALSE; - outInfo.outItem.data = NULL; - outInfo.outItem.len = 0; - - p12ecx = SEC_PKCS12CreateExportContext(pwfn, pwfnarg, slot, wincx); - if(!p12ecx) { - return NULL; - } - - /* set up cert safe */ - if(encryptCert) { - certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem, certEncAlg); - } else { - certSafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx); - } - if(!certSafe) { - goto loser; - } - - /* set up key safe */ - if(shroudKey) { - keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx); - } else { - keySafe = certSafe; - } - if(!keySafe) { - goto loser; - } - - /* add integrity mode */ - if(SEC_PKCS12AddPasswordIntegrity(p12ecx, pwitem, integrityAlg) - != SECSuccess) { - goto loser; - } - - /* add cert and key pair */ - if(SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert, certDb, - keySafe, NULL, shroudKey, pwitem, shroudAlg) - != SECSuccess) { - goto loser; - } - - /* encode the puppy */ - if(SEC_PKCS12Encode(p12ecx, sec_pkcs12_in_place_encoder_output, &outInfo) - != SECSuccess) { - goto loser; - } - if(outInfo.error) { - goto loser; - } - - SEC_PKCS12DestroyExportContext(p12ecx); - - returnItem = SECITEM_DupItem(&outInfo.outItem); - SECITEM_ZfreeItem(&outInfo.outItem, PR_FALSE); - - return returnItem; - -loser: - if(outInfo.outItem.data) { - SECITEM_ZfreeItem(&(outInfo.outItem), PR_TRUE); - } - - if(p12ecx) { - SEC_PKCS12DestroyExportContext(p12ecx); - } - - return NULL; -} - - diff --git a/security/nss/lib/pkcs12/p12exp.c b/security/nss/lib/pkcs12/p12exp.c deleted file mode 100644 index b9ae89241..000000000 --- a/security/nss/lib/pkcs12/p12exp.c +++ /dev/null @@ -1,1410 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "plarena.h" -#include "secitem.h" -#include "secoid.h" -#include "seccomon.h" -#include "secport.h" -#include "cert.h" -#include "pkcs12.h" -#include "p12local.h" -#include "secpkcs7.h" -#include "secasn1.h" -#include "secerr.h" -#include "p12plcy.h" - -/* release the memory taken up by the list of nicknames */ -static void -sec_pkcs12_destroy_nickname_list(SECItem **nicknames) -{ - int i = 0; - - if(nicknames == NULL) { - return; - } - - while(nicknames[i] != NULL) { - SECITEM_FreeItem(nicknames[i], PR_FALSE); - i++; - } - - PORT_Free(nicknames); -} - -/* release the memory taken up by the list of certificates */ -static void -sec_pkcs12_destroy_certificate_list(CERTCertificate **ref_certs) -{ - int i = 0; - - if(ref_certs == NULL) { - return; - } - - while(ref_certs[i] != NULL) { - CERT_DestroyCertificate(ref_certs[i]); - i++; - } -} - -static void -sec_pkcs12_destroy_cinfos_for_cert_bags(SEC_PKCS12CertAndCRLBag *certBag) -{ - int j = 0; - j = 0; - while(certBag->certAndCRLs[j] != NULL) { - SECOidTag certType = SECOID_FindOIDTag(&certBag->certAndCRLs[j]->BagID); - if(certType == SEC_OID_PKCS12_X509_CERT_CRL_BAG) { - SEC_PKCS12X509CertCRL *x509; - x509 = certBag->certAndCRLs[j]->value.x509; - SEC_PKCS7DestroyContentInfo(&x509->certOrCRL); - } - j++; - } -} - -/* destroy all content infos since they were not allocated in common - * pool - */ -static void -sec_pkcs12_destroy_cert_content_infos(SEC_PKCS12SafeContents *safe, - SEC_PKCS12Baggage *baggage) -{ - int i, j; - - if((safe != NULL) && (safe->contents != NULL)) { - i = 0; - while(safe->contents[i] != NULL) { - SECOidTag bagType = SECOID_FindOIDTag(&safe->contents[i]->safeBagType); - if(bagType == SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID) { - SEC_PKCS12CertAndCRLBag *certBag; - certBag = safe->contents[i]->safeContent.certAndCRLBag; - sec_pkcs12_destroy_cinfos_for_cert_bags(certBag); - } - i++; - } - } - - if((baggage != NULL) && (baggage->bags != NULL)) { - i = 0; - while(baggage->bags[i] != NULL) { - if(baggage->bags[i]->unencSecrets != NULL) { - j = 0; - while(baggage->bags[i]->unencSecrets[j] != NULL) { - SECOidTag bagType; - bagType = SECOID_FindOIDTag(&baggage->bags[i]->unencSecrets[j]->safeBagType); - if(bagType == SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID) { - SEC_PKCS12CertAndCRLBag *certBag; - certBag = baggage->bags[i]->unencSecrets[j]->safeContent.certAndCRLBag; - sec_pkcs12_destroy_cinfos_for_cert_bags(certBag); - } - j++; - } - } - i++; - } - } -} - -/* convert the nickname list from a NULL termincated Char list - * to a NULL terminated SECItem list - */ -static SECItem ** -sec_pkcs12_convert_nickname_list(char **nicknames) -{ - SECItem **nicks; - int i, j; - PRBool error = PR_FALSE; - - if(nicknames == NULL) { - return NULL; - } - - i = j = 0; - while(nicknames[i] != NULL) { - i++; - } - - /* allocate the space and copy the data */ - nicks = (SECItem **)PORT_ZAlloc(sizeof(SECItem *) * (i + 1)); - if(nicks != NULL) { - for(j = 0; ((j < i) && (error == PR_FALSE)); j++) { - nicks[j] = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(nicks[j] != NULL) { - nicks[j]->data = - (unsigned char *)PORT_ZAlloc(PORT_Strlen(nicknames[j])+1); - if(nicks[j]->data != NULL) { - nicks[j]->len = PORT_Strlen(nicknames[j]); - PORT_Memcpy(nicks[j]->data, nicknames[j], nicks[j]->len); - nicks[j]->data[nicks[j]->len] = 0; - } else { - error = PR_TRUE; - } - } else { - error = PR_TRUE; - } - } - } - - if(error == PR_TRUE) { - for(i = 0; i < j; i++) { - SECITEM_FreeItem(nicks[i], PR_TRUE); - } - PORT_Free(nicks); - nicks = NULL; - } - - return nicks; -} - -/* package the certificate add_cert into PKCS12 structures, - * retrieve the certificate chain for the cert and return - * the packaged contents. - * poolp -- common memory pool; - * add_cert -- certificate to package up - * nickname for the certificate - * a return of NULL indicates an error - */ -static SEC_PKCS12CertAndCRL * -sec_pkcs12_get_cert(PRArenaPool *poolp, - CERTCertificate *add_cert, - SECItem *nickname) -{ - SEC_PKCS12CertAndCRL *cert; - SEC_PKCS7ContentInfo *cinfo; - SGNDigestInfo *t_di; - void *mark; - SECStatus rv; - - if((poolp == NULL) || (add_cert == NULL) || (nickname == NULL)) { - return NULL; - } - mark = PORT_ArenaMark(poolp); - - cert = sec_pkcs12_new_cert_crl(poolp, SEC_OID_PKCS12_X509_CERT_CRL_BAG); - if(cert != NULL) { - - /* copy the nickname */ - rv = SECITEM_CopyItem(poolp, &cert->nickname, nickname); - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - cert = NULL; - } else { - - /* package the certificate and cert chain into a NULL signer - * PKCS 7 SignedData content Info and prepare it for encoding - * since we cannot use DER_ANY_TEMPLATE - */ - cinfo = SEC_PKCS7CreateCertsOnly(add_cert, PR_TRUE, NULL); - rv = SEC_PKCS7PrepareForEncode(cinfo, NULL, NULL, NULL); - - /* thumbprint the certificate */ - if((cinfo != NULL) && (rv == SECSuccess)) - { - PORT_Memcpy(&cert->value.x509->certOrCRL, cinfo, sizeof(*cinfo)); - t_di = sec_pkcs12_compute_thumbprint(&add_cert->derCert); - if(t_di != NULL) - { - /* test */ - rv = SGN_CopyDigestInfo(poolp, &cert->value.x509->thumbprint, - t_di); - if(rv != SECSuccess) { - cert = NULL; - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - SGN_DestroyDigestInfo(t_di); - } - else - cert = NULL; - } - } - } - - if (cert == NULL) { - PORT_ArenaRelease(poolp, mark); - } else { - PORT_ArenaUnmark(poolp, mark); - } - - return cert; -} - -/* package the private key associated with the certificate and - * return the appropriate PKCS 12 structure - * poolp common memory pool - * nickname key nickname - * cert -- cert to look up - * wincx -- window handle - * an error is indicated by a return of NULL - */ -static SEC_PKCS12PrivateKey * -sec_pkcs12_get_private_key(PRArenaPool *poolp, - SECItem *nickname, - CERTCertificate *cert, - void *wincx) -{ - SECKEYPrivateKeyInfo *pki; - SEC_PKCS12PrivateKey *pk; - SECStatus rv; - void *mark; - - if((poolp == NULL) || (nickname == NULL)) { - return NULL; - } - - mark = PORT_ArenaMark(poolp); - - /* retrieve key from the data base */ - pki = PK11_ExportPrivateKeyInfo(nickname, cert, wincx); - if(pki == NULL) { - PORT_ArenaRelease(poolp, mark); - PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY); - return NULL; - } - - pk = (SEC_PKCS12PrivateKey *)PORT_ArenaZAlloc(poolp, - sizeof(SEC_PKCS12PrivateKey)); - if(pk != NULL) { - rv = sec_pkcs12_init_pvk_data(poolp, &pk->pvkData); - - if(rv == SECSuccess) { - /* copy the key into poolp memory space */ - rv = SECKEY_CopyPrivateKeyInfo(poolp, &pk->pkcs8data, pki); - if(rv == SECSuccess) { - rv = SECITEM_CopyItem(poolp, &pk->pvkData.nickname, nickname); - } - } - - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - pk = NULL; - } - } else { - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - - /* destroy private key, zeroing out data */ - SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE); - if (pk == NULL) { - PORT_ArenaRelease(poolp, mark); - } else { - PORT_ArenaUnmark(poolp, mark); - } - - return pk; -} - -/* get a shrouded key item associated with a certificate - * return the appropriate PKCS 12 structure - * poolp common memory pool - * nickname key nickname - * cert -- cert to look up - * wincx -- window handle - * an error is indicated by a return of NULL - */ -static SEC_PKCS12ESPVKItem * -sec_pkcs12_get_shrouded_key(PRArenaPool *poolp, - SECItem *nickname, - CERTCertificate *cert, - SECOidTag algorithm, - SECItem *pwitem, - PKCS12UnicodeConvertFunction unicodeFn, - void *wincx) -{ - SECKEYEncryptedPrivateKeyInfo *epki; - SEC_PKCS12ESPVKItem *pk; - void *mark; - SECStatus rv; - PK11SlotInfo *slot = NULL; - PRBool swapUnicodeBytes = PR_FALSE; - -#ifdef IS_LITTLE_ENDIAN - swapUnicodeBytes = PR_TRUE; -#endif - - if((poolp == NULL) || (nickname == NULL)) - return NULL; - - mark = PORT_ArenaMark(poolp); - - /* use internal key slot */ - slot = PK11_GetInternalKeySlot(); - - /* retrieve encrypted prviate key */ - epki = PK11_ExportEncryptedPrivateKeyInfo(slot, algorithm, pwitem, - nickname, cert, 1, 0, NULL); - PK11_FreeSlot(slot); - if(epki == NULL) { - PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY); - PORT_ArenaRelease(poolp, mark); - return NULL; - } - - /* create a private key and store the data into the poolp memory space */ - pk = sec_pkcs12_create_espvk(poolp, SEC_OID_PKCS12_PKCS8_KEY_SHROUDING); - if(pk != NULL) { - rv = sec_pkcs12_init_pvk_data(poolp, &pk->espvkData); - rv = SECITEM_CopyItem(poolp, &pk->espvkData.nickname, nickname); - pk->espvkCipherText.pkcs8KeyShroud = - (SECKEYEncryptedPrivateKeyInfo *)PORT_ArenaZAlloc(poolp, - sizeof(SECKEYEncryptedPrivateKeyInfo)); - if((pk->espvkCipherText.pkcs8KeyShroud != NULL) && (rv == SECSuccess)) { - rv = SECKEY_CopyEncryptedPrivateKeyInfo(poolp, - pk->espvkCipherText.pkcs8KeyShroud, epki); - if(rv == SECSuccess) { - rv = (*unicodeFn)(poolp, &pk->espvkData.uniNickName, nickname, - PR_TRUE, swapUnicodeBytes); - } - } - - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - pk = NULL; - } - } - - SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE); - if(pk == NULL) { - PORT_ArenaRelease(poolp, mark); - } else { - PORT_ArenaUnmark(poolp, mark); - } - - return pk; -} - -/* add a thumbprint to a private key associated certs list - * pvk is the area where the list is stored - * thumb is the thumbprint to copy - * a return of SECFailure indicates an error - */ -static SECStatus -sec_pkcs12_add_thumbprint(SEC_PKCS12PVKSupportingData *pvk, - SGNDigestInfo *thumb) -{ - SGNDigestInfo **thumb_list = NULL; - int nthumbs, size; - void *mark, *dummy; - SECStatus rv = SECFailure; - - if((pvk == NULL) || (thumb == NULL)) { - return SECFailure; - } - - mark = PORT_ArenaMark(pvk->poolp); - - thumb_list = pvk->assocCerts; - nthumbs = pvk->nThumbs; - - /* allocate list space needed -- either growing or allocating - * list must be NULL terminated - */ - size = sizeof(SGNDigestInfo *); - dummy = PORT_ArenaGrow(pvk->poolp, thumb_list, (size * (nthumbs + 1)), - (size * (nthumbs + 2))); - thumb_list = dummy; - if(dummy != NULL) { - thumb_list[nthumbs] = (SGNDigestInfo *)PORT_ArenaZAlloc(pvk->poolp, - sizeof(SGNDigestInfo)); - if(thumb_list[nthumbs] != NULL) { - SGN_CopyDigestInfo(pvk->poolp, thumb_list[nthumbs], thumb); - nthumbs += 1; - thumb_list[nthumbs] = 0; - } else { - dummy = NULL; - } - } - - if(dummy == NULL) { - PORT_ArenaRelease(pvk->poolp, mark); - return SECFailure; - } - - pvk->assocCerts = thumb_list; - pvk->nThumbs = nthumbs; - - PORT_ArenaUnmark(pvk->poolp, mark); - return SECSuccess; -} - -/* search the list of shrouded keys in the baggage for the desired - * name. return a pointer to the item. a return of NULL indicates - * that no match was present or that an error occurred. - */ -static SEC_PKCS12ESPVKItem * -sec_pkcs12_get_espvk_by_name(SEC_PKCS12Baggage *luggage, - SECItem *name) -{ - PRBool found = PR_FALSE; - SEC_PKCS12ESPVKItem *espvk = NULL; - int i, j; - SECComparison rv = SECEqual; - SECItem *t_name; - SEC_PKCS12BaggageItem *bag; - - if((luggage == NULL) || (name == NULL)) { - return NULL; - } - - i = 0; - while((found == PR_FALSE) && (i < luggage->luggage_size)) { - j = 0; - bag = luggage->bags[i]; - while((found == PR_FALSE) && (j < bag->nEspvks)) { - espvk = bag->espvks[j]; - if(espvk->poolp == NULL) { - espvk->poolp = luggage->poolp; - } - t_name = SECITEM_DupItem(&espvk->espvkData.nickname); - if(t_name != NULL) { - rv = SECITEM_CompareItem(name, t_name); - if(rv == SECEqual) { - found = PR_TRUE; - } - SECITEM_FreeItem(t_name, PR_TRUE); - } else { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - j++; - } - i++; - } - - if(found != PR_TRUE) { - PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME); - return NULL; - } - - return espvk; -} - -/* locates a certificate and copies the thumbprint to the - * appropriate private key - */ -static SECStatus -sec_pkcs12_propagate_thumbprints(SECItem **nicknames, - CERTCertificate **ref_certs, - SEC_PKCS12SafeContents *safe, - SEC_PKCS12Baggage *baggage) -{ - SEC_PKCS12CertAndCRL *cert; - SEC_PKCS12PrivateKey *key; - SEC_PKCS12ESPVKItem *espvk; - int i; - PRBool error = PR_FALSE; - SECStatus rv = SECFailure; - - if((nicknames == NULL) || (safe == NULL)) { - return SECFailure; - } - - i = 0; - while((nicknames[i] != NULL) && (error == PR_FALSE)) { - /* process all certs */ - cert = (SEC_PKCS12CertAndCRL *)sec_pkcs12_find_object(safe, baggage, - SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID, - nicknames[i], NULL); - if(cert != NULL) { - /* locate key and copy thumbprint */ - key = (SEC_PKCS12PrivateKey *)sec_pkcs12_find_object(safe, baggage, - SEC_OID_PKCS12_KEY_BAG_ID, - nicknames[i], NULL); - if(key != NULL) { - key->pvkData.poolp = key->poolp; - rv = sec_pkcs12_add_thumbprint(&key->pvkData, - &cert->value.x509->thumbprint); - if(rv == SECFailure) - error = PR_TRUE; /* XXX Set error? */ - } - - /* look in the baggage as well...*/ - if((baggage != NULL) && (error == PR_FALSE)) { - espvk = sec_pkcs12_get_espvk_by_name(baggage, nicknames[i]); - if(espvk != NULL) { - espvk->espvkData.poolp = espvk->poolp; - rv = sec_pkcs12_add_thumbprint(&espvk->espvkData, - &cert->value.x509->thumbprint); - if(rv == SECFailure) - error = PR_TRUE; /* XXX Set error? */ - } - } - } - i++; - } - - if(error == PR_TRUE) { - return SECFailure; - } - - return SECSuccess; -} - -/* append a safe bag to the end of the safe contents list */ -SECStatus -sec_pkcs12_append_safe_bag(SEC_PKCS12SafeContents *safe, - SEC_PKCS12SafeBag *bag) -{ - int size; - void *mark = NULL, *dummy = NULL; - - if((bag == NULL) || (safe == NULL)) - return SECFailure; - - mark = PORT_ArenaMark(safe->poolp); - - size = (safe->safe_size * sizeof(SEC_PKCS12SafeBag *)); - - if(safe->safe_size > 0) { - dummy = (SEC_PKCS12SafeBag **)PORT_ArenaGrow(safe->poolp, - safe->contents, - size, - (size + sizeof(SEC_PKCS12SafeBag *))); - safe->contents = dummy; - } else { - safe->contents = (SEC_PKCS12SafeBag **)PORT_ArenaZAlloc(safe->poolp, - (2 * sizeof(SEC_PKCS12SafeBag *))); - dummy = safe->contents; - } - - if(dummy == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - safe->contents[safe->safe_size] = bag; - safe->safe_size++; - safe->contents[safe->safe_size] = NULL; - - PORT_ArenaUnmark(safe->poolp, mark); - return SECSuccess; - -loser: - PORT_ArenaRelease(safe->poolp, mark); - return SECFailure; -} - -/* append a certificate onto the end of a cert bag */ -static SECStatus -sec_pkcs12_append_cert_to_bag(PRArenaPool *arena, - SEC_PKCS12SafeBag *safebag, - CERTCertificate *cert, - SECItem *nickname) -{ - int size; - void *dummy = NULL, *mark = NULL; - SEC_PKCS12CertAndCRL *p12cert; - SEC_PKCS12CertAndCRLBag *bag; - - if((arena == NULL) || (safebag == NULL) || - (cert == NULL) || (nickname == NULL)) { - return SECFailure; - } - - bag = safebag->safeContent.certAndCRLBag; - if(bag == NULL) { - return SECFailure; - } - - mark = PORT_ArenaMark(arena); - - p12cert = sec_pkcs12_get_cert(arena, cert, nickname); - if(p12cert == NULL) { - PORT_ArenaRelease(bag->poolp, mark); - return SECFailure; - } - - size = bag->bag_size * sizeof(SEC_PKCS12CertAndCRL *); - if(bag->bag_size > 0) { - dummy = (SEC_PKCS12CertAndCRL **)PORT_ArenaGrow(bag->poolp, - bag->certAndCRLs, size, size + sizeof(SEC_PKCS12CertAndCRL *)); - bag->certAndCRLs = dummy; - } else { - bag->certAndCRLs = (SEC_PKCS12CertAndCRL **)PORT_ArenaZAlloc(bag->poolp, - (2 * sizeof(SEC_PKCS12CertAndCRL *))); - dummy = bag->certAndCRLs; - } - - if(dummy == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - bag->certAndCRLs[bag->bag_size] = p12cert; - bag->bag_size++; - bag->certAndCRLs[bag->bag_size] = NULL; - - PORT_ArenaUnmark(bag->poolp, mark); - return SECSuccess; - -loser: - PORT_ArenaRelease(bag->poolp, mark); - return SECFailure; -} - -/* append a key onto the end of a list of keys in a key bag */ -SECStatus -sec_pkcs12_append_key_to_bag(SEC_PKCS12SafeBag *safebag, - SEC_PKCS12PrivateKey *pk) -{ - void *mark, *dummy; - SEC_PKCS12PrivateKeyBag *bag; - int size; - - if((safebag == NULL) || (pk == NULL)) - return SECFailure; - - bag = safebag->safeContent.keyBag; - if(bag == NULL) { - return SECFailure; - } - - mark = PORT_ArenaMark(bag->poolp); - - size = (bag->bag_size * sizeof(SEC_PKCS12PrivateKey *)); - - if(bag->bag_size > 0) { - dummy = (SEC_PKCS12PrivateKey **)PORT_ArenaGrow(bag->poolp, - bag->privateKeys, - size, - size + sizeof(SEC_PKCS12PrivateKey *)); - bag->privateKeys = dummy; - } else { - bag->privateKeys = (SEC_PKCS12PrivateKey **)PORT_ArenaZAlloc(bag->poolp, - (2 * sizeof(SEC_PKCS12PrivateKey *))); - dummy = bag->privateKeys; - } - - if(dummy == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - bag->privateKeys[bag->bag_size] = pk; - bag->bag_size++; - bag->privateKeys[bag->bag_size] = NULL; - - PORT_ArenaUnmark(bag->poolp, mark); - return SECSuccess; - -loser: - /* XXX Free memory? */ - PORT_ArenaRelease(bag->poolp, mark); - return SECFailure; -} - -/* append a safe bag to the baggage area */ -static SECStatus -sec_pkcs12_append_unshrouded_bag(SEC_PKCS12BaggageItem *bag, - SEC_PKCS12SafeBag *u_bag) -{ - int size; - void *mark = NULL, *dummy = NULL; - - if((bag == NULL) || (u_bag == NULL)) - return SECFailure; - - mark = PORT_ArenaMark(bag->poolp); - - /* dump things into the first bag */ - size = (bag->nSecrets + 1) * sizeof(SEC_PKCS12SafeBag *); - dummy = PORT_ArenaGrow(bag->poolp, - bag->unencSecrets, size, - size + sizeof(SEC_PKCS12SafeBag *)); - bag->unencSecrets = dummy; - if(dummy == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - bag->unencSecrets[bag->nSecrets] = u_bag; - bag->nSecrets++; - bag->unencSecrets[bag->nSecrets] = NULL; - - PORT_ArenaUnmark(bag->poolp, mark); - return SECSuccess; - -loser: - PORT_ArenaRelease(bag->poolp, mark); - return SECFailure; -} - -/* gather up all certificates and keys and package them up - * in the safe, baggage, or both. - * nicknames is the list of nicknames and corresponding certs in ref_certs - * ref_certs a null terminated list of certificates - * rSafe, rBaggage -- return areas for safe and baggage - * shroud_keys -- store keys externally - * pwitem -- password for computing integrity mac and encrypting contents - * wincx -- window handle - * - * if a failure occurs, an error is set and SECFailure returned. - */ -static SECStatus -sec_pkcs12_package_certs_and_keys(SECItem **nicknames, - CERTCertificate **ref_certs, - PRBool unencryptedCerts, - SEC_PKCS12SafeContents **rSafe, - SEC_PKCS12Baggage **rBaggage, - PRBool shroud_keys, - SECOidTag shroud_alg, - SECItem *pwitem, - PKCS12UnicodeConvertFunction unicodeFn, - void *wincx) -{ - PRArenaPool *permArena; - SEC_PKCS12SafeContents *safe = NULL; - SEC_PKCS12Baggage *baggage = NULL; - - SECStatus rv = SECFailure; - PRBool problem = PR_FALSE; - - SEC_PKCS12ESPVKItem *espvk = NULL; - SEC_PKCS12PrivateKey *pk = NULL; - CERTCertificate *add_cert = NULL; - SEC_PKCS12SafeBag *certbag = NULL, *keybag = NULL; - SEC_PKCS12BaggageItem *external_bag = NULL; - int ncerts = 0, nkeys = 0; - int i; - - if((nicknames == NULL) || (rSafe == NULL) || (rBaggage == NULL)) { - return SECFailure; - } - - *rBaggage = baggage; - *rSafe = safe; - - permArena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if(permArena == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - - /* allocate structures */ - safe = sec_pkcs12_create_safe_contents(permArena); - if(safe == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - rv = SECFailure; - goto loser; - } - - certbag = sec_pkcs12_create_safe_bag(permArena, - SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID); - if(certbag == NULL) { - rv = SECFailure; - goto loser; - } - - if(shroud_keys != PR_TRUE) { - keybag = sec_pkcs12_create_safe_bag(permArena, - SEC_OID_PKCS12_KEY_BAG_ID); - if(keybag == NULL) { - rv = SECFailure; - goto loser; - } - } - - if((shroud_keys == PR_TRUE) || (unencryptedCerts == PR_TRUE)) { - baggage = sec_pkcs12_create_baggage(permArena); - if(baggage == NULL) { - rv = SECFailure; - goto loser; - } - external_bag = sec_pkcs12_create_external_bag(baggage); - } - - /* package keys and certs */ - i = 0; - while((nicknames[i] != NULL) && (problem == PR_FALSE)) { - if(ref_certs[i] != NULL) { - /* append cert to bag o certs */ - rv = sec_pkcs12_append_cert_to_bag(permArena, certbag, - ref_certs[i], - nicknames[i]); - if(rv == SECFailure) { - problem = PR_FALSE; - } else { - ncerts++; - } - - if(rv == SECSuccess) { - /* package up them keys */ - if(shroud_keys == PR_TRUE) { - espvk = sec_pkcs12_get_shrouded_key(permArena, - nicknames[i], - ref_certs[i], - shroud_alg, - pwitem, unicodeFn, - wincx); - if(espvk != NULL) { - rv = sec_pkcs12_append_shrouded_key(external_bag, espvk); - SECITEM_CopyItem(permArena, &espvk->derCert, - &ref_certs[i]->derCert); - } else { - rv = SECFailure; - } - } else { - pk = sec_pkcs12_get_private_key(permArena, nicknames[i], - ref_certs[i], wincx); - if(pk != NULL) { - rv = sec_pkcs12_append_key_to_bag(keybag, pk); - SECITEM_CopyItem(permArena, &espvk->derCert, - &ref_certs[i]->derCert); - } else { - rv = SECFailure; - } - } - - if(rv == SECFailure) { - problem = PR_TRUE; - } else { - nkeys++; - } - } - } else { - /* handle only keys here ? */ - problem = PR_TRUE; - } - i++; - } - - /* let success fall through */ -loser: - if(problem == PR_FALSE) { - /* if we have certs, we want to append the cert bag to the - * appropriate area - */ - if(ncerts > 0) { - if(unencryptedCerts != PR_TRUE) { - rv = sec_pkcs12_append_safe_bag(safe, certbag); - } else { - rv = sec_pkcs12_append_unshrouded_bag(external_bag, certbag); - } - } else { - rv = SECSuccess; - } - - /* append key bag, if they are stored in safe contents */ - if((rv == SECSuccess) && (shroud_keys == PR_FALSE) && (nkeys > 0)) { - rv = sec_pkcs12_append_safe_bag(safe, keybag); - } - } else { - rv = SECFailure; - } - - /* if baggage not used, NULLify it */ - if((shroud_keys == PR_TRUE) || (unencryptedCerts == PR_TRUE)) { - if(((unencryptedCerts == PR_TRUE) && (ncerts == 0)) && - ((shroud_keys == PR_TRUE) && (nkeys == 0))) - baggage = NULL; - } else { - baggage = NULL; - } - - if((problem == PR_TRUE) || (rv == SECFailure)) { - PORT_FreeArena(permArena, PR_TRUE); - rv = SECFailure; - baggage = NULL; - safe = NULL; - } - - *rBaggage = baggage; - *rSafe = safe; - - return rv; -} - -/* DER encode the safe contents and return a SECItem. if an error - * occurs, NULL is returned. - */ -static SECItem * -sec_pkcs12_encode_safe_contents(SEC_PKCS12SafeContents *safe) -{ - SECItem *dsafe = NULL, *tsafe; - void *dummy = NULL; - PRArenaPool *arena; - - if(safe == NULL) { - return NULL; - } - -/* rv = sec_pkcs12_prepare_for_der_code_safe(safe, PR_TRUE); - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - }*/ - - arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if(arena == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - tsafe = (SECItem *)PORT_ArenaZAlloc(arena, sizeof(SECItem)); - if(tsafe != NULL) { - dummy = SEC_ASN1EncodeItem(arena, tsafe, safe, - SEC_PKCS12SafeContentsTemplate); - if(dummy != NULL) { - dsafe = SECITEM_DupItem(tsafe); - } else { - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - } else { - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - - PORT_FreeArena(arena, PR_TRUE); - - return dsafe; -} - -/* prepare the authenicated safe for encoding and encode it. - * baggage is copied to the appropriate area, safe is encoded and - * encrypted. the version and transport mode are set on the asafe. - * the whole ball of wax is then der encoded and packaged up into - * data content info - * safe -- container of certs and keys, is encrypted. - * baggage -- container of certs and keys, keys assumed to be encrypted by - * another method, certs are in the clear - * algorithm -- algorithm by which to encrypt safe - * pwitem -- password for encryption - * wincx - window handle - * - * return of NULL is an error condition. - */ -static SEC_PKCS7ContentInfo * -sec_pkcs12_get_auth_safe(SEC_PKCS12SafeContents *safe, - SEC_PKCS12Baggage *baggage, - SECOidTag algorithm, - SECItem *pwitem, - PKCS12UnicodeConvertFunction unicodeFn, - void *wincx) -{ - SECItem *src = NULL, *dest = NULL, *psalt = NULL; - PRArenaPool *poolp; - SEC_PKCS12AuthenticatedSafe *asafe; - SEC_PKCS7ContentInfo *safe_cinfo = NULL; - SEC_PKCS7ContentInfo *asafe_cinfo = NULL; - void *dummy; - SECStatus rv = SECSuccess; - PRBool swapUnicodeBytes = PR_FALSE; - -#ifdef IS_LITTLE_ENDIAN - swapUnicodeBytes = PR_TRUE; -#endif - - if(((safe != NULL) && (pwitem == NULL)) && (baggage == NULL)) - return NULL; - - poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if(poolp == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - /* prepare authenticated safe for encode */ - asafe = sec_pkcs12_new_asafe(poolp); - if(asafe != NULL) { - - /* set version */ - dummy = SEC_ASN1EncodeInteger(asafe->poolp, &asafe->version, - SEC_PKCS12_PFX_VERSION); - if(dummy == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - rv = SECFailure; - goto loser; - } - - /* generate the privacy salt used to create virtual pwd */ - psalt = sec_pkcs12_generate_salt(); - if(psalt != NULL) { - rv = SECITEM_CopyItem(asafe->poolp, &asafe->privacySalt, - psalt); - if(rv == SECSuccess) { - asafe->privacySalt.len *= 8; - } - else { - SECITEM_ZfreeItem(psalt, PR_TRUE); - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - } - - if((psalt == NULL) || (rv == SECFailure)) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - rv = SECFailure; - goto loser; - } - - /* package up safe contents */ - if(safe != NULL) - { - safe_cinfo = SEC_PKCS7CreateEncryptedData(algorithm, NULL, wincx); - if((safe_cinfo != NULL) && (safe->safe_size > 0)) { - /* encode the safe and encrypt the contents of the - * content info - */ - src = sec_pkcs12_encode_safe_contents(safe); - - if(src != NULL) { - rv = SEC_PKCS7SetContent(safe_cinfo, (char *)src->data, src->len); - SECITEM_ZfreeItem(src, PR_TRUE); - if(rv == SECSuccess) { - SECItem *vpwd; - vpwd = sec_pkcs12_create_virtual_password(pwitem, psalt, - unicodeFn, swapUnicodeBytes); - if(vpwd != NULL) { - rv = SEC_PKCS7EncryptContents(NULL, safe_cinfo, - vpwd, wincx); - SECITEM_ZfreeItem(vpwd, PR_TRUE); - } else { - rv = SECFailure; - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - } else { - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - } else { - rv = SECFailure; - } - } else if(safe->safe_size > 0) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } else { - /* case where there is NULL content in the safe contents */ - rv = SEC_PKCS7SetContent(safe_cinfo, NULL, 0); - if(rv != SECFailure) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - } - - if(rv != SECSuccess) { - SEC_PKCS7DestroyContentInfo(safe_cinfo); - safe_cinfo = NULL; - goto loser; - } - - asafe->safe = safe_cinfo; - /* - PORT_Memcpy(&asafe->safe, safe_cinfo, sizeof(*safe_cinfo)); - */ - } - - /* copy the baggage to the authenticated safe baggage if present */ - if(baggage != NULL) { - PORT_Memcpy(&asafe->baggage, baggage, sizeof(*baggage)); - } - - /* encode authenticated safe and store it in a Data content info */ - dest = (SECItem *)PORT_ArenaZAlloc(poolp, sizeof(SECItem)); - if(dest != NULL) { - dummy = SEC_ASN1EncodeItem(poolp, dest, asafe, - SEC_PKCS12AuthenticatedSafeTemplate); - if(dummy != NULL) { - asafe_cinfo = SEC_PKCS7CreateData(); - if(asafe_cinfo != NULL) { - rv = SEC_PKCS7SetContent(asafe_cinfo, - (char *)dest->data, - dest->len); - if(rv != SECSuccess) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - SEC_PKCS7DestroyContentInfo(asafe_cinfo); - asafe_cinfo = NULL; - } - } - } else { - PORT_SetError(SEC_ERROR_NO_MEMORY); - rv = SECFailure; - } - } - } - -loser: - PORT_FreeArena(poolp, PR_TRUE); - if(safe_cinfo != NULL) { - SEC_PKCS7DestroyContentInfo(safe_cinfo); - } - if(psalt != NULL) { - SECITEM_ZfreeItem(psalt, PR_TRUE); - } - - if(rv == SECFailure) { - return NULL; - } - - return asafe_cinfo; -} - -/* generates the PFX and computes the mac on the authenticated safe - * NULL implies an error - */ -static SEC_PKCS12PFXItem * -sec_pkcs12_get_pfx(SEC_PKCS7ContentInfo *cinfo, - PRBool do_mac, - SECItem *pwitem, PKCS12UnicodeConvertFunction unicodeFn) -{ - SECItem *dest = NULL, *mac = NULL, *salt = NULL, *key = NULL; - SEC_PKCS12PFXItem *pfx; - SECStatus rv = SECFailure; - SGNDigestInfo *di; - SECItem *vpwd; - PRBool swapUnicodeBytes = PR_FALSE; - -#ifdef IS_LITTLE_ENDIAN - swapUnicodeBytes = PR_TRUE; -#endif - - if((cinfo == NULL) || ((do_mac == PR_TRUE) && (pwitem == NULL))) { - return NULL; - } - - /* allocate new pfx structure */ - pfx = sec_pkcs12_new_pfx(); - if(pfx == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - PORT_Memcpy(&pfx->authSafe, cinfo, sizeof(*cinfo)); - if(do_mac == PR_TRUE) { - - /* salt for computing mac */ - salt = sec_pkcs12_generate_salt(); - if(salt != NULL) { - rv = SECITEM_CopyItem(pfx->poolp, &pfx->macData.macSalt, salt); - pfx->macData.macSalt.len *= 8; - - vpwd = sec_pkcs12_create_virtual_password(pwitem, salt, - unicodeFn, swapUnicodeBytes); - if(vpwd == NULL) { - rv = SECFailure; - key = NULL; - } else { - key = sec_pkcs12_generate_key_from_password(SEC_OID_SHA1, - salt, vpwd); - SECITEM_ZfreeItem(vpwd, PR_TRUE); - } - - if((key != NULL) && (rv == SECSuccess)) { - dest = SEC_PKCS7GetContent(cinfo); - if(dest != NULL) { - - /* compute mac on data -- for password integrity mode */ - mac = sec_pkcs12_generate_mac(key, dest, PR_FALSE); - if(mac != NULL) { - di = SGN_CreateDigestInfo(SEC_OID_SHA1, - mac->data, mac->len); - if(di != NULL) { - rv = SGN_CopyDigestInfo(pfx->poolp, - &pfx->macData.safeMac, di); - SGN_DestroyDigestInfo(di); - } else { - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - SECITEM_ZfreeItem(mac, PR_TRUE); - } - } else { - rv = SECFailure; - } - } else { - PORT_SetError(SEC_ERROR_NO_MEMORY); - rv = SECFailure; - } - - if(key != NULL) { - SECITEM_ZfreeItem(key, PR_TRUE); - } - SECITEM_ZfreeItem(salt, PR_TRUE); - } - } - - if(rv == SECFailure) { - SEC_PKCS12DestroyPFX(pfx); - pfx = NULL; - } - - return pfx; -} - -/* der encode the pfx */ -static SECItem * -sec_pkcs12_encode_pfx(SEC_PKCS12PFXItem *pfx) -{ - SECItem *dest; - void *dummy; - - if(pfx == NULL) { - return NULL; - } - - dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(dest == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - dummy = SEC_ASN1EncodeItem(NULL, dest, pfx, SEC_PKCS12PFXItemTemplate); - if(dummy == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - SECITEM_ZfreeItem(dest, PR_TRUE); - dest = NULL; - } - - return dest; -} - -SECItem * -SEC_PKCS12GetPFX(char **nicknames, - CERTCertificate **ref_certs, - PRBool shroud_keys, - SEC_PKCS5GetPBEPassword pbef, - void *pbearg, - PKCS12UnicodeConvertFunction unicodeFn, - void *wincx) -{ - SECItem **nicks = NULL; - SEC_PKCS12PFXItem *pfx = NULL; - SEC_PKCS12Baggage *baggage = NULL; - SEC_PKCS12SafeContents *safe = NULL; - SEC_PKCS7ContentInfo *cinfo = NULL; - SECStatus rv = SECFailure; - SECItem *dest = NULL, *pwitem = NULL; - PRBool problem = PR_FALSE; - PRBool unencryptedCerts; - SECOidTag shroud_alg, safe_alg; - - /* how should we encrypt certs ? */ - unencryptedCerts = !SEC_PKCS12IsEncryptionAllowed(); - if(!unencryptedCerts) { - safe_alg = SEC_PKCS12GetPreferredEncryptionAlgorithm(); - if(safe_alg == SEC_OID_UNKNOWN) { - safe_alg = SEC_PKCS12GetStrongestAllowedAlgorithm(); - } - if(safe_alg == SEC_OID_UNKNOWN) { - unencryptedCerts = PR_TRUE; - /* for export where no encryption is allowed, we still need - * to encrypt the NULL contents per the spec. encrypted info - * is known plaintext, so it shouldn't be a problem. - */ - safe_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; - } - } else { - /* for export where no encryption is allowed, we still need - * to encrypt the NULL contents per the spec. encrypted info - * is known plaintext, so it shouldn't be a problem. - */ - safe_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; - } - - /* keys are always stored with triple DES */ - shroud_alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC; - - /* check for FIPS, if so, do not encrypt certs */ - if(PK11_IsFIPS() && !unencryptedCerts) { - unencryptedCerts = PR_TRUE; - } - - if((nicknames == NULL) || (pbef == NULL) || (ref_certs == NULL)) { - problem = PR_TRUE; - goto loser; - } - - - /* get password */ - pwitem = (*pbef)(pbearg); - if(pwitem == NULL) { - problem = PR_TRUE; - goto loser; - } - nicks = sec_pkcs12_convert_nickname_list(nicknames); - - /* get safe and baggage */ - rv = sec_pkcs12_package_certs_and_keys(nicks, ref_certs, unencryptedCerts, - &safe, &baggage, shroud_keys, - shroud_alg, pwitem, unicodeFn, wincx); - if(rv == SECFailure) { - problem = PR_TRUE; - } - - if((safe != NULL) && (problem == PR_FALSE)) { - /* copy thumbprints */ - rv = sec_pkcs12_propagate_thumbprints(nicks, ref_certs, safe, baggage); - - /* package everything up into AuthenticatedSafe */ - cinfo = sec_pkcs12_get_auth_safe(safe, baggage, - safe_alg, pwitem, unicodeFn, wincx); - - sec_pkcs12_destroy_cert_content_infos(safe, baggage); - - /* get the pfx and mac it */ - if(cinfo != NULL) { - pfx = sec_pkcs12_get_pfx(cinfo, PR_TRUE, pwitem, unicodeFn); - if(pfx != NULL) { - dest = sec_pkcs12_encode_pfx(pfx); - SEC_PKCS12DestroyPFX(pfx); - } - SEC_PKCS7DestroyContentInfo(cinfo); - } - - if(safe != NULL) { - PORT_FreeArena(safe->poolp, PR_TRUE); - } - } else { - if(safe != NULL) { - PORT_FreeArena(safe->poolp, PR_TRUE); - } - } - -loser: - if(nicks != NULL) { - sec_pkcs12_destroy_nickname_list(nicks); - } - - if(ref_certs != NULL) { - sec_pkcs12_destroy_certificate_list(ref_certs); - } - - if(pwitem != NULL) { - SECITEM_ZfreeItem(pwitem, PR_TRUE); - } - - if(problem == PR_TRUE) { - dest = NULL; - } - - return dest; -} diff --git a/security/nss/lib/pkcs12/p12local.c b/security/nss/lib/pkcs12/p12local.c deleted file mode 100644 index 346038333..000000000 --- a/security/nss/lib/pkcs12/p12local.c +++ /dev/null @@ -1,1371 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nssrenam.h" -#include "pkcs12.h" -#include "secpkcs7.h" -#include "secasn1.h" -#include "seccomon.h" -#include "secoid.h" -#include "sechash.h" -#include "secitem.h" -#include "secerr.h" -#include "pk11func.h" -#include "p12local.h" -#include "p12.h" - -#define SALT_LENGTH 16 - -SEC_ASN1_MKSUB(SECKEY_PrivateKeyInfoTemplate) -SEC_ASN1_MKSUB(sgn_DigestInfoTemplate) - -CK_MECHANISM_TYPE -sec_pkcs12_algtag_to_mech(SECOidTag algtag) -{ - switch (algtag) { - case SEC_OID_MD2: - return CKM_MD2_HMAC; - case SEC_OID_MD5: - return CKM_MD5_HMAC; - case SEC_OID_SHA1: - return CKM_SHA_1_HMAC; - case SEC_OID_SHA256: - return CKM_SHA256_HMAC; - case SEC_OID_SHA384: - return CKM_SHA384_HMAC; - case SEC_OID_SHA512: - return CKM_SHA512_HMAC; - default: - break; - } - return CKM_INVALID_MECHANISM; -} - -/* helper functions */ -/* returns proper bag type template based upon object type tag */ -const SEC_ASN1Template * -sec_pkcs12_choose_bag_type_old(void *src_or_dest, PRBool encoding) -{ - const SEC_ASN1Template *theTemplate; - SEC_PKCS12SafeBag *safebag; - SECOidData *oiddata; - - if (src_or_dest == NULL) { - return NULL; - } - - safebag = (SEC_PKCS12SafeBag*)src_or_dest; - - oiddata = safebag->safeBagTypeTag; - if (oiddata == NULL) { - oiddata = SECOID_FindOID(&safebag->safeBagType); - safebag->safeBagTypeTag = oiddata; - } - - switch (oiddata->offset) { - default: - theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); - break; - case SEC_OID_PKCS12_KEY_BAG_ID: - theTemplate = SEC_PointerToPKCS12KeyBagTemplate; - break; - case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID: - theTemplate = SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD; - break; - case SEC_OID_PKCS12_SECRET_BAG_ID: - theTemplate = SEC_PointerToPKCS12SecretBagTemplate; - break; - } - return theTemplate; -} - -const SEC_ASN1Template * -sec_pkcs12_choose_bag_type(void *src_or_dest, PRBool encoding) -{ - const SEC_ASN1Template *theTemplate; - SEC_PKCS12SafeBag *safebag; - SECOidData *oiddata; - - if (src_or_dest == NULL) { - return NULL; - } - - safebag = (SEC_PKCS12SafeBag*)src_or_dest; - - oiddata = safebag->safeBagTypeTag; - if (oiddata == NULL) { - oiddata = SECOID_FindOID(&safebag->safeBagType); - safebag->safeBagTypeTag = oiddata; - } - - switch (oiddata->offset) { - default: - theTemplate = SEC_ASN1_GET(SEC_AnyTemplate); - break; - case SEC_OID_PKCS12_KEY_BAG_ID: - theTemplate = SEC_PKCS12PrivateKeyBagTemplate; - break; - case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID: - theTemplate = SEC_PKCS12CertAndCRLBagTemplate; - break; - case SEC_OID_PKCS12_SECRET_BAG_ID: - theTemplate = SEC_PKCS12SecretBagTemplate; - break; - } - return theTemplate; -} - -/* returns proper cert crl template based upon type tag */ -const SEC_ASN1Template * -sec_pkcs12_choose_cert_crl_type_old(void *src_or_dest, PRBool encoding) -{ - const SEC_ASN1Template *theTemplate; - SEC_PKCS12CertAndCRL *certbag; - SECOidData *oiddata; - - if (src_or_dest == NULL) { - return NULL; - } - - certbag = (SEC_PKCS12CertAndCRL*)src_or_dest; - oiddata = certbag->BagTypeTag; - if (oiddata == NULL) { - oiddata = SECOID_FindOID(&certbag->BagID); - certbag->BagTypeTag = oiddata; - } - - switch (oiddata->offset) { - default: - theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); - break; - case SEC_OID_PKCS12_X509_CERT_CRL_BAG: - theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate_OLD; - break; - case SEC_OID_PKCS12_SDSI_CERT_BAG: - theTemplate = SEC_PointerToPKCS12SDSICertTemplate; - break; - } - return theTemplate; -} - -const SEC_ASN1Template * -sec_pkcs12_choose_cert_crl_type(void *src_or_dest, PRBool encoding) -{ - const SEC_ASN1Template *theTemplate; - SEC_PKCS12CertAndCRL *certbag; - SECOidData *oiddata; - - if (src_or_dest == NULL) { - return NULL; - } - - certbag = (SEC_PKCS12CertAndCRL*)src_or_dest; - oiddata = certbag->BagTypeTag; - if (oiddata == NULL) { - oiddata = SECOID_FindOID(&certbag->BagID); - certbag->BagTypeTag = oiddata; - } - - switch (oiddata->offset) { - default: - theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); - break; - case SEC_OID_PKCS12_X509_CERT_CRL_BAG: - theTemplate = SEC_PointerToPKCS12X509CertCRLTemplate; - break; - case SEC_OID_PKCS12_SDSI_CERT_BAG: - theTemplate = SEC_PointerToPKCS12SDSICertTemplate; - break; - } - return theTemplate; -} - -/* returns appropriate shroud template based on object type tag */ -const SEC_ASN1Template * -sec_pkcs12_choose_shroud_type(void *src_or_dest, PRBool encoding) -{ - const SEC_ASN1Template *theTemplate; - SEC_PKCS12ESPVKItem *espvk; - SECOidData *oiddata; - - if (src_or_dest == NULL) { - return NULL; - } - - espvk = (SEC_PKCS12ESPVKItem*)src_or_dest; - oiddata = espvk->espvkTag; - if (oiddata == NULL) { - oiddata = SECOID_FindOID(&espvk->espvkOID); - espvk->espvkTag = oiddata; - } - - switch (oiddata->offset) { - default: - theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); - break; - case SEC_OID_PKCS12_PKCS8_KEY_SHROUDING: - theTemplate = - SEC_ASN1_GET(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate); - break; - } - return theTemplate; -} - -/* generate SALT placing it into the character array passed in. - * it is assumed that salt_dest is an array of appropriate size - * XXX We might want to generate our own random context - */ -SECItem * -sec_pkcs12_generate_salt(void) -{ - SECItem *salt; - - salt = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(salt == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - salt->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * - SALT_LENGTH); - salt->len = SALT_LENGTH; - if(salt->data == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - SECITEM_ZfreeItem(salt, PR_TRUE); - return NULL; - } - - PK11_GenerateRandom(salt->data, salt->len); - - return salt; -} - -/* generate KEYS -- as per PKCS12 section 7. - * only used for MAC - */ -SECItem * -sec_pkcs12_generate_key_from_password(SECOidTag algorithm, - SECItem *salt, - SECItem *password) -{ - unsigned char *pre_hash=NULL; - unsigned char *hash_dest=NULL; - SECStatus res; - PRArenaPool *poolp; - SECItem *key = NULL; - int key_len = 0; - - if((salt == NULL) || (password == NULL)) { - return NULL; - } - - poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if(poolp == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; - } - - pre_hash = (unsigned char *)PORT_ArenaZAlloc(poolp, sizeof(char) * - (salt->len+password->len)); - if(pre_hash == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - hash_dest = (unsigned char *)PORT_ArenaZAlloc(poolp, - sizeof(unsigned char) * SHA1_LENGTH); - if(hash_dest == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - PORT_Memcpy(pre_hash, salt->data, salt->len); - /* handle password of 0 length case */ - if(password->len > 0) { - PORT_Memcpy(&(pre_hash[salt->len]), password->data, password->len); - } - - res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, pre_hash, - (salt->len+password->len)); - if(res == SECFailure) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - switch(algorithm) { - case SEC_OID_SHA1: - if(key_len == 0) - key_len = 16; - key = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(key == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) - * key_len); - if(key->data == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - key->len = key_len; - PORT_Memcpy(key->data, &hash_dest[SHA1_LENGTH-key->len], key->len); - break; - default: - goto loser; - break; - } - - PORT_FreeArena(poolp, PR_TRUE); - return key; - -loser: - PORT_FreeArena(poolp, PR_TRUE); - if(key != NULL) { - SECITEM_ZfreeItem(key, PR_TRUE); - } - return NULL; -} - -/* MAC is generated per PKCS 12 section 6. It is expected that key, msg - * and mac_dest are pre allocated, non-NULL arrays. msg_len is passed in - * because it is not known how long the message actually is. String - * manipulation routines will not necessarily work because msg may have - * imbedded NULLs - */ -static SECItem * -sec_pkcs12_generate_old_mac(SECItem *key, - SECItem *msg) -{ - SECStatus res; - PRArenaPool *temparena = NULL; - unsigned char *hash_dest=NULL, *hash_src1=NULL, *hash_src2 = NULL; - int i; - SECItem *mac = NULL; - - if((key == NULL) || (msg == NULL)) - goto loser; - - /* allocate return item */ - mac = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(mac == NULL) - return NULL; - mac->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) - * SHA1_LENGTH); - mac->len = SHA1_LENGTH; - if(mac->data == NULL) - goto loser; - - /* allocate temporary items */ - temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if(temparena == NULL) - goto loser; - - hash_src1 = (unsigned char *)PORT_ArenaZAlloc(temparena, - sizeof(unsigned char) * (16+msg->len)); - if(hash_src1 == NULL) - goto loser; - - hash_src2 = (unsigned char *)PORT_ArenaZAlloc(temparena, - sizeof(unsigned char) * (SHA1_LENGTH+16)); - if(hash_src2 == NULL) - goto loser; - - hash_dest = (unsigned char *)PORT_ArenaZAlloc(temparena, - sizeof(unsigned char) * SHA1_LENGTH); - if(hash_dest == NULL) - goto loser; - - /* perform mac'ing as per PKCS 12 */ - - /* first round of hashing */ - for(i = 0; i < 16; i++) - hash_src1[i] = key->data[i] ^ 0x36; - PORT_Memcpy(&(hash_src1[16]), msg->data, msg->len); - res = PK11_HashBuf(SEC_OID_SHA1, hash_dest, hash_src1, (16+msg->len)); - if(res == SECFailure) - goto loser; - - /* second round of hashing */ - for(i = 0; i < 16; i++) - hash_src2[i] = key->data[i] ^ 0x5c; - PORT_Memcpy(&(hash_src2[16]), hash_dest, SHA1_LENGTH); - res = PK11_HashBuf(SEC_OID_SHA1, mac->data, hash_src2, SHA1_LENGTH+16); - if(res == SECFailure) - goto loser; - - PORT_FreeArena(temparena, PR_TRUE); - return mac; - -loser: - if(temparena != NULL) - PORT_FreeArena(temparena, PR_TRUE); - if(mac != NULL) - SECITEM_ZfreeItem(mac, PR_TRUE); - return NULL; -} - -/* MAC is generated per PKCS 12 section 6. It is expected that key, msg - * and mac_dest are pre allocated, non-NULL arrays. msg_len is passed in - * because it is not known how long the message actually is. String - * manipulation routines will not necessarily work because msg may have - * imbedded NULLs - */ -SECItem * -sec_pkcs12_generate_mac(SECItem *key, - SECItem *msg, - PRBool old_method) -{ - SECStatus res = SECFailure; - SECItem *mac = NULL; - PK11Context *pk11cx = NULL; - SECItem ignore = {0}; - - if((key == NULL) || (msg == NULL)) { - return NULL; - } - - if(old_method == PR_TRUE) { - return sec_pkcs12_generate_old_mac(key, msg); - } - - /* allocate return item */ - mac = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH); - if (mac == NULL) { - return NULL; - } - - pk11cx = PK11_CreateContextByRawKey(NULL, CKM_SHA_1_HMAC, PK11_OriginDerive, - CKA_SIGN, key, &ignore, NULL); - if (pk11cx == NULL) { - goto loser; - } - - res = PK11_DigestBegin(pk11cx); - if (res == SECFailure) { - goto loser; - } - - res = PK11_DigestOp(pk11cx, msg->data, msg->len); - if (res == SECFailure) { - goto loser; - } - - res = PK11_DigestFinal(pk11cx, mac->data, &mac->len, SHA1_LENGTH); - if (res == SECFailure) { - goto loser; - } - - PK11_DestroyContext(pk11cx, PR_TRUE); - pk11cx = NULL; - -loser: - - if(res != SECSuccess) { - SECITEM_ZfreeItem(mac, PR_TRUE); - mac = NULL; - if (pk11cx) { - PK11_DestroyContext(pk11cx, PR_TRUE); - } - } - - return mac; -} - -/* compute the thumbprint of the DER cert and create a digest info - * to store it in and return the digest info. - * a return of NULL indicates an error. - */ -SGNDigestInfo * -sec_pkcs12_compute_thumbprint(SECItem *der_cert) -{ - SGNDigestInfo *thumb = NULL; - SECItem digest; - PRArenaPool *temparena = NULL; - SECStatus rv = SECFailure; - - if(der_cert == NULL) - return NULL; - - temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if(temparena == NULL) { - return NULL; - } - - digest.data = (unsigned char *)PORT_ArenaZAlloc(temparena, - sizeof(unsigned char) * - SHA1_LENGTH); - /* digest data and create digest info */ - if(digest.data != NULL) { - digest.len = SHA1_LENGTH; - rv = PK11_HashBuf(SEC_OID_SHA1, digest.data, der_cert->data, - der_cert->len); - if(rv == SECSuccess) { - thumb = SGN_CreateDigestInfo(SEC_OID_SHA1, - digest.data, - digest.len); - } else { - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - } else { - PORT_SetError(SEC_ERROR_NO_MEMORY); - } - - PORT_FreeArena(temparena, PR_TRUE); - - return thumb; -} - -/* create a virtual password per PKCS 12, the password is converted - * to unicode, the salt is prepended to it, and then the whole thing - * is returned */ -SECItem * -sec_pkcs12_create_virtual_password(SECItem *password, SECItem *salt, - PRBool swap) -{ - SECItem uniPwd = {siBuffer, NULL,0}, *retPwd = NULL; - - if((password == NULL) || (salt == NULL)) { - return NULL; - } - - if(password->len == 0) { - uniPwd.data = (unsigned char*)PORT_ZAlloc(2); - uniPwd.len = 2; - if(!uniPwd.data) { - return NULL; - } - } else { - uniPwd.data = (unsigned char*)PORT_ZAlloc(password->len * 3); - uniPwd.len = password->len * 3; - if(!PORT_UCS2_ASCIIConversion(PR_TRUE, password->data, password->len, - uniPwd.data, uniPwd.len, &uniPwd.len, swap)) { - SECITEM_ZfreeItem(&uniPwd, PR_FALSE); - return NULL; - } - } - - retPwd = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(retPwd == NULL) { - goto loser; - } - - /* allocate space and copy proper data */ - retPwd->len = uniPwd.len + salt->len; - retPwd->data = (unsigned char *)PORT_Alloc(retPwd->len); - if(retPwd->data == NULL) { - PORT_Free(retPwd); - goto loser; - } - - PORT_Memcpy(retPwd->data, salt->data, salt->len); - PORT_Memcpy((retPwd->data + salt->len), uniPwd.data, uniPwd.len); - - SECITEM_ZfreeItem(&uniPwd, PR_FALSE); - - return retPwd; - -loser: - PORT_SetError(SEC_ERROR_NO_MEMORY); - SECITEM_ZfreeItem(&uniPwd, PR_FALSE); - return NULL; -} - -/* appends a shrouded key to a key bag. this is used for exporting - * to store externally wrapped keys. it is used when importing to convert - * old items to new - */ -SECStatus -sec_pkcs12_append_shrouded_key(SEC_PKCS12BaggageItem *bag, - SEC_PKCS12ESPVKItem *espvk) -{ - int size; - void *mark = NULL, *dummy = NULL; - - if((bag == NULL) || (espvk == NULL)) - return SECFailure; - - mark = PORT_ArenaMark(bag->poolp); - - /* grow the list */ - size = (bag->nEspvks + 1) * sizeof(SEC_PKCS12ESPVKItem *); - dummy = (SEC_PKCS12ESPVKItem **)PORT_ArenaGrow(bag->poolp, - bag->espvks, size, - size + sizeof(SEC_PKCS12ESPVKItem *)); - bag->espvks = (SEC_PKCS12ESPVKItem**)dummy; - if(dummy == NULL) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - goto loser; - } - - bag->espvks[bag->nEspvks] = espvk; - bag->nEspvks++; - bag->espvks[bag->nEspvks] = NULL; - - PORT_ArenaUnmark(bag->poolp, mark); - return SECSuccess; - -loser: - PORT_ArenaRelease(bag->poolp, mark); - return SECFailure; -} - -/* search a certificate list for a nickname, a thumbprint, or both - * within a certificate bag. if the certificate could not be - * found or an error occurs, NULL is returned; - */ -static SEC_PKCS12CertAndCRL * -sec_pkcs12_find_cert_in_certbag(SEC_PKCS12CertAndCRLBag *certbag, - SECItem *nickname, SGNDigestInfo *thumbprint) -{ - PRBool search_both = PR_FALSE, search_nickname = PR_FALSE; - int i, j; - - if((certbag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) { - return NULL; - } - - if(thumbprint && nickname) { - search_both = PR_TRUE; - } - - if(nickname) { - search_nickname = PR_TRUE; - } - -search_again: - i = 0; - while(certbag->certAndCRLs[i] != NULL) { - SEC_PKCS12CertAndCRL *cert = certbag->certAndCRLs[i]; - - if(SECOID_FindOIDTag(&cert->BagID) == SEC_OID_PKCS12_X509_CERT_CRL_BAG) { - - /* check nicknames */ - if(search_nickname) { - if(SECITEM_CompareItem(nickname, &cert->nickname) == SECEqual) { - return cert; - } - } else { - /* check thumbprints */ - SECItem **derCertList; - - /* get pointer to certificate list, does not need to - * be freed since it is within the arena which will - * be freed later. - */ - derCertList = SEC_PKCS7GetCertificateList(&cert->value.x509->certOrCRL); - j = 0; - if(derCertList != NULL) { - while(derCertList[j] != NULL) { - SECComparison eq; - SGNDigestInfo *di; - di = sec_pkcs12_compute_thumbprint(derCertList[j]); - if(di) { - eq = SGN_CompareDigestInfo(thumbprint, di); - SGN_DestroyDigestInfo(di); - if(eq == SECEqual) { - /* copy the derCert for later reference */ - cert->value.x509->derLeafCert = derCertList[j]; - return cert; - } - } else { - /* an error occurred */ - return NULL; - } - j++; - } - } - } - } - - i++; - } - - if(search_both) { - search_both = PR_FALSE; - search_nickname = PR_FALSE; - goto search_again; - } - - return NULL; -} - -/* search a key list for a nickname, a thumbprint, or both - * within a key bag. if the key could not be - * found or an error occurs, NULL is returned; - */ -static SEC_PKCS12PrivateKey * -sec_pkcs12_find_key_in_keybag(SEC_PKCS12PrivateKeyBag *keybag, - SECItem *nickname, SGNDigestInfo *thumbprint) -{ - PRBool search_both = PR_FALSE, search_nickname = PR_FALSE; - int i, j; - - if((keybag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) { - return NULL; - } - - if(keybag->privateKeys == NULL) { - return NULL; - } - - if(thumbprint && nickname) { - search_both = PR_TRUE; - } - - if(nickname) { - search_nickname = PR_TRUE; - } - -search_again: - i = 0; - while(keybag->privateKeys[i] != NULL) { - SEC_PKCS12PrivateKey *key = keybag->privateKeys[i]; - - /* check nicknames */ - if(search_nickname) { - if(SECITEM_CompareItem(nickname, &key->pvkData.nickname) == SECEqual) { - return key; - } - } else { - /* check digests */ - SGNDigestInfo **assocCerts = key->pvkData.assocCerts; - if((assocCerts == NULL) || (assocCerts[0] == NULL)) { - return NULL; - } - - j = 0; - while(assocCerts[j] != NULL) { - SECComparison eq; - eq = SGN_CompareDigestInfo(thumbprint, assocCerts[j]); - if(eq == SECEqual) { - return key; - } - j++; - } - } - i++; - } - - if(search_both) { - search_both = PR_FALSE; - search_nickname = PR_FALSE; - goto search_again; - } - - return NULL; -} - -/* seach the safe first then try the baggage bag - * safe and bag contain certs and keys to search - * objType is the object type to look for - * bagType is the type of bag that was found by sec_pkcs12_find_object - * index is the entity in safe->safeContents or bag->unencSecrets which - * is being searched - * nickname and thumbprint are the search criteria - * - * a return of null indicates no match - */ -static void * -sec_pkcs12_try_find(SEC_PKCS12SafeContents *safe, - SEC_PKCS12BaggageItem *bag, - SECOidTag objType, SECOidTag bagType, int index, - SECItem *nickname, SGNDigestInfo *thumbprint) -{ - PRBool searchSafe; - int i = index; - - if((safe == NULL) && (bag == NULL)) { - return NULL; - } - - searchSafe = (safe == NULL ? PR_FALSE : PR_TRUE); - switch(objType) { - case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID: - if(objType == bagType) { - SEC_PKCS12CertAndCRLBag *certBag; - - if(searchSafe) { - certBag = safe->contents[i]->safeContent.certAndCRLBag; - } else { - certBag = bag->unencSecrets[i]->safeContent.certAndCRLBag; - } - return sec_pkcs12_find_cert_in_certbag(certBag, nickname, - thumbprint); - } - break; - case SEC_OID_PKCS12_KEY_BAG_ID: - if(objType == bagType) { - SEC_PKCS12PrivateKeyBag *keyBag; - - if(searchSafe) { - keyBag = safe->contents[i]->safeContent.keyBag; - } else { - keyBag = bag->unencSecrets[i]->safeContent.keyBag; - } - return sec_pkcs12_find_key_in_keybag(keyBag, nickname, - thumbprint); - } - break; - default: - break; - } - - return NULL; -} - -/* searches both the baggage and the safe areas looking for - * object of specified type matching either the nickname or the - * thumbprint specified. - * - * safe and baggage store certs and keys - * objType is the OID for the bag type to be searched: - * SEC_OID_PKCS12_KEY_BAG_ID, or - * SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID - * nickname and thumbprint are the search criteria - * - * if no match found, NULL returned and error set - */ -void * -sec_pkcs12_find_object(SEC_PKCS12SafeContents *safe, - SEC_PKCS12Baggage *baggage, - SECOidTag objType, - SECItem *nickname, - SGNDigestInfo *thumbprint) -{ - int i, j; - void *retItem; - - if(((safe == NULL) && (thumbprint == NULL)) || - ((nickname == NULL) && (thumbprint == NULL))) { - return NULL; - } - - i = 0; - if((safe != NULL) && (safe->contents != NULL)) { - while(safe->contents[i] != NULL) { - SECOidTag bagType = SECOID_FindOIDTag(&safe->contents[i]->safeBagType); - retItem = sec_pkcs12_try_find(safe, NULL, objType, bagType, i, - nickname, thumbprint); - if(retItem != NULL) { - return retItem; - } - i++; - } - } - - if((baggage != NULL) && (baggage->bags != NULL)) { - i = 0; - while(baggage->bags[i] != NULL) { - SEC_PKCS12BaggageItem *xbag = baggage->bags[i]; - j = 0; - if(xbag->unencSecrets != NULL) { - while(xbag->unencSecrets[j] != NULL) { - SECOidTag bagType; - bagType = SECOID_FindOIDTag(&xbag->unencSecrets[j]->safeBagType); - retItem = sec_pkcs12_try_find(NULL, xbag, objType, bagType, - j, nickname, thumbprint); - if(retItem != NULL) { - return retItem; - } - j++; - } - } - i++; - } - } - - PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME); - return NULL; -} - -/* this function converts a password to unicode and encures that the - * required double 0 byte be placed at the end of the string - */ -PRBool -sec_pkcs12_convert_item_to_unicode(PRArenaPool *arena, SECItem *dest, - SECItem *src, PRBool zeroTerm, - PRBool asciiConvert, PRBool toUnicode) -{ - PRBool success = PR_FALSE; - if(!src || !dest) { - return PR_FALSE; - } - - dest->len = src->len * 3 + 2; - if(arena) { - dest->data = (unsigned char*)PORT_ArenaZAlloc(arena, dest->len); - } else { - dest->data = (unsigned char*)PORT_ZAlloc(dest->len); - } - - if(!dest->data) { - dest->len = 0; - return PR_FALSE; - } - - if(!asciiConvert) { - success = PORT_UCS2_UTF8Conversion(toUnicode, src->data, src->len, dest->data, - dest->len, &dest->len); - } else { -#ifndef IS_LITTLE_ENDIAN - PRBool swapUnicode = PR_FALSE; -#else - PRBool swapUnicode = PR_TRUE; -#endif - success = PORT_UCS2_ASCIIConversion(toUnicode, src->data, src->len, dest->data, - dest->len, &dest->len, swapUnicode); - } - - if(!success) { - if(!arena) { - PORT_Free(dest->data); - dest->data = NULL; - dest->len = 0; - } - return PR_FALSE; - } - - if((dest->data[dest->len-1] || dest->data[dest->len-2]) && zeroTerm) { - if(dest->len + 2 > 3 * src->len) { - if(arena) { - dest->data = (unsigned char*)PORT_ArenaGrow(arena, - dest->data, dest->len, - dest->len + 2); - } else { - dest->data = (unsigned char*)PORT_Realloc(dest->data, - dest->len + 2); - } - - if(!dest->data) { - return PR_FALSE; - } - } - dest->len += 2; - dest->data[dest->len-1] = dest->data[dest->len-2] = 0; - } - - return PR_TRUE; -} - -/* pkcs 12 templates */ -static const SEC_ASN1TemplateChooserPtr sec_pkcs12_shroud_chooser = - sec_pkcs12_choose_shroud_type; - -const SEC_ASN1Template SEC_PKCS12CodedSafeBagTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) }, - { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) }, - { SEC_ASN1_ANY, offsetof(SEC_PKCS12SafeBag, derSafeContent) }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12CodedCertBagTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) }, - { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) }, - { SEC_ASN1_ANY, offsetof(SEC_PKCS12CertAndCRL, derValue) }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12CodedCertAndCRLBagTemplate[] = -{ - { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs), - SEC_PKCS12CodedCertBagTemplate }, -}; - -const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate_OLD[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) }, - { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) }, - { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData), - SEC_PKCS12PVKSupportingDataTemplate_OLD }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | - SEC_ASN1_DYNAMIC | 0, offsetof(SEC_PKCS12ESPVKItem, espvkCipherText), - &sec_pkcs12_shroud_chooser }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12ESPVKItem) }, - { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12ESPVKItem, espvkOID) }, - { SEC_ASN1_INLINE, offsetof(SEC_PKCS12ESPVKItem, espvkData), - SEC_PKCS12PVKSupportingDataTemplate }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | - SEC_ASN1_DYNAMIC | 0, offsetof(SEC_PKCS12ESPVKItem, espvkCipherText), - &sec_pkcs12_shroud_chooser }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12PVKAdditionalDataTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKAdditionalData) }, - { SEC_ASN1_OBJECT_ID, - offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalType) }, - { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(SEC_PKCS12PVKAdditionalData, pvkAdditionalContent) }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate_OLD[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) }, - { SEC_ASN1_SET_OF | SEC_ASN1_XTRN , - offsetof(SEC_PKCS12PVKSupportingData, assocCerts), - SEC_ASN1_SUB(sgn_DigestInfoTemplate) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, - offsetof(SEC_PKCS12PVKSupportingData, regenerable) }, - { SEC_ASN1_PRINTABLE_STRING, - offsetof(SEC_PKCS12PVKSupportingData, nickname) }, - { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL, - offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PVKSupportingData) }, - { SEC_ASN1_SET_OF | SEC_ASN1_XTRN , - offsetof(SEC_PKCS12PVKSupportingData, assocCerts), - SEC_ASN1_SUB(sgn_DigestInfoTemplate) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_BOOLEAN, - offsetof(SEC_PKCS12PVKSupportingData, regenerable) }, - { SEC_ASN1_BMP_STRING, - offsetof(SEC_PKCS12PVKSupportingData, uniNickName) }, - { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL, - offsetof(SEC_PKCS12PVKSupportingData, pvkAdditionalDER) }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12BaggageItemTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12BaggageItem) }, - { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, espvks), - SEC_PKCS12ESPVKItemTemplate }, - { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets), - SEC_PKCS12SafeBagTemplate }, - /*{ SEC_ASN1_SET_OF, offsetof(SEC_PKCS12BaggageItem, unencSecrets), - SEC_PKCS12CodedSafeBagTemplate }, */ - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12BaggageTemplate[] = -{ - { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage, bags), - SEC_PKCS12BaggageItemTemplate }, -}; - -const SEC_ASN1Template SEC_PKCS12BaggageTemplate_OLD[] = -{ - { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12Baggage_OLD, espvks), - SEC_PKCS12ESPVKItemTemplate_OLD }, -}; - -static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser = - sec_pkcs12_choose_bag_type; - -static const SEC_ASN1TemplateChooserPtr sec_pkcs12_bag_chooser_old = - sec_pkcs12_choose_bag_type_old; - -const SEC_ASN1Template SEC_PKCS12SafeBagTemplate_OLD[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) }, - { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) }, - { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | - SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(SEC_PKCS12SafeBag, safeContent), - &sec_pkcs12_bag_chooser_old }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12SafeBagTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) }, - { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) }, - { SEC_ASN1_DYNAMIC | SEC_ASN1_POINTER, - offsetof(SEC_PKCS12SafeBag, safeContent), - &sec_pkcs12_bag_chooser }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_BMP_STRING, - offsetof(SEC_PKCS12SafeBag, uniSafeBagName) }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate_OLD[] = -{ - { SEC_ASN1_SET_OF, - offsetof(SEC_PKCS12SafeContents, contents), - SEC_PKCS12SafeBagTemplate_OLD } -}; - -const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate[] = -{ - { SEC_ASN1_SET_OF, - offsetof(SEC_PKCS12SafeContents, contents), - SEC_PKCS12SafeBagTemplate } /* here */ -}; - -const SEC_ASN1Template SEC_PKCS12PrivateKeyTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKey) }, - { SEC_ASN1_INLINE, offsetof(SEC_PKCS12PrivateKey, pvkData), - SEC_PKCS12PVKSupportingDataTemplate }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN, - offsetof(SEC_PKCS12PrivateKey, pkcs8data), - SEC_ASN1_SUB(SECKEY_PrivateKeyInfoTemplate) }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12PrivateKeyBagTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PrivateKeyBag) }, - { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12PrivateKeyBag, privateKeys), - SEC_PKCS12PrivateKeyTemplate }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate_OLD[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) }, - { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL), - sec_PKCS7ContentInfoTemplate }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN , - offsetof(SEC_PKCS12X509CertCRL, thumbprint), - SEC_ASN1_SUB(sgn_DigestInfoTemplate) }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) }, - { SEC_ASN1_INLINE, offsetof(SEC_PKCS12X509CertCRL, certOrCRL), - sec_PKCS7ContentInfoTemplate }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12SDSICertTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12X509CertCRL) }, - { SEC_ASN1_IA5_STRING, offsetof(SEC_PKCS12SDSICert, value) }, - { 0 } -}; - -static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser_old = - sec_pkcs12_choose_cert_crl_type_old; - -static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_crl_chooser = - sec_pkcs12_choose_cert_crl_type; - -const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate_OLD[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) }, - { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT | - SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | 0, - offsetof(SEC_PKCS12CertAndCRL, value), - &sec_pkcs12_cert_crl_chooser_old }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRL) }, - { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12CertAndCRL, BagID) }, - { SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | - SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(SEC_PKCS12CertAndCRL, value), - &sec_pkcs12_cert_crl_chooser }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate[] = -{ - { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs), - SEC_PKCS12CertAndCRLTemplate }, -}; - -const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate_OLD[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12CertAndCRLBag) }, - { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12CertAndCRLBag, certAndCRLs), - SEC_PKCS12CertAndCRLTemplate_OLD }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12SecretAdditionalTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SecretAdditional) }, - { SEC_ASN1_OBJECT_ID, - offsetof(SEC_PKCS12SecretAdditional, secretAdditionalType) }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_EXPLICIT, - offsetof(SEC_PKCS12SecretAdditional, secretAdditionalContent) }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12SecretTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) }, - { SEC_ASN1_BMP_STRING, offsetof(SEC_PKCS12Secret, uniSecretName) }, - { SEC_ASN1_ANY, offsetof(SEC_PKCS12Secret, value) }, - { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, - offsetof(SEC_PKCS12Secret, secretAdditional), - SEC_PKCS12SecretAdditionalTemplate }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12SecretItemTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12Secret) }, - { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(SEC_PKCS12SecretItem, secret), SEC_PKCS12SecretTemplate }, - { SEC_ASN1_INLINE | SEC_ASN1_CONTEXT_SPECIFIC | 1, - offsetof(SEC_PKCS12SecretItem, subFolder), SEC_PKCS12SafeBagTemplate }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12SecretBagTemplate[] = -{ - { SEC_ASN1_SET_OF, offsetof(SEC_PKCS12SecretBag, secrets), - SEC_PKCS12SecretItemTemplate }, -}; - -const SEC_ASN1Template SEC_PKCS12MacDataTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN , offsetof(SEC_PKCS12MacData, safeMac), - SEC_ASN1_SUB(sgn_DigestInfoTemplate) }, - { SEC_ASN1_BIT_STRING, offsetof(SEC_PKCS12MacData, macSalt) }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12PFXItemTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) }, - { SEC_ASN1_OPTIONAL | - SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(SEC_PKCS12PFXItem, macData), SEC_PKCS12MacDataTemplate }, - { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, - offsetof(SEC_PKCS12PFXItem, authSafe), - sec_PKCS7ContentInfoTemplate }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12PFXItemTemplate_OLD[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12PFXItem) }, - { SEC_ASN1_OPTIONAL | - SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, - offsetof(SEC_PKCS12PFXItem, old_safeMac), - SEC_ASN1_SUB(sgn_DigestInfoTemplate) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_BIT_STRING, - offsetof(SEC_PKCS12PFXItem, old_macSalt) }, - { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, - offsetof(SEC_PKCS12PFXItem, authSafe), - sec_PKCS7ContentInfoTemplate }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER, - offsetof(SEC_PKCS12AuthenticatedSafe, version) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_OBJECT_ID, - offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) }, - { SEC_ASN1_BIT_STRING | SEC_ASN1_OPTIONAL, - offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_SET_OF, - offsetof(SEC_PKCS12AuthenticatedSafe, baggage.bags), - SEC_PKCS12BaggageItemTemplate }, - { SEC_ASN1_POINTER, - offsetof(SEC_PKCS12AuthenticatedSafe, safe), - sec_PKCS7ContentInfoTemplate }, - { 0 } -}; - -const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate_OLD[] = -{ - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12AuthenticatedSafe) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER, - offsetof(SEC_PKCS12AuthenticatedSafe, version) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER, - offsetof(SEC_PKCS12AuthenticatedSafe, transportMode) }, - { SEC_ASN1_BIT_STRING, - offsetof(SEC_PKCS12AuthenticatedSafe, privacySalt) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | - SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(SEC_PKCS12AuthenticatedSafe, old_baggage), - SEC_PKCS12BaggageTemplate_OLD }, - { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, - offsetof(SEC_PKCS12AuthenticatedSafe, old_safe), - sec_PKCS7ContentInfoTemplate }, - { 0 } -}; - -const SEC_ASN1Template SEC_PointerToPKCS12KeyBagTemplate[] = -{ - { SEC_ASN1_POINTER, 0, SEC_PKCS12PrivateKeyBagTemplate } -}; - -const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD[] = -{ - { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate_OLD } -}; - -const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate[] = -{ - { SEC_ASN1_POINTER, 0, SEC_PKCS12CertAndCRLBagTemplate } -}; - -const SEC_ASN1Template SEC_PointerToPKCS12SecretBagTemplate[] = -{ - { SEC_ASN1_POINTER, 0, SEC_PKCS12SecretBagTemplate } -}; - -const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate_OLD[] = -{ - { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate_OLD } -}; - -const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate[] = -{ - { SEC_ASN1_POINTER, 0, SEC_PKCS12X509CertCRLTemplate } -}; - -const SEC_ASN1Template SEC_PointerToPKCS12SDSICertTemplate[] = -{ - { SEC_ASN1_POINTER, 0, SEC_PKCS12SDSICertTemplate } -}; - - diff --git a/security/nss/lib/pkcs12/p12local.h b/security/nss/lib/pkcs12/p12local.h deleted file mode 100644 index 0c4bd594d..000000000 --- a/security/nss/lib/pkcs12/p12local.h +++ /dev/null @@ -1,91 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -#ifndef _P12LOCAL_H_ -#define _P12LOCAL_H_ - -#include "plarena.h" -#include "secoidt.h" -#include "secasn1.h" -#include "secder.h" -#include "certt.h" -#include "secpkcs7.h" -#include "pkcs12.h" -#include "p12.h" - -/* helper functions */ -extern const SEC_ASN1Template * -sec_pkcs12_choose_bag_type(void *src_or_dest, PRBool encoding); -extern const SEC_ASN1Template * -sec_pkcs12_choose_cert_crl_type(void *src_or_dest, PRBool encoding); -extern const SEC_ASN1Template * -sec_pkcs12_choose_shroud_type(void *src_or_dest, PRBool encoding); -extern SECItem *sec_pkcs12_generate_salt(void); -extern SECItem *sec_pkcs12_generate_key_from_password(SECOidTag algorithm, - SECItem *salt, SECItem *password); -extern SECItem *sec_pkcs12_generate_mac(SECItem *key, SECItem *msg, - PRBool old_method); -extern SGNDigestInfo *sec_pkcs12_compute_thumbprint(SECItem *der_cert); -extern SECItem *sec_pkcs12_create_virtual_password(SECItem *password, - SECItem *salt, PRBool swapUnicodeBytes); -extern SECStatus sec_pkcs12_append_shrouded_key(SEC_PKCS12BaggageItem *bag, - SEC_PKCS12ESPVKItem *espvk); -extern void *sec_pkcs12_find_object(SEC_PKCS12SafeContents *safe, - SEC_PKCS12Baggage *baggage, SECOidTag objType, - SECItem *nickname, SGNDigestInfo *thumbprint); -extern PRBool sec_pkcs12_convert_item_to_unicode(PRArenaPool *arena, SECItem *dest, - SECItem *src, PRBool zeroTerm, - PRBool asciiConvert, PRBool toUnicode); -extern CK_MECHANISM_TYPE sec_pkcs12_algtag_to_mech(SECOidTag algtag); - -/* create functions */ -extern SEC_PKCS12PFXItem *sec_pkcs12_new_pfx(void); -extern SEC_PKCS12SafeContents *sec_pkcs12_create_safe_contents( - PRArenaPool *poolp); -extern SEC_PKCS12Baggage *sec_pkcs12_create_baggage(PRArenaPool *poolp); -extern SEC_PKCS12BaggageItem *sec_pkcs12_create_external_bag(SEC_PKCS12Baggage *luggage); -extern void SEC_PKCS12DestroyPFX(SEC_PKCS12PFXItem *pfx); -extern SEC_PKCS12AuthenticatedSafe *sec_pkcs12_new_asafe(PRArenaPool *poolp); - -/* conversion from old to new */ -extern SEC_PKCS12DecoderContext * -sec_PKCS12ConvertOldSafeToNew(PRArenaPool *arena, PK11SlotInfo *slot, - PRBool swapUnicode, SECItem *pwitem, - void *wincx, SEC_PKCS12SafeContents *safe, - SEC_PKCS12Baggage *baggage); - -#endif diff --git a/security/nss/lib/pkcs12/p12plcy.c b/security/nss/lib/pkcs12/p12plcy.c deleted file mode 100644 index ae3ab0b51..000000000 --- a/security/nss/lib/pkcs12/p12plcy.c +++ /dev/null @@ -1,201 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -#include "p12plcy.h" -#include "secoid.h" -#include "secport.h" -#include "secpkcs5.h" - -#define PKCS12_NULL 0x0000 - -typedef struct pkcs12SuiteMapStr { - SECOidTag algTag; - unsigned int keyLengthBits; /* in bits */ - unsigned long suite; - PRBool allowed; - PRBool preferred; -} pkcs12SuiteMap; - -static pkcs12SuiteMap pkcs12SuiteMaps[] = { - { SEC_OID_RC4, 40, PKCS12_RC4_40, PR_FALSE, PR_FALSE}, - { SEC_OID_RC4, 128, PKCS12_RC4_128, PR_FALSE, PR_FALSE}, - { SEC_OID_RC2_CBC, 40, PKCS12_RC2_CBC_40, PR_FALSE, PR_TRUE}, - { SEC_OID_RC2_CBC, 128, PKCS12_RC2_CBC_128, PR_FALSE, PR_FALSE}, - { SEC_OID_DES_CBC, 64, PKCS12_DES_56, PR_FALSE, PR_FALSE}, - { SEC_OID_DES_EDE3_CBC, 192, PKCS12_DES_EDE3_168, PR_FALSE, PR_FALSE}, - { SEC_OID_UNKNOWN, 0, PKCS12_NULL, PR_FALSE, PR_FALSE}, - { SEC_OID_UNKNOWN, 0, 0L, PR_FALSE, PR_FALSE} -}; - -/* determine if algid is an algorithm which is allowed */ -PRBool -SEC_PKCS12DecryptionAllowed(SECAlgorithmID *algid) -{ - unsigned int keyLengthBits; - SECOidTag algId; - int i; - - algId = SEC_PKCS5GetCryptoAlgorithm(algid); - if(algId == SEC_OID_UNKNOWN) { - return PR_FALSE; - } - - keyLengthBits = (unsigned int)(SEC_PKCS5GetKeyLength(algid) * 8); - - i = 0; - while(pkcs12SuiteMaps[i].algTag != SEC_OID_UNKNOWN) { - if((pkcs12SuiteMaps[i].algTag == algId) && - (pkcs12SuiteMaps[i].keyLengthBits == keyLengthBits)) { - - return pkcs12SuiteMaps[i].allowed; - } - i++; - } - - return PR_FALSE; -} - -/* is any encryption allowed? */ -PRBool -SEC_PKCS12IsEncryptionAllowed(void) -{ - int i; - - i = 0; - while(pkcs12SuiteMaps[i].algTag != SEC_OID_UNKNOWN) { - if(pkcs12SuiteMaps[i].allowed == PR_TRUE) { - return PR_TRUE; - } - i++; - } - - return PR_FALSE; -} - -/* get the preferred algorithm. - */ -SECOidTag -SEC_PKCS12GetPreferredEncryptionAlgorithm(void) -{ - int i; - - i = 0; - while(pkcs12SuiteMaps[i].algTag != SEC_OID_UNKNOWN) { - if((pkcs12SuiteMaps[i].preferred == PR_TRUE) && - (pkcs12SuiteMaps[i].allowed == PR_TRUE)) { - return SEC_PKCS5GetPBEAlgorithm(pkcs12SuiteMaps[i].algTag, - pkcs12SuiteMaps[i].keyLengthBits); - } - i++; - } - - return SEC_OID_UNKNOWN; -} - -/* return the strongest algorithm allowed */ -SECOidTag -SEC_PKCS12GetStrongestAllowedAlgorithm(void) -{ - int i, keyLengthBits = 0; - SECOidTag algorithm = SEC_OID_UNKNOWN; - - i = 0; - while(pkcs12SuiteMaps[i].algTag != SEC_OID_UNKNOWN) { - if((pkcs12SuiteMaps[i].allowed == PR_TRUE) && - (pkcs12SuiteMaps[i].keyLengthBits > (unsigned int)keyLengthBits) && - (pkcs12SuiteMaps[i].algTag != SEC_OID_RC4)) { - algorithm = pkcs12SuiteMaps[i].algTag; - keyLengthBits = pkcs12SuiteMaps[i].keyLengthBits; - } - i++; - } - - if(algorithm == SEC_OID_UNKNOWN) { - return SEC_OID_UNKNOWN; - } - - return SEC_PKCS5GetPBEAlgorithm(algorithm, keyLengthBits); -} - -SECStatus -SEC_PKCS12EnableCipher(long which, int on) -{ - int i; - - i = 0; - while(pkcs12SuiteMaps[i].suite != 0L) { - if(pkcs12SuiteMaps[i].suite == (unsigned long)which) { - if(on) { - pkcs12SuiteMaps[i].allowed = PR_TRUE; - } else { - pkcs12SuiteMaps[i].allowed = PR_FALSE; - } - return SECSuccess; - } - i++; - } - - return SECFailure; -} - -SECStatus -SEC_PKCS12SetPreferredCipher(long which, int on) -{ - int i; - PRBool turnedOff = PR_FALSE; - PRBool turnedOn = PR_FALSE; - - i = 0; - while(pkcs12SuiteMaps[i].suite != 0L) { - if(pkcs12SuiteMaps[i].preferred == PR_TRUE) { - pkcs12SuiteMaps[i].preferred = PR_FALSE; - turnedOff = PR_TRUE; - } - if(pkcs12SuiteMaps[i].suite == (unsigned long)which) { - pkcs12SuiteMaps[i].preferred = PR_TRUE; - turnedOn = PR_TRUE; - } - i++; - } - - if((turnedOn) && (turnedOff)) { - return SECSuccess; - } - - return SECFailure; -} - diff --git a/security/nss/lib/pkcs12/p12plcy.h b/security/nss/lib/pkcs12/p12plcy.h deleted file mode 100644 index 586aea342..000000000 --- a/security/nss/lib/pkcs12/p12plcy.h +++ /dev/null @@ -1,63 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ -#ifndef _P12PLCY_H_ -#define _P12PLCY_H_ - -#include "secoid.h" -#include "ciferfam.h" - -SEC_BEGIN_PROTOS - -/* for the algid specified, can we decrypt it ? */ -extern PRBool SEC_PKCS12DecryptionAllowed(SECAlgorithmID *algid); - -/* is encryption allowed? */ -extern PRBool SEC_PKCS12IsEncryptionAllowed(void); - -/* get the preferred encryption algorithm */ -extern SECOidTag SEC_PKCS12GetPreferredEncryptionAlgorithm(void); - -/* get the stronget crypto allowed (based on order in the table */ -extern SECOidTag SEC_PKCS12GetStrongestAllowedAlgorithm(void); - -/* enable a cipher for encryption/decryption */ -extern SECStatus SEC_PKCS12EnableCipher(long which, int on); - -/* return the preferred cipher for encryption */ -extern SECStatus SEC_PKCS12SetPreferredCipher(long which, int on); - -SEC_END_PROTOS -#endif diff --git a/security/nss/lib/pkcs12/p12t.h b/security/nss/lib/pkcs12/p12t.h deleted file mode 100644 index 11a3bb558..000000000 --- a/security/nss/lib/pkcs12/p12t.h +++ /dev/null @@ -1,187 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef _P12T_H_ -#define _P12T_H_ - -#include "secoid.h" -#include "key.h" -#include "pkcs11.h" -#include "secpkcs7.h" -#include "secdig.h" /* for SGNDigestInfo */ -#include "pkcs12t.h" - -#define SEC_PKCS12_VERSION 3 - -/* structure declarations */ -typedef struct sec_PKCS12PFXItemStr sec_PKCS12PFXItem; -typedef struct sec_PKCS12MacDataStr sec_PKCS12MacData; -typedef struct sec_PKCS12AuthenticatedSafeStr sec_PKCS12AuthenticatedSafe; -typedef struct sec_PKCS12SafeContentsStr sec_PKCS12SafeContents; -typedef struct sec_PKCS12SafeBagStr sec_PKCS12SafeBag; -typedef struct sec_PKCS12PKCS8ShroudedKeyBagStr sec_PKCS12PKCS8ShroudedKeyBag; -typedef struct sec_PKCS12CertBagStr sec_PKCS12CertBag; -typedef struct sec_PKCS12CRLBagStr sec_PKCS12CRLBag; -typedef struct sec_PKCS12SecretBag sec_PKCS12SecretBag; -typedef struct sec_PKCS12AttributeStr sec_PKCS12Attribute; - -struct sec_PKCS12CertBagStr { - /* what type of cert is stored? */ - SECItem bagID; - - /* certificate information */ - union { - SECItem x509Cert; - SECItem SDSICert; - } value; -}; - -struct sec_PKCS12CRLBagStr { - /* what type of cert is stored? */ - SECItem bagID; - - /* certificate information */ - union { - SECItem x509CRL; - } value; -}; - -struct sec_PKCS12SecretBag { - /* what type of secret? */ - SECItem secretType; - - /* secret information. ssshhhh be vewy vewy quiet. */ - SECItem secretContent; -}; - -struct sec_PKCS12AttributeStr { - SECItem attrType; - SECItem **attrValue; -}; - -struct sec_PKCS12SafeBagStr { - - /* What type of bag are we using? */ - SECItem safeBagType; - - /* Dependent upon the type of bag being used. */ - union { - SECKEYPrivateKeyInfo *pkcs8KeyBag; - SECKEYEncryptedPrivateKeyInfo *pkcs8ShroudedKeyBag; - sec_PKCS12CertBag *certBag; - sec_PKCS12CRLBag *crlBag; - sec_PKCS12SecretBag *secretBag; - sec_PKCS12SafeContents *safeContents; - } safeBagContent; - - sec_PKCS12Attribute **attribs; - - /* used locally */ - SECOidData *bagTypeTag; - PRArenaPool *arena; - unsigned int nAttribs; - - /* used for validation/importing */ - PRBool problem, noInstall, validated, hasKey, unused, installed; - int error; - - PRBool swapUnicodeBytes; - PK11SlotInfo *slot; - SECItem *pwitem; - PRBool oldBagType; - SECPKCS12TargetTokenCAs tokenCAs; -}; - -struct sec_PKCS12SafeContentsStr { - sec_PKCS12SafeBag **safeBags; - SECItem **encodedSafeBags; - - /* used locally */ - PRArenaPool *arena; - unsigned int bagCount; -}; - -struct sec_PKCS12MacDataStr { - SGNDigestInfo safeMac; - SECItem macSalt; - SECItem iter; -}; - -struct sec_PKCS12PFXItemStr { - - SECItem version; - - /* Content type will either be Data (password integrity mode) - * or signedData (public-key integrity mode) - */ - SEC_PKCS7ContentInfo *authSafe; - SECItem encodedAuthSafe; - - /* Only present in password integrity mode */ - sec_PKCS12MacData macData; - SECItem encodedMacData; -}; - -struct sec_PKCS12AuthenticatedSafeStr { - /* Content type will either be encryptedData (password privacy mode) - * or envelopedData (public-key privacy mode) - */ - SEC_PKCS7ContentInfo **safes; - SECItem **encodedSafes; - - /* used locally */ - unsigned int safeCount; - SECItem dummySafe; -}; - -extern const SEC_ASN1Template sec_PKCS12PFXItemTemplate[]; -extern const SEC_ASN1Template sec_PKCS12MacDataTemplate[]; -extern const SEC_ASN1Template sec_PKCS12AuthenticatedSafeTemplate[]; -extern const SEC_ASN1Template sec_PKCS12SafeContentsTemplate[]; -extern const SEC_ASN1Template sec_PKCS12SafeContentsDecodeTemplate[]; -extern const SEC_ASN1Template sec_PKCS12NestedSafeContentsDecodeTemplate[]; -extern const SEC_ASN1Template sec_PKCS12CertBagTemplate[]; -extern const SEC_ASN1Template sec_PKCS12CRLBagTemplate[]; -extern const SEC_ASN1Template sec_PKCS12SecretBagTemplate[]; -extern const SEC_ASN1Template sec_PKCS12PointerToCertBagTemplate[]; -extern const SEC_ASN1Template sec_PKCS12PointerToCRLBagTemplate[]; -extern const SEC_ASN1Template sec_PKCS12PointerToSecretBagTemplate[]; -extern const SEC_ASN1Template sec_PKCS12PointerToSafeContentsTemplate[]; -extern const SEC_ASN1Template sec_PKCS12AttributeTemplate[]; -extern const SEC_ASN1Template sec_PKCS12PointerToContentInfoTemplate[]; -extern const SEC_ASN1Template sec_PKCS12SafeBagTemplate[]; - -#endif diff --git a/security/nss/lib/pkcs12/p12tmpl.c b/security/nss/lib/pkcs12/p12tmpl.c deleted file mode 100644 index 9b0f3ddba..000000000 --- a/security/nss/lib/pkcs12/p12tmpl.c +++ /dev/null @@ -1,323 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "plarena.h" -#include "secitem.h" -#include "secoid.h" -#include "seccomon.h" -#include "secport.h" -#include "cert.h" -#include "secpkcs7.h" -#include "secasn1.h" -#include "p12t.h" - -SEC_ASN1_MKSUB(SEC_AnyTemplate) -SEC_ASN1_MKSUB(sgn_DigestInfoTemplate) - -static const SEC_ASN1Template * -sec_pkcs12_choose_safe_bag_type(void *src_or_dest, PRBool encoding) -{ - const SEC_ASN1Template *theTemplate; - sec_PKCS12SafeBag *safeBag; - SECOidData *oiddata; - - if (src_or_dest == NULL) { - return NULL; - } - - safeBag = (sec_PKCS12SafeBag*)src_or_dest; - - oiddata = SECOID_FindOID(&safeBag->safeBagType); - if(oiddata == NULL) { - return SEC_ASN1_GET(SEC_AnyTemplate); - } - - switch (oiddata->offset) { - default: - theTemplate = SEC_ASN1_GET(SEC_AnyTemplate); - break; - case SEC_OID_PKCS12_V1_KEY_BAG_ID: - theTemplate = SEC_ASN1_GET(SECKEY_PointerToPrivateKeyInfoTemplate); - break; - case SEC_OID_PKCS12_V1_CERT_BAG_ID: - theTemplate = sec_PKCS12PointerToCertBagTemplate; - break; - case SEC_OID_PKCS12_V1_CRL_BAG_ID: - theTemplate = sec_PKCS12PointerToCRLBagTemplate; - break; - case SEC_OID_PKCS12_V1_SECRET_BAG_ID: - theTemplate = sec_PKCS12PointerToSecretBagTemplate; - break; - case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID: - theTemplate = - SEC_ASN1_GET(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate); - break; - case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID: - if(encoding) { - theTemplate = sec_PKCS12PointerToSafeContentsTemplate; - } else { - theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); - } - break; - } - return theTemplate; -} - -static const SEC_ASN1Template * -sec_pkcs12_choose_crl_bag_type(void *src_or_dest, PRBool encoding) -{ - const SEC_ASN1Template *theTemplate; - sec_PKCS12CRLBag *crlbag; - SECOidData *oiddata; - - if (src_or_dest == NULL) { - return NULL; - } - - crlbag = (sec_PKCS12CRLBag*)src_or_dest; - - oiddata = SECOID_FindOID(&crlbag->bagID); - if(oiddata == NULL) { - return SEC_ASN1_GET(SEC_AnyTemplate); - } - - switch (oiddata->offset) { - default: - theTemplate = SEC_ASN1_GET(SEC_AnyTemplate); - break; - case SEC_OID_PKCS9_X509_CRL: - theTemplate = SEC_ASN1_GET(SEC_OctetStringTemplate); - break; - } - return theTemplate; -} - -static const SEC_ASN1Template * -sec_pkcs12_choose_cert_bag_type(void *src_or_dest, PRBool encoding) -{ - const SEC_ASN1Template *theTemplate; - sec_PKCS12CertBag *certbag; - SECOidData *oiddata; - - if (src_or_dest == NULL) { - return NULL; - } - - certbag = (sec_PKCS12CertBag*)src_or_dest; - - oiddata = SECOID_FindOID(&certbag->bagID); - if(oiddata == NULL) { - return SEC_ASN1_GET(SEC_AnyTemplate); - } - - switch (oiddata->offset) { - default: - theTemplate = SEC_ASN1_GET(SEC_AnyTemplate); - break; - case SEC_OID_PKCS9_X509_CERT: - theTemplate = SEC_ASN1_GET(SEC_OctetStringTemplate); - break; - case SEC_OID_PKCS9_SDSI_CERT: - theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate); - break; - } - return theTemplate; -} - -static const SEC_ASN1Template * -sec_pkcs12_choose_attr_type(void *src_or_dest, PRBool encoding) -{ - const SEC_ASN1Template *theTemplate; - sec_PKCS12Attribute *attr; - SECOidData *oiddata; - - if (src_or_dest == NULL) { - return NULL; - } - - attr = (sec_PKCS12Attribute*)src_or_dest; - - oiddata = SECOID_FindOID(&attr->attrType); - if(oiddata == NULL) { - return SEC_ASN1_GET(SEC_AnyTemplate); - } - - switch (oiddata->offset) { - default: - theTemplate = SEC_ASN1_GET(SEC_AnyTemplate); - break; - case SEC_OID_PKCS9_FRIENDLY_NAME: - theTemplate = SEC_ASN1_GET(SEC_BMPStringTemplate); - break; - case SEC_OID_PKCS9_LOCAL_KEY_ID: - theTemplate = SEC_ASN1_GET(SEC_OctetStringTemplate); - break; - case SEC_OID_PKCS12_KEY_USAGE: - theTemplate = SEC_ASN1_GET(SEC_BitStringTemplate); - break; - } - - return theTemplate; -} - - -const SEC_ASN1Template sec_PKCS12PointerToContentInfoTemplate[] = { - { SEC_ASN1_POINTER | SEC_ASN1_MAY_STREAM, 0, sec_PKCS7ContentInfoTemplate } -}; - -static const SEC_ASN1TemplateChooserPtr sec_pkcs12_crl_bag_chooser = - sec_pkcs12_choose_crl_bag_type; - -static const SEC_ASN1TemplateChooserPtr sec_pkcs12_cert_bag_chooser = - sec_pkcs12_choose_cert_bag_type; - -static const SEC_ASN1TemplateChooserPtr sec_pkcs12_safe_bag_chooser = - sec_pkcs12_choose_safe_bag_type; - -static const SEC_ASN1TemplateChooserPtr sec_pkcs12_attr_chooser = - sec_pkcs12_choose_attr_type; - -const SEC_ASN1Template sec_PKCS12PointerToCertBagTemplate[] = { - { SEC_ASN1_POINTER, 0, sec_PKCS12CertBagTemplate } -}; - -const SEC_ASN1Template sec_PKCS12PointerToCRLBagTemplate[] = { - { SEC_ASN1_POINTER, 0, sec_PKCS12CRLBagTemplate } -}; - -const SEC_ASN1Template sec_PKCS12PointerToSecretBagTemplate[] = { - { SEC_ASN1_POINTER, 0, sec_PKCS12SecretBagTemplate } -}; - -const SEC_ASN1Template sec_PKCS12PointerToSafeContentsTemplate[] = { - { SEC_ASN1_POINTER, 0, sec_PKCS12SafeContentsTemplate } -}; - -const SEC_ASN1Template sec_PKCS12PFXItemTemplate[] = { - { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, 0, NULL, - sizeof(sec_PKCS12PFXItem) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER, - offsetof(sec_PKCS12PFXItem, version) }, - { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, - offsetof(sec_PKCS12PFXItem, encodedAuthSafe) }, - { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, - offsetof(sec_PKCS12PFXItem, encodedMacData) }, - { 0 } -}; - -const SEC_ASN1Template sec_PKCS12MacDataTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(sec_PKCS12MacData) }, - { SEC_ASN1_INLINE | SEC_ASN1_XTRN , offsetof(sec_PKCS12MacData, safeMac), - SEC_ASN1_SUB(sgn_DigestInfoTemplate) }, - { SEC_ASN1_OCTET_STRING, offsetof(sec_PKCS12MacData, macSalt) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_INTEGER, offsetof(sec_PKCS12MacData, iter) }, - { 0 } -}; - -const SEC_ASN1Template sec_PKCS12AuthenticatedSafeTemplate[] = { - { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_MAY_STREAM | SEC_ASN1_XTRN , - offsetof(sec_PKCS12AuthenticatedSafe, encodedSafes), - SEC_ASN1_SUB(SEC_AnyTemplate) } -}; - -const SEC_ASN1Template sec_PKCS12SafeBagTemplate[] = { - { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, 0, NULL, - sizeof(sec_PKCS12SafeBag) }, - { SEC_ASN1_OBJECT_ID, offsetof(sec_PKCS12SafeBag, safeBagType) }, - { SEC_ASN1_EXPLICIT | SEC_ASN1_DYNAMIC | SEC_ASN1_CONSTRUCTED | - SEC_ASN1_MAY_STREAM | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(sec_PKCS12SafeBag, safeBagContent), - &sec_pkcs12_safe_bag_chooser }, - { SEC_ASN1_SET_OF | SEC_ASN1_OPTIONAL, offsetof(sec_PKCS12SafeBag, attribs), - sec_PKCS12AttributeTemplate }, - { 0 } -}; - -const SEC_ASN1Template sec_PKCS12SafeContentsTemplate[] = { - { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_MAY_STREAM, - offsetof(sec_PKCS12SafeContents, safeBags), - sec_PKCS12SafeBagTemplate } -}; - -const SEC_ASN1Template sec_PKCS12SequenceOfAnyTemplate[] = { - { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_MAY_STREAM | SEC_ASN1_XTRN , 0, - SEC_ASN1_SUB(SEC_AnyTemplate) } -}; - -const SEC_ASN1Template sec_PKCS12NestedSafeContentsDecodeTemplate[] = { - { SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0, - offsetof(sec_PKCS12SafeContents, encodedSafeBags), - sec_PKCS12SequenceOfAnyTemplate } -}; - -const SEC_ASN1Template sec_PKCS12SafeContentsDecodeTemplate[] = { - { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_MAY_STREAM | SEC_ASN1_XTRN , - offsetof(sec_PKCS12SafeContents, encodedSafeBags), - SEC_ASN1_SUB(SEC_AnyTemplate) } -}; - -const SEC_ASN1Template sec_PKCS12CRLBagTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(sec_PKCS12CRLBag) }, - { SEC_ASN1_OBJECT_ID, offsetof(sec_PKCS12CRLBag, bagID) }, - { SEC_ASN1_DYNAMIC | SEC_ASN1_POINTER, - offsetof(sec_PKCS12CRLBag, value), &sec_pkcs12_crl_bag_chooser }, - { 0 } -}; - -const SEC_ASN1Template sec_PKCS12CertBagTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(sec_PKCS12CertBag) }, - { SEC_ASN1_OBJECT_ID, offsetof(sec_PKCS12CertBag, bagID) }, - { SEC_ASN1_DYNAMIC | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | - SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(sec_PKCS12CertBag, value), &sec_pkcs12_cert_bag_chooser }, - { 0 } -}; - -const SEC_ASN1Template sec_PKCS12SecretBagTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(sec_PKCS12SecretBag) }, - { SEC_ASN1_OBJECT_ID, offsetof(sec_PKCS12SecretBag, secretType) }, - { SEC_ASN1_ANY, offsetof(sec_PKCS12SecretBag, secretContent) }, - { 0 } -}; - -const SEC_ASN1Template sec_PKCS12AttributeTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(sec_PKCS12Attribute) }, - { SEC_ASN1_OBJECT_ID, offsetof(sec_PKCS12Attribute, attrType) }, - { SEC_ASN1_SET_OF | SEC_ASN1_DYNAMIC, - offsetof(sec_PKCS12Attribute, attrValue), - &sec_pkcs12_attr_chooser }, - { 0 } -}; diff --git a/security/nss/lib/pkcs12/pkcs12.h b/security/nss/lib/pkcs12/pkcs12.h deleted file mode 100644 index e84a69f6b..000000000 --- a/security/nss/lib/pkcs12/pkcs12.h +++ /dev/null @@ -1,74 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -#ifndef _PKCS12_H_ -#define _PKCS12_H_ - -#include "pkcs12t.h" -#include "p12.h" - -SEC_BEGIN_PROTOS - -typedef SECItem * (* SEC_PKCS12GetPassword)(void *arg); - -/* Decode functions */ -/* Import a PFX item. - * der_pfx is the der-encoded pfx item to import. - * pbef, and pbefarg are used to retrieve passwords for the HMAC, - * and any passwords needed for passing to PKCS5 encryption - * routines. - * algorithm is the algorithm by which private keys are stored in - * the key database. this could be a specific algorithm or could - * be based on a global setting. - * slot is the slot to where the certificates will be placed. if NULL, - * the internal key slot is used. - * If the process is successful, a SECSuccess is returned, otherwise - * a failure occurred. - */ -SECStatus -SEC_PKCS12PutPFX(SECItem *der_pfx, SECItem *pwitem, - SEC_PKCS12NicknameCollisionCallback ncCall, - PK11SlotInfo *slot, void *wincx); - -/* check the first two bytes of a file to make sure that it matches - * the desired header for a PKCS 12 file - */ -PRBool SEC_PKCS12ValidData(char *buf, int bufLen, long int totalLength); - -SEC_END_PROTOS - -#endif diff --git a/security/nss/lib/pkcs12/pkcs12t.h b/security/nss/lib/pkcs12/pkcs12t.h deleted file mode 100644 index 45206f4e9..000000000 --- a/security/nss/lib/pkcs12/pkcs12t.h +++ /dev/null @@ -1,398 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1994-2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef _PKCS12T_H_ -#define _PKCS12T_H_ - -#include "seccomon.h" -#include "secoid.h" -#include "cert.h" -#include "key.h" -#include "plarena.h" -#include "secpkcs7.h" -#include "secdig.h" /* for SGNDigestInfo */ - -typedef enum { - SECPKCS12TargetTokenNoCAs, /* CA get loaded intothe fixed token, - * User certs go to target token */ - SECPKCS12TargetTokenIntermediateCAs, /* User certs and intermediates go to - * target token, root certs got to - * fixed token */ - SECPKCS12TargetTokenAllCAs /* All certs go to target token */ -} SECPKCS12TargetTokenCAs; - -/* PKCS12 Structures */ -typedef struct SEC_PKCS12PFXItemStr SEC_PKCS12PFXItem; -typedef struct SEC_PKCS12MacDataStr SEC_PKCS12MacData; -typedef struct SEC_PKCS12AuthenticatedSafeStr SEC_PKCS12AuthenticatedSafe; -typedef struct SEC_PKCS12BaggageItemStr SEC_PKCS12BaggageItem; -typedef struct SEC_PKCS12BaggageStr SEC_PKCS12Baggage; -typedef struct SEC_PKCS12Baggage_OLDStr SEC_PKCS12Baggage_OLD; -typedef struct SEC_PKCS12ESPVKItemStr SEC_PKCS12ESPVKItem; -typedef struct SEC_PKCS12PVKSupportingDataStr SEC_PKCS12PVKSupportingData; -typedef struct SEC_PKCS12PVKAdditionalDataStr SEC_PKCS12PVKAdditionalData; -typedef struct SEC_PKCS12SafeContentsStr SEC_PKCS12SafeContents; -typedef struct SEC_PKCS12SafeBagStr SEC_PKCS12SafeBag; -typedef struct SEC_PKCS12PrivateKeyStr SEC_PKCS12PrivateKey; -typedef struct SEC_PKCS12PrivateKeyBagStr SEC_PKCS12PrivateKeyBag; -typedef struct SEC_PKCS12CertAndCRLBagStr SEC_PKCS12CertAndCRLBag; -typedef struct SEC_PKCS12CertAndCRLStr SEC_PKCS12CertAndCRL; -typedef struct SEC_PKCS12X509CertCRLStr SEC_PKCS12X509CertCRL; -typedef struct SEC_PKCS12SDSICertStr SEC_PKCS12SDSICert; -typedef struct SEC_PKCS12SecretStr SEC_PKCS12Secret; -typedef struct SEC_PKCS12SecretAdditionalStr SEC_PKCS12SecretAdditional; -typedef struct SEC_PKCS12SecretItemStr SEC_PKCS12SecretItem; -typedef struct SEC_PKCS12SecretBagStr SEC_PKCS12SecretBag; - -typedef SECItem *(* SEC_PKCS12PasswordFunc)(SECItem *args); - -/* PKCS12 types */ - -/* stores shrouded keys */ -struct SEC_PKCS12BaggageStr -{ - PRArenaPool *poolp; - SEC_PKCS12BaggageItem **bags; - - int luggage_size; /* used locally */ -}; - -/* additional data to be associated with keys. currently there - * is nothing defined to be stored here. allows future expansion. - */ -struct SEC_PKCS12PVKAdditionalDataStr -{ - PRArenaPool *poolp; - SECOidData *pvkAdditionalTypeTag; /* used locally */ - SECItem pvkAdditionalType; - SECItem pvkAdditionalContent; -}; - -/* cert and other supporting data for private keys. used - * for both shrouded and non-shrouded keys. - */ -struct SEC_PKCS12PVKSupportingDataStr -{ - PRArenaPool *poolp; - SGNDigestInfo **assocCerts; - SECItem regenerable; - SECItem nickname; - SEC_PKCS12PVKAdditionalData pvkAdditional; - SECItem pvkAdditionalDER; - - SECItem uniNickName; - /* used locally */ - int nThumbs; -}; - -/* shrouded key structure. supports only pkcs8 shrouding - * currently. - */ -struct SEC_PKCS12ESPVKItemStr -{ - PRArenaPool *poolp; /* used locally */ - SECOidData *espvkTag; /* used locally */ - SECItem espvkOID; - SEC_PKCS12PVKSupportingData espvkData; - union - { - SECKEYEncryptedPrivateKeyInfo *pkcs8KeyShroud; - } espvkCipherText; - - PRBool duplicate; /* used locally */ - PRBool problem_cert; /* used locally */ - PRBool single_cert; /* used locally */ - int nCerts; /* used locally */ - SECItem derCert; /* used locally */ -}; - -/* generic bag store for the safe. safeBagType identifies - * the type of bag stored. - */ -struct SEC_PKCS12SafeBagStr -{ - PRArenaPool *poolp; - SECOidData *safeBagTypeTag; /* used locally */ - SECItem safeBagType; - union - { - SEC_PKCS12PrivateKeyBag *keyBag; - SEC_PKCS12CertAndCRLBag *certAndCRLBag; - SEC_PKCS12SecretBag *secretBag; - } safeContent; - - SECItem derSafeContent; - SECItem safeBagName; - - SECItem uniSafeBagName; -}; - -/* stores private keys and certificates in a list. each safebag - * has an ID identifying the type of content stored. - */ -struct SEC_PKCS12SafeContentsStr -{ - PRArenaPool *poolp; - SEC_PKCS12SafeBag **contents; - - /* used for tracking purposes */ - int safe_size; - PRBool old; - PRBool swapUnicode; - PRBool possibleSwapUnicode; -}; - -/* private key structure which holds encrypted private key and - * supporting data including nickname and certificate thumbprint. - */ -struct SEC_PKCS12PrivateKeyStr -{ - PRArenaPool *poolp; - SEC_PKCS12PVKSupportingData pvkData; - SECKEYPrivateKeyInfo pkcs8data; /* borrowed from PKCS 8 */ - - PRBool duplicate; /* used locally */ - PRBool problem_cert;/* used locally */ - PRBool single_cert; /* used locally */ - int nCerts; /* used locally */ - SECItem derCert; /* used locally */ -}; - -/* private key bag, holds a (null terminated) list of private key - * structures. - */ -struct SEC_PKCS12PrivateKeyBagStr -{ - PRArenaPool *poolp; - SEC_PKCS12PrivateKey **privateKeys; - - int bag_size; /* used locally */ -}; - -/* container to hold certificates. currently supports x509 - * and sdsi certificates - */ -struct SEC_PKCS12CertAndCRLStr -{ - PRArenaPool *poolp; - SECOidData *BagTypeTag; /* used locally */ - SECItem BagID; - union - { - SEC_PKCS12X509CertCRL *x509; - SEC_PKCS12SDSICert *sdsi; - } value; - - SECItem derValue; - SECItem nickname; /* used locally */ - PRBool duplicate; /* used locally */ -}; - -/* x509 certificate structure. typically holds the der encoding - * of the x509 certificate. thumbprint contains a digest of the - * certificate - */ -struct SEC_PKCS12X509CertCRLStr -{ - PRArenaPool *poolp; - SEC_PKCS7ContentInfo certOrCRL; - SGNDigestInfo thumbprint; - - SECItem *derLeafCert; /* used locally */ -}; - -/* sdsi certificate structure. typically holds the der encoding - * of the sdsi certificate. thumbprint contains a digest of the - * certificate - */ -struct SEC_PKCS12SDSICertStr -{ - PRArenaPool *poolp; - SECItem value; - SGNDigestInfo thumbprint; -}; - -/* contains a null terminated list of certs and crls */ -struct SEC_PKCS12CertAndCRLBagStr -{ - PRArenaPool *poolp; - SEC_PKCS12CertAndCRL **certAndCRLs; - - int bag_size; /* used locally */ -}; - -/* additional secret information. currently no information - * stored in this structure. - */ -struct SEC_PKCS12SecretAdditionalStr -{ - PRArenaPool *poolp; - SECOidData *secretTypeTag; /* used locally */ - SECItem secretAdditionalType; - SECItem secretAdditionalContent; -}; - -/* secrets container. this will be used to contain currently - * unspecified secrets. (it's a secret) - */ -struct SEC_PKCS12SecretStr -{ - PRArenaPool *poolp; - SECItem secretName; - SECItem value; - SEC_PKCS12SecretAdditional secretAdditional; - - SECItem uniSecretName; -}; - -struct SEC_PKCS12SecretItemStr -{ - PRArenaPool *poolp; - SEC_PKCS12Secret secret; - SEC_PKCS12SafeBag subFolder; -}; - -/* a bag of secrets. holds a null terminated list of secrets. - */ -struct SEC_PKCS12SecretBagStr -{ - PRArenaPool *poolp; - SEC_PKCS12SecretItem **secrets; - - int bag_size; /* used locally */ -}; - -struct SEC_PKCS12MacDataStr -{ - SGNDigestInfo safeMac; - SECItem macSalt; -}; - -/* outer transfer unit */ -struct SEC_PKCS12PFXItemStr -{ - PRArenaPool *poolp; - SEC_PKCS12MacData macData; - SEC_PKCS7ContentInfo authSafe; - - /* for compatibility with beta */ - PRBool old; - SGNDigestInfo old_safeMac; - SECItem old_macSalt; - - /* compatibility between platforms for unicode swapping */ - PRBool swapUnicode; -}; - -struct SEC_PKCS12BaggageItemStr { - PRArenaPool *poolp; - SEC_PKCS12ESPVKItem **espvks; - SEC_PKCS12SafeBag **unencSecrets; - - int nEspvks; - int nSecrets; -}; - -/* stores shrouded keys */ -struct SEC_PKCS12Baggage_OLDStr -{ - PRArenaPool *poolp; - SEC_PKCS12ESPVKItem **espvks; - - int luggage_size; /* used locally */ -}; - -/* authenticated safe, stores certs, keys, and shrouded keys */ -struct SEC_PKCS12AuthenticatedSafeStr -{ - PRArenaPool *poolp; - SECItem version; - SECOidData *transportTypeTag; /* local not part of encoding*/ - SECItem transportMode; - SECItem privacySalt; - SEC_PKCS12Baggage baggage; - SEC_PKCS7ContentInfo *safe; - - /* used for beta compatibility */ - PRBool old; - PRBool emptySafe; - SEC_PKCS12Baggage_OLD old_baggage; - SEC_PKCS7ContentInfo old_safe; - PRBool swapUnicode; -}; -#define SEC_PKCS12_PFX_VERSION 1 /* what we create */ - - - -/* PKCS 12 Templates */ -extern const SEC_ASN1Template SEC_PKCS12PFXItemTemplate_OLD[]; -extern const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate_OLD[]; -extern const SEC_ASN1Template SEC_PKCS12BaggageTemplate_OLD[]; -extern const SEC_ASN1Template SEC_PKCS12PFXItemTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12MacDataTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12AuthenticatedSafeTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12BaggageTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12PVKAdditionalTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate_OLD[]; -extern const SEC_ASN1Template SEC_PKCS12SafeContentsTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12SafeBagTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12PrivateKeyTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12PrivateKeyBagTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12CertAndCRLTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12CertAndCRLBagTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate_OLD[]; -extern const SEC_ASN1Template SEC_PKCS12X509CertCRLTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12SDSICertTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12SecretBagTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12SecretTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12SecretItemTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12SecretAdditionalTemplate[]; -extern const SEC_ASN1Template SGN_DigestInfoTemplate[]; -extern const SEC_ASN1Template SEC_PointerToPKCS12KeyBagTemplate[]; -extern const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate[]; -extern const SEC_ASN1Template SEC_PointerToPKCS12CertAndCRLBagTemplate_OLD[]; -extern const SEC_ASN1Template SEC_PointerToPKCS12SecretBagTemplate[]; -extern const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate_OLD[]; -extern const SEC_ASN1Template SEC_PointerToPKCS12X509CertCRLTemplate[]; -extern const SEC_ASN1Template SEC_PointerToPKCS12SDSICertTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12CodedSafeBagTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12CodedCertBagTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12CodedCertAndCRLBagTemplate[]; -extern const SEC_ASN1Template SEC_PKCS12PVKSupportingDataTemplate_OLD[]; -extern const SEC_ASN1Template SEC_PKCS12ESPVKItemTemplate_OLD[]; -#endif |