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