1/* 2 * Copyright 2014 Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include <Certificate.h> 8 9#include <String.h> 10 11#include "CertificatePrivate.h" 12 13 14#ifdef OPENSSL_ENABLED 15 16 17#include <openssl/x509v3.h> 18 19 20static time_t 21parse_ASN1(ASN1_GENERALIZEDTIME *asn1) 22{ 23 // Get the raw string data out of the ASN1 container. It looks like this: 24 // "YYMMDDHHMMSSZ" 25 struct tm time; 26 27 if (sscanf((char*)asn1->data, "%2d%2d%2d%2d%2d%2d", &time.tm_year, 28 &time.tm_mon, &time.tm_mday, &time.tm_hour, &time.tm_min, 29 &time.tm_sec) == 6) { 30 31 // Month is 0 based, and year is 1900-based for mktime. 32 time.tm_year += 100; 33 time.tm_mon -= 1; 34 35 return mktime(&time); 36 } 37 return B_BAD_DATA; 38} 39 40 41static BString 42decode_X509_NAME(X509_NAME* name) 43{ 44 char* buffer = X509_NAME_oneline(name, NULL, 0); 45 46 BString result(buffer); 47 OPENSSL_free(buffer); 48 return result; 49} 50 51 52// #pragma mark - BCertificate 53 54 55BCertificate::BCertificate(Private* data) 56{ 57 fPrivate = data; 58} 59 60 61BCertificate::BCertificate(const BCertificate& other) 62{ 63 fPrivate = new(std::nothrow) BCertificate::Private(other.fPrivate->fX509); 64} 65 66 67BCertificate::~BCertificate() 68{ 69 delete fPrivate; 70} 71 72 73int 74BCertificate::Version() const 75{ 76 return X509_get_version(fPrivate->fX509) + 1; 77} 78 79 80time_t 81BCertificate::StartDate() const 82{ 83 return parse_ASN1(X509_get_notBefore(fPrivate->fX509)); 84} 85 86 87time_t 88BCertificate::ExpirationDate() const 89{ 90 return parse_ASN1(X509_get_notAfter(fPrivate->fX509)); 91} 92 93 94bool 95BCertificate::IsValidAuthority() const 96{ 97 return X509_check_ca(fPrivate->fX509) > 0; 98} 99 100 101bool 102BCertificate::IsSelfSigned() const 103{ 104 return X509_check_issued(fPrivate->fX509, fPrivate->fX509) == X509_V_OK; 105} 106 107 108BString 109BCertificate::Issuer() const 110{ 111 X509_NAME* name = X509_get_issuer_name(fPrivate->fX509); 112 return decode_X509_NAME(name); 113} 114 115 116BString 117BCertificate::Subject() const 118{ 119 X509_NAME* name = X509_get_subject_name(fPrivate->fX509); 120 return decode_X509_NAME(name); 121} 122 123 124BString 125BCertificate::SignatureAlgorithm() const 126{ 127 int algorithmIdentifier; 128 if (!X509_get_signature_info(fPrivate->fX509, NULL, &algorithmIdentifier, 129 NULL, NULL)) { 130 return BString("invalid"); 131 } 132 133 if (algorithmIdentifier == NID_undef) 134 return BString("undefined"); 135 136 const char* buffer = OBJ_nid2ln(algorithmIdentifier); 137 return BString(buffer); 138} 139 140 141BString 142BCertificate::String() const 143{ 144 BIO *buffer = BIO_new(BIO_s_mem()); 145 X509_print_ex(buffer, fPrivate->fX509, XN_FLAG_COMPAT, X509_FLAG_COMPAT); 146 147 char* pointer; 148 long length = BIO_get_mem_data(buffer, &pointer); 149 BString result(pointer, length); 150 151 BIO_free(buffer); 152 return result; 153} 154 155 156bool 157BCertificate::operator==(const BCertificate& other) const 158{ 159 return X509_cmp(fPrivate->fX509, other.fPrivate->fX509) == 0; 160} 161 162 163// #pragma mark - BCertificate::Private 164 165 166BCertificate::Private::Private(X509* data) 167 : fX509(X509_dup(data)) 168{ 169} 170 171 172BCertificate::Private::~Private() 173{ 174 X509_free(fX509); 175} 176 177 178#else 179 180 181BCertificate::BCertificate(const BCertificate& other) 182{ 183} 184 185 186BCertificate::BCertificate(Private* data) 187{ 188} 189 190 191BCertificate::~BCertificate() 192{ 193} 194 195 196time_t 197BCertificate::StartDate() const 198{ 199 return B_NOT_SUPPORTED; 200} 201 202 203time_t 204BCertificate::ExpirationDate() const 205{ 206 return B_NOT_SUPPORTED; 207} 208 209 210bool 211BCertificate::IsValidAuthority() const 212{ 213 return false; 214} 215 216 217int 218BCertificate::Version() const 219{ 220 return B_NOT_SUPPORTED; 221} 222 223 224BString 225BCertificate::Issuer() const 226{ 227 return BString(); 228} 229 230 231BString 232BCertificate::Subject() const 233{ 234 return BString(); 235} 236 237 238BString 239BCertificate::SignatureAlgorithm() const 240{ 241 return BString(); 242} 243 244 245BString 246BCertificate::String() const 247{ 248 return BString(); 249} 250 251 252bool 253BCertificate::operator==(const BCertificate& other) const 254{ 255 return false; 256} 257 258#endif 259