diff options
author | Jussi Kivilinna <[email protected]> | 2018-11-08 19:31:12 +0000 |
---|---|---|
committer | Jussi Kivilinna <[email protected]> | 2018-11-08 19:31:12 +0000 |
commit | e8142cc69a2ae5a5d0a238bc9f88841067359af8 (patch) | |
tree | 4b47d4aa31bb93b2bfcafcae5c1157b43cee167b /g10/armor.c | |
parent | g10/armor: use libgcrypt's CRC24 implementation (diff) | |
download | gnupg-e8142cc69a2ae5a5d0a238bc9f88841067359af8.tar.gz gnupg-e8142cc69a2ae5a5d0a238bc9f88841067359af8.zip |
g10/armor: optimize binary to radix64 conversion
* g10/armor.c (bintoasc): Change to read-only.
(initialize): Use const pointer for 'bintoasc'.
(armor_output_buf_as_radix64): New function for faster binary to
radix64 conversion.
(armor_filter): Use new conversion function.
--
This patch adds faster binary to radix64 conversion to speed up
armored encryption.
Benchmark results below, tested on Intel Core i7-4790K (turbo off).
Encrypted 2 GiB through pipe to ramfs file using AES128. Decrypt
ramfs file out through pipe to /dev/null.
before patch-set
----------------
gpg process
armor: user time pipe transfer rate
encrypt-aead: 13.8 140 MB/s
decrypt-aead: 30.6 68 MB/s
encrypt-cfb: 17.4 114 MB/s
decrypt-cfb: 32.6 64 MB/s
after (decrypt+iobuf+crc+radix64 opt)
-------------------------------------
gpg process
armor: user time pipe transfer rate
encrypt-aead: 2.7 523 MB/s
encrypt-cfb: 6.7 264 MB/s
Signed-off-by: Jussi Kivilinna <[email protected]>
Diffstat (limited to 'g10/armor.c')
-rw-r--r-- | g10/armor.c | 162 |
1 files changed, 126 insertions, 36 deletions
diff --git a/g10/armor.c b/g10/armor.c index 9da135a2b..95293d91c 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -37,9 +37,9 @@ #define MAX_LINELEN 20000 -static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; +static const byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; static byte asctobin[256]; /* runtime initialized */ static int is_initialized; @@ -169,7 +169,8 @@ static void initialize(void) { u32 i; - byte *s; + const byte *s; + /* build the helptable for radix64 to bin conversion */ for(i=0; i < 256; i++ ) asctobin[i] = 255; /* used to detect invalid characters */ @@ -1003,6 +1004,121 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn, return rc; } +static void +armor_output_buf_as_radix64 (armor_filter_context_t *afx, IOBUF a, + byte *buf, size_t size) +{ + byte radbuf[sizeof (afx->radbuf)]; + byte outbuf[64 + sizeof (afx->eol)]; + unsigned int eollen = strlen (afx->eol); + u32 in, in2; + int idx, idx2; + int i; + + idx = afx->idx; + idx2 = afx->idx2; + memcpy (radbuf, afx->radbuf, sizeof (afx->radbuf)); + + if (size && (idx || idx2)) + { + /* preload eol to outbuf buffer */ + memcpy (outbuf + 4, afx->eol, sizeof (afx->eol)); + + for (; size && (idx || idx2); buf++, size--) + { + radbuf[idx++] = *buf; + if (idx > 2) + { + idx = 0; + in = (u32)radbuf[0] << (2 * 8); + in |= (u32)radbuf[1] << (1 * 8); + in |= (u32)radbuf[2] << (0 * 8); + outbuf[0] = bintoasc[(in >> 18) & 077]; + outbuf[1] = bintoasc[(in >> 12) & 077]; + outbuf[2] = bintoasc[(in >> 6) & 077]; + outbuf[3] = bintoasc[(in >> 0) & 077]; + if (++idx2 >= (64/4)) + { /* pgp doesn't like 72 here */ + idx2=0; + iobuf_write (a, outbuf, 4 + eollen); + } + else + { + iobuf_write (a, outbuf, 4); + } + } + } + } + + if (size >= (64/4)*3) + { + /* preload eol to outbuf buffer */ + memcpy (outbuf + 64, afx->eol, sizeof(afx->eol)); + + do + { + /* idx and idx2 == 0 */ + + for (i = 0; i < (64/8); i++) + { + in = (u32)buf[0] << (2 * 8); + in |= (u32)buf[1] << (1 * 8); + in |= (u32)buf[2] << (0 * 8); + in2 = (u32)buf[3] << (2 * 8); + in2 |= (u32)buf[4] << (1 * 8); + in2 |= (u32)buf[5] << (0 * 8); + outbuf[i*8+0] = bintoasc[(in >> 18) & 077]; + outbuf[i*8+1] = bintoasc[(in >> 12) & 077]; + outbuf[i*8+2] = bintoasc[(in >> 6) & 077]; + outbuf[i*8+3] = bintoasc[(in >> 0) & 077]; + outbuf[i*8+4] = bintoasc[(in2 >> 18) & 077]; + outbuf[i*8+5] = bintoasc[(in2 >> 12) & 077]; + outbuf[i*8+6] = bintoasc[(in2 >> 6) & 077]; + outbuf[i*8+7] = bintoasc[(in2 >> 0) & 077]; + buf+=6; + size-=6; + } + + /* pgp doesn't like 72 here */ + iobuf_write (a, outbuf, 64 + eollen); + } + while (size >= (64/4)*3); + + /* restore eol for tail handling */ + if (size) + memcpy (outbuf + 4, afx->eol, sizeof (afx->eol)); + } + + for (; size; buf++, size--) + { + radbuf[idx++] = *buf; + if (idx > 2) + { + idx = 0; + in = (u32)radbuf[0] << (2 * 8); + in |= (u32)radbuf[1] << (1 * 8); + in |= (u32)radbuf[2] << (0 * 8); + outbuf[0] = bintoasc[(in >> 18) & 077]; + outbuf[1] = bintoasc[(in >> 12) & 077]; + outbuf[2] = bintoasc[(in >> 6) & 077]; + outbuf[3] = bintoasc[(in >> 0) & 077]; + if (++idx2 >= (64/4)) + { /* pgp doesn't like 72 here */ + idx2=0; + iobuf_write (a, outbuf, 4 + eollen); + } + else + { + iobuf_write (a, outbuf, 4); + } + } + } + + memcpy (afx->radbuf, radbuf, sizeof (afx->radbuf)); + afx->idx = idx; + afx->idx2 = idx2; +} + /**************** * This filter is used to handle the armor stuff */ @@ -1012,7 +1128,7 @@ armor_filter( void *opaque, int control, { size_t size = *ret_len; armor_filter_context_t *afx = opaque; - int rc=0, i, c; + int rc=0, c; byte radbuf[3]; int idx, idx2; size_t n=0; @@ -1196,37 +1312,11 @@ armor_filter( void *opaque, int control, afx->idx2 = 0; gcry_md_reset (afx->crc_md); } - idx = afx->idx; - idx2 = afx->idx2; - for(i=0; i < idx; i++ ) - radbuf[i] = afx->radbuf[i]; - - if( size ) - gcry_md_write (afx->crc_md, buf, size); - - for( ; size; buf++, size-- ) { - radbuf[idx++] = *buf; - if( idx > 2 ) { - idx = 0; - c = bintoasc[(*radbuf >> 2) & 077]; - iobuf_put(a, c); - c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077]; - iobuf_put(a, c); - c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077]; - iobuf_put(a, c); - c = bintoasc[radbuf[2]&077]; - iobuf_put(a, c); - if( ++idx2 >= (64/4) ) - { /* pgp doesn't like 72 here */ - iobuf_writestr(a,afx->eol); - idx2=0; - } - } - } - for(i=0; i < idx; i++ ) - afx->radbuf[i] = radbuf[i]; - afx->idx = idx; - afx->idx2 = idx2; + + if( size ) { + gcry_md_write (afx->crc_md, buf, size); + armor_output_buf_as_radix64 (afx, a, buf, size); + } } else if( control == IOBUFCTRL_INIT ) { |