1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License.
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License.
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
17abf945fb9ce99d8c2769ac5b2691b2732fa59887Elliott Hughes#define LOG_TAG "NativeBN"
18abf945fb9ce99d8c2769ac5b2691b2732fa59887Elliott Hughes
1999c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes#include "JNIHelp.h"
20e22935d3c7040c22b48d53bd18878844f381287cElliott Hughes#include "JniConstants.h"
2166e740b765384686ce87003608412e940ab5d489Elliott Hughes#include "JniException.h"
2299c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes#include "ScopedPrimitiveArray.h"
2305960876dff6a5b686821eed8f7ae7cef5af4f50Elliott Hughes#include "ScopedUtfChars.h"
2499c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes#include "jni.h"
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <openssl/bn.h>
2699c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes#include <openssl/crypto.h>
2799c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes#include <openssl/err.h>
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <stdio.h>
29b3aacde3d8af759ee4a7b395c636ea360547d92dIan Rogers#include <memory>
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
318383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley#if defined(OPENSSL_IS_BORINGSSL)
328383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley/* BoringSSL no longer exports |bn_check_top|. */
338383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langleystatic void bn_check_top(const BIGNUM* bn) {
348383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  /* This asserts that |bn->top| (which contains the number of elements of
358383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley   * |bn->d| that are valid) is minimal. In other words, that there aren't
368383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley   * superfluous zeros. */
378383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  if (bn != NULL && bn->top != 0 && bn->d[bn->top-1] == 0) {
388383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley    abort();
398383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  }
408383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley}
418383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley#endif
428383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley
4363710430c17f7c0a1e74b926cd21248fde8e9589Elliott Hughesstruct BN_CTX_Deleter {
4466e740b765384686ce87003608412e940ab5d489Elliott Hughes  void operator()(BN_CTX* p) const {
4566e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_CTX_free(p);
4666e740b765384686ce87003608412e940ab5d489Elliott Hughes  }
4763710430c17f7c0a1e74b926cd21248fde8e9589Elliott Hughes};
48b3aacde3d8af759ee4a7b395c636ea360547d92dIan Rogerstypedef std::unique_ptr<BN_CTX, BN_CTX_Deleter> Unique_BN_CTX;
4963710430c17f7c0a1e74b926cd21248fde8e9589Elliott Hughes
50a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic BIGNUM* toBigNum(jlong address) {
51a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return reinterpret_cast<BIGNUM*>(static_cast<uintptr_t>(address));
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
5466e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic bool throwExceptionIfNecessary(JNIEnv* env) {
5566e740b765384686ce87003608412e940ab5d489Elliott Hughes  long error = ERR_get_error();
5666e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (error == 0) {
5766e740b765384686ce87003608412e940ab5d489Elliott Hughes    return false;
5866e740b765384686ce87003608412e940ab5d489Elliott Hughes  }
5966e740b765384686ce87003608412e940ab5d489Elliott Hughes  char message[256];
6066e740b765384686ce87003608412e940ab5d489Elliott Hughes  ERR_error_string_n(error, message, sizeof(message));
6166e740b765384686ce87003608412e940ab5d489Elliott Hughes  int reason = ERR_GET_REASON(error);
6266e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (reason == BN_R_DIV_BY_ZERO) {
6366e740b765384686ce87003608412e940ab5d489Elliott Hughes    jniThrowException(env, "java/lang/ArithmeticException", "BigInteger division by zero");
6466e740b765384686ce87003608412e940ab5d489Elliott Hughes  } else if (reason == BN_R_NO_INVERSE) {
6566e740b765384686ce87003608412e940ab5d489Elliott Hughes    jniThrowException(env, "java/lang/ArithmeticException", "BigInteger not invertible");
6666e740b765384686ce87003608412e940ab5d489Elliott Hughes  } else if (reason == ERR_R_MALLOC_FAILURE) {
6766e740b765384686ce87003608412e940ab5d489Elliott Hughes    jniThrowOutOfMemoryError(env, message);
6866e740b765384686ce87003608412e940ab5d489Elliott Hughes  } else {
6966e740b765384686ce87003608412e940ab5d489Elliott Hughes    jniThrowException(env, "java/lang/ArithmeticException", message);
7066e740b765384686ce87003608412e940ab5d489Elliott Hughes  }
7166e740b765384686ce87003608412e940ab5d489Elliott Hughes  return true;
7266e740b765384686ce87003608412e940ab5d489Elliott Hughes}
73a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
74a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int isValidHandle(JNIEnv* env, jlong handle, const char* message) {
75a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (handle == 0) {
76a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    jniThrowNullPointerException(env, message);
77a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return JNI_FALSE;
78a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
79a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return JNI_TRUE;
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
82a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int oneValidHandle(JNIEnv* env, jlong a) {
83a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return isValidHandle(env, a, "Mandatory handle (first) passed as null");
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
86a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int twoValidHandles(JNIEnv* env, jlong a, jlong b) {
87a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a)) return JNI_FALSE;
88a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return isValidHandle(env, b, "Mandatory handle (second) passed as null");
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
91a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int threeValidHandles(JNIEnv* env, jlong a, jlong b, jlong c) {
92a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!twoValidHandles(env, a, b)) return JNI_FALSE;
93a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return isValidHandle(env, c, "Mandatory handle (third) passed as null");
94a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
95a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
96a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int fourValidHandles(JNIEnv* env, jlong a, jlong b, jlong c, jlong d) {
97a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!threeValidHandles(env, a, b, c)) return JNI_FALSE;
98a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return isValidHandle(env, d, "Mandatory handle (fourth) passed as null");
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
10166e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic jlong NativeBN_BN_new(JNIEnv* env, jclass) {
10266e740b765384686ce87003608412e940ab5d489Elliott Hughes  jlong result = static_cast<jlong>(reinterpret_cast<uintptr_t>(BN_new()));
10366e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
10466e740b765384686ce87003608412e940ab5d489Elliott Hughes  return result;
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
10733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhlerstatic jlong NativeBN_getNativeFinalizer(JNIEnv*, jclass) {
10833fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler  return static_cast<jlong>(reinterpret_cast<uintptr_t>(&BN_free));
10933fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler}
11033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler
111a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic void NativeBN_BN_free(JNIEnv* env, jclass, jlong a) {
112a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a)) return;
113a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BN_free(toBigNum(a));
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
116a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_BN_cmp(JNIEnv* env, jclass, jlong a, jlong b) {
117a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!twoValidHandles(env, a, b)) return 1;
118a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return BN_cmp(toBigNum(a), toBigNum(b));
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
12166e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_copy(JNIEnv* env, jclass, jlong to, jlong from) {
12266e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!twoValidHandles(env, to, from)) return;
12366e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_copy(toBigNum(to), toBigNum(from));
12466e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
127a961d0b42b313aae32f340d9bf7de18e638da2cbColin Crossstatic void NativeBN_putULongInt(JNIEnv* env, jclass, jlong a0, jlong java_dw, jboolean neg) {
1288383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  if (!oneValidHandle(env, a0)) return;
129a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross
1308383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  uint64_t dw = java_dw;
1318383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  BIGNUM* a = toBigNum(a0);
1328383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  int ok;
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1348383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  static_assert(sizeof(dw) == sizeof(BN_ULONG) ||
1358383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley                sizeof(dw) == 2*sizeof(BN_ULONG), "Unknown BN configuration");
1368383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley
1378383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  if (sizeof(dw) == sizeof(BN_ULONG)) {
1388383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley    ok = BN_set_word(a, dw);
1398383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  } else if (sizeof(dw) == 2 * sizeof(BN_ULONG)) {
1408383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley    ok = (bn_wexpand(a, 2) != NULL);
1418383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley    if (ok) {
142a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      a->d[0] = dw;
1438383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley      a->d[1] = dw >> 32;
1448383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley      a->top = 2;
14566e740b765384686ce87003608412e940ab5d489Elliott Hughes      bn_correct_top(a);
14666e740b765384686ce87003608412e940ab5d489Elliott Hughes    }
1478383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  }
1488383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley
1498383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  BN_set_negative(a, neg);
1508383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley
1518383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  if (!ok) {
1528383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley    throwExceptionIfNecessary(env);
1538383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  }
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
156a961d0b42b313aae32f340d9bf7de18e638da2cbColin Crossstatic void NativeBN_putLongInt(JNIEnv* env, jclass cls, jlong a, jlong dw) {
157a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (dw >= 0) {
15866e740b765384686ce87003608412e940ab5d489Elliott Hughes    NativeBN_putULongInt(env, cls, a, dw, JNI_FALSE);
159a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  } else {
16066e740b765384686ce87003608412e940ab5d489Elliott Hughes    NativeBN_putULongInt(env, cls, a, -dw, JNI_TRUE);
161a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
164a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_BN_dec2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
165a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return -1;
166a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedUtfChars chars(env, str);
167a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (chars.c_str() == NULL) {
168a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return -1;
169a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
170a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
17166e740b765384686ce87003608412e940ab5d489Elliott Hughes  int result = BN_dec2bn(&a, chars.c_str());
17266e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
17366e740b765384686ce87003608412e940ab5d489Elliott Hughes  return result;
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
176a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_BN_hex2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
177a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return -1;
178a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedUtfChars chars(env, str);
179a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (chars.c_str() == NULL) {
180a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return -1;
181a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
182a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
18366e740b765384686ce87003608412e940ab5d489Elliott Hughes  int result = BN_hex2bn(&a, chars.c_str());
18466e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
18566e740b765384686ce87003608412e940ab5d489Elliott Hughes  return result;
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18866e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, jlong ret) {
18966e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, ret)) return;
190a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedByteArrayRO bytes(env, arr);
191a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (bytes.get() == NULL) {
19266e740b765384686ce87003608412e940ab5d489Elliott Hughes    return;
193a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
19466e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, toBigNum(ret));
19566e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!throwExceptionIfNecessary(env) && neg) {
19666e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_set_negative(toBigNum(ret), true);
197a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
20199c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes * Note:
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This procedure directly writes the internal representation of BIGNUMs.
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * We do so as there is no direct interface based on Little Endian Integer Arrays.
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Also note that the same representation is used in the Cordoba Java Implementation of BigIntegers,
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        whereof certain functionality is still being used.
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
20766e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len, jboolean neg, jlong ret0) {
20866e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, ret0)) return;
209a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* ret = toBigNum(ret0);
210a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  bn_check_top(ret);
211a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (len > 0) {
212a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    ScopedIntArrayRO scopedArray(env, arr);
213a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    if (scopedArray.get() == NULL) {
21466e740b765384686ce87003608412e940ab5d489Elliott Hughes      return;
215a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    }
216a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#ifdef __LP64__
217a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    const int wlen = (len + 1) / 2;
218a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#else
219a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    const int wlen = len;
220a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#endif
221a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    const unsigned int* tmpInts = reinterpret_cast<const unsigned int*>(scopedArray.get());
222a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    if ((tmpInts != NULL) && (bn_wexpand(ret, wlen) != NULL)) {
223a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#ifdef __LP64__
224a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      if (len % 2) {
225a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross        ret->d[wlen - 1] = tmpInts[--len];
226a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      }
227a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      if (len > 0) {
228a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross        for (int i = len - 2; i >= 0; i -= 2) {
229a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross          ret->d[i/2] = ((unsigned long long)tmpInts[i+1] << 32) | tmpInts[i];
230a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross        }
231a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      }
232a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#else
233a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
234a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#endif
2356bc20cd8fc6784a75158d8f1db27802a12b28f94Serguei Katkov      ret->top = wlen;
236a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      ret->neg = neg;
237a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      // need to call this due to clear byte at top if avoiding
238a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      // having the top bit set (-ve number)
239a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      // Basically get rid of top zero ints:
240a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      bn_correct_top(ret);
241a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    } else {
24266e740b765384686ce87003608412e940ab5d489Elliott Hughes      throwExceptionIfNecessary(env);
24399c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes    }
244a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  } else { // (len = 0) means value = 0 and sign will be 0, too.
245a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    ret->top = 0;
246a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
250a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#ifdef __LP64__
251a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#define BYTES2ULONG(bytes, k) \
252a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    ((bytes[k + 7] & 0xffULL)       | (bytes[k + 6] & 0xffULL) <<  8 | (bytes[k + 5] & 0xffULL) << 16 | (bytes[k + 4] & 0xffULL) << 24 | \
253a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross     (bytes[k + 3] & 0xffULL) << 32 | (bytes[k + 2] & 0xffULL) << 40 | (bytes[k + 1] & 0xffULL) << 48 | (bytes[k + 0] & 0xffULL) << 56)
254a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#else
255a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#define BYTES2ULONG(bytes, k) \
256a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    ((bytes[k + 3] & 0xff) | (bytes[k + 2] & 0xff) << 8 | (bytes[k + 1] & 0xff) << 16 | (bytes[k + 0] & 0xff) << 24)
257a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#endif
25866e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void negBigEndianBytes2bn(JNIEnv*, jclass, const unsigned char* bytes, int bytesLen, jlong ret0) {
259a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* ret = toBigNum(ret0);
260a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
261a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  bn_check_top(ret);
262a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  // FIXME: assert bytesLen > 0
2638383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  int wLen = (bytesLen + sizeof(BN_ULONG) - 1) / sizeof(BN_ULONG);
264a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  int firstNonzeroDigit = -2;
265a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (bn_wexpand(ret, wLen) != NULL) {
266a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    BN_ULONG* d = ret->d;
267a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    BN_ULONG di;
268a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    ret->top = wLen;
2698383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley    int highBytes = bytesLen % sizeof(BN_ULONG);
270a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    int k = bytesLen;
271a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // Put bytes to the int array starting from the end of the byte array
272a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    int i = 0;
273a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    while (k > highBytes) {
2748383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley      k -= sizeof(BN_ULONG);
275a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      di = BYTES2ULONG(bytes, k);
276a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      if (di != 0) {
277a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        d[i] = -di;
278a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        firstNonzeroDigit = i;
279a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        i++;
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (k > highBytes) {
2818383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley          k -= sizeof(BN_ULONG);
282a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross          d[i] = ~BYTES2ULONG(bytes, k);
283a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes          i++;
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
285a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        break;
286a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      } else {
287a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        d[i] = 0;
288a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        i++;
289a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      }
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
291a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    if (highBytes != 0) {
292a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      di = -1;
293a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      // Put the first bytes in the highest element of the int array
294a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      if (firstNonzeroDigit != -2) {
295a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        for (k = 0; k < highBytes; k++) {
296a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes          di = (di << 8) | (bytes[k] & 0xFF);
297a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        }
298a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        d[i] = ~di;
299a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      } else {
300a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        for (k = 0; k < highBytes; k++) {
301a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes          di = (di << 8) | (bytes[k] & 0xFF);
302a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        }
303a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        d[i] = -di;
304a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      }
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
3061d6c936ab01da702aab6c7e578e2c74cdc90b8a4Kenny Root    // The top may have superfluous zeros, so fix it.
3071d6c936ab01da702aab6c7e578e2c74cdc90b8a4Kenny Root    bn_correct_top(ret);
308a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
309a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
310a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
31166e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, jlong ret0) {
31266e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, ret0)) return;
313a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* ret = toBigNum(ret0);
314a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
315a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedByteArrayRO bytes(env, arr);
316a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (bytes.get() == NULL) {
31766e740b765384686ce87003608412e940ab5d489Elliott Hughes    return;
318a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
319a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get());
320a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if ((bytes[0] & 0X80) == 0) { // Positive value!
321a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    //
322a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // We can use the existing BN implementation for unsigned big endian bytes:
323a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    //
32466e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_bin2bn(s, bytesLen, ret);
32566e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_set_negative(ret, false);
326a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  } else { // Negative value!
327a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    //
328a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // We need to apply two's complement:
329a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    //
33066e740b765384686ce87003608412e940ab5d489Elliott Hughes    negBigEndianBytes2bn(env, cls, s, bytesLen, ret0);
33166e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_set_negative(ret, true);
332a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
33366e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
334a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
335a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
336a961d0b42b313aae32f340d9bf7de18e638da2cbColin Crossstatic jlong NativeBN_longInt(JNIEnv* env, jclass, jlong a0) {
337a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return -1;
338a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross
339a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
340a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  bn_check_top(a);
341a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int wLen = a->top;
342a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (wLen == 0) {
343a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    return 0;
344a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  }
345a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross
346a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#ifdef __LP64__
347a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  jlong result = a->d[0];
348a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#else
349a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  jlong result = static_cast<jlong>(a->d[0]) & 0xffffffff;
350a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (wLen > 1) {
351a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    result |= static_cast<jlong>(a->d[1]) << 32;
352a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
353a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#endif
354a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  return a->neg ? -result : result;
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic char* leadingZerosTrimmed(char* s) {
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    char* p = s;
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (*p == '-') {
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        p++;
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while ((*p == '0') && (*(p + 1) != 0)) { p++; }
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        p--;
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        *p = '-';
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    } else {
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while ((*p == '0') && (*(p + 1) != 0)) { p++; }
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    return p;
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
370a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, jlong a) {
371a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a)) return NULL;
372a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  char* tmpStr = BN_bn2dec(toBigNum(a));
373a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (tmpStr == NULL) {
374a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
375a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
376a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  char* retStr = leadingZerosTrimmed(tmpStr);
377a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  jstring returnJString = env->NewStringUTF(retStr);
378a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  OPENSSL_free(tmpStr);
379a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return returnJString;
380a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
381a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
382a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, jlong a) {
383a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a)) return NULL;
384a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  char* tmpStr = BN_bn2hex(toBigNum(a));
385a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (tmpStr == NULL) {
386a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
387a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
388a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  char* retStr = leadingZerosTrimmed(tmpStr);
389a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  jstring returnJString = env->NewStringUTF(retStr);
390a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  OPENSSL_free(tmpStr);
391a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return returnJString;
392a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
393a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
394a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, jlong a0) {
395a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return NULL;
396a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
397a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  jbyteArray result = env->NewByteArray(BN_num_bytes(a));
398a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (result == NULL) {
399a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
400a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
401a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedByteArrayRW bytes(env, result);
402a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (bytes.get() == NULL) {
403a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
404a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
405a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
406a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return result;
407a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
408a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
409a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, jlong a0) {
410a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return NULL;
411a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
412a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  bn_check_top(a);
413a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int wLen = a->top;
414a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (wLen == 0) {
415a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
416a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
4178383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  jintArray result = env->NewIntArray(wLen * sizeof(BN_ULONG)/sizeof(unsigned int));
418a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (result == NULL) {
419a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
420a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
421a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedIntArrayRW ints(env, result);
422a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (ints.get() == NULL) {
423a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
424a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
425a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  unsigned int* uints = reinterpret_cast<unsigned int*>(ints.get());
426a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (uints == NULL) {
427a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
428a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
429a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#ifdef __LP64__
430a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int i = wLen; do { i--; uints[i*2+1] = a->d[i] >> 32; uints[i*2] = a->d[i]; } while (i > 0);
431a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#else
432a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int i = wLen; do { i--; uints[i] = a->d[i]; } while (i > 0);
433a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#endif
434a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return result;
435a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
436a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
437a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_sign(JNIEnv* env, jclass, jlong a) {
438a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a)) return -2;
439a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (BN_is_zero(toBigNum(a))) {
440a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      return 0;
441a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  } else if (BN_is_negative(toBigNum(a))) {
442a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return -1;
443a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
444a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return 1;
445a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
446a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
447a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic void NativeBN_BN_set_negative(JNIEnv* env, jclass, jlong b, int n) {
448a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, b)) return;
449a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BN_set_negative(toBigNum(b), n);
450a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
451a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
452a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_bitLength(JNIEnv* env, jclass, jlong a0) {
453a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return JNI_FALSE;
454a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
455a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  bn_check_top(a);
456a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int wLen = a->top;
457a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (wLen == 0) return 0;
458a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BN_ULONG* d = a->d;
459a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int i = wLen - 1;
460a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BN_ULONG msd = d[i]; // most significant digit
461a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (a->neg) {
462a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // Handle negative values correctly:
463a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // i.e. decrement the msd if all other digits are 0:
464a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // while ((i > 0) && (d[i] != 0)) { i--; }
465a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    do { i--; } while (!((i < 0) || (d[i] != 0)));
466a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
467a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
4688383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  return (wLen - 1) * sizeof(BN_ULONG) * 8 + BN_num_bits_word(msd);
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
471a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, jlong a, int n) {
472a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a)) return JNI_FALSE;
473a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return BN_is_bit_set(toBigNum(a), n);
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
47666e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_shift(JNIEnv* env, jclass, jlong r, jlong a, int n) {
47766e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!twoValidHandles(env, r, a)) return;
47866e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (n >= 0) {
47966e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_lshift(toBigNum(r), toBigNum(a), n);
48066e740b765384686ce87003608412e940ab5d489Elliott Hughes  } else {
48166e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_rshift(toBigNum(r), toBigNum(a), -n);
48266e740b765384686ce87003608412e940ab5d489Elliott Hughes  }
48366e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
48666e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_add_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
48766e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, a)) return;
48866e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_add_word(toBigNum(a), w);
48966e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
49266e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mul_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
49366e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, a)) return;
49466e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_mul_word(toBigNum(a), w);
49566e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
498a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
49966e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, a)) return 0;
50066e740b765384686ce87003608412e940ab5d489Elliott Hughes  int result = BN_mod_word(toBigNum(a), w);
50166e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
50266e740b765384686ce87003608412e940ab5d489Elliott Hughes  return result;
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
50566e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_add(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
50666e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, b)) return;
50766e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_add(toBigNum(r), toBigNum(a), toBigNum(b));
50866e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
51166e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_sub(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
51266e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, b)) return;
51366e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_sub(toBigNum(r), toBigNum(a), toBigNum(b));
51466e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
51766e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_gcd(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
51866e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, b)) return;
519a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
52066e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_gcd(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
52166e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
52466e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mul(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
52566e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, b)) return;
526a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
52766e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_mul(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
52866e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
53166e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p) {
53266e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, p)) return;
533a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
53466e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_exp(toBigNum(r), toBigNum(a), toBigNum(p), ctx.get());
53566e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
53866e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_div(JNIEnv* env, jclass, jlong dv, jlong rem, jlong m, jlong d) {
53966e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return;
540a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
54166e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_div(toBigNum(dv), toBigNum(rem), toBigNum(m), toBigNum(d), ctx.get());
54266e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
54566e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_nnmod(JNIEnv* env, jclass, jlong r, jlong a, jlong m) {
54666e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, m)) return;
547a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
54866e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_nnmod(toBigNum(r), toBigNum(a), toBigNum(m), ctx.get());
54966e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
55266e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mod_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p, jlong m) {
55366e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!fourValidHandles(env, r, a, p, m)) return;
554a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
55566e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_mod_exp(toBigNum(r), toBigNum(a), toBigNum(p), toBigNum(m), ctx.get());
55666e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
55966e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mod_inverse(JNIEnv* env, jclass, jlong ret, jlong a, jlong n) {
56066e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, ret, a, n)) return;
561a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
56266e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_mod_inverse(toBigNum(ret), toBigNum(a), toBigNum(n), ctx.get());
56366e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
56666e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, jlong ret, int bits,
56766e740b765384686ce87003608412e940ab5d489Elliott Hughes                                          jboolean safe, jlong add, jlong rem, jlong cb) {
56866e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, ret)) return;
56966e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_generate_prime_ex(toBigNum(ret), bits, safe, toBigNum(add), toBigNum(rem),
57066e740b765384686ce87003608412e940ab5d489Elliott Hughes                       reinterpret_cast<BN_GENCB*>(cb));
57166e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
5740a08bbe70ef43ed29cba241e95aa5c338349b021Chris Dearmanstatic jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, jlong p, int nchecks, jlong cb) {
575a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, p)) return JNI_FALSE;
576a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
5770a08bbe70ef43ed29cba241e95aa5c338349b021Chris Dearman  return BN_is_prime_ex(toBigNum(p), nchecks, ctx.get(), reinterpret_cast<BN_GENCB*>(cb));
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
58063710430c17f7c0a1e74b926cd21248fde8e9589Elliott Hughesstatic JNINativeMethod gMethods[] = {
58166e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_add, "(JJJ)V"),
58266e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_add_word, "(JI)V"),
58366e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZJ)V"),
584a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_bn2bin, "(J)[B"),
585a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_bn2dec, "(J)Ljava/lang/String;"),
586a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_bn2hex, "(J)Ljava/lang/String;"),
587a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_cmp, "(JJ)I"),
58866e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_copy, "(JJ)V"),
589a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_dec2bn, "(JLjava/lang/String;)I"),
59066e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_div, "(JJJJ)V"),
59166e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_exp, "(JJJ)V"),
592a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_free, "(J)V"),
59366e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_gcd, "(JJJ)V"),
59466e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(JIZJJJ)V"),
595a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_hex2bn, "(JLjava/lang/String;)I"),
596a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_is_bit_set, "(JI)Z"),
597a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_is_prime_ex, "(JIJ)Z"),
59866e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_mod_exp, "(JJJJ)V"),
59966e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_mod_inverse, "(JJJ)V"),
600a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_mod_word, "(JI)I"),
60166e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_mul, "(JJJ)V"),
60266e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_mul_word, "(JI)V"),
603a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_new, "()J"),
60466e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_nnmod, "(JJJ)V"),
605a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_set_negative, "(JI)V"),
60666e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_shift, "(JJI)V"),
60766e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_sub, "(JJJ)V"),
608a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, bitLength, "(J)I"),
609a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, bn2litEndInts, "(J)[I"),
61033fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler   NATIVE_METHOD(NativeBN, getNativeFinalizer, "()J"),
61166e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZJ)V"),
612a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, longInt, "(J)J"),
61366e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, putLongInt, "(JJ)V"),
61466e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, putULongInt, "(JJZ)V"),
615a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, sign, "(J)I"),
61666e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, twosComp2bn, "([BIJ)V"),
617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project};
6187cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_java_math_NativeBN(JNIEnv* env) {
6197cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes    jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
621