cryptoservices/asnpkcs/source/asnpkcs8enc.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
--- /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;
+	}