public byte[] encodePlaintext(short type, byte[] plaintext, int offset, int len) { int blocksize = encryptCipher.getBlockSize(); int padding_length = blocksize - 1 - ((len + writeMac.getSize()) % blocksize); boolean isTls = context.getServerVersion().getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion(); if (isTls) { // Add a random number of extra blocks worth of padding int maxExtraPadBlocks = (255 - padding_length) / blocksize; int actualExtraPadBlocks = chooseExtraPadBlocks(context.getSecureRandom(), maxExtraPadBlocks); padding_length += actualExtraPadBlocks * blocksize; } int totalsize = len + writeMac.getSize() + padding_length + 1; byte[] outbuf = new byte[totalsize]; System.arraycopy(plaintext, offset, outbuf, 0, len); byte[] mac = writeMac.calculateMac(type, plaintext, offset, len); System.arraycopy(mac, 0, outbuf, len, mac.length); int paddoffset = len + mac.length; for (int i = 0; i <= padding_length; i++) { outbuf[i + paddoffset] = (byte) padding_length; } for (int i = 0; i < totalsize; i += blocksize) { encryptCipher.processBlock(outbuf, i, outbuf, i); } return outbuf; }
protected int checkPaddingConstantTime(byte[] buf, int off, int len, int blockSize, int macSize) { int end = off + len; byte lastByte = buf[end - 1]; int padlen = lastByte & 0xff; int totalPad = padlen + 1; int dummyIndex = 0; byte padDiff = 0; boolean isTls = context.getServerVersion().getFullVersion() >= ProtocolVersion.TLSv10.getFullVersion(); if ((!isTls && totalPad > blockSize) || (macSize + totalPad > len)) { totalPad = 0; } else { int padPos = end - totalPad; do { padDiff |= (buf[padPos++] ^ lastByte); } while (padPos < end); dummyIndex = totalPad; if (padDiff != 0) { totalPad = 0; } } // Run some extra dummy checks so the number of checks is always constant { byte[] dummyPad = randomData; while (dummyIndex < 256) { padDiff |= (dummyPad[dummyIndex++] ^ lastByte); } // Ensure the above loop is not eliminated dummyPad[0] ^= padDiff; } return totalPad; }