The branch master has been updated
       via  3a9f26f3308c5b3e59ec0e589310fd137b0399f6 (commit)
      from  88d870824f1f913877f0f978ae60879575daf56d (commit)


- Log -----------------------------------------------------------------
commit 3a9f26f3308c5b3e59ec0e589310fd137b0399f6
Author: Shane Lontis <shane.lon...@oracle.com>
Date:   Sat Sep 14 09:27:49 2019 +1000

    Add aes_xts cipher to providers
    
    Reviewed-by: Richard Levitte <levi...@openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9327)

-----------------------------------------------------------------------

Summary of changes:
 crypto/err/openssl.txt                             |   2 +
 crypto/evp/evp_enc.c                               |   2 +
 crypto/modes/build.info                            |   5 +-
 providers/common/ciphers/build.info                |   4 +-
 providers/common/ciphers/cipher_aes_xts.c          | 286 +++++++++++++++++++++
 providers/common/ciphers/cipher_aes_xts.h          |  29 +++
 providers/common/ciphers/cipher_aes_xts_hw.c       | 153 +++++++++++
 providers/common/include/internal/provider_algs.h  |   2 +
 .../common/include/internal/providercommonerr.h    |   2 +
 providers/common/provider_err.c                    |   4 +
 providers/default/defltprov.c                      |   2 +
 providers/fips/fipsprov.c                          |   6 +
 test/recipes/30-test_evp_data/evpciph.txt          |  18 +-
 13 files changed, 503 insertions(+), 12 deletions(-)
 create mode 100644 providers/common/ciphers/cipher_aes_xts.c
 create mode 100644 providers/common/ciphers/cipher_aes_xts.h
 create mode 100644 providers/common/ciphers/cipher_aes_xts_hw.c

diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index f74659c599..700f1da20f 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -2706,6 +2706,8 @@ PROV_R_UNSUPPORTED_MAC_TYPE:137:unsupported mac type
 PROV_R_VALUE_ERROR:138:value error
 PROV_R_WRONG_FINAL_BLOCK_LENGTH:107:wrong final block length
 PROV_R_WRONG_OUTPUT_BUFFER_SIZE:139:wrong output buffer size
+PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE:148:xts data unit is too large
+PROV_R_XTS_DUPLICATED_KEYS:149:xts duplicated keys
 RAND_R_ADDITIONAL_INPUT_TOO_LONG:102:additional input too long
 RAND_R_ALREADY_INSTANTIATED:103:already instantiated
 RAND_R_ARGUMENT_OUT_OF_RANGE:105:argument out of range
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 466a03dbf3..6d657f76cd 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -163,6 +163,8 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER 
*cipher,
         case NID_aes_256_ctr:
         case NID_aes_192_ctr:
         case NID_aes_128_ctr:
+        case NID_aes_128_xts:
+        case NID_aes_256_xts:
         case NID_aes_256_gcm:
         case NID_aes_192_gcm:
         case NID_aes_128_gcm:
diff --git a/crypto/modes/build.info b/crypto/modes/build.info
index fa5e52f50e..506e04d5fa 100644
--- a/crypto/modes/build.info
+++ b/crypto/modes/build.info
@@ -48,9 +48,10 @@ IF[{- !$disabled{asm} -}]
   ENDIF
 ENDIF
 
-$COMMON=cbc128.c ctr128.c cfb128.c ofb128.c gcm128.c ccm128.c $MODESASM
+$COMMON=cbc128.c ctr128.c cfb128.c ofb128.c gcm128.c ccm128.c xts128.c 
$MODESASM
 SOURCE[../../libcrypto]=$COMMON \
-        cts128.c xts128.c wrap128.c ocb128.c siv128.c
+        cts128.c wrap128.c ocb128.c siv128.c
+
 DEFINE[../../libcrypto]=$MODESDEF
 SOURCE[../../providers/fips]=$COMMON
 DEFINE[../../providers/fips]=$MODESDEF
