Stefan Seyfried <seife+obs@b1-systems.com>
[vpnc.git] / crypto-gnutls.c
blob5fa884322f72578ed92e822eb6dc001b8546d3f1
1 /* IPSec VPN client compatible with Cisco equipment.
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <gcrypt.h>
24 #include "config.h"
25 #include "sysdep.h"
26 #include "crypto.h"
28 static int gnutls_initialized = 0;
30 #define CERT_STACK_DEPTH 20
32 crypto_ctx *crypto_ctx_new(crypto_error **error)
34 crypto_ctx *ctx;
36 if (!gnutls_initialized) {
37 if (gnutls_global_init() != 0) {
38 crypto_error_set(error, 1, 0, "error initializing gnutls globals");
39 return NULL;
41 gnutls_initialized = 1;
44 ctx = gnutls_calloc(1, sizeof(crypto_ctx));
45 if (!ctx) {
46 crypto_error_set(error, 1, ENOMEM, "not enough memory for crypto context");
47 return NULL;
50 ctx->stack = gnutls_calloc(CERT_STACK_DEPTH, sizeof(gnutls_x509_crt_t));
51 if (!ctx->stack) {
52 crypto_ctx_free(ctx);
53 crypto_error_set(error, 1, ENOMEM,
54 "not enough memory for crypto certificate stack");
55 ctx = NULL;
58 return ctx;
61 void crypto_ctx_free(crypto_ctx *ctx)
63 if (ctx) {
64 int i;
66 for (i = 0; i < ctx->num; i++)
67 gnutls_x509_crt_deinit(ctx->stack[i]);
68 gnutls_free(ctx->stack);
69 memset(ctx, 0, sizeof(crypto_ctx));
70 gnutls_free(ctx);
74 unsigned char *crypto_read_cert(const char *path,
75 size_t *out_len,
76 crypto_error **error)
78 gnutls_x509_crt_t cert;
79 unsigned char *data = NULL;
80 gnutls_datum dt;
81 size_t fsize = 0;
82 int err;
84 dt.data = crypto_read_file(path, &fsize, error);
85 if (!dt.data)
86 return NULL;
88 dt.size = (unsigned int) fsize;
89 if (gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS) {
90 crypto_error_set(error, 1, ENOMEM, "not enough memory for certificate");
91 goto out;
94 err = gnutls_x509_crt_import(cert, &dt, GNUTLS_X509_FMT_PEM);
95 if (err != GNUTLS_E_SUCCESS)
96 err = gnutls_x509_crt_import(cert, &dt, GNUTLS_X509_FMT_DER);
97 if (err != GNUTLS_E_SUCCESS) {
98 crypto_error_set(error, 1, 0, "certificate (%s) format unknown", path);
99 goto out;
102 *out_len = 10000;
103 data = malloc(*out_len);
104 err = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, data, out_len);
105 if (err != GNUTLS_E_SUCCESS) {
106 free(data);
107 *out_len = 0;
108 crypto_error_set(error, 1, 0, "certificate could not be exported");
111 out:
112 if (dt.data)
113 gnutls_free(dt.data);
114 gnutls_x509_crt_deinit(cert);
115 return data;
118 int crypto_push_cert(crypto_ctx *ctx,
119 const unsigned char *data,
120 size_t len,
121 crypto_error **error)
123 gnutls_x509_crt_t cert;
124 gnutls_datum dt;
125 int err;
127 if (!ctx || !data || (len <= 0)) {
128 crypto_error_set(error, 1, 0, "invalid crypto context or data");
129 return 1;
132 if (ctx->num >= CERT_STACK_DEPTH) {
133 crypto_error_set(error, 1, 0, "too many certificates in the chain.");
134 return 1;
137 gnutls_x509_crt_init (&cert);
139 dt.data = (unsigned char *) data;
140 dt.size = len;
141 err = gnutls_x509_crt_import (cert, &dt, GNUTLS_X509_FMT_DER);
142 if (err != GNUTLS_E_SUCCESS) {
143 gnutls_x509_crt_deinit (cert);
144 crypto_error_set(error, 1, 0, "failed to decode certificate");
145 return 1;
148 ctx->stack[ctx->num] = cert;
149 ctx->num++;
150 return 0;
153 static int verify_issuer(gnutls_x509_crt_t crt,
154 gnutls_x509_crt_t issuer,
155 crypto_error **error)
157 unsigned int output;
158 time_t now = time (0);
160 if (gnutls_x509_crt_verify(crt, &issuer, 1, 0, &output) < 0) {
161 crypto_error_set(error, 1, 0, "failed to verify against issuer");
162 return 1;
165 if (output & GNUTLS_CERT_INVALID) {
166 if (output & GNUTLS_CERT_SIGNER_NOT_FOUND) {
167 crypto_error_set(error, 1, 0, "certificate signer not found");
168 return 1;
170 if (output & GNUTLS_CERT_SIGNER_NOT_CA) {
171 crypto_error_set(error, 1, 0, "certificate signer not a CA");
172 return 1;
176 if (gnutls_x509_crt_get_activation_time(crt) > now) {
177 crypto_error_set(error, 1, 0, "certificate activation in the future");
178 return 1;
181 if (gnutls_x509_crt_get_expiration_time(crt) < now) {
182 crypto_error_set(error, 1, 0, "certificate expired");
183 return 1;
186 return 0;
189 static int verify_last(gnutls_x509_crt_t crt,
190 gnutls_x509_crt_t *ca_list,
191 size_t ca_list_size,
192 crypto_error **error)
194 unsigned int output;
195 time_t now = time (0);
197 if (gnutls_x509_crt_verify (crt, ca_list, ca_list_size,
198 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT,
199 &output) < 0) {
200 crypto_error_set(error, 1, 0, "failed to verify against CA list");
201 return 1;
204 if (output & GNUTLS_CERT_INVALID) {
205 if (output & GNUTLS_CERT_SIGNER_NOT_CA) {
206 crypto_error_set(error, 1, 0, "certificate signer not a CA");
207 return 1;
211 if (gnutls_x509_crt_get_activation_time(crt) > now) {
212 crypto_error_set(error, 1, 0, "certificate activation in the future");
213 return 1;
216 if (gnutls_x509_crt_get_expiration_time(crt) < now) {
217 crypto_error_set(error, 1, 0, "certificate expired");
218 return 1;
221 return 0;
224 static gnutls_x509_crt_t *load_one_ca_file(const char *path, crypto_error **error)
226 gnutls_x509_crt_t *list = NULL;
227 gnutls_x509_crt_t cert;
228 gnutls_datum dt;
229 size_t fsize = 0;
230 int err;
232 dt.data = crypto_read_file(path, &fsize, error);
233 if (!dt.data)
234 return NULL;
236 dt.size = (unsigned int) fsize;
237 if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS) {
238 gnutls_free(dt.data);
239 crypto_error_set(error, 1, ENOMEM, "not enough memory for certificate");
240 goto out;
243 err = gnutls_x509_crt_import (cert, &dt, GNUTLS_X509_FMT_PEM);
244 if (err != GNUTLS_E_SUCCESS)
245 err = gnutls_x509_crt_import (cert, &dt, GNUTLS_X509_FMT_DER);
246 gnutls_free(dt.data);
247 if (err != GNUTLS_E_SUCCESS) {
248 crypto_error_set(error, 1, 0, "certificate (%s) format unknown", path);
249 goto out;
252 list = gnutls_malloc(sizeof(gnutls_x509_crt_t));
253 if (!list) {
254 crypto_error_set(error, 1, ENOMEM, "not enough memory for certificate list");
255 goto out;
256 } else
257 list[0] = cert;
259 out:
260 gnutls_x509_crt_deinit (cert);
261 return list;
264 static gnutls_x509_crt_t *load_ca_list_file(const char *path,
265 size_t *out_list_size,
266 crypto_error **error)
268 gnutls_x509_crt_t *list = NULL, *old;
269 gnutls_datum dt = { NULL, 0 };
270 size_t fsize = 0;
271 int err;
272 unsigned int num = 200;
274 dt.data = crypto_read_file(path, &fsize, error);
275 if (!dt.data)
276 return NULL;
278 dt.size = (unsigned int) fsize;
279 old = list = gnutls_malloc(sizeof(gnutls_x509_crt_t) * num);
280 if (!list) {
281 crypto_error_set(error, 1, ENOMEM, "not enough memory for CA list");
282 goto out;
285 err = gnutls_x509_crt_list_import(list, &num, &dt, GNUTLS_X509_FMT_PEM, 0);
286 if (err <= 0) {
287 /* DER then maybe */
288 gnutls_free(list);
289 list = load_one_ca_file(path, error);
290 if (!list)
291 goto out;
292 num = 1;
293 } else
294 num = err; /* gnutls_x509_crt_list_import() returns # read */
296 if (err < 0) {
297 crypto_error_set(error, 1, 0, "importing CA list (%d)", err);
298 gnutls_free(list);
299 list = NULL;
300 } else
301 *out_list_size = num;
303 out:
304 gnutls_free(dt.data);
305 return list;
308 int crypto_verify_chain(crypto_ctx *ctx,
309 const char *ca_file,
310 const char *ca_dir,
311 crypto_error **error)
313 int err, i, ret = 1, start = 0;
314 gnutls_x509_crt_t *ca_list = NULL;
315 size_t ca_list_size = 0;
317 if (!ctx)
318 return 1;
320 if (ctx->num == 0)
321 return 0;
323 if (ca_file) {
324 ca_list = load_ca_list_file(ca_file, &ca_list_size, error);
325 if (!ca_list)
326 return 1;
327 } else if (ca_dir) {
328 /* FIXME: Try to load all files in the directory I guess... */
329 crypto_error_set(error, 1, 0, "ca_dir not yet supported");
330 return 1;
333 /* If the server cert is self-signed, ignore it in the issuers check */
334 err = gnutls_x509_crt_check_issuer(ctx->stack[0], ctx->stack[0]);
335 if (err > 0)
336 start++;
338 /* Check each certificate against its issuer */
339 for (i = start; i < ctx->num - 1; i++) {
340 if (verify_issuer(ctx->stack[i], ctx->stack[i + 1], error))
341 goto out;
344 /* Verify the last certificate */
345 if (verify_last(ctx->stack[ctx->num - 1], ca_list, ca_list_size, error))
346 goto out;
348 ret = 0;
350 out:
351 if (ca_list) {
352 for (i = 0; i < (int) ca_list_size; i++)
353 gnutls_x509_crt_deinit(ca_list[i]);
354 gnutls_free(ca_list);
356 return ret;
359 static unsigned char *check_pkcs1_padding(unsigned char* from,
360 size_t from_len,
361 size_t *out_len,
362 crypto_error **error)
364 int i = 0;
365 unsigned char *rec_hash = NULL;
366 size_t hash_len = 0;
368 /* No function provided to check that hash conforms to
369 * PKCS#1 1.5 padding scheme. Moreover gcrypt trim first
370 * 0 bytes */
371 if (from[i++] != 0x01) {
372 crypto_error_set(error, 1, 0, "hash doesn't conform to PKCS#1 padding");
373 goto out;
376 while (from[i] != 0x00) {
377 if (from[i++] != 0xFF) {
378 crypto_error_set(error, 1, 0, "hash doesn't conform to PKCS#1 padding");
379 goto out;
383 i++; /* Skips 00 byte */
385 if (i < 10) {
386 crypto_error_set(error, 1, 0, "PKCS#1 padding too short");
387 goto out;
390 hash_len = from_len - i;
391 rec_hash = calloc(1, hash_len);
392 if (!rec_hash)
393 goto out;
395 memcpy(rec_hash, from + i, hash_len);
396 *out_len = hash_len;
398 out:
399 return rec_hash;
403 unsigned char *crypto_decrypt_signature(crypto_ctx *ctx,
404 const unsigned char *sig_data,
405 size_t sig_len,
406 size_t *out_len,
407 unsigned int padding,
408 crypto_error **error)
410 unsigned char *buf = NULL, *rec_hash = NULL;
411 gnutls_datum_t n = { NULL, 0 }, e = { NULL, 0 };
412 int err, algo;
413 gcry_sexp_t key = NULL, sig = NULL, decrypted = NULL, child = NULL;
414 gcry_mpi_t n_mpi = NULL, e_mpi = NULL, sig_mpi = NULL, dec_mpi = NULL;
415 size_t buf_len = 0, hash_len = 0;
417 if (!ctx) {
418 crypto_error_set(error, 1, 0, "invalid crypto context");
419 return NULL;
422 if (!ctx->num) {
423 crypto_error_set(error, 1, 0, "no certificates in the stack");
424 return NULL;
427 algo = gnutls_x509_crt_get_pk_algorithm(ctx->stack[ctx->num - 1], NULL);
428 if (algo != GNUTLS_PK_RSA) {
429 crypto_error_set(error, 1, 0, "certificate public key algorithm not RSA");
430 return NULL;
433 err = gnutls_x509_crt_get_pk_rsa_raw(ctx->stack[ctx->num - 1], &n, &e);
434 if (err != GNUTLS_E_SUCCESS) {
435 crypto_error_set(error, 1, 0, "error getting certificate public key");
436 return NULL;
439 err = gcry_mpi_scan(&n_mpi, GCRYMPI_FMT_USG, n.data, n.size, NULL);
440 if (err) {
441 crypto_error_set(error, 1, 0, "invalid RSA key 'n' format");
442 goto out;
445 err = gcry_mpi_scan(&e_mpi, GCRYMPI_FMT_USG, e.data, e.size, NULL);
446 if (err) {
447 crypto_error_set(error, 1, 0, "invalid RSA key 'e' format");
448 goto out;
451 err = gcry_sexp_build(&key, NULL, "(public-key (rsa (n %m) (e %m)))", n_mpi, e_mpi);
452 if (err) {
453 crypto_error_set(error, 1, 0, "could not create public-key expression");
454 goto out;
457 err = gcry_mpi_scan(&sig_mpi, GCRYMPI_FMT_USG, sig_data, sig_len, NULL);
458 if (err) {
459 crypto_error_set(error, 1, 0, "invalid signature format");
460 goto out;
463 err = gcry_sexp_build(&sig, NULL, "(data (flags raw) (value %m))", sig_mpi);
464 if (err) {
465 crypto_error_set(error, 1, 0, "could not create signature expression");
466 goto out;
469 /* encrypt is equivalent to public key decryption for RSA keys */
470 err = gcry_pk_encrypt(&decrypted, sig, key);
471 if (err) {
472 crypto_error_set(error, 1, 0, "could not decrypt signature");
473 goto out;
476 child = gcry_sexp_find_token(decrypted, "a", 1);
477 if (!child) {
478 crypto_error_set(error, 1, 0, "could not get decrypted signature result");
479 goto out;
482 dec_mpi = gcry_sexp_nth_mpi(child, 1, GCRYMPI_FMT_USG);
483 gcry_sexp_release(child);
485 if (!dec_mpi) {
486 crypto_error_set(error, 1, 0, "could not get decrypted signature result");
487 goto out;
490 gcry_mpi_aprint(GCRYMPI_FMT_USG, &buf, &buf_len, dec_mpi);
491 if (!buf) {
492 crypto_error_set(error, 1, 0, "could not get extract decrypted signature");
493 goto out;
496 switch (padding) {
497 case CRYPTO_PAD_NONE:
498 rec_hash = buf;
499 hash_len = buf_len;
500 buf = NULL;
501 *out_len = (int) hash_len;
502 break;
503 case CRYPTO_PAD_PKCS1:
504 rec_hash = check_pkcs1_padding(buf, buf_len, &hash_len, error);
505 if (!rec_hash) {
506 crypto_error_set(error, 1, 0, "could not get extract decrypted padded signature");
507 goto out;
509 *out_len = (int) hash_len;
510 break;
511 default:
512 crypto_error_set(error, 1, 0, "unknown padding mechanism %d", padding);
513 break;
516 out:
517 if (buf)
518 free(buf);
519 if (dec_mpi)
520 gcry_mpi_release(dec_mpi);
521 if (decrypted)
522 gcry_sexp_release(decrypted);
523 if (key)
524 gcry_sexp_release(key);
525 if (sig)
526 gcry_sexp_release(sig);
527 if (sig_mpi)
528 gcry_mpi_release(sig_mpi);
529 if (n_mpi)
530 gcry_mpi_release(n_mpi);
531 if (e_mpi)
532 gcry_mpi_release(e_mpi);
533 if (n.data)
534 gcry_free(n.data);
535 if (e.data)
536 gcry_free(e.data);
538 return rec_hash;