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