Use bits instead of bytes for a private/public key
[strongswan.git] / src / pluto / certs.c
1 /* Certificate support for IKE authentication
2 * Copyright (C) 2002-2009 Andreas Steffen
3 *
4 * HSR - Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <time.h>
22
23 #include <freeswan.h>
24
25 #include <library.h>
26 #include <asn1/asn1.h>
27 #include <credentials/certificates/certificate.h>
28 #include <credentials/certificates/pgp_certificate.h>
29
30 #include "constants.h"
31 #include "defs.h"
32 #include "log.h"
33 #include "certs.h"
34 #include "whack.h"
35 #include "fetch.h"
36 #include "keys.h"
37 #include "builder.h"
38
39 /**
40 * Initialization
41 */
42 const cert_t cert_empty = {
43 NULL , /* cert */
44 NULL , /* *next */
45 0 , /* count */
46 FALSE /* smartcard */
47 };
48
49 /**
50 * Chained lists of X.509 and PGP end entity certificates
51 */
52 static cert_t *certs = NULL;
53
54 /**
55 * Free a pluto certificate
56 */
57 void cert_free(cert_t *cert)
58 {
59 if (cert)
60 {
61 certificate_t *certificate = cert->cert;
62
63 if (certificate)
64 {
65 certificate->destroy(certificate);
66 }
67 free(cert);
68 }
69 }
70
71 /**
72 * Add a pluto end entity certificate to the chained list
73 */
74 cert_t* cert_add(cert_t *cert)
75 {
76 certificate_t *certificate = cert->cert;
77 cert_t *c = certs;
78
79 while (c != NULL)
80 {
81 if (certificate->equals(certificate, c->cert)) /* already in chain, free cert */
82 {
83 cert_free(cert);
84 return c;
85 }
86 c = c->next;
87 }
88
89 /* insert new cert at the root of the chain */
90 lock_certs_and_keys("cert_add");
91 cert->next = certs;
92 certs = cert;
93 DBG(DBG_CONTROL | DBG_PARSING,
94 DBG_log(" cert inserted")
95 )
96 unlock_certs_and_keys("cert_add");
97 return cert;
98 }
99
100 /**
101 * Loads a X.509 or OpenPGP certificate
102 */
103 cert_t* load_cert(char *filename, const char *label, x509_flag_t flags)
104 {
105 cert_t *cert;
106
107 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_PLUTO_CERT,
108 BUILD_FROM_FILE, filename,
109 BUILD_X509_FLAG, flags,
110 BUILD_END);
111 if (cert)
112 {
113 plog(" loaded %s certificate from '%s'", label, filename);
114 }
115 return cert;
116 }
117
118 /**
119 * Loads a host certificate
120 */
121 cert_t* load_host_cert(char *filename)
122 {
123 char *path = concatenate_paths(HOST_CERT_PATH, filename);
124
125 return load_cert(path, "host", X509_NONE);
126 }
127
128 /**
129 * Loads a CA certificate
130 */
131 cert_t* load_ca_cert(char *filename)
132 {
133 char *path = concatenate_paths(CA_CERT_PATH, filename);
134
135 return load_cert(path, "CA", X509_NONE);
136 }
137
138 /**
139 * for each link pointing to the certificate increase the count by one
140 */
141 void cert_share(cert_t *cert)
142 {
143 if (cert != NULL)
144 {
145 cert->count++;
146 }
147 }
148
149 /* release of a certificate decreases the count by one
150 * the certificate is freed when the counter reaches zero
151 */
152 void cert_release(cert_t *cert)
153 {
154 if (cert && --cert->count == 0)
155 {
156 cert_t **pp = &certs;
157 while (*pp != cert)
158 {
159 pp = &(*pp)->next;
160 }
161 *pp = cert->next;
162 cert_free(cert);
163 }
164 }
165
166 /**
167 * Get a X.509 certificate with a given issuer found at a certain position
168 */
169 cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, cert_t *chain)
170 {
171 cert_t *cert = chain ? chain->next : certs;
172
173 while (cert)
174 {
175 certificate_t *certificate = cert->cert;
176 x509_t *x509 = (x509_t*)certificate;
177 chunk_t authKeyID = x509->get_authKeyIdentifier(x509);
178
179 if (keyid.ptr ? same_keyid(keyid, authKeyID) :
180 certificate->has_issuer(certificate, issuer))
181 {
182 return cert;
183 }
184 cert = cert->next;
185 }
186 return NULL;
187 }
188
189 /**
190 * List all PGP end certificates in a chained list
191 */
192 void list_pgp_end_certs(bool utc)
193 {
194 cert_t *cert = certs;
195 time_t now = time(NULL);
196 bool first = TRUE;
197
198
199 while (cert != NULL)
200 {
201 certificate_t *certificate = cert->cert;
202
203 if (certificate->get_type(certificate) == CERT_GPG)
204 {
205 time_t created, until;
206 public_key_t *key;
207 identification_t *userid = certificate->get_subject(certificate);
208 pgp_certificate_t *pgp_cert = (pgp_certificate_t*)certificate;
209 chunk_t fingerprint = pgp_cert->get_fingerprint(pgp_cert);
210
211 if (first)
212 {
213 whack_log(RC_COMMENT, " ");
214 whack_log(RC_COMMENT, "List of PGP End Entity Certificates:");
215 first = false;
216 }
217 whack_log(RC_COMMENT, " ");
218 whack_log(RC_COMMENT, " userid: '%Y'", userid);
219 whack_log(RC_COMMENT, " digest: %#B", &fingerprint);
220
221 /* list validity */
222 certificate->get_validity(certificate, &now, &created, &until);
223 whack_log(RC_COMMENT, " created: %T", &created, utc);
224 whack_log(RC_COMMENT, " until: %T %s%s", &until, utc,
225 check_expiry(until, CA_CERT_WARNING_INTERVAL, TRUE),
226 (until == TIME_32_BIT_SIGNED_MAX) ? " (expires never)":"");
227
228 key = certificate->get_public_key(certificate);
229 if (key)
230 {
231 chunk_t keyid;
232
233 whack_log(RC_COMMENT, " pubkey: %N %4d bits%s",
234 key_type_names, key->get_type(key),
235 key->get_keysize(key),
236 has_private_key(cert)? ", has private key" : "");
237 if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &keyid))
238 {
239 whack_log(RC_COMMENT, " keyid: %#B", &keyid);
240 }
241 if (key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &keyid))
242 {
243 whack_log(RC_COMMENT, " subjkey: %#B", &keyid);
244 }
245 }
246 }
247 cert = cert->next;
248 }
249 }
250
251 /**
252 * List all X.509 end certificates in a chained list
253 */
254 void list_x509_end_certs(bool utc)
255 {
256 list_x509cert_chain("End Entity", certs, X509_NONE, utc);
257 }
258
259 /**
260 * list all X.509 and OpenPGP end certificates
261 */
262 void cert_list(bool utc)
263 {
264 list_x509_end_certs(utc);
265 list_pgp_end_certs(utc);
266 }
267