1 /* Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
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
7 * http://www.apache.org/licenses/LICENSE-2.0
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
16 * @file client-certificate-impl.cpp
17 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
19 * @brief Key implementation.
21 #include <openssl/x509.h>
22 #include <openssl/x509v3.h>
23 #include <openssl/pem.h>
25 #include <dpl/log/log.h>
28 #include <certificate-impl.h>
33 CertificateImpl::CertificateImpl(const RawBuffer &der, DataFormat format)
37 const unsigned char *ptr;
40 LogDebug("Certificate to parse. Size: " << der.size());
42 if (DataFormat::FORM_DER_BASE64 == format) {
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);
62 LogError("Unknown certificate format");
67 LogError("Certificate could not be parsed.");
68 // ThrowMsg(Exception::OpensslInternalError,
69 // "Internal Openssl error in d2i_X509 function.");
73 CertificateImpl::CertificateImpl(X509 *x509, bool duplicate)
76 m_x509 = X509_dup(x509);
81 CertificateImpl::CertificateImpl(const CertificateImpl &second){
82 m_x509 = X509_dup(second.m_x509);
85 CertificateImpl::CertificateImpl(CertificateImpl &&second) {
86 m_x509 = second.m_x509;
88 LogDebug("Certificate moved: " << (void*)m_x509);
91 CertificateImpl& CertificateImpl::operator=(CertificateImpl &&second) {
95 m_x509 = second.m_x509;
97 LogDebug("Certificate moved: " << (void*)m_x509);
101 CertificateImpl& CertificateImpl::operator=(const CertificateImpl &second) {
105 m_x509 = X509_dup(second.m_x509);
109 X509* CertificateImpl::getX509() const {
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");
122 reinterpret_cast<char*>(rawDer),
123 reinterpret_cast<char*>(rawDer) + size);
124 OPENSSL_free(rawDer);
128 bool CertificateImpl::empty() const {
129 return m_x509 == NULL;
132 KeyImpl::EvpShPtr CertificateImpl::getEvpShPtr() const {
133 return KeyImpl::EvpShPtr(X509_get_pubkey(m_x509), EVP_PKEY_free);
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.");
146 X509_NAME *getX509Name(X509 *x509, CertificateFieldId type) {
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);
155 LogError("Invalid param. Unknown CertificateFieldId");
159 std::string CertificateImpl::getOneLine(CertificateFieldId type) const
161 X509_NAME *name = getX509Name(m_x509, type);
163 return std::string();
164 static const int MAXB = 1024;
166 X509_NAME_oneline(name, buffer, MAXB);
167 return std::string(buffer);
170 std::string CertificateImpl::getField(CertificateFieldId type, int fieldNid) const {
171 X509_NAME *subjectName = getX509Name(m_x509, type);
172 X509_NAME_ENTRY *subjectEntry = NULL;
175 return std::string();
177 int entryCount = X509_NAME_entry_count(subjectName);
179 for (int i = 0; i < entryCount; ++i) {
180 subjectEntry = X509_NAME_get_entry(subjectName, i);
186 int nid = OBJ_obj2nid(
187 static_cast<ASN1_OBJECT*>(
188 X509_NAME_ENTRY_get_object(subjectEntry)));
190 if (nid != fieldNid) {
194 ASN1_STRING* pASN1Str = subjectEntry->value;
196 unsigned char* pData = NULL;
197 int nLength = ASN1_STRING_to_UTF8(&pData, pASN1Str);
200 LogError("Reading field error.");
201 return std::string();
204 std::string output(reinterpret_cast<char*>(pData), nLength);
208 return std::string();
211 std::string CertificateImpl::getCommonName(CertificateFieldId type) const {
212 return getField(type, NID_commonName);
215 std::string CertificateImpl::getCountryName(CertificateFieldId type) const {
216 return getField(type, NID_countryName);
219 std::string CertificateImpl::getStateOrProvinceName(CertificateFieldId type) const {
220 return getField(type, NID_stateOrProvinceName);
223 std::string CertificateImpl::getLocalityName(CertificateFieldId type) const {
224 return getField(type, NID_localityName);
227 std::string CertificateImpl::getOrganizationName(CertificateFieldId type) const {
228 return getField(type, NID_organizationName);
231 std::string CertificateImpl::getOrganizationalUnitName(CertificateFieldId type) const {
232 return getField(type, NID_organizationalUnitName);
235 std::string CertificateImpl::getEmailAddres(CertificateFieldId type) const {
236 return getField(type, NID_pkcs9_emailAddress);
239 std::string CertificateImpl::getOCSPURL() const {
241 return std::string();
243 STACK_OF(OPENSSL_STRING) *aia = X509_get1_ocsp(m_x509);
246 return std::string();
248 std::string result(sk_OPENSSL_STRING_value(aia, 0));
249 X509_email_free(aia); // TODO is it correct?
253 CertificateImpl::~CertificateImpl() {
254 LogDebug("free cert start ptr: " << (void*)m_x509);
256 LogDebug("free cert end");
259 CertificateShPtr Certificate::create(const RawBuffer &rawBuffer, DataFormat format) {
261 CertificateShPtr output = std::make_shared<CertificateImpl>(rawBuffer, format);
265 } catch (const std::bad_alloc &) {
266 LogDebug("Bad alloc was caught during CertificateImpl creation");
268 LogError("Critical error: Unknown exception was caught during CertificateImpl creation!");
270 return CertificateShPtr();