Refactor SignatureValidator and reduce interface headers
[platform/core/security/cert-svc.git] / vcore / vcore / CertificateCollection.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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  * @file        CertificateCollection.cpp
18  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
19  * @version     0.1
20  * @brief
21  */
22
23 #include <openssl/pem.h>
24 #include <openssl/x509.h>
25
26 #include <algorithm>
27
28 #include <cert-svc/cinstance.h>
29 #include <cert-svc/ccert.h>
30 #include <cert-svc/cprimitives.h>
31
32 #include <dpl/log/log.h>
33 #include <vcore/Base64.h>
34
35 #include <vcore/CertificateCollection.h>
36
37 namespace {
38
39 using namespace ValidationCore;
40
41 inline std::string toBinaryString(int data)
42 {
43     char buffer[sizeof(int)];
44     memcpy(buffer, &data, sizeof(int));
45     return std::string(buffer, sizeof(int));
46 }
47
48 CertificatePtr getCertFromStore(X509_NAME *subject)
49 {
50     if (!subject) {
51         LogError("Invalid input!");
52         return CertificatePtr();
53     }
54
55     CertSvcInstance instance;
56     if (certsvc_instance_new(&instance) != CERTSVC_SUCCESS) {
57         LogError("Failed to make instance");
58                 return CertificatePtr();
59     }
60
61     char buffer[1024];
62     X509_NAME_oneline(subject, buffer, 1024);
63
64     LogDebug("Search certificate with subject: " << buffer);
65         CertSvcCertificateList certList;
66         int result = certsvc_certificate_search(instance, CERTSVC_SUBJECT, buffer, &certList);
67     if (result != CERTSVC_SUCCESS) {
68         LogError("Error during certificate search. result : " << result);
69                 certsvc_instance_free(instance);
70         return CertificatePtr();
71     }
72
73         size_t listSize = 0;
74         result = certsvc_certificate_list_get_length(certList, &listSize);
75         if (result != CERTSVC_SUCCESS || listSize <= 0) {
76                 LogError("Error in certsvc_certificate_list_get_length. result : " << result);
77                 certsvc_instance_free(instance);
78                 return CertificatePtr();
79         }
80
81         CertSvcCertificate cert;
82         result = certsvc_certificate_list_get_one(certList, 0, &cert);
83         if (result != CERTSVC_SUCCESS) {
84                 LogError("Failed to get cert from cert list. result : " << result);
85                 certsvc_certificate_list_all_free(certList);
86                 certsvc_instance_free(instance);
87                 return CertificatePtr();
88         }
89
90         X509 *pCertX509 = NULL;
91         result = certsvc_certificate_dup_x509(cert, &pCertX509);
92         certsvc_certificate_list_all_free(certList);
93         certsvc_instance_free(instance);
94
95     if (result != CERTSVC_SUCCESS || !pCertX509) {
96         LogError("Error during certificate dup x509. result : " << result);
97         return CertificatePtr();
98     }
99
100     CertificatePtr parentCert(new Certificate(pCertX509));
101     X509_free(pCertX509);
102
103     return parentCert;
104 }
105 } // namespace
106
107 namespace ValidationCore {
108
109 CertificateCollection::CertificateCollection()
110   : m_collectionStatus(COLLECTION_UNSORTED)
111 {}
112
113 void CertificateCollection::clear(void)
114 {
115     m_collectionStatus = COLLECTION_UNSORTED;
116     m_certList.clear();
117 }
118
119 void CertificateCollection::load(const CertificateList &certList)
120 {
121     m_collectionStatus = COLLECTION_UNSORTED;
122     std::copy(certList.begin(),
123               certList.end(),
124               std::back_inserter(m_certList));
125 }
126
127 std::string CertificateCollection::toBase64String() const
128 {
129     std::ostringstream output;
130     int certNum = m_certList.size();
131     output << toBinaryString(certNum);
132
133     for (auto i = m_certList.begin(); i != m_certList.end(); ++i) {
134         std::string derCert = (*i)->getDER();
135         output << toBinaryString(derCert.size());
136         output << derCert;
137     }
138     Base64Encoder base64;
139     base64.reset();
140     base64.append(output.str());
141     base64.finalize();
142     return base64.get();
143 }
144
145 CertificateList CertificateCollection::getCertificateList() const
146 {
147     return m_certList;
148 }
149
150 bool CertificateCollection::isChain() const
151 {
152     if (COLLECTION_SORTED != m_collectionStatus)
153         VcoreThrowMsg(CertificateCollection::Exception::WrongUsage,
154                       "You must sort certificate first");
155
156     return (COLLECTION_SORTED == m_collectionStatus) ? true : false;
157 }
158
159 bool CertificateCollection::sort()
160 {
161     if (COLLECTION_UNSORTED == m_collectionStatus) {
162         sortCollection();
163     }
164     return (COLLECTION_SORTED == m_collectionStatus) ? true : false;
165 }
166
167 CertificateList CertificateCollection::getChain() const
168 {
169     if (COLLECTION_SORTED != m_collectionStatus)
170         VcoreThrowMsg(CertificateCollection::Exception::WrongUsage,
171                       "You must sort certificates first");
172
173     return m_certList;
174 }
175
176 void CertificateCollection::sortCollection()
177 {
178     // sorting is not necessary
179     if (m_certList.empty()) {
180         m_collectionStatus = COLLECTION_SORTED;
181         return;
182     }
183
184     CertificateList sorted;
185     std::map<std::string, CertificatePtr> subTransl;
186     std::map<std::string, CertificatePtr> issTransl;
187
188     // Sort all certificate by subject
189     for (auto it = m_certList.begin(); it != m_certList.end(); ++it) {
190         subTransl.insert(std::make_pair((*it)->getOneLine(), (*it)));
191     }
192     // We need one start certificate
193     sorted.push_back(subTransl.begin()->second);
194     subTransl.erase(subTransl.begin());
195
196     // Get the issuer from front certificate and find certificate with this subject in subTransl.
197     // Add this certificate to the front.
198     while (!subTransl.empty()) {
199         std::string issuer = sorted.back()->getOneLine(Certificate::FIELD_ISSUER);
200         auto it = subTransl.find(issuer);
201         if (it == subTransl.end()) {
202             break;
203         }
204         sorted.push_back(it->second);
205         subTransl.erase(it);
206     }
207
208     // Sort all certificates by issuer
209     for (auto it = subTransl.begin(); it != subTransl.end(); ++it) {
210         issTransl.insert(std::make_pair(it->second->getOneLine(Certificate::FIELD_ISSUER), it->second));
211     }
212
213     // Get the subject from last certificate and find certificate with such issuer in issTransl.
214     // Add this certificate at end.
215     while (!issTransl.empty()) {
216         std::string sub = sorted.front()->getOneLine();
217         auto it = issTransl.find(sub);
218         if (it == issTransl.end()) {
219             break;
220         }
221         sorted.push_front(it->second);
222         issTransl.erase(it);
223     }
224
225     if (!issTransl.empty()) {
226         LogWarning("Certificates don't form a valid chain.");
227         m_collectionStatus = COLLECTION_CHAIN_BROKEN;
228         return;
229     }
230
231     m_collectionStatus = COLLECTION_SORTED;
232     m_certList = sorted;
233 }
234
235 /*
236  *  Precondition : cert list sorted and has more than one cert
237  */
238 bool CertificateCollection::completeCertificateChain()
239 {
240     CertificatePtr last = m_certList.back();
241     if (last->isSignedBy(last))
242         return true;
243
244     /* TODO Add getIssuerName function to Certificate.h */
245     CertificatePtr parent = getCertFromStore(X509_get_issuer_name(last->getX509()));
246
247     if (!parent.get())
248         return false;
249
250     m_certList.push_back(parent);
251     if (!parent->isSignedBy(parent))
252         return false;
253
254     return true;
255 }
256
257 size_t CertificateCollection::size() const {
258     return m_certList.size();
259 }
260
261 bool CertificateCollection::empty() const {
262     return m_certList.empty();
263 }
264
265 CertificateCollection::const_iterator CertificateCollection::begin() const {
266     return m_certList.begin();
267 }
268
269 CertificateCollection::const_iterator CertificateCollection::end() const {
270     return m_certList.end();
271 }
272
273 CertificatePtr CertificateCollection::back() const {
274     return m_certList.back();
275 }
276
277 } // namespace ValidationCore
278