forked from wolfSSL/wolfssl
Implement CTS
Ciphertext stealing on top of CBC is implemented with `wolfSSL_CRYPTO_cts128_encrypt` and `wolfSSL_CRYPTO_cts128_decrypt` APIs
This commit is contained in:
@ -6815,7 +6815,7 @@ then
|
||||
AM_CFLAGS="-DOPENSSL_EXTRA -DWOLFSSL_ALWAYS_VERIFY_CB $AM_CFLAGS"
|
||||
AM_CFLAGS="-DWOLFSSL_VERIFY_CB_ALL_CERTS -DWOLFSSL_EXTRA_ALERTS $AM_CFLAGS"
|
||||
AM_CFLAGS="-DHAVE_EXT_CACHE -DWOLFSSL_FORCE_CACHE_ON_TICKET $AM_CFLAGS"
|
||||
AM_CFLAGS="-DWOLFSSL_AKID_NAME $AM_CFLAGS"
|
||||
AM_CFLAGS="-DWOLFSSL_AKID_NAME -DHAVE_CTS $AM_CFLAGS"
|
||||
fi
|
||||
|
||||
if test "$ENABLED_OPENSSLEXTRA" = "x509small"
|
||||
|
80
src/ssl.c
80
src/ssl.c
@ -99,6 +99,7 @@
|
||||
#include <wolfssl/openssl/ecdsa.h>
|
||||
#include <wolfssl/openssl/ecdh.h>
|
||||
#include <wolfssl/openssl/err.h>
|
||||
#include <wolfssl/openssl/modes.h>
|
||||
#include <wolfssl/openssl/opensslv.h>
|
||||
#include <wolfssl/openssl/rc4.h>
|
||||
#include <wolfssl/openssl/stack.h>
|
||||
@ -30511,7 +30512,84 @@ int wolfSSL_AES_unwrap_key(AES_KEY *key, const unsigned char *iv,
|
||||
#endif /* HAVE_AES_KEYWRAP && !HAVE_FIPS && !HAVE_SELFTEST */
|
||||
#endif /* NO_AES */
|
||||
|
||||
#ifndef NO_ASN_TIME
|
||||
#ifdef HAVE_CTS
|
||||
/*
|
||||
* Ciphertext stealing interface compatible with RFC2040 and RFC3962.
|
||||
*/
|
||||
size_t wolfSSL_CRYPTO_cts128_encrypt(const unsigned char *in,
|
||||
unsigned char *out, size_t len, const void *key,
|
||||
unsigned char *iv, WOLFSSL_CBC128_CB cbc)
|
||||
{
|
||||
byte lastBlk[WOLFSSL_CTS128_BLOCK_SZ] = {0};
|
||||
int lastBlkLen = len % WOLFSSL_CTS128_BLOCK_SZ;
|
||||
WOLFSSL_ENTER("wolfSSL_CRYPTO_cts128_encrypt");
|
||||
|
||||
if (in == NULL || out == NULL || len < WOLFSSL_CTS128_BLOCK_SZ ||
|
||||
cbc == NULL) {
|
||||
WOLFSSL_MSG("Bad parameter");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
if (lastBlkLen == 0)
|
||||
lastBlkLen = WOLFSSL_CTS128_BLOCK_SZ;
|
||||
|
||||
/* Encrypt data up to last block */
|
||||
(*cbc)(in, out, len - lastBlkLen, key, iv, 1);
|
||||
|
||||
/* Move to last block */
|
||||
in += len - lastBlkLen;
|
||||
out += len - lastBlkLen;
|
||||
|
||||
/* RFC2040: Pad Pn with zeros at the end to create P of length BB. */
|
||||
XMEMCPY(lastBlk, in, lastBlkLen);
|
||||
/* RFC2040: Select the first Ln bytes of En-1 to create Cn */
|
||||
XMEMCPY(out, out - WOLFSSL_CTS128_BLOCK_SZ, lastBlkLen);
|
||||
(*cbc)(lastBlk, out - WOLFSSL_CTS128_BLOCK_SZ, WOLFSSL_CTS128_BLOCK_SZ,
|
||||
key, iv, 1);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t wolfSSL_CRYPTO_cts128_decrypt(const unsigned char *in,
|
||||
unsigned char *out, size_t len, const void *key,
|
||||
unsigned char *iv, WOLFSSL_CBC128_CB cbc)
|
||||
{
|
||||
byte lastBlk[WOLFSSL_CTS128_BLOCK_SZ] = {0};
|
||||
byte prevBlk[WOLFSSL_CTS128_BLOCK_SZ] = {0};
|
||||
int lastBlkLen = len % WOLFSSL_CTS128_BLOCK_SZ;
|
||||
WOLFSSL_ENTER("wolfSSL_CRYPTO_cts128_decrypt");
|
||||
|
||||
if (in == NULL || out == NULL || len <= WOLFSSL_CTS128_BLOCK_SZ ||
|
||||
cbc == NULL) {
|
||||
WOLFSSL_MSG("Bad parameter");
|
||||
return WOLFSSL_FAILURE;
|
||||
}
|
||||
|
||||
if (lastBlkLen == 0)
|
||||
lastBlkLen = WOLFSSL_CTS128_BLOCK_SZ;
|
||||
|
||||
/* Decrypt up to last two blocks */
|
||||
(*cbc)(in, out, len - lastBlkLen - WOLFSSL_CTS128_BLOCK_SZ, key, iv, 0);
|
||||
|
||||
/* Move to last two blocks */
|
||||
in += len - lastBlkLen - WOLFSSL_CTS128_BLOCK_SZ;
|
||||
out += len - lastBlkLen - WOLFSSL_CTS128_BLOCK_SZ;
|
||||
|
||||
/* RFC2040: Decrypt Cn-1 to create Dn.
|
||||
* Use 0 buffer as IV to do straight decryption.
|
||||
* This places the Cn-1 block at lastBlk */
|
||||
(*cbc)(in, prevBlk, WOLFSSL_CTS128_BLOCK_SZ, key, lastBlk, 0);
|
||||
/* RFC2040: Append the tail (BB minus Ln) bytes of Xn to Cn
|
||||
* to create En. */
|
||||
XMEMCPY(prevBlk, in + WOLFSSL_CTS128_BLOCK_SZ, lastBlkLen);
|
||||
/* Cn and Cn-1 can now be decrypted */
|
||||
(*cbc)(prevBlk, out, WOLFSSL_CTS128_BLOCK_SZ, key, iv, 0);
|
||||
(*cbc)(lastBlk, lastBlk, WOLFSSL_CTS128_BLOCK_SZ, key, iv, 0);
|
||||
XMEMCPY(out + WOLFSSL_CTS128_BLOCK_SZ, lastBlk, lastBlkLen);
|
||||
return len;
|
||||
}
|
||||
#endif /* HAVE_CTS */
|
||||
|
||||
#ifndef NO_BIO
|
||||
int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a)
|
||||
{
|
||||
|
84
tests/api.c
84
tests/api.c
@ -313,6 +313,7 @@
|
||||
#include <wolfssl/openssl/hmac.h>
|
||||
#include <wolfssl/openssl/objects.h>
|
||||
#include <wolfssl/openssl/rand.h>
|
||||
#include <wolfssl/openssl/modes.h>
|
||||
#ifdef OPENSSL_ALL
|
||||
#include <wolfssl/openssl/txt_db.h>
|
||||
#include <wolfssl/openssl/lhash.h>
|
||||
@ -41975,6 +41976,88 @@ static void test_wolfSSL_AES_cbc_encrypt(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_wolfSSL_CRYPTO_cts128(void)
|
||||
{
|
||||
#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(OPENSSL_EXTRA) \
|
||||
&& defined(HAVE_CTS)
|
||||
byte tmp[64] = {0}; /* Largest vector size */
|
||||
/* Test vectors taken form RFC3962 Appendix B */
|
||||
const testVector vects[] = {
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20",
|
||||
"\xc6\x35\x35\x68\xf2\xbf\x8c\xb4\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
|
||||
"\x97",
|
||||
17, 17
|
||||
},
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20",
|
||||
"\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
|
||||
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5",
|
||||
31, 31
|
||||
},
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43",
|
||||
"\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
|
||||
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84",
|
||||
32, 32
|
||||
},
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
|
||||
"\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c",
|
||||
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
|
||||
"\xb3\xff\xfd\x94\x0c\x16\xa1\x8c\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
|
||||
"\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5",
|
||||
47, 47
|
||||
},
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
|
||||
"\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20",
|
||||
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
|
||||
"\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
|
||||
"\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8",
|
||||
48, 48
|
||||
},
|
||||
{
|
||||
"\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
|
||||
"\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
|
||||
"\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20"
|
||||
"\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e",
|
||||
"\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
|
||||
"\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
|
||||
"\x48\x07\xef\xe8\x36\xee\x89\xa5\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
|
||||
"\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8",
|
||||
64, 64
|
||||
}
|
||||
};
|
||||
byte keyBytes[AES_128_KEY_SIZE] = {
|
||||
0x63, 0x68, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20,
|
||||
0x74, 0x65, 0x72, 0x69, 0x79, 0x61, 0x6b, 0x69
|
||||
};
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(vects)/sizeof(vects[0]); i++) {
|
||||
AES_KEY encKey;
|
||||
AES_KEY decKey;
|
||||
byte iv[AES_IV_SIZE] = {0}; /* All-zero IV for all cases */
|
||||
AssertIntEQ(AES_set_encrypt_key(keyBytes, AES_128_KEY_SIZE * 8, &encKey), 0);
|
||||
AssertIntEQ(AES_set_decrypt_key(keyBytes, AES_128_KEY_SIZE * 8, &decKey), 0);
|
||||
AssertIntEQ(CRYPTO_cts128_encrypt((const unsigned char*)vects[i].input,
|
||||
tmp, vects[i].inLen, &encKey, iv, (cbc128_f)AES_cbc_encrypt),
|
||||
vects[i].outLen);
|
||||
AssertIntEQ(XMEMCMP(tmp, vects[i].output, vects[i].outLen), 0);
|
||||
XMEMSET(iv, 0, sizeof(iv));
|
||||
AssertIntEQ(CRYPTO_cts128_decrypt((const unsigned char*)vects[i].output,
|
||||
tmp, vects[i].outLen, &decKey, iv, (cbc128_f)AES_cbc_encrypt),
|
||||
vects[i].inLen);
|
||||
AssertIntEQ(XMEMCMP(tmp, vects[i].input, vects[i].inLen), 0);
|
||||
}
|
||||
#endif /* !NO_AES && HAVE_AES_CBC && OPENSSL_EXTRA && HAVE_CTS */
|
||||
}
|
||||
|
||||
#if defined(OPENSSL_ALL)
|
||||
#if !defined(NO_ASN)
|
||||
static void test_wolfSSL_ASN1_STRING_to_UTF8(void)
|
||||
@ -51945,6 +52028,7 @@ void ApiTest(void)
|
||||
test_wolfSSL_DC_cert();
|
||||
test_wolfSSL_DES_ncbc();
|
||||
test_wolfSSL_AES_cbc_encrypt();
|
||||
test_wolfSSL_CRYPTO_cts128();
|
||||
test_wolfssl_EVP_aes_gcm_AAD_2_parts();
|
||||
test_wolfssl_EVP_aes_gcm();
|
||||
test_wolfSSL_PKEY_up_ref();
|
||||
|
@ -30,6 +30,7 @@ nobase_include_HEADERS+= \
|
||||
wolfssl/openssl/lhash.h \
|
||||
wolfssl/openssl/md4.h \
|
||||
wolfssl/openssl/md5.h \
|
||||
wolfssl/openssl/modes.h \
|
||||
wolfssl/openssl/ripemd.h \
|
||||
wolfssl/openssl/obj_mac.h \
|
||||
wolfssl/openssl/objects.h \
|
||||
|
45
wolfssl/openssl/modes.h
Normal file
45
wolfssl/openssl/modes.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* modes.h
|
||||
*
|
||||
* Copyright (C) 2006-2021 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSL.
|
||||
*
|
||||
* wolfSSL is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSL 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
#ifndef WOLFSSL_OPENSSL_MODES_H
|
||||
#define WOLFSSL_OPENSSL_MODES_H
|
||||
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#include <wolfssl/openssl/ssl.h>
|
||||
|
||||
typedef void (*WOLFSSL_CBC128_CB) (const unsigned char *in,
|
||||
unsigned char *out, size_t len, const void *key,
|
||||
unsigned char *iv, int enc);
|
||||
|
||||
WOLFSSL_API size_t wolfSSL_CRYPTO_cts128_encrypt(const unsigned char *in,
|
||||
unsigned char *out, size_t len, const void *key,
|
||||
unsigned char *iv, WOLFSSL_CBC128_CB cbc);
|
||||
WOLFSSL_API size_t wolfSSL_CRYPTO_cts128_decrypt(const unsigned char *in,
|
||||
unsigned char *out, size_t len, const void *key,
|
||||
unsigned char *iv, WOLFSSL_CBC128_CB cbc);
|
||||
|
||||
#define WOLFSSL_CTS128_BLOCK_SZ 16
|
||||
|
||||
/* Compatibility layer defines */
|
||||
#define CRYPTO_cts128_encrypt wolfSSL_CRYPTO_cts128_encrypt
|
||||
#define CRYPTO_cts128_decrypt wolfSSL_CRYPTO_cts128_decrypt
|
||||
#define cbc128_f WOLFSSL_CBC128_CB
|
||||
|
||||
#endif /* WOLFSSL_OPENSSL_MODES_H */
|
Reference in New Issue
Block a user