2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file CertificateCollection.cpp
18 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
23 #include <openssl/pem.h>
24 #include <openssl/x509.h>
28 #include <cert-svc/cinstance.h>
29 #include <cert-svc/ccert.h>
30 #include <cert-svc/cprimitives.h>
32 #include <dpl/log/log.h>
33 #include <vcore/Base64.h>
35 #include <vcore/CertificateCollection.h>
39 using namespace ValidationCore;
41 inline std::string toBinaryString(int data)
43 char buffer[sizeof(int)];
44 memcpy(buffer, &data, sizeof(int));
45 return std::string(buffer, sizeof(int));
48 CertificatePtr getCertFromStore(X509_NAME *subject)
51 LogError("Invalid input!");
52 return CertificatePtr();
55 CertSvcInstance instance;
56 if (certsvc_instance_new(&instance) != CERTSVC_SUCCESS) {
57 LogError("Failed to make instance");
58 return CertificatePtr();
62 X509_NAME_oneline(subject, buffer, 1024);
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();
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();
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();
90 X509 *pCertX509 = NULL;
91 result = certsvc_certificate_dup_x509(cert, &pCertX509);
92 certsvc_certificate_list_all_free(certList);
93 certsvc_instance_free(instance);
95 if (result != CERTSVC_SUCCESS || !pCertX509) {
96 LogError("Error during certificate dup x509. result : " << result);
97 return CertificatePtr();
100 CertificatePtr parentCert(new Certificate(pCertX509));
101 X509_free(pCertX509);
107 namespace ValidationCore {
109 CertificateCollection::CertificateCollection()
110 : m_collectionStatus(COLLECTION_UNSORTED)
113 void CertificateCollection::clear(void)
115 m_collectionStatus = COLLECTION_UNSORTED;
119 void CertificateCollection::load(const CertificateList &certList)
121 m_collectionStatus = COLLECTION_UNSORTED;
122 std::copy(certList.begin(),
124 std::back_inserter(m_certList));
127 std::string CertificateCollection::toBase64String() const
129 std::ostringstream output;
130 int certNum = m_certList.size();
131 output << toBinaryString(certNum);
133 for (auto i = m_certList.begin(); i != m_certList.end(); ++i) {
134 std::string derCert = (*i)->getDER();
135 output << toBinaryString(derCert.size());
138 Base64Encoder base64;
140 base64.append(output.str());
145 CertificateList CertificateCollection::getCertificateList() const
150 bool CertificateCollection::isChain() const
152 if (COLLECTION_SORTED != m_collectionStatus)
153 VcoreThrowMsg(CertificateCollection::Exception::WrongUsage,
154 "You must sort certificate first");
156 return (COLLECTION_SORTED == m_collectionStatus) ? true : false;
159 bool CertificateCollection::sort()
161 if (COLLECTION_UNSORTED == m_collectionStatus) {
164 return (COLLECTION_SORTED == m_collectionStatus) ? true : false;
167 CertificateList CertificateCollection::getChain() const
169 if (COLLECTION_SORTED != m_collectionStatus)
170 VcoreThrowMsg(CertificateCollection::Exception::WrongUsage,
171 "You must sort certificates first");
176 void CertificateCollection::sortCollection()
178 // sorting is not necessary
179 if (m_certList.empty()) {
180 m_collectionStatus = COLLECTION_SORTED;
184 CertificateList sorted;
185 std::map<std::string, CertificatePtr> subTransl;
186 std::map<std::string, CertificatePtr> issTransl;
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)));
192 // We need one start certificate
193 sorted.push_back(subTransl.begin()->second);
194 subTransl.erase(subTransl.begin());
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()) {
204 sorted.push_back(it->second);
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));
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()) {
221 sorted.push_front(it->second);
225 if (!issTransl.empty()) {
226 LogWarning("Certificates don't form a valid chain.");
227 m_collectionStatus = COLLECTION_CHAIN_BROKEN;
231 m_collectionStatus = COLLECTION_SORTED;
236 * Precondition : cert list sorted and has more than one cert
238 bool CertificateCollection::completeCertificateChain()
240 CertificatePtr last = m_certList.back();
241 if (last->isSignedBy(last))
244 /* TODO Add getIssuerName function to Certificate.h */
245 CertificatePtr parent = getCertFromStore(X509_get_issuer_name(last->getX509()));
250 m_certList.push_back(parent);
251 if (!parent->isSignedBy(parent))
257 size_t CertificateCollection::size() const {
258 return m_certList.size();
261 bool CertificateCollection::empty() const {
262 return m_certList.empty();
265 CertificateCollection::const_iterator CertificateCollection::begin() const {
266 return m_certList.begin();
269 CertificateCollection::const_iterator CertificateCollection::end() const {
270 return m_certList.end();
273 CertificatePtr CertificateCollection::back() const {
274 return m_certList.back();
277 } // namespace ValidationCore