eliminated ipsec_policy.h
[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
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18
19 #include <freeswan.h>
20
21 #include "asn1/asn1.h"
22
23 #include "constants.h"
24 #include "defs.h"
25 #include "log.h"
26 #include "id.h"
27 #include "x509.h"
28 #include "pgp.h"
29 #include "pem.h"
30 #include "certs.h"
31 #include "pkcs1.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 private RSA key file
122 */
123 err_t load_rsa_private_key(char* filename, prompt_pass_t *pass,
124 RSA_private_key_t *key)
125 {
126 err_t ugh = NULL;
127 bool pgp = FALSE;
128 chunk_t blob = chunk_empty;
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 if (!parse_pgp(blob, NULL, key))
137 ugh = "syntax error in PGP private key file";
138 }
139 else
140 {
141 if (!pkcs1_parse_private_key(blob, key))
142 ugh = "syntax error in PKCS#1 private key file";
143 }
144 free(blob.ptr);
145 }
146 else
147 ugh = "error loading RSA private key file";
148
149 return ugh;
150 }
151
152 /**
153 * Loads a X.509 or OpenPGP certificate
154 */
155 bool load_cert(char *filename, const char *label, cert_t *cert)
156 {
157 bool pgp = FALSE;
158 chunk_t blob = chunk_empty;
159
160 /* initialize cert struct */
161 cert->type = CERT_NONE;
162 cert->u.x509 = NULL;
163
164 if (load_coded_file(filename, NULL, label, &blob, &pgp))
165 {
166 if (pgp)
167 {
168 pgpcert_t *pgpcert = malloc_thing(pgpcert_t);
169 *pgpcert = empty_pgpcert;
170 if (parse_pgp(blob, pgpcert, NULL))
171 {
172 cert->type = CERT_PGP;
173 cert->u.pgp = pgpcert;
174 return TRUE;
175 }
176 else
177 {
178 plog(" error in OpenPGP certificate");
179 free_pgpcert(pgpcert);
180 return FALSE;
181 }
182 }
183 else
184 {
185 x509cert_t *x509cert = malloc_thing(x509cert_t);
186 *x509cert = empty_x509cert;
187 if (parse_x509cert(blob, 0, x509cert))
188 {
189 cert->type = CERT_X509_SIGNATURE;
190 cert->u.x509 = x509cert;
191 return TRUE;
192 }
193 else
194 {
195 plog(" error in X.509 certificate");
196 free_x509cert(x509cert);
197 return FALSE;
198 }
199 }
200 }
201 return FALSE;
202 }
203
204 /**
205 * Loads a host certificate
206 */
207 bool load_host_cert(char *filename, cert_t *cert)
208 {
209 char *path = concatenate_paths(HOST_CERT_PATH, filename);
210
211 return load_cert(path, "host cert", cert);
212 }
213
214 /**
215 * Loads a CA certificate
216 */
217 bool load_ca_cert(char *filename, cert_t *cert)
218 {
219 char *path = concatenate_paths(CA_CERT_PATH, filename);
220
221 return load_cert(path, "CA cert", cert);
222 }
223
224 /**
225 * establish equality of two certificates
226 */
227 bool same_cert(const cert_t *a, const cert_t *b)
228 {
229 return a->type == b->type && a->u.x509 == b->u.x509;
230 }
231
232 /**
233 * for each link pointing to the certificate increase the count by one
234 */
235 void share_cert(cert_t cert)
236 {
237 switch (cert.type)
238 {
239 case CERT_PGP:
240 share_pgpcert(cert.u.pgp);
241 break;
242 case CERT_X509_SIGNATURE:
243 share_x509cert(cert.u.x509);
244 break;
245 default:
246 break;
247 }
248 }
249
250 /* release of a certificate decreases the count by one
251 " the certificate is freed when the counter reaches zero
252 */
253 void
254 release_cert(cert_t cert)
255 {
256 switch (cert.type)
257 {
258 case CERT_PGP:
259 release_pgpcert(cert.u.pgp);
260 break;
261 case CERT_X509_SIGNATURE:
262 release_x509cert(cert.u.x509);
263 break;
264 default:
265 break;
266 }
267 }
268
269 /*
270 * list all X.509 and OpenPGP end certificates
271 */
272 void
273 list_certs(bool utc)
274 {
275 list_x509_end_certs(utc);
276 list_pgp_end_certs(utc);
277 }
278