diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-02-04 11:02:30 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-02-06 22:05:53 +0100 |
commit | 74ff2e952564018a93d5930f2427cdf98266673b (patch) | |
tree | 0a611a4dc93b335f7226bb7a7e8b85e07c70672c /lib/gnutls_cipher_int.c | |
parent | e971ba89e1fac6892ead5c2210e4687055cbad79 (diff) | |
download | gnutls-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.c | 258 |
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); +} |