2f1fb09f7750f56bd70c4eb37c286ae9d50fda1f
[strongswan.git] / src / libstrongswan / plugins / pubkey / pubkey_cert.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "pubkey_cert.h"
17
18 #include <debug.h>
19
20 typedef struct private_pubkey_cert_t private_pubkey_cert_t;
21
22 /**
23 * private data of pubkey_cert
24 */
25 struct private_pubkey_cert_t {
26
27 /**
28 * public functions
29 */
30 pubkey_cert_t public;
31
32 /**
33 * wrapped public key
34 */
35 public_key_t *key;
36
37 /**
38 * dummy issuer id, ID_ANY
39 */
40 identification_t *issuer;
41
42 /**
43 * subject, ID_KEY_ID of the public key
44 */
45 identification_t *subject;
46
47 /**
48 * reference count
49 */
50 refcount_t ref;
51 };
52
53 /**
54 * Implementation of certificate_t.get_type
55 */
56 static certificate_type_t get_type(private_pubkey_cert_t *this)
57 {
58 return CERT_TRUSTED_PUBKEY;
59 }
60
61 /**
62 * Implementation of certificate_t.get_subject
63 */
64 static identification_t* get_subject(private_pubkey_cert_t *this)
65 {
66 return this->subject;
67 }
68
69 /**
70 * Implementation of certificate_t.get_issuer
71 */
72 static identification_t* get_issuer(private_pubkey_cert_t *this)
73 {
74 return this->issuer;
75 }
76
77 /**
78 * Implementation of certificate_t.has_subject.
79 */
80 static id_match_t has_subject(private_pubkey_cert_t *this,
81 identification_t *subject)
82 {
83 if (subject->get_type(subject) == ID_KEY_ID)
84 {
85 key_encoding_type_t type;
86 chunk_t fingerprint;
87
88 for (type = 0; type < KEY_ENCODING_MAX; type++)
89 {
90 if (this->key->get_fingerprint(this->key, type, &fingerprint) &&
91 chunk_equals(fingerprint, subject->get_encoding(subject)))
92 {
93 return ID_MATCH_PERFECT;
94 }
95 }
96 }
97 return ID_MATCH_NONE;
98 }
99
100 /**
101 * Implementation of certificate_t.has_subject.
102 */
103 static id_match_t has_issuer(private_pubkey_cert_t *this,
104 identification_t *issuer)
105 {
106 return ID_MATCH_NONE;
107 }
108
109 /**
110 * Implementation of certificate_t.equals.
111 */
112 static bool equals(private_pubkey_cert_t *this, certificate_t *other)
113 {
114 public_key_t *other_key;
115
116 other_key = other->get_public_key(other);
117 if (other_key)
118 {
119 if (public_key_equals(this->key, other_key))
120 {
121 other_key->destroy(other_key);
122 return TRUE;
123 }
124 other_key->destroy(other_key);
125 }
126 return FALSE;
127 }
128
129 /**
130 * Implementation of certificate_t.issued_by
131 */
132 static bool issued_by(private_pubkey_cert_t *this, certificate_t *issuer)
133 {
134 return equals(this, issuer);
135 }
136
137 /**
138 * Implementation of certificate_t.get_public_key
139 */
140 static public_key_t* get_public_key(private_pubkey_cert_t *this)
141 {
142 this->key->get_ref(this->key);
143 return this->key;
144 }
145
146 /**
147 * Implementation of certificate_t.get_validity.
148 */
149 static bool get_validity(private_pubkey_cert_t *this, time_t *when,
150 time_t *not_before, time_t *not_after)
151 {
152 if (not_before)
153 {
154 *not_before = 0;
155 }
156 if (not_after)
157 {
158 *not_after = ~0;
159 }
160 return TRUE;
161 }
162
163 /**
164 * Implementation of certificate_t.is_newer.
165 */
166 static bool is_newer(certificate_t *this, certificate_t *that)
167 {
168 return FALSE;
169 }
170
171 /**
172 * Implementation of certificate_t.get_encoding.
173 */
174 static chunk_t get_encoding(private_pubkey_cert_t *this)
175 {
176 chunk_t encoding;
177
178 if (this->key->get_encoding(this->key, KEY_PUB_ASN1_DER, &encoding))
179 {
180 return encoding;
181 }
182 return chunk_empty;
183 }
184
185 /**
186 * Implementation of certificate_t.get_ref
187 */
188 static private_pubkey_cert_t* get_ref(private_pubkey_cert_t *this)
189 {
190 ref_get(&this->ref);
191 return this;
192 }
193
194 /**
195 * Implementation of pubkey_cert_t.destroy
196 */
197 static void destroy(private_pubkey_cert_t *this)
198 {
199 if (ref_put(&this->ref))
200 {
201 this->subject->destroy(this->subject);
202 this->issuer->destroy(this->issuer);
203 this->key->destroy(this->key);
204 free(this);
205 }
206 }
207
208 /*
209 * see header file
210 */
211 static pubkey_cert_t *pubkey_cert_create(public_key_t *key)
212 {
213 private_pubkey_cert_t *this = malloc_thing(private_pubkey_cert_t);
214 chunk_t fingerprint;
215
216 this->public.interface.get_type = (certificate_type_t (*)(certificate_t *this))get_type;
217 this->public.interface.get_subject = (identification_t* (*)(certificate_t *this))get_subject;
218 this->public.interface.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
219 this->public.interface.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_subject;
220 this->public.interface.has_issuer = (id_match_t (*)(certificate_t*, identification_t *issuer))has_issuer;
221 this->public.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by;
222 this->public.interface.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
223 this->public.interface.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
224 this->public.interface.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
225 this->public.interface.get_encoding = (chunk_t (*)(certificate_t*))get_encoding;
226 this->public.interface.equals = (bool (*)(certificate_t*, certificate_t *other))equals;
227 this->public.interface.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
228 this->public.interface.destroy = (void (*)(certificate_t *this))destroy;
229
230 this->ref = 1;
231 this->key = key;
232 this->issuer = identification_create_from_encoding(ID_ANY, chunk_empty);
233 if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &fingerprint))
234 {
235 this->subject = identification_create_from_encoding(ID_KEY_ID, fingerprint);
236 }
237 else
238 {
239 this->subject = identification_create_from_encoding(ID_ANY, chunk_empty);
240 }
241
242 return &this->public;
243 }
244
245 typedef struct private_builder_t private_builder_t;
246 /**
247 * Builder implementation for key loading
248 */
249 struct private_builder_t {
250 /** implements the builder interface */
251 builder_t public;
252 /** loaded public key */
253 pubkey_cert_t *key;
254 };
255
256 /**
257 * Implementation of builder_t.build
258 */
259 static pubkey_cert_t *build(private_builder_t *this)
260 {
261 pubkey_cert_t *key = this->key;
262
263 free(this);
264 return key;
265 }
266
267 /**
268 * Implementation of builder_t.add
269 */
270 static void add(private_builder_t *this, builder_part_t part, ...)
271 {
272 if (!this->key)
273 {
274 public_key_t *key;
275 va_list args;
276
277 switch (part)
278 {
279 case BUILD_BLOB_ASN1_DER:
280 {
281 va_start(args, part);
282 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
283 va_arg(args, chunk_t));
284 if (key)
285 {
286 this->key = pubkey_cert_create(key);
287 }
288 va_end(args);
289 return;
290 }
291 case BUILD_PUBLIC_KEY:
292 {
293 va_start(args, part);
294 key = va_arg(args, public_key_t*);
295 pubkey_cert_create(key->get_ref(key));
296 va_end(args);
297 return;
298 }
299 default:
300 break;
301 }
302 }
303 if (this->key)
304 {
305 destroy((private_pubkey_cert_t*)this->key);
306 }
307 builder_cancel(&this->public);
308 }
309
310 /**
311 * Builder construction function
312 */
313 builder_t *pubkey_cert_builder(certificate_type_t type)
314 {
315 private_builder_t *this;
316
317 if (type != CERT_TRUSTED_PUBKEY)
318 {
319 return NULL;
320 }
321
322 this = malloc_thing(private_builder_t);
323
324 this->key = NULL;
325 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
326 this->public.build = (void*(*)(builder_t *this))build;
327
328 return &this->public;
329 }
330