summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c')
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c b/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
new file mode 100644
index 000000000..f82d23185
--- /dev/null
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2009 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "gcrypt_crypter.h"
+
+#include <gcrypt.h>
+
+#include <debug.h>
+
+typedef struct private_gcrypt_crypter_t private_gcrypt_crypter_t;
+
+/**
+ * Private data of gcrypt_crypter_t
+ */
+struct private_gcrypt_crypter_t {
+
+ /**
+ * Public part of this class.
+ */
+ gcrypt_crypter_t public;
+
+ /**
+ * gcrypt cipher handle
+ */
+ gcry_cipher_hd_t h;
+
+ /**
+ * gcrypt algorithm identifier
+ */
+ int alg;
+};
+
+/**
+ * Implementation of crypter_t.decrypt.
+ */
+static void decrypt(private_gcrypt_crypter_t *this, chunk_t data,
+ chunk_t iv, chunk_t *dst)
+{
+ gcry_cipher_setiv(this->h, iv.ptr, iv.len);
+
+ if (dst)
+ {
+ *dst = chunk_alloc(data.len);
+ gcry_cipher_decrypt(this->h, dst->ptr, dst->len, data.ptr, data.len);
+ }
+ else
+ {
+ gcry_cipher_decrypt(this->h, data.ptr, data.len, NULL, 0);
+ }
+}
+
+/**
+ * Implementation of crypter_t.encrypt.
+ */
+static void encrypt(private_gcrypt_crypter_t *this, chunk_t data,
+ chunk_t iv, chunk_t *dst)
+{
+ gcry_cipher_setiv(this->h, iv.ptr, iv.len);
+
+ if (dst)
+ {
+ *dst = chunk_alloc(data.len);
+ gcry_cipher_encrypt(this->h, dst->ptr, dst->len, data.ptr, data.len);
+ }
+ else
+ {
+ gcry_cipher_encrypt(this->h, data.ptr, data.len, NULL, 0);
+ }
+}
+
+/**
+ * Implementation of crypter_t.get_block_size.
+ */
+static size_t get_block_size(private_gcrypt_crypter_t *this)
+{
+ size_t len = 0;
+
+ gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
+ return len;
+}
+
+/**
+ * Implementation of crypter_t.get_key_size.
+ */
+static size_t get_key_size(private_gcrypt_crypter_t *this)
+{
+ size_t len = 0;
+
+ gcry_cipher_algo_info(this->alg, GCRYCTL_GET_KEYLEN, NULL, &len);
+ return len;
+}
+
+/**
+ * Implementation of crypter_t.set_key.
+ */
+static void set_key(private_gcrypt_crypter_t *this, chunk_t key)
+{
+ gcry_cipher_setkey(this->h, key.ptr, key.len);
+}
+
+/**
+ * Implementation of crypter_t.destroy.
+ */
+static void destroy (private_gcrypt_crypter_t *this)
+{
+ gcry_cipher_close(this->h);
+ free(this);
+}
+
+/*
+ * Described in header
+ */
+gcrypt_crypter_t *gcrypt_crypter_create(encryption_algorithm_t algo,
+ size_t key_size)
+{
+ private_gcrypt_crypter_t *this;
+ int gcrypt_alg;
+ int mode = GCRY_CIPHER_MODE_CBC;
+ gcry_error_t err;
+
+ switch (algo)
+ {
+ case ENCR_DES:
+ gcrypt_alg = GCRY_CIPHER_DES;
+ break;
+ case ENCR_DES_ECB:
+ gcrypt_alg = GCRY_CIPHER_DES;
+ mode = GCRY_CIPHER_MODE_ECB;
+ break;
+ case ENCR_3DES:
+ gcrypt_alg = GCRY_CIPHER_3DES;
+ break;
+ case ENCR_IDEA:
+ /* currently not implemented in gcrypt */
+ return NULL;
+ case ENCR_CAST:
+ gcrypt_alg = GCRY_CIPHER_CAST5;
+ break;
+ case ENCR_BLOWFISH:
+ if (key_size != 16)
+ { /* gcrypt currently supports 128 bit blowfish only */
+ return NULL;
+ }
+ gcrypt_alg = GCRY_CIPHER_BLOWFISH;
+ break;
+ /* case ENCR_AES_CTR:
+ mode = GCRY_CIPHER_MODE_CTR; */
+ /* fall */
+ case ENCR_AES_CBC:
+ switch (key_size)
+ {
+ case 16:
+ gcrypt_alg = GCRY_CIPHER_AES128;
+ break;
+ case 24:
+ gcrypt_alg = GCRY_CIPHER_AES192;
+ break;
+ case 32:
+ gcrypt_alg = GCRY_CIPHER_AES256;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ /* case ENCR_CAMELLIA_CTR:
+ mode = GCRY_CIPHER_MODE_CTR; */
+ /* fall */
+ case ENCR_CAMELLIA_CBC:
+ switch (key_size)
+ {
+#ifdef HAVE_GCRY_CIPHER_CAMELLIA
+ case 16:
+ gcrypt_alg = GCRY_CIPHER_CAMELLIA128;
+ break;
+ case 24:
+ gcrypt_alg = GCRY_CIPHER_CAMELLIA192;
+ break;
+ case 32:
+ gcrypt_alg = GCRY_CIPHER_CAMELLIA256;
+ break;
+#endif /* HAVE_GCRY_CIPHER_CAMELLIA */
+ default:
+ return NULL;
+ }
+ break;
+ case ENCR_SERPENT_CBC:
+ switch (key_size)
+ {
+ case 16:
+ gcrypt_alg = GCRY_CIPHER_SERPENT128;
+ break;
+ case 24:
+ gcrypt_alg = GCRY_CIPHER_SERPENT192;
+ break;
+ case 32:
+ gcrypt_alg = GCRY_CIPHER_SERPENT256;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ case ENCR_TWOFISH_CBC:
+ switch (key_size)
+ {
+ case 16:
+ gcrypt_alg = GCRY_CIPHER_TWOFISH128;
+ break;
+ case 32:
+ gcrypt_alg = GCRY_CIPHER_TWOFISH;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ default:
+ return NULL;
+ }
+
+ this = malloc_thing(private_gcrypt_crypter_t);
+
+ this->alg = gcrypt_alg;
+ err = gcry_cipher_open(&this->h, gcrypt_alg, mode, 0);
+ if (err)
+ {
+ DBG1("grcy_cipher_open(%N) failed: %s",
+ encryption_algorithm_names, algo, gpg_strerror(err));
+ free(this);
+ return NULL;
+ }
+
+ this->public.crypter_interface.encrypt = (void (*) (crypter_t *, chunk_t,chunk_t, chunk_t *))encrypt;
+ this->public.crypter_interface.decrypt = (void (*) (crypter_t *, chunk_t , chunk_t, chunk_t *))decrypt;
+ this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *))get_block_size;
+ this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *))get_key_size;
+ this->public.crypter_interface.set_key = (void (*) (crypter_t *,chunk_t))set_key;
+ this->public.crypter_interface.destroy = (void (*) (crypter_t *))destroy;
+
+ return &this->public;
+}
+