提交 bdaa5415 编写于 作者: D Dr. Stephen Henson

Initial *very* experimental EVP support for AES-GCM. Note: probably very

broken and subject to change.
上级 fd3dbc1d
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册