diff -r 000000000000 -r ba25891c3a9e installationservices/swi/source/securitymanager/signatureverifier.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/installationservices/swi/source/securitymanager/signatureverifier.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,195 @@ +/* +* Copyright (c) 2008-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 "signatureverifier.h" +#include "log.h" +#include + +#include +#include +#include +#include +#include + +using namespace Swi; + + +// +// Life cycle methods +// + +/*static*/ CSignatureVerifier* CSignatureVerifier::NewL() + { + CSignatureVerifier* self = CSignatureVerifier::NewLC(); + CleanupStack::Pop(self); + return self; + } + +/*static*/ CSignatureVerifier* CSignatureVerifier::NewLC() + { + CSignatureVerifier* self = new(ELeave) CSignatureVerifier(); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +CSignatureVerifier::~CSignatureVerifier() + { + } + +CSignatureVerifier::CSignatureVerifier() + { + } + +void CSignatureVerifier::ConstructL() + { + } + + +// +// Business Method +// + +TBool CSignatureVerifier::VerifySignatureL(const TDesC& aSchemeOid, + const CSubjectPublicKeyInfo& aPublicKey, + const TPtrC8& aControllerData, + const TDesC8& aSignatureData) + { + CMessageDigest* digester = CreateDigestL(aSchemeOid); + CleanupStack::PushL(digester); + + TPtrC8 digest = digester->Final(aControllerData); + + TX509KeyFactory keyFactory; + TBool result = EFalse; + + switch (aPublicKey.AlgorithmId()) + { + case ERSA : + { + DEBUG_PRINTF(_L8("Security Manager - Verifying RSA signature.")); + + // Get the public key + CRSAPublicKey* publicKey = keyFactory.RSAPublicKeyL(aPublicKey.KeyData()); + CleanupStack::PushL(publicKey); + + CRSAPKCS1v15Verifier* verifier = CRSAPKCS1v15Verifier::NewLC(*publicKey); + + RInteger sig = RInteger::NewL(aSignatureData); + CleanupStack::PushL(sig); + CRSASignature* theSignature = CRSASignature::NewL(sig); + CleanupStack::Pop(&sig); + CleanupStack::PushL(theSignature); + + // Do the ASN1 thing + TAlgorithmId digestAlgId = OidToIdL(aSchemeOid); + CASN1EncBase* digestInfo = DigestInfoLC(digest, *publicKey, digestAlgId); + + // DER encode it! + HBufC8* digestBuf = HBufC8::NewMaxLC(digestInfo->LengthDER()); + TPtr8 oct(digestBuf->Des()); + oct.FillZ(); + + TUint writePos = 0; + digestInfo->WriteDERL(oct, writePos); + + result = verifier->VerifyL(*digestBuf, *theSignature); + + CleanupStack::PopAndDestroy(5, publicKey); // digestBuf, digestInfo, theSignature + // verifier, publicKey + } + break; + + case EDSA : + { + DEBUG_PRINTF(_L8("Security Manager - Verifying DSA signature.")); + + CDSAPublicKey* publicKey = keyFactory.DSAPublicKeyL(aPublicKey.EncodedParams(), + aPublicKey.KeyData()); + CleanupStack::PushL(publicKey); + + CVerifier* verifier = CDSAVerifier::NewL(*publicKey); + CleanupStack::PushL(verifier); + + CDSASignature* sig = keyFactory.DSASignatureL(aSignatureData); + CleanupStack::PushL(sig); + + result = verifier->VerifyL(digest, *sig); + + CleanupStack::PopAndDestroy(3, publicKey); // verifier, sig, publicKey + } + break; + + default: + { + DEBUG_PRINTF(_L8("Security Manager - Signature scheme uses unsupported asymetric algorithm.")); + User::Leave(KErrNotSupported); + } + } + + CleanupStack::PopAndDestroy(digester); + return result; + } + + +// +// Helpers +// + +CASN1EncSequence* CSignatureVerifier::DigestInfoLC(const TDesC8& digest, + const CRSAPublicKey& publicKey, + TAlgorithmId aDigestId) + { + CASN1EncSequence* seq = CASN1EncSequence::NewLC(); + + // DigestAlgorithmIdentifier + TX509RSAKeyEncoder keyEncoder(publicKey, aDigestId); + CASN1EncSequence* digestAlgID = keyEncoder.EncodeDigestAlgorithmLC(); + + seq->AddAndPopChildL(digestAlgID); + + // Actual message digest + CASN1EncOctetString* octet = CASN1EncOctetString::NewLC(digest); + seq->AddAndPopChildL(octet); + + return seq; + } + +TAlgorithmId CSignatureVerifier::OidToIdL(const TDesC& aSchemeOid) + { + if ( (aSchemeOid.Compare(KSHA1WithRSA) != 0) && + (aSchemeOid.Compare(KDSAWithSHA1) != 0) ) + { + User::Leave(KErrDigestNotSupported); + } + return ESHA1; + } + +CMessageDigest* CSignatureVerifier::CreateDigestL(const TDesC& aSchemeOid) + { + if ( (aSchemeOid.Compare(KSHA1WithRSA) != 0) && + (aSchemeOid.Compare(KDSAWithSHA1) != 0) ) + { + DEBUG_PRINTF(_L8("Security Manager - Signature scheme uses unsupported hash algorithm.")); + User::Leave(KErrSignatureSchemeNotSupported); + } + DEBUG_PRINTF(_L8("Security Manager - Signature scheme uses SHA1 hash algorithm")); + return CMessageDigestFactory::NewDigestL(CMessageDigest::ESHA1); + } + +