|
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 } |