protected override void EncryptRecord(DisposeContext d, IBufferOffsetSize input) { ICryptoTransform cipher; if (!Cipher.HasFixedIV) { EncryptionAlgorithm.GenerateIV(); cipher = d.Add(EncryptionAlgorithm.CreateEncryptor()); } else { cipher = encryptionCipher; } if (!Cipher.HasFixedIV) { Buffer.BlockCopy(EncryptionAlgorithm.IV, 0, input.Buffer, input.Offset, BlockSize); } var ret = cipher.TransformBlock(input.Buffer, input.Offset + HeaderSize, input.Size - HeaderSize, input.Buffer, input.Offset + HeaderSize); if (ret <= 0 || ret != input.Size - HeaderSize) { throw new InvalidOperationException(); } if (Cipher.HasFixedIV) { var IV = new byte [BlockSize]; Buffer.BlockCopy(input.Buffer, input.Offset + input.Size - BlockSize, IV, 0, BlockSize); EncryptionAlgorithm.IV = IV; } }
protected override int DecryptRecord(DisposeContext d, IBufferOffsetSize input, IBufferOffsetSize output) { if ((input.Size % BlockSize) != 0) { return(-1); } int ivSize; ICryptoTransform cipher; if (!Cipher.HasFixedIV) { var IV = new byte [BlockSize]; Buffer.BlockCopy(input.Buffer, input.Offset, IV, 0, BlockSize); ivSize = BlockSize; DecryptionAlgorithm.IV = IV; cipher = d.Add(DecryptionAlgorithm.CreateDecryptor()); } else { ivSize = 0; cipher = decryptionCipher; } var ret = cipher.TransformBlock(input.Buffer, input.Offset + ivSize, input.Size - ivSize, output.Buffer, output.Offset); if (ret <= 0 || ret != input.Size - ivSize) { return(-1); } return(ret); }
protected SecureBuffer Expand (DisposeContext d, HMac hmac, string label, SecureBuffer seed, int length) { var blockSize = hmac.MacSize; var iterations = (int)(length / blockSize); if ((length % blockSize) > 0) iterations++; var resMacs = d.CreateBuffer (length); var resOff = 0; var tempBuf = d.CreateBuffer (blockSize); var labelBytes = Encoding.ASCII.GetBytes (label); for (int i = 1; i <= iterations; i++) { hmac.Reset (); if (i == 1) { hmac.TransformBlock (labelBytes, 0, labelBytes.Length); hmac.TransformBlock (seed.Buffer, 0, seed.Size); } else { hmac.TransformBlock (tempBuf.Buffer, 0, blockSize); } hmac.TransformFinalBlock (tempBuf.Buffer, 0, blockSize); hmac.Reset (); hmac.TransformBlock (tempBuf.Buffer, 0, blockSize); hmac.TransformBlock (labelBytes, 0, labelBytes.Length); hmac.TransformBlock (seed.Buffer, 0, seed.Size); hmac.TransformFinalBlock (resMacs.Buffer, resOff, Min (length - resOff, blockSize)); resOff += blockSize; } return new SecureBuffer (resMacs.StealBuffer ()); }
public static bool VerifySignature(SignatureAndHashAlgorithm type, SecureBuffer data, AsymmetricAlgorithm key, SecureBuffer signature) { using (var d = new DisposeContext()) { var algorithm = d.Add((HashAlgorithm)GetAlgorithm(type.Hash)); algorithm.TransformFinalBlock(data.Buffer, 0, data.Size); return(VerifySignature(type, algorithm, d.Add(algorithm.Hash), key, signature)); } }
/// <summary> /// Creates an integer from a string. /// </summary> public GmpInteger(string initialValue) { if (string.IsNullOrWhiteSpace(initialValue)) { throw new ArgumentException("initialValue"); } Interop.mpz_set_str(ref _Storage, initialValue, 10); DisposeContext.AddDisposeObject(this); }
protected override int Decrypt(DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { var implicitNonce = IsClient ? ServerWriteIV : ClientWriteIV; var writeKey = IsClient ? ServerWriteKey : ClientWriteKey; #if DEBUG_FULL if (Cipher.EnableDebugging) { DebugHelper.WriteLine("FIXED IV", implicitNonce); DebugHelper.WriteLine("WRITE KEY", writeKey); DebugHelper.WriteLine("SEQUENCE: {0}", ReadSequenceNumber); } #endif var length = input.Size - ExplicitNonceSize; var aad = new TlsBuffer(13); aad.Write(ReadSequenceNumber); aad.Write((byte)contentType); aad.Write((short)Protocol); aad.Write((short)(length - MacSize)); #if DEBUG_FULL if (Cipher.EnableDebugging) { DebugHelper.WriteFull("TAG", aad); } #endif var gcm = new GcmBlockCipher(new AesEngine()); var key = new KeyParameter(writeKey.Buffer); var nonce = d.CreateBuffer(ImplicitNonceSize + ExplicitNonceSize); Buffer.BlockCopy(implicitNonce.Buffer, 0, nonce.Buffer, 0, ImplicitNonceSize); Buffer.BlockCopy(input.Buffer, input.Offset, nonce.Buffer, ImplicitNonceSize, ExplicitNonceSize); #if DEBUG_FULL if (Cipher.EnableDebugging) { DebugHelper.WriteLine("NONCE", nonce); } #endif var parameters = new AeadParameters(key, 128, nonce.Buffer, aad.Buffer); gcm.Init(false, parameters); int ret; try { ret = gcm.ProcessBytes(input.Buffer, input.Offset + ExplicitNonceSize, length, output.Buffer, output.Offset); ret += gcm.DoFinal(output.Buffer, output.Offset + ret); } catch (CryptoException ex) { throw new TlsException(AlertDescription.BadRecordMAC, ex.Message); } return(ret); }
static byte[] CreateHash (HashAlgorithmType type, SecureBuffer data) { if (!HashAlgorithmProvider.IsAlgorithmSupported (type)) throw new TlsException (AlertDescription.IlegalParameter); using (var d = new DisposeContext ()) { var algorithm = d.Add (HashAlgorithmProvider.CreateAlgorithm (type)); algorithm.TransformBlock (data.Buffer, 0, data.Size); return algorithm.GetRunningHash (); } }
void ComputeMasterSecret (DisposeContext d, TlsContext ctx, SecureBuffer preMasterSecret) { // Compute ClientRandom + ServerRandom int clen = ctx.HandshakeParameters.ClientRandom.Size; int slen = ctx.HandshakeParameters.ServerRandom.Size; int rlen = clen + slen; var cs = d.CreateBuffer (rlen); Buffer.BlockCopy (ctx.HandshakeParameters.ClientRandom.Buffer, 0, cs.Buffer, 0, clen); Buffer.BlockCopy (ctx.HandshakeParameters.ServerRandom.Buffer, 0, cs.Buffer, clen, slen); // Server Random + Client Random var sc = d.CreateBuffer (rlen); Buffer.BlockCopy (ctx.HandshakeParameters.ServerRandom.Buffer, 0, sc.Buffer, 0, slen); Buffer.BlockCopy (ctx.HandshakeParameters.ClientRandom.Buffer, 0, sc.Buffer, slen, clen); // Create master secret var crypto = ctx.Session.PendingCrypto; crypto.MasterSecret = crypto.Cipher.PRF.ComputeMasterSecret (preMasterSecret, cs); #if DEBUG_FULL if (ctx.EnableDebugging) { DebugHelper.WriteLine ("CS", cs); DebugHelper.WriteLine ("SC", sc); DebugHelper.WriteLine ("PRE-MASTER", preMasterSecret); DebugHelper.WriteLine ("MASTER SECRET", crypto.MasterSecret.Buffer); } #endif var keyBlock = crypto.Cipher.PRF.ComputeKeyExpansion (d, crypto.MasterSecret, sc, crypto.Cipher.KeyBlockSize); #if DEBUG_FULL if (ctx.EnableDebugging) { DebugHelper.WriteLine ("KEY BLOCK SIZE: {0}", crypto.Cipher.KeyBlockSize); DebugHelper.WriteLine ("KEY BLOCK", keyBlock.Buffer); } #endif crypto.ClientWriteMac = keyBlock.ReadSecureBuffer (crypto.Cipher.HashSize); crypto.ServerWriteMac = keyBlock.ReadSecureBuffer (crypto.Cipher.HashSize); crypto.ClientWriteKey = keyBlock.ReadSecureBuffer (crypto.Cipher.KeyMaterialSize); crypto.ServerWriteKey = keyBlock.ReadSecureBuffer (crypto.Cipher.KeyMaterialSize); if (crypto.Cipher.HasFixedIV) { crypto.ClientWriteIV = keyBlock.ReadSecureBuffer (crypto.Cipher.FixedIvSize); crypto.ServerWriteIV = keyBlock.ReadSecureBuffer (crypto.Cipher.FixedIvSize); #if DEBUG_FULL if (ctx.EnableDebugging) { DebugHelper.WriteLine ("CLIENT IV", crypto.ClientWriteIV.Buffer); DebugHelper.WriteLine ("SERVER IV", crypto.ServerWriteIV.Buffer); } #endif } }
static byte[] CreateHash(HashAlgorithmType type, SecureBuffer data) { if (!HashAlgorithmProvider.IsAlgorithmSupported(type)) { throw new TlsException(AlertDescription.IlegalParameter); } using (var d = new DisposeContext()) { var algorithm = d.Add(HashAlgorithmProvider.CreateAlgorithm(type)); algorithm.TransformBlock(data.Buffer, 0, data.Size); return(algorithm.GetRunningHash()); } }
/// <summary> /// Create a new integer, importing it from an array of input values and setting the sign. /// The most significant byte is given first. /// This option is here for saving and loading the integer. /// The sign is specified seperately because GMP uses magnitude/sign format. /// </summary> public GmpInteger(byte[] initialValue, bool isNegative = false) { if (initialValue == null) { throw new ArgumentException("initialValue"); } Interop.mpz_import(ref _Storage, initialValue.Length, 1, 1, 0, 0, initialValue); if (isNegative) { mpz_t negStorage = new mpz_t(); Interop.mpz_neg(ref negStorage, ref _Storage); Interop.mpz_clear(ref _Storage); _Storage = negStorage; } DisposeContext.AddDisposeObject(this); }
protected override SecureBuffer PRF(DisposeContext d, SecureBuffer secret, string label, SecureBuffer data, int length) { /* Secret Length calc exmplain from the RFC2246. Section 5 * * S1 and S2 are the two halves of the secret and each is the same * length. S1 is taken from the first half of the secret, S2 from the * second half. Their length is created by rounding up the length of the * overall secret divided by two; thus, if the original secret is an odd * number of bytes long, the last byte of S1 will be the same as the * first byte of S2. */ // split secret in 2 int secretLen = secret.Size >> 1; // rounding up if ((secret.Size & 0x1) == 0x1) { secretLen++; } // Secret 1 var secret1 = d.CreateBuffer(secretLen); Buffer.BlockCopy(secret.Buffer, 0, secret1.Buffer, 0, secretLen); // Secret2 var secret2 = d.CreateBuffer(secretLen); Buffer.BlockCopy(secret.Buffer, (secret.Size - secretLen), secret2.Buffer, 0, secretLen); // Secret 1 processing var p_md5 = d.Add(Expand(d, HMac.Create(HashAlgorithmType.Md5, secret1), label, data, length)); // Secret 2 processing var p_sha = d.Add(Expand(d, HMac.Create(HashAlgorithmType.Sha1, secret2), label, data, length)); // Perfor XOR of both results var masterSecret = new SecureBuffer(length); for (int i = 0; i < length; i++) { masterSecret.Buffer[i] = (byte)(p_md5.Buffer[i] ^ p_sha.Buffer[i]); } return(masterSecret); }
// Protected Methods (1) /// <summary> /// /// </summary> /// <see cref="SyncDisposableBase.OnDispose(DisposeContext)" /> protected override void OnDispose(DisposeContext context) { base.OnDispose(context); // dies zu allerletzt machen { var funcLogger = this.InnerFunctionLogger; if (funcLogger != null) { funcLogger.Clear(); } var aggLogger = this.Logger; if (aggLogger != null) { aggLogger.Clear(); } } }
protected override int Encrypt(DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { // Calculate message MAC byte[] mac = null; if (IsServer) { mac = ComputeServerRecordMAC(contentType, input); } else { mac = ComputeClientRecordMAC(contentType, input); } #if DEBUG_FULL if (Cipher.EnableDebugging) { DebugHelper.WriteLine("RECORD MAC", mac); } #endif int plen; byte padLen; int totalLength = GetEncryptedSize(input.Size, out plen, out padLen); var totalOutput = new BufferOffsetSize(output.Buffer, output.Offset, totalLength); var outputWriter = new TlsBuffer(totalOutput); outputWriter.Position += HeaderSize; outputWriter.Write(input.Buffer, input.Offset, input.Size); outputWriter.Write(mac); for (int i = 0; i <= padLen; i++) { outputWriter.Write(padLen); } // Encrypt the message EncryptRecord(d, totalOutput); return(totalLength); }
protected override void EncryptRecord(DisposeContext d, IBufferOffsetSize buffer) { ICryptoTransform cipher; if (!Cipher.HasFixedIV) { EncryptionAlgorithm.GenerateIV(); cipher = d.Add(EncryptionAlgorithm.CreateEncryptor()); } else { cipher = encryptionCipher; } if (!Cipher.HasFixedIV) { Buffer.BlockCopy(EncryptionAlgorithm.IV, 0, buffer.Buffer, buffer.Offset, BlockSize); } cipher.TransformBlock(buffer.Buffer, buffer.Offset + HeaderSize, buffer.Size - HeaderSize, buffer.Buffer, buffer.Offset + HeaderSize); }
protected override SecureBuffer PRF (DisposeContext d, SecureBuffer secret, string label, SecureBuffer data, int length) { /* Secret Length calc exmplain from the RFC2246. Section 5 * * S1 and S2 are the two halves of the secret and each is the same * length. S1 is taken from the first half of the secret, S2 from the * second half. Their length is created by rounding up the length of the * overall secret divided by two; thus, if the original secret is an odd * number of bytes long, the last byte of S1 will be the same as the * first byte of S2. */ // split secret in 2 int secretLen = secret.Size >> 1; // rounding up if ((secret.Size & 0x1) == 0x1) secretLen++; // Secret 1 var secret1 = d.CreateBuffer (secretLen); Buffer.BlockCopy (secret.Buffer, 0, secret1.Buffer, 0, secretLen); // Secret2 var secret2 = d.CreateBuffer (secretLen); Buffer.BlockCopy (secret.Buffer, (secret.Size - secretLen), secret2.Buffer, 0, secretLen); // Secret 1 processing var p_md5 = d.Add (Expand (d, HMac.Create (HashAlgorithmType.Md5, secret1), label, data, length)); // Secret 2 processing var p_sha = d.Add (Expand (d, HMac.Create (HashAlgorithmType.Sha1, secret2), label, data, length)); // Perfor XOR of both results var masterSecret = new SecureBuffer (length); for (int i = 0; i < length; i++) masterSecret.Buffer[i] = (byte)(p_md5.Buffer[i] ^ p_sha.Buffer[i]); return masterSecret; }
// Private Methods (1) private void Dispose(DisposeContext context) { lock (this._SYNC_ROOT) { if (context == DisposeContext.DisposeMethod) { if (this.IsDisposed) { return; } this.RaiseEventHandler(this.Disposing); } this.OnDispose(context); if (context == DisposeContext.DisposeMethod) { this.RaiseEventHandler(this.Disposed); this.IsDisposed = true; } } }
public int Decrypt(ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { if (output == null || output == input || output.Buffer == input.Buffer) { throw new TlsException(AlertDescription.InternalError, "In-place decryption is not supported."); } if (output.Size < input.Size) { throw new TlsException(AlertDescription.InternalError, "Output buffer overflow."); } using (var d = new DisposeContext()) { var ret = Decrypt(d, contentType, input, output); // Update sequence number ReadSequenceNumber++; if (ret < 0) { throw new TlsException(AlertDescription.BadRecordMAC); } return(ret); } }
/// <summary> /// Initialize a zero valued integer. /// </summary> public GmpInteger() { Interop.mpz_init(ref _Storage); DisposeContext.AddDisposeObject(this); }
protected abstract SecureBuffer PRF(DisposeContext d, SecureBuffer secret, string label, SecureBuffer data, int length);
public SecureBuffer PRF(SecureBuffer secret, string label, SecureBuffer data, int length) { using (var d = new DisposeContext()) return(PRF(d, secret, label, data, length)); }
public TlsBuffer ComputeKeyExpansion(DisposeContext d, SecureBuffer masterSecret, SecureBuffer sc, int size) { var buffer = d.Add(PRF(d, masterSecret, "key expansion", sc, size)); return(new TlsBuffer(buffer.Buffer)); }
protected abstract void EncryptRecord(DisposeContext d, IBufferOffsetSize buffer);
// Protected Methods (3) /// <summary> /// /// </summary> /// <see cref="SyncDisposableBase.OnDispose(DisposeContext)"/> protected override void OnDispose(DisposeContext context) { base.OnDispose(context); this.OnStop(); }
protected abstract SecureBuffer PRF (DisposeContext d, SecureBuffer secret, string label, SecureBuffer data, int length);
public SecureBuffer PRF (SecureBuffer secret, string label, SecureBuffer data, int length) { using (var d = new DisposeContext ()) return PRF (d, secret, label, data, length); }
protected abstract int DecryptRecord(DisposeContext d, IBufferOffsetSize input, IBufferOffsetSize output);
protected override int DecryptRecord (DisposeContext d, IBufferOffsetSize input, IBufferOffsetSize output) { if ((input.Size % BlockSize) != 0) return -1; int ivSize; ICryptoTransform cipher; if (!Cipher.HasFixedIV) { var IV = new byte [BlockSize]; Buffer.BlockCopy (input.Buffer, input.Offset, IV, 0, BlockSize); ivSize = BlockSize; DecryptionAlgorithm.IV = IV; cipher = d.Add (DecryptionAlgorithm.CreateDecryptor ()); } else { ivSize = 0; cipher = decryptionCipher; } var ret = cipher.TransformBlock (input.Buffer, input.Offset + ivSize, input.Size - ivSize, output.Buffer, output.Offset); if (ret <= 0 || ret != input.Size - ivSize) return -1; if (Cipher.HasFixedIV) { var IV = new byte [BlockSize]; Buffer.BlockCopy (input.Buffer, input.Offset + input.Size - BlockSize, IV, 0, BlockSize); DecryptionAlgorithm.IV = IV; } return ret; }
protected override void EncryptRecord (DisposeContext d, IBufferOffsetSize input) { ICryptoTransform cipher; if (!Cipher.HasFixedIV) { EncryptionAlgorithm.GenerateIV (); cipher = d.Add (EncryptionAlgorithm.CreateEncryptor ()); } else { cipher = encryptionCipher; } if (!Cipher.HasFixedIV) Buffer.BlockCopy (EncryptionAlgorithm.IV, 0, input.Buffer, input.Offset, BlockSize); var ret = cipher.TransformBlock (input.Buffer, input.Offset + HeaderSize, input.Size - HeaderSize, input.Buffer, input.Offset + HeaderSize); if (ret <= 0 || ret != input.Size - HeaderSize) throw new InvalidOperationException (); if (Cipher.HasFixedIV) { var IV = new byte [BlockSize]; Buffer.BlockCopy (input.Buffer, input.Offset + input.Size - BlockSize, IV, 0, BlockSize); EncryptionAlgorithm.IV = IV; } }
public static Path FindBestPath(this GameField gameField, Point @from, ushort[] cost, Map <float> cost2, int length, int realStart = 0, int realLen = 0) { var closedList = GetClosedList(gameField); var openProcessed = GetOpenProcessedList(gameField); var cameFrom = new Dictionary <Point, Breadcrump>(); var bStart = new Breadcrump(@from, 0, 0, 0); var openList = GetOpenList(); openList.Add(bStart); var rowLen = gameField.Width; var colLen = gameField.Height; closedList[from.ToIdx(rowLen)] = true; var filter = ScoreClosure(gameField, openProcessed); using var disCx = new DisposeContext(); disCx.Disposed += () => { foreach (var bc in cameFrom) { _breadcrumps.Put(bc.Value); } }; disCx.Disposed += () => { foreach (var bc in openList) { _breadcrumps.Put(bc); } }; while (openList.Count > 0) { var src = openList.FindMax(filter); var srcPos = src.Pos; var srcIdx = srcPos.Y * rowLen + srcPos.X; if (openProcessed[srcIdx]) { break; } openProcessed[srcIdx] = true; // openList.Remove(src); if (src.Hops >= length) { return(ReconstructPath(cameFrom, srcPos, src.HScore)); } var anyAdj = false; for (var i = 0; i < 4; i++) { var adj = new Point(srcPos.X + ColNum[i], srcPos.Y + RowNum[i]); Warp(ref adj, rowLen, colLen); if (!IsValid(adj, rowLen, colLen)) { continue; } var mapFlags = gameField.GetFlags(adj); if (mapFlags.CHasFlag(CellFlags.Wall)) { continue; } var adjIdx = adj.Y * rowLen + adj.X; if (closedList[adjIdx]) { continue; } closedList[adjIdx] = true; anyAdj = true; var adjValue = Balance.GetCellValue(mapFlags); /*if (mapFlags.CHasFlag(CellFlags.GemPellet) * && src.Hops < 3 * && !src.Flags.CHasFlag(CellFlags.MyPac) && !src.Flags.CHasFlag(CellFlags.EnemyPac)) * adjValue = 0f;*/ // inverse heuristic to make sum minimal var cellScore = realLen > 0 ? adjValue * (1 - (realStart + src.Hops + 1) / (float)realLen) : adjValue; var hScore = src.HScore + cellScore; var gScore = cost[adjIdx] + (cost2?[adj] ?? 0); cameFrom[adj] = _breadcrumps.Take().Set(srcPos, src.Hops + 1, hScore, gScore, src.Flags | mapFlags); openList.Add(_breadcrumps.Take().Set(adj, src.Hops + 1, hScore, gScore, src.Flags | mapFlags)); } if (!anyAdj) { return(ReconstructPath(cameFrom, srcPos, src.HScore)); } } // if (lastBest.HasValue) // return ReconstructPath(cameFrom, lastBest.Value.Pos, Math.Abs(lastBest.Value.HScore/maxValue)); // todo add path to last node? Player.Print($"path not found {from} {length}"); return(null); }
public int Decrypt (ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { if (output == null || output == input || output.Buffer == input.Buffer) throw new TlsException (AlertDescription.InternalError, "In-place decryption is not supported."); if (output.Size < input.Size) throw new TlsException (AlertDescription.InternalError, "Output buffer overflow."); using (var d = new DisposeContext ()) { var ret = Decrypt (d, contentType, input, output); // Update sequence number ReadSequenceNumber++; if (ret < 0) throw new TlsException (AlertDescription.BadRecordMAC); return ret; } }
public TlsBuffer ComputeKeyExpansion (DisposeContext d, SecureBuffer masterSecret, SecureBuffer sc, int size) { var buffer = d.Add (PRF (d, masterSecret, "key expansion", sc, size)); return new TlsBuffer (buffer.Buffer); }
protected void ComputeMasterSecret(TlsContext ctx, SecureBuffer preMasterSecret) { using (var d = new DisposeContext()) ComputeMasterSecret(d, ctx, preMasterSecret); }
protected override int Decrypt(DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { if ((input.Size % BlockSize) != 0) { return(-1); } if (input.Size < MinExtraEncryptedBytes) { return(-1); } var plen = DecryptRecord(d, input, output); if (plen <= 0) { return(-1); } var padlen = output.Buffer [output.Offset + plen - 1]; #if DEBUG_FULL if (Cipher.EnableDebugging) { DebugHelper.WriteLine("DECRYPT: {0} {1} {2}", input.Size, plen, padlen); DebugHelper.WriteBuffer("DECRYPTED", output.Buffer, output.Offset, plen); } #endif /* * VERY IMPORTANT: * * The Compiler and JIT *** MUST NOT *** optimize the following block of code. * * It is essential that the dummy checks and dummy calls be kept in place. * Also do not put any debugging code into that region as it would mess up with * the timing. * */ #region The following block of code *** MUST NOT *** be optimized in any way if (MacSize + padlen + 1 > plen) { // Invalid padding: plaintext is not long enough. // First run a loop as if there were 256 bytes of padding, with a dummy check. int ok = -1; for (int i = 0; i < 256; i++) { if (output.Buffer [i % output.Size] != padlen) { ok--; } } // Now assume there's no padding, compute the MAC over the entire buffer. var first = new BufferOffsetSize(output.Buffer, output.Offset, plen - MacSize); var invalidMac = ComputeRecordMAC(contentType, first); // Constant-time compare - this will always fail, TlsBuffer.ConstantTimeCompare() will return a negative value on error. ok += TlsBuffer.ConstantTimeCompare(invalidMac, 0, invalidMac.Length, output.Buffer, output.Offset + plen - MacSize, MacSize); return(ok); } else { int ok = 0; var resultLength = plen - padlen - MacSize - 1; for (int i = 0; i < padlen; i++) { if (output.Buffer [output.Offset + resultLength + MacSize + i] != padlen) { ok--; } } var dummyOk = ok; var dummyLen = 256 - padlen - 1; for (int i = 0; i < dummyLen; i++) { if (output.Buffer [i % output.Size] != padlen) { dummyOk--; } } if (ok < 0) { // Now assume there's no padding, compute the MAC over the entire buffer. var first = new BufferOffsetSize(output.Buffer, output.Offset, plen - MacSize); var invalidMac = ComputeRecordMAC(contentType, first); // Constant-time compare - this will always fail, TlsBuffer.ConstantTimeCompare() will return a negative value on error. ok += TlsBuffer.ConstantTimeCompare(invalidMac, 0, invalidMac.Length, output.Buffer, output.Offset + plen - MacSize, MacSize); return(ok); } else { var first = new BufferOffsetSize(output.Buffer, output.Offset, resultLength); var checkMac = ComputeRecordMAC(contentType, first); var L1 = 13 + plen - MacSize; var L2 = 13 + plen - padlen - 1 - MacSize; var additional = ((L1 - 55) / 64) - ((L2 - 55) / 64); if (additional > 0) { var algorithm = HMac.CreateHash(Cipher.HashAlgorithmType); for (int i = 0; i < additional; i++) { algorithm.TransformBlock(input.Buffer, input.Offset, BlockSize, null, 0); } } ok += TlsBuffer.ConstantTimeCompare(checkMac, 0, checkMac.Length, output.Buffer, output.Offset + resultLength, MacSize); if (ok == 0) { ok = resultLength; } return(ok); } } #endregion }
protected override SecureBuffer PRF (DisposeContext d, SecureBuffer secret, string label, SecureBuffer data, int length) { return Expand (d, HMac.Create (HandshakeHashType, secret), label, data, length); }
protected abstract int Decrypt (DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output);
// Protected Methods (3) /// <summary> /// Die Logik für die <see cref="SyncDisposableBase.Dispose()" />-Methode /// sowie des Destruktors. /// </summary> /// <param name="context">Der Kontext.</param> protected virtual void OnDispose(DisposeContext context) { // dummy }
protected override SecureBuffer PRF(DisposeContext d, SecureBuffer secret, string label, SecureBuffer data, int length) { return(Expand(d, HMac.Create(HandshakeHashType, secret), label, data, length)); }
protected abstract void EncryptRecord (DisposeContext d, IBufferOffsetSize buffer);
protected override int Decrypt (DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { var implicitNonce = IsClient ? ServerWriteIV : ClientWriteIV; var writeKey = IsClient ? ServerWriteKey : ClientWriteKey; #if DEBUG_FULL if (Cipher.EnableDebugging) { DebugHelper.WriteLine ("FIXED IV", implicitNonce); DebugHelper.WriteLine ("WRITE KEY", writeKey); DebugHelper.WriteLine ("SEQUENCE: {0}", ReadSequenceNumber); } #endif var length = input.Size - ExplicitNonceSize; var aad = new TlsBuffer (13); aad.Write (ReadSequenceNumber); aad.Write ((byte)contentType); aad.Write ((short)Protocol); aad.Write ((short)(length - MacSize)); #if DEBUG_FULL if (Cipher.EnableDebugging) DebugHelper.WriteFull ("TAG", aad); #endif var gcm = new GcmBlockCipher (new AesEngine ()); var key = new KeyParameter (writeKey.Buffer); var nonce = d.CreateBuffer (ImplicitNonceSize + ExplicitNonceSize); Buffer.BlockCopy (implicitNonce.Buffer, 0, nonce.Buffer, 0, ImplicitNonceSize); Buffer.BlockCopy (input.Buffer, input.Offset, nonce.Buffer, ImplicitNonceSize, ExplicitNonceSize); #if DEBUG_FULL if (Cipher.EnableDebugging) DebugHelper.WriteLine ("NONCE", nonce); #endif var parameters = new AeadParameters (key, 128, nonce.Buffer, aad.Buffer); gcm.Init (false, parameters); int ret; try { ret = gcm.ProcessBytes (input.Buffer, input.Offset + ExplicitNonceSize, length, output.Buffer, output.Offset); ret += gcm.DoFinal (output.Buffer, output.Offset + ret); } catch (CryptoException ex) { throw new TlsException (AlertDescription.BadRecordMAC, ex.Message); } return ret; }
protected abstract int DecryptRecord (DisposeContext d, IBufferOffsetSize input, IBufferOffsetSize output);
protected override int Encrypt (DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { // Calculate message MAC byte[] mac = null; if (IsServer) mac = ComputeServerRecordMAC (contentType, input); else mac = ComputeClientRecordMAC (contentType, input); #if DEBUG_FULL if (Cipher.EnableDebugging) DebugHelper.WriteLine ("RECORD MAC", mac); #endif int plen; byte padLen; int totalLength = GetEncryptedSize (input.Size, out plen, out padLen); var totalOutput = new BufferOffsetSize (output.Buffer, output.Offset, totalLength); var outputWriter = new TlsBuffer (totalOutput); outputWriter.Position += HeaderSize; outputWriter.Write (input.Buffer, input.Offset, input.Size); outputWriter.Write (mac); for (int i = 0; i <= padLen; i++) outputWriter.Write (padLen); // Encrypt the message EncryptRecord (d, totalOutput); return totalLength; }
protected abstract int Decrypt(DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output);
protected override int Decrypt (DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output) { if ((input.Size % BlockSize) != 0) return -1; if (input.Size < MinExtraEncryptedBytes) return -1; var plen = DecryptRecord (d, input, output); if (plen <= 0) return -1; var padlen = output.Buffer [output.Offset + plen - 1]; #if DEBUG_FULL if (Cipher.EnableDebugging) { DebugHelper.WriteLine ("DECRYPT: {0} {1} {2}", input.Size, plen, padlen); DebugHelper.WriteBuffer ("DECRYPTED", output.Buffer, output.Offset, plen); } #endif /* * VERY IMPORTANT: * * The Compiler and JIT *** MUST NOT *** optimize the following block of code. * * It is essential that the dummy checks and dummy calls be kept in place. * Also do not put any debugging code into that region as it would mess up with * the timing. * */ #region The following block of code *** MUST NOT *** be optimized in any way if (MacSize + padlen + 1 > plen) { // Invalid padding: plaintext is not long enough. // First run a loop as if there were 256 bytes of padding, with a dummy check. int ok = -1; for (int i = 0; i < 256; i++) { if (output.Buffer [i % output.Size] != padlen) ok--; } // Now assume there's no padding, compute the MAC over the entire buffer. var first = new BufferOffsetSize (output.Buffer, output.Offset, plen - MacSize); var invalidMac = ComputeRecordMAC (contentType, first); // Constant-time compare - this will always fail, TlsBuffer.ConstantTimeCompare() will return a negative value on error. ok += TlsBuffer.ConstantTimeCompare (invalidMac, 0, invalidMac.Length, output.Buffer, output.Offset + plen - MacSize, MacSize); return ok; } else { int ok = 0; var resultLength = plen - padlen - MacSize - 1; for (int i = 0; i < padlen; i++) { if (output.Buffer [output.Offset + resultLength + MacSize + i] != padlen) ok--; } var dummyOk = ok; var dummyLen = 256 - padlen - 1; for (int i = 0; i < dummyLen; i++) { if (output.Buffer [i % output.Size] != padlen) dummyOk--; } if (ok < 0) { // Now assume there's no padding, compute the MAC over the entire buffer. var first = new BufferOffsetSize (output.Buffer, output.Offset, plen - MacSize); var invalidMac = ComputeRecordMAC (contentType, first); // Constant-time compare - this will always fail, TlsBuffer.ConstantTimeCompare() will return a negative value on error. ok += TlsBuffer.ConstantTimeCompare (invalidMac, 0, invalidMac.Length, output.Buffer, output.Offset + plen - MacSize, MacSize); return ok; } else { var first = new BufferOffsetSize (output.Buffer, output.Offset, resultLength); var checkMac = ComputeRecordMAC (contentType, first); var L1 = 13 + plen - MacSize; var L2 = 13 + plen - padlen - 1 - MacSize; var additional = ((L1 - 55) / 64) - ((L2 - 55) / 64); if (additional > 0) { var algorithm = HMac.CreateHash (Cipher.HashAlgorithmType); for (int i = 0; i < additional; i++) algorithm.TransformBlock (input.Buffer, input.Offset, BlockSize, null, 0); } ok += TlsBuffer.ConstantTimeCompare (checkMac, 0, checkMac.Length, output.Buffer, output.Offset + resultLength, MacSize); if (ok == 0) ok = resultLength; return ok; } } #endregion }
void ComputeMasterSecret(DisposeContext d, TlsContext ctx, SecureBuffer preMasterSecret) { // Compute ClientRandom + ServerRandom int clen = ctx.HandshakeParameters.ClientRandom.Size; int slen = ctx.HandshakeParameters.ServerRandom.Size; int rlen = clen + slen; var cs = d.CreateBuffer(rlen); Buffer.BlockCopy(ctx.HandshakeParameters.ClientRandom.Buffer, 0, cs.Buffer, 0, clen); Buffer.BlockCopy(ctx.HandshakeParameters.ServerRandom.Buffer, 0, cs.Buffer, clen, slen); // Server Random + Client Random var sc = d.CreateBuffer(rlen); Buffer.BlockCopy(ctx.HandshakeParameters.ServerRandom.Buffer, 0, sc.Buffer, 0, slen); Buffer.BlockCopy(ctx.HandshakeParameters.ClientRandom.Buffer, 0, sc.Buffer, slen, clen); // Create master secret var crypto = ctx.Session.PendingCrypto; crypto.MasterSecret = crypto.Cipher.PRF.ComputeMasterSecret(preMasterSecret, cs); #if DEBUG_FULL if (ctx.EnableDebugging) { DebugHelper.WriteLine("CS", cs); DebugHelper.WriteLine("SC", sc); DebugHelper.WriteLine("PRE-MASTER", preMasterSecret); DebugHelper.WriteLine("MASTER SECRET", crypto.MasterSecret.Buffer); } #endif var keyBlock = crypto.Cipher.PRF.ComputeKeyExpansion(d, crypto.MasterSecret, sc, crypto.Cipher.KeyBlockSize); #if DEBUG_FULL if (ctx.EnableDebugging) { DebugHelper.WriteLine("KEY BLOCK SIZE: {0}", crypto.Cipher.KeyBlockSize); DebugHelper.WriteLine("KEY BLOCK", keyBlock.Buffer); } #endif crypto.ClientWriteMac = keyBlock.ReadSecureBuffer(crypto.Cipher.HashSize); crypto.ServerWriteMac = keyBlock.ReadSecureBuffer(crypto.Cipher.HashSize); crypto.ClientWriteKey = keyBlock.ReadSecureBuffer(crypto.Cipher.KeyMaterialSize); crypto.ServerWriteKey = keyBlock.ReadSecureBuffer(crypto.Cipher.KeyMaterialSize); if (crypto.Cipher.HasFixedIV) { crypto.ClientWriteIV = keyBlock.ReadSecureBuffer(crypto.Cipher.FixedIvSize); crypto.ServerWriteIV = keyBlock.ReadSecureBuffer(crypto.Cipher.FixedIvSize); #if DEBUG_FULL if (ctx.EnableDebugging) { DebugHelper.WriteLine("CLIENT IV", crypto.ClientWriteIV.Buffer); DebugHelper.WriteLine("SERVER IV", crypto.ServerWriteIV.Buffer); } #endif } }
protected void ComputeMasterSecret (TlsContext ctx, SecureBuffer preMasterSecret) { using (var d = new DisposeContext ()) ComputeMasterSecret (d, ctx, preMasterSecret); }