Mailing List Archive

[PATCH 3/4] mpi: optimizations for MPI scanning and printing
* mpi/mpicoder.c (mpi_read_from_buffer): Add word-size buffer
reading loop using 'buf_get_be(32|64)'.
(mpi_fromstr): Use look-up tables for HEX conversion; Add fast-path
loop for converting 8 hex-characters at once; Add string length
parameter.
(do_get_buffer): Use 'buf_put_be(32|64)' instead of byte writes; Add
fast-path for reversing buffer with 'buf_get_(be64|be32|le64|le32)'.
(_gcry_mpi_set_buffer): Use 'buf_get_be(32|64)' instead of byte reads.
(twocompl): Use _gcry_ctz instead of open-coded if-clauses to get
first bit set; Add fast-path for inverting buffer with
'buf_get_(he64|he32)'.
(_gcry_mpi_scan): Use 'buf_get_be32' where possible; Provide string
length to 'mpi_fromstr'.
(_gcry_mpi_print): Use 'buf_put_be32' where possible; Use look-up
table for HEX conversion; Add fast-path loop for converting to
8 hex-characters at once.
* tests/t-convert.c (check_formats): Add new tests for larger values.
--

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
---
mpi/mpicoder.c | 310 +++++++++++++++++---------
tests/t-convert.c | 538 ++++++++++++++++++++++++++++++----------------
2 files changed, 561 insertions(+), 287 deletions(-)

diff --git a/mpi/mpicoder.c b/mpi/mpicoder.c
index f61f777f..830ee4e2 100644
--- a/mpi/mpicoder.c
+++ b/mpi/mpicoder.c
@@ -26,6 +26,7 @@

#include "mpi-internal.h"
#include "g10lib.h"
+#include "../cipher/bufhelp.h"

/* The maximum length we support in the functions converting an
* external representation to an MPI. This limit is used to catch
@@ -51,8 +52,9 @@ mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
unsigned int nbits, nbytes, nlimbs, nread=0;
mpi_limb_t a;
gcry_mpi_t val = MPI_NULL;
+ unsigned int max_nread = *ret_nread;

- if ( *ret_nread < 2 )
+ if ( max_nread < 2 )
goto leave;
nbits = buffer[0] << 8 | buffer[1];
if ( nbits > MAX_EXTERN_MPI_BITS )
@@ -73,9 +75,22 @@ mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
for ( ; j > 0; j-- )
{
a = 0;
+ if (i == 0 && nread + BYTES_PER_MPI_LIMB <= max_nread)
+ {
+#if BYTES_PER_MPI_LIMB == 4
+ a = buf_get_be32 (buffer);
+#elif BYTES_PER_MPI_LIMB == 8
+ a = buf_get_be64 (buffer);
+#else
+# error please implement for this limb size.
+#endif
+ buffer += BYTES_PER_MPI_LIMB;
+ nread += BYTES_PER_MPI_LIMB;
+ i += BYTES_PER_MPI_LIMB;
+ }
for (; i < BYTES_PER_MPI_LIMB; i++ )
{
- if ( ++nread > *ret_nread )
+ if ( ++nread > max_nread )
{
/* log_debug ("mpi larger than buffer"); */
mpi_free (val);
@@ -99,8 +114,45 @@ mpi_read_from_buffer (const unsigned char *buffer, unsigned *ret_nread,
* Fill the mpi VAL from the hex string in STR.
*/
static int
-mpi_fromstr (gcry_mpi_t val, const char *str)
+mpi_fromstr (gcry_mpi_t val, const char *str, size_t slen)
{
+ static const int hex2int[2][256] =
+ {
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x00, 0x10, 0x20, 0x30,
+ 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, -1, -1, -1, -1, -1, -1, -1, 0xa0,
+ 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0xa0,
+ 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ },
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, -1, -1, -1, -1, -1, -1, -1, 0x0a,
+ 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0x0a,
+ 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ }
+ };
int sign = 0;
int prepend_zero = 0;
int i, j, c, c1, c2;
@@ -111,19 +163,17 @@ mpi_fromstr (gcry_mpi_t val, const char *str)
{
sign = 1;
str++;
+ slen--;
}

/* Skip optional hex prefix. */
if ( *str == '0' && str[1] == 'x' )
- str += 2;
-
- nbits = strlen (str);
- if (nbits > MAX_EXTERN_SCAN_BYTES)
{
- mpi_clear (val);
- return 1; /* Error. */
+ str += 2;
+ slen -= 2;
}
- nbits *= 4;
+
+ nbits = slen * 4;
if ((nbits % 8))
prepend_zero = 1;

