|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2009-2013 Free Software Foundation, Inc.
|
|
Packit Service |
4684c1 |
* Copyright (C) 2013 Nikos Mavrogiannopoulos
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Author: Nikos Mavrogiannopoulos
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of GnuTLS.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit Service |
4684c1 |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
4684c1 |
* the License, or (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This library is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* Lesser General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "gnutls_int.h"
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
#include <cipher_int.h>
|
|
Packit Service |
4684c1 |
#include <datum.h>
|
|
Packit Service |
4684c1 |
#include <gnutls/crypto.h>
|
|
Packit Service |
4684c1 |
#include <crypto.h>
|
|
Packit Service |
4684c1 |
#include <fips.h>
|
|
Packit Service |
4684c1 |
#include <algorithms.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define SR_FB(x, cleanup) ret=(x); if ( ret<0 ) { \
|
|
Packit Service |
4684c1 |
if (ret == GNUTLS_E_NEED_FALLBACK) { \
|
|
Packit Service |
4684c1 |
if (handle->handle) \
|
|
Packit Service |
4684c1 |
handle->deinit(handle->handle); \
|
|
Packit Service |
4684c1 |
goto fallback; \
|
|
Packit Service |
4684c1 |
} \
|
|
Packit Service |
4684c1 |
gnutls_assert(); \
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_INTERNAL_ERROR; \
|
|
Packit Service |
4684c1 |
goto cleanup; \
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define SR(x, cleanup) if ( (x)<0 ) { \
|
|
Packit Service |
4684c1 |
gnutls_assert(); \
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_INTERNAL_ERROR; \
|
|
Packit Service |
4684c1 |
goto cleanup; \
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Returns true(non-zero) or false(0) if the
|
|
Packit Service |
4684c1 |
* provided cipher exists
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int _gnutls_cipher_exists(gnutls_cipher_algorithm_t cipher)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const gnutls_crypto_cipher_st *cc;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (is_cipher_algo_forbidden(cipher))
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* All the other ciphers are disabled on the back-end library.
|
|
Packit Service |
4684c1 |
* The NULL needs to be detected here as it is not a cipher
|
|
Packit Service |
4684c1 |
* that is provided by the back-end.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (cipher == GNUTLS_CIPHER_NULL)
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cc = _gnutls_get_crypto_cipher(cipher);
|
|
Packit Service |
4684c1 |
if (cc != NULL)
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_cipher_ops.exists(cipher);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_cipher_init(cipher_hd_st *handle, const cipher_entry_st *e,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t *key, const gnutls_datum_t *iv,
|
|
Packit Service |
4684c1 |
int enc)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret = GNUTLS_E_INTERNAL_ERROR;
|
|
Packit Service |
4684c1 |
const gnutls_crypto_cipher_st *cc = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(e == NULL || e->id == GNUTLS_CIPHER_NULL))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
FAIL_IF_LIB_ERROR;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
handle->e = e;
|
|
Packit Service |
4684c1 |
handle->handle = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* check if a cipher has been registered
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
cc = _gnutls_get_crypto_cipher(e->id);
|
|
Packit Service |
4684c1 |
if (cc != NULL) {
|
|
Packit Service |
4684c1 |
handle->encrypt = cc->encrypt;
|
|
Packit Service |
4684c1 |
handle->decrypt = cc->decrypt;
|
|
Packit Service |
4684c1 |
handle->aead_encrypt = cc->aead_encrypt;
|
|
Packit Service |
4684c1 |
handle->aead_decrypt = cc->aead_decrypt;
|
|
Packit Service |
4684c1 |
handle->deinit = cc->deinit;
|
|
Packit Service |
4684c1 |
handle->auth = cc->auth;
|
|
Packit Service |
4684c1 |
handle->tag = cc->tag;
|
|
Packit Service |
4684c1 |
handle->setiv = cc->setiv;
|
|
Packit Service |
4684c1 |
handle->getiv = cc->getiv;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* if cc->init() returns GNUTLS_E_NEED_FALLBACK we
|
|
Packit Service |
4684c1 |
* use the default ciphers */
|
|
Packit Service |
4684c1 |
SR_FB(cc->init(e->id, &handle->handle, enc), cc_cleanup);
|
|
Packit Service |
4684c1 |
SR_FB(cc->setkey(handle->handle, key->data, key->size),
|
|
Packit Service |
4684c1 |
cc_cleanup);
|
|
Packit Service |
4684c1 |
if (iv) {
|
|
Packit Service |
4684c1 |
if (unlikely(cc->setiv == NULL)) /* the API doesn't accept IV */
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
SR(cc->setiv(handle->handle, iv->data, iv->size),
|
|
Packit Service |
4684c1 |
cc_cleanup);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fallback:
|
|
Packit Service |
4684c1 |
handle->encrypt = _gnutls_cipher_ops.encrypt;
|
|
Packit Service |
4684c1 |
handle->decrypt = _gnutls_cipher_ops.decrypt;
|
|
Packit Service |
4684c1 |
handle->aead_encrypt = _gnutls_cipher_ops.aead_encrypt;
|
|
Packit Service |
4684c1 |
handle->aead_decrypt = _gnutls_cipher_ops.aead_decrypt;
|
|
Packit Service |
4684c1 |
handle->deinit = _gnutls_cipher_ops.deinit;
|
|
Packit Service |
4684c1 |
handle->auth = _gnutls_cipher_ops.auth;
|
|
Packit Service |
4684c1 |
handle->tag = _gnutls_cipher_ops.tag;
|
|
Packit Service |
4684c1 |
handle->setiv = _gnutls_cipher_ops.setiv;
|
|
Packit Service |
4684c1 |
handle->getiv = _gnutls_cipher_ops.getiv;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* otherwise use generic cipher interface
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
ret = _gnutls_cipher_ops.init(e->id, &handle->handle, enc);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_cipher_ops.setkey(handle->handle, key->data,
|
|
Packit Service |
4684c1 |
key->size);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cc_cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (iv) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_cipher_ops.setiv(handle->handle, iv->data,
|
|
Packit Service |
4684c1 |
iv->size);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cc_cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cc_cleanup:
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (handle->handle)
|
|
Packit Service |
4684c1 |
handle->deinit(handle->handle);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Auth_cipher API
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int _gnutls_auth_cipher_init(auth_cipher_hd_st * handle,
|
|
Packit Service |
4684c1 |
const cipher_entry_st * e,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * cipher_key,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * iv,
|
|
Packit Service |
4684c1 |
const mac_entry_st * me,
|
|
Packit Service |
4684c1 |
const gnutls_datum_t * mac_key,
|
|
Packit Service |
4684c1 |
unsigned etm,
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_SSL3
|
|
Packit Service |
4684c1 |
unsigned ssl_hmac,
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
int enc)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(e == NULL))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
FAIL_IF_LIB_ERROR;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memset(handle, 0, sizeof(*handle));
|
|
Packit Service |
4684c1 |
handle->etm = etm;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (e->id != GNUTLS_CIPHER_NULL) {
|
|
Packit Service |
4684c1 |
handle->non_null = 1;
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_cipher_init(&handle->cipher, e, cipher_key, iv,
|
|
Packit Service |
4684c1 |
enc);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
} else
|
|
Packit Service |
4684c1 |
handle->non_null = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (me->id != GNUTLS_MAC_AEAD) {
|
|
Packit Service |
4684c1 |
handle->is_mac = 1;
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_SSL3
|
|
Packit Service |
4684c1 |
handle->ssl_hmac = ssl_hmac;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ssl_hmac)
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_mac_init_ssl3(&handle->mac.dig, me,
|
|
Packit Service |
4684c1 |
mac_key->data,
|
|
Packit Service |
4684c1 |
mac_key->size);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_mac_init(&handle->mac.mac, me,
|
|
Packit Service |
4684c1 |
mac_key->data, mac_key->size);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_GOST
|
|
Packit Service |
4684c1 |
handle->continuous_mac = !!(me->flags & GNUTLS_MAC_FLAG_CONTINUOUS_MAC);
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
handle->tag_size = _gnutls_mac_get_algo_len(me);
|
|
Packit Service |
4684c1 |
} else if (_gnutls_cipher_algo_is_aead(e)) {
|
|
Packit Service |
4684c1 |
handle->tag_size = _gnutls_cipher_get_tag_size(e);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
if (handle->non_null != 0)
|
|
Packit Service |
4684c1 |
_gnutls_cipher_deinit(&handle->cipher);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_SSL3
|
|
Packit Service |
4684c1 |
# define MAC(handle, text, textlen) \
|
|
Packit Service |
4684c1 |
if (handle->ssl_hmac) { \
|
|
Packit Service |
4684c1 |
ret = \
|
|
Packit Service |
4684c1 |
_gnutls_hash(&handle->mac.dig, text, textlen); \
|
|
Packit Service |
4684c1 |
} else { \
|
|
Packit Service |
4684c1 |
ret = _gnutls_mac(&handle->mac.mac, text, textlen); \
|
|
Packit Service |
4684c1 |
} \
|
|
Packit Service |
4684c1 |
if (unlikely(ret < 0)) \
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret)
|
|
Packit Service |
4684c1 |
#else
|
|
Packit Service |
4684c1 |
# define MAC(handle, text, textlen) \
|
|
Packit Service |
4684c1 |
ret = _gnutls_mac(&handle->mac.mac, text, textlen); \
|
|
Packit Service |
4684c1 |
if (unlikely(ret < 0)) \
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret)
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls_auth_cipher_add_auth(auth_cipher_hd_st * handle,
|
|
Packit Service |
4684c1 |
const void *text, int textlen)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (handle->is_mac) {
|
|
Packit Service |
4684c1 |
MAC(handle, text, textlen);
|
|
Packit Service |
4684c1 |
} else if (_gnutls_cipher_is_aead(&handle->cipher))
|
|
Packit Service |
4684c1 |
return _gnutls_cipher_auth(&handle->cipher, text, textlen);
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* The caller must make sure that textlen+pad_size+tag_size is divided by the block size of the cipher */
|
|
Packit Service |
4684c1 |
int _gnutls_auth_cipher_encrypt2_tag(auth_cipher_hd_st * handle,
|
|
Packit Service |
4684c1 |
const uint8_t * text, int textlen,
|
|
Packit Service |
4684c1 |
void *_ciphertext, int ciphertextlen,
|
|
Packit Service |
4684c1 |
int pad_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
uint8_t *ciphertext = _ciphertext;
|
|
Packit Service |
4684c1 |
unsigned blocksize =
|
|
Packit Service |
4684c1 |
_gnutls_cipher_get_block_size(handle->cipher.e);
|
|
Packit Service |
4684c1 |
unsigned l;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
assert(ciphertext != NULL);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (handle->is_mac) { /* cipher + mac */
|
|
Packit Service |
4684c1 |
if (handle->non_null == 0) { /* NULL cipher + MAC */
|
|
Packit Service |
4684c1 |
MAC(handle, text, textlen);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(textlen + pad_size + handle->tag_size) >
|
|
Packit Service |
4684c1 |
ciphertextlen)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (text != ciphertext)
|
|
Packit Service |
4684c1 |
memcpy(ciphertext, text, textlen);
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_auth_cipher_tag(handle,
|
|
Packit Service |
4684c1 |
ciphertext + textlen,
|
|
Packit Service |
4684c1 |
handle->tag_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
uint8_t *orig_ciphertext = ciphertext;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (handle->etm == 0 || handle->cipher.e->type != CIPHER_BLOCK) {
|
|
Packit Service |
4684c1 |
MAC(handle, text, textlen);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(textlen + pad_size + handle->tag_size) >
|
|
Packit Service |
4684c1 |
ciphertextlen)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
assert(blocksize != 0);
|
|
Packit Service |
4684c1 |
l = (textlen / blocksize) * blocksize;
|
|
Packit Service |
4684c1 |
if (l > 0) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_cipher_encrypt2(&handle->cipher, text,
|
|
Packit Service |
4684c1 |
l, ciphertext,
|
|
Packit Service |
4684c1 |
ciphertextlen);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
textlen -= l;
|
|
Packit Service |
4684c1 |
text += l;
|
|
Packit Service |
4684c1 |
ciphertext += l;
|
|
Packit Service |
4684c1 |
ciphertextlen -= l;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ciphertext != text && textlen > 0)
|
|
Packit Service |
4684c1 |
memcpy(ciphertext, text, textlen);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (handle->etm == 0 || handle->cipher.e->type != CIPHER_BLOCK) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_auth_cipher_tag(handle,
|
|
Packit Service |
4684c1 |
ciphertext + textlen,
|
|
Packit Service |
4684c1 |
handle->tag_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
textlen += handle->tag_size;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* TLS 1.0 style padding */
|
|
Packit Service |
4684c1 |
if (pad_size > 0) {
|
|
Packit Service |
4684c1 |
memset(ciphertext + textlen, pad_size - 1,
|
|
Packit Service |
4684c1 |
pad_size);
|
|
Packit Service |
4684c1 |
textlen += pad_size;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_cipher_encrypt2(&handle->cipher,
|
|
Packit Service |
4684c1 |
ciphertext, textlen,
|
|
Packit Service |
4684c1 |
ciphertext,
|
|
Packit Service |
4684c1 |
ciphertextlen);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (handle->etm != 0 && handle->cipher.e->type == CIPHER_BLOCK) {
|
|
Packit Service |
4684c1 |
MAC(handle, orig_ciphertext, l);
|
|
Packit Service |
4684c1 |
MAC(handle, ciphertext, textlen);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_auth_cipher_tag(handle,
|
|
Packit Service |
4684c1 |
ciphertext + textlen,
|
|
Packit Service |
4684c1 |
handle->tag_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else if (_gnutls_cipher_is_aead(&handle->cipher)) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_cipher_encrypt2(&handle->cipher, text, textlen,
|
|
Packit Service |
4684c1 |
ciphertext, ciphertextlen);
|
|
Packit Service |
4684c1 |
if (unlikely(ret < 0))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_auth_cipher_tag(handle, ciphertext + textlen,
|
|
Packit Service |
4684c1 |
handle->tag_size);
|
|
Packit Service |
4684c1 |
if (unlikely(ret < 0))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
} else if (handle->non_null == 0 && text != ciphertext) /* NULL cipher - no MAC */
|
|
Packit Service |
4684c1 |
memcpy(ciphertext, text, textlen);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls_auth_cipher_decrypt2(auth_cipher_hd_st * handle,
|
|
Packit Service |
4684c1 |
const void *ciphertext, int ciphertextlen,
|
|
Packit Service |
4684c1 |
void *text, int textlen)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(ciphertextlen > textlen))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (handle->is_mac && (handle->etm != 0 && handle->cipher.e->type == CIPHER_BLOCK)) {
|
|
Packit Service |
4684c1 |
/* The MAC is not to be hashed */
|
|
Packit Service |
4684c1 |
ciphertextlen -= handle->tag_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
MAC(handle, ciphertext, ciphertextlen);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (handle->non_null != 0) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_cipher_decrypt2(&handle->cipher, ciphertext,
|
|
Packit Service |
4684c1 |
ciphertextlen, text, textlen);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
} else if (handle->non_null == 0 && text != ciphertext)
|
|
Packit Service |
4684c1 |
memcpy(text, ciphertext, ciphertextlen);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (handle->is_mac && (handle->etm == 0 || handle->cipher.e->type != CIPHER_BLOCK)) {
|
|
Packit Service |
4684c1 |
/* The MAC is not to be hashed */
|
|
Packit Service |
4684c1 |
ciphertextlen -= handle->tag_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
MAC(handle, text, ciphertextlen);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls_auth_cipher_tag(auth_cipher_hd_st * handle, void *tag,
|
|
Packit Service |
4684c1 |
int tag_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (handle->is_mac) {
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_SSL3
|
|
Packit Service |
4684c1 |
if (handle->ssl_hmac) {
|
|
Packit Service |
4684c1 |
int ret =
|
|
Packit Service |
4684c1 |
_gnutls_mac_output_ssl3(&handle->mac.dig, tag);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
} else
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_GOST
|
|
Packit Service |
4684c1 |
/* draft-smyshlyaev-tls12-gost-suites section 4.1.2 */
|
|
Packit Service |
4684c1 |
if (handle->continuous_mac) {
|
|
Packit Service |
4684c1 |
mac_hd_st temp_mac;
|
|
Packit Service |
4684c1 |
int ret = _gnutls_mac_copy(&handle->mac.mac, &temp_mac);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
_gnutls_mac_deinit(&temp_mac, tag);
|
|
Packit Service |
4684c1 |
} else
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
_gnutls_mac_output(&handle->mac.mac, tag);
|
|
Packit Service |
4684c1 |
} else if (_gnutls_cipher_is_aead(&handle->cipher)) {
|
|
Packit Service |
4684c1 |
_gnutls_cipher_tag(&handle->cipher, tag, tag_size);
|
|
Packit Service |
4684c1 |
} else
|
|
Packit Service |
4684c1 |
memset(tag, 0, tag_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void _gnutls_auth_cipher_deinit(auth_cipher_hd_st * handle)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (handle->is_mac) {
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_SSL3
|
|
Packit Service |
4684c1 |
if (handle->ssl_hmac) /* failure here doesn't matter */
|
|
Packit Service |
4684c1 |
_gnutls_mac_deinit_ssl3(&handle->mac.dig, NULL);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
_gnutls_mac_deinit(&handle->mac.mac, NULL);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (handle->non_null != 0)
|
|
Packit Service |
4684c1 |
_gnutls_cipher_deinit(&handle->cipher);
|
|
Packit Service |
4684c1 |
}
|