/* ====================================================================
- * Copyright (c) 2001-2011 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2001-2014 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*
*/
-#define OPENSSL_FIPSAPI
+
#include <openssl/opensslconf.h>
#ifndef OPENSSL_NO_AES
ccm128_f str;
} EVP_AES_CCM_CTX;
+#ifndef OPENSSL_NO_OCB
+typedef struct
+ {
+ AES_KEY ksenc; /* AES key schedule to use for encryption */
+ AES_KEY ksdec; /* AES key schedule to use for decryption */
+ int key_set; /* Set if key initialised */
+ int iv_set; /* Set if an iv is set */
+ OCB128_CONTEXT ocb;
+ unsigned char *iv; /* Temporary IV store */
+ unsigned char tag[16];
+ unsigned char data_buf[16]; /* Store partial data blocks */
+ unsigned char aad_buf[16]; /* Store partial AAD blocks */
+ int data_buf_len;
+ int aad_buf_len;
+ int ivlen; /* IV length */
+ int taglen;
+ } EVP_AES_OCB_CTX;
+#endif
+
#define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4))
#ifdef VPAES_ASM
#endif
#if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
-extern unsigned int OPENSSL_ppccap_P;
+# include "ppc_arch.h"
# ifdef VPAES_ASM
-# define VPAES_CAPABLE (OPENSSL_ppccap_P&(1<<1))
+# define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC)
# endif
-# define HWAES_CAPABLE (OPENSSL_ppccap_P&(1<<2))
+# define HWAES_CAPABLE (OPENSSL_ppccap_P & PPC_CRYPTO207)
# define HWAES_set_encrypt_key aes_p8_set_encrypt_key
# define HWAES_set_decrypt_key aes_p8_set_decrypt_key
# define HWAES_encrypt aes_p8_encrypt
#define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
#endif
#ifdef BSAES_ASM
-#define BSAES_CAPABLE VPAES_CAPABLE
+#define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
#endif
/*
* AES-NI section
static int aesni_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
+#ifndef OPENSSL_NO_OCB
+static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+ {
+ EVP_AES_OCB_CTX *octx = ctx->cipher_data;
+ if (!iv && !key)
+ return 1;
+ if (key)
+ {
+ do
+ {
+ /* We set both the encrypt and decrypt key here because decrypt
+ * needs both. We could possibly optimise to remove setting the
+ * decrypt for an encryption operation.
+ */
+ aesni_set_encrypt_key(key, ctx->key_len * 8, &octx->ksenc);
+ aesni_set_decrypt_key(key, ctx->key_len * 8, &octx->ksdec);
+ if(!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc, &octx->ksdec,
+ (block128_f)aesni_encrypt, (block128_f)aesni_decrypt))
+ return 0;
+ }
+ while (0);
+
+ /* If we have an iv we can set it directly, otherwise use
+ * saved IV.
+ */
+ if (iv == NULL && octx->iv_set)
+ iv = octx->iv;
+ if (iv)
+ {
+ if(CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) != 1)
+ return 0;
+ octx->iv_set = 1;
+ }
+ octx->key_set = 1;
+ }
+ else
+ {
+ /* If key set use IV, otherwise copy */
+ if (octx->key_set)
+ CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
+ else
+ memcpy(octx->iv, iv, octx->ivlen);
+ octx->iv_set = 1;
+ }
+ return 1;
+ }
+
+#define aesni_ocb_cipher aes_ocb_cipher
+static int aesni_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+#endif /* OPENSSL_NO_OCB */
+
#define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aesni_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
static int aes_t4_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
+#ifndef OPENSSL_NO_OCB
+static int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+ {
+ EVP_AES_OCB_CTX *octx = ctx->cipher_data;
+ if (!iv && !key)
+ return 1;
+ if (key)
+ {
+ do
+ {
+ /* We set both the encrypt and decrypt key here because decrypt
+ * needs both. We could possibly optimise to remove setting the
+ * decrypt for an encryption operation.
+ */
+ aes_t4_set_encrypt_key(key, ctx->key_len * 8, &octx->ksenc);
+ aes_t4_set_decrypt_key(key, ctx->key_len * 8, &octx->ksdec);
+ if(!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc, &octx->ksdec,
+ (block128_f)aes_t4_encrypt, (block128_f)aes_t4_decrypt))
+ return 0;
+ }
+ while (0);
+
+ /* If we have an iv we can set it directly, otherwise use
+ * saved IV.
+ */
+ if (iv == NULL && octx->iv_set)
+ iv = octx->iv;
+ if (iv)
+ {
+ if(CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) != 1)
+ return 0;
+ octx->iv_set = 1;
+ }
+ octx->key_set = 1;
+ }
+ else
+ {
+ /* If key set use IV, otherwise copy */
+ if (octx->key_set)
+ CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
+ else
+ memcpy(octx->iv, iv, octx->ivlen);
+ octx->iv_set = 1;
+ }
+ return 1;
+ }
+
+#define aes_t4_ocb_cipher aes_ocb_cipher
+static int aes_t4_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len);
+#endif /* OPENSSL_NO_OCB */
+
#define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
return 1;
}
-BLOCK_CIPHER_generic_pack(NID_aes,128,EVP_CIPH_FLAG_FIPS)
-BLOCK_CIPHER_generic_pack(NID_aes,192,EVP_CIPH_FLAG_FIPS)
-BLOCK_CIPHER_generic_pack(NID_aes,256,EVP_CIPH_FLAG_FIPS)
+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)
{
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))
{
| EVP_CIPH_CUSTOM_COPY)
BLOCK_CIPHER_custom(NID_aes,128,1,12,gcm,GCM,
- EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
+ EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes,192,1,12,gcm,GCM,
- EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
+ EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes,256,1,12,gcm,GCM,
- EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
+ EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
return 0;
if (!out || !in || len<AES_BLOCK_SIZE)
return 0;
-#ifdef OPENSSL_FIPS
- /* Requirement of SP800-38E */
- if (FIPS_module_mode() && !(ctx->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW) &&
- (len > (1UL<<20)*16))
- {
- EVPerr(EVP_F_AES_XTS_CIPHER, EVP_R_TOO_LARGE);
- return 0;
- }
-#endif
if (xctx->stream)
(*xctx->stream)(in, out, len,
xctx->xts.key1, xctx->xts.key2, ctx->iv);
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
| EVP_CIPH_CUSTOM_COPY)
-BLOCK_CIPHER_custom(NID_aes,128,1,16,xts,XTS,EVP_CIPH_FLAG_FIPS|XTS_FLAGS)
-BLOCK_CIPHER_custom(NID_aes,256,1,16,xts,XTS,EVP_CIPH_FLAG_FIPS|XTS_FLAGS)
+BLOCK_CIPHER_custom(NID_aes,128,1,16,xts,XTS,XTS_FLAGS)
+BLOCK_CIPHER_custom(NID_aes,256,1,16,xts,XTS,XTS_FLAGS)
static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
#define aes_ccm_cleanup NULL
-BLOCK_CIPHER_custom(NID_aes,128,1,12,ccm,CCM,EVP_CIPH_FLAG_FIPS|CUSTOM_FLAGS)
-BLOCK_CIPHER_custom(NID_aes,192,1,12,ccm,CCM,EVP_CIPH_FLAG_FIPS|CUSTOM_FLAGS)
-BLOCK_CIPHER_custom(NID_aes,256,1,12,ccm,CCM,EVP_CIPH_FLAG_FIPS|CUSTOM_FLAGS)
+BLOCK_CIPHER_custom(NID_aes,128,1,12,ccm,CCM,CUSTOM_FLAGS)
+BLOCK_CIPHER_custom(NID_aes,192,1,12,ccm,CCM,CUSTOM_FLAGS)
+BLOCK_CIPHER_custom(NID_aes,256,1,12,ccm,CCM,CUSTOM_FLAGS)
typedef struct
{
}
if (iv)
{
- memcpy(ctx->iv, iv, 8);
+ memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx));
wctx->iv = ctx->iv;
}
return 1;
{
EVP_AES_WRAP_CTX *wctx = ctx->cipher_data;
size_t rv;
- if (inlen % 8)
+ /* AES wrap with padding has IV length of 4, without padding 8 */
+ int pad = EVP_CIPHER_CTX_iv_length(ctx) == 4;
+ /* No final operation so always return zero length */
+ if (!in)
+ return 0;
+ /* Input length must always be non-zero */
+ if (!inlen)
return -1;
- if (ctx->encrypt && inlen < 8)
+ /* If decrypting need at least 16 bytes and multiple of 8 */
+ if (!ctx->encrypt && (inlen < 16 || inlen & 0x7))
return -1;
- if (!ctx->encrypt && inlen < 16)
+ /* If not padding input must be multiple of 8 */
+ if (!pad && inlen & 0x7)
return -1;
if (!out)
{
if (ctx->encrypt)
+ {
+ /* If padding round up to multiple of 8 */
+ if (pad)
+ inlen = (inlen + 7)/8 * 8;
+ /* 8 byte prefix */
return inlen + 8;
+ }
else
+ {
+ /* If not padding output will be exactly 8 bytes
+ * smaller than input. If padding it will be at
+ * least 8 bytes smaller but we don't know how
+ * much.
+ */
return inlen - 8;
+ }
}
- if (!in)
- return 0;
- if (ctx->encrypt)
- rv = CRYPTO_128_wrap(&wctx->ks.ks, wctx->iv, out, in, inlen,
+ if (pad)
+ {
+ if (ctx->encrypt)
+ rv = CRYPTO_128_wrap_pad(&wctx->ks.ks, wctx->iv,
+ out, in, inlen,
(block128_f)AES_encrypt);
+ else
+ rv = CRYPTO_128_unwrap_pad(&wctx->ks.ks, wctx->iv,
+ out, in, inlen,
+ (block128_f)AES_decrypt);
+ }
else
- rv = CRYPTO_128_unwrap(&wctx->ks.ks, wctx->iv, out, in, inlen,
+ {
+ if (ctx->encrypt)
+ rv = CRYPTO_128_wrap(&wctx->ks.ks, wctx->iv,
+ out, in, inlen,
+ (block128_f)AES_encrypt);
+ else
+ rv = CRYPTO_128_unwrap(&wctx->ks.ks, wctx->iv,
+ out, in, inlen,
(block128_f)AES_decrypt);
+ }
return rv ? (int)rv : -1;
}
NID_id_aes128_wrap,
8, 16, 8, WRAP_FLAGS,
aes_wrap_init_key, aes_wrap_cipher,
- NULL,
+ NULL,
sizeof(EVP_AES_WRAP_CTX),
NULL,NULL,NULL,NULL };
NID_id_aes192_wrap,
8, 24, 8, WRAP_FLAGS,
aes_wrap_init_key, aes_wrap_cipher,
- NULL,
+ NULL,
sizeof(EVP_AES_WRAP_CTX),
NULL,NULL,NULL,NULL };
NID_id_aes256_wrap,
8, 32, 8, WRAP_FLAGS,
aes_wrap_init_key, aes_wrap_cipher,
- NULL,
+ NULL,
sizeof(EVP_AES_WRAP_CTX),
NULL,NULL,NULL,NULL };
return &aes_256_wrap;
}
+static const EVP_CIPHER aes_128_wrap_pad = {
+ NID_id_aes128_wrap_pad,
+ 8, 16, 4, WRAP_FLAGS,
+ aes_wrap_init_key, aes_wrap_cipher,
+ NULL,
+ sizeof(EVP_AES_WRAP_CTX),
+ NULL,NULL,NULL,NULL };
+
+const EVP_CIPHER *EVP_aes_128_wrap_pad(void)
+ {
+ return &aes_128_wrap_pad;
+ }
+
+static const EVP_CIPHER aes_192_wrap_pad = {
+ NID_id_aes192_wrap_pad,
+ 8, 24, 4, WRAP_FLAGS,
+ aes_wrap_init_key, aes_wrap_cipher,
+ NULL,
+ sizeof(EVP_AES_WRAP_CTX),
+ NULL,NULL,NULL,NULL };
+
+const EVP_CIPHER *EVP_aes_192_wrap_pad(void)
+ {
+ return &aes_192_wrap_pad;
+ }
+
+static const EVP_CIPHER aes_256_wrap_pad = {
+ NID_id_aes256_wrap_pad,
+ 8, 32, 4, WRAP_FLAGS,
+ aes_wrap_init_key, aes_wrap_cipher,
+ NULL,
+ sizeof(EVP_AES_WRAP_CTX),
+ NULL,NULL,NULL,NULL };
+
+const EVP_CIPHER *EVP_aes_256_wrap_pad(void)
+ {
+ return &aes_256_wrap_pad;
+ }
+
+#ifndef OPENSSL_NO_OCB
+static int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+ {
+ EVP_AES_OCB_CTX *octx = c->cipher_data;
+ EVP_CIPHER_CTX *newc;
+ EVP_AES_OCB_CTX *new_octx;
+
+ switch (type)
+ {
+ case EVP_CTRL_INIT:
+ octx->key_set = 0;
+ octx->iv_set = 0;
+ octx->ivlen = c->cipher->iv_len;
+ octx->iv = c->iv;
+ octx->taglen = 16;
+ octx->data_buf_len = 0;
+ octx->aad_buf_len = 0;
+ return 1;
+
+ case EVP_CTRL_SET_IVLEN:
+ /* IV len must be 1 to 15 */
+ if (arg <= 0 || arg > 15)
+ return 0;
+
+ octx->ivlen = arg;
+ return 1;
+
+ case EVP_CTRL_OCB_SET_TAGLEN:
+ /* Tag len must be 0 to 16 */
+ if (arg < 0 || arg > 16)
+ return 0;
+
+ octx->taglen = arg;
+ return 1;
+
+ case EVP_CTRL_SET_TAG:
+ if (arg != octx->taglen || c->encrypt)
+ return 0;
+ memcpy(octx->tag, ptr, arg);
+ return 1;
+
+ case EVP_CTRL_GET_TAG:
+ if (arg != octx->taglen || !c->encrypt)
+ return 0;
+
+ memcpy(ptr, octx->tag, arg);
+ return 1;
+
+ case EVP_CTRL_COPY:
+ newc = (EVP_CIPHER_CTX *)ptr;
+ new_octx = newc->cipher_data;
+ return CRYPTO_ocb128_copy_ctx(&new_octx->ocb, &octx->ocb,
+ &new_octx->ksenc, &new_octx->ksdec);
+
+ default:
+ return -1;
+
+ }
+ }
+
+
+static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+ {
+ EVP_AES_OCB_CTX *octx = ctx->cipher_data;
+ if (!iv && !key)
+ return 1;
+ if (key)
+ {
+ do
+ {
+ /* We set both the encrypt and decrypt key here because decrypt
+ * needs both. We could possibly optimise to remove setting the
+ * decrypt for an encryption operation.
+ */
+#ifdef VPAES_CAPABLE
+ if (VPAES_CAPABLE)
+ {
+ vpaes_set_encrypt_key(key,ctx->key_len*8,&octx->ksenc);
+ vpaes_set_decrypt_key(key,ctx->key_len*8,&octx->ksdec);
+ if(!CRYPTO_ocb128_init(&octx->ocb,&octx->ksenc,&octx->ksdec,
+ (block128_f)vpaes_encrypt,(block128_f)vpaes_decrypt))
+ return 0;
+ break;
+ }
+#endif
+ AES_set_encrypt_key(key, ctx->key_len * 8, &octx->ksenc);
+ AES_set_decrypt_key(key, ctx->key_len * 8, &octx->ksdec);
+ if(!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc, &octx->ksdec,
+ (block128_f)AES_encrypt, (block128_f)AES_decrypt))
+ return 0;
+ }
+ while (0);
+
+ /* If we have an iv we can set it directly, otherwise use
+ * saved IV.
+ */
+ if (iv == NULL && octx->iv_set)
+ iv = octx->iv;
+ if (iv)
+ {
+ if(CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) != 1)
+ return 0;
+ octx->iv_set = 1;
+ }
+ octx->key_set = 1;
+ }
+ else
+ {
+ /* If key set use IV, otherwise copy */
+ if (octx->key_set)
+ CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
+ else
+ memcpy(octx->iv, iv, octx->ivlen);
+ octx->iv_set = 1;
+ }
+ return 1;
+ }
+
+static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+ {
+ unsigned char *buf;
+ int *buf_len;
+ int written_len = 0;
+ size_t trailing_len;
+ EVP_AES_OCB_CTX *octx = ctx->cipher_data;
+
+ /* If IV or Key not set then return error */
+ if (!octx->iv_set)
+ return -1;
+
+ if (!octx->key_set)
+ return -1;
+
+ if (in)
+ {
+ /* Need to ensure we are only passing full blocks to low level OCB
+ * routines. We do it here rather than in EVP_EncryptUpdate/
+ * EVP_DecryptUpdate because we need to pass full blocks of AAD too
+ * and those routines don't support that
+ */
+
+ /* Are we dealing with AAD or normal data here? */
+ if (out == NULL)
+ {
+ buf = octx->aad_buf;
+ buf_len = &(octx->aad_buf_len);
+ }
+ else
+ {
+ buf = octx->data_buf;
+ buf_len = &(octx->data_buf_len);
+ }
+
+ /* If we've got a partially filled buffer from a previous call then use
+ * that data first
+ */
+ if(*buf_len)
+ {
+ unsigned int remaining;
+
+ remaining = 16 - (*buf_len);
+ if(remaining > len)
+ {
+ memcpy(buf+(*buf_len), in, len);
+ *(buf_len)+=len;
+ return 0;
+ }
+ memcpy(buf+(*buf_len), in, remaining);
+
+ /* If we get here we've filled the buffer, so process it */
+ len -= remaining;
+ in += remaining;
+ if (out == NULL)
+ {
+ if(!CRYPTO_ocb128_aad(&octx->ocb, buf, 16))
+ return -1;
+ }
+ else if (ctx->encrypt)
+ {
+ if(!CRYPTO_ocb128_encrypt(&octx->ocb, buf, out, 16))
+ return -1;
+ }
+ else
+ {
+ if(!CRYPTO_ocb128_decrypt(&octx->ocb, buf, out, 16))
+ return -1;
+ }
+ written_len = 16;
+ *buf_len = 0;
+ }
+
+ /* Do we have a partial block to handle at the end? */
+ trailing_len = len % 16;
+
+ /* If we've got some full blocks to handle, then process these first */
+ if(len != trailing_len)
+ {
+ if (out == NULL)
+ {
+ if(!CRYPTO_ocb128_aad(&octx->ocb, in, len-trailing_len))
+ return -1;
+ }
+ else if (ctx->encrypt)
+ {
+ if(!CRYPTO_ocb128_encrypt(&octx->ocb, in, out, len-trailing_len))
+ return -1;
+ }
+ else
+ {
+ if(!CRYPTO_ocb128_decrypt(&octx->ocb, in, out, len-trailing_len))
+ return -1;
+ }
+ written_len += len-trailing_len;
+ in += len-trailing_len;
+ }
+
+ /* Handle any trailing partial block */
+ if(trailing_len)
+ {
+ memcpy(buf, in, trailing_len);
+ *buf_len = trailing_len;
+ }
+
+ return written_len;
+ }
+ else
+ {
+ /* First of all empty the buffer of any partial block that we might
+ * have been provided - both for data and AAD
+ */
+ if(octx->data_buf_len)
+ {
+ if (ctx->encrypt)
+ {
+ if(!CRYPTO_ocb128_encrypt(&octx->ocb, octx->data_buf, out,
+ octx->data_buf_len))
+ return -1;
+ }
+ else
+ {
+ if(!CRYPTO_ocb128_decrypt(&octx->ocb, octx->data_buf, out,
+ octx->data_buf_len))
+ return -1;
+ }
+ written_len = octx->data_buf_len;
+ octx->data_buf_len = 0;
+ }
+ if(octx->aad_buf_len)
+ {
+ if(!CRYPTO_ocb128_aad(&octx->ocb, octx->aad_buf, octx->aad_buf_len))
+ return -1;
+ octx->aad_buf_len = 0;
+ }
+ /* If decrypting then verify */
+ if (!ctx->encrypt)
+ {
+ if (octx->taglen < 0)
+ return -1;
+ if (CRYPTO_ocb128_finish(&octx->ocb,
+ octx->tag, octx->taglen) != 0)
+ return -1;
+ octx->iv_set = 0;
+ return written_len;
+ }
+ /* If encrypting then just get the tag */
+ if(CRYPTO_ocb128_tag(&octx->ocb, octx->tag, 16) != 1)
+ return -1;
+ /* Don't reuse the IV */
+ octx->iv_set = 0;
+ return written_len;
+ }
+ }
+
+static int aes_ocb_cleanup(EVP_CIPHER_CTX *c)
+ {
+ EVP_AES_OCB_CTX *octx = c->cipher_data;
+ CRYPTO_ocb128_cleanup(&octx->ocb);
+ return 1;
+ }
+
+BLOCK_CIPHER_custom(NID_aes,128,16,12,ocb,OCB,CUSTOM_FLAGS)
+BLOCK_CIPHER_custom(NID_aes,192,16,12,ocb,OCB,CUSTOM_FLAGS)
+BLOCK_CIPHER_custom(NID_aes,256,16,12,ocb,OCB,CUSTOM_FLAGS)
+#endif /* OPENSSL_NO_OCB */
+
#endif