32 octets, while the SID is 16 octets.
ECB mode used for encrypting the first block of OWAMP-Test packets in
authenticated mode does not involve any actual chaining; this way,
lost, duplicated, or reordered packets do not cause problems with
deciphering any packet in an OWAMP-Test session.
In encrypted mode, the first two blocks (32 octets) are encrypted
using AES CBC mode. The AES Session-key to use is obtained in the
same way as the key for authenticated mode. Each OWAMP-Test packet
is encrypted as a separate stream, with just one chaining operation;
chaining does not span multiple packets so that lost, duplicated, or
reordered packets do not cause problems. The initialization vector
for the CBC encryption is a value with all bits equal to zero.
Implementation note: Naturally, the key schedule for each OWAMP-Test
session MAY be set up only once per session, not once per packet.
HMAC in OWAMP-Test only covers the part of the packet that is also
encrypted. So, in authenticated mode, HMAC covers the first block
(16 octets); in encrypted mode, HMAC covers two first blocks (32
octets). In OWAMP-Test HMAC is not encrypted (note that this is
different from OWAMP-Control, where encryption in stream mode is
used, so everything including the HMAC blocks ends up being
encrypted).
In unauthenticated mode, no encryption or authentication is applied.
Packet Padding in OWAMP-Test SHOULD be pseudo-random (it MUST be
generated independently of any other pseudo-random numbers mentioned
in this document). However, implementations MUST provide a
configuration parameter, an option, or a different means of making
Packet Padding consist of all zeros.
The time elapsed between packets is computed according to the slot
schedule as mentioned in Request-Session command description. At
that point, we skipped over the issue of computing exponentially
distributed pseudo-random numbers in a reproducible fashion. It is
discussed later in a separate section.
4.2. Receiver Behavior
The receiver knows when the sender will send packets. The following
parameter is defined: Timeout (from Request-Session). Packets that
are delayed by more than Timeout are considered lost (or "as good as
lost"). Note that there is never an actual assurance of loss by the
network: a "lost" packet might still be delivered at any time. The
original specification for IPv4 required that packets be delivered
within TTL seconds or never (with TTL having a maximum value of 255).
To the best of the authors’ knowledge, this requirement was never
actually implemented (and, of course, only a complete and universal
implementation would ensure that packets do not travel for longer
than TTL seconds). In fact, in IPv6, the name of this field has
actually been changed to Hop Limit. Further, IPv4 specification
makes no claims about the time it takes the packet to traverse the
last link of the path.
The choice of a reasonable value of Timeout is a problem faced by a
user of OWAMP protocol, not by an implementor. A value such as two
minutes is very safe. Note that certain applications (such as
interactive "one-way ping" might wish to obtain the data faster than
that.
As packets are received,
+ timestamp the received packet;
+ in authenticated or encrypted mode, decrypt and authenticate as
necessary (packets for which authentication fails MUST be
discarded); and
+ store the packet sequence number, send time, receive time, and the
TTL for IPv4 (or Hop Limit for IPv6) from the packet IP header for
the results to be transferred.
Packets not received within the Timeout are considered lost. They
are recorded with their true sequence number, presumed send time,
receive time value with all bits being zero, and a TTL (or Hop Limit)
of 255.
Implementations SHOULD fetch the TTL/Hop Limit value from the IP
header of the packet. If an implementation does not fetch the actual
TTL value (the only good reason not to do so is an inability to
access the TTL field of arriving packets), it MUST record the TTL
value as 255.
Packets that are actually received are recorded in the order of
arrival. Lost packet records serve as indications of the send times
of lost packets. They SHOULD be placed either at the point where the
receiver learns about the loss or at any later point; in particular,
one MAY place all the records that correspond to lost packets at the
very end.
Packets that have send time in the future MUST be recorded normally,
without changing their send timestamp, unless they have to be
discarded. (Send timestamps in the future would normally indicate
clocks that differ by more than the delay. Some data -- such as
jitter -- can be extracted even without knowledge of time difference.
For other kinds of data, the adjustment is best handled by the data
consumer on the basis of the complete information in a measurement
session, as well as, possibly, external data.)
Packets with a sequence number that was already observed (duplicate
packets) MUST be recorded normally. (Duplicate packets are sometimes
introduced by IP networks. The protocol has to be able to measure
duplication.)
If any of the following is true, the packet MUST be discarded:
+ Send timestamp is more than Timeout in the past or in the future.
+ Send timestamp differs by more than Timeout from the time when the
packet should have been sent according to its sequence number.
+ In authenticated or encrypted mode, HMAC verification fails.
5. Computing Exponentially Distributed Pseudo-Random Numbers
Here we describe the way exponential random quantities used in the
protocol are generated. While there is a fair number of algorithms
for generating exponential random variables, most of them rely on
having logarithmic function as a primitive, resulting in potentially
different values, depending on the particular implementation of the
math library. We use algorithm 3.4.1.S from [KNUTH], which is free
of the above-mentioned problem, and which guarantees the same output
on any implementation. The algorithm belongs to the ziggurat family
developed in the 1970s by G. Marsaglia, M. Sibuya, and J. H. Ahrens
[ZIGG]. It replaces the use of logarithmic function by clever bit
manipulation, still producing the exponential variates on output.
5.1. High-Level Description of the Algorithm
For ease of exposition, the algorithm is first described with all
arithmetic operations being interpreted in their natural sense.
Later, exact details on data types, arithmetic, and generation of the
uniform random variates used by the algorithm are given. It is an
almost verbatim quotation from [KNUTH], p.133.
Algorithm S: Given a real positive number "mu", produce an
exponential random variate with mean "mu".
First, the constants
Q[k] = (ln2)/(1!) + (ln2)^2/(2!) + ... + (ln2)^k/(k!), 1 <= k <= 11
are computed in advance. The exact values which MUST be used by all
implementations are given in the next section. This is necessary to
ensure that exactly the same pseudo-random sequences are produced by
all implementations.
S1. [Get U and shift.] Generate a 32-bit uniform random binary
fraction
U = (.b0 b1 b2 ... b31) [note the binary point]
Locate the first zero bit b_j and shift off the leading (j+1) bits,
setting U <- (.b_{j+1} ... b31)
Note: In the rare case that the zero has not been found, it is
prescribed that the algorithm return (mu*32*ln2).
S2. [Immediate acceptance?] If U < ln2, set X <- mu*(j*ln2 + U) and
terminate the algorithm. (Note that Q[1] = ln2.)
S3. [Minimize.] Find the least k >= 2 such that U < Q[k]. Generate k
new uniform random binary fractions U1,...,Uk and set V <-
min(U1,...,Uk).
S4. [Deliver the answer.] Set X <- mu*(j + V)*ln2.
5.2. Data Types, Representation, and Arithmetic
The high-level algorithm operates on real numbers, typically
represented as floating point numbers. This specification prescribes
that unsigned 64-bit integers be used instead.
u_int64_t integers are interpreted as real numbers by placing the
decimal point after the first 32 bits. In other words, conceptually,
the interpretation is given by the following map:
u_int64_t u;
u |--> (double)u / (2**32)
The algorithm produces a sequence of such u_int64_t integers that,
for any given value of SID, is guaranteed to be the same on any
implementation.
We specify that the u_int64_t representations of the first 11 values
of the Q array in the high-level algorithm MUST be as follows:
#1 0xB17217F8,
#2 0xEEF193F7,
#3 0xFD271862,
#4 0xFF9D6DD0,
#5 0xFFF4CFD0,
#6 0xFFFEE819,
#7 0xFFFFE7FF,
#8 0xFFFFFE2B,
#9 0xFFFFFFE0,
#10 0xFFFFFFFE,
#11 0xFFFFFFFF
For example, Q[1] = ln2 is indeed approximated by 0xB17217F8/(2**32)
= 0.693147180601954; for j > 11, Q[j] is 0xFFFFFFFF.
Small integer j in the high-level algorithm is represented as
u_int64_t value j * (2**32).
Operation of addition is done as usual on u_int64_t numbers; however,
the operation of multiplication in the high-level algorithm should be
replaced by
(u, v) |---> (u * v) >> 32.
Implementations MUST compute the product (u * v) exactly. For
example, a fragment of unsigned 128-bit arithmetic can be implemented
for this purpose (see the sample implementation in Appendix A).
5.3. Uniform Random Quantities
The procedure for obtaining a sequence of 32-bit random numbers (such
as U in algorithm S) relies on using AES encryption in counter mode.
To describe the exact working of the algorithm, we introduce two
primitives from Rijndael. Their prototypes and specification are
given below, and they are assumed to be provided by the supporting
Rijndael implementation, such as [RIJN].
+ A function that initializes a Rijndael key with bytes from seed
(the SID will be used as the seed):
void KeyInit(unsigned char seed[16]);
+ A function that encrypts the 16-octet block inblock with the
specified key, returning a 16-octet encrypted block. Here,
keyInstance is an opaque type used to represent Rijndael keys:
void BlockEncrypt(keyInstance key, unsigned char inblock[16]);
Algorithm Unif: given a 16-octet quantity seed, produce a sequence of
unsigned 32-bit pseudo-random uniformly distributed integers. In
OWAMP, the SID (session ID) from Control protocol plays the role of
seed.
U1. [Initialize Rijndael key] key <- KeyInit(seed) [Initialize an
unsigned 16-octet (network byte order) counter] c <- 0
U2. [Need more random bytes?] Set i <- c mod 4. If (i == 0) set s
<- BlockEncrypt(key, c)
U3. [Increment the counter as unsigned 16-octet quantity] c <- c + 1
U4. [Do output] Output the i_th quartet of octets from s starting
from high-order octets, converted to native byte order and
represented as OWPNum64 value (as in 3.b).
U5. [Loop] Go to step U2.
6. Security Considerations
6.1. Introduction
The goal of authenticated mode is to let one passphrase-protect the
service provided by a particular OWAMP-Control server. One can
imagine a variety of circumstances where this could be useful.
Authenticated mode is designed to prohibit theft of service.
An additional design objective of the authenticated mode was to make
it impossible for an attacker who cannot read traffic between OWAMP-
Test sender and receiver to tamper with test results in a fashion
that affects the measurements, but not other traffic.
The goal of encrypted mode is quite different: to make it hard for a
party in the middle of the network to make results look "better" than
they should be. This is especially true if one of client and server
does not coincide with either sender or receiver.
Encryption of OWAMP-Control using AES CBC mode with blocks of HMAC
after each message aims to achieve two goals: (i) to provide secrecy
of exchange, and (ii) to provide authentication of each message.
6.2. Preventing Third-Party Denial of Service
OWAMP-Test sessions directed at an unsuspecting party could be used
for denial of service (DoS) attacks. In unauthenticated mode,
servers SHOULD limit receivers to hosts they control or to the OWAMP-
Control client.
Unless otherwise configured, the default behavior of servers MUST be
to decline requests where the Receiver Address field is not equal to
the address that the control connection was initiated from or an
address of the server (or an address of a host it controls). Given
the TCP handshake procedure and sequence numbers in the control
connection, this ensures that the hosts that make such requests are
actually those hosts themselves, or at least on the path towards
them. If either this test or the handshake procedure were omitted,
it would become possible for attackers anywhere in the Internet to
request that large amounts of test packets be directed against victim
nodes somewhere else.
In any case, OWAMP-Test packets with a given source address MUST only
be sent from the node that has been assigned that address (i.e.,
address spoofing is not permitted).
6.3. Covert Information Channels
OWAMP-Test sessions could be used as covert channels of information.
Environments that are worried about covert channels should take this
into consideration.
6.4. Requirement to Include AES in Implementations
Notice that AES, in counter mode, is used for pseudo-random number
generation, so implementation of AES MUST be included even in a
server that only supports unauthenticated mode.
6.5. Resource Use Limitations
An OWAMP server can consume resources of various kinds. The two most
important kinds of resources are network capacity and memory (primary
or secondary) for storing test results.
Any implementation of OWAMP server MUST include technical mechanisms
to limit the use of network capacity and memory. Mechanisms for
managing the resources consumed by unauthenticated users and users
authenticated with a KeyID and passphrase SHOULD be separate. The
default configuration of an implementation MUST enable these
mechanisms and set the resource use limits to conservatively low
values.
One way to design the resource limitation mechanisms is as follows:
assign each session to a user class. User classes are partially
ordered with "includes" relation, with one class ("all users") that
is always present and that includes any other class. The assignment
of a session to a user class can be based on the presence of
authentication of the session, the KeyID, IP address range, time of
day, and, perhaps, other factors. Each user class would have a limit
for usage of network capacity (specified in units of bit/second) and
memory for storing test results (specified in units of octets).
Along with the limits for resource use, current use would be tracked
by the server. When a session is requested by a user in a specific
user class, the resources needed for this session are computed: the
average network capacity use (based on the sending schedule) and the
maximum memory use (based on the number of packets and number of
octets each packet would need to be stored internally -- note that
outgoing sessions would not require any memory use). These resource
use numbers are added to the current resource use numbers for the
given user class; if such addition would take the resource use
outside of the limits for the given user class, the session is
rejected. When resources are reclaimed, corresponding measures are
subtracted from the current use. Network capacity is reclaimed as
soon as the session ends. Memory is reclaimed when the data is
deleted. For unauthenticated sessions, memory consumed by an OWAMP-
Test session SHOULD be reclaimed after the OWAMP-Control connection
that initiated the session is closed (gracefully or otherwise). For
authenticated sessions, the administrator who configures the service
should be able to decide the exact policy, but useful policy
mechanisms that MAY be implemented are the ability to automatically
reclaim memory when the data is retrieved and the ability to reclaim
memory after a certain configurable (based on user class) period of
time passes after the OWAMP-Test session terminates.
6.6. Use of Cryptographic Primitives in OWAMP
At an early stage in designing the protocol, we considered using
Transport Layer Security (TLS) [RFC2246, RFC3546] and IPsec [RFC2401]
as cryptographic security mechanisms for OWAMP; later, we also
considered DTLS. The disadvantages of those are as follows (not an
exhaustive list):
Regarding TLS:
+ TLS could be used to secure TCP-based OWAMP-Control, but it would
be difficult to use it to secure UDP-based OWAMP-Test: OWAMP-Test
packets, if lost, are not resent, so packets have to be
(optionally) encrypted and authenticated while retaining
individual usability. Stream-based TLS cannot be easily used for
this.
+ Dealing with streams, TLS does not authenticate individual
messages (even in OWAMP-Control). The easiest way out would be to
add some known-format padding to each message and to verify that
the format of the padding is intact before using the message. The
solution would thus lose some of its appeal ("just use TLS"). It
would also be much more difficult to evaluate the security of this
scheme with the various modes and options of TLS; it would almost
certainly not be secure with all. The capacity of an attacker to
replace parts of messages (namely, the end) with random garbage
could have serious security implications and would need to be
analyzed carefully. Suppose, for example, that a parameter that
is used in some form to control the rate were replaced by random
garbage; chances are that the result (an unsigned integer) would
be quite large.
+ Dependent on the mode of use, one can end up with a requirement
for certificates for all users and a PKI. Even if one is to
accept that PKI is desirable, there just isn’t a usable one today.
+ TLS requires a fairly large implementation. OpenSSL, for example,
is larger than our implementation of OWAMP as a whole. This can
matter for embedded implementations.
Regarding DTLS:
+ Duplication and, similarly, reordering are network phenomena that
OWAMP needs to be able to measure; yet anti-replay measures and
reordering protection of DTLS would prevent the duplicated and
reordered packets from reaching the relevant part of the OWAMP
code. One could, of course, modify DTLS so that these protections
are weakened or even specify examining the messages in a carefully
crafted sequence somewhere in between DTLS checks; but then, of
course, the advantage of using an existing protocol would not be
realized.
+ In authenticated mode, the timestamp is in the clear and is not
protected cryptographically in any way, while the rest of the
message has the same protection as in encrypted mode. This mode
allows one to trade off cryptographic protection against accuracy
of timestamps. For example, the APAN hardware implementation of
OWAMP [APAN] is capable of supporting authenticated mode. The
accuracy of these measurements is in the sub-microsecond range.
The errors in OWAMP measurements of Abilene [Abilene] (done using
a software implementation, in its encrypted mode) exceed 10us.
Users in different environments have different concerns, and some
might very well care about every last microsecond of accuracy. At
the same time, users in these same environments might care about
access control to the service. Authenticated mode permits them to
control access to the server yet to use unprotected timestamps,
perhaps generated by a hardware device.
Regarding IPsec:
+ What we now call authenticated mode would not be possible (in
IPsec you can’t authenticate part of a packet).
+ The deployment paths of IPsec and OWAMP could be separate if OWAMP
does not depend on IPsec. After nine years of IPsec, only 0.05%
of traffic on an advanced backbone network, such as Abilene, uses
IPsec (for comparison purposes with encryption above layer 4, SSH
use is at 2-4% and HTTPS use is at 0.2-0.6%). It is desirable to
be able to deploy OWAMP on as large a number of different
platforms as possible.
+ The deployment problems of a protocol dependent on IPsec would be
especially acute in the case of lightweight embedded devices.
Ethernet switches, DSL "modems", and other such devices mostly do
not support IPsec.
+ The API for manipulating IPsec from an application is currently
poorly understood. Writing a program that needs to encrypt some
packets, to authenticate some packets, and to leave some open --
for the same destination -- would become more of an exercise in
IPsec than in IP measurement.
For the enumerated reasons, we decided to use a simple cryptographic
protocol (based on a block cipher in CBC mode) that is different from
TLS and IPsec.
6.7. Cryptographic Primitive Replacement
It might become necessary in the future to replace AES, or the way it
is used in OWAMP, with a new cryptographic primitive, or to make
other security-related changes to the protocol. OWAMP provides a
well-defined point of extensibility: the Modes word in the server
greeting and the Mode response in the Set-Up-Response message. For
example, if a simple replacement of AES with a different block cipher
with a 128-bit block is needed, this could be accomplished as
follows: take two bits from the reserved (MBZ) part of the Modes word
of the server greeting; use one of these bits to indicate encrypted
mode with the new cipher and another one to indicate authenticated
mode with the new cipher. (Bit consumption could, in fact, be
reduced from two to one, if the client is allowed to return a mode
selection with more than a single bit set: one could designate a
single bit to mean that the new cipher is supported (in the case of
the server) or selected (in the case of the client) and continue to
use already allocated bits for authenticated and encrypted modes;
this optimization is unimportant conceptually, but it could be useful
in practice to make the best use of bits.) Then, if the new cipher
is negotiated, all subsequent operations simply use it instead of
AES. Note that the normal transition sequence would be used in such
a case: implementations would probably first start supporting and
preferring the new cipher, and then drop support for the old cipher
(presumably no longer considered secure).
If the need arises to make more extensive changes (perhaps to replace
AES with a 256-bit-block cipher), this would be more difficult and
would require changing the layout of the messages. However, the
change can still be conducted within the framework of OWAMP
extensibility using the Modes/Mode words. The semantics of the new
bits (or single bit, if the optimization described above is used)
would include the change to message layout as well as the change in
the cryptographic primitive.
Each of the bits in the Modes word can be used for an independent
extension. The extensions signaled by various bits are orthogonal;
for example, one bit might be allocated to change from AES-128 to
some other cipher, another bit might be allocated to add a protocol
feature (such as, e.g., support for measuring over multicast), yet
another might be allocated to change a key derivation function, etc.
The progression of versions is not a linear order, but rather a
partial order. An implementation can implement any subset of these
features (of course, features can be made mandatory to implement,