diff -r 000000000000 -r 2c201484c85f cryptoservices/asnpkcs/source/asnpkcs8enc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cryptoservices/asnpkcs/source/asnpkcs8enc.cpp Wed Jul 08 11:25:26 2009 +0100 @@ -0,0 +1,364 @@ +/* +* Copyright (c) 2004-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 "asnpkcs.h" + +const TInt KPkcs8Version = 0; // PKCS#8 version 0 +const TInt KPkcs8RSATwoPrime = 0; // We support only two-prime RSA. + + +/*static*/ void TASN1EncPKCS8::AddAttributesL(CASN1EncSequence& aSeq, const TDesC8& aAttribute) + { + if (aAttribute != KNullDesC8) + { + CASN1EncEncoding* encoded = CASN1EncEncoding::NewLC(aAttribute); + aSeq.AddAndPopChildL(encoded); + } + } + +/** + * Given a ASN1 sequence representing a private key and a CPBEncryptor object, + * it returns an ASN1 octet string containing the key sequence encrypted by + * the given encryptor. + * + * @param aKeySeq The key sequence to be encrypted. + * @param aEncryptor The CPBEncryptor object used to encrypt the given key. + * @return An ASN1 octet string containing the encrypted key. + */ +/*static*/ CASN1EncOctetString* TASN1EncPKCS8::EncryptKeySequenceL(CASN1EncSequence& aKeySeq, CPBEncryptor& aEncryptor) + { + // Make an octet string of the key sequence + TUint seqLen = aKeySeq.LengthDER(); + HBufC8* octetData = HBufC8::NewMaxLC(seqLen); + TPtr8 oct(octetData->Des()); + oct.FillZ(); + TUint writePos = 0; + aKeySeq.WriteDERL(oct, writePos); + + // Encrypt it + HBufC8* encryptedData = HBufC8::NewLC(aEncryptor.MaxFinalOutputLength(seqLen)); + TPtr8 encrypted(encryptedData->Des()); + + aEncryptor.ProcessFinalL(*octetData, encrypted); + + CASN1EncOctetString* octet = CASN1EncOctetString::NewL(encrypted); + + CleanupStack::PopAndDestroy(2, octetData); // encryptedData, octetData + + return octet; + } + + +/*static*/ CASN1EncOctetString* TASN1EncPKCS8::ElementToOctetL(CASN1EncBase& aAsnElement) + { + // Make an octet string from the structure + HBufC8* octetData = HBufC8::NewMaxLC(aAsnElement.LengthDER()); + TPtr8 oct(octetData->Des()); + oct.FillZ(); + + TUint writePos = 0; + aAsnElement.WriteDERL(oct, writePos); + + CASN1EncOctetString* octet = CASN1EncOctetString::NewL(oct); + CleanupStack::PopAndDestroy(octetData); + return octet; + } + + +/*static*/ CASN1EncSequence* TASN1EncPKCS8::EncryptedSequenceL(CASN1EncSequence& aPrivateKeySequence, + CPBEncryptor& aEncryptor, CPBEncryptParms& aData) + { + // Main ASN1 sequence + CASN1EncSequence* seq = CASN1EncSequence::NewLC(); + + // PKCS#5 PBE sequence + CASN1EncSequence* pkcs5Seq = TASN1EncPKCS5::EncodeDERL(aData); + + CleanupStack::PushL(pkcs5Seq); + seq->AddAndPopChildL(pkcs5Seq); + + // Encrypt the Private Key Sequence + CASN1EncOctetString* octet = EncryptKeySequenceL(aPrivateKeySequence, aEncryptor); + CleanupStack::PushL(octet); + seq->AddAndPopChildL(octet); + + CleanupStack::Pop(seq); + + return seq; + } + + +/*static*/ const RInteger TASN1EncPKCS8::CalculateRSAPrivExpL(const CRSAPrivateKeyCRT& aPrivateKey, const CRSAPublicKey& aPublicKey) + { + const TInteger& e = aPublicKey.E(); + + RInteger pTemp = RInteger::NewL(aPrivateKey.P()); + CleanupStack::PushL(pTemp); + RInteger qTemp = RInteger::NewL(aPrivateKey.Q()); + CleanupStack::PushL(qTemp); + + --pTemp; + --qTemp; + + //phi = (p-1)(q-1) + RInteger phi = pTemp.TimesL(qTemp); + + CleanupStack::PopAndDestroy(2, &pTemp); // qTemp, pTemp + CleanupStack::PushL(phi); + + //d = e^(-1) mod ((p-1)(q-1)) + RInteger d = e.InverseModL(phi); + CleanupStack::PopAndDestroy(&phi); + return d; + } + +/** + * Encodes the given private key using the pkcs#8 standard. + * + * The returned ASN1 sequence respects the following grammar: + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * Attributes ::= SET OF Attribute + * + * + * @param aKeyPair A key pair containing the private key we wish to encode. + * @return A CASN1EncSequence encoding the private key. The sequence + * follows the grammar specified above. + * @internalComponent + * @released + */ +/*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeL(const CRSAPrivateKeyCRT& aPrivateKey, + const CRSAPublicKey& aPublicKey, + const TDesC8& aAttributes) + { + // Main ASN1 sequence + CASN1EncSequence* seq = CASN1EncSequence::NewLC(); + + // Start with PKCS#8 header + CASN1EncInt* version = CASN1EncInt::NewLC(KPkcs8Version); + seq->AddAndPopChildL(version); + + // Algorithm sequence + CASN1EncSequence* algSeq = CASN1EncSequence::NewLC(); + + CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KRSA); + algSeq->AddAndPopChildL(oid); + + // No other parameters + CASN1EncNull* nullparams = CASN1EncNull::NewLC(); + algSeq->AddAndPopChildL(nullparams); + + seq->AddAndPopChildL(algSeq); + + // The actual private key sequence + CASN1EncSequence* keySeq = CASN1EncSequence::NewLC(); + + // TASN1DecGeneric* versionData = theData->operator[](seqIndex); + CASN1EncInt* rsaVersion = CASN1EncInt::NewLC(KPkcs8RSATwoPrime); + keySeq->AddAndPopChildL(rsaVersion); + + // The modulus + const TInteger& modulus = aPrivateKey.N(); + CASN1EncBigInt* mod = CASN1EncBigInt::NewLC(modulus); + keySeq->AddAndPopChildL(mod); + + // The public exponent + const TInteger& e = aPublicKey.E(); + CASN1EncBigInt* publicExp = CASN1EncBigInt::NewLC(e); + keySeq->AddAndPopChildL(publicExp); + + // The private exponent + RInteger d = CalculateRSAPrivExpL(aPrivateKey, aPublicKey); + CleanupStack::PushL(d); + + CASN1EncBigInt* privateExp = CASN1EncBigInt::NewLC(d); + + keySeq->AddAndPopChildL(privateExp); + CleanupStack::PopAndDestroy(&d); // RSA Private Exponent + + // The prime1 + const TInteger& p = aPrivateKey.P(); + CASN1EncBigInt* prime1 = CASN1EncBigInt::NewLC(p); + keySeq->AddAndPopChildL(prime1); + + // The prime2 + const TInteger& q = aPrivateKey.Q(); + CASN1EncBigInt* prime2 = CASN1EncBigInt::NewLC(q); + keySeq->AddAndPopChildL(prime2); + + // The exponent 1 + const TInteger& dp = aPrivateKey.DP(); + CASN1EncBigInt* theExp1 = CASN1EncBigInt::NewLC(dp); + keySeq->AddAndPopChildL(theExp1); + + // The exponent 2 + const TInteger& dq = aPrivateKey.DQ(); + CASN1EncBigInt* theExp2 = CASN1EncBigInt::NewLC(dq); + keySeq->AddAndPopChildL(theExp2); + + // The coefficient + const TInteger& coeff = aPrivateKey.QInv(); + CASN1EncBigInt* coefficient = CASN1EncBigInt::NewLC(coeff); + keySeq->AddAndPopChildL(coefficient); + + CASN1EncOctetString* octet = ElementToOctetL(*keySeq); + CleanupStack::PushL(octet); + + // Now add the octet of the key sequence to the sequence + seq->AddAndPopChildL(octet); + + CleanupStack::PopAndDestroy(keySeq); + + AddAttributesL(*seq, aAttributes); + + CleanupStack::Pop(seq); + + return seq; + } + +/** + * Encodes an RSA key in encrypted format. + * + * @param aPrivateKey The private key to be encoded (must be in CRT format) + * @param aPublicKey The corresponding public key. + * @param aEncryptor The object used to encrypt the data. + * @param aData The encryption parameters of the given encryptor. + * These parameters are stored in the resulting sequence. + * + * @return An ASN1 Sequence encoding the encrypted key. + */ +/*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeEncryptedL(const CRSAPrivateKeyCRT& aPrivateKey, const CRSAPublicKey& aPublicKey, + CPBEncryptor& aEncryptor, CPBEncryptParms& aData, const TDesC8& aAttributes) + { + // Now generate a PrivateKeyInfo type + CASN1EncSequence* privKeySeq = EncodeL(aPrivateKey, aPublicKey, aAttributes); + CleanupStack::PushL(privKeySeq); + + CASN1EncSequence* seq = EncryptedSequenceL(*privKeySeq, aEncryptor, aData); + + CleanupStack::PopAndDestroy(privKeySeq); + + return seq; + } + + +/** + * Return the ASN1 PKCS#8 encoding of a DSA private key. + * + * The private key syntax for this key type is defined in + * the PKCS#11 document. + * + * @param aPrivateKey The private key to be encoded (must be in CRT format) + * + * @return An ASN1 Sequence encoding the key. + */ +/*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeL(const CDSAPrivateKey& aPrivateKey, + const TDesC8& aAttributes) + { + // Main ASN1 sequence + CASN1EncSequence* seq = CASN1EncSequence::NewLC(); + + // version + CASN1EncInt* version = CASN1EncInt::NewLC(KPkcs8Version); + seq->AddAndPopChildL(version); + + // Algorithm sequence + CASN1EncSequence* algSeq = CASN1EncSequence::NewLC(); + + CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KDSA); + algSeq->AddAndPopChildL(oid); + + seq->AddAndPopChildL(algSeq); + + // DSA Parameters + CASN1EncSequence* keySeq = CASN1EncSequence::NewLC(); + + // The modulus P + const TInteger& modulus1 = aPrivateKey.P(); + + CASN1EncBigInt* mod = CASN1EncBigInt::NewLC(modulus1); + keySeq->AddAndPopChildL(mod); + + // The modulus Q + const TInteger& modulus2 = aPrivateKey.Q(); + + CASN1EncBigInt* mod2 = CASN1EncBigInt::NewLC(modulus2); + keySeq->AddAndPopChildL(mod2); + + // The base G + const TInteger& base = aPrivateKey.G(); + + CASN1EncBigInt* b = CASN1EncBigInt::NewLC(base); + keySeq->AddAndPopChildL(b); + + algSeq->AddAndPopChildL(keySeq); + + // The private key X + const TInteger& priv = aPrivateKey.X(); + CASN1EncBigInt* x = CASN1EncBigInt::NewLC(priv); + + CASN1EncOctetString* octet = ElementToOctetL(*x); + + CleanupStack::PopAndDestroy(x); + CleanupStack::PushL(octet); + + seq->AddAndPopChildL(octet); + + AddAttributesL(*seq, aAttributes); + + CleanupStack::Pop(seq); + + return seq; + } + + +/** + * Encodes a DSA key in encrypted format. + * + * @param aPrivateKey The private key to be encoded. + * @param aEncryptor The object used to encrypt the data. + * @param aData The encryption parameters of the given encryptor. + * These parameters are stored in the resulting sequence. + * + * @return An ASN1 Sequence encoding the encrypted key. + */ +/*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeEncryptedL(const CDSAPrivateKey& aPrivateKey, CPBEncryptor& aEncryptor, + CPBEncryptParms& aData, const TDesC8& aAttributes) + { + // Now generate a PrivateKeyInfo type + CASN1EncSequence* privKeySeq = EncodeL(aPrivateKey, aAttributes); + CleanupStack::PushL(privKeySeq); + + CASN1EncSequence* seq = EncryptedSequenceL(*privKeySeq, aEncryptor, aData); + + CleanupStack::PopAndDestroy(privKeySeq); + + return seq; + }