Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.bouncycastle.crypto.tls;
  
  
A generic TLS 1.0-1.2 / SSLv3 block cipher. This can be used for AES or 3DES for example.
 
 public class TlsBlockCipher
     implements TlsCipher
 {
     protected TlsContext context;
     protected byte[] randomData;
     protected boolean useExplicitIV;
     protected boolean encryptThenMAC;
 
     protected BlockCipher encryptCipher;
     protected BlockCipher decryptCipher;
 
     protected TlsMac writeMac;
     protected TlsMac readMac;
 
     public TlsMac getWriteMac()
     {
         return ;
     }
 
     public TlsMac getReadMac()
     {
         return ;
     }
 
     public TlsBlockCipher(TlsContext contextBlockCipher clientWriteCipherBlockCipher serverWriteCipher,
         Digest clientWriteDigestDigest serverWriteDigestint cipherKeySizethrows IOException
     {
         this. = context;
 
         this. = new byte[256];
         context.getNonceRandomGenerator().nextBytes();
 
         this. = TlsUtils.isTLSv11(context);
         this. = context.getSecurityParameters().;
 
         int key_block_size = (2 * cipherKeySize) + clientWriteDigest.getDigestSize()
             + serverWriteDigest.getDigestSize();
 
         // From TLS 1.1 onwards, block ciphers don't need client_write_IV
         if (!)
         {
             key_block_size += clientWriteCipher.getBlockSize() + serverWriteCipher.getBlockSize();
         }
 
         byte[] key_block = TlsUtils.calculateKeyBlock(contextkey_block_size);
 
         int offset = 0;
 
         TlsMac clientWriteMac = new TlsMac(contextclientWriteDigestkey_blockoffset,
             clientWriteDigest.getDigestSize());
         offset += clientWriteDigest.getDigestSize();
         TlsMac serverWriteMac = new TlsMac(contextserverWriteDigestkey_blockoffset,
             serverWriteDigest.getDigestSize());
         offset += serverWriteDigest.getDigestSize();
 
         KeyParameter client_write_key = new KeyParameter(key_blockoffsetcipherKeySize);
         offset += cipherKeySize;
         KeyParameter server_write_key = new KeyParameter(key_blockoffsetcipherKeySize);
         offset += cipherKeySize;
 
         byte[] client_write_IVserver_write_IV;
         if ()
         {
             client_write_IV = new byte[clientWriteCipher.getBlockSize()];
             server_write_IV = new byte[serverWriteCipher.getBlockSize()];
         }
         else
         {
             client_write_IV = Arrays.copyOfRange(key_blockoffsetoffset + clientWriteCipher.getBlockSize());
             offset += clientWriteCipher.getBlockSize();
             server_write_IV = Arrays.copyOfRange(key_blockoffsetoffset + serverWriteCipher.getBlockSize());
             offset += serverWriteCipher.getBlockSize();
         }
 
         if (offset != key_block_size)
         {
             throw new TlsFatalAlert(.);
         }
 
         CipherParameters encryptParamsdecryptParams;
         if (context.isServer())
         {
             this. = serverWriteMac;
             this. = clientWriteMac;
            this. = serverWriteCipher;
            this. = clientWriteCipher;
            encryptParams = new ParametersWithIV(server_write_keyserver_write_IV);
            decryptParams = new ParametersWithIV(client_write_keyclient_write_IV);
        }
        else
        {
            this. = clientWriteMac;
            this. = serverWriteMac;
            this. = clientWriteCipher;
            this. = serverWriteCipher;
            encryptParams = new ParametersWithIV(client_write_keyclient_write_IV);
            decryptParams = new ParametersWithIV(server_write_keyserver_write_IV);
        }
        this..init(trueencryptParams);
        this..init(falsedecryptParams);
    }
    public int getPlaintextLimit(int ciphertextLimit)
    {
        int blockSize = .getBlockSize();
        int macSize = .getSize();
        int plaintextLimit = ciphertextLimit;
        // An explicit IV consumes 1 block
        if ()
        {
            plaintextLimit -= blockSize;
        }
        // Leave room for the MAC, and require block-alignment
        if ()
        {
            plaintextLimit -= macSize;
            plaintextLimit -= plaintextLimit % blockSize;
        }
        else
        {
            plaintextLimit -= plaintextLimit % blockSize;
            plaintextLimit -= macSize;
        }
        // Minimum 1 byte of padding
        --plaintextLimit;
        return plaintextLimit;
    }
    public byte[] encodePlaintext(long seqNoshort typebyte[] plaintextint offsetint len)
    {
        int blockSize = .getBlockSize();
        int macSize = .getSize();
        ProtocolVersion version = .getServerVersion();
        int enc_input_length = len;
        if (!)
        {
            enc_input_length += macSize;
        }
        int padding_length = blockSize - 1 - (enc_input_length % blockSize);
        // TODO[DTLS] Consider supporting in DTLS (without exceeding send limit though)
        if (!version.isDTLS() && !version.isSSL())
        {
            // Add a random number of extra blocks worth of padding
            int maxExtraPadBlocks = (255 - padding_length) / blockSize;
            int actualExtraPadBlocks = chooseExtraPadBlocks(.getSecureRandom(), maxExtraPadBlocks);
            padding_length += actualExtraPadBlocks * blockSize;
        }
        int totalSize = len + macSize + padding_length + 1;
        if ()
        {
            totalSize += blockSize;
        }
        byte[] outBuf = new byte[totalSize];
        int outOff = 0;
        if ()
        {
            byte[] explicitIV = new byte[blockSize];
            .getNonceRandomGenerator().nextBytes(explicitIV);
            .init(truenew ParametersWithIV(nullexplicitIV));
            System.arraycopy(explicitIV, 0, outBufoutOffblockSize);
            outOff += blockSize;
        }
        int blocks_start = outOff;
        System.arraycopy(plaintextoffsetoutBufoutOfflen);
        outOff += len;
        if (!)
        {
            byte[] mac = .calculateMac(seqNotypeplaintextoffsetlen);
            System.arraycopy(mac, 0, outBufoutOffmac.length);
            outOff += mac.length;
        }
        for (int i = 0; i <= padding_lengthi++)
        {
            outBuf[outOff++] = (byte)padding_length;
        }
        for (int i = blocks_starti < outOffi += blockSize)
        {
            .processBlock(outBufioutBufi);
        }
        if ()
        {
            byte[] mac = .calculateMac(seqNotypeoutBuf, 0, outOff);
            System.arraycopy(mac, 0, outBufoutOffmac.length);
            outOff += mac.length;
        }
//        assert outBuf.length == outOff;
        return outBuf;
    }
    public byte[] decodeCiphertext(long seqNoshort typebyte[] ciphertextint offsetint len)
        throws IOException
    {
        int blockSize = .getBlockSize();
        int macSize = .getSize();
        int minLen = blockSize;
        if ()
        {
            minLen += macSize;
        }
        else
        {
            minLen = Math.max(minLenmacSize + 1);
        }
        if ()
        {
            minLen += blockSize;
        }
        if (len < minLen)
        {
            throw new TlsFatalAlert(.);
        }
        int blocks_length = len;
        if ()
        {
            blocks_length -= macSize;
        }
        if (blocks_length % blockSize != 0)
        {
            throw new TlsFatalAlert(.);
        }
        if ()
        {
            int end = offset + len;
            byte[] receivedMac = Arrays.copyOfRange(ciphertextend - macSizeend);
            byte[] calculatedMac = .calculateMac(seqNotypeciphertextoffsetlen - macSize);
            boolean badMac = !Arrays.constantTimeAreEqual(calculatedMacreceivedMac);
            if (badMac)
            {
                /*
                 * RFC 7366 3. The MAC SHALL be evaluated before any further processing such as
                 * decryption is performed, and if the MAC verification fails, then processing SHALL
                 * terminate immediately. For TLS, a fatal bad_record_mac MUST be generated [2]. For
                 * DTLS, the record MUST be discarded, and a fatal bad_record_mac MAY be generated
                 * [4]. This immediate response to a bad MAC eliminates any timing channels that may
                 * be available through the use of manipulated packet data.
                 */
                throw new TlsFatalAlert(.);
            }
        }
        if ()
        {
            .init(falsenew ParametersWithIV(nullciphertextoffsetblockSize));
            offset += blockSize;
            blocks_length -= blockSize;
        }
        for (int i = 0; i < blocks_lengthi += blockSize)
        {
            .processBlock(ciphertextoffset + iciphertextoffset + i);
        }
        // If there's anything wrong with the padding, this will return zero
        int totalPad = checkPaddingConstantTime(ciphertextoffsetblocks_lengthblockSize ? 0 : macSize);
        boolean badMac = (totalPad == 0);
        int dec_output_length = blocks_length - totalPad;
        if (!)
        {
            dec_output_length -= macSize;
            int macInputLen = dec_output_length;
            int macOff = offset + macInputLen;
            byte[] receivedMac = Arrays.copyOfRange(ciphertextmacOffmacOff + macSize);
            byte[] calculatedMac = .calculateMacConstantTime(seqNotypeciphertextoffsetmacInputLen,
                blocks_length - macSize);
            badMac |= !Arrays.constantTimeAreEqual(calculatedMacreceivedMac);
        }
        if (badMac)
        {
            throw new TlsFatalAlert(.);
        }
        return Arrays.copyOfRange(ciphertextoffsetoffset + dec_output_length);
    }
    protected int checkPaddingConstantTime(byte[] bufint offint lenint blockSizeint macSize)
    {
        int end = off + len;
        byte lastByte = buf[end - 1];
        int padlen = lastByte & 0xff;
        int totalPad = padlen + 1;
        int dummyIndex = 0;
        byte padDiff = 0;
        if ((TlsUtils.isSSL() && 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 = ;
            while (dummyIndex < 256)
            {
                padDiff |= (dummyPad[dummyIndex++] ^ lastByte);
            }
            // Ensure the above loop is not eliminated
            dummyPad[0] ^= padDiff;
        }
        return totalPad;
    }
    protected int chooseExtraPadBlocks(SecureRandom rint max)
    {
        // return r.nextInt(max + 1);
        int x = r.nextInt();
        int n = lowestBitSet(x);
        return Math.min(nmax);
    }
    protected int lowestBitSet(int x)
    {
        if (x == 0)
        {
            return 32;
        }
        int n = 0;
        while ((x & 1) == 0)
        {
            ++n;
            x >>= 1;
        }
        return n;
    }
New to GrepCode? Check out our FAQ X