Loading CHANGES +4 −0 Original line number Diff line number Diff line Loading @@ -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 Loading crypto/evp/e_aes.c +73 −10 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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) Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading @@ -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; } Loading crypto/evp/evp.h +2 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading fips/aes/fips_gcmtest.c +23 −3 Original line number Diff line number Diff line Loading @@ -172,14 +172,32 @@ 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); 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); if (ptlen) Loading Loading @@ -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 Loading Loading
CHANGES +4 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
crypto/evp/e_aes.c +73 −10 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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) Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading @@ -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; } Loading
crypto/evp/evp.h +2 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
fips/aes/fips_gcmtest.c +23 −3 Original line number Diff line number Diff line Loading @@ -172,14 +172,32 @@ 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); 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); if (ptlen) Loading Loading @@ -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 Loading