diff options
author | Werner Koch <wk@gnupg.org> | 2015-01-16 14:55:03 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2015-01-16 14:55:03 +0100 |
commit | 067d7d8752d4d8a98f8e0e5e9b1a5b13e1b7ff9c (patch) | |
tree | 1eab7affe5d24e919a22a5d4a29c8303342cf8db /tests/benchmark.c | |
parent | 9d2a22c94ae99f9301321082c4fb8d73f4085fda (diff) | |
download | libgcrypt-067d7d8752d4d8a98f8e0e5e9b1a5b13e1b7ff9c.tar.gz |
Add OCB cipher mode
* cipher/cipher-ocb.c: New.
* cipher/Makefile.am (libcipher_la_SOURCES): Add cipher-ocb.c
* cipher/cipher-internal.h (OCB_BLOCK_LEN, OCB_L_TABLE_SIZE): New.
(gcry_cipher_handle): Add fields marks.finalize and u_mode.ocb.
* cipher/cipher.c (_gcry_cipher_open_internal): Add OCB mode.
(_gcry_cipher_open_internal): Setup default taglen of OCB.
(cipher_reset): Clear OCB specific data.
(cipher_encrypt, cipher_decrypt, _gcry_cipher_authenticate)
(_gcry_cipher_gettag, _gcry_cipher_checktag): Call OCB functions.
(_gcry_cipher_setiv): Add OCB specific nonce setting.
(_gcry_cipher_ctl): Add GCRYCTL_FINALIZE and GCRYCTL_SET_TAGLEN
* src/gcrypt.h.in (GCRYCTL_SET_TAGLEN): New.
(gcry_cipher_final): New.
* cipher/bufhelp.h (buf_xor_1): New.
* tests/basic.c (hex2buffer): New.
(check_ocb_cipher): New.
(main): Call it here. Add option --cipher-modes.
* tests/bench-slope.c (bench_aead_encrypt_do_bench): Call
gcry_cipher_final.
(bench_aead_decrypt_do_bench): Ditto.
(bench_aead_authenticate_do_bench): Ditto. Check error code.
(bench_ocb_encrypt_do_bench): New.
(bench_ocb_decrypt_do_bench): New.
(bench_ocb_authenticate_do_bench): New.
(ocb_encrypt_ops): New.
(ocb_decrypt_ops): New.
(ocb_authenticate_ops): New.
(cipher_modes): Add them.
(cipher_bench_one): Skip wrong block length for OCB.
* tests/benchmark.c (cipher_bench): Add field noncelen to MODES. Add
OCB support.
--
See the comments on top of cipher/cipher-ocb.c for the patent status
of the OCB mode.
The implementation has not yet been optimized and as such is not faster
that the other AEAD modes. A first candidate for optimization is the
double_block function. Large improvements can be expected by writing
an AES ECB function to work on multiple blocks.
Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'tests/benchmark.c')
-rw-r--r-- | tests/benchmark.c | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/tests/benchmark.c b/tests/benchmark.c index 5bf92daa..6be9509b 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -779,6 +779,7 @@ cipher_bench ( const char *algoname ) void (* const aead_init)(gcry_cipher_hd_t hd, size_t buflen, int authlen); int req_blocksize; int authlen; + int noncelen; } modes[] = { { GCRY_CIPHER_MODE_ECB, " ECB/Stream", 1 }, { GCRY_CIPHER_MODE_CBC, " CBC", 1 }, @@ -791,6 +792,8 @@ cipher_bench ( const char *algoname ) #endif { GCRY_CIPHER_MODE_GCM, " GCM", 0, NULL, GCRY_GCM_BLOCK_LEN, GCRY_GCM_BLOCK_LEN }, + { GCRY_CIPHER_MODE_OCB, " OCB", 1, + NULL, 16, 16, 15 }, { GCRY_CIPHER_MODE_STREAM, "", 0 }, {0} }; @@ -929,9 +932,30 @@ cipher_bench ( const char *algoname ) exit (1); } } + + if (modes[modeidx].noncelen) + { + char nonce[100]; + size_t noncelen; + + noncelen = modes[modeidx].noncelen; + if (noncelen > sizeof nonce) + noncelen = sizeof nonce; + memset (nonce, 42, noncelen); + err = gcry_cipher_setiv (hd, nonce, noncelen); + if (err) + { + fprintf (stderr, "gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + } + if (modes[modeidx].aead_init) { (*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen); + gcry_cipher_final (hd); err = gcry_cipher_encrypt (hd, outbuf, buflen, buf, buflen); if (err) break; @@ -987,18 +1011,42 @@ cipher_bench ( const char *algoname ) exit (1); } } + + if (modes[modeidx].noncelen) + { + char nonce[100]; + size_t noncelen; + + noncelen = modes[modeidx].noncelen; + if (noncelen > sizeof nonce) + noncelen = sizeof nonce; + memset (nonce, 42, noncelen); + err = gcry_cipher_setiv (hd, nonce, noncelen); + if (err) + { + fprintf (stderr, "gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + } + if (modes[modeidx].aead_init) { (*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen); + gcry_cipher_final (hd); err = gcry_cipher_decrypt (hd, outbuf, buflen, buf, buflen); if (err) break; err = gcry_cipher_checktag (hd, outbuf, modes[modeidx].authlen); if (gpg_err_code (err) == GPG_ERR_CHECKSUM) - err = gpg_error (GPG_ERR_NO_ERROR); + err = 0; } else - err = gcry_cipher_decrypt (hd, outbuf, buflen, buf, buflen); + { + gcry_cipher_final (hd); + err = gcry_cipher_decrypt (hd, outbuf, buflen, buf, buflen); + } } stop_timer (); printf (" %s", elapsed_time ()); |