installationservices/swi/source/securitymanager/signatureverifier.cpp
changeset 0 ba25891c3a9e
--- /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 <swi/sisinstallerrors.h>
+
+#include <x509cert.h>
+#include <x509keys.h> 
+#include <hash.h> 
+#include <asn1enc.h>
+#include <x509keyencoder.h>
+
+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<CDSASignature>* 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);		
+	}
+
+