From cvs at cvs.gnupg.org Wed Jul 4 07:10:32 2018 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Wed, 04 Jul 2018 07:10:32 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.8.1-85-g9660c3f Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 9660c3fafd732b1857bb2697c6f43aed077b9ad6 (commit) from 8a44c55d2fb758f726b8b436aa5c0b88a6c6f112 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 9660c3fafd732b1857bb2697c6f43aed077b9ad6 Author: NIIBE Yutaka Date: Wed Jul 4 14:09:38 2018 +0900 RFC-8439 was published. * cipher/cipher-poly1305.c: Update RFC reference. Signed-off-by: NIIBE Yutaka diff --git a/cipher/cipher-poly1305.c b/cipher/cipher-poly1305.c index a2a74e8..82537aa 100644 --- a/cipher/cipher-poly1305.c +++ b/cipher/cipher-poly1305.c @@ -1,4 +1,4 @@ -/* cipher-poly1305.c - Poly1305 based AEAD cipher mode, RFC-7539 +/* cipher-poly1305.c - Poly1305 based AEAD cipher mode, RFC-8439 * Copyright (C) 2014 Jussi Kivilinna * * This file is part of Libgcrypt. diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 967745f..4cae489 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -1690,7 +1690,7 @@ Associated Data (AEAD) block cipher mode, which is specified in @item GCRY_CIPHER_MODE_POLY1305 @cindex Poly1305 based AEAD mode with ChaCha20 This mode implements the Poly1305 Authenticated Encryption with Associated -Data (AEAD) mode according to RFC-7539. This mode can be used with ChaCha20 +Data (AEAD) mode according to RFC-8439. This mode can be used with ChaCha20 stream cipher. @item GCRY_CIPHER_MODE_OCB ----------------------------------------------------------------------- Summary of changes: cipher/cipher-poly1305.c | 2 +- doc/gcrypt.texi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From sbi at pi4.de Fri Jul 6 10:24:46 2018 From: sbi at pi4.de (Steffen Bingel, pi4) Date: Fri, 6 Jul 2018 10:24:46 +0200 Subject: RSA - relation between message size and key size In-Reply-To: References: Message-ID: <23903ae6-e5b9-ccd8-eaf5-7755a702126a@pi4.de> Hi Karl, thanks for your reply. What I am trying to do goes more into the direction of what gpg offers with its encrypt decrypt feature. As far as I understood there is done what you are suggesting. Create a random key, encrypt the data symmetrically with this key and use asymmetric encryption for this key. Ok... The big unanswered question is still why the gcry_pk_encrypt only works properly with data up to the key size and if that behavior is intended. Why is that function generating unusable output without throwing an error? On 27.06.2018 03:43, Karl Magdsick wrote: > There are a variety of attacks against RSA when used in this manner. You > really should use OAEP ( > https://en.m.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding ) and > you almost certainly should use RSA to exchange keys for a symmetric > authenticated encryption algorithm (such as ChaCha20-Poly1305 or AES-GCM). > > It goes without saying that playing around with encryption is fun, but for > anything serious, use a high-level well-reviewed library implementing > well-studied protocols. libgnutls, libgpgme, and libsodium are good > choices, depending on your use case. libgcrypt is a low-level library > meant as a building block for high-level end-user libraries. > > > Cheers, > Karl > > On Tue, Jun 26, 2018, 23:33 Steffen Bingel, pi4 wrote: > >> Hi, >> >> at first, this is the first time for me using a mailing list and I >> apologize in advance for any violation of rules I may not know yet. >> >> I'm playing around with the private/public key functions of libgcrypt >> and ran into an behavior I couldn't find an explanation for. If my >> message that I try to encrypt is larger than the key I use for >> encryption the pk_encrypt seems to generate random data without throwing >> an error. The following code is a condensed copy from >> https://github.com/vedantk/gcrypt-example/blob/master/main.cc. If my >> message contains 32 characters (256 bit) this works fine but if I pass >> 33 or more characters the decrypted messages makes no sense at all. I >> was also playing around with bigger keys where I could observe the same >> behavior (msg bigger than key not working). >> >> So if the function is not intended to take data larger than the key, why >> is it not returning an error? >> >> What is the correct way to encrypt large, at least larger than the key, >> binary data I have in memory? >> >> Thanks a lot >> >> gcry_error_t err; >> >> #define _assert(cmd) {\ >> err = cmd;\ >> if (err != GPG_ERR_NO_ERROR) {\ >> L("ERR: command returned: %s",gcry_strerror(err));\ >> }} >> >> /* generate key pair */ >> gcry_sexp_t rsa_keypair; >> gcry_sexp_t parms; >> _assert(gcry_sexp_build( &parms, NULL, "(genkey(rsa(nbits >> %d)))",256)); >> >> _assert(gcry_pk_genkey( &rsa_keypair,parms )); >> >> gcry_sexp_t pubk = gcry_sexp_find_token(rsa_keypair, "public-key", 0); >> gcry_sexp_t privk = gcry_sexp_find_token(rsa_keypair, >> "private-key", 0); >> >> /* Create a message. */ >> gcry_mpi_t msg; >> gcry_sexp_t data; >> const unsigned char* s = (const unsigned char*) >> "uweoirdnd1iejfkslrm2kdleirjfm3xss"; >> _assert(gcry_mpi_scan(&msg, GCRYMPI_FMT_USG, s, strlen((const >> char*) s), NULL)); >> >> gcry_mpi_dump(msg); >> >> _assert(gcry_sexp_build(&data, NULL,"(data (flags raw) (value >> %m))", msg)); >> >> gcry_sexp_dump(data); >> >> /* Encrypt the message. */ >> gcry_sexp_t ciph; >> _assert(gcry_pk_encrypt(&ciph, data, pubk)); >> >> gcry_sexp_dump(ciph); >> >> /* Decrypt the message. */ >> gcry_sexp_t plain; >> _assert(gcry_pk_decrypt(&plain, ciph, privk)); >> >> /* Pretty-print the results. */ >> gcry_mpi_t out_msg = gcry_sexp_nth_mpi(plain, 0, GCRYMPI_FMT_USG); >> L("Original:"); >> gcry_mpi_dump(msg); >> L("\n" "Decrypted:"); >> gcry_mpi_dump(out_msg); >> >> if (gcry_mpi_cmp(msg, out_msg)) { >> L("data corruption!"); >> } else { >> L("Messages match.\n"); >> } >> >> >> >> >> >> _______________________________________________ >> Gcrypt-devel mailing list >> Gcrypt-devel at gnupg.org >> http://lists.gnupg.org/mailman/listinfo/gcrypt-devel >> -- shop pi4 Mit freundlichen Gr??en Yours sincerely Steffen Bingel pi4_robotics GmbH Gustav-Meyer-Allee 25 13355 Berlin Tel: +49 (0)30-7009694-210 Fax: +49 (0)30-7009694-69 Email: sbi at pi4.de URL: www.pi4.de Registergericht Berlin HRB 80513 Gesch?ftsf?hrer: Matthias Krinke USt-ID: DE217617178 Zollnr.: 6559298 From w.k at berkeley.edu Fri Jul 6 10:41:45 2018 From: w.k at berkeley.edu (Weikeng Chen) Date: Fri, 6 Jul 2018 01:41:45 -0700 Subject: RSA - relation between message size and key size In-Reply-To: <23903ae6-e5b9-ccd8-eaf5-7755a702126a@pi4.de> References: <23903ae6-e5b9-ccd8-eaf5-7755a702126a@pi4.de> Message-ID: Hi Steffen, I think your question is about whether the encryption algorithm should check where the message fits into the message space. So, asymmetric encryption algorithms today are commonly used to encrypt keys rather than data, and the common key size is far smaller than the message size of common RSA message space. I think that is the reason why such a check does not exist in the current implementation. On Fri, Jul 6, 2018, 1:24 AM Steffen Bingel, pi4 wrote: > Hi Karl, > > thanks for your reply. What I am trying to do goes more into the > direction of what gpg offers with its encrypt decrypt feature. As far as > I understood there is done what you are suggesting. Create a random key, > encrypt the data symmetrically with this key and use asymmetric > encryption for this key. Ok... > > The big unanswered question is still why the gcry_pk_encrypt only works > properly with data up to the key size and if that behavior is intended. > Why is that function generating unusable output without throwing an error? > > On 27.06.2018 03:43, Karl Magdsick wrote: > > There are a variety of attacks against RSA when used in this manner. You > > really should use OAEP ( > > https://en.m.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding ) > and > > you almost certainly should use RSA to exchange keys for a symmetric > > authenticated encryption algorithm (such as ChaCha20-Poly1305 or > AES-GCM). > > > > It goes without saying that playing around with encryption is fun, but > for > > anything serious, use a high-level well-reviewed library implementing > > well-studied protocols. libgnutls, libgpgme, and libsodium are good > > choices, depending on your use case. libgcrypt is a low-level library > > meant as a building block for high-level end-user libraries. > > > > > > Cheers, > > Karl > > > > On Tue, Jun 26, 2018, 23:33 Steffen Bingel, pi4 wrote: > > > >> Hi, > >> > >> at first, this is the first time for me using a mailing list and I > >> apologize in advance for any violation of rules I may not know yet. > >> > >> I'm playing around with the private/public key functions of libgcrypt > >> and ran into an behavior I couldn't find an explanation for. If my > >> message that I try to encrypt is larger than the key I use for > >> encryption the pk_encrypt seems to generate random data without throwing > >> an error. The following code is a condensed copy from > >> https://github.com/vedantk/gcrypt-example/blob/master/main.cc. If my > >> message contains 32 characters (256 bit) this works fine but if I pass > >> 33 or more characters the decrypted messages makes no sense at all. I > >> was also playing around with bigger keys where I could observe the same > >> behavior (msg bigger than key not working). > >> > >> So if the function is not intended to take data larger than the key, why > >> is it not returning an error? > >> > >> What is the correct way to encrypt large, at least larger than the key, > >> binary data I have in memory? > >> > >> Thanks a lot > >> > >> gcry_error_t err; > >> > >> #define _assert(cmd) {\ > >> err = cmd;\ > >> if (err != GPG_ERR_NO_ERROR) {\ > >> L("ERR: command returned: %s",gcry_strerror(err));\ > >> }} > >> > >> /* generate key pair */ > >> gcry_sexp_t rsa_keypair; > >> gcry_sexp_t parms; > >> _assert(gcry_sexp_build( &parms, NULL, "(genkey(rsa(nbits > >> %d)))",256)); > >> > >> _assert(gcry_pk_genkey( &rsa_keypair,parms )); > >> > >> gcry_sexp_t pubk = gcry_sexp_find_token(rsa_keypair, > "public-key", 0); > >> gcry_sexp_t privk = gcry_sexp_find_token(rsa_keypair, > >> "private-key", 0); > >> > >> /* Create a message. */ > >> gcry_mpi_t msg; > >> gcry_sexp_t data; > >> const unsigned char* s = (const unsigned char*) > >> "uweoirdnd1iejfkslrm2kdleirjfm3xss"; > >> _assert(gcry_mpi_scan(&msg, GCRYMPI_FMT_USG, s, strlen((const > >> char*) s), NULL)); > >> > >> gcry_mpi_dump(msg); > >> > >> _assert(gcry_sexp_build(&data, NULL,"(data (flags raw) (value > >> %m))", msg)); > >> > >> gcry_sexp_dump(data); > >> > >> /* Encrypt the message. */ > >> gcry_sexp_t ciph; > >> _assert(gcry_pk_encrypt(&ciph, data, pubk)); > >> > >> gcry_sexp_dump(ciph); > >> > >> /* Decrypt the message. */ > >> gcry_sexp_t plain; > >> _assert(gcry_pk_decrypt(&plain, ciph, privk)); > >> > >> /* Pretty-print the results. */ > >> gcry_mpi_t out_msg = gcry_sexp_nth_mpi(plain, 0, GCRYMPI_FMT_USG); > >> L("Original:"); > >> gcry_mpi_dump(msg); > >> L("\n" "Decrypted:"); > >> gcry_mpi_dump(out_msg); > >> > >> if (gcry_mpi_cmp(msg, out_msg)) { > >> L("data corruption!"); > >> } else { > >> L("Messages match.\n"); > >> } > >> > >> > >> > >> > >> > >> _______________________________________________ > >> Gcrypt-devel mailing list > >> Gcrypt-devel at gnupg.org > >> http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > >> > > -- > > > shop pi4 > > > > Mit freundlichen Gr??en > Yours sincerely > > Steffen Bingel > > pi4_robotics GmbH > Gustav-Meyer-Allee 25 > 13355 Berlin > Tel: +49 (0)30-7009694-210 > Fax: +49 (0)30-7009694-69 > Email: sbi at pi4.de > URL: www.pi4.de > Registergericht Berlin HRB 80513 > Gesch?ftsf?hrer: Matthias Krinke > USt-ID: DE217617178 > Zollnr.: 6559298 > > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From wk at gnupg.org Sat Jul 7 12:25:56 2018 From: wk at gnupg.org (Werner Koch) Date: Sat, 07 Jul 2018 12:25:56 +0200 Subject: RSA - relation between message size and key size In-Reply-To: <23903ae6-e5b9-ccd8-eaf5-7755a702126a@pi4.de> (Steffen Bingel's message of "Fri, 6 Jul 2018 10:24:46 +0200") References: <23903ae6-e5b9-ccd8-eaf5-7755a702126a@pi4.de> Message-ID: <87k1q7tk97.fsf@wheatstone.g10code.de> On Fri, 6 Jul 2018 10:24, sbi at pi4.de said: > The big unanswered question is still why the gcry_pk_encrypt only > works properly with data up to the key size and if that behavior is > intended. Why is that function generating unusable output without > throwing an error? Because Libgcrypt is a low-level library which even the release announcements tell: Libgcrypt is a general purpose library of cryptographic building blocks. It is originally based on code used by GnuPG. It does not provide any implementation of OpenPGP or other protocols. _Thorough_ _understanding of applied cryptography is required to use Libgcrypt_. Salam-Shalom, Werner -- # Please read: Daniel Ellsberg - The Doomsday Machine # Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 227 bytes Desc: not available URL: From stefbon at gmail.com Wed Jul 18 08:33:39 2018 From: stefbon at gmail.com (Stef Bon) Date: Wed, 18 Jul 2018 08:33:39 +0200 Subject: Correct method to generate a Curve25519 keypair In-Reply-To: References: <7E3FC5D1-7172-45D1-ADE9-102EE73AA850@me.com> <68AB9180-0D76-4B76-99A5-C4E8AFA23CF0@me.com> Message-ID: Op vr 29 jun. 2018 om 05:09 schreef Alexander Lyon : > djb-tweak and comp are necessary to generate the key. I have not found out > how to make it work without those flags. In fact, changing comp > (compressed) to nocomp causes the program to crash. > > the flag "comp" is not required. See in the tests/t-cv25519.c line +- 176. Futher hwo do you create the shared secret k. This is described in https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256 at libssh.org.txt 4.3 Shared secret generation. It goes via scalar multiplication of the "other side's public key and the local private key scalar". Both are available, but scalar multiplaction of q_s and d_c? Stef -------------- next part -------------- An HTML attachment was scrubbed... URL: From arlyon at me.com Wed Jul 18 12:55:56 2018 From: arlyon at me.com (Alexander Lyon) Date: Wed, 18 Jul 2018 12:55:56 +0200 Subject: Correct method to generate a Curve25519 keypair In-Reply-To: References: <7E3FC5D1-7172-45D1-ADE9-102EE73AA850@me.com> <68AB9180-0D76-4B76-99A5-C4E8AFA23CF0@me.com> Message-ID: You are correct that it is not required, but when you don't specify it, it adds in anyways. I have successfully managed to get curve25519 diffie-hellman to work, which you can observe here: https://code.videolan.org/GSoC2018/arlyon/vlc/blob/airplay-auth/modules/stream_out/airplay/airplay.c#L911 You could also look at TestCurveDH for an example usage from a hex string https://code.videolan.org/GSoC2018/arlyon/vlc/blob/airplay-auth/modules/stream_out/airplay/airplay.c#L2058 Which successfully passes given the test vectors from RFC7748 https://tools.ietf.org/html/rfc7748#section-5.2 Please note that gcrypt expects the private key in gcry_pk_encrypt to be "backwards" (compared to the RFC) during diffie-hellman which is usually okay because it is stored "backwards" in the sexp. However, to accept the test vectors as they are presented in the specification, it was necessary to have the function accept it the "right" way, which is why the buffer is reversed in the function. gcry_pk_encrypt will output a value "s" which needs to be decompressed and then reversed to give the "correct" shared key. Alex > On 18 Jul 2018, at 08:33, Stef Bon wrote: > > > > Op vr 29 jun. 2018 om 05:09 schreef Alexander Lyon : > djb-tweak and comp are necessary to generate the key. I have not found out how to make it work without those flags. In fact, changing comp (compressed) to nocomp causes the program to crash. > > > the flag "comp" is not required. See in the tests/t-cv25519.c line +- 176. > > Futher hwo do you create the shared secret k. This is described in https://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256 at libssh.org.txt 4.3 Shared secret generation. > It goes via scalar multiplication of the "other side's public key and the local private key scalar". > Both are available, but scalar multiplaction of q_s and d_c? > > Stef > > From stefbon at gmail.com Wed Jul 18 14:16:45 2018 From: stefbon at gmail.com (Stef Bon) Date: Wed, 18 Jul 2018 14:16:45 +0200 Subject: Correct method to generate a Curve25519 keypair In-Reply-To: References: <7E3FC5D1-7172-45D1-ADE9-102EE73AA850@me.com> <68AB9180-0D76-4B76-99A5-C4E8AFA23CF0@me.com> Message-ID: Op wo 18 jul. 2018 om 12:56 schreef Alexander Lyon : > You are correct that it is not required, but when you don't specify it, it > adds in anyways. I have successfully managed to get curve25519 > diffie-hellman to work, which you can observe here: > > > https://code.videolan.org/GSoC2018/arlyon/vlc/blob/airplay-auth/modules/stream_out/airplay/airplay.c#L911 > Using gcry_pk_encrypt does the trick? I did not see that coming. Thank thanks a lot for sharing, Stef Bon Voorburg the Netherlands -------------- next part -------------- An HTML attachment was scrubbed... URL: From stefbon at gmail.com Fri Jul 20 21:49:51 2018 From: stefbon at gmail.com (Stef Bon) Date: Fri, 20 Jul 2018 21:49:51 +0200 Subject: Correct method to generate a Curve25519 keypair In-Reply-To: References: <7E3FC5D1-7172-45D1-ADE9-102EE73AA850@me.com> <68AB9180-0D76-4B76-99A5-C4E8AFA23CF0@me.com> Message-ID: How did you find out you have to use gcry_pk_encrypt for getting the shared k?? I cannot find any doumentation about it and without your help I would still be searching. Stef Bon the Netherlands/ Pays Bas > -------------- next part -------------- An HTML attachment was scrubbed... URL: From stefbon at gmail.com Sun Jul 22 09:47:23 2018 From: stefbon at gmail.com (Stef Bon) Date: Sun, 22 Jul 2018 09:47:23 +0200 Subject: Correct method to generate a Curve25519 keypair In-Reply-To: <54819420-0F13-4964-A80A-37BFD62E853D@gmail.com> References: <7E3FC5D1-7172-45D1-ADE9-102EE73AA850@me.com> <68AB9180-0D76-4B76-99A5-C4E8AFA23CF0@me.com> <54819420-0F13-4964-A80A-37BFD62E853D@gmail.com> Message-ID: Thanks. I've implemented this in my code, see: https://github.com/stefbon/fs-workspace/blob/master/ssh/keyexchange/ecdh.c#L184 I've not tested this but it looks good. Stef -------------- next part -------------- An HTML attachment was scrubbed... URL: From jussi.kivilinna at iki.fi Sat Jul 21 12:11:24 2018 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 21 Jul 2018 13:11:24 +0300 Subject: [PATCH] Add size optimized cipher block copy and xor functions Message-ID: <20180721101124.17748-1-jussi.kivilinna@iki.fi> * cipher/bufhelp.h (buf_get_he32, buf_put_he32, buf_get_he64) (buf_put_he64): New. * cipher/cipher-internal.h (cipher_block_cpy, cipher_block_xor) (cipher_block_xor_1, cipher_block_xor_2dst, cipher_block_xor_n_copy_2) (cipher_block_xor_n_copy): New. * cipher/cipher-gcm-intel-pclmul.c (_gcry_ghash_setup_intel_pclmul): Use assembly for swapping endianness instead of buf_get_be64 and buf_cpy. * cipher/blowfish.c: Use new cipher_block_* functions for cipher block sized buf_cpy/xor* operations. * cipher/camellia-glue.c: Ditto. * cipher/cast5.c: Ditto. * cipher/cipher-aeswrap.c: Ditto. * cipher/cipher-cbc.c: Ditto. * cipher/cipher-ccm.c: Ditto. * cipher/cipher-cfb.c: Ditto. * cipher/cipher-cmac.c: Ditto. * cipher/cipher-ctr.c: Ditto. * cipher/cipher-eax.c: Ditto. * cipher/cipher-gcm.c: Ditto. * cipher/cipher-ocb.c: Ditto. * cipher/cipher-ofb.c: Ditto. * cipher/cipher-xts.c: Ditto. * cipher/des.c: Ditto. * cipher/rijndael.c: Ditto. * cipher/serpent.c: Ditto. * cipher/twofish.c: Ditto. -- This commit adds size-optimized functions for copying and xoring cipher block sized buffers. These functions also allow GCC to use inline auto-vectorization for block cipher copying and xoring on higher optimization levels. Signed-off-by: Jussi Kivilinna --- cipher/blowfish.c | 7 +- cipher/bufhelp.h | 16 +++- cipher/camellia-glue.c | 7 +- cipher/cast5.c | 7 +- cipher/cipher-aeswrap.c | 4 +- cipher/cipher-cbc.c | 15 ++-- cipher/cipher-ccm.c | 7 +- cipher/cipher-cfb.c | 16 ++-- cipher/cipher-cmac.c | 8 +- cipher/cipher-ctr.c | 50 +++++++---- cipher/cipher-eax.c | 11 +-- cipher/cipher-gcm-intel-pclmul.c | 21 +++-- cipher/cipher-gcm.c | 14 +-- cipher/cipher-internal.h | 141 +++++++++++++++++++++++++++++++ cipher/cipher-ocb.c | 81 +++++++++--------- cipher/cipher-ofb.c | 2 +- cipher/cipher-xts.c | 14 +-- cipher/des.c | 7 +- cipher/rijndael.c | 43 +++++----- cipher/serpent.c | 7 +- cipher/twofish.c | 6 +- 21 files changed, 335 insertions(+), 149 deletions(-) diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 2d9182009..f032c5c6f 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -37,6 +37,7 @@ #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" +#include "cipher-internal.h" #include "cipher-selftest.h" #define BLOWFISH_BLOCKSIZE 8 @@ -660,7 +661,7 @@ _gcry_blowfish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, /* Encrypt the counter. */ do_encrypt_block(ctx, tmpbuf, ctr); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, BLOWFISH_BLOCKSIZE); + cipher_block_xor(outbuf, tmpbuf, inbuf, BLOWFISH_BLOCKSIZE); outbuf += BLOWFISH_BLOCKSIZE; inbuf += BLOWFISH_BLOCKSIZE; /* Increment the counter. */ @@ -728,7 +729,7 @@ _gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, the intermediate result to SAVEBUF. */ do_decrypt_block (ctx, savebuf, inbuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOWFISH_BLOCKSIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOWFISH_BLOCKSIZE); inbuf += BLOWFISH_BLOCKSIZE; outbuf += BLOWFISH_BLOCKSIZE; } @@ -785,7 +786,7 @@ _gcry_blowfish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, for ( ;nblocks; nblocks-- ) { do_encrypt_block(ctx, iv, iv); - buf_xor_n_copy(outbuf, iv, inbuf, BLOWFISH_BLOCKSIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, BLOWFISH_BLOCKSIZE); outbuf += BLOWFISH_BLOCKSIZE; inbuf += BLOWFISH_BLOCKSIZE; } diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h index 83d3f53aa..4e97c4d41 100644 --- a/cipher/bufhelp.h +++ b/cipher/bufhelp.h @@ -450,7 +450,21 @@ static inline void buf_put_le64(void *_buf, u64 val) out->a = le_bswap64(val); } - #endif /*BUFHELP_UNALIGNED_ACCESS*/ + +/* Host-endian get/put macros */ +#ifdef WORDS_BIGENDIAN +# define buf_get_he32 buf_get_be32 +# define buf_put_he32 buf_put_be32 +# define buf_get_he64 buf_get_be64 +# define buf_put_he64 buf_put_be64 +#else +# define buf_get_he32 buf_get_le32 +# define buf_put_he32 buf_put_le32 +# define buf_get_he64 buf_get_le64 +# define buf_put_he64 buf_put_le64 +#endif + + #endif /*GCRYPT_BUFHELP_H*/ diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index 22df21469..69b240b79 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -430,7 +430,7 @@ _gcry_camellia_ctr_enc(void *context, unsigned char *ctr, /* Encrypt the counter. */ Camellia_EncryptBlock(ctx->keybitlength, ctr, ctx->keytable, tmpbuf); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, CAMELLIA_BLOCK_SIZE); + cipher_block_xor(outbuf, tmpbuf, inbuf, CAMELLIA_BLOCK_SIZE); outbuf += CAMELLIA_BLOCK_SIZE; inbuf += CAMELLIA_BLOCK_SIZE; /* Increment the counter. */ @@ -523,7 +523,8 @@ _gcry_camellia_cbc_dec(void *context, unsigned char *iv, the intermediate result to SAVEBUF. */ Camellia_DecryptBlock(ctx->keybitlength, inbuf, ctx->keytable, savebuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAMELLIA_BLOCK_SIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, + CAMELLIA_BLOCK_SIZE); inbuf += CAMELLIA_BLOCK_SIZE; outbuf += CAMELLIA_BLOCK_SIZE; } @@ -605,7 +606,7 @@ _gcry_camellia_cfb_dec(void *context, unsigned char *iv, for ( ;nblocks; nblocks-- ) { Camellia_EncryptBlock(ctx->keybitlength, iv, ctx->keytable, iv); - buf_xor_n_copy(outbuf, iv, inbuf, CAMELLIA_BLOCK_SIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, CAMELLIA_BLOCK_SIZE); outbuf += CAMELLIA_BLOCK_SIZE; inbuf += CAMELLIA_BLOCK_SIZE; } diff --git a/cipher/cast5.c b/cipher/cast5.c index e7d324b25..49e8b781b 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -44,6 +44,7 @@ #include "cipher.h" #include "bithelp.h" #include "bufhelp.h" +#include "cipher-internal.h" #include "cipher-selftest.h" /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */ @@ -634,7 +635,7 @@ _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, /* Encrypt the counter. */ do_encrypt_block(ctx, tmpbuf, ctr); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, CAST5_BLOCKSIZE); + cipher_block_xor(outbuf, tmpbuf, inbuf, CAST5_BLOCKSIZE); outbuf += CAST5_BLOCKSIZE; inbuf += CAST5_BLOCKSIZE; /* Increment the counter. */ @@ -702,7 +703,7 @@ _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, the intermediate result to SAVEBUF. */ do_decrypt_block (ctx, savebuf, inbuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAST5_BLOCKSIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAST5_BLOCKSIZE); inbuf += CAST5_BLOCKSIZE; outbuf += CAST5_BLOCKSIZE; } @@ -758,7 +759,7 @@ _gcry_cast5_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, for ( ;nblocks; nblocks-- ) { do_encrypt_block(ctx, iv, iv); - buf_xor_n_copy(outbuf, iv, inbuf, CAST5_BLOCKSIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, CAST5_BLOCKSIZE); outbuf += CAST5_BLOCKSIZE; inbuf += CAST5_BLOCKSIZE; } diff --git a/cipher/cipher-aeswrap.c b/cipher/cipher-aeswrap.c index a8d0e03ee..c182657e1 100644 --- a/cipher/cipher-aeswrap.c +++ b/cipher/cipher-aeswrap.c @@ -99,7 +99,7 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c, break; } /* A := MSB_64(B) ^ t */ - buf_xor(a, b, t, 8); + cipher_block_xor(a, b, t, 8); /* R[i] := LSB_64(B) */ memcpy (r+i*8, b+8, 8); } @@ -170,7 +170,7 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c, for (i = n; i >= 1; i--) { /* B := AES_k^1( (A ^ t)| R[i] ) */ - buf_xor(b, a, t, 8); + cipher_block_xor(b, a, t, 8); memcpy (b+8, r+(i-1)*8, 8); nburn = c->spec->decrypt (&c->context.c, b, b); burn = nburn > burn ? nburn : burn; diff --git a/cipher/cipher-cbc.c b/cipher/cipher-cbc.c index 2ad39d09d..d4df1e72a 100644 --- a/cipher/cipher-cbc.c +++ b/cipher/cipher-cbc.c @@ -56,7 +56,7 @@ cbc_encrypt_inner(gcry_cipher_hd_t c, unsigned char *outbuf, for (n=0; n < nblocks; n++ ) { - buf_xor (outbuf, inbuf, ivp, blocksize); + cipher_block_xor (outbuf, inbuf, ivp, blocksize); nburn = enc_fn ( &c->context.c, outbuf, outbuf ); burn = nburn > burn ? nburn : burn; ivp = outbuf; @@ -66,7 +66,7 @@ cbc_encrypt_inner(gcry_cipher_hd_t c, unsigned char *outbuf, } if (ivp != c->u_iv.iv) - buf_cpy (c->u_iv.iv, ivp, blocksize); + cipher_block_cpy (c->u_iv.iv, ivp, blocksize); } return burn; @@ -156,7 +156,7 @@ _gcry_cipher_cbc_cts_encrypt (gcry_cipher_hd_t c, nburn = enc_fn (&c->context.c, outbuf, outbuf); burn = nburn > burn ? nburn : burn; - buf_cpy (c->u_iv.iv, outbuf, blocksize); + cipher_block_cpy (c->u_iv.iv, outbuf, blocksize); } if (burn > 0) @@ -190,7 +190,8 @@ cbc_decrypt_inner(gcry_cipher_hd_t c, unsigned char *outbuf, storage here because it is not used otherwise. */ nburn = dec_fn ( &c->context.c, c->lastiv, inbuf ); burn = nburn > burn ? nburn : burn; - buf_xor_n_copy_2 (outbuf, c->lastiv, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor_n_copy_2 (outbuf, c->lastiv, c->u_iv.iv, inbuf, + blocksize); inbuf += blocksize; outbuf += blocksize; } @@ -252,7 +253,7 @@ _gcry_cipher_cbc_cts_decrypt (gcry_cipher_hd_t c, nblocks--; if ((inbuflen & blocksize_mask) == 0) nblocks--; - buf_cpy (c->lastiv, c->u_iv.iv, blocksize); + cipher_block_cpy (c->lastiv, c->u_iv.iv, blocksize); } burn = cbc_decrypt_inner(c, outbuf, inbuf, nblocks, blocksize); @@ -268,7 +269,7 @@ _gcry_cipher_cbc_cts_decrypt (gcry_cipher_hd_t c, else restbytes = inbuflen & blocksize_mask; - buf_cpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */ + cipher_block_cpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */ buf_cpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */ nburn = dec_fn ( &c->context.c, outbuf, inbuf ); @@ -280,7 +281,7 @@ _gcry_cipher_cbc_cts_decrypt (gcry_cipher_hd_t c, c->u_iv.iv[i] = outbuf[i]; nburn = dec_fn (&c->context.c, outbuf, c->u_iv.iv); burn = nburn > burn ? nburn : burn; - buf_xor(outbuf, outbuf, c->lastiv, blocksize); + cipher_block_xor(outbuf, outbuf, c->lastiv, blocksize); /* c->lastiv is now really lastlastiv, does this matter? */ } diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c index d7f14d890..e71c6f159 100644 --- a/cipher/cipher-ccm.c +++ b/cipher/cipher-ccm.c @@ -67,7 +67,8 @@ do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen, if (unused > 0) { /* Process one block from macbuf. */ - buf_xor(c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.macbuf, blocksize); + cipher_block_xor(c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.macbuf, + blocksize); set_burn (burn, enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv )); unused = 0; @@ -86,7 +87,7 @@ do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen, { while (inlen >= blocksize) { - buf_xor(c->u_iv.iv, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor(c->u_iv.iv, c->u_iv.iv, inbuf, blocksize); set_burn (burn, enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv )); @@ -272,7 +273,7 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf, burn = do_cbc_mac (c, NULL, 0, 1); /* Perform final padding. */ /* Add S_0 */ - buf_xor (c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.s0, 16); + cipher_block_xor (c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.s0, 16); wipememory (c->u_ctr.ctr, 16); wipememory (c->u_mode.ccm.s0, 16); diff --git a/cipher/cipher-cfb.c b/cipher/cipher-cfb.c index 7f00aee5c..012c6c13c 100644 --- a/cipher/cipher-cfb.c +++ b/cipher/cipher-cfb.c @@ -87,7 +87,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV. */ - buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; inbuflen -= blocksize; @@ -97,11 +97,11 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, if ( inbuflen >= blocksize ) { /* Save the current IV and then encrypt the IV. */ - buf_cpy( c->lastiv, c->u_iv.iv, blocksize ); + cipher_block_cpy( c->lastiv, c->u_iv.iv, blocksize ); nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV */ - buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; inbuflen -= blocksize; @@ -109,7 +109,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, if ( inbuflen ) { /* Save the current IV and then encrypt the IV. */ - buf_cpy( c->lastiv, c->u_iv.iv, blocksize ); + cipher_block_cpy( c->lastiv, c->u_iv.iv, blocksize ); nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; c->unused = blocksize; @@ -185,7 +185,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV. */ - buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; inbuflen -= blocksize; @@ -195,11 +195,11 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, if (inbuflen >= blocksize ) { /* Save the current IV and then encrypt the IV. */ - buf_cpy ( c->lastiv, c->u_iv.iv, blocksize); + cipher_block_cpy ( c->lastiv, c->u_iv.iv, blocksize); nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV */ - buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; inbuflen -= blocksize; @@ -208,7 +208,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, if (inbuflen) { /* Save the current IV and then encrypt the IV. */ - buf_cpy ( c->lastiv, c->u_iv.iv, blocksize ); + cipher_block_cpy ( c->lastiv, c->u_iv.iv, blocksize ); nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; c->unused = blocksize; diff --git a/cipher/cipher-cmac.c b/cipher/cipher-cmac.c index 321ab9eab..da550c372 100644 --- a/cipher/cipher-cmac.c +++ b/cipher/cipher-cmac.c @@ -66,7 +66,7 @@ _gcry_cmac_write (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx, for (; inlen && ctx->mac_unused < blocksize; inlen--) ctx->macbuf[ctx->mac_unused++] = *inbuf++; - buf_xor (ctx->u_iv.iv, ctx->u_iv.iv, ctx->macbuf, blocksize); + cipher_block_xor (ctx->u_iv.iv, ctx->u_iv.iv, ctx->macbuf, blocksize); set_burn (burn, enc_fn (&c->context.c, ctx->u_iv.iv, ctx->u_iv.iv)); ctx->mac_unused = 0; @@ -86,7 +86,7 @@ _gcry_cmac_write (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx, else while (inlen > blocksize) { - buf_xor (ctx->u_iv.iv, ctx->u_iv.iv, inbuf, blocksize); + cipher_block_xor (ctx->u_iv.iv, ctx->u_iv.iv, inbuf, blocksize); set_burn (burn, enc_fn (&c->context.c, ctx->u_iv.iv, ctx->u_iv.iv)); inlen -= blocksize; inbuf += blocksize; @@ -181,9 +181,9 @@ _gcry_cmac_final (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx) ctx->macbuf[count++] = 0; } - buf_xor (ctx->macbuf, ctx->macbuf, subkey, blocksize); + cipher_block_xor (ctx->macbuf, ctx->macbuf, subkey, blocksize); - buf_xor (ctx->u_iv.iv, ctx->u_iv.iv, ctx->macbuf, blocksize); + cipher_block_xor (ctx->u_iv.iv, ctx->u_iv.iv, ctx->macbuf, blocksize); burn = c->spec->encrypt (&c->context.c, ctx->u_iv.iv, ctx->u_iv.iv); if (burn) _gcry_burn_stack (burn + 4 * sizeof (void *)); diff --git a/cipher/cipher-ctr.c b/cipher/cipher-ctr.c index b54fb5a73..2df0b8c3e 100644 --- a/cipher/cipher-ctr.c +++ b/cipher/cipher-ctr.c @@ -77,24 +77,38 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c, { unsigned char tmp[MAX_BLOCKSIZE]; - do { - nburn = enc_fn (&c->context.c, tmp, c->u_ctr.ctr); - burn = nburn > burn ? nburn : burn; - - for (i = blocksize; i > 0; i--) - { - c->u_ctr.ctr[i-1]++; - if (c->u_ctr.ctr[i-1] != 0) - break; - } - - n = blocksize < inbuflen ? blocksize : inbuflen; - buf_xor(outbuf, inbuf, tmp, n); - - inbuflen -= n; - outbuf += n; - inbuf += n; - } while (inbuflen); + do + { + nburn = enc_fn (&c->context.c, tmp, c->u_ctr.ctr); + burn = nburn > burn ? nburn : burn; + + for (i = blocksize; i > 0; i--) + { + c->u_ctr.ctr[i-1]++; + if (c->u_ctr.ctr[i-1] != 0) + break; + } + + if (inbuflen < blocksize) + break; + n = blocksize; + cipher_block_xor(outbuf, inbuf, tmp, blocksize); + + inbuflen -= n; + outbuf += n; + inbuf += n; + } + while (inbuflen); + + if (inbuflen) + { + n = inbuflen; + buf_xor(outbuf, inbuf, tmp, inbuflen); + + inbuflen -= n; + outbuf += n; + inbuf += n; + } /* Save the unused bytes of the counter. */ c->unused = blocksize - n; diff --git a/cipher/cipher-eax.c b/cipher/cipher-eax.c index 1ce479755..3b17bb648 100644 --- a/cipher/cipher-eax.c +++ b/cipher/cipher-eax.c @@ -157,8 +157,8 @@ _gcry_cipher_eax_set_nonce (gcry_cipher_hd_t c, const byte *nonce, if (err != 0) return err; - buf_cpy (c->u_iv.iv, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE); - buf_cpy (c->u_ctr.ctr, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE); + cipher_block_cpy (c->u_iv.iv, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE); + cipher_block_cpy (c->u_ctr.ctr, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE); wipememory (&nonce_cmac, sizeof(nonce_cmac)); @@ -201,9 +201,10 @@ _gcry_cipher_eax_tag (gcry_cipher_hd_t c, if (err != 0) return err; - buf_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_header.u_iv.iv, MAX_BLOCKSIZE); - buf_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_ciphertext.u_iv.iv, - MAX_BLOCKSIZE); + cipher_block_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_header.u_iv.iv, + MAX_BLOCKSIZE); + cipher_block_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_ciphertext.u_iv.iv, + MAX_BLOCKSIZE); _gcry_cmac_reset (&c->u_mode.eax.cmac_header); _gcry_cmac_reset (&c->u_mode.eax.cmac_ciphertext); diff --git a/cipher/cipher-gcm-intel-pclmul.c b/cipher/cipher-gcm-intel-pclmul.c index a32724975..0f26277a5 100644 --- a/cipher/cipher-gcm-intel-pclmul.c +++ b/cipher/cipher-gcm-intel-pclmul.c @@ -248,7 +248,8 @@ static inline void gfmul_pclmul_aggr4(void) void _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c) { - u64 tmp[2]; + static const unsigned char be_mask[16] __attribute__ ((aligned (16))) = + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; #if defined(__x86_64__) && defined(__WIN64__) char win64tmp[3 * 16]; @@ -262,15 +263,19 @@ _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c) #endif /* Swap endianness of hsub. */ - tmp[0] = buf_get_be64(c->u_mode.gcm.u_ghash_key.key + 8); - tmp[1] = buf_get_be64(c->u_mode.gcm.u_ghash_key.key + 0); - buf_cpy (c->u_mode.gcm.u_ghash_key.key, tmp, GCRY_GCM_BLOCK_LEN); + asm volatile ("movdqu (%[key]), %%xmm0\n\t" + "pshufb %[be_mask], %%xmm0\n\t" + "movdqu %%xmm0, (%[key])\n\t" + : + : [key] "r" (c->u_mode.gcm.u_ghash_key.key), + [be_mask] "m" (*be_mask) + : "memory"); #ifdef __x86_64__ - asm volatile ("movdqu %[h_1], %%xmm0\n\t" - "movdqa %%xmm0, %%xmm1\n\t" + asm volatile ("movdqa %%xmm0, %%xmm1\n\t" : - : [h_1] "m" (*tmp)); + : + : "memory"); gfmul_pclmul (); /* H?H => H? */ @@ -324,8 +329,6 @@ _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c) ::: "cc" ); #endif #endif - - wipememory (tmp, sizeof(tmp)); } diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 6169d1427..32ec9fa06 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -150,7 +150,7 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u64 *gcmM) u32 A; int i; - buf_xor (V, result, buf, 16); + cipher_block_xor (V, result, buf, 16); V[0] = be_bswap64 (V[0]); V[1] = be_bswap64 (V[1]); @@ -259,7 +259,7 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u32 *gcmM) u32 T[3]; int i; - buf_xor (V, result, buf, 16); /* V is big-endian */ + cipher_block_xor (V, result, buf, 16); /* V is big-endian */ /* First round can be manually tweaked based on fact that 'tmp' is zero. */ i = 15; @@ -342,7 +342,7 @@ do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) #else unsigned long T[4]; - buf_xor (V, result, buf, 16); + cipher_block_xor (V, result, buf, 16); for (i = 0; i < 4; i++) { V[i] = (V[i] & 0x00ff00ff) << 8 | (V[i] & 0xff00ff00) >> 8; @@ -358,7 +358,7 @@ do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) for (j = 0x80; j; j >>= 1) { if (hsub[i] & j) - buf_xor (p, p, V, 16); + cipher_block_xor (p, p, V, 16); if (bshift (V)) V[0] ^= 0xe1000000; } @@ -598,7 +598,7 @@ gcm_ctr_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, } fix_ctr = 1; - buf_cpy(ctr_copy, c->u_ctr.ctr, GCRY_GCM_BLOCK_LEN); + cipher_block_cpy(ctr_copy, c->u_ctr.ctr, GCRY_GCM_BLOCK_LEN); } } @@ -928,8 +928,8 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, /* Add bitlengths to tag. */ do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, (byte*)bitlengths, GCRY_GCM_BLOCK_LEN, 1); - buf_xor (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.tagiv, - c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); + cipher_block_xor (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.tagiv, + c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); c->marks.tag = 1; wipememory (bitlengths, sizeof (bitlengths)); diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index 6d87561de..f93363b43 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -603,4 +603,145 @@ static inline unsigned int _gcry_blocksize_shift(gcry_cipher_hd_t c) } +/* Optimized function for cipher block copying */ +static inline void +cipher_block_cpy(void *_dst, const void *_src, size_t blocksize) +{ + byte *dst = _dst; + const byte *src = _src; + u64 s[2]; + + if (blocksize == 8) + { + buf_put_he64(dst + 0, buf_get_he64(src + 0)); + } + else /* blocksize == 16 */ + { + s[0] = buf_get_he64(src + 0); + s[1] = buf_get_he64(src + 8); + buf_put_he64(dst + 0, s[0]); + buf_put_he64(dst + 8, s[1]); + } +} + + +/* Optimized function for cipher block xoring */ +static inline void +cipher_block_xor(void *_dst, const void *_src1, const void *_src2, + size_t blocksize) +{ + byte *dst = _dst; + const byte *src1 = _src1; + const byte *src2 = _src2; + u64 s1[2]; + u64 s2[2]; + + if (blocksize == 8) + { + buf_put_he64(dst + 0, buf_get_he64(src1 + 0) ^ buf_get_he64(src2 + 0)); + } + else /* blocksize == 16 */ + { + s1[0] = buf_get_he64(src1 + 0); + s1[1] = buf_get_he64(src1 + 8); + s2[0] = buf_get_he64(src2 + 0); + s2[1] = buf_get_he64(src2 + 8); + buf_put_he64(dst + 0, s1[0] ^ s2[0]); + buf_put_he64(dst + 8, s1[1] ^ s2[1]); + } +} + + +/* Optimized function for in-place cipher block xoring */ +static inline void +cipher_block_xor_1(void *_dst, const void *_src, size_t blocksize) +{ + cipher_block_xor (_dst, _dst, _src, blocksize); +} + + +/* Optimized function for cipher block xoring with two destination cipher + blocks. Used mainly by CFB mode encryption. */ +static inline void +cipher_block_xor_2dst(void *_dst1, void *_dst2, const void *_src, + size_t blocksize) +{ + byte *dst1 = _dst1; + byte *dst2 = _dst2; + const byte *src = _src; + u64 d2[2]; + u64 s[2]; + + if (blocksize == 8) + { + d2[0] = buf_get_he64(dst2 + 0) ^ buf_get_he64(src + 0); + buf_put_he64(dst2 + 0, d2[0]); + buf_put_he64(dst1 + 0, d2[0]); + } + else /* blocksize == 16 */ + { + s[0] = buf_get_he64(src + 0); + s[1] = buf_get_he64(src + 8); + d2[0] = buf_get_he64(dst2 + 0); + d2[1] = buf_get_he64(dst2 + 8); + d2[0] = d2[0] ^ s[0]; + d2[1] = d2[1] ^ s[1]; + buf_put_he64(dst2 + 0, d2[0]); + buf_put_he64(dst2 + 8, d2[1]); + buf_put_he64(dst1 + 0, d2[0]); + buf_put_he64(dst1 + 8, d2[1]); + } +} + + +/* Optimized function for combined cipher block xoring and copying. + Used by mainly CBC mode decryption. */ +static inline void +cipher_block_xor_n_copy_2(void *_dst_xor, const void *_src_xor, + void *_srcdst_cpy, const void *_src_cpy, + size_t blocksize) +{ + byte *dst_xor = _dst_xor; + byte *srcdst_cpy = _srcdst_cpy; + const byte *src_xor = _src_xor; + const byte *src_cpy = _src_cpy; + u64 sc[2]; + u64 sx[2]; + u64 sdc[2]; + + if (blocksize == 8) + { + sc[0] = buf_get_he64(src_cpy + 0); + buf_put_he64(dst_xor + 0, + buf_get_he64(srcdst_cpy + 0) ^ buf_get_he64(src_xor + 0)); + buf_put_he64(srcdst_cpy + 0, sc[0]); + } + else /* blocksize == 16 */ + { + sc[0] = buf_get_he64(src_cpy + 0); + sc[1] = buf_get_he64(src_cpy + 8); + sx[0] = buf_get_he64(src_xor + 0); + sx[1] = buf_get_he64(src_xor + 8); + sdc[0] = buf_get_he64(srcdst_cpy + 0); + sdc[1] = buf_get_he64(srcdst_cpy + 8); + sx[0] ^= sdc[0]; + sx[1] ^= sdc[1]; + buf_put_he64(dst_xor + 0, sx[0]); + buf_put_he64(dst_xor + 8, sx[1]); + buf_put_he64(srcdst_cpy + 0, sc[0]); + buf_put_he64(srcdst_cpy + 8, sc[1]); + } +} + + +/* Optimized function for combined cipher block xoring and copying. + Used by mainly CFB mode decryption. */ +static inline void +cipher_block_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, + size_t blocksize) +{ + cipher_block_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, blocksize); +} + + #endif /*G10_CIPHER_INTERNAL_H*/ diff --git a/cipher/cipher-ocb.c b/cipher/cipher-ocb.c index db42aaf16..f71520ad2 100644 --- a/cipher/cipher-ocb.c +++ b/cipher/cipher-ocb.c @@ -82,7 +82,7 @@ static void double_block_cpy (unsigned char *d, const unsigned char *s) { if (d != s) - buf_cpy (d, s, OCB_BLOCK_LEN); + cipher_block_cpy (d, s, OCB_BLOCK_LEN); double_block (d); } @@ -181,8 +181,8 @@ _gcry_cipher_ocb_set_nonce (gcry_cipher_hd_t c, const unsigned char *nonce, nburn = c->spec->encrypt (&c->context.c, ktop, ktop); burn = nburn > burn ? nburn : burn; /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */ - buf_cpy (stretch, ktop, OCB_BLOCK_LEN); - buf_xor (stretch + OCB_BLOCK_LEN, ktop, ktop + 1, 8); + cipher_block_cpy (stretch, ktop, OCB_BLOCK_LEN); + cipher_block_xor (stretch + OCB_BLOCK_LEN, ktop, ktop + 1, 8); /* Offset_0 = Stretch[1+bottom..128+bottom] (We use the IV field to store the offset) */ bit_copy (c->u_iv.iv, stretch, bottom, OCB_BLOCK_LEN); @@ -267,18 +267,18 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf, } else { - buf_cpy (l_tmp, ocb_get_l (c, c->u_mode.ocb.aad_nblocks), - OCB_BLOCK_LEN); + cipher_block_cpy (l_tmp, ocb_get_l (c, c->u_mode.ocb.aad_nblocks), + OCB_BLOCK_LEN); } /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN); /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ - buf_xor (l_tmp, c->u_mode.ocb.aad_offset, - c->u_mode.ocb.aad_leftover, OCB_BLOCK_LEN); + cipher_block_xor (l_tmp, c->u_mode.ocb.aad_offset, + c->u_mode.ocb.aad_leftover, OCB_BLOCK_LEN); nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp); burn = nburn > burn ? nburn : burn; - buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); c->u_mode.ocb.aad_nleftover = 0; } @@ -309,12 +309,13 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf, ocb_get_L_big(c, c->u_mode.ocb.aad_nblocks, l_tmp); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN); /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ - buf_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf, OCB_BLOCK_LEN); + cipher_block_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf, + OCB_BLOCK_LEN); nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp); burn = nburn > burn ? nburn : burn; - buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); abuf += OCB_BLOCK_LEN; abuflen -= OCB_BLOCK_LEN; @@ -349,14 +350,15 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf, gcry_assert(c->u_mode.ocb.aad_nblocks & table_size_mask); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_mode.ocb.aad_offset, - ocb_get_l (c, c->u_mode.ocb.aad_nblocks), - OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_offset, + ocb_get_l (c, c->u_mode.ocb.aad_nblocks), + OCB_BLOCK_LEN); /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ - buf_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf, OCB_BLOCK_LEN); + cipher_block_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf, + OCB_BLOCK_LEN); nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp); burn = nburn > burn ? nburn : burn; - buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); abuf += OCB_BLOCK_LEN; abuflen -= OCB_BLOCK_LEN; @@ -397,18 +399,18 @@ ocb_aad_finalize (gcry_cipher_hd_t c) if (c->u_mode.ocb.aad_nleftover) { /* Offset_* = Offset_m xor L_* */ - buf_xor_1 (c->u_mode.ocb.aad_offset, - c->u_mode.ocb.L_star, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_offset, + c->u_mode.ocb.L_star, OCB_BLOCK_LEN); /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */ buf_cpy (l_tmp, c->u_mode.ocb.aad_leftover, c->u_mode.ocb.aad_nleftover); memset (l_tmp + c->u_mode.ocb.aad_nleftover, 0, OCB_BLOCK_LEN - c->u_mode.ocb.aad_nleftover); l_tmp[c->u_mode.ocb.aad_nleftover] = 0x80; - buf_xor_1 (l_tmp, c->u_mode.ocb.aad_offset, OCB_BLOCK_LEN); + cipher_block_xor_1 (l_tmp, c->u_mode.ocb.aad_offset, OCB_BLOCK_LEN); /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */ nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp); burn = nburn > burn ? nburn : burn; - buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); c->u_mode.ocb.aad_nleftover = 0; } @@ -431,7 +433,7 @@ ocb_checksum (unsigned char *chksum, const unsigned char *plainbuf, while (nblks > 0) { /* Checksum_i = Checksum_{i-1} xor P_i */ - buf_xor_1(chksum, plainbuf, OCB_BLOCK_LEN); + cipher_block_xor_1(chksum, plainbuf, OCB_BLOCK_LEN); plainbuf += OCB_BLOCK_LEN; nblks--; @@ -491,12 +493,12 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, } /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_iv.iv, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_iv.iv, l_tmp, OCB_BLOCK_LEN); /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ - buf_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN); + cipher_block_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN); nburn = crypt_fn (&c->context.c, outbuf, outbuf); burn = nburn > burn ? nburn : burn; - buf_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN); + cipher_block_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN); if (!encrypt) { @@ -551,14 +553,14 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, gcry_assert(c->u_mode.ocb.data_nblocks & table_size_mask); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_iv.iv, - ocb_get_l (c, c->u_mode.ocb.data_nblocks), - OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_iv.iv, + ocb_get_l (c, c->u_mode.ocb.data_nblocks), + OCB_BLOCK_LEN); /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ - buf_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN); + cipher_block_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN); nburn = crypt_fn (&c->context.c, outbuf, outbuf); burn = nburn > burn ? nburn : burn; - buf_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN); + cipher_block_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN); inbuf += OCB_BLOCK_LEN; inbuflen -= OCB_BLOCK_LEN; @@ -584,7 +586,7 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, unsigned char pad[OCB_BLOCK_LEN]; /* Offset_* = Offset_m xor L_* */ - buf_xor_1 (c->u_iv.iv, c->u_mode.ocb.L_star, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_iv.iv, c->u_mode.ocb.L_star, OCB_BLOCK_LEN); /* Pad = ENCIPHER(K, Offset_*) */ nburn = c->spec->encrypt (&c->context.c, pad, c->u_iv.iv); burn = nburn > burn ? nburn : burn; @@ -596,7 +598,7 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, buf_cpy (l_tmp, inbuf, inbuflen); memset (l_tmp + inbuflen, 0, OCB_BLOCK_LEN - inbuflen); l_tmp[inbuflen] = 0x80; - buf_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN); /* C_* = P_* xor Pad[1..bitlen(P_*)] */ buf_xor (outbuf, inbuf, pad, inbuflen); } @@ -604,13 +606,13 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, { /* P_* = C_* xor Pad[1..bitlen(C_*)] */ /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ - buf_cpy (l_tmp, pad, OCB_BLOCK_LEN); + cipher_block_cpy (l_tmp, pad, OCB_BLOCK_LEN); buf_cpy (l_tmp, inbuf, inbuflen); - buf_xor_1 (l_tmp, pad, OCB_BLOCK_LEN); + cipher_block_xor_1 (l_tmp, pad, OCB_BLOCK_LEN); l_tmp[inbuflen] = 0x80; buf_cpy (outbuf, l_tmp, inbuflen); - buf_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN); } } @@ -618,8 +620,10 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, if (c->marks.finalize) { /* Tag = ENCIPHER(K, Checksum xor Offset xor L_$) xor HASH(K,A) */ - buf_xor (c->u_mode.ocb.tag, c->u_ctr.ctr, c->u_iv.iv, OCB_BLOCK_LEN); - buf_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.L_dollar, OCB_BLOCK_LEN); + cipher_block_xor (c->u_mode.ocb.tag, c->u_ctr.ctr, c->u_iv.iv, + OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.L_dollar, + OCB_BLOCK_LEN); nburn = c->spec->encrypt (&c->context.c, c->u_mode.ocb.tag, c->u_mode.ocb.tag); burn = nburn > burn ? nburn : burn; @@ -672,7 +676,8 @@ compute_tag_if_needed (gcry_cipher_hd_t c) if (!c->marks.tag) { ocb_aad_finalize (c); - buf_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.aad_sum, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.aad_sum, + OCB_BLOCK_LEN); c->marks.tag = 1; } } diff --git a/cipher/cipher-ofb.c b/cipher/cipher-ofb.c index 419a8d085..a3fd2993d 100644 --- a/cipher/cipher-ofb.c +++ b/cipher/cipher-ofb.c @@ -72,7 +72,7 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c, /* Encrypt the IV (and save the current one). */ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; - buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; inbuflen -= blocksize; diff --git a/cipher/cipher-xts.c b/cipher/cipher-xts.c index 045b3539b..0522a271a 100644 --- a/cipher/cipher-xts.c +++ b/cipher/cipher-xts.c @@ -107,10 +107,10 @@ _gcry_cipher_xts_crypt (gcry_cipher_hd_t c, while (nblocks) { /* Xor-Encrypt/Decrypt-Xor block. */ - buf_xor (tmp.x64, inbuf, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (tmp.x64, inbuf, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); nburn = crypt_fn (&c->context.c, tmp.x1, tmp.x1); burn = nburn > burn ? nburn : burn; - buf_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); outbuf += GCRY_XTS_BLOCK_LEN; inbuf += GCRY_XTS_BLOCK_LEN; @@ -133,10 +133,10 @@ _gcry_cipher_xts_crypt (gcry_cipher_hd_t c, xts_gfmul_byA (tmp.x1, c->u_ctr.ctr); /* Decrypt last block first. */ - buf_xor (outbuf, inbuf, tmp.x64, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (outbuf, inbuf, tmp.x64, GCRY_XTS_BLOCK_LEN); nburn = crypt_fn (&c->context.c, outbuf, outbuf); burn = nburn > burn ? nburn : burn; - buf_xor (outbuf, outbuf, tmp.x64, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (outbuf, outbuf, tmp.x64, GCRY_XTS_BLOCK_LEN); inbuflen -= GCRY_XTS_BLOCK_LEN; inbuf += GCRY_XTS_BLOCK_LEN; @@ -147,15 +147,15 @@ _gcry_cipher_xts_crypt (gcry_cipher_hd_t c, outbuf -= GCRY_XTS_BLOCK_LEN; /* Steal ciphertext from previous block. */ - buf_cpy (tmp.x64, outbuf, GCRY_XTS_BLOCK_LEN); + cipher_block_cpy (tmp.x64, outbuf, GCRY_XTS_BLOCK_LEN); buf_cpy (tmp.x64, inbuf, inbuflen); buf_cpy (outbuf + GCRY_XTS_BLOCK_LEN, outbuf, inbuflen); /* Decrypt/Encrypt last block. */ - buf_xor (tmp.x64, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (tmp.x64, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); nburn = crypt_fn (&c->context.c, tmp.x1, tmp.x1); burn = nburn > burn ? nburn : burn; - buf_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); } /* Auto-increment data-unit sequence number */ diff --git a/cipher/des.c b/cipher/des.c index 05092277e..a008b93e5 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -119,6 +119,7 @@ #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" +#include "cipher-internal.h" #include "cipher-selftest.h" @@ -908,7 +909,7 @@ _gcry_3des_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, /* Encrypt the counter. */ tripledes_ecb_encrypt (ctx, ctr, tmpbuf); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, DES_BLOCKSIZE); + cipher_block_xor(outbuf, tmpbuf, inbuf, DES_BLOCKSIZE); outbuf += DES_BLOCKSIZE; inbuf += DES_BLOCKSIZE; /* Increment the counter. */ @@ -964,7 +965,7 @@ _gcry_3des_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, the intermediate result to SAVEBUF. */ tripledes_ecb_decrypt (ctx, inbuf, savebuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, DES_BLOCKSIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, DES_BLOCKSIZE); inbuf += DES_BLOCKSIZE; outbuf += DES_BLOCKSIZE; } @@ -1009,7 +1010,7 @@ _gcry_3des_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, for ( ;nblocks; nblocks-- ) { tripledes_ecb_encrypt (ctx, iv, iv); - buf_xor_n_copy(outbuf, iv, inbuf, DES_BLOCKSIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, DES_BLOCKSIZE); outbuf += DES_BLOCKSIZE; inbuf += DES_BLOCKSIZE; } diff --git a/cipher/rijndael.c b/cipher/rijndael.c index d3fcb76f3..d126f8847 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -831,7 +831,7 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv, /* Encrypt the IV. */ burn_depth = encrypt_fn (ctx, iv, iv); /* XOR the input with the IV and store input into IV. */ - buf_xor_2dst(outbuf, iv, inbuf, BLOCKSIZE); + cipher_block_xor_2dst(outbuf, iv, inbuf, BLOCKSIZE); outbuf += BLOCKSIZE; inbuf += BLOCKSIZE; } @@ -891,7 +891,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, for ( ;nblocks; nblocks-- ) { - buf_xor(outbuf, inbuf, last_iv, BLOCKSIZE); + cipher_block_xor(outbuf, inbuf, last_iv, BLOCKSIZE); burn_depth = encrypt_fn (ctx, outbuf, outbuf); @@ -902,7 +902,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, } if (last_iv != iv) - buf_cpy (iv, last_iv, BLOCKSIZE); + cipher_block_cpy (iv, last_iv, BLOCKSIZE); } if (burn_depth) @@ -962,7 +962,7 @@ _gcry_aes_ctr_enc (void *context, unsigned char *ctr, /* Encrypt the counter. */ burn_depth = encrypt_fn (ctx, tmp.x1, ctr); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmp.x1, inbuf, BLOCKSIZE); + cipher_block_xor(outbuf, tmp.x1, inbuf, BLOCKSIZE); outbuf += BLOCKSIZE; inbuf += BLOCKSIZE; /* Increment the counter. */ @@ -1207,7 +1207,7 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv, for ( ;nblocks; nblocks-- ) { burn_depth = encrypt_fn (ctx, iv, iv); - buf_xor_n_copy(outbuf, iv, inbuf, BLOCKSIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, BLOCKSIZE); outbuf += BLOCKSIZE; inbuf += BLOCKSIZE; } @@ -1272,7 +1272,7 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv, burn_depth = decrypt_fn (ctx, savebuf, inbuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE); inbuf += BLOCKSIZE; outbuf += BLOCKSIZE; } @@ -1330,15 +1330,15 @@ _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const unsigned char *l = ocb_get_l(c, i); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_iv.iv, l, BLOCKSIZE); - buf_cpy (l_tmp.x1, inbuf, BLOCKSIZE); + cipher_block_xor_1 (c->u_iv.iv, l, BLOCKSIZE); + cipher_block_cpy (l_tmp.x1, inbuf, BLOCKSIZE); /* Checksum_i = Checksum_{i-1} xor P_i */ - buf_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE); + cipher_block_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE); /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ - buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); + cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); burn_depth = encrypt_fn (ctx, l_tmp.x1, l_tmp.x1); - buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); - buf_cpy (outbuf, l_tmp.x1, BLOCKSIZE); + cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); + cipher_block_cpy (outbuf, l_tmp.x1, BLOCKSIZE); inbuf += BLOCKSIZE; outbuf += BLOCKSIZE; @@ -1360,15 +1360,15 @@ _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const unsigned char *l = ocb_get_l(c, i); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_iv.iv, l, BLOCKSIZE); - buf_cpy (l_tmp.x1, inbuf, BLOCKSIZE); + cipher_block_xor_1 (c->u_iv.iv, l, BLOCKSIZE); + cipher_block_cpy (l_tmp.x1, inbuf, BLOCKSIZE); /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ - buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); + cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); burn_depth = decrypt_fn (ctx, l_tmp.x1, l_tmp.x1); - buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); + cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); /* Checksum_i = Checksum_{i-1} xor P_i */ - buf_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE); - buf_cpy (outbuf, l_tmp.x1, BLOCKSIZE); + cipher_block_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE); + cipher_block_cpy (outbuf, l_tmp.x1, BLOCKSIZE); inbuf += BLOCKSIZE; outbuf += BLOCKSIZE; @@ -1424,11 +1424,12 @@ _gcry_aes_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks) const unsigned char *l = ocb_get_l(c, i); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_mode.ocb.aad_offset, l, BLOCKSIZE); + cipher_block_xor_1 (c->u_mode.ocb.aad_offset, l, BLOCKSIZE); /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ - buf_xor (l_tmp.x1, c->u_mode.ocb.aad_offset, abuf, BLOCKSIZE); + cipher_block_xor (l_tmp.x1, c->u_mode.ocb.aad_offset, abuf, + BLOCKSIZE); burn_depth = encrypt_fn (ctx, l_tmp.x1, l_tmp.x1); - buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp.x1, BLOCKSIZE); + cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp.x1, BLOCKSIZE); abuf += BLOCKSIZE; } diff --git a/cipher/serpent.c b/cipher/serpent.c index 0736ad195..8e3faa7c5 100644 --- a/cipher/serpent.c +++ b/cipher/serpent.c @@ -1002,7 +1002,7 @@ _gcry_serpent_ctr_enc(void *context, unsigned char *ctr, /* Encrypt the counter. */ serpent_encrypt_internal(ctx, ctr, tmpbuf); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, sizeof(serpent_block_t)); + cipher_block_xor(outbuf, tmpbuf, inbuf, sizeof(serpent_block_t)); outbuf += sizeof(serpent_block_t); inbuf += sizeof(serpent_block_t); /* Increment the counter. */ @@ -1117,7 +1117,8 @@ _gcry_serpent_cbc_dec(void *context, unsigned char *iv, the intermediate result to SAVEBUF. */ serpent_decrypt_internal (ctx, inbuf, savebuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, sizeof(serpent_block_t)); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, + sizeof(serpent_block_t)); inbuf += sizeof(serpent_block_t); outbuf += sizeof(serpent_block_t); } @@ -1221,7 +1222,7 @@ _gcry_serpent_cfb_dec(void *context, unsigned char *iv, for ( ;nblocks; nblocks-- ) { serpent_encrypt_internal(ctx, iv, iv); - buf_xor_n_copy(outbuf, iv, inbuf, sizeof(serpent_block_t)); + cipher_block_xor_n_copy(outbuf, iv, inbuf, sizeof(serpent_block_t)); outbuf += sizeof(serpent_block_t); inbuf += sizeof(serpent_block_t); } diff --git a/cipher/twofish.c b/cipher/twofish.c index 0d187bda4..51982c530 100644 --- a/cipher/twofish.c +++ b/cipher/twofish.c @@ -1161,7 +1161,7 @@ _gcry_twofish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, burn_stack_depth = burn; /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, TWOFISH_BLOCKSIZE); + cipher_block_xor(outbuf, tmpbuf, inbuf, TWOFISH_BLOCKSIZE); outbuf += TWOFISH_BLOCKSIZE; inbuf += TWOFISH_BLOCKSIZE; /* Increment the counter. */ @@ -1243,7 +1243,7 @@ _gcry_twofish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, if (burn > burn_stack_depth) burn_stack_depth = burn; - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, TWOFISH_BLOCKSIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, TWOFISH_BLOCKSIZE); inbuf += TWOFISH_BLOCKSIZE; outbuf += TWOFISH_BLOCKSIZE; } @@ -1315,7 +1315,7 @@ _gcry_twofish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, if (burn > burn_stack_depth) burn_stack_depth = burn; - buf_xor_n_copy(outbuf, iv, inbuf, TWOFISH_BLOCKSIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, TWOFISH_BLOCKSIZE); outbuf += TWOFISH_BLOCKSIZE; inbuf += TWOFISH_BLOCKSIZE; } -- 2.17.1 From alyon.ipride at gmail.com Sat Jul 21 23:39:55 2018 From: alyon.ipride at gmail.com (Alexander Lyon) Date: Sat, 21 Jul 2018 22:39:55 +0100 Subject: Correct method to generate a Curve25519 keypair In-Reply-To: References: <7E3FC5D1-7172-45D1-ADE9-102EE73AA850@me.com> <68AB9180-0D76-4B76-99A5-C4E8AFA23CF0@me.com> Message-ID: <54819420-0F13-4964-A80A-37BFD62E853D@gmail.com> I actually just stumbled across it in the tests after many many hours. If you look here: https://github.com/gpg/libgcrypt/blob/master/tests/t-cv25519.c#L422 There is a call to test_dh which then calls test_cv with a_priv and b_pub https://github.com/gpg/libgcrypt/blob/master/tests/t-cv25519.c#L363 Following that function you can see it parse the hex into binary, reverse the private key, and then create the appropriate s-expressions and finally pass them on to gcry_pk_encrypt before comparing that with the expected result hex string. https://github.com/gpg/libgcrypt/blob/master/tests/t-cv25519.c#L191 Alex > On 20 Jul 2018, at 20:49, Stef Bon wrote: > > How did you find out you have to use gcry_pk_encrypt for getting the shared k?? I cannot find any doumentation about it and without your help > I would still be searching. > > Stef Bon > the Netherlands/ Pays Bas > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel From cvs at cvs.gnupg.org Sat Jul 28 09:53:23 2018 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sat, 28 Jul 2018 09:53:23 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.8.1-86-g86e5e06 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 86e5e06a97ae13b8bbf6923ecc76e02b9c429b46 (commit) from 9660c3fafd732b1857bb2697c6f43aed077b9ad6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 86e5e06a97ae13b8bbf6923ecc76e02b9c429b46 Author: Jussi Kivilinna Date: Sat Jul 21 11:56:46 2018 +0300 Add size optimized cipher block copy and xor functions * cipher/bufhelp.h (buf_get_he32, buf_put_he32, buf_get_he64) (buf_put_he64): New. * cipher/cipher-internal.h (cipher_block_cpy, cipher_block_xor) (cipher_block_xor_1, cipher_block_xor_2dst, cipher_block_xor_n_copy_2) (cipher_block_xor_n_copy): New. * cipher/cipher-gcm-intel-pclmul.c (_gcry_ghash_setup_intel_pclmul): Use assembly for swapping endianness instead of buf_get_be64 and buf_cpy. * cipher/blowfish.c: Use new cipher_block_* functions for cipher block sized buf_cpy/xor* operations. * cipher/camellia-glue.c: Ditto. * cipher/cast5.c: Ditto. * cipher/cipher-aeswrap.c: Ditto. * cipher/cipher-cbc.c: Ditto. * cipher/cipher-ccm.c: Ditto. * cipher/cipher-cfb.c: Ditto. * cipher/cipher-cmac.c: Ditto. * cipher/cipher-ctr.c: Ditto. * cipher/cipher-eax.c: Ditto. * cipher/cipher-gcm.c: Ditto. * cipher/cipher-ocb.c: Ditto. * cipher/cipher-ofb.c: Ditto. * cipher/cipher-xts.c: Ditto. * cipher/des.c: Ditto. * cipher/rijndael.c: Ditto. * cipher/serpent.c: Ditto. * cipher/twofish.c: Ditto. -- This commit adds size-optimized functions for copying and xoring cipher block sized buffers. These functions also allow GCC to use inline auto-vectorization for block cipher copying and xoring on higher optimization levels. Signed-off-by: Jussi Kivilinna diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 2d91820..f032c5c 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -37,6 +37,7 @@ #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" +#include "cipher-internal.h" #include "cipher-selftest.h" #define BLOWFISH_BLOCKSIZE 8 @@ -660,7 +661,7 @@ _gcry_blowfish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, /* Encrypt the counter. */ do_encrypt_block(ctx, tmpbuf, ctr); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, BLOWFISH_BLOCKSIZE); + cipher_block_xor(outbuf, tmpbuf, inbuf, BLOWFISH_BLOCKSIZE); outbuf += BLOWFISH_BLOCKSIZE; inbuf += BLOWFISH_BLOCKSIZE; /* Increment the counter. */ @@ -728,7 +729,7 @@ _gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, the intermediate result to SAVEBUF. */ do_decrypt_block (ctx, savebuf, inbuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOWFISH_BLOCKSIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOWFISH_BLOCKSIZE); inbuf += BLOWFISH_BLOCKSIZE; outbuf += BLOWFISH_BLOCKSIZE; } @@ -785,7 +786,7 @@ _gcry_blowfish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, for ( ;nblocks; nblocks-- ) { do_encrypt_block(ctx, iv, iv); - buf_xor_n_copy(outbuf, iv, inbuf, BLOWFISH_BLOCKSIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, BLOWFISH_BLOCKSIZE); outbuf += BLOWFISH_BLOCKSIZE; inbuf += BLOWFISH_BLOCKSIZE; } diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h index 83d3f53..4e97c4d 100644 --- a/cipher/bufhelp.h +++ b/cipher/bufhelp.h @@ -450,7 +450,21 @@ static inline void buf_put_le64(void *_buf, u64 val) out->a = le_bswap64(val); } - #endif /*BUFHELP_UNALIGNED_ACCESS*/ + +/* Host-endian get/put macros */ +#ifdef WORDS_BIGENDIAN +# define buf_get_he32 buf_get_be32 +# define buf_put_he32 buf_put_be32 +# define buf_get_he64 buf_get_be64 +# define buf_put_he64 buf_put_be64 +#else +# define buf_get_he32 buf_get_le32 +# define buf_put_he32 buf_put_le32 +# define buf_get_he64 buf_get_le64 +# define buf_put_he64 buf_put_le64 +#endif + + #endif /*GCRYPT_BUFHELP_H*/ diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index 22df214..69b240b 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -430,7 +430,7 @@ _gcry_camellia_ctr_enc(void *context, unsigned char *ctr, /* Encrypt the counter. */ Camellia_EncryptBlock(ctx->keybitlength, ctr, ctx->keytable, tmpbuf); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, CAMELLIA_BLOCK_SIZE); + cipher_block_xor(outbuf, tmpbuf, inbuf, CAMELLIA_BLOCK_SIZE); outbuf += CAMELLIA_BLOCK_SIZE; inbuf += CAMELLIA_BLOCK_SIZE; /* Increment the counter. */ @@ -523,7 +523,8 @@ _gcry_camellia_cbc_dec(void *context, unsigned char *iv, the intermediate result to SAVEBUF. */ Camellia_DecryptBlock(ctx->keybitlength, inbuf, ctx->keytable, savebuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAMELLIA_BLOCK_SIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, + CAMELLIA_BLOCK_SIZE); inbuf += CAMELLIA_BLOCK_SIZE; outbuf += CAMELLIA_BLOCK_SIZE; } @@ -605,7 +606,7 @@ _gcry_camellia_cfb_dec(void *context, unsigned char *iv, for ( ;nblocks; nblocks-- ) { Camellia_EncryptBlock(ctx->keybitlength, iv, ctx->keytable, iv); - buf_xor_n_copy(outbuf, iv, inbuf, CAMELLIA_BLOCK_SIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, CAMELLIA_BLOCK_SIZE); outbuf += CAMELLIA_BLOCK_SIZE; inbuf += CAMELLIA_BLOCK_SIZE; } diff --git a/cipher/cast5.c b/cipher/cast5.c index e7d324b..49e8b78 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -44,6 +44,7 @@ #include "cipher.h" #include "bithelp.h" #include "bufhelp.h" +#include "cipher-internal.h" #include "cipher-selftest.h" /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */ @@ -634,7 +635,7 @@ _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, /* Encrypt the counter. */ do_encrypt_block(ctx, tmpbuf, ctr); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, CAST5_BLOCKSIZE); + cipher_block_xor(outbuf, tmpbuf, inbuf, CAST5_BLOCKSIZE); outbuf += CAST5_BLOCKSIZE; inbuf += CAST5_BLOCKSIZE; /* Increment the counter. */ @@ -702,7 +703,7 @@ _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, the intermediate result to SAVEBUF. */ do_decrypt_block (ctx, savebuf, inbuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAST5_BLOCKSIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAST5_BLOCKSIZE); inbuf += CAST5_BLOCKSIZE; outbuf += CAST5_BLOCKSIZE; } @@ -758,7 +759,7 @@ _gcry_cast5_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, for ( ;nblocks; nblocks-- ) { do_encrypt_block(ctx, iv, iv); - buf_xor_n_copy(outbuf, iv, inbuf, CAST5_BLOCKSIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, CAST5_BLOCKSIZE); outbuf += CAST5_BLOCKSIZE; inbuf += CAST5_BLOCKSIZE; } diff --git a/cipher/cipher-aeswrap.c b/cipher/cipher-aeswrap.c index a8d0e03..c182657 100644 --- a/cipher/cipher-aeswrap.c +++ b/cipher/cipher-aeswrap.c @@ -99,7 +99,7 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c, break; } /* A := MSB_64(B) ^ t */ - buf_xor(a, b, t, 8); + cipher_block_xor(a, b, t, 8); /* R[i] := LSB_64(B) */ memcpy (r+i*8, b+8, 8); } @@ -170,7 +170,7 @@ _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c, for (i = n; i >= 1; i--) { /* B := AES_k^1( (A ^ t)| R[i] ) */ - buf_xor(b, a, t, 8); + cipher_block_xor(b, a, t, 8); memcpy (b+8, r+(i-1)*8, 8); nburn = c->spec->decrypt (&c->context.c, b, b); burn = nburn > burn ? nburn : burn; diff --git a/cipher/cipher-cbc.c b/cipher/cipher-cbc.c index 2ad39d0..d4df1e7 100644 --- a/cipher/cipher-cbc.c +++ b/cipher/cipher-cbc.c @@ -56,7 +56,7 @@ cbc_encrypt_inner(gcry_cipher_hd_t c, unsigned char *outbuf, for (n=0; n < nblocks; n++ ) { - buf_xor (outbuf, inbuf, ivp, blocksize); + cipher_block_xor (outbuf, inbuf, ivp, blocksize); nburn = enc_fn ( &c->context.c, outbuf, outbuf ); burn = nburn > burn ? nburn : burn; ivp = outbuf; @@ -66,7 +66,7 @@ cbc_encrypt_inner(gcry_cipher_hd_t c, unsigned char *outbuf, } if (ivp != c->u_iv.iv) - buf_cpy (c->u_iv.iv, ivp, blocksize); + cipher_block_cpy (c->u_iv.iv, ivp, blocksize); } return burn; @@ -156,7 +156,7 @@ _gcry_cipher_cbc_cts_encrypt (gcry_cipher_hd_t c, nburn = enc_fn (&c->context.c, outbuf, outbuf); burn = nburn > burn ? nburn : burn; - buf_cpy (c->u_iv.iv, outbuf, blocksize); + cipher_block_cpy (c->u_iv.iv, outbuf, blocksize); } if (burn > 0) @@ -190,7 +190,8 @@ cbc_decrypt_inner(gcry_cipher_hd_t c, unsigned char *outbuf, storage here because it is not used otherwise. */ nburn = dec_fn ( &c->context.c, c->lastiv, inbuf ); burn = nburn > burn ? nburn : burn; - buf_xor_n_copy_2 (outbuf, c->lastiv, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor_n_copy_2 (outbuf, c->lastiv, c->u_iv.iv, inbuf, + blocksize); inbuf += blocksize; outbuf += blocksize; } @@ -252,7 +253,7 @@ _gcry_cipher_cbc_cts_decrypt (gcry_cipher_hd_t c, nblocks--; if ((inbuflen & blocksize_mask) == 0) nblocks--; - buf_cpy (c->lastiv, c->u_iv.iv, blocksize); + cipher_block_cpy (c->lastiv, c->u_iv.iv, blocksize); } burn = cbc_decrypt_inner(c, outbuf, inbuf, nblocks, blocksize); @@ -268,7 +269,7 @@ _gcry_cipher_cbc_cts_decrypt (gcry_cipher_hd_t c, else restbytes = inbuflen & blocksize_mask; - buf_cpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */ + cipher_block_cpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */ buf_cpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */ nburn = dec_fn ( &c->context.c, outbuf, inbuf ); @@ -280,7 +281,7 @@ _gcry_cipher_cbc_cts_decrypt (gcry_cipher_hd_t c, c->u_iv.iv[i] = outbuf[i]; nburn = dec_fn (&c->context.c, outbuf, c->u_iv.iv); burn = nburn > burn ? nburn : burn; - buf_xor(outbuf, outbuf, c->lastiv, blocksize); + cipher_block_xor(outbuf, outbuf, c->lastiv, blocksize); /* c->lastiv is now really lastlastiv, does this matter? */ } diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c index d7f14d8..e71c6f1 100644 --- a/cipher/cipher-ccm.c +++ b/cipher/cipher-ccm.c @@ -67,7 +67,8 @@ do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen, if (unused > 0) { /* Process one block from macbuf. */ - buf_xor(c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.macbuf, blocksize); + cipher_block_xor(c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.macbuf, + blocksize); set_burn (burn, enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv )); unused = 0; @@ -86,7 +87,7 @@ do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen, { while (inlen >= blocksize) { - buf_xor(c->u_iv.iv, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor(c->u_iv.iv, c->u_iv.iv, inbuf, blocksize); set_burn (burn, enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv )); @@ -272,7 +273,7 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf, burn = do_cbc_mac (c, NULL, 0, 1); /* Perform final padding. */ /* Add S_0 */ - buf_xor (c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.s0, 16); + cipher_block_xor (c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.s0, 16); wipememory (c->u_ctr.ctr, 16); wipememory (c->u_mode.ccm.s0, 16); diff --git a/cipher/cipher-cfb.c b/cipher/cipher-cfb.c index 7f00aee..012c6c1 100644 --- a/cipher/cipher-cfb.c +++ b/cipher/cipher-cfb.c @@ -87,7 +87,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV. */ - buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; inbuflen -= blocksize; @@ -97,11 +97,11 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, if ( inbuflen >= blocksize ) { /* Save the current IV and then encrypt the IV. */ - buf_cpy( c->lastiv, c->u_iv.iv, blocksize ); + cipher_block_cpy( c->lastiv, c->u_iv.iv, blocksize ); nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV */ - buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; inbuflen -= blocksize; @@ -109,7 +109,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, if ( inbuflen ) { /* Save the current IV and then encrypt the IV. */ - buf_cpy( c->lastiv, c->u_iv.iv, blocksize ); + cipher_block_cpy( c->lastiv, c->u_iv.iv, blocksize ); nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; c->unused = blocksize; @@ -185,7 +185,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV. */ - buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; inbuflen -= blocksize; @@ -195,11 +195,11 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, if (inbuflen >= blocksize ) { /* Save the current IV and then encrypt the IV. */ - buf_cpy ( c->lastiv, c->u_iv.iv, blocksize); + cipher_block_cpy ( c->lastiv, c->u_iv.iv, blocksize); nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; /* XOR the input with the IV and store input into IV */ - buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; inbuflen -= blocksize; @@ -208,7 +208,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, if (inbuflen) { /* Save the current IV and then encrypt the IV. */ - buf_cpy ( c->lastiv, c->u_iv.iv, blocksize ); + cipher_block_cpy ( c->lastiv, c->u_iv.iv, blocksize ); nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; c->unused = blocksize; diff --git a/cipher/cipher-cmac.c b/cipher/cipher-cmac.c index 321ab9e..da550c3 100644 --- a/cipher/cipher-cmac.c +++ b/cipher/cipher-cmac.c @@ -66,7 +66,7 @@ _gcry_cmac_write (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx, for (; inlen && ctx->mac_unused < blocksize; inlen--) ctx->macbuf[ctx->mac_unused++] = *inbuf++; - buf_xor (ctx->u_iv.iv, ctx->u_iv.iv, ctx->macbuf, blocksize); + cipher_block_xor (ctx->u_iv.iv, ctx->u_iv.iv, ctx->macbuf, blocksize); set_burn (burn, enc_fn (&c->context.c, ctx->u_iv.iv, ctx->u_iv.iv)); ctx->mac_unused = 0; @@ -86,7 +86,7 @@ _gcry_cmac_write (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx, else while (inlen > blocksize) { - buf_xor (ctx->u_iv.iv, ctx->u_iv.iv, inbuf, blocksize); + cipher_block_xor (ctx->u_iv.iv, ctx->u_iv.iv, inbuf, blocksize); set_burn (burn, enc_fn (&c->context.c, ctx->u_iv.iv, ctx->u_iv.iv)); inlen -= blocksize; inbuf += blocksize; @@ -181,9 +181,9 @@ _gcry_cmac_final (gcry_cipher_hd_t c, gcry_cmac_context_t *ctx) ctx->macbuf[count++] = 0; } - buf_xor (ctx->macbuf, ctx->macbuf, subkey, blocksize); + cipher_block_xor (ctx->macbuf, ctx->macbuf, subkey, blocksize); - buf_xor (ctx->u_iv.iv, ctx->u_iv.iv, ctx->macbuf, blocksize); + cipher_block_xor (ctx->u_iv.iv, ctx->u_iv.iv, ctx->macbuf, blocksize); burn = c->spec->encrypt (&c->context.c, ctx->u_iv.iv, ctx->u_iv.iv); if (burn) _gcry_burn_stack (burn + 4 * sizeof (void *)); diff --git a/cipher/cipher-ctr.c b/cipher/cipher-ctr.c index b54fb5a..2df0b8c 100644 --- a/cipher/cipher-ctr.c +++ b/cipher/cipher-ctr.c @@ -77,24 +77,38 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c, { unsigned char tmp[MAX_BLOCKSIZE]; - do { - nburn = enc_fn (&c->context.c, tmp, c->u_ctr.ctr); - burn = nburn > burn ? nburn : burn; - - for (i = blocksize; i > 0; i--) - { - c->u_ctr.ctr[i-1]++; - if (c->u_ctr.ctr[i-1] != 0) - break; - } - - n = blocksize < inbuflen ? blocksize : inbuflen; - buf_xor(outbuf, inbuf, tmp, n); - - inbuflen -= n; - outbuf += n; - inbuf += n; - } while (inbuflen); + do + { + nburn = enc_fn (&c->context.c, tmp, c->u_ctr.ctr); + burn = nburn > burn ? nburn : burn; + + for (i = blocksize; i > 0; i--) + { + c->u_ctr.ctr[i-1]++; + if (c->u_ctr.ctr[i-1] != 0) + break; + } + + if (inbuflen < blocksize) + break; + n = blocksize; + cipher_block_xor(outbuf, inbuf, tmp, blocksize); + + inbuflen -= n; + outbuf += n; + inbuf += n; + } + while (inbuflen); + + if (inbuflen) + { + n = inbuflen; + buf_xor(outbuf, inbuf, tmp, inbuflen); + + inbuflen -= n; + outbuf += n; + inbuf += n; + } /* Save the unused bytes of the counter. */ c->unused = blocksize - n; diff --git a/cipher/cipher-eax.c b/cipher/cipher-eax.c index 1ce4797..3b17bb6 100644 --- a/cipher/cipher-eax.c +++ b/cipher/cipher-eax.c @@ -157,8 +157,8 @@ _gcry_cipher_eax_set_nonce (gcry_cipher_hd_t c, const byte *nonce, if (err != 0) return err; - buf_cpy (c->u_iv.iv, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE); - buf_cpy (c->u_ctr.ctr, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE); + cipher_block_cpy (c->u_iv.iv, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE); + cipher_block_cpy (c->u_ctr.ctr, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE); wipememory (&nonce_cmac, sizeof(nonce_cmac)); @@ -201,9 +201,10 @@ _gcry_cipher_eax_tag (gcry_cipher_hd_t c, if (err != 0) return err; - buf_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_header.u_iv.iv, MAX_BLOCKSIZE); - buf_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_ciphertext.u_iv.iv, - MAX_BLOCKSIZE); + cipher_block_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_header.u_iv.iv, + MAX_BLOCKSIZE); + cipher_block_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_ciphertext.u_iv.iv, + MAX_BLOCKSIZE); _gcry_cmac_reset (&c->u_mode.eax.cmac_header); _gcry_cmac_reset (&c->u_mode.eax.cmac_ciphertext); diff --git a/cipher/cipher-gcm-intel-pclmul.c b/cipher/cipher-gcm-intel-pclmul.c index a327249..0f26277 100644 --- a/cipher/cipher-gcm-intel-pclmul.c +++ b/cipher/cipher-gcm-intel-pclmul.c @@ -248,7 +248,8 @@ static inline void gfmul_pclmul_aggr4(void) void _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c) { - u64 tmp[2]; + static const unsigned char be_mask[16] __attribute__ ((aligned (16))) = + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; #if defined(__x86_64__) && defined(__WIN64__) char win64tmp[3 * 16]; @@ -262,15 +263,19 @@ _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c) #endif /* Swap endianness of hsub. */ - tmp[0] = buf_get_be64(c->u_mode.gcm.u_ghash_key.key + 8); - tmp[1] = buf_get_be64(c->u_mode.gcm.u_ghash_key.key + 0); - buf_cpy (c->u_mode.gcm.u_ghash_key.key, tmp, GCRY_GCM_BLOCK_LEN); + asm volatile ("movdqu (%[key]), %%xmm0\n\t" + "pshufb %[be_mask], %%xmm0\n\t" + "movdqu %%xmm0, (%[key])\n\t" + : + : [key] "r" (c->u_mode.gcm.u_ghash_key.key), + [be_mask] "m" (*be_mask) + : "memory"); #ifdef __x86_64__ - asm volatile ("movdqu %[h_1], %%xmm0\n\t" - "movdqa %%xmm0, %%xmm1\n\t" + asm volatile ("movdqa %%xmm0, %%xmm1\n\t" : - : [h_1] "m" (*tmp)); + : + : "memory"); gfmul_pclmul (); /* H?H => H? */ @@ -324,8 +329,6 @@ _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c) ::: "cc" ); #endif #endif - - wipememory (tmp, sizeof(tmp)); } diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 6169d14..32ec9fa 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -150,7 +150,7 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u64 *gcmM) u32 A; int i; - buf_xor (V, result, buf, 16); + cipher_block_xor (V, result, buf, 16); V[0] = be_bswap64 (V[0]); V[1] = be_bswap64 (V[1]); @@ -259,7 +259,7 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u32 *gcmM) u32 T[3]; int i; - buf_xor (V, result, buf, 16); /* V is big-endian */ + cipher_block_xor (V, result, buf, 16); /* V is big-endian */ /* First round can be manually tweaked based on fact that 'tmp' is zero. */ i = 15; @@ -342,7 +342,7 @@ do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) #else unsigned long T[4]; - buf_xor (V, result, buf, 16); + cipher_block_xor (V, result, buf, 16); for (i = 0; i < 4; i++) { V[i] = (V[i] & 0x00ff00ff) << 8 | (V[i] & 0xff00ff00) >> 8; @@ -358,7 +358,7 @@ do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) for (j = 0x80; j; j >>= 1) { if (hsub[i] & j) - buf_xor (p, p, V, 16); + cipher_block_xor (p, p, V, 16); if (bshift (V)) V[0] ^= 0xe1000000; } @@ -598,7 +598,7 @@ gcm_ctr_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, } fix_ctr = 1; - buf_cpy(ctr_copy, c->u_ctr.ctr, GCRY_GCM_BLOCK_LEN); + cipher_block_cpy(ctr_copy, c->u_ctr.ctr, GCRY_GCM_BLOCK_LEN); } } @@ -928,8 +928,8 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, /* Add bitlengths to tag. */ do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, (byte*)bitlengths, GCRY_GCM_BLOCK_LEN, 1); - buf_xor (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.tagiv, - c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); + cipher_block_xor (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.tagiv, + c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); c->marks.tag = 1; wipememory (bitlengths, sizeof (bitlengths)); diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index 6d87561..f93363b 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -603,4 +603,145 @@ static inline unsigned int _gcry_blocksize_shift(gcry_cipher_hd_t c) } +/* Optimized function for cipher block copying */ +static inline void +cipher_block_cpy(void *_dst, const void *_src, size_t blocksize) +{ + byte *dst = _dst; + const byte *src = _src; + u64 s[2]; + + if (blocksize == 8) + { + buf_put_he64(dst + 0, buf_get_he64(src + 0)); + } + else /* blocksize == 16 */ + { + s[0] = buf_get_he64(src + 0); + s[1] = buf_get_he64(src + 8); + buf_put_he64(dst + 0, s[0]); + buf_put_he64(dst + 8, s[1]); + } +} + + +/* Optimized function for cipher block xoring */ +static inline void +cipher_block_xor(void *_dst, const void *_src1, const void *_src2, + size_t blocksize) +{ + byte *dst = _dst; + const byte *src1 = _src1; + const byte *src2 = _src2; + u64 s1[2]; + u64 s2[2]; + + if (blocksize == 8) + { + buf_put_he64(dst + 0, buf_get_he64(src1 + 0) ^ buf_get_he64(src2 + 0)); + } + else /* blocksize == 16 */ + { + s1[0] = buf_get_he64(src1 + 0); + s1[1] = buf_get_he64(src1 + 8); + s2[0] = buf_get_he64(src2 + 0); + s2[1] = buf_get_he64(src2 + 8); + buf_put_he64(dst + 0, s1[0] ^ s2[0]); + buf_put_he64(dst + 8, s1[1] ^ s2[1]); + } +} + + +/* Optimized function for in-place cipher block xoring */ +static inline void +cipher_block_xor_1(void *_dst, const void *_src, size_t blocksize) +{ + cipher_block_xor (_dst, _dst, _src, blocksize); +} + + +/* Optimized function for cipher block xoring with two destination cipher + blocks. Used mainly by CFB mode encryption. */ +static inline void +cipher_block_xor_2dst(void *_dst1, void *_dst2, const void *_src, + size_t blocksize) +{ + byte *dst1 = _dst1; + byte *dst2 = _dst2; + const byte *src = _src; + u64 d2[2]; + u64 s[2]; + + if (blocksize == 8) + { + d2[0] = buf_get_he64(dst2 + 0) ^ buf_get_he64(src + 0); + buf_put_he64(dst2 + 0, d2[0]); + buf_put_he64(dst1 + 0, d2[0]); + } + else /* blocksize == 16 */ + { + s[0] = buf_get_he64(src + 0); + s[1] = buf_get_he64(src + 8); + d2[0] = buf_get_he64(dst2 + 0); + d2[1] = buf_get_he64(dst2 + 8); + d2[0] = d2[0] ^ s[0]; + d2[1] = d2[1] ^ s[1]; + buf_put_he64(dst2 + 0, d2[0]); + buf_put_he64(dst2 + 8, d2[1]); + buf_put_he64(dst1 + 0, d2[0]); + buf_put_he64(dst1 + 8, d2[1]); + } +} + + +/* Optimized function for combined cipher block xoring and copying. + Used by mainly CBC mode decryption. */ +static inline void +cipher_block_xor_n_copy_2(void *_dst_xor, const void *_src_xor, + void *_srcdst_cpy, const void *_src_cpy, + size_t blocksize) +{ + byte *dst_xor = _dst_xor; + byte *srcdst_cpy = _srcdst_cpy; + const byte *src_xor = _src_xor; + const byte *src_cpy = _src_cpy; + u64 sc[2]; + u64 sx[2]; + u64 sdc[2]; + + if (blocksize == 8) + { + sc[0] = buf_get_he64(src_cpy + 0); + buf_put_he64(dst_xor + 0, + buf_get_he64(srcdst_cpy + 0) ^ buf_get_he64(src_xor + 0)); + buf_put_he64(srcdst_cpy + 0, sc[0]); + } + else /* blocksize == 16 */ + { + sc[0] = buf_get_he64(src_cpy + 0); + sc[1] = buf_get_he64(src_cpy + 8); + sx[0] = buf_get_he64(src_xor + 0); + sx[1] = buf_get_he64(src_xor + 8); + sdc[0] = buf_get_he64(srcdst_cpy + 0); + sdc[1] = buf_get_he64(srcdst_cpy + 8); + sx[0] ^= sdc[0]; + sx[1] ^= sdc[1]; + buf_put_he64(dst_xor + 0, sx[0]); + buf_put_he64(dst_xor + 8, sx[1]); + buf_put_he64(srcdst_cpy + 0, sc[0]); + buf_put_he64(srcdst_cpy + 8, sc[1]); + } +} + + +/* Optimized function for combined cipher block xoring and copying. + Used by mainly CFB mode decryption. */ +static inline void +cipher_block_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, + size_t blocksize) +{ + cipher_block_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, blocksize); +} + + #endif /*G10_CIPHER_INTERNAL_H*/ diff --git a/cipher/cipher-ocb.c b/cipher/cipher-ocb.c index db42aaf..f71520a 100644 --- a/cipher/cipher-ocb.c +++ b/cipher/cipher-ocb.c @@ -82,7 +82,7 @@ static void double_block_cpy (unsigned char *d, const unsigned char *s) { if (d != s) - buf_cpy (d, s, OCB_BLOCK_LEN); + cipher_block_cpy (d, s, OCB_BLOCK_LEN); double_block (d); } @@ -181,8 +181,8 @@ _gcry_cipher_ocb_set_nonce (gcry_cipher_hd_t c, const unsigned char *nonce, nburn = c->spec->encrypt (&c->context.c, ktop, ktop); burn = nburn > burn ? nburn : burn; /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */ - buf_cpy (stretch, ktop, OCB_BLOCK_LEN); - buf_xor (stretch + OCB_BLOCK_LEN, ktop, ktop + 1, 8); + cipher_block_cpy (stretch, ktop, OCB_BLOCK_LEN); + cipher_block_xor (stretch + OCB_BLOCK_LEN, ktop, ktop + 1, 8); /* Offset_0 = Stretch[1+bottom..128+bottom] (We use the IV field to store the offset) */ bit_copy (c->u_iv.iv, stretch, bottom, OCB_BLOCK_LEN); @@ -267,18 +267,18 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf, } else { - buf_cpy (l_tmp, ocb_get_l (c, c->u_mode.ocb.aad_nblocks), - OCB_BLOCK_LEN); + cipher_block_cpy (l_tmp, ocb_get_l (c, c->u_mode.ocb.aad_nblocks), + OCB_BLOCK_LEN); } /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN); /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ - buf_xor (l_tmp, c->u_mode.ocb.aad_offset, - c->u_mode.ocb.aad_leftover, OCB_BLOCK_LEN); + cipher_block_xor (l_tmp, c->u_mode.ocb.aad_offset, + c->u_mode.ocb.aad_leftover, OCB_BLOCK_LEN); nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp); burn = nburn > burn ? nburn : burn; - buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); c->u_mode.ocb.aad_nleftover = 0; } @@ -309,12 +309,13 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf, ocb_get_L_big(c, c->u_mode.ocb.aad_nblocks, l_tmp); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_offset, l_tmp, OCB_BLOCK_LEN); /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ - buf_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf, OCB_BLOCK_LEN); + cipher_block_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf, + OCB_BLOCK_LEN); nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp); burn = nburn > burn ? nburn : burn; - buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); abuf += OCB_BLOCK_LEN; abuflen -= OCB_BLOCK_LEN; @@ -349,14 +350,15 @@ _gcry_cipher_ocb_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf, gcry_assert(c->u_mode.ocb.aad_nblocks & table_size_mask); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_mode.ocb.aad_offset, - ocb_get_l (c, c->u_mode.ocb.aad_nblocks), - OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_offset, + ocb_get_l (c, c->u_mode.ocb.aad_nblocks), + OCB_BLOCK_LEN); /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ - buf_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf, OCB_BLOCK_LEN); + cipher_block_xor (l_tmp, c->u_mode.ocb.aad_offset, abuf, + OCB_BLOCK_LEN); nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp); burn = nburn > burn ? nburn : burn; - buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); abuf += OCB_BLOCK_LEN; abuflen -= OCB_BLOCK_LEN; @@ -397,18 +399,18 @@ ocb_aad_finalize (gcry_cipher_hd_t c) if (c->u_mode.ocb.aad_nleftover) { /* Offset_* = Offset_m xor L_* */ - buf_xor_1 (c->u_mode.ocb.aad_offset, - c->u_mode.ocb.L_star, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_offset, + c->u_mode.ocb.L_star, OCB_BLOCK_LEN); /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */ buf_cpy (l_tmp, c->u_mode.ocb.aad_leftover, c->u_mode.ocb.aad_nleftover); memset (l_tmp + c->u_mode.ocb.aad_nleftover, 0, OCB_BLOCK_LEN - c->u_mode.ocb.aad_nleftover); l_tmp[c->u_mode.ocb.aad_nleftover] = 0x80; - buf_xor_1 (l_tmp, c->u_mode.ocb.aad_offset, OCB_BLOCK_LEN); + cipher_block_xor_1 (l_tmp, c->u_mode.ocb.aad_offset, OCB_BLOCK_LEN); /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */ nburn = c->spec->encrypt (&c->context.c, l_tmp, l_tmp); burn = nburn > burn ? nburn : burn; - buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp, OCB_BLOCK_LEN); c->u_mode.ocb.aad_nleftover = 0; } @@ -431,7 +433,7 @@ ocb_checksum (unsigned char *chksum, const unsigned char *plainbuf, while (nblks > 0) { /* Checksum_i = Checksum_{i-1} xor P_i */ - buf_xor_1(chksum, plainbuf, OCB_BLOCK_LEN); + cipher_block_xor_1(chksum, plainbuf, OCB_BLOCK_LEN); plainbuf += OCB_BLOCK_LEN; nblks--; @@ -491,12 +493,12 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, } /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_iv.iv, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_iv.iv, l_tmp, OCB_BLOCK_LEN); /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ - buf_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN); + cipher_block_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN); nburn = crypt_fn (&c->context.c, outbuf, outbuf); burn = nburn > burn ? nburn : burn; - buf_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN); + cipher_block_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN); if (!encrypt) { @@ -551,14 +553,14 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, gcry_assert(c->u_mode.ocb.data_nblocks & table_size_mask); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_iv.iv, - ocb_get_l (c, c->u_mode.ocb.data_nblocks), - OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_iv.iv, + ocb_get_l (c, c->u_mode.ocb.data_nblocks), + OCB_BLOCK_LEN); /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ - buf_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN); + cipher_block_xor (outbuf, c->u_iv.iv, inbuf, OCB_BLOCK_LEN); nburn = crypt_fn (&c->context.c, outbuf, outbuf); burn = nburn > burn ? nburn : burn; - buf_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN); + cipher_block_xor_1 (outbuf, c->u_iv.iv, OCB_BLOCK_LEN); inbuf += OCB_BLOCK_LEN; inbuflen -= OCB_BLOCK_LEN; @@ -584,7 +586,7 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, unsigned char pad[OCB_BLOCK_LEN]; /* Offset_* = Offset_m xor L_* */ - buf_xor_1 (c->u_iv.iv, c->u_mode.ocb.L_star, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_iv.iv, c->u_mode.ocb.L_star, OCB_BLOCK_LEN); /* Pad = ENCIPHER(K, Offset_*) */ nburn = c->spec->encrypt (&c->context.c, pad, c->u_iv.iv); burn = nburn > burn ? nburn : burn; @@ -596,7 +598,7 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, buf_cpy (l_tmp, inbuf, inbuflen); memset (l_tmp + inbuflen, 0, OCB_BLOCK_LEN - inbuflen); l_tmp[inbuflen] = 0x80; - buf_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN); /* C_* = P_* xor Pad[1..bitlen(P_*)] */ buf_xor (outbuf, inbuf, pad, inbuflen); } @@ -604,13 +606,13 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, { /* P_* = C_* xor Pad[1..bitlen(C_*)] */ /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ - buf_cpy (l_tmp, pad, OCB_BLOCK_LEN); + cipher_block_cpy (l_tmp, pad, OCB_BLOCK_LEN); buf_cpy (l_tmp, inbuf, inbuflen); - buf_xor_1 (l_tmp, pad, OCB_BLOCK_LEN); + cipher_block_xor_1 (l_tmp, pad, OCB_BLOCK_LEN); l_tmp[inbuflen] = 0x80; buf_cpy (outbuf, l_tmp, inbuflen); - buf_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_ctr.ctr, l_tmp, OCB_BLOCK_LEN); } } @@ -618,8 +620,10 @@ ocb_crypt (gcry_cipher_hd_t c, int encrypt, if (c->marks.finalize) { /* Tag = ENCIPHER(K, Checksum xor Offset xor L_$) xor HASH(K,A) */ - buf_xor (c->u_mode.ocb.tag, c->u_ctr.ctr, c->u_iv.iv, OCB_BLOCK_LEN); - buf_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.L_dollar, OCB_BLOCK_LEN); + cipher_block_xor (c->u_mode.ocb.tag, c->u_ctr.ctr, c->u_iv.iv, + OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.L_dollar, + OCB_BLOCK_LEN); nburn = c->spec->encrypt (&c->context.c, c->u_mode.ocb.tag, c->u_mode.ocb.tag); burn = nburn > burn ? nburn : burn; @@ -672,7 +676,8 @@ compute_tag_if_needed (gcry_cipher_hd_t c) if (!c->marks.tag) { ocb_aad_finalize (c); - buf_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.aad_sum, OCB_BLOCK_LEN); + cipher_block_xor_1 (c->u_mode.ocb.tag, c->u_mode.ocb.aad_sum, + OCB_BLOCK_LEN); c->marks.tag = 1; } } diff --git a/cipher/cipher-ofb.c b/cipher/cipher-ofb.c index 419a8d0..a3fd299 100644 --- a/cipher/cipher-ofb.c +++ b/cipher/cipher-ofb.c @@ -72,7 +72,7 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c, /* Encrypt the IV (and save the current one). */ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); burn = nburn > burn ? nburn : burn; - buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize); + cipher_block_xor(outbuf, c->u_iv.iv, inbuf, blocksize); outbuf += blocksize; inbuf += blocksize; inbuflen -= blocksize; diff --git a/cipher/cipher-xts.c b/cipher/cipher-xts.c index 045b353..0522a27 100644 --- a/cipher/cipher-xts.c +++ b/cipher/cipher-xts.c @@ -107,10 +107,10 @@ _gcry_cipher_xts_crypt (gcry_cipher_hd_t c, while (nblocks) { /* Xor-Encrypt/Decrypt-Xor block. */ - buf_xor (tmp.x64, inbuf, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (tmp.x64, inbuf, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); nburn = crypt_fn (&c->context.c, tmp.x1, tmp.x1); burn = nburn > burn ? nburn : burn; - buf_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); outbuf += GCRY_XTS_BLOCK_LEN; inbuf += GCRY_XTS_BLOCK_LEN; @@ -133,10 +133,10 @@ _gcry_cipher_xts_crypt (gcry_cipher_hd_t c, xts_gfmul_byA (tmp.x1, c->u_ctr.ctr); /* Decrypt last block first. */ - buf_xor (outbuf, inbuf, tmp.x64, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (outbuf, inbuf, tmp.x64, GCRY_XTS_BLOCK_LEN); nburn = crypt_fn (&c->context.c, outbuf, outbuf); burn = nburn > burn ? nburn : burn; - buf_xor (outbuf, outbuf, tmp.x64, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (outbuf, outbuf, tmp.x64, GCRY_XTS_BLOCK_LEN); inbuflen -= GCRY_XTS_BLOCK_LEN; inbuf += GCRY_XTS_BLOCK_LEN; @@ -147,15 +147,15 @@ _gcry_cipher_xts_crypt (gcry_cipher_hd_t c, outbuf -= GCRY_XTS_BLOCK_LEN; /* Steal ciphertext from previous block. */ - buf_cpy (tmp.x64, outbuf, GCRY_XTS_BLOCK_LEN); + cipher_block_cpy (tmp.x64, outbuf, GCRY_XTS_BLOCK_LEN); buf_cpy (tmp.x64, inbuf, inbuflen); buf_cpy (outbuf + GCRY_XTS_BLOCK_LEN, outbuf, inbuflen); /* Decrypt/Encrypt last block. */ - buf_xor (tmp.x64, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (tmp.x64, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); nburn = crypt_fn (&c->context.c, tmp.x1, tmp.x1); burn = nburn > burn ? nburn : burn; - buf_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); + cipher_block_xor (outbuf, tmp.x64, c->u_ctr.ctr, GCRY_XTS_BLOCK_LEN); } /* Auto-increment data-unit sequence number */ diff --git a/cipher/des.c b/cipher/des.c index 0509227..a008b93 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -119,6 +119,7 @@ #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" +#include "cipher-internal.h" #include "cipher-selftest.h" @@ -908,7 +909,7 @@ _gcry_3des_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, /* Encrypt the counter. */ tripledes_ecb_encrypt (ctx, ctr, tmpbuf); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, DES_BLOCKSIZE); + cipher_block_xor(outbuf, tmpbuf, inbuf, DES_BLOCKSIZE); outbuf += DES_BLOCKSIZE; inbuf += DES_BLOCKSIZE; /* Increment the counter. */ @@ -964,7 +965,7 @@ _gcry_3des_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, the intermediate result to SAVEBUF. */ tripledes_ecb_decrypt (ctx, inbuf, savebuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, DES_BLOCKSIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, DES_BLOCKSIZE); inbuf += DES_BLOCKSIZE; outbuf += DES_BLOCKSIZE; } @@ -1009,7 +1010,7 @@ _gcry_3des_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, for ( ;nblocks; nblocks-- ) { tripledes_ecb_encrypt (ctx, iv, iv); - buf_xor_n_copy(outbuf, iv, inbuf, DES_BLOCKSIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, DES_BLOCKSIZE); outbuf += DES_BLOCKSIZE; inbuf += DES_BLOCKSIZE; } diff --git a/cipher/rijndael.c b/cipher/rijndael.c index d3fcb76..d126f88 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -831,7 +831,7 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv, /* Encrypt the IV. */ burn_depth = encrypt_fn (ctx, iv, iv); /* XOR the input with the IV and store input into IV. */ - buf_xor_2dst(outbuf, iv, inbuf, BLOCKSIZE); + cipher_block_xor_2dst(outbuf, iv, inbuf, BLOCKSIZE); outbuf += BLOCKSIZE; inbuf += BLOCKSIZE; } @@ -891,7 +891,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, for ( ;nblocks; nblocks-- ) { - buf_xor(outbuf, inbuf, last_iv, BLOCKSIZE); + cipher_block_xor(outbuf, inbuf, last_iv, BLOCKSIZE); burn_depth = encrypt_fn (ctx, outbuf, outbuf); @@ -902,7 +902,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, } if (last_iv != iv) - buf_cpy (iv, last_iv, BLOCKSIZE); + cipher_block_cpy (iv, last_iv, BLOCKSIZE); } if (burn_depth) @@ -962,7 +962,7 @@ _gcry_aes_ctr_enc (void *context, unsigned char *ctr, /* Encrypt the counter. */ burn_depth = encrypt_fn (ctx, tmp.x1, ctr); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmp.x1, inbuf, BLOCKSIZE); + cipher_block_xor(outbuf, tmp.x1, inbuf, BLOCKSIZE); outbuf += BLOCKSIZE; inbuf += BLOCKSIZE; /* Increment the counter. */ @@ -1207,7 +1207,7 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv, for ( ;nblocks; nblocks-- ) { burn_depth = encrypt_fn (ctx, iv, iv); - buf_xor_n_copy(outbuf, iv, inbuf, BLOCKSIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, BLOCKSIZE); outbuf += BLOCKSIZE; inbuf += BLOCKSIZE; } @@ -1272,7 +1272,7 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv, burn_depth = decrypt_fn (ctx, savebuf, inbuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE); inbuf += BLOCKSIZE; outbuf += BLOCKSIZE; } @@ -1330,15 +1330,15 @@ _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const unsigned char *l = ocb_get_l(c, i); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_iv.iv, l, BLOCKSIZE); - buf_cpy (l_tmp.x1, inbuf, BLOCKSIZE); + cipher_block_xor_1 (c->u_iv.iv, l, BLOCKSIZE); + cipher_block_cpy (l_tmp.x1, inbuf, BLOCKSIZE); /* Checksum_i = Checksum_{i-1} xor P_i */ - buf_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE); + cipher_block_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE); /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ - buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); + cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); burn_depth = encrypt_fn (ctx, l_tmp.x1, l_tmp.x1); - buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); - buf_cpy (outbuf, l_tmp.x1, BLOCKSIZE); + cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); + cipher_block_cpy (outbuf, l_tmp.x1, BLOCKSIZE); inbuf += BLOCKSIZE; outbuf += BLOCKSIZE; @@ -1360,15 +1360,15 @@ _gcry_aes_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg, const unsigned char *l = ocb_get_l(c, i); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_iv.iv, l, BLOCKSIZE); - buf_cpy (l_tmp.x1, inbuf, BLOCKSIZE); + cipher_block_xor_1 (c->u_iv.iv, l, BLOCKSIZE); + cipher_block_cpy (l_tmp.x1, inbuf, BLOCKSIZE); /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ - buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); + cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); burn_depth = decrypt_fn (ctx, l_tmp.x1, l_tmp.x1); - buf_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); + cipher_block_xor_1 (l_tmp.x1, c->u_iv.iv, BLOCKSIZE); /* Checksum_i = Checksum_{i-1} xor P_i */ - buf_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE); - buf_cpy (outbuf, l_tmp.x1, BLOCKSIZE); + cipher_block_xor_1 (c->u_ctr.ctr, l_tmp.x1, BLOCKSIZE); + cipher_block_cpy (outbuf, l_tmp.x1, BLOCKSIZE); inbuf += BLOCKSIZE; outbuf += BLOCKSIZE; @@ -1424,11 +1424,12 @@ _gcry_aes_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks) const unsigned char *l = ocb_get_l(c, i); /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ - buf_xor_1 (c->u_mode.ocb.aad_offset, l, BLOCKSIZE); + cipher_block_xor_1 (c->u_mode.ocb.aad_offset, l, BLOCKSIZE); /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ - buf_xor (l_tmp.x1, c->u_mode.ocb.aad_offset, abuf, BLOCKSIZE); + cipher_block_xor (l_tmp.x1, c->u_mode.ocb.aad_offset, abuf, + BLOCKSIZE); burn_depth = encrypt_fn (ctx, l_tmp.x1, l_tmp.x1); - buf_xor_1 (c->u_mode.ocb.aad_sum, l_tmp.x1, BLOCKSIZE); + cipher_block_xor_1 (c->u_mode.ocb.aad_sum, l_tmp.x1, BLOCKSIZE); abuf += BLOCKSIZE; } diff --git a/cipher/serpent.c b/cipher/serpent.c index 0736ad1..8e3faa7 100644 --- a/cipher/serpent.c +++ b/cipher/serpent.c @@ -1002,7 +1002,7 @@ _gcry_serpent_ctr_enc(void *context, unsigned char *ctr, /* Encrypt the counter. */ serpent_encrypt_internal(ctx, ctr, tmpbuf); /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, sizeof(serpent_block_t)); + cipher_block_xor(outbuf, tmpbuf, inbuf, sizeof(serpent_block_t)); outbuf += sizeof(serpent_block_t); inbuf += sizeof(serpent_block_t); /* Increment the counter. */ @@ -1117,7 +1117,8 @@ _gcry_serpent_cbc_dec(void *context, unsigned char *iv, the intermediate result to SAVEBUF. */ serpent_decrypt_internal (ctx, inbuf, savebuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, sizeof(serpent_block_t)); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, + sizeof(serpent_block_t)); inbuf += sizeof(serpent_block_t); outbuf += sizeof(serpent_block_t); } @@ -1221,7 +1222,7 @@ _gcry_serpent_cfb_dec(void *context, unsigned char *iv, for ( ;nblocks; nblocks-- ) { serpent_encrypt_internal(ctx, iv, iv); - buf_xor_n_copy(outbuf, iv, inbuf, sizeof(serpent_block_t)); + cipher_block_xor_n_copy(outbuf, iv, inbuf, sizeof(serpent_block_t)); outbuf += sizeof(serpent_block_t); inbuf += sizeof(serpent_block_t); } diff --git a/cipher/twofish.c b/cipher/twofish.c index 0d187bd..51982c5 100644 --- a/cipher/twofish.c +++ b/cipher/twofish.c @@ -1161,7 +1161,7 @@ _gcry_twofish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, burn_stack_depth = burn; /* XOR the input with the encrypted counter and store in output. */ - buf_xor(outbuf, tmpbuf, inbuf, TWOFISH_BLOCKSIZE); + cipher_block_xor(outbuf, tmpbuf, inbuf, TWOFISH_BLOCKSIZE); outbuf += TWOFISH_BLOCKSIZE; inbuf += TWOFISH_BLOCKSIZE; /* Increment the counter. */ @@ -1243,7 +1243,7 @@ _gcry_twofish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, if (burn > burn_stack_depth) burn_stack_depth = burn; - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, TWOFISH_BLOCKSIZE); + cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, TWOFISH_BLOCKSIZE); inbuf += TWOFISH_BLOCKSIZE; outbuf += TWOFISH_BLOCKSIZE; } @@ -1315,7 +1315,7 @@ _gcry_twofish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, if (burn > burn_stack_depth) burn_stack_depth = burn; - buf_xor_n_copy(outbuf, iv, inbuf, TWOFISH_BLOCKSIZE); + cipher_block_xor_n_copy(outbuf, iv, inbuf, TWOFISH_BLOCKSIZE); outbuf += TWOFISH_BLOCKSIZE; inbuf += TWOFISH_BLOCKSIZE; } ----------------------------------------------------------------------- Summary of changes: cipher/blowfish.c | 7 +- cipher/bufhelp.h | 16 ++++- cipher/camellia-glue.c | 7 +- cipher/cast5.c | 7 +- cipher/cipher-aeswrap.c | 4 +- cipher/cipher-cbc.c | 15 +++-- cipher/cipher-ccm.c | 7 +- cipher/cipher-cfb.c | 16 ++--- cipher/cipher-cmac.c | 8 +-- cipher/cipher-ctr.c | 50 +++++++++----- cipher/cipher-eax.c | 11 +-- cipher/cipher-gcm-intel-pclmul.c | 21 +++--- cipher/cipher-gcm.c | 14 ++-- cipher/cipher-internal.h | 141 +++++++++++++++++++++++++++++++++++++++ cipher/cipher-ocb.c | 81 +++++++++++----------- cipher/cipher-ofb.c | 2 +- cipher/cipher-xts.c | 14 ++-- cipher/des.c | 7 +- cipher/rijndael.c | 43 ++++++------ cipher/serpent.c | 7 +- cipher/twofish.c | 6 +- 21 files changed, 335 insertions(+), 149 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From peter at lekensteyn.nl Mon Jul 30 14:54:11 2018 From: peter at lekensteyn.nl (Peter Wu) Date: Mon, 30 Jul 2018 14:54:11 +0200 Subject: 25519 usability and performance in Libgcrypt Message-ID: <20180730125411.GA26972@al> Hi, I have been looking at integrating X25519 (Curve25519 ECDH) into an application that already uses Libgcrypt. I was not impressed with the ease of integration nor its performance characteristics and will further elaborate this. The manual lacks documentation on using X25519. The closest thing to documentation is tests/t-cv25519.c. It contains two interfaces: - a low-level MPI implementation (test_it). This is probably the best implementation that is available in Libgcrypt. - a high-level implementation through gcry_pk_encrypt (test_cv). This performs twice as slow as necessary. Internally it computes a scalar multiplication, twice (given secret scalar k, it computes kdG and kG). One use case is to compute the public key for a given private key, so only kG is necessary (and kdG will be equal in this case). Another is to compute the shared secret kdG and thus kG is again superfluous. In fact, the comment for test_cv claims to use gcry_pk_decrypt which it does not do. Using gcry_pk_decrypt would be a better approach, given k and dG, compute kdG. The interface is however rather painful. Lots of internal details leak out of this supposedly high-level interface (this also applies to gcry_pk_decrypt). This is best demonstrated by code: /* * Computes Q = X25519(k, 9) where k and q are both encoded in little-endian * (as specified by the Curve25519 paper). * Returns 0 on success and -1 on failure. */ int x25519_base(unsigned char *q, const unsigned char *k) { unsigned char k_be[32]; gcry_sexp_t s_pk = NULL; gcry_sexp_t s_bp = NULL; gcry_sexp_t s_result = NULL; // Issue 1: Gcrypt MPI library stores integers in big-endian format (MSB // first) while Curve25519 keys are usually little-endian. This seems // also visible when using the "%b" format with gcry_sexp_build. for (int i = 0; i < 32; i++) { k_be[31 - i] = k[i]; } // Issue 2: unlike gcry_pk_encrypt, there is no clamping in // gcry_pk_decrypt. So do it manually. Note big-endian. k_be[0] &= 127; k_be[0] |= 64; k_be[31] &= 0xf8; // Build private key from a valid Curve25519 secret (after clamping). int r = gcry_sexp_build(&s_pk, NULL, "(private-key" " (ecc" " (curve \"Curve25519\")" " (flags djb-tweak)" " (d%b)))", 32, k_be); assert(r == 0); // Issue 3: internal details leak out: why can't the public key directly // be passed? // Issue 4: trying to pass 32 bytes without prefix triggers another bug: // 9 is treated as +0900000000000000 due to _gcry_ecc_mont_decodepoint. unsigned char basepoint[33] = { 0x40, 9 }; r = gcry_sexp_build(&s_bp, NULL, "(enc-val(ecdh(e%b)))", 33, basepoint); assert(r == 0); // Issue 4 also occurs with this alternative code: // gcry_mpi_t mpi_bp = gcry_mpi_set_ui(NULL, 9); // gcry_sexp_build(&s_bp, NULL, "(enc-val (ecdh (e%m)))", mpi_bp); // Finally compute the scalar multiplication. r = gcry_pk_decrypt(&s_result, s_bp, s_pk); if (r == 0) { // Issue 3 continued: why is this internal prefix detail exposed? size_t res_len = 0; unsigned char *buffer = (unsigned char*)gcry_sexp_nth_buffer(s_result, 1, &res_len); assert(res_len == 1 + 32); assert(buffer[0] == 0x40); for (int i = 0; i < 32; i++) { q[i] = buffer[1 + i]; } gcry_free(buffer); } gcry_sexp_release(s_result); gcry_sexp_release(s_bp); gcry_sexp_release(s_pk); return r == 0 ? 0 : -1; } The above x25519_base code can easily be adjusted to compute a shared secret (adjust "basepoint" in the above example), but this should be sufficient to illustrate some issues. Finally I will conclude with a comparison with other implementations. Sodium/NaCl provides a very nice, simple API. The above code could be replaced with: int x25519_base(unsigned char *q, const unsigned char *k) { return crypto_scalarmult_base(q, k); } As for the performance, I conducted some benchmarks on an Ivy Bridge desktop CPU (i7-3770) with GCC 7.3.0 and Ubuntu 18.04. I ran 5?8192 iterations of the above function. Results (from fastest to slowest): Sodium (baseline, has optimized asm impl.) TweetNaCl-O3 18.42x slower (with car25519 fix and -O3). TweetNaCl-O2 37.59x slower (with car25519 fix and -O2). Gcrypt (MPI) 38.95x slower (2.11x tweetnacl) gcry_pk_decrypt 39.12x slower (2.12x tweetnacl) gcry_pk_encrypt 78.48x slower (4.26x tweetnacl) Built with libsodium23 1.0.16-2 and libgcrypt20 1.8.1-4ubuntu1.1. TweetNaCl is a pure C implementation from https://tweetnacl.cr.yp.to/ If performance is important, I would not use Libgcrypt for X25519 since it has no optimized routines and use Sodium instead. Since reuse of existing dependencies (Libgcrypt) would be nice, the next best option is the low-level MPI interface. Not gcry_pk_encrypt because it is twice as slow. Not gcry_pk_decrypt because it still requires manual clamping and ugly conversions. -- Kind regards, Peter Wu https://lekensteyn.nl From mrhines at digitalocean.com Tue Jul 31 02:03:29 2018 From: mrhines at digitalocean.com (Michael R. Hines) Date: Mon, 30 Jul 2018 19:03:29 -0500 Subject: request for TLBleed information / non-constant-time vulnerabilities Message-ID: Greetings, Our team is trying to get an accurate understanding of whether or not the most recent version of libgcrypt does or does not remain vulnerable to the timing attack document here: https://www.vusec.net/wp-content/uploads/2018/07/tlbleed-author-preprint.pdf In addition to that, more generally, as a cloud provider we are also looking for input and guidance on whether or not there are other locations that should be of concern within libgcrypt from the perspective of TLBleed. Thank you! -- /* * Michael R. Hines * Staff Engineer, DigitalOcean. */