summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@crystal.(none)>2008-05-04 15:21:04 +0300
committerNikos Mavrogiannopoulos <nmav@crystal.(none)>2008-05-04 15:21:04 +0300
commit410615e6774f32352f931ee090a93c5820051599 (patch)
tree6ed2a3c37a02462654de3cc7dd3c71ca6e4bcb79
parent4224552bf198c0059b82ae12a8f352532981afce (diff)
downloadgnutls-410615e6774f32352f931ee090a93c5820051599.tar.gz
The crypto interface is now abstract as well.
-rw-r--r--includes/gnutls/crypto.h33
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/cipher-libgcrypt.c131
-rw-r--r--lib/crypto.c27
-rw-r--r--lib/gnutls_cipher_int.c98
-rw-r--r--lib/gnutls_cipher_int.h3
-rw-r--r--lib/mpi-libgcrypt.c2
7 files changed, 215 insertions, 81 deletions
diff --git a/includes/gnutls/crypto.h b/includes/gnutls/crypto.h
index 4b8efb519b..1e8514adea 100644
--- a/includes/gnutls/crypto.h
+++ b/includes/gnutls/crypto.h
@@ -25,7 +25,7 @@
#ifndef GNUTLS_CRYPTO_H
# define GNUTLS_CRYPTO_H
-typedef struct gnutls_crypto_cipher {
+typedef struct {
int (*init)( void** ctx);
int (*setkey)( void* ctx, const void * key, int keysize);
int (*setiv)(void* ctx, const void* iv, int ivsize);
@@ -34,7 +34,7 @@ typedef struct gnutls_crypto_cipher {
void (*deinit)( void* ctx);
} gnutls_crypto_single_cipher_st;
-typedef struct gnutls_crypto_mac {
+typedef struct {
int (*init)( void** ctx);
int (*setkey)( void* ctx, const void * key, int keysize);
int (*hash)( void* ctx, const void * text, int textsize);
@@ -43,6 +43,28 @@ typedef struct gnutls_crypto_mac {
void (*deinit)( void* ctx);
} gnutls_crypto_single_mac_st;
+typedef struct {
+ int (*init)( gnutls_cipher_algorithm_t, void** ctx);
+ int (*setkey)( void* ctx, const void * key, int keysize);
+ int (*setiv)(void* ctx, const void* iv, int ivsize);
+ int (*encrypt)(void* ctx, const void* plain, int plainsize, void* encr, int encrsize);
+ int (*decrypt)(void* ctx, const void* encr, int encrsize, void* plain, int plainsize);
+ void (*deinit)( void* ctx);
+} gnutls_crypto_cipher_st;
+
+typedef struct {
+ int (*init)( gnutls_mac_algorithm_t, void** ctx);
+ int (*setkey)( void* ctx, const void * key, int keysize);
+ int (*hash)( void* ctx, const void * text, int textsize);
+ int (*copy)( void** dst_ctx, void* src_ctx);
+ int (*output) ( void* src_ctx, void* digest, int digestsize);
+ void (*deinit)( void* ctx);
+} gnutls_crypto_mac_st;
+
+/* the same... setkey should be null */
+typedef gnutls_crypto_single_mac_st gnutls_crypto_single_digest_st;
+typedef gnutls_crypto_mac_st gnutls_crypto_digest_st;
+
typedef enum gnutls_rnd_level
{
GNUTLS_RND_KEY = 0, /* fatal in many sessions if broken */
@@ -165,15 +187,16 @@ typedef struct gnutls_crypto_pk {
} gnutls_crypto_pk_st;
-/* the same... setkey should be null */
-typedef gnutls_crypto_single_mac_st gnutls_crypto_single_digest_st;
-
/* priority: infinity for backend algorithms, 90 for kernel algorithms - lowest wins
*/
int gnutls_crypto_single_cipher_register( gnutls_cipher_algorithm_t algorithm, int priority, gnutls_crypto_single_cipher_st* s);
int gnutls_crypto_single_mac_register( gnutls_mac_algorithm_t algorithm, int priority, gnutls_crypto_single_mac_st* s);
int gnutls_crypto_single_digest_register( gnutls_digest_algorithm_t algorithm, int priority, gnutls_crypto_single_digest_st* s);
+int gnutls_crypto_cipher_register( int priority, gnutls_crypto_cipher_st* s);
+int gnutls_crypto_mac_register( int priority, gnutls_crypto_mac_st* s);
+int gnutls_crypto_digest_register( int priority, gnutls_crypto_digest_st* s);
+
int gnutls_crypto_rnd_register( int priority, gnutls_crypto_rnd_st* s);
int gnutls_crypto_pk_register( int priority, gnutls_crypto_pk_st* s);
int gnutls_crypto_bigint_register( int priority, gnutls_crypto_bigint_st* s);
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 701c4d8a54..917d0247f6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -83,7 +83,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c gnutls_cipher.c \
auth_rsa_export.c ext_server_name.c auth_dh_common.c \
gnutls_helper.c ext_inner_application.c \
gnutls_supplemental.c crypto.c random.c pk-libgcrypt.c mpi-libgcrypt.c \
- pk-generic.c rnd-libgcrypt.c
+ pk-generic.c rnd-libgcrypt.c cipher-libgcrypt.c
if ENABLE_OPRFI
COBJECTS += $(OPRFI_COBJECTS)
diff --git a/lib/cipher-libgcrypt.c b/lib/cipher-libgcrypt.c
new file mode 100644
index 0000000000..501ad12eb2
--- /dev/null
+++ b/lib/cipher-libgcrypt.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2008 Free Software Foundation
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Here lie everything that has to do with large numbers, libgcrypt and
+ * other stuff that didn't fit anywhere else.
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <gnutls_cipher_int.h>
+#include <gcrypt.h>
+
+/* Functions that refer to the libgcrypt library.
+ */
+
+static int wrap_gcry_cipher_init( gnutls_cipher_algorithm_t algo, void** ctx)
+{
+int err;
+
+ switch (algo)
+ {
+ case GNUTLS_CIPHER_AES_128_CBC:
+ err = gcry_cipher_open ( (gcry_cipher_hd_t *)ctx, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
+ break;
+
+ case GNUTLS_CIPHER_AES_256_CBC:
+ err = gcry_cipher_open ((gcry_cipher_hd_t *)ctx, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0);
+ break;
+
+ case GNUTLS_CIPHER_3DES_CBC:
+ err = gcry_cipher_open ((gcry_cipher_hd_t *)ctx, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0);
+ break;
+
+ case GNUTLS_CIPHER_DES_CBC:
+ err = gcry_cipher_open ((gcry_cipher_hd_t *)ctx, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_CBC, 0);
+ break;
+
+ case GNUTLS_CIPHER_ARCFOUR_128:
+ case GNUTLS_CIPHER_ARCFOUR_40:
+ err = gcry_cipher_open ((gcry_cipher_hd_t *)ctx, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0);
+ break;
+
+ case GNUTLS_CIPHER_RC2_40_CBC:
+ err = gcry_cipher_open ((gcry_cipher_hd_t *)ctx, GCRY_CIPHER_RFC2268_40, GCRY_CIPHER_MODE_CBC, 0);
+ break;
+
+#ifdef ENABLE_CAMELLIA
+ case GNUTLS_CIPHER_CAMELLIA_128_CBC:
+ err = gcry_cipher_open ((gcry_cipher_hd_t *)ctx, GCRY_CIPHER_CAMELLIA128, GCRY_CIPHER_MODE_CBC, 0);
+ break;
+
+ case GNUTLS_CIPHER_CAMELLIA_256_CBC:
+ err = gcry_cipher_open ((gcry_cipher_hd_t *)ctx, GCRY_CIPHER_CAMELLIA256, GCRY_CIPHER_MODE_CBC, 0);
+ break;
+#endif
+ default:
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if (err == 0) return 0;
+
+ gnutls_assert();
+ return GNUTLS_E_ENCRYPTION_FAILED;
+}
+
+static int wrap_gcry_cipher_setkey( void* ctx, const void * key, int keysize)
+{
+ gcry_cipher_setkey( ctx, key, keysize);
+ return 0;
+}
+
+static int wrap_gcry_cipher_setiv( void* ctx, const void * iv, int ivsize)
+{
+ gcry_cipher_setiv( ctx, iv, ivsize);
+ return 0;
+}
+
+static int wrap_gcry_cipher_decrypt( void* ctx, const void* encr, int encrsize, void* plain, int plainsize)
+{
+int err;
+
+ err = gcry_cipher_decrypt( ctx, plain, plainsize, encr, encrsize);
+ if (err == 0) return 0;
+
+ gnutls_assert();
+ return GNUTLS_E_ENCRYPTION_FAILED;
+}
+
+static int wrap_gcry_cipher_encrypt( void* ctx, const void* plain, int plainsize, void* encr, int encrsize)
+{
+int err;
+
+ err = gcry_cipher_encrypt( ctx, encr, encrsize, plain, plainsize);
+ if (err == 0) return 0;
+
+ gnutls_assert();
+ return GNUTLS_E_ENCRYPTION_FAILED;
+}
+
+int crypto_cipher_prio = INT_MIN;
+
+gnutls_crypto_cipher_st _gnutls_cipher_ops = {
+ .init = wrap_gcry_cipher_init,
+ .setkey = wrap_gcry_cipher_setkey,
+ .setiv = wrap_gcry_cipher_setiv,
+ .encrypt = wrap_gcry_cipher_encrypt,
+ .decrypt = wrap_gcry_cipher_decrypt,
+ .deinit = gcry_cipher_close,
+};
diff --git a/lib/crypto.c b/lib/crypto.c
index 5e5a89e4d1..56d5b54f43 100644
--- a/lib/crypto.c
+++ b/lib/crypto.c
@@ -29,6 +29,7 @@
#include <gnutls_mpi.h>
#include <pk-generic.h>
#include <random.h>
+#include <gnutls_cipher_int.h>
typedef struct algo_list {
int algorithm;
@@ -291,3 +292,29 @@ int gnutls_crypto_pk_register( int priority, gnutls_crypto_pk_st* s)
}
return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
}
+
+/**
+ * gnutls_crypto_cipher_register - register a cipher interface
+ * @priority: is the priority of the cipher interface
+ * @s: is a structure holding new interface's data
+ *
+ * This function will register a cipher interface to be used
+ * by gnutls. Any interface registered will override
+ * the included engine and by convention kernel implemented
+ * interfaces should have priority of 90. The interface with the lowest
+ * priority will be used by gnutls.
+ *
+ * This function should be called before gnutls_global_init().
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
+ *
+ **/
+int gnutls_crypto_cipher_register( int priority, gnutls_crypto_cipher_st* s)
+{
+ if (crypto_cipher_prio < priority) {
+ _gnutls_cipher_ops = *s;
+ crypto_cipher_prio = priority;
+ return 0;
+ }
+ return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
+}
diff --git a/lib/gnutls_cipher_int.c b/lib/gnutls_cipher_int.c
index c4cdf5338f..5ed60fa5b2 100644
--- a/lib/gnutls_cipher_int.c
+++ b/lib/gnutls_cipher_int.c
@@ -31,7 +31,7 @@
#define SR(x, cleanup) if ( (x)<0 ) { \
gnutls_assert(); \
- err = GNUTLS_E_INTERNAL_ERROR; \
+ ret = GNUTLS_E_INTERNAL_ERROR; \
goto cleanup; \
}
@@ -39,7 +39,7 @@ int
_gnutls_cipher_init (cipher_hd_st* handle, gnutls_cipher_algorithm_t cipher,
const gnutls_datum_t * key, const gnutls_datum_t * iv)
{
- int err = GC_INVALID_CIPHER; /* doesn't matter */
+ int ret = GNUTLS_E_INTERNAL_ERROR;
gnutls_crypto_single_cipher_st * cc = NULL;
/* check if a cipher has been registered
@@ -48,75 +48,33 @@ _gnutls_cipher_init (cipher_hd_st* handle, gnutls_cipher_algorithm_t cipher,
if (cc != NULL) {
handle->registered = 1;
handle->hd.rh.cc = cc;
- SR( cc->init(&handle->hd.rh.ctx), cc_cleanup );
+ SR(cc->init(&handle->hd.rh.ctx), cc_cleanup);
SR(cc->setkey( handle->hd.rh.ctx, key->data, key->size), cc_cleanup);
if (iv->data && iv->size && cc->setiv)
SR(cc->setiv( handle->hd.rh.ctx, iv->data, iv->size), cc_cleanup);
return 0;
}
- handle->registered = 0;
- /* otherwise use included ciphers
+ handle->registered = 0;
+
+ /* otherwise use generic cipher interface
*/
- switch (cipher)
- {
- case GNUTLS_CIPHER_AES_128_CBC:
- err = gc_cipher_open (GC_AES128, GC_CBC, &handle->hd.gc);
- break;
-
- case GNUTLS_CIPHER_AES_256_CBC:
- err = gc_cipher_open (GC_AES256, GC_CBC, &handle->hd.gc);
- break;
-
- case GNUTLS_CIPHER_3DES_CBC:
- err = gc_cipher_open (GC_3DES, GC_CBC, &handle->hd.gc);
- break;
-
- case GNUTLS_CIPHER_DES_CBC:
- err = gc_cipher_open (GC_DES, GC_CBC, &handle->hd.gc);
- break;
-
- case GNUTLS_CIPHER_ARCFOUR_128:
- err = gc_cipher_open (GC_ARCFOUR128, GC_STREAM, &handle->hd.gc);
- break;
-
- case GNUTLS_CIPHER_ARCFOUR_40:
- err = gc_cipher_open (GC_ARCFOUR40, GC_STREAM, &handle->hd.gc);
- break;
-
- case GNUTLS_CIPHER_RC2_40_CBC:
- err = gc_cipher_open (GC_ARCTWO40, GC_CBC, &handle->hd.gc);
- break;
-
-#ifdef ENABLE_CAMELLIA
- case GNUTLS_CIPHER_CAMELLIA_128_CBC:
- err = gc_cipher_open (GC_CAMELLIA128, GC_CBC, &handle->hd.gc);
- break;
-
- case GNUTLS_CIPHER_CAMELLIA_256_CBC:
- err = gc_cipher_open (GC_CAMELLIA256, GC_CBC, &handle->hd.gc);
- break;
-#endif
-
- default:
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
+ ret = _gnutls_cipher_ops.init( cipher, &handle->hd.gc);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
- if (err == 0)
- {
- gc_cipher_setkey (handle->hd.gc, key->size, key->data);
- if (iv->data != NULL && iv->size > 0)
- gc_cipher_setiv (handle->hd.gc, iv->size, iv->data);
- }
- else if (cipher != GNUTLS_CIPHER_NULL)
- {
- gnutls_assert ();
- _gnutls_x509_log ("Crypto cipher[%d] error: %d\n", cipher, err);
- return GNUTLS_E_INTERNAL_ERROR;
- /* FIXME: gc_strerror */
- }
+ ret = _gnutls_cipher_ops.setkey (handle->hd.gc, key->data, key->size);
+ if (ret < 0) {
+ _gnutls_cipher_ops.deinit( handle->hd.gc);
+ gnutls_assert();
+ return ret;
+ }
+ if (iv->data != NULL && iv->size > 0)
+ _gnutls_cipher_ops.setiv (handle->hd.gc, iv->data, iv->size);
+
return 0;
cc_cleanup:
@@ -124,7 +82,7 @@ cc_cleanup:
if (handle->hd.rh.cc)
cc->deinit(handle->hd.rh.ctx);
- return err;
+ return ret;
}
int
@@ -138,11 +96,7 @@ _gnutls_cipher_encrypt (const cipher_hd_st* handle, void *text, int textlen)
}
if (handle->hd.gc == NULL) return 0;
- if (gc_cipher_encrypt_inline (handle->hd.gc, textlen, text) != 0)
- {
- gnutls_assert ();
- return GNUTLS_E_INTERNAL_ERROR;
- }
+ return _gnutls_cipher_ops.encrypt( handle->hd.gc, text, textlen, text, textlen);
}
return 0;
}
@@ -159,11 +113,7 @@ _gnutls_cipher_decrypt (const cipher_hd_st *handle, void *ciphertext,
}
if (handle->hd.gc == NULL) return 0;
- if (gc_cipher_decrypt_inline (handle->hd.gc, ciphertextlen, ciphertext) != 0)
- {
- gnutls_assert ();
- return GNUTLS_E_INTERNAL_ERROR;
- }
+ return _gnutls_cipher_ops.decrypt (handle->hd.gc, ciphertext, ciphertextlen, ciphertext, ciphertextlen);
}
return 0;
}
@@ -176,6 +126,6 @@ _gnutls_cipher_deinit (cipher_hd_st* handle)
if (handle->registered && handle->hd.rh.ctx != NULL) {
return handle->hd.rh.cc->deinit( handle->hd.rh.ctx);
}
- gc_cipher_close (handle->hd.gc);
+ _gnutls_cipher_ops.deinit (handle->hd.gc);
}
}
diff --git a/lib/gnutls_cipher_int.h b/lib/gnutls_cipher_int.h
index 088414dc7b..bc24d65c72 100644
--- a/lib/gnutls_cipher_int.h
+++ b/lib/gnutls_cipher_int.h
@@ -27,6 +27,9 @@
#include <gnutls/crypto.h>
+extern int crypto_cipher_prio;
+extern gnutls_crypto_cipher_st _gnutls_cipher_ops;
+
typedef struct {
gnutls_crypto_single_cipher_st* cc;
void* ctx;
diff --git a/lib/mpi-libgcrypt.c b/lib/mpi-libgcrypt.c
index 4f9dad0caf..1df835004a 100644
--- a/lib/mpi-libgcrypt.c
+++ b/lib/mpi-libgcrypt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008 Free Software Foundation
*
* Author: Nikos Mavrogiannopoulos
*