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 &der,
59 Certificate::FormType form)
64 const unsigned char *ptr;
67 if (FORM_BASE64 == form) {
71 if (!base64.finalize()) {
72 LogWarning("Error during decoding");
75 ptr = reinterpret_cast<const unsigned char*>(tmp.c_str());
76 size = static_cast<int>(tmp.size());
78 ptr = reinterpret_cast<const unsigned char*>(der.c_str());
79 size = static_cast<int>(der.size());
82 m_x509 = d2i_X509(NULL, &ptr, size);
84 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
85 "Internal Openssl error in d2i_X509 function.");
88 Certificate::~Certificate()
93 X509* Certificate::getX509(void) const
98 std::string Certificate::getDER(void) const
100 unsigned char *rawDer = NULL;
101 int size = i2d_X509(m_x509, &rawDer);
102 if (!rawDer || size <= 0)
103 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
106 std::string output(reinterpret_cast<char*>(rawDer), size);
107 OPENSSL_free(rawDer);
111 std::string Certificate::getBase64(void) const
113 Base64Encoder base64;
115 base64.append(getDER());
120 bool Certificate::isSignedBy(const CertificatePtr &parent) const
123 LogDebug("Invalid certificate parameter.");
126 return 0 == X509_NAME_cmp(X509_get_subject_name(parent->m_x509),
127 X509_get_issuer_name(m_x509));
130 Certificate::Fingerprint Certificate::getFingerprint(
131 Certificate::FingerprintType type) const
133 unsigned int fingerprintlength = EVP_MAX_MD_SIZE;
134 unsigned char fingerprint[EVP_MAX_MD_SIZE];
137 if (type == FINGERPRINT_MD5) {
138 if (!X509_digest(m_x509, EVP_md5(), fingerprint, &fingerprintlength))
139 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
140 "MD5 digest counting failed!");
143 if (type == FINGERPRINT_SHA1) {
144 if (!X509_digest(m_x509, EVP_sha1(), fingerprint, &fingerprintlength))
145 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
146 "SHA1 digest counting failed");
149 raw.resize(fingerprintlength); // improve performance
150 std::copy(fingerprint, fingerprint + fingerprintlength, raw.begin());
155 X509_NAME *Certificate::getX509Name(FieldType type) const
157 X509_NAME *name = NULL;
161 name = X509_get_issuer_name(m_x509);
164 name = X509_get_subject_name(m_x509);
167 Assert("Invalid field type.");
171 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
172 "Error during x509 name extraction.");
177 std::string Certificate::getOneLine(FieldType type) const
179 X509_NAME *name = getX509Name(type);
180 static const int MAXB = 1024;
181 char buffer[MAXB] = {0, };
182 X509_NAME_oneline(name, buffer, MAXB);
184 return std::string(buffer);
187 std::string Certificate::getField(FieldType type, int fieldNid) const
189 X509_NAME *subjectName = getX509Name(type);
190 X509_NAME_ENTRY *subjectEntry = NULL;
192 int entryCount = X509_NAME_entry_count(subjectName);
194 for (int i = 0; i < entryCount; ++i) {
195 subjectEntry = X509_NAME_get_entry(subjectName,
202 int nid = OBJ_obj2nid(
203 static_cast<ASN1_OBJECT*>(
204 X509_NAME_ENTRY_get_object(subjectEntry)));
206 if (nid != fieldNid) {
210 ASN1_STRING* pASN1Str = subjectEntry->value;
212 unsigned char* pData = NULL;
213 int nLength = ASN1_STRING_to_UTF8(&pData,
217 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
218 "Reading field error.");
221 output = std::string();
224 output = std::string(reinterpret_cast<char*>(pData), nLength);
232 std::string Certificate::getCommonName(FieldType type) const
234 return getField(type, NID_commonName);
237 std::string Certificate::getCountryName(FieldType type) const
239 return getField(type, NID_countryName);
242 std::string Certificate::getStateOrProvinceName(FieldType type) const
244 return getField(type, NID_stateOrProvinceName);
247 std::string Certificate::getLocalityName(FieldType type) const
249 return getField(type, NID_localityName);
252 std::string Certificate::getOrganizationName(FieldType type) const
254 return getField(type, NID_organizationName);
257 std::string Certificate::getOrganizationalUnitName(FieldType type) const
259 return getField(type, NID_organizationalUnitName);
262 std::string Certificate::getEmailAddres(FieldType type) const
264 return getField(type, NID_pkcs9_emailAddress);
267 std::string Certificate::getOCSPURL() const
269 // TODO verify this code
270 std::string retValue;
271 AUTHORITY_INFO_ACCESS *aia = static_cast<AUTHORITY_INFO_ACCESS*>(
272 X509_get_ext_d2i(m_x509,
277 // no AIA extension in the cert
282 int count = sk_ACCESS_DESCRIPTION_num(aia);
284 for (int i = 0; i < count; ++i) {
285 ACCESS_DESCRIPTION* ad = sk_ACCESS_DESCRIPTION_value(aia, i);
287 if (OBJ_obj2nid(ad->method) == NID_ad_OCSP &&
288 ad->location->type == GEN_URI)
290 void *data = ASN1_STRING_data(ad->location->d.ia5);
292 retValue = std::string();
294 retValue = std::string(static_cast<char *>(data));
298 sk_ACCESS_DESCRIPTION_free(aia);
302 Certificate::AltNameSet Certificate::getAlternativeNameDNS() const
306 GENERAL_NAME *namePart = NULL;
308 STACK_OF(GENERAL_NAME)* san =
309 static_cast<STACK_OF(GENERAL_NAME)*>(
310 X509_get_ext_d2i(m_x509,NID_subject_alt_name,NULL,NULL));
312 while (sk_GENERAL_NAME_num(san) > 0) {
313 namePart = sk_GENERAL_NAME_pop(san);
314 if (GEN_DNS == namePart->type) {
315 char *temp = reinterpret_cast<char *>(ASN1_STRING_data(namePart->d.dNSName));
317 set.insert(std::string());
320 set.insert(std::string(temp));
321 LogDebug("FOUND GEN_DNS: " << temp);
324 LogDebug("FOUND GEN TYPE ID: " << namePart->type);
330 time_t Certificate::getNotAfter() const
332 ASN1_TIME *time = X509_get_notAfter(m_x509);
334 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
335 "Reading Not After error.");
338 if (asn1TimeToTimeT(time, &output))
339 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
340 "Converting ASN1_time to time_t error.");
345 time_t Certificate::getNotBefore() const
347 ASN1_TIME *time = X509_get_notBefore(m_x509);
349 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
350 "Reading Not Before error.");
353 if (asn1TimeToTimeT(time, &output))
354 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
355 "Converting ASN1_time to time_t error.");
360 ASN1_TIME* Certificate::getNotAfterTime() const
362 ASN1_TIME *timeafter = X509_get_notAfter(m_x509);
364 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
365 "Reading Not After error.");
370 ASN1_TIME* Certificate::getNotBeforeTime() const
372 ASN1_TIME *timebefore = X509_get_notBefore(m_x509);
374 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
375 "Reading Not Before error.");
380 bool Certificate::isRootCert()
382 // based on that root certificate has the same subject as issuer name
383 return isSignedBy(this->shared_from_this());
386 #ifdef TIZEN_FEATURE_CERT_SVC_OCSP_CRL
387 std::list<std::string>
388 Certificate::getCrlUris() const
390 std::list<std::string> result;
392 STACK_OF(DIST_POINT)* distPoints =
393 static_cast<STACK_OF(DIST_POINT)*>(
396 NID_crl_distribution_points,
400 LogDebug("No distribution points in certificate.");
404 int count = sk_DIST_POINT_num(distPoints);
405 for (int i = 0; i < count; ++i) {
406 DIST_POINT* point = sk_DIST_POINT_value(distPoints, i);
408 LogError("Failed to get distribution point.");
411 if (point->distpoint != NULL &&
412 point->distpoint->name.fullname != NULL)
415 sk_GENERAL_NAME_num(point->distpoint->name.fullname);
416 for (int j = 0; j < countName; ++j) {
417 GENERAL_NAME* name = sk_GENERAL_NAME_value(
418 point->distpoint->name.fullname, j);
419 if (name != NULL && GEN_URI == name->type) {
421 reinterpret_cast<char*>(name->d.ia5->data);
423 LogError("Failed to get URI.");
426 result.push_back(crlUri);
431 sk_DIST_POINT_pop_free(distPoints, DIST_POINT_free);
436 long Certificate::getVersion() const
438 return X509_get_version(m_x509);
441 std::string Certificate::getSerialNumberString() const
443 ASN1_INTEGER *ai = X509_get_serialNumber(m_x509);
445 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
446 "Error in X509_get_serialNumber");
448 std::stringstream stream;
449 stream << std::hex << std::setfill('0');
450 if (ai->type == V_ASN1_NEG_INTEGER) {
451 stream << "(Negetive) ";
453 for (int i=0; i<ai->length; ++i) {
454 stream << std::setw(2) << (int)ai->data[i] << ":";
456 std::string data = stream.str();
458 data.erase(--data.end());
464 std::string Certificate::getKeyUsageString() const
466 // Extensions were defined in RFC 3280
467 const char *usage[] = {
480 ASN1_BIT_STRING *keyUsage = (ASN1_BIT_STRING*)
481 X509_get_ext_d2i(m_x509, NID_key_usage, &crit, &idx);
483 std::stringstream stream;
484 for(int i=0; i<9; ++i) {
485 if (ASN1_BIT_STRING_get_bit(keyUsage, i)) {
486 stream << usage[i] << ",";
489 std::string result = stream.str();
490 if (!result.empty()) {
491 result.erase(--result.end());
497 std::string Certificate::getSignatureAlgorithmString() const
499 std::unique_ptr<BIO, std::function<int(BIO*)>>
500 b(BIO_new(BIO_s_mem()),BIO_free);
503 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
506 if (i2a_ASN1_OBJECT(b.get(), m_x509->cert_info->signature->algorithm) < 0)
507 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
508 "Error in i2a_ASN1_OBJECT");
511 BIO_get_mem_ptr(b.get(), &bptr);
513 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
514 "Error in BIO_get_mem_ptr");
516 std::string result(bptr->data, bptr->length);
521 std::string Certificate::getPublicKeyString() const
523 std::unique_ptr<BIO, std::function<int(BIO*)>>
524 b(BIO_new(BIO_s_mem()),BIO_free);
527 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
530 EVP_PKEY *pkey = X509_get_pubkey(m_x509);
532 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
533 "Error in X509_get_pubkey");
535 EVP_PKEY_print_public(b.get(), pkey, 16, NULL);
539 BIO_get_mem_ptr(b.get(), &bptr);
541 VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
542 "Error in BIO_get_mem_ptr");
544 std::string result(bptr->data, bptr->length);
549 int Certificate::isCA() const
551 return X509_check_ca(m_x509);
554 std::string Certificate::FingerprintToColonHex(
555 const Certificate::Fingerprint &fingerprint)
557 std::string outString;
560 for (size_t i = 0; i < fingerprint.size(); ++i) {
564 static_cast<unsigned int>(fingerprint[i]));
568 // remove trailing ":"
569 outString.erase(outString.end() - 1);
573 } // namespace ValidationCore