Block operations v0.1.0
ZeroizeBlock
pub func ZeroizeBlock(buffer: *var opaque, length: uint)
Clears length bytes at buffer, and is not removed however unread those bytes are afterwards.
buffer is borrowed and written. A length of zero writes nothing and accepts a null pointer.
This is what Zero is not. Clearing a secret is a write nothing reads back, which dead-store elimination is
entitled to delete, and ordinary source cannot say "and mean it" — so this is a compiler guarantee rather than a
library one.
The guarantee is Core::Zeroize's; this adds the empty-case contract the rest of this module has and takes the
*var opaque and uint every other block operation here takes.
Cannot fail. Runs in time proportional to length and allocates nothing.
buffer must be writable for length bytes.
It clears the storage it is given and nothing else. A copy the caller made beforehand, a value the compiler
spilled to the stack, or bytes a reallocation left behind are all still there — so a secret has to be kept in
one place from the start for this to be the whole of its erasure.
Parameters
| Name | Type | Description |
|---|---|---|
buffer | *var opaque | the bytes to clear |
length | uint | how many bytes; zero writes nothing and accepts a null pointer |
Copy
pub func Copy(
destination: *var opaque,
source: *opaque,
length: uint
)
Copies length bytes from source to destination, which must not overlap.
source is borrowed and read; destination is borrowed and written. Nothing is returned and nothing takes
ownership. A length of zero copies nothing and accepts null for either pointer.
Cannot fail. Runs in time proportional to length and allocates nothing.
destination must be writable for length bytes and source readable for length, and the two ranges must not
overlap. Use Move when they might: this one is free to copy in whichever order suits the machine.
Parameters
| Name | Type | Description |
|---|---|---|
destination | *var opaque | where the bytes go; must not overlap source |
source | *opaque | where the bytes come from |
length | uint | how many bytes to copy |
Move
pub func Move(
destination: *var opaque,
source: *opaque,
length: uint
)
Copies length bytes from source to destination, correctly even when the two overlap.
source is borrowed and read; destination is borrowed and written. A length of zero moves nothing and
accepts null for either pointer.
The result is what copying through a temporary would give: every source byte reaches its destination as it was
before the move began. Sliding a run forward within one buffer therefore works, which is what an insertion into
the middle of an array needs.
Cannot fail. Runs in time proportional to length and allocates nothing — the temporary is notional, and the
direction of the copy is what actually makes it right.
destination must be writable for length bytes and source readable for length. They may overlap in any
way, including exactly.
Parameters
| Name | Type | Description |
|---|---|---|
destination | *var opaque | where the bytes go; may overlap source |
source | *opaque | where the bytes come from |
length | uint | how many bytes to move |
Set
pub func Set(
destination: *var opaque,
value: byte,
length: uint
)
Writes value to each of length bytes at destination.
destination is borrowed and written. A length of zero writes nothing and accepts a null pointer.
Cannot fail. Runs in time proportional to length and allocates nothing.
destination must be writable for length bytes. This is not the call for clearing a secret: a write nothing
reads back may be deleted, and Core::Zeroize is the one that may not be.
Parameters
| Name | Type | Description |
|---|---|---|
destination | *var opaque | the bytes to write |
value | byte | the byte to write to each |
length | uint | how many bytes to write |
Zero
pub func Zero(destination: *var opaque, length: uint)
Writes zero to each of length bytes at destination.
destination is borrowed and written. A length of zero writes nothing and accepts a null pointer.
Cannot fail. Runs in time proportional to length and allocates nothing.
destination must be writable for length bytes. For a secret, use Core::Zeroize, which the compiler may not
delete however unread the bytes are afterwards.
Parameters
| Name | Type | Description |
|---|---|---|
destination | *var opaque | the bytes to clear |
length | uint | how many bytes to clear |
MismatchOffset
pub func MismatchOffset(
left: *opaque,
right: *opaque,
length: uint
) -> uint
The offset at which two blocks first differ, or length when they do not.
Both pointers are borrowed and read. A length of zero reports zero and accepts null for either pointer, which
is the same answer two equal empty blocks give.
The answer is a position rather than an ordering, so it says where the blocks diverge and not which one sorts
first. Compare answers that.
Cannot fail. Runs in time proportional to the shared prefix and allocates nothing.
Both pointers must be readable for length bytes. Not constant-time: it stops at the first difference, so it
must not be used on a secret.
Parameters
| Name | Type | Description |
|---|---|---|
left | *opaque | one of the two blocks |
right | *opaque | the other |
length | uint | how many bytes to compare |
Returns: the offset of the first differing byte, or length when none differs
Compare
pub func Compare(
left: *opaque,
right: *opaque,
length: uint
) -> Ordering
Orders two blocks lexicographically, byte by byte.
Both pointers are borrowed and read. Returns Less when left sorts first, Greater when right does, and
Equal when the two ranges hold the same bytes. A length of zero reports Equal and accepts null for either
pointer.
Bytes are compared as unsigned, so the answer does not depend on whether the platform's plain char is signed,
and it matches the order the bytes would sort in as a string.
Cannot fail. Runs in time proportional to the shared prefix and allocates nothing.
Both pointers must be readable for length bytes. Not constant-time: it stops at the first difference, so a
secret compared this way leaks where it differs. Rux/Crypto is where a constant-time comparison belongs.
Parameters
| Name | Type | Description |
|---|---|---|
left | *opaque | one of the two blocks |
right | *opaque | the other |
length | uint | how many bytes to compare |
Returns: how left orders against right
Equal
pub func Equal(
left: *opaque,
right: *opaque,
length: uint
) -> bool
Whether two blocks hold the same bytes.
Both pointers are borrowed and read. A length of zero reports true and accepts null for either pointer: two
empty blocks are equal.
Cannot fail. Runs in time proportional to the shared prefix and allocates nothing.
Both pointers must be readable for length bytes. Not constant-time.
Parameters
| Name | Type | Description |
|---|---|---|
left | *opaque | one of the two blocks |
right | *opaque | the other |
length | uint | how many bytes to compare |
Returns: whether every byte matches
Find
pub func Find(
haystack: *opaque,
length: uint,
value: byte
) -> uint
The offset of the first byte equal to value, or length when there is none.
haystack is borrowed and read. A length of zero reports zero and accepts a null pointer, which is also what a
search that found nothing reports — an empty block contains nothing to find either way.
Cannot fail. Runs in time proportional to the offset returned and allocates nothing.
haystack must be readable for length bytes.
Parameters
| Name | Type | Description |
|---|---|---|
haystack | *opaque | the bytes to search |
length | uint | how many bytes to search |
value | byte | the byte to look for |
Returns: the offset of the first occurrence, or length when there is none