operate method
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 ArgumentException.invalidOperationArguments(
"operate",
name: "length",
reason: "A length should be set for this operation.",
);
}
data = List<int>.filled(length, 0);
} else {
if (length != 0) {
throw ArgumentException.invalidOperationArguments(
"operate",
name: "length",
reason:
"Output length must be zero except for PRF, send_MAC, and RATCHET operations.",
);
}
data = dataConst.clone();
}
if (more) {
if (flags != _curFlags) {
throw ArgumentException.invalidOperationArguments(
"operate",
name: "length",
reason: "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 ArgumentException.invalidOperationArguments(
"operate",
name: "more",
reason:
"Not supposed to check a MAC with the 'more' streaming option.",
);
}
int failures = 0;
for (final dataByte in data) {
failures |= dataByte;
}
return [failures]; // 0 if correct, 1 if not
}
return List.empty();
}