cipher: Add wrappers for AES-XTS

AES-XTS does not support multipart use as it can only operate on an entire
sector at a time.
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index cde2fbd..0a545eb 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -167,6 +167,8 @@
     MBEDTLS_CIPHER_AES_128_OFB,          /**< AES 128-bit cipher in OFB mode. */
     MBEDTLS_CIPHER_AES_192_OFB,          /**< AES 192-bit cipher in OFB mode. */
     MBEDTLS_CIPHER_AES_256_OFB,          /**< AES 256-bit cipher in OFB mode. */
+    MBEDTLS_CIPHER_AES_128_XTS,          /**< AES 128-bit cipher in XTS block mode. */
+    MBEDTLS_CIPHER_AES_256_XTS,          /**< AES 256-bit cipher in XTS block mode. */
 } mbedtls_cipher_type_t;
 
 /** Supported cipher modes. */
@@ -180,6 +182,7 @@
     MBEDTLS_MODE_GCM,                    /**< The GCM cipher mode. */
     MBEDTLS_MODE_STREAM,                 /**< The stream cipher mode. */
     MBEDTLS_MODE_CCM,                    /**< The CCM cipher mode. */
+    MBEDTLS_MODE_XTS,                    /**< The XTS cipher mode. */
 } mbedtls_cipher_mode_t;
 
 /** Supported cipher padding types. */
@@ -295,7 +298,8 @@
     /** Number of Bytes that have not been processed yet. */
     size_t unprocessed_len;
 
-    /** Current IV or NONCE_COUNTER for CTR-mode. */
+    /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number
+     * for XTS-mode. */
     unsigned char iv[MBEDTLS_MAX_IV_LENGTH];
 
     /** IV size in Bytes, for ciphers with variable-length IVs. */
diff --git a/include/mbedtls/cipher_internal.h b/include/mbedtls/cipher_internal.h
index e02b7f1..c6def0b 100644
--- a/include/mbedtls/cipher_internal.h
+++ b/include/mbedtls/cipher_internal.h
@@ -79,6 +79,13 @@
                      const unsigned char *input, unsigned char *output );
 #endif
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    /** Encrypt or decrypt using XTS. */
+    int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length,
+                     const unsigned char data_unit[16],
+                     const unsigned char *input, unsigned char *output );
+#endif
+
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     /** Encrypt using STREAM */
     int (*stream_func)( void *ctx, size_t length,
diff --git a/library/cipher.c b/library/cipher.c
index 2c599e5..2d85228 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -456,6 +456,27 @@
     }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS )
+    {
+        if( ctx->unprocessed_len > 0 ) {
+            /* We can only process an entire data unit at a time. */
+            return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
+        }
+
+        ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx,
+                ctx->operation, ilen, ctx->iv, input, output );
+        if( ret != 0 )
+        {
+            return( ret );
+        }
+
+        *olen = ilen;
+
+        return( 0 );
+    }
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
     {
@@ -658,6 +679,7 @@
         MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
         MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
         MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
+        MBEDTLS_MODE_XTS == ctx->cipher_info->mode ||
         MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
     {
         return( 0 );
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index fd6e69c..16e0a9d 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -161,6 +161,33 @@
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation,
+                               size_t length,
+                               const unsigned char data_unit[16],
+                               const unsigned char *input,
+                               unsigned char *output )
+{
+    mbedtls_aes_xts_context *xts_ctx = ctx;
+    int mode;
+
+    switch( operation )
+    {
+        case MBEDTLS_ENCRYPT:
+            mode = MBEDTLS_AES_ENCRYPT;
+            break;
+        case MBEDTLS_DECRYPT:
+            mode = MBEDTLS_AES_DECRYPT;
+            break;
+        default:
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+
+    return mbedtls_aes_crypt_xts( xts_ctx, mode, length,
+                                  data_unit, input, output );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
                                 unsigned int key_bitlen )
 {
@@ -206,6 +233,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     aes_crypt_ctr_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -388,6 +418,92 @@
 };
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key,
+                                    unsigned int key_bitlen )
+{
+    mbedtls_aes_xts_context *xts_ctx = ctx;
+    return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) );
+}
+
+static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
+                                    unsigned int key_bitlen )
+{
+    mbedtls_aes_xts_context *xts_ctx = ctx;
+    return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) );
+}
+
+static void *xts_aes_ctx_alloc( void )
+{
+    mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) );
+
+    if( xts_ctx != NULL )
+        mbedtls_aes_xts_init( xts_ctx );
+
+    return( xts_ctx );
+}
+
+static void xts_aes_ctx_free( void *ctx )
+{
+    mbedtls_aes_xts_context *xts_ctx = ctx;
+
+    if( xts_ctx == NULL )
+        return;
+
+    mbedtls_aes_xts_free( xts_ctx );
+    mbedtls_free( xts_ctx );
+}
+
+static const mbedtls_cipher_base_t xts_aes_info = {
+    MBEDTLS_CIPHER_ID_AES,
+    NULL,
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+    NULL,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    aes_crypt_xts_wrap,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_STREAM)
+    NULL,
+#endif
+    xts_aes_setkey_enc_wrap,
+    xts_aes_setkey_dec_wrap,
+    xts_aes_ctx_alloc,
+    xts_aes_ctx_free
+};
+
+static const mbedtls_cipher_info_t aes_128_xts_info = {
+    MBEDTLS_CIPHER_AES_128_XTS,
+    MBEDTLS_MODE_XTS,
+    256,
+    "AES-128-XTS",
+    16,
+    0,
+    16,
+    &xts_aes_info
+};
+
+static const mbedtls_cipher_info_t aes_256_xts_info = {
+    MBEDTLS_CIPHER_AES_256_XTS,
+    MBEDTLS_MODE_XTS,
+    512,
+    "AES-256-XTS",
+    16,
+    0,
+    16,
+    &xts_aes_info
+};
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 #if defined(MBEDTLS_GCM_C)
 static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key,
                                 unsigned int key_bitlen )
