--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/x509/x509keysRSA.cpp Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,292 @@
+/*
+* Copyright (c) 1998-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 <x509keys.h>
+#include <asn1dec.h>
+#include <asn1enc.h>
+#include <x509cert.h>
+
+CX509RSAPublicKey::CX509RSAPublicKey()
+{}
+
+//RSA public key
+EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewL(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509RSAPublicKey::NewL(aBinaryData, pos);
+ }
+
+EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewLC(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CX509RSAPublicKey::NewLC(aBinaryData, pos);
+ }
+
+EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509RSAPublicKey* self = CX509RSAPublicKey::NewLC(aBinaryData, aPos);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CX509RSAPublicKey* self = new(ELeave) CX509RSAPublicKey();
+ CleanupStack::PushL(self);
+ self->ConstructL(aBinaryData, aPos);
+ return self;
+ }
+
+void CX509RSAPublicKey::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos));
+ gen.InitL();
+ TInt end = aPos + gen.LengthDER();
+ aPos += gen.LengthDERHeader();
+ if (gen.Tag() != EASN1Sequence)
+ {
+ User::Leave(KErrArgument);
+ }
+ TASN1DecInteger encInt;
+ iN = encInt.DecodeDERLongL(aBinaryData, aPos);
+ iE = encInt.DecodeDERLongL(aBinaryData, aPos);
+
+ // RSA Public keys, modulus and exponent must be positive integers
+ if(!iN.IsPositive() || !iE.IsPositive())
+ {
+ User::Leave(KErrArgument);
+ }
+ if (aPos != end)
+ {
+ User::Leave(KErrArgument);
+ }
+ }
+
+// Encodes public key to DER
+EXPORT_C HBufC8* TASN1EncRSAPublicKey::EncodeDERL(const CRSAPublicKey& aKey) const
+ {
+ CASN1EncSequence* sequence = CASN1EncSequence::NewLC();
+ CASN1EncBigInt* encModulus = CASN1EncBigInt::NewLC(aKey.N());
+ sequence->AddAndPopChildL(encModulus);
+ CASN1EncBigInt* encPublicExponent = CASN1EncBigInt::NewLC(aKey.E());
+ sequence->AddAndPopChildL(encPublicExponent);
+ HBufC8* der = HBufC8::NewMaxLC(sequence->LengthDER());
+ TUint pos = 0;
+ TPtr8 derptr(der->Des());
+ sequence->WriteDERL(derptr, pos);
+ CleanupStack::Pop(der);
+ CleanupStack::PopAndDestroy(sequence);
+ return der;
+ }
+
+// Decodes public key from DER
+EXPORT_C CRSAPublicKey* TASN1DecRSAPublicKey::DecodeDERL(const TDesC8& aDER,
+ TInt& aPos) const
+ {
+ // Enter into the containing SEQUENCE and verify if it is indeed there
+ TASN1DecGeneric gen(aDER.Right(aDER.Length() - aPos));
+ gen.InitL();
+ TInt end = aPos + gen.LengthDER();
+ aPos += gen.LengthDERHeader();
+ if (gen.Tag() != EASN1Sequence)
+ User::Leave(KErrArgument);
+
+ // Decode modulus and public exponent (two large integers)
+ TASN1DecInteger encInt;
+ RInteger modulus = encInt.DecodeDERLongL(aDER, aPos);
+ CleanupStack::PushL(modulus);
+ RInteger publicExponent = encInt.DecodeDERLongL(aDER, aPos);
+ CleanupStack::PushL(publicExponent);
+ if (aPos != end)
+ User::Leave(KErrArgument);
+
+ // Construct a new key without copying
+ CRSAPublicKey* key = CRSAPublicKey::NewL(modulus, publicExponent);
+ CleanupStack::Pop(2); // modulus, publicExponent - owned by public key
+ return key;
+ }
+
+// Decodes RSA key pair from DER-encoded buffer
+EXPORT_C void TASN1DecRSAKeyPair::DecodeDERL(const TDesC8& aDER,
+ TInt& aPos,
+ CRSAPublicKey*& aPublicKey,
+ CRSAPrivateKey*& aPrivateKey,
+ TRSAPrivateKeyType aKeyType /*=EStandardCRT*/)
+{
+ aPublicKey = NULL;
+ aPrivateKey = NULL;
+
+ // Enter into the containing SEQUENCE and verify if it is
+ // indeed there
+ TASN1DecGeneric gen(aDER.Right(aDER.Length() - aPos));
+ gen.InitL();
+ TInt end = aPos + gen.LengthDER();
+ aPos += gen.LengthDERHeader();
+ if (gen.Tag() != EASN1Sequence)
+ User::Leave(KErrArgument);
+
+ TASN1DecInteger encInt;
+
+ // Decode and discard version, which is an integer
+ encInt.DecodeDERShortL(aDER, aPos);
+
+ // Decode public key components
+
+ // Decode modulus
+ RInteger publicModulus = encInt.DecodeDERLongL(aDER, aPos);
+ CleanupStack::PushL(publicModulus);
+
+ // Decode public exponent
+ RInteger publicExponent = encInt.DecodeDERLongL(aDER, aPos);
+ CleanupStack::PushL(publicExponent);
+
+ // Construct public key
+ CRSAPublicKey* publicKey = CRSAPublicKey::NewL(publicModulus, publicExponent);
+ CleanupStack::Pop(2, &publicModulus); // Now owned by publicKey
+ CleanupStack::PushL(publicKey);
+
+ // Decode private key components
+
+ // Copy modulus
+ RInteger privateModulus = RInteger::NewL(publicKey->N());
+ CleanupStack::PushL(privateModulus);
+ // Decode private exponent
+ RInteger privateExponent = encInt.DecodeDERLongL(aDER, aPos);
+ CleanupStack::PushL(privateExponent);
+ // Decode prime 1
+ RInteger p = encInt.DecodeDERLongL(aDER, aPos);
+ CleanupStack::PushL(p);
+ // Decode prime 2
+ RInteger q = encInt.DecodeDERLongL(aDER, aPos);
+ CleanupStack::PushL(q);
+ // Decode exponent 1
+ RInteger dmp1 = encInt.DecodeDERLongL(aDER, aPos);
+ CleanupStack::PushL(dmp1);
+ // Decode exponent 2
+ RInteger dmq1 = encInt.DecodeDERLongL(aDER, aPos);
+ CleanupStack::PushL(dmq1);
+ // Decode coefficient
+ RInteger the_iqmp = encInt.DecodeDERLongL(aDER, aPos);
+ CleanupStack::PushL(the_iqmp);
+
+ // We now should be at the end of the encoding. If not, the
+ // input encoding contains extra fields, and they are not
+ // supported.
+ if (aPos != end)
+ User::Leave(KErrArgument);
+
+// Construct private key
+ CRSAPrivateKey* privateKey = NULL;
+ if (EStandardCRT==aKeyType)
+ {
+ privateKey = CRSAPrivateKeyCRT::NewL(privateModulus, p, q, dmp1, dmq1, the_iqmp);
+ }
+ else if (EStandard==aKeyType)
+ {
+ privateKey = CRSAPrivateKeyStandard::NewL(privateModulus, privateExponent);
+ }
+ else
+ User::Leave(KErrNotSupported);
+
+ CleanupStack::Pop(8,publicKey); // publicKey, privateModulus, privateExponent,
+ // p, q, dmp1, dmq1, iqmp
+
+// Cleanup the TIntegers not owned by private key objects
+ if (EStandard==aKeyType)
+ {
+ p.Close();
+ q.Close();
+ dmp1.Close();
+ dmq1.Close();
+ the_iqmp.Close();
+ }
+ else
+ {
+ privateExponent.Close();
+ }
+
+ aPublicKey = publicKey;
+ aPrivateKey = privateKey;
+}
+
+// TX509RSAKeyEncoder Class Implementation
+
+EXPORT_C TX509RSAKeyEncoder::TX509RSAKeyEncoder(const CRSAPublicKey& aPublicKey, TAlgorithmId aDigestAlg)
+ : TX509KeyEncoder(aDigestAlg),
+ iPublicKey(aPublicKey)
+ {
+ }
+
+EXPORT_C CASN1EncBase* TX509RSAKeyEncoder::EncodeKeyLC() const
+ {
+ // Create higher-level sequence that will contain OID and the public key
+ CASN1EncSequence* subjectPubKeyInfo = CASN1EncSequence::NewLC();
+
+ // The next-level sequence will contain OID of the algorithm followed by NULL
+ CASN1EncSequence* seq = CASN1EncSequence::NewLC();
+ CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KRSA);
+ seq->AddAndPopChildL(oid);
+ CASN1EncNull* null = CASN1EncNull::NewLC();
+ seq->AddAndPopChildL(null);
+ subjectPubKeyInfo->AddAndPopChildL(seq);
+
+ // Add the key itself to the higher-level sequence as a bit string
+ // Obtain a copy of the entity's public key
+ TASN1EncRSAPublicKey keyencoder;
+ HBufC8* encoding = keyencoder.EncodeDERL(iPublicKey);
+ CleanupStack::PushL(encoding);
+ CASN1EncBitString* pubkeyenc = CASN1EncBitString::NewLC(*encoding);
+ subjectPubKeyInfo->AddAndPopChildL(pubkeyenc);
+ CleanupStack::PopAndDestroy(encoding);
+ return subjectPubKeyInfo;
+ }
+
+// Returns ASN.1 sequence containing encoded signature algorithm.
+EXPORT_C CASN1EncSequence* TX509RSAKeyEncoder::EncodeSignatureAlgorithmLC() const
+ {
+ CASN1EncSequence* seq = CASN1EncSequence::NewLC();
+ CASN1EncObjectIdentifier* oid = NULL;
+
+ // Determine OID string for the current combination of algorithms.
+ switch(iDigestAlg)
+ {
+ default:
+ User::Leave(KErrNotSupported);
+ break;
+
+ case EMD2:
+ oid = CASN1EncObjectIdentifier::NewLC(KMD2WithRSA);
+ break;
+
+ case EMD5:
+ oid = CASN1EncObjectIdentifier::NewLC(KMD5WithRSA);
+ break;
+
+ case ESHA1:
+ oid = CASN1EncObjectIdentifier::NewLC(KSHA1WithRSA);
+ break;
+ }
+
+ // Add algorithm OID to the sequence.
+ seq->AddAndPopChildL(oid);
+ // Add NULL after OID.
+ CASN1EncNull* null = CASN1EncNull::NewLC();
+ seq->AddAndPopChildL(null);
+
+ return seq;
+ }