]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_pkcs12/lib/pkcs12Encode.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / libsecurity_pkcs12 / lib / pkcs12Encode.cpp
diff --git a/libsecurity_pkcs12/lib/pkcs12Encode.cpp b/libsecurity_pkcs12/lib/pkcs12Encode.cpp
deleted file mode 100644 (file)
index d99c399..0000000
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved.
- * 
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-/*
- * pkcs12Encode.h - P12Coder encoding engine.
- * 
- * Unlike the decoding side of P12Coder, which can parse PFXs with
- * more or less arbitrary structures, this encoding engine has 
- * a specific layout for what bags go where in the jungle of 
- * SafeContents and ContentInfos. It would be impractical to allow
- * (or to expect) the app to specify this structure. 
- *
- * The knowledge of how a PFX is built out of various components
- * is encapsulated in the authSafeBuild() member function. The rest
- * of the functions in this file are pretty much "PFX-structure-
- * agnostic", so if one wanted to change the overall PFX structure,
- * one would only have to focus on the authSafeBuild() function. 
- */
-
-#include "pkcs12Coder.h"
-#include "pkcs12Debug.h"
-#include "pkcs12Crypto.h"
-#include "pkcs12Templates.h"
-#include "pkcs12Utils.h"
-#include <Security/cssmerr.h>
-#include <Security/oidsattr.h>
-#include <Security/SecBase.h>
-
-void P12Coder::encode(
-       CFDataRef                               *cpfx)          // RETURNED
-{
-       p12EncodeLog("encode top");
-       SecNssCoder localCdr;
-       NSS_P12_DecodedPFX pfx;
-       
-       memset(&pfx, 0, sizeof(pfx));
-       p12IntToData(3, pfx.version, localCdr);
-       authSafeBuild(pfx.authSafe, localCdr);
-       macSignPfx(pfx, localCdr);
-       CSSM_DATA derPfx = {0, NULL};
-       if(localCdr.encodeItem(&pfx, NSS_P12_DecodedPFXTemplate, derPfx)) {
-               p12ErrorLog("Error encoding top-level pfx\n");
-               P12_THROW_ENCODE;
-       }
-       CFDataRef cp = CFDataCreate(NULL, derPfx.Data, derPfx.Length);
-       *cpfx = cp;
-}
-
-void P12Coder::macSignPfx(
-       NSS_P12_DecodedPFX &pfx,
-       SecNssCoder &localCdr)
-{
-       p12EncodeLog("macSignPfx");
-       NSS_P12_MacData *macData = localCdr.mallocn<NSS_P12_MacData>();
-       pfx.macData = macData;
-       p12GenSalt(macData->macSalt, localCdr);
-       p12IntToData(mMacIterCount, macData->iterations, localCdr);
-       NSS_P7_DigestInfo &digInfo = macData->mac;
-       
-       /* this is not negotiable; it's the only one P12 allows */
-       localCdr.allocCopyItem(CSSMOID_SHA1, digInfo.digestAlgorithm.algorithm);
-       /* null algorithm parameters */
-       p12NullAlgParams(digInfo.digestAlgorithm);
-       
-       const CSSM_DATA *macPhrase = getMacPassPhrase();
-       const CSSM_KEY *macPassKey = getMacPassKey();
-       if((macPhrase == NULL) && (macPassKey == NULL)) {
-               p12ErrorLog("no passphrase set\n");
-               CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE);
-       }
-       
-       CSSM_RETURN crtn = p12GenMac(mCspHand, 
-               *pfx.authSafe.content.data, 
-               CSSM_ALGID_SHA1, mMacIterCount, macData->macSalt, 
-               macPhrase, macPassKey, localCdr, digInfo.digest);
-       if(crtn) {
-               p12ErrorLog("Error generating PFX MAC\n");
-               CssmError::throwMe(crtn);
-       }
-}
-
-/*
- * This is the heart of the encoding engine. All knowledge of 
- * "what bags go where" is here. The PFX structure implemented here
- * is derived from empirical observation of PFXs obtained from
- * Mozilla 1.2b and from the DoD test vectors for "Conformance 
- * Testing of Relying Party Client Certificate Path Processing 
- * Logic", written by Cygnacom, Septemtber 28, 2001. 
- *
- * The PFX structure is as follows:
- *
- * -- One AuthenticatedSafe element (a PKCS7 ContentInfo) containing
- *    all certificates and CRLs. 
- *
- *    ContentInfo.type = CT_EncryptedData
- *    Encryption algorithm is our "weak" encryption Alg, default 
- *        of CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4.
- *
- * -- One AuthenticatedSafe element containing all private keys in
- *    the form of ShroudedKeyBags.
- *
- *    ContentInfo.type = CT_Data
- *    Encryption algorithm for shrouded key bags is our "strong"
- *        encryption, default CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC
- *
- * -- Everything else goes in another AuthenticatedSafe element.
- *
- *    ContentInfo.type = CT_EncryptedData
- *    Encryption algorithm is our "strong" encryption Alg
- */
-void P12Coder::authSafeBuild(
-       NSS_P7_DecodedContentInfo &authSafe,
-       SecNssCoder &localCdr)
-{
-       p12EncodeLog("authSafeBuild top");
-
-       /* how many contentInfos are we going to build? */
-       unsigned numContents = 0;
-       if(mCerts.size() || mCrls.size()) {
-               numContents++;
-       }
-       if(mKeys.size()) {
-               numContents++;
-       }
-       if(mOpaques.size()) {
-               numContents++;
-       }
-
-       if(numContents == 0) {
-               p12ErrorLog("authSafeBuild: no contents\n");
-               MacOSError::throwMe(errSecParam);
-       }
-       
-       NSS_P7_DecodedContentInfo **contents = 
-               (NSS_P7_DecodedContentInfo **)p12NssNullArray(numContents, 
-                       localCdr);
-       unsigned contentDex = 0;
-       
-       NSS_P12_SafeBag **safeBags;
-
-       /* certs & crls */
-       unsigned numBags = (unsigned)(mCerts.size() + mCrls.size());
-       p12EncodeLog("authSafeBuild : %u certs + CRLS", numBags);
-       if(numBags) {
-               safeBags = (NSS_P12_SafeBag **)p12NssNullArray(numBags, localCdr);
-               unsigned bagDex = 0;
-               for(unsigned dex=0; dex<mCerts.size(); dex++) {
-                       safeBags[bagDex++] = certBagBuild(mCerts[dex], localCdr);
-               } 
-               for(unsigned dex=0; dex<mCrls.size(); dex++) {
-                       safeBags[bagDex++] = crlBagBuild(mCrls[dex], localCdr);
-               } 
-               contents[contentDex++] = safeContentsBuild(safeBags, 
-                       CT_EncryptedData, &mWeakEncrAlg, mWeakEncrIterCount, localCdr);
-       }
-       
-       /* shrouded keys - encrypted at bag level */
-       numBags = (unsigned)mKeys.size();
-       if(numBags) {
-               p12EncodeLog("authSafeBuild : %u keys", numBags);
-               safeBags = (NSS_P12_SafeBag **)p12NssNullArray(numBags, localCdr);
-               unsigned bagDex = 0;
-               for(unsigned dex=0; dex<numBags; dex++) {
-                       safeBags[bagDex++] = keyBagBuild(mKeys[dex], localCdr);
-               } 
-               contents[contentDex++] = safeContentsBuild(safeBags, 
-                       CT_Data, NULL, 0, localCdr);
-       }
-       
-       /* opaque */
-       numBags = (unsigned)mOpaques.size();
-       if(numBags) {
-               p12EncodeLog("authSafeBuild : %u opaques", numBags);
-               safeBags = (NSS_P12_SafeBag **)p12NssNullArray(numBags, localCdr);
-               unsigned bagDex = 0;
-               for(unsigned dex=0; dex<numBags; dex++) {
-                       safeBags[bagDex++] = opaqueBagBuild(mOpaques[dex], localCdr);
-               } 
-               contents[contentDex++] = safeContentsBuild(safeBags, 
-                       CT_EncryptedData, &mStrongEncrAlg, mStrongEncrIterCount, localCdr);
-       }
-       
-       /*
-        * Encode the whole elements array into authSafe.content.data
-        */
-       NSS_P12_AuthenticatedSafe safe;
-       safe.info = contents;
-       CSSM_DATA *adata = localCdr.mallocn<CSSM_DATA>();
-       authSafe.content.data = adata;
-       adata->Data = NULL;
-       adata->Length = 0;
-       if(localCdr.encodeItem(&safe, NSS_P12_AuthenticatedSafeTemplate,
-                       *adata)) {
-               p12ErrorLog("authSafeBuild: error encoding auth safe\n");
-               P12_THROW_ENCODE;
-       }
-       authSafe.type = CT_Data;
-       authSafe.contentType = CSSMOID_PKCS7_Data;
-}
-
-/*
- * Build a AuthSafe element of specified type out of the 
- * specified array of bags.
- */
-NSS_P7_DecodedContentInfo *P12Coder::safeContentsBuild(
-       NSS_P12_SafeBag **bags,
-       NSS_P7_CI_Type type,    // CT_Data, CT_EncryptedData
-       CSSM_OID *encrOid,              // only for CT_EncryptedData
-       unsigned iterCount,             // ditto
-       SecNssCoder &localCdr)
-{
-       p12EncodeLog("safeContentsBuild type %u", (unsigned)type);
-
-       /*
-        * First, encode the bag array as a SafeContents
-        */
-       CSSM_DATA encSafeContents = {0, NULL};
-       NSS_P12_SafeContents safeContents = {bags};
-       if(localCdr.encodeItem(&safeContents,
-                       NSS_P12_SafeContentsTemplate, encSafeContents)) {
-               p12ErrorLog("error encoding SafeContents\n");
-               P12_THROW_ENCODE;
-       }
-       
-       NSS_P7_DecodedContentInfo *dci = 
-               localCdr.mallocn<NSS_P7_DecodedContentInfo>();
-       dci->type = type;
-       if(type == CT_Data) {
-               /* plaintext gets encoded as an octet string */
-               localCdr.allocCopyItem(CSSMOID_PKCS7_Data, dci->contentType);
-               dci->content.data = localCdr.mallocn<CSSM_DATA>();
-               localCdr.allocCopyItem(encSafeContents, *dci->content.data);
-       }
-       else if(type == CT_EncryptedData) {
-               /* encrypt the encoded SafeContents */
-               localCdr.allocCopyItem(CSSMOID_PKCS7_EncryptedData, 
-                       dci->contentType);
-               dci->content.encryptData = localCdr.mallocn<NSS_P7_EncryptedData>();
-               NSS_P7_EncryptedData *ed = dci->content.encryptData;
-               assert(encrOid != NULL);
-               encryptData(encSafeContents, *encrOid, iterCount, *ed, localCdr);
-       }
-       else {
-               p12ErrorLog("bad type in safeContentsBuild\n");
-               CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
-       }
-       return dci;
-}
-
-/*
- * Encrypt the specified plaintext with specified algorithm.
- * Drop result and other interesting info into an NSS_P7_EncryptedData.
- */
-void P12Coder::encryptData(
-       const CSSM_DATA                 &ptext,
-       CSSM_OID                                &encrOid,
-       unsigned                                iterCount,
-       NSS_P7_EncryptedData    &ed,
-       SecNssCoder                             &localCdr)
-{
-       p12EncodeLog("encryptData");
-
-       /* do the raw encrypt first to make sure we can do it... */
-       CSSM_ALGORITHMS         keyAlg;                 // e.g., CSSM_ALGID_DES
-       CSSM_ALGORITHMS         encrAlg;                // e.g., CSSM_ALGID_3DES_3KEY_EDE
-       CSSM_ALGORITHMS         pbeHashAlg;             // SHA1 or MD5
-       uint32                          keySizeInBits;
-       uint32                          blockSizeInBytes;       // for IV, optional
-       CSSM_PADDING            padding;                // CSSM_PADDING_PKCS7, etc.
-       CSSM_ENCRYPT_MODE       mode;                   // CSSM_ALGMODE_CBCPadIV8, etc.
-       PKCS_Which                      pkcs;
-       
-       bool found = pkcsOidToParams(&encrOid,
-               keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes,
-               padding, mode, pkcs);
-       if(!found || (pkcs != PW_PKCS12)) {
-               p12ErrorLog("encryptData encrAlg not understood\n");
-               CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
-       }
-       
-       /* Salt: we generate random bytes */
-       CSSM_DATA salt;
-       p12GenSalt(salt, localCdr);
-
-       const CSSM_DATA *pwd = getEncrPassPhrase();
-       const CSSM_KEY *passKey = getEncrPassKey();
-       if((pwd == NULL) && (passKey == NULL)) {
-               p12ErrorLog("no passphrase set\n");
-               CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE);
-       }
-       CSSM_DATA ctext = {0, NULL};
-       
-       CSSM_RETURN crtn = p12Encrypt(mCspHand, ptext, 
-               keyAlg, encrAlg, pbeHashAlg,
-               keySizeInBits, blockSizeInBytes,
-               padding, mode,
-               iterCount, salt,
-               pwd, passKey, localCdr,
-               ctext);
-       if(crtn) {
-               CssmError::throwMe(crtn);
-       }
-       
-       /* Now fill in the NSS_P7_EncryptedData */
-       p12IntToData(0, ed.version, localCdr);
-       NSS_P7_EncrContentInfo &eci = ed.contentInfo;
-       localCdr.allocCopyItem(CSSMOID_PKCS7_Data, eci.contentType);
-       algIdBuild(eci.encrAlg, encrOid, salt, iterCount, localCdr);
-       eci.encrContent = ctext;
-}
-
-/* 
- * Fill in an CSSM_X509_ALGORITHM_IDENTIFIER with parameters in
- * the form of an encoded NSS_P12_PBE_Params
- */
-void P12Coder::algIdBuild(
-       CSSM_X509_ALGORITHM_IDENTIFIER  &algId,
-       const CSSM_OID &algOid,
-       const CSSM_DATA &salt,
-       unsigned iterCount,
-       SecNssCoder &localCdr)
-{
-       p12EncodeLog("algIdBuild");
-       localCdr.allocCopyItem(algOid, algId.algorithm);
-       NSS_P12_PBE_Params pbeParams;
-       pbeParams.salt = salt;
-       p12IntToData(iterCount, pbeParams.iterations, localCdr);
-       if(localCdr.encodeItem(&pbeParams, NSS_P12_PBE_ParamsTemplate,
-                       algId.parameters)) {
-               p12ErrorLog("error encoding NSS_P12_PBE_Params\n");
-               P12_THROW_ENCODE;
-       }
-}
-
-#pragma mark --- Individual Bag Builders ---
-
-NSS_P12_SafeBag *P12Coder::certBagBuild(
-       P12CertBag *cert,
-       SecNssCoder &localCdr)
-{
-       p12EncodeLog("certBagBuild");
-
-       NSS_P12_SafeBag *safeBag = localCdr.mallocn<NSS_P12_SafeBag>();
-       safeBag->bagId = CSSMOID_PKCS12_certBag;
-       safeBag->type = BT_CertBag;
-       
-       NSS_P12_CertBag *certBag = localCdr.mallocn<NSS_P12_CertBag>();
-       safeBag->bagValue.certBag = certBag;
-       const CSSM_OID *certTypeOid = NULL;
-       switch(cert->certType()) {
-               case CT_X509:
-                       certTypeOid = &CSSMOID_PKCS9_X509Certificate;
-                       break;
-               case CT_SDSI:
-                       certTypeOid = &CSSMOID_PKCS9_SdsiCertificate;
-                       break;
-               default:
-                       p12ErrorLog("unknown certType on encode\n");
-                       CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
-                       
-       }
-       
-       /* copies not needed, same scope as P12CertBag */
-       certBag->bagType = *certTypeOid;
-       certBag->type = cert->certType();
-       certBag->certValue = cert->certData();
-       safeBag->bagAttrs = cert->getAllAttrs();
-       return safeBag;
-}
-
-NSS_P12_SafeBag *P12Coder::crlBagBuild(
-       P12CrlBag *crl,
-       SecNssCoder &localCdr)
-{
-       p12EncodeLog("crlBagBuild");
-
-       NSS_P12_SafeBag *safeBag = localCdr.mallocn<NSS_P12_SafeBag>();
-       safeBag->bagId = CSSMOID_PKCS12_crlBag;
-       safeBag->type = BT_CrlBag;
-       
-       NSS_P12_CrlBag *crlBag = localCdr.mallocn<NSS_P12_CrlBag>();
-       safeBag->bagValue.crlBag = crlBag;
-       const CSSM_OID *crlTypeOid = NULL;
-       switch(crl->crlType()) {
-               case CRT_X509:
-                       crlTypeOid = &CSSMOID_PKCS9_X509Crl;
-                       break;
-               default:
-                       p12ErrorLog("unknown crlType on encode\n");
-                       CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
-                       
-       }
-       
-       /* copies not needed, same scope as P12CrlBag */
-       crlBag->bagType = *crlTypeOid;
-       crlBag->type = crl->crlType();
-       crlBag->crlValue = crl->crlData();
-       safeBag->bagAttrs = crl->getAllAttrs();
-       return safeBag;
-}
-
-NSS_P12_SafeBag *P12Coder::keyBagBuild(
-       P12KeyBag *key,
-       SecNssCoder &localCdr)
-{
-       p12EncodeLog("keyBagBuild");
-
-       NSS_P12_SafeBag *safeBag = localCdr.mallocn<NSS_P12_SafeBag>();
-       safeBag->bagId = CSSMOID_PKCS12_shroudedKeyBag;
-       safeBag->type = BT_ShroudedKeyBag;
-       
-       NSS_EncryptedPrivateKeyInfo *keyInfo = localCdr.
-               mallocn<NSS_EncryptedPrivateKeyInfo>();
-       safeBag->bagValue.shroudedKeyBag = keyInfo;
-       safeBag->bagAttrs = key->getAllAttrs();
-
-       /* Prepare for key wrap */
-       CSSM_DATA salt;
-       p12GenSalt(salt, localCdr);
-       algIdBuild(keyInfo->algorithm, mStrongEncrAlg, salt, 
-               mStrongEncrIterCount, localCdr);
-       
-       CSSM_ALGORITHMS         keyAlg;                 // e.g., CSSM_ALGID_DES
-       CSSM_ALGORITHMS         encrAlg;                // e.g., CSSM_ALGID_3DES_3KEY_EDE
-       CSSM_ALGORITHMS         pbeHashAlg;             // SHA1 or MD5
-       uint32                          keySizeInBits;
-       uint32                          blockSizeInBytes;       // for IV, optional
-       CSSM_PADDING            padding;                // CSSM_PADDING_PKCS7, etc.
-       CSSM_ENCRYPT_MODE       mode;                   // CSSM_ALGMODE_CBCPadIV8, etc.
-       PKCS_Which                      pkcs;
-       
-       bool found = pkcsOidToParams(&mStrongEncrAlg,
-               keyAlg, encrAlg, pbeHashAlg, keySizeInBits, blockSizeInBytes,
-               padding, mode, pkcs);
-       if(!found || (pkcs != PW_PKCS12)) {
-               /* app config error - they gave us bogus algorithm */
-               p12ErrorLog("keyBagBuild encrAlg not understood\n");
-               CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
-       }
-       const CSSM_DATA *encrPhrase = getEncrPassPhrase();
-       const CSSM_KEY *passKey = getEncrPassKey();
-       if((encrPhrase == NULL) && (passKey == NULL)) {
-               p12ErrorLog("no passphrase set\n");
-               CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_PASSPHRASE);
-       }
-       CSSM_DATA shroudedBits = {0, NULL};
-       
-       CSSM_RETURN crtn = p12WrapKey(mCspHand,
-               key->key(), key->privKeyCreds(),
-               keyAlg, encrAlg, pbeHashAlg,
-               keySizeInBits, blockSizeInBytes,
-               padding, mode,
-               mStrongEncrIterCount, salt,
-               encrPhrase,
-               passKey,
-               localCdr, 
-               shroudedBits);
-       if(crtn) {
-               p12ErrorLog("Error wrapping private key\n");
-               CssmError::throwMe(crtn);
-       }
-       
-       keyInfo->encryptedData = shroudedBits;
-       return safeBag;
-}
-
-NSS_P12_SafeBag *P12Coder::opaqueBagBuild(
-       P12OpaqueBag *opaque,
-       SecNssCoder &localCdr)
-{
-       p12EncodeLog("opaqueBagBuild");
-       NSS_P12_SafeBag *safeBag = localCdr.mallocn<NSS_P12_SafeBag>();
-       safeBag->bagId = opaque->oid();
-       safeBag->bagValue.secretBag = &opaque->blob();
-       safeBag->bagAttrs = opaque->getAllAttrs();
-       return safeBag;
-}