<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "Logging.h"
#include "MozQuic.h"
#include "MozQuicInternal.h"
#include "NSSHelper.h"
#include "Sender.h"
#include "Streams.h"

#include <assert.h>
#include <stdlib.h>
#include <unistd.h>

namespace mozquic  {

static const uint32_t kMinClientInitial = 1200;
extern std::unordered_map<std::string, uint32_t> mVNHash;

#define HandshakeLog1(...) Log::sDoLog(Log::HANDSHAKE, 1, this, __VA_ARGS__);
#define HandshakeLog2(...) Log::sDoLog(Log::HANDSHAKE, 2, this, __VA_ARGS__);
#define HandshakeLog3(...) Log::sDoLog(Log::HANDSHAKE, 3, this, __VA_ARGS__);
#define HandshakeLog4(...) Log::sDoLog(Log::HANDSHAKE, 4, this, __VA_ARGS__);
#define HandshakeLog5(...) Log::sDoLog(Log::HANDSHAKE, 5, this, __VA_ARGS__);
#define HandshakeLog6(...) Log::sDoLog(Log::HANDSHAKE, 6, this, __VA_ARGS__);
#define HandshakeLog7(...) Log::sDoLog(Log::HANDSHAKE, 7, this, __VA_ARGS__);
#define HandshakeLog8(...) Log::sDoLog(Log::HANDSHAKE, 8, this, __VA_ARGS__);
#define HandshakeLog9(...) Log::sDoLog(Log::HANDSHAKE, 9, this, __VA_ARGS__);
#define HandshakeLog10(...) Log::sDoLog(Log::HANDSHAKE, 10, this, __VA_ARGS__);

bool
MozQuic::IntegrityCheck(unsigned char *pkt, uint32_t pktSize, uint32_t headerSize,
                        CID handshakeCID, uint64_t packetNumber, unsigned char *outbuf, uint32_t &outSize)
{
  assert (pkt[0] & 0x80); // long form
  assert (((pkt[0] & 0x7f) == PACKET_TYPE_INITIAL) ||
          ((pkt[0] & 0x7f) == PACKET_TYPE_RETRY) ||
          ((pkt[0] & 0x7f) == PACKET_TYPE_HANDSHAKE));

  uint32_t rv;
  if (mNSSHelper) {
    rv = mNSSHelper->DecryptHandshake(pkt, headerSize, pkt + headerSize, pktSize - headerSize, packetNumber, handshakeCID,
                                      outbuf + headerSize, kMozQuicMSS - headerSize, outSize);
  } else {
    // need longheader.mdestcid
    assert ((pkt[0] & 0x7f) == PACKET_TYPE_INITIAL || (pkt[0] & 0x7f) == PACKET_TYPE_RETRY);
    rv = NSSHelper::staticDecryptHandshake(pkt, headerSize, pkt + headerSize, pktSize - headerSize, packetNumber, handshakeCID,
                                           outbuf + headerSize, kMozQuicMSS - headerSize, outSize);
  }
    
  if (rv != MOZQUIC_OK) {
    ConnectionLog1("Decrypt handshake failed packet %lX integrity error\n", packetNumber);
    return false;
  }
  memcpy(outbuf, pkt, headerSize);
  outSize += headerSize;
  ConnectionLog5("Decrypt handshake (packetNumber=%lX) ok sz=%d\n", packetNumber, outSize);
  return true;
}

uint32_t
MozQuic::FlushStream0(bool forceAck)
{
  mStreamState->FlowControlPromotion();

  if (mStreamState->mConnUnWritten.empty() && !forceAck) {
    return MOZQUIC_OK;
  }

  assert(mMTU <= kMaxMTU);
  unsigned char pkt[kMaxMTU];
  unsigned char *endpkt = pkt + mMTU;
  unsigned char *framePtr = pkt;
  uint32_t tmp32;
  uint32_t rv;
  uint32_t used;

  // section 4.1 of transport
  pkt[0] = 0x80;
  framePtr++;
  if (ServerState()) {
    pkt[0] |=
      (mConnectionState == SERVER_STATE_SSR) ? PACKET_TYPE_RETRY : PACKET_TYPE_HANDSHAKE;
  } else {
    pkt[0] |= mReceivedServerClearText ? PACKET_TYPE_HANDSHAKE : PACKET_TYPE_INITIAL;
  }

  if ((pkt[0] & 0x7f) == PACKET_TYPE_INITIAL) {
    // stateless retry and 0rtt can send us down this road
    mStreamState->mStream0->ResetInbound();
  }

  if (mConnectionState == SERVER_STATE_SSR) {
    HandshakeLog4("Generating Server Stateless Retry.\n");
    assert(mStreamState->mUnAckedPackets.empty());
  }

  tmp32 = htonl(mVersion);
  memcpy(framePtr, &tmp32, 4);
  framePtr += 4;

  rv = CID::FormatLongHeader(mPeerCID, mLocalCID, mLocalOmitCID,
                             framePtr, endpkt - framePtr, used);
  if (rv != MOZQUIC_OK) return rv;
  framePtr += used;

  unsigned char *payloadLenPtr = framePtr;
  if ((endpkt - framePtr) < 2) {
    return MOZQUIC_ERR_GENERAL;
  }
  framePtr += 2;

  tmp32 = htonl(mNextTransmitPacketNumber & 0xffffffff);
  if (mConnectionState == SERVER_STATE_SSR) {
    tmp32 = htonl(mClientInitialPacketNumber & 0xffffffff);
  }
  uint32_t usedPacketNumber = ntohl(tmp32);
  memcpy(framePtr, &tmp32, 4);
  framePtr += 4;

  std::unique_ptr<TransmittedPacket> packet(new TransmittedPacket(mNextTransmitPacketNumber));
  unsigned char *emptyFramePtr = framePtr;
  mStreamState->CreateFrames(framePtr, endpkt - 16, true, packet.get()); // last 16 are aead tag
  bool sentStream = (framePtr != emptyFramePtr);

  // then padding as needed up to mtu on client_initial
  uint32_t paddingNeeded = 0;
  bool bareAck = false;

  if ((pkt[0] & 0x7f) == PACKET_TYPE_INITIAL) {
    if (((framePtr - pkt) + 16) < kMinClientInitial) {
      paddingNeeded = kMinClientInitial - ((framePtr - pkt) + 16);
    }
  } else {
    if (mConnectionState == SERVER_STATE_SSR) {
      mConnectionState = SERVER_STATE_1RTT;
      mStreamState->mUnAckedPackets.clear();
      assert(mStreamState->mConnUnWritten.empty());
      if (mConnEventCB) {
        mConnEventCB(mClosure, MOZQUIC_EVENT_ERROR, this);
      }
    }

    uint32_t room = endpkt - framePtr - 16; // the last 16 are for aead tag
    bareAck = framePtr == emptyFramePtr;
    if (AckPiggyBack(framePtr, mNextTransmitPacketNumber, room, keyPhase0Rtt,
                     bareAck, used) == MOZQUIC_OK) {
      if (used) {<commit_msg>Revert "fix keyphase of handshake ack"<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "Logging.h"
#include "MozQuic.h"
#include "MozQuicInternal.h"
#include "NSSHelper.h"
#include "Sender.h"
#include "Streams.h"

#include <assert.h>
#include <stdlib.h>
#include <unistd.h>

namespace mozquic  {

static const uint32_t kMinClientInitial = 1200;
extern std::unordered_map<std::string, uint32_t> mVNHash;

#define HandshakeLog1(...) Log::sDoLog(Log::HANDSHAKE, 1, this, __VA_ARGS__);
#define HandshakeLog2(...) Log::sDoLog(Log::HANDSHAKE, 2, this, __VA_ARGS__);
#define HandshakeLog3(...) Log::sDoLog(Log::HANDSHAKE, 3, this, __VA_ARGS__);
#define HandshakeLog4(...) Log::sDoLog(Log::HANDSHAKE, 4, this, __VA_ARGS__);
#define HandshakeLog5(...) Log::sDoLog(Log::HANDSHAKE, 5, this, __VA_ARGS__);
#define HandshakeLog6(...) Log::sDoLog(Log::HANDSHAKE, 6, this, __VA_ARGS__);
#define HandshakeLog7(...) Log::sDoLog(Log::HANDSHAKE, 7, this, __VA_ARGS__);
#define HandshakeLog8(...) Log::sDoLog(Log::HANDSHAKE, 8, this, __VA_ARGS__);
#define HandshakeLog9(...) Log::sDoLog(Log::HANDSHAKE, 9, this, __VA_ARGS__);
#define HandshakeLog10(...) Log::sDoLog(Log::HANDSHAKE, 10, this, __VA_ARGS__);

bool
MozQuic::IntegrityCheck(unsigned char *pkt, uint32_t pktSize, uint32_t headerSize,
                        CID handshakeCID, uint64_t packetNumber, unsigned char *outbuf, uint32_t &outSize)
{
  assert (pkt[0] & 0x80); // long form
  assert (((pkt[0] & 0x7f) == PACKET_TYPE_INITIAL) ||
          ((pkt[0] & 0x7f) == PACKET_TYPE_RETRY) ||
          ((pkt[0] & 0x7f) == PACKET_TYPE_HANDSHAKE));

  uint32_t rv;
  if (mNSSHelper) {
    rv = mNSSHelper->DecryptHandshake(pkt, headerSize, pkt + headerSize, pktSize - headerSize, packetNumber, handshakeCID,
                                      outbuf + headerSize, kMozQuicMSS - headerSize, outSize);
  } else {
    // need longheader.mdestcid
    assert ((pkt[0] & 0x7f) == PACKET_TYPE_INITIAL || (pkt[0] & 0x7f) == PACKET_TYPE_RETRY);
    rv = NSSHelper::staticDecryptHandshake(pkt, headerSize, pkt + headerSize, pktSize - headerSize, packetNumber, handshakeCID,
                                           outbuf + headerSize, kMozQuicMSS - headerSize, outSize);
  }
    
  if (rv != MOZQUIC_OK) {
    ConnectionLog1("Decrypt handshake failed packet %lX integrity error\n", packetNumber);
    return false;
  }
  memcpy(outbuf, pkt, headerSize);
  outSize += headerSize;
  ConnectionLog5("Decrypt handshake (packetNumber=%lX) ok sz=%d\n", packetNumber, outSize);
  return true;
}

uint32_t
MozQuic::FlushStream0(bool forceAck)
{
  mStreamState->FlowControlPromotion();

  if (mStreamState->mConnUnWritten.empty() && !forceAck) {
    return MOZQUIC_OK;
  }

  assert(mMTU <= kMaxMTU);
  unsigned char pkt[kMaxMTU];
  unsigned char *endpkt = pkt + mMTU;
  unsigned char *framePtr = pkt;
  uint32_t tmp32;
  uint32_t rv;
  uint32_t used;

  // section 4.1 of transport
  pkt[0] = 0x80;
  framePtr++;
  if (ServerState()) {
    pkt[0] |=
      (mConnectionState == SERVER_STATE_SSR) ? PACKET_TYPE_RETRY : PACKET_TYPE_HANDSHAKE;
  } else {
    pkt[0] |= mReceivedServerClearText ? PACKET_TYPE_HANDSHAKE : PACKET_TYPE_INITIAL;
  }

  if ((pkt[0] & 0x7f) == PACKET_TYPE_INITIAL) {
    // stateless retry and 0rtt can send us down this road
    mStreamState->mStream0->ResetInbound();
  }

  if (mConnectionState == SERVER_STATE_SSR) {
    HandshakeLog4("Generating Server Stateless Retry.\n");
    assert(mStreamState->mUnAckedPackets.empty());
  }

  tmp32 = htonl(mVersion);
  memcpy(framePtr, &tmp32, 4);
  framePtr += 4;

  rv = CID::FormatLongHeader(mPeerCID, mLocalCID, mLocalOmitCID,
                             framePtr, endpkt - framePtr, used);
  if (rv != MOZQUIC_OK) return rv;
  framePtr += used;

  unsigned char *payloadLenPtr = framePtr;
  if ((endpkt - framePtr) < 2) {
    return MOZQUIC_ERR_GENERAL;
  }
  framePtr += 2;

  tmp32 = htonl(mNextTransmitPacketNumber & 0xffffffff);
  if (mConnectionState == SERVER_STATE_SSR) {
    tmp32 = htonl(mClientInitialPacketNumber & 0xffffffff);
  }
  uint32_t usedPacketNumber = ntohl(tmp32);
  memcpy(framePtr, &tmp32, 4);
  framePtr += 4;

  std::unique_ptr<TransmittedPacket> packet(new TransmittedPacket(mNextTransmitPacketNumber));
  unsigned char *emptyFramePtr = framePtr;
  mStreamState->CreateFrames(framePtr, endpkt - 16, true, packet.get()); // last 16 are aead tag
  bool sentStream = (framePtr != emptyFramePtr);

  // then padding as needed up to mtu on client_initial
  uint32_t paddingNeeded = 0;
  bool bareAck = false;

  if ((pkt[0] & 0x7f) == PACKET_TYPE_INITIAL) {
    if (((framePtr - pkt) + 16) < kMinClientInitial) {
      paddingNeeded = kMinClientInitial - ((framePtr - pkt) + 16);
    }
  } else {
    if (mConnectionState == SERVER_STATE_SSR) {
      mConnectionState = SERVER_STATE_1RTT;
      mStreamState->mUnAckedPackets.clear();
      assert(mStreamState->mConnUnWritten.empty());
      if (mConnEventCB) {
        mConnEventCB(mClosure, MOZQUIC_EVENT_ERROR, this);
      }
    }

    uint32_t room = endpkt - framePtr - 16; // the last 16 are for aead tag
    bareAck = framePtr == emptyFramePtr;
    if (AckPiggyBack(framePtr, mNextTransmitPacketNumber, room, keyPhaseUnprotected,
                     bareAck, used) == MOZQUIC_OK) {
      if (used) {
{'fraction_non_alphanumeric': 0.13281391556441385, 'fraction_numerical': 0.02455154919369451, 'mean_word_length': 3.8163176265270504, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1943670', 'n_tokens_mistral': 4182, 'n_tokens_neox': 4053, 'n_words': 891}