diff -r 000000000000 -r 164170e6151a cms/src/CCMSSignerInfo.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cms/src/CCMSSignerInfo.cpp Tue Jan 26 15:20:08 2010 +0200 @@ -0,0 +1,662 @@ +/* +* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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 FILES +#include "CCMSSignerInfo.h" +#include "TCMSTimeUtil.h" + +#include +#include +#include +#include + +// CONSTANTS +const TInt KMinNumberOfSubModules = 5; +const TInt KMaxNumberOfSubModules = 7; +const TInt KDefaultGranularity = 2; +const TInt KCMSVersion1 = 1; +const TInt KCMSVersion3 = 3; +const TInt KSignedAttrsTag = 0; +const TInt KUnsignedAttrsTag = 1; + +// CMS SignedAttributes useful types +_LIT( KContentTypeOID, "1.2.840.113549.1.9.3" ); +_LIT( KMessageDigestOID, "1.2.840.113549.1.9.4" ); +_LIT( KSignTimeOID, "1.2.840.113549.1.9.5" ); + +// Additional oid for adding certificates +_LIT( KPKCS9SigCertOID, "1.2.840.113549.1.9.16.2.12" ); + +// X509 URL certificate OID +_LIT( KURLCertificateOID, "2.23.43.2.1" ); + +// Defaulta id-data oid +_LIT( KIDDataOID, "1.2.840.113549.1.7.1" ); + +// ============================ MEMBER FUNCTIONS =============================== + +// Destructor +CCMSSignerInfo::CSignerInfoData::~CSignerInfoData() + { + delete iIssuerAndSerial; + delete iSubjectKeyIdentifier; + + if( iSignedAttributes ) + { + iSignedAttributes->ResetAndDestroy(); + delete iSignedAttributes; + } + + if( iUnsignedAttributes ) + { + iUnsignedAttributes->ResetAndDestroy(); + delete iUnsignedAttributes; + } + + delete iDigestAI; + delete iSignatureAI; + delete iSignatureValue; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::CCMSSignerInfo +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +EXPORT_C CCMSSignerInfo::CCMSSignerInfo() + { + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CCMSSignerInfo::ConstructL( + const TDesC8& aCertificateUrl, + const TDesC8& aSubjectKeyID, + const TDesC8& aMessageDigest ) + { + iData = new(ELeave) CSignerInfoData(); + BaseConstructL( aMessageDigest ); + SetCertificateUrlL( aCertificateUrl, aSubjectKeyID ); + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CCMSSignerInfo::ConstructL( + const CCMSX509Certificate& aCertificate, + const TDesC8& aMessageDigest ) + { + iData = new(ELeave) CSignerInfoData(); + BaseConstructL( aMessageDigest ); + SetCertificateL( aCertificate ); + } + +void CCMSSignerInfo::BaseConstructL( const TDesC8& aMessageDigest ) + { + iData->iDigestAI = CCMSX509AlgorithmIdentifier::NewL( ESHA1 ); + iData->iSignatureAI = CCMSX509AlgorithmIdentifier::NewL(); + TTime time; + time.UniversalTime(); + iData->iSignedAttributes = new(ELeave)CArrayPtrFlat( KDefaultGranularity ); + SetSignedAttributesL( KIDDataOID(), + aMessageDigest, + time, + NULL ); + iData->iUnsignedAttributes = new(ELeave)CArrayPtrFlat( KDefaultGranularity ); + SetSignatureValueL( aMessageDigest ); + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C CCMSSignerInfo* CCMSSignerInfo::NewL() + { + // creating with empty values + CCMSSignerInfo* self = NewL( KNullDesC8(), + KNullDesC8(), + KNullDesC8() ); + + return self; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C CCMSSignerInfo* CCMSSignerInfo::NewL( + const TDesC8& aCertificateUrl, + const TDesC8& aSubjectKeyID, + const TDesC8& aMessageDigest ) + { + CCMSSignerInfo* self = new( ELeave ) CCMSSignerInfo(); + CleanupStack::PushL( self ); + self->ConstructL( aCertificateUrl, aSubjectKeyID, aMessageDigest ); + CleanupStack::Pop(); + + return self; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C CCMSSignerInfo* CCMSSignerInfo::NewL( + const CCMSX509Certificate& aCertificate, + const TDesC8& aMessageDigest ) + { + CCMSSignerInfo* self = new( ELeave ) CCMSSignerInfo(); + CleanupStack::PushL( self ); + self->ConstructL( aCertificate, aMessageDigest ); + CleanupStack::Pop(); + + return self; + } + +// Destructor +CCMSSignerInfo::~CCMSSignerInfo() + { + delete iData; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::DecodeL +// Decrypts raw data to this instance +// ----------------------------------------------------------------------------- +void CCMSSignerInfo::DecodeL( const TDesC8& aRawData ) + { + CSignerInfoData* tmpData = new(ELeave) CSignerInfoData(); + CleanupStack::PushL( tmpData ); + CArrayPtr* signerInfo = DecodeSequenceLC( aRawData, + KMinNumberOfSubModules, + KMaxNumberOfSubModules ); + // we would not get this far if there is not min 5 elements + TInt pos = 0; + // decode Version + TASN1DecInteger version; + tmpData->iVersion = version.DecodeDERShortL( *signerInfo->At( pos++ ) ); + + if( tmpData->iVersion == KCMSVersion1 ) + { + // decode IssuerAndSerialNumber + tmpData->iIssuerAndSerial = + CCMSIssuerAndSerialNumber::NewL(); + tmpData->iIssuerAndSerial->DecodeL( signerInfo->At( pos++ )->Encoding() ); + } + else + { + // decode SubjectKeyIdentifier + TASN1DecOctetString subjectKey; + tmpData->iSubjectKeyIdentifier = + subjectKey.DecodeDERL( *signerInfo->At( pos++ ) ); + } + + // decode DigestAlgorithIdentifier + tmpData->iDigestAI = CCMSX509AlgorithmIdentifier::NewL(); + tmpData->iDigestAI->DecodeL( signerInfo->At( pos++ )->Encoding() ); + + // decode possible SignedAttributes + tmpData->iSignedAttributes = + new( ELeave )CArrayPtrFlat( KDefaultGranularity ); + if( signerInfo->At( pos )->Tag() == KSignedAttrsTag ) + { + DecodeAttributesL( signerInfo->At( pos++ )->Encoding(), + tmpData->iSignedAttributes ); + } + + // decode SignatureAlgorithIdentifier + tmpData->iSignatureAI = CCMSX509AlgorithmIdentifier::NewL(); + tmpData->iSignatureAI->DecodeL( signerInfo->At( pos++ )->Encoding() ); + + // check that we have enough parameters for mandatory fields + if( pos >= signerInfo->Count() ) + { + User::Leave( KErrArgument ); + } + + // decode SignatureValue + TASN1DecOctetString signValue; + tmpData->iSignatureValue = signValue.DecodeDERL( *signerInfo->At( pos++ ) ); + + // decode possible UnsignedAttributes + tmpData->iUnsignedAttributes = + new( ELeave )CArrayPtrFlat( KDefaultGranularity ); + if( ( pos < signerInfo->Count() ) && + ( signerInfo->At( pos )->Tag() == KUnsignedAttrsTag ) ) + { + DecodeAttributesL( signerInfo->At( pos++ )->Encoding(), + tmpData->iUnsignedAttributes ); + } + + CleanupStack::PopAndDestroy( signerInfo ); + + delete iData; + iData = tmpData; + CleanupStack::Pop( tmpData ); + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::EncoderLC +// Returns ASN1 encoder for this instance +// ----------------------------------------------------------------------------- + +CASN1EncBase* CCMSSignerInfo::EncoderLC() const + { + CASN1EncSequence* root = CASN1EncSequence::NewLC(); + + // Add version + CASN1EncInt* version = CASN1EncInt::NewLC( iData->iVersion ); + root->AddAndPopChildL( version ); + + // Add IssuerAndSerialNumber or SubjectKeyIdentifier + if( iData->iIssuerAndSerial ) + { + CASN1EncBase* issuer = iData->iIssuerAndSerial->EncoderLC(); + root->AddAndPopChildL( issuer ); + } + else + { + CASN1EncOctetString* subjectKey = + CASN1EncOctetString::NewLC( *iData->iSubjectKeyIdentifier ); + root->AddAndPopChildL( subjectKey ); + } + + // Add DigestAlgorithmIdentifier + CASN1EncBase* digestAlg = iData->iDigestAI->EncoderLC(); + root->AddAndPopChildL( digestAlg ); + + // Add SignedAttributes if they exists + TInt signedAttributes = iData->iSignedAttributes->Count(); + if( signedAttributes > 0 ) + { + CASN1EncSequence* signedAttributesSet + = CASN1EncSequence::NewLC(); + signedAttributesSet->SetTag( KSignedAttrsTag ); + + for( TInt i = 0; i < signedAttributes; i++ ) + { + CASN1EncBase* attribute = iData->iSignedAttributes->At( i )->EncoderLC(); + signedAttributesSet->AddAndPopChildL( attribute ); + } + root->AddAndPopChildL( signedAttributesSet ); + } + + // Add SignatureAlgorithmIdentifier + CASN1EncBase* signatureAlg = iData->iSignatureAI->EncoderLC(); + root->AddAndPopChildL( signatureAlg ); + + // Add SignatureValue + CASN1EncOctetString* signValue = + CASN1EncOctetString::NewLC( *iData->iSignatureValue ); + root->AddAndPopChildL( signValue ); + + // Add UnsignedAttributes if they exists + TInt unsignedAttributes = iData->iUnsignedAttributes->Count(); + if( unsignedAttributes > 0 ) + { + CASN1EncSequence* unsignedAttributesSet + = CASN1EncSequence::NewLC(); + unsignedAttributesSet->SetTag( KUnsignedAttrsTag ); + + for( TInt i = 0; i < unsignedAttributes; i++ ) + { + CASN1EncBase* attribute = iData->iUnsignedAttributes->At( i )->EncoderLC(); + unsignedAttributesSet->AddAndPopChildL( attribute ); + } + root->AddAndPopChildL( unsignedAttributesSet ); + } + + return root; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::CMSVersion() +// Getter for Version +// ----------------------------------------------------------------------------- +EXPORT_C TInt CCMSSignerInfo::CMSVersion() const + { + return iData->iVersion; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::IssuerAndSerialNumber() +// Getter for IssuerAndSerialNumber +// ----------------------------------------------------------------------------- +EXPORT_C const CCMSIssuerAndSerialNumber* CCMSSignerInfo::IssuerAndSerialNumber() const + { + return iData->iIssuerAndSerial; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SubjectKeyIdentifier() +// Getter for SubjectKeyIdentifier +// ----------------------------------------------------------------------------- +EXPORT_C const TDesC8* CCMSSignerInfo::SubjectKeyIdentifier() const + { + return iData->iSubjectKeyIdentifier; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::DigestAlgorithmIdentifier() +// Getter for DigestAlgorithmIdentifier +// ----------------------------------------------------------------------------- +EXPORT_C const CCMSX509AlgorithmIdentifier& CCMSSignerInfo::DigestAlgorithmIdentifier() const + { + return *iData->iDigestAI; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SignedAttributes() +// Getter for SignedAttributes +// ----------------------------------------------------------------------------- +EXPORT_C const CArrayPtrFlat& CCMSSignerInfo::SignedAttributes() const + { + return *iData->iSignedAttributes; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SignedAttributesEncodedL() +// Getter for encoded SignedAttributes +// ----------------------------------------------------------------------------- +EXPORT_C HBufC8* CCMSSignerInfo::SignedAttributesEncodedL() const + { + HBufC8* retVal = NULL; + TInt signedAttributes = iData->iSignedAttributes->Count(); + if( signedAttributes > 0 ) + { + CASN1EncSequence* signedAttributesSet + = CASN1EncSequence::NewLC(); + signedAttributesSet->SetTag( EASN1Set, EUniversal ); + + for( TInt i = 0; i < signedAttributes; i++ ) + { + CASN1EncBase* attribute = iData->iSignedAttributes->At( i )->EncoderLC(); + signedAttributesSet->AddAndPopChildL( attribute ); + } + retVal = CreateDerEncodingL( signedAttributesSet ); + CleanupStack::PopAndDestroy( signedAttributesSet ); + } + return retVal; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SignatureAlgorithmIdentifier() +// Getter for SignatureAlgorithmIdentifier +// ----------------------------------------------------------------------------- +EXPORT_C const CCMSX509AlgorithmIdentifier& CCMSSignerInfo::SignatureAlgorithmIdentifier() const + { + return *iData->iSignatureAI; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SignatureValue() +// Getter for SignatureValue +// ----------------------------------------------------------------------------- +EXPORT_C const TDesC8& CCMSSignerInfo::SignatureValue() const + { + return *iData->iSignatureValue; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::UnsignedAttributes() +// Getter for UnsignedAttributes +// ----------------------------------------------------------------------------- +EXPORT_C const CArrayPtrFlat& CCMSSignerInfo::UnsignedAttributes() const + { + return *iData->iUnsignedAttributes; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SetCertificateL() +// Setter for Certificate +// ----------------------------------------------------------------------------- +EXPORT_C void CCMSSignerInfo::SetCertificateL( const CCMSX509Certificate& aCertificate ) + { + // creating Issuer and serial + CCMSIssuerAndSerialNumber* tmpIssuer = CCMSIssuerAndSerialNumber::NewL( + aCertificate.Issuer(), + aCertificate.SerialNumber() ); + + delete iData->iIssuerAndSerial; + iData->iIssuerAndSerial = tmpIssuer; + + // setting normal certificate, deleting possible certificate url + // and subject key identifier + TInt unsignedAttCount = iData->iUnsignedAttributes->Count(); + for( TInt i = 0; i < unsignedAttCount; i++ ) + { + CCMSAttribute* att = iData->iUnsignedAttributes->At( i ); + if( att->AttributeType() == KURLCertificateOID() ) + { + iData->iUnsignedAttributes->Delete( i ); + delete att; + } + } + delete iData->iSubjectKeyIdentifier; + iData->iSubjectKeyIdentifier = NULL; + + // changing version to 1 + iData->iVersion = KCMSVersion1; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SetCertificateUrlL() +// Setter for certificate URL +// ----------------------------------------------------------------------------- +EXPORT_C void CCMSSignerInfo::SetCertificateUrlL( const TDesC8& aCertificateUrl, + const TDesC8& aSubjectKeyID ) + { + CCMSAttribute* certUrl = CreateCertificateUrlLC( aCertificateUrl ); + + // remove possible URL from unsigned attributes + TInt unsignedAttCount = iData->iUnsignedAttributes->Count(); + for( TInt i = 0; i < unsignedAttCount; i++ ) + { + CCMSAttribute* att = iData->iUnsignedAttributes->At( i ); + if( att->AttributeType() == KURLCertificateOID() ) + { + iData->iUnsignedAttributes->Delete( i ); + delete att; + } + } + iData->iUnsignedAttributes->AppendL( certUrl ); + CleanupStack::Pop( certUrl ); + + // taking copy of subject key identifier + HBufC8* tmpSubjectKeyID = aSubjectKeyID.AllocL(); + + delete iData->iSubjectKeyIdentifier; + iData->iSubjectKeyIdentifier = tmpSubjectKeyID; + + // Issuer and serial is only for real certificates + delete iData->iIssuerAndSerial; + iData->iIssuerAndSerial = NULL; + + // changing version to 3 + iData->iVersion = KCMSVersion3; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SetDigestAlgorithmIdentifier() +// Setter for DigestAlgorithmIdentifier +// ----------------------------------------------------------------------------- +EXPORT_C void CCMSSignerInfo::SetDigestAlgorithmIdentifier( + CCMSX509AlgorithmIdentifier& aDigestAI ) + { + delete iData->iDigestAI; + iData->iDigestAI = &aDigestAI; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SetSignatureAlgorithmIdentifier() +// Setter for SignatureAlgorithmIdentifier +// ----------------------------------------------------------------------------- +EXPORT_C void CCMSSignerInfo::SetSignatureAlgorithmIdentifier( + CCMSX509AlgorithmIdentifier& aSignatureAI ) + { + delete iData->iSignatureAI; + iData->iSignatureAI = &aSignatureAI; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SetSignatureValueL() +// Setter for SignatureValue +// ----------------------------------------------------------------------------- +EXPORT_C void CCMSSignerInfo::SetSignatureValueL( const TDesC8& aSignatureValue ) + { + HBufC8* tmpSignValue = aSignatureValue.AllocL(); + delete iData->iSignatureValue; + iData->iSignatureValue = tmpSignValue; + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SetSignedAttributesL() +// Setter for Signed attributes +// ----------------------------------------------------------------------------- +EXPORT_C void CCMSSignerInfo::SetSignedAttributesL( const TDesC& aContentType, + const TDesC8& aMessageDigest, + const TTime& aSigningTime, + const TDesC8* aCertHash ) + { + CArrayPtrFlat* tmpAttributes = + new(ELeave)CArrayPtrFlat( KDefaultGranularity ); + CleanupStack::PushL( tmpAttributes ); + CleanupResetAndDestroy< CArrayPtrFlat >::PushL( *tmpAttributes ); + + + if( aContentType != KNullDesC() ) + { + // creating content type + CASN1EncObjectIdentifier* contOid = + CASN1EncObjectIdentifier::NewLC( aContentType ); + HBufC8* contentType = CreateDerEncodingL( contOid ); + CleanupStack::PushL( contentType ); + CCMSAttribute* contType = CCMSAttribute::NewLC( KContentTypeOID, *contentType ); + tmpAttributes->AppendL( contType ); + CleanupStack::Pop( contType ); + CleanupStack::PopAndDestroy( contentType ); + CleanupStack::PopAndDestroy( contOid ); + } + + if( aMessageDigest != KNullDesC8() ) + { + // creating MessageDigest + CASN1EncOctetString* signature = + CASN1EncOctetString::NewLC( aMessageDigest ); + HBufC8* messageDigest = CreateDerEncodingL( signature ); + CleanupStack::PushL( messageDigest ); + CCMSAttribute* mDigest = CCMSAttribute::NewLC( KMessageDigestOID, *messageDigest ); + tmpAttributes->AppendL( mDigest ); + CleanupStack::Pop( mDigest ); + CleanupStack::PopAndDestroy( messageDigest ); + CleanupStack::PopAndDestroy( signature ); + } + + // creating Signing time + CASN1EncBase* signTimeDER = TCMSTimeUtil::ConvertToEncoderLC( aSigningTime ); + HBufC8* signTime = CreateDerEncodingL( signTimeDER ); + CleanupStack::PushL( signTime ); + CCMSAttribute* sTime = CCMSAttribute::NewLC( KSignTimeOID, *signTime ); + tmpAttributes->AppendL( sTime ); + CleanupStack::Pop( sTime ); + CleanupStack::PopAndDestroy( signTime ); + CleanupStack::PopAndDestroy( signTimeDER ); + + // are we adding certificates + if( aCertHash ) + { + CCMSAttribute* signingCert = + CCMSAttribute::NewLC( KPKCS9SigCertOID, *aCertHash ); + tmpAttributes->AppendL( signingCert ); + CleanupStack::Pop( signingCert ); + } + + iData->iSignedAttributes->ResetAndDestroy(); + delete iData->iSignedAttributes; + iData->iSignedAttributes = tmpAttributes; + CleanupStack::Pop( tmpAttributes ); // ResetAndDestroy + CleanupStack::Pop( tmpAttributes ); + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::SetUnsignedAttributesL() +// Setter for Unsigned attributes +// ----------------------------------------------------------------------------- +EXPORT_C void CCMSSignerInfo::SetUnsignedAttributesL( + CArrayPtrFlat& aUnsignedAttributes ) + { + iData->iUnsignedAttributes->ResetAndDestroy(); + delete iData->iUnsignedAttributes; + iData->iUnsignedAttributes = &aUnsignedAttributes; + } + + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::DecodeAttributesL() +// Decodes Attributes to array +// ----------------------------------------------------------------------------- +void CCMSSignerInfo::DecodeAttributesL( + const TDesC8& aRawData, + CArrayPtrFlat* aAttributes ) + { + TASN1DecSet attributeDec; + TInt pos = 0; + CArrayPtrFlat* attributes = + attributeDec.DecodeDERLC( aRawData, pos ); + + TInt numOfAttributes = attributes->Count(); + for( TInt i = 0; i < numOfAttributes; i++ ) + { + CCMSAttribute* att = CCMSAttribute::NewLC(); + att->DecodeL( attributes->At( i )->Encoding() ); + aAttributes->AppendL( att ); + CleanupStack::Pop( att ); + } + CleanupStack::PopAndDestroy( attributes ); + } + +// ----------------------------------------------------------------------------- +// CCMSSignerInfo::CreateCertificateUrlLC() +// Creates certificate url attribute +// ----------------------------------------------------------------------------- +CCMSAttribute* CCMSSignerInfo::CreateCertificateUrlLC( const TDesC8& aCertificateUrl ) + { + // Add certificate URL to unsigned attributes + CASN1EncOctetString* certificateUrlEnc = + CASN1EncOctetString::NewLC( aCertificateUrl ); + //change tag to IA5 + certificateUrlEnc->SetTag( EASN1IA5String ); + + HBufC8* certificateURL = CreateDerEncodingL( certificateUrlEnc ); + CleanupStack::PushL( certificateURL ); + CCMSAttribute* certUrl = CCMSAttribute::NewL( KURLCertificateOID, *certificateURL ); + CleanupStack::PopAndDestroy( certificateURL ); + CleanupStack::PopAndDestroy( certificateUrlEnc ); + CleanupStack::PushL( certUrl ); + return certUrl; + } +// End of File