diff -r 000000000000 -r 2c201484c85f cryptoservices/certificateandkeymgmt/pkcs12/pkcs12bags.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cryptoservices/certificateandkeymgmt/pkcs12/pkcs12bags.cpp Wed Jul 08 11:25:26 2009 +0100 @@ -0,0 +1,406 @@ +/* +* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include "pkcs12bags.h" + +using namespace PKCS12; +///////////////////////// KeyBag //////////////////////////////// + +CDecPkcs12KeyBag::CDecPkcs12KeyBag() + { + } + +EXPORT_C CDecPkcs12KeyBag* CDecPkcs12KeyBag::NewL(const TDesC8& aSafeBagData) + { + CDecPkcs12KeyBag* self = new(ELeave) CDecPkcs12KeyBag; + CleanupStack::PushL(self); + self->ConstructL(aSafeBagData); + CleanupStack::Pop(self); + return self; + } + +CDecPkcs12KeyBag::~CDecPkcs12KeyBag() + { + } + +void CDecPkcs12KeyBag::ConstructL(const TDesC8& aSafeBagData) + { + CDecPkcs12SafeBag::ConstructL(aSafeBagData); + } + +EXPORT_C CDecPKCS8Data* CDecPkcs12KeyBag::PrivateKeyInfoL() const + { + TASN1DecGeneric seqGen(iBagValue); + seqGen.InitL(); + if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal) + { + User::Leave(KErrArgument); + } + + return TASN1DecPKCS8::DecodeDERL(seqGen.Encoding()); + } + +////////////////////////// ShroudedKeyBag //////////////////////// +CDecPkcs12ShroudedKeyBag::CDecPkcs12ShroudedKeyBag() + { + } + +EXPORT_C CDecPkcs12ShroudedKeyBag* CDecPkcs12ShroudedKeyBag::NewL(const TDesC8& aSafeBagData) + { + CDecPkcs12ShroudedKeyBag* self = new(ELeave) CDecPkcs12ShroudedKeyBag; + CleanupStack::PushL(self); + self->ConstructL(aSafeBagData); + CleanupStack::Pop(self); + return self; + } + +CDecPkcs12ShroudedKeyBag::~CDecPkcs12ShroudedKeyBag() + { + } + +void CDecPkcs12ShroudedKeyBag::ConstructL(const TDesC8& aSafeBagData) + { + CDecPkcs12SafeBag::ConstructL(aSafeBagData); + TASN1DecGeneric seqGen(iBagValue); + seqGen.InitL(); + if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal) + { + User::Leave(KErrArgument); + } + + TASN1DecSequence dec; + CArrayPtrFlat* shroudedKeyBagSeq = dec.DecodeDERLC(seqGen); + TInt seqIndex = 0; + TInt shroudedKeyBagSeqCount = shroudedKeyBagSeq->Count(); + if (seqIndex >= shroudedKeyBagSeqCount) + { + User::Leave(KErrArgument); + } + CleanupStack::PopAndDestroy(shroudedKeyBagSeq); + } + +EXPORT_C CDecPKCS8Data* CDecPkcs12ShroudedKeyBag::PrivateKeyInfoL(TDesC& aPassword) const + { + TASN1DecGeneric seqGen(iBagValue); + seqGen.InitL(); + TASN1DecSequence dec; + CArrayPtrFlat* shroudedKeyBagSeq = dec.DecodeDERLC(seqGen); + // Get the first part of the sequence -> PKCS5 data + const TASN1DecGeneric* shroudedKeyBagSeqAt0 = shroudedKeyBagSeq->At(0); + TPtrC8 theContent(shroudedKeyBagSeqAt0->Encoding());// expect this to be a sequence + CPBEncryptParms* encryptParams = TASN1DecPKCS5::DecodeDERL(theContent); + CleanupStack::PushL(encryptParams); + + CPBEncryptElement* encryptElement; + HBufC8* pkcs12Pwd = PKCS12KDF::GeneratePasswordLC(aPassword); + if(encryptParams->Kdf() == CPBEncryptParms::EKdfPkcs12) + { + TPtrC8 iv = encryptParams->IV(); + HBufC8* ivValue = HBufC8::NewMaxLC(iv.Length()); + TPtr8 encryptKeyBuf = ivValue->Des(); + + switch(encryptParams->Cipher()) + { + case ECipherARC4_128: + case ECipherARC4_40: + { + //derive only key it is unnecessary to derive an IV for RC4 + break; + } + case ECipher3DES_CBC: + case ECipher2Key3DES_CBC: + case ECipherRC2_CBC_128_16: + case ECipherRC2_CBC_40_5: + { + PKCS12KDF::DeriveKeyL(encryptKeyBuf, PKCS12KDF::EIDByteIV, *pkcs12Pwd, encryptParams->Salt(), encryptParams->Iterations()); + encryptParams->SetIV(encryptKeyBuf); + break; + } + default: + { + User::Leave(KErrNotSupported); + break; + } + } + CleanupStack::PopAndDestroy(ivValue); + // Create the decryptor + encryptElement = CPBEncryptElement::NewLC(*pkcs12Pwd, *encryptParams); + } + else + { + TPBPassword password(aPassword); + // Create the decryptor + encryptElement = CPBEncryptElement::NewLC(password.Password(), *encryptParams); + } + CPBDecryptor* decryptor = encryptElement->NewDecryptLC(); + // Decrypt the final part of the sequence -> encrypted PKCS8 object + const TASN1DecGeneric* shroudedKeyBagSeqAt1 = shroudedKeyBagSeq->At(1); + if (shroudedKeyBagSeqAt1->Tag() != EASN1OctetString || shroudedKeyBagSeqAt1->Class() != EUniversal) + { + User::Leave(KErrArgument); + } + TPtrC8 encryptedKey(shroudedKeyBagSeqAt1->GetContentDER()); + TUint encryptLength = encryptedKey.Length(); + TUint maxDecryptLength = decryptor->MaxOutputLength(encryptLength); + if ( maxDecryptLength <= 0 ) + { + User::Leave(KErrGeneral); + } + HBufC8* decryptedContent = HBufC8::NewLC(encryptLength); + TPtr8 dcDes(decryptedContent->Des()); + decryptor->Process(encryptedKey, dcDes); + + CDecPKCS8Data* privateKeyInfo = TASN1DecPKCS8::DecodeDERL(dcDes); + + CleanupStack::PopAndDestroy(6,shroudedKeyBagSeq);//shroudedKeyBagSeq, encryptParams,pkcs12Pwd + // encryptElement, decryptor, decryptedContent. + return privateKeyInfo; + } + +///////////////////////////// CertBag /////////////////////////////// + +CDecPkcs12CertBag::CDecPkcs12CertBag() + { + } + +EXPORT_C CDecPkcs12CertBag* CDecPkcs12CertBag::NewL(const TDesC8& aSafeBagData) + { + CDecPkcs12CertBag* self = new (ELeave) CDecPkcs12CertBag; + CleanupStack::PushL(self); + self->ConstructL(aSafeBagData); + CleanupStack::Pop(self); + return self; + } + +CDecPkcs12CertBag::~CDecPkcs12CertBag() + { + delete iCertId; + } + +void CDecPkcs12CertBag::ConstructL(const TDesC8& aSafeBagData) + { + CDecPkcs12SafeBag::ConstructL(aSafeBagData); + + TASN1DecGeneric seqGen(iBagValue); + seqGen.InitL(); + if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal) + { + User::Leave(KErrArgument); + } + + TASN1DecSequence seq; + CArrayPtr* certBagSequence = seq.DecodeDERLC(seqGen); + const TASN1DecGeneric* certBagSequenceAt0 = certBagSequence->At(0); + if (certBagSequenceAt0->Tag() != EASN1ObjectIdentifier || certBagSequenceAt0->Class() != EUniversal) + { + User::Leave(KErrArgument); + } + + // Obtain the CertId + TASN1DecObjectIdentifier oid; + iCertId = oid.DecodeDERL(*certBagSequenceAt0); + + const TASN1DecGeneric* certBagSequenceAt1 = certBagSequence->At(1); + if (certBagSequenceAt1->Tag() != EASN1EOC || certBagSequenceAt1->Class() != EContextSpecific) + { + User::Leave(KErrArgument); + } + + TASN1DecGeneric certBagSeq(certBagSequenceAt1->GetContentDER()); + certBagSeq.InitL(); + if (certBagSeq.Tag() != EASN1OctetString || certBagSeq.Class() != EUniversal) + { + User::Leave(KErrArgument); + } + else + { + iCertValue.Set(certBagSeq.GetContentDER()); + } + CleanupStack::PopAndDestroy(certBagSequence); + } + +EXPORT_C const TDesC& CDecPkcs12CertBag::CertId() const + { + return *iCertId; + } + +EXPORT_C const TDesC8& CDecPkcs12CertBag::CertValue() const + { + return iCertValue; + } + +EXPORT_C CX509Certificate* CDecPkcs12CertBag::X509CertificateL() const + { + return (*iCertId == KX509CertificateOID) ? CX509Certificate::NewL(iCertValue) : NULL; + } + +/////////////////////// SafeContentsBag /////////////////////// + +CDecPkcs12SafeContentsBag::CDecPkcs12SafeContentsBag() + { + } + +EXPORT_C CDecPkcs12SafeContentsBag* CDecPkcs12SafeContentsBag::NewL(const TDesC8& aSafeContentsBagData) + { + CDecPkcs12SafeContentsBag* self = new(ELeave) CDecPkcs12SafeContentsBag; + CleanupStack::PushL(self); + self->ConstructL(aSafeContentsBagData); + CleanupStack::Pop(self); + return self; + } + +CDecPkcs12SafeContentsBag::~CDecPkcs12SafeContentsBag() + { + iSafeBags.ResetAndDestroy(); + iSafeBags.Close(); + } + +void CDecPkcs12SafeContentsBag::ConstructL(const TDesC8& aSafeBagData) + { + CDecPkcs12SafeBag::ConstructL(aSafeBagData); + // This is SafeBag Sequence containing a SafeContents Bag + TASN1DecGeneric seqGen(iBagValue); + seqGen.InitL(); + + // Check if this is a Sequence + if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal) + { + User::Leave(KErrArgument); + } + + TASN1DecSequence seq; + CArrayPtrFlat* safeContentsBagSeq = seq.DecodeDERLC(seqGen); + + // Find out the number of SafeBags present in the SafeContents Bag + TInt safeContentsBagCount = safeContentsBagSeq->Count(); + const TASN1DecGeneric* safeContentsBagSeqAtPos; + for (TInt index = 0; index < safeContentsBagCount; index++) + { + safeContentsBagSeqAtPos = safeContentsBagSeq->At(index); + if (safeContentsBagSeqAtPos->Tag() != EASN1Sequence || safeContentsBagSeqAtPos->Class() != EUniversal) + { + User::Leave(KErrArgument); + } + + const TDesC8& safeBag(safeContentsBagSeqAtPos->Encoding()); + // Decode this sequence, This is a SafeBag. + CDecPkcs12SafeBag* safeBagObject = CDecPkcs12SafeBag::NewL(safeBag); + CleanupStack::PushL(safeBagObject); + iSafeBags.AppendL(safeBagObject); + CleanupStack::Pop(safeBagObject); + } + CleanupStack::PopAndDestroy(safeContentsBagSeq); + } + +EXPORT_C const RPointerArray& CDecPkcs12SafeContentsBag::SafeBags() const + { + return iSafeBags; + } + +///////////////////////////// Safe Contents /////////////////////////////// +CDecPkcs12SafeContents::CDecPkcs12SafeContents() + { + } + +CDecPkcs12SafeContents::~CDecPkcs12SafeContents() + { + delete iDecryptedData; + iSafeBags.ResetAndDestroy(); + iSafeBags.Close(); + } + +EXPORT_C CDecPkcs12SafeContents* CDecPkcs12SafeContents::NewL(const CPKCS7ContentInfo& aSafeContentsBagData) + { + CDecPkcs12SafeContents* self = new(ELeave) CDecPkcs12SafeContents; + CleanupStack::PushL(self); + self->ConstructL(aSafeContentsBagData.ContentData()); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C CDecPkcs12SafeContents* CDecPkcs12SafeContents::NewL(const CPKCS7ContentInfo& aSafeContentsBagData, const TDesC& aPassword) + { + CDecPkcs12SafeContents* self = new(ELeave) CDecPkcs12SafeContents; + CleanupStack::PushL(self); + self->DecodeEncryptedDataL(aSafeContentsBagData,aPassword); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C CDecPkcs12SafeContents* CDecPkcs12SafeContents::NewL(const TDesC8& aSafeContent) + { + CDecPkcs12SafeContents* self = new(ELeave) CDecPkcs12SafeContents; + CleanupStack::PushL(self); + self->ConstructL(aSafeContent); + CleanupStack::Pop(self); + return self; + } + +void CDecPkcs12SafeContents::ConstructL(const TDesC8& aSafeContent) + { + TASN1DecGeneric decGen(aSafeContent); + decGen.InitL(); + + if(decGen.Tag() != EASN1Sequence || decGen.Class() != EUniversal) + { + User::Leave(KErrArgument); + } + + TASN1DecGeneric decGen2(decGen.GetContentDER()); + decGen2.InitL(); + + if(decGen2.Tag() != EASN1Sequence || decGen.Class() != EUniversal) + { + User ::Leave(KErrArgument); + } + + // Decode sequence + TASN1DecSequence seq; + CArrayPtr* safeBagSequences = seq.DecodeDERLC(decGen); + + // A Sequence of SafeBags are present within the SafeContents Bag Sequence + TInt safeBagCount = safeBagSequences->Count(); + + for(TInt index = 0; index < safeBagCount; index++) + { + CDecPkcs12SafeBag* safeBag = CDecPkcs12SafeBag::NewL(safeBagSequences->At(index)->Encoding()); + CleanupStack::PushL(safeBag); + iSafeBags.AppendL(safeBag); + CleanupStack::Pop(safeBag); + } + CleanupStack::PopAndDestroy(safeBagSequences); // safeBagSequences + } + +void CDecPkcs12SafeContents::DecodeEncryptedDataL(const CPKCS7ContentInfo& aContentInfo, const TDesC& aPassword) + { + CPKCS7EncryptedDataObject* pkcs7EncryptedData = CPKCS7EncryptedDataObject::NewL(aContentInfo); + CleanupStack::PushL(pkcs7EncryptedData); + iDecryptedData = pkcs7EncryptedData->DecryptDataL(aPassword); + ConstructL(iDecryptedData->Des()); + CleanupStack::PopAndDestroy(pkcs7EncryptedData); + } + +EXPORT_C const RPointerArray& CDecPkcs12SafeContents::SafeContentsBags() const + { + return iSafeBags; + } + +EXPORT_C const TDesC8* CDecPkcs12SafeContents::DecryptedData() const + { + return iDecryptedData; + }