|
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 "pkcs7encrypteddataobject.h" |
|
20 |
|
21 /** The last character in the PKCS7 EncryptedData OID */ |
|
22 const TInt KPkcs7EncryptedData = 6; |
|
23 |
|
24 EXPORT_C CPKCS7EncryptedDataObject* CPKCS7EncryptedDataObject::NewL(const CPKCS7ContentInfo& aContentInfo) |
|
25 { |
|
26 CPKCS7EncryptedDataObject* self = new (ELeave) CPKCS7EncryptedDataObject(); |
|
27 CleanupStack::PushL(self); |
|
28 self->ConstructL(aContentInfo); |
|
29 CleanupStack::Pop(self); |
|
30 return self; |
|
31 } |
|
32 |
|
33 CPKCS7EncryptedDataObject::CPKCS7EncryptedDataObject(void) |
|
34 { |
|
35 } |
|
36 |
|
37 CPKCS7EncryptedDataObject::~CPKCS7EncryptedDataObject() |
|
38 { |
|
39 delete iEncryptParams; |
|
40 } |
|
41 |
|
42 EXPORT_C TInt CPKCS7EncryptedDataObject::Version() const |
|
43 { |
|
44 return iVersion; |
|
45 } |
|
46 |
|
47 EXPORT_C CPKCS7EncryptedDataObject::TContentType CPKCS7EncryptedDataObject::ContentType() const |
|
48 { |
|
49 return iContentType; |
|
50 } |
|
51 |
|
52 EXPORT_C const TDesC8& CPKCS7EncryptedDataObject::EncryptedContentInfoData() const |
|
53 { |
|
54 return iEncryptedContent; |
|
55 } |
|
56 |
|
57 EXPORT_C const CPBEncryptParms& CPKCS7EncryptedDataObject::EncryptParams() const |
|
58 { |
|
59 return *iEncryptParams; |
|
60 } |
|
61 |
|
62 CPBEncryptParms* CPKCS7EncryptedDataObject::DecodeContentEncryptionAlgorithmL(const TDesC8& aBinaryData) const |
|
63 { |
|
64 TASN1DecGeneric seqGen(aBinaryData); |
|
65 seqGen.InitL(); |
|
66 if (seqGen.Tag() != EASN1Sequence || seqGen.Class() != EUniversal) |
|
67 { |
|
68 User::Leave(KErrArgument); |
|
69 } |
|
70 |
|
71 TPtrC8 theContent(seqGen.Encoding()); |
|
72 CPBEncryptParms* encryptParams = TASN1DecPKCS5::DecodeDERL(theContent); |
|
73 return encryptParams; |
|
74 } |
|
75 |
|
76 EXPORT_C HBufC8* CPKCS7EncryptedDataObject::DecryptDataL(const TDesC& aPassword) const |
|
77 { |
|
78 CPBEncryptElement* encryptElement; |
|
79 HBufC8* pkcs12Pwd = PKCS12KDF::GeneratePasswordLC(aPassword); |
|
80 if(iEncryptParams->Kdf() == CPBEncryptParms::EKdfPkcs12) |
|
81 { |
|
82 TPtrC8 iv = iEncryptParams->IV(); |
|
83 HBufC8* ivValue = HBufC8::NewMaxLC(iv.Length()); |
|
84 TPtr8 encryptKeyBuf = ivValue->Des(); |
|
85 |
|
86 switch(iEncryptParams->Cipher()) |
|
87 { |
|
88 case ECipherARC4_128: |
|
89 case ECipherARC4_40: |
|
90 { |
|
91 //derive only key it is unnecessary to derive an IV for RC4 |
|
92 break; |
|
93 } |
|
94 case ECipher3DES_CBC: |
|
95 case ECipher2Key3DES_CBC: |
|
96 case ECipherRC2_CBC_128_16: |
|
97 case ECipherRC2_CBC_40_5: |
|
98 { |
|
99 PKCS12KDF::DeriveKeyL(encryptKeyBuf, PKCS12KDF::EIDByteIV, *pkcs12Pwd, iEncryptParams->Salt(), iEncryptParams->Iterations()); |
|
100 iEncryptParams->SetIV(encryptKeyBuf); |
|
101 break; |
|
102 } |
|
103 default: |
|
104 { |
|
105 User::Leave(KErrNotSupported); |
|
106 break; |
|
107 } |
|
108 } |
|
109 CleanupStack::PopAndDestroy(ivValue); |
|
110 // Create the decryptor |
|
111 encryptElement = CPBEncryptElement::NewLC(*pkcs12Pwd, *iEncryptParams); |
|
112 } |
|
113 else |
|
114 { |
|
115 TPBPassword password(aPassword); |
|
116 // Create the decryptor |
|
117 encryptElement = CPBEncryptElement::NewLC(password.Password(), *iEncryptParams); |
|
118 } |
|
119 |
|
120 CPBDecryptor* decryptor = encryptElement->NewDecryptLC(); |
|
121 |
|
122 TPtrC8 encryptedKey(iEncryptedContent); |
|
123 TUint encryptLength = encryptedKey.Length(); |
|
124 TUint maxDecryptLength = decryptor->MaxOutputLength(encryptLength); |
|
125 |
|
126 if ( maxDecryptLength <= 0 ) |
|
127 { |
|
128 User::Leave(KErrGeneral); |
|
129 } |
|
130 |
|
131 HBufC8* decryptedContent = HBufC8::NewLC(maxDecryptLength); |
|
132 TPtr8 dcDes(decryptedContent->Des()); |
|
133 decryptor->Process(encryptedKey, dcDes); |
|
134 CleanupStack::Pop(decryptedContent); |
|
135 CleanupStack::PopAndDestroy(3, pkcs12Pwd); // pkcs12Pwd, encryptElement, decryptor |
|
136 return decryptedContent; |
|
137 } |
|
138 |
|
139 void CPKCS7EncryptedDataObject::ConstructL(const CPKCS7ContentInfo& aContentInfo) |
|
140 { |
|
141 if(aContentInfo.ContentType() != KPkcs7EncryptedData) |
|
142 { |
|
143 User::Leave(KErrArgument); |
|
144 } |
|
145 |
|
146 // EncryptedData SEQUENCE |
|
147 TASN1DecGeneric decGen(aContentInfo.ContentData()); |
|
148 decGen.InitL(); |
|
149 if(decGen.Tag() != EASN1Sequence || decGen.Class() != EUniversal) |
|
150 { |
|
151 User::Leave(KErrArgument); |
|
152 } |
|
153 TASN1DecSequence seq1; |
|
154 CArrayPtrFlat<TASN1DecGeneric>* EncryptedDataContents = seq1.DecodeDERLC(decGen); |
|
155 |
|
156 // Both version and encryptedContentInfo should be present |
|
157 if (EncryptedDataContents->Count() != 2) |
|
158 { |
|
159 User::Leave(KErrArgument); |
|
160 } |
|
161 |
|
162 // VERSION |
|
163 // version is the syntax version number. It shall be 0 for this version of the standard |
|
164 const TASN1DecGeneric* EncryptedDataContentsAt0 = EncryptedDataContents->At(0); |
|
165 if(EncryptedDataContentsAt0->Tag() != EASN1Integer || EncryptedDataContentsAt0->Class() != EUniversal) |
|
166 { |
|
167 User::Leave(KErrArgument); |
|
168 } |
|
169 |
|
170 TASN1DecInteger intDecoder; |
|
171 iVersion = intDecoder.DecodeDERShortL(*EncryptedDataContentsAt0); |
|
172 if (iVersion != 0) |
|
173 { |
|
174 User::Leave(KErrArgument); |
|
175 } |
|
176 |
|
177 // ENCRYPTED CONTENT INFO a SEQUENCE |
|
178 const TASN1DecGeneric* EncryptedDataContentsAt1 = EncryptedDataContents->At(1); |
|
179 if (EncryptedDataContentsAt1->Tag() != EASN1Sequence || EncryptedDataContentsAt1->Class() != EUniversal) |
|
180 { |
|
181 User::Leave(KErrArgument); |
|
182 } |
|
183 TASN1DecSequence seq2; |
|
184 CArrayPtrFlat<TASN1DecGeneric>* EncryptedContentInfo = seq2.DecodeDERLC(*EncryptedDataContentsAt1); |
|
185 |
|
186 // CONTENT TYPE IDENTIFIED BY AN OBJECT IDENTIFIER |
|
187 // Gets the oid |
|
188 TASN1DecObjectIdentifier ContentTypeoidDec; |
|
189 HBufC* contentType = ContentTypeoidDec.DecodeDERL(*EncryptedContentInfo->At(0)); |
|
190 if(contentType->Compare(KPkcs7DataOID()) == 0) |
|
191 { |
|
192 iContentType = EPkcs7Data; |
|
193 } |
|
194 else |
|
195 { |
|
196 User::Leave(KErrNotSupported); |
|
197 } |
|
198 delete contentType; |
|
199 // CONTENT ENCRYPTION ALGORITHM |
|
200 // Get the Cipher used and the encoded params in it |
|
201 iEncryptParams = DecodeContentEncryptionAlgorithmL(EncryptedContentInfo->At(1)->Encoding()); |
|
202 |
|
203 // ENCRYPTED CONTENT |
|
204 // This is an OPTIONAL field |
|
205 TInt encryptedContentInfoCount = EncryptedContentInfo->Count(); |
|
206 if(encryptedContentInfoCount == 3) |
|
207 { |
|
208 TASN1DecGeneric decOctetString(*EncryptedContentInfo->At(2)); |
|
209 decOctetString.InitL(); |
|
210 iEncryptedContent.Set(decOctetString.GetContentDER()); |
|
211 } |
|
212 else if(encryptedContentInfoCount > 3 || encryptedContentInfoCount < 2) |
|
213 { |
|
214 User::Leave(KErrArgument); |
|
215 } |
|
216 else if(encryptedContentInfoCount == 2) |
|
217 { |
|
218 iEncryptedContent.Set(KNullDesC8()); |
|
219 } |
|
220 |
|
221 CleanupStack::PopAndDestroy(2, EncryptedDataContents); //EncryptedDataContents, EncryptedContentInfo |
|
222 } |