Exemple #1
0
        /// <summary>
        /// decodes the packet, verifies match to REQ
        /// </summary>
        /// <param name="reader">is positioned after first byte = packet type</param>
        public static FailurePacket DecodeAndOptionallyVerify(byte[] failureUdpData, RequestP2pSequenceNumber16 reqP2pSeq16)
        {
            var reader  = BinaryProcedures.CreateBinaryReader(failureUdpData, 1);
            var failure = new FailurePacket();

            failure.DecodedUdpPayloadData = failureUdpData;
            failure.Flags = reader.ReadByte();
            if ((failure.Flags & Flag_EPtoA) == 0)
            {
                failure.NeighborToken32 = NeighborToken32.Decode(reader);
            }
            if ((failure.Flags & FlagsMask_MustBeZero) != 0)
            {
                throw new NotImplementedException();
            }
            failure.ReqP2pSeq16 = RequestP2pSequenceNumber16.Decode(reader);
            failure.AssertMatchToReq(reqP2pSeq16);
            failure.ResponseCode = (ResponseOrFailureCode)reader.ReadByte();

            if ((failure.Flags & Flag_EPtoA) == 0)
            {
                failure.NeighborHMAC = HMAC.Decode(reader);
            }

            return(failure);
        }
Exemple #2
0
        public static InviteConfirmationPacket Decode(byte[] udpData)
        {
            var r = new InviteConfirmationPacket();

            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);

            r.ReqTimestamp32S                = reader.ReadUInt32();
            r.RequesterRegistrationId        = RegistrationId.Decode(reader);
            r.ResponderRegistrationId        = RegistrationId.Decode(reader);
            r.ResponderRegistrationSignature = RegistrationSignature.Decode(reader);
            r.ReqP2pSeq16 = RequestP2pSequenceNumber16.Decode(reader);

            r.NeighborHMAC = HMAC.Decode(reader);

            return(r);
        }
Exemple #3
0
 void AssertMatchToReq(RequestP2pSequenceNumber16 reqP2pSeq16)
 {
     if (reqP2pSeq16.Equals(this.ReqP2pSeq16) == false)
     {
         throw new UnmatchedFieldsException();
     }
 }
Exemple #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);
        }
Exemple #5
0
        public static InviteAck1Packet Decode(byte[] udpData)
        {
            var r = new InviteAck1Packet();

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

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

            r.NeighborToken32 = NeighborToken32.Decode(reader);

            r.ReqTimestamp32S         = reader.ReadUInt32();
            r.RequesterRegistrationId = RegistrationId.Decode(reader);
            r.ResponderRegistrationId = RegistrationId.Decode(reader);
            r.ResponderEcdhePublicKey = EcdhPublicKey.Decode(reader);
            r.ToResponderSessionDescriptionEncrypted = BinaryProcedures.DecodeByteArray65536(reader);
            r.ResponderRegistrationSignature         = RegistrationSignature.Decode(reader);
            r.ReqP2pSeq16 = RequestP2pSequenceNumber16.Decode(reader);

            r.NeighborHMAC = HMAC.Decode(reader);

            return(r);
        }
Exemple #6
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);
        }
