sync with tizen_2.0
[platform/framework/native/appfw.git] / src / security / cert / FSecCertX509CertificatePath.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file                FSecCertX509CertificatePath.cpp
20  * @brief               This is the implementation file for X509CertificatePath class.
21  *
22  * This header file contains the implementation of X509CertificatePath class.
23  *
24  */
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <new>
28 #include <unique_ptr.h>
29 #include <FBaseResult.h>
30 #include <FSecCertTypes.h>
31 #include <FSecCertX509CertificatePath.h>
32 #include <FSecCertX509Certificate.h>
33 #include <FBaseSysLog.h>
34 #include <FBase_StringConverter.h>
35 #include <FSecCert_CertService.h>
36
37
38 using namespace Tizen::Base;
39
40 namespace Tizen { namespace Security { namespace Cert
41 {
42
43
44 X509CertificatePath::X509CertificatePath(void)
45         : __certCtx(0)
46         , __depth(0)
47         , __trustAnchorIndex(-1)
48         , __pX509CertificatePathImpl(null)
49 {
50
51 }
52
53 X509CertificatePath::~X509CertificatePath(void)
54 {
55         if (__certCtx != 0)
56         {
57                 _CertService::CloseContext(__certCtx);
58         }
59 }
60
61 Tizen::Base::String
62 X509CertificatePath::GetFormat(void) const
63 {
64         ClearLastResult();
65         return L"X509";
66 }
67
68 result
69 X509CertificatePath::AddCertificate(const Tizen::Security::Cert::ICertificate& certificate)
70 {
71         result r = E_SUCCESS;
72         byte* pCert = null;
73         int certLen = 0;
74         
75         SysTryReturnResult(NID_SEC_CERT, ((certificate.GetFormat()).CompareTo(L"X509")) == 0, E_INVALID_ARG, "Certificate format is not valid.");
76
77         if (__certCtx == 0)
78         {
79                 r = _CertService::OpenContext(_CERT_CONTEXT_CERT, &__certCtx);
80                 SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to create certificate chain context.", GetErrorMessage(r));
81         }
82
83         std::unique_ptr<ByteBuffer> pBuffer(certificate.GetEncodedDataN());
84         SysTryReturnResult(NID_SEC_CERT, pBuffer != null, E_INVALID_ARG, "Failed to get encoded certificate buffer.");
85
86         pCert = const_cast< byte* >(pBuffer->GetPointer());
87         SysTryReturnResult(NID_SEC_CERT, pCert != null, E_INVALID_ARG, "Invalid input certificate passed.");
88
89         certLen = pBuffer->GetRemaining();
90         SysTryReturnResult(NID_SEC_CERT, certLen > 0, E_INVALID_ARG, "Input certificate length is not positive.");
91
92         r = _CertService::AddCertificate(__certCtx, pCert, certLen);
93         SysTryReturn(NID_SEC_CERT, !IsFailed(r), r, r, "[%s] Failed to add certificate chain context.", GetErrorMessage(r));
94
95         __depth++;
96
97         return r;
98 }
99
100 int
101 X509CertificatePath::GetLength(void) const
102 {
103         ClearLastResult();
104         SysTryReturn(NID_SEC_CERT, __certCtx != 0, -1, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
105         return __depth;
106
107 }
108
109 Tizen::Security::Cert::ICertificate*
110 X509CertificatePath::GetCertificateN(int nth) const
111 {
112         result r = E_SUCCESS;
113         CertificateHandle certHandle = 0;
114         char* pCertBufferValue = null;
115         ByteBuffer certInput;
116         int certLen = 0;
117
118         ClearLastResult();
119
120         SysTryReturn(NID_SEC_CERT, nth >= 0 && nth < __depth, null, E_INVALID_ARG, "[E_INVALID_ARG] Invalid input argument.");
121         SysTryReturn(NID_SEC_CERT, __certCtx != 0, null, E_SYSTEM, "[E_SYSTEM] Certificate list is empty, call AddCertificate() function.");
122
123         r = _CertService::GetNthCert(__certCtx, nth, &certHandle);
124         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] Failed to get nth certificate.");
125         SysTryReturn(NID_SEC_CERT, certHandle != null, null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] Certificate not found.");
126
127         r = _CertService::GetCertBufferN(certHandle, pCertBufferValue, &certLen);
128         std::unique_ptr< char[] > pCertBuffer(pCertBufferValue);
129
130         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] Failed to get certificate buffer.");
131         SysTryReturn(NID_SEC_CERT, pCertBuffer != null, null, E_SYSTEM, "[E_SYSTEM] Failed to get certificate buffer.");
132
133         r = certInput.Construct(certLen);
134         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
135
136         r = certInput.SetArray(reinterpret_cast< byte* >(pCertBuffer.get()), 0, certLen);
137         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
138         certInput.Flip();
139
140         std::unique_ptr< X509Certificate > pCert(new (std::nothrow) X509Certificate());
141         SysTryReturn(NID_SEC_CERT, pCert != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
142
143         r = pCert->Construct(certInput);
144         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
145
146         return pCert.release();
147 }
148
149 Tizen::Security::Cert::ValidationResult
150 X509CertificatePath::Validate(void)
151 {
152         result r = E_SUCCESS;
153         int depth = 0;
154         _CertDomainType domain = _CERT_INVALID_DOMAIN;
155         Tizen::Security::Cert::ValidationResult validationResult = VALIDATION_ERROR_INVALID_PATH;
156         ClearLastResult();
157
158         SysTryReturn(NID_SEC_CERT, __certCtx != 0, validationResult, E_SYSTEM, "[E_SYSTEM] Certificate list is empty, call AddCertificate() function.");
159
160         r = _CertService::VerifyChain(__certCtx, &domain);
161         switch (r)
162         {
163         case E_SUCCESS:
164                 validationResult = VALIDATION_SUCCESS;
165                 SysLog(NID_SEC_CERT, "validation result = success");
166                 break;
167
168         case E_DATA_NOT_FOUND:
169                 validationResult = VALIDATION_ERROR_NO_ROOT;
170                 SysLog(NID_SEC_CERT, "validation result = no root cert ");
171                 break;
172
173         case E_INVALID_CERTIFICATE:
174                 validationResult = VALIDATION_ERROR_CERT_EXPIRED;
175                 SysLog(NID_SEC_CERT, "validation result = cert expired");
176                 break;
177
178         case E_CERTIFICATE_VERIFICATION_FAILED:
179                 validationResult = VALIDATION_ERROR_INVALID_SIGNATURE;
180                 SysLog(NID_SEC_CERT, "validation result = invalid signature");
181                 break;
182
183         default:
184                 validationResult = VALIDATION_ERROR_INVALID_PATH;
185                 SysLog(NID_SEC_CERT, "validation result = invalid path");
186                 break;
187
188         }
189         SysTryReturn(NID_SEC_CERT, !IsFailed(r), validationResult, E_SYSTEM, "[E_SYSTEM] Verification of certificate chain failed.");
190
191         r = _CertService::GetChainDepth(__certCtx, &depth);
192         SysTryReturn(NID_SEC_CERT, !IsFailed(r), VALIDATION_ERROR_INVALID_PATH, E_SYSTEM, "[E_SYSTEM] Failed to get certificate chain depth.");
193
194         __trustAnchorIndex = depth - 1;
195         SysTryReturn(NID_SEC_CERT, __trustAnchorIndex > 0, VALIDATION_ERROR_INVALID_PATH, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred, trusted anchor not found.");
196
197         return validationResult;
198
199 }
200
201 Tizen::Security::Cert::ValidationResult
202 X509CertificatePath::Validate(const ICertificate& trustAnchor)
203 {
204         result r = E_SUCCESS;
205
206         ClearLastResult();
207
208         r = AddCertificate(trustAnchor);
209         SysTryReturn(NID_SEC_CERT, !IsFailed(r), VALIDATION_ERROR_INVALID_PATH, r, "[%s] Failed to add certificate.", GetErrorMessage(r));
210
211         return Validate();
212 }
213
214 Tizen::Security::Cert::ICertificate*
215 X509CertificatePath::GetTrustAnchorN(void) const
216 {
217         result r = E_SUCCESS;
218         CertificateHandle certHandle = 0;
219         char* pTempCertValue = null;
220         int certLen = 0;
221         ByteBuffer certBuffer;
222
223         ClearLastResult();
224
225         SysTryReturn(NID_SEC_CERT, __certCtx != 0, null, E_SYSTEM, "[E_SYSTEM] Certificate list is empty, call AddCertificate() function.");
226         SysTryReturn(NID_SEC_CERT, __trustAnchorIndex != -1, null, E_SYSTEM, "[E_SYSTEM] Certificate list is empty, call Validate() function.");
227
228         r = _CertService::GetNthCert(__certCtx, __trustAnchorIndex, &certHandle);
229         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] Failed to get nth certificate.");
230         SysTryReturn(NID_SEC_CERT, certHandle != null, null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] Certificate not found.");
231
232         r = _CertService::GetCertBufferN(certHandle, pTempCertValue, &certLen);
233
234         std::unique_ptr< char[] > pTempCert(pTempCertValue);
235
236         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] Failed to get certificate buffer.");
237         SysTryReturn(NID_SEC_CERT, pTempCert != null, null, E_SYSTEM, "[E_SYSTEM] Failed to get certificate buffer.");
238
239         r = certBuffer.Construct(certLen);
240         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
241
242         r = certBuffer.SetArray(reinterpret_cast< const byte* >(pTempCert.get()), 0, certLen);
243         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, E_SYSTEM, "[E_SYSTEM] An unexpected system error occurred.");
244
245         certBuffer.Flip();
246
247         std::unique_ptr< X509Certificate > pCert(new (std::nothrow) X509Certificate());
248         SysTryReturn(NID_SEC_CERT, pCert != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory.");
249
250         r = pCert->Construct(certBuffer);
251         SysTryReturn(NID_SEC_CERT, !IsFailed(r), null, r, "[%s] Propagated.", GetErrorMessage(r));
252
253         return pCert.release();
254 }
255
256 } } } // Tizen::Security::Cert