Backport GCM support from HEAD. Minimal support at present: no assembly
language optimisation. [original by Andy]
This commit is contained in:
parent
1acd042c85
commit
61cdb9f36a
@ -7,7 +7,7 @@ TOP= ..
|
||||
CC= cc
|
||||
INCLUDE= -I. -I$(TOP) -I../include $(ZLIB_INCLUDE)
|
||||
# INCLUDES targets sudbirs!
|
||||
INCLUDES= -I.. -I../.. -I../asn1 -I../evp -I../../include $(ZLIB_INCLUDE)
|
||||
INCLUDES= -I.. -I../.. -I../modes -I../asn1 -I../evp -I../../include $(ZLIB_INCLUDE)
|
||||
CFLAG= -g
|
||||
MAKEDEPPROG= makedepend
|
||||
MAKEDEPEND= $(TOP)/util/domd $(TOP) -MD $(MAKEDEPPROG)
|
||||
|
@ -167,6 +167,7 @@ void OpenSSL_add_all_ciphers(void)
|
||||
EVP_add_cipher(EVP_aes_128_cfb8());
|
||||
EVP_add_cipher(EVP_aes_128_ofb());
|
||||
EVP_add_cipher(EVP_aes_128_ctr());
|
||||
EVP_add_cipher(EVP_aes_128_gcm());
|
||||
EVP_add_cipher_alias(SN_aes_128_cbc,"AES128");
|
||||
EVP_add_cipher_alias(SN_aes_128_cbc,"aes128");
|
||||
EVP_add_cipher(EVP_aes_192_ecb());
|
||||
@ -176,6 +177,7 @@ void OpenSSL_add_all_ciphers(void)
|
||||
EVP_add_cipher(EVP_aes_192_cfb8());
|
||||
EVP_add_cipher(EVP_aes_192_ofb());
|
||||
EVP_add_cipher(EVP_aes_192_ctr());
|
||||
EVP_add_cipher(EVP_aes_192_gcm());
|
||||
EVP_add_cipher_alias(SN_aes_192_cbc,"AES192");
|
||||
EVP_add_cipher_alias(SN_aes_192_cbc,"aes192");
|
||||
EVP_add_cipher(EVP_aes_256_ecb());
|
||||
@ -185,6 +187,7 @@ void OpenSSL_add_all_ciphers(void)
|
||||
EVP_add_cipher(EVP_aes_256_cfb8());
|
||||
EVP_add_cipher(EVP_aes_256_ofb());
|
||||
EVP_add_cipher(EVP_aes_256_ctr());
|
||||
EVP_add_cipher(EVP_aes_256_gcm());
|
||||
EVP_add_cipher_alias(SN_aes_256_cbc,"AES256");
|
||||
EVP_add_cipher_alias(SN_aes_256_cbc,"aes256");
|
||||
#endif
|
||||
|
@ -55,7 +55,8 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/modes.h>
|
||||
#include <openssl/rand.h>
|
||||
#include "modes_lcl.h"
|
||||
#include "evp_locl.h"
|
||||
|
||||
#ifndef OPENSSL_FIPS
|
||||
@ -65,6 +66,19 @@ typedef struct
|
||||
AES_KEY ks;
|
||||
} EVP_AES_KEY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AES_KEY ks; /* AES key schedule to use */
|
||||
int key_set; /* Set if key initialised */
|
||||
int iv_set; /* Set if an iv is set */
|
||||
GCM128_CONTEXT gcm;
|
||||
unsigned char *iv; /* Temporary IV store */
|
||||
int ivlen; /* IV length */
|
||||
int taglen;
|
||||
int iv_gen; /* It is OK to generate IVs */
|
||||
int tls_aad_len; /* TLS AAD length */
|
||||
} EVP_AES_GCM_CTX;
|
||||
|
||||
#define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4))
|
||||
|
||||
#if defined(AES_ASM) && !defined(I386_ONLY) && ( \
|
||||
@ -383,5 +397,318 @@ BLOCK_CIPHER_generic_pack(NID_aes,128,0)
|
||||
BLOCK_CIPHER_generic_pack(NID_aes,192,0)
|
||||
BLOCK_CIPHER_generic_pack(NID_aes,256,0)
|
||||
|
||||
static int aes_gcm_cleanup(EVP_CIPHER_CTX *c)
|
||||
{
|
||||
EVP_AES_GCM_CTX *gctx = c->cipher_data;
|
||||
OPENSSL_cleanse(&gctx->gcm, sizeof(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;
|
||||
switch (type)
|
||||
{
|
||||
case EVP_CTRL_INIT:
|
||||
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;
|
||||
gctx->tls_aad_len = -1;
|
||||
return 1;
|
||||
|
||||
case EVP_CTRL_GCM_SET_IVLEN:
|
||||
if (arg <= 0)
|
||||
return 0;
|
||||
#ifdef OPENSSL_FIPS
|
||||
if (FIPS_module_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;
|
||||
|
||||
case EVP_CTRL_GCM_SET_TAG:
|
||||
if (arg <= 0 || arg > 16 || c->encrypt)
|
||||
return 0;
|
||||
memcpy(c->buf, 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, c->buf, 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 (c->encrypt &&
|
||||
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);
|
||||
if (arg <= 0 || arg > gctx->ivlen)
|
||||
arg = gctx->ivlen;
|
||||
memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
|
||||
/* 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;
|
||||
|
||||
case EVP_CTRL_GCM_SET_IV_INV:
|
||||
if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt)
|
||||
return 0;
|
||||
memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
|
||||
CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
|
||||
gctx->iv_set = 1;
|
||||
return 1;
|
||||
|
||||
case EVP_CTRL_AEAD_TLS1_AAD:
|
||||
/* Save the AAD for later use */
|
||||
if (arg != 13)
|
||||
return 0;
|
||||
memcpy(c->buf, ptr, arg);
|
||||
gctx->tls_aad_len = arg;
|
||||
{
|
||||
unsigned int len=c->buf[arg-2]<<8|c->buf[arg-1];
|
||||
/* Correct length for explicit IV */
|
||||
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
||||
/* If decrypting correct for tag too */
|
||||
if (!c->encrypt)
|
||||
len -= EVP_GCM_TLS_TAG_LEN;
|
||||
c->buf[arg-2] = len>>8;
|
||||
c->buf[arg-1] = len & 0xff;
|
||||
}
|
||||
/* Extra padding: tag appended to record */
|
||||
return EVP_GCM_TLS_TAG_LEN;
|
||||
|
||||
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);
|
||||
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 = gctx->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
|
||||
memcpy(gctx->iv, iv, gctx->ivlen);
|
||||
gctx->iv_set = 1;
|
||||
gctx->iv_gen = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handle TLS GCM packet format. This consists of the last portion of the IV
|
||||
* followed by the payload and finally the tag. On encrypt generate IV,
|
||||
* encrypt payload and write the tag. On verify retrieve IV, decrypt payload
|
||||
* and verify tag.
|
||||
*/
|
||||
|
||||
static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
const unsigned char *in, size_t len)
|
||||
{
|
||||
EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
|
||||
int rv = -1;
|
||||
/* Encrypt/decrypt must be performed in place */
|
||||
if (out != in)
|
||||
return -1;
|
||||
/* Set IV from start of buffer or generate IV and write to start
|
||||
* of buffer.
|
||||
*/
|
||||
if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ?
|
||||
EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV,
|
||||
EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
|
||||
goto err;
|
||||
/* Use saved AAD */
|
||||
if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len))
|
||||
goto err;
|
||||
/* Fix buffer and length to point to payload */
|
||||
in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
||||
out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
|
||||
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
|
||||
if (ctx->encrypt)
|
||||
{
|
||||
/* Encrypt payload */
|
||||
if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
|
||||
goto err;
|
||||
out += len;
|
||||
/* Finally write tag */
|
||||
CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN);
|
||||
rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Decrypt */
|
||||
if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
|
||||
goto err;
|
||||
/* Retrieve tag */
|
||||
CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf,
|
||||
EVP_GCM_TLS_TAG_LEN);
|
||||
/* If tag mismatch wipe buffer */
|
||||
if (memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN))
|
||||
{
|
||||
OPENSSL_cleanse(out, len);
|
||||
goto err;
|
||||
}
|
||||
rv = len;
|
||||
}
|
||||
|
||||
err:
|
||||
gctx->iv_set = 0;
|
||||
gctx->tls_aad_len = -1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int aes_gcm_cipher(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->key_set)
|
||||
return -1;
|
||||
|
||||
if (gctx->tls_aad_len >= 0)
|
||||
return aes_gcm_tls_cipher(ctx, out, in, len);
|
||||
|
||||
if (!gctx->iv_set)
|
||||
return -1;
|
||||
if (!ctx->encrypt && gctx->taglen < 0)
|
||||
return -1;
|
||||
if (in)
|
||||
{
|
||||
if (out == NULL)
|
||||
{
|
||||
if (CRYPTO_gcm128_aad(&gctx->gcm, in, len))
|
||||
return -1;
|
||||
}
|
||||
else if (ctx->encrypt)
|
||||
{
|
||||
if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
|
||||
return -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ctx->encrypt)
|
||||
{
|
||||
if (CRYPTO_gcm128_finish(&gctx->gcm,
|
||||
ctx->buf, gctx->taglen) != 0)
|
||||
return -1;
|
||||
gctx->iv_set = 0;
|
||||
return 0;
|
||||
}
|
||||
CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
|
||||
gctx->taglen = 16;
|
||||
/* Don't reuse the IV */
|
||||
gctx->iv_set = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
|
||||
static const EVP_CIPHER aes_##keylen##_##mode = { \
|
||||
nid##_##keylen##_##mode,blocksize, \
|
||||
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
|
||||
flags|EVP_CIPH_##MODE##_MODE, \
|
||||
aes_##mode##_init_key, \
|
||||
aes_##mode##_cipher, \
|
||||
aes_##mode##_cleanup, \
|
||||
sizeof(EVP_AES_##MODE##_CTX), \
|
||||
NULL,NULL,aes_##mode##_ctrl,NULL }; \
|
||||
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
|
||||
{ return &aes_##keylen##_##mode; }
|
||||
|
||||
#define CUSTOM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \
|
||||
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
|
||||
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT)
|
||||
|
||||
BLOCK_CIPHER_custom(NID_aes,128,1,12,gcm,GCM,
|
||||
EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
|
||||
BLOCK_CIPHER_custom(NID_aes,192,1,12,gcm,GCM,
|
||||
EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
|
||||
BLOCK_CIPHER_custom(NID_aes,256,1,12,gcm,GCM,
|
||||
EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -391,6 +391,16 @@ struct evp_cipher_st
|
||||
#define EVP_CTRL_AEAD_TLS1_AAD 0x16
|
||||
/* Used by composite AEAD ciphers, no-op in GCM, CCM... */
|
||||
#define EVP_CTRL_AEAD_SET_MAC_KEY 0x17
|
||||
/* Set the GCM invocation field, decrypt only */
|
||||
#define EVP_CTRL_GCM_SET_IV_INV 0x18
|
||||
|
||||
/* GCM TLS constants */
|
||||
/* Length of fixed part of IV derived from PRF */
|
||||
#define EVP_GCM_TLS_FIXED_IV_LEN 4
|
||||
/* Length of explicit part of IV part of TLS records */
|
||||
#define EVP_GCM_TLS_EXPLICIT_IV_LEN 8
|
||||
/* Length of tag for TLS */
|
||||
#define EVP_GCM_TLS_TAG_LEN 16
|
||||
|
||||
|
||||
typedef struct evp_cipher_info_st
|
||||
@ -776,9 +786,9 @@ 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);
|
||||
#ifdef OPENSSL_FIPS
|
||||
const EVP_CIPHER *EVP_aes_128_ccm(void);
|
||||
const EVP_CIPHER *EVP_aes_128_gcm(void);
|
||||
const EVP_CIPHER *EVP_aes_128_xts(void);
|
||||
#endif
|
||||
const EVP_CIPHER *EVP_aes_192_ecb(void);
|
||||
@ -789,9 +799,9 @@ 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);
|
||||
#ifdef OPENSSL_FIPS
|
||||
const EVP_CIPHER *EVP_aes_192_ccm(void);
|
||||
const EVP_CIPHER *EVP_aes_192_gcm(void);
|
||||
#endif
|
||||
const EVP_CIPHER *EVP_aes_256_ecb(void);
|
||||
const EVP_CIPHER *EVP_aes_256_cbc(void);
|
||||
@ -801,9 +811,9 @@ 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);
|
||||
#ifdef OPENSSL_FIPS
|
||||
const EVP_CIPHER *EVP_aes_256_ccm(void);
|
||||
const EVP_CIPHER *EVP_aes_256_gcm(void);
|
||||
const EVP_CIPHER *EVP_aes_256_xts(void);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -17,14 +17,14 @@ TEST=
|
||||
APPS=
|
||||
|
||||
LIB=$(TOP)/libcrypto.a
|
||||
LIBSRC= cbc128.c ctr128.c cts128.c cfb128.c ofb128.c
|
||||
LIBOBJ= cbc128.o ctr128.o cts128.o cfb128.o ofb128.o
|
||||
LIBSRC= cbc128.c ctr128.c cts128.c cfb128.c ofb128.c gcm128.c
|
||||
LIBOBJ= cbc128.o ctr128.o cts128.o cfb128.o ofb128.o gcm128.o
|
||||
|
||||
SRC= $(LIBSRC)
|
||||
|
||||
#EXHEADER= store.h str_compat.h
|
||||
EXHEADER= modes.h
|
||||
HEADER= $(EXHEADER)
|
||||
HEADER= modes_lcl.h $(EXHEADER)
|
||||
|
||||
ALL= $(GENERAL) $(SRC) $(HEADER)
|
||||
|
||||
|
1753
crypto/modes/gcm128.c
Normal file
1753
crypto/modes/gcm128.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -66,3 +66,28 @@ size_t CRYPTO_cts128_decrypt_block(const unsigned char *in, unsigned char *out,
|
||||
size_t CRYPTO_cts128_decrypt(const unsigned char *in, unsigned char *out,
|
||||
size_t len, const void *key,
|
||||
unsigned char ivec[16], cbc128_f cbc);
|
||||
|
||||
typedef struct gcm128_context GCM128_CONTEXT;
|
||||
|
||||
GCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block);
|
||||
void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx,void *key,block128_f block);
|
||||
void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv,
|
||||
size_t len);
|
||||
int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const unsigned char *aad,
|
||||
size_t len);
|
||||
int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
|
||||
const unsigned char *in, unsigned char *out,
|
||||
size_t len);
|
||||
int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
|
||||
const unsigned char *in, unsigned char *out,
|
||||
size_t len);
|
||||
int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
|
||||
const unsigned char *in, unsigned char *out,
|
||||
size_t len, ctr128_f stream);
|
||||
int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
|
||||
const unsigned char *in, unsigned char *out,
|
||||
size_t len, ctr128_f stream);
|
||||
int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx,const unsigned char *tag,
|
||||
size_t len);
|
||||
void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len);
|
||||
void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx);
|
||||
|
131
crypto/modes/modes_lcl.h
Normal file
131
crypto/modes/modes_lcl.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2010 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use is governed by OpenSSL license.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include <openssl/modes.h>
|
||||
|
||||
|
||||
#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
|
||||
typedef __int64 i64;
|
||||
typedef unsigned __int64 u64;
|
||||
#define U64(C) C##UI64
|
||||
#elif defined(__arch64__)
|
||||
typedef long i64;
|
||||
typedef unsigned long u64;
|
||||
#define U64(C) C##UL
|
||||
#else
|
||||
typedef long long i64;
|
||||
typedef unsigned long long u64;
|
||||
#define U64(C) C##ULL
|
||||
#endif
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned char u8;
|
||||
|
||||
#define STRICT_ALIGNMENT 1
|
||||
#if defined(__i386) || defined(__i386__) || \
|
||||
defined(__x86_64) || defined(__x86_64__) || \
|
||||
defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \
|
||||
defined(__s390__) || defined(__s390x__) || \
|
||||
( (defined(__arm__) || defined(__arm)) && \
|
||||
(defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
|
||||
defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__)) )
|
||||
# undef STRICT_ALIGNMENT
|
||||
#endif
|
||||
|
||||
#if !defined(PEDANTIC) && !defined(OPENSSL_NO_ASM) && !defined(OPNESSL_NO_INLINE_ASM)
|
||||
#if defined(__GNUC__) && __GNUC__>=2
|
||||
# if defined(__x86_64) || defined(__x86_64__)
|
||||
# define BSWAP8(x) ({ u64 ret=(x); \
|
||||
asm ("bswapq %0" \
|
||||
: "+r"(ret)); ret; })
|
||||
# define BSWAP4(x) ({ u32 ret=(x); \
|
||||
asm ("bswapl %0" \
|
||||
: "+r"(ret)); ret; })
|
||||
# elif (defined(__i386) || defined(__i386__))
|
||||
# define BSWAP8(x) ({ u32 lo=(u64)(x)>>32,hi=(x); \
|
||||
asm ("bswapl %0; bswapl %1" \
|
||||
: "+r"(hi),"+r"(lo)); \
|
||||
(u64)hi<<32|lo; })
|
||||
# define BSWAP4(x) ({ u32 ret=(x); \
|
||||
asm ("bswapl %0" \
|
||||
: "+r"(ret)); ret; })
|
||||
# elif (defined(__arm__) || defined(__arm)) && !defined(STRICT_ALIGNMENT)
|
||||
# define BSWAP8(x) ({ u32 lo=(u64)(x)>>32,hi=(x); \
|
||||
asm ("rev %0,%0; rev %1,%1" \
|
||||
: "+r"(hi),"+r"(lo)); \
|
||||
(u64)hi<<32|lo; })
|
||||
# define BSWAP4(x) ({ u32 ret; \
|
||||
asm ("rev %0,%1" \
|
||||
: "=r"(ret) : "r"((u32)(x))); \
|
||||
ret; })
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# if _MSC_VER>=1300
|
||||
# pragma intrinsic(_byteswap_uint64,_byteswap_ulong)
|
||||
# define BSWAP8(x) _byteswap_uint64((u64)(x))
|
||||
# define BSWAP4(x) _byteswap_ulong((u32)(x))
|
||||
# elif defined(_M_IX86)
|
||||
__inline u32 _bswap4(u32 val) {
|
||||
_asm mov eax,val
|
||||
_asm bswap eax
|
||||
}
|
||||
# define BSWAP4(x) _bswap4(x)
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(BSWAP4) && !defined(STRICT_ALIGNMENT)
|
||||
#define GETU32(p) BSWAP4(*(const u32 *)(p))
|
||||
#define PUTU32(p,v) *(u32 *)(p) = BSWAP4(v)
|
||||
#else
|
||||
#define GETU32(p) ((u32)(p)[0]<<24|(u32)(p)[1]<<16|(u32)(p)[2]<<8|(u32)(p)[3])
|
||||
#define PUTU32(p,v) ((p)[0]=(u8)((v)>>24),(p)[1]=(u8)((v)>>16),(p)[2]=(u8)((v)>>8),(p)[3]=(u8)(v))
|
||||
#endif
|
||||
|
||||
/* GCM definitions */
|
||||
|
||||
typedef struct { u64 hi,lo; } u128;
|
||||
|
||||
#ifdef TABLE_BITS
|
||||
#undef TABLE_BITS
|
||||
#endif
|
||||
/*
|
||||
* Even though permitted values for TABLE_BITS are 8, 4 and 1, it should
|
||||
* never be set to 8 [or 1]. For further information see gcm128.c.
|
||||
*/
|
||||
#define TABLE_BITS 4
|
||||
|
||||
struct gcm128_context {
|
||||
/* Following 6 names follow names in GCM specification */
|
||||
union { u64 u[2]; u32 d[4]; u8 c[16]; } Yi,EKi,EK0,len,
|
||||
Xi,H;
|
||||
/* Relative position of Xi, H and pre-computed Htable is used
|
||||
* in some assembler modules, i.e. don't change the order! */
|
||||
#if TABLE_BITS==8
|
||||
u128 Htable[256];
|
||||
#else
|
||||
u128 Htable[16];
|
||||
void (*gmult)(u64 Xi[2],const u128 Htable[16]);
|
||||
void (*ghash)(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
|
||||
#endif
|
||||
unsigned int mres, ares;
|
||||
block128_f block;
|
||||
void *key;
|
||||
};
|
||||
|
||||
struct xts128_context {
|
||||
void *key1, *key2;
|
||||
block128_f block1,block2;
|
||||
};
|
||||
|
||||
struct ccm128_context {
|
||||
union { u64 u[2]; u8 c[16]; } nonce, cmac;
|
||||
u64 blocks;
|
||||
block128_f block;
|
||||
void *key;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user