diff --git a/providers/common/ciphers/build.info 
b/providers/common/ciphers/build.info
index 0302cf151e..3f303e96b0 100644
--- a/providers/common/ciphers/build.info
+++ b/providers/common/ciphers/build.info
@@ -6,6 +6,7 @@ ENDIF
 
 $COMMON=cipher_common.c cipher_common_hw.c block.c \
         cipher_aes.c cipher_aes_hw.c \
+        cipher_aes_xts.c cipher_aes_xts_hw.c \
         cipher_gcm.c cipher_gcm_hw.c \
         cipher_aes_gcm.c cipher_aes_gcm_hw.c \
         cipher_ccm.c cipher_ccm_hw.c \
@@ -16,4 +17,5 @@ SOURCE[../../../libcrypto]=$COMMON
 INCLUDE[../../../libcrypto]=. ../../../crypto
 
 SOURCE[../../fips]=$COMMON
-INCLUDE[../../fips]=. ../../../crypto
\ No newline at end of file
+INCLUDE[../../fips]=. ../../../crypto
+
diff --git a/providers/common/ciphers/cipher_aes_xts.c 
b/providers/common/ciphers/cipher_aes_xts.c
new file mode 100644
index 0000000000..feaa36991f
--- /dev/null
+++ b/providers/common/ciphers/cipher_aes_xts.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 "cipher_aes_xts.h"
+#include "internal/provider_algs.h"
+#include "internal/providercommonerr.h"
+
+/* TODO (3.0) Figure out what flags need to be set */
+#define AES_XTS_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV         
\
+                       | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT        
\
+                       | EVP_CIPH_CUSTOM_COPY)
+
+#define AES_XTS_IV_BITS 128
+#define AES_XTS_BLOCK_BITS 8
+
+#ifdef FIPS_MODE
+static const int allow_insecure_decrypt = 0;
+#else
+static const int allow_insecure_decrypt = 1;
+#endif /* FIPS_MODE */
+
+/* forward declarations */
+static OSSL_OP_cipher_encrypt_init_fn aes_xts_einit;
+static OSSL_OP_cipher_decrypt_init_fn aes_xts_dinit;
+static OSSL_OP_cipher_update_fn aes_xts_stream_update;
+static OSSL_OP_cipher_final_fn aes_xts_stream_final;
+static OSSL_OP_cipher_cipher_fn aes_xts_cipher;
+static OSSL_OP_cipher_freectx_fn aes_xts_freectx;
+static OSSL_OP_cipher_dupctx_fn aes_xts_dupctx;
+static OSSL_OP_cipher_set_ctx_params_fn aes_xts_set_ctx_params;
+static OSSL_OP_cipher_settable_ctx_params_fn aes_xts_settable_ctx_params;
+
+/*
+ * Verify that the two keys are different.
+ *
+ * This addresses the vulnerability described in Rogaway's
+ * September 2004 paper:
+ *
+ *      "Efficient Instantiations of Tweakable Blockciphers and
+ *       Refinements to Modes OCB and PMAC".
+ *      (http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf)
+ *
+ * FIPS 140-2 IG A.9 XTS-AES Key Generation Requirements states
+ * that:
+ *      "The check for Key_1 != Key_2 shall be done at any place
+ *       BEFORE using the keys in the XTS-AES algorithm to process
+ *       data with them."
+ */
+static int aes_xts_check_keys_differ(const unsigned char *key, size_t bytes,
+                                     int enc)
+{
+    if ((!allow_insecure_decrypt || enc)
+            && CRYPTO_memcmp(key, key + bytes, bytes) == 0) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DUPLICATED_KEYS);
+        return 0;
+    }
+    return 1;
+}
+
+/*-
+ * Provider dispatch functions
+ */
+static int aes_xts_init(void *vctx, const unsigned char *key, size_t keylen,
+                        const unsigned char *iv, size_t ivlen, int enc)
+{
+    PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)vctx;
+    PROV_CIPHER_CTX *ctx = &xctx->base;
+
+    ctx->enc = enc;
+
+    if (iv != NULL) {
+        if (ivlen != ctx->ivlen) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+            return 0;
+        }
+        memcpy(ctx->iv, iv, ivlen);
+        xctx->iv_set = 1;
+    }
+    if (key != NULL) {
+        if (keylen != ctx->keylen) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+            return 0;
+        }
+        if (!aes_xts_check_keys_differ(key, keylen / 2, enc))
+            return 0;
+        return ctx->hw->init(ctx, key, keylen);
+    }
+    return 1;
+}
+
+static int aes_xts_einit(void *vctx, const unsigned char *key, size_t keylen,
+                         const unsigned char *iv, size_t ivlen)
+{
+    return aes_xts_init(vctx, key, keylen, iv, ivlen, 1);
+}
+
+static int aes_xts_dinit(void *vctx, const unsigned char *key, size_t keylen,
+                         const unsigned char *iv, size_t ivlen)
+{
+    return aes_xts_init(vctx, key, keylen, iv, ivlen, 0);
+}
+
+static void *aes_xts_newctx(void *provctx, unsigned int mode, size_t kbits,
+                            size_t blkbits, size_t ivbits)
+{
+    PROV_AES_XTS_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+    if (ctx != NULL) {
+        cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, mode,
+                               PROV_CIPHER_HW_aes_xts(kbits), NULL);
+    }
+    return ctx;
+}
+
+static void aes_xts_freectx(void *vctx)
+{
+    PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
+
+    OPENSSL_clear_free(ctx,  sizeof(*ctx));
+}
+
+static void *aes_xts_dupctx(void *vctx)
+{
+    PROV_AES_XTS_CTX *in = (PROV_AES_XTS_CTX *)vctx;
+    PROV_AES_XTS_CTX *ret = NULL;
+
+    if (in->xts.key1 != NULL) {
+        if (in->xts.key1 != &in->ks1)
+            return NULL;
+    }
+    if (in->xts.key2 != NULL) {
+        if (in->xts.key2 != &in->ks2)
+            return NULL;
+    }
+    ret = OPENSSL_malloc(sizeof(*ret));
+    if (ret == NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    *ret = *in;
+    return ret;
+}
+
+static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl,
+                          size_t outsize, const unsigned char *in, size_t inl)
+{
+    PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
+
+    if (ctx->xts.key1 == NULL
+            || ctx->xts.key2 == NULL
+            || !ctx->iv_set
+            || out == NULL
+            || in == NULL
+            || inl < AES_BLOCK_SIZE)
+        return 0;
+
+    /*
+     * Impose a limit of 2^20 blocks per data unit as specifed by
+     * IEEE Std 1619-2018.  The earlier and obsolete IEEE Std 1619-2007
+     * indicated that this was a SHOULD NOT rather than a MUST NOT.
+     * NIST SP 800-38E mandates the same limit.
+     */
+    if (inl > XTS_MAX_BLOCKS_PER_DATA_UNIT * AES_BLOCK_SIZE) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE);
+        return 0;
+    }
+
+    if (ctx->stream != NULL)
+        (*ctx->stream)(in, out, inl, ctx->xts.key1, ctx->xts.key2, 
ctx->base.iv);
+    else if (CRYPTO_xts128_encrypt(&ctx->xts, ctx->base.iv, in, out, inl,
+                                   ctx->base.enc))
+        return 0;
+    return 1;
+
+    *outl = inl;
+    return 1;
+}
+
+static int aes_xts_stream_update(void *vctx, unsigned char *out, size_t *outl,
+                                 size_t outsize, const unsigned char *in,
+                                 size_t inl)
+{
+    PROV_AES_XTS_CTX *ctx = (PROV_AES_XTS_CTX *)vctx;
+
+    if (outsize < inl) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+        return 0;
+    }
+
+    if (!aes_xts_cipher(ctx, out, outl, outsize, in, inl)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+        return 0;
+    }
+
+    *outl = inl;
+    return 1;
+}
+
+static int aes_xts_stream_final(void *vctx, unsigned char *out, size_t *outl,
+                                size_t outsize)
+{
+    *outl = 0;
+    return 1;
+}
+
+static const OSSL_PARAM aes_xts_known_settable_ctx_params[] = {
+    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+    OSSL_PARAM_END
+};
+
+static const OSSL_PARAM *aes_xts_settable_ctx_params(void)
+{
+    return aes_xts_known_settable_ctx_params;
+}
+
+static int aes_xts_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+    const OSSL_PARAM *p;
+
+    /*
+     * TODO(3.0) We need a general solution for handling missing parameters
+     * inside set_params and get_params methods.
+     */
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+    if (p != NULL) {
+        size_t keylen;
+
+        if (!OSSL_PARAM_get_size_t(p, &keylen)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        /* The key length can not be modified for xts mode */
+        if (keylen != ctx->keylen)
+            return 0;
+    }
+
+    return 1;
+}
+
+#define IMPLEMENT_cipher(lcmode, UCMODE, kbits, flags)                         
\
+static OSSL_OP_cipher_get_params_fn aes_##kbits##_##lcmode##_get_params;       
\
+static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[])            
\
+{                                                                              
\
+    return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,         
\
+                                     flags, 2 * kbits, AES_XTS_BLOCK_BITS,     
\
+                                     AES_XTS_IV_BITS);                         
\
+}                                                                              
\
+static OSSL_OP_cipher_newctx_fn aes_##kbits##_xts_newctx;                      
\
+static void *aes_##kbits##_xts_newctx(void *provctx)                           
\
+{                                                                              
\
+    return aes_xts_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, 2 * kbits,        
\
+                          AES_XTS_BLOCK_BITS, AES_XTS_IV_BITS);                
\
+}                                                                              
\
+const OSSL_DISPATCH aes##kbits##xts_functions[] = {                            
\
+    { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##kbits##_xts_newctx },     
\
+    { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_xts_einit },          
\
+    { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_xts_dinit },          
\
+    { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_xts_stream_update },        
\
+    { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_xts_stream_final },          
\
+    { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_xts_cipher },               
\
+    { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_xts_freectx },             
\
+    { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_xts_dupctx },               
\
+    { OSSL_FUNC_CIPHER_GET_PARAMS,                                             
\
+      (void (*)(void))aes_##kbits##_##lcmode##_get_params },                   
\
+    { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,                                        
\
+      (void (*)(void))cipher_generic_gettable_params },                        
\
+    { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,                                         
\
+      (void (*)(void))cipher_generic_get_ctx_params },                         
\
+    { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,                                    
\
+      (void (*)(void))cipher_generic_gettable_ctx_params },                    
\
+    { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,                                         
\
+      (void (*)(void))aes_xts_set_ctx_params },                                
\
+    { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                    
\
+     (void (*)(void))aes_xts_settable_ctx_params },                            
\
+    { 0, NULL }                                                                
\
+}
+
+IMPLEMENT_cipher(xts, XTS, 256, AES_XTS_FLAGS);
+IMPLEMENT_cipher(xts, XTS, 128, AES_XTS_FLAGS);
diff --git a/providers/common/ciphers/cipher_aes_xts.h 
b/providers/common/ciphers/cipher_aes_xts.h
new file mode 100644
index 0000000000..daad274328
--- /dev/null
+++ b/providers/common/ciphers/cipher_aes_xts.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 <openssl/aes.h>
+#include "internal/ciphers/ciphercommon.h"
+
+PROV_CIPHER_FUNC(void, xts_stream,
+                 (const unsigned char *in, unsigned char *out, size_t len,
+                  const AES_KEY *key1, const AES_KEY *key2,
+                  const unsigned char iv[16]));
+
+typedef struct prov_aes_xts_ctx_st {
+    PROV_CIPHER_CTX base;      /* Must be first */
+    union {
+        OSSL_UNION_ALIGN;
+        AES_KEY ks;
+    } ks1, ks2;                /* AES key schedules to use */
+    XTS128_CONTEXT xts;
+    OSSL_xts_stream_fn stream;
+    unsigned int iv_set : 1;   /* Set if an iv is set */
+} PROV_AES_XTS_CTX;
+
+const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_xts(size_t keybits);
diff --git a/providers/common/ciphers/cipher_aes_xts_hw.c 
b/providers/common/ciphers/cipher_aes_xts_hw.c
new file mode 100644
index 0000000000..2b06c5bb4b
--- /dev/null
+++ b/providers/common/ciphers/cipher_aes_xts_hw.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (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 "cipher_aes_xts.h"
+
+#define XTS_SET_KEY_FN(fn_set_enc_key, fn_set_dec_key,                         
\
+                       fn_block_enc, fn_block_dec,                             
\
+                       fn_stream_enc, fn_stream_dec) {                         
\
+    size_t bytes = keylen / 2;                                                 
\
+    size_t bits = bytes * 8;                                                   
\
+                                                                               
\
+    if (ctx->enc) {                                                            
\
+        fn_set_enc_key(key, bits, &xctx->ks1.ks);                              
\
+        xctx->xts.block1 = (block128_f)fn_block_enc;                           
\
+    } else {                                                                   
\
+        fn_set_dec_key(key, bits, &xctx->ks1.ks);                              
\
+        xctx->xts.block1 = (block128_f)fn_block_dec;                           
\
+    }                                                                          
\
+    fn_set_enc_key(key + bytes, bits, &xctx->ks2.ks);                          
\
+    xctx->xts.block2 = (block128_f)fn_block_enc;                               
\
+    xctx->xts.key1 = &xctx->ks1;                                               
\
+    xctx->xts.key2 = &xctx->ks2;                                               
\
+    xctx->stream = ctx->enc ? fn_stream_enc : fn_stream_dec;                   
\
+}
+
+static int cipher_hw_aes_xts_generic_initkey(PROV_CIPHER_CTX *ctx,
+                                             const unsigned char *key,
+                                             size_t keylen)
+{
+    PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
+    OSSL_xts_stream_fn stream_enc = NULL;
+    OSSL_xts_stream_fn stream_dec = NULL;
+
+#ifdef AES_XTS_ASM
+    stream_enc = AES_xts_encrypt;
+    stream_dec = AES_xts_decrypt;
+#endif /* AES_XTS_ASM */
+
+#ifdef HWAES_CAPABLE
+    if (HWAES_CAPABLE) {
+# ifdef HWAES_xts_encrypt
+        stream_enc = HWAES_xts_encrypt;
+# endif /* HWAES_xts_encrypt */
+# ifdef HWAES_xts_decrypt
+        stream_dec = HWAES_xts_decrypt;
+# endif /* HWAES_xts_decrypt */
+        XTS_SET_KEY_FN(HWAES_set_encrypt_key, HWAES_set_decrypt_key,
+                       HWAES_encrypt, HWAES_decrypt,
+                       stream_enc, stream_dec);
+    } else
+#endif /* HWAES_CAPABLE */
+
+#ifdef BSAES_CAPABLE
+    if (BSAES_CAPABLE) {
+        stream_enc = bsaes_xts_encrypt;
+        stream_dec = bsaes_xts_decrypt;
+    }
+#endif /* BSAES_CAPABLE */
+
+#ifdef VPAES_CAPABLE
+    if (VPAES_CAPABLE) {
+        XTS_SET_KEY_FN(vpaes_set_encrypt_key, vpaes_set_decrypt_key,
+                       vpaes_encrypt, vpaes_decrypt, stream_enc, stream_dec);
+    } else
+#endif /* VPAES_CAPABLE */
+    {
+        XTS_SET_KEY_FN(AES_set_encrypt_key, AES_set_decrypt_key,
+                       AES_encrypt, AES_decrypt, stream_enc, stream_dec);
+    }
+    return 1;
+}
+
+#if defined(AESNI_CAPABLE)
+
+static int cipher_hw_aesni_xts_initkey(PROV_CIPHER_CTX *ctx,
+                                       const unsigned char *key, size_t keylen)
+{
+    PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
+
+    XTS_SET_KEY_FN(aesni_set_encrypt_key, aesni_set_decrypt_key,
+                   aesni_xts_encrypt, aesni_decrypt,
+                   aesni_xts_encrypt, aesni_xts_decrypt);
+    return 1;
+}
+
+# define PROV_CIPHER_HW_declare_xts()                                          
\
+static const PROV_CIPHER_HW aesni_xts = {                                      
\
+    cipher_hw_aesni_xts_initkey,                                               
\
+    NULL                                                                       
\
+};
+# define PROV_CIPHER_HW_select_xts()                                           
\
+if (AESNI_CAPABLE)                                                             
\
+    return &aesni_xts;
+
+# elif defined(SPARC_AES_CAPABLE)
+
+static int cipher_hw_aes_xts_t4_initkey(PROV_CIPHER_CTX *ctx,
+                                        const unsigned char *key, size_t 
keylen)
+{
+    PROV_AES_XTS_CTX *xctx = (PROV_AES_XTS_CTX *)ctx;
+    OSSL_xts_stream_fn stream_enc = NULL;
+    OSSL_xts_stream_fn stream_dec = NULL;
+
+    /* Note: keylen is the size of 2 keys */
+    switch (keylen) {
+    case 32:
+        stream_enc = aes128_t4_xts_encrypt;
+        stream_dec = aes128_t4_xts_decrypt;
+        break;
+    case 64:
+        stream_enc = aes256_t4_xts_encrypt;
+        stream_dec = aes256_t4_xts_decrypt;
+        break;
+    default:
+        return 0;
+    }
+
+    XTS_SET_KEY_FN(aes_t4_set_encrypt_key, aes_t4_set_decrypt_key,
+                   aes_t4_encrypt, aes_t4_decrypt,
+                   stream_enc, stream_dec);
+    return 1;
+}
+
+# define PROV_CIPHER_HW_declare_xts()                                          
\
+static const PROV_CIPHER_HW aes_xts_t4 = {                                     
\
+    cipher_hw_aes_xts_t4_initkey,                                              
\
+    NULL                                                                       
\
+};
+# define PROV_CIPHER_HW_select_xts()                                           
\
+if (SPARC_AES_CAPABLE)                                                         
\
+    return &aes_xts_t4;
+# else
+/* The generic case */
+# define PROV_CIPHER_HW_declare_xts()
+# define PROV_CIPHER_HW_select_xts()
+#endif
+
+static const PROV_CIPHER_HW aes_generic_xts = {
+    cipher_hw_aes_xts_generic_initkey,
+    NULL
+};
+PROV_CIPHER_HW_declare_xts()
+const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_xts(size_t keybits)
+{
+    PROV_CIPHER_HW_select_xts()
+    return &aes_generic_xts;
+}
diff --git a/providers/common/include/internal/provider_algs.h 
b/providers/common/include/internal/provider_algs.h
index 92aa64772e..e6da5f32a8 100644
--- a/providers/common/include/internal/provider_algs.h
+++ b/providers/common/include/internal/provider_algs.h
@@ -56,6 +56,8 @@ extern const OSSL_DISPATCH aes128cfb8_functions[];
 extern const OSSL_DISPATCH aes256ctr_functions[];
 extern const OSSL_DISPATCH aes192ctr_functions[];
 extern const OSSL_DISPATCH aes128ctr_functions[];
+extern const OSSL_DISPATCH aes256xts_functions[];
+extern const OSSL_DISPATCH aes128xts_functions[];
 extern const OSSL_DISPATCH aes256gcm_functions[];
 extern const OSSL_DISPATCH aes192gcm_functions[];
 extern const OSSL_DISPATCH aes128gcm_functions[];
diff --git a/providers/common/include/internal/providercommonerr.h 
b/providers/common/include/internal/providercommonerr.h
index 39f56b4950..81e5931d84 100644
--- a/providers/common/include/internal/providercommonerr.h
+++ b/providers/common/include/internal/providercommonerr.h
@@ -97,5 +97,7 @@ int ERR_load_PROV_strings(void);
 # define PROV_R_VALUE_ERROR                               138
 # define PROV_R_WRONG_FINAL_BLOCK_LENGTH                  107
 # define PROV_R_WRONG_OUTPUT_BUFFER_SIZE                  139
+# define PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE                148
+# define PROV_R_XTS_DUPLICATED_KEYS                       149
 
 #endif
diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c
index f9524a7f62..27d6837af3 100644
--- a/providers/common/provider_err.c
+++ b/providers/common/provider_err.c
@@ -83,6 +83,10 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     "wrong final block length"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_OUTPUT_BUFFER_SIZE),
     "wrong output buffer size"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_XTS_DATA_UNIT_IS_TOO_LARGE),
