operate method

List<int> operate(
  1. bool meta,
  2. StrobeOperation operation,
  3. List<int> dataConst,
  4. int length,
  5. bool more,
)

STROBE main duplexing mode.

Implementation

List<int> operate(bool meta, StrobeOperation operation, List<int> dataConst,
    int length, bool more) {
  int flags = operation.value;

  if (meta) {
    flags |= StrobeFlags.M;
  }

  List<int> data;
  if (((flags & (StrobeFlags.I | StrobeFlags.T)) !=
          (StrobeFlags.I | StrobeFlags.T)) &&
      ((flags & (StrobeFlags.I | StrobeFlags.A)) != StrobeFlags.A)) {
    if (length == 0) {
      throw const MessageException(
          "A length should be set for this operation.");
    }
    data = List<int>.filled(length, 0);
  } else {
    if (length != 0) {
      throw const MessageException(
          "Output length must be zero except for PRF, send_MAC, and RATCHET operations.");
    }
    data = List<int>.from(dataConst);
  }
  if (more) {
    if (flags != _curFlags) {
      throw const MessageException(
          "Flag should be the same when streaming operations.");
    }
  } else {
    // If `more` isn't set, this is a new operation. Do the begin_op sequence
    _op(flags);
    _curFlags = flags;
  }

  // Operation
  final bool cAfter =
      ((flags & (StrobeFlags.C | StrobeFlags.I | StrobeFlags.T)) ==
          (StrobeFlags.C | StrobeFlags.T));
  final bool cBefore = ((flags & StrobeFlags.C) != 0) && (!cAfter);

  _duplex(data, cBefore, cAfter, false);
  if ((flags & (StrobeFlags.I | StrobeFlags.A)) ==
      (StrobeFlags.I | StrobeFlags.A)) {
    return data;
  } else if ((flags & (StrobeFlags.I | StrobeFlags.T)) == StrobeFlags.T) {
    return data;
  } else if ((flags & (StrobeFlags.I | StrobeFlags.A | StrobeFlags.T)) ==
      (StrobeFlags.I | StrobeFlags.T)) {
    if (more) {
      throw const MessageException(
          "Not supposed to check a MAC with the 'more' streaming option");
    }
    int failures = 0;
    for (final int dataByte in data) {
      failures |= dataByte;
    }
    return List<int>.from([failures]); // 0 if correct, 1 if not
  }

  return List.empty();
}