diff --git a/src/share/classes/sun/security/pkcs11/P11Cipher.java b/src/share/classes/sun/security/pkcs11/P11Cipher.java
--- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
+++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
@@ -412,7 +412,8 @@
token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
}
} catch (PKCS11Exception e) {
- throw new ProviderException("Cancel failed", e);
+ if (e.getErrorCode() != CKR_OPERATION_NOT_INITIALIZED)
+ throw new ProviderException("Cancel failed", e);
} finally {
reset();
}
@@ -747,6 +748,9 @@
throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException {
int requiredOutLen = doFinalLength(0);
+ boolean updating = false;
+ PKCS11Exception err = null;
+
if (outLen < requiredOutLen) {
throw new ShortBufferException();
}
@@ -754,6 +758,7 @@
ensureInitialized();
int k = 0;
if (blockBufferLen != 0) {
+ updating = true;
if (encrypt) {
k = token.p11.C_EncryptUpdate(session.id(),
0, blockBuffer, 0, blockBufferLen,
@@ -768,14 +773,17 @@
blockBuffer, 0, blockBufferLen, 0,
padBuffer, 0, padBuffer.length);
}
+ updating = false;
}
if (encrypt) {
if (paddingObj != null) {
int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
requiredOutLen - bytesBufferedInt);
+ updating = true;
k += token.p11.C_EncryptUpdate(session.id(),
0, padBuffer, 0, actualPadLen,
0, out, (outOfs + k), (outLen - k));
+ updating = false;
}
k += token.p11.C_EncryptFinal(session.id(),
0, out, (outOfs + k), (outLen - k));
@@ -793,10 +801,22 @@
}
return k;
} catch (PKCS11Exception e) {
+ err = e;
handleException(e);
throw new ProviderException("doFinal() failed", e);
} finally {
- reset();
+ if (err != null) {
+ if (err.getErrorCode() != CKR_BUFFER_TOO_SMALL) {
+ if (updating)
+ // Work around NSS not cancelling the
+ // operation on an error in update
+ cancelOperation();
+ else
+ reset();
+ }
+ } else {
+ reset();
+ }
}
}
@@ -805,6 +825,9 @@
BadPaddingException {
int outLen = outBuffer.remaining();
int requiredOutLen = doFinalLength(0);
+ boolean updating = false;
+ PKCS11Exception err = null;
+
if (outLen < requiredOutLen) {
throw new ShortBufferException();
}
@@ -830,6 +853,7 @@
int k = 0;
if (blockBufferLen != 0) {
+ updating = true;
if (encrypt) {
k = token.p11.C_EncryptUpdate(session.id(),
0, blockBuffer, 0, blockBufferLen,
@@ -844,15 +868,18 @@
blockBuffer, 0, blockBufferLen, 0,
padBuffer, 0, padBuffer.length);
}
+ updating = false;
}
if (encrypt) {
if (paddingObj != null) {
int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
requiredOutLen - bytesBuffered);
+ updating = true;
k = token.p11.C_EncryptUpdate(session.id(),
0, padBuffer, 0, actualPadLen,
outAddr, outArray, outOfs, outLen);
+ updating = false;
}
k += token.p11.C_EncryptFinal(session.id(),
outAddr, outArray, (outOfs + k), (outLen - k));
@@ -879,10 +906,22 @@
}
return k;
} catch (PKCS11Exception e) {
+ err = e;
handleException(e);
throw new ProviderException("doFinal() failed", e);
} finally {
- reset();
+ if (err != null) {
+ if (err.getErrorCode() != CKR_BUFFER_TOO_SMALL) {
+ if (updating)
+ // Work around NSS not cancelling the
+ // operation on an error in update
+ cancelOperation();
+ else
+ reset();
+ }
+ } else {
+ reset();
+ }
}
}