--- old/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java 2018-09-18 15:58:00.843385224 +0200 +++ new/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java 2018-09-18 15:58:00.599383582 +0200 @@ -25,7 +25,6 @@ package sun.security.pkcs11; -import java.util.*; import java.nio.ByteBuffer; import java.security.*; @@ -54,27 +53,12 @@ */ final class P11Mac extends MacSpi { - /* unitialized, all fields except session have arbitrary values */ - private final static int S_UNINIT = 1; - - /* session initialized, no data processed yet */ - private final static int S_RESET = 2; - - /* session initialized, data processed */ - private final static int S_UPDATE = 3; - - /* transitional state after doFinal() before we go to S_UNINIT */ - private final static int S_DOFINAL = 4; - // token instance private final Token token; // algorithm name private final String algorithm; - // mechanism id - private final long mechanism; - // mechanism object private final CK_MECHANISM ckMechanism; @@ -87,8 +71,8 @@ // associated session, if any private Session session; - // state, one of S_* above - private int state; + // initialization status + private boolean initialized; // one byte buffer for the update(byte) method, initialized on demand private byte[] oneByte; @@ -98,7 +82,6 @@ super(); this.token = token; this.algorithm = algorithm; - this.mechanism = mechanism; Long params = null; switch ((int)mechanism) { case (int)CKM_MD5_HMAC: @@ -131,47 +114,63 @@ throw new ProviderException("Unknown mechanism: " + mechanism); } ckMechanism = new CK_MECHANISM(mechanism, params); - state = S_UNINIT; - initialize(); } - private void ensureInitialized() throws PKCS11Exception { - token.ensureValid(); - if (state == S_UNINIT) { - initialize(); + // reset the states to the pre-initialized values + private void reset(boolean doCancel) { + if (!initialized) { + return; + } + initialized = false; + try { + if (session == null) { + return; + } + if (doCancel && token.explicitCancel) { + cancelOperation(); + } + } finally { + p11Key.decNativeKeyRef(); + session = token.releaseSession(session); } } private void cancelOperation() { token.ensureValid(); - if (state == S_UNINIT) { - return; - } - state = S_UNINIT; - if ((session == null) || (token.explicitCancel == false)) { + if (session.hasObjects() == false) { + session = token.killSession(session); return; - } - try { - token.p11.C_SignFinal(session.id(), 0); - } catch (PKCS11Exception e) { - throw new ProviderException("Cancel failed", e); + } else { + try { + token.p11.C_SignFinal(session.id(), 0); + } catch (PKCS11Exception e) { + throw new ProviderException("Cancel failed", e); + } } } - private void initialize() throws PKCS11Exception { - if (state == S_RESET) { + private void ensureInitialized() throws PKCS11Exception { + if (initialized) { return; } - if (session == null) { - session = token.getOpSession(); + if (p11Key == null) { + throw new ProviderException( + "Operation cannot be performed without calling engineInit first"); } - if (p11Key != null) { + token.ensureValid(); + p11Key.incNativeKeyRef(); + try { + if (session == null) { + session = token.getOpSession(); + } token.p11.C_SignInit (session.id(), ckMechanism, p11Key.keyID); - state = S_RESET; - } else { - state = S_UNINIT; + } catch (Throwable t) { + p11Key.decNativeKeyRef(); + session = token.releaseSession(session); + throw t; } + initialized = true; } // see JCE spec @@ -181,18 +180,7 @@ // see JCE spec protected void engineReset() { - // the framework insists on calling reset() after doFinal(), - // but we prefer to take care of reinitialization ourselves - if (state == S_DOFINAL) { - state = S_UNINIT; - return; - } - cancelOperation(); - try { - initialize(); - } catch (PKCS11Exception e) { - throw new ProviderException("reset() failed, ", e); - } + reset(true); } // see JCE spec @@ -202,10 +190,10 @@ throw new InvalidAlgorithmParameterException ("Parameters not supported"); } - cancelOperation(); + reset(true); p11Key = P11SecretKeyFactory.convertKey(token, key, algorithm); try { - initialize(); + ensureInitialized(); } catch (PKCS11Exception e) { throw new InvalidKeyException("init() failed", e); } @@ -215,13 +203,12 @@ protected byte[] engineDoFinal() { try { ensureInitialized(); - byte[] mac = token.p11.C_SignFinal(session.id(), 0); - state = S_DOFINAL; - return mac; + return token.p11.C_SignFinal(session.id(), 0); } catch (PKCS11Exception e) { + reset(true); throw new ProviderException("doFinal() failed", e); } finally { - session = token.releaseSession(session); + reset(false); } } @@ -239,7 +226,6 @@ try { ensureInitialized(); token.p11.C_SignUpdate(session.id(), 0, b, ofs, len); - state = S_UPDATE; } catch (PKCS11Exception e) { throw new ProviderException("update() failed", e); } @@ -261,7 +247,6 @@ int ofs = byteBuffer.position(); token.p11.C_SignUpdate(session.id(), addr + ofs, null, 0, len); byteBuffer.position(ofs + len); - state = S_UPDATE; } catch (PKCS11Exception e) { throw new ProviderException("update() failed", e); }