|
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 <cmssignedobject.h> |
|
20 #include <x509cert.h> |
|
21 #include <x509certext.h> |
|
22 #include <asymmetrickeys.h> |
|
23 #include <hash.h> |
|
24 #include <asn1enc.h> |
|
25 #include <asn1dec.h> |
|
26 #include <pkcs7excert.h> |
|
27 #include <cmssigneridentifier.h> |
|
28 #include <cmscontentinfo.h> |
|
29 #include <cmssignerinfo.h> |
|
30 #include "cmsutils.h" |
|
31 #include "pkcs7asn1.h" |
|
32 |
|
33 const TInt KSignedDataCertificates = 0; |
|
34 const TInt KSignedDataRevocationLists = 1; |
|
35 |
|
36 const TInt KCmsMinSignedDataElements = 4; |
|
37 // |
|
38 // Implementation of CMS Signed object |
|
39 // |
|
40 EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData) |
|
41 { |
|
42 CCmsSignedObject* self = new (ELeave) CCmsSignedObject(); |
|
43 CleanupStack::PushL(self); |
|
44 self->ConstructL(aType, aIsDetached, aContentData); |
|
45 return self; |
|
46 } |
|
47 |
|
48 EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData) |
|
49 { |
|
50 CCmsSignedObject* self = NewLC(aType, aIsDetached, aContentData); |
|
51 CleanupStack::Pop(self); |
|
52 return self; |
|
53 } |
|
54 |
|
55 EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType, |
|
56 const TDesC8& aHashValue, |
|
57 TAlgorithmId aDigestAlgorithm, |
|
58 const CDSAPrivateKey& aKey, |
|
59 const CX509Certificate& aCert, |
|
60 TBool aAddCertificate) |
|
61 { |
|
62 CCmsSignedObject* self = new (ELeave) CCmsSignedObject(); |
|
63 CleanupStack::PushL(self); |
|
64 self->ConstructL(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate); |
|
65 return self; |
|
66 } |
|
67 |
|
68 EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType, |
|
69 const TDesC8& aHashValue, |
|
70 TAlgorithmId aDigestAlgorithm, |
|
71 const CDSAPrivateKey& aKey, |
|
72 const CX509Certificate& aCert, |
|
73 TBool aAddCertificate) |
|
74 { |
|
75 CCmsSignedObject* self = NewLC(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate); |
|
76 CleanupStack::Pop(self); |
|
77 return self; |
|
78 } |
|
79 |
|
80 |
|
81 EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(TCmsContentInfoType aType, |
|
82 const TDesC8& aHashValue, |
|
83 TAlgorithmId aDigestAlgorithm, |
|
84 const CRSAPrivateKey& aKey, |
|
85 const CX509Certificate& aCert, |
|
86 TBool aAddCertificate) |
|
87 { |
|
88 CCmsSignedObject* self = new (ELeave) CCmsSignedObject(); |
|
89 CleanupStack::PushL(self); |
|
90 self->ConstructL(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate); |
|
91 return self; |
|
92 } |
|
93 |
|
94 EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(TCmsContentInfoType aType, |
|
95 const TDesC8& aHashValue, |
|
96 TAlgorithmId aDigestAlgorithm, |
|
97 const CRSAPrivateKey& aKey, |
|
98 const CX509Certificate& aCert, |
|
99 TBool aAddCertificate) |
|
100 { |
|
101 CCmsSignedObject* self = NewLC(aType, aHashValue, aDigestAlgorithm, aKey, aCert, aAddCertificate); |
|
102 CleanupStack::Pop(self); |
|
103 return self; |
|
104 } |
|
105 |
|
106 |
|
107 EXPORT_C CCmsSignedObject* CCmsSignedObject::NewL(const CCmsContentInfo& aContentInfo) |
|
108 { |
|
109 CCmsSignedObject* self = NewLC(aContentInfo); |
|
110 CleanupStack::Pop(self); |
|
111 return self; |
|
112 } |
|
113 |
|
114 EXPORT_C CCmsSignedObject* CCmsSignedObject::NewLC(const CCmsContentInfo& aContentInfo) |
|
115 { |
|
116 CCmsSignedObject* self = new (ELeave) CCmsSignedObject(); |
|
117 CleanupStack::PushL(self); |
|
118 self->ConstructL(aContentInfo); |
|
119 return self; |
|
120 } |
|
121 |
|
122 CCmsSignedObject::CCmsSignedObject() : iVersion(EVersion_1) |
|
123 { |
|
124 } |
|
125 |
|
126 EXPORT_C CCmsSignedObject::~CCmsSignedObject() |
|
127 { |
|
128 delete iContentInfo; |
|
129 iDigestAlgorithms.ResetAndDestroy(); |
|
130 iCertificates.ResetAndDestroy(); |
|
131 iSignerInfo.ResetAndDestroy(); |
|
132 for(TInt i = 0; i < KCmsMaxSignedDataElements; i++) |
|
133 { |
|
134 delete iDataElements.At(i); |
|
135 } |
|
136 } |
|
137 |
|
138 |
|
139 EXPORT_C TBool CCmsSignedObject::IsCertificateSetPresent() const |
|
140 { |
|
141 return iIsCertificateSetPresent; |
|
142 } |
|
143 |
|
144 EXPORT_C TBool CCmsSignedObject::IsCertificateRevocationListsPresent() const |
|
145 { |
|
146 return iIsCertificateRevocationListsPresent; |
|
147 } |
|
148 |
|
149 EXPORT_C TInt CCmsSignedObject::Version() const |
|
150 { |
|
151 return iVersion; |
|
152 } |
|
153 |
|
154 EXPORT_C const RPointerArray<CCmsCertificateChoice>& CCmsSignedObject::Certificates() const |
|
155 { |
|
156 return iCertificates; |
|
157 } |
|
158 |
|
159 EXPORT_C const RPointerArray<CX509AlgorithmIdentifier>& CCmsSignedObject::DigestAlgorithms() const |
|
160 { |
|
161 return iDigestAlgorithms; |
|
162 } |
|
163 |
|
164 EXPORT_C const CEncapsulatedContentInfo& CCmsSignedObject::ContentInfo() const |
|
165 { |
|
166 return *iContentInfo; |
|
167 } |
|
168 |
|
169 EXPORT_C const RPointerArray<CCmsSignerInfo>& CCmsSignedObject::SignerInfo() const |
|
170 { |
|
171 return iSignerInfo; |
|
172 } |
|
173 |
|
174 EXPORT_C void CCmsSignedObject::AddCertificateL(const CX509Certificate& aCert) |
|
175 { |
|
176 CmsUtils::AddCertificateL(iCertificates, aCert); |
|
177 } |
|
178 |
|
179 void CCmsSignedObject::AddDigestAlgorithmL(TAlgorithmId aDigestAlgorithm) |
|
180 { |
|
181 CmsUtils::AddAlgorithmIdentifierL(iDigestAlgorithms, aDigestAlgorithm); |
|
182 } |
|
183 |
|
184 EXPORT_C void CCmsSignedObject::AddCertificateL(const TDesC8& aCert, CCmsCertificateChoice::TCertificateType aType) |
|
185 { |
|
186 if (aType==CCmsCertificateChoice::ECertificateAttribute) |
|
187 { |
|
188 iVersion=EVersion_3; |
|
189 } |
|
190 CmsUtils::AddCertificateL(iCertificates, aCert, aType); |
|
191 } |
|
192 |
|
193 void CCmsSignedObject::DecodeSignerInfoL(const TDesC8& aRawData) |
|
194 { |
|
195 CArrayPtr<TASN1DecGeneric>* signerInfo = PKCS7ASN1::DecodeSequenceLC(aRawData); |
|
196 TInt total = signerInfo->Count(); |
|
197 CCmsSignerInfo* signer(NULL); |
|
198 |
|
199 for(TInt item = 0; item < total; item ++) |
|
200 { |
|
201 signer = CCmsSignerInfo::NewL(signerInfo->At(item)->Encoding()); |
|
202 CleanupStack::PushL(signer); |
|
203 User::LeaveIfError(iSignerInfo.Append(signer)); |
|
204 CleanupStack::Pop(signer); |
|
205 } |
|
206 CleanupStack::PopAndDestroy(signerInfo); |
|
207 } |
|
208 |
|
209 void CCmsSignedObject::DecodeEncapsulatedContentInfoL(const TDesC8& aRawData) |
|
210 { |
|
211 iContentInfo = CEncapsulatedContentInfo::NewL(aRawData); |
|
212 } |
|
213 |
|
214 void CCmsSignedObject::ConstructL(const CCmsContentInfo& aContentInfo) |
|
215 { |
|
216 if(aContentInfo.ContentType() != EContentTypeSignedData) |
|
217 { |
|
218 User::Leave(KErrArgument); |
|
219 } |
|
220 |
|
221 TASN1DecGeneric decGen(aContentInfo.ContentData()); |
|
222 decGen.InitL(); |
|
223 |
|
224 if(decGen.Tag() == EASN1Sequence && decGen.Class()==EUniversal) |
|
225 { |
|
226 InitSignedObjectL(decGen.Encoding()); |
|
227 DecodeSignedDataL(*iEncoding); |
|
228 } |
|
229 else |
|
230 { |
|
231 User::Leave(KErrArgument); |
|
232 } |
|
233 } |
|
234 |
|
235 void CCmsSignedObject::ConstructL(TCmsContentInfoType aType, TBool aIsDetached, const TDesC8& aContentData) |
|
236 { |
|
237 if (aContentData==KNullDesC8() && !aIsDetached) |
|
238 { |
|
239 User::Leave(KErrArgument); |
|
240 } |
|
241 iContentInfo=CEncapsulatedContentInfo::NewL(aType, !aIsDetached, aContentData); |
|
242 //For later use to create hash if detached and hash not provided |
|
243 iContentData.Set(aContentData); |
|
244 } |
|
245 |
|
246 CCmsSignerIdentifier* CCmsSignedObject::BuildSignerIdentifierLC(const CX509Certificate& aCert) |
|
247 { |
|
248 CCmsSignerIdentifier* sid(NULL); |
|
249 const CX509CertExtension* certExt = aCert.Extension(KSubjectKeyId); |
|
250 if (certExt) |
|
251 { |
|
252 CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data()); |
|
253 HBufC8* subKeyId=ext->KeyId().AllocL(); |
|
254 CleanupStack::PopAndDestroy(ext); |
|
255 CleanupStack::PushL(subKeyId); |
|
256 sid=CCmsSignerIdentifier::NewL(subKeyId); |
|
257 CleanupStack::Pop(subKeyId); |
|
258 CleanupStack::PushL(sid); |
|
259 iVersion=EVersion_3; |
|
260 } |
|
261 else |
|
262 { |
|
263 CX500DistinguishedName* distinguishedName=CX500DistinguishedName::NewLC(aCert.IssuerName()); |
|
264 CPKCS7IssuerAndSerialNumber* issuerAndSN=CPKCS7IssuerAndSerialNumber::NewL(distinguishedName, aCert.SerialNumber()); |
|
265 CleanupStack::Pop(distinguishedName); |
|
266 CleanupStack::PushL(issuerAndSN); |
|
267 sid=CCmsSignerIdentifier::NewL(issuerAndSN); |
|
268 CleanupStack::Pop(issuerAndSN); |
|
269 CleanupStack::PushL(sid); |
|
270 } |
|
271 return sid; |
|
272 } |
|
273 |
|
274 |
|
275 void CCmsSignedObject::BuildSignerInfoCertListAndAlgoritmListL(TAlgorithmId aDigestAlgorithm, |
|
276 TBool aIsHash, |
|
277 const TDesC8& aValue, |
|
278 const CDSAPrivateKey& aKey, |
|
279 const CX509Certificate& aCert, |
|
280 TBool aAddCertificate) |
|
281 { |
|
282 //build Signer Identifier |
|
283 CCmsSignerIdentifier* sid=BuildSignerIdentifierLC(aCert); |
|
284 |
|
285 //build digest algorithm and signing algorithm |
|
286 CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8()); |
|
287 const CSubjectPublicKeyInfo& publicKeyInfo=aCert.PublicKey(); |
|
288 CX509AlgorithmIdentifier* signingAlg=CX509AlgorithmIdentifier::NewLC(publicKeyInfo.AlgorithmId(), KNullDesC8()); |
|
289 |
|
290 //build signer info |
|
291 CCmsSignerInfo* signerInfo=CCmsSignerInfo::NewL(aValue, |
|
292 aIsHash, |
|
293 aKey, |
|
294 sid, |
|
295 digAlg, |
|
296 signingAlg); |
|
297 CleanupStack::Pop(3, sid); |
|
298 CleanupStack::PushL(signerInfo); |
|
299 //add to the signer info list |
|
300 iSignerInfo.AppendL(signerInfo); |
|
301 CleanupStack::Pop(); |
|
302 |
|
303 //Add the certificate to the list if needed |
|
304 if (aAddCertificate) |
|
305 { |
|
306 AddCertificateL(aCert); |
|
307 } |
|
308 |
|
309 //Add the digest algorithm the list if needed |
|
310 AddDigestAlgorithmL(aDigestAlgorithm); |
|
311 } |
|
312 |
|
313 |
|
314 |
|
315 void CCmsSignedObject::BuildSignerInfoCertListAndAlgoritmListL(TAlgorithmId aDigestAlgorithm, |
|
316 TBool aIsHash, |
|
317 const TDesC8& aValue, |
|
318 const CRSAPrivateKey& aKey, |
|
319 const CX509Certificate& aCert, |
|
320 TBool aAddCertificate) |
|
321 |
|
322 { |
|
323 //build Signer Identifier |
|
324 CCmsSignerIdentifier* sid=BuildSignerIdentifierLC(aCert); |
|
325 |
|
326 //build digest algorithm and signing algorithm |
|
327 CX509AlgorithmIdentifier* digAlg=CX509AlgorithmIdentifier::NewLC(aDigestAlgorithm, KNullDesC8()); |
|
328 const CSubjectPublicKeyInfo& publicKeyInfo=aCert.PublicKey(); |
|
329 CX509AlgorithmIdentifier* signingAlg=CX509AlgorithmIdentifier::NewLC(publicKeyInfo.AlgorithmId(), publicKeyInfo.EncodedParams()); |
|
330 |
|
331 //build signer info |
|
332 CCmsSignerInfo* signerInfo=CCmsSignerInfo::NewL(aValue, |
|
333 aIsHash, |
|
334 aKey, |
|
335 sid, |
|
336 digAlg, |
|
337 signingAlg); |
|
338 CleanupStack::Pop(3, sid); |
|
339 CleanupStack::PushL(signerInfo); |
|
340 //add to the signer info list |
|
341 iSignerInfo.AppendL(signerInfo); |
|
342 CleanupStack::Pop(); |
|
343 |
|
344 //Add the certificate to the list if needed |
|
345 if (aAddCertificate) |
|
346 { |
|
347 AddCertificateL(aCert); |
|
348 } |
|
349 |
|
350 //Add the digest algorithm the list if needed |
|
351 AddDigestAlgorithmL(aDigestAlgorithm); |
|
352 } |
|
353 |
|
354 void CCmsSignedObject::ConstructL(TCmsContentInfoType aType, |
|
355 const TDesC8& aHashValue, |
|
356 TAlgorithmId aDigestAlgorithm, |
|
357 const CDSAPrivateKey& aKey, |
|
358 const CX509Certificate& aCert, |
|
359 TBool aAddCertificate) |
|
360 { |
|
361 //Set the CMS object version to version 3 if the encapsulatedconetent data type is not data |
|
362 if (aType != EContentTypeData) |
|
363 { |
|
364 iVersion=EVersion_3; |
|
365 } |
|
366 |
|
367 //build EncapsulatedContentInfo |
|
368 iContentInfo=CEncapsulatedContentInfo::NewL(aType, EFalse, KNullDesC8()); |
|
369 |
|
370 BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm, |
|
371 ETrue, |
|
372 aHashValue, |
|
373 aKey, |
|
374 aCert, |
|
375 aAddCertificate); |
|
376 |
|
377 } |
|
378 void CCmsSignedObject::ConstructL(TCmsContentInfoType aType, |
|
379 const TDesC8& aHashValue, |
|
380 TAlgorithmId aDigestAlgorithm, |
|
381 const CRSAPrivateKey& aKey, |
|
382 const CX509Certificate& aCert, |
|
383 TBool aAddCertificate) |
|
384 { |
|
385 //Set the CMS object version to version 3 if the encapsulatedconetent data type is not data |
|
386 if (aType != EContentTypeData) |
|
387 { |
|
388 iVersion=EVersion_3; |
|
389 } |
|
390 |
|
391 //build EncapsulatedContentInfo |
|
392 iContentInfo=CEncapsulatedContentInfo::NewL(aType, EFalse, KNullDesC8()); |
|
393 |
|
394 BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm, |
|
395 ETrue, |
|
396 aHashValue, |
|
397 aKey, |
|
398 aCert, |
|
399 aAddCertificate); |
|
400 } |
|
401 |
|
402 |
|
403 EXPORT_C void CCmsSignedObject::SignL(const TDesC8& aHashValue, |
|
404 TAlgorithmId aDigestAlgorithm, |
|
405 const CDSAPrivateKey& aKey, |
|
406 const CX509Certificate& aCert, |
|
407 TBool aAddCertificate) |
|
408 |
|
409 { |
|
410 TBool isHash=(aHashValue!=KNullDesC8())? ETrue:EFalse; |
|
411 if (isHash) |
|
412 { |
|
413 BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm, |
|
414 isHash, |
|
415 aHashValue, |
|
416 aKey, |
|
417 aCert, |
|
418 aAddCertificate); |
|
419 } |
|
420 else |
|
421 { |
|
422 if (iContentData!=KNullDesC8()) |
|
423 { |
|
424 BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm, |
|
425 isHash, |
|
426 iContentData, |
|
427 aKey, |
|
428 aCert, |
|
429 aAddCertificate); |
|
430 } |
|
431 else |
|
432 { |
|
433 //No way to sign if no data content nor its hash. |
|
434 User::Leave(KErrArgument); |
|
435 } |
|
436 } |
|
437 } |
|
438 |
|
439 EXPORT_C void CCmsSignedObject::SignL(const TDesC8& aHashValue, |
|
440 TAlgorithmId aDigestAlgorithm, |
|
441 const CRSAPrivateKey& aKey, |
|
442 const CX509Certificate& aCert, |
|
443 TBool aAddCertificate) |
|
444 { |
|
445 TBool isHash=(aHashValue!=KNullDesC8())? ETrue:EFalse; |
|
446 if (isHash) |
|
447 { |
|
448 BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm, |
|
449 isHash, |
|
450 aHashValue, |
|
451 aKey, |
|
452 aCert, |
|
453 aAddCertificate); |
|
454 } |
|
455 else |
|
456 { |
|
457 if (iContentData!=KNullDesC8()) |
|
458 { |
|
459 BuildSignerInfoCertListAndAlgoritmListL(aDigestAlgorithm, |
|
460 isHash, |
|
461 iContentData, |
|
462 aKey, |
|
463 aCert, |
|
464 aAddCertificate); |
|
465 } |
|
466 else |
|
467 { |
|
468 //No way to sign if no data content nor its hash. |
|
469 User::Leave(KErrArgument); |
|
470 } |
|
471 } |
|
472 } |
|
473 |
|
474 |
|
475 EXPORT_C CASN1EncSequence* CCmsSignedObject::EncodeASN1DERLC() const |
|
476 { |
|
477 // the root sequence contains the signed object |
|
478 CASN1EncSequence* root = CASN1EncSequence::NewLC(); |
|
479 |
|
480 // Encode version |
|
481 CASN1EncInt* version=CASN1EncInt::NewLC(iVersion); |
|
482 root->AddAndPopChildL(version); |
|
483 |
|
484 // Encode Algorithm |
|
485 CASN1EncBase* algorithm=EncodeAlgorithmsLC(); |
|
486 root->AddAndPopChildL(algorithm); |
|
487 |
|
488 |
|
489 // Encode EncapsulatedContentInfo |
|
490 CASN1EncSequence* contentInfo=iContentInfo->EncodeASN1DERLC(); |
|
491 root->AddAndPopChildL(contentInfo); |
|
492 |
|
493 // Encode option fields certificates SET |
|
494 CASN1EncBase* cert=EncodeCertificatesLC(); |
|
495 if (cert) |
|
496 { |
|
497 root->AddAndPopChildL(cert); |
|
498 } |
|
499 |
|
500 // Encode signerinfo |
|
501 CASN1EncBase* signerInfo=EncodeSignerInfoLC(); |
|
502 root->AddAndPopChildL(signerInfo); |
|
503 |
|
504 return root; |
|
505 } |
|
506 |
|
507 |
|
508 CASN1EncBase* CCmsSignedObject::EncodeCertificatesLC() const |
|
509 { |
|
510 return CmsUtils::EncodeCertificatesLC(iCertificates); |
|
511 } |
|
512 |
|
513 CASN1EncBase* CCmsSignedObject::EncodeAlgorithmsLC() const |
|
514 { |
|
515 return CmsUtils::EncodeDigestAlgorithmsLC(iDigestAlgorithms); |
|
516 } |
|
517 |
|
518 CASN1EncBase* CCmsSignedObject::EncodeSignerInfoLC() const |
|
519 { |
|
520 CASN1EncSet* signerInfoSet = CASN1EncSet::NewLC(); |
|
521 TInt count=iSignerInfo.Count(); |
|
522 |
|
523 for (TInt i=0;i<count;i++) |
|
524 { |
|
525 CASN1EncSequence* signerInfo=iSignerInfo[i]->EncodeASN1DERLC(); |
|
526 signerInfoSet->AddAndPopChildL(signerInfo); |
|
527 } |
|
528 return signerInfoSet; |
|
529 } |
|
530 |
|
531 EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, HBufC8*& aCertChainEncoding) |
|
532 { |
|
533 TInt certCount = iCertificates.Count(); |
|
534 TInt endEntityPos = -1; |
|
535 TInt endEncodingSize = 0; |
|
536 TPtrC8 endEntityEncoding; |
|
537 TInt cert; |
|
538 TBool valid = EFalse; |
|
539 |
|
540 const CCmsSignerIdentifier& signerId = aSignerInfo.SignerIdentifier(); |
|
541 |
|
542 // looks for end entity certificate |
|
543 for(cert = 0; cert < certCount; cert++) |
|
544 { |
|
545 if (iCertificates[cert]->CertificateType()==CCmsCertificateChoice::ECertificateX509) |
|
546 { |
|
547 const CX509Certificate& certificate = iCertificates[cert]->Certificate(); |
|
548 |
|
549 endEncodingSize+= certificate.Encoding().Length(); |
|
550 |
|
551 if(endEntityPos == -1) |
|
552 { |
|
553 if (signerId.SignerIdentifierType()==CCmsSignerIdentifier::EIssuerAndSerialNumber) |
|
554 { |
|
555 if (certificate.IssuerName().ExactMatchL(signerId.IssuerAndSerialNumber()->IssuerName())) |
|
556 { |
|
557 RInteger sn1=RInteger::NewL(certificate.SerialNumber()); |
|
558 CleanupClosePushL(sn1); |
|
559 RInteger sn2=RInteger::NewL(signerId.IssuerAndSerialNumber()->SerialNumber()); |
|
560 CleanupClosePushL(sn2); |
|
561 if (sn1==sn2) |
|
562 { |
|
563 endEntityPos = cert; |
|
564 endEntityEncoding.Set(certificate.Encoding()); |
|
565 valid = ValidateSignatureL(aSignerInfo, certificate); |
|
566 } |
|
567 CleanupStack::PopAndDestroy(2, &sn1);//sn2, sn1 |
|
568 } |
|
569 } |
|
570 else |
|
571 { |
|
572 const CX509CertExtension* certExt = certificate.Extension(KSubjectKeyId); |
|
573 if (certExt) |
|
574 { |
|
575 CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data()); |
|
576 if (signerId.SubjectKeyIdentifier().Compare(ext->KeyId())==0) |
|
577 { |
|
578 endEntityPos = cert; |
|
579 endEntityEncoding.Set(certificate.Encoding()); |
|
580 valid = ValidateSignatureL(aSignerInfo, certificate); |
|
581 } |
|
582 CleanupStack::PopAndDestroy(ext); |
|
583 } |
|
584 } |
|
585 } |
|
586 } |
|
587 } |
|
588 |
|
589 // checks if end entity was found |
|
590 if(endEntityPos != -1) |
|
591 { |
|
592 // builds the cert chain encoding by putting the end entity first then all remaining |
|
593 // certs |
|
594 aCertChainEncoding = HBufC8::NewLC(endEncodingSize); |
|
595 TPtr8 encodingPtr(aCertChainEncoding->Des()); |
|
596 encodingPtr.Copy(endEntityEncoding); |
|
597 for(cert = 0; cert < certCount; cert++) |
|
598 { |
|
599 if (iCertificates[cert]->CertificateType()==CCmsCertificateChoice::ECertificateX509) |
|
600 { |
|
601 const CX509Certificate& certificate = iCertificates[cert]->Certificate(); |
|
602 if(cert != endEntityPos) |
|
603 { |
|
604 encodingPtr.Append(certificate.Encoding()); |
|
605 } |
|
606 } |
|
607 } |
|
608 } |
|
609 else |
|
610 { |
|
611 User::Leave(KErrNotFound); |
|
612 } |
|
613 return valid; |
|
614 } |
|
615 |
|
616 |
|
617 EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, const RPointerArray<CX509Certificate>& aCertificates, HBufC8*& aCertChainEncoding) |
|
618 { |
|
619 TInt certCount = aCertificates.Count(); |
|
620 TInt endEntityPos = -1; |
|
621 TInt endEncodingSize = 0; |
|
622 TPtrC8 endEntityEncoding; |
|
623 TInt cert; |
|
624 TBool valid = EFalse; |
|
625 const CCmsSignerIdentifier& signerId = aSignerInfo.SignerIdentifier(); |
|
626 |
|
627 // looks for end entity certificate |
|
628 for(cert = 0; cert < certCount; cert++) |
|
629 { |
|
630 const CX509Certificate& certificate = *aCertificates[cert]; |
|
631 endEncodingSize+= certificate.Encoding().Length(); |
|
632 if(endEntityPos == -1) |
|
633 { |
|
634 if (signerId.SignerIdentifierType()==CCmsSignerIdentifier::EIssuerAndSerialNumber) |
|
635 { |
|
636 if (certificate.IssuerName().ExactMatchL(signerId.IssuerAndSerialNumber()->IssuerName())) |
|
637 { |
|
638 RInteger sn1=RInteger::NewL(certificate.SerialNumber()); |
|
639 CleanupClosePushL(sn1); |
|
640 RInteger sn2=RInteger::NewL(signerId.IssuerAndSerialNumber()->SerialNumber()); |
|
641 CleanupClosePushL(sn2); |
|
642 if (sn1==sn2) |
|
643 { |
|
644 endEntityPos = cert; |
|
645 endEntityEncoding.Set(certificate.Encoding()); |
|
646 valid = ValidateSignatureL(aSignerInfo, certificate); |
|
647 } |
|
648 CleanupStack::PopAndDestroy(2, &sn1);//sn2, sn1 |
|
649 } |
|
650 } |
|
651 else |
|
652 { |
|
653 const CX509CertExtension* certExt = certificate.Extension(KSubjectKeyId); |
|
654 if (certExt) |
|
655 { |
|
656 CX509SubjectKeyIdExt* ext=CX509SubjectKeyIdExt::NewLC(certExt->Data()); |
|
657 if (signerId.SubjectKeyIdentifier().Compare(ext->KeyId())==0) |
|
658 { |
|
659 endEntityPos = cert; |
|
660 endEntityEncoding.Set(certificate.Encoding()); |
|
661 valid = ValidateSignatureL(aSignerInfo, certificate); |
|
662 } |
|
663 CleanupStack::PopAndDestroy(ext); |
|
664 } |
|
665 } |
|
666 } |
|
667 } |
|
668 |
|
669 // checks if end entity was found |
|
670 if(endEntityPos != -1) |
|
671 { |
|
672 // builds the cert chain encoding by putting the end entity first then all remaining |
|
673 // certs |
|
674 aCertChainEncoding = HBufC8::NewLC(endEncodingSize); |
|
675 TPtr8 encodingPtr(aCertChainEncoding->Des()); |
|
676 encodingPtr.Copy(endEntityEncoding); |
|
677 for(cert = 0; cert < certCount; cert++) |
|
678 { |
|
679 const CX509Certificate& certificate = *aCertificates[cert]; |
|
680 |
|
681 if(cert != endEntityPos) |
|
682 { |
|
683 encodingPtr.Append(certificate.Encoding()); |
|
684 } |
|
685 } |
|
686 } |
|
687 else |
|
688 { |
|
689 User::Leave(KErrNotFound); |
|
690 } |
|
691 |
|
692 return valid; |
|
693 } |
|
694 |
|
695 |
|
696 EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, HBufC8*& aCertChainEncoding, TBool aIsHash, const TDesC8& aContentDataOrHash) |
|
697 { |
|
698 if (aIsHash) |
|
699 { |
|
700 SetHash(aContentDataOrHash); |
|
701 } |
|
702 else |
|
703 { |
|
704 SetContentData(aContentDataOrHash); |
|
705 } |
|
706 return ValidateSignerLC(aSignerInfo, aCertChainEncoding); |
|
707 } |
|
708 |
|
709 EXPORT_C TBool CCmsSignedObject::ValidateSignerLC(const CCmsSignerInfo& aSignerInfo, const RPointerArray<CX509Certificate>& aCertificates, HBufC8*& aCertChainEncoding, TBool aIsHash, const TDesC8& aContentDataOrHash) |
|
710 { |
|
711 if (aIsHash) |
|
712 { |
|
713 SetHash(aContentDataOrHash); |
|
714 } |
|
715 else |
|
716 { |
|
717 SetContentData(aContentDataOrHash); |
|
718 } |
|
719 return ValidateSignerLC(aSignerInfo, aCertificates, aCertChainEncoding); |
|
720 } |
|
721 |
|
722 TBool CCmsSignedObject::ValidateSignatureL(const CCmsSignerInfo& aSignerInfo, const CX509Certificate& aEndEntityCert) |
|
723 { |
|
724 delete iSigningAlgorithm; |
|
725 iSigningAlgorithm = NULL; |
|
726 iSigningAlgorithm = CX509SigningAlgorithmIdentifier::NewL(aSignerInfo.SignatureAlgorithm(), aSignerInfo.DigestAlgorithm()); |
|
727 |
|
728 delete iSignature; |
|
729 iSignature = NULL; |
|
730 iSignature = aSignerInfo.SignatureValue().AllocL(); |
|
731 |
|
732 if (aSignerInfo.SignatureAlgorithm().Algorithm()==EDSA) |
|
733 { |
|
734 delete iParameters; |
|
735 iParameters = NULL; |
|
736 CDSAParameters* theDSAParams = iKeyFactory->DSAParametersL(aEndEntityCert.PublicKey().EncodedParams()); |
|
737 CleanupStack::PushL(theDSAParams); |
|
738 CSigningKeyParameters* params = CSigningKeyParameters::NewLC(); |
|
739 params->SetDSAParamsL(*theDSAParams); |
|
740 SetParametersL(*params); |
|
741 CleanupStack::PopAndDestroy(2, theDSAParams); |
|
742 } |
|
743 |
|
744 if (iContentInfo->IsContentDataPresent() || iContentData != KNullDesC8) |
|
745 { |
|
746 return VerifySignatureL(aEndEntityCert.PublicKey().KeyData()); |
|
747 } |
|
748 else if (iHash!=KNullDesC8) |
|
749 { |
|
750 return VerifySignatureL(aEndEntityCert.PublicKey().KeyData(), iHash); |
|
751 } |
|
752 else |
|
753 { |
|
754 User::Leave(KErrArgument); |
|
755 return EFalse; |
|
756 } |
|
757 |
|
758 } |
|
759 |
|
760 void CCmsSignedObject::InitSignedObjectL(const TDesC8& aRawData) |
|
761 { |
|
762 // Populate CSignedObject data members |
|
763 iKeyFactory = new (ELeave) TX509KeyFactory; |
|
764 iEncoding = aRawData.AllocL(); |
|
765 |
|
766 CSHA1* hash = CSHA1::NewL(); |
|
767 CleanupStack::PushL(hash); |
|
768 iFingerprint = hash->Hash(Encoding()).AllocL(); |
|
769 CleanupStack::PopAndDestroy(hash); |
|
770 } |
|
771 |
|
772 void CCmsSignedObject::DecodeSignedDataL(const TDesC8& aRawData) |
|
773 { |
|
774 CArrayPtr<TASN1DecGeneric>* signedData = PKCS7ASN1::DecodeSequenceLC(aRawData, KCmsMinSignedDataElements, KCmsMaxSignedDataElements); |
|
775 TInt totalItems = signedData->Count(); |
|
776 TASN1DecInteger decInt; |
|
777 |
|
778 // decodes version |
|
779 iDataElements.At(EVersionNumber) = new(ELeave) TPtrC8(signedData->At(0)->GetContentDER()); |
|
780 iVersion = decInt.DecodeDERShortL(*signedData->At(0)); |
|
781 if (iVersion>4 || iVersion<0) |
|
782 { |
|
783 User::Leave(KErrArgument); |
|
784 } |
|
785 // decodes algorithms |
|
786 iDataElements.At(EDigestAlgorithms) = new(ELeave) TPtrC8(signedData->At(1)->GetContentDER()); |
|
787 DecodeDigestAlgorithmsL(signedData->At(1)->Encoding()); |
|
788 // decodes contentinfo |
|
789 iDataElements.At(EEncapsulatedContentInfo) = new(ELeave) TPtrC8(signedData->At(2)->GetContentDER()); |
|
790 DecodeEncapsulatedContentInfoL(signedData->At(2)->Encoding()); |
|
791 |
|
792 // Checks for optional fields |
|
793 TInt pos = 3; // Skip first non-optional fields |
|
794 do |
|
795 { |
|
796 const TASN1DecGeneric& currentItem = *signedData->At(pos); |
|
797 switch(currentItem.Tag()) |
|
798 { |
|
799 case KSignedDataCertificates: |
|
800 { |
|
801 if (currentItem.Class()!=EContextSpecific) |
|
802 { |
|
803 User::Leave(KErrArgument); |
|
804 } |
|
805 iIsCertificateSetPresent=ETrue; |
|
806 iDataElements.At(ECertificates) = new(ELeave) TPtrC8(currentItem.GetContentDER()); |
|
807 DecodeCertificatesL(currentItem.Encoding()); |
|
808 break; |
|
809 } |
|
810 case KSignedDataRevocationLists: |
|
811 { |
|
812 if (currentItem.Class()!=EContextSpecific) |
|
813 { |
|
814 User::Leave(KErrArgument); |
|
815 } |
|
816 iIsCertificateRevocationListsPresent=ETrue; |
|
817 iDataElements.At(ERevocationLists) = new(ELeave) TPtrC8(currentItem.GetContentDER()); |
|
818 DecodeRevocationListsL(currentItem.Encoding()); |
|
819 break; |
|
820 } |
|
821 default: |
|
822 { |
|
823 //Optional field with wrong tag and class |
|
824 if (pos<totalItems-1) |
|
825 { |
|
826 User::Leave(KErrArgument); |
|
827 } |
|
828 // else Non-optional field |
|
829 } |
|
830 } |
|
831 pos++; |
|
832 } |
|
833 while(pos < totalItems); |
|
834 |
|
835 iDataElements.At(ESignedInfo) = new(ELeave) TPtrC8(signedData->At(totalItems-1)->GetContentDER()); |
|
836 DecodeSignerInfoL(signedData->At(totalItems-1)->Encoding()); |
|
837 |
|
838 CleanupStack::PopAndDestroy(signedData); |
|
839 } |
|
840 |
|
841 void CCmsSignedObject::DecodeDigestAlgorithmsL(const TDesC8& aRawData) |
|
842 { |
|
843 CmsUtils::DecodeDigestAlgorithmsL(iDigestAlgorithms, aRawData); |
|
844 } |
|
845 |
|
846 void CCmsSignedObject::DecodeCertificatesL(const TDesC8& aRawData) |
|
847 { |
|
848 CmsUtils::DecodeCertificatesL(iCertificates, aRawData); |
|
849 } |
|
850 |
|
851 void CCmsSignedObject::DecodeRevocationListsL(const TDesC8& /*aRawData*/) |
|
852 { |
|
853 } |
|
854 |
|
855 EXPORT_C const TPtrC8 CCmsSignedObject::SignedDataL() const |
|
856 { |
|
857 if (iContentInfo->IsContentDataPresent()) |
|
858 { |
|
859 return iContentInfo->ContentData(); |
|
860 } |
|
861 else |
|
862 { |
|
863 if (iContentData!=KNullDesC8) |
|
864 { |
|
865 return iContentData; |
|
866 } |
|
867 else |
|
868 { |
|
869 User::Leave(KErrArgument); |
|
870 } |
|
871 } |
|
872 return KNullDesC8(); |
|
873 } |
|
874 |
|
875 EXPORT_C void CCmsSignedObject::InternalizeL(RReadStream& /*aStream*/) |
|
876 { |
|
877 User::Leave(KErrNotSupported); |
|
878 } |
|
879 |
|
880 EXPORT_C const TPtrC8* CCmsSignedObject::DataElementEncoding(const TUint aIndex) const |
|
881 { |
|
882 return iDataElements.At(aIndex); |
|
883 } |
|
884 |
|
885 void CCmsSignedObject::SetContentData(const TDesC8& aContentData) |
|
886 { |
|
887 iContentData.Set(aContentData); |
|
888 } |
|
889 |
|
890 void CCmsSignedObject::SetHash(const TDesC8& aHash) |
|
891 { |
|
892 iHash.Set(aHash); |
|
893 } |
|
894 |
|
895 |
|
896 |