os/security/cryptoservices/asnpkcs/source/asnpkcs8enc.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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 	}
   365