|
1 /* |
|
2 * Copyright (c) 2006-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 "cmsutils.h" |
|
20 #include <asymmetric.h> |
|
21 #include <asn1enc.h> |
|
22 #include <asn1dec.h> |
|
23 #include <cmsdefs.h> |
|
24 #include <pkcs7excert.h> |
|
25 #include <x509cert.h> |
|
26 #include "pkcs7asn1.h" |
|
27 |
|
28 |
|
29 TInt CmsUtils::DecodeContentTypeL(const TASN1DecGeneric* aASN1DecGeneric) |
|
30 { |
|
31 TInt type(0); |
|
32 if(aASN1DecGeneric->Tag()==EASN1ObjectIdentifier || aASN1DecGeneric->Class() == EUniversal) |
|
33 { |
|
34 TASN1DecObjectIdentifier oidDec; |
|
35 HBufC* oidVal = oidDec.DecodeDERL(*aASN1DecGeneric); |
|
36 CleanupStack::PushL(oidVal); |
|
37 |
|
38 // Checks if it is data OID. |
|
39 if(*oidVal == KCmsDataOID) |
|
40 { |
|
41 // The Content Type is indicated by an Integer. |
|
42 // Here if Content Type is equal to Data then,it is represented by 1 |
|
43 type = EContentTypeData; |
|
44 } |
|
45 else if(*oidVal == KCmsSignedDataOID) |
|
46 { |
|
47 // The Content Type is indicated by an Integer. |
|
48 // Here if Content Type is equal to SignedData then,it is represented by 2 |
|
49 type = EContentTypeSignedData; |
|
50 } |
|
51 else if(*oidVal == KCmsEnvelopedDataOID) |
|
52 { |
|
53 // The Content Type is indicated by an Integer. |
|
54 // Here if Content Type is equal to EnvelopedData then,it is represented by 3. |
|
55 type = EContentTypeEnvelopedData; |
|
56 } |
|
57 else if(*oidVal == KCmsDigestedDataOID) |
|
58 { |
|
59 // The Content Type is indicated by an Integer. |
|
60 // Here if Content Type is equal to DigestedData then,it is represented by 5. |
|
61 type = EContentTypeDigestedData; |
|
62 } |
|
63 else if(*oidVal == KCmsEncryptedDataOID) |
|
64 { |
|
65 // The Content Type is indicated by an Integer. |
|
66 // Here if Content Type is equal to EncryptedData then,it is represented by 6 |
|
67 type = EContentTypeEncryptedData; |
|
68 } |
|
69 else if(*oidVal == KCmsAuthenticatedDataOID) |
|
70 { |
|
71 // The Content Type is indicated by an Integer. |
|
72 // Here if Content Type is equal to EncryptedData then,it is represented by 7 |
|
73 type = EContentTypeAuthenticatedData; |
|
74 } |
|
75 |
|
76 else |
|
77 { |
|
78 User::Leave(KErrArgument); |
|
79 } |
|
80 CleanupStack::PopAndDestroy(oidVal); |
|
81 } |
|
82 else |
|
83 { |
|
84 User::Leave(KErrArgument); |
|
85 } |
|
86 return type; |
|
87 } |
|
88 |
|
89 CASN1EncObjectIdentifier* CmsUtils::EncodeContentTypeLC(TInt aContentType) |
|
90 { |
|
91 TPtrC oidBuf; |
|
92 switch (aContentType) |
|
93 { |
|
94 case EContentTypeData: |
|
95 oidBuf.Set(KCmsDataOID()); |
|
96 break; |
|
97 |
|
98 case EContentTypeSignedData: |
|
99 oidBuf.Set(KCmsSignedDataOID()); |
|
100 break; |
|
101 |
|
102 case EContentTypeEnvelopedData: |
|
103 oidBuf.Set(KCmsEnvelopedDataOID()); |
|
104 break; |
|
105 |
|
106 case EContentTypeDigestedData: |
|
107 oidBuf.Set(KCmsDigestedDataOID()); |
|
108 break; |
|
109 |
|
110 case EContentTypeEncryptedData: |
|
111 oidBuf.Set(KCmsEncryptedDataOID()); |
|
112 break; |
|
113 |
|
114 default: |
|
115 User::Leave(KErrArgument); |
|
116 } |
|
117 //Encode the OID |
|
118 CASN1EncObjectIdentifier* oid=CASN1EncObjectIdentifier::NewLC(oidBuf); |
|
119 return oid; |
|
120 } |
|
121 |
|
122 void CmsUtils::AddCertificateL(RPointerArray<CCmsCertificateChoice>& aCertList, const TDesC8& aCert, CCmsCertificateChoice::TCertificateType aType) |
|
123 { |
|
124 TInt found(EFalse); |
|
125 TInt count=aCertList.Count(); |
|
126 for (TInt i=0;i<count;i++) |
|
127 { |
|
128 if (aCertList[i]->CertificateType()==CCmsCertificateChoice::ECertificateAttribute |
|
129 && aCert.Compare(*aCertList[i]->AttributeCertificate())==0) |
|
130 { |
|
131 found=ETrue; |
|
132 break; |
|
133 } |
|
134 } |
|
135 |
|
136 if (!found) |
|
137 { |
|
138 CCmsCertificateChoice* cert=CCmsCertificateChoice::NewL(aType, aCert); |
|
139 CleanupStack::PushL(cert); |
|
140 aCertList.AppendL(cert); |
|
141 CleanupStack::Pop(cert); |
|
142 } |
|
143 } |
|
144 |
|
145 void CmsUtils::AddCertificateL(RPointerArray<CCmsCertificateChoice>& aCertList, const CX509Certificate& aCert) |
|
146 { |
|
147 |
|
148 TInt found(EFalse); |
|
149 TInt count=aCertList.Count(); |
|
150 for (TInt i=0;i<count;i++) |
|
151 { |
|
152 if (aCertList[i]->CertificateType()==CCmsCertificateChoice::ECertificateX509 |
|
153 && aCert.IsEqualL(aCertList[i]->Certificate())) |
|
154 { |
|
155 found=ETrue; |
|
156 break; |
|
157 } |
|
158 } |
|
159 |
|
160 if (!found) |
|
161 { |
|
162 CCmsCertificateChoice* cert=CCmsCertificateChoice::NewL(aCert); |
|
163 CleanupStack::PushL(cert); |
|
164 aCertList.AppendL(cert); |
|
165 CleanupStack::Pop(cert); |
|
166 } |
|
167 |
|
168 } |
|
169 |
|
170 void CmsUtils::AddAlgorithmIdentifierL(RPointerArray<CX509AlgorithmIdentifier>& aAlgorithmIdList, TAlgorithmId aDigestAlgorithm) |
|
171 { |
|
172 TInt found(EFalse); |
|
173 TInt count=aAlgorithmIdList.Count(); |
|
174 for (TInt i=0;i<count;i++) |
|
175 { |
|
176 if (aAlgorithmIdList[i]->Algorithm()==aDigestAlgorithm) |
|
177 { |
|
178 found=ETrue; |
|
179 break; |
|
180 } |
|
181 } |
|
182 if (!found) |
|
183 { |
|
184 CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8()); |
|
185 aAlgorithmIdList.AppendL(digAlg); |
|
186 CleanupStack::Pop(digAlg); |
|
187 } |
|
188 } |
|
189 |
|
190 void CmsUtils::DecodeDigestAlgorithmsL(RPointerArray<CX509AlgorithmIdentifier>& aDigestAlgorithms, const TDesC8& aRawData) |
|
191 { |
|
192 CArrayPtr<TASN1DecGeneric>* algsData = PKCS7ASN1::DecodeSequenceLC(aRawData); |
|
193 TInt count = algsData->Count(); |
|
194 CX509AlgorithmIdentifier* alIdent; |
|
195 |
|
196 for(TInt item = 0; item < count; item++) |
|
197 { |
|
198 alIdent = CX509AlgorithmIdentifier::NewLC(algsData->At(item)->Encoding()); |
|
199 aDigestAlgorithms.AppendL(alIdent); |
|
200 CleanupStack::Pop(alIdent); |
|
201 } |
|
202 CleanupStack::PopAndDestroy(algsData); |
|
203 } |
|
204 |
|
205 void CmsUtils::DecodeCertificatesL(RPointerArray<CCmsCertificateChoice>& aCertificates, const TDesC8& aRawData) |
|
206 { |
|
207 TASN1DecGeneric decGen(aRawData); |
|
208 decGen.InitL(); |
|
209 TASN1DecSequence decSeq; |
|
210 // have to do manual decoding of sequence because field is optional |
|
211 CArrayPtr<TASN1DecGeneric>* items = NULL; |
|
212 items = decSeq.DecodeDERLC(decGen); |
|
213 TInt count = items->Count(); |
|
214 |
|
215 CCmsCertificateChoice* certificate; |
|
216 |
|
217 for(TInt item = 0; item < count; item++) |
|
218 { |
|
219 certificate = CCmsCertificateChoice::NewL(items->At(item)->Encoding()); |
|
220 CleanupStack::PushL(certificate); |
|
221 aCertificates.AppendL(certificate); |
|
222 CleanupStack::Pop(certificate); |
|
223 } |
|
224 |
|
225 CleanupStack::PopAndDestroy(items); |
|
226 } |
|
227 |
|
228 CASN1EncBase* CmsUtils::EncodeCertificatesLC(const RPointerArray<CCmsCertificateChoice>& aCertificates) |
|
229 { |
|
230 CASN1EncSet* certSet(NULL); |
|
231 TInt count=aCertificates.Count(); |
|
232 if (count>0) |
|
233 { |
|
234 certSet = CASN1EncSet::NewLC(); |
|
235 for (TInt i=0;i<count;i++) |
|
236 { |
|
237 CASN1EncEncoding* cert=aCertificates[i]->EncodeASN1DERLC(); |
|
238 certSet->AddAndPopChildL(cert); |
|
239 } |
|
240 // [0] implicit |
|
241 certSet->SetTag(0); |
|
242 } |
|
243 return certSet; |
|
244 } |
|
245 |
|
246 CASN1EncBase* CmsUtils::EncodeDigestAlgorithmsLC(const RPointerArray<CX509AlgorithmIdentifier>& aDigestAlgorithms) |
|
247 { |
|
248 CASN1EncSet* algorithmSet = CASN1EncSet::NewLC(); |
|
249 TInt count=aDigestAlgorithms.Count(); |
|
250 |
|
251 for (TInt i=0;i<count;i++) |
|
252 { |
|
253 CASN1EncSequence* tmp=aDigestAlgorithms[i]->EncodeASN1DERLC(); |
|
254 algorithmSet->AddAndPopChildL(tmp); |
|
255 } |
|
256 |
|
257 return algorithmSet; |
|
258 } |
|
259 |
|
260 void CmsUtils::DecodeOctetStringL(const TDesC8& aRawData, HBufC8*& aBuf) |
|
261 { |
|
262 TASN1DecGeneric decGen(aRawData); |
|
263 decGen.InitL(); |
|
264 |
|
265 if(decGen.Tag()==EASN1OctetString && decGen.Class()==EUniversal) |
|
266 { |
|
267 TASN1DecOctetString decOct; |
|
268 aBuf = decOct.DecodeDERL(decGen); |
|
269 } |
|
270 else |
|
271 { |
|
272 User::Leave(KErrArgument); |
|
273 } |
|
274 } |
|
275 |
|
276 |
|
277 CMessageDigest* CmsUtils::CreateHashLC(TAlgorithmId aAlgorithm) |
|
278 { |
|
279 CMessageDigest* hash(NULL); |
|
280 switch (aAlgorithm) |
|
281 { |
|
282 case EMD2: |
|
283 hash=CMD2::NewL(); |
|
284 break; |
|
285 |
|
286 case EMD5: |
|
287 hash=CMD5::NewL(); |
|
288 break; |
|
289 |
|
290 case ESHA1: |
|
291 hash=CSHA1::NewL(); |
|
292 break; |
|
293 |
|
294 default: |
|
295 User::Leave(KErrNotSupported); |
|
296 } |
|
297 CleanupStack::PushL(hash); |
|
298 return hash; |
|
299 } |
|
300 |
|
301 |
|
302 HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aDataToBeSigned, TBool aIsHash, TAlgorithmId aAlgorithm, const CDSAPrivateKey& aKey) |
|
303 { |
|
304 HBufC8* signature(NULL); |
|
305 |
|
306 if (!aIsHash) |
|
307 { |
|
308 TPtrC8 hashValue; |
|
309 // Create hash first |
|
310 CMessageDigest* hash=CreateHashLC(aAlgorithm); |
|
311 hashValue.Set(hash->Hash(aDataToBeSigned)); |
|
312 signature=CreateSignatureL(hashValue, aKey); |
|
313 CleanupStack::PopAndDestroy(); // hash |
|
314 } |
|
315 else |
|
316 { |
|
317 signature=CreateSignatureL(aDataToBeSigned, aKey); |
|
318 } |
|
319 |
|
320 return signature; |
|
321 } |
|
322 |
|
323 HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aDataToBeSigned, TBool aIsHash, TAlgorithmId aAlgorithm, const CRSAPrivateKey& aKey) |
|
324 { |
|
325 HBufC8* signature(NULL); |
|
326 TPtrC8 hashValue; |
|
327 if (!aIsHash) |
|
328 { |
|
329 // Create hash first |
|
330 CMessageDigest* hash=CreateHashLC(aAlgorithm); |
|
331 hashValue.Set(hash->Hash(aDataToBeSigned)); |
|
332 } |
|
333 else |
|
334 { |
|
335 hashValue.Set(aDataToBeSigned); |
|
336 } |
|
337 |
|
338 //Build the digestInfo Sequence |
|
339 CASN1EncSequence* digestInfoSeq = CASN1EncSequence::NewLC(); |
|
340 |
|
341 //Encode the Algorithm |
|
342 CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aAlgorithm, KNullDesC8()); |
|
343 CASN1EncSequence* sigAlg=digAlg->EncodeASN1DERLC(); |
|
344 digestInfoSeq->AddAndPopChildL(sigAlg); |
|
345 CleanupStack::PopAndDestroy(digAlg); |
|
346 |
|
347 //Encode the digest itself |
|
348 CASN1EncOctetString* sigEnc=CASN1EncOctetString::NewLC(hashValue); |
|
349 digestInfoSeq->AddAndPopChildL(sigEnc); |
|
350 |
|
351 //Get the Encoding |
|
352 HBufC8* digestInfo=CreateDEREncodingLC(*digestInfoSeq); |
|
353 signature=CreateSignatureL(digestInfo->Des(), aKey); |
|
354 |
|
355 CleanupStack::PopAndDestroy(2, digestInfoSeq); //digestInfo, digestInfoSeq |
|
356 if (!aIsHash) |
|
357 { |
|
358 CleanupStack::PopAndDestroy(); // hash |
|
359 } |
|
360 return signature; |
|
361 } |
|
362 |
|
363 HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aHash, const CDSAPrivateKey& aKey) |
|
364 { |
|
365 //Create Signer and sign the hash |
|
366 CDSASigner* signer=CDSASigner::NewLC(aKey); |
|
367 const CDSASignature* sig=signer->SignL(aHash); |
|
368 CDSASignature* signonc=const_cast<CDSASignature*>(sig); |
|
369 |
|
370 CleanupStack::PushL(signonc); |
|
371 |
|
372 //The sequence |
|
373 CASN1EncSequence* sigSeq = CASN1EncSequence::NewLC(); |
|
374 CASN1EncBigInt* r = CASN1EncBigInt::NewLC(static_cast<const RInteger&>(sig->R())); |
|
375 sigSeq->AddAndPopChildL(r); |
|
376 CASN1EncBigInt* s = CASN1EncBigInt::NewLC(static_cast<const RInteger&>(sig->S())); |
|
377 sigSeq->AddAndPopChildL(s); |
|
378 |
|
379 //Write the buffer |
|
380 TUint len=sigSeq->LengthDER(); |
|
381 HBufC8* buf=HBufC8::NewMaxLC(len); |
|
382 TPtr8 des=buf->Des(); |
|
383 TUint pos=0; |
|
384 sigSeq->WriteDERL(des, pos); |
|
385 |
|
386 //Clean up |
|
387 CleanupStack::Pop(buf); //buf |
|
388 CleanupStack::PopAndDestroy(3, signer); //sigSeq, signonc, signer |
|
389 return buf; |
|
390 } |
|
391 |
|
392 HBufC8* CmsUtils::CreateSignatureL(const TDesC8& aHash, const CRSAPrivateKey& aKey) |
|
393 { |
|
394 //Create Signer and sign the hash |
|
395 CRSAPKCS1v15Signer* signer=CRSAPKCS1v15Signer::NewLC(aKey); |
|
396 const CRSASignature* sig=signer->SignL(aHash); |
|
397 CRSASignature* signonc=const_cast<CRSASignature*>(sig); |
|
398 |
|
399 CleanupStack::PushL(signonc); |
|
400 |
|
401 HBufC8* sigData = sig->S().BufferWithNoTruncationLC(); |
|
402 |
|
403 //Clean up |
|
404 CleanupStack::Pop(sigData); |
|
405 CleanupStack::PopAndDestroy(2, signer);//signonc signer |
|
406 return sigData; |
|
407 } |
|
408 |
|
409 HBufC8* CmsUtils::CreateDEREncodingLC(const CASN1EncBase& aEncoding) |
|
410 { |
|
411 TUint len = aEncoding.LengthDER(); |
|
412 HBufC8* buf = HBufC8::NewMaxLC(len); |
|
413 TUint pos = 0; |
|
414 TPtr8 bufptr(buf->Des()); |
|
415 aEncoding.WriteDERL(bufptr, pos); |
|
416 return buf; |
|
417 } |