Refactor SignatureValidator and reduce interface headers
[platform/core/security/cert-svc.git] / vcore / src / vcore / Certificate.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        Certificate.cpp
18  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
19  * @version     1.0
20  * @brief
21  */
22 #include <vcore/Certificate.h>
23
24 #include <memory>
25 #include <sstream>
26 #include <iomanip>
27
28 #include <openssl/x509v3.h>
29 #include <openssl/bn.h>
30
31 #include <dpl/assert.h>
32 #include <dpl/log/log.h>
33
34 #include <vcore/Base64.h>
35 #include <vcore/TimeConversion.h>
36
37 namespace ValidationCore {
38
39 Certificate::Certificate(X509 *cert)
40 {
41     Assert(cert);
42     m_x509 = X509_dup(cert);
43     if (!m_x509)
44         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
45                       "Internal Openssl error in d2i_X509 function.");
46 }
47
48 Certificate::Certificate(cert_svc_mem_buff &buffer)
49 {
50     Assert(buffer.data);
51     const unsigned char *ptr = buffer.data;
52     m_x509 = d2i_X509(NULL, &ptr, buffer.size);
53     if (!m_x509)
54         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
55                       "Internal Openssl error in d2i_X509 function.");
56 }
57
58 Certificate::Certificate(const std::string &data,
59                          Certificate::FormType form)
60 {
61     Assert(data.size());
62
63     int size;
64     const unsigned char *ptr;
65     std::string tmp = data;
66
67     // transform to DER format
68     if (FORM_BASE64 == form) {
69         try {
70             Base64Decoder base64;
71             base64.reset();
72             base64.append(data);
73             if (!base64.finalize()) {
74                 LogWarning("Error during decoding");
75             }
76             tmp = base64.get();
77         } catch (const Base64Decoder::Exception::Base &e) {
78             LogError("Exception in Certificate constructor : " << e.DumpToString());
79             VcoreThrowMsg(Certificate::Exception::Base64Error, "Failed to Base64Decoder");
80         }
81     }
82
83     ptr = reinterpret_cast<const unsigned char*>(tmp.c_str());
84     size = static_cast<int>(tmp.size());
85
86     m_x509 = d2i_X509(NULL, &ptr, size);
87     if (!m_x509)
88         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
89                       "Internal Openssl error in d2i_X509 function.");
90 }
91
92 Certificate::~Certificate()
93 {
94     X509_free(m_x509);
95 }
96
97 X509* Certificate::getX509(void) const
98 {
99     return m_x509;
100 }
101
102 std::string Certificate::getDER(void) const
103 {
104     unsigned char *rawDer = NULL;
105     int size = i2d_X509(m_x509, &rawDer);
106     if (!rawDer || size <= 0)
107         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
108                       "i2d_X509 failed");
109
110     std::string output(reinterpret_cast<char*>(rawDer), size);
111     OPENSSL_free(rawDer);
112     return output;
113 }
114
115 std::string Certificate::getBase64(void) const
116 {
117     Base64Encoder base64;
118     try {
119         base64.reset();
120         base64.append(getDER());
121         base64.finalize();
122     } catch (const Base64Encoder::Exception::Base &e) {
123         LogError("Exception in Certificate getBase64 : " << e.DumpToString());
124         VcoreThrowMsg(Certificate::Exception::Base64Error, "Failed to Base64Encoder");
125     }
126     return base64.get();
127 }
128
129 bool Certificate::isSignedBy(const CertificatePtr &parent) const
130 {
131     if (!parent) {
132         LogDebug("Invalid certificate parameter.");
133         return false;
134     }
135     return 0 == X509_NAME_cmp(X509_get_subject_name(parent->m_x509),
136                               X509_get_issuer_name(m_x509));
137 }
138
139 Certificate::Fingerprint Certificate::getFingerprint(
140         Certificate::FingerprintType type) const
141 {
142     unsigned int fingerprintlength = EVP_MAX_MD_SIZE;
143     unsigned char fingerprint[EVP_MAX_MD_SIZE];
144     Fingerprint raw;
145
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!");
150     }
151
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");
156     }
157
158     raw.resize(fingerprintlength); // improve performance
159     std::copy(fingerprint, fingerprint + fingerprintlength, raw.begin());
160
161     return raw;
162 }
163
164 X509_NAME *Certificate::getX509Name(FieldType type) const
165 {
166     X509_NAME *name = NULL;
167
168     switch (type) {
169     case FIELD_ISSUER:
170         name = X509_get_issuer_name(m_x509);
171         break;
172     case FIELD_SUBJECT:
173         name = X509_get_subject_name(m_x509);
174         break;
175     default:
176         Assert("Invalid field type.");
177     }
178
179     if (!name)
180         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
181                       "Error during x509 name extraction.");
182
183     return name;
184 }
185
186 std::string Certificate::getOneLine(FieldType type) const
187 {
188     X509_NAME *name = getX509Name(type);
189     static const int MAXB = 1024;
190     char buffer[MAXB] = {0, };
191     X509_NAME_oneline(name, buffer, MAXB);
192
193     return std::string(buffer);
194 }
195
196 std::string Certificate::getField(FieldType type, int fieldNid) const
197 {
198     X509_NAME *subjectName = getX509Name(type);
199     X509_NAME_ENTRY *subjectEntry = NULL;
200     std::string output;
201     int entryCount = X509_NAME_entry_count(subjectName);
202
203     for (int i = 0; i < entryCount; ++i) {
204         subjectEntry = X509_NAME_get_entry(subjectName,
205                                            i);
206
207         if (!subjectEntry) {
208             continue;
209         }
210
211         int nid = OBJ_obj2nid(
212             static_cast<ASN1_OBJECT*>(
213                     X509_NAME_ENTRY_get_object(subjectEntry)));
214
215         if (nid != fieldNid) {
216             continue;
217         }
218
219         ASN1_STRING* pASN1Str = subjectEntry->value;
220
221         unsigned char* pData = NULL;
222         int nLength = ASN1_STRING_to_UTF8(&pData,
223                                           pASN1Str);
224
225         if (nLength < 0)
226             VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
227                           "Reading field error.");
228
229         if (!pData) {
230             output = std::string();
231         }
232         else {
233             output = std::string(reinterpret_cast<char*>(pData), nLength);
234             OPENSSL_free(pData);
235         }
236     }
237
238     return output;
239 }
240
241 std::string Certificate::getCommonName(FieldType type) const
242 {
243     return getField(type, NID_commonName);
244 }
245
246 std::string Certificate::getCountryName(FieldType type) const
247 {
248     return getField(type, NID_countryName);
249 }
250
251 std::string Certificate::getStateOrProvinceName(FieldType type) const
252 {
253     return getField(type, NID_stateOrProvinceName);
254 }
255
256 std::string Certificate::getLocalityName(FieldType type) const
257 {
258     return getField(type, NID_localityName);
259 }
260
261 std::string Certificate::getOrganizationName(FieldType type) const
262 {
263     return getField(type, NID_organizationName);
264 }
265
266 std::string Certificate::getOrganizationalUnitName(FieldType type) const
267 {
268     return getField(type, NID_organizationalUnitName);
269 }
270
271 std::string Certificate::getEmailAddres(FieldType type) const
272 {
273     return getField(type, NID_pkcs9_emailAddress);
274 }
275
276 std::string Certificate::getOCSPURL() const
277 {
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,
282                              NID_info_access,
283                              NULL,
284                              NULL));
285
286     // no AIA extension in the cert
287     if (NULL == aia) {
288         return retValue;
289     }
290
291     int count = sk_ACCESS_DESCRIPTION_num(aia);
292
293     for (int i = 0; i < count; ++i) {
294         ACCESS_DESCRIPTION* ad = sk_ACCESS_DESCRIPTION_value(aia, i);
295
296         if (OBJ_obj2nid(ad->method) == NID_ad_OCSP &&
297             ad->location->type == GEN_URI)
298         {
299             void *data = ASN1_STRING_data(ad->location->d.ia5);
300             if (!data)
301                 retValue = std::string();
302             else
303                 retValue = std::string(static_cast<char *>(data));
304             break;
305         }
306     }
307     sk_ACCESS_DESCRIPTION_free(aia);
308     return retValue;
309 }
310
311 Certificate::AltNameSet Certificate::getAlternativeNameDNS() const
312 {
313     AltNameSet set;
314
315     GENERAL_NAME *namePart = NULL;
316
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));
320
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));
325             if (!temp) {
326                 set.insert(std::string());
327             }
328             else {
329                 set.insert(std::string(temp));
330                 LogDebug("FOUND GEN_DNS: " << temp);
331             }
332         } else {
333             LogDebug("FOUND GEN TYPE ID: " << namePart->type);
334         }
335     }
336     return set;
337 }
338
339 time_t Certificate::getNotAfter() const
340 {
341     ASN1_TIME *time = X509_get_notAfter(m_x509);
342     if (!time)
343         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
344                       "Reading Not After error.");
345
346     time_t output;
347     if (asn1TimeToTimeT(time, &output))
348         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
349                       "Converting ASN1_time to time_t error.");
350
351     return output;
352 }
353
354 time_t Certificate::getNotBefore() const
355 {
356     ASN1_TIME *time = X509_get_notBefore(m_x509);
357     if (!time)
358         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
359                       "Reading Not Before error.");
360
361     time_t output;
362     if (asn1TimeToTimeT(time, &output))
363         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
364                       "Converting ASN1_time to time_t error.");
365
366     return output;
367 }
368
369 ASN1_TIME* Certificate::getNotAfterTime() const
370 {
371     ASN1_TIME *timeafter = X509_get_notAfter(m_x509);
372     if (!timeafter)
373         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
374                       "Reading Not After error.");
375
376     return timeafter;
377 }
378
379 ASN1_TIME* Certificate::getNotBeforeTime() const
380 {
381     ASN1_TIME *timebefore = X509_get_notBefore(m_x509);
382     if (!timebefore)
383         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
384                       "Reading Not Before error.");
385
386     return timebefore;
387 }
388
389 bool Certificate::isRootCert()
390 {
391     // based on that root certificate has the same subject as issuer name
392     return isSignedBy(this->shared_from_this());
393 }
394
395 long Certificate::getVersion() const
396 {
397     return X509_get_version(m_x509);
398 }
399
400 std::string Certificate::getSerialNumberString() const
401 {
402     ASN1_INTEGER *ai = X509_get_serialNumber(m_x509);
403     if (!ai)
404         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
405                       "Error in X509_get_serialNumber");
406
407     std::stringstream stream;
408     stream << std::hex << std::setfill('0');
409     if (ai->type == V_ASN1_NEG_INTEGER) {
410         stream << "(Negetive) ";
411     }
412     for (int i=0; i<ai->length; ++i) {
413         stream << std::setw(2) << (int)ai->data[i] << ":";
414     }
415     std::string data = stream.str();
416     if (!data.empty()) {
417         data.erase(--data.end());
418     }
419
420     return data;
421 }
422
423 std::string Certificate::getKeyUsageString() const
424 {
425     // Extensions were defined in RFC 3280
426     const char *usage[] = {
427         "digitalSignature",
428         "nonRepudiation",
429         "keyEncipherment",
430         "dataEncipherment",
431         "keyAgreement",
432         "keyCertSign",
433         "cRLSign",
434         "encipherOnly",
435         "decipherOnly"
436     };
437     int crit = -1;
438     int idx = -1;
439     ASN1_BIT_STRING *keyUsage = (ASN1_BIT_STRING*)
440         X509_get_ext_d2i(m_x509, NID_key_usage, &crit, &idx);
441
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] << ",";
446         }
447     }
448     std::string result = stream.str();
449     if (!result.empty()) {
450         result.erase(--result.end());
451     }
452
453     return result;
454 }
455
456 std::string Certificate::getSignatureAlgorithmString() const
457 {
458     std::unique_ptr<BIO, std::function<int(BIO*)>>
459         b(BIO_new(BIO_s_mem()),BIO_free);
460
461     if (!b.get())
462         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
463                       "Error in BIO_new");
464
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");
468
469     BUF_MEM *bptr = 0;
470     BIO_get_mem_ptr(b.get(), &bptr);
471     if (bptr == 0)
472         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
473                       "Error in BIO_get_mem_ptr");
474
475     std::string result(bptr->data, bptr->length);
476
477     return result;
478 }
479
480 std::string Certificate::getPublicKeyString() const
481 {
482     std::unique_ptr<BIO, std::function<int(BIO*)>>
483         b(BIO_new(BIO_s_mem()),BIO_free);
484
485     if (!b.get())
486         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
487                       "Error in BIO_new");
488
489     EVP_PKEY *pkey = X509_get_pubkey(m_x509);
490     if (!pkey)
491         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
492                       "Error in X509_get_pubkey");
493
494     EVP_PKEY_print_public(b.get(), pkey, 16, NULL);
495     EVP_PKEY_free(pkey);
496
497     BUF_MEM *bptr = 0;
498     BIO_get_mem_ptr(b.get(), &bptr);
499     if (bptr == 0)
500         VcoreThrowMsg(Certificate::Exception::OpensslInternalError,
501                       "Error in BIO_get_mem_ptr");
502
503     std::string result(bptr->data, bptr->length);
504
505     return result;
506 }
507
508 int Certificate::isCA() const
509 {
510     return X509_check_ca(m_x509);
511 }
512
513 std::string Certificate::FingerprintToColonHex(
514         const Certificate::Fingerprint &fingerprint)
515 {
516     std::string outString;
517     char buff[8];
518
519     for (size_t i = 0; i < fingerprint.size(); ++i) {
520         snprintf(buff,
521                  sizeof(buff),
522                  "%02X:",
523                  static_cast<unsigned int>(fingerprint[i]));
524         outString += buff;
525     }
526
527     // remove trailing ":"
528     outString.erase(outString.end() - 1);
529     return outString;
530 }
531
532 } //  namespace ValidationCore