Add ctaes-based constant time AES implementation

This commit is contained in:
Pieter Wuille 2016-03-30 15:37:41 +02:00
parent cd2be4419e
commit 6bec172eb9
4 changed files with 198 additions and 1 deletions

View File

@ -225,6 +225,8 @@ libbitcoin_wallet_a_SOURCES = \
crypto_libbitcoin_crypto_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_CONFIG_INCLUDES)
crypto_libbitcoin_crypto_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
crypto_libbitcoin_crypto_a_SOURCES = \
crypto/aes.cpp \
crypto/aes.h \
crypto/common.h \
crypto/hmac_sha256.cpp \
crypto/hmac_sha256.h \
@ -434,7 +436,7 @@ CLEANFILES += zmq/*.gcda zmq/*.gcno
DISTCLEANFILES = obj/build.h
EXTRA_DIST = leveldb
EXTRA_DIST = leveldb crypto/ctaes
clean-local:
-$(MAKE) -C leveldb clean

73
src/crypto/aes.cpp Normal file
View File

@ -0,0 +1,73 @@
// Copyright (c) 2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "aes.h"
#include "crypto/common.h"
#include <assert.h>
#include <string.h>
extern "C" {
#include "crypto/ctaes/ctaes.c"
}
AES128Encrypt::AES128Encrypt(const unsigned char key[16])
{
AES128_init(&ctx, key);
}
AES128Encrypt::~AES128Encrypt()
{
memset(&ctx, 0, sizeof(ctx));
}
void AES128Encrypt::Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const
{
AES128_encrypt(&ctx, 1, ciphertext, plaintext);
}
AES128Decrypt::AES128Decrypt(const unsigned char key[16])
{
AES128_init(&ctx, key);
}
AES128Decrypt::~AES128Decrypt()
{
memset(&ctx, 0, sizeof(ctx));
}
void AES128Decrypt::Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const
{
AES128_decrypt(&ctx, 1, plaintext, ciphertext);
}
AES256Encrypt::AES256Encrypt(const unsigned char key[32])
{
AES256_init(&ctx, key);
}
AES256Encrypt::~AES256Encrypt()
{
memset(&ctx, 0, sizeof(ctx));
}
void AES256Encrypt::Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const
{
AES256_encrypt(&ctx, 1, ciphertext, plaintext);
}
AES256Decrypt::AES256Decrypt(const unsigned char key[32])
{
AES256_init(&ctx, key);
}
AES256Decrypt::~AES256Decrypt()
{
memset(&ctx, 0, sizeof(ctx));
}
void AES256Decrypt::Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const
{
AES256_decrypt(&ctx, 1, plaintext, ciphertext);
}

66
src/crypto/aes.h Normal file
View File

@ -0,0 +1,66 @@
// Copyright (c) 2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//
// C++ wrapper around ctaes, a constant-time AES implementation
#ifndef BITCOIN_CRYPTO_AES_H
#define BITCOIN_CRYPTO_AES_H
extern "C" {
#include "crypto/ctaes/ctaes.h"
}
static const int AES_BLOCKSIZE = 16;
static const int AES128_KEYSIZE = 16;
static const int AES256_KEYSIZE = 32;
/** An encryption class for AES-128. */
class AES128Encrypt
{
private:
AES128_ctx ctx;
public:
AES128Encrypt(const unsigned char key[16]);
~AES128Encrypt();
void Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const;
};
/** A decryption class for AES-128. */
class AES128Decrypt
{
private:
AES128_ctx ctx;
public:
AES128Decrypt(const unsigned char key[16]);
~AES128Decrypt();
void Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const;
};
/** An encryption class for AES-256. */
class AES256Encrypt
{
private:
AES256_ctx ctx;
public:
AES256Encrypt(const unsigned char key[32]);
~AES256Encrypt();
void Encrypt(unsigned char ciphertext[16], const unsigned char plaintext[16]) const;
};
/** A decryption class for AES-256. */
class AES256Decrypt
{
private:
AES256_ctx ctx;
public:
AES256Decrypt(const unsigned char key[32]);
~AES256Decrypt();
void Decrypt(unsigned char plaintext[16], const unsigned char ciphertext[16]) const;
};
#endif // BITCOIN_CRYPTO_AES_H

