Mercurial > hg > openjdk > bsd-port > jdk
changeset 8763:227722ebc440
8049312: AES/CICO test failed with on several modes
Summary: Fixed error in calculating data sizes when using feedback modes
Reviewed-by: xuelei
author | akosarev |
---|---|
date | Fri, 10 Nov 2017 17:31:46 +0000 |
parents | 8bc402c20e02 |
children | 219100e82eb2 |
files | src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java src/share/classes/com/sun/crypto/provider/CipherCore.java src/share/classes/com/sun/crypto/provider/CipherFeedback.java src/share/classes/com/sun/crypto/provider/CounterMode.java src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java src/share/classes/com/sun/crypto/provider/OutputFeedback.java src/share/classes/com/sun/crypto/provider/PCBC.java |
diffstat | 7 files changed, 240 insertions(+), 282 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java Fri Jun 17 12:59:14 2016 +0000 +++ b/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java Fri Nov 10 17:31:46 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import java.security.ProviderException; + /** * This class represents ciphers in cipher block chaining (CBC) mode. @@ -122,31 +124,31 @@ * * <p>The input plain text <code>plain</code>, starting at * <code>plainOffset</code> and ending at - * <code>(plainOffset + len - 1)</code>, is encrypted. + * <code>(plainOffset + plainLen - 1)</code>, is encrypted. * The result is stored in <code>cipher</code>, starting at * <code>cipherOffset</code>. * - * <p>It is the application's responsibility to make sure that - * <code>plainLen</code> is a multiple of the embedded cipher's block size, - * as any excess bytes are ignored. - * * @param plain the buffer with the input data to be encrypted * @param plainOffset the offset in <code>plain</code> * @param plainLen the length of the input data * @param cipher the buffer for the result * @param cipherOffset the offset in <code>cipher</code> + * @exception ProviderException if <code>len</code> is not + * a multiple of the block size * @return the length of the encrypted data */ int encrypt(byte[] plain, int plainOffset, int plainLen, byte[] cipher, int cipherOffset) { - int i; + if ((plainLen % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } int endIndex = plainOffset + plainLen; for (; plainOffset < endIndex; plainOffset+=blockSize, cipherOffset += blockSize) { - for (i=0; i<blockSize; i++) { - k[i] = (byte)(plain[i+plainOffset] ^ r[i]); + for (int i = 0; i < blockSize; i++) { + k[i] = (byte)(plain[i + plainOffset] ^ r[i]); } embeddedCipher.encryptBlock(k, 0, cipher, cipherOffset); System.arraycopy(cipher, cipherOffset, r, 0, blockSize); @@ -159,14 +161,10 @@ * * <p>The input cipher text <code>cipher</code>, starting at * <code>cipherOffset</code> and ending at - * <code>(cipherOffset + len - 1)</code>, is decrypted. + * <code>(cipherOffset + cipherLen - 1)</code>, is decrypted. * The result is stored in <code>plain</code>, starting at * <code>plainOffset</code>. * - * <p>It is the application's responsibility to make sure that - * <code>cipherLen</code> is a multiple of the embedded cipher's block - * size, as any excess bytes are ignored. - * * <p>It is also the application's responsibility to make sure that * <code>init</code> has been called before this method is called. * (This check is omitted here, to avoid double checking.) @@ -176,23 +174,23 @@ * @param cipherLen the length of the input data * @param plain the buffer for the result * @param plainOffset the offset in <code>plain</code> + * @exception ProviderException if <code>len</code> is not + * a multiple of the block size * @return the length of the decrypted data - * - * @exception IllegalBlockSizeException if input data whose length does - * not correspond to the embedded cipher's block size is passed to the - * embedded cipher */ int decrypt(byte[] cipher, int cipherOffset, int cipherLen, byte[] plain, int plainOffset) { - int i; + if ((cipherLen % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } int endIndex = cipherOffset + cipherLen; for (; cipherOffset < endIndex; cipherOffset += blockSize, plainOffset += blockSize) { embeddedCipher.decryptBlock(cipher, cipherOffset, k, 0); - for (i = 0; i < blockSize; i++) { - plain[i+plainOffset] = (byte)(k[i] ^ r[i]); + for (int i = 0; i < blockSize; i++) { + plain[i + plainOffset] = (byte)(k[i] ^ r[i]); } System.arraycopy(cipher, cipherOffset, r, 0, blockSize); }
--- a/src/share/classes/com/sun/crypto/provider/CipherCore.java Fri Jun 17 12:59:14 2016 +0000 +++ b/src/share/classes/com/sun/crypto/provider/CipherCore.java Fri Nov 10 17:31:46 2017 +0000 @@ -584,7 +584,7 @@ len -= blockSize; } // do not count the trailing bytes which do not make up a unit - len = (len > 0 ? (len - (len%unitBytes)) : 0); + len = (len > 0 ? (len - (len % unitBytes)) : 0); // check output buffer capacity if ((output == null) || @@ -623,6 +623,9 @@ int bufferCapacity = buffer.length - buffered; if (bufferCapacity != 0) { temp = Math.min(bufferCapacity, inputConsumed); + if (unitBytes != blockSize) { + temp -= ((buffered + temp) % unitBytes); + } System.arraycopy(input, inputOffset, buffer, buffered, temp); inputOffset += temp; inputConsumed -= temp;
--- a/src/share/classes/com/sun/crypto/provider/CipherFeedback.java Fri Jun 17 12:59:14 2016 +0000 +++ b/src/share/classes/com/sun/crypto/provider/CipherFeedback.java Fri Nov 10 17:31:46 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import java.security.ProviderException; /** * This class represents ciphers in cipher-feedback (CFB) mode. @@ -133,66 +134,72 @@ * * <p>The input plain text <code>plain</code>, starting at * <code>plainOffset</code> and ending at - * <code>(plainOffset + len - 1)</code>, is encrypted. + * <code>(plainOffset + plainLen - 1)</code>, is encrypted. * The result is stored in <code>cipher</code>, starting at * <code>cipherOffset</code>. * - * <p>It is the application's responsibility to make sure that - * <code>plainLen</code> is a multiple of the stream unit size - * <code>numBytes</code>, as any excess bytes are ignored. - * - * <p>It is also the application's responsibility to make sure that - * <code>init</code> has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * * @param plain the buffer with the input data to be encrypted * @param plainOffset the offset in <code>plain</code> * @param plainLen the length of the input data * @param cipher the buffer for the result * @param cipherOffset the offset in <code>cipher</code> + * @exception ProviderException if <code>plainLen</code> is not + * a multiple of the <code>numBytes</code> * @return the length of the encrypted data */ int encrypt(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) - { - int i, len; - len = blockSize - numBytes; + byte[] cipher, int cipherOffset) { + if ((plainLen % numBytes) != 0) { + throw new ProviderException("Internal error in input buffering"); + } + + int nShift = blockSize - numBytes; int loopCount = plainLen / numBytes; - int oddBytes = plainLen % numBytes; - if (len == 0) { - for (; loopCount > 0 ; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i = 0; i < blockSize; i++) - register[i] = cipher[i+cipherOffset] = - (byte)(k[i] ^ plain[i+plainOffset]); + for (; loopCount > 0 ; + plainOffset += numBytes, cipherOffset += numBytes, + loopCount--) { + embeddedCipher.encryptBlock(register, 0, k, 0); + if (nShift != 0) { + System.arraycopy(register, numBytes, register, 0, nShift); + } + for (int i = 0; i < numBytes; i++) { + register[nShift + i] = cipher[i + cipherOffset] = + (byte)(k[i] ^ plain[i + plainOffset]); } - if (oddBytes > 0) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; i<oddBytes; i++) - register[i] = cipher[i+cipherOffset] = - (byte)(k[i] ^ plain[i+plainOffset]); - } - } else { - for (; loopCount > 0 ; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - System.arraycopy(register, numBytes, register, 0, len); - for (i=0; i<numBytes; i++) - register[i+len] = cipher[i+cipherOffset] = - (byte)(k[i] ^ plain[i+plainOffset]); + } + return plainLen; + } - } - if (oddBytes != 0) { - embeddedCipher.encryptBlock(register, 0, k, 0); - System.arraycopy(register, numBytes, register, 0, len); - for (i=0; i<oddBytes; i++) { - register[i+len] = cipher[i+cipherOffset] = - (byte)(k[i] ^ plain[i+plainOffset]); - } + /** + * Performs the last encryption operation. + * + * <p>The input plain text <code>plain</code>, starting at + * <code>plainOffset</code> and ending at + * <code>(plainOffset + plainLen - 1)</code>, is encrypted. + * The result is stored in <code>cipher</code>, starting at + * <code>cipherOffset</code>. + * + * @param plain the buffer with the input data to be encrypted + * @param plainOffset the offset in <code>plain</code> + * @param plainLen the length of the input data + * @param cipher the buffer for the result + * @param cipherOffset the offset in <code>cipher</code> + * @return the number of bytes placed into <code>cipher</code> + */ + int encryptFinal(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) { + + int oddBytes = plainLen % numBytes; + int len = encrypt(plain, plainOffset, (plainLen - oddBytes), + cipher, cipherOffset); + plainOffset += len; + cipherOffset += len; + if (oddBytes != 0) { + embeddedCipher.encryptBlock(register, 0, k, 0); + for (int i = 0; i < oddBytes; i++) { + cipher[i + cipherOffset] = + (byte)(k[i] ^ plain[i + plainOffset]); } } return plainLen; @@ -203,17 +210,52 @@ * * <p>The input cipher text <code>cipher</code>, starting at * <code>cipherOffset</code> and ending at - * <code>(cipherOffset + len - 1)</code>, is decrypted. + * <code>(cipherOffset + cipherLen - 1)</code>, is decrypted. * The result is stored in <code>plain</code>, starting at * <code>plainOffset</code>. * - * <p>It is the application's responsibility to make sure that - * <code>cipherLen</code> is a multiple of the stream unit size - * <code>numBytes</code>, as any excess bytes are ignored. + * @param cipher the buffer with the input data to be decrypted + * @param cipherOffset the offset in <code>cipherOffset</code> + * @param cipherLen the length of the input data + * @param plain the buffer for the result + * @param plainOffset the offset in <code>plain</code> + * @exception ProviderException if <code>cipherLen</code> is not + * a multiple of the <code>numBytes</code> + * @return the length of the decrypted data + */ + int decrypt(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) { + if ((cipherLen % numBytes) != 0) { + throw new ProviderException("Internal error in input buffering"); + } + + int nShift = blockSize - numBytes; + int loopCount = cipherLen / numBytes; + + for (; loopCount > 0; + plainOffset += numBytes, cipherOffset += numBytes, + loopCount--) { + embeddedCipher.encryptBlock(register, 0, k, 0); + if (nShift != 0) { + System.arraycopy(register, numBytes, register, 0, nShift); + } + for (int i = 0; i < numBytes; i++) { + register[i + nShift] = cipher[i + cipherOffset]; + plain[i + plainOffset] + = (byte)(cipher[i + cipherOffset] ^ k[i]); + } + } + return cipherLen; + } + + /** + * Performs the last decryption operation. * - * <p>It is also the application's responsibility to make sure that - * <code>init</code> has been called before this method is called. - * (This check is omitted here, to avoid double checking.) + * <p>The input cipher text <code>cipher</code>, starting at + * <code>cipherOffset</code> and ending at + * <code>(cipherOffset + cipherLen - 1)</code>, is decrypted. + * The result is stored in <code>plain</code>, starting at + * <code>plainOffset</code>. * * @param cipher the buffer with the input data to be decrypted * @param cipherOffset the offset in <code>cipherOffset</code> @@ -222,53 +264,19 @@ * @param plainOffset the offset in <code>plain</code> * @return the length of the decrypted data */ - int decrypt(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset) - { - int i, len; - len = blockSize - numBytes; - int loopCount = cipherLen / numBytes; - int oddBytes = cipherLen % numBytes; + int decryptFinal(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) { - if (len == 0) { - for (; loopCount > 0; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i = 0; i < blockSize; i++) { - register[i] = cipher[i+cipherOffset]; - plain[i+plainOffset] - = (byte)(cipher[i+cipherOffset] ^ k[i]); - } - } - if (oddBytes > 0) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; i<oddBytes; i++) { - register[i] = cipher[i+cipherOffset]; - plain[i+plainOffset] - = (byte)(cipher[i+cipherOffset] ^ k[i]); - } - } - } else { - for (; loopCount > 0; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - System.arraycopy(register, numBytes, register, 0, len); - for (i=0; i<numBytes; i++) { - register[i+len] = cipher[i+cipherOffset]; - plain[i+plainOffset] - = (byte)(cipher[i+cipherOffset] ^ k[i]); - } - } - if (oddBytes != 0) { - embeddedCipher.encryptBlock(register, 0, k, 0); - System.arraycopy(register, numBytes, register, 0, len); - for (i=0; i<oddBytes; i++) { - register[i+len] = cipher[i+cipherOffset]; - plain[i+plainOffset] - = (byte)(cipher[i+cipherOffset] ^ k[i]); - } + int oddBytes = cipherLen % numBytes; + int len = decrypt(cipher, cipherOffset, (cipherLen - oddBytes), + plain, plainOffset); + cipherOffset += len; + plainOffset += len; + if (oddBytes != 0) { + embeddedCipher.encryptBlock(register, 0, k, 0); + for (int i = 0; i < oddBytes; i++) { + plain[i + plainOffset] + = (byte)(cipher[i + cipherOffset] ^ k[i]); } } return cipherLen;
--- a/src/share/classes/com/sun/crypto/provider/CounterMode.java Fri Jun 17 12:59:14 2016 +0000 +++ b/src/share/classes/com/sun/crypto/provider/CounterMode.java Fri Nov 10 17:31:46 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 201313, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.security.InvalidKeyException; + /** * This class represents ciphers in counter (CTR) mode. * @@ -136,14 +137,6 @@ * The result is stored in <code>cipher</code>, starting at * <code>cipherOffset</code>. * - * <p>It is the application's responsibility to make sure that - * <code>plainLen</code> is a multiple of the embedded cipher's block size, - * as any excess bytes are ignored. - * - * <p>It is also the application's responsibility to make sure that - * <code>init</code> has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * * @param in the buffer with the input data to be encrypted * @param inOffset the offset in <code>plain</code> * @param len the length of the input data @@ -155,30 +148,7 @@ return crypt(in, inOff, len, out, outOff); } - /** - * Performs decryption operation. - * - * <p>The input cipher text <code>cipher</code>, starting at - * <code>cipherOffset</code> and ending at - * <code>(cipherOffset + len - 1)</code>, is decrypted. - * The result is stored in <code>plain</code>, starting at - * <code>plainOffset</code>. - * - * <p>It is the application's responsibility to make sure that - * <code>cipherLen</code> is a multiple of the embedded cipher's block - * size, as any excess bytes are ignored. - * - * <p>It is also the application's responsibility to make sure that - * <code>init</code> has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * - * @param in the buffer with the input data to be decrypted - * @param inOff the offset in <code>cipherOffset</code> - * @param len the length of the input data - * @param out the buffer for the result - * @param outOff the offset in <code>plain</code> - * @return the length of the decrypted data - */ + // CTR encrypt and decrypt are identical int decrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { return crypt(in, inOff, len, out, outOff); }
--- a/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java Fri Jun 17 12:59:14 2016 +0000 +++ b/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java Fri Nov 10 17:31:46 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import java.security.ProviderException; /** * This class represents ciphers in electronic codebook (ECB) mode. @@ -96,28 +97,24 @@ /** * Performs encryption operation. * - * <p>The input plain text <code>plain</code>, starting at - * <code>plainOffset</code> and ending at - * <code>(plainOffset + len - 1)</code>, is encrypted. - * The result is stored in <code>cipher</code>, starting at - * <code>cipherOffset</code>. - * - * <p>It is the application's responsibility to make sure that - * <code>plainLen</code> is a multiple of the embedded cipher's block size, - * as any excess bytes are ignored. - * - * <p>It is also the application's responsibility to make sure that - * <code>init</code> has been called before this method is called. - * (This check is omitted here, to avoid double checking.) + * <p>The input plain text <code>in</code>, starting at + * <code>inOff</code> and ending at * <code>(inOff + len - 1)</code>, + * is encrypted. The result is stored in <code>out</code>, starting at + * <code>outOff</code>. * * @param in the buffer with the input data to be encrypted - * @param inOffset the offset in <code>plain</code> + * @param inOff the offset in <code>plain</code> * @param len the length of the input data * @param out the buffer for the result * @param outOff the offset in <code>cipher</code> + * @exception ProviderException if <code>len</code> is not + * a multiple of the block size * @return the length of the encrypted data */ int encrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { + if ((len % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } for (int i = len; i >= blockSize; i -= blockSize) { embeddedCipher.encryptBlock(in, inOff, out, outOff); inOff += blockSize; @@ -129,28 +126,24 @@ /** * Performs decryption operation. * - * <p>The input cipher text <code>cipher</code>, starting at - * <code>cipherOffset</code> and ending at - * <code>(cipherOffset + len - 1)</code>, is decrypted. - * The result is stored in <code>plain</code>, starting at - * <code>plainOffset</code>. - * - * <p>It is the application's responsibility to make sure that - * <code>cipherLen</code> is a multiple of the embedded cipher's block - * size, as any excess bytes are ignored. - * - * <p>It is also the application's responsibility to make sure that - * <code>init</code> has been called before this method is called. - * (This check is omitted here, to avoid double checking.) + * <p>The input cipher text <code>in</code>, starting at + * <code>inOff</code> and ending at * <code>(inOff + len - 1)</code>, + * is decrypted.The result is stored in <code>out</code>, starting at + * <code>outOff</code>. * * @param in the buffer with the input data to be decrypted * @param inOff the offset in <code>cipherOffset</code> * @param len the length of the input data * @param out the buffer for the result * @param outOff the offset in <code>plain</code> + * @exception ProviderException if <code>len</code> is not + * a multiple of the block size * @return the length of the decrypted data */ int decrypt(byte[] in, int inOff, int len, byte[] out, int outOff) { + if ((len % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } for (int i = len; i >= blockSize; i -= blockSize) { embeddedCipher.decryptBlock(in, inOff, out, outOff); inOff += blockSize;
--- a/src/share/classes/com/sun/crypto/provider/OutputFeedback.java Fri Jun 17 12:59:14 2016 +0000 +++ b/src/share/classes/com/sun/crypto/provider/OutputFeedback.java Fri Nov 10 17:31:46 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import java.security.ProviderException; /** * This class represents ciphers in output-feedback (OFB) mode. @@ -132,17 +133,52 @@ * * <p>The input plain text <code>plain</code>, starting at * <code>plainOffset</code> and ending at - * <code>(plainOffset + len - 1)</code>, is encrypted. + * <code>(plainOffset + plainLen - 1)</code>, is encrypted. * The result is stored in <code>cipher</code>, starting at * <code>cipherOffset</code>. * - * <p>It is the application's responsibility to make sure that - * <code>plainLen</code> is a multiple of the stream unit size - * <code>numBytes</code>, as any excess bytes are ignored. + * @param plain the buffer with the input data to be encrypted + * @param plainOffset the offset in <code>plain</code> + * @param plainLen the length of the input data + * @param cipher the buffer for the result + * @param cipherOffset the offset in <code>cipher</code> + * @exception ProviderException if <code>plainLen</code> is not + * a multiple of the <code>numBytes</code> + * @return the length of the encrypted data + */ + int encrypt(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) { + + if ((plainLen % numBytes) != 0) { + throw new ProviderException("Internal error in input buffering"); + } + int nShift = blockSize - numBytes; + int loopCount = plainLen / numBytes; + + for (; loopCount > 0; + plainOffset += numBytes, cipherOffset += numBytes, + loopCount--) { + embeddedCipher.encryptBlock(register, 0, k, 0); + for (int i = 0; i < numBytes; i++) { + cipher[i + cipherOffset] = + (byte)(k[i] ^ plain[i + plainOffset]); + if (nShift != 0) { + System.arraycopy(register, numBytes, register, 0, nShift); + } + System.arraycopy(k, 0, register, nShift, numBytes); + } + } + return plainLen; + } + + /** + * Performs last encryption operation. * - * <p>It is also the application's responsibility to make sure that - * <code>init</code> has been called before this method is called. - * (This check is omitted here, to avoid double checking.) + * <p>The input plain text <code>plain</code>, starting at + * <code>plainOffset</code> and ending at + * <code>(plainOffset + plainLen - 1)</code>, is encrypted. + * The result is stored in <code>cipher</code>, starting at + * <code>cipherOffset</code>. * * @param plain the buffer with the input data to be encrypted * @param plainOffset the offset in <code>plain</code> @@ -151,82 +187,34 @@ * @param cipherOffset the offset in <code>cipher</code> * @return the length of the encrypted data */ - int encrypt(byte[] plain, int plainOffset, int plainLen, - byte[] cipher, int cipherOffset) - { - int i; - int len = blockSize - numBytes; - int loopCount = plainLen / numBytes; + int encryptFinal(byte[] plain, int plainOffset, int plainLen, + byte[] cipher, int cipherOffset) { int oddBytes = plainLen % numBytes; + int len = encrypt(plain, plainOffset, (plainLen - oddBytes), + cipher, cipherOffset); + plainOffset += len; + cipherOffset += len; - if (len == 0) { - for (; loopCount > 0; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; i<numBytes; i++) - cipher[i+cipherOffset] = - (byte)(k[i] ^ plain[i+plainOffset]); - System.arraycopy(k, 0, register, 0, numBytes); - } - if (oddBytes > 0) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; i<oddBytes; i++) - cipher[i+cipherOffset] = - (byte)(k[i] ^ plain[i+plainOffset]); - System.arraycopy(k, 0, register, 0, numBytes); - } - } else { - for (; loopCount > 0; - plainOffset += numBytes, cipherOffset += numBytes, - loopCount--) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; i<numBytes; i++) - cipher[i+cipherOffset] = - (byte)(k[i] ^ plain[i+plainOffset]); - System.arraycopy(register, numBytes, register, 0, len); - System.arraycopy(k, 0, register, len, numBytes); - } - if (oddBytes > 0) { - embeddedCipher.encryptBlock(register, 0, k, 0); - for (i=0; i<oddBytes; i++) - cipher[i+cipherOffset] = - (byte)(k[i] ^ plain[i+plainOffset]); - System.arraycopy(register, numBytes, register, 0, len); - System.arraycopy(k, 0, register, len, numBytes); + if (oddBytes != 0) { + embeddedCipher.encryptBlock(register, 0, k, 0); + for (int i = 0; i < oddBytes; i++) { + cipher[i + cipherOffset] = + (byte)(k[i] ^ plain[ i + plainOffset]); } } return plainLen; } - /** - * Performs decryption operation. - * - * <p>The input cipher text <code>cipher</code>, starting at - * <code>cipherOffset</code> and ending at - * <code>(cipherOffset + len - 1)</code>, is decrypted. - * The result is stored in <code>plain</code>, starting at - * <code>plainOffset</code>. - * - * <p>It is the application's responsibility to make sure that - * <code>cipherLen</code> is a multiple of the stream unit size - * <code>numBytes</code>, as any excess bytes are ignored. - * - * <p>It is also the application's responsibility to make sure that - * <code>init</code> has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * - * @param cipher the buffer with the input data to be decrypted - * @param cipherOffset the offset in <code>cipherOffset</code> - * @param cipherLen the length of the input data - * @param plain the buffer for the result - * @param plainOffset the offset in <code>plain</code> - * @return the length of the decrypted data - */ + // OFB encrypt and decrypt are identical int decrypt(byte[] cipher, int cipherOffset, int cipherLen, - byte[] plain, int plainOffset) - { - // OFB encrypt and decrypt are identical + byte[] plain, int plainOffset) { return encrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); } + + // OFB encrypt and decrypt are identical + int decryptFinal(byte[] cipher, int cipherOffset, int cipherLen, + byte[] plain, int plainOffset) { + // OFB encrypt and decrypt are identical + return encryptFinal(cipher, cipherOffset, cipherLen, plain, plainOffset); + } }
--- a/src/share/classes/com/sun/crypto/provider/PCBC.java Fri Jun 17 12:59:14 2016 +0000 +++ b/src/share/classes/com/sun/crypto/provider/PCBC.java Fri Nov 10 17:31:46 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ package com.sun.crypto.provider; import java.security.InvalidKeyException; +import java.security.ProviderException; + /** * This class represents ciphers in Plaintext Cipher Block Chaining (PCBC) @@ -118,38 +120,36 @@ * * <p>The input plain text <code>plain</code>, starting at * <code>plainOffset</code> and ending at - * <code>(plainOffset + len - 1)</code>, is encrypted. + * <code>(plainOffset + plainLen - 1)</code>, is encrypted. * The result is stored in <code>cipher</code>, starting at * <code>cipherOffset</code>. * - * <p>It is the application's responsibility to make sure that - * <code>plainLen</code> is a multiple of the embedded cipher's block size, - * as any excess bytes are ignored. - * - * <p>It is also the application's responsibility to make sure that - * <code>init</code> has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * * @param plain the buffer with the input data to be encrypted * @param plainOffset the offset in <code>plain</code> * @param plainLen the length of the input data * @param cipher the buffer for the result * @param cipherOffset the offset in <code>cipher</code> + * @exception ProviderException if <code>plainLen</code> is not + * a multiple of the block size + * @return the length of the encrypted data */ int encrypt(byte[] plain, int plainOffset, int plainLen, byte[] cipher, int cipherOffset) { + if ((plainLen % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } int i; int endIndex = plainOffset + plainLen; for (; plainOffset < endIndex; plainOffset += blockSize, cipherOffset += blockSize) { - for (i=0; i<blockSize; i++) { - k[i] ^= plain[i+plainOffset]; + for (i = 0; i < blockSize; i++) { + k[i] ^= plain[i + plainOffset]; } embeddedCipher.encryptBlock(k, 0, cipher, cipherOffset); for (i = 0; i < blockSize; i++) { - k[i] = (byte)(plain[i+plainOffset] ^ cipher[i+cipherOffset]); + k[i] = (byte)(plain[i + plainOffset] ^ cipher[i + cipherOffset]); } } return plainLen; @@ -160,27 +160,25 @@ * * <p>The input cipher text <code>cipher</code>, starting at * <code>cipherOffset</code> and ending at - * <code>(cipherOffset + len - 1)</code>, is decrypted. + * <code>(cipherOffset + cipherLen - 1)</code>, is decrypted. * The result is stored in <code>plain</code>, starting at * <code>plainOffset</code>. * - * <p>It is the application's responsibility to make sure that - * <code>cipherLen</code> is a multiple of the embedded cipher's block - * size, as any excess bytes are ignored. - * - * <p>It is also the application's responsibility to make sure that - * <code>init</code> has been called before this method is called. - * (This check is omitted here, to avoid double checking.) - * * @param cipher the buffer with the input data to be decrypted * @param cipherOffset the offset in <code>cipherOffset</code> * @param cipherLen the length of the input data * @param plain the buffer for the result * @param plainOffset the offset in <code>plain</code> + * @exception ProviderException if <code>cipherLen</code> is not + * a multiple of the block size + * @return the length of the decrypted data */ int decrypt(byte[] cipher, int cipherOffset, int cipherLen, byte[] plain, int plainOffset) { + if ((cipherLen % blockSize) != 0) { + throw new ProviderException("Internal error in input buffering"); + } int i; int endIndex = cipherOffset + cipherLen; @@ -189,10 +187,10 @@ embeddedCipher.decryptBlock(cipher, cipherOffset, plain, plainOffset); for (i = 0; i < blockSize; i++) { - plain[i+plainOffset] ^= k[i]; + plain[i + plainOffset] ^= k[i]; } for (i = 0; i < blockSize; i++) { - k[i] = (byte)(plain[i+plainOffset] ^ cipher[i+cipherOffset]); + k[i] = (byte)(plain[i + plainOffset] ^ cipher[i + cipherOffset]); } } return cipherLen;