Initial *very* experimental EVP support for AES-GCM. Note: probably very
broken and subject to change.
This commit is contained in:
parent
fd3dbc1dbf
commit
bdaa54155c
9
CHANGES
9
CHANGES
@ -4,6 +4,15 @@
|
||||
|
||||
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
|
||||
|
||||
*) Initial, experimental EVP support for AES-GCM. AAD can be input by
|
||||
setting output buffer to NULL. The *Final function must be
|
||||
called although it will not retrieve any additional data. The tag
|
||||
can be set or retrieved with a ctrl. The IV length is by default 12
|
||||
bytes (96 bits) but can be set to an alternative value. If the IV
|
||||
length exceeds the maximum IV length (currently 16 bytes) it cannot be
|
||||
set before the key.
|
||||
[Steve Henson]
|
||||
|
||||
*) New flag in ciphers: EVP_CIPH_FLAG_CUSTOM_CIPHER. This means the
|
||||
underlying do_cipher function handles all cipher semantics itself
|
||||
including padding and finalisation. This is useful if (for example)
|
||||
|
@ -57,8 +57,8 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/modes.h>
|
||||
#include "evp_locl.h"
|
||||
#include <openssl/modes.h>
|
||||
|
||||
static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc);
|
||||
@ -187,4 +187,212 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* AES key schedule to use */
|
||||
AES_KEY ks;
|
||||
/* Set if key initialised */
|
||||
int key_set;
|
||||
/* Set if an iv is set */
|
||||
int iv_set;
|
||||
/* Pointer to GCM128_CTX: FIXME actual structure later */
|
||||
GCM128_CONTEXT *gcm;
|
||||
/* IV length */
|
||||
int ivlen;
|
||||
/* Tag to verify */
|
||||
unsigned char tag[16];
|
||||
int taglen;
|
||||
} EVP_AES_GCM_CTX;
|
||||
|
||||
static int aes_gcm_cleanup(EVP_CIPHER_CTX *c)
|
||||
{
|
||||
EVP_AES_GCM_CTX *gctx = c->cipher_data;
|
||||
if (gctx->gcm)
|
||||
CRYPTO_gcm128_release(gctx->gcm);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
|
||||
{
|
||||
EVP_AES_GCM_CTX *gctx = c->cipher_data;
|
||||
switch (type)
|
||||
{
|
||||
case EVP_CTRL_INIT:
|
||||
gctx->gcm = NULL;
|
||||
gctx->key_set = 0;
|
||||
gctx->iv_set = 0;
|
||||
gctx->ivlen = c->cipher->iv_len;
|
||||
gctx->taglen = -1;
|
||||
return 1;
|
||||
|
||||
case EVP_CTRL_GCM_SET_IVLEN:
|
||||
if (arg <= 0)
|
||||
return 0;
|
||||
gctx->ivlen = arg;
|
||||
return 1;
|
||||
|
||||
case EVP_CTRL_GCM_SET_TAG:
|
||||
if (arg <= 0 || arg > 16 || c->encrypt)
|
||||
return 0;
|
||||
memcpy(gctx->tag, ptr, arg);
|
||||
gctx->taglen = arg;
|
||||
return 1;
|
||||
|
||||
case EVP_CTRL_GCM_GET_TAG:
|
||||
if (arg <= 0 || arg > 16 || !c->encrypt || gctx->taglen < 0)
|
||||
return 0;
|
||||
memcpy(ptr, gctx->tag, arg);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc)
|
||||
{
|
||||
EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
|
||||
if (!iv && !key)
|
||||
return 1;
|
||||
if (key)
|
||||
{
|
||||
AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks);
|
||||
if (!gctx->gcm)
|
||||
{
|
||||
gctx->gcm =
|
||||
CRYPTO_gcm128_new(&gctx->ks, (block128_f)AES_encrypt);
|
||||
if (!gctx->gcm)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
CRYPTO_gcm128_init(gctx->gcm, &gctx->ks, (block128_f)AES_encrypt);
|
||||
/* If we have an iv can set it directly, otherwise use
|
||||
* saved IV.
|
||||
*/
|
||||
if (iv == NULL && gctx->iv_set)
|
||||
iv = ctx->iv;
|
||||
if (iv)
|
||||
{
|
||||
CRYPTO_gcm128_setiv(gctx->gcm, iv, gctx->ivlen);
|
||||
gctx->iv_set = 1;
|
||||
}
|
||||
gctx->key_set = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If key set use IV, otherwise copy */
|
||||
if (gctx->key_set)
|
||||
CRYPTO_gcm128_setiv(gctx->gcm, iv, gctx->ivlen);
|
||||
else
|
||||
{
|
||||
/* If IV is too large for EVP_CIPHER_CTX buffer
|
||||
* return an error. This can be avoided by either
|
||||
* setting the key first or key and iv simultaneously.
|
||||
*/
|
||||
if (gctx->ivlen > EVP_MAX_IV_LENGTH)
|
||||
return 0;
|
||||
memcpy(ctx->iv, iv, gctx->ivlen);
|
||||
}
|
||||
gctx->iv_set = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aes_gcm(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
|
||||
/* If not set up, return error */
|
||||
if (!gctx->iv_set && !gctx->key_set)
|
||||
return -1;
|
||||
if (!ctx->encrypt && gctx->taglen < 0)
|
||||
return -1;
|
||||
if (in)
|
||||
{
|
||||
if (out == NULL)
|
||||
CRYPTO_gcm128_aad(gctx->gcm, in, len);
|
||||
else if (ctx->encrypt)
|
||||
CRYPTO_gcm128_encrypt(gctx->gcm, in, out, len);
|
||||
else
|
||||
CRYPTO_gcm128_decrypt(gctx->gcm, in, out, len);
|
||||
return len;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ctx->encrypt)
|
||||
{
|
||||
if (CRYPTO_gcm128_finish(gctx->gcm,
|
||||
gctx->tag, gctx->taglen) != 0)
|
||||
return -1;
|
||||
gctx->iv_set = 0;
|
||||
return 0;
|
||||
}
|
||||
CRYPTO_gcm128_tag(gctx->gcm, gctx->tag, 16);
|
||||
gctx->taglen = 16;
|
||||
/* Don't reuse the IV */
|
||||
gctx->iv_set = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const EVP_CIPHER aes_128_gcm_cipher=
|
||||
{
|
||||
NID_aes_128_gcm,1,16,12,
|
||||
EVP_CIPH_GCM_MODE|EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_DEFAULT_ASN1
|
||||
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER
|
||||
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT,
|
||||
aes_gcm_init_key,
|
||||
aes_gcm,
|
||||
aes_gcm_cleanup,
|
||||
sizeof(EVP_AES_GCM_CTX),
|
||||
NULL,
|
||||
NULL,
|
||||
aes_gcm_ctrl,
|
||||
NULL
|
||||
};
|
||||
|
||||
const EVP_CIPHER *EVP_aes_128_gcm (void)
|
||||
{ return &aes_128_gcm_cipher; }
|
||||
|
||||
static const EVP_CIPHER aes_192_gcm_cipher=
|
||||
{
|
||||
NID_aes_128_gcm,1,24,12,
|
||||
EVP_CIPH_GCM_MODE|EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_DEFAULT_ASN1
|
||||
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER
|
||||
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT,
|
||||
aes_gcm_init_key,
|
||||
aes_gcm,
|
||||
aes_gcm_cleanup,
|
||||
sizeof(EVP_AES_GCM_CTX),
|
||||
NULL,
|
||||
NULL,
|
||||
aes_gcm_ctrl,
|
||||
NULL
|
||||
};
|
||||
|
||||
const EVP_CIPHER *EVP_aes_192_gcm (void)
|
||||
{ return &aes_192_gcm_cipher; }
|
||||
|
||||
static const EVP_CIPHER aes_256_gcm_cipher=
|
||||
{
|
||||
NID_aes_128_gcm,1,32,12,
|
||||
EVP_CIPH_GCM_MODE|EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_DEFAULT_ASN1
|
||||
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER
|
||||
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT,
|
||||
aes_gcm_init_key,
|
||||
aes_gcm,
|
||||
aes_gcm_cleanup,
|
||||
sizeof(EVP_AES_GCM_CTX),
|
||||
NULL,
|
||||
NULL,
|
||||
aes_gcm_ctrl,
|
||||
NULL
|
||||
};
|
||||
|
||||
const EVP_CIPHER *EVP_aes_256_gcm (void)
|
||||
{ return &aes_256_gcm_cipher; }
|
||||
|
||||
#endif
|
||||
|
@ -329,6 +329,7 @@ struct evp_cipher_st
|
||||
#define EVP_CIPH_CFB_MODE 0x3
|
||||
#define EVP_CIPH_OFB_MODE 0x4
|
||||
#define EVP_CIPH_CTR_MODE 0x5
|
||||
#define EVP_CIPH_GCM_MODE 0x6
|
||||
#define EVP_CIPH_MODE 0xF0007
|
||||
/* Set if variable length cipher */
|
||||
#define EVP_CIPH_VARIABLE_LENGTH 0x8
|
||||
@ -370,6 +371,9 @@ struct evp_cipher_st
|
||||
#define EVP_CTRL_RAND_KEY 0x6
|
||||
#define EVP_CTRL_PBE_PRF_NID 0x7
|
||||
#define EVP_CTRL_COPY 0x8
|
||||
#define EVP_CTRL_GCM_SET_IVLEN 0x9
|
||||
#define EVP_CTRL_GCM_GET_TAG 0x10
|
||||
#define EVP_CTRL_GCM_SET_TAG 0x11
|
||||
|
||||
typedef struct evp_cipher_info_st
|
||||
{
|
||||
@ -770,6 +774,7 @@ const EVP_CIPHER *EVP_aes_128_cfb128(void);
|
||||
# define EVP_aes_128_cfb EVP_aes_128_cfb128
|
||||
const EVP_CIPHER *EVP_aes_128_ofb(void);
|
||||
const EVP_CIPHER *EVP_aes_128_ctr(void);
|
||||
const EVP_CIPHER *EVP_aes_128_gcm(void);
|
||||
const EVP_CIPHER *EVP_aes_192_ecb(void);
|
||||
const EVP_CIPHER *EVP_aes_192_cbc(void);
|
||||
const EVP_CIPHER *EVP_aes_192_cfb1(void);
|
||||
@ -778,6 +783,7 @@ const EVP_CIPHER *EVP_aes_192_cfb128(void);
|
||||
# define EVP_aes_192_cfb EVP_aes_192_cfb128
|
||||
const EVP_CIPHER *EVP_aes_192_ofb(void);
|
||||
const EVP_CIPHER *EVP_aes_192_ctr(void);
|
||||
const EVP_CIPHER *EVP_aes_192_gcm(void);
|
||||
const EVP_CIPHER *EVP_aes_256_ecb(void);
|
||||
const EVP_CIPHER *EVP_aes_256_cbc(void);
|
||||
const EVP_CIPHER *EVP_aes_256_cfb1(void);
|
||||
@ -786,6 +792,7 @@ const EVP_CIPHER *EVP_aes_256_cfb128(void);
|
||||
# define EVP_aes_256_cfb EVP_aes_256_cfb128
|
||||
const EVP_CIPHER *EVP_aes_256_ofb(void);
|
||||
const EVP_CIPHER *EVP_aes_256_ctr(void);
|
||||
const EVP_CIPHER *EVP_aes_256_gcm(void);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CAMELLIA
|
||||
const EVP_CIPHER *EVP_camellia_128_ecb(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user