diff --git a/Makefile b/Makefile index eb598a7..aad52d9 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ MODULES += list mbuf hash MODULES += fmt tmr main mem dbg sys lock mqueue MODULES += mod conf MODULES += bfcp +MODULES += aes INSTALL := install ifeq ($(DESTDIR),) diff --git a/include/re.h b/include/re.h index 1c4e28b..a506fff 100644 --- a/include/re.h +++ b/include/re.h @@ -20,6 +20,7 @@ extern "C" { #include "re_sa.h" /* Library modules */ +#include "re_aes.h" #include "re_base64.h" #include "re_bfcp.h" #include "re_conf.h" diff --git a/include/re_aes.h b/include/re_aes.h new file mode 100644 index 0000000..ec8567c --- /dev/null +++ b/include/re_aes.h @@ -0,0 +1,23 @@ +/** + * @file re_aes.h Interface to AES (Advanced Encryption Standard) + * + * Copyright (C) 2010 Creytiv.com + */ + + +#ifndef AES_BLOCK_SIZE +#define AES_BLOCK_SIZE 16 +#endif + +enum aes_mode { + AES_MODE_CTR /**< AES Counter mode (CTR) */ +}; + +struct aes; + +int aes_alloc(struct aes **stp, enum aes_mode mode, + const uint8_t *key, size_t key_bits, + const uint8_t iv[AES_BLOCK_SIZE]); +void aes_set_iv(struct aes *aes, const uint8_t iv[AES_BLOCK_SIZE]); +int aes_encr(struct aes *aes, uint8_t *out, const uint8_t *in, size_t len); +int aes_decr(struct aes *aes, uint8_t *out, const uint8_t *in, size_t len); diff --git a/mk/re.mk b/mk/re.mk index f72c29d..3158df1 100644 --- a/mk/re.mk +++ b/mk/re.mk @@ -758,7 +758,7 @@ SPLINT_OPTIONS += -DHAVE_INET_NTOP -DHAVE_INET_PTON -DHAVE_INET6 # ignore these files for now SPLINT_IGNORE := src/tls/openssl/tls.c src/tls/openssl/tls_tcp.c -SPLINT_IGNORE += src/dns/darwin/srv.c +SPLINT_IGNORE += src/dns/darwin/srv.c src/aes/openssl/aes.c SPLINT_SOURCES += $(filter-out $(SPLINT_IGNORE), $(patsubst %,src/%,$(SRCS))) diff --git a/src/aes/mod.mk b/src/aes/mod.mk new file mode 100644 index 0000000..931e5cf --- /dev/null +++ b/src/aes/mod.mk @@ -0,0 +1,11 @@ +# +# mod.mk +# +# Copyright (C) 2010 Creytiv.com +# + +ifneq ($(USE_OPENSSL),) +SRCS += aes/openssl/aes.c +else +SRCS += aes/stub.c +endif diff --git a/src/aes/openssl/aes.c b/src/aes/openssl/aes.c new file mode 100644 index 0000000..287a182 --- /dev/null +++ b/src/aes/openssl/aes.c @@ -0,0 +1,187 @@ +/** + * @file openssl/aes.c AES (Advanced Encryption Standard) using OpenSSL + * + * Copyright (C) 2010 Creytiv.com + */ +#include +#include +#include +#include +#include +#include +#include + + +#ifdef EVP_CIPH_CTR_MODE + + +struct aes { + EVP_CIPHER_CTX ctx; +}; + + +static void destructor(void *arg) +{ + struct aes *st = arg; + + EVP_CIPHER_CTX_cleanup(&st->ctx); +} + + +int aes_alloc(struct aes **aesp, enum aes_mode mode, + const uint8_t *key, size_t key_bits, + const uint8_t iv[AES_BLOCK_SIZE]) +{ + const EVP_CIPHER *cipher; + struct aes *st; + int err = 0, r; + + if (!aesp || !key) + return EINVAL; + + if (mode != AES_MODE_CTR) + return ENOTSUP; + + st = mem_zalloc(sizeof(*st), destructor); + if (!st) + return ENOMEM; + + EVP_CIPHER_CTX_init(&st->ctx); + + switch (key_bits) { + + case 128: cipher = EVP_aes_128_ctr(); break; + case 192: cipher = EVP_aes_192_ctr(); break; + case 256: cipher = EVP_aes_256_ctr(); break; + default: + re_fprintf(stderr, "aes: unknown key: %zu bits\n", key_bits); + err = EINVAL; + goto out; + } + + r = EVP_EncryptInit_ex(&st->ctx, cipher, NULL, key, iv); + if (!r) + err = EPROTO; + + out: + if (err) + mem_deref(st); + else + *aesp = st; + + return err; +} + + +void aes_set_iv(struct aes *aes, const uint8_t iv[AES_BLOCK_SIZE]) +{ + if (!aes) + return; + + if (iv) + (void)EVP_EncryptInit_ex(&aes->ctx, NULL, NULL, NULL, iv); +} + + +int aes_encr(struct aes *aes, uint8_t *out, const uint8_t *in, size_t len) +{ + int c_len = (int)len; + + if (!aes || !out || !in || !len) + return EINVAL; + + if (!EVP_EncryptUpdate(&aes->ctx, out, &c_len, in, (int)len)) + return EPROTO; + + return 0; +} + + +#else /* EVP_CIPH_CTR_MODE */ + + +struct aes { + AES_KEY key; + uint8_t iv[AES_BLOCK_SIZE]; +}; + + +static void destructor(void *arg) +{ + struct aes *st = arg; + + memset(&st->key, 0, sizeof(st->key)); +} + + +int aes_alloc(struct aes **aesp, enum aes_mode mode, + const uint8_t *key, size_t key_bits, + const uint8_t iv[AES_BLOCK_SIZE]) +{ + struct aes *st; + int err = 0, r; + + if (!aesp || !key) + return EINVAL; + + if (mode != AES_MODE_CTR) + return ENOTSUP; + + st = mem_zalloc(sizeof(*st), destructor); + if (!st) + return ENOMEM; + + r = AES_set_encrypt_key(key, (int)key_bits, &st->key); + if (r != 0) { + err = EPROTO; + goto out; + } + if (iv) + memcpy(st->iv, iv, sizeof(st->iv)); + + out: + if (err) + mem_deref(st); + else + *aesp = st; + + return err; +} + + +void aes_set_iv(struct aes *aes, const uint8_t iv[AES_BLOCK_SIZE]) +{ + if (!aes) + return; + + if (iv) + memcpy(aes->iv, iv, sizeof(aes->iv)); +} + + +int aes_encr(struct aes *aes, uint8_t *out, const uint8_t *in, size_t len) +{ + unsigned char ec[AES_BLOCK_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + unsigned int num = 0; + + if (!aes || !out || !in || !len) + return EINVAL; + + AES_ctr128_encrypt(in, out, len, &aes->key, aes->iv, ec, &num); + + return 0; +} + + +#endif /* EVP_CIPH_CTR_MODE */ + + +/* + * Common code: + */ + + +int aes_decr(struct aes *aes, uint8_t *out, const uint8_t *in, size_t len) +{ + return aes_encr(aes, out, in, len); +} diff --git a/src/aes/stub.c b/src/aes/stub.c new file mode 100644 index 0000000..1a1af52 --- /dev/null +++ b/src/aes/stub.c @@ -0,0 +1,47 @@ +/** + * @file aes/stub.c AES stub + * + * Copyright (C) 2010 Creytiv.com + */ +#include +#include + + +int aes_alloc(struct aes **stp, enum aes_mode mode, + const uint8_t *key, size_t key_bits, + const uint8_t iv[AES_BLOCK_SIZE]) +{ + (void)stp; + (void)mode; + (void)key; + (void)key_bits; + (void)iv; + return ENOSYS; +} + + +void aes_set_iv(struct aes *st, const uint8_t iv[AES_BLOCK_SIZE]) +{ + (void)st; + (void)iv; +} + + +int aes_encr(struct aes *st, uint8_t *out, const uint8_t *in, size_t len) +{ + (void)st; + (void)out; + (void)in; + (void)len; + return ENOSYS; +} + + +int aes_decr(struct aes *st, uint8_t *out, const uint8_t *in, size_t len) +{ + (void)st; + (void)out; + (void)in; + (void)len; + return ENOSYS; +}