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> 29b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan#include <algorithm> 30b3aacde3d8af759ee4a7b395c636ea360547d92dIan Rogers#include <memory> 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 3263710430c17f7c0a1e74b926cd21248fde8e9589Elliott Hughesstruct BN_CTX_Deleter { 3366e740b765384686ce87003608412e940ab5d489Elliott Hughes void operator()(BN_CTX* p) const { 3466e740b765384686ce87003608412e940ab5d489Elliott Hughes BN_CTX_free(p); 3566e740b765384686ce87003608412e940ab5d489Elliott Hughes } 3663710430c17f7c0a1e74b926cd21248fde8e9589Elliott Hughes}; 37b3aacde3d8af759ee4a7b395c636ea360547d92dIan Rogerstypedef std::unique_ptr<BN_CTX, BN_CTX_Deleter> Unique_BN_CTX; 3863710430c17f7c0a1e74b926cd21248fde8e9589Elliott Hughes 39a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic BIGNUM* toBigNum(jlong address) { 40a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return reinterpret_cast<BIGNUM*>(static_cast<uintptr_t>(address)); 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 43ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjaminstatic void throwException(JNIEnv* env) { 4466e740b765384686ce87003608412e940ab5d489Elliott Hughes long error = ERR_get_error(); 45ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin // OpenSSL's error queue may contain multiple errors. Clean up after them. 46ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin ERR_clear_error(); 47ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin 4866e740b765384686ce87003608412e940ab5d489Elliott Hughes if (error == 0) { 49ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin // An operation failed but did not push to the error queue. Throw a default 50ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin // exception. 51ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin jniThrowException(env, "java/lang/ArithmeticException", "Operation failed"); 52ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin return; 5366e740b765384686ce87003608412e940ab5d489Elliott Hughes } 54ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin 5566e740b765384686ce87003608412e940ab5d489Elliott Hughes char message[256]; 5666e740b765384686ce87003608412e940ab5d489Elliott Hughes ERR_error_string_n(error, message, sizeof(message)); 5766e740b765384686ce87003608412e940ab5d489Elliott Hughes int reason = ERR_GET_REASON(error); 5866e740b765384686ce87003608412e940ab5d489Elliott Hughes if (reason == BN_R_DIV_BY_ZERO) { 5966e740b765384686ce87003608412e940ab5d489Elliott Hughes jniThrowException(env, "java/lang/ArithmeticException", "BigInteger division by zero"); 6066e740b765384686ce87003608412e940ab5d489Elliott Hughes } else if (reason == BN_R_NO_INVERSE) { 6166e740b765384686ce87003608412e940ab5d489Elliott Hughes jniThrowException(env, "java/lang/ArithmeticException", "BigInteger not invertible"); 6266e740b765384686ce87003608412e940ab5d489Elliott Hughes } else if (reason == ERR_R_MALLOC_FAILURE) { 6366e740b765384686ce87003608412e940ab5d489Elliott Hughes jniThrowOutOfMemoryError(env, message); 6466e740b765384686ce87003608412e940ab5d489Elliott Hughes } else { 6566e740b765384686ce87003608412e940ab5d489Elliott Hughes jniThrowException(env, "java/lang/ArithmeticException", message); 6666e740b765384686ce87003608412e940ab5d489Elliott Hughes } 6766e740b765384686ce87003608412e940ab5d489Elliott Hughes} 68a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 69a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int isValidHandle(JNIEnv* env, jlong handle, const char* message) { 70a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (handle == 0) { 71a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes jniThrowNullPointerException(env, message); 72a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return JNI_FALSE; 73a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 74a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return JNI_TRUE; 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 77a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int oneValidHandle(JNIEnv* env, jlong a) { 78a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return isValidHandle(env, a, "Mandatory handle (first) passed as null"); 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 81a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int twoValidHandles(JNIEnv* env, jlong a, jlong b) { 82a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, a)) return JNI_FALSE; 83a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return isValidHandle(env, b, "Mandatory handle (second) passed as null"); 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 86a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int threeValidHandles(JNIEnv* env, jlong a, jlong b, jlong c) { 87a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!twoValidHandles(env, a, b)) return JNI_FALSE; 88a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return isValidHandle(env, c, "Mandatory handle (third) passed as null"); 89a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes} 90a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 91a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int fourValidHandles(JNIEnv* env, jlong a, jlong b, jlong c, jlong d) { 92a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!threeValidHandles(env, a, b, c)) return JNI_FALSE; 93a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return isValidHandle(env, d, "Mandatory handle (fourth) passed as null"); 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9666e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic jlong NativeBN_BN_new(JNIEnv* env, jclass) { 9766e740b765384686ce87003608412e940ab5d489Elliott Hughes jlong result = static_cast<jlong>(reinterpret_cast<uintptr_t>(BN_new())); 98ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!result) { 99ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 100ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 10166e740b765384686ce87003608412e940ab5d489Elliott Hughes return result; 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 10433fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhlerstatic jlong NativeBN_getNativeFinalizer(JNIEnv*, jclass) { 10533fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler return static_cast<jlong>(reinterpret_cast<uintptr_t>(&BN_free)); 10633fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler} 10733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler 108a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic void NativeBN_BN_free(JNIEnv* env, jclass, jlong a) { 109a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, a)) return; 110a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes BN_free(toBigNum(a)); 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 113a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_BN_cmp(JNIEnv* env, jclass, jlong a, jlong b) { 114a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!twoValidHandles(env, a, b)) return 1; 115a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return BN_cmp(toBigNum(a), toBigNum(b)); 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 11866e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_copy(JNIEnv* env, jclass, jlong to, jlong from) { 11966e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!twoValidHandles(env, to, from)) return; 120ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_copy(toBigNum(to), toBigNum(from))) { 121ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 122ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 125a961d0b42b313aae32f340d9bf7de18e638da2cbColin Crossstatic void NativeBN_putULongInt(JNIEnv* env, jclass, jlong a0, jlong java_dw, jboolean neg) { 1268383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley if (!oneValidHandle(env, a0)) return; 127a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross 1288383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley uint64_t dw = java_dw; 1298383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley BIGNUM* a = toBigNum(a0); 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 131571cc4d33f5fdbfdae8bf219854c211581fdc4b4David Benjamin if (!BN_set_u64(a, dw)) { 132571cc4d33f5fdbfdae8bf219854c211581fdc4b4David Benjamin throwException(env); 133571cc4d33f5fdbfdae8bf219854c211581fdc4b4David Benjamin return; 1348383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley } 1358383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley 1368383f343119f7a98cbe3b4a5bddc89038ac5c166Adam Langley BN_set_negative(a, neg); 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 139a961d0b42b313aae32f340d9bf7de18e638da2cbColin Crossstatic void NativeBN_putLongInt(JNIEnv* env, jclass cls, jlong a, jlong dw) { 140a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (dw >= 0) { 14166e740b765384686ce87003608412e940ab5d489Elliott Hughes NativeBN_putULongInt(env, cls, a, dw, JNI_FALSE); 142a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } else { 14366e740b765384686ce87003608412e940ab5d489Elliott Hughes NativeBN_putULongInt(env, cls, a, -dw, JNI_TRUE); 144a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 147a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_BN_dec2bn(JNIEnv* env, jclass, jlong a0, jstring str) { 148a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, a0)) return -1; 149a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes ScopedUtfChars chars(env, str); 150a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (chars.c_str() == NULL) { 151a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return -1; 152a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 153a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes BIGNUM* a = toBigNum(a0); 15466e740b765384686ce87003608412e940ab5d489Elliott Hughes int result = BN_dec2bn(&a, chars.c_str()); 155ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (result == 0) { 156ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 157ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 15866e740b765384686ce87003608412e940ab5d489Elliott Hughes return result; 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 161a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_BN_hex2bn(JNIEnv* env, jclass, jlong a0, jstring str) { 162a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, a0)) return -1; 163a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes ScopedUtfChars chars(env, str); 164a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (chars.c_str() == NULL) { 165a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return -1; 166a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 167a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes BIGNUM* a = toBigNum(a0); 16866e740b765384686ce87003608412e940ab5d489Elliott Hughes int result = BN_hex2bn(&a, chars.c_str()); 169ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (result == 0) { 170ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 171ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 17266e740b765384686ce87003608412e940ab5d489Elliott Hughes return result; 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17566e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, jlong ret) { 17666e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!oneValidHandle(env, ret)) return; 177a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes ScopedByteArrayRO bytes(env, arr); 178a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (bytes.get() == NULL) { 17966e740b765384686ce87003608412e940ab5d489Elliott Hughes return; 180a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 181ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, toBigNum(ret))) { 182ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 183ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin return; 184a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 185ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin 186ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin BN_set_negative(toBigNum(ret), neg); 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18966e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len, jboolean neg, jlong ret0) { 19066e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!oneValidHandle(env, ret0)) return; 191a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes BIGNUM* ret = toBigNum(ret0); 192ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin 193b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan ScopedIntArrayRO scopedArray(env, arr); 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 195b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan if (scopedArray.get() == NULL) { 196b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan return; 197b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan } 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 199b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan // We can simply interpret the little-endian integer stream as a 200b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan // little-endian byte stream and use BN_le2bn. 201b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan const uint8_t* tmpBytes = reinterpret_cast<const uint8_t *>(scopedArray.get()); 202b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan size_t numBytes = len * sizeof(int); 203a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 204b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan if (!BN_le2bn(tmpBytes, numBytes, ret)) { 205b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan throwException(env); 206ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 207ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin 208b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan BN_set_negative(ret, neg); 209a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes} 210a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 211b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloanstatic void NativeBN_twosComp2bn(JNIEnv* env, jclass, jbyteArray arr, int bytesLen, jlong ret0) { 21266e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!oneValidHandle(env, ret0)) return; 213a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes BIGNUM* ret = toBigNum(ret0); 214a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 215a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes ScopedByteArrayRO bytes(env, arr); 216a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (bytes.get() == NULL) { 21766e740b765384686ce87003608412e940ab5d489Elliott Hughes return; 218a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 219b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 220725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan if (bytesLen == 0) { 221725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan BN_zero(ret); 222725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan return; 223725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan } 224b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 225725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan const unsigned char* bytesTmp = reinterpret_cast<const unsigned char*>(bytes.get()); 226b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 227725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan if (!BN_bin2bn(bytesTmp, bytesLen, ret)) { 228725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan throwException(env); 229725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan return; 230725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan } 231b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 232725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan // Use the high bit to determine the sign in twos-complement. 233725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan BN_set_negative(ret, (bytes[0] & 0x80) != 0); 234b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 235725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan if (BN_is_negative(ret)) { 236725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan // For negative values, BN_bin2bn doesn't interpret the twos-complement 237725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan // representation, so ret is now (- value - 2^N). We can use nnmod_pow2 to set 238725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan // ret to (-value). 239725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan if (!BN_nnmod_pow2(ret, ret, bytesLen * 8)) { 240b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan throwException(env); 241b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan return; 242b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan } 243725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan 244725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan // And now we correct the sign. 245725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan BN_set_negative(ret, 1); 246a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 247a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes} 248a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 249a961d0b42b313aae32f340d9bf7de18e638da2cbColin Crossstatic jlong NativeBN_longInt(JNIEnv* env, jclass, jlong a0) { 250a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, a0)) return -1; 251a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes BIGNUM* a = toBigNum(a0); 252b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan uint64_t word; 253a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross 254b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan if (BN_get_u64(a, &word)) { 255b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan return BN_is_negative(a) ? -((jlong) word) : word; 256b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan } else { 257b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan // This should be unreachable if our caller checks BigInt::twosCompFitsIntoBytes(8) 258b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan throwException(env); 259b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan return 0; 260a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectstatic char* leadingZerosTrimmed(char* s) { 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project char* p = s; 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (*p == '-') { 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project p++; 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while ((*p == '0') && (*(p + 1) != 0)) { p++; } 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project p--; 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *p = '-'; 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project while ((*p == '0') && (*(p + 1) != 0)) { p++; } 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return p; 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 276a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, jlong a) { 277a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, a)) return NULL; 278a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes char* tmpStr = BN_bn2dec(toBigNum(a)); 279a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (tmpStr == NULL) { 280ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 281a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return NULL; 282a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 283a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes char* retStr = leadingZerosTrimmed(tmpStr); 284a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes jstring returnJString = env->NewStringUTF(retStr); 285a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes OPENSSL_free(tmpStr); 286a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return returnJString; 287a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes} 288a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 289a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, jlong a) { 290a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, a)) return NULL; 291a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes char* tmpStr = BN_bn2hex(toBigNum(a)); 292a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (tmpStr == NULL) { 293ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 294a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return NULL; 295a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 296a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes char* retStr = leadingZerosTrimmed(tmpStr); 297a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes jstring returnJString = env->NewStringUTF(retStr); 298a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes OPENSSL_free(tmpStr); 299a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return returnJString; 300a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes} 301a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 302a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, jlong a0) { 303a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, a0)) return NULL; 304a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes BIGNUM* a = toBigNum(a0); 305a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes jbyteArray result = env->NewByteArray(BN_num_bytes(a)); 306a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (result == NULL) { 307a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return NULL; 308a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 309a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes ScopedByteArrayRW bytes(env, result); 310a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (bytes.get() == NULL) { 311a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return NULL; 312a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 313a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get())); 314a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return result; 315a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes} 316a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 317a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, jlong a0) { 318a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, a0)) return NULL; 319b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 320a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes BIGNUM* a = toBigNum(a0); 321b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 322b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan // The number of integers we need is BN_num_bytes(a) / sizeof(int), rounded up 323b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan int intLen = (BN_num_bytes(a) + sizeof(int) - 1) / sizeof(int); 324b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 325b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan // Allocate our result with the JNI boilerplate 326b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan jintArray result = env->NewIntArray(intLen); 327b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 328a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (result == NULL) { 329b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan throwException(env); 330a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return NULL; 331a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 332b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 333a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes ScopedIntArrayRW ints(env, result); 334b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 335a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross unsigned int* uints = reinterpret_cast<unsigned int*>(ints.get()); 336a961d0b42b313aae32f340d9bf7de18e638da2cbColin Cross if (uints == NULL) { 337b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan throwException(env); 338a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return NULL; 339a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 340b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 341b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan // We can simply interpret a little-endian byte stream as a little-endian integer stream. 342b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan if (!BN_bn2le_padded(reinterpret_cast<uint8_t*>(uints), intLen * sizeof(int), a)) { 343b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan throwException(env); 344b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan return NULL; 345b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan } 346b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 347a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return result; 348a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes} 349a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 350a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic int NativeBN_sign(JNIEnv* env, jclass, jlong a) { 351a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, a)) return -2; 352a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (BN_is_zero(toBigNum(a))) { 353a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return 0; 354a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } else if (BN_is_negative(toBigNum(a))) { 355a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return -1; 356a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes } 357a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes return 1; 358a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes} 359a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 360a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic void NativeBN_BN_set_negative(JNIEnv* env, jclass, jlong b, int n) { 361a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, b)) return; 362a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes BN_set_negative(toBigNum(b), n); 363a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes} 364a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes 365725aa55c317e0541a891d3be8d69892609340e6cRobert Sloanstatic int NativeBN_bitLength(JNIEnv* env, jclass, jlong a0) { 366725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan if (!oneValidHandle(env, a0)) return JNI_FALSE; 367725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan BIGNUM* a = toBigNum(a0); 368b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 369725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan // If a is not negative, we can use BN_num_bits directly. 370725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan if (!BN_is_negative(a)) { 371725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan return BN_num_bits(a); 372b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan } 373b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 374725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan // In the negative case, the number of bits in a is the same as the number of bits in |a|, 375725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan // except one less when |a| is a power of two. 376725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan BIGNUM positiveA; 377725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan BN_init(&positiveA); 378b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 379725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan if (!BN_copy(&positiveA, a)) { 380725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan BN_free(&positiveA); 381b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan throwException(env); 382725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan return -1; 383b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan } 384b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 385725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan BN_set_negative(&positiveA, false); 386725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan int numBits = BN_is_pow2(&positiveA) ? BN_num_bits(&positiveA) - 1 : BN_num_bits(&positiveA); 387b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 388725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan BN_free(&positiveA); 389725aa55c317e0541a891d3be8d69892609340e6cRobert Sloan return numBits; 390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 392a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, jlong a, int n) { 393a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes if (!oneValidHandle(env, a)) return JNI_FALSE; 394b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan 395b23d3f2954007f4c24556cdb90b624d2e3b5748cRobert Sloan // NOTE: this is only called in the positive case, so BN_is_bit_set is fine here. 396ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin return BN_is_bit_set(toBigNum(a), n) ? JNI_TRUE : JNI_FALSE; 397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 39966e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_shift(JNIEnv* env, jclass, jlong r, jlong a, int n) { 40066e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!twoValidHandles(env, r, a)) return; 401ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin int ok; 40266e740b765384686ce87003608412e940ab5d489Elliott Hughes if (n >= 0) { 403ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin ok = BN_lshift(toBigNum(r), toBigNum(a), n); 40466e740b765384686ce87003608412e940ab5d489Elliott Hughes } else { 405ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin ok = BN_rshift(toBigNum(r), toBigNum(a), -n); 406ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 407ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!ok) { 408ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 40966e740b765384686ce87003608412e940ab5d489Elliott Hughes } 410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 41266e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_add_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) { 41366e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!oneValidHandle(env, a)) return; 414ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_add_word(toBigNum(a), w)) { 415ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 416ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 41966e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mul_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) { 42066e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!oneValidHandle(env, a)) return; 421ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_mul_word(toBigNum(a), w)) { 422ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 423ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 426a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughesstatic BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) { 42766e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!oneValidHandle(env, a)) return 0; 428ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin BN_ULONG result = BN_mod_word(toBigNum(a), w); 429ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (result == (BN_ULONG)-1) { 430ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 431ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 43266e740b765384686ce87003608412e940ab5d489Elliott Hughes return result; 433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 43566e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_add(JNIEnv* env, jclass, jlong r, jlong a, jlong b) { 43666e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!threeValidHandles(env, r, a, b)) return; 437ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_add(toBigNum(r), toBigNum(a), toBigNum(b))) { 438ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 439ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 44266e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_sub(JNIEnv* env, jclass, jlong r, jlong a, jlong b) { 44366e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!threeValidHandles(env, r, a, b)) return; 444ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_sub(toBigNum(r), toBigNum(a), toBigNum(b))) { 445ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 446ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 44966e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_gcd(JNIEnv* env, jclass, jlong r, jlong a, jlong b) { 45066e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!threeValidHandles(env, r, a, b)) return; 451a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes Unique_BN_CTX ctx(BN_CTX_new()); 452ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_gcd(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get())) { 453ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 454ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 45766e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mul(JNIEnv* env, jclass, jlong r, jlong a, jlong b) { 45866e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!threeValidHandles(env, r, a, b)) return; 459a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes Unique_BN_CTX ctx(BN_CTX_new()); 460ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_mul(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get())) { 461ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 462ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 46566e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p) { 46666e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!threeValidHandles(env, r, a, p)) return; 467a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes Unique_BN_CTX ctx(BN_CTX_new()); 468ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_exp(toBigNum(r), toBigNum(a), toBigNum(p), ctx.get())) { 469ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 470ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 47366e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_div(JNIEnv* env, jclass, jlong dv, jlong rem, jlong m, jlong d) { 47466e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return; 475a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes Unique_BN_CTX ctx(BN_CTX_new()); 476ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_div(toBigNum(dv), toBigNum(rem), toBigNum(m), toBigNum(d), ctx.get())) { 477ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 478ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 48166e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_nnmod(JNIEnv* env, jclass, jlong r, jlong a, jlong m) { 48266e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!threeValidHandles(env, r, a, m)) return; 483a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes Unique_BN_CTX ctx(BN_CTX_new()); 484ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_nnmod(toBigNum(r), toBigNum(a), toBigNum(m), ctx.get())) { 485ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 486ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 48966e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mod_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p, jlong m) { 49066e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!fourValidHandles(env, r, a, p, m)) return; 491a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes Unique_BN_CTX ctx(BN_CTX_new()); 492ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_mod_exp(toBigNum(r), toBigNum(a), toBigNum(p), toBigNum(m), ctx.get())) { 493ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 494ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 49766e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_mod_inverse(JNIEnv* env, jclass, jlong ret, jlong a, jlong n) { 49866e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!threeValidHandles(env, ret, a, n)) return; 499a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes Unique_BN_CTX ctx(BN_CTX_new()); 500ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_mod_inverse(toBigNum(ret), toBigNum(a), toBigNum(n), ctx.get())) { 501ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 502ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 50566e740b765384686ce87003608412e940ab5d489Elliott Hughesstatic void NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, jlong ret, int bits, 506ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin jboolean safe, jlong add, jlong rem) { 50766e740b765384686ce87003608412e940ab5d489Elliott Hughes if (!oneValidHandle(env, ret)) return; 508ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_generate_prime_ex(toBigNum(ret), bits, safe, toBigNum(add), toBigNum(rem), 509ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin NULL)) { 510ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 511ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 514ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjaminstatic jboolean NativeBN_BN_primality_test(JNIEnv* env, jclass, jlong candidate, int checks, 515ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin jboolean do_trial_decryption) { 516ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!oneValidHandle(env, candidate)) return JNI_FALSE; 517a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes Unique_BN_CTX ctx(BN_CTX_new()); 518ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin int is_probably_prime; 519ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin if (!BN_primality_test(&is_probably_prime, toBigNum(candidate), checks, ctx.get(), 520ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin do_trial_decryption, NULL)) { 521ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin throwException(env); 522ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin return JNI_FALSE; 523ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin } 524ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin return is_probably_prime ? JNI_TRUE : JNI_FALSE; 525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 52763710430c17f7c0a1e74b926cd21248fde8e9589Elliott Hughesstatic JNINativeMethod gMethods[] = { 52866e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_add, "(JJJ)V"), 52966e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_add_word, "(JI)V"), 53066e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZJ)V"), 531a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, BN_bn2bin, "(J)[B"), 532a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, BN_bn2dec, "(J)Ljava/lang/String;"), 533a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, BN_bn2hex, "(J)Ljava/lang/String;"), 534a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, BN_cmp, "(JJ)I"), 53566e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_copy, "(JJ)V"), 536a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, BN_dec2bn, "(JLjava/lang/String;)I"), 53766e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_div, "(JJJJ)V"), 53866e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_exp, "(JJJ)V"), 539a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, BN_free, "(J)V"), 54066e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_gcd, "(JJJ)V"), 541ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(JIZJJ)V"), 542a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, BN_hex2bn, "(JLjava/lang/String;)I"), 543a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, BN_is_bit_set, "(JI)Z"), 544ef742f1823504e4166f678d2651cccf16e711b1eDavid Benjamin NATIVE_METHOD(NativeBN, BN_primality_test, "(JIZ)Z"), 54566e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_mod_exp, "(JJJJ)V"), 54666e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_mod_inverse, "(JJJ)V"), 547a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, BN_mod_word, "(JI)I"), 54866e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_mul, "(JJJ)V"), 54966e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_mul_word, "(JI)V"), 550a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, BN_new, "()J"), 55166e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_nnmod, "(JJJ)V"), 552a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, BN_set_negative, "(JI)V"), 55366e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_shift, "(JJI)V"), 55466e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, BN_sub, "(JJJ)V"), 555a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, bitLength, "(J)I"), 556a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, bn2litEndInts, "(J)[I"), 55733fc9556dfda6298fcd7c119f68a7375e13cbed9Richard Uhler NATIVE_METHOD(NativeBN, getNativeFinalizer, "()J"), 55866e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZJ)V"), 559a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, longInt, "(J)J"), 56066e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, putLongInt, "(JJ)V"), 56166e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, putULongInt, "(JJZ)V"), 562a125dded8ab0490d05e2fa9ec2e821ef1ae6facdElliott Hughes NATIVE_METHOD(NativeBN, sign, "(J)I"), 56366e740b765384686ce87003608412e940ab5d489Elliott Hughes NATIVE_METHOD(NativeBN, twosComp2bn, "([BIJ)V"), 564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}; 5657cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_java_math_NativeBN(JNIEnv* env) { 5667cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods)); 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 568