sl@0: /* sl@0: * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * RSA Keypair implementation sl@0: * RSA keypair generation implementation sl@0: * sl@0: */ sl@0: sl@0: sl@0: /** sl@0: @file sl@0: */ sl@0: sl@0: #include "rsakeypairgenimpl.h" sl@0: #include "pluginconfig.h" sl@0: sl@0: #include "keypair.h" sl@0: #include sl@0: sl@0: #include "common/inlines.h" // For TClassSwap sl@0: sl@0: using namespace SoftwareCrypto; sl@0: sl@0: /* CRSAKeyPairGenImpl */ sl@0: CRSAKeyPairGenImpl::CRSAKeyPairGenImpl() sl@0: { sl@0: } sl@0: sl@0: CRSAKeyPairGenImpl::~CRSAKeyPairGenImpl() sl@0: { sl@0: } sl@0: sl@0: CRSAKeyPairGenImpl* CRSAKeyPairGenImpl::NewL(void) sl@0: { sl@0: CRSAKeyPairGenImpl* self = CRSAKeyPairGenImpl::NewLC(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CRSAKeyPairGenImpl* CRSAKeyPairGenImpl::NewLC(void) sl@0: { sl@0: CRSAKeyPairGenImpl* self = new(ELeave) CRSAKeyPairGenImpl(); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: return self; sl@0: } sl@0: sl@0: void CRSAKeyPairGenImpl::ConstructL(void) sl@0: { sl@0: CKeyPairGenImpl::ConstructL(); sl@0: } sl@0: sl@0: CExtendedCharacteristics* CRSAKeyPairGenImpl::CreateExtendedCharacteristicsL() sl@0: { sl@0: // All Symbian software plug-ins have unlimited concurrency, cannot be reserved sl@0: // for exclusive use and are not CERTIFIED to be standards compliant. sl@0: return CExtendedCharacteristics::NewL(KMaxTInt, EFalse); sl@0: } sl@0: sl@0: const CExtendedCharacteristics* CRSAKeyPairGenImpl::GetExtendedCharacteristicsL() sl@0: { sl@0: return CRSAKeyPairGenImpl::CreateExtendedCharacteristicsL(); sl@0: } sl@0: sl@0: TUid CRSAKeyPairGenImpl::ImplementationUid() const sl@0: { sl@0: return KCryptoPluginRsaKeyPairGenUid; sl@0: } sl@0: sl@0: void CRSAKeyPairGenImpl::Reset() sl@0: { sl@0: // does nothing in this plugin sl@0: } sl@0: sl@0: void CRSAKeyPairGenImpl::GenerateKeyPairL(TInt aKeySize, const CCryptoParams& aKeyParameters, CKeyPair*& aKeyPair) sl@0: { sl@0: /* sl@0: * extract e sl@0: */ sl@0: const TInt aKeyType = aKeyParameters.GetTIntL(KRsaKeyTypeUid); sl@0: const TInt aPublicExponent = aKeyParameters.GetTIntL(KRsaKeyParameterEUid); sl@0: sl@0: RInteger e = RInteger::NewL(aPublicExponent); sl@0: CleanupStack::PushL(e); sl@0: sl@0: /* sl@0: * calculate p, q, n & d sl@0: */ sl@0: RInteger p; sl@0: RInteger q; sl@0: sl@0: //these make sure n is a least aKeySize long sl@0: TInt pbits=(aKeySize+1)/2; sl@0: TInt qbits=aKeySize-pbits; sl@0: sl@0: //generate a prime p such that GCD(e,p-1) == 1 sl@0: for (;;) sl@0: { sl@0: p = RInteger::NewPrimeL(pbits,TInteger::ETop2BitsSet); sl@0: CleanupStack::PushL(p); sl@0: --p; sl@0: sl@0: RInteger gcd = e.GCDL(p); sl@0: if( gcd == 1 ) sl@0: { sl@0: ++p; sl@0: gcd.Close(); sl@0: //p is still on cleanup stack sl@0: break; sl@0: } sl@0: CleanupStack::PopAndDestroy(&p); sl@0: gcd.Close(); sl@0: } sl@0: sl@0: //generate a prime q such that GCD(e,q-1) == 1 && (p != q) sl@0: for (;;) sl@0: { sl@0: q = RInteger::NewPrimeL(qbits,TInteger::ETop2BitsSet); sl@0: CleanupStack::PushL(q); sl@0: --q; sl@0: sl@0: RInteger gcd = e.GCDL(q); sl@0: if( gcd == 1 ) sl@0: { sl@0: ++q; sl@0: if( p != q ) sl@0: { sl@0: gcd.Close(); sl@0: //q is still on cleanup stack sl@0: break; sl@0: } sl@0: } sl@0: CleanupStack::PopAndDestroy(&q); sl@0: gcd.Close(); sl@0: } sl@0: sl@0: //make sure p > q sl@0: if ( p < q) sl@0: { sl@0: TClassSwap(p,q); sl@0: } sl@0: sl@0: //calculate n = p * q sl@0: RInteger n = p.TimesL(q); sl@0: CleanupStack::PushL(n); sl@0: sl@0: --p; sl@0: --q; sl@0: sl@0: //temp = (p-1)(q-1) sl@0: RInteger temp = p.TimesL(q); sl@0: CleanupStack::PushL(temp); sl@0: sl@0: //e * d = 1 mod ((p-1)(q-1)) sl@0: //d = e^(-1) mod ((p-1)(q-1)) sl@0: RInteger d = e.InverseModL(temp); sl@0: CleanupStack::PopAndDestroy(&temp); //temp sl@0: CleanupStack::PushL(d); sl@0: sl@0: /* sl@0: * create private key depending on aKeyType sl@0: */ sl@0: CCryptoParams* privateKeyParameters = CCryptoParams::NewLC(); sl@0: privateKeyParameters->AddL(n, KRsaKeyParameterNUid); sl@0: TKeyProperty* privateKeyProperties = NULL; sl@0: TKeyProperty privateKeyProperties_RsaPrivateKeyCRT = {KRSAKeyPairGeneratorUid, KCryptoPluginRsaKeyPairGenUid, sl@0: KRsaPrivateKeyCRTUid, KNonEmbeddedKeyUid }; sl@0: TKeyProperty privateKeyProperties_RsaPrivateKeyStandard = {KRSAKeyPairGeneratorUid, KCryptoPluginRsaKeyPairGenUid, sl@0: KRsaPrivateKeyStandardUid, KNonEmbeddedKeyUid }; sl@0: sl@0: CCryptoParams*publicKeyParameters = CCryptoParams::NewLC(); sl@0: publicKeyParameters->AddL(n, KRsaKeyParameterNUid); sl@0: publicKeyParameters->AddL(e, KRsaKeyParameterEUid); sl@0: TKeyProperty publicKeyProperties = {KRSAKeyPairGeneratorUid, KCryptoPluginRsaKeyPairGenUid, sl@0: KRsaPublicKeyUid, KNonEmbeddedKeyUid }; sl@0: sl@0: if (aKeyType == KRsaPrivateKeyCRT) // cleanup stack contains e, p, q, n, d and privateKeyParameters sl@0: { sl@0: sl@0: /* sl@0: * calculate dP, dQ and qInv sl@0: */ sl@0: //calculate dP = d mod (p-1) sl@0: RInteger dP = d.ModuloL(p); //p is still p-1 sl@0: CleanupStack::PushL(dP); sl@0: privateKeyParameters->AddL(dP, KRsaKeyParameterDPUid); sl@0: CleanupStack::PopAndDestroy(&dP); sl@0: sl@0: //calculate dQ = d mod (q-1) sl@0: RInteger dQ = d.ModuloL(q); //q is still q-1 sl@0: CleanupStack::PushL(dQ); sl@0: privateKeyParameters->AddL(dQ, KRsaKeyParameterDQUid); sl@0: CleanupStack::PopAndDestroy(&dQ); sl@0: sl@0: ++p; sl@0: ++q; sl@0: //calculate inverse of qInv = q^(-1)mod(p) sl@0: RInteger qInv = q.InverseModL(p); sl@0: CleanupStack::PushL(qInv); sl@0: privateKeyParameters->AddL(qInv, KRsaKeyParameterQInvUid); sl@0: CleanupStack::PopAndDestroy(&qInv); sl@0: sl@0: privateKeyParameters->AddL(p, KRsaKeyParameterPUid); sl@0: privateKeyParameters->AddL(q, KRsaKeyParameterQUid); sl@0: sl@0: privateKeyProperties = &privateKeyProperties_RsaPrivateKeyCRT; sl@0: } sl@0: else if (aKeyType == KRsaPrivateKeyStandard) sl@0: { sl@0: privateKeyParameters->AddL(d, KRsaKeyParameterDUid); sl@0: privateKeyProperties = &privateKeyProperties_RsaPrivateKeyStandard; sl@0: } sl@0: else sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: // cleanup stack contains e, p, q, n, d and privateKeyParameters sl@0: CKey* privateKey = CKey::NewL(*privateKeyProperties, *privateKeyParameters); sl@0: CleanupStack::PushL(privateKey); sl@0: sl@0: /* sl@0: * create public key sl@0: */ sl@0: CKey* publicKey = CKey::NewL(publicKeyProperties, *publicKeyParameters); sl@0: CleanupStack::PushL(publicKey); sl@0: sl@0: /* sl@0: * create the key pair sl@0: */ sl@0: aKeyPair = CKeyPair::NewL(publicKey, privateKey); sl@0: sl@0: CleanupStack::Pop(2, privateKey); //privateKey and publicKey sl@0: CleanupStack::PopAndDestroy(7, &e); //e, p, q, n, d, privateKeyParameters and publicKeyParameters sl@0: }