diff -r 000000000000 -r bde4ae8d615e os/security/cryptoservices/certificateandkeymgmt/x509/x509keysRSA.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/security/cryptoservices/certificateandkeymgmt/x509/x509keysRSA.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,293 @@ +/* +* 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 +#include +#include +#include +#include "x509keyencoder.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; + }