|
1 /* |
|
2 * Copyright (c) 2005-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 "pkcs12bags.h" |
|
20 |
|
21 using namespace PKCS12; |
|
22 ///////////////////////// KeyBag //////////////////////////////// |
|
23 |
|
24 CDecPkcs12KeyBag::CDecPkcs12KeyBag() |
|
25 { |
|
26 } |
|
27 |
|
28 EXPORT_C CDecPkcs12KeyBag* CDecPkcs12KeyBag::NewL(const TDesC8& aSafeBagData) |
|
29 { |
|
30 CDecPkcs12KeyBag* self = new(ELeave) CDecPkcs12KeyBag; |
|
31 CleanupStack::PushL(self); |
|
32 self->ConstructL(aSafeBagData); |
|
33 CleanupStack::Pop(self); |
|
34 return self; |
|
35 } |
|
36 |
|
37 CDecPkcs12KeyBag::~CDecPkcs12KeyBag() |
|
38 { |
|
39 } |
|
40 |
|
41 void CDecPkcs12KeyBag::ConstructL(const TDesC8& aSafeBagData) |
|
42 { |
|
43 CDecPkcs12SafeBag::ConstructL(aSafeBagData); |
|
44 } |
|
45 |
|
46 EXPORT_C CDecPKCS8Data* CDecPkcs12KeyBag::PrivateKeyInfoL() const |
|
47 { |
|
48 TASN1DecGeneric seqGen(iBagValue); |
|
49 seqGen.InitL(); |
|
50 if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal) |
|
51 { |
|
52 User::Leave(KErrArgument); |
|
53 } |
|
54 |
|
55 return TASN1DecPKCS8::DecodeDERL(seqGen.Encoding()); |
|
56 } |
|
57 |
|
58 ////////////////////////// ShroudedKeyBag //////////////////////// |
|
59 CDecPkcs12ShroudedKeyBag::CDecPkcs12ShroudedKeyBag() |
|
60 { |
|
61 } |
|
62 |
|
63 EXPORT_C CDecPkcs12ShroudedKeyBag* CDecPkcs12ShroudedKeyBag::NewL(const TDesC8& aSafeBagData) |
|
64 { |
|
65 CDecPkcs12ShroudedKeyBag* self = new(ELeave) CDecPkcs12ShroudedKeyBag; |
|
66 CleanupStack::PushL(self); |
|
67 self->ConstructL(aSafeBagData); |
|
68 CleanupStack::Pop(self); |
|
69 return self; |
|
70 } |
|
71 |
|
72 CDecPkcs12ShroudedKeyBag::~CDecPkcs12ShroudedKeyBag() |
|
73 { |
|
74 } |
|
75 |
|
76 void CDecPkcs12ShroudedKeyBag::ConstructL(const TDesC8& aSafeBagData) |
|
77 { |
|
78 CDecPkcs12SafeBag::ConstructL(aSafeBagData); |
|
79 TASN1DecGeneric seqGen(iBagValue); |
|
80 seqGen.InitL(); |
|
81 if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal) |
|
82 { |
|
83 User::Leave(KErrArgument); |
|
84 } |
|
85 |
|
86 TASN1DecSequence dec; |
|
87 CArrayPtrFlat<TASN1DecGeneric>* shroudedKeyBagSeq = dec.DecodeDERLC(seqGen); |
|
88 TInt seqIndex = 0; |
|
89 TInt shroudedKeyBagSeqCount = shroudedKeyBagSeq->Count(); |
|
90 if (seqIndex >= shroudedKeyBagSeqCount) |
|
91 { |
|
92 User::Leave(KErrArgument); |
|
93 } |
|
94 CleanupStack::PopAndDestroy(shroudedKeyBagSeq); |
|
95 } |
|
96 |
|
97 EXPORT_C CDecPKCS8Data* CDecPkcs12ShroudedKeyBag::PrivateKeyInfoL(TDesC& aPassword) const |
|
98 { |
|
99 TASN1DecGeneric seqGen(iBagValue); |
|
100 seqGen.InitL(); |
|
101 TASN1DecSequence dec; |
|
102 CArrayPtrFlat<TASN1DecGeneric>* shroudedKeyBagSeq = dec.DecodeDERLC(seqGen); |
|
103 // Get the first part of the sequence -> PKCS5 data |
|
104 const TASN1DecGeneric* shroudedKeyBagSeqAt0 = shroudedKeyBagSeq->At(0); |
|
105 TPtrC8 theContent(shroudedKeyBagSeqAt0->Encoding());// expect this to be a sequence |
|
106 CPBEncryptParms* encryptParams = TASN1DecPKCS5::DecodeDERL(theContent); |
|
107 CleanupStack::PushL(encryptParams); |
|
108 |
|
109 CPBEncryptElement* encryptElement; |
|
110 HBufC8* pkcs12Pwd = PKCS12KDF::GeneratePasswordLC(aPassword); |
|
111 if(encryptParams->Kdf() == CPBEncryptParms::EKdfPkcs12) |
|
112 { |
|
113 TPtrC8 iv = encryptParams->IV(); |
|
114 HBufC8* ivValue = HBufC8::NewMaxLC(iv.Length()); |
|
115 TPtr8 encryptKeyBuf = ivValue->Des(); |
|
116 |
|
117 switch(encryptParams->Cipher()) |
|
118 { |
|
119 case ECipherARC4_128: |
|
120 case ECipherARC4_40: |
|
121 { |
|
122 //derive only key it is unnecessary to derive an IV for RC4 |
|
123 break; |
|
124 } |
|
125 case ECipher3DES_CBC: |
|
126 case ECipher2Key3DES_CBC: |
|
127 case ECipherRC2_CBC_128_16: |
|
128 case ECipherRC2_CBC_40_5: |
|
129 { |
|
130 PKCS12KDF::DeriveKeyL(encryptKeyBuf, PKCS12KDF::EIDByteIV, *pkcs12Pwd, encryptParams->Salt(), encryptParams->Iterations()); |
|
131 encryptParams->SetIV(encryptKeyBuf); |
|
132 break; |
|
133 } |
|
134 default: |
|
135 { |
|
136 User::Leave(KErrNotSupported); |
|
137 break; |
|
138 } |
|
139 } |
|
140 CleanupStack::PopAndDestroy(ivValue); |
|
141 // Create the decryptor |
|
142 encryptElement = CPBEncryptElement::NewLC(*pkcs12Pwd, *encryptParams); |
|
143 } |
|
144 else |
|
145 { |
|
146 TPBPassword password(aPassword); |
|
147 // Create the decryptor |
|
148 encryptElement = CPBEncryptElement::NewLC(password.Password(), *encryptParams); |
|
149 } |
|
150 CPBDecryptor* decryptor = encryptElement->NewDecryptLC(); |
|
151 // Decrypt the final part of the sequence -> encrypted PKCS8 object |
|
152 const TASN1DecGeneric* shroudedKeyBagSeqAt1 = shroudedKeyBagSeq->At(1); |
|
153 if (shroudedKeyBagSeqAt1->Tag() != EASN1OctetString || shroudedKeyBagSeqAt1->Class() != EUniversal) |
|
154 { |
|
155 User::Leave(KErrArgument); |
|
156 } |
|
157 TPtrC8 encryptedKey(shroudedKeyBagSeqAt1->GetContentDER()); |
|
158 TUint encryptLength = encryptedKey.Length(); |
|
159 TUint maxDecryptLength = decryptor->MaxOutputLength(encryptLength); |
|
160 if ( maxDecryptLength <= 0 ) |
|
161 { |
|
162 User::Leave(KErrGeneral); |
|
163 } |
|
164 HBufC8* decryptedContent = HBufC8::NewLC(encryptLength); |
|
165 TPtr8 dcDes(decryptedContent->Des()); |
|
166 decryptor->Process(encryptedKey, dcDes); |
|
167 |
|
168 CDecPKCS8Data* privateKeyInfo = TASN1DecPKCS8::DecodeDERL(dcDes); |
|
169 |
|
170 CleanupStack::PopAndDestroy(6,shroudedKeyBagSeq);//shroudedKeyBagSeq, encryptParams,pkcs12Pwd |
|
171 // encryptElement, decryptor, decryptedContent. |
|
172 return privateKeyInfo; |
|
173 } |
|
174 |
|
175 ///////////////////////////// CertBag /////////////////////////////// |
|
176 |
|
177 CDecPkcs12CertBag::CDecPkcs12CertBag() |
|
178 { |
|
179 } |
|
180 |
|
181 EXPORT_C CDecPkcs12CertBag* CDecPkcs12CertBag::NewL(const TDesC8& aSafeBagData) |
|
182 { |
|
183 CDecPkcs12CertBag* self = new (ELeave) CDecPkcs12CertBag; |
|
184 CleanupStack::PushL(self); |
|
185 self->ConstructL(aSafeBagData); |
|
186 CleanupStack::Pop(self); |
|
187 return self; |
|
188 } |
|
189 |
|
190 CDecPkcs12CertBag::~CDecPkcs12CertBag() |
|
191 { |
|
192 delete iCertId; |
|
193 } |
|
194 |
|
195 void CDecPkcs12CertBag::ConstructL(const TDesC8& aSafeBagData) |
|
196 { |
|
197 CDecPkcs12SafeBag::ConstructL(aSafeBagData); |
|
198 |
|
199 TASN1DecGeneric seqGen(iBagValue); |
|
200 seqGen.InitL(); |
|
201 if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal) |
|
202 { |
|
203 User::Leave(KErrArgument); |
|
204 } |
|
205 |
|
206 TASN1DecSequence seq; |
|
207 CArrayPtr<TASN1DecGeneric>* certBagSequence = seq.DecodeDERLC(seqGen); |
|
208 const TASN1DecGeneric* certBagSequenceAt0 = certBagSequence->At(0); |
|
209 if (certBagSequenceAt0->Tag() != EASN1ObjectIdentifier || certBagSequenceAt0->Class() != EUniversal) |
|
210 { |
|
211 User::Leave(KErrArgument); |
|
212 } |
|
213 |
|
214 // Obtain the CertId |
|
215 TASN1DecObjectIdentifier oid; |
|
216 iCertId = oid.DecodeDERL(*certBagSequenceAt0); |
|
217 |
|
218 const TASN1DecGeneric* certBagSequenceAt1 = certBagSequence->At(1); |
|
219 if (certBagSequenceAt1->Tag() != EASN1EOC || certBagSequenceAt1->Class() != EContextSpecific) |
|
220 { |
|
221 User::Leave(KErrArgument); |
|
222 } |
|
223 |
|
224 TASN1DecGeneric certBagSeq(certBagSequenceAt1->GetContentDER()); |
|
225 certBagSeq.InitL(); |
|
226 if (certBagSeq.Tag() != EASN1OctetString || certBagSeq.Class() != EUniversal) |
|
227 { |
|
228 User::Leave(KErrArgument); |
|
229 } |
|
230 else |
|
231 { |
|
232 iCertValue.Set(certBagSeq.GetContentDER()); |
|
233 } |
|
234 CleanupStack::PopAndDestroy(certBagSequence); |
|
235 } |
|
236 |
|
237 EXPORT_C const TDesC& CDecPkcs12CertBag::CertId() const |
|
238 { |
|
239 return *iCertId; |
|
240 } |
|
241 |
|
242 EXPORT_C const TDesC8& CDecPkcs12CertBag::CertValue() const |
|
243 { |
|
244 return iCertValue; |
|
245 } |
|
246 |
|
247 EXPORT_C CX509Certificate* CDecPkcs12CertBag::X509CertificateL() const |
|
248 { |
|
249 return (*iCertId == KX509CertificateOID) ? CX509Certificate::NewL(iCertValue) : NULL; |
|
250 } |
|
251 |
|
252 /////////////////////// SafeContentsBag /////////////////////// |
|
253 |
|
254 CDecPkcs12SafeContentsBag::CDecPkcs12SafeContentsBag() |
|
255 { |
|
256 } |
|
257 |
|
258 EXPORT_C CDecPkcs12SafeContentsBag* CDecPkcs12SafeContentsBag::NewL(const TDesC8& aSafeContentsBagData) |
|
259 { |
|
260 CDecPkcs12SafeContentsBag* self = new(ELeave) CDecPkcs12SafeContentsBag; |
|
261 CleanupStack::PushL(self); |
|
262 self->ConstructL(aSafeContentsBagData); |
|
263 CleanupStack::Pop(self); |
|
264 return self; |
|
265 } |
|
266 |
|
267 CDecPkcs12SafeContentsBag::~CDecPkcs12SafeContentsBag() |
|
268 { |
|
269 iSafeBags.ResetAndDestroy(); |
|
270 iSafeBags.Close(); |
|
271 } |
|
272 |
|
273 void CDecPkcs12SafeContentsBag::ConstructL(const TDesC8& aSafeBagData) |
|
274 { |
|
275 CDecPkcs12SafeBag::ConstructL(aSafeBagData); |
|
276 // This is SafeBag Sequence containing a SafeContents Bag |
|
277 TASN1DecGeneric seqGen(iBagValue); |
|
278 seqGen.InitL(); |
|
279 |
|
280 // Check if this is a Sequence |
|
281 if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal) |
|
282 { |
|
283 User::Leave(KErrArgument); |
|
284 } |
|
285 |
|
286 TASN1DecSequence seq; |
|
287 CArrayPtrFlat<TASN1DecGeneric>* safeContentsBagSeq = seq.DecodeDERLC(seqGen); |
|
288 |
|
289 // Find out the number of SafeBags present in the SafeContents Bag |
|
290 TInt safeContentsBagCount = safeContentsBagSeq->Count(); |
|
291 const TASN1DecGeneric* safeContentsBagSeqAtPos; |
|
292 for (TInt index = 0; index < safeContentsBagCount; index++) |
|
293 { |
|
294 safeContentsBagSeqAtPos = safeContentsBagSeq->At(index); |
|
295 if (safeContentsBagSeqAtPos->Tag() != EASN1Sequence || safeContentsBagSeqAtPos->Class() != EUniversal) |
|
296 { |
|
297 User::Leave(KErrArgument); |
|
298 } |
|
299 |
|
300 const TDesC8& safeBag(safeContentsBagSeqAtPos->Encoding()); |
|
301 // Decode this sequence, This is a SafeBag. |
|
302 CDecPkcs12SafeBag* safeBagObject = CDecPkcs12SafeBag::NewL(safeBag); |
|
303 CleanupStack::PushL(safeBagObject); |
|
304 iSafeBags.AppendL(safeBagObject); |
|
305 CleanupStack::Pop(safeBagObject); |
|
306 } |
|
307 CleanupStack::PopAndDestroy(safeContentsBagSeq); |
|
308 } |
|
309 |
|
310 EXPORT_C const RPointerArray<CDecPkcs12SafeBag>& CDecPkcs12SafeContentsBag::SafeBags() const |
|
311 { |
|
312 return iSafeBags; |
|
313 } |
|
314 |
|
315 ///////////////////////////// Safe Contents /////////////////////////////// |
|
316 CDecPkcs12SafeContents::CDecPkcs12SafeContents() |
|
317 { |
|
318 } |
|
319 |
|
320 CDecPkcs12SafeContents::~CDecPkcs12SafeContents() |
|
321 { |
|
322 delete iDecryptedData; |
|
323 iSafeBags.ResetAndDestroy(); |
|
324 iSafeBags.Close(); |
|
325 } |
|
326 |
|
327 EXPORT_C CDecPkcs12SafeContents* CDecPkcs12SafeContents::NewL(const CPKCS7ContentInfo& aSafeContentsBagData) |
|
328 { |
|
329 CDecPkcs12SafeContents* self = new(ELeave) CDecPkcs12SafeContents; |
|
330 CleanupStack::PushL(self); |
|
331 self->ConstructL(aSafeContentsBagData.ContentData()); |
|
332 CleanupStack::Pop(self); |
|
333 return self; |
|
334 } |
|
335 |
|
336 EXPORT_C CDecPkcs12SafeContents* CDecPkcs12SafeContents::NewL(const CPKCS7ContentInfo& aSafeContentsBagData, const TDesC& aPassword) |
|
337 { |
|
338 CDecPkcs12SafeContents* self = new(ELeave) CDecPkcs12SafeContents; |
|
339 CleanupStack::PushL(self); |
|
340 self->DecodeEncryptedDataL(aSafeContentsBagData,aPassword); |
|
341 CleanupStack::Pop(self); |
|
342 return self; |
|
343 } |
|
344 |
|
345 EXPORT_C CDecPkcs12SafeContents* CDecPkcs12SafeContents::NewL(const TDesC8& aSafeContent) |
|
346 { |
|
347 CDecPkcs12SafeContents* self = new(ELeave) CDecPkcs12SafeContents; |
|
348 CleanupStack::PushL(self); |
|
349 self->ConstructL(aSafeContent); |
|
350 CleanupStack::Pop(self); |
|
351 return self; |
|
352 } |
|
353 |
|
354 void CDecPkcs12SafeContents::ConstructL(const TDesC8& aSafeContent) |
|
355 { |
|
356 TASN1DecGeneric decGen(aSafeContent); |
|
357 decGen.InitL(); |
|
358 |
|
359 if(decGen.Tag() != EASN1Sequence || decGen.Class() != EUniversal) |
|
360 { |
|
361 User::Leave(KErrArgument); |
|
362 } |
|
363 |
|
364 TASN1DecGeneric decGen2(decGen.GetContentDER()); |
|
365 decGen2.InitL(); |
|
366 |
|
367 if(decGen2.Tag() != EASN1Sequence || decGen.Class() != EUniversal) |
|
368 { |
|
369 User ::Leave(KErrArgument); |
|
370 } |
|
371 |
|
372 // Decode sequence |
|
373 TASN1DecSequence seq; |
|
374 CArrayPtr<TASN1DecGeneric>* safeBagSequences = seq.DecodeDERLC(decGen); |
|
375 |
|
376 // A Sequence of SafeBags are present within the SafeContents Bag Sequence |
|
377 TInt safeBagCount = safeBagSequences->Count(); |
|
378 |
|
379 for(TInt index = 0; index < safeBagCount; index++) |
|
380 { |
|
381 CDecPkcs12SafeBag* safeBag = CDecPkcs12SafeBag::NewL(safeBagSequences->At(index)->Encoding()); |
|
382 CleanupStack::PushL(safeBag); |
|
383 iSafeBags.AppendL(safeBag); |
|
384 CleanupStack::Pop(safeBag); |
|
385 } |
|
386 CleanupStack::PopAndDestroy(safeBagSequences); // safeBagSequences |
|
387 } |
|
388 |
|
389 void CDecPkcs12SafeContents::DecodeEncryptedDataL(const CPKCS7ContentInfo& aContentInfo, const TDesC& aPassword) |
|
390 { |
|
391 CPKCS7EncryptedDataObject* pkcs7EncryptedData = CPKCS7EncryptedDataObject::NewL(aContentInfo); |
|
392 CleanupStack::PushL(pkcs7EncryptedData); |
|
393 iDecryptedData = pkcs7EncryptedData->DecryptDataL(aPassword); |
|
394 ConstructL(iDecryptedData->Des()); |
|
395 CleanupStack::PopAndDestroy(pkcs7EncryptedData); |
|
396 } |
|
397 |
|
398 EXPORT_C const RPointerArray<CDecPkcs12SafeBag>& CDecPkcs12SafeContents::SafeContentsBags() const |
|
399 { |
|
400 return iSafeBags; |
|
401 } |
|
402 |
|
403 EXPORT_C const TDesC8* CDecPkcs12SafeContents::DecryptedData() const |
|
404 { |
|
405 return iDecryptedData; |
|
406 } |