Android currently implements this manually (see NativeBN_putULongInt) by reaching into BIGNUM's internals. BN_ULONG is a somewhat unfortunate API anyway as the size is platform-dependent, so add a platform-independent way to do this. The other things Android needs are going to need more work, but this one's easy. BUG=97 Change-Id: I4af4dc29f9845bdce0f0663c379b4b5d3e1dc46e Reviewed-on: https://boringssl-review.googlesource.com/11088 Commit-Queue: David Benjamin <davidben@google.com> Commit-Queue: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <agl@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>kris/onging/CECPQ3_patch15
@@ -266,6 +266,28 @@ int BN_set_word(BIGNUM *bn, BN_ULONG value) { | |||||
return 1; | return 1; | ||||
} | } | ||||
int BN_set_u64(BIGNUM *bn, uint64_t value) { | |||||
#if BN_BITS2 == 64 | |||||
return BN_set_word(bn, value); | |||||
#elif BN_BITS2 == 32 | |||||
if (value <= BN_MASK2) { | |||||
return BN_set_word(bn, (BN_ULONG)value); | |||||
} | |||||
if (bn_wexpand(bn, 2) == NULL) { | |||||
return 0; | |||||
} | |||||
bn->neg = 0; | |||||
bn->d[0] = (BN_ULONG)value; | |||||
bn->d[1] = (BN_ULONG)(value >> 32); | |||||
bn->top = 2; | |||||
return 1; | |||||
#else | |||||
#error "BN_BITS2 must be 32 or 64." | |||||
#endif | |||||
} | |||||
int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) { | int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) { | ||||
if (bn_wexpand(bn, num) == NULL) { | if (bn_wexpand(bn, num) == NULL) { | ||||
return 0; | return 0; | ||||
@@ -1437,6 +1437,33 @@ static bool TestBN2Dec() { | |||||
return true; | return true; | ||||
} | } | ||||
static bool TestBNSetU64() { | |||||
static const struct { | |||||
const char *hex; | |||||
uint64_t value; | |||||
} kU64Tests[] = { | |||||
{"0", UINT64_C(0x0)}, | |||||
{"1", UINT64_C(0x1)}, | |||||
{"ffffffff", UINT64_C(0xffffffff)}, | |||||
{"100000000", UINT64_C(0x100000000)}, | |||||
{"ffffffffffffffff", UINT64_C(0xffffffffffffffff)}, | |||||
}; | |||||
for (const auto& test : kU64Tests) { | |||||
bssl::UniquePtr<BIGNUM> bn(BN_new()), expected; | |||||
if (!bn || | |||||
!BN_set_u64(bn.get(), test.value) || | |||||
!HexToBIGNUM(&expected, test.hex) || | |||||
BN_cmp(bn.get(), expected.get()) != 0) { | |||||
fprintf(stderr, "BN_set_u64 test failed for 0x%s.\n", test.hex); | |||||
ERR_print_errors_fp(stderr); | |||||
return false; | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
int main(int argc, char *argv[]) { | int main(int argc, char *argv[]) { | ||||
CRYPTO_library_init(); | CRYPTO_library_init(); | ||||
@@ -1462,7 +1489,8 @@ int main(int argc, char *argv[]) { | |||||
!TestExpModZero() || | !TestExpModZero() || | ||||
!TestSmallPrime(ctx.get()) || | !TestSmallPrime(ctx.get()) || | ||||
!TestCmpWord() || | !TestCmpWord() || | ||||
!TestBN2Dec()) { | |||||
!TestBN2Dec() || | |||||
!TestBNSetU64()) { | |||||
return 1; | return 1; | ||||
} | } | ||||
@@ -221,6 +221,10 @@ OPENSSL_EXPORT int BN_one(BIGNUM *bn); | |||||
* allocation failure. */ | * allocation failure. */ | ||||
OPENSSL_EXPORT int BN_set_word(BIGNUM *bn, BN_ULONG value); | OPENSSL_EXPORT int BN_set_word(BIGNUM *bn, BN_ULONG value); | ||||
/* BN_set_u64 sets |bn| to |value|. It returns one on success or zero on | |||||
* allocation failure. */ | |||||
OPENSSL_EXPORT int BN_set_u64(BIGNUM *bn, uint64_t value); | |||||
/* BN_set_negative sets the sign of |bn|. */ | /* BN_set_negative sets the sign of |bn|. */ | ||||
OPENSSL_EXPORT void BN_set_negative(BIGNUM *bn, int sign); | OPENSSL_EXPORT void BN_set_negative(BIGNUM *bn, int sign); | ||||