summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorTodd Short <tshort@akamai.com>2017-05-19 10:27:28 -0400
committerPauli <paul.dale@oracle.com>2018-12-12 08:16:10 +1000
commitb1ceb439f234a998db84f27a3a245dab95d322ab (patch)
tree98dbc974b4a6119fe88c01ae0a4017b13fa10e93 /crypto
parent6de98b4fb6265f8a4b2e5b599d6714ff937dca6b (diff)
Add RFC5297 AES-SIV support
Based originally on github.com/dfoxfranke/libaes_siv This creates an SIV128 mode that uses EVP interfaces for the CBC, CTR and CMAC code to reduce complexity at the cost of perfomance. The expected use is for short inputs, not TLS-sized records. Add multiple AAD input capacity in the EVP tests. Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/3540)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/evp/c_allc.c6
-rw-r--r--crypto/evp/e_aes.c127
-rw-r--r--crypto/modes/build.info2
-rw-r--r--crypto/modes/modes_lcl.h25
-rw-r--r--crypto/modes/siv128.c349
-rw-r--r--crypto/objects/obj_dat.h15
-rw-r--r--crypto/objects/obj_mac.num3
-rw-r--r--crypto/objects/objects.txt5
8 files changed, 521 insertions, 11 deletions
diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c
index 4a803e6dc6..a97eaa1685 100644
--- a/crypto/evp/c_allc.c
+++ b/crypto/evp/c_allc.c
@@ -190,7 +190,11 @@ void openssl_add_all_ciphers_int(void)
EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1());
EVP_add_cipher(EVP_aes_128_cbc_hmac_sha256());
EVP_add_cipher(EVP_aes_256_cbc_hmac_sha256());
-
+#ifndef OPENSSL_NO_SIV
+ EVP_add_cipher(EVP_aes_128_siv());
+ EVP_add_cipher(EVP_aes_192_siv());
+ EVP_add_cipher(EVP_aes_256_siv());
+#endif
#ifndef OPENSSL_NO_ARIA
EVP_add_cipher(EVP_aria_128_ecb());
EVP_add_cipher(EVP_aria_128_cbc());
diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c
index 09f6598b6c..a882f2170a 100644
--- a/crypto/evp/e_aes.c
+++ b/crypto/evp/e_aes.c
@@ -17,6 +17,7 @@
#include "internal/evp_int.h"
#include "modes_lcl.h"
#include <openssl/rand.h>
+#include <openssl/cmac.h>
#include "evp_locl.h"
typedef struct {
@@ -540,7 +541,8 @@ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
static const EVP_CIPHER aesni_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
- (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
+ ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aesni_##mode##_init_key, \
aesni_##mode##_cipher, \
@@ -549,7 +551,8 @@ static const EVP_CIPHER aesni_##keylen##_##mode = { \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
- (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
+ ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
@@ -948,7 +951,8 @@ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
- (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
+ ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_t4_##mode##_init_key, \
aes_t4_##mode##_cipher, \
@@ -957,7 +961,8 @@ static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
- (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
+ ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
@@ -2512,7 +2517,8 @@ const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
# 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, \
+ (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE||EVP_CIPH_##MODE##_MODE==EVP_CIPH_SIV_MODE?2:1)*keylen/8, \
+ ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
@@ -4263,3 +4269,114 @@ BLOCK_CIPHER_custom(NID_aes, 192, 16, 12, ocb, OCB,
BLOCK_CIPHER_custom(NID_aes, 256, 16, 12, ocb, OCB,
EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
#endif /* OPENSSL_NO_OCB */
+
+/* AES-SIV mode */
+#ifndef OPENSSL_NO_SIV
+
+typedef SIV128_CONTEXT EVP_AES_SIV_CTX;
+
+#define aesni_siv_init_key aes_siv_init_key
+static int aes_siv_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ const EVP_CIPHER *ctr;
+ const EVP_CIPHER *cbc;
+ SIV128_CONTEXT *sctx = EVP_C_DATA(SIV128_CONTEXT, ctx);
+ int klen = EVP_CIPHER_CTX_key_length(ctx) / 2;
+
+ if (key == NULL)
+ return 1;
+
+ switch (klen) {
+ case 16:
+ cbc = EVP_aes_128_cbc();
+ ctr = EVP_aes_128_ctr();
+ break;
+ case 24:
+ cbc = EVP_aes_192_cbc();
+ ctr = EVP_aes_192_ctr();
+ break;
+ case 32:
+ cbc = EVP_aes_256_cbc();
+ ctr = EVP_aes_256_ctr();
+ break;
+ default:
+ return 0;
+ }
+
+ /* klen is the length of the underlying cipher, not the input key,
+ which should be twice as long */
+ return CRYPTO_siv128_init(sctx, key, klen, cbc, ctr);
+}
+
+#define aesni_siv_cipher aes_siv_cipher
+static int aes_siv_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t len)
+{
+ SIV128_CONTEXT *sctx = EVP_C_DATA(SIV128_CONTEXT, ctx);
+
+ /* EncryptFinal or DecryptFinal */
+ if (in == NULL)
+ return CRYPTO_siv128_finish(sctx);
+
+ /* Deal with associated data */
+ if (out == NULL)
+ return CRYPTO_siv128_aad(sctx, in, len);
+
+ if (EVP_CIPHER_CTX_encrypting(ctx))
+ return CRYPTO_siv128_encrypt(sctx, in, out, len);
+
+ return CRYPTO_siv128_decrypt(sctx, in, out, len);
+}
+
+#define aesni_siv_cleanup aes_siv_cleanup
+static int aes_siv_cleanup(EVP_CIPHER_CTX *c)
+{
+ SIV128_CONTEXT *sctx = EVP_C_DATA(SIV128_CONTEXT, c);
+
+ return CRYPTO_siv128_cleanup(sctx);
+}
+
+
+#define aesni_siv_ctrl aes_siv_ctrl
+static int aes_siv_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+{
+ SIV128_CONTEXT *sctx = EVP_C_DATA(SIV128_CONTEXT, c);
+ SIV128_CONTEXT *sctx_out;
+
+ switch (type) {
+ case EVP_CTRL_INIT:
+ return CRYPTO_siv128_cleanup(sctx);
+
+ case EVP_CTRL_SET_SPEED:
+ return CRYPTO_siv128_speed(sctx, arg);
+
+ case EVP_CTRL_AEAD_SET_TAG:
+ if (!EVP_CIPHER_CTX_encrypting(c))
+ return CRYPTO_siv128_set_tag(sctx, ptr, arg);
+ return 1;
+
+ case EVP_CTRL_AEAD_GET_TAG:
+ if (!EVP_CIPHER_CTX_encrypting(c))
+ return 0;
+ return CRYPTO_siv128_get_tag(sctx, ptr, arg);
+
+ case EVP_CTRL_COPY:
+ sctx_out = EVP_C_DATA(SIV128_CONTEXT, (EVP_CIPHER_CTX*)ptr);
+ return CRYPTO_siv128_copy_ctx(sctx_out, sctx);
+
+ default:
+ return -1;
+
+ }
+}
+
+#define SIV_FLAGS (EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_DEFAULT_ASN1 \
+ | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
+ | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_COPY \
+ | EVP_CIPH_CTRL_INIT)
+
+BLOCK_CIPHER_custom(NID_aes, 128, 1, 0, siv, SIV, SIV_FLAGS)
+BLOCK_CIPHER_custom(NID_aes, 192, 1, 0, siv, SIV, SIV_FLAGS)
+BLOCK_CIPHER_custom(NID_aes, 256, 1, 0, siv, SIV, SIV_FLAGS)
+#endif
diff --git a/crypto/modes/build.info b/crypto/modes/build.info
index 821340eb90..1820ab26ba 100644
--- a/crypto/modes/build.info
+++ b/crypto/modes/build.info
@@ -1,7 +1,7 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
cbc128.c ctr128.c cts128.c cfb128.c ofb128.c gcm128.c \
- ccm128.c xts128.c wrap128.c ocb128.c \
+ ccm128.c xts128.c wrap128.c ocb128.c siv128.c \
{- $target{modes_asm_src} -}
INCLUDE[gcm128.o]=..
diff --git a/crypto/modes/modes_lcl.h b/crypto/modes/modes_lcl.h
index 0215bbdedd..d042d30016 100644
--- a/crypto/modes/modes_lcl.h
+++ b/crypto/modes/modes_lcl.h
@@ -188,3 +188,28 @@ struct ocb128_context {
} sess;
};
#endif /* OPENSSL_NO_OCB */
+
+#ifndef OPENSSL_NO_SIV
+
+#include <openssl/cmac.h>
+
+#define SIV_LEN 16
+
+typedef union siv_block_u {
+ uint64_t word[SIV_LEN/sizeof(uint64_t)];
+ unsigned char byte[SIV_LEN];
+} SIV_BLOCK;
+
+struct siv128_context {
+ /* d stores intermediate results of S2V; it corresponds to D from the
+ pseudocode in section 2.4 of RFC 5297. */
+ SIV_BLOCK d;
+ SIV_BLOCK tag;
+ EVP_CIPHER_CTX *cipher_ctx;
+ CMAC_CTX *cmac_ctx_init;
+ CMAC_CTX *cmac_ctx;
+ int final_ret;
+ int crypto_ok;
+};
+
+#endif /* OPENSSL_NO_SIV */
diff --git a/crypto/modes/siv128.c b/crypto/modes/siv128.c
new file mode 100644
index 0000000000..f4d07d514a
--- /dev/null
+++ b/crypto/modes/siv128.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <openssl/crypto.h>
+#include <openssl/cmac.h>
+#include "modes_lcl.h"
+
+#ifndef OPENSSL_NO_SIV
+
+__owur static ossl_inline uint32_t rotl8(uint32_t x)
+{
+ return (x << 8) | (x >> 24);
+}
+
+__owur static ossl_inline uint32_t rotr8(uint32_t x)
+{
+ return (x >> 8) | (x << 24);
+}
+
+__owur static ossl_inline uint64_t byteswap8(uint64_t x)
+{
+ uint32_t high = (uint32_t)(x >> 32);
+ uint32_t low = (uint32_t)x;
+
+ high = (rotl8(high) & 0x00ff00ff) | (rotr8(high) & 0xff00ff00);
+ low = (rotl8(low) & 0x00ff00ff) | (rotr8(low) & 0xff00ff00);
+ return ((uint64_t)low) << 32 | (uint64_t)high;
+}
+
+__owur static ossl_inline uint64_t siv128_getword(SIV_BLOCK const *b, size_t i)
+{
+ const union {
+ long one;
+ char little;
+ } is_endian = { 1 };
+
+ if (is_endian.little)
+ return byteswap8(b->word[i]);
+ return b->word[i];
+}
+
+static ossl_inline void siv128_putword(SIV_BLOCK *b, size_t i, uint64_t x)
+{
+ const union {
+ long one;
+ char little;
+ } is_endian = { 1 };
+
+ if (is_endian.little)
+ b->word[i] = byteswap8(x);
+ else
+ b->word[i] = x;
+}
+
+static ossl_inline void siv128_xorblock(SIV_BLOCK *x,
+ SIV_BLOCK const *y)
+{
+ x->word[0] ^= y->word[0];
+ x->word[1] ^= y->word[1];
+}
+
+/*
+ * Doubles |b|, which is 16 bytes representing an element
+ * of GF(2**128) modulo the irreducible polynomial
+ * x**128 + x**7 + x**2 + x + 1.
+ * Assumes two's-complement arithmetic
+ */
+static ossl_inline void siv128_dbl(SIV_BLOCK *b)
+{
+ uint64_t high = siv128_getword(b, 0);
+ uint64_t low = siv128_getword(b, 1);
+ uint64_t high_carry = high & (((uint64_t)1) << 63);
+ uint64_t low_carry = low & (((uint64_t)1) << 63);
+ int64_t low_mask = -((int64_t)(high_carry >> 63)) & 0x87;
+ uint64_t high_mask = low_carry >> 63;
+
+ high = (high << 1) | high_mask;
+ low = (low << 1) ^ (uint64_t)low_mask;
+ siv128_putword(b, 0, high);
+ siv128_putword(b, 1, low);
+}
+
+__owur static ossl_inline int siv128_do_s2v_p(SIV128_CONTEXT *ctx, SIV_BLOCK *out,
+ unsigned char const* in, size_t len)
+{
+ SIV_BLOCK t;
+ size_t out_len = sizeof(out->byte);
+
+ if (!CMAC_CTX_copy(ctx->cmac_ctx, ctx->cmac_ctx_init))
+ return 0;
+
+ if (len >= SIV_LEN) {
+ if (!CMAC_Update(ctx->cmac_ctx, in, len - SIV_LEN))
+ return 0;
+ memcpy(&t, in + (len-SIV_LEN), SIV_LEN);
+ siv128_xorblock(&t, &ctx->d);
+ if (!CMAC_Update(ctx->cmac_ctx, t.byte, SIV_LEN))
+ return 0;
+ } else {
+ memset(&t, 0, sizeof(t));
+ memcpy(&t, in, len);
+ t.byte[len] = 0x80;
+ siv128_dbl(&ctx->d);
+ siv128_xorblock(&t, &ctx->d);
+ if (!CMAC_Update(ctx->cmac_ctx, t.byte, SIV_LEN))
+ return 0;
+ }
+ if (!CMAC_Final(ctx->cmac_ctx, out->byte, &out_len)
+ || out_len != SIV_LEN)
+ return 0;
+ return 1;
+}
+
+
+__owur static ossl_inline int siv128_do_encrypt(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ unsigned char const *in, size_t len,
+ SIV_BLOCK *icv)
+{
+ int out_len = (int)len;
+
+ if (!EVP_CipherInit_ex(ctx, NULL, NULL, NULL, icv->byte, 1))
+ return 0;
+ return EVP_EncryptUpdate(ctx, out, &out_len, in, out_len);
+}
+
+/*
+ * Create a new SIV128_CONTEXT
+ */
+SIV128_CONTEXT *CRYPTO_siv128_new(const unsigned char *key, int klen, EVP_CIPHER* cbc, EVP_CIPHER* ctr)
+{
+ SIV128_CONTEXT *ctx;
+ int ret;
+
+ if ((ctx = OPENSSL_malloc(sizeof(*ctx))) != NULL) {
+ ret = CRYPTO_siv128_init(ctx, key, klen, cbc, ctr);
+ if (ret)
+ return ctx;
+ OPENSSL_free(ctx);
+ }
+
+ return NULL;
+}
+
+/*
+ * Initialise an existing SIV128_CONTEXT
+ */
+int CRYPTO_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen,
+ const EVP_CIPHER* cbc, const EVP_CIPHER* ctr)
+{
+ static const unsigned char zero[SIV_LEN] = { 0 };
+ size_t out_len = SIV_LEN;
+
+ memset(&ctx->d, 0, sizeof(ctx->d));
+ ctx->cipher_ctx = NULL;
+ ctx->cmac_ctx = NULL;
+ ctx->cmac_ctx_init = NULL;
+
+ if (key == NULL || cbc == NULL || ctr == NULL
+ || (ctx->cipher_ctx = EVP_CIPHER_CTX_new()) == NULL
+ || (ctx->cmac_ctx_init = CMAC_CTX_new()) == NULL
+ || (ctx->cmac_ctx = CMAC_CTX_new()) == NULL
+ || !CMAC_Init(ctx->cmac_ctx_init, key, klen, cbc, NULL)
+ || !EVP_EncryptInit_ex(ctx->cipher_ctx, ctr, NULL, key + klen, NULL)
+ || !CMAC_CTX_copy(ctx->cmac_ctx, ctx->cmac_ctx_init)
+ || !CMAC_Update(ctx->cmac_ctx, zero, sizeof(zero))
+ || !CMAC_Final(ctx->cmac_ctx, ctx->d.byte, &out_len)) {
+ EVP_CIPHER_CTX_free(ctx->cipher_ctx);
+ CMAC_CTX_free(ctx->cmac_ctx_init);
+ CMAC_CTX_free(ctx->cmac_ctx);
+ return 0;
+ }
+
+ ctx->final_ret = -1;
+ ctx->crypto_ok = 1;
+
+ return 1;
+}
+
+/*
+ * Copy an SIV128_CONTEXT object
+ */
+int CRYPTO_siv128_copy_ctx(SIV128_CONTEXT *dest, SIV128_CONTEXT *src)
+{
+ memcpy(&dest->d, &src->d, sizeof(src->d));
+ if (!EVP_CIPHER_CTX_copy(dest->cipher_ctx, src->cipher_ctx))
+ return 0;
+ if (!CMAC_CTX_copy(dest->cmac_ctx_init, src->cmac_ctx_init))
+ return 0;
+ /* no need to copy cmac_ctx since it's temp storage */
+ return 1;
+}
+
+/*
+ * Provide any AAD. This can be called multiple times.
+ * Per RFC5297, the last piece of associated data
+ * is the nonce, but it's not treated special
+ */
+int CRYPTO_siv128_aad(SIV128_CONTEXT *ctx, const unsigned char *aad,
+ size_t len)
+{
+ SIV_BLOCK cmac_out;
+ size_t out_len = SIV_LEN;
+
+ siv128_dbl(&ctx->d);
+
+ if (!CMAC_CTX_copy(ctx->cmac_ctx, ctx->cmac_ctx_init)
+ || !CMAC_Update(ctx->cmac_ctx, aad, len)
+ || !CMAC_Final(ctx->cmac_ctx, cmac_out.byte, &out_len)
+ || out_len != SIV_LEN)
+ return 0;
+
+ siv128_xorblock(&ctx->d, &cmac_out);
+
+ return 1;
+
+}
+
+/*
+ * Provide any data to be encrypted. This can be called once.
+ */
+int CRYPTO_siv128_encrypt(SIV128_CONTEXT *ctx,
+ const unsigned char *in, unsigned char *out,
+ size_t len)
+{
+ SIV_BLOCK q;
+
+ /* can only do one crypto operation */
+ if (ctx->crypto_ok == 0)
+ return 0;
+ ctx->crypto_ok--;
+
+ if (!siv128_do_s2v_p(ctx, &q, in, len))
+ return 0;
+
+ memcpy(ctx->tag.byte, &q, SIV_LEN);
+ q.byte[8] &= 0x7f;
+ q.byte[12] &= 0x7f;
+
+ if (!siv128_do_encrypt(ctx->cipher_ctx, out, in, len, &q))
+ return 0;
+ ctx->final_ret = 0;
+ return len;
+}
+
+/*
+ * Provide any data to be decrypted. This can be called once.
+ */
+int CRYPTO_siv128_decrypt(SIV128_CONTEXT *ctx,
+ const unsigned char *in, unsigned char *out,
+ size_t len)
+{
+ unsigned char* p;
+ SIV_BLOCK t, q;
+ int i;
+
+ /* can only do one crypto operation */
+ if (ctx->crypto_ok == 0)
+ return 0;
+ ctx->crypto_ok--;
+
+ memcpy(&q, ctx->tag.byte, SIV_LEN);
+ q.byte[8] &= 0x7f;
+ q.byte[12] &= 0x7f;
+
+ if (!siv128_do_encrypt(ctx->cipher_ctx, out, in, len, &q)
+ || !siv128_do_s2v_p(ctx, &t, out, len))
+ return 0;
+
+ p = ctx->tag.byte;
+ for (i = 0; i < SIV_LEN; i++)
+ t.byte[i] ^= p[i];
+
+ if ((t.word[0] | t.word[1]) != 0) {
+ OPENSSL_cleanse(out, len);
+ return 0;
+ }
+ ctx->final_ret = 0;
+ return len;
+}
+
+/*
+ * Return the already calculated final result.
+ */
+int CRYPTO_siv128_finish(SIV128_CONTEXT *ctx)
+{
+ return ctx->final_ret;
+}
+
+/*
+ * Set the tag
+ */
+int CRYPTO_siv128_set_tag(SIV128_CONTEXT *ctx, const unsigned char *tag, size_t len)
+{
+ if (len != SIV_LEN)
+ return 0;
+
+ /* Copy the tag from the supplied buffer */
+ memcpy(ctx->tag.byte, tag, len);
+ return 1;
+}
+
+/*
+ * Retrieve the calculated tag
+ */
+int CRYPTO_siv128_get_tag(SIV128_CONTEXT *ctx, unsigned char *tag, size_t len)
+{
+ if (len != SIV_LEN)
+ return 0;
+
+ /* Copy the tag into the supplied buffer */
+ memcpy(tag, ctx->tag.byte, len);
+ return 1;
+}
+
+/*
+ * Release all resources
+ */
+int CRYPTO_siv128_cleanup(SIV128_CONTEXT *ctx)
+{
+ if (ctx != NULL) {
+ EVP_CIPHER_CTX_free(ctx->cipher_ctx);
+ ctx->cipher_ctx = NULL;
+ CMAC_CTX_free(ctx->cmac_ctx_init);
+ ctx->cmac_ctx_init = NULL;
+ CMAC_CTX_free(ctx->cmac_ctx);
+ ctx->cmac_ctx = NULL;
+ OPENSSL_cleanse(&ctx->d, sizeof(ctx->d));
+ OPENSSL_cleanse(&ctx->tag, sizeof(ctx->tag));
+ ctx->final_ret = -1;
+ ctx->crypto_ok = 1;
+ }
+ return 1;
+}
+
+int CRYPTO_siv128_speed(SIV128_CONTEXT *ctx, int arg)
+{
+ ctx->crypto_ok = (arg == 1) ? -1 : 1;
+ return 1;
+}
+
+#endif /* OPENSSL_NO_SIV */
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index 9e2d3f0565..86bcfcaee0 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -1079,7 +1079,7 @@ static const unsigned char so[7767] = {
0x28,0xCC,0x45,0x03,0x04, /* [ 7761] OBJ_gmac */
};
-#define NUM_NID 1198
+#define NUM_NID 1201
static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"UNDEF", "undefined", NID_undef},
{"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@@ -2279,9 +2279,12 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"GMAC", "gmac", NID_gmac, 5, &so[7761]},
{"KMAC128", "kmac128", NID_kmac128},
{"KMAC256", "kmac256", NID_kmac256},
+ {"AES-128-SIV", "aes-128-siv", NID_aes_128_siv},
+ {"AES-192-SIV", "aes-192-siv", NID_aes_192_siv},
+ {"AES-256-SIV", "aes-256-siv", NID_aes_256_siv},
};
-#define NUM_SN 1189
+#define NUM_SN 1192
static const unsigned int sn_objs[NUM_SN] = {
364, /* "AD_DVCS" */
419, /* "AES-128-CBC" */
@@ -2294,6 +2297,7 @@ static const unsigned int sn_objs[NUM_SN] = {
418, /* "AES-128-ECB" */
958, /* "AES-128-OCB" */
420, /* "AES-128-OFB" */
+ 1198, /* "AES-128-SIV" */
913, /* "AES-128-XTS" */
423, /* "AES-192-CBC" */
917, /* "AES-192-CBC-HMAC-SHA1" */
@@ -2305,6 +2309,7 @@ static const unsigned int sn_objs[NUM_SN] = {
422, /* "AES-192-ECB" */
959, /* "AES-192-OCB" */
424, /* "AES-192-OFB" */
+ 1199, /* "AES-192-SIV" */
427, /* "AES-256-CBC" */
918, /* "AES-256-CBC-HMAC-SHA1" */
950, /* "AES-256-CBC-HMAC-SHA256" */
@@ -2315,6 +2320,7 @@ static const unsigned int sn_objs[NUM_SN] = {
426, /* "AES-256-ECB" */
960, /* "AES-256-OCB" */
428, /* "AES-256-OFB" */
+ 1200, /* "AES-256-SIV" */
914, /* "AES-256-XTS" */
1066, /* "ARIA-128-CBC" */
1120, /* "ARIA-128-CCM" */
@@ -3474,7 +3480,7 @@ static const unsigned int sn_objs[NUM_SN] = {
1093, /* "x509ExtAdmission" */
};
-#define NUM_LN 1189
+#define NUM_LN 1192
static const unsigned int ln_objs[NUM_LN] = {
363, /* "AD Time Stamping" */
405, /* "ANSI X9.62" */
@@ -3701,6 +3707,7 @@ static const unsigned int ln_objs[NUM_LN] = {
895, /* "aes-128-gcm" */
958, /* "aes-128-ocb" */
420, /* "aes-128-ofb" */
+ 1198, /* "aes-128-siv" */
913, /* "aes-128-xts" */
423, /* "aes-192-cbc" */
917, /* "aes-192-cbc-hmac-sha1" */
@@ -3714,6 +3721,7 @@ static const unsigned int ln_objs[NUM_LN] = {
898, /* "aes-192-gcm" */
959, /* "aes-192-ocb" */
424, /* "aes-192-ofb" */
+ 1199, /* "aes-192-siv" */
427, /* "aes-256-cbc" */
918, /* "aes-256-cbc-hmac-sha1" */
950, /* "aes-256-cbc-hmac-sha256" */
@@ -3726,6 +3734,7 @@ static const unsigned int ln_objs[NUM_LN] = {
901, /* "aes-256-gcm" */
960, /* "aes-256-ocb" */
428, /* "aes-256-ofb" */
+ 1200, /* "aes-256-siv" */
914, /* "aes-256-xts" */
376, /* "algorithm" */
1066, /* "aria-128-cbc" */
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index ad47750f5d..021875d9e4 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -1195,3 +1195,6 @@ hmacWithSHA512_256 1194
gmac 1195
kmac128 1196
kmac256 1197
+aes_128_siv 1198
+aes_192_siv 1199
+aes_256_siv 1200
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index 590bbe9a13..851e31e5aa 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -1645,7 +1645,6 @@ id-pkinit 5 : pkInitKDC : Signing KDC Response
: Poly1305 : poly1305
# NID for SipHash
: SipHash : siphash
-
# NIDs for RFC7919 DH parameters
: ffdhe2048
: ffdhe3072
@@ -1682,3 +1681,7 @@ dstu4145le 2 6 : uacurve6 : DSTU curve 6
dstu4145le 2 7 : uacurve7 : DSTU curve 7
dstu4145le 2 8 : uacurve8 : DSTU curve 8
dstu4145le 2 9 : uacurve9 : DSTU curve 9
+# NID for AES-SIV
+ : AES-128-SIV : aes-128-siv
+ : AES-192-SIV : aes-192-siv
+ : AES-256-SIV : aes-256-siv