• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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