Update contrib.
2 * Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
21 #include <asymmetrickeys.h>
25 const TInt KPkcs8Version = 0; // PKCS#8 version 0
26 const TInt KPkcs8RSATwoPrime = 0; // We support only two-prime RSA.
29 /*static*/ void TASN1EncPKCS8::AddAttributesL(CASN1EncSequence& aSeq, const TDesC8& aAttribute)
31 if (aAttribute != KNullDesC8)
33 CASN1EncEncoding* encoded = CASN1EncEncoding::NewLC(aAttribute);
34 aSeq.AddAndPopChildL(encoded);
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.
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.
47 /*static*/ CASN1EncOctetString* TASN1EncPKCS8::EncryptKeySequenceL(CASN1EncSequence& aKeySeq, CPBEncryptor& aEncryptor)
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());
55 aKeySeq.WriteDERL(oct, writePos);
58 HBufC8* encryptedData = HBufC8::NewLC(aEncryptor.MaxFinalOutputLength(seqLen));
59 TPtr8 encrypted(encryptedData->Des());
61 aEncryptor.ProcessFinalL(*octetData, encrypted);
63 CASN1EncOctetString* octet = CASN1EncOctetString::NewL(encrypted);
65 CleanupStack::PopAndDestroy(2, octetData); // encryptedData, octetData
71 /*static*/ CASN1EncOctetString* TASN1EncPKCS8::ElementToOctetL(CASN1EncBase& aAsnElement)
73 // Make an octet string from the structure
74 HBufC8* octetData = HBufC8::NewMaxLC(aAsnElement.LengthDER());
75 TPtr8 oct(octetData->Des());
79 aAsnElement.WriteDERL(oct, writePos);
81 CASN1EncOctetString* octet = CASN1EncOctetString::NewL(oct);
82 CleanupStack::PopAndDestroy(octetData);
87 /*static*/ CASN1EncSequence* TASN1EncPKCS8::EncryptedSequenceL(CASN1EncSequence& aPrivateKeySequence,
88 CPBEncryptor& aEncryptor, CPBEncryptParms& aData)
91 CASN1EncSequence* seq = CASN1EncSequence::NewLC();
93 // PKCS#5 PBE sequence
94 CASN1EncSequence* pkcs5Seq = TASN1EncPKCS5::EncodeDERL(aData);
96 CleanupStack::PushL(pkcs5Seq);
97 seq->AddAndPopChildL(pkcs5Seq);
99 // Encrypt the Private Key Sequence
100 CASN1EncOctetString* octet = EncryptKeySequenceL(aPrivateKeySequence, aEncryptor);
101 CleanupStack::PushL(octet);
102 seq->AddAndPopChildL(octet);
104 CleanupStack::Pop(seq);
110 /*static*/ const RInteger TASN1EncPKCS8::CalculateRSAPrivExpL(const CRSAPrivateKeyCRT& aPrivateKey, const CRSAPublicKey& aPublicKey)
112 const TInteger& e = aPublicKey.E();
114 RInteger pTemp = RInteger::NewL(aPrivateKey.P());
115 CleanupStack::PushL(pTemp);
116 RInteger qTemp = RInteger::NewL(aPrivateKey.Q());
117 CleanupStack::PushL(qTemp);
123 RInteger phi = pTemp.TimesL(qTemp);
125 CleanupStack::PopAndDestroy(2, &pTemp); // qTemp, pTemp
126 CleanupStack::PushL(phi);
128 //d = e^(-1) mod ((p-1)(q-1))
129 RInteger d = e.InverseModL(phi);
130 CleanupStack::PopAndDestroy(&phi);
135 * Encodes the given private key using the pkcs#8 standard.
137 * The returned ASN1 sequence respects the following grammar:
139 * PrivateKeyInfo ::= SEQUENCE {
141 * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
142 * privateKey PrivateKey,
143 * attributes [0] IMPLICIT Attributes OPTIONAL }
145 * Version ::= INTEGER
146 * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
147 * PrivateKey ::= OCTET STRING
148 * Attributes ::= SET OF Attribute
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.
157 /*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeL(const CRSAPrivateKeyCRT& aPrivateKey,
158 const CRSAPublicKey& aPublicKey,
159 const TDesC8& aAttributes)
161 // Main ASN1 sequence
162 CASN1EncSequence* seq = CASN1EncSequence::NewLC();
164 // Start with PKCS#8 header
165 CASN1EncInt* version = CASN1EncInt::NewLC(KPkcs8Version);
166 seq->AddAndPopChildL(version);
168 // Algorithm sequence
169 CASN1EncSequence* algSeq = CASN1EncSequence::NewLC();
171 CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KRSA);
172 algSeq->AddAndPopChildL(oid);
174 // No other parameters
175 CASN1EncNull* nullparams = CASN1EncNull::NewLC();
176 algSeq->AddAndPopChildL(nullparams);
178 seq->AddAndPopChildL(algSeq);
180 // The actual private key sequence
181 CASN1EncSequence* keySeq = CASN1EncSequence::NewLC();
183 // TASN1DecGeneric* versionData = theData->operator[](seqIndex);
184 CASN1EncInt* rsaVersion = CASN1EncInt::NewLC(KPkcs8RSATwoPrime);
185 keySeq->AddAndPopChildL(rsaVersion);
188 const TInteger& modulus = aPrivateKey.N();
189 CASN1EncBigInt* mod = CASN1EncBigInt::NewLC(modulus);
190 keySeq->AddAndPopChildL(mod);
192 // The public exponent
193 const TInteger& e = aPublicKey.E();
194 CASN1EncBigInt* publicExp = CASN1EncBigInt::NewLC(e);
195 keySeq->AddAndPopChildL(publicExp);
197 // The private exponent
198 RInteger d = CalculateRSAPrivExpL(aPrivateKey, aPublicKey);
199 CleanupStack::PushL(d);
201 CASN1EncBigInt* privateExp = CASN1EncBigInt::NewLC(d);
203 keySeq->AddAndPopChildL(privateExp);
204 CleanupStack::PopAndDestroy(&d); // RSA Private Exponent
207 const TInteger& p = aPrivateKey.P();
208 CASN1EncBigInt* prime1 = CASN1EncBigInt::NewLC(p);
209 keySeq->AddAndPopChildL(prime1);
212 const TInteger& q = aPrivateKey.Q();
213 CASN1EncBigInt* prime2 = CASN1EncBigInt::NewLC(q);
214 keySeq->AddAndPopChildL(prime2);
217 const TInteger& dp = aPrivateKey.DP();
218 CASN1EncBigInt* theExp1 = CASN1EncBigInt::NewLC(dp);
219 keySeq->AddAndPopChildL(theExp1);
222 const TInteger& dq = aPrivateKey.DQ();
223 CASN1EncBigInt* theExp2 = CASN1EncBigInt::NewLC(dq);
224 keySeq->AddAndPopChildL(theExp2);
227 const TInteger& coeff = aPrivateKey.QInv();
228 CASN1EncBigInt* coefficient = CASN1EncBigInt::NewLC(coeff);
229 keySeq->AddAndPopChildL(coefficient);
231 CASN1EncOctetString* octet = ElementToOctetL(*keySeq);
232 CleanupStack::PushL(octet);
234 // Now add the octet of the key sequence to the sequence
235 seq->AddAndPopChildL(octet);
237 CleanupStack::PopAndDestroy(keySeq);
239 AddAttributesL(*seq, aAttributes);
241 CleanupStack::Pop(seq);
247 * Encodes an RSA key in encrypted format.
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.
255 * @return An ASN1 Sequence encoding the encrypted key.
257 /*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeEncryptedL(const CRSAPrivateKeyCRT& aPrivateKey, const CRSAPublicKey& aPublicKey,
258 CPBEncryptor& aEncryptor, CPBEncryptParms& aData, const TDesC8& aAttributes)
260 // Now generate a PrivateKeyInfo type
261 CASN1EncSequence* privKeySeq = EncodeL(aPrivateKey, aPublicKey, aAttributes);
262 CleanupStack::PushL(privKeySeq);
264 CASN1EncSequence* seq = EncryptedSequenceL(*privKeySeq, aEncryptor, aData);
266 CleanupStack::PopAndDestroy(privKeySeq);
273 * Return the ASN1 PKCS#8 encoding of a DSA private key.
275 * The private key syntax for this key type is defined in
276 * the PKCS#11 document.
278 * @param aPrivateKey The private key to be encoded (must be in CRT format)
280 * @return An ASN1 Sequence encoding the key.
282 /*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeL(const CDSAPrivateKey& aPrivateKey,
283 const TDesC8& aAttributes)
285 // Main ASN1 sequence
286 CASN1EncSequence* seq = CASN1EncSequence::NewLC();
289 CASN1EncInt* version = CASN1EncInt::NewLC(KPkcs8Version);
290 seq->AddAndPopChildL(version);
292 // Algorithm sequence
293 CASN1EncSequence* algSeq = CASN1EncSequence::NewLC();
295 CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KDSA);
296 algSeq->AddAndPopChildL(oid);
298 seq->AddAndPopChildL(algSeq);
301 CASN1EncSequence* keySeq = CASN1EncSequence::NewLC();
304 const TInteger& modulus1 = aPrivateKey.P();
306 CASN1EncBigInt* mod = CASN1EncBigInt::NewLC(modulus1);
307 keySeq->AddAndPopChildL(mod);
310 const TInteger& modulus2 = aPrivateKey.Q();
312 CASN1EncBigInt* mod2 = CASN1EncBigInt::NewLC(modulus2);
313 keySeq->AddAndPopChildL(mod2);
316 const TInteger& base = aPrivateKey.G();
318 CASN1EncBigInt* b = CASN1EncBigInt::NewLC(base);
319 keySeq->AddAndPopChildL(b);
321 algSeq->AddAndPopChildL(keySeq);
324 const TInteger& priv = aPrivateKey.X();
325 CASN1EncBigInt* x = CASN1EncBigInt::NewLC(priv);
327 CASN1EncOctetString* octet = ElementToOctetL(*x);
329 CleanupStack::PopAndDestroy(x);
330 CleanupStack::PushL(octet);
332 seq->AddAndPopChildL(octet);
334 AddAttributesL(*seq, aAttributes);
336 CleanupStack::Pop(seq);
343 * Encodes a DSA key in encrypted format.
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.
350 * @return An ASN1 Sequence encoding the encrypted key.
352 /*static*/ EXPORT_C CASN1EncSequence* TASN1EncPKCS8::EncodeEncryptedL(const CDSAPrivateKey& aPrivateKey, CPBEncryptor& aEncryptor,
353 CPBEncryptParms& aData, const TDesC8& aAttributes)
355 // Now generate a PrivateKeyInfo type
356 CASN1EncSequence* privKeySeq = EncodeL(aPrivateKey, aAttributes);
357 CleanupStack::PushL(privKeySeq);
359 CASN1EncSequence* seq = EncryptedSequenceL(*privKeySeq, aEncryptor, aData);
361 CleanupStack::PopAndDestroy(privKeySeq);