os/security/cryptoplugins/cryptospiplugins/source/softwarecrypto/rsakeypairgenimpl.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoplugins/cryptospiplugins/source/softwarecrypto/rsakeypairgenimpl.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,245 @@
1.4 +/*
1.5 +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +* RSA Keypair implementation
1.19 +* RSA keypair generation implementation
1.20 +*
1.21 +*/
1.22 +
1.23 +
1.24 +/**
1.25 + @file
1.26 +*/
1.27 +
1.28 +#include "rsakeypairgenimpl.h"
1.29 +#include "pluginconfig.h"
1.30 +
1.31 +#include "keypair.h"
1.32 +#include <cryptospi/cryptospidef.h>
1.33 +
1.34 +#include "common/inlines.h" // For TClassSwap
1.35 +
1.36 +using namespace SoftwareCrypto;
1.37 +
1.38 +/* CRSAKeyPairGenImpl */
1.39 +CRSAKeyPairGenImpl::CRSAKeyPairGenImpl()
1.40 + {
1.41 + }
1.42 +
1.43 +CRSAKeyPairGenImpl::~CRSAKeyPairGenImpl()
1.44 + {
1.45 + }
1.46 +
1.47 +CRSAKeyPairGenImpl* CRSAKeyPairGenImpl::NewL(void)
1.48 + {
1.49 + CRSAKeyPairGenImpl* self = CRSAKeyPairGenImpl::NewLC();
1.50 + CleanupStack::Pop(self);
1.51 + return self;
1.52 + }
1.53 +
1.54 +CRSAKeyPairGenImpl* CRSAKeyPairGenImpl::NewLC(void)
1.55 + {
1.56 + CRSAKeyPairGenImpl* self = new(ELeave) CRSAKeyPairGenImpl();
1.57 + CleanupStack::PushL(self);
1.58 + self->ConstructL();
1.59 + return self;
1.60 + }
1.61 +
1.62 +void CRSAKeyPairGenImpl::ConstructL(void)
1.63 + {
1.64 + CKeyPairGenImpl::ConstructL();
1.65 + }
1.66 +
1.67 +CExtendedCharacteristics* CRSAKeyPairGenImpl::CreateExtendedCharacteristicsL()
1.68 + {
1.69 + // All Symbian software plug-ins have unlimited concurrency, cannot be reserved
1.70 + // for exclusive use and are not CERTIFIED to be standards compliant.
1.71 + return CExtendedCharacteristics::NewL(KMaxTInt, EFalse);
1.72 +}
1.73 +
1.74 +const CExtendedCharacteristics* CRSAKeyPairGenImpl::GetExtendedCharacteristicsL()
1.75 + {
1.76 + return CRSAKeyPairGenImpl::CreateExtendedCharacteristicsL();
1.77 + }
1.78 +
1.79 +TUid CRSAKeyPairGenImpl::ImplementationUid() const
1.80 + {
1.81 + return KCryptoPluginRsaKeyPairGenUid;
1.82 + }
1.83 +
1.84 +void CRSAKeyPairGenImpl::Reset()
1.85 + {
1.86 + // does nothing in this plugin
1.87 + }
1.88 +
1.89 +void CRSAKeyPairGenImpl::GenerateKeyPairL(TInt aKeySize, const CCryptoParams& aKeyParameters, CKeyPair*& aKeyPair)
1.90 + {
1.91 + /*
1.92 + * extract e
1.93 + */
1.94 + const TInt aKeyType = aKeyParameters.GetTIntL(KRsaKeyTypeUid);
1.95 + const TInt aPublicExponent = aKeyParameters.GetTIntL(KRsaKeyParameterEUid);
1.96 +
1.97 + RInteger e = RInteger::NewL(aPublicExponent);
1.98 + CleanupStack::PushL(e);
1.99 +
1.100 + /*
1.101 + * calculate p, q, n & d
1.102 + */
1.103 + RInteger p;
1.104 + RInteger q;
1.105 +
1.106 + //these make sure n is a least aKeySize long
1.107 + TInt pbits=(aKeySize+1)/2;
1.108 + TInt qbits=aKeySize-pbits;
1.109 +
1.110 + //generate a prime p such that GCD(e,p-1) == 1
1.111 + for (;;)
1.112 + {
1.113 + p = RInteger::NewPrimeL(pbits,TInteger::ETop2BitsSet);
1.114 + CleanupStack::PushL(p);
1.115 + --p;
1.116 +
1.117 + RInteger gcd = e.GCDL(p);
1.118 + if( gcd == 1 )
1.119 + {
1.120 + ++p;
1.121 + gcd.Close();
1.122 + //p is still on cleanup stack
1.123 + break;
1.124 + }
1.125 + CleanupStack::PopAndDestroy(&p);
1.126 + gcd.Close();
1.127 + }
1.128 +
1.129 + //generate a prime q such that GCD(e,q-1) == 1 && (p != q)
1.130 + for (;;)
1.131 + {
1.132 + q = RInteger::NewPrimeL(qbits,TInteger::ETop2BitsSet);
1.133 + CleanupStack::PushL(q);
1.134 + --q;
1.135 +
1.136 + RInteger gcd = e.GCDL(q);
1.137 + if( gcd == 1 )
1.138 + {
1.139 + ++q;
1.140 + if( p != q )
1.141 + {
1.142 + gcd.Close();
1.143 + //q is still on cleanup stack
1.144 + break;
1.145 + }
1.146 + }
1.147 + CleanupStack::PopAndDestroy(&q);
1.148 + gcd.Close();
1.149 + }
1.150 +
1.151 + //make sure p > q
1.152 + if ( p < q)
1.153 + {
1.154 + TClassSwap(p,q);
1.155 + }
1.156 +
1.157 + //calculate n = p * q
1.158 + RInteger n = p.TimesL(q);
1.159 + CleanupStack::PushL(n);
1.160 +
1.161 + --p;
1.162 + --q;
1.163 +
1.164 + //temp = (p-1)(q-1)
1.165 + RInteger temp = p.TimesL(q);
1.166 + CleanupStack::PushL(temp);
1.167 +
1.168 + //e * d = 1 mod ((p-1)(q-1))
1.169 + //d = e^(-1) mod ((p-1)(q-1))
1.170 + RInteger d = e.InverseModL(temp);
1.171 + CleanupStack::PopAndDestroy(&temp); //temp
1.172 + CleanupStack::PushL(d);
1.173 +
1.174 + /*
1.175 + * create private key depending on aKeyType
1.176 + */
1.177 + CCryptoParams* privateKeyParameters = CCryptoParams::NewLC();
1.178 + privateKeyParameters->AddL(n, KRsaKeyParameterNUid);
1.179 + TKeyProperty* privateKeyProperties = NULL;
1.180 + TKeyProperty privateKeyProperties_RsaPrivateKeyCRT = {KRSAKeyPairGeneratorUid, KCryptoPluginRsaKeyPairGenUid,
1.181 + KRsaPrivateKeyCRTUid, KNonEmbeddedKeyUid };
1.182 + TKeyProperty privateKeyProperties_RsaPrivateKeyStandard = {KRSAKeyPairGeneratorUid, KCryptoPluginRsaKeyPairGenUid,
1.183 + KRsaPrivateKeyStandardUid, KNonEmbeddedKeyUid };
1.184 +
1.185 + CCryptoParams*publicKeyParameters = CCryptoParams::NewLC();
1.186 + publicKeyParameters->AddL(n, KRsaKeyParameterNUid);
1.187 + publicKeyParameters->AddL(e, KRsaKeyParameterEUid);
1.188 + TKeyProperty publicKeyProperties = {KRSAKeyPairGeneratorUid, KCryptoPluginRsaKeyPairGenUid,
1.189 + KRsaPublicKeyUid, KNonEmbeddedKeyUid };
1.190 +
1.191 + if (aKeyType == KRsaPrivateKeyCRT) // cleanup stack contains e, p, q, n, d and privateKeyParameters
1.192 + {
1.193 +
1.194 + /*
1.195 + * calculate dP, dQ and qInv
1.196 + */
1.197 + //calculate dP = d mod (p-1)
1.198 + RInteger dP = d.ModuloL(p); //p is still p-1
1.199 + CleanupStack::PushL(dP);
1.200 + privateKeyParameters->AddL(dP, KRsaKeyParameterDPUid);
1.201 + CleanupStack::PopAndDestroy(&dP);
1.202 +
1.203 + //calculate dQ = d mod (q-1)
1.204 + RInteger dQ = d.ModuloL(q); //q is still q-1
1.205 + CleanupStack::PushL(dQ);
1.206 + privateKeyParameters->AddL(dQ, KRsaKeyParameterDQUid);
1.207 + CleanupStack::PopAndDestroy(&dQ);
1.208 +
1.209 + ++p;
1.210 + ++q;
1.211 + //calculate inverse of qInv = q^(-1)mod(p)
1.212 + RInteger qInv = q.InverseModL(p);
1.213 + CleanupStack::PushL(qInv);
1.214 + privateKeyParameters->AddL(qInv, KRsaKeyParameterQInvUid);
1.215 + CleanupStack::PopAndDestroy(&qInv);
1.216 +
1.217 + privateKeyParameters->AddL(p, KRsaKeyParameterPUid);
1.218 + privateKeyParameters->AddL(q, KRsaKeyParameterQUid);
1.219 +
1.220 + privateKeyProperties = &privateKeyProperties_RsaPrivateKeyCRT;
1.221 + }
1.222 + else if (aKeyType == KRsaPrivateKeyStandard)
1.223 + {
1.224 + privateKeyParameters->AddL(d, KRsaKeyParameterDUid);
1.225 + privateKeyProperties = &privateKeyProperties_RsaPrivateKeyStandard;
1.226 + }
1.227 + else
1.228 + {
1.229 + User::Leave(KErrNotSupported);
1.230 + }
1.231 + // cleanup stack contains e, p, q, n, d and privateKeyParameters
1.232 + CKey* privateKey = CKey::NewL(*privateKeyProperties, *privateKeyParameters);
1.233 + CleanupStack::PushL(privateKey);
1.234 +
1.235 + /*
1.236 + * create public key
1.237 + */
1.238 + CKey* publicKey = CKey::NewL(publicKeyProperties, *publicKeyParameters);
1.239 + CleanupStack::PushL(publicKey);
1.240 +
1.241 + /*
1.242 + * create the key pair
1.243 + */
1.244 + aKeyPair = CKeyPair::NewL(publicKey, privateKey);
1.245 +
1.246 + CleanupStack::Pop(2, privateKey); //privateKey and publicKey
1.247 + CleanupStack::PopAndDestroy(7, &e); //e, p, q, n, d, privateKeyParameters and publicKeyParameters
1.248 + }