+    "xts data unit is too large"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_XTS_DUPLICATED_KEYS),
+    "xts duplicated keys"},
     {0, NULL}
 };
 
diff --git a/providers/default/defltprov.c b/providers/default/defltprov.c
index 3f2ad610a9..e829dbfac0 100644
--- a/providers/default/defltprov.c
+++ b/providers/default/defltprov.c
@@ -114,6 +114,8 @@ static const OSSL_ALGORITHM deflt_ciphers[] = {
     { "AES-256-CTR", "default=yes", aes256ctr_functions },
     { "AES-192-CTR", "default=yes", aes192ctr_functions },
     { "AES-128-CTR", "default=yes", aes128ctr_functions },
+    { "AES-256-XTS", "default=yes", aes256xts_functions },
+    { "AES-128-XTS", "default=yes", aes128xts_functions },
 /* TODO(3.0) Add aliases when they are supported */
     { "id-aes256-GCM", "default=yes", aes256gcm_functions },
     { "id-aes192-GCM", "default=yes", aes192gcm_functions },
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index e5bb9b41d6..cff172921c 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -268,6 +268,10 @@ const char *ossl_prov_util_nid_to_name(int nid)
         return "AES-192-CTR";
     case NID_aes_128_ctr:
         return "AES-128-CTR";
+    case NID_aes_256_xts:
+        return "AES-256-XTS";
+    case NID_aes_128_xts:
+        return "AES-128-XTS";
     /* TODO(3.0) Change these when we have aliases */
     case NID_aes_256_gcm:
         return "id-aes256-GCM";
@@ -320,6 +324,8 @@ static const OSSL_ALGORITHM fips_ciphers[] = {
     { "AES-256-CTR", "fips=yes", aes256ctr_functions },
     { "AES-192-CTR", "fips=yes", aes192ctr_functions },
     { "AES-128-CTR", "fips=yes", aes128ctr_functions },
+    { "AES-256-XTS", "fips=yes", aes256xts_functions },
+    { "AES-128-XTS", "fips=yes", aes128xts_functions },
     /* TODO(3.0) Add aliases for these ciphers */
     { "id-aes256-GCM", "fips=yes", aes256gcm_functions },
     { "id-aes192-GCM", "fips=yes", aes192gcm_functions },
diff --git a/test/recipes/30-test_evp_data/evpciph.txt 
b/test/recipes/30-test_evp_data/evpciph.txt
index 28820ecf52..3d7d817bc8 100644
--- a/test/recipes/30-test_evp_data/evpciph.txt
+++ b/test/recipes/30-test_evp_data/evpciph.txt
@@ -1258,18 +1258,18 @@ Ciphertext = 
917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e
 Result = KEY_SET_ERROR
 
 # Using the same key twice for decryption is banned in FIPS mode.
-#Cipher = aes-128-xts
-#FIPS = YES
-#Operation = DECRYPT
-#Key = 0000000000000000000000000000000000000000000000000000000000000000
-#IV = 00000000000000000000000000000000
-#Plaintext = 0000000000000000000000000000000000000000000000000000000000000000
-#Ciphertext = 917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e
-#Result = KEY_SET_ERROR
+Cipher = aes-128-xts
+Availablein = fips
+Operation = DECRYPT
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 00000000000000000000000000000000
+Plaintext = 0000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 917cf69ebd68b2ec9b9fe9a3eadda692cd43d2f59598ed858c02c2652fbf922e
+Result = KEY_SET_ERROR
 
 # Using the same key twice for decryption is allowed outside of FIPS mode.
 Cipher = aes-128-xts
-#FIPS = NO
+Availablein = default
 Operation = DECRYPT
 Key = 0000000000000000000000000000000000000000000000000000000000000000
 IV = 00000000000000000000000000000000

Reply via email to