Пример #1
0
        /// <param name="connectionToNeighbor">is null for A->EP mode</param>
        public byte[] Encode_OptionallySignNeighborHMAC(ConnectionToNeighbor connectionToNeighborNullable)
        {
            BinaryProcedures.CreateBinaryWriter(out var ms, out var writer);

            writer.Write((byte)PacketTypes.RegisterAck2);
            byte flags = 0;

            if (connectionToNeighborNullable == null)
            {
                flags |= Flag_AtoEP;
            }
            writer.Write(flags);

            if (connectionToNeighborNullable != null)
            {
                NeighborToken32 = connectionToNeighborNullable.RemoteNeighborToken32;
                NeighborToken32.Encode(writer);
            }

            GetSharedSignedFields(writer, true, true);

            ReqP2pSeq16.Encode(writer);

            if (connectionToNeighborNullable != null)
            {
                connectionToNeighborNullable.GetNeighborHMAC(this.GetSignedFieldsForNeighborHMAC).Encode(writer);
            }

            return(ms.ToArray());
        }
Пример #2
0
        /// <param name="waitNpaFromNeighborNullable">is used to verify NPACK.NeighborHMAC</param>
        public static LowLevelUdpResponseScanner GetScanner(RequestP2pSequenceNumber16 reqP2pSeq16, ConnectionToNeighbor waitNpaFromNeighborNullable = null,
                                                            Action <BinaryWriter> npaRequestFieldsForNeighborHmacNullable = null)
        {
            PacketProcedures.CreateBinaryWriter(out var ms, out var w);
            EncodeHeader(w, reqP2pSeq16);
            var r = new LowLevelUdpResponseScanner {
                ResponseFirstBytes = ms.ToArray()
            };

            if (waitNpaFromNeighborNullable != null)
            {
                if (npaRequestFieldsForNeighborHmacNullable == null)
                {
                    throw new ArgumentNullException();
                }
                r.OptionalFilter = (responseData) =>
                {
                    if (waitNpaFromNeighborNullable.IsDisposed)
                    {
                        return(false);
                    }
                    var npack = new NeighborPeerAckPacket(responseData);
                    if (npack.NeighborHMAC == null)
                    {
                        return(false);
                    }
                    if (!npack.NeighborHMAC.Equals(waitNpaFromNeighborNullable.GetNeighborHMAC(w2 => npack.GetSignedFieldsForNeighborHMAC(w2, npaRequestFieldsForNeighborHmacNullable))))
                    {
                        return(false);
                    }
                    return(true);
                };
            }
            return(r);
        }
Пример #3
0
        /// <param name="reqReceivedFromInP2pMode">is not null for packets between registered peers</param>
        public byte[] Encode_OpionallySignNeighborHMAC(ConnectionToNeighbor reqReceivedFromInP2pMode)
        {
            BinaryProcedures.CreateBinaryWriter(out var ms, out var writer);

            writer.Write((byte)PacketTypes.Failure);
            byte flags = 0;

            if (reqReceivedFromInP2pMode == null)
            {
                flags |= Flag_EPtoA;
            }
            writer.Write(flags);
            if (reqReceivedFromInP2pMode != null)
            {
                NeighborToken32 = reqReceivedFromInP2pMode.RemoteNeighborToken32;
                NeighborToken32.Encode(writer);
            }

            ReqP2pSeq16.Encode(writer);
            writer.Write((byte)ResponseCode);

            if (reqReceivedFromInP2pMode != null)
            {
                this.NeighborHMAC = reqReceivedFromInP2pMode.GetNeighborHMAC(this.GetSignedFieldsForNeighborHMAC);
                this.NeighborHMAC.Encode(writer);
            }

            return(ms.ToArray());
        }
Пример #4
0
        public static InviteRequestPacket Decode_VerifyNeighborHMAC(byte[] udpData, ConnectionToNeighbor receivedFromNeighbor)
        {
            var r = new InviteRequestPacket();

            r.DecodedUdpPayloadData = udpData;
            var reader = PacketProcedures.CreateBinaryReader(udpData, 1);
            var flags  = reader.ReadByte();

            if ((flags & FlagsMask_MustBeZero) != 0)
            {
                throw new NotImplementedException();
            }

            r.NeighborToken32 = NeighborToken32.Decode(reader);
            if (receivedFromNeighbor.LocalNeighborToken32.Equals(r.NeighborToken32) == false)
            {
                throw new UnmatchedFieldsException();
            }

            r.ReqTimestamp32S                = reader.ReadUInt32();
            r.RequesterRegistrationId        = RegistrationId.Decode(reader);
            r.ResponderRegistrationId        = RegistrationId.Decode(reader);
            r.RequesterEcdhePublicKey        = EcdhPublicKey.Decode(reader);
            r.RequesterRegistrationSignature = RegistrationSignature.Decode(reader);
            r.NumberOfHopsRemaining          = reader.ReadByte();
            r.ReqP2pSeq16 = RequestP2pSequenceNumber16.Decode(reader);

            r.NeighborHMAC = HMAC.Decode(reader);
            if (r.NeighborHMAC.Equals(receivedFromNeighbor.GetNeighborHMAC(r.GetSignedFieldsForNeighborHMAC)) == false)
            {
                throw new BadSignatureException("invalid INVITE REQ NeighborHMAC 5902");
            }

            return(r);
        }
