tizen 2.4 release
[framework/security/key-manager.git] / src / manager / service / certificate-store.cpp
1 /* Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
2  *
3  *  Licensed under the Apache License, Version 2.0 (the "License");
4  *  you may not use this file except in compliance with the License.
5  *  You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  *  Unless required by applicable law or agreed to in writing, software
10  *  distributed under the License is distributed on an "AS IS" BASIS,
11  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  *  See the License for the specific language governing permissions and
13  *  limitations under the License
14  *
15  *
16  * @file        certificate-stack.cpp
17  * @author      Barlomiej Grzelewski (b.grzelewski@samsung.com)
18  * @version     1.0
19  * @brief       Certificate Stack Implmentation.
20  */
21 #include <openssl/x509.h>
22
23 #include <stdexcept>
24
25 #include <dpl/log/log.h>
26
27 #include <certificate-store.h>
28 #include <certificate-config.h>
29 #include <ckm/ckm-error.h>
30 #include <ckm/ckm-type.h>
31 #include <openssl_utils.h>
32
33 namespace CKM {
34
35 CertificateStore::CertificateStore() : m_store(X509_STORE_new())
36 {
37     if (!m_store) {
38         LogError("Failed to create store");
39         throw std::runtime_error("Failed to create store");
40     }
41 }
42
43 CertificateStore::~CertificateStore()
44 {
45     X509_STORE_free(m_store);
46 }
47
48 int CertificateStore::verifyCertificate(
49     const CertificateImpl &cert,
50     const CertificateImplVector &untrustedVector,
51     const CertificateImplVector &trustedVector,
52     bool useTrustedSystemCertificates,
53     bool stateCCMode,
54     CertificateImplVector &chainVector)
55 {
56     int ret;
57     LogDebug("Certificate for verfication ptr: " << (void*)cert.getX509());
58     LogDebug("Verfication with " << untrustedVector.size() << " untrusted certificates" <<
59              trustedVector.size() << "trusted certificates" << " and system certificates set to: "
60              << useTrustedSystemCertificates);
61
62     X509_STORE_CTX_PTR csc= create_x509_store_ctx();
63     if (!csc) {
64         LogError("failed to create csc");
65         return CKM_API_ERROR_UNKNOWN;
66     }
67
68     if (useTrustedSystemCertificates) {
69         ret = addSystemCertificateDirs();
70         if (ret != CKM_API_SUCCESS)
71             return ret;
72
73         ret = addSystemCertificateFiles();
74         if (ret != CKM_API_SUCCESS)
75             return ret;
76     }
77
78     ret = addCustomTrustedCertificates(trustedVector);
79     if (ret != CKM_API_SUCCESS)
80         return ret;
81
82     // create stack of untrusted certificates
83     X509_STACK_PTR untrusted = create_x509_stack();
84     if (!untrustedVector.empty()) {
85         for (auto &e : untrustedVector) {
86             // we don't want to free certificates because we wont create copies
87             sk_X509_push(untrusted.get(), e.getX509());
88         }
89     }
90
91     if (0 == X509_STORE_CTX_init(csc.get(), m_store, cert.getX509(), untrusted.get())) {
92         LogError("failed to X509_STORE_CTX_init");
93         return CKM_API_ERROR_UNKNOWN;
94     }
95
96     if(stateCCMode) {
97         X509_VERIFY_PARAM_set_flags(csc->param, X509_V_FLAG_X509_STRICT);
98     }
99
100     int result = X509_verify_cert(csc.get()); // 1 == ok; 0 == fail; -1 == error
101
102     LogDebug("Openssl verification result: " << result);
103
104     if (result > 0) {
105         STACK_OF(X509) *chain = X509_STORE_CTX_get_chain(csc.get());
106         for (int i = 0; i < sk_X509_num(chain); ++i) {
107             X509* icert = (X509*)sk_X509_value(chain, i);
108             chainVector.push_back(CertificateImpl(icert));
109         }
110     }
111
112     switch (result) {
113     case 0:
114         ret = X509_STORE_CTX_get_error(csc.get());
115         LogError("verify error[" << ret << "]: " << X509_verify_cert_error_string(ret));
116         return CKM_API_ERROR_VERIFICATION_FAILED;
117     case 1:
118         return CKM_API_SUCCESS;
119     default:
120         return CKM_API_ERROR_UNKNOWN;
121     }
122 }
123
124 int CertificateStore::addSystemCertificateDirs()
125 {
126     const auto& dirs = CertificateConfig::getSystemCertificateDirs();
127     if (dirs.empty())
128         return CKM_API_SUCCESS;
129
130     // add system certificate directories
131     auto dir_lookup = X509_STORE_add_lookup(m_store, X509_LOOKUP_hash_dir());
132     if (!dir_lookup) {
133         LogError("Error in X509_STORE_add_lookup");
134         return CKM_API_ERROR_UNKNOWN;
135     }
136     for(const auto& i: dirs) {
137         if (!X509_LOOKUP_add_dir(dir_lookup, i.c_str(), X509_FILETYPE_PEM)) {
138             LogError("Error in X509_LOOKUP_add_dir");
139             return CKM_API_ERROR_UNKNOWN;
140         }
141     }
142     return CKM_API_SUCCESS;
143 }
144
145 int CertificateStore::addSystemCertificateFiles()
146 {
147     const auto& files = CertificateConfig::getSystemCertificateFiles();
148     if (files.empty())
149         return CKM_API_SUCCESS;
150
151     // add system certificate files
152     auto file_lookup = X509_STORE_add_lookup(m_store, X509_LOOKUP_file());
153     if (!file_lookup) {
154         LogError("Error in X509_STORE_add_lookup");
155         return CKM_API_ERROR_UNKNOWN;
156     }
157
158     for(const auto& i:files) {
159         if (!X509_LOOKUP_load_file(file_lookup, i.c_str(), X509_FILETYPE_PEM)) {
160             LogError("Error in X509_LOOKUP_load_file");
161             return CKM_API_ERROR_UNKNOWN;
162         }
163     }
164     return CKM_API_SUCCESS;
165 }
166
167 int CertificateStore::addCustomTrustedCertificates(const CertificateImplVector &trustedVector)
168 {
169     // add trusted certificates to store
170     for (const auto& i:trustedVector) {
171         if(1 != X509_STORE_add_cert(m_store, i.getX509())) {
172             LogError("failed to add certificate to the store");
173             return CKM_API_ERROR_UNKNOWN;
174         }
175     }
176     return CKM_API_SUCCESS;
177 }
178
179 } // namespace CKM