/* * Class: sun_security_pkcs11_wrapper_PKCS11 * Method: C_CreateObject * Signature: (J[Lsun/security/pkcs11/wrapper/CK_ATTRIBUTE;)J * Parametermapping: *PKCS11* * @param jlong jSessionHandle CK_SESSION_HANDLE hSession * @param jobjectArray jTemplate CK_ATTRIBUTE_PTR pTemplate * CK_ULONG ulCount * @return jlong jObjectHandle CK_OBJECT_HANDLE_PTR phObject */ JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1CreateObject (JNIEnv *env, jobject obj, jlong jSessionHandle, jobjectArray jTemplate) { CK_SESSION_HANDLE ckSessionHandle; CK_OBJECT_HANDLE ckObjectHandle; CK_ATTRIBUTE_PTR ckpAttributes = NULL_PTR; CK_ULONG ckAttributesLength; jlong jObjectHandle = 0L; CK_RV rv; CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); if (ckpFunctions == NULL) { return 0L; } ckSessionHandle = jLongToCKULong(jSessionHandle); jAttributeArrayToCKAttributeArray(env, jTemplate, &ckpAttributes, &ckAttributesLength); if ((*env)->ExceptionCheck(env)) { return 0L; } rv = (*ckpFunctions->C_CreateObject)(ckSessionHandle, ckpAttributes, ckAttributesLength, &ckObjectHandle); jObjectHandle = ckULongToJLong(ckObjectHandle); freeCKAttributeArray(ckpAttributes, ckAttributesLength); if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return 0L ; } return jObjectHandle ; }
/* * Class: sun_security_pkcs11_wrapper_PKCS11 * Method: C_GenerateKey * Signature: (JLsun/security/pkcs11/wrapper/CK_MECHANISM;[Lsun/security/pkcs11/wrapper/CK_ATTRIBUTE;)J * Parametermapping: *PKCS11* * @param jlong jSessionHandle CK_SESSION_HANDLE hSession * @param jobject jMechanism CK_MECHANISM_PTR pMechanism * @param jobjectArray jTemplate CK_ATTRIBUTE_PTR pTemplate * CK_ULONG ulCount * @return jlong jKeyHandle CK_OBJECT_HANDLE_PTR phKey */ JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GenerateKey (JNIEnv *env, jobject obj, jlong jSessionHandle, jobject jMechanism, jobjectArray jTemplate) { CK_SESSION_HANDLE ckSessionHandle; CK_MECHANISM ckMechanism; CK_ATTRIBUTE_PTR ckpAttributes = NULL_PTR; CK_ULONG ckAttributesLength; CK_OBJECT_HANDLE ckKeyHandle = 0; jlong jKeyHandle = 0L; CK_RV rv; CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); if (ckpFunctions == NULL) { return 0L; } ckSessionHandle = jLongToCKULong(jSessionHandle); jMechanismToCKMechanism(env, jMechanism, &ckMechanism); if ((*env)->ExceptionCheck(env)) { return 0L ; } jAttributeArrayToCKAttributeArray(env, jTemplate, &ckpAttributes, &ckAttributesLength); if ((*env)->ExceptionCheck(env)) { if (ckMechanism.pParameter != NULL_PTR) { free(ckMechanism.pParameter); } return 0L; } rv = (*ckpFunctions->C_GenerateKey)(ckSessionHandle, &ckMechanism, ckpAttributes, ckAttributesLength, &ckKeyHandle); if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) { jKeyHandle = ckULongToJLong(ckKeyHandle); /* cheack, if we must give a initialization vector back to Java */ switch (ckMechanism.mechanism) { case CKM_PBE_MD2_DES_CBC: case CKM_PBE_MD5_DES_CBC: case CKM_PBE_MD5_CAST_CBC: case CKM_PBE_MD5_CAST3_CBC: case CKM_PBE_MD5_CAST128_CBC: /* case CKM_PBE_MD5_CAST5_CBC: the same as CKM_PBE_MD5_CAST128_CBC */ case CKM_PBE_SHA1_CAST128_CBC: /* case CKM_PBE_SHA1_CAST5_CBC: the same as CKM_PBE_SHA1_CAST128_CBC */ /* we must copy back the initialization vector to the jMechanism object */ copyBackPBEInitializationVector(env, &ckMechanism, jMechanism); break; } } if (ckMechanism.pParameter != NULL_PTR) { free(ckMechanism.pParameter); } freeCKAttributeArray(ckpAttributes, ckAttributesLength); return jKeyHandle ; }
/* * converts a CK_ULONG pointer to a Java long Object. * * @param env - used to call JNI funktions to create the new Java object * @param ckpValue - the pointer to the CK_ULONG value * @return - the new Java long object with the long value */ jobject ckULongPtrToJLongObject(JNIEnv *env, const CK_ULONG_PTR ckpValue) { jclass jValueObjectClass; jmethodID jConstructor; jobject jValueObject; jlong jValue; jValueObjectClass = (*env)->FindClass(env, "java/lang/Long"); if (jValueObjectClass == NULL) { return NULL; } jConstructor = (*env)->GetMethodID(env, jValueObjectClass, "<init>", "(J)V"); if (jConstructor == NULL) { return NULL; } jValue = ckULongToJLong(*ckpValue); jValueObject = (*env)->NewObject(env, jValueObjectClass, jConstructor, jValue); return jValueObject ; }
/* * Class: sun_security_pkcs11_wrapper_PKCS11 * Method: C_GetObjectSize * Signature: (JJ)J * Parametermapping: *PKCS11* * @param jlong jSessionHandle CK_SESSION_HANDLE hSession * @param jlong jObjectHandle CK_OBJECT_HANDLE hObject * @return jlong jObjectSize CK_ULONG_PTR pulSize */ JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetObjectSize (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jObjectHandle) { CK_SESSION_HANDLE ckSessionHandle; CK_OBJECT_HANDLE ckObjectHandle; CK_ULONG ckObjectSize; jlong jObjectSize = 0L; CK_RV rv; CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); if (ckpFunctions == NULL) { return 0L; } ckSessionHandle = jLongToCKULong(jSessionHandle); ckObjectHandle = jLongToCKULong(jObjectHandle); rv = (*ckpFunctions->C_GetObjectSize)(ckSessionHandle, ckObjectHandle, &ckObjectSize); if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return 0L ; } jObjectSize = ckULongToJLong(ckObjectSize); return jObjectSize ; }
/* * function to convert a PKCS#11 return value into a PKCS#11Exception * * This function generates a PKCS#11Exception with the returnValue as the errorcode * if the returnValue is not CKR_OK. The functin returns 0, if the returnValue is * CKR_OK. Otherwise, it returns the returnValue as a jLong. * * @param env - used to call JNI funktions and to get the Exception class * @param returnValue - of the PKCS#11 function */ jlong ckAssertReturnValueOK(JNIEnv *env, CK_RV returnValue) { jclass jPKCS11ExceptionClass; jmethodID jConstructor; jthrowable jPKCS11Exception; jlong jErrorCode = 0L; if (returnValue != CKR_OK) { jErrorCode = ckULongToJLong(returnValue); jPKCS11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION); if (jPKCS11ExceptionClass != NULL) { jConstructor = (*env)->GetMethodID(env, jPKCS11ExceptionClass, "<init>", "(J)V"); if (jConstructor != NULL) { jPKCS11Exception = (jthrowable) (*env)->NewObject(env, jPKCS11ExceptionClass, jConstructor, jErrorCode); if (jPKCS11Exception != NULL) { (*env)->Throw(env, jPKCS11Exception); } } } (*env)->DeleteLocalRef(env, jPKCS11ExceptionClass); } return jErrorCode ; }
/* * Class: sun_security_pkcs11_wrapper_PKCS11 * Method: C_OpenSession * Signature: (JJLjava/lang/Object;Lsun/security/pkcs11/wrapper/CK_NOTIFY;)J * Parametermapping: *PKCS11* * @param jlong jSlotID CK_SLOT_ID slotID * @param jlong jFlags CK_FLAGS flags * @param jobject jApplication CK_VOID_PTR pApplication * @param jobject jNotify CK_NOTIFY Notify * @return jlong jSessionHandle CK_SESSION_HANDLE_PTR phSession */ JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1OpenSession (JNIEnv *env, jobject obj, jlong jSlotID, jlong jFlags, jobject jApplication, jobject jNotify) { CK_SESSION_HANDLE ckSessionHandle; CK_SLOT_ID ckSlotID; CK_FLAGS ckFlags; CK_VOID_PTR ckpApplication; CK_NOTIFY ckNotify; jlong jSessionHandle; CK_RV rv; #ifndef NO_CALLBACKS NotifyEncapsulation *notifyEncapsulation = NULL; #endif /* NO_CALLBACKS */ CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); if (ckpFunctions == NULL) { return 0L; } ckSlotID = jLongToCKULong(jSlotID); ckFlags = jLongToCKULong(jFlags); #ifndef NO_CALLBACKS if (jNotify != NULL) { notifyEncapsulation = (NotifyEncapsulation *) malloc(sizeof(NotifyEncapsulation)); if (notifyEncapsulation == NULL) { JNU_ThrowOutOfMemoryError(env, 0); return 0L; } notifyEncapsulation->jApplicationData = (jApplication != NULL) ? (*env)->NewGlobalRef(env, jApplication) : NULL; notifyEncapsulation->jNotifyObject = (*env)->NewGlobalRef(env, jNotify); ckpApplication = notifyEncapsulation; ckNotify = (CK_NOTIFY) ¬ifyCallback; } else { ckpApplication = NULL_PTR; ckNotify = NULL_PTR; } #else ckpApplication = NULL_PTR; ckNotify = NULL_PTR; #endif /* NO_CALLBACKS */ TRACE0("DEBUG: C_OpenSession"); TRACE1(", slotID=%u", ckSlotID); TRACE1(", flags=%x", ckFlags); TRACE0(" ... "); rv = (*ckpFunctions->C_OpenSession)(ckSlotID, ckFlags, ckpApplication, ckNotify, &ckSessionHandle); if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { #ifndef NO_CALLBACKS if (notifyEncapsulation != NULL) { if (notifyEncapsulation->jApplicationData != NULL) { (*env)->DeleteGlobalRef(env, jApplication); } (*env)->DeleteGlobalRef(env, jNotify); free(notifyEncapsulation); } #endif /* NO_CALLBACKS */ return 0L; } TRACE0("got session"); TRACE1(", SessionHandle=%u", ckSessionHandle); TRACE0(" ... "); jSessionHandle = ckULongToJLong(ckSessionHandle); #ifndef NO_CALLBACKS if (notifyEncapsulation != NULL) { /* store the notifyEncapsulation to enable later cleanup */ putNotifyEntry(env, ckSessionHandle, notifyEncapsulation); } #endif /* NO_CALLBACKS */ TRACE0("FINISHED\n"); return jSessionHandle ; }
/* * The function handling notify callbacks. It casts the pApplication paramter * back to a NotifyEncapsulation structure and retrieves the Notify object and * the application data from it. * * @param hSession The session, this callback is comming from. * @param event The type of event that occurred. * @param pApplication The application data as passed in upon OpenSession. In this wrapper we always pass in a NotifyEncapsulation object, which holds necessary information for delegating the callback to the Java VM. * @return */ CK_RV notifyCallback( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_NOTIFICATION event, CK_VOID_PTR pApplication /* passed to C_OpenSession */ ) { NotifyEncapsulation *notifyEncapsulation; JavaVM *jvm; JNIEnv *env; jsize actualNumberVMs; jint returnValue; jlong jSessionHandle; jlong jEvent; jclass ckNotifyClass; jmethodID jmethod; jthrowable pkcs11Exception; jclass pkcs11ExceptionClass; jlong errorCode; CK_RV rv = CKR_OK; int wasAttached = 1; if (pApplication == NULL) { return rv ; } /* This should not occur in this wrapper. */ notifyEncapsulation = (NotifyEncapsulation *) pApplication; /* Get the currently running Java VM */ returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs); if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */ /* Determine, if current thread is already attached */ returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); if (returnValue == JNI_EDETACHED) { /* thread detached, so attach it */ wasAttached = 0; returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); } else if (returnValue == JNI_EVERSION) { /* this version of JNI is not supported, so just try to attach */ /* we assume it was attached to ensure that this thread is not detached * afterwards even though it should not */ wasAttached = 1; returnValue = (*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); } else { /* attached */ wasAttached = 1; } jSessionHandle = ckULongToJLong(hSession); jEvent = ckULongToJLong(event); ckNotifyClass = (*env)->FindClass(env, CLASS_NOTIFY); if (ckNotifyClass == NULL) { return rv; } jmethod = (*env)->GetMethodID(env, ckNotifyClass, "CK_NOTIFY", "(JJLjava/lang/Object;)V"); if (jmethod == NULL) { return rv; } (*env)->CallVoidMethod(env, notifyEncapsulation->jNotifyObject, jmethod, jSessionHandle, jEvent, notifyEncapsulation->jApplicationData); /* check, if callback threw an exception */ pkcs11Exception = (*env)->ExceptionOccurred(env); if (pkcs11Exception != NULL) { /* TBD: clear the pending exception with ExceptionClear? */ /* The was an exception thrown, now we get the error-code from it */ pkcs11ExceptionClass = (*env)->FindClass(env, CLASS_PKCS11EXCEPTION); if (pkcs11ExceptionClass == NULL) { return rv; } jmethod = (*env)->GetMethodID(env, pkcs11ExceptionClass, "getErrorCode", "()J"); if (jmethod == NULL) { return rv; } errorCode = (*env)->CallLongMethod(env, pkcs11Exception, jmethod); rv = jLongToCKULong(errorCode); } /* if we attached this thread to the VM just for callback, we detach it now */ if (wasAttached) { returnValue = (*jvm)->DetachCurrentThread(jvm); } return rv ; }
/* * Copy back the derived keys and initialization vectors from the native * structure to the Java object. This is only used for the * CKM_SSL3_KEY_AND_MAC_DERIVE mechanism when used for deriving a key. * */ void copyBackSSLKeyMatParams(JNIEnv *env, CK_MECHANISM *ckMechanism, jobject jMechanism) { jclass jMechanismClass, jSSL3KeyMatParamsClass, jSSL3KeyMatOutClass; CK_SSL3_KEY_MAT_PARAMS *ckSSL3KeyMatParam; CK_SSL3_KEY_MAT_OUT *ckSSL3KeyMatOut; jfieldID fieldID; CK_MECHANISM_TYPE ckMechanismType; jlong jMechanismType; CK_BYTE_PTR iv; jobject jSSL3KeyMatParam; jobject jSSL3KeyMatOut; jobject jIV; jint jLength; jbyte* jBytes; int i; /* get mechanism */ jMechanismClass= (*env)->FindClass(env, CLASS_MECHANISM); if (jMechanismClass == NULL) { return; } fieldID = (*env)->GetFieldID(env, jMechanismClass, "mechanism", "J"); if (fieldID == NULL) { return; } jMechanismType = (*env)->GetLongField(env, jMechanism, fieldID); ckMechanismType = jLongToCKULong(jMechanismType); if (ckMechanismType != ckMechanism->mechanism) { /* we do not have maching types, this should not occur */ return; } /* get the native CK_SSL3_KEY_MAT_PARAMS */ ckSSL3KeyMatParam = (CK_SSL3_KEY_MAT_PARAMS *) ckMechanism->pParameter; if (ckSSL3KeyMatParam != NULL_PTR) { // free malloc'd data if (ckSSL3KeyMatParam->RandomInfo.pClientRandom != NULL) { free(ckSSL3KeyMatParam->RandomInfo.pClientRandom); } if (ckSSL3KeyMatParam->RandomInfo.pServerRandom != NULL) { free(ckSSL3KeyMatParam->RandomInfo.pServerRandom); } /* get the native CK_SSL3_KEY_MAT_OUT */ ckSSL3KeyMatOut = ckSSL3KeyMatParam->pReturnedKeyMaterial; if (ckSSL3KeyMatOut != NULL_PTR) { /* get the Java CK_SSL3_KEY_MAT_PARAMS (pParameter) */ fieldID = (*env)->GetFieldID(env, jMechanismClass, "pParameter", "Ljava/lang/Object;"); if (fieldID == NULL) { return; } jSSL3KeyMatParam = (*env)->GetObjectField(env, jMechanism, fieldID); /* get the Java CK_SSL3_KEY_MAT_OUT */ jSSL3KeyMatParamsClass = (*env)->FindClass(env, CLASS_SSL3_KEY_MAT_PARAMS); if (jSSL3KeyMatParamsClass == NULL) { return; } fieldID = (*env)->GetFieldID(env, jSSL3KeyMatParamsClass, "pReturnedKeyMaterial", "L"CLASS_SSL3_KEY_MAT_OUT";"); if (fieldID == NULL) { return; } jSSL3KeyMatOut = (*env)->GetObjectField(env, jSSL3KeyMatParam, fieldID); /* now copy back all the key handles and the initialization vectors */ /* copy back client MAC secret handle */ jSSL3KeyMatOutClass = (*env)->FindClass(env, CLASS_SSL3_KEY_MAT_OUT); if (jSSL3KeyMatOutClass == NULL) { return; } fieldID = (*env)->GetFieldID(env, jSSL3KeyMatOutClass, "hClientMacSecret", "J"); if (fieldID == NULL) { return; } (*env)->SetLongField(env, jSSL3KeyMatOut, fieldID, ckULongToJLong(ckSSL3KeyMatOut->hClientMacSecret)); /* copy back server MAC secret handle */ fieldID = (*env)->GetFieldID(env, jSSL3KeyMatOutClass, "hServerMacSecret", "J"); if (fieldID == NULL) { return; } (*env)->SetLongField(env, jSSL3KeyMatOut, fieldID, ckULongToJLong(ckSSL3KeyMatOut->hServerMacSecret)); /* copy back client secret key handle */ fieldID = (*env)->GetFieldID(env, jSSL3KeyMatOutClass, "hClientKey", "J"); if (fieldID == NULL) { return; } (*env)->SetLongField(env, jSSL3KeyMatOut, fieldID, ckULongToJLong(ckSSL3KeyMatOut->hClientKey)); /* copy back server secret key handle */ fieldID = (*env)->GetFieldID(env, jSSL3KeyMatOutClass, "hServerKey", "J"); if (fieldID == NULL) { return; } (*env)->SetLongField(env, jSSL3KeyMatOut, fieldID, ckULongToJLong(ckSSL3KeyMatOut->hServerKey)); /* copy back the client IV */ fieldID = (*env)->GetFieldID(env, jSSL3KeyMatOutClass, "pIVClient", "[B"); if (fieldID == NULL) { return; } jIV = (*env)->GetObjectField(env, jSSL3KeyMatOut, fieldID); iv = ckSSL3KeyMatOut->pIVClient; if (jIV != NULL) { jLength = (*env)->GetArrayLength(env, jIV); jBytes = (*env)->GetByteArrayElements(env, jIV, NULL); if (jBytes == NULL) { return; } /* copy the bytes to the Java buffer */ for (i=0; i < jLength; i++) { jBytes[i] = ckByteToJByte(iv[i]); } /* copy back the Java buffer to the object */ (*env)->ReleaseByteArrayElements(env, jIV, jBytes, 0); } // free malloc'd data free(ckSSL3KeyMatOut->pIVClient); /* copy back the server IV */ fieldID = (*env)->GetFieldID(env, jSSL3KeyMatOutClass, "pIVServer", "[B"); if (fieldID == NULL) { return; } jIV = (*env)->GetObjectField(env, jSSL3KeyMatOut, fieldID); iv = ckSSL3KeyMatOut->pIVServer; if (jIV != NULL) { jLength = (*env)->GetArrayLength(env, jIV); jBytes = (*env)->GetByteArrayElements(env, jIV, NULL); if (jBytes == NULL) { return; } /* copy the bytes to the Java buffer */ for (i=0; i < jLength; i++) { jBytes[i] = ckByteToJByte(iv[i]); } /* copy back the Java buffer to the object */ (*env)->ReleaseByteArrayElements(env, jIV, jBytes, 0); } // free malloc'd data free(ckSSL3KeyMatOut->pIVServer); free(ckSSL3KeyMatOut); } } }