@@ -140,6 +190,44 @@ mpi_fromstr (gcry_mpi_t val, const char *str)
for (; j > 0; j--)
{
a = 0;
+
+ if (prepend_zero == 0 && (i & 31) == 0)
+ {
+ while (slen >= sizeof(u32) * 2)
+ {
+ u32 n, m;
+ u32 x, y;
+
+ x = buf_get_le32(str);
+ y = buf_get_le32(str + 4);
+ str += 8;
+ slen -= 8;
+
+ a <<= 31; /* Two step to avoid compiler warning on 32-bit. */
+ a <<= 1;
+
+ n = (hex2int[0][(x >> 0) & 0xff]
+ | hex2int[1][(x >> 8) & 0xff]) << 8;
+ m = (hex2int[0][(y >> 0) & 0xff]
+ | hex2int[1][(y >> 8) & 0xff]) << 8;
+ n |= hex2int[0][(x >> 16) & 0xff];
+ n |= hex2int[1][(x >> 24) & 0xff];
+ m |= hex2int[0][(y >> 16) & 0xff];
+ m |= hex2int[1][(y >> 24) & 0xff];
+
+ a |= (n << 16) | m;
+ i += 32;
+ if ((int)(n | m) < 0)
+ {
+ /* Invalid character. */
+ mpi_clear (val);
+ return 1; /* Error. */
+ }
+ if (i == BITS_PER_MPI_LIMB)
+ break;
+ }
+ }
+
for (; i < BYTES_PER_MPI_LIMB; i++)
{
if (prepend_zero)
@@ -148,7 +236,10 @@ mpi_fromstr (gcry_mpi_t val, const char *str)
prepend_zero = 0;
}
else
- c1 = *str++;
+ {
+ c1 = *str++;
+ slen--;
+ }

if (!c1)
{
@@ -156,30 +247,15 @@ mpi_fromstr (gcry_mpi_t val, const char *str)
return 1; /* Error. */
}
c2 = *str++;
+ slen--;
if (!c2)
{
mpi_clear (val);
return 1; /* Error. */
}
- if ( c1 >= '0' && c1 <= '9' )
- c = c1 - '0';
- else if ( c1 >= 'a' && c1 <= 'f' )
- c = c1 - 'a' + 10;
- else if ( c1 >= 'A' && c1 <= 'F' )
- c = c1 - 'A' + 10;
- else
- {
- mpi_clear (val);
- return 1; /* Error. */
- }
- c <<= 4;
- if ( c2 >= '0' && c2 <= '9' )
- c |= c2 - '0';
- else if( c2 >= 'a' && c2 <= 'f' )
- c |= c2 - 'a' + 10;
- else if( c2 >= 'A' && c2 <= 'F' )
- c |= c2 - 'A' + 10;
- else
+ c = hex2int[0][c1 & 0xff];
+ c |= hex2int[1][c2 & 0xff];
+ if (c < 0)
{
mpi_clear(val);
return 1; /* Error. */
@@ -248,19 +324,11 @@ do_get_buffer (gcry_mpi_t a, unsigned int fill_le, int extraalloc,
{
alimb = a->d[i];
#if BYTES_PER_MPI_LIMB == 4
- *p++ = alimb >> 24;
- *p++ = alimb >> 16;
- *p++ = alimb >> 8;
- *p++ = alimb ;
+ buf_put_be32 (p, alimb);
+ p += 4;
#elif BYTES_PER_MPI_LIMB == 8
- *p++ = alimb >> 56;
- *p++ = alimb >> 48;
- *p++ = alimb >> 40;
- *p++ = alimb >> 32;
- *p++ = alimb >> 24;
- *p++ = alimb >> 16;
- *p++ = alimb >> 8;
- *p++ = alimb ;
+ buf_put_be64 (p, alimb);
+ p += 8;
#else
# error please implement for this limb size.
#endif
@@ -270,7 +338,22 @@ do_get_buffer (gcry_mpi_t a, unsigned int fill_le, int extraalloc,
{
length = *nbytes;
/* Reverse buffer and pad with zeroes. */
- for (i=0; i < length/2; i++)
+ for (i = 0; i + 8 < length / 2; i += 8)
+ {
+ u64 head = buf_get_be64 (buffer + i);
+ u64 tail = buf_get_be64 (buffer + length - 8 - i);
+ buf_put_le64 (buffer + length - 8 - i, head);
+ buf_put_le64 (buffer + i, tail);
+ }
+ if (i + 4 < length / 2)
+ {
+ u32 head = buf_get_be32 (buffer + i);
+ u32 tail = buf_get_be32 (buffer + length - 4 - i);
+ buf_put_le32 (buffer + length - 4 - i, head);
+ buf_put_le32 (buffer + i, tail);
+ i += 4;
+ }
+ for (; i < length/2; i++)
{
tmp = buffer[i];
buffer[i] = buffer[length-1-i];
@@ -354,53 +437,33 @@ _gcry_mpi_set_buffer (gcry_mpi_t a, const void *buffer_arg,
for (i=0, p = buffer+nbytes-1; p >= buffer+BYTES_PER_MPI_LIMB; )
{
#if BYTES_PER_MPI_LIMB == 4
- alimb = (mpi_limb_t)*p-- ;
- alimb |= (mpi_limb_t)*p-- << 8 ;
- alimb |= (mpi_limb_t)*p-- << 16 ;
- alimb |= (mpi_limb_t)*p-- << 24 ;
+ alimb = buf_get_be32(p - 4 + 1);
+ p -= 4;
#elif BYTES_PER_MPI_LIMB == 8
- alimb = (mpi_limb_t)*p-- ;
- alimb |= (mpi_limb_t)*p-- << 8 ;
- alimb |= (mpi_limb_t)*p-- << 16 ;
- alimb |= (mpi_limb_t)*p-- << 24 ;
- alimb |= (mpi_limb_t)*p-- << 32 ;
- alimb |= (mpi_limb_t)*p-- << 40 ;
- alimb |= (mpi_limb_t)*p-- << 48 ;
- alimb |= (mpi_limb_t)*p-- << 56 ;
+ alimb = buf_get_be64(p - 8 + 1);
+ p -= 8;
#else
-# error please implement for this limb size.
+# error please implement for this limb size.
#endif
a->d[i++] = alimb;
}
if ( p >= buffer )
{
+ byte last[BYTES_PER_MPI_LIMB] = { 0 };
+ unsigned int n = (p - buffer) + 1;
+
+ n = n > BYTES_PER_MPI_LIMB ? BYTES_PER_MPI_LIMB : n;
+ memcpy (last + BYTES_PER_MPI_LIMB - n, p - n + 1, n);
+ p -= n;
+
#if BYTES_PER_MPI_LIMB == 4
- alimb = (mpi_limb_t)*p--;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 8;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 16;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 24;
+ alimb = buf_get_be32(last);
#elif BYTES_PER_MPI_LIMB == 8
- alimb = (mpi_limb_t)*p--;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 8;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 16;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 24;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 32;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 40;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 48;
- if (p >= buffer)
- alimb |= (mpi_limb_t)*p-- << 56;
+ alimb = buf_get_be64(last);
#else
# error please implement for this limb size.
#endif
+
a->d[i++] = alimb;
}
a->nlimbs = i;
@@ -446,25 +509,24 @@ twocompl (unsigned char *p, unsigned int n)
;
if (i >= 0)
{
- if ((p[i] & 0x01))
- p[i] = (((p[i] ^ 0xfe) | 0x01) & 0xff);
- else if ((p[i] & 0x02))
- p[i] = (((p[i] ^ 0xfc) | 0x02) & 0xfe);
- else if ((p[i] & 0x04))
- p[i] = (((p[i] ^ 0xf8) | 0x04) & 0xfc);
- else if ((p[i] & 0x08))
- p[i] = (((p[i] ^ 0xf0) | 0x08) & 0xf8);
- else if ((p[i] & 0x10))
- p[i] = (((p[i] ^ 0xe0) | 0x10) & 0xf0);
- else if ((p[i] & 0x20))
- p[i] = (((p[i] ^ 0xc0) | 0x20) & 0xe0);
- else if ((p[i] & 0x40))
- p[i] = (((p[i] ^ 0x80) | 0x40) & 0xc0);
- else
- p[i] = 0x80;
+ unsigned char pi = p[i];
+ unsigned int ntz = _gcry_ctz (pi);
+
+ p[i] = ((p[i] ^ (0xfe << ntz)) | (0x01 << ntz)) & (0xff << ntz);

- for (i--; i >= 0; i--)
- p[i] ^= 0xff;
+ for (i--; i >= 7; i -= 8)
+ {
+ buf_put_he64(&p[i-7], ~buf_get_he64(&p[i-7]));
+ }
+ if (i >= 3)
+ {
+ buf_put_he32(&p[i-3], ~buf_get_he32(&p[i-3]));
+ i -= 4;
+ }
+ for (; i >= 0; i--)
+ {
+ p[i] ^= 0xff;
+ }
}
}

@@ -571,7 +633,7 @@ _gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
if (len && len < 4)
return GPG_ERR_TOO_SHORT;

- n = (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]);
+ n = buf_get_be32 (s);
s += 4;
if (len)
len -= 4;
@@ -605,12 +667,19 @@ _gcry_mpi_scan (struct gcry_mpi **ret_mpi, enum gcry_mpi_format format,
}
else if (format == GCRYMPI_FMT_HEX)
{
+ size_t slen;
/* We can only handle C strings for now. */
if (buflen)
return GPG_ERR_INV_ARG;

- a = secure? mpi_alloc_secure (0) : mpi_alloc(0);
- if (mpi_fromstr (a, (const char *)buffer))
+ slen = strlen ((const char *)buffer);
+ if (slen > MAX_EXTERN_SCAN_BYTES)
+ return GPG_ERR_INV_OBJ;
+ a = secure? mpi_alloc_secure ((((slen+1)/2)+BYTES_PER_MPI_LIMB-1)
+ /BYTES_PER_MPI_LIMB)
+ : mpi_alloc((((slen+1)/2)+BYTES_PER_MPI_LIMB-1)
+ /BYTES_PER_MPI_LIMB);
+ if (mpi_fromstr (a, (const char *)buffer, slen))
{
mpi_free (a);
return GPG_ERR_INV_OBJ;
@@ -798,10 +867,8 @@ _gcry_mpi_print (enum gcry_mpi_format format,
{
unsigned char *s = buffer;

- *s++ = n >> 24;
- *s++ = n >> 16;
- *s++ = n >> 8;
- *s++ = n;
+ buf_put_be32 (s, n);
+ s += 4;
if (extra == 1)
*s++ = 0;
else if (extra)
@@ -832,6 +899,11 @@ _gcry_mpi_print (enum gcry_mpi_format format,
}
if (buffer)
{
+ static const u32 nibble2hex[] =
+ {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
unsigned char *s = buffer;

if (negative)
@@ -842,13 +914,37 @@ _gcry_mpi_print (enum gcry_mpi_format format,
*s++ = '0';
}

- for (i=0; i < n; i++)
+ for (i = 0; i + 4 < n; i += 4)
+ {
+ u32 c = buf_get_be32(tmp + i);
+ u32 o1, o2;
+
+ o1 = nibble2hex[(c >> 28) & 0xF];
+ o1 <<= 8;
+ o1 |= nibble2hex[(c >> 24) & 0xF];
+ o1 <<= 8;
+ o1 |= nibble2hex[(c >> 20) & 0xF];
+ o1 <<= 8;
+ o1 |= nibble2hex[(c >> 16) & 0xF];
+
+ o2 = nibble2hex[(c >> 12) & 0xF];
+ o2 <<= 8;
+ o2 |= (u64)nibble2hex[(c >> 8) & 0xF];
+ o2 <<= 8;
+ o2 |= (u64)nibble2hex[(c >> 4) & 0xF];
+ o2 <<= 8;
+ o2 |= (u64)nibble2hex[(c >> 0) & 0xF];
+
+ buf_put_be32 (s + 0, o1);
+ buf_put_be32 (s + 4, o2);
+ s += 8;
+ }
+ for (; i < n; i++)
{
unsigned int c = tmp[i];

- *s++ = (c >> 4) < 10? '0'+(c>>4) : 'A'+(c>>4)-10 ;
- c &= 15;
- *s++ = c < 10? '0'+c : 'A'+c-10 ;
+ *s++ = nibble2hex[c >> 4];
+ *s++ = nibble2hex[c & 0xF];
}
*s++ = 0;
*nwritten = s - buffer;
diff --git a/tests/t-convert.c b/tests/t-convert.c
index 4450a9e3..d5d162b9 100644
--- a/tests/t-convert.c
+++ b/tests/t-convert.c
@@ -141,6 +141,7 @@ static void
check_formats (void)
{
static struct {
+ int have_value;
int value;
struct {
const char *hex;
@@ -154,136 +155,283 @@ check_formats (void)
const char *pgp;
} a;
} data[] = {
- { 0, { "00",
- 0, "",
- 4, "\x00\x00\x00\x00",
- 0, "",
- 2, "\x00\x00"}
- },
- { 1, { "01",
- 1, "\x01",
- 5, "\x00\x00\x00\x01\x01",
- 1, "\x01",
- 3, "\x00\x01\x01" }
- },
- { 2, { "02",
- 1, "\x02",
- 5, "\x00\x00\x00\x01\x02",
- 1, "\x02",
- 3, "\x00\x02\x02" }
- },
- { 127, { "7F",
- 1, "\x7f",
- 5, "\x00\x00\x00\x01\x7f",
- 1, "\x7f",
- 3, "\x00\x07\x7f" }
- },
- { 128, { "0080",
- 2, "\x00\x80",
- 6, "\x00\x00\x00\x02\x00\x80",
- 1, "\x80",
- 3, "\x00\x08\x80" }
- },
- { 129, { "0081",
- 2, "\x00\x81",
- 6, "\x00\x00\x00\x02\x00\x81",
- 1, "\x81",
- 3, "\x00\x08\x81" }
- },
- { 255, { "00FF",
- 2, "\x00\xff",
- 6, "\x00\x00\x00\x02\x00\xff",
- 1, "\xff",
- 3, "\x00\x08\xff" }
- },
- { 256, { "0100",
- 2, "\x01\x00",
- 6, "\x00\x00\x00\x02\x01\x00",
- 2, "\x01\x00",
- 4, "\x00\x09\x01\x00" }
- },
- { 257, { "0101",
- 2, "\x01\x01",
- 6, "\x00\x00\x00\x02\x01\x01",
- 2, "\x01\x01",
- 4, "\x00\x09\x01\x01" }
- },
- { -1, { "-01",
- 1, "\xff",
- 5, "\x00\x00\x00\x01\xff",
- 1,"\x01" }
- },
- { -2, { "-02",
- 1, "\xfe",
- 5, "\x00\x00\x00\x01\xfe",
- 1, "\x02" }
- },
- { -127, { "-7F",
- 1, "\x81",
- 5, "\x00\x00\x00\x01\x81",
- 1, "\x7f" }
- },
- { -128, { "-0080",
- 1, "\x80",
- 5, "\x00\x00\x00\x01\x80",
- 1, "\x80" }
- },
- { -129, { "-0081",
- 2, "\xff\x7f",
- 6, "\x00\x00\x00\x02\xff\x7f",
- 1, "\x81" }
- },
- { -255, { "-00FF",
- 2, "\xff\x01",
- 6, "\x00\x00\x00\x02\xff\x01",
- 1, "\xff" }
- },
- { -256, { "-0100",
- 2, "\xff\x00",
- 6, "\x00\x00\x00\x02\xff\x00",
- 2, "\x01\x00" }
- },
- { -257, { "-0101",
- 2, "\xfe\xff",
- 6, "\x00\x00\x00\x02\xfe\xff",
- 2, "\x01\x01" }
- },
- { 65535, { "00FFFF",
- 3, "\x00\xff\xff",
- 7, "\x00\x00\x00\x03\x00\xff\xff",
- 2, "\xff\xff",
- 4, "\x00\x10\xff\xff" }
- },
- { 65536, { "010000",
- 3, "\x01\00\x00",
- 7, "\x00\x00\x00\x03\x01\x00\x00",
- 3, "\x01\x00\x00",
- 5, "\x00\x11\x01\x00\x00 "}
- },
- { 65537, { "010001",
- 3, "\x01\00\x01",
- 7, "\x00\x00\x00\x03\x01\x00\x01",
- 3, "\x01\x00\x01",
- 5, "\x00\x11\x01\x00\x01" }
- },
- { -65537, { "-010001",
- 3, "\xfe\xff\xff",
- 7, "\x00\x00\x00\x03\xfe\xff\xff",
- 3, "\x01\x00\x01" }
- },
- { -65536, { "-010000",
- 3, "\xff\x00\x00",
- 7, "\x00\x00\x00\x03\xff\x00\x00",
- 3, "\x01\x00\x00" }
- },
- { -65535, { "-00FFFF",
- 3, "\xff\x00\x01",
- 7, "\x00\x00\x00\x03\xff\x00\x01",
- 2, "\xff\xff" }
+ {
+ 1, 0,
+ { "00",
+ 0, "",
+ 4, "\x00\x00\x00\x00",
+ 0, "",
+ 2, "\x00\x00" }
+ },
+ {
+ 1, 1,
+ { "01",
+ 1, "\x01",
+ 5, "\x00\x00\x00\x01\x01",
+ 1, "\x01",
+ 3, "\x00\x01\x01" }
+ },
+ {
+ 1, 2,
+ { "02",
+ 1, "\x02",
+ 5, "\x00\x00\x00\x01\x02",
+ 1, "\x02",
+ 3, "\x00\x02\x02" }
+ },
+ {
+ 1, 127,
+ { "7F",
+ 1, "\x7f",
+ 5, "\x00\x00\x00\x01\x7f",
+ 1, "\x7f",
+ 3, "\x00\x07\x7f" }
+ },
+ {
+ 1, 128,
+ { "0080",
+ 2, "\x00\x80",
+ 6, "\x00\x00\x00\x02\x00\x80",
+ 1, "\x80",
+ 3, "\x00\x08\x80" }
+ },
+ {
+ 1, 129,
+ { "0081",
+ 2, "\x00\x81",
+ 6, "\x00\x00\x00\x02\x00\x81",
+ 1, "\x81",
+ 3, "\x00\x08\x81" }
+ },
+ {
+ 1, 255,
+ { "00FF",
+ 2, "\x00\xff",
+ 6, "\x00\x00\x00\x02\x00\xff",
+ 1, "\xff",
+ 3, "\x00\x08\xff" }
+ },
+ {
+ 1, 256,
+ { "0100",
+ 2, "\x01\x00",
+ 6, "\x00\x00\x00\x02\x01\x00",
+ 2, "\x01\x00",
+ 4, "\x00\x09\x01\x00" }
+ },
+ {
+ 1, 257,
+ { "0101",
+ 2, "\x01\x01",
+ 6, "\x00\x00\x00\x02\x01\x01",
+ 2, "\x01\x01",
+ 4, "\x00\x09\x01\x01" }
+ },
+ {
+ 1, -1,
+ { "-01",
+ 1, "\xff",
+ 5, "\x00\x00\x00\x01\xff",
+ 1,"\x01" }
+ },
+ {
+ 1, -2,
+ { "-02",
+ 1, "\xfe",
+ 5, "\x00\x00\x00\x01\xfe",
+ 1, "\x02" }
+ },
+ {
+ 1, -127,
+ { "-7F",
+ 1, "\x81",
+ 5, "\x00\x00\x00\x01\x81",
+ 1, "\x7f" }
+ },
+ {
+ 1, -128,
+ { "-0080",
+ 1, "\x80",
+ 5, "\x00\x00\x00\x01\x80",
+ 1, "\x80" }
+ },
+ {
+ 1, -129,
+ { "-0081",
+ 2, "\xff\x7f",
+ 6, "\x00\x00\x00\x02\xff\x7f",
+ 1, "\x81" }
+ },
+ {
+ 1, -255,
+ { "-00FF",
+ 2, "\xff\x01",
+ 6, "\x00\x00\x00\x02\xff\x01",
+ 1, "\xff" }
+ },
+ {
+ 1, -256,
+ { "-0100",
+ 2, "\xff\x00",
+ 6, "\x00\x00\x00\x02\xff\x00",
+ 2, "\x01\x00" }
+ },
+ {
+ 1, -257,
+ { "-0101",
+ 2, "\xfe\xff",
+ 6, "\x00\x00\x00\x02\xfe\xff",
+ 2, "\x01\x01" }
+ },
+ {
+ 1, 65535,
+ { "00FFFF",
+ 3, "\x00\xff\xff",
+ 7, "\x00\x00\x00\x03\x00\xff\xff",
+ 2, "\xff\xff",
+ 4, "\x00\x10\xff\xff" }
+ },
+ {
+ 1, 65536,
+ { "010000",
+ 3, "\x01\00\x00",
+ 7, "\x00\x00\x00\x03\x01\x00\x00",
+ 3, "\x01\x00\x00",
+ 5, "\x00\x11\x01\x00\x00 "}
+ },
+ {
+ 1, 65537,
+ { "010001",
+ 3, "\x01\00\x01",
+ 7, "\x00\x00\x00\x03\x01\x00\x01",
+ 3, "\x01\x00\x01",
+ 5, "\x00\x11\x01\x00\x01" }
+ },
+ {
+ 1, -65537,
+ { "-010001",
+ 3, "\xfe\xff\xff",
+ 7, "\x00\x00\x00\x03\xfe\xff\xff",
+ 3, "\x01\x00\x01" }
+ },
+ {
+ 1, -65536,
+ { "-010000",
+ 3, "\xff\x00\x00",
+ 7, "\x00\x00\x00\x03\xff\x00\x00",
+ 3, "\x01\x00\x00" }
+ },
+ {
+ 1, -65535,
+ { "-00FFFF",
+ 3, "\xff\x00\x01",
+ 7, "\x00\x00\x00\x03\xff\x00\x01",
+ 2, "\xff\xff" }
+ },
+ {
+ 1, 0x7fffffff,
+ { "7FFFFFFF",
+ 4, "\x7f\xff\xff\xff",
+ 8, "\x00\x00\x00\x04\x7f\xff\xff\xff",
+ 4, "\x7f\xff\xff\xff",
+ 6, "\x00\x1f\x7f\xff\xff\xff" }
+ },
+ { 1, -0x7fffffff,
+ { "-7FFFFFFF",
+ 4, "\x80\x00\x00\x01",
+ 8, "\x00\x00\x00\x04\x80\x00\x00\x01",
+ 4, "\x7f\xff\xff\xff" }
+ },
+ {
+ 1, (int)0x800000ffU,
+ { "-7FFFFF01",
+ 4, "\x80\x00\x00\xff",
+ 8, "\x00\x00\x00\x04\x80\x00\x00\xff",
+ 4, "\x7f\xff\xff\x01" }
+ },
+ {
+ 1, (int)0x800000feU,
+ { "-7FFFFF02",
+ 4, "\x80\x00\x00\xfe",
+ 8, "\x00\x00\x00\x04\x80\x00\x00\xfe",
+ 4, "\x7f\xff\xff\x02" }
+ },
+ {
+ 1, (int)0x800000fcU,
+ { "-7FFFFF04",
+ 4, "\x80\x00\x00\xfc",
+ 8, "\x00\x00\x00\x04\x80\x00\x00\xfc",
+ 4, "\x7f\xff\xff\x04" }
+ },
+ {
+ 1, (int)0x800000f8U,
+ { "-7FFFFF08",
+ 4, "\x80\x00\x00\xf8",
+ 8, "\x00\x00\x00\x04\x80\x00\x00\xf8",
+ 4, "\x7f\xff\xff\x08" }
+ },
+ {
+ 1, (int)0x800000f0U,
+ { "-7FFFFF10",
+ 4, "\x80\x00\x00\xf0",
+ 8, "\x00\x00\x00\x04\x80\x00\x00\xf0",
+ 4, "\x7f\xff\xff\x10" }
+ },
+ {
+ 1, (int)0x800000e0U,
+ { "-7FFFFF20",
+ 4, "\x80\x00\x00\xe0",
+ 8, "\x00\x00\x00\x04\x80\x00\x00\xe0",
+ 4, "\x7f\xff\xff\x20" }
+ },
+ {
+ 1, (int)0x800000c0U,
+ { "-7FFFFF40",
+ 4, "\x80\x00\x00\xc0",
+ 8, "\x00\x00\x00\x04\x80\x00\x00\xc0",
+ 4, "\x7f\xff\xff\x40" }
+ },
+ {
+ 1, (int)0x80000080U,
+ { "-7FFFFF80",
+ 4, "\x80\x00\x00\x80",
+ 8, "\x00\x00\x00\x04\x80\x00\x00\x80",
+ 4, "\x7f\xff\xff\x80" }
+ },
+ {
+ 1, (int)0x80000100U,
+ { "-7FFFFF00",
+ 4, "\x80\x00\x01\x00",
+ 8, "\x00\x00\x00\x04\x80\x00\x01\x00",
+ 4, "\x7f\xff\xff\x00" }
+ },
+ {
+ 0, 0,
+ { "076543210FEDCBA9876543210123456789ABCDEF00112233",
+ 24, "\x07\x65\x43\x21\x0f\xed\xcb\xa9\x87\x65\x43\x21\x01\x23"
+ "\x45\x67\x89\xab\xcd\xef\x00\x11\x22\x33",
+ 28, "\x00\x00\x00\x18\x07\x65\x43\x21\x0f\xed\xcb\xa9\x87\x65"
+ "\x43\x21\x01\x23\x45\x67\x89\xab\xcd\xef\x00\x11\x22\x33"
+ "\x44",
+ 24, "\x07\x65\x43\x21\x0f\xed\xcb\xa9\x87\x65\x43\x21\x01\x23"
+ "\x45\x67\x89\xab\xcd\xef\x00\x11\x22\x33",
+ 26, "\x00\xbb\x07\x65\x43\x21\x0f\xed\xcb\xa9\x87\x65\x43\x21"
+ "\x01\x23\x45\x67\x89\xab\xcd\xef\x00\x11\x22\x33" }
+ },
+ {
+ 0, 0,
+ { "-07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01",
+ 24, "\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff",
+ 28, "\x00\x00\x00\x18\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff",
+ 24, "\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01" }
}
};
gpg_error_t err;
gcry_mpi_t a, b;
+ char valuestr[128];
char *buf;
void *bufaddr = &buf;
int idx;
@@ -295,24 +443,39 @@ check_formats (void)
if (debug)
info ("print test %d\n", data[idx].value);

- if (data[idx].value < 0)
- {
- gcry_mpi_set_ui (a, -data[idx].value);
- gcry_mpi_neg (a, a);
- }
+ if (data[idx].have_value)
+ {
+ snprintf(valuestr, sizeof(valuestr), "%d", data[idx].value);
+ if (data[idx].value < 0)
+ {
+ gcry_mpi_set_ui (a, -data[idx].value);
+ gcry_mpi_neg (a, a);
+ }
+ else
+ gcry_mpi_set_ui (a, data[idx].value);
+ }
else
- gcry_mpi_set_ui (a, data[idx].value);
+ {
+ /* Use hex-format as source test vector. */
+ snprintf(valuestr, sizeof(valuestr), "%s", data[idx].a.hex);
+ gcry_mpi_release (a);
+ err = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, data[idx].a.hex, 0,
+ &buflen);
+ if (err)
+ fail ("error scanning value %s from %s: %s\n",
+ valuestr, "HEX", gpg_strerror (err));
+ }

err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
if (err)
- fail ("error printing value %d as %s: %s\n",
- data[idx].value, "HEX", gpg_strerror (err));
+ fail ("error printing value %s as %s: %s\n",
+ valuestr, "HEX", gpg_strerror (err));
else
{
if (strcmp (buf, data[idx].a.hex))
{
- fail ("error printing value %d as %s: %s\n",
- data[idx].value, "HEX", "wrong result");
+ fail ("error printing value %s as %s: %s\n",
+ valuestr, "HEX", "wrong result");
info ("expected: '%s'\n", data[idx].a.hex);
info (" got: '%s'\n", buf);
}
@@ -321,15 +484,15 @@ check_formats (void)

err = gcry_mpi_aprint (GCRYMPI_FMT_STD, bufaddr, &buflen, a);
if (err)
- fail ("error printing value %d as %s: %s\n",
- data[idx].value, "STD", gpg_strerror (err));
+ fail ("error printing value %s as %s: %s\n",
+ valuestr, "STD", gpg_strerror (err));
else
{
if (buflen != data[idx].a.stdlen
|| memcmp (buf, data[idx].a.std, data[idx].a.stdlen))
{
- fail ("error printing value %d as %s: %s\n",
- data[idx].value, "STD", "wrong result");
+ fail ("error printing value %s as %s: %s\n",
+ valuestr, "STD", "wrong result");
showhex ("expected:", data[idx].a.std, data[idx].a.stdlen);
showhex (" got:", buf, buflen);
}
@@ -338,15 +501,15 @@ check_formats (void)

err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, bufaddr, &buflen, a);
if (err)
- fail ("error printing value %d as %s: %s\n",
- data[idx].value, "SSH", gpg_strerror (err));
+ fail ("error printing value %s as %s: %s\n",
+ valuestr, "SSH", gpg_strerror (err));
else
{
if (buflen != data[idx].a.sshlen
|| memcmp (buf, data[idx].a.ssh, data[idx].a.sshlen))
{
- fail ("error printing value %d as %s: %s\n",
- data[idx].value, "SSH", "wrong result");
+ fail ("error printing value %s as %s: %s\n",
+ valuestr, "SSH", "wrong result");
showhex ("expected:", data[idx].a.ssh, data[idx].a.sshlen);
showhex (" got:", buf, buflen);
}
@@ -355,15 +518,15 @@ check_formats (void)

err = gcry_mpi_aprint (GCRYMPI_FMT_USG, bufaddr, &buflen, a);
if (err)
- fail ("error printing value %d as %s: %s\n",
- data[idx].value, "USG", gpg_strerror (err));
+ fail ("error printing value %s as %s: %s\n",
+ valuestr, "USG", gpg_strerror (err));
else
{
if (buflen != data[idx].a.usglen
|| memcmp (buf, data[idx].a.usg, data[idx].a.usglen))
{
- fail ("error printing value %d as %s: %s\n",
- data[idx].value, "USG", "wrong result");
+ fail ("error printing value %s as %s: %s\n",
+ valuestr, "USG", "wrong result");
showhex ("expected:", data[idx].a.usg, data[idx].a.usglen);
showhex (" got:", buf, buflen);
}
@@ -374,19 +537,19 @@ check_formats (void)
if (gcry_mpi_is_neg (a))
{
if (gpg_err_code (err) != GPG_ERR_INV_ARG)
- fail ("error printing value %d as %s: %s\n",
- data[idx].value, "PGP", "Expected error not returned");
+ fail ("error printing value %s as %s: %s\n",
+ valuestr, "PGP", "Expected error not returned");
}
else if (err)
- fail ("error printing value %d as %s: %s\n",
- data[idx].value, "PGP", gpg_strerror (err));
+ fail ("error printing value %s as %s: %s\n",
+ valuestr, "PGP", gpg_strerror (err));
else
{
if (buflen != data[idx].a.pgplen
|| memcmp (buf, data[idx].a.pgp, data[idx].a.pgplen))
{
- fail ("error printing value %d as %s: %s\n",
- data[idx].value, "PGP", "wrong result");
+ fail ("error printing value %s as %s: %s\n",
+ valuestr, "PGP", "wrong result");
showhex ("expected:", data[idx].a.pgp, data[idx].a.pgplen);
showhex (" got:", buf, buflen);
}
@@ -401,24 +564,39 @@ check_formats (void)
if (debug)
info ("scan test %d\n", data[idx].value);

- if (data[idx].value < 0)
- {
- gcry_mpi_set_ui (a, -data[idx].value);
- gcry_mpi_neg (a, a);
- }
+ if (data[idx].have_value)
+ {
+ snprintf(valuestr, sizeof(valuestr), "%d", data[idx].value);
+ if (data[idx].value < 0)
+ {
+ gcry_mpi_set_ui (a, -data[idx].value);
+ gcry_mpi_neg (a, a);
+ }
+ else
+ gcry_mpi_set_ui (a, data[idx].value);
+ }
else
- gcry_mpi_set_ui (a, data[idx].value);
+ {
+ /* Use hex-format as source test vector. */
+ snprintf(valuestr, sizeof(valuestr), "%s", data[idx].a.hex);
+ gcry_mpi_release (a);
+ err = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, data[idx].a.hex, 0,
+ &buflen);
+ if (err)
+ fail ("error scanning value %s from %s: %s\n",
+ valuestr, "HEX", gpg_strerror (err));
+ }

err = gcry_mpi_scan (&b, GCRYMPI_FMT_HEX, data[idx].a.hex, 0, &buflen);
if (err)
- fail ("error scanning value %d from %s: %s\n",
- data[idx].value, "HEX", gpg_strerror (err));
+ fail ("error scanning value %s from %s: %s\n",
+ valuestr, "HEX", gpg_strerror (err));
else
{
if (gcry_mpi_cmp (a, b))
{
- fail ("error scanning value %d from %s: %s\n",
- data[idx].value, "HEX", "wrong result");
+ fail ("error scanning value %s from %s: %s\n",
+ valuestr, "HEX", "wrong result");
showmpi ("expected:", a);
showmpi (" got:", b);
}
@@ -428,14 +606,14 @@ check_formats (void)
err = gcry_mpi_scan (&b, GCRYMPI_FMT_STD,
data[idx].a.std, data[idx].a.stdlen, &buflen);
if (err)
- fail ("error scanning value %d as %s: %s\n",
- data[idx].value, "STD", gpg_strerror (err));
+ fail ("error scanning value %s as %s: %s\n",
+ valuestr, "STD", gpg_strerror (err));
else
{
if (gcry_mpi_cmp (a, b) || data[idx].a.stdlen != buflen)
{
- fail ("error scanning value %d from %s: %s (%lu)\n",
- data[idx].value, "STD", "wrong result",
+ fail ("error scanning value %s from %s: %s (%lu)\n",
+ valuestr, "STD", "wrong result",
(long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
@@ -446,14 +624,14 @@ check_formats (void)
err = gcry_mpi_scan (&b, GCRYMPI_FMT_SSH,
data[idx].a.ssh, data[idx].a.sshlen, &buflen);
if (err)
- fail ("error scanning value %d as %s: %s\n",
- data[idx].value, "SSH", gpg_strerror (err));
+ fail ("error scanning value %s as %s: %s\n",
+ valuestr, "SSH", gpg_strerror (err));
else
{
if (gcry_mpi_cmp (a, b) || data[idx].a.sshlen != buflen)
{
- fail ("error scanning value %d from %s: %s (%lu)\n",
- data[idx].value, "SSH", "wrong result",
+ fail ("error scanning value %s from %s: %s (%lu)\n",
+ valuestr, "SSH", "wrong result",
(long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
@@ -464,16 +642,16 @@ check_formats (void)
err = gcry_mpi_scan (&b, GCRYMPI_FMT_USG,
data[idx].a.usg, data[idx].a.usglen, &buflen);
if (err)
- fail ("error scanning value %d as %s: %s\n",
- data[idx].value, "USG", gpg_strerror (err));
+ fail ("error scanning value %s as %s: %s\n",
+ valuestr, "USG", gpg_strerror (err));
else
{
if (gcry_mpi_is_neg (a))
gcry_mpi_neg (b, b);
if (gcry_mpi_cmp (a, b) || data[idx].a.usglen != buflen)
{
- fail ("error scanning value %d from %s: %s (%lu)\n",
- data[idx].value, "USG", "wrong result",
+ fail ("error scanning value %s from %s: %s (%lu)\n",
+ valuestr, "USG", "wrong result",
(long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
@@ -488,14 +666,14 @@ check_formats (void)
err = gcry_mpi_scan (&b, GCRYMPI_FMT_PGP,
data[idx].a.pgp, data[idx].a.pgplen, &buflen);
if (err)
- fail ("error scanning value %d as %s: %s\n",
- data[idx].value, "PGP", gpg_strerror (err));
+ fail ("error scanning value %s as %s: %s\n",
+ valuestr, "PGP", gpg_strerror (err));
else
{
if (gcry_mpi_cmp (a, b) || data[idx].a.pgplen != buflen)
{
- fail ("error scanning value %d from %s: %s (%lu)\n",
- data[idx].value, "PGP", "wrong result",
+ fail ("error scanning value %s from %s: %s (%lu)\n",
+ valuestr, "PGP", "wrong result",
(long unsigned int)buflen);
showmpi ("expected:", a);
showmpi (" got:", b);
--
2.30.2


_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel