Commit 43152353 authored by Niels Möller's avatar Niels Möller

(nettle_mpz_sizeinbase_256_s): New function.

(nettle_mpz_sizeinbase_256_u): New name, was
nettle_mpz_sizeinbase_256.
(nettle_mpz_to_octets): New function.
(nettle_mpz_get_str_256): Handle negative numbers.
(nettle_mpz_from_octets): New function.
(nettle_mpz_set_str_256_u): New name, was nettle_mpz_set_str_256.
(nettle_mpz_init_set_str_256_u): New name, was
nettle_mpz_init_set_str_256.
(nettle_mpz_set_str_256_s): New function, handling negative two's
complement numbers.
(nettle_mpz_init_set_str_256_s): And an init variant.

Rev: src/nettle/bignum.c:1.5
Rev: src/nettle/bignum.h:1.6
parent 52c695ff
......@@ -34,29 +34,54 @@
#include <assert.h>
#include <string.h>
/* Two's complement negation means that -x = ~x + 1, ~x = -(x+1),
* and we use that x = ~~x = ~(-x-1).
*
* Examples:
*
* x ~x = -x+1 ~~x = x
* -1 0 ff
* -2 1 fe
* -7f 7e 81
* -80 7f 80
* -81 80 ff7f
*/
/* Including extra sign bit, if needed. Also one byte for zero. */
unsigned
nettle_mpz_sizeinbase_256(const mpz_t x)
nettle_mpz_sizeinbase_256_s(const mpz_t x)
{
return (mpz_sizeinbase(x, 2) + 7) / 8;
if (mpz_sgn(x) >= 0)
return 1 + mpz_sizeinbase(x, 2) / 8;
else
{
/* We'll output ~~x, so we need as many bits as for ~x */
unsigned size;
mpz_t c;
mpz_init(c);
mpz_com(c, x); /* Same as c = - x - 1 = |x| + 1 */
size = 1 + mpz_sizeinbase(c,2) / 8;
mpz_clear(c);
return size;
}
}
void
nettle_mpz_get_str_256(unsigned length, uint8_t *s, const mpz_t x)
unsigned
nettle_mpz_sizeinbase_256_u(const mpz_t x)
{
return (mpz_sizeinbase(x,2) + 7) / 8;
}
static void
nettle_mpz_to_octets(unsigned length, uint8_t *s,
const mpz_t x, uint8_t sign)
{
uint8_t *dst = s + length - 1;
unsigned size = mpz_size(x);
unsigned i;
if (!length)
{
/* x must be zero */
assert(!mpz_sgn(x));
return;
}
assert(mpz_sgn(x) >= 0);
assert(nettle_mpz_sizeinbase_256(x) <= length);
for (i = 0; i<size; i++)
{
mp_limb_t limb = mpz_getlimbn(x, i);
......@@ -64,28 +89,58 @@ nettle_mpz_get_str_256(unsigned length, uint8_t *s, const mpz_t x)
for (j = 0; length && j < sizeof(mp_limb_t); j++)
{
*dst-- = limb & 0xff;
*dst-- = sign ^ (limb & 0xff);
limb >>= 8;
length--;
}
}
if (length)
memset(s, 0, length);
memset(s, sign, length);
}
void
nettle_mpz_set_str_256(mpz_t x,
unsigned length, const uint8_t *s)
nettle_mpz_get_str_256(unsigned length, uint8_t *s, const mpz_t x)
{
if (!length)
{
/* x must be zero */
assert(!mpz_sgn(x));
return;
}
if (mpz_sgn(x) >= 0)
{
assert(nettle_mpz_sizeinbase_256_u(x) <= length);
nettle_mpz_to_octets(length, s, x, 0);
}
else
{
mpz_t c;
mpz_init(c);
mpz_com(c, x);
assert(nettle_mpz_sizeinbase_256_u(c) <= length);
nettle_mpz_to_octets(length, s, c, 0xff);
mpz_clear(c);
}
}
/* Converting from strings */
static void
nettle_mpz_from_octets(mpz_t x,
unsigned length, const uint8_t *s,
uint8_t sign)
{
size_t i;
unsigned i;
mpz_t digit;
mpz_init(digit);
mpz_set_ui(x, 0);
for (i = 0; i < length; i++)
{
mpz_set_ui(digit, s[i]);
mpz_set_ui(digit, sign ^ s[i]);
mpz_mul_2exp(digit, digit, (length - i - 1) * 8);
mpz_ior(x, x, digit);
}
......@@ -93,11 +148,45 @@ nettle_mpz_set_str_256(mpz_t x,
}
void
nettle_mpz_init_set_str_256(mpz_t x,
unsigned length, const uint8_t *s)
nettle_mpz_set_str_256_u(mpz_t x,
unsigned length, const uint8_t *s)
{
mpz_set_ui(x, 0);
nettle_mpz_from_octets(x, length, s, 0);
}
void
nettle_mpz_init_set_str_256_u(mpz_t x,
unsigned length, const uint8_t *s)
{
mpz_init_set_ui(x, 0);
nettle_mpz_from_octets(x, length, s, 0);
}
void
nettle_mpz_set_str_256_s(mpz_t x,
unsigned length, const uint8_t *s)
{
mpz_set_ui(x, 0);
if (!length)
return;
if (s[0] & 0x80)
{
nettle_mpz_from_octets(x, length, s, 0xff);
mpz_com(x, x);
}
else
nettle_mpz_from_octets(x, length, s, 0);
}
void
nettle_mpz_init_set_str_256_s(mpz_t x,
unsigned length, const uint8_t *s)
{
mpz_init(x);
nettle_mpz_set_str_256(x, length, s);
nettle_mpz_set_str_256_s(x, length, s);
}
#endif /* HAVE_LIBGMP */
......@@ -31,21 +31,39 @@
#include <gmp.h>
#include <inttypes.h>
/* Size needed for signed encoding, including extra sign byte if
* necessary. */
unsigned
nettle_mpz_sizeinbase_256(const mpz_t x);
nettle_mpz_sizeinbase_256_s(const mpz_t x);
/* Writes an unsigned integer as length octets, using big endian byte
* order. */
/* Size needed for unsigned encoding */
unsigned
nettle_mpz_sizeinbase_256_u(const mpz_t x);
/* Writes an integer as length octets, using big endian byte order,
* and two's complement for negative numbers. */
/* FIXME: Change order of arguments, putting the mpz_t first? */
void
nettle_mpz_get_str_256(unsigned length, uint8_t *s, const mpz_t x);
/* Reads a big endian, two's complement, integer. */
void
nettle_mpz_set_str_256_s(mpz_t x,
unsigned length, const uint8_t *s);
void
nettle_mpz_init_set_str_256_s(mpz_t x,
unsigned length, const uint8_t *s);
/* Similar, but for unsigned format. These function don't interpret
* the most significant bit as the sign. */
void
nettle_mpz_set_str_256(mpz_t x,
unsigned length, const uint8_t *s);
nettle_mpz_set_str_256_u(mpz_t x,
unsigned length, const uint8_t *s);
void
nettle_mpz_init_set_str_256(mpz_t x,
unsigned length, const uint8_t *s);
nettle_mpz_init_set_str_256_u(mpz_t x,
unsigned length, const uint8_t *s);
/* Returns a uniformly distributed random number 0 <= x < 2^n */
void
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment