diff -r 675a964f4eb5 -r 35751d3474b7 cryptoservices/asnpkcs/source/asnpkcs8.cpp --- 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 -#include -#include -#include "asnpkcs.h" -#include -#include -#include - -/*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* 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* 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 +#include +#include +#include "asnpkcs.h" +#include +#include +#include + +/*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* 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* 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); +}