Пример #5
0
        /// <param name="reqReceivedFromInP2pMode">is not null for packets between registered peers</param>
        public byte[] Encode_OpionallySignNeighborHMAC(ConnectionToNeighbor reqReceivedFromInP2pMode)
        {
            BinaryProcedures.CreateBinaryWriter(out var ms, out var writer);

            writer.Write((byte)PacketTypes.RegisterAck1);
            byte flags = 0;

            if (reqReceivedFromInP2pMode == null)
            {
                flags |= Flag_EPtoA;
            }
            writer.Write(flags);
            if (reqReceivedFromInP2pMode != null)
            {
                NeighborToken32 = reqReceivedFromInP2pMode.RemoteNeighborToken32;
                NeighborToken32.Encode(writer);
            }

            GetSharedSignedFields(writer, true, true);

            if (reqReceivedFromInP2pMode != null)
            {
                ReqP2pSeq16.Encode(writer);
                this.NeighborHMAC = reqReceivedFromInP2pMode.GetNeighborHMAC(this.GetSignedFieldsForNeighborHMAC);
                this.NeighborHMAC.Encode(writer);
            }
            else
            {
                BinaryProcedures.EncodeIPEndPoint(writer, RequesterEndpoint);
            }

            return(ms.ToArray());
        }
Пример #6
0
        /// <param name="connectionToNeighbor">is not null for packets between registered peers</param>
        public byte[] Encode_OptionallySignNeighborHMAC(ConnectionToNeighbor connectionToNeighbor)
        {
            BinaryProcedures.CreateBinaryWriter(out var ms, out var writer);

            writer.Write((byte)PacketTypes.RegisterConfirmation);
            Flags = 0;
            if (connectionToNeighbor == null)
            {
                Flags |= Flag_AtoEP;
            }
            writer.Write(Flags);
            if (connectionToNeighbor != null)
            {
                NeighborToken32 = connectionToNeighbor.RemoteNeighborToken32;
                NeighborToken32.Encode(writer);
            }

            writer.Write(ReqTimestamp64);
            RequesterRegistrationId.Encode(writer);

            ResponderRegistrationConfirmationSignature.Encode(writer);
            RequesterRegistrationConfirmationSignature.Encode(writer);

            ReqP2pSeq16.Encode(writer);
            if (connectionToNeighbor != null)
            {
                this.NeighborHMAC = connectionToNeighbor.GetNeighborHMAC(this.GetSignedFieldsForNeighborHMAC);
                this.NeighborHMAC.Encode(writer);
            }


            return(ms.ToArray());
        }
Пример #7
0
        /// <summary>
        /// creates a scanner that finds ACK1 that matches to REQ
        /// </summary>
        /// <param name="connectionToNeighborNullable">
        /// peer that responds to REQ with ACK1
        /// if not null - the scanner will verify ACK1.NeighborHMAC
        /// </param>
        public static LowLevelUdpResponseScanner GetScanner(Logger logger, RequestP2pSequenceNumber16 reqP2pSeq16, ConnectionToNeighbor connectionToNeighborNullable = null)
        {
            if (logger.WriteToLog_detail_enabled)
            {
                logger.WriteToLog_detail($">> FailurePacket.GetScanner() reqP2pSeq16={reqP2pSeq16}");
            }
            BinaryProcedures.CreateBinaryWriter(out var ms, out var w);
            w.Write((byte)PacketTypes.Failure);
            w.Write((byte)0);
            if (connectionToNeighborNullable != null)
            {
                connectionToNeighborNullable.LocalNeighborToken32.Encode(w);
            }

            reqP2pSeq16.Encode(w);

            var r = new LowLevelUdpResponseScanner
            {
                ResponseFirstBytes   = ms.ToArray(),
                IgnoredByteAtOffset1 = 1 // ignore flags
            };

            if (connectionToNeighborNullable != null)
            {
                r.OptionalFilter = (responseData) =>
                {
                    if (logger.WriteToLog_detail_enabled)
                    {
                        logger.WriteToLog_detail($"filtering FAILURE @scanner: hash={MiscProcedures.GetArrayHashCodeString(responseData)}");
                    }
                    if (connectionToNeighborNullable.IsDisposed)
                    {
                        logger.WriteToLog_needsAttention("ignoring FAILURE: connection is disposed");
                        return(false);
                    }
                    var failure = DecodeAndOptionallyVerify(responseData, reqP2pSeq16);
                    if (failure.NeighborHMAC.Equals(connectionToNeighborNullable.GetNeighborHMAC(failure.GetSignedFieldsForNeighborHMAC)) == false)
                    {
                        logger.WriteToLog_attacks("ignoring FAILURE: received HMAC is invalid");
                        return(false);
                    }
                    return(true);
                };
            }
            return(r);
        }
