Example #1
0
 /** Get the current message sequence number */
 byte[] /*NilOK*/ getSequence() {
   if (null != myTransform) {
     return myTransform.getSuspendInfo();
   } else {
     return mySequence;
   }
 }
Example #2
0
  /**
   * Change the authorization protocol being used to receive messages on the connection. This
   * routine must be called when the RecvThread is synchronized with the Vat thread. This assertion
   * is checked by setting myChangeProtocolIsOk just before calling into the Vat with a new incoming
   * message and resetting it when the call returns. This routine will throw an Assertion failure if
   * that boolean is not true.
   *
   * @param protocolParms is the parameter bundle for the protocol suite to use. This routine must,
   *     of course, support the selected suite.
   */
  void changeProtocol(AuthSecrets protocolParms) {
    if (Trace.comm.verbose && Trace.ON) {
      Trace.comm.verbosem("ProtocolChange, pp=" + protocolParms);
    }
    T.require(
        myChangeProtocolIsOk,
        "Must only be called while caller " + "is processing an input message");
    // For calculating the header length
    int headerLengthIndex = HEADER_INVALID;

    if (StartUpProtocol.PROTO_NONE.equals(protocolParms.myProtocolSuite)) {
      myIsAggragating = false;
      myIsDoingMac = false;
      mySequence = null;
      headerLengthIndex = HEADER_INT_LENGTH;
      // begin daffE -> E
    } else if (StartUpProtocol.PROTO_3DES_SDH_M.equals(protocolParms.myProtocolSuite)) {
      myIsAggragating = true;
      MessageDigest md5 = setSHA1(protocolParms);
      headerLengthIndex = HEADER_VLEN_SHA1;
      mySequence = null;
      byte[] raw_3des_key = TripleDESKeyConstructor.make(protocolParms.myDHSecret);
      myTransform = new Decrypt3DES(raw_3des_key, protocolParms.myIncomingSequence);
      // end daffE -> E
      // begin improved E protocol
    } else if (StartUpProtocol.PROTO_3DES_SDH_M2.equals(protocolParms.myProtocolSuite)) {
      myIsAggragating = true;
      MessageDigest md5 = setSHA1(protocolParms);
      headerLengthIndex = HEADER_VLEN_HMAC;
      mySequence = new byte[4]; // Assume initialized to zero
      byte[] raw_3des_key = TripleDESKeyConstructor.make(protocolParms.myDHSecret);
      myTransform = new Decrypt3DES(raw_3des_key, protocolParms.myIncomingSequence);
      myTransform.init();
      myIsStandardCBC = true;
      myIsDoingHMAC = true;
      // end improved E protocol
    } else {
      T.fail("Invalid protocol type " + protocolParms);
    }
    myIsCompressingMsgLengths = myIsAggragating;

    int len = theHeaderLengths[headerLengthIndex];
    T.require(0 <= len, "Invalid header length code");
    myHeader = new byte[len];
  }
