public virtual byte[] DecodeCiphertext(ContentType type, byte[] ciphertext, int offset, int len) { int blockSize = decryptCipher.GetBlockSize(); int macSize = rMac.Size; /* * TODO[TLS 1.1] Explicit IV implies minLen = blockSize + max(blockSize, macSize + 1), * and will need further changes to offset and plen variables below. */ int minLen = System.Math.Max(blockSize, macSize + 1); if (len < minLen) { throw new TlsFatalAlert(AlertDescription.decode_error); } if (len % blockSize != 0) { throw new TlsFatalAlert(AlertDescription.decryption_failed); } for (int i = 0; i < len; i += blockSize) { decryptCipher.ProcessBlock(ciphertext, offset + i, ciphertext, offset + i); } int plen = len; // If there's anything wrong with the padding, this will return zero int totalPad = CheckPaddingConstantTime(ciphertext, offset, plen, blockSize, macSize); int macInputLen = plen - totalPad - macSize; byte[] decryptedMac = Arrays.Copy(ciphertext, offset + macInputLen, macSize); byte[] calculatedMac = rMac.CalculateMacConstantTime(type, ciphertext, offset, macInputLen, plen - macSize, randomData); bool badMac = !Arrays.ConstantTimeAreEqual(calculatedMac, decryptedMac); if (badMac || totalPad == 0) { throw new TlsFatalAlert(AlertDescription.bad_record_mac); } return(Arrays.Copy(ciphertext, offset, macInputLen)); }
/// <exception cref="IOException"></exception> public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len) { int blockSize = decryptCipher.GetBlockSize(); int macSize = mReadMac.Size; int minLen = blockSize; if (encryptThenMac) { minLen += macSize; } else { minLen = System.Math.Max(minLen, macSize + 1); } if (useExplicitIV) { minLen += blockSize; } if (len < minLen) { throw new TlsFatalAlert(AlertDescription.decode_error); } int blocks_length = len; if (encryptThenMac) { blocks_length -= macSize; } if (blocks_length % blockSize != 0) { throw new TlsFatalAlert(AlertDescription.decryption_failed); } if (encryptThenMac) { int end = offset + len; byte[] receivedMac = Arrays.CopyOfRange(ciphertext, end - macSize, end); byte[] calculatedMac = mReadMac.CalculateMac(seqNo, type, ciphertext, offset, len - macSize); bool badMac = !Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac); if (badMac) { throw new TlsFatalAlert(AlertDescription.bad_record_mac); } } if (useExplicitIV) { decryptCipher.Init(false, new ParametersWithIV(null, ciphertext, offset, blockSize)); offset += blockSize; blocks_length -= blockSize; } for (int i = 0; i < blocks_length; i += blockSize) { decryptCipher.ProcessBlock(ciphertext, offset + i, ciphertext, offset + i); } // If there's anything wrong with the padding, this will return zero int totalPad = CheckPaddingConstantTime(ciphertext, offset, blocks_length, blockSize, encryptThenMac ? 0 : macSize); int dec_output_length = blocks_length - totalPad; if (!encryptThenMac) { dec_output_length -= macSize; int macInputLen = dec_output_length; int macOff = offset + macInputLen; byte[] receivedMac = Arrays.CopyOfRange(ciphertext, macOff, macOff + macSize); byte[] calculatedMac = mReadMac.CalculateMacConstantTime(seqNo, type, ciphertext, offset, macInputLen, blocks_length - macSize, randomData); bool badMac = !Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac); if (badMac || totalPad == 0) { throw new TlsFatalAlert(AlertDescription.bad_record_mac); } } return(Arrays.CopyOfRange(ciphertext, offset, offset + dec_output_length)); }
/// <exception cref="IOException"></exception> public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len) { int blockSize = decryptCipher.GetBlockSize(); int macSize = mReadMac.Size; int minLen = blockSize; if (encryptThenMac) { minLen += macSize; } else { minLen = System.Math.Max(minLen, macSize + 1); } if (useExplicitIV) { minLen += blockSize; } if (len < minLen) { throw new TlsFatalAlert(AlertDescription.decode_error); } int blocks_length = len; if (encryptThenMac) { blocks_length -= macSize; } if (blocks_length % blockSize != 0) { throw new TlsFatalAlert(AlertDescription.decryption_failed); } if (encryptThenMac) { int end = offset + len; byte[] receivedMac = Arrays.CopyOfRange(ciphertext, end - macSize, end); byte[] calculatedMac = mReadMac.CalculateMac(seqNo, type, ciphertext, offset, len - macSize); bool badMacEtm = !Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac); if (badMacEtm) { /* * 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(AlertDescription.bad_record_mac); } } if (useExplicitIV) { decryptCipher.Init(false, new ParametersWithIV(null, ciphertext, offset, blockSize)); offset += blockSize; blocks_length -= blockSize; } for (int i = 0; i < blocks_length; i += blockSize) { decryptCipher.ProcessBlock(ciphertext, offset + i, ciphertext, offset + i); } // If there's anything wrong with the padding, this will return zero int totalPad = CheckPaddingConstantTime(ciphertext, offset, blocks_length, blockSize, encryptThenMac ? 0 : macSize); bool badMac = (totalPad == 0); int dec_output_length = blocks_length - totalPad; if (!encryptThenMac) { dec_output_length -= macSize; int macInputLen = dec_output_length; int macOff = offset + macInputLen; byte[] receivedMac = Arrays.CopyOfRange(ciphertext, macOff, macOff + macSize); byte[] calculatedMac = mReadMac.CalculateMacConstantTime(seqNo, type, ciphertext, offset, macInputLen, blocks_length - macSize, randomData); badMac |= !Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac); } if (badMac) { throw new TlsFatalAlert(AlertDescription.bad_record_mac); } return(Arrays.CopyOfRange(ciphertext, offset, offset + dec_output_length)); }
public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len) { int blockSize = decryptCipher.GetBlockSize(); int size = mReadMac.Size; int num = blockSize; num = ((!encryptThenMac) ? Math.Max(num, size + 1) : (num + size)); if (useExplicitIV) { num += blockSize; } if (len < num) { throw new TlsFatalAlert(50); } int num2 = len; if (encryptThenMac) { num2 -= size; } if (num2 % blockSize != 0) { throw new TlsFatalAlert(21); } if (encryptThenMac) { int num3 = offset + len; byte[] b = Arrays.CopyOfRange(ciphertext, num3 - size, num3); byte[] a = mReadMac.CalculateMac(seqNo, type, ciphertext, offset, len - size); if (!Arrays.ConstantTimeAreEqual(a, b)) { throw new TlsFatalAlert(20); } } if (useExplicitIV) { decryptCipher.Init(forEncryption: false, new ParametersWithIV(null, ciphertext, offset, blockSize)); offset += blockSize; num2 -= blockSize; } for (int i = 0; i < num2; i += blockSize) { decryptCipher.ProcessBlock(ciphertext, offset + i, ciphertext, offset + i); } int num4 = CheckPaddingConstantTime(ciphertext, offset, num2, blockSize, (!encryptThenMac) ? size : 0); bool flag = num4 == 0; int num5 = num2 - num4; if (!encryptThenMac) { num5 -= size; int num6 = num5; int num7 = offset + num6; byte[] b2 = Arrays.CopyOfRange(ciphertext, num7, num7 + size); byte[] a2 = mReadMac.CalculateMacConstantTime(seqNo, type, ciphertext, offset, num6, num2 - size, randomData); flag |= !Arrays.ConstantTimeAreEqual(a2, b2); } if (flag) { throw new TlsFatalAlert(20); } return(Arrays.CopyOfRange(ciphertext, offset, offset + num5)); }