--- a/cryptoservices/asnpkcs/source/asnpkcs8.cpp Tue Jul 21 01:04:32 2009 +0100
+++ b/cryptoservices/asnpkcs/source/asnpkcs8.cpp Thu Sep 10 14:01:51 2009 +0300
@@ -1,506 +1,506 @@
-/*
-* Copyright (c) 2004-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 <asn1dec.h>
-#include <x509keys.h>
-#include <x509cert.h>
-#include "asnpkcs.h"
-#include <pbe.h>
-#include <pbedata.h>
-#include <keyidentifierutil.h>
-
-/*static*/ EXPORT_C CDecPKCS8Data* TASN1DecPKCS8::DecodeDERL(const TDesC8& aBinaryData)
-{
- return (CDecPKCS8Data::NewL(aBinaryData));
-}
-
-/*
-EncryptedPrivateKeyInfo ::= SEQUENCE {
- encryptionAlgorithm EncryptionAlgorithmIdentifier,
- encryptedData EncryptedData }
-EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
-EncryptedData ::= OCTET STRING
-*/
-
-/*static*/ EXPORT_C CDecPKCS8Data* TASN1DecPKCS8::DecodeEncryptedDERL(const TDesC8& aBinaryData, const TDesC8& aPassword)
-{
- TASN1DecGeneric seqGen(aBinaryData);
- seqGen.InitL();
- if (seqGen.Tag() != EASN1Sequence)
- {
- User::Leave(KErrArgument);
- }
-
- TASN1DecSequence dec;
- CArrayPtrFlat<TASN1DecGeneric>* theData = dec.DecodeDERLC(seqGen);
- TInt seqIndex = 0;
- TInt count = theData->Count();
- if (seqIndex >= count)
- {
- User::Leave(KErrArgument);
- }
-
-// Get the first part of the sequence -> PKCS5 data
- TASN1DecGeneric* pkcs5 = theData->operator[](seqIndex);
- TPtrC8 theContent(pkcs5->Encoding()); // expect this to be a sequence
- CPBEncryptParms* encryptParams = TASN1DecPKCS5::DecodeDERL(theContent);
- CleanupStack::PushL(encryptParams);
-
-// Create the decryptor
- CPBEncryptElement* encryptElement = CPBEncryptElement::NewLC(aPassword, *encryptParams);
- CPBDecryptor* decryptor = encryptElement->NewDecryptLC();
-// Decrypt the final part of the sequence -> encrypted PKCS8 object
- TASN1DecGeneric* pkcs8 = theData->operator[](count-1);
- if (pkcs8->Tag() != EASN1OctetString)
- {
- User::Leave(KErrArgument);
- }
- TPtrC8 encryptedKey(pkcs8->GetContentDER());
- TUint encryptLength = encryptedKey.Length();
- TUint maxDecryptLength = decryptor->MaxOutputLength(encryptLength);
- if (maxDecryptLength<=0)
- {
- User::Leave(KErrGeneral);
- }
-
- HBufC8* decryptOutput = HBufC8::NewLC(encryptLength);
- TPtr8 decryptOutputPtr(decryptOutput->Des());
- decryptOutputPtr.FillZ();
- decryptor->Process(encryptedKey, decryptOutputPtr);
-
- CDecPKCS8Data* pkcs8Data = CDecPKCS8Data::NewL(decryptOutputPtr);
-
- // decryptOutput decryptor encryptElement
- // encryptParams theData
- CleanupStack::PopAndDestroy(5, theData);
-
- return (pkcs8Data);
-}
-
-/*
-Sample cleartext pkcs8 data from pkcs8dsa.001:
-
- SEQUENCE
-30 Tag: Constructed sequence
-81 c8 Length (may be one or more bytes)
-
- INTEGER
-02 Tag: Integer
-01 Length: 1 byte
-00 Value: 0
-
- SEQUENCE
-30 Tag: Constructed sequence
-81 a9 Length (may be one or more bytes)
-
- OID
-06 Tag: OID
-07 Length: 7 bytes
-2a 86 48 ce 38 04 01
- Value: dsa (1 2 840 10040 4 1)
-*/
-
-_LIT8(KPKCS8DataVersion0, "\x02\x01\x00");
-_LIT8(KPKCS8DataOIDDSA, "\x06\x07\x2a\x86\x48\xce\x38\x04\x01");
-_LIT8(KPKCS8DataOIDRSA, "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01");
-
-/*static*/ EXPORT_C TBool TASN1DecPKCS8::IsPKCS8Data(const TDesC8& aBinaryData)
- {
- // We don't decode the data because we may only have the first few bytes -
- // instead we check the ASN1 by hand.
-
- ASSERT(aBinaryData.Length() >= KIsPKCS8DataMinLength);
- TInt pos = 0;
-
- return
- IsASN1Sequence(aBinaryData, pos) &&
- IsExpectedData(aBinaryData, pos, KPKCS8DataVersion0) &&
- IsASN1Sequence(aBinaryData, pos) &&
- (IsExpectedData(aBinaryData, pos, KPKCS8DataOIDDSA) ||
- IsExpectedData(aBinaryData, pos, KPKCS8DataOIDRSA));
- }
-
-/*
-Sample encrypted pkcs8 data from encryptPK8rsa1.txt
-
- SEQUENCE
-30 Tag: Constructed sequence
-82 01 a3 Length (may be one or more bytes)
-
- SEQUENCE
-30 Tag: Constructed sequence
-3d Length (may be one or more bytes)
-
- OID
-06 Tag: OID
-09 Length: 9 bytes
-2a 86 48 86 f7 0d 01 05 0d
- Value: pkcs5PBES2 (1 2 840 113549 1 5 13)
-
- SEQUENCE
-30 Tag: Constructed sequence
-30 Length (may be one or more bytes)
-
- SEQUENCE
-30 Tag: Constructed sequence
-1b Length (may be one or more bytes)
-
- OID
-06 Tag: OID
-09 Length: 9 bytes
-2a 86 48 86 f7 0d 01 05 0c
- Value: pkcs5PBKDF2 (1 2 840 113549 1 5 12)
-*/
-
-_LIT8(KEncryptedPKCS8DataOIDpkcs5PBES2, "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x05\x0d");
-_LIT8(KEncryptedPKCS8DataOIDpkcs5PBKDF2, "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x05\x0c");
-
-EXPORT_C TBool TASN1DecPKCS8::IsEncryptedPKCS8Data(const TDesC8& aBinaryData)
- {
- // We don't decode the data because we may only have the first few bytes -
- // instead we check the ASN1 by hand.
-
- ASSERT(aBinaryData.Length() >= KIsEncryptedPKCS8DataMinLength);
- TInt pos = 0;
-
- return
- IsASN1Sequence(aBinaryData, pos) &&
- IsASN1Sequence(aBinaryData, pos) &&
- IsExpectedData(aBinaryData, pos, KEncryptedPKCS8DataOIDpkcs5PBES2) &&
- IsASN1Sequence(aBinaryData, pos) &&
- IsASN1Sequence(aBinaryData, pos) &&
- IsExpectedData(aBinaryData, pos, KEncryptedPKCS8DataOIDpkcs5PBKDF2);
- }
-
-/**
- * Determine if the some data represents the start of an ASN1 sequence. The
- * data is specified by a descriptor and an offset. If the data matches, the
- * offset is advanced to point to the contents of the sequence.
- */
-TBool TASN1DecPKCS8::IsASN1Sequence(const TDesC8& aBinaryData, TInt& aPos)
- {
- // Check we have enough data
- if ((aPos + 2) >= aBinaryData.Length())
- {
- return EFalse;
- }
- // Check the outermost sequence is valid
- if (aBinaryData[aPos++] != 0x30 /* constructed sequence */)
- {
- return EFalse;
- }
- // Skip sequence length
- TInt length0 = aBinaryData[aPos++];
- if (length0 & 0x80)
- {
- aPos += length0 & 0x7f;
- }
- return ETrue;
- }
-
-/**
- * Determine if some data starts with an expected string. The data is specified
- * by a descriptor and an offset. If the data matches, the offset is advanced
- * to point after the match.
- */
-TBool TASN1DecPKCS8::IsExpectedData(const TDesC8& aBinaryData, TInt& aPos, const TDesC8& aExpectedData)
- {
- TInt length = aExpectedData.Length();
- // Check we have enough data
- if (aPos + length >= aBinaryData.Length())
- {
- return EFalse;
- }
- // Check data matches
- if (aBinaryData.Mid(aPos, length) != aExpectedData)
- {
- return EFalse;
- }
- aPos += length;
- return ETrue;
- }
-
-// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
-// PKCS#8 object data representation
-// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
-
-/*static*/ CDecPKCS8Data* CDecPKCS8Data::NewL(const TDesC8& aData)
-{
- CDecPKCS8Data* me = new (ELeave) CDecPKCS8Data();
- CleanupStack::PushL(me);
- me->ConstructL(aData);
- CleanupStack::Pop(me);
- return (me);
-}
-
-CDecPKCS8Data::CDecPKCS8Data()
-{}
-
-CDecPKCS8Data::~CDecPKCS8Data()
-{
- if (iKeyPairData)
- {
- iKeyPairData->Release();
- iKeyPairData = NULL;
- }
-
- if (iAttributes)
- {
- delete iAttributes;
- iAttributes = NULL;
- }
-}
-
-// Because this is part of construction, don't rely on
-// cleanup of partially constructed items...
-void CDecPKCS8Data::ConstructL(const TDesC8& aData)
- {
- TASN1DecGeneric seqGen(aData);
- seqGen.InitL();
- if (seqGen.Tag() != EASN1Sequence)
- {
- User::Leave(KErrArgument);
- }
-
- TASN1DecSequence seq;
- CArrayPtrFlat<TASN1DecGeneric>* seqContents = seq.DecodeDERLC(seqGen);
- if (seqContents->Count() < 3 || seqContents->Count() > 4)
- {
- User::Leave(KErrArgument);
- }
-
-// VERSION
- if (seqContents->At(0)->Tag() != EASN1Integer)
- {
- User::Leave(KErrArgument);
- }
- TASN1DecInteger intDecoder;
- iVersion = intDecoder.DecodeDERShortL(*(seqContents->At(0)));
- if (iVersion!=0)
- {
- User::Leave(KErrArgument);
- }
-
-// ALGORITHM
- CX509AlgorithmIdentifier* algorithm = CX509AlgorithmIdentifier::NewLC(seqContents->At(1)->Encoding());
- iAlgorithmID = algorithm->Algorithm();
-
-// KEY DATA
- switch (iAlgorithmID)
- {// Only support RSA, DSA, DH
- case ERSA:
- iKeyPairData = CPKCS8KeyPairRSA::NewL(*(seqContents->At(2)));
- break;
-
- case EDSA:
- {
- TPtrC8 params(algorithm->EncodedParams());
- iKeyPairData = CPKCS8KeyPairDSA::NewL(params, *(seqContents->At(2)));
- break;
- }
-
- case EDH: // Currently not supported because no test data is available
- default:
- User::Leave(KErrNotSupported);
- break;
- }
-
- CleanupStack::PopAndDestroy(algorithm);
-
- if (seqContents->Count() == 4)
- {
- // I think we should check the tag is zero here, but we're going to be
- // lenient due to lack of real test data
-
- //if (seqContents->At(3)->Tag() != 0) // Implicitly tagged
- // {
- // User::Leave(KErrArgument);
- // }
-
- iAttributes = seqContents->At(3)->Encoding().AllocL();
- }
-
- CleanupStack::PopAndDestroy(seqContents);
- }
-
-// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
-// RSA decoding
-// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
-
-/*static*/ MPKCS8DecodedKeyPairData* CPKCS8KeyPairRSA::NewL(const TASN1DecGeneric& aSource)
-{
- CPKCS8KeyPairRSA* me = new (ELeave) CPKCS8KeyPairRSA();
- CleanupStack::PushL(me);
- me->ConstructL(aSource);
- CleanupStack::Pop(me);
-
- return (me);
-}
-
-MPKCS8DecodedKeyPairData::~MPKCS8DecodedKeyPairData()
- {
- }
-
-CPKCS8KeyPairRSA::~CPKCS8KeyPairRSA()
-{
- delete iPublicKey;
- delete iPrivateKey;
-}
-
-void CPKCS8KeyPairRSA::Release()
-{
- delete this;
-}
-
-void CPKCS8KeyPairRSA::GetKeyIdentifierL(TKeyIdentifier& aKeyIdentifier) const
-{
- if (iPublicKey)
- KeyIdentifierUtil::RSAKeyIdentifierL(*iPublicKey, aKeyIdentifier);
- else
- User::Leave(KErrNotReady);
-}
-
-TUint CPKCS8KeyPairRSA::KeySize() const
-{
- if (!iPublicKey)
- {
- ASSERT(EFalse);
- return (0xffffffff);
- }
-
- const TInteger& modulus = iPublicKey->N();
-
- TUint size = modulus.BitCount();
- return (size);
-}
-
-void CPKCS8KeyPairRSA::ConstructL(const TASN1DecGeneric& aSource)
-{
- TPtrC8 theContent(aSource.GetContentDER());
- TASN1DecRSAKeyPair keyPairDecoder;
- TInt tempPos = 0;
- keyPairDecoder.DecodeDERL(theContent, tempPos, iPublicKey, iPrivateKey);
-}
-
-
-// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
-// DSA decoding
-// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
-
-/*static*/ MPKCS8DecodedKeyPairData* CPKCS8KeyPairDSA::NewL(const TDesC8& aParamsData, const TASN1DecGeneric& aSource)
-{
- CPKCS8KeyPairDSA* me = new (ELeave) CPKCS8KeyPairDSA();
- CleanupStack::PushL(me);
- me->ConstructL(aParamsData, aSource);
- CleanupStack::Pop(me);
-
- return (me);
-}
-
-CPKCS8KeyPairDSA::~CPKCS8KeyPairDSA()
-{
- delete iPublicKey;
- delete iPrivateKey;
-}
-
-void CPKCS8KeyPairDSA::Release()
-{
- delete this;
-}
-
-void CPKCS8KeyPairDSA::GetKeyIdentifierL(TKeyIdentifier& aKeyIdentifier) const
-{
- if (iPublicKey)
- KeyIdentifierUtil::DSAKeyIdentifierL(*iPublicKey, aKeyIdentifier);
- else
- User::Leave(KErrNotReady);
-}
-
-TUint CPKCS8KeyPairDSA::KeySize() const
-{
- if (!iPublicKey)
- {
- ASSERT(EFalse);
- return (0xffffffff);
- }
-
- const TInteger& P = iPublicKey->P();
-
- TUint size = P.BitCount();
- return (size);
-}
-
-void CPKCS8KeyPairDSA::ConstructL(const TDesC8& aParamsData, const TASN1DecGeneric& aSource)
-{
- TX509KeyFactory keyFactory;
- CDSAParameters* params = keyFactory.DSAParametersL(aParamsData);
- CleanupStack::PushL(params);
-
- RInteger P = RInteger::NewL(params->P());
- CleanupStack::PushL(P);
-
- RInteger Q = RInteger::NewL(params->Q());
- CleanupStack::PushL(Q);
-
- RInteger G = RInteger::NewL(params->G());
- CleanupStack::PushL(G);
-
- if (aSource.Tag() != EASN1OctetString)
- {
- User::Leave(KErrArgument);
- }
- TASN1DecOctetString octetDecoder;
- HBufC8* wrapped = octetDecoder.DecodeDERL(aSource);
- CleanupStack::PushL(wrapped);
-
- TASN1DecGeneric integer(*wrapped);
- integer.InitL();
- if (integer.Tag() != EASN1Integer)
- {
- User::Leave(KErrArgument);
- }
- TASN1DecInteger decInt;
- RInteger X = decInt.DecodeDERLongL(integer);
- CleanupStack::PopAndDestroy(wrapped);
- CleanupStack::PushL(X);
-
- RInteger P1 = RInteger::NewL(params->P());
- CleanupStack::PushL(P1);
-
- RInteger Q1 = RInteger::NewL(params->Q());
- CleanupStack::PushL(Q1);
-
- RInteger G1 = RInteger::NewL(params->G());
- CleanupStack::PushL(G1);
-
- RInteger Y = TInteger::ModularExponentiateL(G, X, P);
- CleanupStack::PushL(Y);
-
- iPublicKey = CDSAPublicKey::NewL(P1, Q1, G1, Y);
-
- // Now have to pop everything owned by iPublicKey otherwise it will be
- // deleted twice if the CDSAPrivateKey::NewL leaves
-
- CleanupStack::Pop(4, &P1); // now owned by iPublicKey
-
- iPrivateKey = CDSAPrivateKey::NewL(P, Q, G, X);
-
- CleanupStack::Pop(4, &P); // now owned by iPrivateKey
-
- CleanupStack::PopAndDestroy(params);
-}
+/*
+* Copyright (c) 2004-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 <asn1dec.h>
+#include <x509keys.h>
+#include <x509cert.h>
+#include "asnpkcs.h"
+#include <pbe.h>
+#include <pbedata.h>
+#include <keyidentifierutil.h>
+
+/*static*/ EXPORT_C CDecPKCS8Data* TASN1DecPKCS8::DecodeDERL(const TDesC8& aBinaryData)
+{
+ return (CDecPKCS8Data::NewL(aBinaryData));
+}
+
+/*
+EncryptedPrivateKeyInfo ::= SEQUENCE {
+ encryptionAlgorithm EncryptionAlgorithmIdentifier,
+ encryptedData EncryptedData }
+EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+EncryptedData ::= OCTET STRING
+*/
+
+/*static*/ EXPORT_C CDecPKCS8Data* TASN1DecPKCS8::DecodeEncryptedDERL(const TDesC8& aBinaryData, const TDesC8& aPassword)
+{
+ TASN1DecGeneric seqGen(aBinaryData);
+ seqGen.InitL();
+ if (seqGen.Tag() != EASN1Sequence)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TASN1DecSequence dec;
+ CArrayPtrFlat<TASN1DecGeneric>* theData = dec.DecodeDERLC(seqGen);
+ TInt seqIndex = 0;
+ TInt count = theData->Count();
+ if (seqIndex >= count)
+ {
+ User::Leave(KErrArgument);
+ }
+
+// Get the first part of the sequence -> PKCS5 data
+ TASN1DecGeneric* pkcs5 = theData->operator[](seqIndex);
+ TPtrC8 theContent(pkcs5->Encoding()); // expect this to be a sequence
+ CPBEncryptParms* encryptParams = TASN1DecPKCS5::DecodeDERL(theContent);
+ CleanupStack::PushL(encryptParams);
+
+// Create the decryptor
+ CPBEncryptElement* encryptElement = CPBEncryptElement::NewLC(aPassword, *encryptParams);
+ CPBDecryptor* decryptor = encryptElement->NewDecryptLC();
+// Decrypt the final part of the sequence -> encrypted PKCS8 object
+ TASN1DecGeneric* pkcs8 = theData->operator[](count-1);
+ if (pkcs8->Tag() != EASN1OctetString)
+ {
+ User::Leave(KErrArgument);
+ }
+ TPtrC8 encryptedKey(pkcs8->GetContentDER());
+ TUint encryptLength = encryptedKey.Length();
+ TUint maxDecryptLength = decryptor->MaxOutputLength(encryptLength);
+ if (maxDecryptLength<=0)
+ {
+ User::Leave(KErrGeneral);
+ }
+
+ HBufC8* decryptOutput = HBufC8::NewLC(encryptLength);
+ TPtr8 decryptOutputPtr(decryptOutput->Des());
+ decryptOutputPtr.FillZ();
+ decryptor->Process(encryptedKey, decryptOutputPtr);
+
+ CDecPKCS8Data* pkcs8Data = CDecPKCS8Data::NewL(decryptOutputPtr);
+
+ // decryptOutput decryptor encryptElement
+ // encryptParams theData
+ CleanupStack::PopAndDestroy(5, theData);
+
+ return (pkcs8Data);
+}
+
+/*
+Sample cleartext pkcs8 data from pkcs8dsa.001:
+
+ SEQUENCE
+30 Tag: Constructed sequence
+81 c8 Length (may be one or more bytes)
+
+ INTEGER
+02 Tag: Integer
+01 Length: 1 byte
+00 Value: 0
+
+ SEQUENCE
+30 Tag: Constructed sequence
+81 a9 Length (may be one or more bytes)
+
+ OID
+06 Tag: OID
+07 Length: 7 bytes
+2a 86 48 ce 38 04 01
+ Value: dsa (1 2 840 10040 4 1)
+*/
+
+_LIT8(KPKCS8DataVersion0, "\x02\x01\x00");
+_LIT8(KPKCS8DataOIDDSA, "\x06\x07\x2a\x86\x48\xce\x38\x04\x01");
+_LIT8(KPKCS8DataOIDRSA, "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01");
+
+/*static*/ EXPORT_C TBool TASN1DecPKCS8::IsPKCS8Data(const TDesC8& aBinaryData)
+ {
+ // We don't decode the data because we may only have the first few bytes -
+ // instead we check the ASN1 by hand.
+
+ ASSERT(aBinaryData.Length() >= KIsPKCS8DataMinLength);
+ TInt pos = 0;
+
+ return
+ IsASN1Sequence(aBinaryData, pos) &&
+ IsExpectedData(aBinaryData, pos, KPKCS8DataVersion0) &&
+ IsASN1Sequence(aBinaryData, pos) &&
+ (IsExpectedData(aBinaryData, pos, KPKCS8DataOIDDSA) ||
+ IsExpectedData(aBinaryData, pos, KPKCS8DataOIDRSA));
+ }
+
+/*
+Sample encrypted pkcs8 data from encryptPK8rsa1.txt
+
+ SEQUENCE
+30 Tag: Constructed sequence
+82 01 a3 Length (may be one or more bytes)
+
+ SEQUENCE
+30 Tag: Constructed sequence
+3d Length (may be one or more bytes)
+
+ OID
+06 Tag: OID
+09 Length: 9 bytes
+2a 86 48 86 f7 0d 01 05 0d
+ Value: pkcs5PBES2 (1 2 840 113549 1 5 13)
+
+ SEQUENCE
+30 Tag: Constructed sequence
+30 Length (may be one or more bytes)
+
+ SEQUENCE
+30 Tag: Constructed sequence
+1b Length (may be one or more bytes)
+
+ OID
+06 Tag: OID
+09 Length: 9 bytes
+2a 86 48 86 f7 0d 01 05 0c
+ Value: pkcs5PBKDF2 (1 2 840 113549 1 5 12)
+*/
+
+_LIT8(KEncryptedPKCS8DataOIDpkcs5PBES2, "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x05\x0d");
+_LIT8(KEncryptedPKCS8DataOIDpkcs5PBKDF2, "\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x05\x0c");
+
+EXPORT_C TBool TASN1DecPKCS8::IsEncryptedPKCS8Data(const TDesC8& aBinaryData)
+ {
+ // We don't decode the data because we may only have the first few bytes -
+ // instead we check the ASN1 by hand.
+
+ ASSERT(aBinaryData.Length() >= KIsEncryptedPKCS8DataMinLength);
+ TInt pos = 0;
+
+ return
+ IsASN1Sequence(aBinaryData, pos) &&
+ IsASN1Sequence(aBinaryData, pos) &&
+ IsExpectedData(aBinaryData, pos, KEncryptedPKCS8DataOIDpkcs5PBES2) &&
+ IsASN1Sequence(aBinaryData, pos) &&
+ IsASN1Sequence(aBinaryData, pos) &&
+ IsExpectedData(aBinaryData, pos, KEncryptedPKCS8DataOIDpkcs5PBKDF2);
+ }
+
+/**
+ * Determine if the some data represents the start of an ASN1 sequence. The
+ * data is specified by a descriptor and an offset. If the data matches, the
+ * offset is advanced to point to the contents of the sequence.
+ */
+TBool TASN1DecPKCS8::IsASN1Sequence(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ // Check we have enough data
+ if ((aPos + 2) >= aBinaryData.Length())
+ {
+ return EFalse;
+ }
+ // Check the outermost sequence is valid
+ if (aBinaryData[aPos++] != 0x30 /* constructed sequence */)
+ {
+ return EFalse;
+ }
+ // Skip sequence length
+ TInt length0 = aBinaryData[aPos++];
+ if (length0 & 0x80)
+ {
+ aPos += length0 & 0x7f;
+ }
+ return ETrue;
+ }
+
+/**
+ * Determine if some data starts with an expected string. The data is specified
+ * by a descriptor and an offset. If the data matches, the offset is advanced
+ * to point after the match.
+ */
+TBool TASN1DecPKCS8::IsExpectedData(const TDesC8& aBinaryData, TInt& aPos, const TDesC8& aExpectedData)
+ {
+ TInt length = aExpectedData.Length();
+ // Check we have enough data
+ if (aPos + length >= aBinaryData.Length())
+ {
+ return EFalse;
+ }
+ // Check data matches
+ if (aBinaryData.Mid(aPos, length) != aExpectedData)
+ {
+ return EFalse;
+ }
+ aPos += length;
+ return ETrue;
+ }
+
+// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
+// PKCS#8 object data representation
+// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
+
+/*static*/ CDecPKCS8Data* CDecPKCS8Data::NewL(const TDesC8& aData)
+{
+ CDecPKCS8Data* me = new (ELeave) CDecPKCS8Data();
+ CleanupStack::PushL(me);
+ me->ConstructL(aData);
+ CleanupStack::Pop(me);
+ return (me);
+}
+
+CDecPKCS8Data::CDecPKCS8Data()
+{}
+
+CDecPKCS8Data::~CDecPKCS8Data()
+{
+ if (iKeyPairData)
+ {
+ iKeyPairData->Release();
+ iKeyPairData = NULL;
+ }
+
+ if (iAttributes)
+ {
+ delete iAttributes;
+ iAttributes = NULL;
+ }
+}
+
+// Because this is part of construction, don't rely on
+// cleanup of partially constructed items...
+void CDecPKCS8Data::ConstructL(const TDesC8& aData)
+ {
+ TASN1DecGeneric seqGen(aData);
+ seqGen.InitL();
+ if (seqGen.Tag() != EASN1Sequence)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TASN1DecSequence seq;
+ CArrayPtrFlat<TASN1DecGeneric>* seqContents = seq.DecodeDERLC(seqGen);
+ if (seqContents->Count() < 3 || seqContents->Count() > 4)
+ {
+ User::Leave(KErrArgument);
+ }
+
+// VERSION
+ if (seqContents->At(0)->Tag() != EASN1Integer)
+ {
+ User::Leave(KErrArgument);
+ }
+ TASN1DecInteger intDecoder;
+ iVersion = intDecoder.DecodeDERShortL(*(seqContents->At(0)));
+ if (iVersion!=0)
+ {
+ User::Leave(KErrArgument);
+ }
+
+// ALGORITHM
+ CX509AlgorithmIdentifier* algorithm = CX509AlgorithmIdentifier::NewLC(seqContents->At(1)->Encoding());
+ iAlgorithmID = algorithm->Algorithm();
+
+// KEY DATA
+ switch (iAlgorithmID)
+ {// Only support RSA, DSA, DH
+ case ERSA:
+ iKeyPairData = CPKCS8KeyPairRSA::NewL(*(seqContents->At(2)));
+ break;
+
+ case EDSA:
+ {
+ TPtrC8 params(algorithm->EncodedParams());
+ iKeyPairData = CPKCS8KeyPairDSA::NewL(params, *(seqContents->At(2)));
+ break;
+ }
+
+ case EDH: // Currently not supported because no test data is available
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+ }
+
+ CleanupStack::PopAndDestroy(algorithm);
+
+ if (seqContents->Count() == 4)
+ {
+ // I think we should check the tag is zero here, but we're going to be
+ // lenient due to lack of real test data
+
+ //if (seqContents->At(3)->Tag() != 0) // Implicitly tagged
+ // {
+ // User::Leave(KErrArgument);
+ // }
+
+ iAttributes = seqContents->At(3)->Encoding().AllocL();
+ }
+
+ CleanupStack::PopAndDestroy(seqContents);
+ }
+
+// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
+// RSA decoding
+// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
+
+/*static*/ MPKCS8DecodedKeyPairData* CPKCS8KeyPairRSA::NewL(const TASN1DecGeneric& aSource)
+{
+ CPKCS8KeyPairRSA* me = new (ELeave) CPKCS8KeyPairRSA();
+ CleanupStack::PushL(me);
+ me->ConstructL(aSource);
+ CleanupStack::Pop(me);
+
+ return (me);
+}
+
+MPKCS8DecodedKeyPairData::~MPKCS8DecodedKeyPairData()
+ {
+ }
+
+CPKCS8KeyPairRSA::~CPKCS8KeyPairRSA()
+{
+ delete iPublicKey;
+ delete iPrivateKey;
+}
+
+void CPKCS8KeyPairRSA::Release()
+{
+ delete this;
+}
+
+void CPKCS8KeyPairRSA::GetKeyIdentifierL(TKeyIdentifier& aKeyIdentifier) const
+{
+ if (iPublicKey)
+ KeyIdentifierUtil::RSAKeyIdentifierL(*iPublicKey, aKeyIdentifier);
+ else
+ User::Leave(KErrNotReady);
+}
+
+TUint CPKCS8KeyPairRSA::KeySize() const
+{
+ if (!iPublicKey)
+ {
+ ASSERT(EFalse);
+ return (0xffffffff);
+ }
+
+ const TInteger& modulus = iPublicKey->N();
+
+ TUint size = modulus.BitCount();
+ return (size);
+}
+
+void CPKCS8KeyPairRSA::ConstructL(const TASN1DecGeneric& aSource)
+{
+ TPtrC8 theContent(aSource.GetContentDER());
+ TASN1DecRSAKeyPair keyPairDecoder;
+ TInt tempPos = 0;
+ keyPairDecoder.DecodeDERL(theContent, tempPos, iPublicKey, iPrivateKey);
+}
+
+
+// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
+// DSA decoding
+// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\
+
+/*static*/ MPKCS8DecodedKeyPairData* CPKCS8KeyPairDSA::NewL(const TDesC8& aParamsData, const TASN1DecGeneric& aSource)
+{
+ CPKCS8KeyPairDSA* me = new (ELeave) CPKCS8KeyPairDSA();
+ CleanupStack::PushL(me);
+ me->ConstructL(aParamsData, aSource);
+ CleanupStack::Pop(me);
+
+ return (me);
+}
+
+CPKCS8KeyPairDSA::~CPKCS8KeyPairDSA()
+{
+ delete iPublicKey;
+ delete iPrivateKey;
+}
+
+void CPKCS8KeyPairDSA::Release()
+{
+ delete this;
+}
+
+void CPKCS8KeyPairDSA::GetKeyIdentifierL(TKeyIdentifier& aKeyIdentifier) const
+{
+ if (iPublicKey)
+ KeyIdentifierUtil::DSAKeyIdentifierL(*iPublicKey, aKeyIdentifier);
+ else
+ User::Leave(KErrNotReady);
+}
+
+TUint CPKCS8KeyPairDSA::KeySize() const
+{
+ if (!iPublicKey)
+ {
+ ASSERT(EFalse);
+ return (0xffffffff);
+ }
+
+ const TInteger& P = iPublicKey->P();
+
+ TUint size = P.BitCount();
+ return (size);
+}
+
+void CPKCS8KeyPairDSA::ConstructL(const TDesC8& aParamsData, const TASN1DecGeneric& aSource)
+{
+ TX509KeyFactory keyFactory;
+ CDSAParameters* params = keyFactory.DSAParametersL(aParamsData);
+ CleanupStack::PushL(params);
+
+ RInteger P = RInteger::NewL(params->P());
+ CleanupStack::PushL(P);
+
+ RInteger Q = RInteger::NewL(params->Q());
+ CleanupStack::PushL(Q);
+
+ RInteger G = RInteger::NewL(params->G());
+ CleanupStack::PushL(G);
+
+ if (aSource.Tag() != EASN1OctetString)
+ {
+ User::Leave(KErrArgument);
+ }
+ TASN1DecOctetString octetDecoder;
+ HBufC8* wrapped = octetDecoder.DecodeDERL(aSource);
+ CleanupStack::PushL(wrapped);
+
+ TASN1DecGeneric integer(*wrapped);
+ integer.InitL();
+ if (integer.Tag() != EASN1Integer)
+ {
+ User::Leave(KErrArgument);
+ }
+ TASN1DecInteger decInt;
+ RInteger X = decInt.DecodeDERLongL(integer);
+ CleanupStack::PopAndDestroy(wrapped);
+ CleanupStack::PushL(X);
+
+ RInteger P1 = RInteger::NewL(params->P());
+ CleanupStack::PushL(P1);
+
+ RInteger Q1 = RInteger::NewL(params->Q());
+ CleanupStack::PushL(Q1);
+
+ RInteger G1 = RInteger::NewL(params->G());
+ CleanupStack::PushL(G1);
+
+ RInteger Y = TInteger::ModularExponentiateL(G, X, P);
+ CleanupStack::PushL(Y);
+
+ iPublicKey = CDSAPublicKey::NewL(P1, Q1, G1, Y);
+
+ // Now have to pop everything owned by iPublicKey otherwise it will be
+ // deleted twice if the CDSAPrivateKey::NewL leaves
+
+ CleanupStack::Pop(4, &P1); // now owned by iPublicKey
+
+ iPrivateKey = CDSAPrivateKey::NewL(P, Q, G, X);
+
+ CleanupStack::Pop(4, &P); // now owned by iPrivateKey
+
+ CleanupStack::PopAndDestroy(params);
+}