--- old/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java 2018-06-04 19:27:24.961711214 -0300 +++ new/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java 2018-06-04 19:27:24.736709615 -0300 @@ -196,7 +196,7 @@ } private void implInit(int opmode, Key key) throws InvalidKeyException { - cancelOperation(); + reset(true); p11Key = P11KeyFactory.convertKey(token, key, algorithm); boolean encrypt; if (opmode == Cipher.ENCRYPT_MODE) { @@ -235,86 +235,107 @@ maxInputSize = ((padType == PAD_PKCS1 && encrypt) ? (n - PKCS1_MIN_PADDING_LENGTH) : n); try { - initialize(); + ensureInitialized(); } catch (PKCS11Exception e) { throw new InvalidKeyException("init() failed", e); } } - private void cancelOperation() { - token.ensureValid(); - if (initialized == false) { + // reset the states to the pre-initialized values + private void reset(boolean doCancel) { + if (!initialized) { return; } initialized = false; - if ((session == null) || (token.explicitCancel == false)) { - return; + try { + if (session == null) { + return; + } + if (doCancel && token.explicitCancel) { + cancelOperation(); + } + } finally { + p11Key.decNativeKeyRef(); + session = token.releaseSession(session); } + } + + private void cancelOperation() { + token.ensureValid(); if (session.hasObjects() == false) { session = token.killSession(session); return; + } else { + try { + PKCS11 p11 = token.p11; + int inLen = maxInputSize; + int outLen = buffer.length; + switch (mode) { + case MODE_ENCRYPT: + p11.C_Encrypt + (session.id(), buffer, 0, inLen, buffer, 0, outLen); + break; + case MODE_DECRYPT: + p11.C_Decrypt + (session.id(), buffer, 0, inLen, buffer, 0, outLen); + break; + case MODE_SIGN: + byte[] tmpBuffer = new byte[maxInputSize]; + p11.C_Sign + (session.id(), tmpBuffer); + break; + case MODE_VERIFY: + p11.C_VerifyRecover + (session.id(), buffer, 0, inLen, buffer, 0, outLen); + break; + default: + throw new ProviderException("internal error"); + } + } catch (PKCS11Exception e) { + // XXX ensure this always works, ignore error + } } + } + + private void ensureInitialized() throws PKCS11Exception { + if (initialized) { + return; + } + if (p11Key == null) { + throw new ProviderException( + "Operation cannot be performed without calling engineInit first"); + } + token.ensureValid(); + p11Key.incNativeKeyRef(); try { + if (session == null) { + session = token.getOpSession(); + } PKCS11 p11 = token.p11; - int inLen = maxInputSize; - int outLen = buffer.length; + CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism); switch (mode) { case MODE_ENCRYPT: - p11.C_Encrypt - (session.id(), buffer, 0, inLen, buffer, 0, outLen); + p11.C_EncryptInit(session.id(), ckMechanism, p11Key.keyID); break; case MODE_DECRYPT: - p11.C_Decrypt - (session.id(), buffer, 0, inLen, buffer, 0, outLen); + p11.C_DecryptInit(session.id(), ckMechanism, p11Key.keyID); break; case MODE_SIGN: - byte[] tmpBuffer = new byte[maxInputSize]; - p11.C_Sign - (session.id(), tmpBuffer); + p11.C_SignInit(session.id(), ckMechanism, p11Key.keyID); break; case MODE_VERIFY: - p11.C_VerifyRecover - (session.id(), buffer, 0, inLen, buffer, 0, outLen); + p11.C_VerifyRecoverInit(session.id(), ckMechanism, p11Key.keyID); break; default: - throw new ProviderException("internal error"); + throw new AssertionError("internal error"); } - } catch (PKCS11Exception e) { - // XXX ensure this always works, ignore error - } - } - - private void ensureInitialized() throws PKCS11Exception { - token.ensureValid(); - if (initialized == false) { - initialize(); - } - } - - private void initialize() throws PKCS11Exception { - if (session == null) { - session = token.getOpSession(); - } - PKCS11 p11 = token.p11; - CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism); - switch (mode) { - case MODE_ENCRYPT: - p11.C_EncryptInit(session.id(), ckMechanism, p11Key.keyID); - break; - case MODE_DECRYPT: - p11.C_DecryptInit(session.id(), ckMechanism, p11Key.keyID); - break; - case MODE_SIGN: - p11.C_SignInit(session.id(), ckMechanism, p11Key.keyID); - break; - case MODE_VERIFY: - p11.C_VerifyRecoverInit(session.id(), ckMechanism, p11Key.keyID); - break; - default: - throw new AssertionError("internal error"); + } catch (Throwable t) { + p11Key.decNativeKeyRef(); + session = token.releaseSession(session); + throw t; } - bufOfs = 0; initialized = true; + bufOfs = 0; } private void implUpdate(byte[] in, int inOfs, int inLen) { @@ -377,8 +398,7 @@ throw (BadPaddingException)new BadPaddingException ("doFinal() failed").initCause(e); } finally { - initialized = false; - session = token.releaseSession(session); + reset(false); } } @@ -454,11 +474,15 @@ Session s = null; try { s = token.getOpSession(); + p11Key.incNativeKeyRef(); + sKey.incNativeKeyRef(); return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism), p11Key.keyID, sKey.keyID); } catch (PKCS11Exception e) { throw new InvalidKeyException("wrap() failed", e); } finally { + p11Key.decNativeKeyRef(); + sKey.decNativeKeyRef(); token.releaseSession(s); } } @@ -528,11 +552,17 @@ }; attributes = token.getAttributes( O_IMPORT, CKO_SECRET_KEY, keyType, attributes); - long keyID = token.p11.C_UnwrapKey(s.id(), - new CK_MECHANISM(mechanism), p11Key.keyID, + p11Key.incNativeKeyRef(); + long keyID; + try { + keyID = token.p11.C_UnwrapKey(s.id(), + new CK_MECHANISM(mechanism), p11Key.keyID, wrappedKey, attributes); + } finally { + p11Key.decNativeKeyRef(); + } secretKey = P11Key.secretKey(s, keyID, - algorithm, 48 << 3, attributes); + algorithm, 48 << 3, attributes, true); } catch (PKCS11Exception e) { if (isTlsRsaPremasterSecret) { failover = e; @@ -581,7 +611,7 @@ new CK_MECHANISM(CKM_SSL3_PRE_MASTER_KEY_GEN, version), attributes); newKey = P11Key.secretKey(session, - keyID, "TlsRsaPremasterSecret", 48 << 3, attributes); + keyID, "TlsRsaPremasterSecret", 48 << 3, attributes, true); } catch (PKCS11Exception e) { throw new ProviderException( "Could not generate premaster secret", e);