Пример #8
0
        /// <param name="connectionToNeighborNullable">
        /// peer that sends ACK2
        /// if not null - the scanner will verify ACK2.NeighborHMAC
        /// </param>
        public static LowLevelUdpResponseScanner GetScanner(Logger logger, ConnectionToNeighbor connectionToNeighborNullable, RegisterRequestPacket req)
        {
            BinaryProcedures.CreateBinaryWriter(out var ms, out var writer);

            writer.Write((byte)PacketTypes.RegisterAck2);

            writer.Write((byte)0); // ignored flags

            if (connectionToNeighborNullable != null)
            {
                connectionToNeighborNullable.LocalNeighborToken32.Encode(writer);
            }

            writer.Write(req.ReqTimestamp64);
            req.RequesterRegistrationId.Encode(writer);

            var r = new LowLevelUdpResponseScanner
            {
                IgnoredByteAtOffset1 = 1,
                ResponseFirstBytes   = ms.ToArray()
            };

            if (connectionToNeighborNullable != null)
            {
                r.OptionalFilter = (responseData) =>
                {
                    if (connectionToNeighborNullable.IsDisposed)
                    {
                        logger.WriteToLog_needsAttention("ignoring ACK2: connection is disposed");
                        return(false);
                    }
                    var ack2 = Decode_OptionallyVerify_InitializeP2pStreamAtResponder(logger, responseData, null, null, null);
                    if (ack2.NeighborHMAC.Equals(connectionToNeighborNullable.GetNeighborHMAC(ack2.GetSignedFieldsForNeighborHMAC)) == false)
                    {
                        logger.WriteToLog_attacks("ignoring ACK2: received NeighborHMAC is invalid");
                        return(false);
                    }
                    return(true);
                };
            }


            return(r);
        }
Пример #9
0
        /// <param name="connectionToNeighborNullable">is not null for packets between registered peers. if set, the procedure sets NeighborToken32 and NeighborHMAC</param>
        public byte[] Encode_OptionallySignNeighborHMAC(ConnectionToNeighbor connectionToNeighborNullable)
        {
            PacketProcedures.CreateBinaryWriter(out var ms, out var writer);

            writer.Write((byte)PacketTypes.RegisterReq);
            byte flags = 0;

            if (connectionToNeighborNullable == null)
            {
                flags |= Flag_AtoEP;
            }
            if (DirectionVectorNullable != null)
            {
                flags |= Flag_DirectionVectorExists;
            }

            writer.Write(flags);
            if (connectionToNeighborNullable != null)
            {
                NeighborToken32 = connectionToNeighborNullable.RemoteNeighborToken32;
                NeighborToken32.Encode(writer);
            }

            GetSharedSignedFields(writer, true);

            if (connectionToNeighborNullable == null)
            {
                if (ProofOfWork2.Length != 64)
                {
                    throw new ArgumentException();
                }
                writer.Write(ProofOfWork2);
            }
            writer.Write(NumberOfHopsRemaining);
            writer.Write(NumberOfRandomHopsRemaining);
            ReqP2pSeq16.Encode(writer);
            if (connectionToNeighborNullable != null)
            {
                NeighborHMAC = connectionToNeighborNullable.GetNeighborHMAC(this.GetSignedFieldsForNeighborHMAC);
                NeighborHMAC.Encode(writer);
            }

            return(ms.ToArray());
        }
Пример #10
0
        public byte[] Encode_SetP2pFields(ConnectionToNeighbor transmitToNeighbor)
        {
            PacketProcedures.CreateBinaryWriter(out var ms, out var w);
            w.Write((byte)PacketTypes.InviteReq);
            byte flags = 0;

            w.Write(flags);

            ReqP2pSeq16     = transmitToNeighbor.GetNewRequestP2pSeq16_P2P();
            NeighborToken32 = transmitToNeighbor.RemoteNeighborToken32;
            NeighborToken32.Encode(w);

            GetSignedFieldsForNeighborHMAC(w);

            NeighborHMAC = transmitToNeighbor.GetNeighborHMAC(GetSignedFieldsForNeighborHMAC);
            NeighborHMAC.Encode(w);

            return(ms.ToArray());
        }
