java_math_NativeBN.cpp revision 8383f343119f7a98cbe3b4a5bddc89038ac5c166
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"
2463710430c17f7c0a1e74b926cd21248fde8e9589Elliott Hughes#include "UniquePtr.h"
2599c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes#include "jni.h"
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <openssl/bn.h>
2799c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes#include <openssl/crypto.h>
2899c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes#include <openssl/err.h>
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project#include <stdio.h>
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};
4863710430c17f7c0a1e74b926cd21248fde8e9589Elliott Hughestypedef UniquePtr<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
107a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic void NativeBN_BN_free(JNIEnv* env, jclass, jlong a) {
108a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a)) return;
109a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BN_free(toBigNum(a));
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
112a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_BN_cmp(JNIEnv* env, jclass, jlong a, jlong b) {
113a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!twoValidHandles(env, a, b)) return 1;
114a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return BN_cmp(toBigNum(a), toBigNum(b));
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
11766e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_copy(JNIEnv* env, jclass, jlong to, jlong from) {
11866e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!twoValidHandles(env, to, from)) return;
11966e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_copy(toBigNum(to), toBigNum(from));
12066e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
123a961d0b42b313aae32f340d9bf7de18e638da2cbColin Crossstatic void NativeBN_putULongInt(JNIEnv* env, jclass, jlong a0, jlong java_dw, jboolean neg) {
1248383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  if (!oneValidHandle(env, a0)) return;
125a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross
1268383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  uint64_t dw = java_dw;
1278383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  BIGNUM* a = toBigNum(a0);
1288383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  int ok;
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1308383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  static_assert(sizeof(dw) == sizeof(BN_ULONG) ||
1318383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley                sizeof(dw) == 2*sizeof(BN_ULONG), "Unknown BN configuration");
1328383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley
1338383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  if (sizeof(dw) == sizeof(BN_ULONG)) {
1348383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley    ok = BN_set_word(a, dw);
1358383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  } else if (sizeof(dw) == 2 * sizeof(BN_ULONG)) {
1368383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley    ok = (bn_wexpand(a, 2) != NULL);
1378383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley    if (ok) {
138a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      a->d[0] = dw;
1398383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley      a->d[1] = dw >> 32;
1408383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley      a->top = 2;
14166e740b765384686ce87003608412e940ab5d489Elliott Hughes      bn_correct_top(a);
14266e740b765384686ce87003608412e940ab5d489Elliott Hughes    }
1438383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  }
1448383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley
1458383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  BN_set_negative(a, neg);
1468383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley
1478383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  if (!ok) {
1488383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley    throwExceptionIfNecessary(env);
1498383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  }
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
152a961d0b42b313aae32f340d9bf7de18e638da2cbColin Crossstatic void NativeBN_putLongInt(JNIEnv* env, jclass cls, jlong a, jlong dw) {
153a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (dw >= 0) {
15466e740b765384686ce87003608412e940ab5d489Elliott Hughes    NativeBN_putULongInt(env, cls, a, dw, JNI_FALSE);
155a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  } else {
15666e740b765384686ce87003608412e940ab5d489Elliott Hughes    NativeBN_putULongInt(env, cls, a, -dw, JNI_TRUE);
157a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
160a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_BN_dec2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
161a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return -1;
162a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedUtfChars chars(env, str);
163a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (chars.c_str() == NULL) {
164a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return -1;
165a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
166a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
16766e740b765384686ce87003608412e940ab5d489Elliott Hughes  int result = BN_dec2bn(&a, chars.c_str());
16866e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
16966e740b765384686ce87003608412e940ab5d489Elliott Hughes  return result;
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
172a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_BN_hex2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
173a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return -1;
174a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedUtfChars chars(env, str);
175a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (chars.c_str() == NULL) {
176a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return -1;
177a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
178a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
17966e740b765384686ce87003608412e940ab5d489Elliott Hughes  int result = BN_hex2bn(&a, chars.c_str());
18066e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
18166e740b765384686ce87003608412e940ab5d489Elliott Hughes  return result;
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18466e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, jlong ret) {
18566e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, ret)) return;
186a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedByteArrayRO bytes(env, arr);
187a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (bytes.get() == NULL) {
18866e740b765384686ce87003608412e940ab5d489Elliott Hughes    return;
189a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
19066e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, toBigNum(ret));
19166e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!throwExceptionIfNecessary(env) && neg) {
19266e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_set_negative(toBigNum(ret), true);
193a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
19799c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes * Note:
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This procedure directly writes the internal representation of BIGNUMs.
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * We do so as there is no direct interface based on Little Endian Integer Arrays.
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Also note that the same representation is used in the Cordoba Java Implementation of BigIntegers,
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        whereof certain functionality is still being used.
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
20366e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len, jboolean neg, jlong ret0) {
20466e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, ret0)) return;
205a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* ret = toBigNum(ret0);
206a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  bn_check_top(ret);
207a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (len > 0) {
208a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    ScopedIntArrayRO scopedArray(env, arr);
209a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    if (scopedArray.get() == NULL) {
21066e740b765384686ce87003608412e940ab5d489Elliott Hughes      return;
211a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    }
212a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#ifdef __LP64__
213a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    const int wlen = (len + 1) / 2;
214a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#else
215a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    const int wlen = len;
216a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#endif
217a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    const unsigned int* tmpInts = reinterpret_cast<const unsigned int*>(scopedArray.get());
218a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    if ((tmpInts != NULL) && (bn_wexpand(ret, wlen) != NULL)) {
219a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#ifdef __LP64__
220a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      if (len % 2) {
221a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross        ret->d[wlen - 1] = tmpInts[--len];
222a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      }
223a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      if (len > 0) {
224a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross        for (int i = len - 2; i >= 0; i -= 2) {
225a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross          ret->d[i/2] = ((unsigned long long)tmpInts[i+1] << 32) | tmpInts[i];
226a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross        }
227a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      }
228a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#else
229a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
230a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#endif
2316bc20cd8fc6784a75158d8f1db27802a12b28f94Serguei Katkov      ret->top = wlen;
232a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      ret->neg = neg;
233a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      // need to call this due to clear byte at top if avoiding
234a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      // having the top bit set (-ve number)
235a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      // Basically get rid of top zero ints:
236a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      bn_correct_top(ret);
237a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    } else {
23866e740b765384686ce87003608412e940ab5d489Elliott Hughes      throwExceptionIfNecessary(env);
23999c59bfa432e36933a7a5033fba8b89209f737bcElliott Hughes    }
240a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  } else { // (len = 0) means value = 0 and sign will be 0, too.
241a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    ret->top = 0;
242a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
246a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#ifdef __LP64__
247a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#define BYTES2ULONG(bytes, k) \
248a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    ((bytes[k + 7] & 0xffULL)       | (bytes[k + 6] & 0xffULL) <<  8 | (bytes[k + 5] & 0xffULL) << 16 | (bytes[k + 4] & 0xffULL) << 24 | \
249a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross     (bytes[k + 3] & 0xffULL) << 32 | (bytes[k + 2] & 0xffULL) << 40 | (bytes[k + 1] & 0xffULL) << 48 | (bytes[k + 0] & 0xffULL) << 56)
250a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#else
251a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#define BYTES2ULONG(bytes, k) \
252a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    ((bytes[k + 3] & 0xff) | (bytes[k + 2] & 0xff) << 8 | (bytes[k + 1] & 0xff) << 16 | (bytes[k + 0] & 0xff) << 24)
253a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#endif
25466e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void negBigEndianBytes2bn(JNIEnv*, jclass, const unsigned char* bytes, int bytesLen, jlong ret0) {
255a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* ret = toBigNum(ret0);
256a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
257a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  bn_check_top(ret);
258a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  // FIXME: assert bytesLen > 0
2598383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  int wLen = (bytesLen + sizeof(BN_ULONG) - 1) / sizeof(BN_ULONG);
260a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  int firstNonzeroDigit = -2;
261a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (bn_wexpand(ret, wLen) != NULL) {
262a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    BN_ULONG* d = ret->d;
263a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    BN_ULONG di;
264a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    ret->top = wLen;
2658383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley    int highBytes = bytesLen % sizeof(BN_ULONG);
266a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    int k = bytesLen;
267a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // Put bytes to the int array starting from the end of the byte array
268a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    int i = 0;
269a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    while (k > highBytes) {
2708383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley      k -= sizeof(BN_ULONG);
271a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross      di = BYTES2ULONG(bytes, k);
272a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      if (di != 0) {
273a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        d[i] = -di;
274a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        firstNonzeroDigit = i;
275a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        i++;
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (k > highBytes) {
2778383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley          k -= sizeof(BN_ULONG);
278a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross          d[i] = ~BYTES2ULONG(bytes, k);
279a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes          i++;
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
281a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        break;
282a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      } else {
283a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        d[i] = 0;
284a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        i++;
285a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      }
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
287a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    if (highBytes != 0) {
288a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      di = -1;
289a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      // Put the first bytes in the highest element of the int array
290a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      if (firstNonzeroDigit != -2) {
291a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        for (k = 0; k < highBytes; k++) {
292a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes          di = (di << 8) | (bytes[k] & 0xFF);
293a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        }
294a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        d[i] = ~di;
295a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      } else {
296a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        for (k = 0; k < highBytes; k++) {
297a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes          di = (di << 8) | (bytes[k] & 0xFF);
298a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        }
299a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes        d[i] = -di;
300a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      }
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
3021d6c936ab01da702aab6c7e578e2c74cdc90b8a4Kenny Root    // The top may have superfluous zeros, so fix it.
3031d6c936ab01da702aab6c7e578e2c74cdc90b8a4Kenny Root    bn_correct_top(ret);
304a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
305a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
306a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
30766e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, jlong ret0) {
30866e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, ret0)) return;
309a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* ret = toBigNum(ret0);
310a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
311a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedByteArrayRO bytes(env, arr);
312a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (bytes.get() == NULL) {
31366e740b765384686ce87003608412e940ab5d489Elliott Hughes    return;
314a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
315a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get());
316a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if ((bytes[0] & 0X80) == 0) { // Positive value!
317a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    //
318a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // We can use the existing BN implementation for unsigned big endian bytes:
319a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    //
32066e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_bin2bn(s, bytesLen, ret);
32166e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_set_negative(ret, false);
322a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  } else { // Negative value!
323a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    //
324a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // We need to apply two's complement:
325a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    //
32666e740b765384686ce87003608412e940ab5d489Elliott Hughes    negBigEndianBytes2bn(env, cls, s, bytesLen, ret0);
32766e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_set_negative(ret, true);
328a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
32966e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
330a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
331a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
332a961d0b42b313aae32f340d9bf7de18e638da2cbColin Crossstatic jlong NativeBN_longInt(JNIEnv* env, jclass, jlong a0) {
333a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return -1;
334a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross
335a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
336a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  bn_check_top(a);
337a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int wLen = a->top;
338a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (wLen == 0) {
339a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    return 0;
340a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  }
341a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross
342a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#ifdef __LP64__
343a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  jlong result = a->d[0];
344a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#else
345a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  jlong result = static_cast<jlong>(a->d[0]) & 0xffffffff;
346a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (wLen > 1) {
347a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross    result |= static_cast<jlong>(a->d[1]) << 32;
348a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
349a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#endif
350a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  return a->neg ? -result : result;
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic char* leadingZerosTrimmed(char* s) {
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    char* p = s;
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    if (*p == '-') {
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        p++;
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while ((*p == '0') && (*(p + 1) != 0)) { p++; }
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        p--;
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        *p = '-';
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    } else {
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while ((*p == '0') && (*(p + 1) != 0)) { p++; }
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    return p;
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
366a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, jlong a) {
367a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a)) return NULL;
368a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  char* tmpStr = BN_bn2dec(toBigNum(a));
369a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (tmpStr == NULL) {
370a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
371a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
372a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  char* retStr = leadingZerosTrimmed(tmpStr);
373a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  jstring returnJString = env->NewStringUTF(retStr);
374a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  OPENSSL_free(tmpStr);
375a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return returnJString;
376a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
377a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
378a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, jlong a) {
379a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a)) return NULL;
380a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  char* tmpStr = BN_bn2hex(toBigNum(a));
381a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (tmpStr == NULL) {
382a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
383a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
384a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  char* retStr = leadingZerosTrimmed(tmpStr);
385a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  jstring returnJString = env->NewStringUTF(retStr);
386a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  OPENSSL_free(tmpStr);
387a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return returnJString;
388a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
389a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
390a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, jlong a0) {
391a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return NULL;
392a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
393a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  jbyteArray result = env->NewByteArray(BN_num_bytes(a));
394a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (result == NULL) {
395a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
396a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
397a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedByteArrayRW bytes(env, result);
398a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (bytes.get() == NULL) {
399a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
400a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
401a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
402a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return result;
403a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
404a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
405a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, jlong a0) {
406a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return NULL;
407a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
408a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  bn_check_top(a);
409a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int wLen = a->top;
410a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (wLen == 0) {
411a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
412a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
4138383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  jintArray result = env->NewIntArray(wLen * sizeof(BN_ULONG)/sizeof(unsigned int));
414a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (result == NULL) {
415a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
416a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
417a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  ScopedIntArrayRW ints(env, result);
418a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (ints.get() == NULL) {
419a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
420a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
421a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  unsigned int* uints = reinterpret_cast<unsigned int*>(ints.get());
422a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (uints == NULL) {
423a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return NULL;
424a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
425a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#ifdef __LP64__
426a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int i = wLen; do { i--; uints[i*2+1] = a->d[i] >> 32; uints[i*2] = a->d[i]; } while (i > 0);
427a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#else
428a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int i = wLen; do { i--; uints[i] = a->d[i]; } while (i > 0);
429a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross#endif
430a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return result;
431a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
432a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
433a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_sign(JNIEnv* env, jclass, jlong a) {
434a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a)) return -2;
435a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (BN_is_zero(toBigNum(a))) {
436a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes      return 0;
437a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  } else if (BN_is_negative(toBigNum(a))) {
438a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    return -1;
439a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
440a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return 1;
441a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
442a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
443a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic void NativeBN_BN_set_negative(JNIEnv* env, jclass, jlong b, int n) {
444a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, b)) return;
445a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BN_set_negative(toBigNum(b), n);
446a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes}
447a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes
448a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_bitLength(JNIEnv* env, jclass, jlong a0) {
449a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a0)) return JNI_FALSE;
450a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BIGNUM* a = toBigNum(a0);
451a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  bn_check_top(a);
452a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int wLen = a->top;
453a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  if (wLen == 0) return 0;
454a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BN_ULONG* d = a->d;
455a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross  int i = wLen - 1;
456a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  BN_ULONG msd = d[i]; // most significant digit
457a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (a->neg) {
458a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // Handle negative values correctly:
459a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // i.e. decrement the msd if all other digits are 0:
460a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    // while ((i > 0) && (d[i] != 0)) { i--; }
461a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    do { i--; } while (!((i < 0) || (d[i] != 0)));
462a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes    if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
463a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  }
4648383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley  return (wLen - 1) * sizeof(BN_ULONG) * 8 + BN_num_bits_word(msd);
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
467a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, jlong a, int n) {
468a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, a)) return JNI_FALSE;
469a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  return BN_is_bit_set(toBigNum(a), n);
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
47266e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_shift(JNIEnv* env, jclass, jlong r, jlong a, int n) {
47366e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!twoValidHandles(env, r, a)) return;
47466e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (n >= 0) {
47566e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_lshift(toBigNum(r), toBigNum(a), n);
47666e740b765384686ce87003608412e940ab5d489Elliott Hughes  } else {
47766e740b765384686ce87003608412e940ab5d489Elliott Hughes    BN_rshift(toBigNum(r), toBigNum(a), -n);
47866e740b765384686ce87003608412e940ab5d489Elliott Hughes  }
47966e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
48266e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_add_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
48366e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, a)) return;
48466e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_add_word(toBigNum(a), w);
48566e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
48866e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mul_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
48966e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, a)) return;
49066e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_mul_word(toBigNum(a), w);
49166e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
494a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
49566e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, a)) return 0;
49666e740b765384686ce87003608412e940ab5d489Elliott Hughes  int result = BN_mod_word(toBigNum(a), w);
49766e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
49866e740b765384686ce87003608412e940ab5d489Elliott Hughes  return result;
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
50166e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_add(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
50266e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, b)) return;
50366e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_add(toBigNum(r), toBigNum(a), toBigNum(b));
50466e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
50766e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_sub(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
50866e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, b)) return;
50966e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_sub(toBigNum(r), toBigNum(a), toBigNum(b));
51066e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
51366e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_gcd(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
51466e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, b)) return;
515a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
51666e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_gcd(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
51766e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
52066e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mul(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
52166e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, b)) return;
522a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
52366e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_mul(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
52466e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
52766e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p) {
52866e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, p)) return;
529a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
53066e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_exp(toBigNum(r), toBigNum(a), toBigNum(p), ctx.get());
53166e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
53466e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_div(JNIEnv* env, jclass, jlong dv, jlong rem, jlong m, jlong d) {
53566e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return;
536a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
53766e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_div(toBigNum(dv), toBigNum(rem), toBigNum(m), toBigNum(d), ctx.get());
53866e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
54166e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_nnmod(JNIEnv* env, jclass, jlong r, jlong a, jlong m) {
54266e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, r, a, m)) return;
543a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
54466e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_nnmod(toBigNum(r), toBigNum(a), toBigNum(m), ctx.get());
54566e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
54866e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mod_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p, jlong m) {
54966e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!fourValidHandles(env, r, a, p, m)) return;
550a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
55166e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_mod_exp(toBigNum(r), toBigNum(a), toBigNum(p), toBigNum(m), ctx.get());
55266e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
55566e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mod_inverse(JNIEnv* env, jclass, jlong ret, jlong a, jlong n) {
55666e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!threeValidHandles(env, ret, a, n)) return;
557a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
55866e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_mod_inverse(toBigNum(ret), toBigNum(a), toBigNum(n), ctx.get());
55966e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
56266e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, jlong ret, int bits,
56366e740b765384686ce87003608412e940ab5d489Elliott Hughes                                          jboolean safe, jlong add, jlong rem, jlong cb) {
56466e740b765384686ce87003608412e940ab5d489Elliott Hughes  if (!oneValidHandle(env, ret)) return;
56566e740b765384686ce87003608412e940ab5d489Elliott Hughes  BN_generate_prime_ex(toBigNum(ret), bits, safe, toBigNum(add), toBigNum(rem),
56666e740b765384686ce87003608412e940ab5d489Elliott Hughes                       reinterpret_cast<BN_GENCB*>(cb));
56766e740b765384686ce87003608412e940ab5d489Elliott Hughes  throwExceptionIfNecessary(env);
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
5700a08bbe70ef43ed29cba241e95aa5c338349b021Chris Dearmanstatic jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, jlong p, int nchecks, jlong cb) {
571a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  if (!oneValidHandle(env, p)) return JNI_FALSE;
572a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes  Unique_BN_CTX ctx(BN_CTX_new());
5730a08bbe70ef43ed29cba241e95aa5c338349b021Chris Dearman  return BN_is_prime_ex(toBigNum(p), nchecks, ctx.get(), reinterpret_cast<BN_GENCB*>(cb));
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
57663710430c17f7c0a1e74b926cd21248fde8e9589Elliott Hughesstatic JNINativeMethod gMethods[] = {
57766e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_add, "(JJJ)V"),
57866e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_add_word, "(JI)V"),
57966e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZJ)V"),
580a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_bn2bin, "(J)[B"),
581a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_bn2dec, "(J)Ljava/lang/String;"),
582a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_bn2hex, "(J)Ljava/lang/String;"),
583a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_cmp, "(JJ)I"),
58466e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_copy, "(JJ)V"),
585a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_dec2bn, "(JLjava/lang/String;)I"),
58666e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_div, "(JJJJ)V"),
58766e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_exp, "(JJJ)V"),
588a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_free, "(J)V"),
58966e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_gcd, "(JJJ)V"),
59066e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(JIZJJJ)V"),
591a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_hex2bn, "(JLjava/lang/String;)I"),
592a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_is_bit_set, "(JI)Z"),
593a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_is_prime_ex, "(JIJ)Z"),
59466e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_mod_exp, "(JJJJ)V"),
59566e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_mod_inverse, "(JJJ)V"),
596a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_mod_word, "(JI)I"),
59766e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_mul, "(JJJ)V"),
59866e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_mul_word, "(JI)V"),
599a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_new, "()J"),
60066e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_nnmod, "(JJJ)V"),
601a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, BN_set_negative, "(JI)V"),
60266e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_shift, "(JJI)V"),
60366e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, BN_sub, "(JJJ)V"),
604a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, bitLength, "(J)I"),
605a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, bn2litEndInts, "(J)[I"),
60666e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZJ)V"),
607a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, longInt, "(J)J"),
60866e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, putLongInt, "(JJ)V"),
60966e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, putULongInt, "(JJZ)V"),
610a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes   NATIVE_METHOD(NativeBN, sign, "(J)I"),
61166e740b765384686ce87003608412e940ab5d489Elliott Hughes   NATIVE_METHOD(NativeBN, twosComp2bn, "([BIJ)V"),
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project};
6137cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_java_math_NativeBN(JNIEnv* env) {
6147cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes    jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
616