diff -r 000000000000 -r 2c201484c85f cryptoservices/certificateandkeymgmt/pkcs7/cmsutils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cryptoservices/certificateandkeymgmt/pkcs7/cmsutils.cpp Wed Jul 08 11:25:26 2009 +0100 @@ -0,0 +1,417 @@ +/* +* Copyright (c) 2006-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 "cmsutils.h" +#include +#include +#include +#include +#include +#include +#include "pkcs7asn1.h" + + +TInt CmsUtils::DecodeContentTypeL(const TASN1DecGeneric* aASN1DecGeneric) + { + TInt type(0); + if(aASN1DecGeneric->Tag()==EASN1ObjectIdentifier || aASN1DecGeneric->Class() == EUniversal) + { + TASN1DecObjectIdentifier oidDec; + HBufC* oidVal = oidDec.DecodeDERL(*aASN1DecGeneric); + CleanupStack::PushL(oidVal); + + // Checks if it is data OID. + if(*oidVal == KCmsDataOID) + { + // The Content Type is indicated by an Integer. + // Here if Content Type is equal to Data then,it is represented by 1 + type = EContentTypeData; + } + else if(*oidVal == KCmsSignedDataOID) + { + // The Content Type is indicated by an Integer. + // Here if Content Type is equal to SignedData then,it is represented by 2 + type = EContentTypeSignedData; + } + else if(*oidVal == KCmsEnvelopedDataOID) + { + // The Content Type is indicated by an Integer. + // Here if Content Type is equal to EnvelopedData then,it is represented by 3. + type = EContentTypeEnvelopedData; + } + else if(*oidVal == KCmsDigestedDataOID) + { + // The Content Type is indicated by an Integer. + // Here if Content Type is equal to DigestedData then,it is represented by 5. + type = EContentTypeDigestedData; + } + else if(*oidVal == KCmsEncryptedDataOID) + { + // The Content Type is indicated by an Integer. + // Here if Content Type is equal to EncryptedData then,it is represented by 6 + type = EContentTypeEncryptedData; + } + else if(*oidVal == KCmsAuthenticatedDataOID) + { + // The Content Type is indicated by an Integer. + // Here if Content Type is equal to EncryptedData then,it is represented by 7 + type = EContentTypeAuthenticatedData; + } + + else + { + User::Leave(KErrArgument); + } + CleanupStack::PopAndDestroy(oidVal); + } + else + { + User::Leave(KErrArgument); + } + return type; + } + +CASN1EncObjectIdentifier* CmsUtils::EncodeContentTypeLC(TInt aContentType) + { + TPtrC oidBuf; + switch (aContentType) + { + case EContentTypeData: + oidBuf.Set(KCmsDataOID()); + break; + + case EContentTypeSignedData: + oidBuf.Set(KCmsSignedDataOID()); + break; + + case EContentTypeEnvelopedData: + oidBuf.Set(KCmsEnvelopedDataOID()); + break; + + case EContentTypeDigestedData: + oidBuf.Set(KCmsDigestedDataOID()); + break; + + case EContentTypeEncryptedData: + oidBuf.Set(KCmsEncryptedDataOID()); + break; + + default: + User::Leave(KErrArgument); + } + //Encode the OID + CASN1EncObjectIdentifier* oid=CASN1EncObjectIdentifier::NewLC(oidBuf); + return oid; + } + +void CmsUtils::AddCertificateL(RPointerArray& aCertList, const TDesC8& aCert, CCmsCertificateChoice::TCertificateType aType) + { + TInt found(EFalse); + TInt count=aCertList.Count(); + for (TInt i=0;iCertificateType()==CCmsCertificateChoice::ECertificateAttribute + && aCert.Compare(*aCertList[i]->AttributeCertificate())==0) + { + found=ETrue; + break; + } + } + + if (!found) + { + CCmsCertificateChoice* cert=CCmsCertificateChoice::NewL(aType, aCert); + CleanupStack::PushL(cert); + aCertList.AppendL(cert); + CleanupStack::Pop(cert); + } + } + +void CmsUtils::AddCertificateL(RPointerArray& aCertList, const CX509Certificate& aCert) + { + + TInt found(EFalse); + TInt count=aCertList.Count(); + for (TInt i=0;iCertificateType()==CCmsCertificateChoice::ECertificateX509 + && aCert.IsEqualL(aCertList[i]->Certificate())) + { + found=ETrue; + break; + } + } + + if (!found) + { + CCmsCertificateChoice* cert=CCmsCertificateChoice::NewL(aCert); + CleanupStack::PushL(cert); + aCertList.AppendL(cert); + CleanupStack::Pop(cert); + } + + } + +void CmsUtils::AddAlgorithmIdentifierL(RPointerArray& aAlgorithmIdList, TAlgorithmId aDigestAlgorithm) + { + TInt found(EFalse); + TInt count=aAlgorithmIdList.Count(); + for (TInt i=0;iAlgorithm()==aDigestAlgorithm) + { + found=ETrue; + break; + } + } + if (!found) + { + CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8()); + aAlgorithmIdList.AppendL(digAlg); + CleanupStack::Pop(digAlg); + } + } + +void CmsUtils::DecodeDigestAlgorithmsL(RPointerArray& aDigestAlgorithms, const TDesC8& aRawData) + { + CArrayPtr* algsData = PKCS7ASN1::DecodeSequenceLC(aRawData); + TInt count = algsData->Count(); + CX509AlgorithmIdentifier* alIdent; + + for(TInt item = 0; item < count; item++) + { + alIdent = CX509AlgorithmIdentifier::NewLC(algsData->At(item)->Encoding()); + aDigestAlgorithms.AppendL(alIdent); + CleanupStack::Pop(alIdent); + } + CleanupStack::PopAndDestroy(algsData); + } + +void CmsUtils::DecodeCertificatesL(RPointerArray& aCertificates, const TDesC8& aRawData) + { + TASN1DecGeneric decGen(aRawData); + decGen.InitL(); + TASN1DecSequence decSeq; + // have to do manual decoding of sequence because field is optional + CArrayPtr* items = NULL; + items = decSeq.DecodeDERLC(decGen); + TInt count = items->Count(); + + CCmsCertificateChoice* certificate; + + for(TInt item = 0; item < count; item++) + { + certificate = CCmsCertificateChoice::NewL(items->At(item)->Encoding()); + CleanupStack::PushL(certificate); + aCertificates.AppendL(certificate); + CleanupStack::Pop(certificate); + } + + CleanupStack::PopAndDestroy(items); + } + +CASN1EncBase* CmsUtils::EncodeCertificatesLC(const RPointerArray& aCertificates) + { + CASN1EncSet* certSet(NULL); + TInt count=aCertificates.Count(); + if (count>0) + { + certSet = CASN1EncSet::NewLC(); + for (TInt i=0;iEncodeASN1DERLC(); + certSet->AddAndPopChildL(cert); + } + // [0] implicit + certSet->SetTag(0); + } + return certSet; + } + +CASN1EncBase* CmsUtils::EncodeDigestAlgorithmsLC(const RPointerArray& aDigestAlgorithms) + { + CASN1EncSet* algorithmSet = CASN1EncSet::NewLC(); + TInt count=aDigestAlgorithms.Count(); + + for (TInt i=0;iEncodeASN1DERLC(); + algorithmSet->AddAndPopChildL(tmp); + } + + return algorithmSet; + } + +void CmsUtils::DecodeOctetStringL(const TDesC8& aRawData, HBufC8*& aBuf) + { + TASN1DecGeneric decGen(aRawData); + decGen.InitL(); + + if(decGen.Tag()==EASN1OctetString && decGen.Class()==EUniversal) + { + TASN1DecOctetString decOct; + aBuf = decOct.DecodeDERL(decGen); + } + else + { + User::Leave(KErrArgument); + } + } + + +CMessageDigest* CmsUtils::CreateHashLC(TAlgorithmId aAlgorithm) + { + CMessageDigest* hash(NULL); + switch (aAlgorithm) + { + case EMD2: + hash=CMD2::NewL(); + break; + + case EMD5: + hash=CMD5::NewL(); + break; + + case ESHA1: + hash=CSHA1::NewL(); + break; + + default: + User::Leave(KErrNotSupported); + } + CleanupStack::PushL(hash); + return hash; + } + + +HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aDataToBeSigned, TBool aIsHash, TAlgorithmId aAlgorithm, const CDSAPrivateKey& aKey) + { + HBufC8* signature(NULL); + + if (!aIsHash) + { + TPtrC8 hashValue; + // Create hash first + CMessageDigest* hash=CreateHashLC(aAlgorithm); + hashValue.Set(hash->Hash(aDataToBeSigned)); + signature=CreateSignatureL(hashValue, aKey); + CleanupStack::PopAndDestroy(); // hash + } + else + { + signature=CreateSignatureL(aDataToBeSigned, aKey); + } + + return signature; + } + +HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aDataToBeSigned, TBool aIsHash, TAlgorithmId aAlgorithm, const CRSAPrivateKey& aKey) + { + HBufC8* signature(NULL); + TPtrC8 hashValue; + if (!aIsHash) + { + // Create hash first + CMessageDigest* hash=CreateHashLC(aAlgorithm); + hashValue.Set(hash->Hash(aDataToBeSigned)); + } + else + { + hashValue.Set(aDataToBeSigned); + } + + //Build the digestInfo Sequence + CASN1EncSequence* digestInfoSeq = CASN1EncSequence::NewLC(); + + //Encode the Algorithm + CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aAlgorithm, KNullDesC8()); + CASN1EncSequence* sigAlg=digAlg->EncodeASN1DERLC(); + digestInfoSeq->AddAndPopChildL(sigAlg); + CleanupStack::PopAndDestroy(digAlg); + + //Encode the digest itself + CASN1EncOctetString* sigEnc=CASN1EncOctetString::NewLC(hashValue); + digestInfoSeq->AddAndPopChildL(sigEnc); + + //Get the Encoding + HBufC8* digestInfo=CreateDEREncodingLC(*digestInfoSeq); + signature=CreateSignatureL(digestInfo->Des(), aKey); + + CleanupStack::PopAndDestroy(2, digestInfoSeq); //digestInfo, digestInfoSeq + if (!aIsHash) + { + CleanupStack::PopAndDestroy(); // hash + } + return signature; + } + +HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aHash, const CDSAPrivateKey& aKey) + { + //Create Signer and sign the hash + CDSASigner* signer=CDSASigner::NewLC(aKey); + const CDSASignature* sig=signer->SignL(aHash); + CDSASignature* signonc=const_cast(sig); + + CleanupStack::PushL(signonc); + + //The sequence + CASN1EncSequence* sigSeq = CASN1EncSequence::NewLC(); + CASN1EncBigInt* r = CASN1EncBigInt::NewLC(static_cast(sig->R())); + sigSeq->AddAndPopChildL(r); + CASN1EncBigInt* s = CASN1EncBigInt::NewLC(static_cast(sig->S())); + sigSeq->AddAndPopChildL(s); + + //Write the buffer + TUint len=sigSeq->LengthDER(); + HBufC8* buf=HBufC8::NewMaxLC(len); + TPtr8 des=buf->Des(); + TUint pos=0; + sigSeq->WriteDERL(des, pos); + + //Clean up + CleanupStack::Pop(buf); //buf + CleanupStack::PopAndDestroy(3, signer); //sigSeq, signonc, signer + return buf; + } + +HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aHash, const CRSAPrivateKey& aKey) + { + //Create Signer and sign the hash + CRSAPKCS1v15Signer* signer=CRSAPKCS1v15Signer::NewLC(aKey); + const CRSASignature* sig=signer->SignL(aHash); + CRSASignature* signonc=const_cast(sig); + + CleanupStack::PushL(signonc); + + HBufC8* sigData = sig->S().BufferWithNoTruncationLC(); + + //Clean up + CleanupStack::Pop(sigData); + CleanupStack::PopAndDestroy(2, signer);//signonc signer + return sigData; + } + +HBufC8* CmsUtils::CreateDEREncodingLC(const CASN1EncBase& aEncoding) + { + TUint len = aEncoding.LengthDER(); + HBufC8* buf = HBufC8::NewMaxLC(len); + TUint pos = 0; + TPtr8 bufptr(buf->Des()); + aEncoding.WriteDERL(bufptr, pos); + return buf; + }