8255409: Support the new C_GetInterfaceList, C_GetInterface, and C_SessionCancel APIs in PKCS#11 v3.0

Reviewed-by: ascarpino, weijun
This commit is contained in:
Valerie Peng 2021-12-08 23:04:15 +00:00
parent 3cec700a5c
commit 83e6a4c0e9
18 changed files with 647 additions and 201 deletions

View File

@ -165,7 +165,7 @@ final class Config {
// name of the C function that returns the PKCS#11 functionlist
// This option primarily exists for the deprecated
// Secmod.Module.getProvider() method.
private String functionList = "C_GetFunctionList";
private String functionList = null;
// whether to use NSS secmod mode. Implicitly set if nssLibraryDirectory,
// nssSecmodDirectory, or nssModule is specified.
@ -311,6 +311,12 @@ final class Config {
}
String getFunctionList() {
if (functionList == null) {
// defaults to "C_GetFunctionList" for NSS secmod
if (nssUseSecmod || nssUseSecmodTrust) {
return "C_GetFunctionList";
}
}
return functionList;
}
@ -408,67 +414,73 @@ final class Config {
if (token != TT_WORD) {
throw excToken("Unexpected token:");
}
String word = st.sval;
if (word.equals("name")) {
name = parseStringEntry(word);
} else if (word.equals("library")) {
library = parseLibrary(word);
} else if (word.equals("description")) {
parseDescription(word);
} else if (word.equals("slot")) {
parseSlotID(word);
} else if (word.equals("slotListIndex")) {
parseSlotListIndex(word);
} else if (word.equals("enabledMechanisms")) {
parseEnabledMechanisms(word);
} else if (word.equals("disabledMechanisms")) {
parseDisabledMechanisms(word);
} else if (word.equals("attributes")) {
parseAttributes(word);
} else if (word.equals("handleStartupErrors")) {
parseHandleStartupErrors(word);
} else if (word.endsWith("insertionCheckInterval")) {
insertionCheckInterval = parseIntegerEntry(word);
switch (st.sval) {
case "name"->
name = parseStringEntry(st.sval);
case "library"->
library = parseLibrary(st.sval);
case "description"->
parseDescription(st.sval);
case "slot"->
parseSlotID(st.sval);
case "slotListIndex"->
parseSlotListIndex(st.sval);
case "enabledMechanisms"->
parseEnabledMechanisms(st.sval);
case "disabledMechanisms"->
parseDisabledMechanisms(st.sval);
case "attributes"->
parseAttributes(st.sval);
case "handleStartupErrors"->
parseHandleStartupErrors(st.sval);
case "insertionCheckInterval"-> {
insertionCheckInterval = parseIntegerEntry(st.sval);
if (insertionCheckInterval < 100) {
throw excLine(word + " must be at least 100 ms");
throw excLine(st.sval + " must be at least 100 ms");
}
} else if (word.equals("cleaner.shortInterval")) {
resourceCleanerShortInterval = parseIntegerEntry(word);
}
case "cleaner.shortInterval"-> {
resourceCleanerShortInterval = parseIntegerEntry(st.sval);
if (resourceCleanerShortInterval < 1_000) {
throw excLine(word + " must be at least 1000 ms");
throw excLine(st.sval + " must be at least 1000 ms");
}
} else if (word.equals("cleaner.longInterval")) {
resourceCleanerLongInterval = parseIntegerEntry(word);
}
case "cleaner.longInterval"-> {
resourceCleanerLongInterval = parseIntegerEntry(st.sval);
if (resourceCleanerLongInterval < 1_000) {
throw excLine(word + " must be at least 1000 ms");
throw excLine(st.sval + " must be at least 1000 ms");
}
} else if (word.equals("destroyTokenAfterLogout")) {
destroyTokenAfterLogout = parseBooleanEntry(word);
} else if (word.equals("showInfo")) {
showInfo = parseBooleanEntry(word);
} else if (word.equals("keyStoreCompatibilityMode")) {
keyStoreCompatibilityMode = parseBooleanEntry(word);
} else if (word.equals("explicitCancel")) {
explicitCancel = parseBooleanEntry(word);
} else if (word.equals("omitInitialize")) {
omitInitialize = parseBooleanEntry(word);
} else if (word.equals("allowSingleThreadedModules")) {
allowSingleThreadedModules = parseBooleanEntry(word);
} else if (word.equals("functionList")) {
functionList = parseStringEntry(word);
} else if (word.equals("nssUseSecmod")) {
nssUseSecmod = parseBooleanEntry(word);
} else if (word.equals("nssLibraryDirectory")) {
nssLibraryDirectory = parseLibrary(word);
}
case "destroyTokenAfterLogout"->
destroyTokenAfterLogout = parseBooleanEntry(st.sval);
case "showInfo"->
showInfo = parseBooleanEntry(st.sval);
case "keyStoreCompatibilityMode"->
keyStoreCompatibilityMode = parseBooleanEntry(st.sval);
case "explicitCancel"->
explicitCancel = parseBooleanEntry(st.sval);
case "omitInitialize"->
omitInitialize = parseBooleanEntry(st.sval);
case "allowSingleThreadedModules"->
allowSingleThreadedModules = parseBooleanEntry(st.sval);
case "functionList"->
functionList = parseStringEntry(st.sval);
case "nssUseSecmod"->
nssUseSecmod = parseBooleanEntry(st.sval);
case "nssLibraryDirectory"-> {
nssLibraryDirectory = parseLibrary(st.sval);
nssUseSecmod = true;
} else if (word.equals("nssSecmodDirectory")) {
nssSecmodDirectory = expand(parseStringEntry(word));
}
case "nssSecmodDirectory"-> {
nssSecmodDirectory = expand(parseStringEntry(st.sval));
nssUseSecmod = true;
} else if (word.equals("nssModule")) {
nssModule = parseStringEntry(word);
}
case "nssModule"-> {
nssModule = parseStringEntry(st.sval);
nssUseSecmod = true;
} else if (word.equals("nssDbMode")) {
String mode = parseStringEntry(word);
}
case "nssDbMode"-> {
String mode = parseStringEntry(st.sval);
if (mode.equals("readWrite")) {
nssDbMode = Secmod.DbMode.READ_WRITE;
} else if (mode.equals("readOnly")) {
@ -479,22 +491,25 @@ final class Config {
throw excToken("nssDbMode must be one of readWrite, readOnly, and noDb:");
}
nssUseSecmod = true;
} else if (word.equals("nssNetscapeDbWorkaround")) {
nssNetscapeDbWorkaround = parseBooleanEntry(word);
nssUseSecmod = true;
} else if (word.equals("nssArgs")) {
parseNSSArgs(word);
} else if (word.equals("nssUseSecmodTrust")) {
nssUseSecmodTrust = parseBooleanEntry(word);
} else if (word.equals("useEcX963Encoding")) {
useEcX963Encoding = parseBooleanEntry(word);
} else if (word.equals("nssOptimizeSpace")) {
nssOptimizeSpace = parseBooleanEntry(word);
} else {
throw new ConfigurationException
("Unknown keyword '" + word + "', line " + st.lineno());
}
parsedKeywords.add(word);
case "nssNetscapeDbWorkaround"-> {
nssNetscapeDbWorkaround = parseBooleanEntry(st.sval);
nssUseSecmod = true;
}
case "nssArgs"->
parseNSSArgs(st.sval);
case "nssUseSecmodTrust"->
nssUseSecmodTrust = parseBooleanEntry(st.sval);
case "useEcX963Encoding"->
useEcX963Encoding = parseBooleanEntry(st.sval);
case "nssOptimizeSpace"->
nssOptimizeSpace = parseBooleanEntry(st.sval);
default->
throw new ConfigurationException
("Unknown keyword '" + st.sval + "', line " +
st.lineno());
}
parsedKeywords.add(st.sval);
}
reader.close();
reader = null;

View File

@ -401,7 +401,13 @@ final class P11AEADCipher extends CipherSpi {
}
private void cancelOperation() {
// cancel operation by finishing it; avoid killSession as some
token.ensureValid();
if (P11Util.trySessionCancel(token, session,
(encrypt ? CKF_ENCRYPT : CKF_DECRYPT))) {
return;
}
// cancel by finishing operations; avoid killSession as some
// hardware vendors may require re-login
int bufLen = doFinalLength(0);
byte[] buffer = new byte[bufLen];
@ -453,7 +459,7 @@ final class P11AEADCipher extends CipherSpi {
token.ensureValid();
byte[] aad = (aadBuffer.size() > 0? aadBuffer.toByteArray() : null);
byte[] aad = (aadBuffer.size() > 0 ? aadBuffer.toByteArray() : null);
long p11KeyID = p11Key.getKeyID();
try {
@ -507,7 +513,7 @@ final class P11AEADCipher extends CipherSpi {
result -= tagLen;
}
}
return (result > 0? result : 0);
return (result > 0 ? result : 0);
}
// reset the states to the pre-initialized values

View File

@ -445,8 +445,14 @@ final class P11Cipher extends CipherSpi {
private void cancelOperation() {
token.ensureValid();
// cancel operation by finishing it; avoid killSession as some
// hardware vendors may require re-login
if (P11Util.trySessionCancel(token, session,
(encrypt ? CKF_ENCRYPT : CKF_DECRYPT))) {
return;
}
// cancel by finishing operations; avoid killSession as
// some hardware vendors may require re-login
try {
int bufLen = doFinalLength(0);
byte[] buffer = new byte[bufLen];
@ -458,7 +464,7 @@ final class P11Cipher extends CipherSpi {
} catch (PKCS11Exception e) {
if (e.match(CKR_OPERATION_NOT_INITIALIZED)) {
// Cancel Operation may be invoked after an error on a PKCS#11
// call. If the operation inside the token was already cancelled,
// call. If the operation inside the token is already cancelled,
// do not fail here. This is part of a defensive mechanism for
// PKCS#11 libraries that do not strictly follow the standard.
return;
@ -488,7 +494,7 @@ final class P11Cipher extends CipherSpi {
if (session == null) {
session = token.getOpSession();
}
CK_MECHANISM mechParams = (blockMode == MODE_CTR?
CK_MECHANISM mechParams = (blockMode == MODE_CTR ?
new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
new CK_MECHANISM(mechanism, iv));
if (encrypt) {

View File

@ -126,7 +126,7 @@ final class P11KeyWrapCipher extends CipherSpi {
String[] algoParts = algorithm.split("/");
if (algoParts[0].startsWith("AES")) {
int index = algoParts[0].indexOf('_');
fixedKeySize = (index == -1? -1 :
fixedKeySize = (index == -1 ? -1 :
// should be well-formed since we specify what we support
Integer.parseInt(algoParts[0].substring(index+1)) >> 3);
try {
@ -180,7 +180,7 @@ final class P11KeyWrapCipher extends CipherSpi {
protected AlgorithmParameters engineGetParameters() {
// KW and KWP uses but not require parameters, return the default
// IV when no IV is supplied by caller
byte[] iv = (this.iv == null? type.defIv : this.iv);
byte[] iv = (this.iv == null ? type.defIv : this.iv);
AlgorithmParameterSpec spec = new IvParameterSpec(iv);
try {
@ -213,7 +213,7 @@ final class P11KeyWrapCipher extends CipherSpi {
("Only IvParameterSpec is supported");
}
byte[] ivValue = (params == null? null :
byte[] ivValue = (params == null ? null :
((IvParameterSpec)params).getIV());
implInit(opmode, key, ivValue, sr);
@ -285,7 +285,14 @@ final class P11KeyWrapCipher extends CipherSpi {
}
private void cancelOperation() {
// cancel operation by finishing it; avoid killSession as some
token.ensureValid();
if (P11Util.trySessionCancel(token, session,
(opmode == Cipher.ENCRYPT_MODE ? CKF_ENCRYPT : CKF_DECRYPT))) {
return;
}
// cancel by finishing operations; avoid killSession as some
// hardware vendors may require re-login
byte[] in = dataBuffer.toByteArray();
int inLen = in.length;
@ -379,7 +386,7 @@ final class P11KeyWrapCipher extends CipherSpi {
} else {
result -= BLK_SIZE; // minus the leading block including the ICV
}
return (result > 0? result : 0);
return (result > 0 ? result : 0);
}
// reset the states to the pre-initialized values
@ -654,7 +661,7 @@ final class P11KeyWrapCipher extends CipherSpi {
P11Key tbwP11Key = null;
if (!(tbwKey instanceof P11Key)) {
try {
tbwP11Key = (tbwKey instanceof SecretKey?
tbwP11Key = (tbwKey instanceof SecretKey ?
P11SecretKeyFactory.convertKey(token, tbwKey,
tbwKey.getAlgorithm()) :
P11KeyFactory.convertKey(token, tbwKey,

View File

@ -147,7 +147,12 @@ final class P11Mac extends MacSpi {
private void cancelOperation() {
token.ensureValid();
// cancel operation by finishing it; avoid killSession as some
if (P11Util.trySessionCancel(token, session, CKF_SIGN)) {
return;
}
// cancel by finishing operations; avoid killSession as some
// hardware vendors may require re-login
try {
token.p11.C_SignFinal(session.id(), 0);

View File

@ -170,7 +170,7 @@ final class P11PSSSignature extends SignatureSpi {
this.mechanism = new CK_MECHANISM(mechId);
int idx = algorithm.indexOf("with");
// convert to stdName
this.mdAlg = (idx == -1?
this.mdAlg = (idx == -1 ?
null : toStdName(algorithm.substring(0, idx)));
switch ((int)mechId) {
@ -193,7 +193,7 @@ final class P11PSSSignature extends SignatureSpi {
throw new NoSuchAlgorithmException("Unsupported algorithm: " +
algorithm);
}
this.md = (this.mdAlg == null? null :
this.md = (this.mdAlg == null ? null :
MessageDigest.getInstance(this.mdAlg));
type = T_DIGEST;
break;
@ -269,9 +269,16 @@ final class P11PSSSignature extends SignatureSpi {
private void cancelOperation() {
token.ensureValid();
if (DEBUG) System.out.print("Cancelling operation");
// cancel operation by finishing it; avoid killSession as some
if (P11Util.trySessionCancel(token, session,
(mode == M_SIGN ? CKF_SIGN : CKF_VERIFY))) {
if (DEBUG) System.out.println(" by C_SessionCancel");
return;
}
// cancel by finishing operations; avoid killSession call as some
// hardware vendors may require re-login
try {
if (mode == M_SIGN) {
@ -280,7 +287,7 @@ final class P11PSSSignature extends SignatureSpi {
token.p11.C_SignFinal(session.id(), 0);
} else {
byte[] digest =
(md == null? new byte[0] : md.digest());
(md == null ? new byte[0] : md.digest());
if (DEBUG) System.out.println(" by C_Sign");
token.p11.C_Sign(session.id(), digest);
}
@ -292,7 +299,7 @@ final class P11PSSSignature extends SignatureSpi {
token.p11.C_VerifyFinal(session.id(), signature);
} else {
byte[] digest =
(md == null? new byte[0] : md.digest());
(md == null ? new byte[0] : md.digest());
if (DEBUG) System.out.println(" by C_Verify");
token.p11.C_Verify(session.id(), digest, signature);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,6 +37,7 @@ import javax.crypto.spec.*;
import static sun.security.pkcs11.TemplateManager.*;
import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*;
import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
import sun.security.util.KeyUtil;
@ -266,7 +267,21 @@ final class P11RSACipher extends CipherSpi {
// state variables such as "initialized"
private void cancelOperation() {
token.ensureValid();
// cancel operation by finishing it; avoid killSession as some
long flags = switch(mode) {
case MODE_ENCRYPT -> CKF_ENCRYPT;
case MODE_DECRYPT -> CKF_DECRYPT;
case MODE_SIGN -> CKF_SIGN;
case MODE_VERIFY -> CKF_VERIFY;
default -> {
throw new AssertionError("Unexpected value: " + mode);
}
};
if (P11Util.trySessionCancel(token, session, flags)) {
return;
}
// cancel by finishing operations; avoid killSession as some
// hardware vendors may require re-login
try {
PKCS11 p11 = token.p11;

View File

@ -283,7 +283,13 @@ final class P11Signature extends SignatureSpi {
private void cancelOperation() {
token.ensureValid();
// cancel operation by finishing it; avoid killSession as some
if (P11Util.trySessionCancel(token, session,
(mode == M_SIGN ? CKF_SIGN : CKF_VERIFY))) {
return;
}
// cancel by finishing operations; avoid killSession call as some
// hardware vendors may require re-login
try {
if (mode == M_SIGN) {
@ -315,9 +321,9 @@ final class P11Signature extends SignatureSpi {
} catch (PKCS11Exception e) {
if (e.match(CKR_OPERATION_NOT_INITIALIZED)) {
// Cancel Operation may be invoked after an error on a PKCS#11
// call. If the operation inside the token was already cancelled,
// do not fail here. This is part of a defensive mechanism for
// PKCS#11 libraries that do not strictly follow the standard.
// call. If the operation was already cancelled, do not fail
// here. This is part of a defensive mechanism for PKCS#11
// libraries that do not strictly follow the standard.
return;
}
if (mode == M_VERIFY) {

View File

@ -28,6 +28,9 @@ package sun.security.pkcs11;
import java.math.BigInteger;
import java.security.*;
import sun.security.pkcs11.wrapper.PKCS11Exception;
import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*;
/**
* Collection of static utility methods.
*
@ -187,4 +190,22 @@ public final class P11Util {
return sb.toString();
}
// returns true if successfully cancelled
static boolean trySessionCancel(Token token, Session session, long flags)
throws ProviderException {
if (token.p11.getVersion().major == 3) {
try {
token.p11.C_SessionCancel(session.id(), flags);
return true;
} catch (PKCS11Exception e) {
// return false for CKR_OPERATION_CANCEL_FAILED, so callers
// can cancel in the pre v3.0 way, i.e. by finishing off the
// current operation
if (!e.match(CKR_OPERATION_CANCEL_FAILED)) {
throw new ProviderException("cancel failed", e);
}
}
}
return false;
}
}

View File

@ -150,7 +150,7 @@ public final class SunPKCS11 extends AuthProvider {
this.config = c;
if (debug != null) {
System.out.println("SunPKCS11 loading " + config.getFileName());
debug.println("SunPKCS11 loading " + config.getFileName());
}
String library = config.getLibrary();
@ -176,7 +176,6 @@ public final class SunPKCS11 extends AuthProvider {
// switch to using the NSS trust attributes for trusted certs
// (KeyStore).
//
if (useSecmod) {
// note: Config ensures library/slot/slotListIndex not specified
// in secmod mode.
@ -328,8 +327,7 @@ public final class SunPKCS11 extends AuthProvider {
initArgs.flags = CKF_OS_LOCKING_OK;
PKCS11 tmpPKCS11;
try {
tmpPKCS11 = PKCS11.getInstance(
library, functionList, initArgs,
tmpPKCS11 = PKCS11.getInstance(library, functionList, initArgs,
config.getOmitInitialize());
} catch (PKCS11Exception e) {
if (debug != null) {
@ -345,18 +343,18 @@ public final class SunPKCS11 extends AuthProvider {
} else {
initArgs.flags = 0;
}
tmpPKCS11 = PKCS11.getInstance(library,
functionList, initArgs, config.getOmitInitialize());
tmpPKCS11 = PKCS11.getInstance(library, functionList, initArgs,
config.getOmitInitialize());
}
p11 = tmpPKCS11;
CK_INFO p11Info = p11.C_GetInfo();
if (p11Info.cryptokiVersion.major < 2) {
if (p11.getVersion().major < 2) {
throw new ProviderException("Only PKCS#11 v2.0 and later "
+ "supported, library version is v" + p11Info.cryptokiVersion);
+ "supported, library version is v" + p11.getVersion());
}
boolean showInfo = config.getShowInfo();
if (showInfo) {
CK_INFO p11Info = p11.C_GetInfo();
System.out.println("Information for provider " + getName());
System.out.println("Library info:");
System.out.println(p11Info);
@ -1482,12 +1480,10 @@ public final class SunPKCS11 extends AuthProvider {
}
// get the pin if necessary
char[] pin = null;
if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
// get password
CallbackHandler myHandler = getCallbackHandler(handler);
if (myHandler == null) {
throw new LoginException
@ -1503,6 +1499,7 @@ public final class SunPKCS11 extends AuthProvider {
PasswordCallback pcall = new PasswordCallback(form.format(source),
false);
Callback[] callbacks = { pcall };
try {
myHandler.handle(callbacks);
} catch (Exception e) {
@ -1522,13 +1519,12 @@ public final class SunPKCS11 extends AuthProvider {
}
// perform token login
Session session = null;
try {
session = token.getOpSession();
// pin is NULL if using CKF_PROTECTED_AUTHENTICATION_PATH
p11.C_Login(session.id(), CKU_USER, pin);
if (debug != null) {
debug.println("login succeeded");
}

View File

@ -110,7 +110,7 @@ public class PKCS11 {
* e.g. pk2priv.dll.
*/
private final String pkcs11ModulePath;
private final CK_VERSION version;
private long pNativeData;
/**
@ -141,13 +141,30 @@ public class PKCS11 {
* path, if the driver is not in the system's search path.
*
* @param pkcs11ModulePath the PKCS#11 library path
* @param functionList the method name for retrieving the PKCS#11
* function list; may be null if not set in config file
* @preconditions (pkcs11ModulePath <> null)
* @postconditions
*/
PKCS11(String pkcs11ModulePath, String functionListName)
PKCS11(String pkcs11ModulePath, String functionList)
throws IOException {
connect(pkcs11ModulePath, functionListName);
this.version = connect(pkcs11ModulePath, functionList);
this.pkcs11ModulePath = pkcs11ModulePath;
// bug in native PKCS#11 lib; workaround it by calling C_GetInfo()
// and get cryptoki version from there
if (this.version.major != 2 && this.version.major != 3) {
try {
CK_INFO p11Info = C_GetInfo();
this.version.major = p11Info.cryptokiVersion.major;
this.version.minor = p11Info.cryptokiVersion.minor;
} catch (PKCS11Exception e) {
// give up; just use what is returned by connect()
}
}
}
public CK_VERSION getVersion() {
return version;
}
public static synchronized PKCS11 getInstance(String pkcs11ModulePath,
@ -186,11 +203,14 @@ public class PKCS11 {
* native part.
*
* @param pkcs11ModulePath The PKCS#11 library path.
* @param functionList the method name for retrieving the PKCS#11
* function list; may be null if not set in config file
* @return the actual PKCS11 interface version
* @preconditions (pkcs11ModulePath <> null)
* @postconditions
*/
private native void connect(String pkcs11ModulePath, String functionListName)
throws IOException;
private native CK_VERSION connect(String pkcs11ModulePath,
String functionList) throws IOException;
/**
* Disconnects the PKCS#11 library from this object. After calling this
@ -463,6 +483,20 @@ public class PKCS11 {
public native CK_SESSION_INFO C_GetSessionInfo(long hSession)
throws PKCS11Exception;
/**
* C_SessionCancel terminates active session based operations.
* (Session management) (New in PKCS#11 v3.0)
*
* @param hSession the session's handle
* (PKCS#11 param: CK_SESSION_HANDLE hSession)
* @param flags indicates the operations to cancel.
* (PKCS#11 param: CK_FLAGS flags)
* @exception PKCS11Exception If function returns other value than CKR_OK.
* @preconditions
* @postconditions
*/
public native void C_SessionCancel(long hSession, long flags)
throws PKCS11Exception;
/**
* C_GetOperationState obtains the state of the cryptographic operation
@ -521,6 +555,24 @@ public class PKCS11 {
public native void C_Login(long hSession, long userType, char[] pPin)
throws PKCS11Exception;
///**
// * C_LoginUser logs a user into a token. (New in PKCS#11 v3.0)
// * (Session management)
// *
// * @param hSession the session's handle
// * (PKCS#11 param: CK_SESSION_HANDLE hSession)
// * @param userType the user type
// * (PKCS#11 param: CK_USER_TYPE userType)
// * @param pPin the user's PIN and the length of the PIN
// * (PKCS#11 param: CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
// * @param pUsername the user name and the length of the user name
// * (PKCS#11 param: CK_CHAR_PTR pUsername, CK_ULONG ulUsernameLen)
// * @exception PKCS11Exception If function returns other value than CKR_OK.
// * @preconditions
// * @postconditions
// */
//public native void C_LoginUser(long hSession, long userType, char[] pPin,
// String pUsername) throws PKCS11Exception;
/**
* C_Logout logs a user out from a token.
@ -807,7 +859,6 @@ public class PKCS11 {
public native int C_EncryptFinal(long hSession, long directOut, byte[] out,
int outOfs, int outLen) throws PKCS11Exception;
/**
* C_DecryptInit initializes a decryption operation.
* (Encryption and decryption)
@ -902,8 +953,6 @@ public class PKCS11 {
public native int C_DecryptFinal(long hSession, long directOut, byte[] out,
int outOfs, int outLen) throws PKCS11Exception;
/* *****************************************************************************
* Message digesting
******************************************************************************/
@ -1624,9 +1673,9 @@ public class PKCS11 {
// parent. Used for tokens that only support single threaded access
static class SynchronizedPKCS11 extends PKCS11 {
SynchronizedPKCS11(String pkcs11ModulePath, String functionListName)
SynchronizedPKCS11(String pkcs11ModulePath, String functionList)
throws IOException {
super(pkcs11ModulePath, functionListName);
super(pkcs11ModulePath, functionList);
}
synchronized void C_Initialize(Object pInitArgs) throws PKCS11Exception {
@ -1682,11 +1731,22 @@ static class SynchronizedPKCS11 extends PKCS11 {
return super.C_GetSessionInfo(hSession);
}
public synchronized void C_Login(long hSession, long userType, char[] pPin)
public synchronized void C_SessionCancel(long hSession, long flags)
throws PKCS11Exception {
super.C_SessionCancel(hSession, flags);
}
public synchronized void C_Login(long hSession, long userType,
char[] pPin) throws PKCS11Exception {
super.C_Login(hSession, userType, pPin);
}
//public synchronized void C_LoginUser(long hSession, long userType,
// char[] pPin, String pUsername)
// throws PKCS11Exception {
// super.C_LoginUser(hSession, userType, pPin, pUsername);
//}
public synchronized void C_Logout(long hSession) throws PKCS11Exception {
super.C_Logout(hSession);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
@ -272,6 +272,33 @@ JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetSessionI
}
#endif
#ifdef P11_ENABLE_C_SESSIONCANCEL
/*
* Class: sun_security_pkcs11_wrapper_PKCS11
* Method: C_SessionCancel
* Signature: (JJ)V
* Parametermapping: *PKCS11*
* @param jlong jSessionHandle CK_SESSION_HANDLE hSession
* @param jlong jFlags CK_FLAGS flags
*/
JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SessionCancel
(JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jFlags)
{
CK_SESSION_HANDLE ckSessionHandle;
CK_RV rv;
CK_FUNCTION_LIST_3_0_PTR ckpFunctions30 = getFunctionList30(env, obj);
if (ckpFunctions30 == NULL) { return; }
ckSessionHandle = jLongToCKULong(jSessionHandle);
rv = (*ckpFunctions30->C_SessionCancel)(ckSessionHandle,
jLongToCKULong(jFlags));
ckAssertReturnValueOK(env, rv);
}
#endif
#ifdef P11_ENABLE_C_GETOPERATIONSTATE
/*
* Class: sun_security_pkcs11_wrapper_PKCS11
@ -351,7 +378,7 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationSt
free(ckpState);
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
ckAssertReturnValueOK(env, rv);
}
#endif
@ -367,30 +394,85 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SetOperationSt
* CK_ULONG ulPinLen
*/
JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Login
(JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType, jcharArray jPin)
(JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType,
jcharArray jPin)
{
CK_SESSION_HANDLE ckSessionHandle;
CK_USER_TYPE ckUserType;
CK_CHAR_PTR ckpPinArray = NULL_PTR;
CK_ULONG ckPinLength;
CK_RV rv;
CK_FUNCTION_LIST_PTR ckpFunctions;
CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
if (ckpFunctions == NULL) { return; }
ckpFunctions = getFunctionList(env, obj);
if (ckpFunctions == NULL) {
return;
}
ckSessionHandle = jLongToCKULong(jSessionHandle);
ckUserType = jLongToCKULong(jUserType);
jCharArrayToCKCharArray(env, jPin, &ckpPinArray, &ckPinLength);
if ((*env)->ExceptionCheck(env)) { return; }
rv = (*ckpFunctions->C_Login)(ckSessionHandle, ckUserType, ckpPinArray, ckPinLength);
rv = (*ckpFunctions->C_Login)(ckSessionHandle, ckUserType, ckpPinArray,
ckPinLength);
free(ckpPinArray);
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
ckAssertReturnValueOK(env, rv);
}
#endif
#ifdef P11_ENABLE_C_LOGINUSER
/*
* Class: sun_security_pkcs11_wrapper_PKCS11
* Method: C_LoginUser
* Signature: (JJ[C;Ljava/lang/String;)V
* Parametermapping: *PKCS11*
* @param jlong jSessionHandle CK_SESSION_HANDLE hSession
* @param jlong jUserType CK_USER_TYPE userType
* @param jcharArray jPin CK_CHAR_PTR pPin
* CK_ULONG ulPinLen
* @param jstring jUsername CK_CHAR_PTR pUsername
* CK_ULONG ulUsernameLen
*/
JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1LoginUser
(JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jUserType,
jcharArray jPin, jstring jUsername)
{
CK_SESSION_HANDLE ckSessionHandle;
CK_USER_TYPE ckUserType;
CK_CHAR_PTR ckpPinArray = NULL_PTR;
CK_ULONG ckPinLength;
CK_CHAR_PTR ckpUsername = NULL_PTR;
CK_ULONG ckUsernameLength;
CK_RV rv;
CK_FUNCTION_LIST_3_0_PTR ckpFunctions30;
ckpFunctions30 = getFunctionList30(env, obj);
ckSessionHandle = jLongToCKULong(jSessionHandle);
ckUserType = jLongToCKULong(jUserType);
jCharArrayToCKCharArray(env, jPin, &ckpPinArray, &ckPinLength);
if ((*env)->ExceptionCheck(env)) { return; }
jStringToCKUTF8CharArray(env, jUsername, &ckpUsername,
&ckUsernameLength);
if ((*env)->ExceptionCheck(env)) { return; }
if (ckpFunctions30 == NULL) {
return;
}
rv = (*ckpFunctions30->C_LoginUser)(ckSessionHandle, ckUserType,
ckpPinArray, ckPinLength, ckpUsername, ckUsernameLength);
free(ckpPinArray);
free(ckpUsername);
ckAssertReturnValueOK(env, rv);
}
#endif
#ifdef P11_ENABLE_C_LOGOUT
/*
* Class: sun_security_pkcs11_wrapper_PKCS11
@ -411,7 +493,7 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Logout
ckSessionHandle = jLongToCKULong(jSessionHandle);
rv = (*ckpFunctions->C_Logout)(ckSessionHandle);
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
ckAssertReturnValueOK(env, rv);
}
#endif

View File

@ -136,6 +136,20 @@ CK_FUNCTION_LIST_PTR getFunctionList(JNIEnv *env, jobject pkcs11Implementation)
return ckpFunctions;
}
CK_FUNCTION_LIST_3_0_PTR getFunctionList30(JNIEnv *env, jobject
pkcs11Implementation) {
ModuleData *moduleData;
CK_FUNCTION_LIST_3_0_PTR ckpFunctions30;
moduleData = getModuleEntry(env, pkcs11Implementation);
if (moduleData == NULL) {
throwDisconnectedRuntimeException(env);
return NULL;
}
ckpFunctions30 = moduleData->ckFunctionList30Ptr;
return ckpFunctions30;
}
/*
* Returns 1, if the given pkcs11Implementation is in the list.

View File

@ -100,9 +100,11 @@
#define P11_ENABLE_C_CLOSESESSION
#undef P11_ENABLE_C_CLOSEALLSESSIONS
#define P11_ENABLE_C_GETSESSIONINFO
#define P11_ENABLE_C_SESSIONCANCEL
#define P11_ENABLE_C_GETOPERATIONSTATE
#define P11_ENABLE_C_SETOPERATIONSTATE
#define P11_ENABLE_C_LOGIN
//#define P11_ENABLE_C_LOGINUSER
#define P11_ENABLE_C_LOGOUT
#define P11_ENABLE_C_CREATEOBJECT
#define P11_ENABLE_C_COPYOBJECT
@ -209,17 +211,21 @@
//#define TRACE0d(s) { printf(s); fflush(stdout); }
//#define TRACE1d(s, p1) { printf(s, p1); fflush(stdout); }
//#define TRACE2d(s, p1, p2) { printf(s, p1, p2); fflush(stdout); }
//#define TRACE3d(s, p1, p2, p3) { printf(s, p1, p2, p3); fflush(stdout); }
//#define TRACE4d(s, p1, p2, p3, p4) { printf(s, p1, p2, p3, p4); fflush(stdout); }
#ifdef P11_DEBUG
#define TRACE0(s) { printf(s); fflush(stdout); }
#define TRACE1(s, p1) { printf(s, p1); fflush(stdout); }
#define TRACE2(s, p1, p2) { printf(s, p1, p2); fflush(stdout); }
#define TRACE3(s, p1, p2, p3) { printf(s, p1, p2, p3); fflush(stdout); }
#define TRACE4(s, p1, p2, p3, p4) { printf(s, p1, p2, p3, p4); fflush(stdout); }
#else
#define TRACE0(s)
#define TRACE1(s, p1)
#define TRACE2(s, p1, p2)
#define TRACE3(s, p1, p2, p3)
#define TRACE4(s, p1, p2, p3, p4)
#define TRACE_INTEND
#define TRACE_UNINTEND
#endif
@ -412,6 +418,8 @@ CK_RV callJUnlockMutex(CK_VOID_PTR pMutex);
void putModuleEntry(JNIEnv *env, jobject pkcs11Implementation, ModuleData *moduleData);
ModuleData * removeModuleEntry(JNIEnv *env, jobject pkcs11Implementation);
CK_FUNCTION_LIST_PTR getFunctionList(JNIEnv *env, jobject pkcs11Implementation);
CK_FUNCTION_LIST_3_0_PTR getFunctionList30(JNIEnv *env, jobject
pkcs11Implementation);
/* A structure to encapsulate the required data for a Notify callback */
struct NotifyEncapsulation {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
@ -72,26 +72,34 @@
/*
* Class: sun_security_pkcs11_wrapper_PKCS11
* Method: connect
* Signature: (Ljava/lang/String;)V
* Signature: (Ljava/lang/String;)Lsun/security/pkcs11/wrapper/CK_VERSION;
*/
JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
(JNIEnv *env, jobject obj, jstring jPkcs11ModulePath, jstring jGetFunctionList)
{
JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
(JNIEnv *env, jobject obj, jstring jPkcs11ModulePath,
jstring jGetFunctionList) {
void *hModule;
char *error;
CK_C_GetFunctionList C_GetFunctionList=NULL;
int i;
CK_ULONG ulCount = 0;
CK_C_GetInterfaceList C_GetInterfaceList = NULL;
CK_INTERFACE_PTR iList = NULL;
CK_C_GetInterface C_GetInterface = NULL;
CK_INTERFACE_PTR interface = NULL;
CK_C_GetFunctionList C_GetFunctionList = NULL;
CK_RV rv;
ModuleData *moduleData;
ModuleData *moduleData = NULL;
jobject globalPKCS11ImplementationReference;
char *systemErrorMessage;
char *exceptionMessage;
const char *getFunctionListStr;
const char *getFunctionListStr = NULL;
const char *libraryNameStr = (*env)->GetStringUTFChars(env, jPkcs11ModulePath, 0);
const char *libraryNameStr = (*env)->GetStringUTFChars(env,
jPkcs11ModulePath, 0);
if (libraryNameStr == NULL) {
return;
return NULL;
}
TRACE1("DEBUG: connect to PKCS#11 module: %s ... ", libraryNameStr);
TRACE1("Connect: connect to PKCS#11 module: %s ... ", libraryNameStr);
/*
* Load the PKCS #11 DLL
@ -108,39 +116,92 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
exceptionMessage = (char *) malloc(sizeof(char) * (strlen(systemErrorMessage) + strlen(libraryNameStr) + 1));
if (exceptionMessage == NULL) {
throwOutOfMemoryError(env, 0);
(*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr);
return;
goto cleanup;
}
strcpy(exceptionMessage, systemErrorMessage);
strcat(exceptionMessage, libraryNameStr);
throwIOException(env, exceptionMessage);
(*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr);
free(exceptionMessage);
return;
goto cleanup;
}
(*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr);
/*
* Get function pointer to C_GetFunctionList
*/
dlerror(); /* clear any old error message not fetched */
// with the old JAR file jGetFunctionList is null, temporarily check for that
if (jGetFunctionList != NULL) {
getFunctionListStr = (*env)->GetStringUTFChars(env, jGetFunctionList, 0);
if (getFunctionListStr == NULL) {
return;
// clear any old error message not fetched
dlerror();
#ifdef DEBUG
C_GetInterfaceList = (CK_C_GetInterfaceList) dlsym(hModule,
"C_GetInterfaceList");
if (C_GetInterfaceList != NULL) {
TRACE0("Connect: Found C_GetInterfaceList func\n");
rv = (C_GetInterfaceList)(NULL, &ulCount);
if (rv == CKR_OK) {
TRACE1("Connect: interface list size %ld \n", ulCount);
// retrieve available interfaces and report their info
iList = (CK_INTERFACE_PTR)
malloc(ulCount*sizeof(CK_INTERFACE));
rv = C_GetInterfaceList(iList, &ulCount);
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
TRACE0("Connect: error polling interface list\n");
goto cleanup;
}
for (i=0; i < (int)ulCount; i++) {
TRACE4("Connect: name %s, version %d.%d, flags 0x%lX\n",
iList[i].pInterfaceName,
((CK_VERSION *)iList[i].pFunctionList)->major,
((CK_VERSION *)iList[i].pFunctionList)->minor,
iList[i].flags);
}
} else {
TRACE0("Connect: error polling interface list size\n");
}
C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, getFunctionListStr);
(*env)->ReleaseStringUTFChars(env, jGetFunctionList, getFunctionListStr);
} else {
TRACE0("Connect: No C_GetInterfaceList func\n");
}
if (C_GetFunctionList == NULL) {
throwIOException(env, "ERROR: C_GetFunctionList == NULL");
return;
} else if ( (systemErrorMessage = dlerror()) != NULL ){
throwIOException(env, systemErrorMessage);
return;
#endif
if (jGetFunctionList != NULL) {
getFunctionListStr = (*env)->GetStringUTFChars(env,
jGetFunctionList, 0);
if (getFunctionListStr == NULL) {
goto cleanup;
}
C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule,
getFunctionListStr);
if ((systemErrorMessage = dlerror()) != NULL){
throwIOException(env, systemErrorMessage);
goto cleanup;
}
if (C_GetFunctionList == NULL) {
TRACE1("Connect: No %s func\n", getFunctionListStr);
throwIOException(env, "ERROR: C_GetFunctionList == NULL");
goto cleanup;
}
TRACE1("Connect: Found %s func\n", getFunctionListStr);
} else {
// if none specified, then we try 3.0 API first before trying 2.40
C_GetInterface = (CK_C_GetInterface) dlsym(hModule, "C_GetInterface");
if ((C_GetInterface != NULL) && (dlerror() == NULL)) {
TRACE0("Connect: Found C_GetInterface func\n");
rv = (C_GetInterface)(NULL, NULL, &interface, 0L);
if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) {
goto setModuleData;
}
}
C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule,
"C_GetFunctionList");
if ((systemErrorMessage = dlerror()) != NULL){
throwIOException(env, systemErrorMessage);
goto cleanup;
}
if (C_GetFunctionList == NULL) {
TRACE0("Connect: No C_GetFunctionList func\n");
throwIOException(env, "ERROR: C_GetFunctionList == NULL");
goto cleanup;
}
TRACE0("Connect: Found C_GetFunctionList func\n");
}
setModuleData:
/*
* Get function pointers to all PKCS #11 functions
*/
@ -148,19 +209,56 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
if (moduleData == NULL) {
dlclose(hModule);
throwOutOfMemoryError(env, 0);
return;
goto cleanup;
}
moduleData->hModule = hModule;
moduleData->applicationMutexHandler = NULL;
rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr));
if (C_GetFunctionList != NULL) {
rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr));
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
goto cleanup;
}
} else if (interface != NULL) {
moduleData->ckFunctionListPtr = interface->pFunctionList;
if (((CK_VERSION *)moduleData->ckFunctionListPtr)->major == 3) {
moduleData->ckFunctionList30Ptr = interface->pFunctionList;
}
} else {
// should never happen
throwIOException(env, "ERROR: No function list ptr found");
goto cleanup;
}
if (((CK_VERSION *)moduleData->ckFunctionListPtr)->major == 3) {
moduleData->ckFunctionList30Ptr = interface->pFunctionList;
} else {
moduleData->ckFunctionList30Ptr = NULL;
}
TRACE2("Connect: FunctionListPtr version = %d.%d\n",
((CK_VERSION *)moduleData->ckFunctionListPtr)->major,
((CK_VERSION *)moduleData->ckFunctionListPtr)->minor);
globalPKCS11ImplementationReference = (*env)->NewGlobalRef(env, obj);
putModuleEntry(env, globalPKCS11ImplementationReference, moduleData);
TRACE0("FINISHED\n");
if(ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
cleanup:
if (jPkcs11ModulePath != NULL && libraryNameStr != NULL) {
(*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr);
}
if (jGetFunctionList != NULL && getFunctionListStr != NULL) {
(*env)->ReleaseStringUTFChars(env, jGetFunctionList,
getFunctionListStr);
}
TRACE0("Connect: FINISHED\n");
if (moduleData != NULL) {
return ckVersionPtrToJVersion(env,
(CK_VERSION *)moduleData->ckFunctionListPtr);
} else {
return NULL;
}
}
/*
* Class: sun_security_pkcs11_wrapper_PKCS11
* Method: disconnect

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
*/
/*
@ -83,8 +83,9 @@ struct ModuleData {
/* the module (DLL or shared library) handle */
void *hModule;
/* The pointer to the PKCS#11 functions of this module. */
/* The pointers to the PKCS#11 functions of this module. */
CK_FUNCTION_LIST_PTR ckFunctionListPtr;
CK_FUNCTION_LIST_3_0_PTR ckFunctionList30Ptr;
/* Reference to the object to use for mutex handling. NULL, if not used. */
jobject applicationMutexHandler;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
@ -72,16 +72,22 @@
/*
* Class: sun_security_pkcs11_wrapper_PKCS11
* Method: connect
* Signature: (Ljava/lang/String;)V
* Signature: (Ljava/lang/String;)Lsun/security/pkcs11/wrapper/CK_VERSION;
*/
JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
(JNIEnv *env, jobject obj, jstring jPkcs11ModulePath,
jstring jGetFunctionList)
jstring jGetFunctionList)
{
HINSTANCE hModule;
CK_C_GetFunctionList C_GetFunctionList;
int i = 0;
CK_ULONG ulCount = 0;
CK_C_GetInterfaceList C_GetInterfaceList = NULL;
CK_INTERFACE_PTR iList = NULL;
CK_C_GetInterface C_GetInterface = NULL;
CK_INTERFACE_PTR interface = NULL;
CK_C_GetFunctionList C_GetFunctionList = NULL;
CK_RV rv = CK_ASSERT_OK;
ModuleData *moduleData;
ModuleData *moduleData = NULL;
jobject globalPKCS11ImplementationReference;
LPVOID lpMsgBuf = NULL;
char *exceptionMessage = NULL;
@ -91,10 +97,9 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
jPkcs11ModulePath, 0);
TRACE1("DEBUG: connect to PKCS#11 module: %s ... ", libraryNameStr);
/*
* Load the PKCS #11 DLL
*/
/*
* Load the PKCS #11 DLL
*/
hModule = LoadLibrary(libraryNameStr);
if (hModule == NULL) {
FormatMessage(
@ -120,29 +125,93 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
goto cleanup;
}
#ifdef DEBUG
/*
* Get function pointer to C_GetFunctionList
* Get function pointer to C_GetInterfaceList
*/
getFunctionListStr = (*env)->GetStringUTFChars(env, jGetFunctionList, 0);
C_GetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hModule,
getFunctionListStr);
(*env)->ReleaseStringUTFChars(env, jGetFunctionList, getFunctionListStr);
if (C_GetFunctionList == NULL) {
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
0, /* Default language */
(LPTSTR) &lpMsgBuf,
0,
NULL
);
throwIOException(env, (LPTSTR) lpMsgBuf);
goto cleanup;
C_GetInterfaceList = (CK_C_GetInterfaceList) GetProcAddress(hModule,
"C_GetInterfaceList");
if (C_GetInterfaceList != NULL) {
TRACE0("Found C_GetInterfaceList func\n");
rv = (C_GetInterfaceList)(NULL, &ulCount);
if (rv == CKR_OK) {
/* get copy of interfaces */
iList = (CK_INTERFACE_PTR)
malloc(ulCount*sizeof(CK_INTERFACE));
rv = C_GetInterfaceList(iList, &ulCount);
for (i=0; i < (int)ulCount; i++) {
printf("interface %s version %d.%d funcs %p flags 0x%lu\n",
iList[i].pInterfaceName,
((CK_VERSION *)iList[i].pFunctionList)->major,
((CK_VERSION *)iList[i].pFunctionList)->minor,
iList[i].pFunctionList, iList[i].flags);
}
} else {
TRACE0("Connect: error polling interface list size\n");
}
} else {
TRACE0("Connect: No C_GetInterfaceList func\n");
}
#endif
if (jGetFunctionList != NULL) {
getFunctionListStr = (*env)->GetStringUTFChars(env,
jGetFunctionList, 0);
if (getFunctionListStr == NULL) {
goto cleanup;
}
C_GetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hModule,
getFunctionListStr);
if (C_GetFunctionList == NULL) {
TRACE1("Connect: No %s func\n", getFunctionListStr);
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
0, /* Default language */
(LPTSTR) &lpMsgBuf,
0,
NULL
);
throwIOException(env, (LPTSTR) lpMsgBuf);
goto cleanup;
}
TRACE1("Connect: Found %s func\n", getFunctionListStr);
} else {
// if none specified, then we try 3.0 API first before trying 2.40
C_GetInterface = (CK_C_GetInterface) GetProcAddress(hModule,
"C_GetInterface");
if (C_GetInterface != NULL) {
TRACE0("Connect: Found C_GetInterface func\n");
rv = (C_GetInterface)(NULL, NULL, &interface, 0);
if (ckAssertReturnValueOK(env, rv) == CK_ASSERT_OK) {
goto setModuleData;
}
}
C_GetFunctionList = (CK_C_GetFunctionList) GetProcAddress(hModule,
"C_GetFunctionList");
if (C_GetFunctionList == NULL) {
TRACE0("Connect: No C_GetFunctionList func\n");
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
0, /* Default language */
(LPTSTR) &lpMsgBuf,
0,
NULL
);
throwIOException(env, (LPTSTR) lpMsgBuf);
goto cleanup;
}
TRACE0("Connect: Found C_GetFunctionList func\n");
}
setModuleData:
/*
* Get function pointers to all PKCS #11 functions
*/
@ -153,12 +222,31 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
}
moduleData->hModule = hModule;
moduleData->applicationMutexHandler = NULL;
rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr));
if (C_GetFunctionList != NULL) {
rv = (C_GetFunctionList)(&(moduleData->ckFunctionListPtr));
if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
goto cleanup;
}
} else if (interface != NULL) {
moduleData->ckFunctionListPtr = interface->pFunctionList;
} else {
// should never happen
throwIOException(env, "ERROR: No function list ptr found");
goto cleanup;
}
if (((CK_VERSION *)moduleData->ckFunctionListPtr)->major == 3) {
moduleData->ckFunctionList30Ptr = interface->pFunctionList;
} else {
moduleData->ckFunctionList30Ptr = NULL;
}
TRACE2("Connect: FunctionListPtr version = %d.%d\n",
((CK_VERSION *)moduleData->ckFunctionListPtr)->major,
((CK_VERSION *)moduleData->ckFunctionListPtr)->minor);
globalPKCS11ImplementationReference = (*env)->NewGlobalRef(env, obj);
putModuleEntry(env, globalPKCS11ImplementationReference, moduleData);
TRACE0("FINISHED\n");
cleanup:
/* Free up allocated buffers we no longer need */
if (lpMsgBuf != NULL) {
@ -167,11 +255,21 @@ cleanup:
if (libraryNameStr != NULL) {
(*env)->ReleaseStringUTFChars(env, jPkcs11ModulePath, libraryNameStr);
}
if (jGetFunctionList != NULL && getFunctionListStr != NULL) {
(*env)->ReleaseStringUTFChars(env, jGetFunctionList,
getFunctionListStr);
}
if (exceptionMessage != NULL) {
free(exceptionMessage);
}
TRACE0("Connect: FINISHED\n");
if (moduleData != NULL) {
return ckVersionPtrToJVersion(env,
(CK_VERSION *)moduleData->ckFunctionListPtr);
} else {
return NULL;
}
if(ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; }
}
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
*/
/*
@ -93,8 +93,9 @@ struct ModuleData {
HINSTANCE hModule;
/* The pointer to the PKCS#11 functions of this module. */
/* The pointers to the PKCS#11 functions of this module. */
CK_FUNCTION_LIST_PTR ckFunctionListPtr;
CK_FUNCTION_LIST_3_0_PTR ckFunctionList30Ptr;
/* Reference to the object to use for mutex handling. NULL, if not used. */
jobject applicationMutexHandler;