blob: ac9cd905f9c3378236230d25aab8a9ab1056fff9 [file] [log] [blame]
The Android Open Source Projectadc854b2009-03-03 19:28:47 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * Native glue for Java class org.openssl.NativeBN
19 */
20
Elliott Hughesabf945f2010-06-03 19:55:20 -070021#define LOG_TAG "NativeBN"
22
Elliott Hughes99c59bf2010-05-17 16:22:04 -070023#include "JNIHelp.h"
24#include "ScopedPrimitiveArray.h"
Elliott Hughes05960872010-05-26 17:45:07 -070025#include "ScopedUtfChars.h"
Elliott Hughes63710432010-06-11 12:58:06 -070026#include "UniquePtr.h"
Elliott Hughes99c59bf2010-05-17 16:22:04 -070027#include "jni.h"
28#include <assert.h>
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080029#include <openssl/bn.h>
Elliott Hughes99c59bf2010-05-17 16:22:04 -070030#include <openssl/crypto.h>
31#include <openssl/err.h>
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080032#include <stdio.h>
33
Elliott Hughes63710432010-06-11 12:58:06 -070034struct BN_CTX_Deleter {
35 void operator()(BN_CTX* p) const {
36 BN_CTX_free(p);
37 }
38};
39typedef UniquePtr<BN_CTX, BN_CTX_Deleter> Unique_BN_CTX;
40
Elliott Hughesda4f31d2010-01-28 13:43:39 -080041static int isValidHandle (JNIEnv* env, void* handle, const char *message) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080042 if (handle == NULL) {
Elliott Hughesda4f31d2010-01-28 13:43:39 -080043 jniThrowNullPointerException(env, message);
Elliott Hughes99c59bf2010-05-17 16:22:04 -070044 return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080045 }
Elliott Hughes99c59bf2010-05-17 16:22:04 -070046 return JNI_TRUE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080047}
48
49static int oneValidHandle (JNIEnv* env, void* a)
50{
51 return isValidHandle(env, a, "Mandatory handle (first) passed as null");
52}
53
54static int twoValidHandles (JNIEnv* env, void* a, void *b)
55{
Elliott Hughes99c59bf2010-05-17 16:22:04 -070056 if (!oneValidHandle(env, a)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080057 return isValidHandle(env, b, "Mandatory handle (second) passed as null");
58}
59
60static int threeValidHandles (JNIEnv* env, void* a, void *b, void* c)
61{
Elliott Hughes99c59bf2010-05-17 16:22:04 -070062 if (!twoValidHandles(env, a, b)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080063 return isValidHandle(env, c, "Mandatory handle (third) passed as null");
64}
65
66static int fourValidHandles (JNIEnv* env, void* a, void *b, void* c, void* d)
67{
Elliott Hughes99c59bf2010-05-17 16:22:04 -070068 if (!threeValidHandles(env, a, b, c)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080069 return isValidHandle(env, d, "Mandatory handle (fourth) passed as null");
70}
71
Brian Carlstromec2f5932010-05-07 16:58:16 -070072static unsigned long NativeBN_ERR_get_error(JNIEnv*, jclass) {
73 return ERR_get_error();
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080074}
75
Brian Carlstromec2f5932010-05-07 16:58:16 -070076static jstring NativeBN_ERR_error_string(JNIEnv* env, jclass, unsigned long e) {
77 char* errStr = ERR_error_string(e, NULL);
78 return env->NewStringUTF(errStr);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080079}
80
Brian Carlstromec2f5932010-05-07 16:58:16 -070081static BIGNUM* NativeBN_BN_new(JNIEnv*, jclass) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080082 return BN_new();
83}
84
Brian Carlstromec2f5932010-05-07 16:58:16 -070085static void NativeBN_BN_free(JNIEnv* env, jclass, BIGNUM* a) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080086 if (!oneValidHandle(env, a)) return;
87 BN_free(a);
88}
89
Brian Carlstromec2f5932010-05-07 16:58:16 -070090static int NativeBN_BN_cmp(JNIEnv* env, jclass, BIGNUM* a, BIGNUM* b) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080091 if (!twoValidHandles(env, a, b)) return 1;
92 return BN_cmp(a, b);
93}
94
Brian Carlstromec2f5932010-05-07 16:58:16 -070095static jboolean NativeBN_BN_copy(JNIEnv* env, jclass, BIGNUM* to, BIGNUM* from) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -070096 if (!twoValidHandles(env, to, from)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -080097 return (BN_copy(to, from) != NULL);
98}
99
Brian Carlstromec2f5932010-05-07 16:58:16 -0700100static jboolean NativeBN_putULongInt(JNIEnv* env, jclass, BIGNUM* a, unsigned long long dw, jboolean neg) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700101 if (!oneValidHandle(env, a)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800102 unsigned int hi = dw >> 32; // This shifts without sign extension.
103 int lo = (int)dw; // This truncates implicitely.
104
105 // cf. litEndInts2bn:
106 bn_check_top(a);
107 if (bn_wexpand(a, 2) != NULL) {
108 a->d[0] = lo;
109 a->d[1] = hi;
110 a->top = 2;
111 a->neg = neg;
112 bn_correct_top(a);
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700113 return JNI_TRUE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800114 }
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700115 else return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800116}
117
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800118static jboolean NativeBN_putLongInt(JNIEnv* env, jclass cls, BIGNUM* a, long long dw) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700119 if (dw >= 0) return NativeBN_putULongInt(env, cls, a, dw, JNI_FALSE);
120 else return NativeBN_putULongInt(env, cls, a, -dw, JNI_TRUE);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800121}
122
Brian Carlstromec2f5932010-05-07 16:58:16 -0700123static int NativeBN_BN_dec2bn(JNIEnv* env, jclass, BIGNUM* a, jstring str) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800124 if (!oneValidHandle(env, a)) return -1;
Elliott Hughes05960872010-05-26 17:45:07 -0700125 ScopedUtfChars chars(env, str);
126 if (chars.c_str() == NULL) {
127 return -1;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800128 }
Elliott Hughes05960872010-05-26 17:45:07 -0700129 return BN_dec2bn(&a, chars.c_str());
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800130}
131
Brian Carlstromec2f5932010-05-07 16:58:16 -0700132static int NativeBN_BN_hex2bn(JNIEnv* env, jclass, BIGNUM* a, jstring str) {
Elliott Hughes05960872010-05-26 17:45:07 -0700133 if (!oneValidHandle(env, a)) return -1;
134 ScopedUtfChars chars(env, str);
135 if (chars.c_str() == NULL) {
136 return -1;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800137 }
Elliott Hughes05960872010-05-26 17:45:07 -0700138 return BN_hex2bn(&a, chars.c_str());
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800139}
140
Brian Carlstromec2f5932010-05-07 16:58:16 -0700141static jboolean NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, BIGNUM* ret) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700142 if (!oneValidHandle(env, ret)) return JNI_FALSE;
Elliott Hughesebca53a2010-05-20 20:54:45 -0700143 ScopedByteArrayRO bytes(env, arr);
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700144 if (bytes.get() == NULL) {
145 return -1;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800146 }
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700147 jboolean success = (BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, ret) != NULL);
148 if (success && neg) {
149 BN_set_negative(ret, 1);
150 }
151 return success;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800152}
153
154/**
155 * public static native boolean litEndInts2bn(int[], int, int, int)
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700156 * Note:
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800157 * This procedure directly writes the internal representation of BIGNUMs.
158 * We do so as there is no direct interface based on Little Endian Integer Arrays.
159 * Also note that the same representation is used in the Cordoba Java Implementation of BigIntegers,
160 * whereof certain functionality is still being used.
161 */
Brian Carlstromec2f5932010-05-07 16:58:16 -0700162static jboolean NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len, jboolean neg, BIGNUM* ret) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700163 if (!oneValidHandle(env, ret)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800164 bn_check_top(ret);
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700165 if (len > 0) {
Elliott Hughesebca53a2010-05-20 20:54:45 -0700166 ScopedIntArrayRO scopedArray(env, arr);
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700167 assert(sizeof(BN_ULONG) == sizeof(jint));
168 const BN_ULONG* tmpInts = reinterpret_cast<const BN_ULONG*>(scopedArray.get());
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800169 if ((tmpInts != NULL) && (bn_wexpand(ret, len) != NULL)) {
170 int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800171 ret->top = len;
172 ret->neg = neg;
173 // need to call this due to clear byte at top if avoiding
174 // having the top bit set (-ve number)
175 // Basically get rid of top zero ints:
176 bn_correct_top(ret);
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700177 return JNI_TRUE;
178 } else {
179 return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800180 }
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700181 } else { // (len = 0) means value = 0 and sign will be 0, too.
182 ret->top = 0;
183 return JNI_TRUE;
184 }
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800185}
186
187
188#define BYTES2INT(bytes, k) \
189 ( (bytes[k + 3] & 0xFF) \
190 | (bytes[k + 2] & 0xFF) << 8 \
191 | (bytes[k + 1] & 0xFF) << 16 \
192 | (bytes[k + 0] & 0xFF) << 24 )
193
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700194static jboolean negBigEndianBytes2bn(JNIEnv*, jclass, const unsigned char* bytes, int bytesLen, BIGNUM* ret) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800195// We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
196//
197 bn_check_top(ret);
198// FIXME: ASSERT (bytesLen > 0);
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700199 int intLen = (bytesLen + 3) / 4;
200 int firstNonzeroDigit = -2;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800201 if (bn_wexpand(ret, intLen) != NULL) {
202 BN_ULONG* d = ret->d;
203 BN_ULONG di;
204 ret->top = intLen;
205 int highBytes = bytesLen % 4;
206 int k = bytesLen;
207 // Put bytes to the int array starting from the end of the byte array
208 int i = 0;
209 while (k > highBytes) {
210 k -= 4;
211 di = BYTES2INT(bytes, k);
212 if (di != 0) {
213 d[i] = -di;
214 firstNonzeroDigit = i;
215 i++;
216 while (k > highBytes) {
217 k -= 4;
218 d[i] = ~BYTES2INT(bytes, k);
219 i++;
220 }
221 break;
222 } else {
223 d[i] = 0;
224 i++;
225 }
226 }
227 if (highBytes != 0) {
228 di = -1;
229 // Put the first bytes in the highest element of the int array
230 if (firstNonzeroDigit != -2) {
231 for (k = 0; k < highBytes; k++) {
232 di = (di << 8) | (bytes[k] & 0xFF);
233 }
234 d[i] = ~di;
235 } else {
236 for (k = 0; k < highBytes; k++) {
237 di = (di << 8) | (bytes[k] & 0xFF);
238 }
239 d[i] = -di;
240 }
241 }
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700242 return JNI_TRUE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800243 }
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700244 else return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800245}
246
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800247static jboolean NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, BIGNUM* ret) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700248 if (!oneValidHandle(env, ret)) return JNI_FALSE;
Elliott Hughesebca53a2010-05-20 20:54:45 -0700249 ScopedByteArrayRO bytes(env, arr);
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700250 if (bytes.get() == NULL) {
251 return -1;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800252 }
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700253 jboolean success;
254 const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get());
255 if ((bytes[0] & 0X80) == 0) { // Positive value!
256 //
257 // We can use the existing BN implementation for unsigned big endian bytes:
258 //
259 success = (BN_bin2bn(s, bytesLen, ret) != NULL);
260 BN_set_negative(ret, JNI_FALSE);
261 } else { // Negative value!
262 //
263 // We need to apply two's complement:
264 //
265 success = negBigEndianBytes2bn(env, cls, s, bytesLen, ret);
266 BN_set_negative(ret, JNI_TRUE);
267 }
268 return success;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800269}
270
Brian Carlstromec2f5932010-05-07 16:58:16 -0700271static long long NativeBN_longInt(JNIEnv* env, jclass, BIGNUM* a) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800272 if (!oneValidHandle(env, a)) return -1;
273 bn_check_top(a);
274 int intLen = a->top;
275 BN_ULONG* d = a->d;
276 switch (intLen) {
277 case 0:
278 return 0;
279 case 1:
280 if (!a->neg) return d[0] & 0X00000000FFFFFFFFLL;
281 else return -(d[0] & 0X00000000FFFFFFFFLL);
282 default:
283 if (!a->neg) return ((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL);
284 else return -(((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL));
285 }
286}
287
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800288static char* leadingZerosTrimmed(char* s) {
289 char* p = s;
290 if (*p == '-') {
291 p++;
292 while ((*p == '0') && (*(p + 1) != 0)) { p++; }
293 p--;
294 *p = '-';
295 } else {
296 while ((*p == '0') && (*(p + 1) != 0)) { p++; }
297 }
298 return p;
299}
300
Brian Carlstromec2f5932010-05-07 16:58:16 -0700301static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, BIGNUM* a) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800302 if (!oneValidHandle(env, a)) return NULL;
303 char* tmpStr;
304 char* retStr;
305 tmpStr = BN_bn2dec(a);
306 if (tmpStr != NULL) {
307 retStr = leadingZerosTrimmed(tmpStr);
Brian Carlstromec2f5932010-05-07 16:58:16 -0700308 jstring returnJString = env->NewStringUTF(retStr);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800309 OPENSSL_free(tmpStr);
310 return returnJString;
311 }
312 else return NULL;
313}
314
Brian Carlstromec2f5932010-05-07 16:58:16 -0700315static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, BIGNUM* a) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800316 if (!oneValidHandle(env, a)) return NULL;
317 char* tmpStr;
318 char* retStr;
319 tmpStr = BN_bn2hex(a);
320 if (tmpStr != NULL) {
321 retStr = leadingZerosTrimmed(tmpStr);
Brian Carlstromec2f5932010-05-07 16:58:16 -0700322 jstring returnJString = env->NewStringUTF(retStr);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800323 OPENSSL_free(tmpStr);
324 return returnJString;
325 }
326 else return NULL;
327}
328
Elliott Hughes4e216322010-05-18 15:06:16 -0700329static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, BIGNUM* a) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800330 if (!oneValidHandle(env, a)) return NULL;
Elliott Hughes4e216322010-05-18 15:06:16 -0700331 jbyteArray result = env->NewByteArray(BN_num_bytes(a));
332 if (result == NULL) {
333 return NULL;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800334 }
Elliott Hughesebca53a2010-05-20 20:54:45 -0700335 ScopedByteArrayRW bytes(env, result);
336 if (bytes.get() == NULL) {
Elliott Hughes4e216322010-05-18 15:06:16 -0700337 return NULL;
338 }
Elliott Hughesebca53a2010-05-20 20:54:45 -0700339 BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
Elliott Hughes4e216322010-05-18 15:06:16 -0700340 return result;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800341}
342
Elliott Hughes4e216322010-05-18 15:06:16 -0700343static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, BIGNUM* a) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800344 if (!oneValidHandle(env, a)) return NULL;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800345 bn_check_top(a);
346 int len = a->top;
Elliott Hughes4e216322010-05-18 15:06:16 -0700347 if (len == 0) {
348 return NULL;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800349 }
Elliott Hughes4e216322010-05-18 15:06:16 -0700350 jintArray result = env->NewIntArray(len);
351 if (result == NULL) {
352 return NULL;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800353 }
Elliott Hughesebca53a2010-05-20 20:54:45 -0700354 ScopedIntArrayRW ints(env, result);
355 BN_ULONG* ulongs = reinterpret_cast<BN_ULONG*>(ints.get());
356 if (ulongs == NULL) {
Elliott Hughes4e216322010-05-18 15:06:16 -0700357 return NULL;
358 }
Elliott Hughesebca53a2010-05-20 20:54:45 -0700359 int i = len; do { i--; ulongs[i] = a->d[i]; } while (i > 0);
Elliott Hughes4e216322010-05-18 15:06:16 -0700360 return result;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800361}
362
Brian Carlstromec2f5932010-05-07 16:58:16 -0700363static int NativeBN_sign(JNIEnv* env, jclass, BIGNUM* a) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800364 if (!oneValidHandle(env, a)) return -2;
365 if (BN_is_zero(a)) return 0;
366 else if (BN_is_negative(a)) return -1;
367 else return 1;
368}
369
Brian Carlstromec2f5932010-05-07 16:58:16 -0700370static void NativeBN_BN_set_negative(JNIEnv* env, jclass, BIGNUM* b, int n) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800371 if (!oneValidHandle(env, b)) return;
372 BN_set_negative(b, n);
373}
374
Brian Carlstromec2f5932010-05-07 16:58:16 -0700375static int NativeBN_bitLength(JNIEnv* env, jclass, BIGNUM* a) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800376// We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
377//
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700378 if (!oneValidHandle(env, a)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800379 bn_check_top(a);
380 int intLen = a->top;
381 if (intLen == 0) return 0;
382 BN_ULONG* d = a->d;
383 int i = intLen - 1;
384 BN_ULONG msd = d[i]; // most significant digit
385 if (a->neg) {
386 // Handle negative values correctly:
387 // i.e. decrement the msd if all other digits are 0:
388 // while ((i > 0) && (d[i] != 0)) { i--; }
389 do { i--; } while (!((i < 0) || (d[i] != 0)));
390 if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
391 }
392 return (intLen - 1) * 32 + BN_num_bits_word(msd);
393}
394
Brian Carlstromec2f5932010-05-07 16:58:16 -0700395static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, BIGNUM* a, int n) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700396 if (!oneValidHandle(env, a)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800397 return (jboolean)BN_is_bit_set(a, n);
398}
399
Brian Carlstromec2f5932010-05-07 16:58:16 -0700400static jboolean NativeBN_modifyBit(JNIEnv* env, jclass, BIGNUM* a, int n, int op) {
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800401// LOGD("NativeBN_BN_modifyBit");
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700402 if (!oneValidHandle(env, a)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800403 switch (op) {
404 case 1: return BN_set_bit(a, n);
405 case 0: return BN_clear_bit(a, n);
406 case -1:
407 if (BN_is_bit_set(a, n)) return BN_clear_bit(a, n);
408 else return BN_set_bit(a, n);
409 }
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700410 return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800411}
412
Brian Carlstromec2f5932010-05-07 16:58:16 -0700413static jboolean NativeBN_BN_shift(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, int n) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700414 if (!twoValidHandles(env, r, a)) return JNI_FALSE;
Elliott Hughes13d47bd2010-02-03 15:23:07 -0800415 return (n >= 0) ? BN_lshift(r, a, n) : BN_rshift(r, a, -n);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800416}
417
Brian Carlstromec2f5932010-05-07 16:58:16 -0700418static jboolean NativeBN_BN_add_word(JNIEnv* env, jclass, BIGNUM *a, BN_ULONG w) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700419 if (!oneValidHandle(env, a)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800420 return BN_add_word(a, w);
421}
422
Brian Carlstromec2f5932010-05-07 16:58:16 -0700423static jboolean NativeBN_BN_sub_word(JNIEnv* env, jclass, BIGNUM *a, BN_ULONG w) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700424 if (!oneValidHandle(env, a)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800425 return BN_sub_word(a, w);
426}
427
Brian Carlstromec2f5932010-05-07 16:58:16 -0700428static jboolean NativeBN_BN_mul_word(JNIEnv* env, jclass, BIGNUM *a, BN_ULONG w) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700429 if (!oneValidHandle(env, a)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800430 return BN_mul_word(a, w);
431}
432
Brian Carlstromec2f5932010-05-07 16:58:16 -0700433static BN_ULONG NativeBN_BN_div_word(JNIEnv* env, jclass, BIGNUM *a, BN_ULONG w) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700434 if (!oneValidHandle(env, a)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800435 return BN_div_word(a, w);
436}
437
Brian Carlstromec2f5932010-05-07 16:58:16 -0700438static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, BIGNUM *a, BN_ULONG w) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700439 if (!oneValidHandle(env, a)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800440 return BN_mod_word(a, w);
441}
442
Brian Carlstromec2f5932010-05-07 16:58:16 -0700443static jboolean NativeBN_BN_add(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700444 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800445 return BN_add(r, a, b);
446}
447
Brian Carlstromec2f5932010-05-07 16:58:16 -0700448static jboolean NativeBN_BN_sub(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700449 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800450 return BN_sub(r, a, b);
451}
452
Elliott Hughes63710432010-06-11 12:58:06 -0700453static jboolean NativeBN_BN_gcd(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700454 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
Elliott Hughes63710432010-06-11 12:58:06 -0700455 Unique_BN_CTX ctx(BN_CTX_new());
456 return BN_gcd(r, a, b, ctx.get());
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800457}
458
Elliott Hughes63710432010-06-11 12:58:06 -0700459static jboolean NativeBN_BN_mul(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700460 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
Elliott Hughes63710432010-06-11 12:58:06 -0700461 Unique_BN_CTX ctx(BN_CTX_new());
462 return BN_mul(r, a, b, ctx.get());
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800463}
464
Elliott Hughes63710432010-06-11 12:58:06 -0700465static jboolean NativeBN_BN_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700466 if (!threeValidHandles(env, r, a, p)) return JNI_FALSE;
Elliott Hughes63710432010-06-11 12:58:06 -0700467 Unique_BN_CTX ctx(BN_CTX_new());
468 return BN_exp(r, a, p, ctx.get());
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800469}
470
Elliott Hughes63710432010-06-11 12:58:06 -0700471static jboolean NativeBN_BN_div(JNIEnv* env, jclass, BIGNUM* dv, BIGNUM* rem, BIGNUM* m, BIGNUM* d) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700472 if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return JNI_FALSE;
Elliott Hughes63710432010-06-11 12:58:06 -0700473 Unique_BN_CTX ctx(BN_CTX_new());
474 return BN_div(dv, rem, m, d, ctx.get());
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800475}
476
Elliott Hughes63710432010-06-11 12:58:06 -0700477static jboolean NativeBN_BN_nnmod(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* m) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700478 if (!threeValidHandles(env, r, a, m)) return JNI_FALSE;
Elliott Hughes63710432010-06-11 12:58:06 -0700479 Unique_BN_CTX ctx(BN_CTX_new());
480 return BN_nnmod(r, a, m, ctx.get());
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800481}
482
Elliott Hughes63710432010-06-11 12:58:06 -0700483static jboolean NativeBN_BN_mod_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p, BIGNUM* m) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700484 if (!fourValidHandles(env, r, a, p, m)) return JNI_FALSE;
Elliott Hughes63710432010-06-11 12:58:06 -0700485 Unique_BN_CTX ctx(BN_CTX_new());
486 return BN_mod_exp(r, a, p, m, ctx.get());
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800487}
488
Elliott Hughes63710432010-06-11 12:58:06 -0700489static jboolean NativeBN_BN_mod_inverse(JNIEnv* env, jclass, BIGNUM* ret, BIGNUM* a, BIGNUM* n) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700490 if (!threeValidHandles(env, ret, a, n)) return JNI_FALSE;
Elliott Hughes63710432010-06-11 12:58:06 -0700491 Unique_BN_CTX ctx(BN_CTX_new());
492 return (BN_mod_inverse(ret, a, n, ctx.get()) != NULL);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800493}
494
Brian Carlstromec2f5932010-05-07 16:58:16 -0700495static jboolean NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, BIGNUM* ret, int bits, jboolean safe,
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800496 BIGNUM* add, BIGNUM* rem, jint cb) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700497 if (!oneValidHandle(env, ret)) return JNI_FALSE;
Elliott Hughes13d47bd2010-02-03 15:23:07 -0800498 return BN_generate_prime_ex(ret, bits, safe, add, rem, (BN_GENCB*) cb);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800499}
500
Elliott Hughes63710432010-06-11 12:58:06 -0700501static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, BIGNUM* p, int nchecks, jint cb) {
Elliott Hughes99c59bf2010-05-17 16:22:04 -0700502 if (!oneValidHandle(env, p)) return JNI_FALSE;
Elliott Hughes63710432010-06-11 12:58:06 -0700503 Unique_BN_CTX ctx(BN_CTX_new());
504 return BN_is_prime_ex(p, nchecks, ctx.get(), (BN_GENCB*) cb);
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800505}
506
Elliott Hughes63710432010-06-11 12:58:06 -0700507static JNINativeMethod gMethods[] = {
508 { "BN_add", "(III)Z", (void*)NativeBN_BN_add },
509 { "BN_add_word", "(II)Z", (void*)NativeBN_BN_add_word },
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800510 { "BN_bin2bn", "([BIZI)Z", (void*)NativeBN_BN_bin2bn },
Elliott Hughes63710432010-06-11 12:58:06 -0700511 { "BN_bn2bin", "(I)[B", (void*)NativeBN_BN_bn2bin },
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800512 { "BN_bn2dec", "(I)Ljava/lang/String;", (void*)NativeBN_BN_bn2dec },
513 { "BN_bn2hex", "(I)Ljava/lang/String;", (void*)NativeBN_BN_bn2hex },
Elliott Hughes63710432010-06-11 12:58:06 -0700514 { "BN_cmp", "(II)I", (void*)NativeBN_BN_cmp },
515 { "BN_copy", "(II)Z", (void*)NativeBN_BN_copy },
516 { "BN_dec2bn", "(ILjava/lang/String;)I", (void*)NativeBN_BN_dec2bn },
517 { "BN_div", "(IIII)Z", (void*)NativeBN_BN_div },
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800518 { "BN_div_word", "(II)I", (void*)NativeBN_BN_div_word },
Elliott Hughes63710432010-06-11 12:58:06 -0700519 { "BN_exp", "(III)Z", (void*)NativeBN_BN_exp },
520 { "BN_free", "(I)V", (void*)NativeBN_BN_free },
521 { "BN_gcd", "(III)Z", (void*)NativeBN_BN_gcd },
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800522 { "BN_generate_prime_ex", "(IIZIII)Z", (void*)NativeBN_BN_generate_prime_ex },
Elliott Hughes63710432010-06-11 12:58:06 -0700523 { "BN_hex2bn", "(ILjava/lang/String;)I", (void*)NativeBN_BN_hex2bn },
524 { "BN_is_bit_set", "(II)Z", (void*)NativeBN_BN_is_bit_set },
525 { "BN_is_prime_ex", "(III)Z", (void*)NativeBN_BN_is_prime_ex },
526 { "BN_mod_exp", "(IIII)Z", (void*)NativeBN_BN_mod_exp },
527 { "BN_mod_inverse", "(III)Z", (void*)NativeBN_BN_mod_inverse },
528 { "BN_mod_word", "(II)I", (void*)NativeBN_BN_mod_word },
529 { "BN_mul", "(III)Z", (void*)NativeBN_BN_mul },
530 { "BN_mul_word", "(II)Z", (void*)NativeBN_BN_mul_word },
531 { "BN_new", "()I", (void*)NativeBN_BN_new },
532 { "BN_nnmod", "(III)Z", (void*)NativeBN_BN_nnmod },
533 { "BN_set_negative", "(II)V", (void*)NativeBN_BN_set_negative },
534 { "BN_shift", "(III)Z", (void*)NativeBN_BN_shift },
535 { "BN_sub", "(III)Z", (void*)NativeBN_BN_sub },
536 { "BN_sub_word", "(II)Z", (void*)NativeBN_BN_sub_word },
537 { "ERR_error_string", "(I)Ljava/lang/String;", (void*)NativeBN_ERR_error_string },
538 { "ERR_get_error", "()I", (void*)NativeBN_ERR_get_error },
539 { "bitLength", "(I)I", (void*)NativeBN_bitLength },
540 { "bn2litEndInts", "(I)[I", (void*)NativeBN_bn2litEndInts },
541 { "litEndInts2bn", "([IIZI)Z", (void*)NativeBN_litEndInts2bn },
542 { "longInt", "(I)J", (void*)NativeBN_longInt },
543 { "modifyBit", "(III)Z", (void*)NativeBN_modifyBit },
544 { "putLongInt", "(IJ)Z", (void*)NativeBN_putLongInt },
545 { "putULongInt", "(IJZ)Z", (void*)NativeBN_putULongInt },
546 { "sign", "(I)I", (void*)NativeBN_sign },
547 { "twosComp2bn", "([BII)Z", (void*)NativeBN_twosComp2bn },
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800548};
Brian Carlstrom12cd1f02010-06-22 23:43:20 -0700549int register_java_math_NativeBN(JNIEnv* env) {
550 return jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
The Android Open Source Projectadc854b2009-03-03 19:28:47 -0800551}