diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2016-02-01 00:02:05 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2016-02-02 17:17:38 +0000 |
commit | 85a4807f94580b9b666b3e24fff5752515470b1c (patch) | |
tree | e2e4f5242dcfe694575a1b003badc5b56e14f71e /crypto/bn | |
parent | 19f7130beb97170b8e825aee1ae9e309520f5f29 (diff) |
New BN functions.
Add new function BN_bn2binpad() which checks the length of the output
buffer and pads the result with zeroes if necessary.
New functions BN_bn2lebinpad() and BN_lebin2bn() which use little endian
format.
Reviewed-by: Rich Salz <rsalz@openssl.org>
Diffstat (limited to 'crypto/bn')
-rw-r--r-- | crypto/bn/bn_lib.c | 94 |
1 files changed, 90 insertions, 4 deletions
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index cd8b1dc3bf..dd07d19b07 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -575,18 +575,104 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) } /* ignore negative */ -int BN_bn2bin(const BIGNUM *a, unsigned char *to) +static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) { - int n, i; + int i; BN_ULONG l; bn_check_top(a); - n = i = BN_num_bytes(a); + i = BN_num_bytes(a); + if (tolen == -1) + tolen = i; + else if (tolen < i) + return -1; + /* Add leading zeroes if necessary */ + if (tolen > i) { + memset(to, 0, tolen - i); + to += tolen - i; + } while (i--) { l = a->d[i / BN_BYTES]; *(to++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff; } - return (n); + return tolen; +} + +int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + if (tolen < 0) + return -1; + return bn2binpad(a, to, tolen); +} + +int BN_bn2bin(const BIGNUM *a, unsigned char *to) +{ + return bn2binpad(a, to, -1); +} + +BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + unsigned int i, m; + unsigned int n; + BN_ULONG l; + BIGNUM *bn = NULL; + + if (ret == NULL) + ret = bn = BN_new(); + if (ret == NULL) + return (NULL); + bn_check_top(ret); + s += len - 1; + /* Skip trailing zeroes. */ + for ( ; len > 0 && *s == 0; s--, len--) + continue; + n = len; + if (n == 0) { + ret->top = 0; + return ret; + } + i = ((n - 1) / BN_BYTES) + 1; + m = ((n - 1) % (BN_BYTES)); + if (bn_wexpand(ret, (int)i) == NULL) { + BN_free(bn); + return NULL; + } + ret->top = i; + ret->neg = 0; + l = 0; + while (n--) { + l = (l << 8L) | *(s--); + if (m-- == 0) { + ret->d[--i] = l; + l = 0; + m = BN_BYTES - 1; + } + } + /* + * need to call this due to clear byte at top if avoiding having the top + * bit set (-ve number) + */ + bn_correct_top(ret); + return ret; +} + +int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + int i; + BN_ULONG l; + bn_check_top(a); + i = BN_num_bytes(a); + if (tolen < i) + return -1; + /* Add trailing zeroes if necessary */ + if (tolen > i) + memset(to + i, 0, tolen - i); + to += i - 1; + while (i--) { + l = a->d[i / BN_BYTES]; + *(to--) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff; + } + return tolen; } int BN_ucmp(const BIGNUM *a, const BIGNUM *b) |