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

Add GCM IV generator. Add some FIPS restrictions to GCM. Update fips_gcmtest.

上级 632d83f0
......@@ -4,6 +4,10 @@
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
*) Add some FIPS mode restrictions to GCM. Add internal IV generator.
Update fips_gcmtest to use IV generator.
[Steve Henson]
*) 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
......
......@@ -59,6 +59,7 @@
#include <openssl/aes.h>
#include "evp_locl.h"
#include <openssl/modes.h>
#include <openssl/rand.h>
static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
......@@ -197,11 +198,15 @@ typedef struct
int iv_set;
/* Pointer to GCM128_CTX: FIXME actual structure later */
GCM128_CONTEXT *gcm;
/* Temporary IV store */
unsigned char *iv;
/* IV length */
int ivlen;
/* Tag to verify */
unsigned char tag[16];
int taglen;
/* It is OK to generate IVs */
int iv_gen;
} EVP_AES_GCM_CTX;
static int aes_gcm_cleanup(EVP_CIPHER_CTX *c)
......@@ -209,9 +214,25 @@ 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);
if (gctx->iv != c->iv)
OPENSSL_free(gctx->iv);
return 1;
}
/* increment counter (64-bit int) by 1 */
static void ctr64_inc(unsigned char *counter) {
int n=8;
unsigned char c;
do {
--n;
c = counter[n];
++c;
counter[n] = c;
if (c) return;
} while (n);
}
static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
EVP_AES_GCM_CTX *gctx = c->cipher_data;
......@@ -222,12 +243,28 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
gctx->key_set = 0;
gctx->iv_set = 0;
gctx->ivlen = c->cipher->iv_len;
gctx->iv = c->iv;
gctx->taglen = -1;
gctx->iv_gen = 0;
return 1;
case EVP_CTRL_GCM_SET_IVLEN:
if (arg <= 0)
return 0;
#ifdef OPENSSL_FIPS
if (FIPS_mode() && !(c->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW)
&& arg < 12)
return 0;
#endif
/* Allocate memory for IV if needed */
if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen))
{
if (gctx->iv != c->iv)
OPENSSL_free(gctx->iv);
gctx->iv = OPENSSL_malloc(arg);
if (!gctx->iv)
return 0;
}
gctx->ivlen = arg;
return 1;
......@@ -244,6 +281,39 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
memcpy(ptr, gctx->tag, arg);
return 1;
case EVP_CTRL_GCM_SET_IV_FIXED:
/* Special case: -1 length restores whole IV */
if (arg == -1)
{
memcpy(gctx->iv, ptr, gctx->ivlen);
gctx->iv_gen = 1;
return 1;
}
/* Fixed field must be at least 4 bytes and invocation field
* at least 8.
*/
if ((arg < 4) || (gctx->ivlen - arg) < 8)
return 0;
if (arg)
memcpy(gctx->iv, ptr, arg);
if (RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
return 0;
gctx->iv_gen = 1;
return 1;
case EVP_CTRL_GCM_IV_GEN:
if (gctx->iv_gen == 0 || gctx->key_set == 0)
return 0;
CRYPTO_gcm128_setiv(gctx->gcm, gctx->iv, gctx->ivlen);
memcpy(ptr, gctx->iv, gctx->ivlen);
/* Invocation field will be at least 8 bytes in size and
* so no need to check wrap around or increment more than
* last 8 bytes.
*/
ctr64_inc(gctx->iv + gctx->ivlen - 8);
gctx->iv_set = 1;
return 1;
default:
return -1;
......@@ -272,7 +342,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
* saved IV.
*/
if (iv == NULL && gctx->iv_set)
iv = ctx->iv;
iv = gctx->iv;
if (iv)
{
CRYPTO_gcm128_setiv(gctx->gcm, iv, gctx->ivlen);
......@@ -286,16 +356,9 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
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);
}
memcpy(gctx->iv, iv, gctx->ivlen);
gctx->iv_set = 1;
gctx->iv_gen = 0;
}
return 1;
}
......
......@@ -374,6 +374,8 @@ struct evp_cipher_st
#define EVP_CTRL_GCM_SET_IVLEN 0x9
#define EVP_CTRL_GCM_GET_TAG 0x10
#define EVP_CTRL_GCM_SET_TAG 0x11
#define EVP_CTRL_GCM_SET_IV_FIXED 0x12
#define EVP_CTRL_GCM_IV_GEN 0x13
typedef struct evp_cipher_info_st
{
......
......@@ -172,13 +172,31 @@ static void gcmtest(int encrypt)
exit(1);
}
}
/* FIXME: need intenal IV generation */
if (encrypt && iv && pt && aad)
if (encrypt && pt && aad && (iv || encrypt==1))
{
tag = OPENSSL_malloc(taglen);
EVP_CipherInit_ex(&ctx, gcm, NULL, NULL, NULL, 1);
EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, ivlen, 0);
EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, 1);
if (encrypt == 1)
{
static unsigned char iv_fixed[4] = {1,2,3,4};
if (!iv)
iv = OPENSSL_malloc(ivlen);
EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1);
EVP_CIPHER_CTX_ctrl(&ctx,
EVP_CTRL_GCM_SET_IV_FIXED,
4, iv_fixed);
if (!EVP_CIPHER_CTX_ctrl(&ctx,
EVP_CTRL_GCM_IV_GEN, 0, iv))
{
fprintf(stderr, "IV gen error\n");
exit(1);
}
OutputValue("IV", iv, ivlen, stdout, 0);
}
else
EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, 1);
if (aadlen)
EVP_Cipher(&ctx, NULL, aad, aadlen);
......@@ -254,6 +272,8 @@ int main(int argc,char **argv)
exit(1);
if(!strcmp(argv[1],"-encrypt"))
encrypt = 1;
else if(!strcmp(argv[1],"-encryptIVext"))
encrypt = 2;
else if(!strcmp(argv[1],"-decrypt"))
encrypt = 0;
else
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册