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