@@ -411,6 +527,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -477,6 +596,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -607,6 +729,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     camellia_crypt_ctr_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -777,6 +902,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -843,6 +971,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -974,6 +1105,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     aria_crypt_ctr_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -1144,6 +1278,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -1210,6 +1347,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -1389,6 +1529,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -1437,6 +1580,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -1485,6 +1631,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -1597,6 +1746,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     blowfish_crypt_ctr_wrap,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
@@ -1710,6 +1862,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     arc4_crypt_stream_wrap,
 #endif
@@ -1776,6 +1931,9 @@
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     NULL,
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    NULL,
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     null_crypt_stream,
 #endif
@@ -1823,6 +1981,10 @@
     { MBEDTLS_CIPHER_AES_192_CTR,          &aes_192_ctr_info },
     { MBEDTLS_CIPHER_AES_256_CTR,          &aes_256_ctr_info },
 #endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+    { MBEDTLS_CIPHER_AES_128_XTS,          &aes_128_xts_info },
+    { MBEDTLS_CIPHER_AES_256_XTS,          &aes_256_xts_info },
+#endif
 #if defined(MBEDTLS_GCM_C)
     { MBEDTLS_CIPHER_AES_128_GCM,          &aes_128_gcm_info },
     { MBEDTLS_CIPHER_AES_192_GCM,          &aes_192_gcm_info },
diff --git a/tests/suites/test_suite_cipher.aes.data b/tests/suites/test_suite_cipher.aes.data
index 4ac1cb5..baab358 100644
--- a/tests/suites/test_suite_cipher.aes.data
+++ b/tests/suites/test_suite_cipher.aes.data
@@ -786,6 +786,70 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_OFB
 enc_dec_buf_multipart:MBEDTLS_CIPHER_AES_256_OFB:256:16:16:-1:16:16:16:16
 
+AES-128 XTS - Encrypt and decrypt 16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:16:-1
+
+AES-128 XTS - Encrypt and decrypt 17 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:17:-1
+
+AES-128 XTS - Encrypt and decrypt 31 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:31:-1
+
+AES-128 XTS - Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:32:-1
+
+AES-128 XTS - Encrypt and decrypt 33 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:33:-1
+
+AES-128 XTS - Encrypt and decrypt 47 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:47:-1
+
+AES-128 XTS - Encrypt and decrypt 48 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:48:-1
+
+AES-128 XTS - Encrypt and decrypt 49 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_128_XTS:"AES-128-XTS":256:49:-1
+
+AES-256 XTS - Encrypt and decrypt 16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:16:-1
+
+AES-256 XTS - Encrypt and decrypt 17 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:17:-1
+
+AES-256 XTS - Encrypt and decrypt 31 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:31:-1
+
+AES-256 XTS - Encrypt and decrypt 32 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:32:-1
+
+AES-256 XTS - Encrypt and decrypt 33 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:33:-1
+
+AES-256 XTS - Encrypt and decrypt 47 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:47:-1
+
+AES-256 XTS - Encrypt and decrypt 48 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:48:-1
+
+AES-256 XTS - Encrypt and decrypt 49 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+enc_dec_buf:MBEDTLS_CIPHER_AES_256_XTS:"AES-256-XTS":512:49:-1
+
 AES-128 CTR - Encrypt and decrypt 0 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 enc_dec_buf:MBEDTLS_CIPHER_AES_128_CTR:"AES-128-CTR":128:0:-1