Class naming scheme re-factoring: move towards better consistency.
[platform/core/security/key-manager.git] / src / manager / common / certificate-impl.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        client-certificate-impl.cpp
17  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
18  * @version     1.0
19  * @brief       Key implementation.
20  */
21 #include <openssl/x509.h>
22 #include <openssl/x509v3.h>
23 #include <openssl/pem.h>
24
25 #include <dpl/log/log.h>
26
27 #include <key-impl.h>
28 #include <certificate-impl.h>
29 #include <base64.h>
30
31 namespace CKM {
32
33 CertificateImpl::CertificateImpl(const RawBuffer &der, DataFormat format)
34   : m_x509(NULL)
35 {
36     int size;
37     const unsigned char *ptr;
38     RawBuffer tmp;
39
40     LogDebug("Certificate to parse. Size: " << der.size());
41
42     if (DataFormat::FORM_DER_BASE64 == format) {
43         Base64Decoder base64;
44         base64.reset();
45         base64.append(der);
46         base64.finalize();
47         tmp = base64.get();
48         ptr = reinterpret_cast<const unsigned char*>(tmp.data());
49         size = static_cast<int>(tmp.size());
50         m_x509 = d2i_X509(NULL, &ptr, size);
51     } else if (DataFormat::FORM_DER == format) {
52         ptr = reinterpret_cast<const unsigned char*>(der.data());
53         size = static_cast<int>(der.size());
54         m_x509 = d2i_X509(NULL, &ptr, size);
55     } else if (DataFormat::FORM_PEM == format) {
56         BIO *buff = BIO_new(BIO_s_mem());
57         BIO_write(buff, der.data(), der.size());
58         m_x509 = PEM_read_bio_X509(buff, NULL, NULL, NULL);
59         BIO_free_all(buff);
60     } else {
61         // TODO
62         LogError("Unknown certificate format");
63     }
64
65     if (!m_x509) {
66         // TODO
67         LogError("Certificate could not be parsed.");
68 //        ThrowMsg(Exception::OpensslInternalError,
69 //          "Internal Openssl error in d2i_X509 function.");
70     }
71 }
72
73 CertificateImpl::CertificateImpl(X509 *x509, bool duplicate)
74 {
75     if (duplicate)
76         m_x509 = X509_dup(x509);
77     else
78         m_x509 = x509;
79 }
80
81 CertificateImpl::CertificateImpl(const CertificateImpl &second){
82     m_x509 = X509_dup(second.m_x509);
83 }
84
85 CertificateImpl::CertificateImpl(CertificateImpl &&second) {
86     m_x509 = second.m_x509;
87     second.m_x509 = NULL;
88     LogDebug("Certificate moved: " << (void*)m_x509);
89 }
90
91 CertificateImpl& CertificateImpl::operator=(CertificateImpl &&second) {
92     if (this == &second)
93         return *this;
94     X509_free(m_x509);
95     m_x509 = second.m_x509;
96     second.m_x509 = NULL;
97     LogDebug("Certificate moved: " << (void*)m_x509);
98     return *this;
99 }
100
101 CertificateImpl& CertificateImpl::operator=(const CertificateImpl &second) {
102     if (this == &second)
103         return *this;
104     X509_free(m_x509);
105     m_x509 = X509_dup(second.m_x509);
106     return *this;
107 }
108
109 X509* CertificateImpl::getX509() const {
110     return m_x509;
111 }
112
113 RawBuffer CertificateImpl::getDER(void) const {
114     unsigned char *rawDer = NULL;
115     int size = i2d_X509(m_x509, &rawDer);
116     if (!rawDer || size <= 0) {
117         LogError("i2d_X509 failed");
118         return RawBuffer();
119     }
120
121     RawBuffer output(
122         reinterpret_cast<char*>(rawDer),
123         reinterpret_cast<char*>(rawDer) + size);
124     OPENSSL_free(rawDer);
125     return output;
126 }
127
128 bool CertificateImpl::empty() const {
129     return m_x509 == NULL;
130 }
131
132 KeyImpl::EvpShPtr CertificateImpl::getEvpShPtr() const {
133     return KeyImpl::EvpShPtr(X509_get_pubkey(m_x509), EVP_PKEY_free);
134 }
135
136 KeyImpl CertificateImpl::getKeyImpl() const {
137     KeyImpl::EvpShPtr evp(X509_get_pubkey(m_x509), EVP_PKEY_free);
138     if (EVP_PKEY_type(evp->type) == EVP_PKEY_RSA)
139         return KeyImpl(evp, KeyType::KEY_RSA_PUBLIC);
140     if (EVP_PKEY_type(evp->type) == EVP_PKEY_EC)
141         return KeyImpl(evp, KeyType::KEY_ECDSA_PUBLIC);
142     LogError("Unsupported key type in certificate.");
143     return KeyImpl();
144 }
145
146 X509_NAME *getX509Name(X509 *x509, CertificateFieldId type) {
147     if (!x509)
148         return NULL;
149
150     if (type == CertificateFieldId::ISSUER)
151         return X509_get_issuer_name(x509);
152     else if (type == CertificateFieldId::SUBJECT)
153         return X509_get_subject_name(x509);
154
155     LogError("Invalid param. Unknown CertificateFieldId");
156     return NULL;
157 }
158
159 std::string CertificateImpl::getOneLine(CertificateFieldId type) const
160 {
161     X509_NAME *name = getX509Name(m_x509, type);
162     if (!name)
163         return std::string();
164     static const int MAXB = 1024;
165     char buffer[MAXB];
166     X509_NAME_oneline(name, buffer, MAXB);
167     return std::string(buffer);
168 }
169
170 std::string CertificateImpl::getField(CertificateFieldId type, int fieldNid) const {
171     X509_NAME *subjectName = getX509Name(m_x509, type);
172     X509_NAME_ENTRY *subjectEntry = NULL;
173
174     if (!subjectName)
175         return std::string();
176
177     int entryCount = X509_NAME_entry_count(subjectName);
178
179     for (int i = 0; i < entryCount; ++i) {
180         subjectEntry = X509_NAME_get_entry(subjectName, i);
181
182         if (!subjectEntry) {
183             continue;
184         }
185
186         int nid = OBJ_obj2nid(
187             static_cast<ASN1_OBJECT*>(
188                     X509_NAME_ENTRY_get_object(subjectEntry)));
189
190         if (nid != fieldNid) {
191             continue;
192         }
193
194         ASN1_STRING* pASN1Str = subjectEntry->value;
195
196         unsigned char* pData = NULL;
197         int nLength = ASN1_STRING_to_UTF8(&pData, pASN1Str);
198
199         if (nLength < 0) {
200             LogError("Reading field error.");
201             return std::string();
202         }
203
204         std::string output(reinterpret_cast<char*>(pData), nLength);
205         OPENSSL_free(pData);
206         return output;
207     }
208     return std::string();
209 }
210
211 std::string CertificateImpl::getCommonName(CertificateFieldId type) const {
212     return getField(type, NID_commonName);
213 }
214
215 std::string CertificateImpl::getCountryName(CertificateFieldId type) const {
216     return getField(type, NID_countryName);
217 }
218
219 std::string CertificateImpl::getStateOrProvinceName(CertificateFieldId type) const {
220     return getField(type, NID_stateOrProvinceName);
221 }
222
223 std::string CertificateImpl::getLocalityName(CertificateFieldId type) const {
224     return getField(type, NID_localityName);
225 }
226
227 std::string CertificateImpl::getOrganizationName(CertificateFieldId type) const {
228     return getField(type, NID_organizationName);
229 }
230
231 std::string CertificateImpl::getOrganizationalUnitName(CertificateFieldId type) const {
232     return getField(type, NID_organizationalUnitName);
233 }
234
235 std::string CertificateImpl::getEmailAddres(CertificateFieldId type) const {
236     return getField(type, NID_pkcs9_emailAddress);
237 }
238
239 std::string CertificateImpl::getOCSPURL() const {
240     if (!m_x509)
241         return std::string();
242
243     STACK_OF(OPENSSL_STRING) *aia = X509_get1_ocsp(m_x509);
244
245     if (NULL == aia)
246         return std::string();
247
248     std::string result(sk_OPENSSL_STRING_value(aia, 0));
249     X509_email_free(aia);   // TODO is it correct?
250     return result;
251 }
252
253 CertificateImpl::~CertificateImpl() {
254     LogDebug("free cert start ptr: " << (void*)m_x509);
255     X509_free(m_x509);
256     LogDebug("free cert end");
257 }
258
259 CertificateShPtr Certificate::create(const RawBuffer &rawBuffer, DataFormat format) {
260     try {
261         CertificateShPtr output = std::make_shared<CertificateImpl>(rawBuffer, format);
262         if (output->empty())
263             output.reset();
264         return output;
265     } catch (const std::bad_alloc &) {
266         LogDebug("Bad alloc was caught during CertificateImpl creation");
267     } catch (...) {
268         LogError("Critical error: Unknown exception was caught during CertificateImpl creation!");
269     }
270     return CertificateShPtr();
271 }
272
273 } // namespace CKM
274