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