Blob Blame History Raw
diff -up openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java.sav openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java
--- openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java.sav	2012-02-14 16:12:51.000000000 -0500
+++ openjdk/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java	2012-05-02 14:07:20.642722122 -0400
@@ -160,10 +160,16 @@ final class P11Cipher extends CipherSpi
     // original IV, if in MODE_CBC or MODE_CTR
     private byte[] iv;
 
-    // number of bytes buffered internally by the native mechanism and padBuffer
-    // if we do the padding
+    // number of bytes buffered by the blockBuffer
     private int bytesBuffered;
 
+    // number of bytes buffered internally
+    private int bytesBufferedInt;
+
+    // bytes buffered from an incomplete block
+    private byte[] blockBuffer;
+    private int blockBufferLen;
+
     P11Cipher(Token token, String algorithm, long mechanism)
             throws PKCS11Exception, NoSuchAlgorithmException {
         super();
@@ -194,6 +200,9 @@ final class P11Cipher extends CipherSpi
             // should not happen
             throw new ProviderException(nspe);
         }
+
+	if (blockSize > 0)
+	    blockBuffer = new byte[blockSize];
     }
 
     protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
@@ -435,7 +444,9 @@ final class P11Cipher extends CipherSpi
             throw ex;
         }
         bytesBuffered = 0;
+	bytesBufferedInt = 0;
         padBufferLen = 0;
+	blockBufferLen = 0;
         initialized = true;
     }
 
@@ -445,7 +456,7 @@ final class P11Cipher extends CipherSpi
             return 0;
         }
 
-        int result = inLen + bytesBuffered;
+        int result = inLen + bytesBuffered + bytesBufferedInt;
         if (blockSize != 0) {
             // minus the number of bytes in the last incomplete block.
             result -= (result & (blockSize - 1));
@@ -459,7 +470,7 @@ final class P11Cipher extends CipherSpi
             return 0;
         }
 
