|
1 /* |
|
2 * Copyright (c) 2003-2007 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: Class that handles user input and launching of dialogs |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include <aknnotewrappers.h> // Note dialogs |
|
21 #include <aknmessagequerydialog.h> // For CAknMessageQueryDialog |
|
22 #include <StringLoader.h> // For loading resource strings |
|
23 #include <unifiedcertstore.h> // For saving the certificates |
|
24 #include <mctwritablecertstore.h> // For saving the certificates |
|
25 #include <sysutil.h> // For FFSSpaceBelowCriticalLevelL(..) |
|
26 #include <X509CertNameParser.h> // For default label |
|
27 #include <x509cert.h> // For CX509Certificate |
|
28 #include <wtlscert.h> // For WTLSCertificate |
|
29 #include <hash.h> // MD5 fingerprint |
|
30 #include <certificateapps.h> |
|
31 #include <mctkeystore.h> |
|
32 #include <securityerr.h> |
|
33 #include <asnpkcs.h> |
|
34 #include <unifiedkeystore.h> |
|
35 #include <x509certext.h> |
|
36 #include <mctkeystore.h> |
|
37 #include <TrustedSitesStore.h> |
|
38 |
|
39 #include <CertSaver.rsg> |
|
40 #include "CertSaverModel.h" |
|
41 #include "CertSaverDocument.h" |
|
42 #include "CertSaverAppUi.h" |
|
43 #include "CertSaverSyncWrapper.h" |
|
44 #include "certsaver.hrh" |
|
45 #include "securityuisvariant.hrh" |
|
46 |
|
47 // CONSTANTS |
|
48 const TInt32 KWTLSTrusterUID( 268479059 ); |
|
49 const TInt32 KInternetTrusterUID( 268441661 ); |
|
50 const TInt32 KApplicationControllerTrusterUID( 268452523 ); |
|
51 const TInt32 KJavaInstallTrusterUID( 270506792 ); |
|
52 const TInt32 KOCSPTrusterUID( 268478646 ); |
|
53 const TInt32 KVPNUID( 270498195 ); |
|
54 |
|
55 const TInt KTrusterArrayInitSize( 2 ); |
|
56 |
|
57 const TInt KMaxLengthTextMeassageBody( 5000 ); |
|
58 const TInt KMaxLengthTextDateString( 11 ); // "dd/mm/yyyy0" |
|
59 |
|
60 //Issuer and Owner max visible length |
|
61 const TInt KMaxLengthTextCertIdentifierVisible( 1000 ); |
|
62 const TInt KAttempts( 3 ); |
|
63 |
|
64 const TInt KFingerprintLength( 50 ); |
|
65 |
|
66 _LIT( KCertSaverListBoxItemPrefix, "1\t" ); |
|
67 const TInt KItemBufLen = 2 + KMaxName; |
|
68 |
|
69 _LIT( KPrivateKeyLabel, "PrivateKey " ); |
|
70 const TInt KPrivaKeyLabelLength( 50 ); |
|
71 _LIT( KDateString,"%D%M%Y%1%2%3" ); |
|
72 _LIT( KTimeString,"%-B%:0%J%:1%T%:2%S%:3%+B" ); |
|
73 _LIT( KSpace, " " ); |
|
74 _LIT( KDoubleEnter, "\n\n" ); |
|
75 _LIT( KEnter, "\n" ); |
|
76 |
|
77 const TUid KTrustedServerTokenUid = { 0x101FB66F }; |
|
78 const TUid KFileTokensUid = { 0x101F501A }; |
|
79 |
|
80 _LIT_SECURITY_POLICY_V1( KSymbianKeyStoreMgmtPolicy, |
|
81 VID_DEFAULT, ECapabilityWriteUserData ); |
|
82 _LIT_SECURITY_POLICY_C1( KSymbianKeyStoreUsePolicy, ECapabilityReadUserData ); |
|
83 |
|
84 |
|
85 // ================= MEMBER FUNCTIONS ======================= |
|
86 |
|
87 // Destructor |
|
88 CCertSaverModel::~CCertSaverModel() |
|
89 { |
|
90 delete iWrapper; |
|
91 iEntries.Close(); |
|
92 delete iUnifiedCertStore; |
|
93 iTrusterUids.Close(); |
|
94 } |
|
95 |
|
96 // ---------------------------------------------------------- |
|
97 // CCertSaverModel::CCertSaverModel( |
|
98 // const CCertSaverDocument* aDocument, CCertSaverAppUi* aAppUi) |
|
99 // ---------------------------------------------------------- |
|
100 // |
|
101 CCertSaverModel::CCertSaverModel( |
|
102 CCertSaverAppUi* aAppUi, |
|
103 const CCertParser& aParser ): |
|
104 iAppUi( aAppUi ), iFs( iAppUi->CoeEnv()->FsSession() ), iParser( aParser ), |
|
105 iSavedCACertsCount( 0 ), iSavedKeysCount( 0 ), |
|
106 iSavedUserCertsCount( 0 ), iKeyAlreadyExists( EFalse ) |
|
107 { |
|
108 } |
|
109 |
|
110 // ---------------------------------------------------------- |
|
111 // CCertSaverModel::SaveCertificateL() |
|
112 // ---------------------------------------------------------- |
|
113 // |
|
114 void CCertSaverModel::SaveCertificateL( |
|
115 const CX509Certificate& aCertificate, |
|
116 const TCertificateOwnerType& aOwnerType, |
|
117 const TCertificateFormat& aCertFormat ) |
|
118 { |
|
119 iCertOwnerType = aOwnerType; |
|
120 iCertFormat = aCertFormat; |
|
121 iNewCert = &aCertificate; |
|
122 |
|
123 if ( aOwnerType == EPeerCertificate ) |
|
124 { |
|
125 TInt ret = QueryTrustedSiteL(); |
|
126 if ( ret != KErrNone ) |
|
127 { |
|
128 return; |
|
129 } |
|
130 } |
|
131 |
|
132 SaveCertL(); |
|
133 } |
|
134 |
|
135 // ---------------------------------------------------------- |
|
136 // CCertSaverModel::DoSavePrivateKeyL() |
|
137 // |
|
138 // ---------------------------------------------------------- |
|
139 // |
|
140 void CCertSaverModel::DoSavePrivateKeyL( const TDesC8& aKey ) |
|
141 { |
|
142 CheckFSSpaceL( aKey ); |
|
143 |
|
144 TKeyIdentifier keyIdentifier; |
|
145 CDecPKCS8Data* pkcs8Data = TASN1DecPKCS8::DecodeDERL( aKey ); |
|
146 CleanupStack::PushL( pkcs8Data ); |
|
147 MPKCS8DecodedKeyPairData* keyPairData = pkcs8Data->KeyPairData(); |
|
148 keyPairData->GetKeyIdentifierL( keyIdentifier ); |
|
149 |
|
150 TTime startDate; |
|
151 TTime endDate; |
|
152 GetKeyValidityPeriodL( startDate, endDate, keyIdentifier ); |
|
153 |
|
154 TInt err = KErrNone; |
|
155 CCTKeyInfo* keyInfo = NULL; |
|
156 TBuf<KPrivaKeyLabelLength> keyLabel( KPrivateKeyLabel ); |
|
157 TKeyUsagePKCS15 keyUsage = KeyUsageL( keyIdentifier, pkcs8Data->Algorithm() ); |
|
158 CleanupStack::PopAndDestroy( pkcs8Data ); |
|
159 if (KeyAlreadyExistsL( startDate, endDate, keyIdentifier, keyUsage) ) |
|
160 { |
|
161 User::Leave( KErrNone ); |
|
162 } |
|
163 |
|
164 TInt accessType( 0 ); |
|
165 |
|
166 accessType |= CCTKeyInfo::EExtractable; |
|
167 |
|
168 for ( TInt i = 0; i < KAttempts; i++ ) |
|
169 { |
|
170 CreateKeyLabelL( keyLabel ); |
|
171 // Should not use hardcoded index |
|
172 err = iWrapper->AddKey( 0, aKey, keyUsage, keyLabel, |
|
173 accessType, startDate, endDate, keyInfo ); |
|
174 if ( err != KErrAlreadyExists ) |
|
175 { |
|
176 i = KAttempts; |
|
177 } |
|
178 keyLabel.Zero(); |
|
179 } |
|
180 |
|
181 TCTTokenObjectHandle handle; |
|
182 if ( keyInfo ) |
|
183 { |
|
184 handle = keyInfo->Handle(); |
|
185 keyInfo->Release(); |
|
186 keyInfo = NULL; |
|
187 } |
|
188 |
|
189 switch ( err ) |
|
190 { |
|
191 case KErrNone: |
|
192 { |
|
193 ++iSavedKeysCount; |
|
194 break; |
|
195 } |
|
196 case KErrKeySize: |
|
197 case KErrArgument: |
|
198 { |
|
199 ShowErrorNoteL( R_CERTSAVER_KEY_TYPE_NOT_SUPPORTED ); |
|
200 User::Leave( KErrCancel ); |
|
201 break; |
|
202 } |
|
203 case KErrKeyValidity: |
|
204 { |
|
205 ShowInformationNoteL( R_CERTSAVER_QTN_CM_PKCS12_EXPIRED ); |
|
206 User::Leave( KErrCancel ); |
|
207 } |
|
208 case KErrKeyUsage: |
|
209 { |
|
210 ShowErrorNoteL( R_CERTSAVER_PRIVATE_KEY_CORRUPTED ); |
|
211 User::Leave( KErrCancel ); |
|
212 break; |
|
213 } |
|
214 case KErrCancel: |
|
215 case KErrPermissionDenied: |
|
216 { |
|
217 ShowErrorNoteL( R_CERTSAVER_PKCS12_DISCARDED ); |
|
218 User::Leave( KErrCancel ); |
|
219 break; |
|
220 } |
|
221 case KErrCorrupt: |
|
222 case KErrEof: |
|
223 { |
|
224 ShowErrorNoteL( R_CERTSAVER_KEYSTORE_CORRUPTED ); |
|
225 User::Leave( KErrCancel ); |
|
226 break; |
|
227 } |
|
228 case KErrAlreadyExists: |
|
229 { |
|
230 User::Leave( KErrCancel ); |
|
231 break; |
|
232 } |
|
233 default: |
|
234 { |
|
235 User::Leave( err ); |
|
236 break; |
|
237 } |
|
238 } |
|
239 |
|
240 User::LeaveIfError( |
|
241 iWrapper->SetManagementPolicy( handle, KSymbianKeyStoreMgmtPolicy) ); |
|
242 User::LeaveIfError( |
|
243 iWrapper->SetUsePolicy( handle, KSymbianKeyStoreUsePolicy ) ); |
|
244 } |
|
245 |
|
246 // ---------------------------------------------------------- |
|
247 // TBool CCertSaverModel::KeyAlreadyExistsL() |
|
248 // |
|
249 // ---------------------------------------------------------- |
|
250 // |
|
251 TBool CCertSaverModel::KeyAlreadyExistsL( |
|
252 TTime& aStartDate, |
|
253 TTime& aEndDate, |
|
254 const TKeyIdentifier& aKeyIdentifier, |
|
255 TKeyUsagePKCS15& aKeyUsage ) |
|
256 { |
|
257 TBool ret = EFalse; |
|
258 TCTKeyAttributeFilter keyFilter; |
|
259 keyFilter.iKeyAlgorithm = CKeyInfoBase::EInvalidAlgorithm; |
|
260 keyFilter.iKeyId = aKeyIdentifier; |
|
261 keyFilter.iPolicyFilter = TCTKeyAttributeFilter::EManageableKeys; |
|
262 keyFilter.iUsage = aKeyUsage; |
|
263 RMPointerArray<CCTKeyInfo> keyArray; |
|
264 TInt err = iWrapper->ListKeys( keyArray, keyFilter ); |
|
265 CleanupClosePushL( keyArray ); |
|
266 switch ( err ) |
|
267 { |
|
268 case KErrNone: |
|
269 { |
|
270 break; |
|
271 } |
|
272 case KErrCorrupt: |
|
273 case KErrEof: |
|
274 { |
|
275 ShowErrorNoteL( R_CERTSAVER_KEYSTORE_CORRUPTED ); |
|
276 User::Leave( KErrCancel ); |
|
277 } |
|
278 default: |
|
279 { |
|
280 User::Leave( err ); |
|
281 } |
|
282 } |
|
283 for ( TInt i = 0; ret == EFalse && i < keyArray.Count(); i++ ) |
|
284 { |
|
285 if ( keyArray[i]->StartDate() == aStartDate && |
|
286 keyArray[i]->EndDate() == aEndDate ) |
|
287 { |
|
288 ret = ETrue; |
|
289 iKeyAlreadyExists = ETrue; |
|
290 } |
|
291 } |
|
292 CleanupStack::PopAndDestroy( &keyArray ); |
|
293 return ret; |
|
294 } |
|
295 |
|
296 // ---------------------------------------------------------- |
|
297 // CCertSaverModel::GetKeyValidityPeriodL() |
|
298 // |
|
299 // ---------------------------------------------------------- |
|
300 // |
|
301 void CCertSaverModel::GetKeyValidityPeriodL( |
|
302 TTime& aStartDate, |
|
303 TTime& aEndDate, |
|
304 const TKeyIdentifier& aKeyIdentifier ) |
|
305 { |
|
306 |
|
307 for ( TInt i = 0; i < iParser.UserCertificates().Count(); i++ ) |
|
308 { |
|
309 const CX509Certificate* cert = iParser.UserCertificates().At( i ); |
|
310 if ( cert->KeyIdentifierL() == aKeyIdentifier ) |
|
311 { |
|
312 // Associated certificate found |
|
313 // In the first round aStartDate and aEndDate is initialised. |
|
314 if ( i == 0 || aStartDate > cert->ValidityPeriod().Start() ) |
|
315 { |
|
316 aStartDate = cert->ValidityPeriod().Start(); |
|
317 } |
|
318 if ( i == 0 || aEndDate < cert->ValidityPeriod().Finish() ) |
|
319 { |
|
320 aEndDate = cert->ValidityPeriod().Finish(); |
|
321 } |
|
322 } |
|
323 } |
|
324 } |
|
325 |
|
326 // ---------------------------------------------------------- |
|
327 // CCertSaverModel::CreateKeyLabelL() |
|
328 // |
|
329 // ---------------------------------------------------------- |
|
330 // |
|
331 void CCertSaverModel::CreateKeyLabelL( TDes& aLabel ) |
|
332 { |
|
333 TTime time; |
|
334 time.UniversalTime(); |
|
335 TBuf<KPrivaKeyLabelLength> dateBuf; |
|
336 time.FormatL( dateBuf, KDateString ); |
|
337 aLabel.Append( dateBuf ); |
|
338 dateBuf.Zero(); |
|
339 aLabel.Append( KSpace ); |
|
340 |
|
341 time.FormatL( dateBuf, KTimeString ); |
|
342 aLabel.Append( dateBuf ); |
|
343 } |
|
344 |
|
345 // ---------------------------------------------------------- |
|
346 // CCertSaverModel::SavePrivateKeyL() |
|
347 // |
|
348 // ---------------------------------------------------------- |
|
349 // |
|
350 void CCertSaverModel::SavePrivateKeyL() |
|
351 { |
|
352 if ( iParser.Keys().Count() <= 0 ) |
|
353 { |
|
354 return; |
|
355 } |
|
356 if ( NULL == iWrapper ) |
|
357 { |
|
358 iWrapper = CCertSaverSyncWrapper::NewL(); |
|
359 } |
|
360 TInt err = iWrapper->InitializeKeyStoreL( iFs ); |
|
361 |
|
362 TInt keyStoreCount = iWrapper->UnifiedKeyStore().KeyStoreManagerCount(); |
|
363 if ( keyStoreCount <= 0 ) |
|
364 { |
|
365 User::Leave( KErrCancel ); |
|
366 } |
|
367 else |
|
368 { |
|
369 for ( TInt i = 0; i < keyStoreCount; ++i ) |
|
370 { |
|
371 TUid uid = |
|
372 iWrapper->UnifiedKeyStore().KeyStoreManager(i).Token().TokenType().Type(); |
|
373 if ( uid == TUid::Uid( KTokenTypeFileKeystore ) ) |
|
374 // if this is not found, we use the first one, |
|
375 // which is already initialised |
|
376 { |
|
377 iSelectedKeyStore = i; |
|
378 } |
|
379 } |
|
380 } |
|
381 |
|
382 for ( TInt i = 0; i < iParser.Keys().Count(); i++ ) |
|
383 { |
|
384 const HBufC8* key = iParser.Keys().At( i ); |
|
385 TRAP(err, DoSavePrivateKeyL( *key )); |
|
386 User::LeaveIfError( err ); |
|
387 } |
|
388 } |
|
389 |
|
390 // ---------------------------------------------------------- |
|
391 // CCertSaverModel::KeyUsageL( |
|
392 // const TKeyIdentifier& aKeyIdentifier, TAlgorithmId aAlgorithm) |
|
393 // ---------------------------------------------------------- |
|
394 // |
|
395 TKeyUsagePKCS15 CCertSaverModel::KeyUsageL( |
|
396 const TKeyIdentifier& aKeyIdentifier, |
|
397 TAlgorithmId aAlgorithm ) |
|
398 { |
|
399 |
|
400 TKeyUsagePKCS15 pkcs15KeyUsage = EPKCS15UsageNone; |
|
401 TKeyUsageX509 x509Usage = EX509UsageNone; |
|
402 |
|
403 for ( TInt i = 0; i < iParser.UserCertificates().Count(); i++ ) |
|
404 { |
|
405 const CX509Certificate* cert = iParser.UserCertificates().At( i ); |
|
406 if ( cert->KeyIdentifierL() == aKeyIdentifier ) |
|
407 { |
|
408 const CX509CertExtension* ext = cert->Extension( KKeyUsage ); |
|
409 if (ext) |
|
410 { |
|
411 CX509KeyUsageExt* keyUsageExt = |
|
412 CX509KeyUsageExt::NewLC( ext->Data() ); |
|
413 if ( keyUsageExt->IsSet( EX509DigitalSignature ) ) |
|
414 { |
|
415 x509Usage |= EX509UsageDigitalSignature; |
|
416 } |
|
417 if ( keyUsageExt->IsSet( EX509NonRepudiation ) ) |
|
418 { |
|
419 x509Usage |= EX509UsageNonRepudiation; |
|
420 } |
|
421 if ( keyUsageExt->IsSet( EX509KeyEncipherment ) ) |
|
422 { |
|
423 x509Usage |= EX509UsageKeyEncipherment; |
|
424 } |
|
425 if ( keyUsageExt->IsSet( EX509DataEncipherment ) ) |
|
426 { |
|
427 x509Usage |= EX509UsageDataEncipherment; |
|
428 } |
|
429 if ( keyUsageExt->IsSet( EX509KeyAgreement ) ) |
|
430 { |
|
431 x509Usage |= EX509UsageKeyAgreement; |
|
432 } |
|
433 if ( keyUsageExt->IsSet( EX509KeyCertSign ) ) |
|
434 { |
|
435 x509Usage |= EX509UsageKeyCertSign; |
|
436 } |
|
437 if ( keyUsageExt->IsSet( EX509CRLSign ) ) |
|
438 { |
|
439 x509Usage |= EX509UsageCRLSign; |
|
440 } |
|
441 if ( keyUsageExt->IsSet( EX509EncipherOnly ) ) |
|
442 { |
|
443 x509Usage |= EX509UsageEncipherOnly; |
|
444 } |
|
445 if ( keyUsageExt->IsSet( EX509DecipherOnly ) ) |
|
446 { |
|
447 x509Usage |= EX509UsageDecipherOnly; |
|
448 } |
|
449 CleanupStack::PopAndDestroy( keyUsageExt ); |
|
450 } |
|
451 } |
|
452 } |
|
453 |
|
454 pkcs15KeyUsage = KeyUsageX509ToPKCS15Private( x509Usage ); |
|
455 // If any certificate in the file did not include key usage, |
|
456 // let's use default values. |
|
457 if ( EPKCS15UsageNone == pkcs15KeyUsage ) |
|
458 { |
|
459 switch ( aAlgorithm ) |
|
460 { |
|
461 case ERSA: |
|
462 { |
|
463 pkcs15KeyUsage |= EPKCS15UsageSignSignRecover; |
|
464 pkcs15KeyUsage |= EPKCS15UsageDecryptUnwrap; |
|
465 break; |
|
466 } |
|
467 case EDSA: |
|
468 { |
|
469 pkcs15KeyUsage |= EPKCS15UsageSignSignRecover; |
|
470 break; |
|
471 } |
|
472 default: |
|
473 { |
|
474 break; |
|
475 } |
|
476 } |
|
477 } |
|
478 return pkcs15KeyUsage; |
|
479 } |
|
480 |
|
481 // ---------------------------------------------------------- |
|
482 // CCertSaverModel::CheckFSSpaceL( |
|
483 // const TDesC8& aDataToSave) |
|
484 // ---------------------------------------------------------- |
|
485 // |
|
486 void CCertSaverModel::CheckFSSpaceL( const TDesC8& aDataToSave ) |
|
487 { |
|
488 if (SysUtil::FFSSpaceBelowCriticalLevelL( &iFs, aDataToSave.Size() )) |
|
489 { |
|
490 HBufC* p = StringLoader::LoadLC( R_CERTSAVER_MEMORY ); |
|
491 CAknErrorNote* note = new (ELeave) CAknErrorNote( ETrue ); |
|
492 note->ExecuteLD( p->Des() ); |
|
493 CleanupStack::PopAndDestroy( p ); |
|
494 User::Leave( KErrExitApp ); |
|
495 } |
|
496 } |
|
497 |
|
498 // ---------------------------------------------------------- |
|
499 // CCertSaverModel::SaveCertL() |
|
500 // Saves certificate |
|
501 // ---------------------------------------------------------- |
|
502 // |
|
503 void CCertSaverModel::SaveCertL() |
|
504 { |
|
505 if ( !CertificateOkL() ) |
|
506 { |
|
507 User::Leave( KErrCancel ); |
|
508 } |
|
509 |
|
510 HBufC* message = HBufC::NewLC( KMaxLengthTextMeassageBody ); |
|
511 TPtr msgPtr = message->Des(); |
|
512 ConstructMessageL( msgPtr ); |
|
513 CAknMessageQueryDialog* dlg = CAknMessageQueryDialog::NewL( *message ); |
|
514 CleanupStack::PopAndDestroy( message ); |
|
515 CleanupStack::PushL( dlg ); |
|
516 |
|
517 |
|
518 dlg->PrepareLC( R_MESSAGE_QUERY_DOSAVE ); |
|
519 |
|
520 HBufC* header = StringLoader::LoadLC( R_CERTSAVER_DETAILS_HEADING ); |
|
521 dlg->QueryHeading()->SetTextL( header->Des() ); |
|
522 CleanupStack::PopAndDestroy( header ); |
|
523 CleanupStack::Pop( dlg ); |
|
524 TBool doSave = dlg->RunLD(); |
|
525 |
|
526 if ( doSave && iCertOwnerType == ECACertificate ) |
|
527 { |
|
528 // warn user about security risk |
|
529 CAknQueryDialog* warningDialog = CAknQueryDialog::NewL(); |
|
530 doSave = warningDialog->ExecuteLD( R_CERTSAVER_WARNING_NOTE ); |
|
531 } |
|
532 |
|
533 if ( doSave ) |
|
534 { |
|
535 //Check that there still is enough space to store the |
|
536 //certificate. |
|
537 CheckFSSpaceL( iNewCert->Encoding() ); |
|
538 DoSaveCertL(); |
|
539 } |
|
540 else |
|
541 { |
|
542 ShowConfirmationNoteL( R_CERTSAVER_CERT_DISCARDED ); |
|
543 User::Leave( KErrCancel ); |
|
544 } |
|
545 } |
|
546 |
|
547 // ---------------------------------------------------------- |
|
548 // CCertSaverModel::InitCertStoreL() |
|
549 // |
|
550 // ---------------------------------------------------------- |
|
551 // |
|
552 void CCertSaverModel::InitCertStoreL() |
|
553 { |
|
554 if ( !iUnifiedCertStore ) |
|
555 { |
|
556 TRAPD( status, iUnifiedCertStore = CUnifiedCertStore::NewL( iFs, ETrue ) ); |
|
557 if ( status != KErrNone ) |
|
558 { |
|
559 ShowErrorNoteL( R_CERTSAVER_ERROR_CACERTS_DB_CORRUPTED ); |
|
560 User::Leave( KErrExitApp ); |
|
561 } |
|
562 // initialize unified cert store |
|
563 status = iWrapper->InitializeCertStore( *iUnifiedCertStore ); |
|
564 if ( status ) |
|
565 { |
|
566 HandleSaveErrorL( status ); |
|
567 User::Leave( KErrExitApp ); |
|
568 } |
|
569 } |
|
570 } |
|
571 |
|
572 // ---------------------------------------------------------- |
|
573 // CCertSaverModel::DoSaveCertL() |
|
574 // Tries to save the certificate to phone memory. |
|
575 // ---------------------------------------------------------- |
|
576 // |
|
577 void CCertSaverModel::DoSaveCertL() |
|
578 { |
|
579 TInt status = KErrNone; |
|
580 CCertAttributeFilter* filter = NULL; |
|
581 TCertificateFormat certFormat = EX509Certificate; |
|
582 HBufC* secondaryName = NULL; |
|
583 TCertLabel labelBuf; |
|
584 CCertificate* certificate = NULL; |
|
585 HBufC* label = NULL; |
|
586 |
|
587 if ( NULL == iWrapper ) |
|
588 { |
|
589 iWrapper = CCertSaverSyncWrapper::NewL(); |
|
590 } |
|
591 // Init unified certstore |
|
592 InitCertStoreL(); |
|
593 |
|
594 // Check that certificate doesn't already exist. |
|
595 // Fingerprint of certificate is used to confirm this. |
|
596 filter = CCertAttributeFilter::NewL(); |
|
597 filter->SetFormat( iCertFormat ); |
|
598 filter->SetOwnerType( iCertOwnerType ); |
|
599 // Delete old array first |
|
600 iEntries.Close(); |
|
601 status = iWrapper->ListCerts( *iUnifiedCertStore, iEntries, *filter ); |
|
602 delete filter; |
|
603 filter = NULL; |
|
604 if ( status ) |
|
605 { |
|
606 if ( status != KErrCancel ) |
|
607 { |
|
608 HandleSaveErrorL( status ); |
|
609 } |
|
610 User::Leave( KErrExitApp ); |
|
611 } |
|
612 |
|
613 TBool found = EFalse; |
|
614 |
|
615 for ( TInt i = 0; i < iEntries.Count() && !found; ++i ) |
|
616 { |
|
617 iWrapper->Retrieve( *iUnifiedCertStore, *iEntries[i], certificate ); |
|
618 // Compare fingerprint of listed certificates to |
|
619 // fingerprint of new certificate |
|
620 // If the certificate is already in CACerts.dat, |
|
621 // then don't save it |
|
622 if ( iNewCert->Fingerprint() == certificate->Fingerprint() && |
|
623 (( *iEntries[i]).Handle().iTokenHandle.iTokenTypeUid == KFileTokensUid ) ) |
|
624 { |
|
625 found = ETrue; |
|
626 } |
|
627 delete certificate; |
|
628 certificate = NULL; |
|
629 } |
|
630 |
|
631 // Cancel if certificate already exists. |
|
632 if ( found ) |
|
633 { |
|
634 HandleSaveErrorL( KErrAlreadyExists ); |
|
635 User::Leave( KErrCancel ); |
|
636 } |
|
637 |
|
638 // Create default label from the certificate |
|
639 X509CertNameParser::PrimaryAndSecondaryNameL( |
|
640 (*(CX509Certificate*)iNewCert), label, secondaryName ); |
|
641 CleanupStack::PushL( label ); |
|
642 delete secondaryName; |
|
643 secondaryName = NULL; |
|
644 labelBuf = label->Des().Left( CERTSAVER_MAX_LABEL_LEN ); |
|
645 CleanupStack::PopAndDestroy( label ); |
|
646 label = NULL; |
|
647 // Asks unique label from user. |
|
648 status = QueryLabelL( labelBuf, *iUnifiedCertStore ); |
|
649 if ( status ) |
|
650 { |
|
651 if ( status != KErrCancel ) |
|
652 { |
|
653 HandleSaveErrorL( status ); |
|
654 } |
|
655 User::Leave( KErrCancel ); |
|
656 } |
|
657 |
|
658 if ( ECACertificate == iCertOwnerType ) |
|
659 { |
|
660 // Query trusted UIDs |
|
661 status = QueryTrusterUidsL( iTrusterUids ); |
|
662 if ( status ) |
|
663 { |
|
664 HandleSaveErrorL( status ); |
|
665 User::Leave( KErrCancel ); |
|
666 } |
|
667 } |
|
668 |
|
669 // Get interface to writable store. |
|
670 TInt certstoreIndex( -1 ); |
|
671 TInt count = iUnifiedCertStore->WritableCertStoreCount(); |
|
672 if ( count > 0 ) |
|
673 { |
|
674 for ( TInt i = 0; i < count; i++ ) |
|
675 { |
|
676 MCTWritableCertStore& writableCertStore = |
|
677 iUnifiedCertStore->WritableCertStore( i ); |
|
678 |
|
679 MCTToken& token = writableCertStore.Token(); |
|
680 TUid tokenuid = token.Handle().iTokenTypeUid; |
|
681 if ( ( tokenuid == KTrustedServerTokenUid ) && ( iCertOwnerType == EPeerCertificate ) || |
|
682 ( tokenuid == KFileTokensUid ) && ( iCertOwnerType == ECACertificate ) || |
|
683 ( tokenuid == KFileTokensUid ) && ( iCertOwnerType == EUserCertificate ) ) |
|
684 { |
|
685 certstoreIndex = i; |
|
686 break; |
|
687 } |
|
688 } |
|
689 |
|
690 if ( certstoreIndex < 0 ) |
|
691 { |
|
692 // Couldn't find certificate storage |
|
693 ShowErrorNoteL( R_CERTSAVER_ERROR_CACERTS_DB_CORRUPTED ); |
|
694 User::Leave( KErrExitApp ); |
|
695 } |
|
696 |
|
697 status = iWrapper->AddCert( iUnifiedCertStore->WritableCertStore( certstoreIndex ), |
|
698 labelBuf, iCertFormat, iCertOwnerType, 0, 0, iNewCert->Encoding() ); |
|
699 |
|
700 if ( ( status == KErrNone ) && ( iCertOwnerType == EPeerCertificate) ) |
|
701 { |
|
702 // Adding certificate succeded. Update trust site storage |
|
703 CTrustSitesStore* trustedSitesStore = CTrustSitesStore::NewL(); |
|
704 CleanupStack::PushL( trustedSitesStore ); |
|
705 TPtrC8 certBuf = iParser.CertificateBuf(); |
|
706 TInt err = trustedSitesStore->AddL( certBuf, labelBuf ); |
|
707 CleanupStack::PopAndDestroy( trustedSitesStore ); |
|
708 } |
|
709 |
|
710 // If error happened, show error note and give up. Otherwise, continue |
|
711 HandleSaveErrorL( status ); |
|
712 if ( status ) |
|
713 { |
|
714 User::Leave( KErrCancel ); |
|
715 } |
|
716 else |
|
717 { |
|
718 if ( ECACertificate == iCertOwnerType ) |
|
719 { |
|
720 ++iSavedCACertsCount; |
|
721 } |
|
722 else |
|
723 { |
|
724 ++iSavedUserCertsCount; |
|
725 } |
|
726 } |
|
727 } |
|
728 else |
|
729 { |
|
730 // If there is none WritableCertStore, |
|
731 // then at least cacerts.dat is corrupted. |
|
732 ShowErrorNoteL( R_CERTSAVER_ERROR_CACERTS_DB_CORRUPTED ); |
|
733 User::Leave( KErrExitApp ); |
|
734 } |
|
735 |
|
736 if ( ECACertificate == iCertOwnerType ) |
|
737 { |
|
738 // get just saved certificate |
|
739 // first, create a filter |
|
740 filter = CCertAttributeFilter::NewL(); |
|
741 filter->SetLabel( labelBuf ); |
|
742 filter->SetFormat( certFormat ); |
|
743 filter->SetOwnerType( ECACertificate ); |
|
744 |
|
745 // Delete array |
|
746 iEntries.Close(); |
|
747 // then list certificates |
|
748 status = iWrapper->ListCerts( *iUnifiedCertStore, iEntries, *filter ); |
|
749 delete filter; |
|
750 filter = NULL; |
|
751 |
|
752 // If error happened, show error note and give up. Otherwise, continue |
|
753 if ( status ) |
|
754 { |
|
755 HandleSaveErrorL( status ); |
|
756 User::Leave( KErrExitApp ); |
|
757 } |
|
758 |
|
759 // takes ownership of trusterUids |
|
760 status = iWrapper->SetApplicability( |
|
761 iUnifiedCertStore->WritableCertStore( certstoreIndex ), *(iEntries[0]), iTrusterUids ); |
|
762 |
|
763 // If error happened, show error note and give up. Otherwise, continue |
|
764 if ( status ) |
|
765 { |
|
766 HandleSaveErrorL( status ); |
|
767 User::Leave( KErrExitApp ); |
|
768 } |
|
769 |
|
770 // Downloaded certificate is trusted by default |
|
771 status = iWrapper->SetTrust( |
|
772 iUnifiedCertStore->WritableCertStore(certstoreIndex), *(iEntries[0]), ETrue ); |
|
773 if ( status ) |
|
774 { |
|
775 HandleSaveErrorL( status ); |
|
776 } |
|
777 |
|
778 |
|
779 } // if ( ECACertificate == iCertOwnerType ) |
|
780 } |
|
781 // ---------------------------------------------------------- |
|
782 // CCertSaverModel::QueryLabel() |
|
783 // Queries label from user and confirms that it doesn't |
|
784 // already exist. |
|
785 // ---------------------------------------------------------- |
|
786 // |
|
787 TInt CCertSaverModel::QueryLabelL( TCertLabel& aLabel, CUnifiedCertStore& aStore ) |
|
788 { |
|
789 CCertAttributeFilter* filter = NULL; |
|
790 TInt status = KErrNone; |
|
791 RMPointerArray<CCTCertInfo> entries; |
|
792 TBool loop = ETrue; |
|
793 |
|
794 while ( loop ) |
|
795 { |
|
796 CAknTextQueryDialog* dialog = CAknTextQueryDialog::NewL( aLabel ); |
|
797 if ( !dialog->ExecuteLD( R_CERTSAVER_LABEL_QUERY ) ) |
|
798 { |
|
799 // cancel |
|
800 ShowConfirmationNoteL( R_CERTSAVER_CERT_DISCARDED ); |
|
801 return KErrCancel; |
|
802 } |
|
803 // Create filter to confirm that label doesn't already exist. |
|
804 filter = CCertAttributeFilter::NewL(); |
|
805 filter->SetLabel( aLabel ); |
|
806 |
|
807 // then list certificates |
|
808 status = iWrapper->ListCerts( aStore, entries, *filter ); |
|
809 CleanupClosePushL( entries ); |
|
810 delete filter; |
|
811 |
|
812 // If error happened, show error note and give up. Otherwise, continue |
|
813 if ( status ) |
|
814 { |
|
815 HandleSaveErrorL( status ); |
|
816 User::Leave( KErrExitApp ); |
|
817 } |
|
818 |
|
819 if ( entries.Count() ) |
|
820 { |
|
821 // Label already exists. Label is queried again. |
|
822 HandleSaveErrorL( KErrBadName ); |
|
823 } |
|
824 else |
|
825 { |
|
826 // Label didn't exist. |
|
827 loop = EFalse; |
|
828 } |
|
829 CleanupStack::PopAndDestroy( &entries ); // entries |
|
830 } // while |
|
831 |
|
832 return status; |
|
833 } |
|
834 |
|
835 // ---------------------------------------------------------- |
|
836 // CCertSaverModel::HandleSaveErrorL() const |
|
837 // Shows a note according to aStatus. aStatus is the status |
|
838 // of the save operation. |
|
839 // ---------------------------------------------------------- |
|
840 // |
|
841 void CCertSaverModel::HandleSaveErrorL( TInt aStatus ) const |
|
842 { |
|
843 switch ( aStatus ) |
|
844 { |
|
845 case KErrNone: |
|
846 { |
|
847 ShowConfirmationNoteL( R_CERTSAVER_ERROR_SAVEOK ); |
|
848 break; |
|
849 } |
|
850 case KErrNotSupported: |
|
851 { |
|
852 ShowErrorNoteL( R_CERTSAVER_ERROR_UNSUPPORTED_CERT ); |
|
853 break; |
|
854 } |
|
855 case KErrBadName: |
|
856 { |
|
857 ShowErrorNoteL( R_CERTSAVER_ERROR_LABEL_ALREADY_EXISTS ); |
|
858 break; |
|
859 } |
|
860 case KErrAlreadyExists: |
|
861 { |
|
862 ShowErrorNoteL( R_CERTSAVER_ERROR_ALREADY_EXISTS ); |
|
863 break; |
|
864 } |
|
865 case KErrArgument: |
|
866 { |
|
867 ShowErrorNoteL( R_CERTSAVER_ERROR_CACERTS_DB_CORRUPTED ); |
|
868 break; |
|
869 } |
|
870 default: |
|
871 { |
|
872 //No error note defined for unknown error. |
|
873 User::Leave( aStatus ); |
|
874 break; |
|
875 } |
|
876 } //switch |
|
877 } |
|
878 |
|
879 // ---------------------------------------------------------- |
|
880 // CCertSaverModel::AddToMessageWithStringL() const |
|
881 // String loaded from resources with StringLoader. |
|
882 // ---------------------------------------------------------- |
|
883 // |
|
884 void CCertSaverModel::AddToMessageWithStringL( |
|
885 TDes& aMessage, TInt aStringResID, const TDesC& aString ) const |
|
886 { |
|
887 HBufC* promptPtr = NULL; |
|
888 promptPtr = StringLoader::LoadL( aStringResID, aString ); |
|
889 CleanupStack::PushL( promptPtr ); |
|
890 TPtrC prompt( promptPtr->Des() ); |
|
891 |
|
892 aMessage.Append( prompt ); |
|
893 |
|
894 CleanupStack::PopAndDestroy( promptPtr ); // promptPtr |
|
895 } |
|
896 |
|
897 // ---------------------------------------------------------- |
|
898 // CCertSaverModel::AddToMessageWithStringL() const |
|
899 // String loaded from resources with StringLoader. |
|
900 // ---------------------------------------------------------- |
|
901 // |
|
902 void CCertSaverModel::AddToMessageWithIntL( |
|
903 TDes& aMessage, |
|
904 TInt aStringResID, |
|
905 TInt aInt ) const |
|
906 { |
|
907 HBufC* promptPtr = NULL; |
|
908 promptPtr = StringLoader::LoadL( aStringResID, aInt ); |
|
909 CleanupStack::PushL( promptPtr ); |
|
910 TPtrC prompt( promptPtr->Des() ); |
|
911 |
|
912 aMessage.Append( prompt ); |
|
913 aMessage.Append( KEnter ); |
|
914 |
|
915 CleanupStack::PopAndDestroy( promptPtr ); // promptPtr |
|
916 } |
|
917 |
|
918 // ---------------------------------------------------------- |
|
919 // CCertSaverModel::AddToMessageL() const |
|
920 // String loaded from resources with StringLoader. |
|
921 // ---------------------------------------------------------- |
|
922 // |
|
923 void CCertSaverModel::AddToMessageL( TDes& aMessage, TInt aStringResID ) const |
|
924 { |
|
925 HBufC* promptPtr = NULL; |
|
926 promptPtr = StringLoader::LoadL( aStringResID ); |
|
927 CleanupStack::PushL( promptPtr ); |
|
928 TPtrC prompt( promptPtr->Des() ); |
|
929 |
|
930 aMessage.Append( prompt ); |
|
931 aMessage.Append( KEnter ); |
|
932 |
|
933 CleanupStack::PopAndDestroy( promptPtr ); // promptPtr |
|
934 } |
|
935 |
|
936 // ---------------------------------------------------------- |
|
937 // CCertSaverModel::ConstructMessageL() const |
|
938 // Creates the certificate details message shown to the user. |
|
939 // ---------------------------------------------------------- |
|
940 // |
|
941 void CCertSaverModel::ConstructMessageL( TDes& aMessage ) const |
|
942 { |
|
943 HBufC16* issuerName = NULL; |
|
944 HBufC16* subjectName = NULL; |
|
945 |
|
946 |
|
947 X509CertNameParser::SubjectFullNameL( *((CX509Certificate*)iNewCert), |
|
948 subjectName ); |
|
949 CleanupStack::PushL( subjectName ); |
|
950 |
|
951 X509CertNameParser::IssuerFullNameL( *((CX509Certificate*)iNewCert), |
|
952 issuerName ); |
|
953 CleanupStack::PushL( issuerName ); |
|
954 |
|
955 AddToMessageWithStringL( aMessage, R_CERTSAVER_TEXT_LABEL, |
|
956 CutCertificateField(*subjectName) ); |
|
957 AddNewlinesToMessage( aMessage ); |
|
958 |
|
959 AddToMessageWithStringL( aMessage, R_CERTSAVER_TEXT_ISSUER, |
|
960 CutCertificateField( *issuerName ) ); |
|
961 CleanupStack::PopAndDestroy( 2, subjectName ); |
|
962 AddNewlinesToMessage( aMessage ); |
|
963 |
|
964 if ( iCertOwnerType==EUserCertificate ) |
|
965 { |
|
966 AddKeyUsageL( aMessage, *((CX509Certificate*)iNewCert) ); |
|
967 } |
|
968 |
|
969 AddValidityPeriodL( aMessage, *((CX509Certificate*)iNewCert) ); |
|
970 |
|
971 // SHA-1 fingerprint |
|
972 TBuf<KFingerprintLength> divided_fingerprint; |
|
973 DivideToBlocks( iNewCert->Fingerprint(), divided_fingerprint ); |
|
974 AddToMessageWithStringL( aMessage, R_CERTSAVER_TEXT_FINGERPRINT, |
|
975 divided_fingerprint ); |
|
976 |
|
977 AddNewlinesToMessage( aMessage ); |
|
978 divided_fingerprint.Zero(); |
|
979 |
|
980 // MD5 fingerprint |
|
981 CMD5* md5 = CMD5::NewL(); |
|
982 CleanupStack::PushL( md5 ); |
|
983 TPtrC8 MD5fingerprint = md5->Hash( iNewCert->Encoding() ); |
|
984 |
|
985 // Divide fingerprint to blocks |
|
986 DivideToBlocks( MD5fingerprint, divided_fingerprint ); |
|
987 CleanupStack::PopAndDestroy( md5 ); |
|
988 AddToMessageWithStringL( aMessage, R_CERTSAVER_TEXT_FINGERPRINT_MD5, |
|
989 divided_fingerprint ); |
|
990 AddNewlinesToMessage( aMessage ); |
|
991 } |
|
992 |
|
993 // ----------------------------------------------------------------------------- |
|
994 // CCTSecurityDialogsAO::AddKeyUsageL(...) |
|
995 // ----------------------------------------------------------------------------- |
|
996 // |
|
997 void CCertSaverModel::AddKeyUsageL( TDes& aMessage, const CX509Certificate& aCert ) const |
|
998 { |
|
999 TKeyUsageX509 x509Usage = EX509UsageNone; |
|
1000 TKeyUsagePKCS15 pkcs15KeyUsage = EPKCS15UsageNone; |
|
1001 const CX509CertExtension* ext = aCert.Extension( KKeyUsage ); |
|
1002 if (ext) |
|
1003 { |
|
1004 CX509KeyUsageExt* keyUsageExt = |
|
1005 CX509KeyUsageExt::NewLC( ext->Data() ); |
|
1006 if ( keyUsageExt->IsSet( EX509DigitalSignature ) ) |
|
1007 { |
|
1008 x509Usage |= EX509UsageDigitalSignature; |
|
1009 } |
|
1010 if ( keyUsageExt->IsSet( EX509NonRepudiation ) ) |
|
1011 { |
|
1012 x509Usage |= EX509UsageNonRepudiation; |
|
1013 } |
|
1014 if ( keyUsageExt->IsSet( EX509KeyEncipherment ) ) |
|
1015 { |
|
1016 x509Usage |= EX509UsageKeyEncipherment; |
|
1017 } |
|
1018 if ( keyUsageExt->IsSet( EX509DataEncipherment ) ) |
|
1019 { |
|
1020 x509Usage |= EX509UsageDataEncipherment; |
|
1021 } |
|
1022 if ( keyUsageExt->IsSet( EX509KeyAgreement ) ) |
|
1023 { |
|
1024 x509Usage |= EX509UsageKeyAgreement; |
|
1025 } |
|
1026 if ( keyUsageExt->IsSet( EX509KeyCertSign ) ) |
|
1027 { |
|
1028 x509Usage |= EX509UsageKeyCertSign; |
|
1029 } |
|
1030 if ( keyUsageExt->IsSet( EX509CRLSign ) ) |
|
1031 { |
|
1032 x509Usage |= EX509UsageCRLSign; |
|
1033 } |
|
1034 if ( keyUsageExt->IsSet( EX509EncipherOnly ) ) |
|
1035 { |
|
1036 x509Usage |= EX509UsageEncipherOnly; |
|
1037 } |
|
1038 if ( keyUsageExt->IsSet( EX509DecipherOnly ) ) |
|
1039 { |
|
1040 x509Usage |= EX509UsageDecipherOnly; |
|
1041 } |
|
1042 CleanupStack::PopAndDestroy( keyUsageExt ); |
|
1043 } |
|
1044 |
|
1045 pkcs15KeyUsage = KeyUsageX509ToPKCS15Private( x509Usage ); |
|
1046 |
|
1047 TInt usage = 0; |
|
1048 switch( pkcs15KeyUsage ) |
|
1049 { |
|
1050 case EPKCS15UsageSignSignRecover: |
|
1051 case EPKCS15UsageSign: |
|
1052 case EPKCS15UsageSignDecrypt: |
|
1053 { |
|
1054 usage = R_QTN_CM_CLIENT_AUTHENTICATION; |
|
1055 break; |
|
1056 } |
|
1057 case EPKCS15UsageNonRepudiation: |
|
1058 { |
|
1059 usage = R_QTN_CM_DIGITAL_SIGNING; |
|
1060 break; |
|
1061 } |
|
1062 default: |
|
1063 { |
|
1064 usage = R_QTN_CM_NOT_DEFINED; |
|
1065 break; |
|
1066 } |
|
1067 } |
|
1068 AddToMessageL( aMessage, R_QTN_CM_KEY_USAGE ); |
|
1069 HBufC* usageString = iAppUi->CoeEnv()->AllocReadResourceLC( usage ); |
|
1070 aMessage.Append( *usageString ); |
|
1071 CleanupStack::PopAndDestroy( usageString ); |
|
1072 AddNewlinesToMessage( aMessage ); |
|
1073 } |
|
1074 |
|
1075 // ----------------------------------------------------------------------------- |
|
1076 // CCTSecurityDialogsAO::AddValidityPeriodL(...) |
|
1077 // ----------------------------------------------------------------------------- |
|
1078 // |
|
1079 void CCertSaverModel::AddValidityPeriodL( |
|
1080 TDes& aMessage, const CX509Certificate& aCert ) const |
|
1081 { |
|
1082 // Hometime's offset to UTC |
|
1083 TLocale locale; |
|
1084 TTimeIntervalSeconds offSet = locale.UniversalTimeOffset(); |
|
1085 AddToMessageL( aMessage, R_CERTSAVER_QTN_CM_VALID_FROM ); |
|
1086 |
|
1087 const CValidityPeriod& validityPeriod = aCert.ValidityPeriod(); |
|
1088 TTime startValue = validityPeriod.Start(); |
|
1089 startValue += offSet; |
|
1090 TBuf<KMaxLengthTextDateString> startString; |
|
1091 // read format string from AVKON resource |
|
1092 HBufC* dateFormatString = iAppUi->CoeEnv()->AllocReadResourceLC( |
|
1093 R_QTN_DATE_USUAL_WITH_ZERO ); |
|
1094 // format the date to user readable format. The format is locale dependent |
|
1095 startValue.FormatL( startString, *dateFormatString ); |
|
1096 AknTextUtils::DisplayTextLanguageSpecificNumberConversion( startString ); |
|
1097 CleanupStack::PopAndDestroy( dateFormatString ); // dateFormatString |
|
1098 aMessage.Append( startString ); |
|
1099 AddNewlinesToMessage( aMessage ); |
|
1100 |
|
1101 AddToMessageL( aMessage, R_CERTSAVER_QTN_CM_VALID_UNTIL ); |
|
1102 TTime finishValue = validityPeriod.Finish(); |
|
1103 finishValue += offSet; |
|
1104 TBuf<KMaxLengthTextDateString> finishString; |
|
1105 // read format string from AVKON resource |
|
1106 dateFormatString = iAppUi->CoeEnv()->AllocReadResourceLC( |
|
1107 R_QTN_DATE_USUAL_WITH_ZERO ); |
|
1108 // format the date to user readable format. The format is locale dependent |
|
1109 finishValue.FormatL( finishString, *dateFormatString ); |
|
1110 AknTextUtils::DisplayTextLanguageSpecificNumberConversion( finishString ); |
|
1111 CleanupStack::PopAndDestroy(); // dateFormatString |
|
1112 aMessage.Append( finishString ); |
|
1113 AddNewlinesToMessage( aMessage ); |
|
1114 } |
|
1115 |
|
1116 // ---------------------------------------------------------- |
|
1117 // CCertSaverModel::AddNewlinesToMessage() const |
|
1118 // Adds two new lines to message. |
|
1119 // ---------------------------------------------------------- |
|
1120 // |
|
1121 void CCertSaverModel::AddNewlinesToMessage( TDes& aMessage ) const |
|
1122 { |
|
1123 aMessage.Append( KDoubleEnter ); |
|
1124 } |
|
1125 |
|
1126 // ---------------------------------------------------------- |
|
1127 // CCertSaverModel::CertificateSupported() const |
|
1128 // Checks that cert is of supported type. |
|
1129 // ---------------------------------------------------------- |
|
1130 // |
|
1131 TBool CCertSaverModel::CertificateSupported() const |
|
1132 { |
|
1133 if ( iCertFormat == EX509Certificate && |
|
1134 ( iCertOwnerType == ECACertificate || |
|
1135 iCertOwnerType == EPeerCertificate || |
|
1136 iCertOwnerType == EUserCertificate)) |
|
1137 { |
|
1138 return ETrue; |
|
1139 } |
|
1140 return EFalse; |
|
1141 } |
|
1142 |
|
1143 |
|
1144 // ---------------------------------------------------------- |
|
1145 // CCertSaverModel::CertificateOkL() const |
|
1146 // Checks that cert is ok. Shows an error note if not. |
|
1147 // If certificate is not valid yet/anymore an error note is shown |
|
1148 // but ETrue is returned so that user can still save the |
|
1149 // certificate. |
|
1150 // ---------------------------------------------------------- |
|
1151 // |
|
1152 TBool CCertSaverModel::CertificateOkL() const |
|
1153 { |
|
1154 if ( !CertificateSupported() ) |
|
1155 { |
|
1156 ShowErrorNoteL( R_CERTSAVER_ERROR_UNSUPPORTED_CERT ); |
|
1157 return EFalse; |
|
1158 } |
|
1159 if ( CertNotValidAnymore() ) |
|
1160 { |
|
1161 ShowErrorNoteL( R_CERTSAVER_ERROR_CERT_NOT_VALID ); |
|
1162 return ETrue; |
|
1163 } |
|
1164 else if ( CertNotValidYet() ) |
|
1165 { |
|
1166 ShowErrorNoteL( R_CERTSAVER_ERROR_CERT_NOT_VALID_YET ); |
|
1167 } |
|
1168 return ETrue; |
|
1169 } |
|
1170 |
|
1171 // ---------------------------------------------------------- |
|
1172 // CCertSaverModel::CertNotValidAnymore() const |
|
1173 // Checks if cert isn't valid anymore. |
|
1174 // ---------------------------------------------------------- |
|
1175 // |
|
1176 TBool CCertSaverModel::CertNotValidAnymore() const |
|
1177 { |
|
1178 TTime homeTime; |
|
1179 homeTime.HomeTime(); |
|
1180 if ( iNewCert->ValidityPeriod().Finish() < homeTime ) |
|
1181 { |
|
1182 return ETrue; |
|
1183 } |
|
1184 return EFalse; |
|
1185 } |
|
1186 |
|
1187 // ---------------------------------------------------------- |
|
1188 // CCertSaverModel::CertNotValidYet() const |
|
1189 // Checks if cert isn't valid yet. |
|
1190 // ---------------------------------------------------------- |
|
1191 // |
|
1192 TBool CCertSaverModel::CertNotValidYet() const |
|
1193 { |
|
1194 TTime homeTime; |
|
1195 homeTime.HomeTime(); |
|
1196 if ( iNewCert->ValidityPeriod().Start() > homeTime ) |
|
1197 { |
|
1198 return ETrue; |
|
1199 } |
|
1200 return EFalse; |
|
1201 } |
|
1202 |
|
1203 // ---------------------------------------------------------- |
|
1204 // CCertSaverModel::ShowInformationNoteL() const |
|
1205 // Creates and shows a confirmation note. |
|
1206 // ---------------------------------------------------------- |
|
1207 // |
|
1208 void CCertSaverModel::ShowInformationNoteL( TInt aResourceID ) const |
|
1209 { |
|
1210 HBufC* buffer = iAppUi->CoeEnv()->AllocReadResourceLC( aResourceID ); |
|
1211 CAknInformationNote* note = new (ELeave) CAknInformationNote( ETrue ); |
|
1212 note->ExecuteLD( buffer->Des() ); |
|
1213 CleanupStack::PopAndDestroy( buffer ); |
|
1214 } |
|
1215 // ---------------------------------------------------------- |
|
1216 // CCertSaverModel::ShowConfirmationNoteL() const |
|
1217 // Creates and shows a confirmation note. |
|
1218 // ---------------------------------------------------------- |
|
1219 // |
|
1220 void CCertSaverModel::ShowConfirmationNoteL( TInt aResourceID ) const |
|
1221 { |
|
1222 HBufC* buffer = iAppUi->CoeEnv()->AllocReadResourceLC( aResourceID ); |
|
1223 CAknConfirmationNote* note = new (ELeave) CAknConfirmationNote( ETrue ); |
|
1224 note->ExecuteLD( buffer->Des() ); |
|
1225 CleanupStack::PopAndDestroy( buffer ); |
|
1226 } |
|
1227 |
|
1228 // ---------------------------------------------------------- |
|
1229 // CCertSaverModel::ShowErrorNoteL() const |
|
1230 // Creates and shows an error note. |
|
1231 // ---------------------------------------------------------- |
|
1232 // |
|
1233 void CCertSaverModel::ShowErrorNoteL( TInt aResourceID ) const |
|
1234 { |
|
1235 HBufC* buffer = iAppUi->CoeEnv()->AllocReadResourceLC( aResourceID ); |
|
1236 CAknErrorNote* note = new (ELeave) CAknErrorNote( ETrue ); |
|
1237 note->ExecuteLD(buffer->Des()); |
|
1238 CleanupStack::PopAndDestroy( buffer ); |
|
1239 } |
|
1240 |
|
1241 // ---------------------------------------------------------- |
|
1242 // CCertSaverModel::TrimCertificateFields() const |
|
1243 // Trims given descriptor so that everything after and |
|
1244 // including the fourth semicolon (;) is cropped. |
|
1245 // Returns the trimmed certificate field. |
|
1246 // ---------------------------------------------------------- |
|
1247 // |
|
1248 TPtrC CCertSaverModel::TrimCertificateFields( TPtrC aField ) const |
|
1249 { |
|
1250 TPtrC cutField = CutCertificateField( aField ); |
|
1251 // Find one semicolon at a time and crop the |
|
1252 // helpField from the left to search for the next semicolon |
|
1253 TInt position = cutField.Locate( ';' ); // 1st semicolon |
|
1254 TInt fieldLength = cutField.Length(); |
|
1255 |
|
1256 // Need to check that position is not bigger than the length of cutField |
|
1257 if ( position != KErrNotFound && position < fieldLength ) |
|
1258 { |
|
1259 // Locate function counts from zero, Mid function |
|
1260 // counts also from zero, add one to exclude the found semicolon |
|
1261 TInt totalPosition = position; |
|
1262 TPtrC field = cutField.Mid(totalPosition + 1); |
|
1263 position = field.Locate(';'); // 2nd semicolon |
|
1264 fieldLength = field.Length(); |
|
1265 |
|
1266 if ( position != KErrNotFound && position < fieldLength ) |
|
1267 { |
|
1268 totalPosition += position + 1; |
|
1269 TPtrC field = cutField.Mid( totalPosition + 1 ); |
|
1270 position = field.Locate( ';' ); // 3rd semicolon |
|
1271 fieldLength = field.Length(); |
|
1272 |
|
1273 if ( position != KErrNotFound && position < fieldLength ) |
|
1274 { |
|
1275 totalPosition += position + 1; |
|
1276 TPtrC field = cutField.Mid( totalPosition + 1 ); |
|
1277 position = field.Locate( ';' ); // 4th semicolon |
|
1278 fieldLength = field.Length(); |
|
1279 |
|
1280 if ( position != KErrNotFound && position < fieldLength ) |
|
1281 { |
|
1282 totalPosition += position + 1; |
|
1283 // Extract the leftmost part of the data field up to n:th character |
|
1284 TPtrC field = cutField.Mid( 0, totalPosition ); |
|
1285 return field; |
|
1286 } // if |
|
1287 } // if |
|
1288 } // if |
|
1289 } // if |
|
1290 return cutField; |
|
1291 } |
|
1292 |
|
1293 // ---------------------------------------------------------- |
|
1294 // CCertSaverModel::CutCertificateField() const |
|
1295 // If given descriptor is larger than defined maximum length |
|
1296 // this function cuts it. |
|
1297 // ---------------------------------------------------------- |
|
1298 // |
|
1299 TPtrC CCertSaverModel::CutCertificateField( TPtrC aField ) const |
|
1300 { |
|
1301 TInt fieldLength = aField.Length(); |
|
1302 if ( fieldLength >= KMaxLengthTextCertIdentifierVisible ) |
|
1303 { |
|
1304 TPtrC cutCertLabel = aField.Mid( 0, KMaxLengthTextCertIdentifierVisible ); |
|
1305 return cutCertLabel; |
|
1306 } |
|
1307 return aField; |
|
1308 } |
|
1309 |
|
1310 // ---------------------------------------------------------- |
|
1311 // CCertSaverModel::QueryTrusterUidsL() |
|
1312 // Does needed tasks to exit. |
|
1313 // ---------------------------------------------------------- |
|
1314 // |
|
1315 TInt CCertSaverModel::QueryTrusterUidsL( RArray<TUid>& aUids ) |
|
1316 { |
|
1317 TInt ret = KErrCancel; |
|
1318 CArrayFixFlat<TInt>* selectionArray = |
|
1319 new (ELeave) CArrayFixFlat<TInt>( KTrusterArrayInitSize ); |
|
1320 CleanupStack::PushL( selectionArray ); |
|
1321 CDesCArray* itemsArray = new (ELeave) CDesCArrayFlat( KTrusterArrayInitSize ); |
|
1322 CleanupStack::PushL( itemsArray ); |
|
1323 |
|
1324 CCertificateAppInfoManager* appInfoManager = |
|
1325 CCertificateAppInfoManager::NewL( iFs, EFalse ); |
|
1326 CleanupStack::PushL( appInfoManager ); |
|
1327 // copy applications to own array |
|
1328 const RArray<TCertificateAppInfo>& apps = appInfoManager->Applications(); |
|
1329 RArray<TCertificateAppInfo> appsInItemArray( KTrusterArrayInitSize ); |
|
1330 CleanupClosePushL( appsInItemArray ); |
|
1331 UpdateTrustListboxItemL( apps, appsInItemArray, *itemsArray ); |
|
1332 |
|
1333 CAknListQueryDialog* dlg = new (ELeave) CAknListQueryDialog( selectionArray ); |
|
1334 CleanupStack::PushL( dlg ); |
|
1335 dlg->PrepareLC( R_CERTSAVER_TRUST_SETTINGS_QUERY ); |
|
1336 dlg->SetItemTextArray( itemsArray ); |
|
1337 dlg->SetOwnershipType( ELbmDoesNotOwnItemArray ); |
|
1338 if ( dlg->RunLD() ) |
|
1339 { |
|
1340 for ( TInt i = 0; i < selectionArray->Count(); ++i ) |
|
1341 { |
|
1342 TInt ii = (*selectionArray)[ i ]; |
|
1343 aUids.Append( appsInItemArray[ ii ].Id() ); |
|
1344 } |
|
1345 ret = KErrNone; |
|
1346 } |
|
1347 else |
|
1348 { |
|
1349 ShowConfirmationNoteL( R_CERTSAVER_CERT_DISCARDED ); |
|
1350 ret = KErrCancel; |
|
1351 } |
|
1352 CleanupStack::Pop( dlg ); |
|
1353 CleanupStack::PopAndDestroy( 4, selectionArray ); |
|
1354 return ret; |
|
1355 } |
|
1356 |
|
1357 // ---------------------------------------------------------- |
|
1358 // CCertSaverModel::QueryTrustedSiteL() |
|
1359 // Shows query for trusted site certificate |
|
1360 // ---------------------------------------------------------- |
|
1361 // |
|
1362 TInt CCertSaverModel::QueryTrustedSiteL() |
|
1363 { |
|
1364 TInt ret = KErrCancel; |
|
1365 HBufC* label = NULL; |
|
1366 HBufC* secondaryName = NULL; |
|
1367 TCertLabel labelBuf; |
|
1368 |
|
1369 X509CertNameParser::PrimaryAndSecondaryNameL( |
|
1370 (*(CX509Certificate*)iNewCert), label, secondaryName ); |
|
1371 CleanupStack::PushL( label ); |
|
1372 delete secondaryName; |
|
1373 secondaryName = NULL; |
|
1374 labelBuf = label->Des().Left( CERTSAVER_MAX_LABEL_LEN ); |
|
1375 |
|
1376 |
|
1377 HBufC* prompt = StringLoader::LoadLC( R_CERTSAVER_TRUSTEDSITE_WARNING, labelBuf ); |
|
1378 |
|
1379 CAknMessageQueryDialog* note = CAknMessageQueryDialog::NewL( *prompt ); |
|
1380 |
|
1381 note->PrepareLC( R_CERTSAVER_TRUSTED_SITE_QUERY ); |
|
1382 note->SetPromptL( *prompt ); |
|
1383 |
|
1384 if ( note->RunLD() ) |
|
1385 { |
|
1386 ret = KErrNone; |
|
1387 } |
|
1388 else |
|
1389 { |
|
1390 ShowConfirmationNoteL( R_CERTSAVER_CERT_DISCARDED ); |
|
1391 ret = KErrCancel; |
|
1392 } |
|
1393 |
|
1394 CleanupStack::PopAndDestroy( prompt ); |
|
1395 |
|
1396 CleanupStack::PopAndDestroy( label ); |
|
1397 return ret; |
|
1398 } |
|
1399 |
|
1400 // ---------------------------------------------------------- |
|
1401 // CCertSaverModel::UpdateTrustListboxItemL() |
|
1402 // Updates trust setting listbox items |
|
1403 // ---------------------------------------------------------- |
|
1404 // |
|
1405 void CCertSaverModel::UpdateTrustListboxItemL( |
|
1406 const RArray<TCertificateAppInfo>& aApps, |
|
1407 RArray<TCertificateAppInfo>& aAppsInItemArray, |
|
1408 CDesCArray& aItemsArray ) const |
|
1409 { |
|
1410 for ( TInt i = 0; i < aApps.Count(); i++ ) |
|
1411 { |
|
1412 TCertificateAppInfo appInfo = aApps[ i ]; |
|
1413 TBuf<KItemBufLen> item; |
|
1414 item.Append( KCertSaverListBoxItemPrefix ); |
|
1415 TBuf<KMaxName> resource; |
|
1416 |
|
1417 switch( appInfo.Id().iUid ) |
|
1418 { |
|
1419 case KWTLSTrusterUID: |
|
1420 { |
|
1421 // X.509 certiticate isn't needed with WTLS |
|
1422 break; |
|
1423 } |
|
1424 case KInternetTrusterUID: |
|
1425 { |
|
1426 iAppUi->CoeEnv()->ReadResource( |
|
1427 resource, R_CERTSAVER_ITEM_MAIL_IMAGE_CONN ); |
|
1428 break; |
|
1429 } |
|
1430 case KApplicationControllerTrusterUID: |
|
1431 { |
|
1432 // SWI certs are ROM based in platsec world. |
|
1433 break; |
|
1434 } |
|
1435 case KJavaInstallTrusterUID: |
|
1436 { |
|
1437 // MIDP certstore is read-only.. |
|
1438 break; |
|
1439 } |
|
1440 case KOCSPTrusterUID: |
|
1441 { |
|
1442 iAppUi->CoeEnv()->ReadResource( resource, R_CERTSAVER_ITEM_OCSP ); |
|
1443 break; |
|
1444 } |
|
1445 case KVPNUID: |
|
1446 { |
|
1447 iAppUi->CoeEnv()->ReadResource( resource, R_CERTSAVER_ITEM_VPN ); |
|
1448 break; |
|
1449 } |
|
1450 default: |
|
1451 { |
|
1452 resource = appInfo.Name(); |
|
1453 break; |
|
1454 } |
|
1455 } |
|
1456 if ( 0 < resource.Length()) |
|
1457 { |
|
1458 item.Append( resource ); |
|
1459 aItemsArray.AppendL( item ); |
|
1460 aAppsInItemArray.Append( appInfo ); |
|
1461 resource.Zero(); |
|
1462 } |
|
1463 } |
|
1464 } |
|
1465 |
|
1466 // --------------------------------------------------------- |
|
1467 // CCertManUIViewAuthority::DevideToBlocks |
|
1468 // --------------------------------------------------------- |
|
1469 // |
|
1470 void CCertSaverModel::DivideToBlocks( const TDesC8& aInput, TDes& aOutput ) const |
|
1471 { |
|
1472 _LIT( KBlockSeparator, " " ); |
|
1473 const TInt KBlockLength = 2; |
|
1474 TInt blockIndex = 0; |
|
1475 for ( TInt j = 0 ; j < aInput.Length() ; j++ ) |
|
1476 { |
|
1477 if ( blockIndex == KBlockLength ) |
|
1478 { |
|
1479 aOutput.Append( KBlockSeparator ); |
|
1480 blockIndex = 0; |
|
1481 } |
|
1482 aOutput.AppendNumFixedWidthUC( (TUint)(aInput[ j ]), EHex, 2 ); |
|
1483 ++blockIndex; |
|
1484 } |
|
1485 } |
|
1486 |
|
1487 // ---------------------------------------------------- |
|
1488 // CCertSaverModel::SavePKCS12L() |
|
1489 // Saves content of the PKCS#12 file |
|
1490 // ---------------------------------------------------- |
|
1491 // |
|
1492 void CCertSaverModel::SavePKCS12L() |
|
1493 { |
|
1494 HBufC* message = HBufC::NewLC( KMaxLengthTextMeassageBody ); |
|
1495 TPtr msgPtr = message->Des(); |
|
1496 ConstructPKCS12QueryMsgL(msgPtr, iParser.Keys().Count(), |
|
1497 iParser.UserCertificates().Count(), |
|
1498 iParser.CACertificates().Count() ); |
|
1499 TBool save = DoMessageQueryL( |
|
1500 R_MESSAGE_QUERY_DOSAVE, R_CERTSAVER_HEADER_PKCS12_FILE_CONTAINS, |
|
1501 *message ); |
|
1502 CleanupStack::PopAndDestroy( message ); |
|
1503 message = NULL; |
|
1504 if ( !save ) |
|
1505 { |
|
1506 ShowInformationNoteL( R_CERTSAVER_PKCS12_DISCARDED ); |
|
1507 User::Leave( KErrExitApp ); |
|
1508 } |
|
1509 TInt status = KErrNone; |
|
1510 // save private keys |
|
1511 TRAP( status, SavePrivateKeyL() ); |
|
1512 |
|
1513 // save user certificates if private key was saved. |
|
1514 if ( ( iSavedKeysCount > 0 || iKeyAlreadyExists ) && iParser.UserCertificates().Count() > 0 ) |
|
1515 { |
|
1516 for ( TInt i = 0; i < iParser.UserCertificates().Count(); i++ ) |
|
1517 { |
|
1518 const CX509Certificate* cert = iParser.UserCertificates().At(i); |
|
1519 iCertOwnerType = EUserCertificate; |
|
1520 iCertFormat = EX509Certificate; |
|
1521 iNewCert = cert; |
|
1522 TRAP( status, SaveCertL() ); |
|
1523 if ( KErrExitApp == status ) |
|
1524 { |
|
1525 User::Leave( KErrExitApp ); |
|
1526 } |
|
1527 } |
|
1528 } |
|
1529 // save CA certificates |
|
1530 if ( iParser.CACertificates().Count() > 0 ) |
|
1531 { |
|
1532 for ( TInt i = 0; i < iParser.CACertificates().Count(); i++ ) |
|
1533 { |
|
1534 const CX509Certificate* cert = iParser.CACertificates().At( i ); |
|
1535 iCertOwnerType = ECACertificate; |
|
1536 iCertFormat = EX509Certificate; |
|
1537 iNewCert = cert; |
|
1538 TRAP( status, SaveCertL() ); |
|
1539 if ( KErrExitApp == status ) |
|
1540 { |
|
1541 User::Leave( KErrExitApp ); |
|
1542 } |
|
1543 } |
|
1544 } |
|
1545 if ( iSavedCACertsCount != 0 || iSavedKeysCount != 0 |
|
1546 || iSavedUserCertsCount != 0 ) |
|
1547 { |
|
1548 message = HBufC::NewLC( KMaxLengthTextMeassageBody ); |
|
1549 TPtr msgPtr2 = message->Des(); |
|
1550 ConstructPKCS12QueryMsgL( |
|
1551 msgPtr2, iSavedKeysCount, iSavedUserCertsCount, iSavedCACertsCount ); |
|
1552 DoMessageQueryL( |
|
1553 R_MESSAGE_QUERY_SAVED, R_CERTSAVER_HEADER_SAVED, *message ); |
|
1554 CleanupStack::PopAndDestroy( message ); |
|
1555 } |
|
1556 else |
|
1557 { |
|
1558 ShowInformationNoteL( R_QTN_CM_PKCS12_SAVING_FAILED ); |
|
1559 } |
|
1560 } |
|
1561 |
|
1562 // ---------------------------------------------------------- |
|
1563 // CCertSaverModel::DoMessageQuery() |
|
1564 // Displays message query dialog for user. |
|
1565 // ---------------------------------------------------------- |
|
1566 // |
|
1567 TBool CCertSaverModel::DoMessageQueryL( |
|
1568 TInt aDialogResId, |
|
1569 TInt aHeadingResId, |
|
1570 TDesC& aMessage ) |
|
1571 { |
|
1572 CAknMessageQueryDialog* dlg = CAknMessageQueryDialog::NewL( aMessage ); |
|
1573 CleanupStack::PushL( dlg ); |
|
1574 dlg->PrepareLC( aDialogResId ); |
|
1575 |
|
1576 HBufC* header = StringLoader::LoadLC( aHeadingResId ); |
|
1577 dlg->QueryHeading()->SetTextL( header->Des() ); |
|
1578 CleanupStack::PopAndDestroy( header ); |
|
1579 CleanupStack::Pop( dlg ); |
|
1580 return dlg->RunLD(); |
|
1581 } |
|
1582 |
|
1583 // ---------------------------------------------------------- |
|
1584 // CCertSaverModel::ConstructPKCS12QueryMsgL() const |
|
1585 // Creates the certificate details message shown to the user. |
|
1586 // ---------------------------------------------------------- |
|
1587 // |
|
1588 void CCertSaverModel::ConstructPKCS12QueryMsgL( |
|
1589 TDes& aMessage, |
|
1590 TInt aPrivateKeys, |
|
1591 TInt aUserCerts, |
|
1592 TInt aCACerts ) const |
|
1593 { |
|
1594 if ( aPrivateKeys > 0 ) |
|
1595 { |
|
1596 if ( aPrivateKeys == 1 ) |
|
1597 { |
|
1598 AddToMessageL( aMessage, R_CERTSAVER_ONE_PRIVATE_KEY ); |
|
1599 } |
|
1600 else |
|
1601 { |
|
1602 AddToMessageWithIntL( aMessage, R_CERTSAVER_PRIVATE_KEYS, aPrivateKeys ); |
|
1603 } |
|
1604 } |
|
1605 if ( aUserCerts > 0 ) |
|
1606 { |
|
1607 if ( aUserCerts == 1 ) |
|
1608 { |
|
1609 AddToMessageL( |
|
1610 aMessage, R_CERTSAVER_ONE_PERSONAL_CERTIFICATE ); |
|
1611 } |
|
1612 else |
|
1613 { |
|
1614 AddToMessageWithIntL( |
|
1615 aMessage, R_CERTSAVER_PERSONAL_CERTIFICATES, aUserCerts ); |
|
1616 } |
|
1617 } |
|
1618 if ( aCACerts > 0 ) |
|
1619 { |
|
1620 |
|
1621 if ( aCACerts == 1 ) |
|
1622 { |
|
1623 AddToMessageL( |
|
1624 aMessage, R_CERTSAVER_ONE_AUTHORITY_CERTIFICATE ); |
|
1625 } |
|
1626 else |
|
1627 { |
|
1628 AddToMessageWithIntL( |
|
1629 aMessage, R_CERTSAVER_AUTHORITY_CERTIFICATES, aCACerts ); |
|
1630 } |
|
1631 } |
|
1632 } |
|
1633 |
|
1634 // End of File |