The Universal Security Transform (UST) is a cryptographic transform for
providing confidentiality, message authentication, and replay protection.
This transform is sufficient for providing these services to network
protocols, though it does not specify a protocol itself.
UST has the following parameters:
- INDEX_LENGTH: The number of octets in an Index.
- MAX_KEYSTREAM_LENGTH: The maximum number of octets in a
keystream segment.
- PREFIX_LENGTH: The number of octets in the keystream prefix.
- TAG_LENGTH: The number of octets in an Authentication Tag.
- MAX_HASH_LENGTH: The maximum number of octets that can be input
to the hash function.
- HASH_KEY_LENGTH: The number of octets in a hash key.
All of these parameters
MUST remain fixed for any given UST
context.
The parameters
INDEX_LENGTH
and
MAX_KEYSTREAM_LENGTH
are defined by the keystream generator. This is because the keystream
generators used in UST are families of
length-expanding pseudorandom
functions. At the time of implementing UST, the only such generators
available are (a)
UMacGenerator
and (b)
ICMGenerator
. Yet, both of these two algorithms require more
than just these two parameters to be fully qualified, and hence instantiated.
They both require an underlying
block cipher as well as a
block
size and
key material. While default values are used for the
former two of these parameters -if they are not included in their
initialisation
Map
- the latter parameter; i.e.
key
material, should be specified.
The parameters
TAG_LENGTH
,
MAX_HASH_LENGTH
, and
HASH_KEY_LENGTH
are defined by the hash function. Please note
that when the UST document refers to a
hash function it actually
means a
Universal Hash Function. At the time of implementing UST,
the only such functions available are
UHash32
and
TMMH16
, with the latter more suited for UST purposes
because it is independent from any other algorithm --the same is not true for
(our implementation of)
UHash32
because of its current
dependencies on
UMac32
; although this may change in
the future. For this reason we shall only allow
TMMH16
as the UST's underlying
Universal Hash Function.
The length of any
Plaintext protected by UST
MUST NOT
exceed the smaller of
(MAX_KEYSTREAM_LENGTH - TAG_LENGTH)
and
MAX_HASH_LEN
.
The value of
HASH_KEY_LENGTH
MUST be no greater than
MAX_KEYSTREAM_LENGTH
. The value of
TAG_LENGTH
MUST be no greater than
HASH_KEY_LENGTH
.
Once a UST instance is initialised, one can (a) authenticate designated
bytes -an operation that does not yield any output- and/or (b) encipher
designated bytes -an operation that does yield an output equal in length to
the input.
The understanding of the author of this implementation is that an
initialised UST can be used to process different messages while relying on
that UST to generate and use a different index value for each message without
the need for specifying eveytime that value; i.e. the implementation shall
keep track of the index to ensure no previously used value, generated and
used with the same key material, is ever re-used. Furthermore, because we
want to
maximise the possible length of messages processed by a UST
with a given
key material, each new/updated index value should yield
two keystream generators: one for use with the
Integrity Protection
service (referred to as the Authentication Function in the UST draft),
and the other for use to encipher the message (
Confidentiality Protection
service) --see Figures 1 and 2 in the UST draft. This way the maximum
plaintext protected by such a UST is
(MAX_KEYSTREAM_LENGTH - TAG_LENGTH)
only, and the number of different messages protected by one set of
key material is
(2^(8*INDEX_LENGTH) - 1)
--the index
value
0
being reserved to generate all other keying material! To
achieve this objective this implementation does the following:
- We define
MAX_INDEX
to be (2^(8*INDEX_LENGTH) - 1)
--all length quantities are expressed in bytes. - With every initialisation of a UST, a keying index of value
0
and the user-supplied key material are used to initialise
an internal keystream generator. A message index is initialised
to -1
. - With every start-of-message, (a) increment the message index,
and (b) check if it is greater than
MAX_INDEX
. If it is we
throw an exception. Otherwise, we generate from the internal
keystream enough key material to initialise two keystream generators, both
with that same index, one for the Integrity Protection Function
and the other for the Confidentiality Protection Function. Please
note that strictly speaking, the first of this pair of keystreams is NOT
the Confidentiality Protection Function keystream generator, since it is
also used to generate the bytes of the Integrity Protection Function's
Prefix. In other words, as soon as we detect the requirement for
Integrity Protection service, we instantiate the keystream generator
pair, even if the Confidentiality Protection service is not required. - If on the other hand, the start-of-message includes a designated index
value, we use that index as is, in combination with enough key material
generated by our internal keystream.
- With every process-message (be it autheticate or encipher) we process
the message through one or both functions as desired (integrity protection
only, or integrity protection as well as confidentiality protection).
- With every end-of-message, we terminate the integrity protection and
compute the authentication tag.
- It is easy to show that it is possible to re-construct the state of
such a UST, given the user-supplied key material and a designated index
value.
- The new constraint that would limit the number of messages, and their
length, with this scheme becomes:
MAX_INDEX * 2 * (BLOCK_SIZE - INDEX_LENGTH) <= MAX_KEYSTREAM_LENGTH
where BLOCK_SIZE
is the underlying cipher's block size in
bytes.
Another alternative to using two keystream generators, would have been to
(a) use only one, but (b) in-line the code of the Authentication Function
inside the UST. This way, (a) enough output bytes from that keystream would
be used to setup the Authentication Function, and (b) the same output bytes
from that keystream would be used to compute the authentication context, as
well as encipher the message. But this weakens the UST, since an attacker,
with a known plaintext, can reconstruct the keystream generator output (used
for both the authentication and encipherement functions) by simply xoring the
message with the ciphertext.
The next figure depicts a block diagram of our implementation of the UST:
+----------------------------+ +-----------+
| user-supplied key material +------+ +-----+ Index = 0 |
+----------------------------+ | | +-----------+
V V
+-----------+ +------------------------------+
| Index | | Internal Keystream Generator |
+-----+-----+ +-------------+----------------+
| |
+----|------------------------------+
| | +-----------------+
| +--->| Confidentiality |
+----|--->| Protection +--+-----------------+
| | | Generator | | |
| | +-----------------+ V V
| | +------------+---------------------------+
| | +------------+ Prefix | Suffix +---+
| | | +------------+---------------------------+ |
| | | <------------- message -------------> |
| | | +-------+---------------------------+ |
| | | +-------+ Clear | Opaque +--(+)
| | | | +-------+---------------------------+ |
| | | | +---------------------------+ |
| | | | +--------+ Ciphertext |<--+
| | | | | +---------------------------+
| | | V V
| | | +-----------------+
| | +--->| Integrity | +-----------+
| +-------->| Protection +--->| Auth. Tag |
+------------->| Generator | +-----------+
+-----------------+
References:
-
The Universal Security Transform, David A. McGrew.