View File

@ -2,6 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "crypto/aes.h"
#include "crypto/ripemd160.h"
#include "crypto/sha1.h"
#include "crypto/sha256.h"
@ -63,6 +64,45 @@ void TestHMACSHA512(const std::string &hexkey, const std::string &hexin, const s
TestVector(CHMAC_SHA512(&key[0], key.size()), ParseHex(hexin), ParseHex(hexout));
}
void TestAES128(const std::string &hexkey, const std::string &hexin, const std::string &hexout)
{
std::vector<unsigned char> key = ParseHex(hexkey);
std::vector<unsigned char> in = ParseHex(hexin);
std::vector<unsigned char> correctout = ParseHex(hexout);
std::vector<unsigned char> buf, buf2;
assert(key.size() == 16);
assert(in.size() == 16);
assert(correctout.size() == 16);
AES128Encrypt enc(&key[0]);
buf.resize(correctout.size());
buf2.resize(correctout.size());
enc.Encrypt(&buf[0], &in[0]);
BOOST_CHECK_EQUAL(HexStr(buf), HexStr(correctout));
AES128Decrypt dec(&key[0]);
dec.Decrypt(&buf2[0], &buf[0]);
BOOST_CHECK_EQUAL(HexStr(buf2), HexStr(in));
}
void TestAES256(const std::string &hexkey, const std::string &hexin, const std::string &hexout)
{
std::vector<unsigned char> key = ParseHex(hexkey);
std::vector<unsigned char> in = ParseHex(hexin);
std::vector<unsigned char> correctout = ParseHex(hexout);
std::vector<unsigned char> buf;
assert(key.size() == 32);
assert(in.size() == 16);
assert(correctout.size() == 16);
AES256Encrypt enc(&key[0]);
buf.resize(correctout.size());
enc.Encrypt(&buf[0], &in[0]);
BOOST_CHECK(buf == correctout);
AES256Decrypt dec(&key[0]);
dec.Decrypt(&buf[0], &buf[0]);
BOOST_CHECK(buf == in);
}
std::string LongTestString(void) {
std::string ret;
for (int i=0; i<200000; i++) {
@ -248,4 +288,20 @@ BOOST_AUTO_TEST_CASE(hmac_sha512_testvectors) {
"b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58");
}
BOOST_AUTO_TEST_CASE(aes_testvectors) {
// AES test vectors from FIPS 197.
TestAES128("000102030405060708090a0b0c0d0e0f", "00112233445566778899aabbccddeeff", "69c4e0d86a7b0430d8cdb78070b4c55a");
TestAES256("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", "00112233445566778899aabbccddeeff", "8ea2b7ca516745bfeafc49904b496089");
// AES-ECB test vectors from NIST sp800-38a.
TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "6bc1bee22e409f96e93d7e117393172a", "3ad77bb40d7a3660a89ecaf32466ef97");
TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "ae2d8a571e03ac9c9eb76fac45af8e51", "f5d3d58503b9699de785895a96fdbaaf");
TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "30c81c46a35ce411e5fbc1191a0a52ef", "43b1cd7f598ece23881b00e3ed030688");
TestAES128("2b7e151628aed2a6abf7158809cf4f3c", "f69f2445df4f9b17ad2b417be66c3710", "7b0c785e27e8ad3f8223207104725dd4");
TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "6bc1bee22e409f96e93d7e117393172a", "f3eed1bdb5d2a03c064b5a7e3db181f8");
TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "ae2d8a571e03ac9c9eb76fac45af8e51", "591ccb10d410ed26dc5ba74a31362870");
TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "30c81c46a35ce411e5fbc1191a0a52ef", "b6ed21b99ca6f4f9f153e7b1beafed1d");
TestAES256("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4", "f69f2445df4f9b17ad2b417be66c3710", "23304b7a39f9f3ff067d8d8f9e24ecc7");
}
BOOST_AUTO_TEST_SUITE_END()