diff options
Diffstat (limited to '')
-rw-r--r-- | tests/cipher-padding.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/tests/cipher-padding.c b/tests/cipher-padding.c new file mode 100644 index 0000000..e8e66fb --- /dev/null +++ b/tests/cipher-padding.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2022 Red Hat, Inc. + * + * Author: Daiki Ueno + * + * This file is part of GnuTLS. + * + * The GnuTLS 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 program. If not, see <https://www.gnu.org/licenses/> + * + */ + +#include <config.h> + +#include <gnutls/crypto.h> +#include <limits.h> +#include <stdint.h> +#include <stdio.h> +#include "utils.h" + +static void tls_log_func(int level, const char *str) +{ + fprintf(stderr, "<%d>| %s", level, str); +} + +#define CLAMP(x, b) (((x) + (b)) / (b)) * (b) + +static void +start(gnutls_cipher_algorithm_t algo, size_t plaintext_size, unsigned int flags) +{ + int ret; + gnutls_cipher_hd_t ch; + uint8_t key16[64]; + uint8_t iv16[32]; + uint8_t plaintext[128]; + uint8_t ciphertext[128]; + size_t block_size; + size_t size; + gnutls_datum_t key, iv; + + success("%s %zu %u\n", + gnutls_cipher_get_name(algo), plaintext_size, flags); + + block_size = gnutls_cipher_get_block_size(algo); + + key.data = key16; + key.size = gnutls_cipher_get_key_size(algo); + assert(key.size <= sizeof(key16)); + + iv.data = iv16; + iv.size = gnutls_cipher_get_iv_size(algo); + assert(iv.size <= sizeof(iv16)); + + memset(iv.data, 0xff, iv.size); + memset(key.data, 0xfe, key.size); + memset(plaintext, 0xfa, sizeof(plaintext)); + + ret = gnutls_cipher_init(&ch, algo, &key, &iv); + if (ret < 0) { + fail("gnutls_cipher_init failed\n"); + } + + /* Check overflow if PKCS#7 is requested */ + if (flags & GNUTLS_CIPHER_PADDING_PKCS7) { + ret = gnutls_cipher_encrypt3(ch, + plaintext, SIZE_MAX, + NULL, &size, + flags); + if (ret != GNUTLS_E_INVALID_REQUEST) { + fail("gnutls_cipher_encrypt3 succeeded\n"); + } + } + + /* Get the ciphertext size */ + ret = gnutls_cipher_encrypt3(ch, + plaintext, plaintext_size, + NULL, &size, + flags); + if (ret < 0) { + fail("gnutls_cipher_encrypt3 failed\n"); + } + + if (flags & GNUTLS_CIPHER_PADDING_PKCS7) { + if (size <= plaintext_size) { + fail("no padding appended\n"); + } + if (size != CLAMP(plaintext_size, block_size)) { + fail("size does not match: %zu (expected %zu)\n", + size, CLAMP(plaintext_size, block_size)); + } + } else { + if (size != plaintext_size) { + fail("size does not match: %zu (expected %zu)\n", + size, plaintext_size); + } + } + + /* Encrypt with padding */ + ret = gnutls_cipher_encrypt3(ch, + plaintext, plaintext_size, + ciphertext, &size, + flags); + if (ret < 0) { + fail("gnutls_cipher_encrypt3 failed\n"); + } + + /* Decrypt with padding */ + ret = gnutls_cipher_decrypt3(ch, + ciphertext, size, + ciphertext, &size, + flags); + if (ret < 0) { + fail("gnutls_cipher_encrypt3 failed\n"); + } + + if (size != plaintext_size) { + fail("size does not match: %zu (expected %zu)\n", + size, plaintext_size); + } + + if (memcmp(ciphertext, plaintext, size) != 0) { + fail("plaintext does not match\n"); + } + + gnutls_cipher_deinit(ch); +} + +void doit(void) { + int ret; + + gnutls_global_set_log_function(tls_log_func); + if (debug) { + gnutls_global_set_log_level(4711); + } + + ret = global_init(); + if (ret < 0) { + fail("Cannot initialize library\n"); + } + + start(GNUTLS_CIPHER_AES_128_CBC, 0, GNUTLS_CIPHER_PADDING_PKCS7); + start(GNUTLS_CIPHER_AES_128_CBC, 11, GNUTLS_CIPHER_PADDING_PKCS7); + start(GNUTLS_CIPHER_AES_128_CBC, 77, GNUTLS_CIPHER_PADDING_PKCS7); + start(GNUTLS_CIPHER_AES_128_CBC, 80, GNUTLS_CIPHER_PADDING_PKCS7); + + start(GNUTLS_CIPHER_AES_128_CBC, 0, 0); + start(GNUTLS_CIPHER_AES_128_CBC, 80, 0); + + gnutls_global_deinit(); +} |