mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 15:44:21 +01:00
You will want to 'make distclean' after this. I also removed libsecp; we use the one in in libwally anyway. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
180 lines
5.6 KiB
C
180 lines
5.6 KiB
C
#include "internal.h"
|
|
#include <include/wally_crypto.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "ctaes/ctaes.h"
|
|
#include "ctaes/ctaes.c"
|
|
|
|
#define ALL_OPS (AES_FLAG_ENCRYPT | AES_FLAG_DECRYPT)
|
|
|
|
static bool is_valid_key_len(size_t key_len)
|
|
{
|
|
return key_len == AES_KEY_LEN_128 || key_len == AES_KEY_LEN_192 ||
|
|
key_len == AES_KEY_LEN_256;
|
|
}
|
|
|
|
static bool are_valid_args(const unsigned char *key, size_t key_len,
|
|
const unsigned char *bytes_in, uint32_t flags)
|
|
{
|
|
return key && is_valid_key_len(key_len) && bytes_in &&
|
|
(flags & ALL_OPS) != ALL_OPS;
|
|
}
|
|
|
|
static void aes_enc(AES256_ctx *ctx,
|
|
const unsigned char *key, size_t key_len,
|
|
const unsigned char *bytes_in, size_t len_in,
|
|
unsigned char *bytes_out)
|
|
{
|
|
len_in /= AES_BLOCK_LEN;
|
|
|
|
switch (key_len) {
|
|
case AES_KEY_LEN_128:
|
|
AES128_init((AES128_ctx *)ctx, key);
|
|
AES128_encrypt((AES128_ctx *)ctx, len_in, bytes_out, bytes_in);
|
|
break;
|
|
|
|
case AES_KEY_LEN_192:
|
|
AES192_init((AES192_ctx *)ctx, key);
|
|
AES192_encrypt((AES192_ctx *)ctx, len_in, bytes_out, bytes_in);
|
|
break;
|
|
|
|
case AES_KEY_LEN_256:
|
|
AES256_init(ctx, key);
|
|
AES256_encrypt(ctx, len_in, bytes_out, bytes_in);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void aes_dec(AES256_ctx *ctx,
|
|
const unsigned char *key, size_t key_len,
|
|
const unsigned char *bytes_in, size_t len_in,
|
|
unsigned char *bytes_out)
|
|
{
|
|
len_in /= AES_BLOCK_LEN;
|
|
|
|
switch (key_len) {
|
|
case AES_KEY_LEN_128:
|
|
AES128_init((AES128_ctx *)ctx, key);
|
|
AES128_decrypt((AES128_ctx *)ctx, len_in, bytes_out, bytes_in);
|
|
break;
|
|
|
|
case AES_KEY_LEN_192:
|
|
AES192_init((AES192_ctx *)ctx, key);
|
|
AES192_decrypt((AES192_ctx *)ctx, len_in, bytes_out, bytes_in);
|
|
break;
|
|
|
|
case AES_KEY_LEN_256:
|
|
AES256_init(ctx, key);
|
|
AES256_decrypt(ctx, len_in, bytes_out, bytes_in);
|
|
break;
|
|
}
|
|
}
|
|
|
|
int wally_aes(const unsigned char *key, size_t key_len,
|
|
const unsigned char *bytes_in, size_t len_in,
|
|
uint32_t flags,
|
|
unsigned char *bytes_out, size_t len)
|
|
{
|
|
AES256_ctx ctx;
|
|
|
|
if (!are_valid_args(key, key_len, bytes_in, flags) ||
|
|
len % AES_BLOCK_LEN || !len_in || len_in % AES_BLOCK_LEN ||
|
|
flags & ~ALL_OPS || !bytes_out || !len)
|
|
return WALLY_EINVAL;
|
|
|
|
if (flags & AES_FLAG_ENCRYPT)
|
|
aes_enc(&ctx, key, key_len, bytes_in, len_in, bytes_out);
|
|
else
|
|
aes_dec(&ctx, key, key_len, bytes_in, len_in, bytes_out);
|
|
|
|
clear(&ctx, sizeof(ctx));
|
|
return WALLY_OK;
|
|
}
|
|
|
|
int wally_aes_cbc(const unsigned char *key, size_t key_len,
|
|
const unsigned char *iv, size_t iv_len,
|
|
const unsigned char *bytes_in, size_t len_in,
|
|
uint32_t flags,
|
|
unsigned char *bytes_out, size_t len,
|
|
size_t *written)
|
|
{
|
|
unsigned char buf[AES_BLOCK_LEN];
|
|
AES256_ctx ctx;
|
|
size_t i, n, blocks;
|
|
unsigned char remainder;
|
|
|
|
if (written)
|
|
*written = 0;
|
|
|
|
if (!are_valid_args(key, key_len, bytes_in, flags) ||
|
|
((flags & AES_FLAG_ENCRYPT) && (len % AES_BLOCK_LEN)) ||
|
|
((flags & AES_FLAG_DECRYPT) && (len_in % AES_BLOCK_LEN)) ||
|
|
!iv || iv_len != AES_BLOCK_LEN || flags & ~ALL_OPS || !written)
|
|
return WALLY_EINVAL;
|
|
|
|
blocks = len_in / AES_BLOCK_LEN;
|
|
|
|
if (flags & AES_FLAG_ENCRYPT) {
|
|
/* Determine output length from input length */
|
|
remainder = len_in % AES_BLOCK_LEN;
|
|
*written = (blocks + 1) * AES_BLOCK_LEN;
|
|
} else {
|
|
/* Determine output length from decrypted final block */
|
|
const unsigned char *last = bytes_in + len_in - AES_BLOCK_LEN;
|
|
const unsigned char *prev = last - AES_BLOCK_LEN;
|
|
|
|
if (!--blocks)
|
|
prev = iv;
|
|
aes_dec(&ctx, key, key_len, last, AES_BLOCK_LEN, buf);
|
|
for (n = 0; n < AES_BLOCK_LEN; ++n)
|
|
buf[n] = prev[n] ^ buf[n];
|
|
|
|
/* Modulo the resulting padding amount to the block size - we do
|
|
* not attempt to verify the decryption by checking the padding in
|
|
* the decrypted block. */
|
|
remainder = AES_BLOCK_LEN - (buf[AES_BLOCK_LEN - 1] % AES_BLOCK_LEN);
|
|
if (remainder == AES_BLOCK_LEN)
|
|
remainder = 0;
|
|
*written = blocks * AES_BLOCK_LEN + remainder;
|
|
}
|
|
if (len < *written || !*written)
|
|
goto finish; /* Inform caller how much space is needed */
|
|
|
|
if (!bytes_out) {
|
|
clear_n(2, buf, sizeof(buf), &ctx, sizeof(ctx));
|
|
return WALLY_EINVAL;
|
|
}
|
|
|
|
if (flags & AES_FLAG_DECRYPT)
|
|
memcpy(bytes_out + blocks * AES_BLOCK_LEN, buf, remainder);
|
|
|
|
for (i = 0; i < blocks; ++i) {
|
|
if (flags & AES_FLAG_ENCRYPT) {
|
|
for (n = 0; n < AES_BLOCK_LEN; ++n)
|
|
buf[n] = bytes_in[n] ^ iv[n];
|
|
aes_enc(&ctx, key, key_len, buf, AES_BLOCK_LEN, bytes_out);
|
|
iv = bytes_out;
|
|
} else {
|
|
aes_dec(&ctx, key, key_len, bytes_in, AES_BLOCK_LEN, bytes_out);
|
|
for (n = 0; n < AES_BLOCK_LEN; ++n)
|
|
bytes_out[n] = bytes_out[n] ^ iv[n];
|
|
iv = bytes_in;
|
|
}
|
|
bytes_in += AES_BLOCK_LEN;
|
|
bytes_out += AES_BLOCK_LEN;
|
|
}
|
|
|
|
if (flags & AES_FLAG_ENCRYPT) {
|
|
for (n = 0; n < remainder; ++n)
|
|
buf[n] = bytes_in[n] ^ iv[n];
|
|
remainder = 16 - remainder;
|
|
for (; n < AES_BLOCK_LEN; ++n)
|
|
buf[n] = remainder ^ iv[n];
|
|
aes_enc(&ctx, key, key_len, buf, AES_BLOCK_LEN, bytes_out);
|
|
}
|
|
|
|
finish:
|
|
clear_n(2, buf, sizeof(buf), &ctx, sizeof(ctx));
|
|
return WALLY_OK;
|
|
}
|