-        int result = inLen + bytesBuffered;
+        int result = inLen + bytesBuffered + bytesBufferedInt;
         if (blockSize != 0 && encrypt && paddingType != PAD_NONE) {
             // add the number of bytes to make the last block complete.
             result += (blockSize - (result & (blockSize - 1)));
@@ -471,7 +482,9 @@ final class P11Cipher extends CipherSpi
     private void reset() {
         initialized = false;
         bytesBuffered = 0;
+	bytesBufferedInt = 0;
         padBufferLen = 0;
+	blockBufferLen = 0;
         if (session != null) {
             session = token.releaseSession(session);
         }
@@ -547,48 +560,57 @@ final class P11Cipher extends CipherSpi
         try {
             ensureInitialized();
             int k = 0;
-            if (encrypt) {
-                k = token.p11.C_EncryptUpdate(session.id(), 0, in, inOfs, inLen,
-                        0, out, outOfs, outLen);
-            } else {
-                int newPadBufferLen = 0;
-                if (paddingObj != null) {
-                    if (padBufferLen != 0) {
-                        // NSS throws up when called with data not in multiple
-                        // of blocks. Try to work around this by holding the
-                        // extra data in padBuffer.
-                        if (padBufferLen != padBuffer.length) {
-                            int bufCapacity = padBuffer.length - padBufferLen;
-                            if (inLen > bufCapacity) {
-                                bufferInputBytes(in, inOfs, bufCapacity);
-                                inOfs += bufCapacity;
-                                inLen -= bufCapacity;
-                            } else {
-                                bufferInputBytes(in, inOfs, inLen);
-                                return 0;
-                            }
-                        }
-                        k = token.p11.C_DecryptUpdate(session.id(),
-                                0, padBuffer, 0, padBufferLen,
-                                0, out, outOfs, outLen);
-                        padBufferLen = 0;
-                    }
-                    newPadBufferLen = inLen & (blockSize - 1);
-                    if (newPadBufferLen == 0) {
-                        newPadBufferLen = padBuffer.length;
-                    }
-                    inLen -= newPadBufferLen;
-                }
-                if (inLen > 0) {
-                    k += token.p11.C_DecryptUpdate(session.id(), 0, in, inOfs,
+	    int newBlockBufferLen = 0;
+
+	    // NSS throws up when called with data not in multiple
+	    // of blocks. Try to work around this by holding the
+	    // extra data in blockBuffer.
+	    if (blockBufferLen != 0) {
+		if (blockBufferLen != blockBuffer.length) {
+		    int bufCapacity = blockBuffer.length - blockBufferLen;
+		    if (inLen >= bufCapacity) {
+			bufferInputBytes(in, inOfs, bufCapacity);
+			inOfs += bufCapacity;
+			inLen -= bufCapacity;
+		    } else {
+			bufferInputBytes(in, inOfs, inLen);
+			return 0;
+		    }
+		}
+		if (encrypt) {
+		    k = token.p11.C_EncryptUpdate(session.id(), 0, blockBuffer, 0,
+						  blockBufferLen, 0, out, outOfs,
+						  outLen);
+		} else {
+		    k = token.p11.C_DecryptUpdate(session.id(), 0, blockBuffer, 0,
+						  blockBufferLen, 0, out, outOfs,
+						  outLen);
+		}
+		blockBufferLen = 0;
+		bytesBuffered = 0;
+	    }
+
+	    if (inLen == 0)
+		return k;
+
+	    newBlockBufferLen = inLen & (blockSize - 1);
+	    if (!encrypt && paddingObj != null && newBlockBufferLen == 0)
+		// Hold the last block in the buffer if we need to unpad
+		newBlockBufferLen = blockBuffer.length;
+	    inLen -= newBlockBufferLen;
+
+	    if (inLen > 0) {
+		if (encrypt) {
+                    k = token.p11.C_EncryptUpdate(session.id(), 0, in, inOfs,
                             inLen, 0, out, (outOfs + k), (outLen - k));
-                }
-                // update 'padBuffer' if using our own padding impl.
-                if (paddingObj != null) {
-                    bufferInputBytes(in, inOfs + inLen, newPadBufferLen);
-                }
-            }
-            bytesBuffered += (inLen - k);
+		} else {
+                    k = token.p11.C_DecryptUpdate(session.id(), 0, in, inOfs,
+                            inLen, 0, out, (outOfs + k), (outLen - k));
+		}
+	    }
+
+	    bufferInputBytes(in, inOfs + inLen, newBlockBufferLen);
+            bytesBufferedInt += (inLen - k);
             return k;
         } catch (PKCS11Exception e) {
             if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
@@ -643,62 +665,65 @@ final class P11Cipher extends CipherSpi
             }
 
             int k = 0;
-            if (encrypt) {
-                if (inAddr == 0 && inArray == null) {
-                    inArray = new byte[inLen];
-                    inBuffer.get(inArray);
-                } else {
-                    inBuffer.position(origPos + inLen);
-                }
-                k = token.p11.C_EncryptUpdate(session.id(),
-                        inAddr, inArray, inOfs, inLen,
-                        outAddr, outArray, outOfs, outLen);
-            } else {
-                int newPadBufferLen = 0;
-                if (paddingObj != null) {
-                    if (padBufferLen != 0) {
-                        // NSS throws up when called with data not in multiple
-                        // of blocks. Try to work around this by holding the
-                        // extra data in padBuffer.
-                        if (padBufferLen != padBuffer.length) {
-                            int bufCapacity = padBuffer.length - padBufferLen;
-                            if (inLen > bufCapacity) {
-                                bufferInputBytes(inBuffer, bufCapacity);
-                                inOfs += bufCapacity;
-                                inLen -= bufCapacity;
-                            } else {
-                                bufferInputBytes(inBuffer, inLen);
-                                return 0;
-                            }
-                        }
-                        k = token.p11.C_DecryptUpdate(session.id(), 0,
-                                padBuffer, 0, padBufferLen, outAddr, outArray,
-                                outOfs, outLen);
-                        padBufferLen = 0;
-                    }
-                    newPadBufferLen = inLen & (blockSize - 1);
-                    if (newPadBufferLen == 0) {
-                        newPadBufferLen = padBuffer.length;
-                    }
-                    inLen -= newPadBufferLen;
-                }
-                if (inLen > 0) {
-                    if (inAddr == 0 && inArray == null) {
-                        inArray = new byte[inLen];
-                        inBuffer.get(inArray);
-                    } else {
-                        inBuffer.position(inBuffer.position() + inLen);
-                    }
-                    k += token.p11.C_DecryptUpdate(session.id(), inAddr,
-                            inArray, inOfs, inLen, outAddr, outArray,
-                            (outOfs + k), (outLen - k));
-                }
-                // update 'padBuffer' if using our own padding impl.
-                if (paddingObj != null && newPadBufferLen != 0) {
-                    bufferInputBytes(inBuffer, newPadBufferLen);
-                }
-            }
-            bytesBuffered += (inLen - k);
+	    int newBlockBufferLen = 0;
+
+	    // NSS throws up when called with data not in multiple
+	    // of blocks. Try to work around this by holding the
+	    // extra data in blockBuffer.
+	    if (blockBufferLen != 0) {
+		if (blockBufferLen != blockBuffer.length) {
+		    int bufCapacity = blockBuffer.length - blockBufferLen;
+		    if (inLen >= bufCapacity) {
+			bufferInputBytes(inBuffer, bufCapacity);
+			inOfs += bufCapacity;
+			inLen -= bufCapacity;
+		    } else {
+			bufferInputBytes(inBuffer, inLen);
+			return 0;
+		    }
+		}
+		if (encrypt) {
+		    k = token.p11.C_EncryptUpdate(session.id(), 0, blockBuffer, 0,
+						  blockBufferLen, outAddr, outArray, outOfs,
+						  outLen);
+		} else {
+		    k = token.p11.C_DecryptUpdate(session.id(), 0, blockBuffer, 0,
+						  blockBufferLen, outAddr, outArray, outOfs,
+						  outLen);
+		}
+		blockBufferLen = 0;
+		bytesBuffered = 0;
+	    }
+
+	    if (inLen == 0)
+		return k;
+
+	    newBlockBufferLen = inLen & (blockSize - 1);
+	    if (!encrypt && paddingObj != null && newBlockBufferLen == 0)
+		// Hold the last block in the buffer if we need to unpad
+		newBlockBufferLen = blockBuffer.length;
+	    inLen -= newBlockBufferLen;
+
+	    if (inAddr == 0 && inArray == null) {
+		inArray = new byte[inLen];
+		inBuffer.get(inArray);
+	    } else {
+		inBuffer.position(inBuffer.position() + inLen);
+	    }
+
+	    if (inLen > 0) {
+		if (encrypt) {
+                    k = token.p11.C_EncryptUpdate(session.id(), inAddr, inArray, inOfs,
+                            inLen, outAddr, outArray, (outOfs + k), (outLen - k));
+		} else {
+                    k = token.p11.C_DecryptUpdate(session.id(), inAddr, inArray, inOfs,
+                            inLen, outAddr, outArray, (outOfs + k), (outLen - k));
+		}
+	    }
+
+	    bufferInputBytes(inBuffer, newBlockBufferLen);
+            bytesBufferedInt += (inLen - k);
+
             if (!(outBuffer instanceof DirectBuffer) &&
                     !outBuffer.hasArray()) {
                 outBuffer.put(outArray, outOfs, k);
@@ -728,31 +753,42 @@ final class P11Cipher extends CipherSpi
         try {
             ensureInitialized();
             int k = 0;
+	    if (blockBufferLen != 0) {
+		if (encrypt) {
+                    k = token.p11.C_EncryptUpdate(session.id(),
+						  0, blockBuffer, 0, blockBufferLen,
+						  0, out, outOfs, outLen);
+		} else {
+		    if (paddingObj == null)
+			k = token.p11.C_DecryptUpdate(session.id(), 0,
+						      blockBuffer, 0, blockBufferLen, 0,
+						      out, outOfs, outLen);
+		    else
+			k = token.p11.C_DecryptUpdate(session.id(), 0,
+						      blockBuffer, 0, blockBufferLen, 0,
+						      padBuffer, 0, padBuffer.length);
+		}
+	    }
             if (encrypt) {
                 if (paddingObj != null) {
                     int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
-                            requiredOutLen - bytesBuffered);
-                    k = token.p11.C_EncryptUpdate(session.id(),
-                            0, padBuffer, 0, actualPadLen,
-                            0, out, outOfs, outLen);
+                            requiredOutLen - bytesBufferedInt);
+                    k += token.p11.C_EncryptUpdate(session.id(),
+						   0, padBuffer, 0, actualPadLen,
+						   0, out, (outOfs + k), (outLen - k));
                 }
                 k += token.p11.C_EncryptFinal(session.id(),
                         0, out, (outOfs + k), (outLen - k));
             } else {
                 if (paddingObj != null) {
-                    if (padBufferLen != 0) {
-                        k = token.p11.C_DecryptUpdate(session.id(), 0,
-                                padBuffer, 0, padBufferLen, 0, padBuffer, 0,
-                                padBuffer.length);
-                    }
                     k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k,
                             padBuffer.length - k);
                     int actualPadLen = paddingObj.unpad(padBuffer, k);
                     k -= actualPadLen;
                     System.arraycopy(padBuffer, 0, out, outOfs, k);
                 } else {
-                    k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs,
-                            outLen);
+                    k += token.p11.C_DecryptFinal(session.id(), 0, out, (outOfs + k),
+						  (outLen - k));
                 }
             }
             return k;
@@ -793,6 +829,23 @@ final class P11Cipher extends CipherSpi
 
             int k = 0;
 
+	    if (blockBufferLen != 0) {
+		if (encrypt) {
+                    k = token.p11.C_EncryptUpdate(session.id(),
+						  0, blockBuffer, 0, blockBufferLen,
+						  outAddr, outArray, outOfs, outLen);
+		} else {
+		    if (paddingObj == null)
+			k = token.p11.C_DecryptUpdate(session.id(), 0,
+						      blockBuffer, 0, blockBufferLen, outAddr,
+						      outArray, outOfs, outLen);
+		    else
+			k = token.p11.C_DecryptUpdate(session.id(), 0,
+						      blockBuffer, 0, blockBufferLen, 0,
+						      padBuffer, 0, padBuffer.length);
+		}
+	    }
+
             if (encrypt) {
                 if (paddingObj != null) {
                     int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
@@ -805,12 +858,6 @@ final class P11Cipher extends CipherSpi
                         outAddr, outArray, (outOfs + k), (outLen - k));
             } else {
                 if (paddingObj != null) {
-                    if (padBufferLen != 0) {
-                        k = token.p11.C_DecryptUpdate(session.id(),
-                                0, padBuffer, 0, padBufferLen,
-                                0, padBuffer, 0, padBuffer.length);
-                        padBufferLen = 0;
-                    }
                     k += token.p11.C_DecryptFinal(session.id(),
                             0, padBuffer, k, padBuffer.length - k);
                     int actualPadLen = paddingObj.unpad(padBuffer, k);
@@ -819,7 +866,8 @@ final class P11Cipher extends CipherSpi
                     outOfs = 0;
                 } else {
                     k = token.p11.C_DecryptFinal(session.id(),
-                            outAddr, outArray, outOfs, outLen);
+						 outAddr, outArray,
+						 (outOfs + k), (outLen - k));
                 }
             }
             if ((!encrypt && paddingObj != null) ||
@@ -875,14 +923,14 @@ final class P11Cipher extends CipherSpi
     }
 
     private final void bufferInputBytes(byte[] in, int inOfs, int len) {
-        System.arraycopy(in, inOfs, padBuffer, padBufferLen, len);
-        padBufferLen += len;
+        System.arraycopy(in, inOfs, blockBuffer, blockBufferLen, len);
+        blockBufferLen += len;
         bytesBuffered += len;
     }
 
     private final void bufferInputBytes(ByteBuffer inBuffer, int len) {
-        inBuffer.get(padBuffer, padBufferLen, len);
-        padBufferLen += len;
+        inBuffer.get(blockBuffer, blockBufferLen, len);
+        blockBufferLen += len;
         bytesBuffered += len;
     }
 }