First public contribution.
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.
26 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
28 /** OpenSSL PKCS8 Effective Key Length Compatibility.*/
29 const TUint KPkcs8CompatibilityBits = 128;
34 _LIT(Kpkcs5PBES2, "1.2.840.113549.1.5.13");
35 _LIT(Kpkcs5PBKDF2, "1.2.840.113549.1.5.12");
36 _LIT(KDESCBC, "1.3.14.3.2.7");
37 _LIT(K3DESCBC, "1.2.840.113549.3.7");
38 _LIT(KRC2CBC, "1.2.840.113549.3.2");
41 _LIT(KPbeWithSHA1And128BitRC4, "1.2.840.113549.1.12.1.1");
42 _LIT(KPbeWithSHA1And40BitRC4, "1.2.840.113549.1.12.1.2");
43 _LIT(KPbeWithSHA1And3_KeyTripleDES_CBC, "1.2.840.113549.1.12.1.3");
44 _LIT(KPbeWithSHA1And2_KeyTripleDES_CBC, "1.2.840.113549.1.12.1.4");
45 _LIT(KPbeWithSHA1And128BitRC2_CBC, "1.2.840.113549.1.12.1.5");
46 _LIT(KPbeWithSHA1And40BitRC2_CBC, "1.2.840.113549.1.12.1.6");
47 //The size of the Initialization vector
48 const TInt KIvSize = 8;
59 * OCTET STRING -- salt
60 * INTEGER -- iteration count
61 * INTEGER -- effective key length in octets
63 * OID -- algorithm id (rc2)
65 * INTEGER -- RC2 parameter version 58 = 128, 160 = 40
75 * OCTET STRING -- salt
76 * INTEGER -- iteration count
78 * OID -- algorithm id (des, 3des)
82 EXPORT_C CASN1EncSequence* TASN1EncPKCS5::EncodeDERL(const CPBEncryptParms& aParms)
84 CASN1EncSequence* seq = CASN1EncSequence::NewLC();
85 CASN1EncObjectIdentifier* pbes2 = CASN1EncObjectIdentifier::NewLC(Kpkcs5PBES2);
86 seq->AddChildL(pbes2);
87 CleanupStack::Pop(pbes2);
89 CASN1EncSequence* seq1 = CASN1EncSequence::NewLC();
91 CleanupStack::Pop(seq1);
93 CASN1EncSequence* seq2 = CASN1EncSequence::NewLC();
94 seq1->AddChildL(seq2);
95 CleanupStack::Pop(seq2);
97 CASN1EncObjectIdentifier* pbkdf2 = CASN1EncObjectIdentifier::NewLC(Kpkcs5PBKDF2);
98 seq2->AddChildL(pbkdf2);
99 CleanupStack::Pop(pbkdf2);
101 CASN1EncSequence* seq3 = CASN1EncSequence::NewLC();
102 seq2->AddChildL(seq3);
103 CleanupStack::Pop(seq3);
105 CASN1EncOctetString* salt = CASN1EncOctetString::NewLC(aParms.Salt());
106 seq3->AddChildL(salt);
107 CleanupStack::Pop(salt);
109 CASN1EncInt* iterations = CASN1EncInt::NewLC(aParms.Iterations());
110 seq3->AddChildL(iterations);
111 CleanupStack::Pop(iterations);
113 CASN1EncInt* keysize = 0;
114 switch(aParms.Cipher())
117 case ECipher3DES_CBC:
119 case ECipherRC2_CBC_40:
120 keysize = CASN1EncInt::NewLC(KSSLCompatibilityBits/8); // effective key length in *octets*
121 seq3->AddChildL(keysize);
122 CleanupStack::Pop(keysize);
124 case ECipherRC2_CBC_128:
125 keysize = CASN1EncInt::NewLC(KSSLCompatibilityBits/8); // effective key length in *octets*
126 seq3->AddChildL(keysize);
127 CleanupStack::Pop(keysize);
129 case ECipherRC2_CBC_40_16:
130 keysize = CASN1EncInt::NewLC(KPkcs8CompatibilityBits/8); // effective key length in *octets*
131 seq3->AddChildL(keysize);
132 CleanupStack::Pop(keysize);
134 case ECipherRC2_CBC_128_16:
135 keysize = CASN1EncInt::NewLC(KPkcs8CompatibilityBits/8); // effective key length in *octets*
136 seq3->AddChildL(keysize);
137 CleanupStack::Pop(keysize);
140 User::Leave(KErrNotSupported);
144 CASN1EncSequence* seq4 = CASN1EncSequence::NewLC();
145 seq1->AddChildL(seq4);
146 CleanupStack::Pop(seq4);
148 CASN1EncObjectIdentifier* algid = 0;
149 switch(aParms.Cipher())
152 algid = CASN1EncObjectIdentifier::NewLC(KDESCBC);
154 case ECipher3DES_CBC:
155 algid = CASN1EncObjectIdentifier::NewLC(K3DESCBC);
157 case ECipherRC2_CBC_40:
158 case ECipherRC2_CBC_128:
159 case ECipherRC2_CBC_40_16:
160 case ECipherRC2_CBC_128_16:
161 algid = CASN1EncObjectIdentifier::NewLC(KRC2CBC);
164 User::Leave(KErrNotSupported);
167 seq4->AddChildL(algid);
168 CleanupStack::Pop(algid);
170 CASN1EncSequence* seq5 = 0;
171 CASN1EncInt* keysize1 = 0;
172 CASN1EncOctetString* iv = 0;
173 switch(aParms.Cipher())
176 case ECipher3DES_CBC:
177 iv = CASN1EncOctetString::NewLC(aParms.IV());
179 CleanupStack::Pop(iv);
181 case ECipherRC2_CBC_40:
182 case ECipherRC2_CBC_40_16:
183 seq5 = CASN1EncSequence::NewLC();
184 seq4->AddChildL(seq5);
185 CleanupStack::Pop(seq5);
187 keysize1 = CASN1EncInt::NewLC(160); //encoding for 40 bit
188 seq5->AddChildL(keysize1);
189 CleanupStack::Pop(keysize1);
191 iv = CASN1EncOctetString::NewLC(aParms.IV());
193 CleanupStack::Pop(iv);
195 case ECipherRC2_CBC_128:
196 case ECipherRC2_CBC_128_16:
197 seq5 = CASN1EncSequence::NewLC();
198 seq4->AddChildL(seq5);
199 CleanupStack::Pop(seq5);
201 keysize1 = CASN1EncInt::NewLC(58); //encoding for 128 bit
202 seq5->AddChildL(keysize1);
203 CleanupStack::Pop(keysize1);
205 iv = CASN1EncOctetString::NewLC(aParms.IV());
207 CleanupStack::Pop(iv);
210 User::Leave(KErrNotSupported);
213 CleanupStack::Pop(seq);
217 EXPORT_C CPBEncryptParms* TASN1DecPKCS5::DecodeDERL(const TDesC8& aBinaryData)
219 TASN1DecGeneric seqGen(aBinaryData);
221 if (seqGen.Tag() != EASN1Sequence)
223 User::Leave(KErrArgument);
226 //Decode the Algorithm Identifier Sequence
227 TASN1DecSequence seq;
228 CArrayPtrFlat<TASN1DecGeneric>* seqContents = seq.DecodeDERLC(seqGen);
231 if (seqContents->At(0)->Tag() != EASN1ObjectIdentifier)
233 User::Leave(KErrArgument);
235 CPBEncryptParms* params = NULL;
236 TASN1DecObjectIdentifier oid;
237 HBufC* oiddes = oid.DecodeDERL(*(seqContents->At(0)));
238 CleanupStack::PushL(oiddes);
239 //Algorithm Id is a pkcs-12Pbe Algorithm Id.
240 if(*oiddes != Kpkcs5PBES2)
242 // Initialise to impossible value
243 TPBECipher cipher = (TPBECipher) -1;
244 // Pbe12Algorithm Ids
245 if(*oiddes == KPbeWithSHA1And128BitRC4)
247 cipher = ECipherARC4_128;
249 else if(*oiddes == KPbeWithSHA1And40BitRC4)
251 cipher = ECipherARC4_40;
253 else if(*oiddes == KPbeWithSHA1And3_KeyTripleDES_CBC)
255 cipher = ECipher3DES_CBC;
257 else if(*oiddes == KPbeWithSHA1And2_KeyTripleDES_CBC)
259 cipher = ECipher2Key3DES_CBC;
261 else if(*oiddes == KPbeWithSHA1And128BitRC2_CBC)
263 cipher = ECipherRC2_CBC_128_16;
265 else if(*oiddes == KPbeWithSHA1And40BitRC2_CBC)
267 cipher = ECipherRC2_CBC_40_5;
271 User::Leave(KErrNotSupported);
274 TInt seqContentsCount = seqContents->Count();
276 //All pkcs-12Pbe algorithms require the Algorithm Parameters.
277 //Algorithm Parameters are not OPTIONAL for pkcs-12Pbe algorithms.
279 //seqContentsCount should be equal to 2.That is, the Algorithm Id
280 //and associated Algorithm Parameters have to be present.
281 if(seqContentsCount != 2)
283 User::Leave(KErrArgument);
285 //This if statement checks if the pkcs-12PbeParams Sequence is present in the
286 //AlgorithmIdentifier Sequence Since pkcs-12PbeParams are OPTIONAL
289 //Set the Initialization vector size to 8 bytes.
290 TBuf8<KIvSize> iv(KIvSize);
291 // Initialized to NULL, if salt is not present.
295 const TASN1DecGeneric* seqContentsAt1 = seqContents->At(1);
296 if (seqContentsAt1->Tag() != EASN1Sequence || seqContentsAt1->Class() != EUniversal)
298 User::Leave(KErrArgument);
301 CArrayPtrFlat<TASN1DecGeneric>* seq1Contents = seq.DecodeDERLC(*seqContentsAt1);
302 const TASN1DecGeneric* seq1ContentsAt0 = seq1Contents->At(0);
303 if (seq1ContentsAt0->Tag() != EASN1OctetString || seq1ContentsAt0->Class() != EUniversal)
305 User::Leave(KErrArgument);
307 salt.Set(seq1ContentsAt0->GetContentDER());
308 const TASN1DecGeneric* seq1ContentsAt1 = seq1Contents->At(1);
309 if (seq1ContentsAt1->Tag() != EASN1Integer || seq1ContentsAt1->Class() != EUniversal)
311 User::Leave(KErrArgument);
313 TASN1DecInteger integer;
314 iterations = integer.DecodeDERShortL(*seq1ContentsAt1);
317 User::Leave(KErrArgument);
319 params = CPBEncryptParms::NewL(cipher, salt, iv, iterations);
320 params->SetKdf(CPBEncryptParms::EKdfPkcs12);
321 CleanupStack::PopAndDestroy(seq1Contents);
324 //Algorithm Id is a pkcs-5Pbe Algorithm Id.
325 else if (*oiddes == Kpkcs5PBES2)
327 if (seqContents->At(1)->Tag() != EASN1Sequence)
329 User::Leave(KErrArgument);
331 CArrayPtrFlat<TASN1DecGeneric>* seq1Contents = seq.DecodeDERLC(*(seqContents->At(1)));
333 if (seq1Contents->At(0)->Tag() != EASN1Sequence)
335 User::Leave(KErrArgument);
337 CArrayPtrFlat<TASN1DecGeneric>* seq2Contents = seq.DecodeDERLC(*(seq1Contents->At(0)));
339 if (seq2Contents->At(0)->Tag() != EASN1ObjectIdentifier)
341 User::Leave(KErrArgument);
343 HBufC* oid1des = oid.DecodeDERL(*(seq2Contents->At(0)));
344 CleanupStack::PushL(oid1des);
346 if(*oid1des != Kpkcs5PBKDF2)
348 User::Leave(KErrNotSupported);
350 if (seq2Contents->At(1)->Tag() != EASN1Sequence)
352 User::Leave(KErrArgument);
354 CArrayPtrFlat<TASN1DecGeneric>* seq3Contents = seq.DecodeDERLC(*(seq2Contents->At(1)));
356 if (seq3Contents->At(0)->Tag() != EASN1OctetString)
358 User::Leave(KErrArgument);
360 TASN1DecOctetString octet;
361 HBufC8* salt = octet.DecodeDERL(*(seq3Contents->At(0)));
362 CleanupStack::PushL(salt);
364 if (seq3Contents->At(1)->Tag() != EASN1Integer)
366 User::Leave(KErrArgument);
368 TASN1DecInteger integer;
369 TInt iterations = integer.DecodeDERShortL(*(seq3Contents->At(1)));
371 if (seq1Contents->At(1)->Tag() != EASN1Sequence)
373 User::Leave(KErrArgument);
375 CArrayPtrFlat<TASN1DecGeneric>* seq4Contents = seq.DecodeDERLC(*(seq1Contents->At(1)));
377 TPBECipher cipher = (TPBECipher) -1; // Initialise to impossible value
378 if (seq4Contents->At(0)->Tag() != EASN1ObjectIdentifier)
380 User::Leave(KErrArgument);
382 HBufC* oid2des = oid.DecodeDERL(*(seq4Contents->At(0)));
383 CleanupStack::PushL(oid2des);
385 CArrayPtrFlat<TASN1DecGeneric>* seq5Contents = 0;
387 if(*oid2des == K3DESCBC)
389 cipher = ECipher3DES_CBC;
390 CleanupStack::PushL(seq5Contents);
392 else if(*oid2des == KDESCBC)
394 cipher = ECipherDES_CBC;
395 CleanupStack::PushL(seq5Contents);
397 else if(*oid2des == KRC2CBC)
399 // RC2 has an additional parameter, the effective key lenght in octets.
400 if (seq3Contents->At(2)->Tag() != EASN1Integer)
402 User::Leave(KErrArgument);
404 TInt effectiveKeyLength = integer.DecodeDERShortL(*(seq3Contents->At(2)));
406 if (seq4Contents->At(1)->Tag() != EASN1Sequence)
408 User::Leave(KErrArgument);
410 seq5Contents = seq.DecodeDERLC(*(seq4Contents->At(1)));
411 if (seq5Contents->At(0)->Tag() != EASN1Integer)
413 User::Leave(KErrArgument);
415 TInt keysize = integer.DecodeDERShortL(*(seq5Contents->At(0)));
418 // These values come from the PKCS#5 v2 specs
420 if (effectiveKeyLength == 16)
422 cipher = ECipherRC2_CBC_40_16;
426 if (effectiveKeyLength == 128)
428 cipher = ECipherRC2_CBC_40;
432 User::Leave(KErrNotSupported); // Unsupported effective key length!
437 if (effectiveKeyLength == 16)
439 cipher = ECipherRC2_CBC_128_16;
443 if (effectiveKeyLength == 128)
445 cipher = ECipherRC2_CBC_128;
449 User::Leave(KErrNotSupported); // Unsupported effective key length!
454 //would be RC_CBC_64 but we don't support that
456 User::Leave(KErrNotSupported);
462 User::Leave(KErrNotSupported);
468 case ECipher3DES_CBC:
470 if (seq4Contents->At(1)->Tag() != EASN1OctetString)
472 User::Leave(KErrArgument);
474 iv = octet.DecodeDERL(*(seq4Contents->At(1)));
475 CleanupStack::PushL(iv);
477 case ECipherRC2_CBC_40:
478 case ECipherRC2_CBC_128:
479 case ECipherRC2_CBC_40_16:
480 case ECipherRC2_CBC_128_16:
481 if (seq5Contents->At(1)->Tag() != EASN1OctetString)
483 User::Leave(KErrArgument);
485 iv = octet.DecodeDERL(*(seq5Contents->At(1)));
486 CleanupStack::PushL(iv);
489 User::Leave(KErrNotSupported);
493 params = CPBEncryptParms::NewL(cipher, *salt, *iv,
495 CleanupStack::PopAndDestroy(9); //iv, seq5contents, oid2des, seq4Contents,
496 //salt, seq3Contents, oid1des, seq2Contents, seq1Contents
500 User::Leave(KErrNotSupported);
502 CleanupStack::PopAndDestroy(2, seqContents);