|
Packit |
aea12f |
#include <config.h>
|
|
Packit |
aea12f |
#include <stdint.h>
|
|
Packit |
aea12f |
#include <stdio.h>
|
|
Packit |
aea12f |
#include <string.h>
|
|
Packit |
aea12f |
#include <utils.h>
|
|
Packit |
aea12f |
#include <stdlib.h>
|
|
Packit |
aea12f |
#include <assert.h>
|
|
Packit |
aea12f |
#include <gnutls/gnutls.h>
|
|
Packit |
aea12f |
#include <gnutls/crypto.h>
|
|
Packit |
aea12f |
#include <openssl/evp.h>
|
|
Packit |
aea12f |
#include <openssl/opensslv.h>
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* This does check the AES and CHACHA20 implementations for compatibility
|
|
Packit |
aea12f |
* with openssl.
|
|
Packit |
aea12f |
*/
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#define BSIZE (64*1024+12)
|
|
Packit |
aea12f |
#define B2SIZE (1024+7)
|
|
Packit |
aea12f |
static unsigned char buffer_auth[B2SIZE];
|
|
Packit |
aea12f |
static unsigned char orig_plain_data[BSIZE];
|
|
Packit |
aea12f |
static unsigned char enc_data[BSIZE + 32]; /* allow for tag */
|
|
Packit |
aea12f |
static unsigned char dec_data[BSIZE];
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static int cipher_test(const char *ocipher, gnutls_cipher_algorithm_t gcipher,
|
|
Packit |
aea12f |
unsigned tag_size)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
int ret;
|
|
Packit |
aea12f |
gnutls_aead_cipher_hd_t hd;
|
|
Packit |
aea12f |
gnutls_datum_t dkey, dnonce;
|
|
Packit |
aea12f |
unsigned char key[32];
|
|
Packit |
aea12f |
unsigned char nonce[32];
|
|
Packit |
aea12f |
size_t enc_data_size, dec_data_size;
|
|
Packit |
aea12f |
int dec_data_size2;
|
|
Packit |
aea12f |
EVP_CIPHER_CTX *ctx;
|
|
Packit |
aea12f |
const EVP_CIPHER *evp_cipher;
|
|
Packit |
aea12f |
unsigned char tag[64];
|
|
Packit |
aea12f |
unsigned i;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
success("cipher: %s\n", ocipher);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* decrypt with openssl */
|
|
Packit |
aea12f |
evp_cipher = EVP_get_cipherbyname(ocipher);
|
|
Packit |
aea12f |
if (!evp_cipher) {
|
|
Packit |
aea12f |
/* XXX: fix version check later when LibreSSL fixes support for aes-ccm and chacha20-poly1305 */
|
|
Packit |
aea12f |
#ifdef LIBRESSL_VERSION_NUMBER
|
|
Packit |
aea12f |
fprintf(stderr, "EVP_get_cipherbyname failed for %s\n", ocipher);
|
|
Packit |
aea12f |
return -1;
|
|
Packit |
aea12f |
#else
|
|
Packit |
aea12f |
/* OpenSSL should always work! */
|
|
Packit |
aea12f |
fail("EVP_get_cipherbyname failed for %s\n", ocipher);
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
for (i = 0; i < 32; i++) { /* try with multiple keys and nonces */
|
|
Packit |
aea12f |
assert(gnutls_rnd
|
|
Packit |
aea12f |
(GNUTLS_RND_NONCE, orig_plain_data,
|
|
Packit |
aea12f |
sizeof(orig_plain_data)) >= 0);
|
|
Packit |
aea12f |
assert(gnutls_rnd
|
|
Packit |
aea12f |
(GNUTLS_RND_NONCE, buffer_auth,
|
|
Packit |
aea12f |
sizeof(buffer_auth)) >= 0);
|
|
Packit |
aea12f |
assert(gnutls_rnd(GNUTLS_RND_NONCE, key, sizeof(key)) >= 0);
|
|
Packit |
aea12f |
assert(gnutls_rnd(GNUTLS_RND_NONCE, nonce, sizeof(nonce)) >= 0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
dkey.data = (void *)key;
|
|
Packit |
aea12f |
dkey.size = gnutls_cipher_get_key_size(gcipher);
|
|
Packit |
aea12f |
assert(gnutls_aead_cipher_init(&hd, gcipher, &dkey) >= 0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
dnonce.data = (void *)nonce;
|
|
Packit |
aea12f |
dnonce.size = gnutls_cipher_get_iv_size(gcipher);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
enc_data_size = sizeof(enc_data);
|
|
Packit |
aea12f |
assert(gnutls_aead_cipher_encrypt(hd, dnonce.data, dnonce.size,
|
|
Packit |
aea12f |
buffer_auth,
|
|
Packit |
aea12f |
sizeof(buffer_auth), tag_size,
|
|
Packit |
aea12f |
orig_plain_data,
|
|
Packit |
aea12f |
sizeof(orig_plain_data),
|
|
Packit |
aea12f |
enc_data,
|
|
Packit |
aea12f |
&enc_data_size) >= 0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (debug)
|
|
Packit |
aea12f |
success("encrypted %d bytes, to %d\n",
|
|
Packit |
aea12f |
(int)sizeof(orig_plain_data),
|
|
Packit |
aea12f |
(int)enc_data_size);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
dec_data_size = sizeof(dec_data);
|
|
Packit |
aea12f |
ret = gnutls_aead_cipher_decrypt(hd, dnonce.data, dnonce.size,
|
|
Packit |
aea12f |
buffer_auth,
|
|
Packit |
aea12f |
sizeof(buffer_auth), tag_size,
|
|
Packit |
aea12f |
enc_data, enc_data_size,
|
|
Packit |
aea12f |
dec_data, &dec_data_size);
|
|
Packit |
aea12f |
if (ret < 0) {
|
|
Packit |
aea12f |
fail("error in gnutls_aead_cipher_decrypt for %s: %s\n",
|
|
Packit |
aea12f |
ocipher, gnutls_strerror(ret));
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (dec_data_size != sizeof(orig_plain_data)
|
|
Packit |
aea12f |
|| memcmp(dec_data, orig_plain_data,
|
|
Packit |
aea12f |
sizeof(orig_plain_data)) != 0) {
|
|
Packit |
aea12f |
fail("gnutls encrypt-decrypt failed (got: %d, expected: %d)\n", (int)dec_data_size, (int)sizeof(orig_plain_data));
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
gnutls_aead_cipher_deinit(hd);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
ctx = EVP_CIPHER_CTX_new();
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
|
Packit |
aea12f |
if (gcipher == GNUTLS_CIPHER_AES_128_CCM
|
|
Packit |
aea12f |
|| gcipher == GNUTLS_CIPHER_AES_256_CCM) {
|
|
Packit |
aea12f |
assert(EVP_CipherInit_ex(ctx, evp_cipher, 0, 0, 0, 0) >
|
|
Packit |
aea12f |
0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
assert(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, dnonce.size, 0)==1);
|
|
Packit |
aea12f |
assert(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_size,
|
|
Packit |
aea12f |
enc_data + enc_data_size - tag_size) == 1);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
assert(EVP_CipherInit_ex(ctx, 0, 0, key, nonce, 0) >
|
|
Packit |
aea12f |
0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
dec_data_size2 = sizeof(dec_data);
|
|
Packit |
aea12f |
/* Add plain size */
|
|
Packit |
aea12f |
assert(EVP_CipherUpdate
|
|
Packit |
aea12f |
(ctx, NULL, &dec_data_size2, NULL,
|
|
Packit |
aea12f |
enc_data_size - tag_size) > 0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Add AAD */
|
|
Packit |
aea12f |
assert(EVP_CipherUpdate
|
|
Packit |
aea12f |
(ctx, NULL, &dec_data_size2, buffer_auth,
|
|
Packit |
aea12f |
sizeof(buffer_auth)) > 0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Decrypt */
|
|
Packit |
aea12f |
assert(EVP_CipherUpdate
|
|
Packit |
aea12f |
(ctx, dec_data, &dec_data_size2, enc_data,
|
|
Packit |
aea12f |
enc_data_size - tag_size) > 0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
dec_data_size = dec_data_size2;
|
|
Packit |
aea12f |
dec_data_size2 = tag_size;
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (dec_data_size != sizeof(orig_plain_data)
|
|
Packit |
aea12f |
|| memcmp(dec_data, orig_plain_data,
|
|
Packit |
aea12f |
sizeof(orig_plain_data)) != 0) {
|
|
Packit |
aea12f |
fail("openssl decrypt failed for %s\n", ocipher);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
} else
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
assert(EVP_CipherInit_ex(ctx, evp_cipher, NULL, key, nonce, 0) >
|
|
Packit |
aea12f |
0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag_size,
|
|
Packit |
aea12f |
enc_data + enc_data_size - tag_size);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
dec_data_size2 = sizeof(dec_data);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Add AAD */
|
|
Packit |
aea12f |
assert(EVP_CipherUpdate
|
|
Packit |
aea12f |
(ctx, NULL, &dec_data_size2, buffer_auth,
|
|
Packit |
aea12f |
sizeof(buffer_auth)) > 0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* Decrypt */
|
|
Packit |
aea12f |
assert(EVP_CipherUpdate
|
|
Packit |
aea12f |
(ctx, dec_data, &dec_data_size2, enc_data,
|
|
Packit |
aea12f |
enc_data_size - tag_size) > 0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
dec_data_size = dec_data_size2;
|
|
Packit |
aea12f |
dec_data_size2 = tag_size;
|
|
Packit |
aea12f |
assert(EVP_CipherFinal_ex(ctx, tag, &dec_data_size2) > 0);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
if (dec_data_size != sizeof(orig_plain_data)
|
|
Packit |
aea12f |
|| memcmp(dec_data, orig_plain_data,
|
|
Packit |
aea12f |
sizeof(orig_plain_data)) != 0) {
|
|
Packit |
aea12f |
fail("openssl decrypt failed for %s\n", ocipher);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
return 0;
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
static void tls_log_func(int level, const char *str)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
fprintf(stderr, "<%d>| %s", level, str);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
void doit(void)
|
|
Packit |
aea12f |
{
|
|
Packit |
aea12f |
gnutls_global_set_log_function(tls_log_func);
|
|
Packit |
aea12f |
if (debug)
|
|
Packit |
aea12f |
gnutls_global_set_log_level(4711);
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
global_init();
|
|
Packit |
aea12f |
OpenSSL_add_all_algorithms();
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
/* ciphers */
|
|
Packit |
aea12f |
cipher_test("aes-128-gcm", GNUTLS_CIPHER_AES_128_GCM, 16);
|
|
Packit Service |
991b93 |
cipher_test("aes-192-gcm", GNUTLS_CIPHER_AES_192_GCM, 16);
|
|
Packit |
aea12f |
cipher_test("aes-256-gcm", GNUTLS_CIPHER_AES_256_GCM, 16);
|
|
Packit |
aea12f |
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
|
Packit |
aea12f |
if (!gnutls_fips140_mode_enabled()) {
|
|
Packit |
aea12f |
cipher_test("chacha20-poly1305", GNUTLS_CIPHER_CHACHA20_POLY1305, 16);
|
|
Packit |
aea12f |
}
|
|
Packit |
aea12f |
cipher_test("aes-128-ccm", GNUTLS_CIPHER_AES_128_CCM, 16);
|
|
Packit |
aea12f |
cipher_test("aes-256-ccm", GNUTLS_CIPHER_AES_256_CCM, 16);
|
|
Packit |
aea12f |
#endif
|
|
Packit |
aea12f |
|
|
Packit |
aea12f |
gnutls_global_deinit();
|
|
Packit |
aea12f |
return;
|
|
Packit |
aea12f |
}
|