--- /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 <asn1enc.h>
+#include <pbe.h>
+#include <asymmetrickeys.h>
+#include <bigint.h>
+#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;
+ }