1 /*
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
21 #define LOG_TAG "NativeBN"
22
23 #include "JNIHelp.h"
24 #include "JniConstants.h"
25 #include "ScopedPrimitiveArray.h"
26 #include "ScopedUtfChars.h"
27 #include "UniquePtr.h"
28 #include "jni.h"
29 #include <assert.h>
30 #include <openssl/bn.h>
31 #include <openssl/crypto.h>
32 #include <openssl/err.h>
33 #include <stdio.h>
34
35 struct BN_CTX_Deleter {
operator ()BN_CTX_Deleter36 void operator()(BN_CTX* p) const {
37 BN_CTX_free(p);
38 }
39 };
40 typedef UniquePtr<BN_CTX, BN_CTX_Deleter> Unique_BN_CTX;
41
isValidHandle(JNIEnv * env,void * handle,const char * message)42 static int isValidHandle (JNIEnv* env, void* handle, const char* message) {
43 if (handle == NULL) {
44 jniThrowNullPointerException(env, message);
45 return JNI_FALSE;
46 }
47 return JNI_TRUE;
48 }
49
oneValidHandle(JNIEnv * env,void * a)50 static int oneValidHandle (JNIEnv* env, void* a)
51 {
52 return isValidHandle(env, a, "Mandatory handle (first) passed as null");
53 }
54
twoValidHandles(JNIEnv * env,void * a,void * b)55 static int twoValidHandles (JNIEnv* env, void* a, void* b)
56 {
57 if (!oneValidHandle(env, a)) return JNI_FALSE;
58 return isValidHandle(env, b, "Mandatory handle (second) passed as null");
59 }
60
threeValidHandles(JNIEnv * env,void * a,void * b,void * c)61 static int threeValidHandles (JNIEnv* env, void* a, void* b, void* c)
62 {
63 if (!twoValidHandles(env, a, b)) return JNI_FALSE;
64 return isValidHandle(env, c, "Mandatory handle (third) passed as null");
65 }
66
fourValidHandles(JNIEnv * env,void * a,void * b,void * c,void * d)67 static int fourValidHandles (JNIEnv* env, void* a, void* b, void* c, void* d)
68 {
69 if (!threeValidHandles(env, a, b, c)) return JNI_FALSE;
70 return isValidHandle(env, d, "Mandatory handle (fourth) passed as null");
71 }
72
NativeBN_ERR_get_error(JNIEnv *,jclass)73 static unsigned long NativeBN_ERR_get_error(JNIEnv*, jclass) {
74 return ERR_get_error();
75 }
76
NativeBN_ERR_error_string(JNIEnv * env,jclass,unsigned long e)77 static jstring NativeBN_ERR_error_string(JNIEnv* env, jclass, unsigned long e) {
78 char* errStr = ERR_error_string(e, NULL);
79 return env->NewStringUTF(errStr);
80 }
81
NativeBN_BN_new(JNIEnv *,jclass)82 static BIGNUM* NativeBN_BN_new(JNIEnv*, jclass) {
83 return BN_new();
84 }
85
NativeBN_BN_free(JNIEnv * env,jclass,BIGNUM * a)86 static void NativeBN_BN_free(JNIEnv* env, jclass, BIGNUM* a) {
87 if (!oneValidHandle(env, a)) return;
88 BN_free(a);
89 }
90
NativeBN_BN_cmp(JNIEnv * env,jclass,BIGNUM * a,BIGNUM * b)91 static int NativeBN_BN_cmp(JNIEnv* env, jclass, BIGNUM* a, BIGNUM* b) {
92 if (!twoValidHandles(env, a, b)) return 1;
93 return BN_cmp(a, b);
94 }
95
NativeBN_BN_copy(JNIEnv * env,jclass,BIGNUM * to,BIGNUM * from)96 static jboolean NativeBN_BN_copy(JNIEnv* env, jclass, BIGNUM* to, BIGNUM* from) {
97 if (!twoValidHandles(env, to, from)) return JNI_FALSE;
98 return (BN_copy(to, from) != NULL);
99 }
100
NativeBN_putULongInt(JNIEnv * env,jclass,BIGNUM * a,unsigned long long dw,jboolean neg)101 static jboolean NativeBN_putULongInt(JNIEnv* env, jclass, BIGNUM* a, unsigned long long dw, jboolean neg) {
102 if (!oneValidHandle(env, a)) return JNI_FALSE;
103 unsigned int hi = dw >> 32; // This shifts without sign extension.
104 int lo = (int)dw; // This truncates implicitely.
105
106 // cf. litEndInts2bn:
107 bn_check_top(a);
108 if (bn_wexpand(a, 2) != NULL) {
109 a->d[0] = lo;
110 a->d[1] = hi;
111 a->top = 2;
112 a->neg = neg;
113 bn_correct_top(a);
114 return JNI_TRUE;
115 }
116 else return JNI_FALSE;
117 }
118
NativeBN_putLongInt(JNIEnv * env,jclass cls,BIGNUM * a,long long dw)119 static jboolean NativeBN_putLongInt(JNIEnv* env, jclass cls, BIGNUM* a, long long dw) {
120 if (dw >= 0) return NativeBN_putULongInt(env, cls, a, dw, JNI_FALSE);
121 else return NativeBN_putULongInt(env, cls, a, -dw, JNI_TRUE);
122 }
123
NativeBN_BN_dec2bn(JNIEnv * env,jclass,BIGNUM * a,jstring str)124 static int NativeBN_BN_dec2bn(JNIEnv* env, jclass, BIGNUM* a, jstring str) {
125 if (!oneValidHandle(env, a)) return -1;
126 ScopedUtfChars chars(env, str);
127 if (chars.c_str() == NULL) {
128 return -1;
129 }
130 return BN_dec2bn(&a, chars.c_str());
131 }
132
NativeBN_BN_hex2bn(JNIEnv * env,jclass,BIGNUM * a,jstring str)133 static int NativeBN_BN_hex2bn(JNIEnv* env, jclass, BIGNUM* a, jstring str) {
134 if (!oneValidHandle(env, a)) return -1;
135 ScopedUtfChars chars(env, str);
136 if (chars.c_str() == NULL) {
137 return -1;
138 }
139 return BN_hex2bn(&a, chars.c_str());
140 }
141
NativeBN_BN_bin2bn(JNIEnv * env,jclass,jbyteArray arr,int len,jboolean neg,BIGNUM * ret)142 static jboolean NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, BIGNUM* ret) {
143 if (!oneValidHandle(env, ret)) return JNI_FALSE;
144 ScopedByteArrayRO bytes(env, arr);
145 if (bytes.get() == NULL) {
146 return -1;
147 }
148 jboolean success = (BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, ret) != NULL);
149 if (success && neg) {
150 BN_set_negative(ret, 1);
151 }
152 return success;
153 }
154
155 /**
156 * public static native boolean litEndInts2bn(int[], int, int, int)
157 * Note:
158 * This procedure directly writes the internal representation of BIGNUMs.
159 * We do so as there is no direct interface based on Little Endian Integer Arrays.
160 * Also note that the same representation is used in the Cordoba Java Implementation of BigIntegers,
161 * whereof certain functionality is still being used.
162 */
NativeBN_litEndInts2bn(JNIEnv * env,jclass,jintArray arr,int len,jboolean neg,BIGNUM * ret)163 static jboolean NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len, jboolean neg, BIGNUM* ret) {
164 if (!oneValidHandle(env, ret)) return JNI_FALSE;
165 bn_check_top(ret);
166 if (len > 0) {
167 ScopedIntArrayRO scopedArray(env, arr);
168 if (scopedArray.get() == NULL) {
169 return JNI_FALSE;
170 }
171
172 assert(sizeof(BN_ULONG) == sizeof(jint));
173 const BN_ULONG* tmpInts = reinterpret_cast<const BN_ULONG*>(scopedArray.get());
174 if ((tmpInts != NULL) && (bn_wexpand(ret, len) != NULL)) {
175 int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
176 ret->top = len;
177 ret->neg = neg;
178 // need to call this due to clear byte at top if avoiding
179 // having the top bit set (-ve number)
180 // Basically get rid of top zero ints:
181 bn_correct_top(ret);
182 return JNI_TRUE;
183 } else {
184 return JNI_FALSE;
185 }
186 } else { // (len = 0) means value = 0 and sign will be 0, too.
187 ret->top = 0;
188 return JNI_TRUE;
189 }
190 }
191
192
193 #define BYTES2INT(bytes, k) \
194 ( (bytes[k + 3] & 0xFF) \
195 | (bytes[k + 2] & 0xFF) << 8 \
196 | (bytes[k + 1] & 0xFF) << 16 \
197 | (bytes[k + 0] & 0xFF) << 24 )
198
negBigEndianBytes2bn(JNIEnv *,jclass,const unsigned char * bytes,int bytesLen,BIGNUM * ret)199 static jboolean negBigEndianBytes2bn(JNIEnv*, jclass, const unsigned char* bytes, int bytesLen, BIGNUM* ret) {
200 // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
201 //
202 bn_check_top(ret);
203 // FIXME: ASSERT (bytesLen > 0);
204 int intLen = (bytesLen + 3) / 4;
205 int firstNonzeroDigit = -2;
206 if (bn_wexpand(ret, intLen) != NULL) {
207 BN_ULONG* d = ret->d;
208 BN_ULONG di;
209 ret->top = intLen;
210 int highBytes = bytesLen % 4;
211 int k = bytesLen;
212 // Put bytes to the int array starting from the end of the byte array
213 int i = 0;
214 while (k > highBytes) {
215 k -= 4;
216 di = BYTES2INT(bytes, k);
217 if (di != 0) {
218 d[i] = -di;
219 firstNonzeroDigit = i;
220 i++;
221 while (k > highBytes) {
222 k -= 4;
223 d[i] = ~BYTES2INT(bytes, k);
224 i++;
225 }
226 break;
227 } else {
228 d[i] = 0;
229 i++;
230 }
231 }
232 if (highBytes != 0) {
233 di = -1;
234 // Put the first bytes in the highest element of the int array
235 if (firstNonzeroDigit != -2) {
236 for (k = 0; k < highBytes; k++) {
237 di = (di << 8) | (bytes[k] & 0xFF);
238 }
239 d[i] = ~di;
240 } else {
241 for (k = 0; k < highBytes; k++) {
242 di = (di << 8) | (bytes[k] & 0xFF);
243 }
244 d[i] = -di;
245 }
246 }
247 return JNI_TRUE;
248 }
249 else return JNI_FALSE;
250 }
251
NativeBN_twosComp2bn(JNIEnv * env,jclass cls,jbyteArray arr,int bytesLen,BIGNUM * ret)252 static jboolean NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, BIGNUM* ret) {
253 if (!oneValidHandle(env, ret)) return JNI_FALSE;
254 ScopedByteArrayRO bytes(env, arr);
255 if (bytes.get() == NULL) {
256 return -1;
257 }
258 jboolean success;
259 const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get());
260 if ((bytes[0] & 0X80) == 0) { // Positive value!
261 //
262 // We can use the existing BN implementation for unsigned big endian bytes:
263 //
264 success = (BN_bin2bn(s, bytesLen, ret) != NULL);
265 BN_set_negative(ret, JNI_FALSE);
266 } else { // Negative value!
267 //
268 // We need to apply two's complement:
269 //
270 success = negBigEndianBytes2bn(env, cls, s, bytesLen, ret);
271 BN_set_negative(ret, JNI_TRUE);
272 }
273 return success;
274 }
275
NativeBN_longInt(JNIEnv * env,jclass,BIGNUM * a)276 static long long NativeBN_longInt(JNIEnv* env, jclass, BIGNUM* a) {
277 if (!oneValidHandle(env, a)) return -1;
278 bn_check_top(a);
279 int intLen = a->top;
280 BN_ULONG* d = a->d;
281 switch (intLen) {
282 case 0:
283 return 0;
284 case 1:
285 if (!a->neg) return d[0] & 0X00000000FFFFFFFFLL;
286 else return -(d[0] & 0X00000000FFFFFFFFLL);
287 default:
288 if (!a->neg) return ((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL);
289 else return -(((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL));
290 }
291 }
292
leadingZerosTrimmed(char * s)293 static char* leadingZerosTrimmed(char* s) {
294 char* p = s;
295 if (*p == '-') {
296 p++;
297 while ((*p == '0') && (*(p + 1) != 0)) { p++; }
298 p--;
299 *p = '-';
300 } else {
301 while ((*p == '0') && (*(p + 1) != 0)) { p++; }
302 }
303 return p;
304 }
305
NativeBN_BN_bn2dec(JNIEnv * env,jclass,BIGNUM * a)306 static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, BIGNUM* a) {
307 if (!oneValidHandle(env, a)) return NULL;
308 char* tmpStr;
309 char* retStr;
310 tmpStr = BN_bn2dec(a);
311 if (tmpStr != NULL) {
312 retStr = leadingZerosTrimmed(tmpStr);
313 jstring returnJString = env->NewStringUTF(retStr);
314 OPENSSL_free(tmpStr);
315 return returnJString;
316 }
317 else return NULL;
318 }
319
NativeBN_BN_bn2hex(JNIEnv * env,jclass,BIGNUM * a)320 static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, BIGNUM* a) {
321 if (!oneValidHandle(env, a)) return NULL;
322 char* tmpStr;
323 char* retStr;
324 tmpStr = BN_bn2hex(a);
325 if (tmpStr != NULL) {
326 retStr = leadingZerosTrimmed(tmpStr);
327 jstring returnJString = env->NewStringUTF(retStr);
328 OPENSSL_free(tmpStr);
329 return returnJString;
330 }
331 else return NULL;
332 }
333
NativeBN_BN_bn2bin(JNIEnv * env,jclass,BIGNUM * a)334 static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, BIGNUM* a) {
335 if (!oneValidHandle(env, a)) return NULL;
336 jbyteArray result = env->NewByteArray(BN_num_bytes(a));
337 if (result == NULL) {
338 return NULL;
339 }
340 ScopedByteArrayRW bytes(env, result);
341 if (bytes.get() == NULL) {
342 return NULL;
343 }
344 BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
345 return result;
346 }
347
NativeBN_bn2litEndInts(JNIEnv * env,jclass,BIGNUM * a)348 static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, BIGNUM* a) {
349 if (!oneValidHandle(env, a)) return NULL;
350 bn_check_top(a);
351 int len = a->top;
352 if (len == 0) {
353 return NULL;
354 }
355 jintArray result = env->NewIntArray(len);
356 if (result == NULL) {
357 return NULL;
358 }
359 ScopedIntArrayRW ints(env, result);
360 if (ints.get() == NULL) {
361 return NULL;
362 }
363 BN_ULONG* ulongs = reinterpret_cast<BN_ULONG*>(ints.get());
364 if (ulongs == NULL) {
365 return NULL;
366 }
367 int i = len; do { i--; ulongs[i] = a->d[i]; } while (i > 0);
368 return result;
369 }
370
NativeBN_sign(JNIEnv * env,jclass,BIGNUM * a)371 static int NativeBN_sign(JNIEnv* env, jclass, BIGNUM* a) {
372 if (!oneValidHandle(env, a)) return -2;
373 if (BN_is_zero(a)) return 0;
374 else if (BN_is_negative(a)) return -1;
375 else return 1;
376 }
377
NativeBN_BN_set_negative(JNIEnv * env,jclass,BIGNUM * b,int n)378 static void NativeBN_BN_set_negative(JNIEnv* env, jclass, BIGNUM* b, int n) {
379 if (!oneValidHandle(env, b)) return;
380 BN_set_negative(b, n);
381 }
382
NativeBN_bitLength(JNIEnv * env,jclass,BIGNUM * a)383 static int NativeBN_bitLength(JNIEnv* env, jclass, BIGNUM* a) {
384 // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
385 //
386 if (!oneValidHandle(env, a)) return JNI_FALSE;
387 bn_check_top(a);
388 int intLen = a->top;
389 if (intLen == 0) return 0;
390 BN_ULONG* d = a->d;
391 int i = intLen - 1;
392 BN_ULONG msd = d[i]; // most significant digit
393 if (a->neg) {
394 // Handle negative values correctly:
395 // i.e. decrement the msd if all other digits are 0:
396 // while ((i > 0) && (d[i] != 0)) { i--; }
397 do { i--; } while (!((i < 0) || (d[i] != 0)));
398 if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
399 }
400 return (intLen - 1) * 32 + BN_num_bits_word(msd);
401 }
402
NativeBN_BN_is_bit_set(JNIEnv * env,jclass,BIGNUM * a,int n)403 static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, BIGNUM* a, int n) {
404 if (!oneValidHandle(env, a)) return JNI_FALSE;
405 return (jboolean)BN_is_bit_set(a, n);
406 }
407
NativeBN_modifyBit(JNIEnv * env,jclass,BIGNUM * a,int n,int op)408 static jboolean NativeBN_modifyBit(JNIEnv* env, jclass, BIGNUM* a, int n, int op) {
409 // LOGD("NativeBN_BN_modifyBit");
410 if (!oneValidHandle(env, a)) return JNI_FALSE;
411 switch (op) {
412 case 1: return BN_set_bit(a, n);
413 case 0: return BN_clear_bit(a, n);
414 case -1:
415 if (BN_is_bit_set(a, n)) return BN_clear_bit(a, n);
416 else return BN_set_bit(a, n);
417 }
418 return JNI_FALSE;
419 }
420
NativeBN_BN_shift(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,int n)421 static jboolean NativeBN_BN_shift(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, int n) {
422 if (!twoValidHandles(env, r, a)) return JNI_FALSE;
423 return (n >= 0) ? BN_lshift(r, a, n) : BN_rshift(r, a, -n);
424 }
425
NativeBN_BN_add_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)426 static jboolean NativeBN_BN_add_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
427 if (!oneValidHandle(env, a)) return JNI_FALSE;
428 return BN_add_word(a, w);
429 }
430
NativeBN_BN_sub_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)431 static jboolean NativeBN_BN_sub_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
432 if (!oneValidHandle(env, a)) return JNI_FALSE;
433 return BN_sub_word(a, w);
434 }
435
NativeBN_BN_mul_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)436 static jboolean NativeBN_BN_mul_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
437 if (!oneValidHandle(env, a)) return JNI_FALSE;
438 return BN_mul_word(a, w);
439 }
440
NativeBN_BN_div_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)441 static BN_ULONG NativeBN_BN_div_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
442 if (!oneValidHandle(env, a)) return JNI_FALSE;
443 return BN_div_word(a, w);
444 }
445
NativeBN_BN_mod_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)446 static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
447 if (!oneValidHandle(env, a)) return JNI_FALSE;
448 return BN_mod_word(a, w);
449 }
450
NativeBN_BN_add(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)451 static jboolean NativeBN_BN_add(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
452 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
453 return BN_add(r, a, b);
454 }
455
NativeBN_BN_sub(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)456 static jboolean NativeBN_BN_sub(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
457 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
458 return BN_sub(r, a, b);
459 }
460
NativeBN_BN_gcd(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)461 static jboolean NativeBN_BN_gcd(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
462 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
463 Unique_BN_CTX ctx(BN_CTX_new());
464 return BN_gcd(r, a, b, ctx.get());
465 }
466
NativeBN_BN_mul(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)467 static jboolean NativeBN_BN_mul(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
468 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
469 Unique_BN_CTX ctx(BN_CTX_new());
470 return BN_mul(r, a, b, ctx.get());
471 }
472
NativeBN_BN_exp(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * p)473 static jboolean NativeBN_BN_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p) {
474 if (!threeValidHandles(env, r, a, p)) return JNI_FALSE;
475 Unique_BN_CTX ctx(BN_CTX_new());
476 return BN_exp(r, a, p, ctx.get());
477 }
478
NativeBN_BN_div(JNIEnv * env,jclass,BIGNUM * dv,BIGNUM * rem,BIGNUM * m,BIGNUM * d)479 static jboolean NativeBN_BN_div(JNIEnv* env, jclass, BIGNUM* dv, BIGNUM* rem, BIGNUM* m, BIGNUM* d) {
480 if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return JNI_FALSE;
481 Unique_BN_CTX ctx(BN_CTX_new());
482 return BN_div(dv, rem, m, d, ctx.get());
483 }
484
NativeBN_BN_nnmod(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * m)485 static jboolean NativeBN_BN_nnmod(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* m) {
486 if (!threeValidHandles(env, r, a, m)) return JNI_FALSE;
487 Unique_BN_CTX ctx(BN_CTX_new());
488 return BN_nnmod(r, a, m, ctx.get());
489 }
490
NativeBN_BN_mod_exp(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * p,BIGNUM * m)491 static jboolean NativeBN_BN_mod_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p, BIGNUM* m) {
492 if (!fourValidHandles(env, r, a, p, m)) return JNI_FALSE;
493 Unique_BN_CTX ctx(BN_CTX_new());
494 return BN_mod_exp(r, a, p, m, ctx.get());
495 }
496
NativeBN_BN_mod_inverse(JNIEnv * env,jclass,BIGNUM * ret,BIGNUM * a,BIGNUM * n)497 static jboolean NativeBN_BN_mod_inverse(JNIEnv* env, jclass, BIGNUM* ret, BIGNUM* a, BIGNUM* n) {
498 if (!threeValidHandles(env, ret, a, n)) return JNI_FALSE;
499 Unique_BN_CTX ctx(BN_CTX_new());
500 return (BN_mod_inverse(ret, a, n, ctx.get()) != NULL);
501 }
502
NativeBN_BN_generate_prime_ex(JNIEnv * env,jclass,BIGNUM * ret,int bits,jboolean safe,BIGNUM * add,BIGNUM * rem,jint cb)503 static jboolean NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, BIGNUM* ret, int bits, jboolean safe,
504 BIGNUM* add, BIGNUM* rem, jint cb) {
505 if (!oneValidHandle(env, ret)) return JNI_FALSE;
506 return BN_generate_prime_ex(ret, bits, safe, add, rem, reinterpret_cast<BN_GENCB*>(cb));
507 }
508
NativeBN_BN_is_prime_ex(JNIEnv * env,jclass,BIGNUM * p,int nchecks,jint cb)509 static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, BIGNUM* p, int nchecks, jint cb) {
510 if (!oneValidHandle(env, p)) return JNI_FALSE;
511 Unique_BN_CTX ctx(BN_CTX_new());
512 return BN_is_prime_ex(p, nchecks, ctx.get(), reinterpret_cast<BN_GENCB*>(cb));
513 }
514
515 static JNINativeMethod gMethods[] = {
516 NATIVE_METHOD(NativeBN, BN_add, "(III)Z"),
517 NATIVE_METHOD(NativeBN, BN_add_word, "(II)Z"),
518 NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZI)Z"),
519 NATIVE_METHOD(NativeBN, BN_bn2bin, "(I)[B"),
520 NATIVE_METHOD(NativeBN, BN_bn2dec, "(I)Ljava/lang/String;"),
521 NATIVE_METHOD(NativeBN, BN_bn2hex, "(I)Ljava/lang/String;"),
522 NATIVE_METHOD(NativeBN, BN_cmp, "(II)I"),
523 NATIVE_METHOD(NativeBN, BN_copy, "(II)Z"),
524 NATIVE_METHOD(NativeBN, BN_dec2bn, "(ILjava/lang/String;)I"),
525 NATIVE_METHOD(NativeBN, BN_div, "(IIII)Z"),
526 NATIVE_METHOD(NativeBN, BN_div_word, "(II)I"),
527 NATIVE_METHOD(NativeBN, BN_exp, "(III)Z"),
528 NATIVE_METHOD(NativeBN, BN_free, "(I)V"),
529 NATIVE_METHOD(NativeBN, BN_gcd, "(III)Z"),
530 NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(IIZIII)Z"),
531 NATIVE_METHOD(NativeBN, BN_hex2bn, "(ILjava/lang/String;)I"),
532 NATIVE_METHOD(NativeBN, BN_is_bit_set, "(II)Z"),
533 NATIVE_METHOD(NativeBN, BN_is_prime_ex, "(III)Z"),
534 NATIVE_METHOD(NativeBN, BN_mod_exp, "(IIII)Z"),
535 NATIVE_METHOD(NativeBN, BN_mod_inverse, "(III)Z"),
536 NATIVE_METHOD(NativeBN, BN_mod_word, "(II)I"),
537 NATIVE_METHOD(NativeBN, BN_mul, "(III)Z"),
538 NATIVE_METHOD(NativeBN, BN_mul_word, "(II)Z"),
539 NATIVE_METHOD(NativeBN, BN_new, "()I"),
540 NATIVE_METHOD(NativeBN, BN_nnmod, "(III)Z"),
541 NATIVE_METHOD(NativeBN, BN_set_negative, "(II)V"),
542 NATIVE_METHOD(NativeBN, BN_shift, "(III)Z"),
543 NATIVE_METHOD(NativeBN, BN_sub, "(III)Z"),
544 NATIVE_METHOD(NativeBN, BN_sub_word, "(II)Z"),
545 NATIVE_METHOD(NativeBN, ERR_error_string, "(I)Ljava/lang/String;"),
546 NATIVE_METHOD(NativeBN, ERR_get_error, "()I"),
547 NATIVE_METHOD(NativeBN, bitLength, "(I)I"),
548 NATIVE_METHOD(NativeBN, bn2litEndInts, "(I)[I"),
549 NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZI)Z"),
550 NATIVE_METHOD(NativeBN, longInt, "(I)J"),
551 NATIVE_METHOD(NativeBN, modifyBit, "(III)Z"),
552 NATIVE_METHOD(NativeBN, putLongInt, "(IJ)Z"),
553 NATIVE_METHOD(NativeBN, putULongInt, "(IJZ)Z"),
554 NATIVE_METHOD(NativeBN, sign, "(I)I"),
555 NATIVE_METHOD(NativeBN, twosComp2bn, "([BII)Z"),
556 };
register_java_math_NativeBN(JNIEnv * env)557 int register_java_math_NativeBN(JNIEnv* env) {
558 return jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
559 }
560