aboutsummaryrefslogtreecommitdiff
path: root/doc/users-guide/users-guide-crypto.adoc
blob: 029f47b17b912ce4c787e831cbb5e38a8d5d869d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
== Cryptographic services

ODP provides APIs to perform cryptographic operations required by
applications. ODP cryptographic APIs are session based and provide
cryptographic algorithm offload services. ODP also offers cryptographic
protocol offload services for protocols such as IPsec using a different set
of APIs. This section covers the main crypto APIs.

ODP provides APIs for following cryptographic services:

* Ciphering
* Authentication/data integrity via Keyed-Hashing (HMAC)
* Random number generation
* Crypto capability inquiries

Ciphering and authentication services are accessible via two complementary
sets of related APIs. The original ODP crypto APIs, and a newer
_packet-oriented_ set of crypto APIs that are designed to be consistent with
the protocol-aware cryptographic services offered by the IPsec API set.

=== Crypto Sessions

To apply a cryptographic operation to a packet a session must be created. All
packets processed by a session share the parameters that define the session.

ODP supports synchronous and asynchronous crypto sessions. For asynchronous
sessions, the output of crypto operation is posted in a queue defined as
the completion queue in its session parameters.

ODP crypto APIs support chained operation sessions in which hashing and
ciphering both can be achieved using a single session and operation call. The
order of cipher and hashing can be controlled by the `auth_cipher_text`
session parameter.

Other Session parameters include algorithms, keys, initialization vector
(optional), encode or decode, output queue for async mode and output packet
pool for allocation of an output packet if required.

The parameters that describe the characteristics of a crypto session are
encoded in the `odp_crypto_session_param_t` struct that is passed to the
`odp_crypto_session_create()` API. A successful call returns an
`odp_crypto_session_t` object that in turn is passed as an input parameter to
crypto operation calls.

When an application is finished with a crypto session the
`odp_crypto_session_destroy()` API is used to release the resources associated
with an `odp_crypto_session_t`.

=== Crypto operations

After session creation, a cryptographic operation can be applied to a packet
in one of two ways.

==== Parameter-based Crypto Operations
This is the original ODP support for cryptographic operations. The
`odp_crypto_operation()` API takes an input `odp_crypto_op_param_t` struct
that describes the cryptographic operation to be performed. This struct
contains the session to use as well as the input packet the operation is to be
performed on. The caller may either specify an output packet to receive the
operation results or may request that the ODP implementation allocate a new
packet to receive these results from the output pool associated with the
`odp_crypto_session_t`. If the input packet is also used as the output packet,
then an "in place" operation is requested.

When using the `odp_crypto_operation()` API. Applications may indicate a
preference for synchronous or asynchronous processing in the session's
`pref_mode` parameter.  However crypto operations may complete synchronously
even if an asynchronous preference is indicated, and applications must examine
the `posted` output parameter from `odp_crypto_operation()` to determine
whether the operation has completed or if an `ODP_EVENT_CRYPTO_COMPL`
notification is expected. In the case of an async operation, the `posted`
output parameter will be set to true.

The operation arguments specify for each packet the areas that are to be
encrypted or decrypted and authenticated. Also, there is an option of overriding
the initialization vector specified in session parameters.

An operation can be executed in in-place, out-of-place or new buffer mode.
In in-place mode output packet is same as the input packet.
In case of out-of-place mode output packet is different from input packet as
specified by the application, while in new buffer mode implementation allocates
a new output buffer from the session’s output pool.

The application can also specify a context associated with a given operation
that will be retained during async operation and can be retrieved via the
completion event.

Results of an asynchronous session will be posted as completion events to the
session’s completion queue, which can be accessed directly or via the ODP
scheduler. The completion event contains the status of the operation and the
result. The application has the responsibility to free the completion event.

Upon receipt of an `ODP_EVENT_CRYPTO_COMPL` event, the
`odp_crypto_compl_result()` API is used to retrieve the
`odp_crypto_op_result_t` associated with the event. This result struct in turn
contains:

* An indication of the success or failure of the crypto operation
* The user context associated with the event
* The output `odp_packet_t`.
* The `odp_crypto_op_status_t` for the requested cipher operation
* The `odp_crypto_op_status_t` for the requested authentication operation

==== Packet-based Crypto Operations
To simplify the original cryptographic operation request API, as well as to
be more flexible and consistent with the protocol-aware APIs introduced for
IPsec support, a newer packet-oriented set of cryptographic operation
APIs is also provided. Applications may use either API set, but going forward
it is expected that these newer APIs will be the focus of continued
development.

