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 = OBJ_obj2nid(
128		fPrivate->fX509->cert_info->key->algor->algorithm);
129
130	if (algorithmIdentifier == NID_undef)
131		return BString("undefined");
132
133	const char* buffer = OBJ_nid2ln(algorithmIdentifier);
134	return BString(buffer);
135}
136
137
138BString
139BCertificate::String() const
140{
141	BIO *buffer = BIO_new(BIO_s_mem());
142	X509_print_ex(buffer, fPrivate->fX509, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
143
144	char* pointer;
145	long length = BIO_get_mem_data(buffer, &pointer);
146	BString result(pointer, length);
147
148	BIO_free(buffer);
149	return result;
150}
151
152
153bool
154BCertificate::operator==(const BCertificate& other) const
155{
156	return X509_cmp(fPrivate->fX509, other.fPrivate->fX509) == 0;
157}
158
159
160// #pragma mark - BCertificate::Private
161
162
163BCertificate::Private::Private(X509* data)
164	: fX509(X509_dup(data))
165{
166}
167
168
169BCertificate::Private::~Private()
170{
171	X509_free(fX509);
172}
173
174
175#else
176
177
178BCertificate::BCertificate(const BCertificate& other)
179{
180}
181
182
183BCertificate::BCertificate(Private* data)
184{
185}
186
187
188BCertificate::~BCertificate()
189{
190}
191
192
193time_t
194BCertificate::StartDate() const
195{
196	return B_NOT_SUPPORTED;
197}
198
199
200time_t
201BCertificate::ExpirationDate() const
202{
203	return B_NOT_SUPPORTED;
204}
205
206
207bool
208BCertificate::IsValidAuthority() const
209{
210	return false;
211}
212
213
214int
215BCertificate::Version() const
216{
217	return B_NOT_SUPPORTED;
218}
219
220
221BString
222BCertificate::Issuer() const
223{
224	return BString();
225}
226
227
228BString
229BCertificate::Subject() const
230{
231	return BString();
232}
233
234
235BString
236BCertificate::SignatureAlgorithm() const
237{
238	return BString();
239}
240
241
242BString
243BCertificate::String() const
244{
245	return BString();
246}
247
248
249bool
250BCertificate::operator==(const BCertificate& other) const
251{
252	return false;
253}
254
255#endif
256