Add GCM IV generator. Add some FIPS restrictions to GCM. Update fips_gcmtest.
This commit is contained in:
parent
632d83f0a3
commit
b3d8022edd
4
CHANGES
4
CHANGES
@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
|
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
|
*) Initial, experimental EVP support for AES-GCM. AAD can be input by
|
||||||
setting output buffer to NULL. The *Final function must be
|
setting output buffer to NULL. The *Final function must be
|
||||||
called although it will not retrieve any additional data. The tag
|
called although it will not retrieve any additional data. The tag
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
#include "evp_locl.h"
|
#include "evp_locl.h"
|
||||||
#include <openssl/modes.h>
|
#include <openssl/modes.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||||
const unsigned char *iv, int enc);
|
const unsigned char *iv, int enc);
|
||||||
@ -197,11 +198,15 @@ typedef struct
|
|||||||
int iv_set;
|
int iv_set;
|
||||||
/* Pointer to GCM128_CTX: FIXME actual structure later */
|
/* Pointer to GCM128_CTX: FIXME actual structure later */
|
||||||
GCM128_CONTEXT *gcm;
|
GCM128_CONTEXT *gcm;
|
||||||
|
/* Temporary IV store */
|
||||||
|
unsigned char *iv;
|
||||||
/* IV length */
|
/* IV length */
|
||||||
int ivlen;
|
int ivlen;
|
||||||
/* Tag to verify */
|
/* Tag to verify */
|
||||||
unsigned char tag[16];
|
unsigned char tag[16];
|
||||||
int taglen;
|
int taglen;
|
||||||
|
/* It is OK to generate IVs */
|
||||||
|
int iv_gen;
|
||||||
} EVP_AES_GCM_CTX;
|
} EVP_AES_GCM_CTX;
|
||||||
|
|
||||||
static int aes_gcm_cleanup(EVP_CIPHER_CTX *c)
|
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;
|
EVP_AES_GCM_CTX *gctx = c->cipher_data;
|
||||||
if (gctx->gcm)
|
if (gctx->gcm)
|
||||||
CRYPTO_gcm128_release(gctx->gcm);
|
CRYPTO_gcm128_release(gctx->gcm);
|
||||||
|
if (gctx->iv != c->iv)
|
||||||
|
OPENSSL_free(gctx->iv);
|
||||||
return 1;
|
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)
|
static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
|
||||||
{
|
{
|
||||||
EVP_AES_GCM_CTX *gctx = c->cipher_data;
|
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->key_set = 0;
|
||||||
gctx->iv_set = 0;
|
gctx->iv_set = 0;
|
||||||
gctx->ivlen = c->cipher->iv_len;
|
gctx->ivlen = c->cipher->iv_len;
|
||||||
|
gctx->iv = c->iv;
|
||||||
gctx->taglen = -1;
|
gctx->taglen = -1;
|
||||||
|
gctx->iv_gen = 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case EVP_CTRL_GCM_SET_IVLEN:
|
case EVP_CTRL_GCM_SET_IVLEN:
|
||||||
if (arg <= 0)
|
if (arg <= 0)
|
||||||
return 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;
|
gctx->ivlen = arg;
|
||||||
return 1;
|
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);
|
memcpy(ptr, gctx->tag, arg);
|
||||||
return 1;
|
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:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -272,7 +342,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
|||||||
* saved IV.
|
* saved IV.
|
||||||
*/
|
*/
|
||||||
if (iv == NULL && gctx->iv_set)
|
if (iv == NULL && gctx->iv_set)
|
||||||
iv = ctx->iv;
|
iv = gctx->iv;
|
||||||
if (iv)
|
if (iv)
|
||||||
{
|
{
|
||||||
CRYPTO_gcm128_setiv(gctx->gcm, iv, gctx->ivlen);
|
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)
|
if (gctx->key_set)
|
||||||
CRYPTO_gcm128_setiv(gctx->gcm, iv, gctx->ivlen);
|
CRYPTO_gcm128_setiv(gctx->gcm, iv, gctx->ivlen);
|
||||||
else
|
else
|
||||||
{
|
memcpy(gctx->iv, iv, gctx->ivlen);
|
||||||
/* 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;
|
gctx->iv_set = 1;
|
||||||
|
gctx->iv_gen = 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -374,6 +374,8 @@ struct evp_cipher_st
|
|||||||
#define EVP_CTRL_GCM_SET_IVLEN 0x9
|
#define EVP_CTRL_GCM_SET_IVLEN 0x9
|
||||||
#define EVP_CTRL_GCM_GET_TAG 0x10
|
#define EVP_CTRL_GCM_GET_TAG 0x10
|
||||||
#define EVP_CTRL_GCM_SET_TAG 0x11
|
#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
|
typedef struct evp_cipher_info_st
|
||||||
{
|
{
|
||||||
|
@ -172,13 +172,31 @@ static void gcmtest(int encrypt)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* FIXME: need intenal IV generation */
|
if (encrypt && pt && aad && (iv || encrypt==1))
|
||||||
if (encrypt && iv && pt && aad)
|
|
||||||
{
|
{
|
||||||
tag = OPENSSL_malloc(taglen);
|
tag = OPENSSL_malloc(taglen);
|
||||||
EVP_CipherInit_ex(&ctx, gcm, NULL, NULL, NULL, 1);
|
EVP_CipherInit_ex(&ctx, gcm, NULL, NULL, NULL, 1);
|
||||||
EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, ivlen, 0);
|
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)
|
if (aadlen)
|
||||||
EVP_Cipher(&ctx, NULL, aad, aadlen);
|
EVP_Cipher(&ctx, NULL, aad, aadlen);
|
||||||
@ -254,6 +272,8 @@ int main(int argc,char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
if(!strcmp(argv[1],"-encrypt"))
|
if(!strcmp(argv[1],"-encrypt"))
|
||||||
encrypt = 1;
|
encrypt = 1;
|
||||||
|
else if(!strcmp(argv[1],"-encryptIVext"))
|
||||||
|
encrypt = 2;
|
||||||
else if(!strcmp(argv[1],"-decrypt"))
|
else if(!strcmp(argv[1],"-decrypt"))
|
||||||
encrypt = 0;
|
encrypt = 0;
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user