Example #3
0
  /** Process input data. */
  private void readAndProcessMessage() throws IOException {
    long authTime = 0;
    long macTime = 0;
    long startTime = 0;

    // Read the header
    fillArray(myHeader, 0, myHeader.length);

    if (null != myTransform) {
      if (Trace.comm.timing && Trace.ON) {
        startTime = MicroTime.queryTimer();
      }
      if (!myIsStandardCBC) {
        myTransform.init();
      }
      myTransform.transform(myHeader);
      if (Trace.comm.timing && Trace.ON) {
        authTime += MicroTime.queryTimer() - startTime;
      }
    }
    if (Trace.comm.verbose && Trace.ON) {
      String hdr = HexStringUtils.bytesToReadableHexStr(myHeader);
      Trace.comm.verbosem("Header: " + hdr);
    }

    int length;
    int nextItemOffset; // Offset to the next item in the header
    if (myIsCompressingMsgLengths) {
      int l1 = myHeader[0]; // First byte of the length
      if (0 == (l1 & 0x80)) {
        // len < 128
        length = l1;
        nextItemOffset = 1;
      } else {
        if (0x80 == (l1 & 0xc0)) {
          // len < 16,384
          length = ((l1 & 0x3f) << 8) | ((myHeader[1] & 0xff));
          nextItemOffset = 2;
        } else if (0xc0 == (l1 & 0xe0)) {
          // len < 2,097,152
          length = ((l1 & 0x1f) << 16) | ((myHeader[1] & 0xff) << 8) | ((myHeader[2] & 0xff));
          nextItemOffset = 3;
        } else if (0xe0 == (l1 & 0xf0)) {
          // len < 2**28
          length =
              ((l1 & 0x0f) << 24)
                  | ((myHeader[1] & 0xff) << 16)
                  | ((myHeader[2] & 0xff) << 8)
                  | ((myHeader[3] & 0xff));
          nextItemOffset = 4;
        } else {
          throw new IOException(
              "Invalid compressed length code" + HexStringUtils.bytesToReadableHexStr(myHeader));
        }
      }
    } else {
      // Not compressing
      length =
          ((myHeader[0] & 0xff) << 24)
              | ((myHeader[1] & 0xff) << 16)
              | ((myHeader[2] & 0xff) << 8)
              | (myHeader[3] & 0xff);
      nextItemOffset = 4;
    }
    if (Trace.comm.verbose && Trace.ON) {
      Trace.comm.verbosem("incoming packet len = " + length);
    }
    if (Msg.MAX_INBOUND_MSG_LENGTH < length || 0 > length) {
      throw new IOException("Packet too large: " + length + " > " + Msg.MAX_INBOUND_MSG_LENGTH);
    }
    if (myIsDoingMac) {
      System.arraycopy(myHeader, nextItemOffset, myMAC, 0, 20); // Save MAC
      nextItemOffset += 20;
    }
    if (null != mySequence) {
      int seqLen = mySequence.length;
      byte[] theirSequence = new byte[seqLen];
      System.arraycopy(myHeader, nextItemOffset, theirSequence, 0, seqLen);
      if (!isEqual(mySequence, theirSequence)) {
        if (Trace.comm.error) {
          traceErrorMsg(
              theirSequence, 0, theirSequence.length, "sequence error, [remote sequence number]:");
          traceErrorMsg(
              mySequence, 0, mySequence.length, "sequence error, [local sequence number]:");
        }
        throw new IOException("incoming packet sequence error");
      }
      nextItemOffset += seqLen;
    }
    // Calculate message length + padding and allocate a buffer
    // The length required is the length of the data portion plus the
    // padding length for the original message.
    // The padding length for the original message is calculated:
    //    msglen = (length_of_length + length_of_headers + length_of_data
    //    padlen = ((msglen + 7) & 0xfffffff8) - msglen
    // length_of_length + length_of_headers is equal to nextItemOffset
    //    (the amount of data eaten by processing them above).
    // length_of_data is length.
    byte[] message;
    if (myIsCompressingMsgLengths || null != myTransform) {
      int msglen = nextItemOffset + length;
      int padlen = ((msglen + 7) & 0xfffffff8) - msglen;
      message = new byte[length + padlen];
    } else {
      message = new byte[length];
    }
    if (nextItemOffset < myHeader.length) {
      // Copy compressed data read with header
      System.arraycopy(myHeader, nextItemOffset, message, 0, myHeader.length - nextItemOffset);
    }
    if (Trace.comm.verbose && Trace.ON) {
      String msg = HexStringUtils.bytesToReadableHexStr(message);
      Trace.comm.verbosem("Initial message: " + msg);
    }

    // Read rest of message into the buffer allocated for it
    fillArray(
        message,
        myHeader.length - nextItemOffset,
        message.length - (myHeader.length - nextItemOffset));

    if (null != myTransform) {
      if (Trace.comm.timing && Trace.ON) {
        startTime = MicroTime.queryTimer();
      }
      myTransform.transform(
          message,
          (myHeader.length - nextItemOffset),
          message.length - (myHeader.length - nextItemOffset));
      if (Trace.comm.timing && Trace.ON) {
        authTime += MicroTime.queryTimer() - startTime;
      }
    }

    if (Trace.comm.verbose && Trace.ON) {
      String msg = HexStringUtils.bytesToReadableHexStr(message);
      Trace.comm.verbosem("Full message: " + msg);
    }

    myMessagesToPass.removeAllElements();
    if (myIsAggragating) {
      if (Trace.comm.timing && Trace.ON) {
        startTime = MicroTime.queryTimer();
      }
      ByteArrayInputStream bais = new ByteArrayInputStream(message);
      while (true) {
        length = 0;
        int input = bais.read();
        if (0 >= input) {
          break; // -1 for eof on bais, 0 if only msg shorter than 3
        }
        int count;
        if (myIsCompressingMsgLengths) {
          if (0 == (input & 0x80)) {
            length = input;
            count = 0;
          } else if (0x80 == (input & 0xc0)) {
            // len < 16,384
            length = input & 0x3f;
            count = 1;
          } else if (0xc0 == (input & 0xe0)) {
            // len < 2,097,152
            length = input & 0x1f;
            count = 2;
          } else if (0xe0 == (input & 0xf0)) {
            // len < 2**28
            length = input & 0x0f;
            count = 3;
          } else {
            String msg = HexStringUtils.bytesToReadableHexStr(message);
            throw new IOException("Invalid compressed length code" + msg);
          }
        } else {
          count = 3;
        }
        for (int i = 0; i < count; i++) {
          length <<= 8;
          input = bais.read();
          length |= input & 0xff;
        }
        if (Msg.MAX_INBOUND_MSG_LENGTH < length || 0 > length) {
          throw new IOException(
              "Message too large: " + length + " > " + Msg.MAX_INBOUND_MSG_LENGTH);
        }

        byte[] emsg = new byte[length];
        int offset = 0;
        while (offset < emsg.length) {
          int read = bais.read(emsg, offset, emsg.length - offset);
          if (-1 == read) {
            break;
          }
          offset += read;
        }
        if (offset != length) {
          throw new IOException(
              "incoming packet not aggragated properly,"
                  + " expectedLength="
                  + length
                  + " foundLength="
                  + offset
                  + HexStringUtils.bytesToReadableHexStr(message));
        }
        myMessagesToPass.addElement(emsg);
      }
    } else if (message.length != length) {
      byte[] a = new byte[length];
      System.arraycopy(message, 0, a, 0, length);
      myMessagesToPass.addElement(a);
    } else {
      myMessagesToPass.addElement(message);
    }

    if (myIsDoingMac) {
      if (Trace.comm.timing && Trace.ON) {
        startTime = MicroTime.queryTimer();
      }
      byte[] digest = computeMAC(myMessagesToPass);
      if (!MessageDigest.isEqual(digest, myMAC)) {
        if (Trace.comm.error) {
          traceErrorMsg(myMAC, 0, myMAC.length, "checksum mismatch, [remote checksum]:");
          traceErrorMsg(digest, 0, digest.length, "checksum mismatch, [local checksum]:");
          Enumeration itr = myMessagesToPass.elements();
          while (itr.hasMoreElements()) {
            byte[] msg = (byte[]) (itr.nextElement());
            int len = msg.length;
            byte[] m = new byte[len + 4];
            m[0] = (byte) ((len >> 24) & 0xff); // The message length
            m[1] = (byte) ((len >> 16) & 0xff);
            m[2] = (byte) ((len >> 8) & 0xff);
            m[3] = (byte) ((len) & 0xff);
            System.arraycopy(msg, 0, m, 4, len);
            traceErrorMsg(m, 0, m.length, "checksum mismatch, [data         ]:");
          }
        }
        throw new IOException("incoming packet checksum mismatch");
      }
      if (Trace.comm.timing && Trace.ON) {
        macTime += MicroTime.queryTimer() - startTime;
      }
    }
    // The input data counts are maintained in the DataPath
    // myDataPath.updateReceivedCounts(msgLengths, compressedLength);

    Enumeration itr;
    if (Trace.comm.timing && Trace.ON) {
      // Generate event record message
      itr = myMessagesToPass.elements();
      String logMsg = "Processed message length(s)";
      while (itr.hasMoreElements()) {
        byte[] msg = (byte[]) (itr.nextElement());
        logMsg += " " + msg.length;
      }
      if (0 != authTime) {
        logMsg += " AuthTime=" + authTime;
      }
      if (0 != macTime) {
        logMsg += " MACTime=" + macTime;
      }
      myTotalTime += authTime + macTime;
      if (0 != myTotalTime) {
        logMsg += " TotalTime=" + myTotalTime;
      }
      Trace.comm.timingm(logMsg);
    }

    itr = myMessagesToPass.elements();
    while (itr.hasMoreElements()) {
      byte[] msg = (byte[]) (itr.nextElement());
      if (Trace.comm.debug && Trace.ON) {
        traceDebugMsg(msg, 0, msg.length, "incoming packet data");
      }
      myChangeProtocolIsOk = true;

      // XXX should make embargo work again
      if (Msg.E_MSG == msg[0]) {
        myDataPath.getEmbargoLock().waitTillOff();
      }

      callDataPath(new DataCommThunk(myDataPath, msg));
      myChangeProtocolIsOk = false;
    }
    myMessagesToPass.removeAllElements(); // Clean up for garbage collecter
  }