Exemple #7
0
        public static RequestP2pSequenceNumber16 Decode(BinaryReader reader)
        {
            var r = new RequestP2pSequenceNumber16();

            r.Seq16 = reader.ReadUInt16();
            return(r);
        }
        public static RegisterConfirmationPacket DecodeAndOptionallyVerify(byte[] regCfmUdpPayload, RegisterRequestPacket reqNullable, ConnectionToNeighbor newConnectionToRequesterAtResponderNullable)
        {
            var reader = BinaryProcedures.CreateBinaryReader(regCfmUdpPayload, 1);

            var cfm = new RegisterConfirmationPacket();

            cfm.DecodedUdpPayloadData = regCfmUdpPayload;

            cfm.Flags = reader.ReadByte();
            if ((cfm.Flags & FlagsMask_MustBeZero) != 0)
            {
                throw new NotImplementedException();
            }
            if ((cfm.Flags & Flag_AtoEP) == 0)
            {
                cfm.NeighborToken32 = NeighborToken32.Decode(reader);
            }

            cfm.ReqTimestamp64          = reader.ReadInt64();
            cfm.RequesterRegistrationId = RegistrationId.Decode(reader);
            if (reqNullable != null)
            {
                cfm.AssertMatchToRegisterReq(reqNullable);
            }

            if (newConnectionToRequesterAtResponderNullable != null)
            {
                cfm.ResponderRegistrationConfirmationSignature = RegistrationSignature.DecodeAndVerify(reader, newConnectionToRequesterAtResponderNullable.Engine.CryptoLibrary,
                                                                                                       w => newConnectionToRequesterAtResponderNullable.GetResponderRegistrationConfirmationSignatureFields(w),
                                                                                                       newConnectionToRequesterAtResponderNullable.LocalDrpPeer.Configuration.LocalPeerRegistrationId
                                                                                                       );
                cfm.RequesterRegistrationConfirmationSignature = RegistrationSignature.DecodeAndVerify(reader, newConnectionToRequesterAtResponderNullable.Engine.CryptoLibrary,
                                                                                                       w => newConnectionToRequesterAtResponderNullable.GetRequesterRegistrationConfirmationSignatureFields(w, cfm.ResponderRegistrationConfirmationSignature),
                                                                                                       newConnectionToRequesterAtResponderNullable.RemoteRegistrationId
                                                                                                       );
            }
            else
            {
                cfm.ResponderRegistrationConfirmationSignature = RegistrationSignature.Decode(reader);
                cfm.RequesterRegistrationConfirmationSignature = RegistrationSignature.Decode(reader);
            }

            cfm.ReqP2pSeq16 = RequestP2pSequenceNumber16.Decode(reader);
            if ((cfm.Flags & Flag_AtoEP) == 0)
            {
                cfm.NeighborHMAC = HMAC.Decode(reader);
            }

            return(cfm);
        }
Exemple #9
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);
        }
Exemple #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());
        }
Exemple #11
0
        public NeighborPeerAckPacket(byte[] nextHopResponsePacketData)
        {
            var reader = PacketProcedures.CreateBinaryReader(nextHopResponsePacketData, 1);

            ReqP2pSeq16 = RequestP2pSequenceNumber16.Decode(reader);
            var flags = reader.ReadByte();

            if ((flags & FlagsMask_MustBeZero) != 0)
            {
                throw new NotImplementedException();
            }
            if ((flags & Flag_EPtoA) == 0)
            {
                NeighborToken32 = NeighborToken32.Decode(reader);
            }
            ResponseCode = (ResponseOrFailureCode)reader.ReadByte();
            if ((flags & Flag_EPtoA) == 0)
            {
                NeighborHMAC = HMAC.Decode(reader);
            }
        }
Exemple #12
0
        /// <param name="newConnectionAtResponderToRequesterNullable">
        /// direct P2P stream from N to A
        /// if newConnectionAtResponderToRequesterNullable is specified, the procedure
        /// verifies RequesterHMAC, decrypts endpoint of A (ToRequesterTxParametersEncrypted), initializes P2P stream
        /// </param>
        public static RegisterAck2Packet Decode_OptionallyVerify_InitializeP2pStreamAtResponder(Logger logger, byte[] registerAckPacketData,
                                                                                                RegisterRequestPacket reqNullable,
                                                                                                RegisterAck1Packet ack1Nullable,
                                                                                                ConnectionToNeighbor newConnectionAtResponderToRequesterNullable
                                                                                                )
        {
            var reader = BinaryProcedures.CreateBinaryReader(registerAckPacketData, 1);

            var ack = new RegisterAck2Packet();

            ack.DecodedUdpPayloadData = registerAckPacketData;
            ack.Flags = reader.ReadByte();
            if ((ack.Flags & FlagsMask_MustBeZero) != 0)
            {
                throw new NotImplementedException();
            }
            if ((ack.Flags & Flag_AtoEP) == 0)
            {
                ack.NeighborToken32 = NeighborToken32.Decode(reader);
            }

            ack.ReqTimestamp64          = reader.ReadInt64();
            ack.RequesterRegistrationId = RegistrationId.Decode(reader);
            if (reqNullable != null)
            {
                ack.AssertMatchToSyn(reqNullable);
            }

            ack.ToRequesterTxParametersEncrypted = reader.ReadBytes(ToRequesterTxParametersEncryptedLength);
            if (newConnectionAtResponderToRequesterNullable != null)
            {
                newConnectionAtResponderToRequesterNullable.Decrypt_ack2_ToRequesterTxParametersEncrypted_AtResponder_InitializeP2pStream(logger, reqNullable, ack1Nullable, ack);
            }

            ack.RequesterSignature = RegistrationSignature.Decode(reader);
            if (newConnectionAtResponderToRequesterNullable != null)
            {
                if (reqNullable == null)
                {
                    throw new ArgumentException();
                }
                if (ack1Nullable == null)
                {
                    throw new ArgumentException();
                }
                if (!ack.RequesterSignature.Verify(newConnectionAtResponderToRequesterNullable.Engine.CryptoLibrary,
                                                   w =>
                {
                    reqNullable.GetSharedSignedFields(w, true);
                    ack1Nullable.GetSharedSignedFields(w, true, true);
                    ack.GetSharedSignedFields(w, false, true);
                },
                                                   reqNullable.RequesterRegistrationId))
                {
                    throw new BadSignatureException("invalid REGISTER ACK2 RequesterSignature 6106");
                }
            }

            ack.ReqP2pSeq16 = RequestP2pSequenceNumber16.Decode(reader);

            if ((ack.Flags & Flag_AtoEP) == 0)
            {
                ack.NeighborHMAC = HMAC.Decode(reader); // is verified by Filter
            }

            return(ack);
        }
