pluto and scepclient use private and public key plugins of libstrongswan
[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
21 #include <freeswan.h>
22
23 #include "library.h"
24 #include "asn1/asn1.h"
25
26 #include "constants.h"
27 #include "defs.h"
28 #include "log.h"
29 #include "id.h"
30 #include "pem.h"
31 #include "certs.h"
32
33 /**
34 * used for initializatin of certs
35 */
36 const cert_t empty_cert = {CERT_NONE, {NULL}};
37
38 /**
39 * extracts the certificate to be sent to the peer
40 */
41 chunk_t get_mycert(cert_t cert)
42 {
43 switch (cert.type)
44 {
45 case CERT_PGP:
46 return cert.u.pgp->certificate;
47 case CERT_X509_SIGNATURE:
48 return cert.u.x509->certificate;
49 default:
50 return chunk_empty;
51 }
52 }
53
54 /* load a coded key or certificate file with autodetection
55 * of binary DER or base64 PEM ASN.1 formats and armored PGP format
56 */
57 bool load_coded_file(char *filename, prompt_pass_t *pass, const char *type,
58 chunk_t *blob, bool *pgp)
59 {
60 err_t ugh = NULL;
61
62 FILE *fd = fopen(filename, "r");
63
64 if (fd)
65 {
66 int bytes;
67 fseek(fd, 0, SEEK_END );
68 blob->len = ftell(fd);
69 rewind(fd);
70 blob->ptr = malloc(blob->len);
71 bytes = fread(blob->ptr, 1, blob->len, fd);
72 fclose(fd);
73 plog(" loaded %s file '%s' (%d bytes)", type, filename, bytes);
74
75 *pgp = FALSE;
76
77 /* try DER format */
78 if (is_asn1(*blob))
79 {
80 DBG(DBG_PARSING,
81 DBG_log(" file coded in DER format");
82 )
83 return TRUE;
84 }
85
86 /* try PEM format */
87 ugh = pemtobin(blob, pass, filename, pgp);
88
89 if (ugh == NULL)
90 {
91 if (*pgp)
92 {
93 DBG(DBG_PARSING,
94 DBG_log(" file coded in armored PGP format");
95 )
96 return TRUE;
97 }
98 if (is_asn1(*blob))
99 {
100 DBG(DBG_PARSING,
101 DBG_log(" file coded in PEM format");
102 )
103 return TRUE;
104 }
105 ugh = "file coded in unknown format, discarded";
106 }
107
108 /* a conversion error has occured */
109 plog(" %s", ugh);
110 free(blob->ptr);
111 *blob = chunk_empty;
112 }
113 else
114 {
115 plog(" could not open %s file '%s'", type, filename);
116 }
117 return FALSE;
118 }
119
120 /**
121 * Loads a PKCS#1 or PGP privatekey file
122 */
123 private_key_t* load_private_key(char* filename, prompt_pass_t *pass,
124 key_type_t type)
125 {
126 private_key_t *key = NULL;
127 chunk_t blob = chunk_empty;
128 bool pgp = FALSE;
129
130 char *path = concatenate_paths(PRIVATE_KEY_PATH, filename);
131
132 if (load_coded_file(path, pass, "private key", &blob, &pgp))
133 {
134 if (pgp)
135 {
136 parse_pgp(blob, NULL, &key);
137 }
138 else
139 {
140 key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
141 BUILD_BLOB_ASN1_DER, blob, BUILD_END);
142 }
143 if (key == NULL)
144 {
145 plog("syntax error in %s private key file", pgp ? "PGP":"PKCS#");
146 }
147 free(blob.ptr);
148 }
149 else
150 {
151 plog("error loading RSA private key file");
152 }
153 return key;
154 }
155
156 /**
157 * Loads a X.509 or OpenPGP certificate
158 */
159 bool load_cert(char *filename, const char *label, cert_t *cert)
160 {
161 bool pgp = FALSE;
162 chunk_t blob = chunk_empty;
163
164 /* initialize cert struct */
165 cert->type = CERT_NONE;
166 cert->u.x509 = NULL;
167
168 if (load_coded_file(filename, NULL, label, &blob, &pgp))
169 {
170 if (pgp)
171 {
172 pgpcert_t *pgpcert = malloc_thing(pgpcert_t);
173 *pgpcert = empty_pgpcert;
174 if (parse_pgp(blob, pgpcert, NULL))
175 {
176 cert->type = CERT_PGP;
177 cert->u.pgp = pgpcert;
178 return TRUE;
179 }
180 else
181 {
182 plog(" error in OpenPGP certificate");
183 free_pgpcert(pgpcert);
184 return FALSE;
185 }
186 }
187 else
188 {
189 x509cert_t *x509cert = malloc_thing(x509cert_t);
190 *x509cert = empty_x509cert;
191 if (parse_x509cert(blob, 0, x509cert))
192 {
193 cert->type = CERT_X509_SIGNATURE;
194 cert->u.x509 = x509cert;
195 return TRUE;
196 }
197 else
198 {
199 plog(" error in X.509 certificate");
200 free_x509cert(x509cert);
201 return FALSE;
202 }
203 }
204 }
205 return FALSE;
206 }
207
208 /**
209 * Loads a host certificate
210 */
211 bool load_host_cert(char *filename, cert_t *cert)
212 {
213 char *path = concatenate_paths(HOST_CERT_PATH, filename);
214
215 return load_cert(path, "host cert", cert);
216 }
217
218 /**
219 * Loads a CA certificate
220 */
221 bool load_ca_cert(char *filename, cert_t *cert)
222 {
223 char *path = concatenate_paths(CA_CERT_PATH, filename);
224
225 return load_cert(path, "CA cert", cert);
226 }
227
228 /**
229 * establish equality of two certificates
230 */
231 bool same_cert(const cert_t *a, const cert_t *b)
232 {
233 return a->type == b->type && a->u.x509 == b->u.x509;
234 }
235
236 /**
237 * for each link pointing to the certificate increase the count by one
238 */
239 void share_cert(cert_t cert)
240 {
241 switch (cert.type)
242 {
243 case CERT_PGP:
244 share_pgpcert(cert.u.pgp);
245 break;
246 case CERT_X509_SIGNATURE:
247 share_x509cert(cert.u.x509);
248 break;
249 default:
250 break;
251 }
252 }
253
254 /* release of a certificate decreases the count by one
255 " the certificate is freed when the counter reaches zero
256 */
257 void
258 release_cert(cert_t cert)
259 {
260 switch (cert.type)
261 {
262 case CERT_PGP:
263 release_pgpcert(cert.u.pgp);
264 break;
265 case CERT_X509_SIGNATURE:
266 release_x509cert(cert.u.x509);
267 break;
268 default:
269 break;
270 }
271 }
272
273 /*
274 * list all X.509 and OpenPGP end certificates
275 */
276 void
277 list_certs(bool utc)
278 {
279 list_x509_end_certs(utc);
280 list_pgp_end_certs(utc);
281 }
282