1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoservices/certificateandkeymgmt/x509/x509keysRSA.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,293 @@
1.4 +/*
1.5 +* Copyright (c) 1998-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 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include <x509keys.h>
1.23 +#include <asn1dec.h>
1.24 +#include <asn1enc.h>
1.25 +#include <x509cert.h>
1.26 +#include "x509keyencoder.h"
1.27 +
1.28 +CX509RSAPublicKey::CX509RSAPublicKey()
1.29 +{}
1.30 +
1.31 +//RSA public key
1.32 +EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewL(const TDesC8& aBinaryData)
1.33 + {
1.34 + TInt pos = 0;
1.35 + return CX509RSAPublicKey::NewL(aBinaryData, pos);
1.36 + }
1.37 +
1.38 +EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewLC(const TDesC8& aBinaryData)
1.39 + {
1.40 + TInt pos = 0;
1.41 + return CX509RSAPublicKey::NewLC(aBinaryData, pos);
1.42 + }
1.43 +
1.44 +EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewL(const TDesC8& aBinaryData, TInt& aPos)
1.45 + {
1.46 + CX509RSAPublicKey* self = CX509RSAPublicKey::NewLC(aBinaryData, aPos);
1.47 + CleanupStack::Pop();
1.48 + return self;
1.49 + }
1.50 +
1.51 +EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewLC(const TDesC8& aBinaryData, TInt& aPos)
1.52 + {
1.53 + CX509RSAPublicKey* self = new(ELeave) CX509RSAPublicKey();
1.54 + CleanupStack::PushL(self);
1.55 + self->ConstructL(aBinaryData, aPos);
1.56 + return self;
1.57 + }
1.58 +
1.59 +void CX509RSAPublicKey::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
1.60 + {
1.61 + TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
1.62 + gen.InitL();
1.63 + TInt end = aPos + gen.LengthDER();
1.64 + aPos += gen.LengthDERHeader();
1.65 + if (gen.Tag() != EASN1Sequence)
1.66 + {
1.67 + User::Leave(KErrArgument);
1.68 + }
1.69 + TASN1DecInteger encInt;
1.70 + iN = encInt.DecodeDERLongL(aBinaryData, aPos);
1.71 + iE = encInt.DecodeDERLongL(aBinaryData, aPos);
1.72 +
1.73 + // RSA Public keys, modulus and exponent must be positive integers
1.74 + if(!iN.IsPositive() || !iE.IsPositive())
1.75 + {
1.76 + User::Leave(KErrArgument);
1.77 + }
1.78 + if (aPos != end)
1.79 + {
1.80 + User::Leave(KErrArgument);
1.81 + }
1.82 + }
1.83 +
1.84 +// Encodes public key to DER
1.85 +EXPORT_C HBufC8* TASN1EncRSAPublicKey::EncodeDERL(const CRSAPublicKey& aKey) const
1.86 + {
1.87 + CASN1EncSequence* sequence = CASN1EncSequence::NewLC();
1.88 + CASN1EncBigInt* encModulus = CASN1EncBigInt::NewLC(aKey.N());
1.89 + sequence->AddAndPopChildL(encModulus);
1.90 + CASN1EncBigInt* encPublicExponent = CASN1EncBigInt::NewLC(aKey.E());
1.91 + sequence->AddAndPopChildL(encPublicExponent);
1.92 + HBufC8* der = HBufC8::NewMaxLC(sequence->LengthDER());
1.93 + TUint pos = 0;
1.94 + TPtr8 derptr(der->Des());
1.95 + sequence->WriteDERL(derptr, pos);
1.96 + CleanupStack::Pop(der);
1.97 + CleanupStack::PopAndDestroy(sequence);
1.98 + return der;
1.99 + }
1.100 +
1.101 +// Decodes public key from DER
1.102 +EXPORT_C CRSAPublicKey* TASN1DecRSAPublicKey::DecodeDERL(const TDesC8& aDER,
1.103 + TInt& aPos) const
1.104 + {
1.105 + // Enter into the containing SEQUENCE and verify if it is indeed there
1.106 + TASN1DecGeneric gen(aDER.Right(aDER.Length() - aPos));
1.107 + gen.InitL();
1.108 + TInt end = aPos + gen.LengthDER();
1.109 + aPos += gen.LengthDERHeader();
1.110 + if (gen.Tag() != EASN1Sequence)
1.111 + User::Leave(KErrArgument);
1.112 +
1.113 + // Decode modulus and public exponent (two large integers)
1.114 + TASN1DecInteger encInt;
1.115 + RInteger modulus = encInt.DecodeDERLongL(aDER, aPos);
1.116 + CleanupStack::PushL(modulus);
1.117 + RInteger publicExponent = encInt.DecodeDERLongL(aDER, aPos);
1.118 + CleanupStack::PushL(publicExponent);
1.119 + if (aPos != end)
1.120 + User::Leave(KErrArgument);
1.121 +
1.122 + // Construct a new key without copying
1.123 + CRSAPublicKey* key = CRSAPublicKey::NewL(modulus, publicExponent);
1.124 + CleanupStack::Pop(2); // modulus, publicExponent - owned by public key
1.125 + return key;
1.126 + }
1.127 +
1.128 +// Decodes RSA key pair from DER-encoded buffer
1.129 +EXPORT_C void TASN1DecRSAKeyPair::DecodeDERL(const TDesC8& aDER,
1.130 + TInt& aPos,
1.131 + CRSAPublicKey*& aPublicKey,
1.132 + CRSAPrivateKey*& aPrivateKey,
1.133 + TRSAPrivateKeyType aKeyType /*=EStandardCRT*/)
1.134 +{
1.135 + aPublicKey = NULL;
1.136 + aPrivateKey = NULL;
1.137 +
1.138 + // Enter into the containing SEQUENCE and verify if it is
1.139 + // indeed there
1.140 + TASN1DecGeneric gen(aDER.Right(aDER.Length() - aPos));
1.141 + gen.InitL();
1.142 + TInt end = aPos + gen.LengthDER();
1.143 + aPos += gen.LengthDERHeader();
1.144 + if (gen.Tag() != EASN1Sequence)
1.145 + User::Leave(KErrArgument);
1.146 +
1.147 + TASN1DecInteger encInt;
1.148 +
1.149 + // Decode and discard version, which is an integer
1.150 + encInt.DecodeDERShortL(aDER, aPos);
1.151 +
1.152 + // Decode public key components
1.153 +
1.154 + // Decode modulus
1.155 + RInteger publicModulus = encInt.DecodeDERLongL(aDER, aPos);
1.156 + CleanupStack::PushL(publicModulus);
1.157 +
1.158 + // Decode public exponent
1.159 + RInteger publicExponent = encInt.DecodeDERLongL(aDER, aPos);
1.160 + CleanupStack::PushL(publicExponent);
1.161 +
1.162 + // Construct public key
1.163 + CRSAPublicKey* publicKey = CRSAPublicKey::NewL(publicModulus, publicExponent);
1.164 + CleanupStack::Pop(2, &publicModulus); // Now owned by publicKey
1.165 + CleanupStack::PushL(publicKey);
1.166 +
1.167 + // Decode private key components
1.168 +
1.169 + // Copy modulus
1.170 + RInteger privateModulus = RInteger::NewL(publicKey->N());
1.171 + CleanupStack::PushL(privateModulus);
1.172 + // Decode private exponent
1.173 + RInteger privateExponent = encInt.DecodeDERLongL(aDER, aPos);
1.174 + CleanupStack::PushL(privateExponent);
1.175 + // Decode prime 1
1.176 + RInteger p = encInt.DecodeDERLongL(aDER, aPos);
1.177 + CleanupStack::PushL(p);
1.178 + // Decode prime 2
1.179 + RInteger q = encInt.DecodeDERLongL(aDER, aPos);
1.180 + CleanupStack::PushL(q);
1.181 + // Decode exponent 1
1.182 + RInteger dmp1 = encInt.DecodeDERLongL(aDER, aPos);
1.183 + CleanupStack::PushL(dmp1);
1.184 + // Decode exponent 2
1.185 + RInteger dmq1 = encInt.DecodeDERLongL(aDER, aPos);
1.186 + CleanupStack::PushL(dmq1);
1.187 + // Decode coefficient
1.188 + RInteger the_iqmp = encInt.DecodeDERLongL(aDER, aPos);
1.189 + CleanupStack::PushL(the_iqmp);
1.190 +
1.191 + // We now should be at the end of the encoding. If not, the
1.192 + // input encoding contains extra fields, and they are not
1.193 + // supported.
1.194 + if (aPos != end)
1.195 + User::Leave(KErrArgument);
1.196 +
1.197 +// Construct private key
1.198 + CRSAPrivateKey* privateKey = NULL;
1.199 + if (EStandardCRT==aKeyType)
1.200 + {
1.201 + privateKey = CRSAPrivateKeyCRT::NewL(privateModulus, p, q, dmp1, dmq1, the_iqmp);
1.202 + }
1.203 + else if (EStandard==aKeyType)
1.204 + {
1.205 + privateKey = CRSAPrivateKeyStandard::NewL(privateModulus, privateExponent);
1.206 + }
1.207 + else
1.208 + User::Leave(KErrNotSupported);
1.209 +
1.210 + CleanupStack::Pop(8,publicKey); // publicKey, privateModulus, privateExponent,
1.211 + // p, q, dmp1, dmq1, iqmp
1.212 +
1.213 +// Cleanup the TIntegers not owned by private key objects
1.214 + if (EStandard==aKeyType)
1.215 + {
1.216 + p.Close();
1.217 + q.Close();
1.218 + dmp1.Close();
1.219 + dmq1.Close();
1.220 + the_iqmp.Close();
1.221 + }
1.222 + else
1.223 + {
1.224 + privateExponent.Close();
1.225 + }
1.226 +
1.227 + aPublicKey = publicKey;
1.228 + aPrivateKey = privateKey;
1.229 +}
1.230 +
1.231 +// TX509RSAKeyEncoder Class Implementation
1.232 +
1.233 +EXPORT_C TX509RSAKeyEncoder::TX509RSAKeyEncoder(const CRSAPublicKey& aPublicKey, TAlgorithmId aDigestAlg)
1.234 + : TX509KeyEncoder(aDigestAlg),
1.235 + iPublicKey(aPublicKey)
1.236 + {
1.237 + }
1.238 +
1.239 +EXPORT_C CASN1EncBase* TX509RSAKeyEncoder::EncodeKeyLC() const
1.240 + {
1.241 + // Create higher-level sequence that will contain OID and the public key
1.242 + CASN1EncSequence* subjectPubKeyInfo = CASN1EncSequence::NewLC();
1.243 +
1.244 + // The next-level sequence will contain OID of the algorithm followed by NULL
1.245 + CASN1EncSequence* seq = CASN1EncSequence::NewLC();
1.246 + CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KRSA);
1.247 + seq->AddAndPopChildL(oid);
1.248 + CASN1EncNull* null = CASN1EncNull::NewLC();
1.249 + seq->AddAndPopChildL(null);
1.250 + subjectPubKeyInfo->AddAndPopChildL(seq);
1.251 +
1.252 + // Add the key itself to the higher-level sequence as a bit string
1.253 + // Obtain a copy of the entity's public key
1.254 + TASN1EncRSAPublicKey keyencoder;
1.255 + HBufC8* encoding = keyencoder.EncodeDERL(iPublicKey);
1.256 + CleanupStack::PushL(encoding);
1.257 + CASN1EncBitString* pubkeyenc = CASN1EncBitString::NewLC(*encoding);
1.258 + subjectPubKeyInfo->AddAndPopChildL(pubkeyenc);
1.259 + CleanupStack::PopAndDestroy(encoding);
1.260 + return subjectPubKeyInfo;
1.261 + }
1.262 +
1.263 +// Returns ASN.1 sequence containing encoded signature algorithm.
1.264 +EXPORT_C CASN1EncSequence* TX509RSAKeyEncoder::EncodeSignatureAlgorithmLC() const
1.265 + {
1.266 + CASN1EncSequence* seq = CASN1EncSequence::NewLC();
1.267 + CASN1EncObjectIdentifier* oid = NULL;
1.268 +
1.269 + // Determine OID string for the current combination of algorithms.
1.270 + switch(iDigestAlg)
1.271 + {
1.272 + default:
1.273 + User::Leave(KErrNotSupported);
1.274 + break;
1.275 +
1.276 + case EMD2:
1.277 + oid = CASN1EncObjectIdentifier::NewLC(KMD2WithRSA);
1.278 + break;
1.279 +
1.280 + case EMD5:
1.281 + oid = CASN1EncObjectIdentifier::NewLC(KMD5WithRSA);
1.282 + break;
1.283 +
1.284 + case ESHA1:
1.285 + oid = CASN1EncObjectIdentifier::NewLC(KSHA1WithRSA);
1.286 + break;
1.287 + }
1.288 +
1.289 + // Add algorithm OID to the sequence.
1.290 + seq->AddAndPopChildL(oid);
1.291 + // Add NULL after OID.
1.292 + CASN1EncNull* null = CASN1EncNull::NewLC();
1.293 + seq->AddAndPopChildL(null);
1.294 +
1.295 + return seq;
1.296 + }