Added support for Event creation in worker thread
[platform/framework/native/appfw.git] / src / security / cert / FSecCert_X509CertificateStoreImpl.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file                FSecCert_X509CertificateStoreImpl.cpp
19  * @brief               This is the implementation file for _X509CertificateStoreImpl class.
20  */
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <new>
24 #include <unique_ptr.h>
25 #include <FBaseResult.h>
26 #include <FSecCertX509Certificate.h>
27 #include <FBaseSysLog.h>
28 #include <FBase_StringConverter.h>
29 #include <FSec_AccessController.h>
30 #include <FSec_AccessControlTypes.h>
31 #include <FSecCert_CertServer.h>
32 #include <FSecCert_CertService.h>
33 #include <FSecCert_CertServiceProxy.h>
34 #include <FSecCert_X509CertificateStoreImpl.h>
35
36 using namespace Tizen::Base;
37
38 namespace Tizen { namespace Security { namespace Cert
39 {
40
41 static const int _MAX_CERT_BUFFER_SIZE = 2048;
42
43 int
44 GetIndexFromCertType(int certType)
45 {
46         int index = 0;
47         switch (certType)
48         {
49         case _CERT_TYPE_ROOT_CA:
50                 index = 0;
51                 break;
52
53         case _CERT_TYPE_ROOT_DOMAIN1:
54                 index = 1;
55                 break;
56
57         case _CERT_TYPE_ROOT_DOMAIN3:
58                 index = 2;
59                 break;
60
61         default:
62                 SysTryReturn(NID_SEC_CERT, false, -1, E_INVALID_ARG, "[%s] Invalid certificate type.", GetErrorMessage(E_INVALID_ARG));
63                 break;
64         }
65
66         return index;
67 }
68
69 _X509CertificateStoreImpl::_X509CertificateStoreImpl(void)
70         : __certType(static_cast< int >(_CERT_TYPE_NOT_BOUNDED))
71         , __curPos(0)
72 {
73         ClearLastResult();
74
75         memset(__context, 0, sizeof(__context));
76
77         __pCertServiceProxy = _CertServiceProxy::GetInstance();
78         SysTryReturnVoidResult(NID_SEC_CERT, __pCertServiceProxy != null, E_SYSTEM, "[E_SYSTEM] Failed to get certificate proxy instance.");
79
80         // restore root CA cert DB
81         __pCertServiceProxy->RestoreRootCaIntegrity();
82         ClearLastResult();
83 }
84
85 _X509CertificateStoreImpl::~_X509CertificateStoreImpl(void)
86 {
87         if ((__certType > _CERT_TYPE_NOT_BOUNDED) && (__certType < _CERT_TYPE_MAX))
88         {
89                 __pCertServiceProxy->CloseCertificateStore(__certType);
90         }
91 }
92
93 result
94 _X509CertificateStoreImpl::GetName(String& name) const
95 {
96         name = L"CertServiceStore";
97         return E_SUCCESS;
98 }
99
100 result
101 _X509CertificateStoreImpl::SetCertificateSelector(const Tizen::Security::Cert::ICertificateSelector& selector)
102 {
103         result r = E_SUCCESS;
104
105         int prevIndex = GetIndexFromCertType(__certType);
106         if (__certType == _CERT_TYPE_USER_CERT)
107         {
108                 r = __pCertServiceProxy->CloseCertificateStore(__certType);
109                 SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to close certificate store.");
110         }
111         else if (prevIndex > -1 && __context[prevIndex] != 0)
112         {
113                 r = _CertServer::CloseCertificateStore(reinterpret_cast< CertificateStoreCtx >(__context[prevIndex]));
114                 __context[prevIndex] = 0;
115                 SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to close certificate store.");
116         }
117
118         int count = 0;
119         __curPos = 0;
120
121         CertificateType certType = (const_cast< ICertificateSelector& >(selector)).GetType();
122         switch (certType)
123         {
124         case ROOT_CA:
125                 __certType = _CERT_TYPE_ROOT_CA;
126                 break;
127
128         case OPERATOR_DOMAIN:
129                 __certType = _CERT_TYPE_ROOT_DOMAIN1;
130                 break;
131
132         case TRUSTED_THIRD_PARTY_DOMAIN:
133                 __certType = _CERT_TYPE_ROOT_DOMAIN3;
134                 break;
135
136         case USER_CERT:
137                 __certType = _CERT_TYPE_USER_CERT;
138                 return __pCertServiceProxy->OpenCertificateStoreByType(static_cast< _CaCertType >(__certType), count);
139
140         default:
141                 SysTryReturnResult(NID_SEC_CERT, false, E_INVALID_ARG, "Invalid certificate type.");
142                 break;
143         }
144
145         CertificateStoreCtx certList = null;
146         int index = GetIndexFromCertType(__certType);
147
148         if (__context[index] == 0)
149         {
150                 certList = _CertServer::OpenCertificateStoreByType(static_cast< _CaCertType >(__certType), &count);
151                 r = GetLastResult();
152                 SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to open certificate store.");
153                 __context[index] = reinterpret_cast< int >(certList);
154         }
155
156         return E_SUCCESS;
157 }
158
159 result
160 _X509CertificateStoreImpl::GetCertificateCount(int& count)
161 {
162         result r = E_SUCCESS;
163
164         if (__certType == _CERT_TYPE_USER_CERT)
165         {
166                 r = __pCertServiceProxy->GetCertificateCount(__certType, count);
167         }
168         else
169         {
170                 r = _AccessController::CheckUserPrivilege(_PRV_CERTIFICATE_READ);
171                 SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
172
173                 int index = GetIndexFromCertType(__certType);
174                 SysTryReturnResult(NID_SEC_CERT, index > -1, E_SYSTEM, "Failed to open certificate store.");
175                 count = _CertServer::GetCertificateCount(reinterpret_cast< CertificateStoreCtx >(__context[index]));
176         }
177
178         return r;
179 }
180
181 Tizen::Security::Cert::ICertificate*
182 _X509CertificateStoreImpl::GetNextCertificateN(void)
183 {
184         result r = E_SUCCESS;
185         ByteBuffer certBuffer;
186         byte certBytes[_MAX_CERT_BUFFER_SIZE] = {0, };
187         int certLen = sizeof(certBytes);
188         int curPos = __curPos;
189
190         ClearLastResult();
191
192         if (__certType == _CERT_TYPE_USER_CERT)
193         {
194                 r = __pCertServiceProxy->GetNextCertificate(__certType, curPos, certBytes, certLen);
195                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, r, "[%s] Failed to get next root certificate.", GetErrorMessage(r));
196         }
197         else
198         {
199                 r = _AccessController::CheckUserPrivilege(_PRV_CERTIFICATE_READ);
200                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_PRIVILEGE_DENIED, "The application does not have the privilege to call this method.");
201
202                 _CertRootCaInfo* pRootCa = null;
203                 _CertRootList* pTemp = null;
204                 int count = 0;
205
206                 int index = GetIndexFromCertType(__certType);
207                 SysTryReturnResult(NID_SEC_CERT, index > -1, null, "Failed to open certificate store.");
208
209                 CertificateStoreCtx certificateStoreCtx = reinterpret_cast< CertificateStoreCtx >(__context[index]);
210                 SysTryReturn(NID_SEC_CERT, certificateStoreCtx != null, null, E_INVALID_ARG, "Invalid certificate store context.");
211
212                 pRootCa = reinterpret_cast< _CertRootCaInfo* >(certificateStoreCtx);
213                 SysTryReturn(NID_SEC_CERT, pRootCa->pRootList != null, null, E_OBJ_NOT_FOUND, "Certificate list is empty.");
214
215                 pTemp = pRootCa->pRootList;
216
217                 while (count != curPos)
218                 {
219                         count++;
220                         SysTryReturn(NID_SEC_CERT, pTemp->pNext != null, null, E_OBJ_NOT_FOUND, "Certificate index not found.");
221
222                         pTemp = pTemp->pNext;
223                 }
224
225                 pRootCa->pCurrRootList = pTemp;
226                 if (certLen > static_cast< int >(pRootCa->pCurrRootList->length))
227                 {
228                         memcpy(certBytes, pRootCa->pCurrRootList->certificate, pRootCa->pCurrRootList->length);
229                         certLen = pRootCa->pCurrRootList->length;
230                 }
231                 else
232                 {
233                         memcpy(certBytes, pRootCa->pCurrRootList->certificate, certLen);
234                 }
235
236                 curPos++;
237         }
238
239         __curPos = curPos;
240
241         r = certBuffer.Construct(certLen);
242         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, r, "[%s] Failed to allocate memory.", GetErrorMessage(r));
243
244         r = certBuffer.SetArray(certBytes, 0, certLen);
245         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM]An unexpected system error occurred.");
246
247         certBuffer.Flip();
248
249         std::unique_ptr< X509Certificate > pCert(new (std::nothrow) X509Certificate());
250         SysTryReturn(NID_SEC_CERT, pCert != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
251
252         r = pCert->Construct(certBuffer);
253         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] X509Certificate instance is not constructed.");
254
255         return pCert.release();
256 }
257
258
259 result
260 _X509CertificateStoreImpl::Insert(CertificateType certificateType, const Tizen::Security::Cert::ICertificate& certificate)
261 {
262         result r = E_SUCCESS;
263         byte* pBuffer = null;
264         int bufferLen = 0;
265         _CaCertType certType = _CERT_TYPE_NOT_BOUNDED;
266
267         switch (certificateType)
268         {
269         case ROOT_CA:
270                 certType = _CERT_TYPE_ROOT_CA;
271                 break;
272
273         case OPERATOR_DOMAIN:
274                 certType = _CERT_TYPE_ROOT_DOMAIN1;
275                 break;
276
277         case TRUSTED_THIRD_PARTY_DOMAIN:
278                 certType = _CERT_TYPE_ROOT_DOMAIN3;
279                 break;
280
281         case USER_CERT:
282                 certType = _CERT_TYPE_USER_CERT;
283                 break;
284
285         default:
286                 SysTryReturnResult(NID_SEC_CERT, false, E_INVALID_ARG, "Invalid certificate type.");
287                 break;
288         }
289
290         std::unique_ptr< ByteBuffer > pEncodedData(certificate.GetEncodedDataN());
291         SysTryReturnResult(NID_SEC_CERT, pEncodedData != null, E_INVALID_ARG, "Failed to get encoded data on input certificate.");
292
293         pBuffer = const_cast< byte* >(pEncodedData->GetPointer());
294         SysTryReturnResult(NID_SEC_CERT, pBuffer != null, E_INVALID_ARG, "Invalid input argument passed.");
295
296         bufferLen = pEncodedData->GetRemaining();
297         SysTryReturnResult(NID_SEC_CERT, bufferLen > 0, E_INVALID_ARG, "Length value is not positive.");
298
299         if (certType == _CERT_TYPE_USER_CERT)
300         {
301                 r = __pCertServiceProxy->InsertUserCertChainPrivateKey(reinterpret_cast< char* >(pBuffer), bufferLen, null, 0);
302         }
303         else
304         {
305                 r = __pCertServiceProxy->InsertCaCertificate(static_cast< int >(certType), _CERT_X509, pBuffer, bufferLen);
306
307                 UpdateCertStoreContext(certType);
308                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update cert store.", GetErrorMessage(r));
309         }
310
311         if (r == E_FILE_ALREADY_EXIST)
312         {
313                 r = E_SUCCESS;
314         }
315         SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to insert root certificate.", GetErrorMessage(r));
316
317         return r;
318 }
319
320 result
321 _X509CertificateStoreImpl::InsertPkcs12(const String& filePath, const String& password, bool checkPrivilege)
322 {
323         result r = E_SUCCESS;
324         std::unique_ptr< char[] > pFilePath(_StringConverter::CopyToCharArrayN(filePath));
325         std::unique_ptr< char[] > pPassword(_StringConverter::CopyToCharArrayN(password));
326
327         SysTryReturnResult(NID_SEC_CERT, filePath.GetLength() > 0, E_INVALID_ARG, "Length of file path is not positive.");
328         SysTryReturnResult(NID_SEC_CERT, pFilePath != null, E_INVALID_ARG, "File path is invalid.");
329
330         //password can be null
331         r = __pCertServiceProxy->InsertPkcs12Content(pFilePath.get(), pPassword.get(), checkPrivilege);
332         if (r == E_FILE_ALREADY_EXIST)
333         {
334                 r = E_SUCCESS;
335         }
336         SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to insert pkcs 12 user certificate.", GetErrorMessage(r));
337
338         return r;
339 }
340
341
342 result
343 _X509CertificateStoreImpl::Update(CertificateType certificateType, const Tizen::Security::Cert::ICertificate& oldCert, const Tizen::Security::Cert::ICertificate& newCert)
344 {
345         result r = E_SUCCESS;
346         byte* pOldBuffer = null;
347         byte* pNewBuffer = null;
348         int oldBufferLen = 0;
349         int newBufferLen = 0;
350         _CaCertType certType = _CERT_TYPE_NOT_BOUNDED;
351
352         switch (certificateType)
353         {
354         case ROOT_CA:
355                 certType = _CERT_TYPE_ROOT_CA;
356                 break;
357
358         case OPERATOR_DOMAIN:
359                 certType = _CERT_TYPE_ROOT_DOMAIN1;
360                 break;
361
362         case TRUSTED_THIRD_PARTY_DOMAIN:
363                 certType = _CERT_TYPE_ROOT_DOMAIN3;
364                 break;
365
366         case USER_CERT:
367                 certType = _CERT_TYPE_USER_CERT;
368                 break;
369
370         default:
371                 SysTryReturnResult(NID_SEC_CERT, false, E_INVALID_ARG, "Invalid certificate type.");
372                 break;
373         }
374
375         std::unique_ptr< ByteBuffer > pOldEncodedData(oldCert.GetEncodedDataN());
376         SysTryReturnResult(NID_SEC_CERT, pOldEncodedData != null, E_INVALID_ARG, "Failed to get encoded data on old input certificate.");
377
378         pOldBuffer = const_cast< byte* >(pOldEncodedData->GetPointer());
379         SysTryReturnResult(NID_SEC_CERT, pOldBuffer != null, E_INVALID_ARG, "Invalid input argument passed.");
380
381         oldBufferLen = pOldEncodedData->GetRemaining();
382         SysTryReturnResult(NID_SEC_CERT, oldBufferLen > 0, E_INVALID_ARG, "Input old certificate length is not positive.");
383
384         pOldEncodedData.reset(null);
385
386         std::unique_ptr< ByteBuffer > pNewEncodedData(newCert.GetEncodedDataN());
387         SysTryReturnResult(NID_SEC_CERT, pNewEncodedData != null, E_INVALID_ARG, "Failed to get encoded data on new input certificate.");
388
389         pNewBuffer = const_cast< byte* >(pNewEncodedData->GetPointer());
390         SysTryReturnResult(NID_SEC_CERT, pNewBuffer != null, E_INVALID_ARG, "Invalid input argument passed.");
391
392         newBufferLen = pNewEncodedData->GetRemaining();
393         SysTryReturnResult(NID_SEC_CERT, newBufferLen > 0, E_INVALID_ARG, "Input new certificate length is not positive.");
394
395         if (certType == _CERT_TYPE_USER_CERT)
396         {
397                 CertificateHandle certHandle = 0;
398                 int certId = 0;
399
400                 r = _CertService::OpenCertificate(reinterpret_cast< char* >(pOldBuffer), oldBufferLen, &certHandle);
401                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to open certificates.", GetErrorMessage(r));
402
403                 r = _CertService::GetUserCertificateId(certHandle, certId);
404
405                 _CertService::CloseCertificate(&certHandle);
406                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to find user certificates in store.", GetErrorMessage(r));
407
408                 r = __pCertServiceProxy->RemoveUserCertChainByCertId(certId);
409                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to remove/update user certificates from store.", GetErrorMessage(r));
410
411                 r = __pCertServiceProxy->InsertUserCertChainPrivateKey(reinterpret_cast< char* >(pNewBuffer), newBufferLen, null, 0);
412                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to install/update user certificates.", GetErrorMessage(r));
413         }
414         else
415         {
416                 r = __pCertServiceProxy->UpdateCaCertificate(static_cast< int >(certType), pOldBuffer, oldBufferLen, pNewBuffer, newBufferLen);
417                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update certificate.", GetErrorMessage(r));
418
419                 UpdateCertStoreContext(certType);
420                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update cert store.", GetErrorMessage(r));
421         }
422
423         return r;
424 }
425
426
427 result
428 _X509CertificateStoreImpl::Remove(CertificateType certificateType, const Tizen::Security::Cert::ICertificate& certificate)
429 {
430         result r = E_SUCCESS;
431         byte* pBuffer = null;
432         int bufferLen = 0;
433
434         _CaCertType certType = _CERT_TYPE_NOT_BOUNDED;
435
436         switch (certificateType)
437         {
438         case ROOT_CA:
439                 certType = _CERT_TYPE_ROOT_CA;
440                 break;
441
442         case OPERATOR_DOMAIN:
443                 certType = _CERT_TYPE_ROOT_DOMAIN1;
444                 break;
445
446         case TRUSTED_THIRD_PARTY_DOMAIN:
447                 certType = _CERT_TYPE_ROOT_DOMAIN3;
448                 break;
449
450         case USER_CERT:
451                 certType = _CERT_TYPE_USER_CERT;
452                 break;
453
454         default:
455                 SysTryReturnResult(NID_SEC_CERT, false, E_INVALID_ARG, "Invalid certificate type.");
456                 break;
457         }
458
459         std::unique_ptr< ByteBuffer > pEncodedData(certificate.GetEncodedDataN());
460         SysTryReturnResult(NID_SEC_CERT, pEncodedData != null, E_INVALID_ARG, "Failed to get encoded data on input certificate.");
461
462         pBuffer = const_cast< byte* >(pEncodedData->GetPointer());
463         SysTryReturnResult(NID_SEC_CERT, pBuffer != null, E_INVALID_ARG, "Invalid input argument passed.");
464
465         bufferLen = pEncodedData->GetRemaining();
466         SysTryReturnResult(NID_SEC_CERT, bufferLen > 0, E_INVALID_ARG, "Input certificate length is not positive.");
467
468         if (certType == _CERT_TYPE_USER_CERT)
469         {
470                 CertificateHandle certHandle = 0;
471                 int certId = 0;
472
473                 r = _CertService::OpenCertificate(reinterpret_cast< char* >(pBuffer), bufferLen, &certHandle);
474                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to open certificates.", GetErrorMessage(r));
475
476                 r = _CertService::GetUserCertificateId(certHandle, certId);
477
478                 _CertService::CloseCertificate(&certHandle);
479                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to find user certificates in store.", GetErrorMessage(r));
480
481                 r = __pCertServiceProxy->RemoveUserCertChainByCertId(certId);
482                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s]Failed to remove user certificates.", GetErrorMessage(r));
483         }
484         else
485         {
486                 r = __pCertServiceProxy->RemoveCaCertificate(static_cast< int >(certType), pBuffer, bufferLen);
487                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to remove certificate.", GetErrorMessage(r));
488
489                 UpdateCertStoreContext(certType);
490                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to update cert store.", GetErrorMessage(r));
491         }
492
493         return r;
494 }
495
496 result
497 _X509CertificateStoreImpl::UpdateCertStoreContext(int type)
498 {
499         result r = E_SUCCESS;
500
501         CertificateStoreCtx certList = null;
502         int index = GetIndexFromCertType(type);
503
504         int count = 0;
505
506         if (index > -1 && type == __certType)
507         {
508                 if (__context[index] != 0)
509                 {
510                         r = _CertServer::CloseCertificateStore(reinterpret_cast< CertificateStoreCtx >(__context[index]));
511                         TryReturnResult(!IsFailed(r), r, r, "[%s] Propagating.", GetErrorMessage(r));
512                 }
513                 certList = _CertServer::OpenCertificateStoreByType(static_cast< _CaCertType >(type), &count);
514                 r = GetLastResult();
515                 SysTryReturnResult(NID_SEC_CERT, !IsFailed(r), E_SYSTEM, "Failed to open certificate store.");
516                 __context[index] = reinterpret_cast< int >(certList);
517         }
518
519         return r;
520 }
521
522 _X509CertificateStoreImpl*
523 _X509CertificateStoreImpl::GetInstance(X509CertificateStore& x509CertificateStore)
524 {
525         return x509CertificateStore.__pX509CertificateStoreImpl;
526 }
527
528 const _X509CertificateStoreImpl*
529 _X509CertificateStoreImpl::GetInstance(const X509CertificateStore& x509CertificateStore)
530 {
531         return x509CertificateStore.__pX509CertificateStoreImpl;
532 }
533
534 int
535 InsertPkcs12Content(const char* pPath, const char* pPassword)
536 {
537         result r = E_SUCCESS;
538         _X509CertificateStoreImpl store;
539         String filePath;
540         String password;
541
542         filePath.SetCapacity(strlen(pPath) + 1);
543         password.SetCapacity(strlen(pPassword) + 1);
544
545         filePath.Format(strlen(pPath) + 1, L"%s", pPath);
546         password.Format(strlen(pPassword) + 1, L"%s", pPassword);
547
548         r = store.InsertPkcs12(filePath, password, false);
549         SysTryReturn(NID_SEC_CERT, !IsFailed(r), -1, r, "[%s] Failed to remove certificate.", GetErrorMessage(r));
550
551         return 0;
552 }
553
554
555 } } }      // Tizen::Security::Cert