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 #include <jni.h>
22 #include <JNIHelp.h>
23 #include <openssl/err.h>
24 #include <openssl/crypto.h>
25 #include <openssl/bn.h>
26 #include <stdio.h>
27
28 #define mcSignednessBull void *
29 #ifndef FALSE
30 #define FALSE 0
31 #define TRUE 1
32 #endif
33
34
35 static void
throwOutOfMemoryException(JNIEnv * env,const char * message)36 throwOutOfMemoryException(JNIEnv* env, const char* message)
37 {
38 jniThrowException(env, "java/lang/OutOfMemoryError", message);
39 }
40
41 static void
throwNewNullPointerException(JNIEnv * env,const char * message)42 throwNewNullPointerException (JNIEnv* env, const char* message)
43 {
44 jniThrowException(env, "java/lang/NullPointerException", message);
45 }
46
isValidHandle(JNIEnv * env,void * handle,const char * message)47 static int isValidHandle (JNIEnv* env, void* handle, const char *message)
48 {
49 if (handle == NULL) {
50 throwNewNullPointerException(env, message);
51 return FALSE;
52 }
53 else return TRUE;
54 }
55
oneValidHandle(JNIEnv * env,void * a)56 static int oneValidHandle (JNIEnv* env, void* a)
57 {
58 return isValidHandle(env, a, "Mandatory handle (first) passed as null");
59 }
60
twoValidHandles(JNIEnv * env,void * a,void * b)61 static int twoValidHandles (JNIEnv* env, void* a, void *b)
62 {
63 if (!oneValidHandle(env, a)) return FALSE;
64 return isValidHandle(env, b, "Mandatory handle (second) passed as null");
65 }
66
threeValidHandles(JNIEnv * env,void * a,void * b,void * c)67 static int threeValidHandles (JNIEnv* env, void* a, void *b, void* c)
68 {
69 if (!twoValidHandles(env, a, b)) return FALSE;
70 return isValidHandle(env, c, "Mandatory handle (third) passed as null");
71 }
72
fourValidHandles(JNIEnv * env,void * a,void * b,void * c,void * d)73 static int fourValidHandles (JNIEnv* env, void* a, void *b, void* c, void* d)
74 {
75 if (!threeValidHandles(env, a, b, c)) return FALSE;
76 return isValidHandle(env, d, "Mandatory handle (fourth) passed as null");
77 }
78
79
80 /**
81 * public static native int ERR_get_error();
82 */
NativeBN_ERR_get_error(JNIEnv * env,jclass cls)83 static unsigned long NativeBN_ERR_get_error(JNIEnv* env, jclass cls) {
84 unsigned long e = ERR_get_error();
85 return e;
86 }
87
88 /**
89 * public static native String ERR_error_string(int);
90 */
NativeBN_ERR_error_string(JNIEnv * env,jclass cls,unsigned long e)91 static jstring NativeBN_ERR_error_string(JNIEnv* env, jclass cls, unsigned long e) {
92 jstring returnJString = 0;
93 char* errStr;
94 errStr = ERR_error_string(e, NULL);
95 returnJString = ((*env)->NewStringUTF(env, (mcSignednessBull)errStr));
96 return returnJString;
97 }
98
99
100 /**
101 * public static native int BN_CTX_new()
102 */
NativeBN_BN_CTX_new(JNIEnv * env,jclass cls)103 static BN_CTX* NativeBN_BN_CTX_new(JNIEnv* env, jclass cls) {
104 return BN_CTX_new();
105 }
106
107
108 /**
109 * public static native int BN_new()
110 */
NativeBN_BN_new(JNIEnv * env,jclass cls)111 static BIGNUM* NativeBN_BN_new(JNIEnv* env, jclass cls) {
112 return BN_new();
113 }
114
115 /**
116 * public static native int BN_free()
117 */
NativeBN_BN_free(JNIEnv * env,jclass cls,BIGNUM * a)118 static void NativeBN_BN_free(JNIEnv* env, jclass cls, BIGNUM* a) {
119 if (!oneValidHandle(env, a)) return;
120 BN_free(a);
121 }
122
123
124 /**
125 * public static native int BN_cmp(int, int)
126 */
NativeBN_BN_cmp(JNIEnv * env,jclass cls,BIGNUM * a,BIGNUM * b)127 static int NativeBN_BN_cmp(JNIEnv* env, jclass cls, BIGNUM* a, BIGNUM* b) {
128 if (!twoValidHandles(env, a, b)) return 1;
129 return BN_cmp(a, b);
130 }
131
132 /**
133 * public static native int BN_copy(int, int)
134 */
NativeBN_BN_copy(JNIEnv * env,jclass cls,BIGNUM * to,BIGNUM * from)135 static jboolean NativeBN_BN_copy(JNIEnv* env, jclass cls, BIGNUM* to, BIGNUM* from) {
136 if (!twoValidHandles(env, to, from)) return FALSE;
137 return (BN_copy(to, from) != NULL);
138 }
139
140
141 /**
142 * public static native int putULongInt(int, long, int)
143 */
NativeBN_putULongInt(JNIEnv * env,jclass cls,BIGNUM * a,unsigned long long dw,jboolean neg)144 static jboolean NativeBN_putULongInt(JNIEnv* env, jclass cls, BIGNUM* a, unsigned long long dw, jboolean neg) {
145 if (!oneValidHandle(env, a)) return FALSE;
146 unsigned int hi = dw >> 32; // This shifts without sign extension.
147 int lo = (int)dw; // This truncates implicitely.
148
149 // cf. litEndInts2bn:
150 bn_check_top(a);
151 if (bn_wexpand(a, 2) != NULL) {
152 a->d[0] = lo;
153 a->d[1] = hi;
154 a->top = 2;
155 a->neg = neg;
156 bn_correct_top(a);
157 return TRUE;
158 }
159 else return FALSE;
160 }
161
162 /**
163 * public static native int putLongInt(int, long)
164 */
NativeBN_putLongInt(JNIEnv * env,jclass cls,BIGNUM * a,long long dw)165 static jboolean NativeBN_putLongInt(JNIEnv* env, jclass cls, BIGNUM* a, long long dw) {
166 if (dw >= 0) return NativeBN_putULongInt(env, cls, a, dw, FALSE);
167 else return NativeBN_putULongInt(env, cls, a, -dw, TRUE);
168 }
169
170 /**
171 * public static native int BN_dec2bn(int, java.lang.String)
172 */
NativeBN_BN_dec2bn(JNIEnv * env,jclass cls,BIGNUM * a,jstring str)173 static int NativeBN_BN_dec2bn(JNIEnv* env, jclass cls, BIGNUM* a, jstring str) {
174 if (!oneValidHandle(env, a)) return -1;
175 char* tmpStr = (char*)(*env)->GetStringUTFChars(env, str, NULL);
176 if (tmpStr != NULL) {
177 int len = BN_dec2bn(&a, tmpStr);
178 (*env)->ReleaseStringUTFChars(env, str, tmpStr);
179 return len; // len == 0: Error
180 }
181 else return -1; // Error outside BN.
182 }
183
184 /**
185 * public static native int BN_hex2bn(int, java.lang.String)
186 */
NativeBN_BN_hex2bn(JNIEnv * env,jclass cls,BIGNUM * a,jstring str)187 static int NativeBN_BN_hex2bn(JNIEnv* env, jclass cls, BIGNUM* a, jstring str) {
188 if (!oneValidHandle(env, a)) return -1;
189 char* tmpStr = (char*)(*env)->GetStringUTFChars(env, str, NULL);
190 if (tmpStr != NULL) {
191 int len = BN_hex2bn(&a, tmpStr);
192 (*env)->ReleaseStringUTFChars(env, str, tmpStr);
193 return len; // len == 0: Error
194 }
195 else return -1; // Error outside BN.
196 }
197
198 /**
199 * public static native boolean BN_bin2bn(byte[], int, int, int)
200 */
NativeBN_BN_bin2bn(JNIEnv * env,jclass cls,jbyteArray arr,int len,jboolean neg,BIGNUM * ret)201 static jboolean NativeBN_BN_bin2bn(JNIEnv* env, jclass cls, jbyteArray arr, int len, jboolean neg, BIGNUM* ret) {
202 if (!oneValidHandle(env, ret)) return FALSE;
203 jboolean success;
204 unsigned char * tmpBytes;
205 tmpBytes = (unsigned char *)((*env)->GetPrimitiveArrayCritical(env, arr, 0));
206 if (tmpBytes != NULL) {
207 success = (BN_bin2bn(tmpBytes, len, ret) != NULL);
208 if (neg) {
209 BN_set_negative(ret, 1);
210 }
211 (*env)->ReleasePrimitiveArrayCritical(env, arr, tmpBytes, JNI_ABORT);
212 return success;
213 }
214 else return -1; // Error outside BN. mc FIXME: what to do in this case? Does JNI throw exception itself?
215 }
216
217 /**
218 * public static native boolean litEndInts2bn(int[], int, int, int)
219 * Note:
220 * This procedure directly writes the internal representation of BIGNUMs.
221 * We do so as there is no direct interface based on Little Endian Integer Arrays.
222 * Also note that the same representation is used in the Cordoba Java Implementation of BigIntegers,
223 * whereof certain functionality is still being used.
224 */
NativeBN_litEndInts2bn(JNIEnv * env,jclass cls,jintArray arr,int len,jboolean neg,BIGNUM * ret)225 static jboolean NativeBN_litEndInts2bn(JNIEnv* env, jclass cls, jintArray arr, int len, jboolean neg, BIGNUM* ret) {
226 if (!oneValidHandle(env, ret)) return FALSE;
227 bn_check_top(ret);
228 if (len > 0) {
229 BN_ULONG* tmpInts; // BN_ULONG is 4 Bytes on this system for sure, i.e. same as jint!
230 tmpInts = (BN_ULONG*)((*env)->GetPrimitiveArrayCritical(env, arr, 0));
231 if ((tmpInts != NULL) && (bn_wexpand(ret, len) != NULL)) {
232 int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
233 (*env)->ReleasePrimitiveArrayCritical(env, arr, tmpInts, JNI_ABORT);
234 ret->top = len;
235 ret->neg = neg;
236 // need to call this due to clear byte at top if avoiding
237 // having the top bit set (-ve number)
238 // Basically get rid of top zero ints:
239 bn_correct_top(ret);
240 return TRUE;
241 }
242 else {
243 if (tmpInts != NULL)
244 (*env)->ReleasePrimitiveArrayCritical(env, arr, tmpInts, JNI_ABORT);
245 return FALSE;
246 }
247 }
248 else { // (len = 0) means value = 0 and sign will be 0, too.
249 ret->top = 0;
250 return TRUE;
251 }
252 }
253
254
255 #define BYTES2INT(bytes, k) \
256 ( (bytes[k + 3] & 0xFF) \
257 | (bytes[k + 2] & 0xFF) << 8 \
258 | (bytes[k + 1] & 0xFF) << 16 \
259 | (bytes[k + 0] & 0xFF) << 24 )
260
negBigEndianBytes2bn(JNIEnv * env,jclass cls,unsigned char * bytes,int bytesLen,BIGNUM * ret)261 static jboolean negBigEndianBytes2bn(JNIEnv* env, jclass cls, unsigned char* bytes, int bytesLen, BIGNUM* ret) {
262 // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
263 //
264 bn_check_top(ret);
265 // FIXME: ASSERT (bytesLen > 0);
266 int intLen = (bytesLen + 3) / 4;
267 int firstNonzeroDigit = -2;
268 if (bn_wexpand(ret, intLen) != NULL) {
269 BN_ULONG* d = ret->d;
270 BN_ULONG di;
271 ret->top = intLen;
272 int highBytes = bytesLen % 4;
273 int k = bytesLen;
274 // Put bytes to the int array starting from the end of the byte array
275 int i = 0;
276 while (k > highBytes) {
277 k -= 4;
278 di = BYTES2INT(bytes, k);
279 if (di != 0) {
280 d[i] = -di;
281 firstNonzeroDigit = i;
282 i++;
283 while (k > highBytes) {
284 k -= 4;
285 d[i] = ~BYTES2INT(bytes, k);
286 i++;
287 }
288 break;
289 } else {
290 d[i] = 0;
291 i++;
292 }
293 }
294 if (highBytes != 0) {
295 di = -1;
296 // Put the first bytes in the highest element of the int array
297 if (firstNonzeroDigit != -2) {
298 for (k = 0; k < highBytes; k++) {
299 di = (di << 8) | (bytes[k] & 0xFF);
300 }
301 d[i] = ~di;
302 } else {
303 for (k = 0; k < highBytes; k++) {
304 di = (di << 8) | (bytes[k] & 0xFF);
305 }
306 d[i] = -di;
307 }
308 }
309 return TRUE;
310 }
311 else return FALSE;
312 }
313
314 /**
315 * public static native boolean twosComp2bn(byte[], int, int)
316 */
NativeBN_twosComp2bn(JNIEnv * env,jclass cls,jbyteArray arr,int bytesLen,BIGNUM * ret)317 static jboolean NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, BIGNUM* ret) {
318 if (!oneValidHandle(env, ret)) return FALSE;
319 jboolean success;
320 unsigned char* tmpBytes;
321 tmpBytes = (unsigned char*)((*env)->GetPrimitiveArrayCritical(env, arr, 0));
322 if (tmpBytes != NULL) {
323 if ((tmpBytes[0] & 0X80) == 0) { // Positive value!
324 //
325 // We can use the existing BN implementation for unsigned big endian bytes:
326 //
327 success = (BN_bin2bn(tmpBytes, bytesLen, ret) != NULL);
328 BN_set_negative(ret, FALSE);
329 }
330 else { // Negative value!
331 //
332 // We need to apply two's complement:
333 //
334 success = negBigEndianBytes2bn(env, cls, tmpBytes, bytesLen, ret);
335 BN_set_negative(ret, TRUE);
336 }
337 (*env)->ReleasePrimitiveArrayCritical(env, arr, tmpBytes, JNI_ABORT);
338 return success;
339 }
340 else return -1; // Error outside BN. mc FIXME: what to do in this case? Does JNI throw exception itself?
341 }
342
343
344 /**
345 * public static native long longInt(int)
346 */
NativeBN_longInt(JNIEnv * env,jclass cls,BIGNUM * a)347 static long long NativeBN_longInt(JNIEnv* env, jclass cls, BIGNUM* a) {
348 if (!oneValidHandle(env, a)) return -1;
349 bn_check_top(a);
350 int intLen = a->top;
351 BN_ULONG* d = a->d;
352 switch (intLen) {
353 case 0:
354 return 0;
355 case 1:
356 if (!a->neg) return d[0] & 0X00000000FFFFFFFFLL;
357 else return -(d[0] & 0X00000000FFFFFFFFLL);
358 default:
359 if (!a->neg) return ((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL);
360 else return -(((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL));
361 }
362 }
363
364
leadingZerosTrimmed(char * s)365 static char* leadingZerosTrimmed(char* s) {
366 char* p = s;
367 if (*p == '-') {
368 p++;
369 while ((*p == '0') && (*(p + 1) != 0)) { p++; }
370 p--;
371 *p = '-';
372 } else {
373 while ((*p == '0') && (*(p + 1) != 0)) { p++; }
374 }
375 return p;
376 }
377
378 /**
379 * public static native java.lang.String BN_bn2dec(int)
380 */
NativeBN_BN_bn2dec(JNIEnv * env,jclass cls,BIGNUM * a)381 static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass cls, BIGNUM* a) {
382 if (!oneValidHandle(env, a)) return NULL;
383 char* tmpStr;
384 char* retStr;
385 tmpStr = BN_bn2dec(a);
386 if (tmpStr != NULL) {
387 retStr = leadingZerosTrimmed(tmpStr);
388 jstring returnJString = ((*env)->NewStringUTF(env, (mcSignednessBull)retStr));
389 OPENSSL_free(tmpStr);
390 return returnJString;
391 }
392 else return NULL;
393 }
394
395 /**
396 * public static native java.lang.String BN_bn2hex(int)
397 */
NativeBN_BN_bn2hex(JNIEnv * env,jclass cls,BIGNUM * a)398 static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass cls, BIGNUM* a) {
399 if (!oneValidHandle(env, a)) return NULL;
400 char* tmpStr;
401 char* retStr;
402 tmpStr = BN_bn2hex(a);
403 if (tmpStr != NULL) {
404 retStr = leadingZerosTrimmed(tmpStr);
405 jstring returnJString = ((*env)->NewStringUTF(env, (mcSignednessBull)retStr));
406 OPENSSL_free(tmpStr);
407 return returnJString;
408 }
409 else return NULL;
410 }
411
412 /**
413 * public static native byte[] BN_bn2bin(int, byte[])
414 */
NativeBN_BN_bn2bin(JNIEnv * env,jclass cls,BIGNUM * a,jbyteArray to)415 static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass cls, BIGNUM* a, jbyteArray to) {
416 if (!oneValidHandle(env, a)) return NULL;
417 jbyteArray returnJBytes = to;
418 unsigned char * tmpBytes;
419 int len, byteCnt;
420 byteCnt = BN_num_bytes(a);
421 // FIXME: Currently ignoring array passed in to:
422 returnJBytes = (*env)->NewByteArray(env, byteCnt);
423 // FIXME: is it neccessary to check for returnJBytes != NULL?
424 tmpBytes = (unsigned char *)((*env)->GetPrimitiveArrayCritical(env, returnJBytes, NULL));
425 if (tmpBytes != NULL) {
426 len = BN_bn2bin(a, tmpBytes);
427 (*env)->ReleasePrimitiveArrayCritical(env, returnJBytes, tmpBytes, 0);
428 return returnJBytes;
429 }
430 else return NULL;
431 }
432
433 /**
434 * public static native int[] bn2litEndInts(int, int[])
435 * cf. litEndInts2bn
436 */
NativeBN_bn2litEndInts(JNIEnv * env,jclass cls,BIGNUM * a,jintArray to)437 static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass cls, BIGNUM* a, jintArray to) {
438 if (!oneValidHandle(env, a)) return NULL;
439 jintArray returnJInts = to;
440 bn_check_top(a);
441 int len = a->top;
442 if (len > 0) {
443 // FIXME: Currently ignoring array passed in to:
444 returnJInts = (*env)->NewIntArray(env, len);
445 // FIXME: is it neccessary to check for returnJBytes != NULL?
446 BN_ULONG* tmpInts = (BN_ULONG*)((*env)->GetPrimitiveArrayCritical(env, returnJInts, NULL));
447 if (tmpInts != NULL) {
448 int i = len; do { i--; tmpInts[i] = a->d[i]; } while (i > 0);
449 (*env)->ReleasePrimitiveArrayCritical(env, returnJInts, tmpInts, 0);
450 return returnJInts;
451 }
452 else return NULL;
453 }
454 else { // value = 0
455 return NULL; // Client should not call when sign = 0!
456 }
457 }
458
459 /**
460 * public static native byte[] bn2twosComp(int, byte[])
461 */
NativeBN_bn2twosComp(JNIEnv * env,jclass cls,BIGNUM * a,jbyteArray to)462 static jbyteArray NativeBN_bn2twosComp(JNIEnv* env, jclass cls, BIGNUM* a, jbyteArray to) {
463 if (!oneValidHandle(env, a)) return NULL;
464 jbyteArray returnJBytes = to;
465 unsigned char * tmpBytes;
466 int len, byteCnt;
467 byteCnt = BN_num_bytes(a);
468 // FIXME: Currently ignoring array passed in to:
469 returnJBytes = (*env)->NewByteArray(env, byteCnt);
470 // FIXME: is it neccessary to check for returnJBytes != NULL?
471 tmpBytes = (unsigned char *)((*env)->GetPrimitiveArrayCritical(env, returnJBytes, NULL));
472 if (tmpBytes != NULL) {
473 len = BN_bn2bin(a, tmpBytes);
474 (*env)->ReleasePrimitiveArrayCritical(env, returnJBytes, tmpBytes, 0);
475 return returnJBytes;
476 }
477 else return NULL;
478 }
479
480
481 /**
482 * public static native int sign(int)
483 */
NativeBN_sign(JNIEnv * env,jclass cls,BIGNUM * a)484 static int NativeBN_sign(JNIEnv* env, jclass cls, BIGNUM* a) {
485 if (!oneValidHandle(env, a)) return -2;
486 if (BN_is_zero(a)) return 0;
487 else if (BN_is_negative(a)) return -1;
488 else return 1;
489 }
490
491 /**
492 * public static native void BN_set_negative(int, int)
493 */
NativeBN_BN_set_negative(JNIEnv * env,jclass cls,BIGNUM * b,int n)494 static void NativeBN_BN_set_negative(JNIEnv* env, jclass cls, BIGNUM* b, int n) {
495 if (!oneValidHandle(env, b)) return;
496 BN_set_negative(b, n);
497 }
498
499
500 /**
501 * public static native int twosCompFitsIntoBytes(int, int)
502 */
NativeBN_twosCompFitsIntoBytes(JNIEnv * env,jclass cls,BIGNUM * a,int byteCnt)503 static jboolean NativeBN_twosCompFitsIntoBytes(JNIEnv* env, jclass cls, BIGNUM* a, int byteCnt) {
504 // byteCnt IN {1, 2, 4, 8, 12, 16, ... (k * 4)}
505 // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
506 //
507 // LOGD("NativeBN_twosCompFitsIntoBytes");
508 if (!oneValidHandle(env, a)) return FALSE;
509 bn_check_top(a);
510 int intLen = a->top;
511 BN_ULONG* d = a->d;
512 BN_ULONG msd; // most significant digit
513 switch (byteCnt) {
514 case 1:
515 if (intLen > 1) return FALSE;
516 else if (intLen == 0) return TRUE;
517 msd = d[0];
518 if (a->neg) msd--;
519 return ((msd & 0XFFFFFF80) == 0);
520 case 2:
521 if (intLen > 1) return FALSE;
522 else if (intLen == 0) return TRUE;
523 msd = d[0];
524 if (a->neg) msd--;
525 return ((msd & 0XFFFF8000) == 0);
526 case 4:
527 if (intLen > 1) return FALSE;
528 else if (intLen == 0) return TRUE;
529 msd = d[0];
530 if (a->neg) msd--;
531 return ((msd & 0X80000000) == 0);
532 case 8:
533 if (intLen > 2) return FALSE;
534 else if (intLen == 0) return TRUE;
535 msd = d[1];
536 if ((a->neg) && (d[0]) == 0) msd--;
537 return ((msd & 0X80000000) == 0);
538 default:
539 if (intLen > byteCnt / 4) return FALSE;
540 else if (intLen == 0) return TRUE;
541 int i = intLen - 1;
542 msd = d[i];
543 if (a->neg) {
544 // Handle negative values correctly:
545 // i.e. decrement the msd if all other digits are 0:
546 do { i--; } while (!((i < 0) || (d[i] != 0)));
547 if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
548 }
549 return ((msd & 0X80000000) == 0);
550 }
551 }
552
553 /**
554 * public static native int bitLength(int)
555 */
NativeBN_bitLength(JNIEnv * env,jclass cls,BIGNUM * a)556 static int NativeBN_bitLength(JNIEnv* env, jclass cls, BIGNUM* a) {
557 // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
558 //
559 if (!oneValidHandle(env, a)) return FALSE;
560 bn_check_top(a);
561 int intLen = a->top;
562 if (intLen == 0) return 0;
563 BN_ULONG* d = a->d;
564 int i = intLen - 1;
565 BN_ULONG msd = d[i]; // most significant digit
566 if (a->neg) {
567 // Handle negative values correctly:
568 // i.e. decrement the msd if all other digits are 0:
569 // while ((i > 0) && (d[i] != 0)) { i--; }
570 do { i--; } while (!((i < 0) || (d[i] != 0)));
571 if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
572 }
573 return (intLen - 1) * 32 + BN_num_bits_word(msd);
574 }
575
576 /**
577 * public static native int BN_num_bits(int)
578 */
579 // static int NativeBN_BN_num_bits(JNIEnv* env, jclass cls, BIGNUM* a) {
580 // LOGD("NativeBN_BN_num_bits");
581 // if (!oneValidHandle(env, a)) return FALSE;
582 // return BN_num_bits(a);
583 // }
584
585 /**
586 * public static native boolean BN_is_bit_set(int, int)
587 */
NativeBN_BN_is_bit_set(JNIEnv * env,jclass cls,BIGNUM * a,int n)588 static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass cls, BIGNUM* a, int n) {
589 if (!oneValidHandle(env, a)) return FALSE;
590 return (jboolean)BN_is_bit_set(a, n);
591 }
592
593 /**
594 * public static native void modifyBit(int, int, int)
595 */
NativeBN_modifyBit(JNIEnv * env,jclass cls,BIGNUM * a,int n,int op)596 static jboolean NativeBN_modifyBit(JNIEnv* env, jclass cls, BIGNUM* a, int n, int op) {
597 // LOGD("NativeBN_BN_modifyBit");
598 if (!oneValidHandle(env, a)) return FALSE;
599 switch (op) {
600 case 1: return BN_set_bit(a, n);
601 case 0: return BN_clear_bit(a, n);
602 case -1:
603 if (BN_is_bit_set(a, n)) return BN_clear_bit(a, n);
604 else return BN_set_bit(a, n);
605 }
606 return FALSE;
607 }
608
609 /**
610 * public static native int BN_lshift(int, int, int)
611 */
NativeBN_BN_lshift(JNIEnv * env,jclass cls,BIGNUM * r,BIGNUM * a,int n)612 static jboolean NativeBN_BN_lshift(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, int n) {
613 // LOGD("NativeBN_BN_lshift %p %p %d", r, a, n);
614 if (!twoValidHandles(env, r, a)) return FALSE;
615 if (n >= 0) return BN_lshift(r, a, n);
616
617 n = -n;
618 // return BN_rshift(r, a, n);
619 // Following code insourced from bn_shift.c in order to have bug fixed:
620 // FIXME: Should report to openssl team!!!
621
622 int i,j,nw,lb,rb;
623 BN_ULONG *t,*f;
624 BN_ULONG l,tmp;
625
626 bn_check_top(r);
627 bn_check_top(a);
628
629 nw=n/BN_BITS2;
630 rb=n%BN_BITS2;
631 lb=BN_BITS2-rb;
632 // Changed "nw > a->top || a->top == 0" to nw >= a->top" as considering this a bug:
633 if (nw >= a->top)
634 {
635 BN_zero(r);
636 return(1);
637 }
638 if (r != a)
639 {
640 r->neg=a->neg;
641 if (bn_wexpand(r,a->top-nw+1) == NULL) return(0);
642 }
643 else
644 {
645 if (n == 0)
646 return 1; /* or the copying loop will go berserk */
647 }
648
649 f= &(a->d[nw]);
650 t=r->d;
651 j=a->top-nw;
652 r->top=j;
653
654 if (rb == 0)
655 {
656 for (i=j; i != 0; i--)
657 *(t++)= *(f++);
658 }
659 else
660 {
661 l= *(f++);
662 for (i=j-1; i != 0; i--)
663 {
664 tmp =(l>>rb)&BN_MASK2;
665 l= *(f++);
666 *(t++) =(tmp|(l<<lb))&BN_MASK2;
667 }
668 *(t++) =(l>>rb)&BN_MASK2;
669 }
670 bn_correct_top(r);
671 bn_check_top(r);
672 return(1);
673 }
674
675
676 /**
677 * public static native boolean BN_add_word(int, int)
678 */
NativeBN_BN_add_word(JNIEnv * env,jclass cls,BIGNUM * a,BN_ULONG w)679 static jboolean NativeBN_BN_add_word(JNIEnv* env, jclass cls, BIGNUM *a, BN_ULONG w) {
680 if (!oneValidHandle(env, a)) return FALSE;
681 return BN_add_word(a, w);
682 }
683
684 /**
685 * public static native boolean BN_sub_word(int, int)
686 */
NativeBN_BN_sub_word(JNIEnv * env,jclass cls,BIGNUM * a,BN_ULONG w)687 static jboolean NativeBN_BN_sub_word(JNIEnv* env, jclass cls, BIGNUM *a, BN_ULONG w) {
688 if (!oneValidHandle(env, a)) return FALSE;
689 return BN_sub_word(a, w);
690 }
691
692 /**
693 * public static native boolean BN_mul_word(int, int)
694 */
NativeBN_BN_mul_word(JNIEnv * env,jclass cls,BIGNUM * a,BN_ULONG w)695 static jboolean NativeBN_BN_mul_word(JNIEnv* env, jclass cls, BIGNUM *a, BN_ULONG w) {
696 if (!oneValidHandle(env, a)) return FALSE;
697 return BN_mul_word(a, w);
698 }
699
700 /**
701 * public static native boolean BN_div_word(int, int)
702 */
NativeBN_BN_div_word(JNIEnv * env,jclass cls,BIGNUM * a,BN_ULONG w)703 static BN_ULONG NativeBN_BN_div_word(JNIEnv* env, jclass cls, BIGNUM *a, BN_ULONG w) {
704 if (!oneValidHandle(env, a)) return FALSE;
705 return BN_div_word(a, w);
706 }
707
708 /**
709 * public static native boolean BN_mod_word(int, int)
710 */
NativeBN_BN_mod_word(JNIEnv * env,jclass cls,BIGNUM * a,BN_ULONG w)711 static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass cls, BIGNUM *a, BN_ULONG w) {
712 if (!oneValidHandle(env, a)) return FALSE;
713 return BN_mod_word(a, w);
714 }
715
716
717
718 /**
719 * public static native int BN_add(int, int, int)
720 */
NativeBN_BN_add(JNIEnv * env,jclass cls,BIGNUM * r,BIGNUM * a,BIGNUM * b)721 static jboolean NativeBN_BN_add(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
722 if (!threeValidHandles(env, r, a, b)) return FALSE;
723 return BN_add(r, a, b);
724 }
725
726 /**
727 * public static native int BN_sub(int, int, int)
728 */
NativeBN_BN_sub(JNIEnv * env,jclass cls,BIGNUM * r,BIGNUM * a,BIGNUM * b)729 static jboolean NativeBN_BN_sub(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
730 if (!threeValidHandles(env, r, a, b)) return FALSE;
731 return BN_sub(r, a, b);
732 }
733
734
735 /**
736 * public static native int BN_gcd(int, int, int, int)
737 */
NativeBN_BN_gcd(JNIEnv * env,jclass cls,BIGNUM * r,BIGNUM * a,BIGNUM * b,BN_CTX * ctx)738 static jboolean NativeBN_BN_gcd(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* b, BN_CTX* ctx) {
739 if (!threeValidHandles(env, r, a, b)) return FALSE;
740 return BN_gcd(r, a, b, ctx);
741 }
742
743 /**
744 * public static native int BN_mul(int, int, int, int)
745 */
NativeBN_BN_mul(JNIEnv * env,jclass cls,BIGNUM * r,BIGNUM * a,BIGNUM * b,BN_CTX * ctx)746 static jboolean NativeBN_BN_mul(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* b, BN_CTX* ctx) {
747 if (!threeValidHandles(env, r, a, b)) return FALSE;
748 return BN_mul(r, a, b, ctx);
749 }
750
751 /**
752 * public static native int BN_exp(int, int, int, int)
753 */
NativeBN_BN_exp(JNIEnv * env,jclass cls,BIGNUM * r,BIGNUM * a,BIGNUM * p,BN_CTX * ctx)754 static jboolean NativeBN_BN_exp(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* p, BN_CTX* ctx) {
755 if (!threeValidHandles(env, r, a, p)) return FALSE;
756 return BN_exp(r, a, p, ctx);
757 }
758
759 /**
760 * public static native boolean BN_div(int, int, int, int, int)
761 */
NativeBN_BN_div(JNIEnv * env,jclass cls,BIGNUM * dv,BIGNUM * rem,BIGNUM * m,BIGNUM * d,BN_CTX * ctx)762 static jboolean NativeBN_BN_div(JNIEnv* env, jclass cls, BIGNUM* dv, BIGNUM* rem, BIGNUM* m, BIGNUM* d, BN_CTX* ctx) {
763 if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return FALSE;
764 return BN_div(dv, rem, m, d, ctx);
765 }
766
767 /**
768 * public static native int BN_nnmod(int, int, int, int)
769 */
NativeBN_BN_nnmod(JNIEnv * env,jclass cls,BIGNUM * r,BIGNUM * a,BIGNUM * m,BN_CTX * ctx)770 static jboolean NativeBN_BN_nnmod(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* m, BN_CTX* ctx) {
771 if (!threeValidHandles(env, r, a, m)) return FALSE;
772 return BN_nnmod(r, a, m, ctx);
773 }
774
775 /**
776 * public static native int BN_mod_exp(int, int, int, int, int)
777 */
NativeBN_BN_mod_exp(JNIEnv * env,jclass cls,BIGNUM * r,BIGNUM * a,BIGNUM * p,BIGNUM * m,BN_CTX * ctx)778 static jboolean NativeBN_BN_mod_exp(JNIEnv* env, jclass cls, BIGNUM* r, BIGNUM* a, BIGNUM* p, BIGNUM* m, BN_CTX* ctx) {
779 if (!fourValidHandles(env, r, a, p, m)) return FALSE;
780 return BN_mod_exp(r, a, p, m, ctx);
781 }
782
783
784 /**
785 * public static native int BN_mod_inverse(int, int, int, int)
786 */
NativeBN_BN_mod_inverse(JNIEnv * env,jclass cls,BIGNUM * ret,BIGNUM * a,BIGNUM * n,BN_CTX * ctx)787 static jboolean NativeBN_BN_mod_inverse(JNIEnv* env, jclass cls, BIGNUM* ret, BIGNUM* a, BIGNUM* n, BN_CTX* ctx) {
788 if (!threeValidHandles(env, ret, a, n)) return FALSE;
789 return (BN_mod_inverse(ret, a, n, ctx) != NULL);
790 }
791
792
793 /**
794 * public static native int BN_generate_prime_ex(int, int, boolean, int, int, int)
795 */
NativeBN_BN_generate_prime_ex(JNIEnv * env,jclass cls,BIGNUM * ret,int bits,jboolean safe,BIGNUM * add,BIGNUM * rem,jint cb)796 static jboolean NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass cls, BIGNUM* ret, int bits, jboolean safe,
797 BIGNUM* add, BIGNUM* rem, jint cb) {
798 if (!oneValidHandle(env, ret)) return FALSE;
799 return BN_generate_prime_ex(ret, bits, safe, add, rem, cb);
800 }
801
802 /**
803 * public static native int BN_mod_inverse(int, int, int, int)
804 */
NativeBN_BN_is_prime_ex(JNIEnv * env,jclass cls,BIGNUM * p,int nchecks,BN_CTX * ctx,jint cb)805 static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass cls, BIGNUM* p, int nchecks, BN_CTX* ctx, jint cb) {
806 if (!oneValidHandle(env, p)) return FALSE;
807 return BN_is_prime_ex(p, nchecks, ctx, cb);
808 }
809
810
811 /**
812 * Defines the mapping from Java methods and their signatures
813 * to native functions. Order is Java name, Java signature,
814 * then pointer to C function.
815 */
816 static JNINativeMethod METHODS[] = {
817 { "ERR_get_error", "()I", (void*)NativeBN_ERR_get_error },
818 { "ERR_error_string", "(I)Ljava/lang/String;", (void*)NativeBN_ERR_error_string },
819 { "BN_CTX_new", "()I", (void*)NativeBN_BN_CTX_new },
820 { "BN_new", "()I", (void*)NativeBN_BN_new },
821 { "BN_free", "(I)V", (void*)NativeBN_BN_free },
822 { "BN_cmp", "(II)I", (void*)NativeBN_BN_cmp },
823 { "BN_copy", "(II)Z", (void*)NativeBN_BN_copy },
824 { "putLongInt", "(IJ)Z", (void*)NativeBN_putLongInt },
825 { "putULongInt", "(IJZ)Z", (void*)NativeBN_putULongInt },
826 { "BN_dec2bn", "(ILjava/lang/String;)I", (void*)NativeBN_BN_dec2bn },
827 { "BN_hex2bn", "(ILjava/lang/String;)I", (void*)NativeBN_BN_hex2bn },
828 { "BN_bin2bn", "([BIZI)Z", (void*)NativeBN_BN_bin2bn },
829 { "litEndInts2bn", "([IIZI)Z", (void*)NativeBN_litEndInts2bn },
830 { "twosComp2bn", "([BII)Z", (void*)NativeBN_twosComp2bn },
831 { "longInt", "(I)J", (void*)NativeBN_longInt },
832 { "BN_bn2dec", "(I)Ljava/lang/String;", (void*)NativeBN_BN_bn2dec },
833 { "BN_bn2hex", "(I)Ljava/lang/String;", (void*)NativeBN_BN_bn2hex },
834 { "BN_bn2bin", "(I[B)[B", (void*)NativeBN_BN_bn2bin },
835 { "bn2litEndInts", "(I[I)[I", (void*)NativeBN_bn2litEndInts },
836 { "bn2twosComp", "(I[B)[B", (void*)NativeBN_bn2twosComp },
837 { "sign", "(I)I", (void*)NativeBN_sign },
838 { "BN_set_negative", "(II)V", (void*)NativeBN_BN_set_negative },
839 { "twosCompFitsIntoBytes", "(II)Z", (void*)NativeBN_twosCompFitsIntoBytes },
840 { "bitLength", "(I)I", (void*)NativeBN_bitLength },
841 // { "BN_num_bits", "(I)I", (void*)NativeBN_BN_num_bits },
842 { "BN_is_bit_set", "(II)Z", (void*)NativeBN_BN_is_bit_set },
843 { "modifyBit", "(III)Z", (void*)NativeBN_modifyBit },
844 { "BN_lshift", "(III)Z", (void*)NativeBN_BN_lshift },
845 { "BN_add_word", "(II)Z", (void*)NativeBN_BN_add_word },
846 { "BN_sub_word", "(II)Z", (void*)NativeBN_BN_sub_word },
847 { "BN_mul_word", "(II)Z", (void*)NativeBN_BN_mul_word },
848 { "BN_div_word", "(II)I", (void*)NativeBN_BN_div_word },
849 { "BN_mod_word", "(II)I", (void*)NativeBN_BN_mod_word },
850 { "BN_add", "(III)Z", (void*)NativeBN_BN_add },
851 { "BN_sub", "(III)Z", (void*)NativeBN_BN_sub },
852 { "BN_gcd", "(IIII)Z", (void*)NativeBN_BN_gcd },
853 { "BN_mul", "(IIII)Z", (void*)NativeBN_BN_mul },
854 { "BN_exp", "(IIII)Z", (void*)NativeBN_BN_exp },
855 { "BN_div", "(IIIII)Z", (void*)NativeBN_BN_div },
856 { "BN_nnmod", "(IIII)Z", (void*)NativeBN_BN_nnmod },
857 { "BN_mod_exp", "(IIIII)Z", (void*)NativeBN_BN_mod_exp },
858 { "BN_mod_inverse", "(IIII)Z", (void*)NativeBN_BN_mod_inverse },
859 { "BN_generate_prime_ex", "(IIZIII)Z", (void*)NativeBN_BN_generate_prime_ex },
860 { "BN_is_prime_ex", "(IIII)Z", (void*)NativeBN_BN_is_prime_ex }
861 };
862
863 /*
864 * Peforms the actual registration of the native methods.
865 * Also looks up the fields that belong to the class (if
866 * any) and stores the field IDs.
867 */
register_org_openssl_NativeBN(JNIEnv * env)868 int register_org_openssl_NativeBN(JNIEnv* env) {
869 /*
870 jclass clazz;
871
872 clazz = (*env)->FindClass(env, "org/openssl/NativeBN");
873 if (clazz == NULL) {
874 return -1;
875 }
876 */
877 return jniRegisterNativeMethods(env, "org/openssl/NativeBN", METHODS, NELEM(METHODS));
878 }
879