Exemple #13
0
 static void EncodeHeader(BinaryWriter w, RequestP2pSequenceNumber16 reqP2pSeq16)
 {
     w.Write((byte)PacketTypes.NeighborPeerAck);
     reqP2pSeq16.Encode(w);
 }
Exemple #14
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);
        }
Exemple #15
0
        /// <summary>
        /// decodes the packet, decrypts ToNeighborTxParametersEncrypted, verifies NeighborSignature, verifies match to register REQ
        /// </summary>
        /// <param name="newConnectionToNeighborAtRequesterNullable">if not null (at requester) - this procedure verifies ResponderSignature</param>
        /// <param name="reader">is positioned after first byte = packet type</param>
        public static RegisterAck1Packet DecodeAndOptionallyVerify(Logger logger, byte[] ack1UdpData, RegisterRequestPacket reqNullable,
                                                                   ConnectionToNeighbor newConnectionToNeighborAtRequesterNullable)
        {
            var reader = BinaryProcedures.CreateBinaryReader(ack1UdpData, 1);
            var ack1   = new RegisterAck1Packet();

            ack1.DecodedUdpPayloadData = ack1UdpData;
            ack1.Flags = reader.ReadByte();
            if ((ack1.Flags & Flag_EPtoA) == 0)
            {
                ack1.NeighborToken32 = NeighborToken32.Decode(reader);
            }
            if ((ack1.Flags & FlagsMask_MustBeZero) != 0)
            {
                throw new NotImplementedException();
            }
            ack1.RequesterRegistrationId          = RegistrationId.Decode(reader);
            ack1.ReqTimestamp64                   = reader.ReadInt64();
            ack1.ResponderEcdhePublicKey          = EcdhPublicKey.Decode(reader);
            ack1.ToResponderTxParametersEncrypted = reader.ReadBytes(ToResponderTxParametersEncryptedLength);
            ack1.ResponderRegistrationId          = RegistrationId.Decode(reader);

            if (newConnectionToNeighborAtRequesterNullable != null)
            {
                if (reqNullable == null)
                {
                    throw new ArgumentException();
                }
                ack1.ResponderSignature = RegistrationSignature.DecodeAndVerify(
                    reader, newConnectionToNeighborAtRequesterNullable.Engine.CryptoLibrary,
                    w =>
                {
                    reqNullable.GetSharedSignedFields(w, true);
                    ack1.GetSharedSignedFields(w, false, true);
                },
                    ack1.ResponderRegistrationId);
            }
            else
            { // at proxy we don't verify responder's signature, to avoid high spending of resources
                ack1.ResponderSignature = RegistrationSignature.Decode(reader);
            }

            if (reqNullable != null)
            {
                ack1.AssertMatchToRegisterReq(reqNullable);
                if (newConnectionToNeighborAtRequesterNullable != null)
                {
                    newConnectionToNeighborAtRequesterNullable.Decrypt_ack1_ToResponderTxParametersEncrypted_AtRequester_DeriveSharedDhSecret(logger, reqNullable, ack1);
                }
            }

            if ((ack1.Flags & Flag_EPtoA) != 0)
            {
                ack1.RequesterEndpoint = BinaryProcedures.DecodeIPEndPoint(reader);
            }
            else
            {
                ack1.ReqP2pSeq16  = RequestP2pSequenceNumber16.Decode(reader);
                ack1.NeighborHMAC = HMAC.Decode(reader);
            }

            return(ack1);
        }