diff options
author | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2017-01-06 12:48:17 +0200 |
---|---|---|
committer | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2017-01-06 12:48:17 +0200 |
commit | 232a129b1f915fc54881506e4b07c89cf84932e6 (patch) | |
tree | 21830feb80af49e2ab2ff344a647d0a0ec10aac5 /cipher/cipher.c | |
parent | aada604594fd42224d366d3cb98f67fd3b989cd6 (diff) | |
download | libgcrypt-232a129b1f915fc54881506e4b07c89cf84932e6.tar.gz |
Add XTS cipher mode
* cipher/Makefile.am: Add 'cipher-xts.c'.
* cipher/cipher-internal.h (gcry_cipher_handle): Add 'bulk.xts_crypt'
and 'u_mode.xts' members.
(_gcry_cipher_xts_crypt): New prototype.
* cipher/cipher-xts.c: New.
* cipher/cipher.c (_gcry_cipher_open_internal, cipher_setkey)
(cipher_reset, cipher_encrypt, cipher_decrypt): Add XTS mode handling.
* doc/gcrypt.texi: Add XTS mode to documentation.
* src/gcrypt.h.in (GCRY_CIPHER_MODE_XTS, GCRY_XTS_BLOCK_LEN): New.
* tests/basic.c (do_check_xts_cipher, check_xts_cipher): New.
(check_bulk_cipher_modes): Add XTS test-vectors.
(check_one_cipher_core, check_one_cipher, check_ciphers): Add XTS
testing support.
(check_cipher_modes): Add XTS test.
* tests/bench-slope.c (bench_xts_encrypt_init)
(bench_xts_encrypt_do_bench, bench_xts_decrypt_do_bench)
(xts_encrypt_ops, xts_decrypt_ops): New.
(cipher_modes, cipher_bench_one): Add XTS.
* tests/benchmark.c (cipher_bench): Add XTS testing.
--
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'cipher/cipher.c')
-rw-r--r-- | cipher/cipher.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/cipher/cipher.c b/cipher/cipher.c index 55853da9..06ce1dad 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -405,6 +405,13 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, err = GPG_ERR_INV_CIPHER_MODE; break; + case GCRY_CIPHER_MODE_XTS: + if (spec->blocksize != GCRY_XTS_BLOCK_LEN) + err = GPG_ERR_INV_CIPHER_MODE; + if (!spec->encrypt || !spec->decrypt) + err = GPG_ERR_INV_CIPHER_MODE; + break; + case GCRY_CIPHER_MODE_ECB: case GCRY_CIPHER_MODE_CBC: case GCRY_CIPHER_MODE_CFB: @@ -468,6 +475,18 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, #endif /*NEED_16BYTE_ALIGNED_CONTEXT*/ ); + /* Space needed per mode. */ + switch (mode) + { + case GCRY_CIPHER_MODE_XTS: + /* Additional cipher context for tweak. */ + size += 2 * spec->contextsize + 15; + break; + + default: + break; + } + if (secure) h = xtrycalloc_secure (1, size); else @@ -478,6 +497,7 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, else { size_t off = 0; + char *tc; #ifdef NEED_16BYTE_ALIGNED_CONTEXT if ( ((uintptr_t)h & 0x0f) ) @@ -578,6 +598,13 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, h->u_mode.ocb.taglen = 16; /* Bytes. */ break; + case GCRY_CIPHER_MODE_XTS: + tc = h->context.c + spec->contextsize * 2; + tc += (16 - (uintptr_t)tc % 16) % 16; + h->u_mode.xts.tweak_context = tc; + + break; + default: break; } @@ -630,6 +657,23 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) { gcry_err_code_t rc; + if (c->mode == GCRY_CIPHER_MODE_XTS) + { + /* XTS uses two keys. */ + if (keylen % 2) + return GPG_ERR_INV_KEYLEN; + keylen /= 2; + + if (fips_mode ()) + { + /* Reject key if subkeys Key_1 and Key_2 are equal. + See "Implementation Guidance for FIPS 140-2, A.9 XTS-AES + Key Generation Requirements" for details. */ + if (buf_eq_const (key, key + keylen, keylen)) + return GPG_ERR_WEAK_KEY; + } + } + rc = c->spec->setkey (&c->context.c, key, keylen); if (!rc) { @@ -653,6 +697,20 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) _gcry_cipher_poly1305_setkey (c); break; + case GCRY_CIPHER_MODE_XTS: + /* Setup tweak cipher with second part of XTS key. */ + rc = c->spec->setkey (c->u_mode.xts.tweak_context, key + keylen, + keylen); + if (!rc) + { + /* Duplicate initial tweak context. */ + memcpy (c->u_mode.xts.tweak_context + c->spec->contextsize, + c->u_mode.xts.tweak_context, c->spec->contextsize); + } + else + c->marks.key = 0; + break; + default: break; }; @@ -751,6 +809,12 @@ cipher_reset (gcry_cipher_hd_t c) c->u_mode.ocb.taglen = 16; break; + case GCRY_CIPHER_MODE_XTS: + memcpy (c->u_mode.xts.tweak_context, + c->u_mode.xts.tweak_context + c->spec->contextsize, + c->spec->contextsize); + break; + default: break; /* u_mode unused by other modes. */ } @@ -872,6 +936,10 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = _gcry_cipher_ocb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_XTS: + rc = _gcry_cipher_xts_crypt (c, outbuf, outbuflen, inbuf, inbuflen, 1); + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stencrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); @@ -995,6 +1063,10 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = _gcry_cipher_ocb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_XTS: + rc = _gcry_cipher_xts_crypt (c, outbuf, outbuflen, inbuf, inbuflen, 0); + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stdecrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); |