Instead of a single `odp_crypto_operation()` API, the packet-based form
provides two APIs: `odp_crypto_op()` is the synchronous form while
`odp_crypto_op_enq()` is the asynchronous form. To check which of these are
supported by the ODP implementation, examine the `sync_mode` and `async_mode`
fields in the `odp_crypto_capability_t` struct returned by the
`odp_crypto_capability()` API.

Both forms take an input array of packets, an optional output array of packets
to receive the results, and an array of `odp_crypto_packet_op_param_t` structs
that describe the operation to be performed on each input packet. As with the
original APIs, the output array may be the same packets to request in-place
operation, or may be specified as `ODP_PACKET_INVALID` to request that ODP
allocate output packets from the pool associated with the
`odp_crypto_session_t` being used.

The key differences between the `odp_crypto_op_param_t` used by the original
APIs and the `odp_crypto_packet_op_param_t` used by the new APIs are:

* The original API takes a single `odp_crypto_op_param_t` since it operates on
a single packet whereas the new forms take an array of
`odp_crypto_packet_op_param_t` structs, one for each input packet.

* The `odp_crypto_packet_op_param_t` does not contain any packet information
since the input and output packets are supplied as API parameters rather than
being encoded in this struct.

* The `odp_crypto_packet_op_param_t` does not contain a user context field.

In addition, the `odp_crypto_session_t` field `op_mode` is used instead of
the `pref_mode` field when the packet-oriented APIs are used. If the
`op_mode` is set to `ODP_CRYPTO_SYNC` then the synchronous form of the API
must be used and if `op_mode` is set to `ODP_CRYPTO_ASYNC` then the
asynchronous form of the API must be used. It is an error to attempt to use
a form of the API not properly matched to the mode of the crypto session.

The output of a packet-based crypto operation is an `odp_packet_t` (one for
each input packet) that is returned either synchronously or
asynchronously. Asynchronous return is in the form of `ODP_EVENT_PACKET`
events that have event subtype `ODP_EVENT_PACKET_CRYPTO`. The packet
associated with such events is obtained via the
`odp_crypto_packet_from_event()` API. The `odp_crypto_result()` API, in turn,
retrieves the `odp_crypto_packet_result_t` from this `odp_packet_t` that
contains:

* An indication of whether the crypto packet operation was successful or not
* The `odp_crypto_op_status_t` for the requested cipher operation
* The `odp_crypto_op_status_t` for the requested authentication operation

=== Random number Generation

ODP provides two APIs to generate various kinds of random data bytes. Random
data is characterized by _kind_, which specifies the "quality" of the
randomness required. ODP support three kinds of random data:

ODP_RANDOM_BASIC:: No specific requirement other than the data appear to be
uniformly distributed. Suitable for load-balancing or other non-cryptographic
use.

ODP_RANDOM_CRYPTO:: Data suitable for cryptographic use. This is a more
stringent requirement that the data pass tests for statistical randomness.

ODP_RANDOM_TRUE:: Data generated from a hardware entropy source rather than
any software generated pseudo-random data. May not be available on all
platforms.

These form a hierarchy with BASIC being the lowest kind of random and TRUE
behing the highest. The main API for accessing random data is:

[source,c]
-----
int32_t odp_random_data(uint8_t buf, uint32_t len, odp_random_kind_t kind);
-----

The expectation is that lesser-quality random is easier and faster to generate
while higher-quality random may take more time. Implementations are always free
to substitute a higher kind of random than the one requested if they are able
to do so more efficiently, however calls must return a failure indicator
(rc < 0) if a higher kind of data is requested than the implementation can
provide. This is most likely the case for ODP_RANDOM_TRUE since not all
platforms have access to a true hardware random number generator.

The `odp_random_max_kind()` API returns the highest kind of random data
available on this implementation.

For testing purposes it is often desirable to generate repeatable sequences
of "random" data. To address this need ODP provides the additional API:

[source,c]
-----
int32_t odp_random_test_data(uint8_t buf, uint32_t len, uint64_t *seed);
-----

This operates the same as `odp_random_data()` except that it always returns
data of kind `ODP_RANDOM_BASIC` and an additional thread-local `seed`
parameter is provide that specifies a seed value to use in generating the
data. This value is updated on each call, so repeated calls with the same
variable will generate a sequence of random data starting from the initial
specified seed. If another sequence of calls is made starting with the same
initial seed value, then `odp_random_test_data()` will return the same
sequence of data bytes.

=== Capability inquiries

ODP provides the API `odp_crypto_capability()` to inquire the implementation’s
crypto capabilities. This interface returns a the maximum number of crypto
sessions supported as well as bitmasks for supported algorithms and hardware
backed algorithms.