Esempio n. 1
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);
        }
Esempio n. 2
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);
        }
 public static void GetResponderRegistrationConfirmationSignatureFields(BinaryWriter writer, RegisterRequestPacket req, RegisterAck1Packet ack1, RegisterAck2Packet ack2)
 {
     req.GetSharedSignedFields(writer, true);
     ack1.GetSharedSignedFields(writer, true, true);
     ack2.GetSharedSignedFields(writer, true, true);
     writer.Write(ResponderRegistrationConfirmationSignature_MagicNumber);
 }