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 "StaticAssert.h"
28 #include "UniquePtr.h"
29 #include "jni.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 STATIC_ASSERT(sizeof(BN_ULONG) == sizeof(jint), BN_ULONG_not_32_bit);
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 bn_check_top(ret);
202 // FIXME: assert bytesLen > 0
203 int intLen = (bytesLen + 3) / 4;
204 int firstNonzeroDigit = -2;
205 if (bn_wexpand(ret, intLen) != NULL) {
206 BN_ULONG* d = ret->d;
207 BN_ULONG di;
208 ret->top = intLen;
209 int highBytes = bytesLen % 4;
210 int k = bytesLen;
211 // Put bytes to the int array starting from the end of the byte array
212 int i = 0;
213 while (k > highBytes) {
214 k -= 4;
215 di = BYTES2INT(bytes, k);
216 if (di != 0) {
217 d[i] = -di;
218 firstNonzeroDigit = i;
219 i++;
220 while (k > highBytes) {
221 k -= 4;
222 d[i] = ~BYTES2INT(bytes, k);
223 i++;
224 }
225 break;
226 } else {
227 d[i] = 0;
228 i++;
229 }
230 }
231 if (highBytes != 0) {
232 di = -1;
233 // Put the first bytes in the highest element of the int array
234 if (firstNonzeroDigit != -2) {
235 for (k = 0; k < highBytes; k++) {
236 di = (di << 8) | (bytes[k] & 0xFF);
237 }
238 d[i] = ~di;
239 } else {
240 for (k = 0; k < highBytes; k++) {
241 di = (di << 8) | (bytes[k] & 0xFF);
242 }
243 d[i] = -di;
244 }
245 }
246 return JNI_TRUE;
247 }
248 else return JNI_FALSE;
249 }
250
NativeBN_twosComp2bn(JNIEnv * env,jclass cls,jbyteArray arr,int bytesLen,BIGNUM * ret)251 static jboolean NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, BIGNUM* ret) {
252 if (!oneValidHandle(env, ret)) return JNI_FALSE;
253 ScopedByteArrayRO bytes(env, arr);
254 if (bytes.get() == NULL) {
255 return -1;
256 }
257 jboolean success;
258 const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get());
259 if ((bytes[0] & 0X80) == 0) { // Positive value!
260 //
261 // We can use the existing BN implementation for unsigned big endian bytes:
262 //
263 success = (BN_bin2bn(s, bytesLen, ret) != NULL);
264 BN_set_negative(ret, JNI_FALSE);
265 } else { // Negative value!
266 //
267 // We need to apply two's complement:
268 //
269 success = negBigEndianBytes2bn(env, cls, s, bytesLen, ret);
270 BN_set_negative(ret, JNI_TRUE);
271 }
272 return success;
273 }
274
NativeBN_longInt(JNIEnv * env,jclass,BIGNUM * a)275 static long long NativeBN_longInt(JNIEnv* env, jclass, BIGNUM* a) {
276 if (!oneValidHandle(env, a)) return -1;
277 bn_check_top(a);
278 int intLen = a->top;
279 BN_ULONG* d = a->d;
280 switch (intLen) {
281 case 0:
282 return 0;
283 case 1:
284 if (!a->neg) return d[0] & 0X00000000FFFFFFFFLL;
285 else return -(d[0] & 0X00000000FFFFFFFFLL);
286 default:
287 if (!a->neg) return ((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL);
288 else return -(((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL));
289 }
290 }
291
leadingZerosTrimmed(char * s)292 static char* leadingZerosTrimmed(char* s) {
293 char* p = s;
294 if (*p == '-') {
295 p++;
296 while ((*p == '0') && (*(p + 1) != 0)) { p++; }
297 p--;
298 *p = '-';
299 } else {
300 while ((*p == '0') && (*(p + 1) != 0)) { p++; }
301 }
302 return p;
303 }
304
NativeBN_BN_bn2dec(JNIEnv * env,jclass,BIGNUM * a)305 static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, BIGNUM* a) {
306 if (!oneValidHandle(env, a)) return NULL;
307 char* tmpStr;
308 char* retStr;
309 tmpStr = BN_bn2dec(a);
310 if (tmpStr != NULL) {
311 retStr = leadingZerosTrimmed(tmpStr);
312 jstring returnJString = env->NewStringUTF(retStr);
313 OPENSSL_free(tmpStr);
314 return returnJString;
315 }
316 else return NULL;
317 }
318
NativeBN_BN_bn2hex(JNIEnv * env,jclass,BIGNUM * a)319 static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, BIGNUM* a) {
320 if (!oneValidHandle(env, a)) return NULL;
321 char* tmpStr;
322 char* retStr;
323 tmpStr = BN_bn2hex(a);
324 if (tmpStr != NULL) {
325 retStr = leadingZerosTrimmed(tmpStr);
326 jstring returnJString = env->NewStringUTF(retStr);
327 OPENSSL_free(tmpStr);
328 return returnJString;
329 }
330 else return NULL;
331 }
332
NativeBN_BN_bn2bin(JNIEnv * env,jclass,BIGNUM * a)333 static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, BIGNUM* a) {
334 if (!oneValidHandle(env, a)) return NULL;
335 jbyteArray result = env->NewByteArray(BN_num_bytes(a));
336 if (result == NULL) {
337 return NULL;
338 }
339 ScopedByteArrayRW bytes(env, result);
340 if (bytes.get() == NULL) {
341 return NULL;
342 }
343 BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
344 return result;
345 }
346
NativeBN_bn2litEndInts(JNIEnv * env,jclass,BIGNUM * a)347 static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, BIGNUM* a) {
348 if (!oneValidHandle(env, a)) return NULL;
349 bn_check_top(a);
350 int len = a->top;
351 if (len == 0) {
352 return NULL;
353 }
354 jintArray result = env->NewIntArray(len);
355 if (result == NULL) {
356 return NULL;
357 }
358 ScopedIntArrayRW ints(env, result);
359 if (ints.get() == NULL) {
360 return NULL;
361 }
362 BN_ULONG* ulongs = reinterpret_cast<BN_ULONG*>(ints.get());
363 if (ulongs == NULL) {
364 return NULL;
365 }
366 int i = len; do { i--; ulongs[i] = a->d[i]; } while (i > 0);
367 return result;
368 }
369
NativeBN_sign(JNIEnv * env,jclass,BIGNUM * a)370 static int NativeBN_sign(JNIEnv* env, jclass, BIGNUM* a) {
371 if (!oneValidHandle(env, a)) return -2;
372 if (BN_is_zero(a)) return 0;
373 else if (BN_is_negative(a)) return -1;
374 else return 1;
375 }
376
NativeBN_BN_set_negative(JNIEnv * env,jclass,BIGNUM * b,int n)377 static void NativeBN_BN_set_negative(JNIEnv* env, jclass, BIGNUM* b, int n) {
378 if (!oneValidHandle(env, b)) return;
379 BN_set_negative(b, n);
380 }
381
NativeBN_bitLength(JNIEnv * env,jclass,BIGNUM * a)382 static int NativeBN_bitLength(JNIEnv* env, jclass, BIGNUM* a) {
383 // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
384 //
385 if (!oneValidHandle(env, a)) return JNI_FALSE;
386 bn_check_top(a);
387 int intLen = a->top;
388 if (intLen == 0) return 0;
389 BN_ULONG* d = a->d;
390 int i = intLen - 1;
391 BN_ULONG msd = d[i]; // most significant digit
392 if (a->neg) {
393 // Handle negative values correctly:
394 // i.e. decrement the msd if all other digits are 0:
395 // while ((i > 0) && (d[i] != 0)) { i--; }
396 do { i--; } while (!((i < 0) || (d[i] != 0)));
397 if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
398 }
399 return (intLen - 1) * 32 + BN_num_bits_word(msd);
400 }
401
NativeBN_BN_is_bit_set(JNIEnv * env,jclass,BIGNUM * a,int n)402 static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, BIGNUM* a, int n) {
403 if (!oneValidHandle(env, a)) return JNI_FALSE;
404 return (jboolean)BN_is_bit_set(a, n);
405 }
406
NativeBN_modifyBit(JNIEnv * env,jclass,BIGNUM * a,int n,int op)407 static jboolean NativeBN_modifyBit(JNIEnv* env, jclass, BIGNUM* a, int n, int op) {
408 // ALOGD("NativeBN_BN_modifyBit");
409 if (!oneValidHandle(env, a)) return JNI_FALSE;
410 switch (op) {
411 case 1: return BN_set_bit(a, n);
412 case 0: return BN_clear_bit(a, n);
413 case -1:
414 if (BN_is_bit_set(a, n)) return BN_clear_bit(a, n);
415 else return BN_set_bit(a, n);
416 }
417 return JNI_FALSE;
418 }
419
NativeBN_BN_shift(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,int n)420 static jboolean NativeBN_BN_shift(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, int n) {
421 if (!twoValidHandles(env, r, a)) return JNI_FALSE;
422 return (n >= 0) ? BN_lshift(r, a, n) : BN_rshift(r, a, -n);
423 }
424
NativeBN_BN_add_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)425 static jboolean NativeBN_BN_add_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
426 if (!oneValidHandle(env, a)) return JNI_FALSE;
427 return BN_add_word(a, w);
428 }
429
NativeBN_BN_sub_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)430 static jboolean NativeBN_BN_sub_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
431 if (!oneValidHandle(env, a)) return JNI_FALSE;
432 return BN_sub_word(a, w);
433 }
434
NativeBN_BN_mul_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)435 static jboolean NativeBN_BN_mul_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
436 if (!oneValidHandle(env, a)) return JNI_FALSE;
437 return BN_mul_word(a, w);
438 }
439
NativeBN_BN_div_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)440 static BN_ULONG NativeBN_BN_div_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
441 if (!oneValidHandle(env, a)) return JNI_FALSE;
442 return BN_div_word(a, w);
443 }
444
NativeBN_BN_mod_word(JNIEnv * env,jclass,BIGNUM * a,BN_ULONG w)445 static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
446 if (!oneValidHandle(env, a)) return JNI_FALSE;
447 return BN_mod_word(a, w);
448 }
449
NativeBN_BN_add(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)450 static jboolean NativeBN_BN_add(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
451 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
452 return BN_add(r, a, b);
453 }
454
NativeBN_BN_sub(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)455 static jboolean NativeBN_BN_sub(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
456 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
457 return BN_sub(r, a, b);
458 }
459
NativeBN_BN_gcd(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)460 static jboolean NativeBN_BN_gcd(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
461 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
462 Unique_BN_CTX ctx(BN_CTX_new());
463 return BN_gcd(r, a, b, ctx.get());
464 }
465
NativeBN_BN_mul(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * b)466 static jboolean NativeBN_BN_mul(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
467 if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
468 Unique_BN_CTX ctx(BN_CTX_new());
469 return BN_mul(r, a, b, ctx.get());
470 }
471
NativeBN_BN_exp(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * p)472 static jboolean NativeBN_BN_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p) {
473 if (!threeValidHandles(env, r, a, p)) return JNI_FALSE;
474 Unique_BN_CTX ctx(BN_CTX_new());
475 return BN_exp(r, a, p, ctx.get());
476 }
477
NativeBN_BN_div(JNIEnv * env,jclass,BIGNUM * dv,BIGNUM * rem,BIGNUM * m,BIGNUM * d)478 static jboolean NativeBN_BN_div(JNIEnv* env, jclass, BIGNUM* dv, BIGNUM* rem, BIGNUM* m, BIGNUM* d) {
479 if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return JNI_FALSE;
480 Unique_BN_CTX ctx(BN_CTX_new());
481 return BN_div(dv, rem, m, d, ctx.get());
482 }
483
NativeBN_BN_nnmod(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * m)484 static jboolean NativeBN_BN_nnmod(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* m) {
485 if (!threeValidHandles(env, r, a, m)) return JNI_FALSE;
486 Unique_BN_CTX ctx(BN_CTX_new());
487 return BN_nnmod(r, a, m, ctx.get());
488 }
489
NativeBN_BN_mod_exp(JNIEnv * env,jclass,BIGNUM * r,BIGNUM * a,BIGNUM * p,BIGNUM * m)490 static jboolean NativeBN_BN_mod_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p, BIGNUM* m) {
491 if (!fourValidHandles(env, r, a, p, m)) return JNI_FALSE;
492 Unique_BN_CTX ctx(BN_CTX_new());
493 return BN_mod_exp(r, a, p, m, ctx.get());
494 }
495
NativeBN_BN_mod_inverse(JNIEnv * env,jclass,BIGNUM * ret,BIGNUM * a,BIGNUM * n)496 static jboolean NativeBN_BN_mod_inverse(JNIEnv* env, jclass, BIGNUM* ret, BIGNUM* a, BIGNUM* n) {
497 if (!threeValidHandles(env, ret, a, n)) return JNI_FALSE;
498 Unique_BN_CTX ctx(BN_CTX_new());
499 return (BN_mod_inverse(ret, a, n, ctx.get()) != NULL);
500 }
501
NativeBN_BN_generate_prime_ex(JNIEnv * env,jclass,BIGNUM * ret,int bits,jboolean safe,BIGNUM * add,BIGNUM * rem,jint cb)502 static jboolean NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, BIGNUM* ret, int bits, jboolean safe,
503 BIGNUM* add, BIGNUM* rem, jint cb) {
504 if (!oneValidHandle(env, ret)) return JNI_FALSE;
505 return BN_generate_prime_ex(ret, bits, safe, add, rem, reinterpret_cast<BN_GENCB*>(cb));
506 }
507
NativeBN_BN_is_prime_ex(JNIEnv * env,jclass,BIGNUM * p,int nchecks,jint cb)508 static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, BIGNUM* p, int nchecks, jint cb) {
509 if (!oneValidHandle(env, p)) return JNI_FALSE;
510 Unique_BN_CTX ctx(BN_CTX_new());
511 return BN_is_prime_ex(p, nchecks, ctx.get(), reinterpret_cast<BN_GENCB*>(cb));
512 }
513
514 static JNINativeMethod gMethods[] = {
515 NATIVE_METHOD(NativeBN, BN_add, "(III)Z"),
516 NATIVE_METHOD(NativeBN, BN_add_word, "(II)Z"),
517 NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZI)Z"),
518 NATIVE_METHOD(NativeBN, BN_bn2bin, "(I)[B"),
519 NATIVE_METHOD(NativeBN, BN_bn2dec, "(I)Ljava/lang/String;"),
520 NATIVE_METHOD(NativeBN, BN_bn2hex, "(I)Ljava/lang/String;"),
521 NATIVE_METHOD(NativeBN, BN_cmp, "(II)I"),
522 NATIVE_METHOD(NativeBN, BN_copy, "(II)Z"),
523 NATIVE_METHOD(NativeBN, BN_dec2bn, "(ILjava/lang/String;)I"),
524 NATIVE_METHOD(NativeBN, BN_div, "(IIII)Z"),
525 NATIVE_METHOD(NativeBN, BN_div_word, "(II)I"),
526 NATIVE_METHOD(NativeBN, BN_exp, "(III)Z"),
527 NATIVE_METHOD(NativeBN, BN_free, "(I)V"),
528 NATIVE_METHOD(NativeBN, BN_gcd, "(III)Z"),
529 NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(IIZIII)Z"),
530 NATIVE_METHOD(NativeBN, BN_hex2bn, "(ILjava/lang/String;)I"),
531 NATIVE_METHOD(NativeBN, BN_is_bit_set, "(II)Z"),
532 NATIVE_METHOD(NativeBN, BN_is_prime_ex, "(III)Z"),
533 NATIVE_METHOD(NativeBN, BN_mod_exp, "(IIII)Z"),
534 NATIVE_METHOD(NativeBN, BN_mod_inverse, "(III)Z"),
535 NATIVE_METHOD(NativeBN, BN_mod_word, "(II)I"),
536 NATIVE_METHOD(NativeBN, BN_mul, "(III)Z"),
537 NATIVE_METHOD(NativeBN, BN_mul_word, "(II)Z"),
538 NATIVE_METHOD(NativeBN, BN_new, "()I"),
539 NATIVE_METHOD(NativeBN, BN_nnmod, "(III)Z"),
540 NATIVE_METHOD(NativeBN, BN_set_negative, "(II)V"),
541 NATIVE_METHOD(NativeBN, BN_shift, "(III)Z"),
542 NATIVE_METHOD(NativeBN, BN_sub, "(III)Z"),
543 NATIVE_METHOD(NativeBN, BN_sub_word, "(II)Z"),
544 NATIVE_METHOD(NativeBN, ERR_error_string, "(I)Ljava/lang/String;"),
545 NATIVE_METHOD(NativeBN, ERR_get_error, "()I"),
546 NATIVE_METHOD(NativeBN, bitLength, "(I)I"),
547 NATIVE_METHOD(NativeBN, bn2litEndInts, "(I)[I"),
548 NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZI)Z"),
549 NATIVE_METHOD(NativeBN, longInt, "(I)J"),
550 NATIVE_METHOD(NativeBN, modifyBit, "(III)Z"),
551 NATIVE_METHOD(NativeBN, putLongInt, "(IJ)Z"),
552 NATIVE_METHOD(NativeBN, putULongInt, "(IJZ)Z"),
553 NATIVE_METHOD(NativeBN, sign, "(I)I"),
554 NATIVE_METHOD(NativeBN, twosComp2bn, "([BII)Z"),
555 };
register_java_math_NativeBN(JNIEnv * env)556 void register_java_math_NativeBN(JNIEnv* env) {
557 jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
558 }
559