Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.bouncycastle.tls.crypto.impl.TlsStreamCipher Maven / Gradle / Ivy
package org.bouncycastle.tls.crypto.impl;
import java.io.IOException;
import org.bouncycastle.tls.AlertDescription;
import org.bouncycastle.tls.TlsFatalAlert;
import org.bouncycastle.tls.TlsUtils;
import org.bouncycastle.tls.crypto.TlsCipher;
import org.bouncycastle.tls.crypto.TlsCryptoParameters;
import org.bouncycastle.tls.crypto.TlsHMAC;
import org.bouncycastle.util.Arrays;
/**
* A generic TLS 1.0-1.2 / SSLv3 stream cipher.
*/
public class TlsStreamCipher
implements TlsCipher
{
protected TlsCryptoParameters cryptoParams;
protected TlsStreamCipherImpl encryptCipher;
protected TlsStreamCipherImpl decryptCipher;
protected TlsSuiteMac writeMac;
protected TlsSuiteMac readMac;
protected boolean usesNonce;
public TlsStreamCipher(TlsCryptoParameters cryptoParams, TlsStreamCipherImpl encryptCipher,
TlsStreamCipherImpl decryptCipher, TlsHMAC clientWriteDigest, TlsHMAC serverWriteDigest,
int cipherKeySize, boolean usesNonce) throws IOException
{
boolean isServer = cryptoParams.isServer();
this.cryptoParams = cryptoParams;
this.usesNonce = usesNonce;
this.encryptCipher = encryptCipher;
this.decryptCipher = decryptCipher;
int key_block_size = (2 * cipherKeySize) + clientWriteDigest.getMacLength()
+ serverWriteDigest.getMacLength();
byte[] key_block = TlsImplUtils.calculateKeyBlock(cryptoParams, key_block_size);
int offset = 0;
// Init MACs
TlsSuiteMac clientWriteMac = new TlsSuiteHMac(cryptoParams, clientWriteDigest);
clientWriteMac.setKey(Arrays.copyOfRange(key_block, offset, offset + clientWriteDigest.getMacLength()));
offset += clientWriteDigest.getMacLength();
TlsSuiteMac serverWriteMac = new TlsSuiteHMac(cryptoParams, serverWriteDigest);
serverWriteMac.setKey(Arrays.copyOfRange(key_block, offset, offset + serverWriteDigest.getMacLength()));
offset += serverWriteDigest.getMacLength();
// Build keys
byte[] clientWriteKey = Arrays.copyOfRange(key_block, offset, offset + cipherKeySize);
offset += cipherKeySize;
byte[] serverWriteKey = Arrays.copyOfRange(key_block, offset, offset + cipherKeySize);
offset += cipherKeySize;
if (offset != key_block_size)
{
throw new TlsFatalAlert(AlertDescription.internal_error);
}
byte[] encryptParams, decryptParams;
if (isServer)
{
this.writeMac = serverWriteMac;
this.readMac = clientWriteMac;
encryptParams = serverWriteKey;
decryptParams = clientWriteKey;
}
else
{
this.writeMac = clientWriteMac;
this.readMac = serverWriteMac;
encryptParams = clientWriteKey;
decryptParams = serverWriteKey;
}
this.encryptCipher.setKey(encryptParams);
this.decryptCipher.setKey(decryptParams);
if (usesNonce)
{
byte[] dummyNonce = new byte[8];
this.encryptCipher.init(dummyNonce);
this.decryptCipher.init(dummyNonce);
}
else
{
this.encryptCipher.init(null);
this.decryptCipher.init(null);
}
}
public int getPlaintextLimit(int ciphertextLimit)
{
return ciphertextLimit - writeMac.getSize();
}
public byte[] encodePlaintext(long seqNo, short type, byte[] plaintext, int offset, int len)
throws IOException
{
if (usesNonce)
{
updateIV(encryptCipher, true, seqNo);
}
byte[] outBuf = new byte[len + writeMac.getSize()];
byte[] mac = writeMac.calculateMac(seqNo, type, plaintext, offset, len);
System.arraycopy(plaintext, offset, outBuf, 0, len);
System.arraycopy(mac, 0, outBuf, len, mac.length);
encryptCipher.doFinal(outBuf, 0, outBuf.length, outBuf, 0);
return outBuf;
}
public byte[] decodeCiphertext(long seqNo, short type, byte[] ciphertext, int offset, int len)
throws IOException
{
if (usesNonce)
{
updateIV(decryptCipher, false, seqNo);
}
int macSize = readMac.getSize();
if (len < macSize)
{
throw new TlsFatalAlert(AlertDescription.decode_error);
}
int plaintextLength = len - macSize;
byte[] deciphered = new byte[len];
decryptCipher.doFinal(ciphertext, offset, len, deciphered, 0);
checkMAC(seqNo, type, deciphered, plaintextLength, len, deciphered, 0, plaintextLength);
return Arrays.copyOfRange(deciphered, 0, plaintextLength);
}
protected void checkMAC(long seqNo, short type, byte[] recBuf, int recStart, int recEnd, byte[] calcBuf, int calcOff, int calcLen)
throws IOException
{
byte[] receivedMac = Arrays.copyOfRange(recBuf, recStart, recEnd);
byte[] computedMac = readMac.calculateMac(seqNo, type, calcBuf, calcOff, calcLen);
if (!Arrays.constantTimeAreEqual(receivedMac, computedMac))
{
throw new TlsFatalAlert(AlertDescription.bad_record_mac);
}
}
protected void updateIV(org.bouncycastle.tls.crypto.impl.TlsStreamCipherImpl cipher, boolean forEncryption, long seqNo)
throws IOException
{
byte[] nonce = new byte[8];
TlsUtils.writeUint64(seqNo, nonce, 0);
cipher.init(nonce);
}
}