renamed empty_chunk to chunk_empty
[strongswan.git] / src / pluto / certs.c
1 /* Certificate support for IKE authentication
2 * Copyright (C) 2002-2004 Andreas Steffen, Zuercher Hochschule Winterthur
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * RCSID $Id$
15 */
16
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20
21 #include <freeswan.h>
22 #include <ipsec_policy.h>
23
24 #include "constants.h"
25 #include "defs.h"
26 #include "log.h"
27 #include "asn1.h"
28 #include "id.h"
29 #include "x509.h"
30 #include "pgp.h"
31 #include "pem.h"
32 #include "certs.h"
33 #include "pkcs1.h"
34
35 /*
36 * used for initializatin of certs
37 */
38 const cert_t empty_cert = {CERT_NONE, {NULL}};
39
40 /*
41 * extracts the certificate to be sent to the peer
42 */
43 chunk_t
44 get_mycert(cert_t cert)
45 {
46 switch (cert.type)
47 {
48 case CERT_PGP:
49 return cert.u.pgp->certificate;
50 case CERT_X509_SIGNATURE:
51 return cert.u.x509->certificate;
52 default:
53 return chunk_empty;
54 }
55 }
56
57 /* load a coded key or certificate file with autodetection
58 * of binary DER or base64 PEM ASN.1 formats and armored PGP format
59 */
60 bool
61 load_coded_file(const char *filename, prompt_pass_t *pass, const char *type
62 , chunk_t *blob, bool *pgp)
63 {
64 err_t ugh = NULL;
65
66 FILE *fd = fopen(filename, "r");
67
68 if (fd)
69 {
70 int bytes;
71 fseek(fd, 0, SEEK_END );
72 blob->len = ftell(fd);
73 rewind(fd);
74 blob->ptr = malloc(blob->len);
75 bytes = fread(blob->ptr, 1, blob->len, fd);
76 fclose(fd);
77 plog(" loaded %s file '%s' (%d bytes)", type, filename, bytes);
78
79 *pgp = FALSE;
80
81 /* try DER format */
82 if (is_asn1(*blob))
83 {
84 DBG(DBG_PARSING,
85 DBG_log(" file coded in DER format");
86 )
87 return TRUE;
88 }
89
90 /* try PEM format */
91 ugh = pemtobin(blob, pass, filename, pgp);
92
93 if (ugh == NULL)
94 {
95 if (*pgp)
96 {
97 DBG(DBG_PARSING,
98 DBG_log(" file coded in armored PGP format");
99 )
100 return TRUE;
101 }
102 if (is_asn1(*blob))
103 {
104 DBG(DBG_PARSING,
105 DBG_log(" file coded in PEM format");
106 )
107 return TRUE;
108 }
109 ugh = "file coded in unknown format, discarded";
110 }
111
112 /* a conversion error has occured */
113 plog(" %s", ugh);
114 free(blob->ptr);
115 *blob = chunk_empty;
116 }
117 else
118 {
119 plog(" could not open %s file '%s'", type, filename);
120 }
121 return FALSE;
122 }
123
124 /*
125 * Loads a PKCS#1 or PGP private RSA key file
126 */
127 err_t
128 load_rsa_private_key(const char* filename, prompt_pass_t *pass
129 , RSA_private_key_t *key)
130 {
131 err_t ugh = NULL;
132 bool pgp = FALSE;
133 chunk_t blob = chunk_empty;
134
135 const char *path = concatenate_paths(PRIVATE_KEY_PATH, filename);
136
137 if (load_coded_file(path, pass, "private key", &blob, &pgp))
138 {
139 if (pgp)
140 {
141 if (!parse_pgp(blob, NULL, key))
142 ugh = "syntax error in PGP private key file";
143 }
144 else
145 {
146 if (!pkcs1_parse_private_key(blob, key))
147 ugh = "syntax error in PKCS#1 private key file";
148 }
149 free(blob.ptr);
150 }
151 else
152 ugh = "error loading RSA private key file";
153
154 return ugh;
155 }
156 /*
157 * Loads a X.509 or OpenPGP certificate
158 */
159 bool
160 load_cert(const char *filename, const char *label, cert_t *cert)
161 {
162 bool pgp = FALSE;
163 chunk_t blob = chunk_empty;
164
165 /* initialize cert struct */
166 cert->type = CERT_NONE;
167 cert->u.x509 = NULL;
168
169 if (load_coded_file(filename, NULL, label, &blob, &pgp))
170 {
171 if (pgp)
172 {
173 pgpcert_t *pgpcert = malloc_thing(pgpcert_t);
174 *pgpcert = empty_pgpcert;
175 if (parse_pgp(blob, pgpcert, NULL))
176 {
177 cert->type = CERT_PGP;
178 cert->u.pgp = pgpcert;
179 return TRUE;
180 }
181 else
182 {
183 plog(" error in OpenPGP certificate");
184 free_pgpcert(pgpcert);
185 return FALSE;
186 }
187 }
188 else
189 {
190 x509cert_t *x509cert = malloc_thing(x509cert_t);
191 *x509cert = empty_x509cert;
192 if (parse_x509cert(blob, 0, x509cert))
193 {
194 cert->type = CERT_X509_SIGNATURE;
195 cert->u.x509 = x509cert;
196 return TRUE;
197 }
198 else
199 {
200 plog(" error in X.509 certificate");
201 free_x509cert(x509cert);
202 return FALSE;
203 }
204 }
205 }
206 return FALSE;
207 }
208
209 /*
210 * Loads a host certificate
211 */
212 bool
213 load_host_cert(const char *filename, cert_t *cert)
214 {
215 const char *path = concatenate_paths(HOST_CERT_PATH, filename);
216
217 return load_cert(path, "host cert", cert);
218 }
219
220 /*
221 * Loads a CA certificate
222 */
223 bool
224 load_ca_cert(const char *filename, cert_t *cert)
225 {
226 const char *path = concatenate_paths(CA_CERT_PATH, filename);
227
228 return load_cert(path, "CA cert", cert);
229 }
230
231 /*
232 * establish equality of two certificates
233 */
234 bool
235 same_cert(const cert_t *a, const cert_t *b)
236 {
237 return a->type == b->type && a->u.x509 == b->u.x509;
238 }
239
240 /* for each link pointing to the certif icate
241 " increase the count by one
242 */
243 void
244 share_cert(cert_t cert)
245 {
246 switch (cert.type)
247 {
248 case CERT_PGP:
249 share_pgpcert(cert.u.pgp);
250 break;
251 case CERT_X509_SIGNATURE:
252 share_x509cert(cert.u.x509);
253 break;
254 default:
255 break;
256 }
257 }
258
259 /* release of a certificate decreases the count by one
260 " the certificate is freed when the counter reaches zero
261 */
262 void
263 release_cert(cert_t cert)
264 {
265 switch (cert.type)
266 {
267 case CERT_PGP:
268 release_pgpcert(cert.u.pgp);
269 break;
270 case CERT_X509_SIGNATURE:
271 release_x509cert(cert.u.x509);
272 break;
273 default:
274 break;
275 }
276 }
277
278 /*
279 * list all X.509 and OpenPGP end certificates
280 */
281 void
282 list_certs(bool utc)
283 {
284 list_x509_end_certs(utc);
285 list_pgp_end_certs(utc);
286 }
287