Second iteration of the cryb-cipher API.

We now have separate encryption and decryption methods, and can process an arbitrary amount of plaintext or ciphertext per call, rounded down to the block size (if applicable).  For stream ciphers, we also have a keystream method which fills the provided buffer with an arbitrary amount of keystream (once again, rounded down if applicable).
This commit is contained in:
Dag-Erling Smørgrav 2017-03-16 15:09:34 +01:00
parent 5f4d82e99e
commit 1073dceed9
7 changed files with 110 additions and 28 deletions

View file

@ -43,7 +43,9 @@ CRYB_BEGIN
#define aes_cipher cryb_aes_cipher
#define aes_ctx cryb_aes_ctx
#define aes_init cryb_aes_init
#define aes_update cryb_aes_update
#define aes_keystream cryb_aes_keystream
#define aes_encrypt cryb_aes_encrypt
#define aes_decrypt cryb_aes_decrypt
#define aes_finish cryb_aes_finish
extern cipher_algorithm aes128_cipher;
@ -56,8 +58,10 @@ typedef struct {
uint32_t rk[68];
} aes_ctx;
void aes_init(aes_ctx *, cipher_mode, const uint8_t *, size_t);
void aes_update(aes_ctx *, const void *, size_t, void *);
void aes_init(aes_ctx *, cipher_mode mode, const uint8_t *, size_t);
size_t aes_keystream(aes_ctx *, uint8_t *, size_t);
size_t aes_encrypt(aes_ctx *, const void *, uint8_t *, size_t);
size_t aes_decrypt(aes_ctx *, const uint8_t *, void *, size_t);
void aes_finish(aes_ctx *);
CRYB_END

View file