Пример #11
0
        /// <summary>
        /// creates a scanner that finds CFM that matches to REQ
        /// the scanner will verify CFM.NeighborHMAC
        /// </summary>
        /// <param name="connectionToNeighbor">
        /// peer that responds with CFM
        /// </param>
        public static LowLevelUdpResponseScanner GetScanner(Logger logger, InviteRequestPacket req, ConnectionToNeighbor connectionToNeighbor)
        {
            PacketProcedures.CreateBinaryWriter(out var ms, out var w);
            w.Write((byte)PacketTypes.InviteCfm);
            w.Write((byte)0); // flags

            connectionToNeighbor.LocalNeighborToken32.Encode(w);

            w.Write(req.ReqTimestamp32S);
            req.RequesterRegistrationId.Encode(w);
            req.ResponderRegistrationId.Encode(w);

            var r = new LowLevelUdpResponseScanner
            {
                ResponseFirstBytes   = ms.ToArray(),
                IgnoredByteAtOffset1 = 1 // ignore flags
            };

            r.OptionalFilter = (responseData) =>
            {
                if (connectionToNeighbor.IsDisposed)
                {
                    logger.WriteToLog_needsAttention("ignoring CFM: connection is disposed");
                    return(false);
                }
                var cfm = Decode(responseData);
                if (cfm.NeighborHMAC.Equals(connectionToNeighbor.GetNeighborHMAC(cfm.GetSignedFieldsForNeighborHMAC)) == false)
                {
                    logger.WriteToLog_attacks("ignoring CFM: received NeighborHMAC is invalid");
                    return(false);
                }
                return(true);
            };

            return(r);
        }
Пример #12
0
        /// <summary>
        /// when REQ is received from neighbor, verifies senderHMAC and NeighborToken32
        /// </summary>
        /// <param name="receivedFromNeighborNullable">is NULL when decoding REQ from A at EP</param>
        public static RegisterRequestPacket Decode_OptionallyVerifyNeighborHMAC(byte[] udpData, ConnectionToNeighbor receivedFromNeighborNullable, int numberOfDimensions)
        {
            var r = new RegisterRequestPacket();

            r.DecodedUdpPayloadData = udpData;
            var reader = PacketProcedures.CreateBinaryReader(udpData, 1);

            var flags = reader.ReadByte();

            if ((flags & FlagsMask_MustBeZero) != 0)
            {
                throw new NotImplementedException();
            }
            if ((flags & Flag_AtoEP) == 0)
            {
                if (receivedFromNeighborNullable == null)
                {
                    throw new UnmatchedFieldsException();
                }
                r.NeighborToken32 = NeighborToken32.Decode(reader);
                if (receivedFromNeighborNullable.LocalNeighborToken32.Equals(r.NeighborToken32) == false)
                {
                    throw new UnmatchedFieldsException();
                }
            }
            else
            {
                if (receivedFromNeighborNullable != null)
                {
                    throw new UnmatchedFieldsException();
                }
            }

            r.RequesterRegistrationId         = RegistrationId.Decode(reader);
            r.RequesterNeighborsBusySectorIds = reader.ReadUInt16();
            r.RequesterEcdhePublicKey         = EcdhPublicKey.Decode(reader);
            r.ReqTimestamp64            = reader.ReadInt64();
            r.MinimalDistanceToNeighbor = reader.ReadUInt32();

            if ((flags & Flag_DirectionVectorExists) != 0)
            {
                r.DirectionVectorNullable = new sbyte[numberOfDimensions];
                for (int i = 0; i < numberOfDimensions; i++)
                {
                    r.DirectionVectorNullable[i] = reader.ReadSByte();
                }
            }

            r.EpEndpoint         = PacketProcedures.DecodeIPEndPoint(reader);
            r.RequesterSignature = RegistrationSignature.Decode(reader);

            if ((flags & Flag_AtoEP) != 0)
            {
                r.ProofOfWork2 = reader.ReadBytes(64);
            }
            r.NumberOfHopsRemaining       = reader.ReadByte();
            r.NumberOfRandomHopsRemaining = reader.ReadByte();
            r.ReqP2pSeq16 = RequestP2pSequenceNumber16.Decode(reader);
            if ((flags & Flag_AtoEP) == 0)
            {
                r.NeighborHMAC = HMAC.Decode(reader);
                if (r.NeighborHMAC.Equals(receivedFromNeighborNullable.GetNeighborHMAC(r.GetSignedFieldsForNeighborHMAC)) == false)
                {
                    throw new BadSignatureException("invalid REGISTER REQ NeighborHMAC 1573");
                }
            }

            return(r);
        }