private void ProcessPreMessages(HandshakePattern handshakePattern) { foreach (var token in handshakePattern.Initiator.Tokens) { if (token == Token.S) { state.MixHash(role == Role.Alice ? s.PublicKey : rs); } } foreach (var token in handshakePattern.Responder.Tokens) { if (token == Token.S) { state.MixHash(role == Role.Alice ? rs : s.PublicKey); } } }
private void ProcessPreMessages(HandshakePattern handshakePattern) { foreach (var preMessage in handshakePattern.Initiator.Tokens) { if (preMessage == Token.S) { state.MixHash(initiator ? this.s.PublicKey : rs); } } foreach (var preMessage in handshakePattern.Responder.Tokens) { if (preMessage == Token.S) { state.MixHash(initiator ? rs : this.s.PublicKey); } } }
public HandshakeState( Protocol protocol, bool initiator, ReadOnlySpan <byte> prologue, ReadOnlySpan <byte> s, ReadOnlySpan <byte> rs, IEnumerable <byte[]> psks) { Debug.Assert(psks != null); if (!s.IsEmpty && s.Length != dh.DhLen) { throw new ArgumentException("Invalid local static private key.", nameof(s)); } if (!rs.IsEmpty && rs.Length != dh.DhLen) { throw new ArgumentException("Invalid remote static public key.", nameof(rs)); } if (s.IsEmpty && protocol.HandshakePattern.LocalStaticRequired(initiator)) { throw new ArgumentException("Local static private key required, but not provided.", nameof(s)); } if (!s.IsEmpty && !protocol.HandshakePattern.LocalStaticRequired(initiator)) { throw new ArgumentException("Local static private key provided, but not required.", nameof(s)); } if (rs.IsEmpty && protocol.HandshakePattern.RemoteStaticRequired(initiator)) { throw new ArgumentException("Remote static public key required, but not provided.", nameof(rs)); } if (!rs.IsEmpty && !protocol.HandshakePattern.RemoteStaticRequired(initiator)) { throw new ArgumentException("Remote static public key provided, but not required.", nameof(rs)); } state = new SymmetricState <CipherType, DhType, HashType>(protocol.Name); state.MixHash(prologue); this.initiator = initiator; this.turnToWrite = initiator; this.s = s.IsEmpty ? null : dh.GenerateKeyPair(s); this.rs = rs.IsEmpty ? null : rs.ToArray(); ProcessPreMessages(protocol.HandshakePattern); ProcessPreSharedKeys(protocol, psks); isOneWay = messagePatterns.Count == 1; isPsk = protocol.Modifiers != PatternModifiers.None; }
public void Fallback(Protocol protocol, ProtocolConfig config) { ThrowIfDisposed(); Exceptions.ThrowIfNull(protocol, nameof(protocol)); Exceptions.ThrowIfNull(config, nameof(config)); if (protocol.HandshakePattern != HandshakePattern.XX || protocol.Modifiers != PatternModifiers.Fallback) { throw new ArgumentException("The only fallback pattern currently supported is XXfallback."); } if (config.LocalStatic == null) { throw new ArgumentException("Local static private key is required for the XXfallback pattern."); } if (initiator == Role.Bob) { throw new InvalidOperationException("Fallback cannot be applied to a Bob-initiated pattern."); } if (messagePatterns.Count + 1 != this.protocol.HandshakePattern.Patterns.Count()) { throw new InvalidOperationException("Fallback can only be applied after the first handshake message."); } this.protocol = null; initiator = Role.Bob; turnToWrite = role == Role.Bob; s = dh.GenerateKeyPair(config.LocalStatic); rs = null; isPsk = false; isOneWay = false; while (psks.Count > 0) { var psk = psks.Dequeue(); Utilities.ZeroMemory(psk); } state.Dispose(); state = new SymmetricState <CipherType, DhType, HashType>(protocol.Name); state.MixHash(config.Prologue); if (role == Role.Alice) { Debug.Assert(e != null && re == null); state.MixHash(e.PublicKey); } else { Debug.Assert(e == null && re != null); state.MixHash(re); } messagePatterns.Clear(); foreach (var pattern in protocol.HandshakePattern.Patterns.Skip(1)) { messagePatterns.Enqueue(pattern); } }
public HandshakeState( Protocol protocol, bool initiator, ReadOnlySpan <byte> prologue, ReadOnlySpan <byte> s, ReadOnlySpan <byte> rs, IEnumerable <byte[]> psks) { Debug.Assert(psks != null); if (!s.IsEmpty && s.Length != dh.DhLen) { throw new ArgumentException("Invalid local static private key.", nameof(s)); } if (!rs.IsEmpty && rs.Length != dh.DhLen) { throw new ArgumentException("Invalid remote static public key.", nameof(rs)); } if (s.IsEmpty && protocol.HandshakePattern.LocalStaticRequired(initiator)) { throw new ArgumentException("Local static private key required, but not provided.", nameof(s)); } if (!s.IsEmpty && !protocol.HandshakePattern.LocalStaticRequired(initiator)) { throw new ArgumentException("Local static private key provided, but not required.", nameof(s)); } if (rs.IsEmpty && protocol.HandshakePattern.RemoteStaticRequired(initiator)) { throw new ArgumentException("Remote static public key required, but not provided.", nameof(rs)); } if (!rs.IsEmpty && !protocol.HandshakePattern.RemoteStaticRequired(initiator)) { throw new ArgumentException("Remote static public key provided, but not required.", nameof(rs)); } if ((protocol.Modifiers & PatternModifiers.Fallback) != 0) { throw new ArgumentException($"Fallback modifier can only be applied by calling the {nameof(Fallback)} method."); } state = new SymmetricState <CipherType, DhType, HashType>(protocol.Name); state.MixHash(prologue); this.protocol = protocol; this.role = initiator ? Role.Alice : Role.Bob; this.initiator = Role.Alice; this.turnToWrite = initiator; this.s = s.IsEmpty ? null : dh.GenerateKeyPair(s); this.rs = rs.IsEmpty ? null : rs.ToArray(); ProcessPreMessages(protocol.HandshakePattern); ProcessPreSharedKeys(protocol, psks); var pskModifiers = PatternModifiers.Psk0 | PatternModifiers.Psk1 | PatternModifiers.Psk2 | PatternModifiers.Psk3; isPsk = (protocol.Modifiers & pskModifiers) != 0; isOneWay = messagePatterns.Count == 1; }