@ -40,7 +40,9 @@ const char *cryb_cipher_version(void);
#define cipher_ctx cryb_cipher_ctx
#define cipher_init_func cryb_cipher_init_func
#define cipher_update_func cryb_cipher_update_func
#define cipher_keystream_func cryb_cipher_keystream_func
#define cipher_encrypt_func cryb_cipher_encrypt_func
#define cipher_decrypt_func cryb_cipher_decrypt_func
#define cipher_finish_func cryb_cipher_finish_func
#define cipher_algorithm cryb_cipher_algorithm
@ -51,7 +53,9 @@ typedef enum {
typedef void cipher_ctx;
typedef void (*cipher_init_func)(cipher_ctx *, cipher_mode, const uint8_t *, size_t);
typedef void (*cipher_update_func)(cipher_ctx *, const void *, size_t, void *);
typedef void (*cipher_keystream_func)(cipher_ctx *, uint8_t *, size_t);
typedef void (*cipher_encrypt_func)(cipher_ctx *, const void *, uint8_t *, size_t);
typedef void (*cipher_decrypt_func)(cipher_ctx *, const uint8_t *, void *, size_t);
typedef void (*cipher_finish_func)(cipher_ctx *);
typedef struct {
@ -59,9 +63,11 @@ typedef struct {
size_t contextlen; /* size of context structure */
size_t blocklen; /* block length */
size_t keylen; /* key length */
cipher_init_func init; /* initialization method */
cipher_update_func update; /* {enc,dec}ryption method */
cipher_finish_func finish; /* finalization method */
cipher_init_func init; /* initialize */
cipher_keystream_func keystream; /* generate keystream */
cipher_encrypt_func encrypt; /* encrypt */
cipher_decrypt_func decrypt; /* decrypt */
cipher_finish_func finish; /* finalize */
} cipher_algorithm;
#define get_cipher_algorithm cryb_get_cipher_algorithm
@ -70,8 +76,12 @@ const cipher_algorithm *get_cipher_algorithm(const char *);
#define cipher_init(alg, ctx, mode, key, keylen) \
(alg)->init((ctx), (mode), (key), (keylen))
#define cipher_update(alg, ctx, in, len, out) \
(alg)->update((ctx), (in), (len), (out))
#define cipher_keystream(alg, ctx, out, len) \
(alg)->keystream((ctx), (out), (len))
#define cipher_encrypt(alg, ctx, in, out, len) \
(alg)->encrypt((ctx), (in), (out), (len))
#define cipher_decrypt(alg, ctx, in, out, len) \
(alg)->decrypt((ctx), (in), (out), (len))
#define cipher_finish(alg, ctx) \
(alg)->finish((ctx))

View file

@ -41,7 +41,9 @@ CRYB_BEGIN
#define rc4_cipher cryb_rc4_cipher
#define rc4_ctx cryb_rc4_ctx
#define rc4_init cryb_rc4_init
#define rc4_update cryb_rc4_update
#define rc4_keystream cryb_rc4_keystream
#define rc4_encrypt cryb_rc4_encrypt
#define rc4_decrypt cryb_rc4_decrypt
#define rc4_finish cryb_rc4_finish
extern cipher_algorithm rc4_cipher;
@ -50,8 +52,10 @@ typedef struct {
uint8_t s[256], i, j;
} rc4_ctx;
void rc4_init(rc4_ctx *, cipher_mode, const uint8_t *, size_t);
void rc4_update(rc4_ctx *, const void *, size_t, void *);
void rc4_init(rc4_ctx *, cipher_mode mode, const uint8_t *, size_t);
size_t rc4_keystream(rc4_ctx *, uint8_t *, size_t);
size_t rc4_encrypt(rc4_ctx *, const void *, uint8_t *, size_t);
size_t rc4_decrypt(rc4_ctx *, const uint8_t *, void *, size_t);
void rc4_finish(rc4_ctx *);
CRYB_END

View file

@ -597,6 +597,30 @@ aes_update(aes_ctx *ctx, const void *in, size_t len, void *out)
aes_enc(ctx, in, out);
}
size_t
aes_encrypt(aes_ctx *ctx, const void *vpt, uint8_t *ct, size_t len)
{
const uint8_t *pt = vpt;
unsigned int i;
len -= len % AES_BLOCK_LEN;
for (i = 0; i < len; i += AES_BLOCK_LEN)
aes_enc(ctx, pt + i, ct + i);
return (len);
}
size_t
aes_decrypt(aes_ctx *ctx, const uint8_t *ct, void *vpt, size_t len)
{
uint8_t *pt = vpt;
unsigned int i;
len -= len % AES_BLOCK_LEN;
for (i = 0; i < len; i += AES_BLOCK_LEN)
aes_dec(ctx, ct + i, pt + i);
return (len);
}
void
aes_finish(aes_ctx *ctx)
{
@ -610,7 +634,8 @@ cipher_algorithm aes128_cipher = {
.blocklen = AES_BLOCK_LEN,
.keylen = 128 / 8,
.init = (cipher_init_func)aes_init,
.update = (cipher_update_func)aes_update,
.encrypt = (cipher_encrypt_func)aes_encrypt,
.decrypt = (cipher_decrypt_func)aes_decrypt,
.finish = (cipher_finish_func)aes_finish,
};
@ -620,7 +645,8 @@ cipher_algorithm aes192_cipher = {
.blocklen = AES_BLOCK_LEN,
.keylen = 192 / 8,
.init = (cipher_init_func)aes_init,
.update = (cipher_update_func)aes_update,
.encrypt = (cipher_encrypt_func)aes_encrypt,
.decrypt = (cipher_decrypt_func)aes_decrypt,
.finish = (cipher_finish_func)aes_finish,
};
@ -630,6 +656,7 @@ cipher_algorithm aes256_cipher = {
.blocklen = AES_BLOCK_LEN,
.keylen = 256 / 8,
.init = (cipher_init_func)aes_init,
.update = (cipher_update_func)aes_update,
.encrypt = (cipher_encrypt_func)aes_encrypt,
.decrypt = (cipher_decrypt_func)aes_decrypt,
.finish = (cipher_finish_func)aes_finish,
};

View file

@ -34,6 +34,7 @@
#include <cryb/bitwise.h>
#include <cryb/endian.h>
#include <cryb/memset_s.h>
#include <cryb/rc4.h>
@ -55,12 +56,30 @@ rc4_init(rc4_ctx *ctx, cipher_mode mode, const uint8_t *key, size_t keylen)
}
}
void
rc4_update(rc4_ctx *ctx, const void *in, size_t len, void *out)
size_t
rc4_keystream(rc4_ctx *ctx, uint8_t *ks, size_t len)
{
const uint8_t *is = in;
uint8_t t, k, *os = out;
unsigned int i;
uint8_t t;
for (i = 0; i < len; ++i) {
ctx->i = ctx->i + 1;
ctx->j = ctx->j + ctx->s[ctx->i];
t = ctx->s[ctx->i];
ctx->s[ctx->i] = ctx->s[ctx->j];
ctx->s[ctx->j] = t;
t = ctx->s[ctx->i] + ctx->s[ctx->j];
*ks++ = ctx->s[t];
}
return (len);
}
size_t
rc4_encrypt(rc4_ctx *ctx, const void *vpt, uint8_t *ct, size_t len)
{
const uint8_t *pt = vpt;
unsigned int i;
uint8_t t, k;
for (i = 0; i < len; ++i) {
ctx->i = ctx->i + 1;
@ -70,15 +89,23 @@ rc4_update(rc4_ctx *ctx, const void *in, size_t len, void *out)
ctx->s[ctx->j] = t;
t = ctx->s[ctx->i] + ctx->s[ctx->j];
k = ctx->s[t];
*os++ = *is++ ^ k;
*ct++ = *pt++ ^ k;
}
return (len);
}
size_t
rc4_decrypt(rc4_ctx *ctx, const uint8_t *in, void *out, size_t len)
{
return (rc4_encrypt(ctx, in, out, len));
}
void
rc4_finish(rc4_ctx *ctx)
{
memset(ctx, 0, sizeof *ctx);
memset_s(ctx, 0, sizeof *ctx, sizeof *ctx);
}
cipher_algorithm rc4_cipher = {
@ -87,6 +114,8 @@ cipher_algorithm rc4_cipher = {
.blocklen = 1,
.keylen = 0,
.init = (cipher_init_func)rc4_init,
.update = (cipher_update_func)rc4_update,
.keystream = (cipher_keystream_func)rc4_keystream,
.encrypt = (cipher_encrypt_func)rc4_encrypt,
.decrypt = (cipher_decrypt_func)rc4_decrypt,
.finish = (cipher_finish_func)rc4_finish,
};

View file

@ -113,12 +113,16 @@ t_aes_enc(char **desc, void *arg)
struct t_case *t = arg;
uint8_t out[AES_BLOCK_LEN];
aes_ctx ctx;
size_t len;
int ret;
(void)asprintf(desc, "%s (encrypt)", t->desc);
aes_init(&ctx, CIPHER_MODE_ENCRYPT, t->key, t->keylen / 8);
aes_update(&ctx, t->ptext, AES_BLOCK_LEN, out);
len = aes_encrypt(&ctx, t->ptext, out, AES_BLOCK_LEN);
aes_finish(&ctx);
return (t_compare_mem(t->ctext, out, AES_BLOCK_LEN));
ret = t_compare_sz(AES_BLOCK_LEN, len) &
t_compare_mem(t->ctext, out, AES_BLOCK_LEN);
return (ret);
}
static int
@ -127,12 +131,16 @@ t_aes_dec(char **desc, void *arg)
struct t_case *t = arg;
uint8_t out[AES_BLOCK_LEN];
aes_ctx ctx;
size_t len;
int ret;
(void)asprintf(desc, "%s (decrypt)", t->desc);
aes_init(&ctx, CIPHER_MODE_DECRYPT, t->key, t->keylen / 8);
aes_update(&ctx, t->ctext, AES_BLOCK_LEN, out);
len = aes_decrypt(&ctx, t->ctext, out, AES_BLOCK_LEN);
aes_finish(&ctx);
return (t_compare_mem(t->ptext, out, AES_BLOCK_LEN));
ret = t_compare_sz(AES_BLOCK_LEN, len) &
t_compare_mem(t->ptext, out, AES_BLOCK_LEN);
return (ret);
}

View file

@ -1975,7 +1975,7 @@ t_rc4(char **desc CRYB_UNUSED, void *arg)
rc4_init(&ctx, CIPHER_MODE_ENCRYPT, t->key, t->keylen);
for (i = offset = 0; i < 18; ++i) {
do {
rc4_update(&ctx, t_zero, 16, out);
rc4_encrypt(&ctx, t_zero, out, 16);
offset += 16;
} while (offset <= t->out[i].offset);
ret &= t_compare_mem(t->out[i].bytes, out, 16);