Changeset a3c6cc1d for core/c


Ignore:
Timestamp:
Nov 30, 2014 9:19:28 PM (6 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
55c411a, a074654
Parents:
7ab6708
Message:

libjbigi updates:

Added:

nativeJbigiVersion()
nativeGMPMajorVersion()
nativeGMPMinorVersion()
nativeGMPPatchVersion()
nativeModInverse()
nativeModPowCT()

Support negative vaules in conversion functions
Support negative base value in modPow()
Throw ArithmeticException? for bad arguments rather than crashing
Switch to GMP 6.0.0
New build targets

NativeBigInteger? changes:

Test improvements
Version reporting

Crypto changes:

Use constant time modPow() for signing and decryption
Use native modInverse()

Location:
core/c/jbigi
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • core/c/jbigi/build-all.sh

    r7ab6708 ra3c6cc1d  
    11#!/bin/sh
     2#
     3#  NOTE:
     4#  This script is not supported - see mbuild-all.sh
     5#
    26
    37case `uname -sr` in
     
    1519esac
    1620
    17 VER=4.2.4
     21VER=6.0.0
     22TARVER=${VER}a
     23TAR=gmp-${TARVER}.tar.bz2
     24
    1825echo "Extracting GMP Version $VER ..."
    19 tar -xjf gmp-$VER.tar.bz2
     26tar -xjf $TAR
    2027echo "Building..."
    21 mkdir bin
    22 mkdir lib
    23 mkdir lib/net
    24 mkdir lib/net/i2p
    25 mkdir lib/net/i2p/util
     28mkdir -p lib/net/i2p/util
    2629
    27 for x in none pentium pentiummmx pentium2 pentium3 pentium4 k6 k62 k63 athlon geode pentiumm core2
     30#
     31# look in configure file in gmp source for supported host CPUs, at about line 5000
     32#
     33#
     34for x in \
     35  none pentium pentiummmx pentium2 pentium3 pentium4 k6 k62 k63 athlon geode pentiumm core2 \
     36  athlon64 k10 bobcat jaguar bulldozer piledriver steamroller excavator corei atom nano
    2837do
    29         mkdir bin/$x
     38        mkdir -p bin/$x
    3039        cd bin/$x
    31         ../../gmp-$VER/configure --build=$x
     40        ../../gmp-$VER/configure --with-pic --build=$x
     41        make clean
    3242        make
    3343        sh ../../build_jbigi.sh static
  • core/c/jbigi/build.sh

    r7ab6708 ra3c6cc1d  
    2323# Use 4.3.2 32bit CPUs.
    2424# Use 5.0.2 64bit CPUs.
    25 VER=4.3.2
     25VER=6.0.0
     26TARVER=${VER}a
     27TAR=gmp-${TARVER}.tar.bz2
    2628
    2729# If JAVA_HOME isn't set, try to figure it out on our own
     
    3840download_gmp ()
    3941{
     42URL="https://gmplib.org/download/gmp/${TAR}"
    4043if [ $(which wget) ]; then
    41     echo "Downloading ftp://ftp.gmplib.org/pub/gmp-${VER}/${TAR}"
    42     wget -N --progress=dot ftp://ftp.gmplib.org/pub/gmp-${VER}/${TAR}
     44    echo "Downloading $URL"
     45    wget -N --progress=dot $URL
    4346else
    4447    echo "ERROR: Cannot find wget." >&2
    4548    echo >&2
    46     echo "Please download ftp://ftp.gmplib.org/pub/gmp-${VER}/${TAR}" >&2
     49    echo "Please download $URL" >&2
    4750    echo "manually and rerun this script." >&2
    4851    exit 1
     
    5457tar -xjf ${TAR} > /dev/null 2>&1|| (rm -f ${TAR} && download_gmp && extract_gmp || exit 1)
    5558}
    56 
    57 TAR=gmp-${VER}.tar.bz2
    5859
    5960if [ "$1" != "dynamic" -a ! -d gmp-${VER} ]; then
  • core/c/jbigi/build_jbigi.sh

    r7ab6708 ra3c6cc1d  
    66
    77# If JAVA_HOME isn't set we'll try to figure it out
    8 [ -z $JAVA_HOME ] && . ../find-java-home
     8[ -z $JAVA_HOME ] && . `dirname $0`/../find-java-home
    99if [ ! -f "$JAVA_HOME/include/jni.h" ]; then
    1010    echo "Cannot find jni.h! Looked in '$JAVA_HOME/include/jni.h'"
  • core/c/jbigi/jbigi/src/jbigi.c

    r7ab6708 ra3c6cc1d  
    88void convert_mp2j(JNIEnv* env, mpz_t mvalue, jbyteArray* jvalue);
    99
     10/*
     11 * Versions:
     12 *
     13 * 1: Original version, with nativeModPow() and nativeDoubleValue()
     14 *
     15 * 2: (I2P 0.8.7)
     16 *    Removed nativeDoubleValue()
     17 *
     18 * 3: (I2P 0.9.18)
     19 *    Added:
     20 *      nativeJbigiVersion()
     21 *      nativeGMPMajorVersion()
     22 *      nativeGMPMinorVersion()
     23 *      nativeGMPPatchVersion()
     24 *      nativeModInverse()
     25 *      nativeModPowCT()
     26 *    Support negative base value in modPow()
     27 *    Throw ArithmeticException for bad arguments in modPow()
     28 *
     29 */
     30#define JBIGI_VERSION 3
    1031
    1132/*****************************************
     
    1334 *****************************************/
    1435
     36/* since version 3 */
     37JNIEXPORT jint JNICALL Java_net_i2p_util_NativeBigInteger_nativeJbigiVersion
     38        (JNIEnv* env, jclass cls) {
     39    return (jint) JBIGI_VERSION;
     40}
     41
     42/* since version 3 */
     43JNIEXPORT jint JNICALL Java_net_i2p_util_NativeBigInteger_nativeGMPMajorVersion
     44        (JNIEnv* env, jclass cls) {
     45    return (jint) __GNU_MP_VERSION;
     46}
     47
     48/* since version 3 */
     49JNIEXPORT jint JNICALL Java_net_i2p_util_NativeBigInteger_nativeGMPMinorVersion
     50        (JNIEnv* env, jclass cls) {
     51    return (jint) __GNU_MP_VERSION_MINOR;
     52}
     53
     54/* since version 3 */
     55JNIEXPORT jint JNICALL Java_net_i2p_util_NativeBigInteger_nativeGMPPatchVersion
     56        (JNIEnv* env, jclass cls) {
     57    return (jint) __GNU_MP_VERSION_PATCHLEVEL;
     58}
     59
    1560/******** nativeModPow() */
    1661/*
     
    2267 *
    2368 * calculate (base ^ exponent) % modulus.
    24  * @param curVal big endian twos complement representation of the base (but it must be positive)
    25  * @param exponent big endian twos complement representation of the exponent
    26  * @param modulus big endian twos complement representation of the modulus
     69 * @param jbase big endian twos complement representation of the base
     70 *             Negative values allowed as of version 3
     71 * @param jexp big endian twos complement representation of the exponent
     72 *             Must be greater than or equal to zero.
     73 *             As of version 3, throws java.lang.ArithmeticException if < 0.
     74 * @param jmod big endian twos complement representation of the modulus
     75 *             Must be greater than zero.
     76 *             As of version 3, throws java.lang.ArithmeticException if <= 0.
     77 *             Prior to version 3, crashed the JVM if <= 0.
    2778 * @return big endian twos complement representation of (base ^ exponent) % modulus
     79 * @throws java.lang.ArithmeticException if jmod is <= 0
    2880 */
    2981
     
    4092        jbyteArray jresult;
    4193
     94        convert_j2mp(env, jmod,  &mmod);
     95        if (mpz_sgn(mmod) <= 0) {
     96            mpz_clear(mmod);
     97            jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
     98            (*env)->ThrowNew(env, exc, "Modulus must be positive");
     99            return 0;
     100        }
     101
     102        // disallow negative exponents to avoid divide by zero exception if no inverse exists
     103        convert_j2mp(env, jexp,  &mexp);
     104        if (mpz_sgn(mexp) < 0) {
     105            mpz_clears(mmod, mexp, 0);
     106            jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
     107            (*env)->ThrowNew(env, exc, "Exponent cannot be negative");
     108            return 0;
     109        }
     110
    42111        convert_j2mp(env, jbase, &mbase);
     112 
     113        /* Perform the actual powmod. We use mmod for the result because it is
     114         * always at least as big as the result.
     115         */
     116        mpz_powm(mmod, mbase, mexp, mmod);
     117
     118        convert_mp2j(env, mmod, &jresult);
     119
     120        mpz_clears(mbase, mexp, mmod, 0);
     121
     122        return jresult;
     123}
     124
     125/******** nativeModPowCT() */
     126/*
     127 * Class:     net_i2p_util_NativeBigInteger
     128 * Method:    nativeModPowCT
     129 * Signature: ([B[B[B)[B
     130 *
     131 * Constant time version of nativeModPow()
     132 *
     133 * From the javadoc:
     134 *
     135 * calculate (base ^ exponent) % modulus.
     136 * @param jbase big endian twos complement representation of the base
     137 *             Negative values allowed.
     138 * @param jexp big endian twos complement representation of the exponent
     139 *             Must be positive.
     140 * @param jmod big endian twos complement representation of the modulus
     141 *             Must be positive and odd.
     142 * @return big endian twos complement representation of (base ^ exponent) % modulus
     143 * @throws java.lang.ArithmeticException if jmod or jexp is <= 0, or jmod is even.
     144 * @since version 3
     145 */
     146
     147JNIEXPORT jbyteArray JNICALL Java_net_i2p_util_NativeBigInteger_nativeModPowCT
     148        (JNIEnv* env, jclass cls, jbyteArray jbase, jbyteArray jexp, jbyteArray jmod) {
     149
     150        mpz_t mbase;
     151        mpz_t mexp;
     152        mpz_t mmod;
     153        jbyteArray jresult;
     154
     155        convert_j2mp(env, jmod,  &mmod);
     156        if (mpz_sgn(mmod) <= 0) {
     157            mpz_clear(mmod);
     158            jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
     159            (*env)->ThrowNew(env, exc, "Modulus must be positive");
     160            return 0;
     161        }
     162        // disallow even modulus as specified in the GMP docs
     163        if (mpz_odd_p(mmod) == 0) {
     164            mpz_clear(mmod);
     165            jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
     166            (*env)->ThrowNew(env, exc, "Modulus must be odd");
     167            return 0;
     168        }
     169
     170        // disallow negative or zero exponents as specified in the GMP docs
    43171        convert_j2mp(env, jexp,  &mexp);
     172        if (mpz_sgn(mexp) <= 0) {
     173            mpz_clears(mmod, mexp, 0);
     174            jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
     175            (*env)->ThrowNew(env, exc, "Exponent must be positive");
     176            return 0;
     177        }
     178
     179        convert_j2mp(env, jbase, &mbase);
     180 
     181        mpz_powm_sec(mmod, mbase, mexp, mmod);
     182
     183        convert_mp2j(env, mmod, &jresult);
     184
     185        mpz_clears(mbase, mexp, mmod, 0);
     186
     187        return jresult;
     188}
     189
     190/******** nativeModInverse() */
     191/*
     192 * Class:     net_i2p_util_NativeBigInteger
     193 * Method:    nativeModInverse
     194 * Signature: ([B[B)[B
     195 *
     196 * From the javadoc:
     197 *
     198 * calculate (base ^ -1) % modulus.
     199 * @param jbase big endian twos complement representation of the base
     200 *             Negative values allowed
     201 * @param jmod big endian twos complement representation of the modulus
     202 *             Zero or Negative values will throw a java.lang.ArithmeticException
     203 * @return big endian twos complement representation of (base ^ exponent) % modulus
     204 * @throws java.lang.ArithmeticException if jbase and jmod are not coprime or jmod is <= 0
     205 * @since version 3
     206 */
     207
     208JNIEXPORT jbyteArray JNICALL Java_net_i2p_util_NativeBigInteger_nativeModInverse
     209        (JNIEnv* env, jclass cls, jbyteArray jbase, jbyteArray jmod) {
     210
     211        mpz_t mbase;
     212        mpz_t mexp;
     213        mpz_t mmod;
     214        mpz_t mgcd;
     215        jbyteArray jresult;
     216
    44217        convert_j2mp(env, jmod,  &mmod);
     218
     219        if (mpz_sgn(mmod) <= 0) {
     220            mpz_clear(mmod);
     221            jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
     222            (*env)->ThrowNew(env, exc, "Modulus must be positive");
     223            return 0;
     224        }
     225
     226        convert_j2mp(env, jbase, &mbase);
     227        mpz_init_set_si(mexp, -1);
    45228 
    46                 /* Perform the actual powmod. We use mmod for the result because it is
     229        /* We must protect the jvm by doing a gcd test first.
     230         * If the arguments are not coprime, GMP will throw a divide by zero
     231         * and crash the JVM.
     232         * We could test in Java using BigInteger.gcd() but it is almost as slow
     233         * as the Java modInverse() itself, thus defeating the point.
     234         * Unfortunately, this almost doubles our time here too.
     235         */
     236        mpz_init(mgcd);
     237        mpz_gcd(mgcd, mbase, mmod);
     238        if (mpz_cmp_si(mgcd, 1) != 0) {
     239            mpz_clears(mbase, mexp, mmod, mgcd, 0);
     240            jclass exc = (*env)->FindClass(env, "java/lang/ArithmeticException");
     241            (*env)->ThrowNew(env, exc, "Not coprime in nativeModInverse()");
     242            return 0;
     243        }
     244
     245        /* Perform the actual powmod. We use mmod for the result because it is
    47246         * always at least as big as the result.
    48247         */
    49248        mpz_powm(mmod, mbase, mexp, mmod);
    50249
    51                 convert_mp2j(env, mmod, &jresult);
    52 
    53         mpz_clear(mbase);
    54         mpz_clear(mexp);
    55         mpz_clear(mmod);
     250        convert_mp2j(env, mmod, &jresult);
     251
     252        mpz_clears(mbase, mexp, mmod, mgcd, 0);
    56253
    57254        return jresult;
    58255}
     256
     257/******** nativeNeg() */
     258/* since version 3 */
     259/*
     260 * Class:     net_i2p_util_NativeBigInteger
     261 * Method:    nativeNeg
     262 * Signature: ([B)[B
     263 *
     264 * For testing of the conversion functions only!
     265 *
     266 * calculate n mod d
     267 * @param n big endian twos complement representation
     268 * @return big endian twos complement representation of -n
     269 */
     270
     271/****
     272JNIEXPORT jbyteArray JNICALL Java_net_i2p_util_NativeBigInteger_nativeNeg
     273        (JNIEnv* env, jclass cls, jbyteArray jn) {
     274
     275        mpz_t mn;
     276        jbyteArray jresult;
     277
     278        convert_j2mp(env, jn,  &mn);
     279 
     280        // result to mn
     281        mpz_neg(mn, mn);
     282
     283        convert_mp2j(env, mn, &jresult);
     284
     285        mpz_clear(mn);
     286
     287        return jresult;
     288}
     289****/
    59290
    60291/******************************
     
    71302 * Java value into the GMP value. The value that mvalue points to should be
    72303 * uninitialized
     304 *
     305 * As of version 3, negative values are correctly converted.
    73306 */
    74307
     
    77310        jsize size;
    78311        jbyte* jbuffer;
    79                 //int sign;
     312        mpz_t mask;
    80313
    81314        size = (*env)->GetArrayLength(env, jvalue);
     
    99332         */
    100333        mpz_import(*mvalue, size, 1, sizeof(jbyte), 1, 0, (void*)jbuffer);
    101                 /*Uncomment this to support negative integer values,
    102                 not tested though..
    103                 sign = jbuffer[0] < 0?-1:1;
    104                 if(sign == -1)
    105                         mpz_neg(*mvalue,*mvalue);
    106                 */
     334        if (jbuffer[0] < 0) {
     335            // ones complement, making a negative number
     336            mpz_com(*mvalue, *mvalue);
     337            // construct the mask needed to get rid of the new high bit
     338            mpz_init_set_ui(mask, 1);
     339            mpz_mul_2exp(mask, mask, size * 8);
     340            mpz_sub_ui(mask, mask, 1);
     341            // mask off the high bits, making a postive number (the magnitude, off by one)
     342            mpz_and(*mvalue, *mvalue, mask);
     343            // release the mask
     344            mpz_clear(mask);
     345            // add one to get the correct magnitude
     346            mpz_add_ui(*mvalue, *mvalue, 1);
     347            // invert to a negative number
     348            mpz_neg(*mvalue, *mvalue);
     349        }
    107350        (*env)->ReleaseByteArrayElements(env, jvalue, jbuffer, JNI_ABORT);
    108351}
     
    113356 * Pads the resulting jbyte array with 0, so the twos complement value is always
    114357 * positive.
     358 *
     359 * As of version 3, negative values are correctly converted.
    115360 */
    116361
     
    122367        jbyte* buffer;
    123368        jboolean copy;
    124                 //int i;
     369        int i;
     370        int neg;
    125371
    126372        copy = JNI_FALSE;
     373
     374        neg = mpz_sgn(mvalue) < 0;
     375        if (neg) {
     376            // add 1...
     377            // have to do this before we calculate the size!
     378            mpz_add_ui(mvalue, mvalue, 1);
     379        }
    127380
    128381        /* sizeinbase() + 7 => Ceil division */
     
    132385        buffer = (*env)->GetByteArrayElements(env, *jvalue, &copy);
    133386        buffer[0] = 0x00;
    134                 //Uncomment the comments below to support negative integer values,
    135                 //not very well-tested though..
    136                 //if(mpz_sgn(mvalue) >=0){
    137                 mpz_export((void*)&buffer[1], &size, 1, sizeof(jbyte), 1, 0, mvalue);
    138                 //}else{
    139                 //      mpz_add_ui(mvalue,mvalue,1);
    140                 //      mpz_export((void*)&buffer[1], &size, 1, sizeof(jbyte), 1, 0, mvalue);
    141                 //      for(i =0;i<=size;i++){ //This could be done more effectively
    142                 //              buffer[i]=~buffer[i];
    143                 //      }
    144                 //}
    145 
    146                 /* mode has (supposedly) no effect if elems is not a copy of the
     387
     388        if (!neg) {
     389            mpz_export((void*)&buffer[1], NULL, 1, sizeof(jbyte), 1, 0, mvalue);
     390        } else {
     391            mpz_export((void*)&buffer[1], NULL, 1, sizeof(jbyte), 1, 0, mvalue);
     392            // ... and invert the bits
     393            // This could be done all in mpz, the reverse of the above
     394            for (i = 0; i <= size; i++) {
     395                buffer[i] = ~buffer[i];
     396            }
     397        }
     398
     399        /* mode has (supposedly) no effect if elems is not a copy of the
    147400         * elements in array
    148401         */
     
    150403        //mode has (supposedly) no effect if elems is not a copy of the elements in array
    151404}
    152 
    153 /******** eof */
  • core/c/jbigi/mbuild-all.sh

    r7ab6708 ra3c6cc1d  
    11#!/bin/sh
     2#
     3# Run with BITS=32 to generate 32-bit libs on a 64-bit platform
     4# On Ubuntu you will need sudo apt-get install gcc-multilib libc6-i386 libc6-dev-i386
     5#
    26
    37# ON Solaris 11 (at least) this variable must be set.
     
    59#
    610#BITS=32
     11
     12#
     13# look in configure file in gmp source for supported host CPUs, at about line 5000
     14#
    715
    816# FIXME Is this all?
     
    3745# Are there any other X86 platforms that work on i2p? Add them here.
    3846#
    39 
    4047# Note! these build on 32bit as 32bit when operating as 32bit...
    41 X86_64_PLATFORMS="atom athlon64 core2 corei nano pentium4"
     48# starting with k10 added for 6.0.0
     49# As of GMP 6.0.0, libgmp 3,
     50# the following architectures appear to build to identical code:
     51#    core2 corei
     52#    bulldozer piledriver streamroller excavator
     53#    bobcat jaguar
     54#    k62 k63
     55#    viac32 pentium3
     56#
     57# Even more duplicates are in 32-bit mode, so it doesn't pay to have everything for 32 bit.
     58#
     59X86_64_PLATFORMS="atom athlon64 core2 corei nano pentium4 k10 bobcat jaguar bulldozer piledriver steamroller excavator"
    4260
    4361# Note! these are 32bit _ONLY_
Note: See TracChangeset for help on using the changeset viewer.