diff options
-rw-r--r-- | includes/gnutls/crypto.h | 33 | ||||
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/cipher-libgcrypt.c | 131 | ||||
-rw-r--r-- | lib/crypto.c | 27 | ||||
-rw-r--r-- | lib/gnutls_cipher_int.c | 98 | ||||
-rw-r--r-- | lib/gnutls_cipher_int.h | 3 | ||||
-rw-r--r-- | lib/mpi-libgcrypt.c | 2 |
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 * |