|
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 "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 * CPKIMapper class holds the information required to map API set to |
|
16 * use the storage model which is not native for that API. |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 #include <x500dn.h> |
|
22 #include <x509cert.h> |
|
23 |
|
24 #include "PKIMapper.h" |
|
25 #include "pkcs10.h" |
|
26 #include "log_r6.h" |
|
27 #include "pkiserviceassert.h" |
|
28 |
|
29 |
|
30 CMapDescriptor::CMapDescriptor(TSecurityObjectDescriptor &aDesc) |
|
31 { |
|
32 this->iSubjectKeyId = aDesc.iSubjectKeyId; |
|
33 this->iOwnerType = aDesc.iOwnerType; |
|
34 this->iKeySize = aDesc.iKeySize; |
|
35 this->iKeyAlgorithm = aDesc.iKeyAlgorithm; |
|
36 this->iIsDeletable = aDesc.iIsDeletable; |
|
37 } |
|
38 |
|
39 CMapDescriptor& CMapDescriptor::operator=(CMapDescriptor& aMapDesc) |
|
40 { |
|
41 delete this->iTrustedAuthority; |
|
42 this->iTrustedAuthority = NULL; |
|
43 if(aMapDesc.iTrustedAuthority != NULL) |
|
44 { |
|
45 this->iTrustedAuthority = aMapDesc.iTrustedAuthority->Des().AllocL(); // Cert TrustedAuthority |
|
46 } |
|
47 delete this->iIdentitySubjectName; |
|
48 this->iIdentitySubjectName = NULL; |
|
49 if(aMapDesc.iIdentitySubjectName != NULL) |
|
50 { |
|
51 this->iIdentitySubjectName = aMapDesc.iIdentitySubjectName->Des().AllocL(); // Identity subject name |
|
52 } |
|
53 delete this->iIdentityRfc822Name; |
|
54 this->iIdentityRfc822Name = NULL; |
|
55 if(aMapDesc.iIdentityRfc822Name != NULL) |
|
56 { |
|
57 this->iIdentityRfc822Name = aMapDesc.iIdentityRfc822Name->Des().AllocL(); // Identity subjectAltName rfc822 name |
|
58 } |
|
59 delete this->iSerialNumber; |
|
60 this->iSerialNumber = NULL; |
|
61 if(aMapDesc.iSerialNumber != NULL) |
|
62 { |
|
63 this->iSerialNumber = aMapDesc.iSerialNumber->Des().AllocL(); // Serialnumber |
|
64 } |
|
65 |
|
66 this->iSubjectKeyId = aMapDesc.iSubjectKeyId; // SHA1 hash of the corresponding private key |
|
67 this->iOwnerType = aMapDesc.iOwnerType; // User, CA or peer. If user certificate, at least key usage must be set |
|
68 this->iKeyUsageDer = aMapDesc.iKeyUsageDer; // Der format flags |
|
69 this->iObjectName = aMapDesc.iObjectName; |
|
70 this->iKeySize = aMapDesc.iKeySize; // Key size |
|
71 this->iKeyAlgorithm = aMapDesc.iKeyAlgorithm; // RSA, DSA |
|
72 this->iStartTime = aMapDesc.iStartTime; |
|
73 this->iEndTime = aMapDesc.iEndTime; |
|
74 this->iIsDeletable = aMapDesc.iIsDeletable; |
|
75 TInt i; |
|
76 for(i=0;i<aMapDesc.iApplUids.Count();i++) |
|
77 { |
|
78 this->iApplUids.Append(aMapDesc.iApplUids[i]); |
|
79 } |
|
80 |
|
81 this->iCertStoreType = aMapDesc.iCertStoreType; |
|
82 return *this; |
|
83 } |
|
84 |
|
85 |
|
86 TBool CMapDescriptor::IsMatchingL(TSecurityObjectDescriptor &aDesc, |
|
87 const TBool aInfoOnly, |
|
88 TPkiServiceStoreType aCertStoreType) const |
|
89 { |
|
90 TBool match(EFalse); |
|
91 |
|
92 LOG(Log::Printf(_L("Matching"))); |
|
93 LOG_1(" Pure informational: %d", aInfoOnly); |
|
94 |
|
95 LOG(Log::Printf(_L("Matching: certificate %S"), &iObjectName)); |
|
96 for(;;) |
|
97 { |
|
98 if (aDesc.iOwnerType != EPKICACertificate && |
|
99 aCertStoreType != EPkiStoreTypeAny) |
|
100 { |
|
101 if (iCertStoreType != aCertStoreType) |
|
102 { |
|
103 LOG(Log::Printf(_L(" Store doesn't match, aborting"))); |
|
104 match = EFalse; |
|
105 break; |
|
106 } |
|
107 } |
|
108 else |
|
109 { |
|
110 LOG(Log::Printf(_L("Skipping store check, not relevant"))); |
|
111 } |
|
112 |
|
113 |
|
114 if (aDesc.iSubjectKeyIdUsed) |
|
115 { |
|
116 if(iSubjectKeyId == aDesc.iSubjectKeyId) |
|
117 { |
|
118 match = ETrue; |
|
119 } |
|
120 else |
|
121 { |
|
122 match = EFalse; |
|
123 break; |
|
124 } |
|
125 } |
|
126 |
|
127 if(aDesc.iTrustedAuthorityUsed) |
|
128 { |
|
129 if(iTrustedAuthority == NULL) |
|
130 { |
|
131 match = EFalse; |
|
132 break; |
|
133 } |
|
134 else |
|
135 { |
|
136 CX500DistinguishedName* dnSuffix1 = CX500DistinguishedName::NewLC(*iTrustedAuthority); |
|
137 CX500DistinguishedName* dnSuffix2; |
|
138 TInt popCount = 3; |
|
139 |
|
140 // ASN1 or plain text |
|
141 if((aDesc.iTrustedAuthority[0] != 0x30) |
|
142 || ((aDesc.iTrustedAuthority[1] != 0x81) |
|
143 && (aDesc.iTrustedAuthority[1] != 0x82) |
|
144 && ((aDesc.iTrustedAuthority[1] + 2) != aDesc.iTrustedAuthority.Length()))) |
|
145 { |
|
146 HBufC8* name2Der; |
|
147 CPkcs10Req::BuildDistinguishedNameDerFromTextL(name2Der, |
|
148 aDesc.iTrustedAuthority, |
|
149 EFalse, KNullDesC8); |
|
150 CleanupStack::PushL(name2Der); |
|
151 |
|
152 dnSuffix2 = CX500DistinguishedName::NewLC(*name2Der); |
|
153 } |
|
154 else |
|
155 { |
|
156 dnSuffix2 = CX500DistinguishedName::NewLC(aDesc.iTrustedAuthority); |
|
157 popCount = 2; |
|
158 } |
|
159 |
|
160 |
|
161 if(PkiUtil::MatchL(*dnSuffix1, *dnSuffix2)) |
|
162 { |
|
163 match = ETrue; |
|
164 CleanupStack::PopAndDestroy(popCount); |
|
165 } |
|
166 else |
|
167 { |
|
168 match = EFalse; |
|
169 CleanupStack::PopAndDestroy(popCount); |
|
170 break; |
|
171 } |
|
172 } |
|
173 } |
|
174 if(aDesc.iOwnerTypeUsed) |
|
175 { |
|
176 if(iOwnerType == aDesc.iOwnerType) |
|
177 { |
|
178 match = ETrue; |
|
179 } |
|
180 else |
|
181 { |
|
182 match = EFalse; |
|
183 break; |
|
184 } |
|
185 } |
|
186 if(aDesc.iSerialNumberUsed) |
|
187 { |
|
188 if ((iSerialNumber != NULL) && ((*iSerialNumber).Compare(aDesc.iSerialNumber) == 0)) |
|
189 { |
|
190 match = ETrue; |
|
191 } |
|
192 else |
|
193 { |
|
194 match = EFalse; |
|
195 break; |
|
196 } |
|
197 } |
|
198 |
|
199 if(aDesc.iIdentitySubjectNameUsed) |
|
200 { |
|
201 if(iIdentitySubjectName == NULL) |
|
202 { |
|
203 match = EFalse; |
|
204 break; |
|
205 } |
|
206 else |
|
207 { |
|
208 CX500DistinguishedName* dnSuffix1 = CX500DistinguishedName::NewLC(*iIdentitySubjectName); |
|
209 CX500DistinguishedName* dnSuffix2; |
|
210 TInt popCount = 3; |
|
211 // ASN1 or plain text |
|
212 if((aDesc.iIdentitySubjectName[0] != 0x30) |
|
213 || ((aDesc.iIdentitySubjectName[1] != 0x81) |
|
214 && (aDesc.iIdentitySubjectName[1] != 0x82) |
|
215 && ((aDesc.iIdentitySubjectName[1] + 2) != aDesc.iIdentitySubjectName.Length()))) |
|
216 { |
|
217 HBufC8* name2Der; |
|
218 CPkcs10Req::BuildDistinguishedNameDerFromTextL(name2Der, |
|
219 aDesc.iIdentitySubjectName, |
|
220 EFalse, KNullDesC8); |
|
221 CleanupStack::PushL(name2Der); |
|
222 |
|
223 dnSuffix2 = CX500DistinguishedName::NewLC(*name2Der); |
|
224 } |
|
225 else |
|
226 { |
|
227 dnSuffix2 = CX500DistinguishedName::NewLC(aDesc.iIdentitySubjectName); |
|
228 popCount = 2; |
|
229 } |
|
230 |
|
231 if(PkiUtil::MatchL(*dnSuffix1, *dnSuffix2)) |
|
232 { |
|
233 CleanupStack::PopAndDestroy(popCount); |
|
234 match = ETrue; |
|
235 } |
|
236 else |
|
237 { |
|
238 CleanupStack::PopAndDestroy(popCount); |
|
239 match = EFalse; |
|
240 break; |
|
241 } |
|
242 } |
|
243 } |
|
244 |
|
245 if(aDesc.iIdentityRfc822NameUsed) |
|
246 { |
|
247 if(iIdentityRfc822Name == NULL) |
|
248 { |
|
249 match = EFalse; |
|
250 break; |
|
251 } |
|
252 else |
|
253 { |
|
254 TInt bytes = aDesc.iIdentityRfc822Name.Length(); |
|
255 TPtrC8 tail = (*iIdentityRfc822Name).Right(bytes); |
|
256 if (tail.CompareF(aDesc.iIdentityRfc822Name) == 0) |
|
257 { |
|
258 match = ETrue; |
|
259 } |
|
260 else |
|
261 { |
|
262 match = EFalse; |
|
263 break; |
|
264 } |
|
265 } |
|
266 } |
|
267 |
|
268 if(aDesc.iKeyUsageUsed) |
|
269 { |
|
270 CX509KeyUsageExt* tempUsage = NULL; |
|
271 if(iKeyUsageDer.Length() != 0) |
|
272 { |
|
273 tempUsage = CX509KeyUsageExt::NewL(iKeyUsageDer); |
|
274 } |
|
275 if((tempUsage == NULL) || tempUsage->IsSet(aDesc.iKeyUsage)) |
|
276 { |
|
277 delete tempUsage; |
|
278 match = ETrue; |
|
279 } |
|
280 else |
|
281 { |
|
282 delete tempUsage; |
|
283 match = EFalse; |
|
284 break; |
|
285 } |
|
286 } |
|
287 |
|
288 if(aDesc.iKeySizeUsed) |
|
289 { |
|
290 if(iKeySize == aDesc.iKeySize) |
|
291 { |
|
292 match = ETrue; |
|
293 } |
|
294 else |
|
295 { |
|
296 match = EFalse; |
|
297 break; |
|
298 } |
|
299 } |
|
300 |
|
301 if (match && !aInfoOnly) |
|
302 { |
|
303 TValidity val = CPKIMapper::CertValidity(iStartTime, iEndTime); |
|
304 // Treat future certificates as valid |
|
305 if((val == EValid) || (val == ENotValidYet)) |
|
306 { |
|
307 match = ETrue; |
|
308 } |
|
309 else |
|
310 { |
|
311 LOG_("Matching: Expired, and not an informational request"); |
|
312 match = EFalse; |
|
313 break; |
|
314 } |
|
315 } |
|
316 |
|
317 break; |
|
318 } |
|
319 |
|
320 return match; |
|
321 } |
|
322 |
|
323 TBool CMapDescriptor::IsEqual(CMapDescriptor &aDesc) |
|
324 { |
|
325 TBool match = EFalse; |
|
326 |
|
327 for(;;) |
|
328 { |
|
329 if((iTrustedAuthority != NULL) && (aDesc.iTrustedAuthority != NULL) && (iTrustedAuthority->Des().Compare(*aDesc.iTrustedAuthority) == 0)) |
|
330 { |
|
331 match = ETrue; |
|
332 } |
|
333 else |
|
334 { |
|
335 match = EFalse; |
|
336 break; |
|
337 } |
|
338 |
|
339 if((iSerialNumber != NULL) && (aDesc.iSerialNumber != NULL) && (iSerialNumber->Des().Compare(*aDesc.iSerialNumber) == 0)) |
|
340 { |
|
341 match = ETrue; |
|
342 } |
|
343 else |
|
344 { |
|
345 match = EFalse; |
|
346 break; |
|
347 } |
|
348 |
|
349 break; |
|
350 } |
|
351 |
|
352 return match; |
|
353 } |
|
354 |
|
355 |
|
356 void CMapDescriptor::SetCertStoreType(TPkiServiceStoreType aCertStoreType) |
|
357 { |
|
358 iCertStoreType = aCertStoreType; |
|
359 } |
|
360 |
|
361 CPKIMapper* CPKIMapper::NewL() |
|
362 { |
|
363 CPKIMapper* self = new (ELeave) CPKIMapper(); |
|
364 CleanupStack::PushL(self); |
|
365 self->ConstructL(); |
|
366 CleanupStack::Pop(self); |
|
367 return self; |
|
368 } |
|
369 |
|
370 CPKIMapper::~CPKIMapper() |
|
371 { |
|
372 if ( iMapping ) |
|
373 { |
|
374 iMapping->ResetAndDestroy(); |
|
375 delete iMapping; |
|
376 } |
|
377 } |
|
378 |
|
379 |
|
380 CPKIMapper::CPKIMapper() |
|
381 { |
|
382 } |
|
383 |
|
384 void CPKIMapper::ConstructL() |
|
385 { |
|
386 LOG_("CPKIMapper::ConstructL"); |
|
387 // Allocate mapping vector. Approx granularity 20 |
|
388 iMapping = new (ELeave) RPointerArray<CMapDescriptor>(20); |
|
389 } |
|
390 |
|
391 void CPKIMapper::SetCacheCreated() |
|
392 { |
|
393 iCacheCreated = ETrue; |
|
394 } |
|
395 TBool CPKIMapper::CacheCreated() |
|
396 { |
|
397 return iCacheCreated; |
|
398 } |
|
399 |
|
400 TInt CPKIMapper::AddMapping(CMapDescriptor& aMap) |
|
401 { |
|
402 // Insert as first element, so that newest object will be found first |
|
403 return iMapping->Insert(&aMap, 0); |
|
404 } |
|
405 |
|
406 void CPKIMapper::LogMap(CMapDescriptor &aDescriptor) const |
|
407 { |
|
408 TInt len = aDescriptor.iSubjectKeyId.Length(); |
|
409 LOG(Log::Printf(_L("====CertificateObject====\n"))); |
|
410 LOG(Log::Printf(_L("ObjectName: %S\n"), &(aDescriptor.iObjectName))); |
|
411 LOG(Log::Printf(_L("KeyId:"))); |
|
412 LOG(Log::HexDump(NULL, NULL, aDescriptor.iSubjectKeyId.Ptr(), len)); |
|
413 } |
|
414 |
|
415 |
|
416 void CPKIMapper::DeleteMapping(TInt aIndex) |
|
417 { |
|
418 // Delete mapping at index |
|
419 LOG(Log::Printf(_L("Delete mapping entry"))); |
|
420 LogMap(*(*iMapping)[aIndex]); |
|
421 delete (*iMapping)[aIndex]; |
|
422 iMapping->Remove(aIndex); |
|
423 iMapping->Compress(); |
|
424 } |
|
425 |
|
426 TInt CPKIMapper::DeleteMapping(CMapDescriptor &aDesc) |
|
427 { |
|
428 TInt status(KErrNotFound); |
|
429 |
|
430 for(TInt i(0); i < iMapping->Count(); i++) |
|
431 { |
|
432 if((*iMapping)[i]->IsEqual(aDesc)) |
|
433 { |
|
434 DeleteMapping(i); |
|
435 status = KErrNone; |
|
436 break; |
|
437 } |
|
438 } |
|
439 return status; |
|
440 } |
|
441 |
|
442 TInt CPKIMapper::CertCount() |
|
443 { |
|
444 TInt count(0); |
|
445 |
|
446 for(TInt i(0); i < iMapping->Count(); i++) |
|
447 { |
|
448 CMapDescriptor* mapping = (*iMapping)[i]; |
|
449 count++; |
|
450 if (CertValidity(mapping->iStartTime, mapping->iEndTime) == EExpired) |
|
451 { |
|
452 // do not count expider certificates |
|
453 count--; |
|
454 } |
|
455 } |
|
456 iCount = count; |
|
457 return count; |
|
458 } |
|
459 |
|
460 TInt CPKIMapper::ApplicableCertCount(const RArray<TUid>& aUidArray) |
|
461 { |
|
462 TInt count(0); |
|
463 TBool uidMatch(EFalse); |
|
464 |
|
465 for(TInt i(0); i < iMapping->Count(); i++) |
|
466 { |
|
467 CMapDescriptor* mapping = (*iMapping)[i]; |
|
468 if(mapping->iOwnerType == EPKICACertificate) |
|
469 { |
|
470 if(CertValidity(mapping->iStartTime, mapping->iEndTime) != EExpired) |
|
471 { |
|
472 uidMatch = EFalse; |
|
473 for(TInt j = 0; j < mapping->iApplUids.Count(); j++) |
|
474 { |
|
475 for(TInt k = 0; k < aUidArray.Count(); k++) |
|
476 { |
|
477 if(mapping->iApplUids[j].iUid == aUidArray[k].iUid) |
|
478 { |
|
479 uidMatch = ETrue; |
|
480 break; |
|
481 } |
|
482 } |
|
483 if(uidMatch) |
|
484 { |
|
485 count++; |
|
486 break; |
|
487 } |
|
488 } |
|
489 } |
|
490 } |
|
491 } |
|
492 iCount = count; |
|
493 return count; |
|
494 } |
|
495 |
|
496 |
|
497 TInt CPKIMapper::GetCertListL(const RMessage2 &aMessage, TPkiServiceStoreType aStoreType, |
|
498 TBool aDescUsed) |
|
499 { |
|
500 TInt pos = 0; |
|
501 TInt iLast = 0; |
|
502 TInt iFirst = 0; |
|
503 |
|
504 if(aDescUsed) |
|
505 { |
|
506 aMessage.ReadL(1, iCurrentDescriptor); |
|
507 TSecurityObjectDescriptor& secDesc = iCurrentDescriptor(); |
|
508 TInt status = ResolveCertMappingL( |
|
509 iCurrentDescriptor(), iObjectName, iFirst, EFalse, aStoreType); |
|
510 if(status == KErrNone) |
|
511 { |
|
512 iCount = 1; |
|
513 iLast = iFirst + 1; |
|
514 } |
|
515 } |
|
516 else |
|
517 { |
|
518 iLast = iMapping->Count(); |
|
519 } |
|
520 |
|
521 CBufFlat* list = CBufFlat::NewL(sizeof(TCertificateListEntry)); |
|
522 CleanupStack::PushL(list); |
|
523 list->ResizeL(iCount * sizeof(TCertificateListEntry)); |
|
524 TCertificateListEntry certInfo; |
|
525 |
|
526 for(TInt i = iFirst; i < iLast; i++) |
|
527 { |
|
528 CMapDescriptor* mapping = (*iMapping)[i]; |
|
529 if(CertValidity(mapping->iStartTime, mapping->iEndTime) != EExpired) |
|
530 { |
|
531 certInfo.iObjectName = mapping->iObjectName; |
|
532 certInfo.iOwnerType = mapping->iOwnerType; |
|
533 if(mapping->iTrustedAuthority != NULL) |
|
534 { |
|
535 certInfo.iTrustedAuthority = *(mapping->iTrustedAuthority); |
|
536 } |
|
537 if(mapping->iIdentitySubjectName != NULL) |
|
538 { |
|
539 certInfo.iIdentitySubjectName = *(mapping->iIdentitySubjectName); |
|
540 } |
|
541 if(mapping->iSerialNumber != NULL) |
|
542 { |
|
543 certInfo.iSerialNumber = *(mapping->iSerialNumber); |
|
544 } |
|
545 certInfo.iSubjectKeyId = mapping->iSubjectKeyId; |
|
546 certInfo.iKeySize = mapping->iKeySize; // Key size |
|
547 certInfo.iKeyAlgorithm = mapping->iKeyAlgorithm; // RSA, DSA |
|
548 certInfo.iIsDeletable = mapping->iIsDeletable; // IsDeletable |
|
549 |
|
550 list->Write(pos * sizeof(TCertificateListEntry), |
|
551 (TAny*)&certInfo, |
|
552 sizeof(TCertificateListEntry)); |
|
553 pos++; |
|
554 if(pos >= iCount) |
|
555 { |
|
556 break; |
|
557 } |
|
558 } |
|
559 } |
|
560 TPtr8 ptrList = list->Ptr(0); |
|
561 aMessage.WriteL(0, ptrList); |
|
562 |
|
563 CleanupStack::PopAndDestroy(1); // list |
|
564 return KErrNone; |
|
565 } |
|
566 |
|
567 |
|
568 void CPKIMapper::GetApplicableCertListL(const RMessage2& aMessage, const RArray<TUid>& aUidArray) |
|
569 { |
|
570 TBool uidMatch = EFalse; |
|
571 TInt pos(0); |
|
572 |
|
573 CBufFlat* list = CBufFlat::NewL(sizeof(TCertificateListEntry)); |
|
574 CleanupStack::PushL(list); |
|
575 list->ResizeL(iCount * sizeof(TCertificateListEntry)); |
|
576 TCertificateListEntry certInfo; |
|
577 |
|
578 for(TInt i = 0; (i < iMapping->Count()) && (pos < iCount); i++) |
|
579 { |
|
580 CMapDescriptor* mapping = (*iMapping)[i]; |
|
581 if(mapping->iOwnerType == EPKICACertificate) |
|
582 { |
|
583 if(CertValidity(mapping->iStartTime, mapping->iEndTime) != EExpired) |
|
584 { |
|
585 uidMatch = EFalse; |
|
586 for(TInt j = 0; j < mapping->iApplUids.Count(); j++) |
|
587 { |
|
588 for(TInt k = 0; k < aUidArray.Count(); k++) |
|
589 { |
|
590 if(mapping->iApplUids[j].iUid == aUidArray[k].iUid) |
|
591 { |
|
592 uidMatch = ETrue; |
|
593 break; |
|
594 } |
|
595 } |
|
596 if(uidMatch) |
|
597 { |
|
598 certInfo.iObjectName = mapping->iObjectName; |
|
599 certInfo.iOwnerType = mapping->iOwnerType; |
|
600 if(mapping->iTrustedAuthority != NULL) |
|
601 { |
|
602 certInfo.iTrustedAuthority = *(mapping->iTrustedAuthority); |
|
603 } |
|
604 if(mapping->iIdentitySubjectName != NULL) |
|
605 { |
|
606 certInfo.iIdentitySubjectName = *(mapping->iIdentitySubjectName); |
|
607 } |
|
608 if(mapping->iSerialNumber != NULL) |
|
609 { |
|
610 certInfo.iSerialNumber = *(mapping->iSerialNumber); |
|
611 } |
|
612 certInfo.iSubjectKeyId = mapping->iSubjectKeyId; |
|
613 certInfo.iKeySize = mapping->iKeySize; // Key size |
|
614 certInfo.iKeyAlgorithm = mapping->iKeyAlgorithm; // RSA, DSA |
|
615 certInfo.iIsDeletable = mapping->iIsDeletable; // IsDeletable |
|
616 |
|
617 list->Write(pos * sizeof(TCertificateListEntry), |
|
618 (TAny*)&certInfo, |
|
619 sizeof(TCertificateListEntry)); |
|
620 pos++; |
|
621 break; |
|
622 } |
|
623 } |
|
624 } |
|
625 } |
|
626 } |
|
627 TPtr8 ptrList = list->Ptr(0); |
|
628 aMessage.WriteL(0, ptrList); |
|
629 |
|
630 CleanupStack::PopAndDestroy(1); // list |
|
631 } |
|
632 |
|
633 |
|
634 |
|
635 CMapDescriptor& CPKIMapper::GetMapDescriptorAtIndex(TInt aIndex) |
|
636 { |
|
637 PKISERVICE_ASSERT(aIndex < iMapping->Count()); |
|
638 return *(*iMapping)[aIndex]; |
|
639 } |
|
640 |
|
641 |
|
642 void CPKIMapper::GetCertificateKeyIdL(TSecurityObjectDescriptor &aDescriptor, TPKIKeyIdentifier &aKeyId, |
|
643 TPkiServiceStoreType aStoreType) const |
|
644 { |
|
645 LOG(Log::Printf(_L("-> CPKIMapper::GetCertificateKeyIdL"), aStoreType)); |
|
646 aKeyId.Zero(); |
|
647 |
|
648 TInt index; |
|
649 |
|
650 TFileName* fileName = new (ELeave) TFileName; |
|
651 CleanupDeletePushL(fileName); |
|
652 fileName->Zero(); |
|
653 |
|
654 TInt status = ResolveCertMappingL(aDescriptor, *fileName, index, EFalse, aStoreType); |
|
655 |
|
656 CleanupStack::PopAndDestroy(fileName); |
|
657 |
|
658 |
|
659 if(status == KErrNone) |
|
660 { |
|
661 aKeyId.Copy((*iMapping)[index]->iSubjectKeyId); |
|
662 } |
|
663 else |
|
664 { |
|
665 LOG(Log::Printf(_L("ResolveKeyMapping: key NOT found\n"))); |
|
666 LogSearchArguments(aDescriptor); |
|
667 } |
|
668 LOG(Log::Printf(_L("<- CPKIMapper::GetCertificateKeyIdL"), aStoreType)); |
|
669 } |
|
670 |
|
671 /** |
|
672 Check whether the given label is unique among all VPN certs. |
|
673 @return True only if the given label doesn't exist |
|
674 */ |
|
675 TBool CPKIMapper::LabelIsUnique(const TDesC& aLabel) const |
|
676 { |
|
677 for (TInt i(0); i < iMapping->Count(); i++) |
|
678 { |
|
679 if ((*iMapping)[i]->iObjectName.Compare(aLabel) == 0) |
|
680 { |
|
681 return EFalse; |
|
682 } |
|
683 } |
|
684 return ETrue; |
|
685 } |
|
686 |
|
687 /** |
|
688 Check whether the given certificate already exists among VPN certs. |
|
689 @return True only if the given certificate does not exist in VPN's cert list. |
|
690 */ |
|
691 TBool CPKIMapper::CertificateIsUniqueL(const TDesC8& aCertData) |
|
692 { |
|
693 TBool ret(ETrue); |
|
694 |
|
695 LOG(Log::Printf(_L("Verifying the uniqueness of certificate:"))); |
|
696 |
|
697 CX509Certificate* certificate = CX509Certificate::NewLC(aCertData); |
|
698 const TPtrC8* issuername = certificate->DataElementEncoding(CX509Certificate::EIssuerName); |
|
699 const TPtrC8* subjectname = certificate->DataElementEncoding(CX509Certificate::ESubjectName); |
|
700 |
|
701 HBufC* issuerdispname = certificate->IssuerName().DisplayNameL(); |
|
702 CleanupStack::PushL(issuerdispname); |
|
703 HBufC* subjectdispname = certificate->SubjectName().DisplayNameL(); |
|
704 CleanupStack::PushL(subjectdispname); |
|
705 |
|
706 TInt count(iMapping->Count()); |
|
707 |
|
708 for (TInt i(0); i < count; i++) |
|
709 { |
|
710 CMapDescriptor* mapitem = (*iMapping)[i]; |
|
711 |
|
712 // Use subject name for uniqueness criterion |
|
713 if (mapitem->iIdentitySubjectName) |
|
714 { |
|
715 if (subjectname->Compare(*(mapitem->iIdentitySubjectName)) == 0) |
|
716 { |
|
717 LOG(Log::Printf(_L("Found an existing cert that matches subject"))); |
|
718 if (issuername->Compare(*(mapitem->iTrustedAuthority)) == 0) |
|
719 { |
|
720 ret = EFalse; |
|
721 break; |
|
722 } |
|
723 } |
|
724 } |
|
725 else if (mapitem->iTrustedAuthority && (subjectname->Compare(*issuername) == 0)) |
|
726 { |
|
727 if (subjectname->Compare(*(mapitem->iTrustedAuthority)) == 0) |
|
728 { |
|
729 LOG(Log::Printf(_L("Found an existing cert that matches subject (CA)"))); |
|
730 ret = EFalse; |
|
731 break; |
|
732 } |
|
733 } |
|
734 } |
|
735 |
|
736 CleanupStack::PopAndDestroy(3, certificate); // issuerdispname, subjectdispname |
|
737 |
|
738 return ret; |
|
739 } |
|
740 |
|
741 /** |
|
742 Generates an unique label name for a certificate, based on its subject name. |
|
743 @param1 The binary data describing the certificate |
|
744 @param2 Return value for the generated unique name |
|
745 @param3 Certificate owner type -- currently not supported. |
|
746 @return none |
|
747 */ |
|
748 void CPKIMapper::GenerateUniqueNameL( |
|
749 const TDesC8 &aCertData, TDes& aName, |
|
750 TCertificateOwnerType /*aOwnerType*/ ) |
|
751 { |
|
752 LOG(Log::Printf(_L("CPKIMapper::GenerateUniqueNameL() entry"))); |
|
753 |
|
754 CX509Certificate* certificate = CX509Certificate::NewLC(aCertData); |
|
755 |
|
756 HBufC* baseline = certificate->SubjectName().DisplayNameL(); |
|
757 CleanupStack::PushL(baseline); |
|
758 // +5 for (999) suffix |
|
759 HBufC* variation = HBufC::NewLC(baseline->Length() + 5); |
|
760 variation->Des().Append(*baseline); |
|
761 |
|
762 if (baseline->Length() == 0) |
|
763 { |
|
764 TPtr ptr = variation->Des(); |
|
765 ptr.Format(_L("(1)")); |
|
766 } |
|
767 |
|
768 // See whether the initial label is already unique |
|
769 TInt iter(2); |
|
770 while (!LabelIsUnique(*variation)) |
|
771 { |
|
772 // Iterate a new version of the label |
|
773 if (iter > 999) |
|
774 { |
|
775 // too long name, just go with the previous. |
|
776 break; |
|
777 } |
|
778 TPtr ptr = variation->Des(); |
|
779 ptr.Format(_L("%S(%d)"), &(*baseline), iter); |
|
780 iter++; |
|
781 } |
|
782 |
|
783 // Sanity check for string lengths |
|
784 aName = variation->Left(MAX_FILENAME_LENGTH); |
|
785 |
|
786 CleanupStack::PopAndDestroy(3); //variation, baseline, certificate |
|
787 |
|
788 LOG(Log::Printf(_L("CPKIMapper::GenerateUniqueNameL() exit"))); |
|
789 } |
|
790 |
|
791 TInt CPKIMapper::ResolveCertMappingL(TSecurityObjectDescriptor &aDescriptor, TDes16 &aFilename, |
|
792 TInt &aIndex, const TBool aInfoOnly, |
|
793 TPkiServiceStoreType aStoreType) const |
|
794 { |
|
795 TInt i; |
|
796 TInt status = KErrNotFound; |
|
797 TInt foundIndex = -1; |
|
798 TTime furthestEndTime = TTime(0); |
|
799 |
|
800 LOG(Log::Printf(_L("Resolving cert mapping, STORETYPE: %d\n"), aStoreType)); |
|
801 |
|
802 LOG(LogSearchArguments(aDescriptor)); |
|
803 |
|
804 // Scan available mappings |
|
805 for(i = 0; i < iMapping->Count(); i++) |
|
806 { |
|
807 // Bypass entry in case that function leaves |
|
808 // (issuer/subject name can be invalid) |
|
809 CMapDescriptor* mapping = (*iMapping)[i]; |
|
810 if(mapping->IsMatchingL(aDescriptor, aInfoOnly, aStoreType)) |
|
811 { |
|
812 // If we found a match, process it further |
|
813 _LIT(KMidp2Label, "MIDP2"); |
|
814 TBuf<12> buf; |
|
815 buf.Append(KMidp2Label); |
|
816 // Discard all MIDP2 certificates to avoid label-mapping problem |
|
817 if (buf.Compare(mapping->iObjectName) != 0) |
|
818 { |
|
819 if(mapping->iEndTime > furthestEndTime) |
|
820 { |
|
821 furthestEndTime = mapping->iEndTime; |
|
822 foundIndex = i; |
|
823 LOG(Log::Printf(_L("Resolve cert mapping: Tentatively found a suitable one"))); |
|
824 // Continue to search the longest lasting certificate |
|
825 } |
|
826 } |
|
827 else |
|
828 { |
|
829 LOG(Log::Printf(_L("Found a cert, but it was a MIDP2 one - continuing search"))); |
|
830 } |
|
831 } |
|
832 } |
|
833 |
|
834 if(foundIndex == -1) |
|
835 { |
|
836 LOG(Log::Printf(_L("Resolve cert mapping: No matching certificate found"))); |
|
837 status = KErrNotFound; |
|
838 } |
|
839 else |
|
840 { |
|
841 aFilename.Zero(); |
|
842 status = KErrNone; |
|
843 if(status == KErrNone) |
|
844 { |
|
845 aFilename.Append((*iMapping)[foundIndex]->iObjectName); |
|
846 status = KErrNone; |
|
847 aIndex = foundIndex; |
|
848 } |
|
849 LOG(Log::Printf(_L("ResolveCertMapping: certificate found\n"))); |
|
850 LogSearchArguments(aDescriptor); |
|
851 LOG(Log::Printf(_L("ResolveCertMapping: Object info\n"))); |
|
852 LogMap(*(*iMapping)[aIndex]); |
|
853 } |
|
854 return status; |
|
855 } |
|
856 |
|
857 |
|
858 TValidity CPKIMapper::CertValidity(const TTime &aStartTime, const TTime &aEndTime) |
|
859 { |
|
860 TTimeIntervalSeconds tolerance(120); |
|
861 TTime currentTime; |
|
862 currentTime.UniversalTime(); |
|
863 |
|
864 if (aEndTime <= currentTime) |
|
865 { |
|
866 return EExpired; |
|
867 } |
|
868 |
|
869 if (aStartTime >= currentTime + tolerance) |
|
870 { |
|
871 return ENotValidYet; |
|
872 } |
|
873 |
|
874 return EValid; |
|
875 } |
|
876 |
|
877 void CPKIMapper::LogSearchArguments(TSecurityObjectDescriptor &aDescriptor) const |
|
878 { |
|
879 TBuf<256> temp; |
|
880 LOG(Log::Printf(_L("====Object Search arguments====\n"))); |
|
881 if(aDescriptor.iTrustedAuthorityUsed) |
|
882 { |
|
883 temp.Copy(aDescriptor.iTrustedAuthority); |
|
884 if((aDescriptor.iTrustedAuthority[0] != 0x30) |
|
885 || ((aDescriptor.iTrustedAuthority[1] != 0x81) |
|
886 && (aDescriptor.iTrustedAuthority[1] != 0x82) |
|
887 && ((aDescriptor.iTrustedAuthority[1] + 2) != aDescriptor.iTrustedAuthority.Length()))) |
|
888 { |
|
889 LOG(Log::Printf(_L("Trusted authority: %S\n"), &temp)); |
|
890 } |
|
891 else |
|
892 { |
|
893 LOG(Log::Printf(_L("Trusted authority:"))); |
|
894 LOG(Log::HexDump(NULL, NULL, aDescriptor.iTrustedAuthority.Ptr(), aDescriptor.iTrustedAuthority.Length())); |
|
895 } |
|
896 } |
|
897 if(aDescriptor.iIdentitySubjectNameUsed) |
|
898 { |
|
899 temp.Copy(aDescriptor.iIdentitySubjectName); |
|
900 if((aDescriptor.iIdentitySubjectName[0] != 0x30) |
|
901 || ((aDescriptor.iIdentitySubjectName[1] != 0x81) |
|
902 && (aDescriptor.iIdentitySubjectName[1] != 0x82) |
|
903 && ((aDescriptor.iIdentitySubjectName[1] + 2) != aDescriptor.iIdentitySubjectName.Length()))) |
|
904 { |
|
905 LOG(Log::Printf(_L("SubjectName: %S\n"), &temp)); |
|
906 } |
|
907 else |
|
908 { |
|
909 LOG(Log::Printf(_L("SubjectName:"))); |
|
910 LOG(Log::HexDump(NULL, NULL, aDescriptor.iIdentitySubjectName.Ptr(), aDescriptor.iIdentitySubjectName.Length())); |
|
911 } |
|
912 } |
|
913 if(aDescriptor.iIdentityRfc822NameUsed) |
|
914 { |
|
915 temp.Copy(aDescriptor.iIdentityRfc822Name); |
|
916 LOG(Log::Printf(_L("Rfc822Name: %S\n"), &temp)); |
|
917 } |
|
918 if(aDescriptor.iSerialNumberUsed) |
|
919 { |
|
920 LOG(Log::Printf(_L("SerialNumber:"))); |
|
921 LOG(Log::HexDump(NULL, NULL, aDescriptor.iSerialNumber.Ptr(), aDescriptor.iSerialNumber.Length())); |
|
922 } |
|
923 if(aDescriptor.iSubjectKeyIdUsed) |
|
924 { |
|
925 LOG(Log::Printf(_L("KeyId:"))); |
|
926 LOG(Log::HexDump(NULL, NULL, aDescriptor.iSubjectKeyId.Ptr(), aDescriptor.iSubjectKeyId.Length())); |
|
927 } |
|
928 if(aDescriptor.iOwnerTypeUsed) |
|
929 { |
|
930 LOG(Log::Printf(_L("OwnerType: %d\n"), aDescriptor.iOwnerType)); |
|
931 } |
|
932 if(aDescriptor.iKeyUsageUsed) |
|
933 { |
|
934 LOG(Log::Printf(_L("KeyUsage:"))); |
|
935 LOG(Log::HexDump(NULL, NULL, aDescriptor.iKeyUsageDer.Ptr(), aDescriptor.iKeyUsageDer.Length())); |
|
936 } |
|
937 if(aDescriptor.iKeySizeUsed) |
|
938 { |
|
939 LOG(Log::Printf(_L("KeySize: %d\n"), aDescriptor.iKeySize)); |
|
940 } |
|
941 if(aDescriptor.iKeyAlgorithmUsed) |
|
942 { |
|
943 LOG(Log::Printf(_L("KeyAlgorithm: %d\n"), aDescriptor.iKeyAlgorithm)); |
|
944 } |
|
945 } |
|
946 |
|
947 TBool PkiUtil::MatchL(const CX500DistinguishedName& aDn1, const CX500DistinguishedName& aDn2) |
|
948 { |
|
949 if((aDn1.Count() == 0) || (aDn2.Count() == 0)) |
|
950 { |
|
951 return EFalse; |
|
952 } |
|
953 |
|
954 if (aDn1.Count() < aDn2.Count()) |
|
955 { |
|
956 return EFalse; |
|
957 } |
|
958 else |
|
959 { |
|
960 // For each field in aDn2, aDn1 must contain a field with the same value |
|
961 for (TInt i = 0; i < aDn2.Count(); i++) |
|
962 { |
|
963 if (!HasElementL(aDn1, aDn2.Element(i))) |
|
964 { |
|
965 return EFalse; |
|
966 } |
|
967 } |
|
968 } |
|
969 |
|
970 return ETrue; |
|
971 } |
|
972 |
|
973 TBool PkiUtil::HasElementL(const CX500DistinguishedName& aDn, const CX520AttributeTypeAndValue& aElement) |
|
974 { |
|
975 for (TInt i = 0; i < aDn.Count(); i++) |
|
976 { |
|
977 if (aElement.ExactMatchL(aDn.Element(i))) |
|
978 { |
|
979 return ETrue; |
|
980 } |
|
981 } |
|
982 return EFalse; |
|
983 } |
|
984 |