Blob Blame History Raw
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();
+	    }
         }
     }