8fe8953c7dc5da5307772d9431c18fcbfaca10bf
[platform/core/security/cert-svc.git] / vcore / src / 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 #include <vcore/CertificateCollection.h>
23
24 #include <vcore/Base64.h>
25 #include <dpl/binary_queue.h>
26 #include <dpl/foreach.h>
27 #include <dpl/log/log.h>
28
29 #include <algorithm>
30
31 namespace {
32
33 using namespace ValidationCore;
34
35 inline std::string toBinaryString(int data)
36 {
37     char buffer[sizeof(int)];
38     memcpy(buffer, &data, sizeof(int));
39     return std::string(buffer, sizeof(int));
40 }
41
42 } // namespace
43
44 namespace ValidationCore {
45
46 CertificateCollection::CertificateCollection()
47   : m_collectionStatus(COLLECTION_UNSORTED)
48 {}
49
50 void CertificateCollection::clear(void)
51 {
52     m_collectionStatus = COLLECTION_UNSORTED;
53     m_certList.clear();
54 }
55
56 void CertificateCollection::load(const CertificateList &certList)
57 {
58     m_collectionStatus = COLLECTION_UNSORTED;
59     std::copy(certList.begin(),
60               certList.end(),
61               std::back_inserter(m_certList));
62 }
63
64 bool CertificateCollection::load(const std::string &buffer)
65 {
66     Base64Decoder base64;
67     base64.reset();
68     base64.append(buffer);
69     if (!base64.finalize()) {
70         LogWarning("Error during chain decoding");
71         return false;
72     }
73     std::string binaryData = base64.get();
74
75     VcoreDPL::BinaryQueue queue;
76     queue.AppendCopy(binaryData.c_str(), binaryData.size());
77
78     int certNum;
79     queue.FlattenConsume(&certNum, sizeof(int));
80
81     CertificateList list;
82     CertificatePtr certPtr;
83
84     for (int i = 0; i < certNum; ++i) {
85         int certSize;
86         queue.FlattenConsume(&certSize, sizeof(int));
87         std::vector<char> rawDERCert;
88         rawDERCert.resize(certSize);
89         queue.FlattenConsume(&rawDERCert[0], certSize);
90         VcoreTry {
91             list.push_back(CertificatePtr(new Certificate(std::string(
92                 rawDERCert.begin(),
93                 rawDERCert.end()))));
94         } VcoreCatch (Certificate::Exception::Base) {
95             LogWarning("Error during certificate creation.");
96             return false;
97         }
98
99         LogDebug("Loading certificate. Certificate common name: " << list.back()->getCommonName());
100     }
101     load(list);
102     return true;
103 }
104
105 std::string CertificateCollection::toBase64String() const
106 {
107     std::ostringstream output;
108     int certNum = m_certList.size();
109     output << toBinaryString(certNum);
110     FOREACH(i, m_certList){
111         std::string derCert = (*i)->getDER();
112         output << toBinaryString(derCert.size());
113         output << derCert;
114     }
115     Base64Encoder base64;
116     base64.reset();
117     base64.append(output.str());
118     base64.finalize();
119     return base64.get();
120 }
121
122 CertificateList CertificateCollection::getCertificateList() const
123 {
124     return m_certList;
125 }
126
127 bool CertificateCollection::isChain() const
128 {
129     if (COLLECTION_SORTED != m_collectionStatus)
130         VcoreThrowMsg(CertificateCollection::Exception::WrongUsage,
131                       "You must sort certificate first");
132
133     return (COLLECTION_SORTED == m_collectionStatus) ? true : false;
134 }
135
136 bool CertificateCollection::sort()
137 {
138     if (COLLECTION_UNSORTED == m_collectionStatus) {
139         sortCollection();
140     }
141     return (COLLECTION_SORTED == m_collectionStatus) ? true : false;
142 }
143
144 CertificateList CertificateCollection::getChain() const
145 {
146     if (COLLECTION_SORTED != m_collectionStatus)
147         VcoreThrowMsg(CertificateCollection::Exception::WrongUsage,
148                       "You must sort certificates first");
149     return m_certList;
150 }
151
152 void CertificateCollection::sortCollection()
153 {
154     // sorting is not necessary
155     if (m_certList.empty()) {
156         m_collectionStatus = COLLECTION_SORTED;
157         return;
158     }
159
160     CertificateList sorted;
161     std::map<std::string, CertificatePtr> subTransl;
162     std::map<std::string, CertificatePtr> issTransl;
163
164     // Sort all certificate by subject
165     for (auto it = m_certList.begin(); it != m_certList.end(); ++it) {
166         subTransl.insert(std::make_pair((*it)->getOneLine(), (*it)));
167     }
168     // We need one start certificate
169     sorted.push_back(subTransl.begin()->second);
170     subTransl.erase(subTransl.begin());
171
172     // Get the issuer from front certificate and find certificate with this subject in subTransl.
173     // Add this certificate to the front.
174     while (!subTransl.empty()) {
175         std::string issuer = sorted.back()->getOneLine(Certificate::FIELD_ISSUER);
176         auto it = subTransl.find(issuer);
177         if (it == subTransl.end()) {
178             break;
179         }
180         sorted.push_back(it->second);
181         subTransl.erase(it);
182     }
183
184     // Sort all certificates by issuer
185     for (auto it = subTransl.begin(); it != subTransl.end(); ++it) {
186         issTransl.insert(std::make_pair(it->second->getOneLine(Certificate::FIELD_ISSUER), it->second));
187     }
188
189     // Get the subject from last certificate and find certificate with such issuer in issTransl.
190     // Add this certificate at end.
191     while (!issTransl.empty()) {
192         std::string sub = sorted.front()->getOneLine();
193         auto it = issTransl.find(sub);
194         if (it == issTransl.end()) {
195             break;
196         }
197         sorted.push_front(it->second);
198         issTransl.erase(it);
199     }
200
201     if (!issTransl.empty()) {
202         LogWarning("Certificates don't form a valid chain.");
203         m_collectionStatus = COLLECTION_CHAIN_BROKEN;
204         return;
205     }
206
207     m_collectionStatus = COLLECTION_SORTED;
208     m_certList = sorted;
209 }
210
211 size_t CertificateCollection::size() const {
212     return m_certList.size();
213 }
214
215 bool CertificateCollection::empty() const {
216     return m_certList.empty();
217 }
218
219 CertificateCollection::const_iterator CertificateCollection::begin() const {
220     return m_certList.begin();
221 }
222
223 CertificateCollection::const_iterator CertificateCollection::end() const {
224     return m_certList.end();
225 }
226
227 CertificatePtr CertificateCollection::back() const {
228     return m_certList.back();
229 }
230
231 } // namespace ValidationCore
232