[openssl-commits] [openssl] OpenSSL source code branch master updated. 0c1bd7f03fcd1cc8256f89f4962d91b78432c74a
Matt Caswell
matt at openssl.org
Mon Dec 8 05:31:42 EST 2014
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "OpenSSL source code".
The branch, master has been updated
via 0c1bd7f03fcd1cc8256f89f4962d91b78432c74a (commit)
via 3feb63054a981528e77a4a8f58a822c8dff4f4c5 (commit)
via e4bbee963348414a8f5e75dc7d23c3e30c72a860 (commit)
via d827c5edb54263f81cc46899080e2ad7b70ca9f5 (commit)
via e6b336efa31c9916bd64504a478d56532f86d6aa (commit)
via c857a80c9dccf82de94137410c754b18e893a55d (commit)
from 376e2ca3e3525290619602dc6013c97c9653c037 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 0c1bd7f03fcd1cc8256f89f4962d91b78432c74a
Author: Matt Caswell <matt at openssl.org>
Date: Mon Dec 8 00:04:25 2014 +0000
Add CHANGES entry for OCB
Reviewed-by: Tim Hudson <tjh at openssl.org>
commit 3feb63054a981528e77a4a8f58a822c8dff4f4c5
Author: Matt Caswell <matt at openssl.org>
Date: Sun Dec 7 23:53:22 2014 +0000
Added OPENSSL_NO_OCB guards
Reviewed-by: Tim Hudson <tjh at openssl.org>
commit e4bbee963348414a8f5e75dc7d23c3e30c72a860
Author: Matt Caswell <matt at openssl.org>
Date: Sat Dec 6 20:55:53 2014 +0000
Add documentation for OCB mode
Reviewed-by: Tim Hudson <tjh at openssl.org>
commit d827c5edb54263f81cc46899080e2ad7b70ca9f5
Author: Matt Caswell <matt at openssl.org>
Date: Sat Dec 6 20:55:36 2014 +0000
Add tests for OCB mode
Reviewed-by: Tim Hudson <tjh at openssl.org>
commit e6b336efa31c9916bd64504a478d56532f86d6aa
Author: Matt Caswell <matt at openssl.org>
Date: Sat Dec 6 20:55:10 2014 +0000
Add EVP support for OCB mode
Reviewed-by: Tim Hudson <tjh at openssl.org>
commit c857a80c9dccf82de94137410c754b18e893a55d
Author: Matt Caswell <matt at openssl.org>
Date: Sat Dec 6 20:53:35 2014 +0000
Add support for OCB mode as per RFC7253
Reviewed-by: Tim Hudson <tjh at openssl.org>
-----------------------------------------------------------------------
Summary of changes:
CHANGES | 5 +
crypto/evp/c_allc.c | 9 +
crypto/evp/e_aes.c | 412 ++++++++++++++++++++++++++++
crypto/evp/evp.h | 16 ++
crypto/evp/evp_test.c | 39 ++-
crypto/evp/evptests.txt | 21 ++
crypto/modes/Makefile | 9 +-
crypto/modes/modes.h | 25 ++
crypto/modes/modes_lcl.h | 42 +++
crypto/modes/ocb128.c | 591 ++++++++++++++++++++++++++++++++++++++++
crypto/objects/obj_dat.h | 15 +-
crypto/objects/obj_mac.h | 12 +
crypto/objects/obj_mac.num | 3 +
crypto/objects/objects.txt | 3 +
doc/crypto/EVP_EncryptInit.pod | 44 ++-
util/libeay.num | 12 +
16 files changed, 1229 insertions(+), 29 deletions(-)
create mode 100644 crypto/modes/ocb128.c
diff --git a/CHANGES b/CHANGES
index 389aab9..a8b55bf 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
Changes between 1.0.2 and 1.1.0 [xx XXX xxxx]
+ *) Added support for OCB mode. OpenSSL has been granted a patent license
+ compatible with the OpenSSL license for use of OCB. Details are available
+ at https://www.openssl.org/docs/misc/OCB-patent-grant-OpenSSL.pdf. Support
+ for OCB can be removed by calling config with no-ocb.
+
*) SSLv2 support has been removed. It still supports receiving a SSLv2
compatible client hello.
[Kurt Roeckx]
diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c
index a714f12..b95e781 100644
--- a/crypto/evp/c_allc.c
+++ b/crypto/evp/c_allc.c
@@ -172,6 +172,9 @@ void OpenSSL_add_all_ciphers(void)
EVP_add_cipher(EVP_aes_128_ofb());
EVP_add_cipher(EVP_aes_128_ctr());
EVP_add_cipher(EVP_aes_128_gcm());
+#ifndef OPENSSL_NO_OCB
+ EVP_add_cipher(EVP_aes_128_ocb());
+#endif
EVP_add_cipher(EVP_aes_128_xts());
EVP_add_cipher(EVP_aes_128_ccm());
EVP_add_cipher(EVP_aes_128_wrap());
@@ -186,6 +189,9 @@ void OpenSSL_add_all_ciphers(void)
EVP_add_cipher(EVP_aes_192_ofb());
EVP_add_cipher(EVP_aes_192_ctr());
EVP_add_cipher(EVP_aes_192_gcm());
+#ifndef OPENSSL_NO_OCB
+ EVP_add_cipher(EVP_aes_192_ocb());
+#endif
EVP_add_cipher(EVP_aes_192_ccm());
EVP_add_cipher(EVP_aes_192_wrap());
EVP_add_cipher(EVP_aes_192_wrap_pad());
@@ -199,6 +205,9 @@ void OpenSSL_add_all_ciphers(void)
EVP_add_cipher(EVP_aes_256_ofb());
EVP_add_cipher(EVP_aes_256_ctr());
EVP_add_cipher(EVP_aes_256_gcm());
+#ifndef OPENSSL_NO_OCB
+ EVP_add_cipher(EVP_aes_256_ocb());
+#endif
EVP_add_cipher(EVP_aes_256_xts());
EVP_add_cipher(EVP_aes_256_ccm());
EVP_add_cipher(EVP_aes_256_wrap());
diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c
index 7762623..2222188 100644
--- a/crypto/evp/e_aes.c
+++ b/crypto/evp/e_aes.c
@@ -107,6 +107,25 @@ typedef struct
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
@@ -451,6 +470,59 @@ static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
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, \
@@ -837,6 +909,59 @@ static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
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, \
@@ -2238,4 +2363,291 @@ 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
diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
index bafe339..757b796 100644
--- a/crypto/evp/evp.h
+++ b/crypto/evp/evp.h
@@ -340,6 +340,7 @@ struct evp_cipher_st
#define EVP_CIPH_CCM_MODE 0x7
#define EVP_CIPH_XTS_MODE 0x10001
#define EVP_CIPH_WRAP_MODE 0x10002
+#define EVP_CIPH_OCB_MODE 0x10003
#define EVP_CIPH_MODE 0xF0007
/* Set if variable length cipher */
#define EVP_CIPH_VARIABLE_LENGTH 0x8
@@ -422,6 +423,12 @@ typedef struct {
unsigned int interleave;
} EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM;
+#define EVP_CTRL_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN
+#define EVP_CTRL_GET_TAG EVP_CTRL_GCM_GET_TAG
+#define EVP_CTRL_SET_TAG EVP_CTRL_GCM_SET_TAG
+#define EVP_CTRL_OCB_SET_TAGLEN 0x1c
+
+
/* GCM TLS constants */
/* Length of fixed part of IV derived from PRF */
#define EVP_GCM_TLS_FIXED_IV_LEN 4
@@ -850,6 +857,9 @@ const EVP_CIPHER *EVP_aes_128_gcm(void);
const EVP_CIPHER *EVP_aes_128_xts(void);
const EVP_CIPHER *EVP_aes_128_wrap(void);
const EVP_CIPHER *EVP_aes_128_wrap_pad(void);
+#ifndef OPENSSL_NO_OCB
+const EVP_CIPHER *EVP_aes_128_ocb(void);
+#endif
const EVP_CIPHER *EVP_aes_192_ecb(void);
const EVP_CIPHER *EVP_aes_192_cbc(void);
const EVP_CIPHER *EVP_aes_192_cfb1(void);
@@ -862,6 +872,9 @@ const EVP_CIPHER *EVP_aes_192_ccm(void);
const EVP_CIPHER *EVP_aes_192_gcm(void);
const EVP_CIPHER *EVP_aes_192_wrap(void);
const EVP_CIPHER *EVP_aes_192_wrap_pad(void);
+#ifndef OPENSSL_NO_OCB
+const EVP_CIPHER *EVP_aes_192_ocb(void);
+#endif
const EVP_CIPHER *EVP_aes_256_ecb(void);
const EVP_CIPHER *EVP_aes_256_cbc(void);
const EVP_CIPHER *EVP_aes_256_cfb1(void);
@@ -875,6 +888,9 @@ const EVP_CIPHER *EVP_aes_256_gcm(void);
const EVP_CIPHER *EVP_aes_256_xts(void);
const EVP_CIPHER *EVP_aes_256_wrap(void);
const EVP_CIPHER *EVP_aes_256_wrap_pad(void);
+#ifndef OPENSSL_NO_OCB
+const EVP_CIPHER *EVP_aes_256_ocb(void);
+#endif
# if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void);
const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void);
diff --git a/crypto/evp/evp_test.c b/crypto/evp/evp_test.c
index 63d7095..2b70c59 100644
--- a/crypto/evp/evp_test.c
+++ b/crypto/evp/evp_test.c
@@ -178,7 +178,7 @@ static void test1(const EVP_CIPHER *c,const unsigned char *key,int kn,
EVP_CIPHER_CTX_set_flags(ctx,EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
if (encdec != 0)
{
- if (mode == EVP_CIPH_GCM_MODE)
+ if ((mode == EVP_CIPH_GCM_MODE) || (mode == EVP_CIPH_OCB_MODE))
{
if(!EVP_EncryptInit_ex(ctx,c,NULL,NULL,NULL))
{
@@ -186,12 +186,19 @@ static void test1(const EVP_CIPHER *c,const unsigned char *key,int kn,
ERR_print_errors_fp(stderr);
test1_exit(10);
}
- if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL))
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_IVLEN, in, NULL))
{
fprintf(stderr,"IV length set failed\n");
ERR_print_errors_fp(stderr);
test1_exit(11);
}
+ if((mode == EVP_CIPH_OCB_MODE) &&
+ !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_OCB_SET_TAGLEN, tn, NULL))
+ {
+ fprintf(stderr,"Tag length set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(15);
+ }
if(!EVP_EncryptInit_ex(ctx,NULL,NULL,key,iv))
{
fprintf(stderr,"Key/IV set failed\n");
@@ -290,13 +297,12 @@ static void test1(const EVP_CIPHER *c,const unsigned char *key,int kn,
hexdump(stderr,"Expected",ciphertext,cn);
test1_exit(9);
}
- if (mode == EVP_CIPH_GCM_MODE || mode == EVP_CIPH_CCM_MODE)
+ if ((mode == EVP_CIPH_GCM_MODE) || (mode == EVP_CIPH_OCB_MODE)
+ || (mode == EVP_CIPH_CCM_MODE))
{
unsigned char rtag[16];
- /* Note: EVP_CTRL_CCM_GET_TAG has same value as
- * EVP_CTRL_GCM_GET_TAG
- */
- if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tn, rtag))
+
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GET_TAG, tn, rtag))
{
fprintf(stderr,"Get tag failed\n");
ERR_print_errors_fp(stderr);
@@ -314,27 +320,34 @@ static void test1(const EVP_CIPHER *c,const unsigned char *key,int kn,
if (encdec <= 0)
{
- if (mode == EVP_CIPH_GCM_MODE)
+ if ((mode == EVP_CIPH_GCM_MODE) || (mode == EVP_CIPH_OCB_MODE))
{
if(!EVP_DecryptInit_ex(ctx,c,NULL,NULL,NULL))
{
- fprintf(stderr,"EncryptInit failed\n");
+ fprintf(stderr,"DecryptInit failed\n");
ERR_print_errors_fp(stderr);
test1_exit(10);
}
- if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL))
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_IVLEN, in, NULL))
{
fprintf(stderr,"IV length set failed\n");
ERR_print_errors_fp(stderr);
test1_exit(11);
}
+ if((mode == EVP_CIPH_OCB_MODE) &&
+ !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_OCB_SET_TAGLEN, tn, NULL))
+ {
+ fprintf(stderr,"Tag length set failed\n");
+ ERR_print_errors_fp(stderr);
+ test1_exit(15);
+ }
if(!EVP_DecryptInit_ex(ctx,NULL,NULL,key,iv))
{
fprintf(stderr,"Key/IV set failed\n");
ERR_print_errors_fp(stderr);
test1_exit(12);
}
- if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tn, (void *)tag))
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_TAG, tn, (void *)tag))
{
fprintf(stderr,"Set tag failed\n");
ERR_print_errors_fp(stderr);
@@ -449,6 +462,10 @@ static int test_cipher(const char *cipher,const unsigned char *key,int kn,
{
const EVP_CIPHER *c;
+#ifdef OPENSSL_NO_OCB
+ if(strstr(cipher, "ocb") != NULL)
+ return 1;
+#endif
c=EVP_get_cipherbyname(cipher);
if(!c)
return 0;
diff --git a/crypto/evp/evptests.txt b/crypto/evp/evptests.txt
index 42eb42e..cc985b4 100644
--- a/crypto/evp/evptests.txt
+++ b/crypto/evp/evptests.txt
@@ -372,6 +372,27 @@ aes-128-gcm:00000000000000000000000000000000:ffffffff000000000000000000000000000
# 80 bytes plaintext, submitted by Intel
aes-128-gcm:843ffcf5d2b72694d19ed01d01249412:dbcca32ebf9b804617c3aa9e:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f:6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5:00000000000000000000000000000000101112131415161718191a1b1c1d1e1f:3b629ccfbc1119b7319e1dce2cd6fd6d
+#AES OCB Test vectors
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B::::197B9C3C441D3C83EAFB2BEF633B9182
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:0001020304050607:92B657130A74B85A:0001020304050607:16DC76A46D47E1EAD537209E8A96D14E
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:::0001020304050607:98B91552C8C009185044E30A6EB2FE21
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:0001020304050607:92B657130A74B85A::971EFFCAE19AD4716F88E87B871FBEED
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:000102030405060708090A0B0C0D0E0F:BEA5E8798DBE7110031C144DA0B26122:000102030405060708090A0B0C0D0E0F:776C9924D6723A1FC4524532AC3E5BEB
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:::000102030405060708090A0B0C0D0E0F:7DDB8E6CEA6814866212509619B19CC6
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:000102030405060708090A0B0C0D0E0F:BEA5E8798DBE7110031C144DA0B26122::13CC8B747807121A4CBB3E4BD6B456AF
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:000102030405060708090A0B0C0D0E0F1011121314151617:BEA5E8798DBE7110031C144DA0B26122FCFCEE7A2A8D4D48:000102030405060708090A0B0C0D0E0F1011121314151617:5FA94FC3F38820F1DC3F3D1FD4E55E1C
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:::000102030405060708090A0B0C0D0E0F1011121314151617:282026DA3068BC9FA118681D559F10F6
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:000102030405060708090A0B0C0D0E0F1011121314151617:BEA5E8798DBE7110031C144DA0B26122FCFCEE7A2A8D4D48::6EF2F52587FDA0ED97DC7EEDE241DF68
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A657149D53773463CB:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:B2A040DD3BD5164372D76D7BB6824240
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:::000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:E1E072633BADE51A60E85951D9C42A1B
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A657149D53773463CB::4A3BAE824465CFDAF8C41FC50C7DF9D9
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627:BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A657149D53773463CB68C65778B058A635:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627:659C623211DEEA0DE30D2C381879F4C8
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:::000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627:7AEB7A69A1687DD082CA27B0D9A37096
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627:BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A657149D53773463CB68C65778B058A635::060C8467F4ABAB5E8B3C2067A2E115DC
+#AES OCB Non standard test vectors - generated from reference implementation
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627:09a4fd29de949d9a9aa9924248422097ad4883b4713e6c214ff6567ada08a96766fc4e2ee3e3a5a1:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627:1b6c44f34e3abb3cbf8976e7
+aes-128-ocb:000102030405060708090A0B0C0D0E0F:000102030405060708090A0B0C0D0E:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627:5e2fa7367ffbdb3938845cfd415fcc71ec79634eb31451609d27505f5e2978f43c44213d8fa441ee:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627:1ad62009901f40cba7cd7156f94a7324
+
# AES XTS test vectors from IEEE Std 1619-2007
aes-128-xts:0000000000000000000000000000000000000000000000000000000000000000:00000000000000000000000000000000:0000000000000000000000000000000000000000000000000000000000000000:917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e
aes-128-xts:1111111111111111111111111111111122222222222222222222222222222222:33333333330000000000000000000000:4444444444444444444444444444444444444444444444444444444444444444:c454185e6a16936e39334038acef838bfb186fff7480adc4289382ecd6d394f0
diff --git a/crypto/modes/Makefile b/crypto/modes/Makefile
index c6ac7ee..66cbd8f 100644
--- a/crypto/modes/Makefile
+++ b/crypto/modes/Makefile
@@ -22,9 +22,9 @@ APPS=
LIB=$(TOP)/libcrypto.a
LIBSRC= cbc128.c ctr128.c cts128.c cfb128.c ofb128.c gcm128.c \
- ccm128.c xts128.c wrap128.c
+ ccm128.c xts128.c wrap128.c ocb128.c
LIBOBJ= cbc128.o ctr128.o cts128.o cfb128.o ofb128.o gcm128.o \
- ccm128.o xts128.o wrap128.o $(MODES_ASM_OBJ)
+ ccm128.o xts128.o wrap128.o ocb128.o $(MODES_ASM_OBJ)
SRC= $(LIBSRC)
@@ -138,6 +138,11 @@ gcm128.o: ../../include/openssl/modes.h ../../include/openssl/opensslconf.h
gcm128.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
gcm128.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
gcm128.o: ../../include/openssl/symhacks.h gcm128.c modes_lcl.h
+ocb128.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
+ocb128.o: ../../include/openssl/modes.h ../../include/openssl/opensslconf.h
+ocb128.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+ocb128.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
+ocb128.o: ../../include/openssl/symhacks.h modes_lcl.h ocb128.c
ofb128.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
ofb128.o: ../../include/openssl/modes.h ../../include/openssl/opensslconf.h
ofb128.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
diff --git a/crypto/modes/modes.h b/crypto/modes/modes.h
index a12aca1..3fb1b4b 100644
--- a/crypto/modes/modes.h
+++ b/crypto/modes/modes.h
@@ -137,6 +137,7 @@ typedef struct xts128_context XTS128_CONTEXT;
int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, const unsigned char iv[16],
const unsigned char *inp, unsigned char *out, size_t len, int enc);
+
size_t CRYPTO_128_wrap(void *key, const unsigned char *iv,
unsigned char *out,
const unsigned char *in, size_t inlen, block128_f block);
@@ -150,6 +151,30 @@ size_t CRYPTO_128_wrap_pad(void *key, const unsigned char *icv,
size_t CRYPTO_128_unwrap_pad(void *key, const unsigned char *icv,
unsigned char *out,
const unsigned char *in, size_t inlen, block128_f block);
+
+#ifndef OPENSSL_NO_OCB
+typedef struct ocb128_context OCB128_CONTEXT;
+
+OCB128_CONTEXT *CRYPTO_ocb128_new(void *keyenc, void *keydec, block128_f encrypt, block128_f decrypt);
+int CRYPTO_ocb128_init(OCB128_CONTEXT *ctx,void *keyenc, void *keydec,block128_f encrypt,block128_f decrypt);
+int CRYPTO_ocb128_copy_ctx(OCB128_CONTEXT *dest, OCB128_CONTEXT *src,
+ void *keyenc, void *keydec);
+int CRYPTO_ocb128_setiv(OCB128_CONTEXT *ctx, const unsigned char *iv,
+ size_t len, size_t taglen);
+int CRYPTO_ocb128_aad(OCB128_CONTEXT *ctx, const unsigned char *aad,
+ size_t len);
+int CRYPTO_ocb128_encrypt(OCB128_CONTEXT *ctx,
+ const unsigned char *in, unsigned char *out,
+ size_t len);
+int CRYPTO_ocb128_decrypt(OCB128_CONTEXT *ctx,
+ const unsigned char *in, unsigned char *out,
+ size_t len);
+int CRYPTO_ocb128_finish(OCB128_CONTEXT *ctx,const unsigned char *tag,
+ size_t len);
+int CRYPTO_ocb128_tag(OCB128_CONTEXT *ctx, unsigned char *tag, size_t len);
+void CRYPTO_ocb128_cleanup(OCB128_CONTEXT *ctx);
+#endif /* OPENSSL_NO_ECB */
+
#ifdef __cplusplus
}
#endif
diff --git a/crypto/modes/modes_lcl.h b/crypto/modes/modes_lcl.h
index 2d7015a..1d83155 100644
--- a/crypto/modes/modes_lcl.h
+++ b/crypto/modes/modes_lcl.h
@@ -136,3 +136,45 @@ struct ccm128_context {
void *key;
};
+#ifndef OPENSSL_NO_OCB
+
+#ifdef STRICT_ALIGNMENT
+typedef struct {
+ unsigned char a[16];
+} OCB_BLOCK;
+# define ocb_block16_xor(in1,in2,out) \
+ ocb_block_xor((in1)->a,(in2)->a,16,(out)->a)
+#else /* STRICT_ALIGNMENT */
+typedef struct {
+ u64 a;
+ u64 b;
+} OCB_BLOCK;
+# define ocb_block16_xor(in1,in2,out) \
+ (out)->a=(in1)->a^(in2)->a; (out)->b=(in1)->b^(in2)->b;
+#endif /* STRICT_ALIGNMENT */
+
+struct ocb128_context {
+ /* Need both encrypt and decrypt key schedules for decryption */
+ block128_f encrypt;
+ block128_f decrypt;
+ void *keyenc;
+ void *keydec;
+
+ /* Key dependent variables. Can be reused if key remains the same */
+ size_t l_index;
+ size_t max_l_index;
+ OCB_BLOCK l_star;
+ OCB_BLOCK l_dollar;
+ OCB_BLOCK *l;
+
+ /* Must be reset for each session */
+ u64 blocks_hashed;
+ u64 blocks_processed;
+ OCB_BLOCK tag;
+ OCB_BLOCK offset_aad;
+ OCB_BLOCK sum;
+ OCB_BLOCK offset;
+ OCB_BLOCK checksum;
+
+};
+#endif /* OPENSSL_NO_OCB */
diff --git a/crypto/modes/ocb128.c b/crypto/modes/ocb128.c
new file mode 100644
index 0000000..ef8b2f4
--- /dev/null
+++ b/crypto/modes/ocb128.c
@@ -0,0 +1,591 @@
+/* ====================================================================
+ * Copyright (c) 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core at openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include <string.h>
+#include <openssl/crypto.h>
+#include "modes_lcl.h"
+
+#ifndef OPENSSL_NO_OCB
+
+union ublock {
+ unsigned char *chrblk;
+ OCB_BLOCK *ocbblk;
+};
+
+/*
+ * Calculate the number of binary trailing zero's in any given number
+ */
+static u32 ocb_ntz(u64 n)
+{
+ u32 cnt = 0;
+
+ /*
+ * We do a right-to-left simple sequential search. This is surprisingly
+ * efficient as the distribution of trailing zeros is not uniform,
+ * e.g. the number of possible inputs with no trailing zeros is equal to
+ * the number with 1 or more; the number with exactly 1 is equal to the
+ * number with 2 or more, etc. Checking the last two bits covers 75% of
+ * all numbers. Checking the last three covers 87.5%
+ */
+ while (!(n & 1)) {
+ n >>= 1;
+ cnt++;
+ }
+ return cnt;
+}
+
+/*
+ * Shift a block of 16 bytes left by shift bits
+ */
+static void ocb_block_lshift(OCB_BLOCK *in, size_t shift, OCB_BLOCK *out)
+{
+ unsigned char shift_mask;
+ int i;
+ unsigned char mask[15];
+ union ublock locin;
+ union ublock locout;
+
+ locin.ocbblk = in;
+ locout.ocbblk = out;
+
+ shift_mask = 0xff;
+ shift_mask <<= (8 - shift);
+ for (i = 15; i >= 0; i--) {
+ if (i > 0) {
+ mask[i - 1] = locin.chrblk[i] & shift_mask;
+ mask[i - 1] >>= 8 - shift;
+ }
+ locout.chrblk[i] = locin.chrblk[i] << shift;
+
+ if (i != 15) {
+ locout.chrblk[i] ^= mask[i];
+ }
+ }
+}
+
+/*
+ * Perform a "double" operation as per OCB spec
+ */
+static void ocb_double(OCB_BLOCK *in, OCB_BLOCK *out)
+{
+ unsigned char mask;
+ union ublock locin;
+ union ublock locout;
+
+ locin.ocbblk = in;
+ locout.ocbblk = out;
+
+ /*
+ * Calculate the mask based on the most significant bit. There are more
+ * efficient ways to do this - but this way is constant time
+ */
+ mask = locin.chrblk[0] & 0x80;
+ mask >>= 7;
+ mask *= 135;
+
+ ocb_block_lshift(in, 1, out);
+
+ locout.chrblk[15] ^= mask;
+}
+
+/*
+ * Perform an xor on in1 and in2 - each of len bytes. Store result in out
+ */
+static void ocb_block_xor(const unsigned char *in1,
+ const unsigned char *in2, size_t len,
+ unsigned char *out)
+{
+ size_t i;
+ for (i = 0; i < len; i++) {
+ out[i] = in1[i] ^ in2[i];
+ }
+}
+
+/*
+ * Lookup L_index in our lookup table. If we haven't already got it we need to
+ * calculate it
+ */
+static OCB_BLOCK *ocb_lookup_l(OCB128_CONTEXT * ctx, size_t index)
+{
+ if (index <= ctx->l_index) {
+ return ctx->l + index;
+ }
+
+ /* We don't have it - so calculate it */
+ ctx->l_index++;
+ if (ctx->l_index == ctx->max_l_index) {
+ ctx->max_l_index *= 2;
+ ctx->l = OPENSSL_realloc(ctx->l, ctx->max_l_index * sizeof(OCB_BLOCK));
+ if (!ctx->l)
+ return NULL;
+ }
+ ocb_double(ctx->l + (index - 1), ctx->l + index);
+
+ return ctx->l + index;
+}
+
+/*
+ * Encrypt a block from |in| and store the result in |out|
+ */
+static void ocb_encrypt(OCB128_CONTEXT *ctx, OCB_BLOCK *in, OCB_BLOCK *out, void *keyenc)
+{
+ union ublock locin;
+ union ublock locout;
+
+ locin.ocbblk = in;
+ locout.ocbblk = out;
+
+ ctx->encrypt(locin.chrblk, locout.chrblk, keyenc);
+}
+
+/*
+ * Decrypt a block from |in| and store the result in |out|
+ */
+static void ocb_decrypt(OCB128_CONTEXT *ctx, OCB_BLOCK *in, OCB_BLOCK *out, void *keydec)
+{
+ union ublock locin;
+ union ublock locout;
+
+ locin.ocbblk = in;
+ locout.ocbblk = out;
+
+ ctx->decrypt(locin.chrblk, locout.chrblk, keydec);
+}
+
+/*
+ * Create a new OCB128_CONTEXT
+ */
+OCB128_CONTEXT *CRYPTO_ocb128_new(void *keyenc, void *keydec,
+ block128_f encrypt, block128_f decrypt)
+{
+ OCB128_CONTEXT *octx;
+ int ret;
+
+ if ((octx = (OCB128_CONTEXT *) OPENSSL_malloc(sizeof(OCB128_CONTEXT)))) {
+ ret = CRYPTO_ocb128_init(octx, keyenc, keydec, encrypt, decrypt);
+ if (ret)
+ return octx;
+ OPENSSL_free(octx);
+ }
+
+ return NULL;
+}
+
+/*
+ * Initialise an existing OCB128_CONTEXT
+ */
+int CRYPTO_ocb128_init(OCB128_CONTEXT *ctx, void *keyenc, void *keydec,
+ block128_f encrypt, block128_f decrypt)
+{
+ /* Clear everything to NULLs */
+ memset(ctx, 0, sizeof(*ctx));
+
+ ctx->l_index = 0;
+ ctx->max_l_index = 1;
+ ctx->l = OPENSSL_malloc(ctx->max_l_index * 16);
+ if (!ctx->l)
+ return 0;
+
+ /*
+ * We set both the encryption and decryption key schedules - decryption
+ * needs both. Don't really need decryption schedule if only doing
+ * encryption - but it simplifies things to take it anyway
+ */
+ ctx->encrypt = encrypt;
+ ctx->decrypt = decrypt;
+ ctx->keyenc = keyenc;
+ ctx->keydec = keydec;
+
+ /* L_* = ENCIPHER(K, zeros(128)) */
+ ocb_encrypt(ctx, &ctx->l_star, &ctx->l_star, ctx->keyenc);
+
+ /* L_$ = double(L_*) */
+ ocb_double(&ctx->l_star, &ctx->l_dollar);
+
+ /* L_0 = double(L_$) */
+ ocb_double(&ctx->l_dollar, ctx->l);
+
+ return 1;
+}
+
+/*
+ * Copy an OCB128_CONTEXT object
+ */
+int CRYPTO_ocb128_copy_ctx(OCB128_CONTEXT * dest, OCB128_CONTEXT * src,
+ void *keyenc, void *keydec)
+{
+ memcpy(dest, src, sizeof(OCB128_CONTEXT));
+ if (keyenc)
+ dest->keyenc = keyenc;
+ if (keydec)
+ dest->keydec = keydec;
+ if (src->l) {
+ dest->l = OPENSSL_malloc(src->max_l_index * 16);
+ if (!dest->l)
+ return 0;
+ memcpy(dest->l, src->l, (src->l_index + 1) * 16);
+ }
+ return 1;
+}
+
+/*
+ * Set the IV to be used for this operation. Must be 1 - 15 bytes.
+ */
+int CRYPTO_ocb128_setiv(OCB128_CONTEXT * ctx, const unsigned char *iv,
+ size_t len, size_t taglen)
+{
+ unsigned char ktop[16], tmp[16], mask;
+ unsigned char stretch[24], nonce[16];
+ size_t bottom, shift;
+ union ublock offset;
+
+ offset.ocbblk = &ctx->offset;
+
+ /*
+ * Spec says IV is 120 bits or fewer - it allows non byte aligned lengths.
+ * We don't support this at this stage
+ */
+ if ((len > 15) || (len < 1) || (taglen > 16) || (taglen < 1)) {
+ return -1;
+ }
+
+ /* Nonce = num2str(TAGLEN mod 128,7) || zeros(120-bitlen(N)) || 1 || N */
+ nonce[0] = ((taglen * 8) % 128) << 1;
+ memset(nonce + 1, 0, 15);
+ memcpy(nonce + 16 - len, iv, len);
+ nonce[15 - len] |= 1;
+
+ /* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) */
+ memcpy(tmp, nonce, 16);
+ tmp[15] &= 0xc0;
+ ctx->encrypt(tmp, ktop, ctx->keyenc);
+
+ /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */
+ memcpy(stretch, ktop, 16);
+ ocb_block_xor(ktop, ktop + 1, 8, stretch + 16);
+
+ /* bottom = str2num(Nonce[123..128]) */
+ bottom = nonce[15] & 0x3f;
+
+ /* Offset_0 = Stretch[1+bottom..128+bottom] */
+ shift = bottom % 8;
+ ocb_block_lshift((OCB_BLOCK *)(stretch + (bottom / 8)), shift, &ctx->offset);
+ mask = 0xff;
+ mask <<= 8 - shift;
+ offset.chrblk[15] |= (*(stretch + (bottom / 8) + 16) & mask) >> (8 - shift);
+
+ return 1;
+}
+
+/*
+ * Provide any AAD. This can be called multiple times. Only the final time can
+ * have a partial block
+ */
+int CRYPTO_ocb128_aad(OCB128_CONTEXT * ctx, const unsigned char *aad,
+ size_t len)
+{
+ u64 all_num_blocks, num_blocks;
+ u64 i;
+ OCB_BLOCK tmp1;
+ OCB_BLOCK tmp2;
+ int last_len;
+
+ /* Calculate the number of blocks of AAD provided now, and so far */
+ num_blocks = len / 16;
+ all_num_blocks = num_blocks + ctx->blocks_hashed;
+
+ /* Loop through all full blocks of AAD */
+ for (i = ctx->blocks_hashed + 1; i <= all_num_blocks; i++) {
+ OCB_BLOCK *lookup;
+ OCB_BLOCK *aad_block;
+
+ /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+ lookup = ocb_lookup_l(ctx, ocb_ntz(i));
+ if (!lookup)
+ return 0;
+ ocb_block16_xor(&ctx->offset_aad, lookup, &ctx->offset_aad);
+
+ /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */
+ aad_block = (OCB_BLOCK *) (aad + ((i - ctx->blocks_hashed - 1) * 16));
+ ocb_block16_xor(&ctx->offset_aad, aad_block, &tmp1);
+ ocb_encrypt(ctx, &tmp1, &tmp2, ctx->keyenc);
+ ocb_block16_xor(&ctx->sum, &tmp2, &ctx->sum);
+ }
+
+ /*
+ * Check if we have any partial blocks left over. This is only valid in the
+ * last call to this function
+ */
+ last_len = len % 16;
+
+ if (last_len > 0) {
+ /* Offset_* = Offset_m xor L_* */
+ ocb_block16_xor(&ctx->offset_aad, &ctx->l_star, &ctx->offset_aad);
+
+ /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */
+ memset((void *)&tmp1, 0, 16);
+ memcpy((void *)&tmp1, aad + (num_blocks * 16), last_len);
+ ((unsigned char *)&tmp1)[last_len] = 0x80;
+ ocb_block16_xor(&ctx->offset_aad, &tmp1, &tmp2);
+
+ /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */
+ ocb_encrypt(ctx, &tmp2, &tmp1, ctx->keyenc);
+ ocb_block16_xor(&ctx->sum, &tmp1, &ctx->sum);
+ }
+
+ ctx->blocks_hashed = all_num_blocks;
+
+ return 1;
+}
+
+/*
+ * Provide any data to be encrypted. This can be called multiple times. Only
+ * the final time can have a partial block
+ */
+int CRYPTO_ocb128_encrypt(OCB128_CONTEXT * ctx,
+ const unsigned char *in, unsigned char *out,
+ size_t len)
+{
+ u64 i;
+ u64 all_num_blocks, num_blocks;
+ OCB_BLOCK tmp1;
+ OCB_BLOCK tmp2;
+ OCB_BLOCK pad;
+ int last_len;
+
+ /*
+ * Calculate the number of blocks of data to be encrypted provided now, and
+ * so far
+ */
+ num_blocks = len / 16;
+ all_num_blocks = num_blocks + ctx->blocks_processed;
+
+ /* Loop through all full blocks to be encrypted */
+ for (i = ctx->blocks_processed + 1; i <= all_num_blocks; i++) {
+ OCB_BLOCK *lookup;
+ OCB_BLOCK *inblock;
+ OCB_BLOCK *outblock;
+
+ /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+ lookup = ocb_lookup_l(ctx, ocb_ntz(i));
+ if (!lookup)
+ return 0;
+ ocb_block16_xor(&ctx->offset, lookup, &ctx->offset);
+
+ /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
+ inblock = (OCB_BLOCK *) (in + ((i - ctx->blocks_processed - 1) * 16));
+ ocb_block16_xor(&ctx->offset, inblock, &tmp1);
+ ocb_encrypt(ctx, &tmp1, &tmp2, ctx->keyenc);
+ outblock =
+ (OCB_BLOCK *) (out + ((i - ctx->blocks_processed - 1) * 16));
+ ocb_block16_xor(&ctx->offset, &tmp2, outblock);
+
+ /* Checksum_i = Checksum_{i-1} xor P_i */
+ ocb_block16_xor(&ctx->checksum, inblock, &ctx->checksum);
+ }
+
+ /*
+ * Check if we have any partial blocks left over. This is only valid in the
+ * last call to this function
+ */
+ last_len = len % 16;
+
+ if (last_len > 0) {
+ /* Offset_* = Offset_m xor L_* */
+ ocb_block16_xor(&ctx->offset, &ctx->l_star, &ctx->offset);
+
+ /* Pad = ENCIPHER(K, Offset_*) */
+ ocb_encrypt(ctx, &ctx->offset, &pad, ctx->keyenc);
+
+ /* C_* = P_* xor Pad[1..bitlen(P_*)] */
+ ocb_block_xor(in + (len / 16) * 16, (unsigned char *)&pad, last_len,
+ out + (num_blocks * 16));
+
+ /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
+ memset((void *)&tmp1, 0, 16);
+ memcpy((void *)&tmp1, in + (len / 16) * 16, last_len);
+ ((unsigned char *)(&tmp1))[last_len] = 0x80;
+ ocb_block16_xor(&ctx->checksum, &tmp1, &ctx->checksum);
+ }
+
+ ctx->blocks_processed = all_num_blocks;
+
+ return 1;
+}
+
+/*
+ * Provide any data to be decrypted. This can be called multiple times. Only
+ * the final time can have a partial block
+ */
+int CRYPTO_ocb128_decrypt(OCB128_CONTEXT * ctx,
+ const unsigned char *in, unsigned char *out,
+ size_t len)
+{
+ u64 i;
+ u64 all_num_blocks, num_blocks;
+ OCB_BLOCK tmp1;
+ OCB_BLOCK tmp2;
+ OCB_BLOCK pad;
+ int last_len;
+ /*
+ * Calculate the number of blocks of data to be decrypted provided now, and
+ * so far
+ */
+ num_blocks = len / 16;
+ all_num_blocks = num_blocks + ctx->blocks_processed;
+
+ /* Loop through all full blocks to be decrypted */
+ for (i = ctx->blocks_processed + 1; i <= all_num_blocks; i++) {
+ OCB_BLOCK *inblock;
+ OCB_BLOCK *outblock;
+
+ /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+ OCB_BLOCK *lookup = ocb_lookup_l(ctx, ocb_ntz(i));
+ if (!lookup)
+ return 0;
+ ocb_block16_xor(&ctx->offset, lookup, &ctx->offset);
+
+ /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */
+ inblock = (OCB_BLOCK *) (in + ((i - ctx->blocks_processed - 1) * 16));
+ ocb_block16_xor(&ctx->offset, inblock, &tmp1);
+ ocb_decrypt(ctx, &tmp1, &tmp2, ctx->keydec);
+ outblock = (OCB_BLOCK *) (out + ((i - ctx->blocks_processed - 1) * 16));
+ ocb_block16_xor(&ctx->offset, &tmp2, outblock);
+
+ /* Checksum_i = Checksum_{i-1} xor P_i */
+ ocb_block16_xor(&ctx->checksum, outblock, &ctx->checksum);
+ }
+
+ /*
+ * Check if we have any partial blocks left over. This is only valid in the
+ * last call to this function
+ */
+ last_len = len % 16;
+
+ if (last_len > 0) {
+ /* Offset_* = Offset_m xor L_* */
+ ocb_block16_xor(&ctx->offset, &ctx->l_star, &ctx->offset);
+
+ /* Pad = ENCIPHER(K, Offset_*) */
+ ocb_encrypt(ctx, &ctx->offset, &pad, ctx->keyenc);
+
+ /* P_* = C_* xor Pad[1..bitlen(C_*)] */
+ ocb_block_xor(in + (len / 16) * 16, (unsigned char *)&pad, last_len,
+ out + (num_blocks * 16));
+
+ /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
+ memset((void *)&tmp1, 0, 16);
+ memcpy((void *)&tmp1, out + (len / 16) * 16, last_len);
+ ((unsigned char *)(&tmp1))[last_len] = 0x80;
+ ocb_block16_xor(&ctx->checksum, &tmp1, &ctx->checksum);
+ }
+
+ ctx->blocks_processed = all_num_blocks;
+
+ return 1;
+}
+
+/*
+ * Calculate the tag and verify it against the supplied tag
+ */
+int CRYPTO_ocb128_finish(OCB128_CONTEXT * ctx, const unsigned char *tag,
+ size_t len)
+{
+ OCB_BLOCK tmp1, tmp2;
+
+ /*Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */
+ ocb_block16_xor(&ctx->checksum, &ctx->offset, &tmp1);
+ ocb_block16_xor(&tmp1, &ctx->l_dollar, &tmp2);
+ ocb_encrypt(ctx, &tmp2, &tmp1, ctx->keyenc);
+ ocb_block16_xor(&tmp1, &ctx->sum, &ctx->tag);
+
+ if (len > 16 || len < 1) {
+ return -1;
+ }
+
+ /* Compare the tag if we've been given one */
+ if (tag)
+ return CRYPTO_memcmp(&ctx->tag, tag, len);
+ else
+ return -1;
+}
+
+/*
+ * Retrieve the calculated tag
+ */
+int CRYPTO_ocb128_tag(OCB128_CONTEXT * ctx, unsigned char *tag, size_t len)
+{
+ if (len > 16 || len < 1) {
+ return -1;
+ }
+
+ /* Calculate the tag */
+ CRYPTO_ocb128_finish(ctx, NULL, 0);
+
+ /* Copy the tag into the supplied buffer */
+ memcpy(tag, &ctx->tag, len);
+
+ return 1;
+}
+
+/*
+ * Release all resources
+ */
+void CRYPTO_ocb128_cleanup(OCB128_CONTEXT * ctx)
+{
+ if (ctx) {
+ if (ctx->l) {
+ OPENSSL_cleanse(ctx->l, ctx->max_l_index * 16);
+ OPENSSL_free(ctx->l);
+ }
+ OPENSSL_cleanse(ctx, sizeof(*ctx));
+ }
+}
+
+#endif /* OPENSSL_NO_OCB */
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index b7e3cf2..e93e1b0 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -62,9 +62,9 @@
* [including the GNU Public Licence.]
*/
-#define NUM_NID 958
-#define NUM_SN 951
-#define NUM_LN 951
+#define NUM_NID 961
+#define NUM_SN 954
+#define NUM_LN 954
#define NUM_OBJ 890
static const unsigned char lvalues[6255]={
@@ -2514,6 +2514,9 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={
NID_jurisdictionStateOrProvinceName,11,&(lvalues[6232]),0},
{"jurisdictionC","jurisdictionCountryName",
NID_jurisdictionCountryName,11,&(lvalues[6243]),0},
+{"AES-128-OCB","aes-128-ocb",NID_aes_128_ocb,0,NULL,0},
+{"AES-192-OCB","aes-192-ocb",NID_aes_192_ocb,0,NULL,0},
+{"AES-256-OCB","aes-256-ocb",NID_aes_256_ocb,0,NULL,0},
};
static const unsigned int sn_objs[NUM_SN]={
@@ -2526,6 +2529,7 @@ static const unsigned int sn_objs[NUM_SN]={
653, /* "AES-128-CFB8" */
904, /* "AES-128-CTR" */
418, /* "AES-128-ECB" */
+958, /* "AES-128-OCB" */
420, /* "AES-128-OFB" */
913, /* "AES-128-XTS" */
423, /* "AES-192-CBC" */
@@ -2536,6 +2540,7 @@ static const unsigned int sn_objs[NUM_SN]={
654, /* "AES-192-CFB8" */
905, /* "AES-192-CTR" */
422, /* "AES-192-ECB" */
+959, /* "AES-192-OCB" */
424, /* "AES-192-OFB" */
427, /* "AES-256-CBC" */
918, /* "AES-256-CBC-HMAC-SHA1" */
@@ -2545,6 +2550,7 @@ static const unsigned int sn_objs[NUM_SN]={
655, /* "AES-256-CFB8" */
906, /* "AES-256-CTR" */
426, /* "AES-256-ECB" */
+960, /* "AES-256-OCB" */
428, /* "AES-256-OFB" */
914, /* "AES-256-XTS" */
91, /* "BF-CBC" */
@@ -3629,6 +3635,7 @@ static const unsigned int ln_objs[NUM_LN]={
904, /* "aes-128-ctr" */
418, /* "aes-128-ecb" */
895, /* "aes-128-gcm" */
+958, /* "aes-128-ocb" */
420, /* "aes-128-ofb" */
913, /* "aes-128-xts" */
423, /* "aes-192-cbc" */
@@ -3641,6 +3648,7 @@ static const unsigned int ln_objs[NUM_LN]={
905, /* "aes-192-ctr" */
422, /* "aes-192-ecb" */
898, /* "aes-192-gcm" */
+959, /* "aes-192-ocb" */
424, /* "aes-192-ofb" */
427, /* "aes-256-cbc" */
918, /* "aes-256-cbc-hmac-sha1" */
@@ -3652,6 +3660,7 @@ static const unsigned int ln_objs[NUM_LN]={
906, /* "aes-256-ctr" */
426, /* "aes-256-ecb" */
901, /* "aes-256-gcm" */
+960, /* "aes-256-ocb" */
428, /* "aes-256-ofb" */
914, /* "aes-256-xts" */
376, /* "algorithm" */
diff --git a/crypto/objects/obj_mac.h b/crypto/objects/obj_mac.h
index f0690b0..0ce54a8 100644
--- a/crypto/objects/obj_mac.h
+++ b/crypto/objects/obj_mac.h
@@ -2745,6 +2745,18 @@
#define LN_aes_256_ctr "aes-256-ctr"
#define NID_aes_256_ctr 906
+#define SN_aes_128_ocb "AES-128-OCB"
+#define LN_aes_128_ocb "aes-128-ocb"
+#define NID_aes_128_ocb 958
+
+#define SN_aes_192_ocb "AES-192-OCB"
+#define LN_aes_192_ocb "aes-192-ocb"
+#define NID_aes_192_ocb 959
+
+#define SN_aes_256_ocb "AES-256-OCB"
+#define LN_aes_256_ocb "aes-256-ocb"
+#define NID_aes_256_ocb 960
+
#define SN_aes_128_xts "AES-128-XTS"
#define LN_aes_128_xts "aes-128-xts"
#define NID_aes_128_xts 913
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index 8e5ea83..648e2df 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -955,3 +955,6 @@ ct_cert_scts 954
jurisdictionLocalityName 955
jurisdictionStateOrProvinceName 956
jurisdictionCountryName 957
+aes_128_ocb 958
+aes_192_ocb 959
+aes_256_ocb 960
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index b57aabb..a4af282 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -894,6 +894,9 @@ aes 48 : id-aes256-wrap-pad
: AES-128-CTR : aes-128-ctr
: AES-192-CTR : aes-192-ctr
: AES-256-CTR : aes-256-ctr
+ : AES-128-OCB : aes-128-ocb
+ : AES-192-OCB : aes-192-ocb
+ : AES-256-OCB : aes-256-ocb
: AES-128-XTS : aes-128-xts
: AES-256-XTS : aes-256-xts
: DES-CFB1 : des-cfb1
diff --git a/doc/crypto/EVP_EncryptInit.pod b/doc/crypto/EVP_EncryptInit.pod
index ea166bf..524921f 100644
--- a/doc/crypto/EVP_EncryptInit.pod
+++ b/doc/crypto/EVP_EncryptInit.pod
@@ -368,7 +368,13 @@ bits and 12 rounds.
AES Galois Counter Mode (GCM) for 128, 192 and 256 bit keys respectively.
These ciphers require additional control operations to function correctly: see
-L<GCM mode> section below for details.
+the L<GCM and OCB modes> section below for details.
+
+=item EVP_aes_128_ocb(void), EVP_aes_192_ocb(void), EVP_aes_256_ocb(void)
+
+Offest Codebook Mode (OCB) for 128, 192 and 256 bit keys respectively.
+These ciphers require additional control operations to function correctly: see
+the L<GCM and OCB modes> section below for details.
=item EVP_aes_128_ccm(), EVP_aes_192_ccm(), EVP_aes_256_ccm()
@@ -378,10 +384,10 @@ CCM mode section below for details.
=back
-=head1 GCM Mode
+=head1 GCM and OCB Modes
-For GCM mode ciphers the behaviour of the EVP interface is subtly altered and
-several GCM specific ctrl operations are supported.
+For GCM and OCB mode ciphers the behaviour of the EVP interface is subtly
+altered and several additional ctrl operations are supported.
To specify any additional authenticated data (AAD) a call to EVP_CipherUpdate(),
EVP_EncryptUpdate() or EVP_DecryptUpdate() should be made with the output
@@ -392,24 +398,35 @@ indicates if the operation was successful. If it does not indicate success
the authentication operation has failed and any output data B<MUST NOT>
be used as it is corrupted.
-The following ctrls are supported in GCM mode:
+The following ctrl is supported in OCB mode only:
+
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_OCB_SET_TAGLEN, taglen, NULL);
+
+Sets the tag length: this call can only be made before specifying an IV. If
+not called a default tag length is used. For OCB AES the default is 16 (i.e. 128
+bits). This is also the maximum tag length.
+
+The following ctrls are supported in both GCM and OCB modes:
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, ivlen, NULL);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_IVLEN, ivlen, NULL);
-Sets the GCM IV length: this call can only be made before specifying an IV. If
-not called a default IV length is used (96 bits for AES).
+Sets the IV length: this call can only be made before specifying an IV. If
+not called a default IV length is used. For GCM AES and OCB AES the default is
+12 (i.e. 96 bits). For OCB mode the maximum is 15.
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, taglen, tag);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GET_TAG, taglen, tag);
Writes B<taglen> bytes of the tag value to the buffer indicated by B<tag>.
This call can only be made when encrypting data and B<after> all data has been
-processed (e.g. after an EVP_EncryptFinal() call).
+processed (e.g. after an EVP_EncryptFinal() call). For OCB mode the taglen must
+either be 16 or the value previously set via EVP_CTRL_OCB_SET_TAGLEN.
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, taglen, tag);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_TAG, taglen, tag);
Sets the expected tag to B<taglen> bytes from B<tag>. This call is only legal
when decrypting data and must be made B<before> any data is processed (e.g.
-before any EVP_DecryptUpdate() call).
+before any EVP_DecryptUpdate() call). For OCB mode the taglen must
+either be 16 or the value previously set via EVP_CTRL_OCB_SET_TAGLEN.
See L<EXAMPLES> below for an example of the use of GCM mode.
@@ -418,7 +435,7 @@ See L<EXAMPLES> below for an example of the use of GCM mode.
The behaviour of CCM mode ciphers is similar to CCM mode but with a few
additional requirements and different ctrl values.
-Like GCM mode any additional authenticated data (AAD) is passed by calling
+Like GCM and OCB modes any additional authenticated data (AAD) is passed by calling
EVP_CipherUpdate(), EVP_EncryptUpdate() or EVP_DecryptUpdate() with the output
parameter B<out> set to B<NULL>. Additionally the total plaintext or ciphertext
length B<MUST> be passed to EVP_CipherUpdate(), EVP_EncryptUpdate() or
@@ -607,4 +624,5 @@ OpenSSL 0.9.7.
IDEA appeared in OpenSSL 0.9.7 but was often disabled due to
patent concerns; the last patents expired in 2012.
+Support for OCB mode was added in OpenSSL 1.1.0
=cut
diff --git a/util/libeay.num b/util/libeay.num
index 5dd8b58..4d813e8 100755
--- a/util/libeay.num
+++ b/util/libeay.num
@@ -4514,3 +4514,15 @@ i2s_ASN1_IA5STRING 4874 EXIST::FUNCTION:
s2i_ASN1_IA5STRING 4875 EXIST::FUNCTION:
FIPS_dsa_sign_ctx 4876 EXIST:OPENSSL_FIPS:FUNCTION:DSA
FIPS_ecdsa_sign 4877 EXIST:OPENSSL_FIPS:FUNCTION:ECDSA
+CRYPTO_ocb128_release 4878 EXIST::FUNCTION:
+CRYPTO_ocb128_new 4879 EXIST::FUNCTION:
+CRYPTO_ocb128_finish 4880 EXIST::FUNCTION:
+EVP_aes_256_ocb 4881 EXIST::FUNCTION:AES
+CRYPTO_ocb128_setiv 4882 EXIST::FUNCTION:
+CRYPTO_ocb128_aad 4883 EXIST::FUNCTION:
+CRYPTO_ocb128_decrypt 4884 EXIST::FUNCTION:
+CRYPTO_ocb128_tag 4885 EXIST::FUNCTION:
+EVP_aes_192_ocb 4886 EXIST::FUNCTION:AES
+EVP_aes_128_ocb 4887 EXIST::FUNCTION:AES
+CRYPTO_ocb128_init 4888 EXIST::FUNCTION:
+CRYPTO_ocb128_encrypt 4889 EXIST::FUNCTION:
hooks/post-receive
--
OpenSSL source code
More information about the openssl-commits
mailing list