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 Certificate.cpp
18 * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
22 #include <vcore/Certificate.h>
28 #include <openssl/x509v3.h>
29 #include <openssl/bn.h>
31 #include <dpl/assert.h>
32 #include <dpl/log/log.h>
34 #include <vcore/Base64.h>
35 #include <vcore/TimeConversion.h>
37 namespace ValidationCore {
39 Certificate::Certificate(X509 *cert)
42 m_x509 = X509_dup(cert);
44 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
45 "Internal Openssl error in d2i_X509 function.");
48 Certificate::Certificate(cert_svc_mem_buff &buffer)
51 const unsigned char *ptr = buffer.data;
52 m_x509 = d2i_X509(NULL, &ptr, buffer.size);
54 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
55 "Internal Openssl error in d2i_X509 function.");
58 Certificate::Certificate(const std::string &data,
59 Certificate::FormType form)
64 const unsigned char *ptr;
65 std::string tmp = data;
67 // transform to DER format
68 if (FORM_BASE64 == form) {
73 if (!base64.finalize()) {
74 LogWarning("Error during decoding");
77 } catch (const Base64Decoder::Exception::Base &e) {
78 LogError("Exception in Certificate constructor : " << e.DumpToString());
79 VcoreThrowMsg(Certificate::Exception::Base64Error, "Failed to Base64Decoder");
83 ptr = reinterpret_cast<const unsigned char*>(tmp.c_str());
84 size = static_cast<int>(tmp.size());
86 m_x509 = d2i_X509(NULL, &ptr, size);
88 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
89 "Internal Openssl error in d2i_X509 function.");
92 Certificate::~Certificate()
97 X509* Certificate::getX509(void) const
102 std::string Certificate::getDER(void) const
104 unsigned char *rawDer = NULL;
105 int size = i2d_X509(m_x509, &rawDer);
106 if (!rawDer || size <= 0)
107 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
110 std::string output(reinterpret_cast<char*>(rawDer), size);
111 OPENSSL_free(rawDer);
115 std::string Certificate::getBase64(void) const
117 Base64Encoder base64;
120 base64.append(getDER());
122 } catch (const Base64Encoder::Exception::Base &e) {
123 LogError("Exception in Certificate getBase64 : " << e.DumpToString());
124 VcoreThrowMsg(Certificate::Exception::Base64Error, "Failed to Base64Encoder");
129 bool Certificate::isSignedBy(const CertificatePtr &parent) const
132 LogDebug("Invalid certificate parameter.");
135 return 0 == X509_NAME_cmp(X509_get_subject_name(parent->m_x509),
136 X509_get_issuer_name(m_x509));
139 Certificate::Fingerprint Certificate::getFingerprint(
140 Certificate::FingerprintType type) const
142 unsigned int fingerprintlength = EVP_MAX_MD_SIZE;
143 unsigned char fingerprint[EVP_MAX_MD_SIZE];
146 if (type == FINGERPRINT_MD5) {
147 if (!X509_digest(m_x509, EVP_md5(), fingerprint, &fingerprintlength))
148 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
149 "MD5 digest counting failed!");
152 if (type == FINGERPRINT_SHA1) {
153 if (!X509_digest(m_x509, EVP_sha1(), fingerprint, &fingerprintlength))
154 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
155 "SHA1 digest counting failed");
158 raw.resize(fingerprintlength); // improve performance
159 std::copy(fingerprint, fingerprint + fingerprintlength, raw.begin());
164 X509_NAME *Certificate::getX509Name(FieldType type) const
166 X509_NAME *name = NULL;
170 name = X509_get_issuer_name(m_x509);
173 name = X509_get_subject_name(m_x509);
176 Assert("Invalid field type.");
180 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
181 "Error during x509 name extraction.");
186 std::string Certificate::getOneLine(FieldType type) const
188 X509_NAME *name = getX509Name(type);
189 static const int MAXB = 1024;
190 char buffer[MAXB] = {0, };
191 X509_NAME_oneline(name, buffer, MAXB);
193 return std::string(buffer);
196 std::string Certificate::getField(FieldType type, int fieldNid) const
198 X509_NAME *subjectName = getX509Name(type);
199 X509_NAME_ENTRY *subjectEntry = NULL;
201 int entryCount = X509_NAME_entry_count(subjectName);
203 for (int i = 0; i < entryCount; ++i) {
204 subjectEntry = X509_NAME_get_entry(subjectName,
211 int nid = OBJ_obj2nid(
212 static_cast<ASN1_OBJECT*>(
213 X509_NAME_ENTRY_get_object(subjectEntry)));
215 if (nid != fieldNid) {
219 ASN1_STRING* pASN1Str = subjectEntry->value;
221 unsigned char* pData = NULL;
222 int nLength = ASN1_STRING_to_UTF8(&pData,
226 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
227 "Reading field error.");
230 output = std::string();
233 output = std::string(reinterpret_cast<char*>(pData), nLength);
241 std::string Certificate::getCommonName(FieldType type) const
243 return getField(type, NID_commonName);
246 std::string Certificate::getCountryName(FieldType type) const
248 return getField(type, NID_countryName);
251 std::string Certificate::getStateOrProvinceName(FieldType type) const
253 return getField(type, NID_stateOrProvinceName);
256 std::string Certificate::getLocalityName(FieldType type) const
258 return getField(type, NID_localityName);
261 std::string Certificate::getOrganizationName(FieldType type) const
263 return getField(type, NID_organizationName);
266 std::string Certificate::getOrganizationalUnitName(FieldType type) const
268 return getField(type, NID_organizationalUnitName);
271 std::string Certificate::getEmailAddres(FieldType type) const
273 return getField(type, NID_pkcs9_emailAddress);
276 std::string Certificate::getOCSPURL() const
278 // TODO verify this code
279 std::string retValue;
280 AUTHORITY_INFO_ACCESS *aia = static_cast<AUTHORITY_INFO_ACCESS*>(
281 X509_get_ext_d2i(m_x509,
286 // no AIA extension in the cert
291 int count = sk_ACCESS_DESCRIPTION_num(aia);
293 for (int i = 0; i < count; ++i) {
294 ACCESS_DESCRIPTION* ad = sk_ACCESS_DESCRIPTION_value(aia, i);
296 if (OBJ_obj2nid(ad->method) == NID_ad_OCSP &&
297 ad->location->type == GEN_URI)
299 void *data = ASN1_STRING_data(ad->location->d.ia5);
301 retValue = std::string();
303 retValue = std::string(static_cast<char *>(data));
307 sk_ACCESS_DESCRIPTION_free(aia);
311 Certificate::AltNameSet Certificate::getAlternativeNameDNS() const
315 GENERAL_NAME *namePart = NULL;
317 STACK_OF(GENERAL_NAME)* san =
318 static_cast<STACK_OF(GENERAL_NAME)*>(
319 X509_get_ext_d2i(m_x509,NID_subject_alt_name,NULL,NULL));
321 while (sk_GENERAL_NAME_num(san) > 0) {
322 namePart = sk_GENERAL_NAME_pop(san);
323 if (GEN_DNS == namePart->type) {
324 char *temp = reinterpret_cast<char *>(ASN1_STRING_data(namePart->d.dNSName));
326 set.insert(std::string());
329 set.insert(std::string(temp));
330 LogDebug("FOUND GEN_DNS: " << temp);
333 LogDebug("FOUND GEN TYPE ID: " << namePart->type);
339 time_t Certificate::getNotAfter() const
341 ASN1_TIME *time = X509_get_notAfter(m_x509);
343 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
344 "Reading Not After error.");
347 if (asn1TimeToTimeT(time, &output))
348 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
349 "Converting ASN1_time to time_t error.");
354 time_t Certificate::getNotBefore() const
356 ASN1_TIME *time = X509_get_notBefore(m_x509);
358 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
359 "Reading Not Before error.");
362 if (asn1TimeToTimeT(time, &output))
363 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
364 "Converting ASN1_time to time_t error.");
369 ASN1_TIME* Certificate::getNotAfterTime() const
371 ASN1_TIME *timeafter = X509_get_notAfter(m_x509);
373 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
374 "Reading Not After error.");
379 ASN1_TIME* Certificate::getNotBeforeTime() const
381 ASN1_TIME *timebefore = X509_get_notBefore(m_x509);
383 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
384 "Reading Not Before error.");
389 bool Certificate::isRootCert()
391 // based on that root certificate has the same subject as issuer name
392 return isSignedBy(this->shared_from_this());
395 long Certificate::getVersion() const
397 return X509_get_version(m_x509);
400 std::string Certificate::getSerialNumberString() const
402 ASN1_INTEGER *ai = X509_get_serialNumber(m_x509);
404 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
405 "Error in X509_get_serialNumber");
407 std::stringstream stream;
408 stream << std::hex << std::setfill('0');
409 if (ai->type == V_ASN1_NEG_INTEGER) {
410 stream << "(Negetive) ";
412 for (int i=0; i<ai->length; ++i) {
413 stream << std::setw(2) << (int)ai->data[i] << ":";
415 std::string data = stream.str();
417 data.erase(--data.end());
423 std::string Certificate::getKeyUsageString() const
425 // Extensions were defined in RFC 3280
426 const char *usage[] = {
439 ASN1_BIT_STRING *keyUsage = (ASN1_BIT_STRING*)
440 X509_get_ext_d2i(m_x509, NID_key_usage, &crit, &idx);
442 std::stringstream stream;
443 for(int i=0; i<9; ++i) {
444 if (ASN1_BIT_STRING_get_bit(keyUsage, i)) {
445 stream << usage[i] << ",";
448 std::string result = stream.str();
449 if (!result.empty()) {
450 result.erase(--result.end());
456 std::string Certificate::getSignatureAlgorithmString() const
458 std::unique_ptr<BIO, std::function<int(BIO*)>>
459 b(BIO_new(BIO_s_mem()),BIO_free);
462 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
465 if (i2a_ASN1_OBJECT(b.get(), m_x509->cert_info->signature->algorithm) < 0)
466 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
467 "Error in i2a_ASN1_OBJECT");
470 BIO_get_mem_ptr(b.get(), &bptr);
472 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
473 "Error in BIO_get_mem_ptr");
475 std::string result(bptr->data, bptr->length);
480 std::string Certificate::getPublicKeyString() const
482 std::unique_ptr<BIO, std::function<int(BIO*)>>
483 b(BIO_new(BIO_s_mem()),BIO_free);
486 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
489 EVP_PKEY *pkey = X509_get_pubkey(m_x509);
491 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
492 "Error in X509_get_pubkey");
494 EVP_PKEY_print_public(b.get(), pkey, 16, NULL);
498 BIO_get_mem_ptr(b.get(), &bptr);
500 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
501 "Error in BIO_get_mem_ptr");
503 std::string result(bptr->data, bptr->length);
508 int Certificate::isCA() const
510 return X509_check_ca(m_x509);
513 std::string Certificate::FingerprintToColonHex(
514 const Certificate::Fingerprint &fingerprint)
516 std::string outString;
519 for (size_t i = 0; i < fingerprint.size(); ++i) {
523 static_cast<unsigned int>(fingerprint[i]));
527 // remove trailing ":"
528 outString.erase(outString.end() - 1);
532 } // namespace ValidationCore