1 /*
   2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <stdlib.h>
  27 #include <string.h>
  28 #include <strings.h>
  29 #include <jni.h>
  30 #include "jni_util.h"
  31 #include "nativeCrypto.h"
  32 #include "nativeFunc.h"
  33 
  34 /*
  35  * Dumps out byte array in hex with and name and length info
  36  */
  37 void printError(char* header, int mech, int rv) {
  38   if (mech != -1) {
  39     printf("%s, mech = %d, rv = 0x%0x\n", header, mech, rv);
  40   } else {
  41     printf("%s, rv = 0x%0x\n", header, rv);
  42   }
  43   if (*ftab->ucryptoStrerror != NULL) {
  44     char * reason = (*ftab->ucryptoStrerror)(rv);
  45     printf("\tcause = %s\n", reason);
  46     free(reason);
  47   }
  48 }
  49 
  50 /*
  51  * Dumps out byte array in hex with and name and length info
  52  */
  53 void printBytes(char* header, unsigned char* bytes, int len) {
  54   int i;
  55 
  56   printf("%s", header);
  57   printf("len=%d {", len);
  58   for (i = 0; i < len; i++) {
  59     if (i > 0) printf(":");
  60     printf("%02X", bytes[i]);
  61   }
  62   printf("}\n");
  63 }
  64 
  65 /*
  66  * Throws java.lang.OutOfMemoryError
  67  */
  68 void throwOutOfMemoryError(JNIEnv *env, const char *msg)
  69 {
  70   jclass jExClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
  71   if (jExClass != 0) /* Otherwise an exception has already been thrown */ {
  72     (*env)->ThrowNew(env, jExClass, msg);
  73   }
  74   /* free the local ref */
  75   (*env)->DeleteLocalRef(env, jExClass);
  76 }
  77 
  78 /*
  79  * De-allocates all memory associated with crypto_ctx_t
  80  */
  81 void freeContext(crypto_ctx_t *context) {
  82   if (ftab->ucryptoFreeContext != NULL) {
  83     (*ftab->ucryptoFreeContext)(context);
  84   }
  85   free(context);
  86 }
  87 
  88 JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) {
  89     return JNI_VERSION_1_4;
  90 }
  91 
  92 /*
  93  * Class:     com_oracle_security_ucrypto_UcryptoProvider
  94  * Method:    loadLibraries
  95  * Signature: ()[Z
  96  */
  97 JNIEXPORT jbooleanArray JNICALL Java_com_oracle_security_ucrypto_UcryptoProvider_loadLibraries
  98 (JNIEnv *env, jclass jcls) {
  99   jbooleanArray jResult;
 100   jboolean *result;
 101   jResult = (*env)->NewBooleanArray(env, 2);
 102 
 103   if (jResult != NULL) {
 104     result = loadNative();
 105     (*env)->SetBooleanArrayRegion(env, jResult, 0, 2, result);
 106     free(result);
 107   }
 108   return jResult;
 109 }
 110 
 111 /*
 112  * Class:     com_oracle_security_ucrypto_UcryptoProvider
 113  * Method:    getMechList
 114  * Signature: ()Ljava/lang/String;
 115  */
 116 JNIEXPORT jstring JNICALL Java_com_oracle_security_ucrypto_UcryptoProvider_getMechList
 117 (JNIEnv *env, jclass jcls) {
 118   jstring jResult;
 119   char* result;
 120   int length;
 121 
 122   jResult = NULL;
 123   if (ftab->ucryptoVersion != NULL && ftab->ucryptoGetMechList != NULL) {
 124       length = (*ftab->ucryptoGetMechList)(NULL);
 125       if (J2UC_DEBUG) printf("mech list length: %d\n", length);
 126       result = malloc(length);
 127       if (result == NULL) {
 128         throwOutOfMemoryError(env, NULL);
 129         return NULL;
 130       }
 131       length = (*ftab->ucryptoGetMechList)(result);
 132       if (J2UC_DEBUG) printf("mech list: %s\n", result);
 133       jResult = (*env)->NewStringUTF(env, result);
 134       free(result);
 135   } else {
 136       // version 0 on Solaris 10
 137       result = "CRYPTO_AES_ECB,CRYPTO_AES_CBC,CRYPTO_AES_CFB128,";
 138       jResult = (*env)->NewStringUTF(env, result);
 139   }
 140   return jResult;
 141 }
 142 
 143 /*
 144  * Utility function for throwing a UcryptoException when rv is not CRYPTO_OK(0)
 145  */
 146 void throwUCExceptionUsingRV(JNIEnv *env, int rv) {
 147   jclass jExClass;
 148   jmethodID jConstructor;
 149   jthrowable jException;
 150 
 151   if ((*env)->ExceptionCheck(env)) return;
 152 
 153   jExClass = (*env)->FindClass(env, "com/oracle/security/ucrypto/UcryptoException");
 154   /* if jExClass is NULL, an exception has already been thrown */
 155   if (jExClass != NULL) {
 156     jConstructor = (*env)->GetMethodID(env, jExClass, "<init>", "(I)V");
 157     if (jConstructor != NULL) {
 158       jException = (jthrowable) (*env)->NewObject(env, jExClass, jConstructor, rv);
 159       if (jException != NULL) {
 160         (*env)->Throw(env, jException);
 161       }
 162     }
 163   }
 164   /* free the local ref */
 165   (*env)->DeleteLocalRef(env, jExClass);
 166 }
 167 
 168 /*
 169  * Utility function for duplicating a byte array from jbyteArray
 170  * If anything went wrong, no memory will be allocated.
 171  * NOTE: caller is responsible for freeing the allocated memory
 172  * once this method returned successfully.
 173  */
 174 jbyte* getBytes(JNIEnv *env, jbyteArray bytes, int offset, int len) {
 175   jbyte* result = NULL;
 176 
 177   if (!(*env)->ExceptionCheck(env)) {
 178     result = (jbyte*) calloc(len, sizeof(char));
 179     if (result == NULL) {
 180       throwOutOfMemoryError(env, NULL);
 181       return NULL;
 182     }
 183     (*env)->GetByteArrayRegion(env, bytes, offset, len, result);
 184     if ((*env)->ExceptionCheck(env)) {
 185         // free allocated memory if error occurred
 186         free(result);
 187         return NULL;
 188     }
 189   }
 190   return result;
 191 }
 192 
 193 
 194 int
 195 CipherInit(crypto_ctx_t *context, int encrypt, ucrypto_mech_t mech,
 196            unsigned char *jKey, int jKeyLen, unsigned char *jIv, int jIvLen,
 197            int tagLen, unsigned char *jAad, int jAadLen)
 198 
 199 {
 200   int rv = 0;
 201   void *iv;
 202   size_t ivLen;
 203 
 204   if (J2UC_DEBUG) printf("CipherInit: mech %i, key %i(%i), iv %i(%i) tagLen %i, aad %i(%i)\n",
 205                     mech, jKey, jKeyLen, jIv, jIvLen, tagLen, jAad, jAadLen);
 206   if (mech == CRYPTO_AES_CTR) {
 207     ivLen = sizeof(CK_AES_CTR_PARAMS);
 208     iv = (CK_AES_CTR_PARAMS*) malloc(ivLen);
 209     if (iv == NULL) return -1;
 210 
 211     ((CK_AES_CTR_PARAMS*)iv)->ulCounterBits = 32;
 212     memcpy(((CK_AES_CTR_PARAMS*)iv)->cb, jIv, 16);
 213   } else if (mech == CRYPTO_AES_GCM) {
 214     ivLen = sizeof(CK_AES_GCM_PARAMS);
 215     iv = (CK_AES_GCM_PARAMS*) malloc(ivLen);
 216     if (iv == NULL) return -1;
 217 
 218     ((CK_AES_GCM_PARAMS*)iv)->pIv = (uchar_t *)jIv;
 219     ((CK_AES_GCM_PARAMS*)iv)->ulIvLen = (ulong_t)jIvLen;
 220     ((CK_AES_GCM_PARAMS*)iv)->ulIvBits = 96;
 221     ((CK_AES_GCM_PARAMS*)iv)->pAAD = (uchar_t *)jAad;
 222     ((CK_AES_GCM_PARAMS*)iv)->ulAADLen = (ulong_t)jAadLen;
 223     ((CK_AES_GCM_PARAMS*)iv)->ulTagBits = (ulong_t)tagLen;
 224   } else {
 225     // normal bytes
 226     iv = jIv;
 227     ivLen = jIvLen;
 228   }
 229   if (encrypt) {
 230     rv = (*ftab->ucryptoEncryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
 231     if (rv != 0 && J2UC_DEBUG) printError("ucryptoEncryptInit", mech, rv);
 232   } else {
 233     rv =(*ftab->ucryptoDecryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
 234     if (rv != 0 && J2UC_DEBUG) printError("ucryptoDecryptInit", mech, rv);
 235   }
 236 
 237   if (iv != jIv) {
 238     if (mech == CRYPTO_AES_CTR) {
 239       free((CK_AES_CTR_PARAMS*)iv);
 240     } else {
 241       free((CK_AES_GCM_PARAMS*)iv);
 242     }
 243   }
 244 
 245   return rv;
 246 }
 247 
 248 int
 249 CipherUpdate(crypto_ctx_t *context, int encrypt, unsigned char *bufIn, int inOfs,
 250              int inLen, unsigned char *bufOut, int outOfs, int *outLen)
 251 {
 252   int rv = 0;
 253   size_t outLength;
 254 
 255   outLength = (size_t) *outLen;
 256   if (J2UC_DEBUG) {
 257     printf("CipherUpdate: Inofs %i, InLen %i, OutOfs %i, OutLen %i\n", inOfs, inLen, outOfs, *outLen);
 258     printBytes("BufIn=", (unsigned char*)(bufIn+inOfs), inLen);
 259   }
 260   if (encrypt) {
 261     rv = (*ftab->ucryptoEncryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
 262     if (rv) {
 263       if (J2UC_DEBUG) printError("ucryptoEncryptUpdate", -1, rv);
 264     } else {
 265       *outLen = (int)outLength;
 266     }
 267   } else {
 268     rv = (*ftab->ucryptoDecryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
 269     if (rv) {
 270       if (J2UC_DEBUG) printError("ucryptoDecryptUpdate", -1, rv);
 271     } else {
 272       if (J2UC_DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
 273       *outLen = (int)outLength;
 274     }
 275   }
 276 
 277   return rv;
 278 }
 279 
 280 int
 281 CipherFinal(crypto_ctx_t *context, int encrypt, unsigned char *bufOut, int outOfs, int *outLen)
 282 {
 283   int rv = 0;
 284   size_t outLength;
 285 
 286   outLength = (size_t)*outLen;
 287 
 288   if (J2UC_DEBUG) printf("CipherFinal: OutOfs %i, outLen %i\n", outOfs, *outLen);
 289   if (encrypt) {
 290     rv = (*ftab->ucryptoEncryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
 291     if (rv) {
 292       if (J2UC_DEBUG) printError("ucryptoDecryptFinal", -1, rv);
 293     } else {
 294       if (J2UC_DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
 295       *outLen = (int)outLength;
 296     }
 297   } else {
 298     rv = (*ftab->ucryptoDecryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
 299     if (rv) {
 300       if (J2UC_DEBUG) printError("ucryptoDecryptFinal", -1, rv);
 301     } else {
 302       if (J2UC_DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
 303       *outLen = (int)outLength;
 304     }
 305   }
 306   return rv;
 307 }
 308 
 309 ////////////////////////////////////////////////////////
 310 // SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
 311 ////////////////////////////////////////////////////////
 312 JNIEXPORT jlong JNICALL
 313 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit(jint mech) {
 314   crypto_ctx_t *context = NULL;
 315   int rv;
 316 
 317   context = malloc(sizeof(crypto_ctx_t));
 318   if (context != NULL) {
 319     rv = (*ftab->ucryptoDigestInit)(context, (ucrypto_mech_t) mech, NULL, 0);
 320     if (rv) {
 321       freeContext(context);
 322       if (J2UC_DEBUG) printError("ucryptoDigestInit", mech, rv);
 323       return 0L;
 324     }
 325   }
 326   return (jlong) context;
 327 }
 328 
 329 JNIEXPORT jint JNICALL
 330 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate
 331   (jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) {
 332   crypto_ctx_t *context;
 333   jint rv = 0;
 334 
 335   context = (crypto_ctx_t *) pContext;
 336   rv = (*ftab->ucryptoDigestUpdate)(context, (const unsigned char*)(in + ofs),
 337                                     (size_t) len);
 338 
 339   if (rv) {
 340     freeContext(context);
 341     if (J2UC_DEBUG) printError("ucryptoDigestUpdate", mech, rv);
 342   }
 343 
 344   return -rv; // use negative value to indicate error
 345 }
 346 
 347 JNIEXPORT jint JNICALL
 348 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest
 349   (jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) {
 350   crypto_ctx_t *context;
 351   jint rv = 0;
 352   size_t digest_len = digestLen;
 353 
 354   context = (crypto_ctx_t *) pContext;
 355   rv = (*ftab->ucryptoDigestFinal)(context, (unsigned char*)(out + ofs),
 356                                    &digest_len);
 357   if (rv) {
 358     freeContext(context);
 359     if (J2UC_DEBUG) printError("ucryptoDigestFinal", mech, rv);
 360   }
 361 
 362   return -rv; // use negative value to indicate error
 363 }
 364 
 365 JNIEXPORT void JNICALL
 366 JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree
 367   (jint mech, jlong pContext) {
 368   crypto_ctx_t *context;
 369 
 370   context = (crypto_ctx_t *) pContext;
 371   freeContext(context);
 372 }
 373 
 374 // AES
 375 JNIEXPORT jlong JNICALL
 376 JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeInit
 377   (jint mech, jboolean encrypt, int keyLen, unsigned char* bufKey,
 378    int ivLen, unsigned char* bufIv, jint tagLen, int aadLen, unsigned char* bufAad) {
 379   crypto_ctx_t *context = NULL;
 380   int rv;
 381 
 382   context = malloc(sizeof(crypto_ctx_t));
 383   if (context != NULL) {
 384     rv = CipherInit(context, encrypt, (ucrypto_mech_t) mech, bufKey, keyLen,
 385                     bufIv, ivLen, tagLen, bufAad, aadLen);
 386     if (rv) {
 387       freeContext(context);
 388       return 0L;
 389     }
 390   }
 391   return (jlong)context;
 392 }
 393 
 394 /*
 395  * Class:     com_oracle_security_ucrypto_NativeCipher
 396  * Method:    nativeUpdate
 397  * Signature: (JZ[BII[BI)I
 398  */
 399 JNIEXPORT jint JNICALL
 400 JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate
 401   (jlong pContext, jboolean encrypt, int notUsed, jbyte* bufIn, jint inOfs, jint inLen,
 402    int outCapacity, jbyte* bufOut, jint outOfs) {
 403   crypto_ctx_t *context;
 404   int rv = 0;
 405   int outLen = outCapacity - outOfs; // recalculate the real out length
 406 
 407   context = (crypto_ctx_t *) pContext;
 408   rv = CipherUpdate(context, encrypt, (unsigned char*)bufIn, inOfs, inLen, (unsigned char*)bufOut, outOfs, &outLen);
 409   if (rv) {
 410     freeContext(context);
 411     return -rv; // use negative value to indicate error!
 412   }
 413 
 414   return outLen;
 415 }
 416 
 417 /*
 418  * Class:     com_oracle_security_ucrypto_NativeCipher
 419  * Method:    nativeFinal
 420  * Signature: (JZ[BI)I
 421  */
 422 JNIEXPORT jint JNICALL
 423 JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeFinal
 424   (jlong pContext, jboolean encrypt, int outLen, jbyte* out, jint outOfs) {
 425   crypto_ctx_t *context;
 426   int rv = 0;
 427   unsigned char* bufOut = (unsigned char*) out;
 428 
 429   context = (crypto_ctx_t *) pContext;
 430   // Avoid null output buffer to workaround Solaris bug21481818 (fixed in S12)
 431   if (bufOut == NULL) {
 432     bufOut = (unsigned char*)(&outLen);
 433     outLen = 0;
 434   }
 435   rv = CipherFinal(context, encrypt, bufOut, outOfs, &outLen);
 436   freeContext(context);
 437   if (rv) {
 438      return -rv; // use negative value to indicate error!
 439   }
 440 
 441   return outLen;
 442 }
 443 
 444 /*
 445  * Class:     com_oracle_security_ucrypto_NativeDigest
 446  * Method:    nativeInit
 447  * Signature: (I)J
 448  */
 449 JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeInit
 450   (JNIEnv *env, jclass jcls, jint mech) {
 451   jlong result = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit(mech);
 452   if (result == NULL) {
 453      throwOutOfMemoryError(env, NULL);
 454   }
 455   return result;
 456 }
 457 
 458 /*
 459  * Class:     com_oracle_security_ucrypto_NativeDigest
 460  * Method:    nativeUpdate
 461  * Signature: (IJ[BII)I
 462  */
 463 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate
 464   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
 465   unsigned char *bufIn;
 466   jint rv = 0;
 467 
 468 
 469   bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
 470   if (!(*env)->ExceptionCheck(env)) {
 471     rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
 472     free(bufIn);
 473   }
 474   return rv;
 475 }
 476 
 477 /*
 478  * Class:     com_oracle_security_ucrypto_NativeDigest
 479  * Method:    nativeDigest
 480  * Signature: (IJ[BII)I
 481  */
 482 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest
 483   (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
 484   unsigned char *bufOut;
 485   jint rv = 0;
 486 
 487   bufOut = (unsigned char *) malloc(digestLen);
 488   if (bufOut == NULL) {
 489     throwOutOfMemoryError(env, NULL);
 490     return 0;
 491   }
 492 
 493   rv = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
 494   if (rv == 0) {
 495       (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
 496   }
 497   free(bufOut);
 498   return rv;
 499 }
 500 
 501 /*
 502  * Class:     com_oracle_security_ucrypto_NativeDigest
 503  * Method:    nativeFree
 504  * Signature: (IJ)V
 505  */
 506 JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeFree
 507   (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
 508   JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree(mech, pContext);
 509 }
 510 
 511 /*
 512  * Class:     com_oracle_security_ucrypto_NativeCipher
 513  * Method:    nativeInit
 514  * Signature: (IZ[B[BI[B)J
 515  */
 516 JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeInit
 517 (JNIEnv *env, jclass jcls, jint mech, jboolean encrypt, jbyteArray jKey,
 518  jbyteArray jIv, jint tagLen, jbyteArray jAad) {
 519 
 520   crypto_ctx_t *context;
 521   unsigned char *bufKey;
 522   unsigned char *bufIv;
 523   unsigned char *bufAad;
 524   int keyLen, ivLen, aadLen, rv = 0;
 525   jlong result = 0L;
 526 
 527   bufKey = bufIv = bufAad = NULL;
 528   keyLen = ivLen = aadLen = 0;
 529   context = malloc(sizeof(crypto_ctx_t));
 530   if (context == NULL) {
 531     throwOutOfMemoryError(env, NULL);
 532     return 0L;
 533   }
 534 
 535   // jKey MUST NOT BE NULL;
 536   keyLen = (*env)->GetArrayLength(env, jKey);
 537   bufKey = (unsigned char *) (*env)->GetByteArrayElements(env, jKey, NULL);
 538   if (bufKey == NULL) {
 539     goto cleanup;
 540   }
 541 
 542   if (jIv != NULL) {
 543     ivLen = (*env)->GetArrayLength(env, jIv);
 544     bufIv = (unsigned char *) (*env)->GetByteArrayElements(env, jIv, NULL);
 545     if (bufIv == NULL) {
 546       goto cleanup;
 547     }
 548   }
 549 
 550   if (jAad != NULL) {
 551     aadLen = (*env)->GetArrayLength(env, jAad);
 552     bufAad = (unsigned char *) (*env)->GetByteArrayElements(env, jAad, NULL);
 553     if (bufAad == NULL) {
 554       goto cleanup;
 555     }
 556   }
 557 
 558   rv = CipherInit(context, encrypt, mech, bufKey, keyLen, bufIv, ivLen, tagLen, bufAad, aadLen);
 559   if (rv != 0) {
 560     throwUCExceptionUsingRV(env, rv);
 561   } else {
 562      result = (jlong) context;
 563   }
 564 
 565 cleanup:
 566   if ((result == 0L) && (context != NULL)) {
 567     freeContext(context);
 568   }
 569   if (bufKey != NULL) {
 570     (*env)->ReleaseByteArrayElements(env, jKey, (jbyte *)bufKey, 0);
 571   }
 572   if (bufIv != NULL) {
 573     (*env)->ReleaseByteArrayElements(env, jIv, (jbyte *)bufIv, 0);
 574   }
 575   if (bufAad != NULL) {
 576     (*env)->ReleaseByteArrayElements(env, jAad, (jbyte *)bufAad, 0);
 577   }
 578 
 579   return result;
 580 }
 581 
 582 /*
 583  * Class:     com_oracle_security_ucrypto_NativeCipher
 584  * Method:    nativeUpdate
 585  * Signature: (JZ[BII[BI)I
 586  */
 587 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate
 588   (JNIEnv *env, jclass jcls, jlong contextID, jboolean encrypt,
 589     jbyteArray jIn, jint inOfs, jint inLen, jbyteArray jOut, jint outOfs) {
 590   crypto_ctx_t *context;
 591   unsigned char *bufIn;
 592   unsigned char *bufOut;
 593   int outLen, rv = 0;
 594 
 595   context = (crypto_ctx_t *) contextID;
 596   bufIn = (unsigned char *) getBytes(env, jIn, inOfs, inLen);
 597   if ((*env)->ExceptionCheck(env)) {
 598     return 0;
 599   }
 600 
 601   outLen = (*env)->GetArrayLength(env, jOut) - outOfs;
 602   bufOut = calloc(outLen, sizeof(char));
 603   if (bufOut == NULL) {
 604     free(bufIn);
 605     throwOutOfMemoryError(env, NULL);
 606     return 0;
 607   }
 608 
 609   rv = CipherUpdate(context, encrypt, bufIn, 0, inLen, bufOut, 0, &outLen);
 610   if (rv) {
 611     freeContext(context);
 612     free(bufIn);
 613     free(bufOut);
 614     return -rv;
 615   } else {
 616     (*env)->SetByteArrayRegion(env, jOut, outOfs, outLen, (jbyte *)bufOut);
 617     free(bufIn);
 618     free(bufOut);
 619     return outLen;
 620   }
 621 }
 622 
 623 /*
 624  * Class:     com_oracle_security_ucrypto_NativeCipher
 625  * Method:    nativeFinal
 626  * Signature: (JZ[BI)I
 627  */
 628 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal
 629   (JNIEnv *env, jclass jCls, jlong contextID, jboolean encrypt,
 630    jbyteArray out, jint outOfs) {
 631   crypto_ctx_t *context;
 632   unsigned char *bufIn;
 633   unsigned char *bufOut;
 634   int outLen, rv = 0;
 635   jint rc;
 636 
 637   context = (crypto_ctx_t *) contextID;
 638 
 639   // out is null when nativeFinal() is called solely for resource clean up
 640   if (out == NULL) {
 641     // Avoid null output buffer to workaround Solaris bug21481818 (fixed in S12)
 642     bufOut = (unsigned char *)(&outLen);
 643     outLen = 0;
 644   } else {
 645     outLen = (*env)->GetArrayLength(env, out) - outOfs;
 646     bufOut = calloc(outLen, sizeof(char));
 647     if (bufOut == NULL) {
 648       throwOutOfMemoryError(env, NULL);
 649       return 0;
 650     }
 651   }
 652   rv = CipherFinal(context, encrypt, bufOut, 0, &outLen);
 653   if (rv) {
 654     rc = -rv;
 655   } else {
 656     if (outLen > 0) {
 657       (*env)->SetByteArrayRegion(env, out, outOfs, outLen, (jbyte *)bufOut);
 658     }
 659     rc = outLen;
 660   }
 661   free(context);
 662   if (bufOut != (unsigned char *)(&outLen)) {
 663     free(bufOut);
 664   }
 665   return rc;
 666 }
 667 
 668 
 669 /*
 670  * Class:     com_oracle_security_ucrypto_NativeKey
 671  * Method:    nativeFree
 672  * Signature: (JI)V
 673  */
 674 JNIEXPORT void JNICALL
 675 JavaCritical_com_oracle_security_ucrypto_NativeKey_nativeFree
 676   (jlong id, jint numOfComponents) {
 677   crypto_object_attribute_t* pKey;
 678   int i;
 679 
 680   pKey = (crypto_object_attribute_t*) id;
 681   for (i = 0; i < numOfComponents; i++) {
 682     free(pKey[i].oa_value);
 683   }
 684   free(pKey);
 685 }
 686 
 687 JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeKey_nativeFree
 688   (JNIEnv *env, jclass jCls, jlong id, jint numOfComponents) {
 689   JavaCritical_com_oracle_security_ucrypto_NativeKey_nativeFree(id, numOfComponents);
 690 }
 691 
 692 /*
 693  * Class:     com_oracle_security_ucrypto_NativeKey_RSAPrivate
 694  * Method:    nativeInit
 695  * Signature: ([B[B)J
 696  */
 697 JNIEXPORT jlong JNICALL
 698 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit
 699 (int modLen, jbyte* jMod, int privLen, jbyte* jPriv) {
 700 
 701   unsigned char *mod, *priv;
 702   crypto_object_attribute_t* pKey = NULL;
 703 
 704   pKey = calloc(2, sizeof(crypto_object_attribute_t));
 705   if (pKey == NULL) {
 706     return 0L;
 707   }
 708   mod = priv = NULL;
 709   mod = malloc(modLen);
 710   priv = malloc(privLen);
 711   if (mod == NULL || priv == NULL) {
 712     free(pKey);
 713     free(mod);
 714     free(priv);
 715     return 0L;
 716   } else {
 717     memcpy(mod, jMod, modLen);
 718     memcpy(priv, jPriv, privLen);
 719   }
 720 
 721   // NOTE: numOfComponents should be 2
 722   pKey[0].oa_type = SUN_CKA_MODULUS;
 723   pKey[0].oa_value = (char*) mod;
 724   pKey[0].oa_value_len = (size_t) modLen;
 725   pKey[1].oa_type = SUN_CKA_PRIVATE_EXPONENT;
 726   pKey[1].oa_value = (char*) priv;
 727   pKey[1].oa_value_len = (size_t) privLen;
 728 
 729   return (jlong) pKey;
 730 }
 731 
 732 JNIEXPORT jlong JNICALL
 733 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivate_nativeInit
 734   (JNIEnv *env, jclass jCls, jbyteArray jMod, jbyteArray jPriv) {
 735 
 736   int modLen, privLen;
 737   jbyte *bufMod, *bufPriv;
 738   crypto_object_attribute_t* pKey = NULL;
 739 
 740   bufMod = bufPriv = NULL;
 741 
 742   modLen = (*env)->GetArrayLength(env, jMod);
 743   bufMod = getBytes(env, jMod, 0, modLen);
 744   if ((*env)->ExceptionCheck(env)) goto cleanup;
 745 
 746   privLen = (*env)->GetArrayLength(env, jPriv);
 747   bufPriv = getBytes(env, jPriv, 0, privLen);
 748   if ((*env)->ExceptionCheck(env)) goto cleanup;
 749 
 750   // proceed if no error; otherwise free allocated memory
 751   pKey = calloc(2, sizeof(crypto_object_attribute_t));
 752   if (pKey == NULL) {
 753     throwOutOfMemoryError(env, NULL);
 754     goto cleanup;
 755   }
 756 
 757   // NOTE: numOfComponents should be 2
 758   pKey[0].oa_type = SUN_CKA_MODULUS;
 759   pKey[0].oa_value = (char*) bufMod;
 760   pKey[0].oa_value_len = (size_t) modLen;
 761   pKey[1].oa_type = SUN_CKA_PRIVATE_EXPONENT;
 762   pKey[1].oa_value = (char*) bufPriv;
 763   pKey[1].oa_value_len = (size_t) privLen;
 764   return (jlong) pKey;
 765 
 766 cleanup:
 767   free(bufMod);
 768   free(bufPriv);
 769 
 770   return 0L;
 771 }
 772 
 773 /*
 774  * Class:     com_oracle_security_ucrypto_NativeKey_RSAPrivateCrt
 775  * Method:    nativeInit
 776  * Signature: ([B[B[B[B[B[B[B[B)J
 777  */
 778 JNIEXPORT jlong JNICALL
 779 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit
 780 (int modLen, jbyte* jMod, int pubLen, jbyte* jPub, int privLen, jbyte* jPriv,
 781  int pLen, jbyte* jP, int qLen, jbyte* jQ, int expPLen, jbyte* jExpP,
 782  int expQLen, jbyte* jExpQ, int crtCoeffLen, jbyte* jCrtCoeff) {
 783 
 784   unsigned char *mod, *pub, *priv, *p, *q, *expP, *expQ, *crtCoeff;
 785   crypto_object_attribute_t* pKey = NULL;
 786 
 787   pKey = calloc(8, sizeof(crypto_object_attribute_t));
 788   if (pKey == NULL) {
 789     return 0L;
 790   }
 791   mod = pub = priv = p = q = expP = expQ = crtCoeff = NULL;
 792   mod = malloc(modLen);
 793   pub = malloc(pubLen);
 794   priv = malloc(privLen);
 795   p = malloc(pLen);
 796   q = malloc(qLen);
 797   expP = malloc(expPLen);
 798   expQ = malloc(expQLen);
 799   crtCoeff = malloc(crtCoeffLen);
 800   if (mod == NULL || pub == NULL || priv == NULL || p == NULL ||
 801       q == NULL || expP == NULL || expQ == NULL || crtCoeff == NULL) {
 802     free(pKey);
 803     free(mod);
 804     free(pub);
 805     free(priv);
 806     free(p);
 807     free(q);
 808     free(expP);
 809     free(expQ);
 810     free(crtCoeff);
 811     return 0L;
 812   } else {
 813     memcpy(mod, jMod, modLen);
 814     memcpy(pub, jPub, pubLen);
 815     memcpy(priv, jPriv, privLen);
 816     memcpy(p, jP, pLen);
 817     memcpy(q, jQ, qLen);
 818     memcpy(expP, jExpP, expPLen);
 819     memcpy(expQ, jExpQ, expQLen);
 820     memcpy(crtCoeff, jCrtCoeff, crtCoeffLen);
 821   }
 822 
 823   // NOTE: numOfComponents should be 8
 824   pKey[0].oa_type = SUN_CKA_MODULUS;
 825   pKey[0].oa_value = (char*) mod;
 826   pKey[0].oa_value_len = (size_t) modLen;
 827   pKey[1].oa_type = SUN_CKA_PUBLIC_EXPONENT;
 828   pKey[1].oa_value = (char*) pub;
 829   pKey[1].oa_value_len = (size_t) pubLen;
 830   pKey[2].oa_type = SUN_CKA_PRIVATE_EXPONENT;
 831   pKey[2].oa_value = (char*) priv;
 832   pKey[2].oa_value_len = (size_t) privLen;
 833   pKey[3].oa_type = SUN_CKA_PRIME_1;
 834   pKey[3].oa_value = (char*) p;
 835   pKey[3].oa_value_len = (size_t) pLen;
 836   pKey[4].oa_type = SUN_CKA_PRIME_2;
 837   pKey[4].oa_value = (char*) q;
 838   pKey[4].oa_value_len = (size_t) qLen;
 839   pKey[5].oa_type = SUN_CKA_EXPONENT_1;
 840   pKey[5].oa_value = (char*) expP;
 841   pKey[5].oa_value_len = (size_t) expPLen;
 842   pKey[6].oa_type = SUN_CKA_EXPONENT_2;
 843   pKey[6].oa_value = (char*) expQ;
 844   pKey[6].oa_value_len = (size_t) expQLen;
 845   pKey[7].oa_type = SUN_CKA_COEFFICIENT;
 846   pKey[7].oa_value = (char*) crtCoeff;
 847   pKey[7].oa_value_len = (size_t) crtCoeffLen;
 848 
 849   return (jlong) pKey;
 850 }
 851 
 852 
 853 JNIEXPORT jlong JNICALL
 854 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit
 855   (JNIEnv *env, jclass jCls, jbyteArray jMod, jbyteArray jPub, jbyteArray jPriv,
 856    jbyteArray jP, jbyteArray jQ, jbyteArray jExpP, jbyteArray jExpQ,
 857    jbyteArray jCrtCoeff) {
 858 
 859   int modLen, pubLen, privLen, pLen, qLen, expPLen, expQLen, crtCoeffLen;
 860   jbyte *bufMod, *bufPub, *bufPriv, *bufP, *bufQ, *bufExpP, *bufExpQ, *bufCrtCoeff;
 861   crypto_object_attribute_t* pKey = NULL;
 862 
 863   bufMod = bufPub = bufPriv = bufP = bufQ = bufExpP = bufExpQ = bufCrtCoeff = NULL;
 864 
 865   modLen = (*env)->GetArrayLength(env, jMod);
 866   bufMod = getBytes(env, jMod, 0, modLen);
 867   if ((*env)->ExceptionCheck(env)) goto cleanup;
 868 
 869   pubLen = (*env)->GetArrayLength(env, jPub);
 870   bufPub = getBytes(env, jPub, 0, pubLen);
 871   if ((*env)->ExceptionCheck(env)) goto cleanup;
 872 
 873   privLen = (*env)->GetArrayLength(env, jPriv);
 874   bufPriv = getBytes(env, jPriv, 0, privLen);
 875   if ((*env)->ExceptionCheck(env)) goto cleanup;
 876 
 877   pLen = (*env)->GetArrayLength(env, jP);
 878   bufP = getBytes(env, jP, 0, pLen);
 879   if ((*env)->ExceptionCheck(env)) goto cleanup;
 880 
 881   qLen = (*env)->GetArrayLength(env, jQ);
 882   bufQ = getBytes(env, jQ, 0, qLen);
 883   if ((*env)->ExceptionCheck(env)) goto cleanup;
 884 
 885   expPLen = (*env)->GetArrayLength(env, jExpP);
 886   bufExpP = getBytes(env, jExpP, 0, expPLen);
 887   if ((*env)->ExceptionCheck(env)) goto cleanup;
 888 
 889   expQLen = (*env)->GetArrayLength(env, jExpQ);
 890   bufExpQ = getBytes(env, jExpQ, 0, expQLen);
 891   if ((*env)->ExceptionCheck(env)) goto cleanup;
 892 
 893   crtCoeffLen = (*env)->GetArrayLength(env, jCrtCoeff);
 894   bufCrtCoeff = getBytes(env, jCrtCoeff, 0, crtCoeffLen);
 895   if ((*env)->ExceptionCheck(env)) goto cleanup;
 896 
 897   // proceed if no error; otherwise free allocated memory
 898   pKey = calloc(8, sizeof(crypto_object_attribute_t));
 899   if (pKey == NULL) {
 900     throwOutOfMemoryError(env, NULL);
 901     goto cleanup;
 902   }
 903 
 904   // NOTE: numOfComponents should be 8
 905   pKey[0].oa_type = SUN_CKA_MODULUS;
 906   pKey[0].oa_value = (char*) bufMod;
 907   pKey[0].oa_value_len = (size_t) modLen;
 908   pKey[1].oa_type = SUN_CKA_PUBLIC_EXPONENT;
 909   pKey[1].oa_value = (char*) bufPub;
 910   pKey[1].oa_value_len = (size_t) pubLen;
 911   pKey[2].oa_type = SUN_CKA_PRIVATE_EXPONENT;
 912   pKey[2].oa_value = (char*) bufPriv;
 913   pKey[2].oa_value_len = (size_t) privLen;
 914   pKey[3].oa_type = SUN_CKA_PRIME_1;
 915   pKey[3].oa_value = (char*) bufP;
 916   pKey[3].oa_value_len = (size_t) pLen;
 917   pKey[4].oa_type = SUN_CKA_PRIME_2;
 918   pKey[4].oa_value = (char*) bufQ;
 919   pKey[4].oa_value_len = (size_t) qLen;
 920   pKey[5].oa_type = SUN_CKA_EXPONENT_1;
 921   pKey[5].oa_value = (char*) bufExpP;
 922   pKey[5].oa_value_len = (size_t) expPLen;
 923   pKey[6].oa_type = SUN_CKA_EXPONENT_2;
 924   pKey[6].oa_value = (char*) bufExpQ;
 925   pKey[6].oa_value_len = (size_t) expQLen;
 926   pKey[7].oa_type = SUN_CKA_COEFFICIENT;
 927   pKey[7].oa_value = (char*) bufCrtCoeff;
 928   pKey[7].oa_value_len = (size_t) crtCoeffLen;
 929   return (jlong) pKey;
 930 
 931 cleanup:
 932   free(bufMod);
 933   free(bufPub);
 934   free(bufPriv);
 935   free(bufP);
 936   free(bufQ);
 937   free(bufExpP);
 938   free(bufExpQ);
 939   free(bufCrtCoeff);
 940 
 941   return 0L;
 942 }
 943 
 944 /*
 945  * Class:     com_oracle_security_ucrypto_NativeKey_RSAPublic
 946  * Method:    nativeInit
 947  * Signature: ([B[B)J
 948  */
 949 
 950 JNIEXPORT jlong JNICALL
 951 JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit
 952 (int modLen, jbyte* jMod, int pubLen, jbyte* jPub) {
 953   unsigned char *mod, *pub;
 954   crypto_object_attribute_t* pKey = NULL;
 955 
 956   pKey = calloc(2, sizeof(crypto_object_attribute_t));
 957   if (pKey == NULL) {
 958     return 0L;
 959   }
 960   mod = pub = NULL;
 961   mod = malloc(modLen);
 962   pub = malloc(pubLen);
 963   if (mod == NULL || pub == NULL) {
 964     free(pKey);
 965     free(mod);
 966     free(pub);
 967     return 0L;
 968   } else {
 969     memcpy(mod, jMod, modLen);
 970     memcpy(pub, jPub, pubLen);
 971   }
 972 
 973   if (J2UC_DEBUG) {
 974     printf("RSAPublicKey.nativeInit: keyValue=%ld, keyLen=2\n", pKey);
 975     printBytes("\tmod: ", (unsigned char*) mod, modLen);
 976     printBytes("\tpubExp: ", (unsigned char*) pub, pubLen);
 977   }
 978 
 979   pKey[0].oa_type = SUN_CKA_MODULUS;
 980   pKey[0].oa_value = (char*) mod;
 981   pKey[0].oa_value_len = (size_t) modLen;
 982   pKey[1].oa_type = SUN_CKA_PUBLIC_EXPONENT;
 983   pKey[1].oa_value = (char*) pub;
 984   pKey[1].oa_value_len = (size_t) pubLen;
 985 
 986   return (jlong) pKey;
 987 }
 988 
 989 JNIEXPORT jlong JNICALL
 990 Java_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit
 991 (JNIEnv *env, jclass jCls, jbyteArray jMod, jbyteArray jPub) {
 992   int modLen, pubLen;
 993   jbyte *bufMod, *bufPub;
 994   crypto_object_attribute_t* pKey = NULL;
 995 
 996   bufMod = bufPub = NULL;
 997 
 998   modLen = (*env)->GetArrayLength(env, jMod);
 999   bufMod = getBytes(env, jMod, 0, modLen);
1000   if ((*env)->ExceptionCheck(env)) {
1001     return 0L;
1002   }
1003 
1004   pubLen = (*env)->GetArrayLength(env, jPub);
1005   bufPub = getBytes(env, jPub, 0, pubLen);
1006   if ((*env)->ExceptionCheck(env)) {
1007     free(bufMod);
1008     return 0L;
1009   }
1010 
1011   // proceed if no error; otherwise free allocated memory
1012   pKey = calloc(2, sizeof(crypto_object_attribute_t));
1013   if (pKey != NULL) {
1014     // NOTE: numOfComponents should be 2
1015     pKey[0].oa_type = SUN_CKA_MODULUS;
1016     pKey[0].oa_value = (char*) bufMod;
1017     pKey[0].oa_value_len = (size_t) modLen;
1018     pKey[1].oa_type = SUN_CKA_PUBLIC_EXPONENT;
1019     pKey[1].oa_value = (char*) bufPub;
1020     pKey[1].oa_value_len = (size_t) pubLen;
1021     return (jlong) pKey;
1022   } else {
1023     free(bufMod);
1024     free(bufPub);
1025     throwOutOfMemoryError(env, NULL);
1026     return 0L;
1027   }
1028 }
1029 
1030 ////////////////////////
1031 // NativeRSASignature
1032 ////////////////////////
1033 
1034 int
1035 SignatureInit(crypto_ctx_t *context, jint mechVal, jboolean sign,
1036               uchar_t *pKey, size_t keyLength) {
1037   ucrypto_mech_t mech;
1038   int rv = 0;
1039 
1040   mech = (ucrypto_mech_t) mechVal;
1041 
1042   if (sign) {
1043     rv = (*ftab->ucryptoSignInit)(context, mech, pKey, keyLength,
1044                                   NULL, 0);
1045   } else {
1046     rv = (*ftab->ucryptoVerifyInit)(context, mech, pKey, keyLength,
1047                                     NULL, 0);
1048   }
1049   if (J2UC_DEBUG) {
1050     printf("SignatureInit: context=%ld, mech=%d, sign=%d, keyValue=%ld, keyLength=%d\n",
1051            context, mech, sign, pKey, keyLength);
1052     printError("SignatureInit", mech, rv);
1053   }
1054   return rv;
1055 }
1056 
1057 /*
1058  * Class:     com_oracle_security_ucrypto_NativeRSASignature
1059  * Method:    nativeInit
1060  * Signature: (IZJI[B)J
1061  */
1062 JNIEXPORT jlong JNICALL
1063 JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit
1064 (jint mech, jboolean sign, jlong jKey, jint keyLength) {
1065   crypto_ctx_t *context;
1066   int rv;
1067   uchar_t *pKey;
1068 
1069   context = malloc(sizeof(crypto_ctx_t));
1070   if (context != NULL) {
1071     pKey = (uchar_t *) jKey;
1072     rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
1073     if (rv) {
1074       freeContext(context);
1075       return 0L;
1076     }
1077   }
1078   return (jlong)context;
1079 }
1080 
1081 JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit
1082 (JNIEnv *env, jclass jCls, jint mech, jboolean sign, jlong jKey, jint keyLength) {
1083   crypto_ctx_t *context;
1084   int rv = 0;
1085   uchar_t *pKey;
1086 
1087   context = malloc(sizeof(crypto_ctx_t));
1088   if (context == NULL) {
1089     throwOutOfMemoryError(env, NULL);
1090     return 0L;
1091   }
1092 
1093   pKey = (uchar_t *) jKey;
1094   rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
1095   if (rv) {
1096     freeContext(context);
1097     throwUCExceptionUsingRV(env, rv);
1098     return 0L;
1099   }
1100 
1101   return (jlong)context;
1102 }
1103 
1104 /*
1105  * Class:     com_oracle_security_ucrypto_NativeRSASignature
1106  * Method:    nativeUpdate
1107  * Signature: (JZ[BII)I
1108  */
1109 JNIEXPORT jint JNICALL
1110 JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII
1111 (jlong pCtxt, jboolean sign, int notUsed, jbyte* jIn, jint jInOfs, jint jInLen) {
1112   crypto_ctx_t *context;
1113   int rv = 0;
1114 
1115   context = (crypto_ctx_t *) pCtxt;
1116   if (J2UC_DEBUG) {
1117     printf("NativeRSASignature.nativeUpdate: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n",
1118            context, sign, jIn, jInOfs, jInLen);
1119   }
1120   if (sign) {
1121     rv = (*ftab->ucryptoSignUpdate)(context, (uchar_t *) (jIn + jInOfs), (size_t) jInLen);
1122   } else {
1123     rv = (*ftab->ucryptoVerifyUpdate)(context, (uchar_t *) (jIn + jInOfs), (size_t) jInLen);
1124   }
1125   if (rv) {
1126     freeContext(context);
1127     if (J2UC_DEBUG) printError("NativeRSASignature.nativeUpdate", -1, rv);
1128     return -rv; // use negative value to indicate error!
1129   }
1130 
1131   return 0;
1132 }
1133 
1134 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII
1135 (JNIEnv *env, jclass jCls, jlong pCtxt, jboolean sign, jbyteArray jIn, jint inOfs, jint inLen) {
1136   int rv = 0;
1137   jbyte* bufIn;
1138 
1139   bufIn = getBytes(env, jIn, inOfs, inLen);
1140   if ((*env)->ExceptionCheck(env)) {
1141     return -1; // use negative value to indicate error!
1142   }
1143 
1144   if (J2UC_DEBUG) printBytes("Update w/ data: ", (unsigned char*)bufIn, (size_t) inLen);
1145 
1146   rv = JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII
1147     (pCtxt, sign, inLen, bufIn, 0, inLen);
1148 
1149   free(bufIn);
1150   return rv;
1151 }
1152 
1153 /*
1154  * Class:     com_oracle_security_ucrypto_NativeRSASignature
1155  * Method:    nativeUpdate
1156  * Signature: (JZJI)I
1157  */
1158 JNIEXPORT jint JNICALL
1159 JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI
1160 (jlong pCtxt, jboolean sign, jlong inAddr, jint inLen) {
1161 
1162   return JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII
1163     (pCtxt, sign, inLen, (jbyte*)inAddr, 0, inLen);
1164 }
1165 
1166 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI
1167 (JNIEnv *env, jclass jCls, jlong pCtxt, jboolean sign, jlong inAddr, jint inLen) {
1168 
1169   return JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII
1170     (pCtxt, sign, inLen, (jbyte*)inAddr, 0, inLen);
1171 }
1172 
1173 /*
1174  * Class:     com_oracle_security_ucrypto_NativeRSASignature
1175  * Method:    nativeFinal
1176  * Signature: (JZ[BII)I
1177  */
1178 JNIEXPORT jint JNICALL
1179 JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal
1180 (jlong pCtxt, jboolean sign, int notUsed, jbyte* bufSig, jint sigOfs, jint jSigLen) {
1181 
1182   crypto_ctx_t *context;
1183   int rv = 0;
1184   size_t sigLength = (size_t) jSigLen;
1185 
1186   context = (crypto_ctx_t *) pCtxt;
1187   if (J2UC_DEBUG) {
1188       printf("NativeRSASignature.nativeFinal: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n",
1189              context, sign, bufSig, sigOfs, jSigLen);
1190       printBytes("Before: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
1191   }
1192   if (sign) {
1193     rv = (*ftab->ucryptoSignFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
1194   } else {
1195     rv = (*ftab->ucryptoVerifyFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
1196   }
1197 
1198   freeContext(context);
1199   if (rv) {
1200     if (J2UC_DEBUG) {
1201       printError("NativeRSASignature.nativeFinal", -1, rv);
1202       if (sigLength != jSigLen) {
1203         printf("NativeRSASignature.nativeFinal out sig len=%d\n", sigLength);
1204       }
1205       if (sign) {
1206         printBytes("After: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
1207       }
1208     }
1209     return -rv;
1210   } else return 0;
1211 }
1212 
1213 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal
1214 (JNIEnv *env, jclass jCls, jlong pCtxt, jboolean sign, jbyteArray jSig, jint jSigOfs, jint jSigLen) {
1215   int rv = 0;
1216   jbyte* bufSig = NULL;
1217 
1218   if (jSigLen != 0) {
1219     bufSig = calloc(jSigLen, sizeof(char));
1220     if (bufSig == NULL) {
1221       throwOutOfMemoryError(env, NULL);
1222       return 0;
1223     }
1224     if (!sign) {
1225       // need to copy over the to-be-verified signature bytes
1226       (*env)->GetByteArrayRegion(env, jSig, jSigOfs, jSigLen, (jbyte *)bufSig);
1227     }
1228   }
1229 
1230   if (!(*env)->ExceptionCheck(env)) {
1231     // Frees context + converts rv to negative if error occurred
1232     rv = JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal
1233       (pCtxt, sign, jSigLen, bufSig, 0, jSigLen);
1234 
1235     if (rv == 0 && sign) {
1236       // need to copy the generated signature bytes to the java bytearray
1237       (*env)->SetByteArrayRegion(env, jSig, jSigOfs, jSigLen, (jbyte *)bufSig);
1238     }
1239   } else {
1240     // set rv to negative to indicate error
1241     rv = -1;
1242   }
1243 
1244   free(bufSig);
1245 
1246   return rv;
1247 }
1248 
1249 /*
1250  * Class:     com_oracle_security_ucrypto_NativeRSACipher
1251  * Method:    nativeAtomic
1252  * Signature: (IZJI[BI[BII)I
1253  */
1254 JNIEXPORT jint JNICALL
1255 JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic
1256   (jint mech, jboolean encrypt, jlong keyValue, jint keyLength,
1257    int notUsed1, jbyte* bufIn, jint jInLen,
1258    int notUsed2, jbyte* bufOut, jint jOutOfs, jint jOutLen) {
1259 
1260   uchar_t *pKey;
1261   crypto_object_attribute_t* pKey2;
1262   int rv = 0;
1263   size_t outLength = (size_t) jOutLen;
1264 
1265   pKey = (uchar_t *) keyValue;
1266   if (J2UC_DEBUG) {
1267     printf("NativeRSACipher.nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n",
1268            mech, encrypt, pKey, keyLength);
1269     printBytes("Before: in  = ", (unsigned char*) bufIn, jInLen);
1270     printBytes("Before: out = ", (unsigned char*) (bufOut + jOutOfs), jOutLen);
1271   }
1272 
1273   if (encrypt) {
1274     rv = (*ftab->ucryptoEncrypt)((ucrypto_mech_t)mech, pKey, (size_t)keyLength,
1275       NULL, 0, (uchar_t *)bufIn, (size_t)jInLen,
1276       (uchar_t *)(bufOut + jOutOfs), &outLength);
1277   } else {
1278     rv = (*ftab->ucryptoDecrypt)((ucrypto_mech_t)mech, pKey, (size_t)keyLength,
1279       NULL, 0, (uchar_t *)bufIn, (size_t)jInLen,
1280       (uchar_t *)(bufOut + jOutOfs), &outLength);
1281   }
1282   if (J2UC_DEBUG) {
1283     printError("NativeRSACipher.nativeAtomic", mech, rv);
1284     if (outLength != jOutLen) {
1285       printf("NativeRSACipher.nativeAtomic out len=%d\n", outLength);
1286     }
1287     printBytes("After: ", (unsigned char*) (bufOut + jOutOfs), outLength);
1288   }
1289 
1290   if (rv) {
1291     return -rv;
1292   } else return outLength;
1293 }
1294 
1295 JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic
1296   (JNIEnv *env, jclass jCls, jint mech, jboolean encrypt,
1297    jlong keyValue, jint keyLength, jbyteArray jIn, jint jInLen,
1298    jbyteArray jOut, jint jOutOfs, jint jOutLen) {
1299   int rv = 0;
1300   jbyte *bufIn = NULL;
1301   jbyte *bufOut = NULL;
1302 
1303   if (jInLen != 0) {
1304     bufIn = (*env)->GetByteArrayElements(env, jIn, NULL);
1305     if (bufIn == NULL) {
1306       return 0;
1307     }
1308   }
1309   bufOut = calloc(jOutLen, sizeof(jbyte));
1310   if (bufOut == NULL) {
1311     (*env)->ReleaseByteArrayElements(env, jIn, bufIn, 0);
1312     throwOutOfMemoryError(env, NULL);
1313     return 0;
1314   }
1315 
1316   // rv: output length or error code (if negative)
1317   rv = JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic
1318     (mech, encrypt, keyValue, keyLength, jInLen, bufIn, jInLen,
1319      jOutLen, bufOut, 0, jOutLen);
1320 
1321   if (rv > 0) {
1322     (*env)->SetByteArrayRegion(env, jOut, jOutOfs, rv, (jbyte *)bufOut);
1323   }
1324 
1325   if (bufIn != NULL) {
1326     (*env)->ReleaseByteArrayElements(env, jIn, bufIn, 0);
1327   }
1328   free(bufOut);
1329   return rv;
1330 }