cryptoservices/asnpkcs/source/asnpkcs8enc.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
equal deleted inserted replaced
-1:000000000000 0:2c201484c85f
       
     1 /*
       
     2 * Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <asn1enc.h>
       
    20 #include <pbe.h>
       
    21 #include <asymmetrickeys.h>
       
    22 #include <bigint.h>
       
    23 #include "asnpkcs.h"
       
    24 
       
    25 const TInt KPkcs8Version = 0;      // PKCS#8 version 0 
       
    26 const TInt KPkcs8RSATwoPrime = 0;  // We support only two-prime RSA. 
       
    27 
       
    28 
       
    29 /*static*/ void TASN1EncPKCS8::AddAttributesL(CASN1EncSequence& aSeq, const TDesC8& aAttribute)
       
    30 	{
       
    31 	if (aAttribute != KNullDesC8)
       
    32 		{
       
    33 		CASN1EncEncoding* encoded = CASN1EncEncoding::NewLC(aAttribute);
       
    34 		aSeq.AddAndPopChildL(encoded);		
       
    35 		}
       
    36 	}
       
    37 
       
    38 /**
       
    39  * Given a ASN1 sequence representing a private key and a CPBEncryptor object,
       
    40  * it returns an ASN1 octet string containing the key sequence encrypted by
       
    41  * the given encryptor.
       
    42  *
       
    43  * @param aKeySeq The key sequence to be encrypted.
       
    44  * @param aEncryptor The CPBEncryptor object used to encrypt the given key.
       
    45  * @return An ASN1 octet string containing the encrypted key.
       
    46  */
       
    47 /*static*/ CASN1EncOctetString* TASN1EncPKCS8::EncryptKeySequenceL(CASN1EncSequence& aKeySeq, CPBEncryptor& aEncryptor)
       
    48 	{
       
    49 	//	Make an octet string of the key sequence
       
    50 	TUint seqLen = aKeySeq.LengthDER();
       
    51 	HBufC8* octetData = HBufC8::NewMaxLC(seqLen);
       
    52 	TPtr8 oct(octetData->Des());
       
    53 	oct.FillZ();
       
    54 	TUint writePos = 0;
       
    55 	aKeySeq.WriteDERL(oct, writePos);
       
    56 	
       
    57 	// Encrypt it
       
    58         HBufC8* encryptedData = HBufC8::NewLC(aEncryptor.MaxFinalOutputLength(seqLen)); 
       
    59         TPtr8 encrypted(encryptedData->Des());  
       
    60 
       
    61 	aEncryptor.ProcessFinalL(*octetData, encrypted);
       
    62 		
       
    63 	CASN1EncOctetString* octet = CASN1EncOctetString::NewL(encrypted);
       
    64 	
       
    65 	CleanupStack::PopAndDestroy(2, octetData); // encryptedData, octetData
       
    66 	
       
    67 	return octet;
       
    68 	}
       
    69 
       
    70 
       
    71 /*static*/ CASN1EncOctetString* TASN1EncPKCS8::ElementToOctetL(CASN1EncBase& aAsnElement)
       
    72 	{
       
    73 	//	Make an octet string from the structure
       
    74 	HBufC8* octetData = HBufC8::NewMaxLC(aAsnElement.LengthDER());
       
    75 	TPtr8 oct(octetData->Des());
       
    76 	oct.FillZ();
       
    77 
       
    78 	TUint writePos = 0;
       
    79 	aAsnElement.WriteDERL(oct, writePos);
       
    80 	
       
    81 	CASN1EncOctetString* octet = CASN1EncOctetString::NewL(oct);
       
    82 	CleanupStack::PopAndDestroy(octetData);
       
    83 	return octet;
       
    84 	}
       
    85 
       
    86 
       
    87 /*static*/ CASN1EncSequence* TASN1EncPKCS8::EncryptedSequenceL(CASN1EncSequence& aPrivateKeySequence, 
       
    88                                                                CPBEncryptor& aEncryptor, CPBEncryptParms& aData)
       
    89 	{
       
    90 	// Main ASN1 sequence
       
    91 	CASN1EncSequence* seq = CASN1EncSequence::NewLC();
       
    92 	
       
    93 	// PKCS#5 PBE sequence
       
    94 	CASN1EncSequence* pkcs5Seq = TASN1EncPKCS5::EncodeDERL(aData);
       
    95 	 
       
    96 	CleanupStack::PushL(pkcs5Seq);
       
    97 	seq->AddAndPopChildL(pkcs5Seq);
       
    98 	
       
    99 	// Encrypt the Private Key Sequence
       
   100 	CASN1EncOctetString* octet = EncryptKeySequenceL(aPrivateKeySequence, aEncryptor);
       
   101 	CleanupStack::PushL(octet);
       
   102 	seq->AddAndPopChildL(octet);
       
   103 
       
   104 	CleanupStack::Pop(seq);
       
   105 
       
   106 	return seq;
       
   107 	}
       
   108 
       
   109 
       
   110 /*static*/ const RInteger TASN1EncPKCS8::CalculateRSAPrivExpL(const CRSAPrivateKeyCRT& aPrivateKey, const CRSAPublicKey& aPublicKey)
       
   111 	{
       
   112 	const TInteger& e = aPublicKey.E();
       
   113 
       
   114 	RInteger pTemp = RInteger::NewL(aPrivateKey.P());
       
   115 	CleanupStack::PushL(pTemp);
       
   116 	RInteger qTemp = RInteger::NewL(aPrivateKey.Q());
       
   117 	CleanupStack::PushL(qTemp);
       
   118 	
       
   119   	--pTemp;
       
   120     	--qTemp;
       
   121  
       
   122 	//phi = (p-1)(q-1)
       
   123 	RInteger phi = pTemp.TimesL(qTemp);
       
   124 
       
   125 	CleanupStack::PopAndDestroy(2, &pTemp);  // qTemp, pTemp
       
   126  	CleanupStack::PushL(phi);
       
   127     	
       
   128     	//d = e^(-1) mod ((p-1)(q-1))
       
   129    	 RInteger d = e.InverseModL(phi);
       
   130     	CleanupStack::PopAndDestroy(&phi); 
       
   131 	return d;	
       
   132 	}
       
   133 
       
   134 /**
       
   135  * Encodes the given private key using the pkcs#8 standard.
       
   136  *
       
   137  * The returned ASN1 sequence respects the following grammar:
       
   138  * 
       
   139  *	PrivateKeyInfo ::= SEQUENCE {
       
   140  *	version Version,
       
   141  *	privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
       
   142  *	privateKey PrivateKey,
       
   143  *	attributes [0] IMPLICIT Attributes OPTIONAL }
       
   144  *	
       
   145  *	Version ::= INTEGER
       
   146  *	PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
       
   147  *	PrivateKey ::= OCTET STRING
       
   148  *	Attributes ::= SET OF Attribute
       
   149  *
       
   150  *
       
   151  * @param aKeyPair A key pair containing the private key we wish to encode.
       
   152  * @return A CASN1EncSequence encoding the private key. The sequence
       
   153  *         follows the grammar specified above. 
       
   154  * @internalComponent
       
   155  * @released
       
   156  */
       
   157 /*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeL(const CRSAPrivateKeyCRT& aPrivateKey, 
       
   158 														  const CRSAPublicKey& aPublicKey, 
       
   159 														  const TDesC8& aAttributes)
       
   160 	{
       
   161 	// Main ASN1 sequence
       
   162 	CASN1EncSequence* seq = CASN1EncSequence::NewLC();
       
   163 
       
   164 	// Start with PKCS#8 header
       
   165 	CASN1EncInt* version = CASN1EncInt::NewLC(KPkcs8Version); 
       
   166 	seq->AddAndPopChildL(version);
       
   167 	
       
   168 	//	Algorithm sequence
       
   169 	CASN1EncSequence* algSeq = CASN1EncSequence::NewLC();
       
   170 
       
   171 	CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KRSA);
       
   172 	algSeq->AddAndPopChildL(oid);
       
   173 
       
   174 	//	No other parameters
       
   175 	CASN1EncNull* nullparams = CASN1EncNull::NewLC();
       
   176 	algSeq->AddAndPopChildL(nullparams);
       
   177 
       
   178 	seq->AddAndPopChildL(algSeq);
       
   179 	
       
   180 	// The actual private key sequence		
       
   181 	CASN1EncSequence* keySeq = CASN1EncSequence::NewLC();
       
   182 
       
   183 	//	TASN1DecGeneric* versionData = theData->operator[](seqIndex);
       
   184 	CASN1EncInt* rsaVersion = CASN1EncInt::NewLC(KPkcs8RSATwoPrime); 
       
   185 	keySeq->AddAndPopChildL(rsaVersion);
       
   186 	
       
   187 	//	The modulus	
       
   188 	const TInteger& modulus = aPrivateKey.N();
       
   189 	CASN1EncBigInt* mod = CASN1EncBigInt::NewLC(modulus);
       
   190 	keySeq->AddAndPopChildL(mod);
       
   191 
       
   192 	//	The public exponent
       
   193 	const TInteger& e = aPublicKey.E();
       
   194 	CASN1EncBigInt* publicExp = CASN1EncBigInt::NewLC(e);
       
   195 	keySeq->AddAndPopChildL(publicExp);
       
   196 
       
   197 	// The private exponent
       
   198 	RInteger d = CalculateRSAPrivExpL(aPrivateKey, aPublicKey);
       
   199 	CleanupStack::PushL(d);
       
   200 
       
   201 	CASN1EncBigInt* privateExp = CASN1EncBigInt::NewLC(d);
       
   202 
       
   203 	keySeq->AddAndPopChildL(privateExp);
       
   204 	CleanupStack::PopAndDestroy(&d);  // RSA Private Exponent 
       
   205 
       
   206 	//	The prime1
       
   207 	const TInteger& p = aPrivateKey.P();
       
   208 	CASN1EncBigInt* prime1 = CASN1EncBigInt::NewLC(p);
       
   209 	keySeq->AddAndPopChildL(prime1);
       
   210 
       
   211 	//	The prime2
       
   212 	const TInteger& q = aPrivateKey.Q();
       
   213 	CASN1EncBigInt* prime2 = CASN1EncBigInt::NewLC(q);
       
   214 	keySeq->AddAndPopChildL(prime2);
       
   215 
       
   216 	//	The exponent 1	
       
   217 	const TInteger& dp = aPrivateKey.DP();
       
   218 	CASN1EncBigInt* theExp1 = CASN1EncBigInt::NewLC(dp);
       
   219 	keySeq->AddAndPopChildL(theExp1);
       
   220 
       
   221 	//	The exponent 2
       
   222 	const TInteger& dq = aPrivateKey.DQ();
       
   223 	CASN1EncBigInt* theExp2 = CASN1EncBigInt::NewLC(dq);
       
   224 	keySeq->AddAndPopChildL(theExp2);
       
   225 
       
   226 	//	The coefficient
       
   227 	const TInteger& coeff = aPrivateKey.QInv();
       
   228 	CASN1EncBigInt* coefficient = CASN1EncBigInt::NewLC(coeff);
       
   229 	keySeq->AddAndPopChildL(coefficient);
       
   230 	
       
   231 	CASN1EncOctetString* octet = ElementToOctetL(*keySeq);
       
   232 	CleanupStack::PushL(octet);
       
   233 	
       
   234 	//	Now add the octet of the key sequence to the sequence
       
   235 	seq->AddAndPopChildL(octet);
       
   236 	
       
   237   	CleanupStack::PopAndDestroy(keySeq);
       
   238 
       
   239 	AddAttributesL(*seq, aAttributes);
       
   240 
       
   241   	CleanupStack::Pop(seq);
       
   242 					
       
   243 	return seq;
       
   244 	}
       
   245 
       
   246 /**
       
   247  * Encodes an RSA key in encrypted format.
       
   248  * 
       
   249  * @param aPrivateKey The private key to be encoded (must be in CRT format)
       
   250  * @param aPublicKey The corresponding public key.
       
   251  * @param aEncryptor The object used to encrypt the data.
       
   252  * @param aData The encryption parameters of the given encryptor.
       
   253  *              These parameters are stored in the resulting sequence.
       
   254  *
       
   255  * @return An ASN1 Sequence encoding the encrypted key.
       
   256  */
       
   257 /*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeEncryptedL(const CRSAPrivateKeyCRT& aPrivateKey, const CRSAPublicKey& aPublicKey, 
       
   258                                                                       CPBEncryptor& aEncryptor, CPBEncryptParms& aData, const TDesC8& aAttributes)
       
   259 	{
       
   260 	// Now generate a PrivateKeyInfo type 
       
   261 	CASN1EncSequence* privKeySeq = EncodeL(aPrivateKey, aPublicKey, aAttributes);
       
   262 	CleanupStack::PushL(privKeySeq);
       
   263 	
       
   264 	CASN1EncSequence* seq = EncryptedSequenceL(*privKeySeq, aEncryptor, aData);
       
   265 	
       
   266 	CleanupStack::PopAndDestroy(privKeySeq);
       
   267 		
       
   268 	return seq;
       
   269 	}
       
   270 
       
   271 
       
   272 /**
       
   273  * Return the ASN1 PKCS#8 encoding of a DSA private key.
       
   274  *
       
   275  * The private key syntax for this key type is defined in 
       
   276  * the PKCS#11 document. 
       
   277  *
       
   278  * @param aPrivateKey The private key to be encoded (must be in CRT format)
       
   279  *
       
   280  * @return An ASN1 Sequence encoding the key.
       
   281  */	
       
   282 /*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeL(const CDSAPrivateKey& aPrivateKey, 
       
   283 													          const TDesC8& aAttributes)
       
   284 	{
       
   285 	// Main ASN1 sequence
       
   286 	CASN1EncSequence* seq = CASN1EncSequence::NewLC();
       
   287 
       
   288 	//	version
       
   289 	CASN1EncInt* version = CASN1EncInt::NewLC(KPkcs8Version);
       
   290 	seq->AddAndPopChildL(version);
       
   291 	
       
   292 	//	Algorithm sequence
       
   293 	CASN1EncSequence* algSeq = CASN1EncSequence::NewLC();
       
   294 
       
   295 	CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KDSA);
       
   296 	algSeq->AddAndPopChildL(oid);
       
   297 
       
   298 	seq->AddAndPopChildL(algSeq);
       
   299 
       
   300 	// DSA Parameters	
       
   301 	CASN1EncSequence* keySeq = CASN1EncSequence::NewLC();
       
   302 
       
   303 	//	The modulus	P
       
   304 	const TInteger& modulus1 = aPrivateKey.P();
       
   305 
       
   306 	CASN1EncBigInt* mod = CASN1EncBigInt::NewLC(modulus1);
       
   307 	keySeq->AddAndPopChildL(mod);
       
   308 
       
   309 	//	The modulus	Q
       
   310 	const TInteger& modulus2 = aPrivateKey.Q();
       
   311 	
       
   312 	CASN1EncBigInt* mod2 = CASN1EncBigInt::NewLC(modulus2);
       
   313 	keySeq->AddAndPopChildL(mod2);
       
   314 	
       
   315 	//	The base G 
       
   316 	const TInteger& base = aPrivateKey.G();
       
   317 
       
   318 	CASN1EncBigInt* b = CASN1EncBigInt::NewLC(base);
       
   319 	keySeq->AddAndPopChildL(b);
       
   320 	
       
   321 	algSeq->AddAndPopChildL(keySeq);
       
   322 	
       
   323 	//	The private key X
       
   324 	const TInteger& priv = aPrivateKey.X();	
       
   325 	CASN1EncBigInt* x = CASN1EncBigInt::NewLC(priv);
       
   326 
       
   327 	CASN1EncOctetString* octet = ElementToOctetL(*x);
       
   328 
       
   329 	CleanupStack::PopAndDestroy(x);
       
   330 	CleanupStack::PushL(octet);
       
   331 
       
   332 	seq->AddAndPopChildL(octet);
       
   333 
       
   334 	AddAttributesL(*seq, aAttributes);
       
   335 	
       
   336 	CleanupStack::Pop(seq);
       
   337 
       
   338 	return seq;	
       
   339 	}
       
   340 
       
   341 
       
   342 /**
       
   343  * Encodes a DSA key in encrypted format.
       
   344  * 
       
   345  * @param aPrivateKey The private key to be encoded.
       
   346  * @param aEncryptor The object used to encrypt the data.
       
   347  * @param aData The encryption parameters of the given encryptor.
       
   348  *              These parameters are stored in the resulting sequence.
       
   349  *
       
   350  * @return An ASN1 Sequence encoding the encrypted key.
       
   351  */
       
   352 /*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeEncryptedL(const CDSAPrivateKey& aPrivateKey, CPBEncryptor& aEncryptor, 
       
   353                                                                       CPBEncryptParms& aData, const TDesC8& aAttributes)
       
   354 	{
       
   355 	// Now generate a PrivateKeyInfo type 
       
   356 	CASN1EncSequence* privKeySeq = EncodeL(aPrivateKey, aAttributes);
       
   357 	CleanupStack::PushL(privKeySeq);
       
   358 	
       
   359 	CASN1EncSequence* seq = EncryptedSequenceL(*privKeySeq, aEncryptor, aData);
       
   360 	
       
   361 	CleanupStack::PopAndDestroy(privKeySeq);
       
   362 		
       
   363 	return seq;
       
   364 	}