summaryrefslogtreecommitdiff
path: root/lib/gnutls_cipher_int.c
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-02-04 11:02:30 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-02-06 22:05:53 +0100
commit74ff2e952564018a93d5930f2427cdf98266673b (patch)
tree0a611a4dc93b335f7226bb7a7e8b85e07c70672c /lib/gnutls_cipher_int.c
parente971ba89e1fac6892ead5c2210e4687055cbad79 (diff)
downloadgnutls-74ff2e952564018a93d5930f2427cdf98266673b.tar.gz
Added support for GCM ciphersuites (not tested with other implementation).
Diffstat (limited to 'lib/gnutls_cipher_int.c')
-rw-r--r--lib/gnutls_cipher_int.c258
1 files changed, 224 insertions, 34 deletions
diff --git a/lib/gnutls_cipher_int.c b/lib/gnutls_cipher_int.c
index d3b7698a94..410a6b48ef 100644
--- a/lib/gnutls_cipher_int.c
+++ b/lib/gnutls_cipher_int.c
@@ -28,6 +28,7 @@
#include <gnutls_datum.h>
#include <gnutls/crypto.h>
#include <crypto.h>
+#include <gnutls_algorithms.h>
#define SR(x, cleanup) if ( (x)<0 ) { \
gnutls_assert(); \
@@ -47,18 +48,30 @@ _gnutls_cipher_init (cipher_hd_st * handle, gnutls_cipher_algorithm_t cipher,
cc = _gnutls_get_crypto_cipher (cipher);
if (cc != NULL)
{
- SR (cc->init (cipher, &handle->handle), cc_cleanup);
- SR (cc->setkey (handle->handle, key->data, key->size), cc_cleanup);
-
handle->encrypt = cc->encrypt;
handle->decrypt = cc->decrypt;
handle->deinit = cc->deinit;
+ handle->auth = cc->auth;
+ handle->tag = cc->tag;
+ handle->setiv = cc->setiv;
+
+ SR (cc->init (cipher, &handle->handle), cc_cleanup);
+ SR (cc->setkey( handle->handle, key->data, key->size), cc_cleanup);
+ if (iv)
+ {
+ SR (cc->setiv( handle->handle, iv->data, iv->size), cc_cleanup);
+ }
- if (iv && iv->data && iv->size && cc->setiv)
- SR (cc->setiv (handle->handle, iv->data, iv->size), cc_cleanup);
return 0;
}
+ handle->encrypt = _gnutls_cipher_ops.encrypt;
+ handle->decrypt = _gnutls_cipher_ops.decrypt;
+ handle->deinit = _gnutls_cipher_ops.deinit;
+ handle->auth = _gnutls_cipher_ops.auth;
+ handle->tag = _gnutls_cipher_ops.tag;
+ handle->setiv = _gnutls_cipher_ops.setiv;
+
/* otherwise use generic cipher interface
*/
ret = _gnutls_cipher_ops.init (cipher, &handle->handle);
@@ -68,51 +81,37 @@ _gnutls_cipher_init (cipher_hd_st * handle, gnutls_cipher_algorithm_t cipher,
return ret;
}
- ret = _gnutls_cipher_ops.setkey (handle->handle, key->data, key->size);
+ ret = _gnutls_cipher_ops.setkey(handle->handle, key->data, key->size);
if (ret < 0)
{
- _gnutls_cipher_ops.deinit (handle->handle);
gnutls_assert ();
- return ret;
+ goto cc_cleanup;
}
- handle->encrypt = _gnutls_cipher_ops.encrypt;
- handle->decrypt = _gnutls_cipher_ops.decrypt;
- handle->deinit = _gnutls_cipher_ops.deinit;
-
- if (iv && iv->data != NULL && iv->size > 0)
- _gnutls_cipher_ops.setiv (handle->handle, iv->data, iv->size);
+ if (iv)
+ {
+ ret = _gnutls_cipher_ops.setiv(handle->handle, iv->data, iv->size);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ goto cc_cleanup;
+ }
+ }
return 0;
cc_cleanup:
if (handle->handle)
- cc->deinit (handle->handle);
+ handle->deinit (handle->handle);
return ret;
}
-int
-_gnutls_cipher_encrypt (const cipher_hd_st * handle, void *text, int textlen)
+void _gnutls_cipher_setiv (const cipher_hd_st * handle,
+ const void *iv, int ivlen)
{
- if (handle != NULL && handle->handle != NULL)
- {
- return handle->encrypt (handle->handle, text, textlen, text, textlen);
- }
- return 0;
-}
-
-int
-_gnutls_cipher_decrypt (const cipher_hd_st * handle, void *ciphertext,
- int ciphertextlen)
-{
- if (handle != NULL && handle->handle != NULL)
- {
- return handle->decrypt (handle->handle, ciphertext, ciphertextlen,
- ciphertext, ciphertextlen);
- }
- return 0;
+ handle->setiv(handle->handle, iv, ivlen);
}
int
@@ -124,6 +123,7 @@ _gnutls_cipher_encrypt2 (const cipher_hd_st * handle, const void *text,
return handle->encrypt (handle->handle, text, textlen, ciphertext,
ciphertextlen);
}
+
return 0;
}
@@ -136,6 +136,7 @@ _gnutls_cipher_decrypt2 (const cipher_hd_st * handle, const void *ciphertext,
return handle->decrypt (handle->handle, ciphertext, ciphertextlen,
text, textlen);
}
+
return 0;
}
@@ -148,3 +149,192 @@ _gnutls_cipher_deinit (cipher_hd_st * handle)
handle->handle = NULL;
}
}
+
+/* returns the tag in AUTHENC ciphers */
+void _gnutls_cipher_tag( const cipher_hd_st * handle, void* tag, int tag_size)
+{
+ if (handle != NULL && handle->handle != NULL)
+ {
+ handle->tag (handle->handle, tag, tag_size);
+ }
+}
+
+int _gnutls_cipher_auth (const cipher_hd_st * handle, const void *text,
+ int textlen)
+{
+ if (handle != NULL && handle->handle != NULL)
+ {
+ return handle->auth (handle->handle, text, textlen);
+ }
+ return GNUTLS_E_INTERNAL_ERROR;
+}
+
+/* Auth_cipher API
+ */
+int _gnutls_auth_cipher_init (auth_cipher_hd_st * handle,
+ gnutls_cipher_algorithm_t cipher,
+ const gnutls_datum_t * cipher_key,
+ const gnutls_datum_t * iv,
+ gnutls_mac_algorithm_t mac,
+ const gnutls_datum_t * mac_key,
+ int ssl_hmac)
+{
+int ret;
+
+ memset(handle, 0, sizeof(*handle));
+
+ ret = _gnutls_cipher_init(&handle->cipher, cipher, cipher_key, iv);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+
+ if (mac != GNUTLS_MAC_AEAD)
+ {
+ handle->is_mac = 1;
+ handle->ssl_hmac = ssl_hmac;
+
+ if (ssl_hmac)
+ ret = _gnutls_mac_init_ssl3(&handle->mac, mac, mac_key->data, mac_key->size);
+ else
+ ret = _gnutls_hmac_init(&handle->mac, mac, mac_key->data, mac_key->size);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ handle->tag_size = _gnutls_hash_get_algo_len(mac);
+ }
+ else
+ {
+ handle->is_auth = _gnutls_cipher_is_aead(cipher);
+ if (handle->is_auth)
+ handle->tag_size = gnutls_cipher_get_block_size(cipher);
+ }
+
+ return 0;
+cleanup:
+ _gnutls_cipher_deinit(&handle->cipher);
+ return ret;
+
+}
+
+int _gnutls_auth_cipher_add_auth (auth_cipher_hd_st * handle, const void *text,
+ int textlen)
+{
+ if (handle->is_mac)
+ {
+ if (handle->ssl_hmac)
+ return _gnutls_hash(&handle->mac, text, textlen);
+ else
+ return _gnutls_hmac(&handle->mac, text, textlen);
+ }
+ else if (handle->is_auth)
+ return _gnutls_cipher_auth(&handle->cipher, text, textlen);
+ else
+ return 0;
+}
+
+int _gnutls_auth_cipher_encrypt2_tag (auth_cipher_hd_st * handle, const uint8_t *text,
+ int textlen, void *ciphertext, int ciphertextlen,
+ void* tag_ptr, int tag_size,
+ int auth_size)
+{
+int ret;
+
+ if (handle->is_mac)
+ {
+ if (handle->ssl_hmac)
+ ret = _gnutls_hash(&handle->mac, text, auth_size);
+ else
+ ret = _gnutls_hmac(&handle->mac, text, auth_size);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ _gnutls_auth_cipher_tag(handle, tag_ptr, tag_size);
+
+ ret = _gnutls_cipher_encrypt2(&handle->cipher, text, textlen, ciphertext, ciphertextlen);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ }
+ else if (handle->is_auth)
+ {
+ ret = _gnutls_cipher_encrypt2(&handle->cipher, text, textlen, ciphertext, ciphertextlen);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+ _gnutls_auth_cipher_tag(handle, tag_ptr, tag_size);
+ }
+
+ return 0;
+}
+
+int _gnutls_auth_cipher_decrypt2 (auth_cipher_hd_st * handle,
+ const void *ciphertext, int ciphertextlen,
+ void *text, int textlen)
+{
+int ret;
+
+ ret = _gnutls_cipher_decrypt2(&handle->cipher, ciphertext, ciphertextlen,
+ text, textlen);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ return ret;
+ }
+
+ if (handle->is_mac)
+ {
+ /* The MAC is not to be hashed */
+ textlen -= handle->tag_size;
+
+ if (handle->ssl_hmac)
+ return _gnutls_hash(&handle->mac, text, textlen);
+ else
+ return _gnutls_hmac(&handle->mac, text, textlen);
+ }
+
+ return 0;
+}
+
+void _gnutls_auth_cipher_tag(auth_cipher_hd_st * handle, void* tag, int tag_size)
+{
+ if (handle->is_mac)
+ {
+ if (handle->ssl_hmac)
+ {
+ _gnutls_mac_output_ssl3 (&handle->mac, tag);
+ _gnutls_hash_reset (&handle->mac);
+ }
+ else
+ {
+ _gnutls_hmac_output (&handle->mac, tag);
+ _gnutls_hmac_reset (&handle->mac);
+ }
+ }
+ else if (handle->is_auth)
+ {
+ _gnutls_cipher_tag(&handle->cipher, tag, tag_size);
+ }
+}
+
+void _gnutls_auth_cipher_deinit (auth_cipher_hd_st * handle)
+{
+ if (handle->is_mac)
+ {
+ if (handle->ssl_hmac)
+ _gnutls_mac_deinit_ssl3 (&handle->mac, NULL);
+ else
+ _gnutls_hmac_deinit(&handle->mac, NULL);
+ }
+ _gnutls_cipher_deinit(&handle->cipher);
+}