Path: blob/main/crypto/openssl/doc/designs/evp-cipher-pipeline.md
34923 views
EVP APIs for supporting cipher pipelining in provided ciphers
OpenSSL previously supported "pipeline" ciphers via ENGINE implementations. That support was lost when we moved to providers. This document discusses API design to restore that capability and enable providers to implement such ciphers.
Pipeline operation
Certain ciphers, such as AES-GCM, can be optimized by computing blocks in parallel. Cipher pipelining support allows application to submit multiple chunks of data in one cipher update call, thereby allowing the provided implementation to take advantage of parallel computing. This is very beneficial for hardware accelerators as pipeline amortizes the latency over multiple chunks. Our libssl makes use of pipeline as discussed in here.
Pipelining with ENGINE
Before discussing API design for providers, let's take a look at existing pipeline API that works with engines.
EVP Interface: Flag to denote pipeline support
Input/output and aad buffers are set using EVP_CIPHER_CTX_ctrl()
Single-call cipher invoked to perform encryption/decryption.
Proposal for EVP pipeline APIs
Current API design is made similar to non-pipeline counterpart. The document will be final once the changes are integrated.
EVP Interface: API to check for pipeline support in provided cipher.
Multi-call APIs for init, update and final. Associated data for AEAD ciphers are set in EVP_CipherPipelineUpdate
.
API to get/set AEAD auth tag.
Alternative: iovec style interface for input/output buffers.
Design Decisions:
Denoting pipeline support
a. A cipher flag
EVP_CIPH_FLAG_PROVIDED_PIPELINE
(this has to be different than EVP_CIPH_FLAG_PIPELINE, so that it doesn't break legacy applications).b. A function
EVP_CIPHER_can_pipeline()
that checks if the provider exports pipeline functions.
Justification: flags variable is deprecated in EVP_CIPHER struct. Moreover, EVP can check for presence of pipeline functions, rather than requiring providers to set a flag.
With the introduction of this new API, there will be two APIs for pipelining available until the legacy code is phased out: a. When an Engine that supports pipelining is loaded, it will set the ctx->flags & EVP_CIPH_FLAG_PIPELINE
. If this flag is set, applications can continue to use the legacy API for pipelining. b. When a Provider that supports pipelining is fetched, EVP_CIPHER_can_pipeline()
will return true, allowing applications to utilize the new API for pipelining.
numpipes
argumenta.
numpipes
received only inEVP_CipherPipelineEncryptInit()
and saved in EVP_CIPHER_CTX for further use.b.
numpipes
value is repeatedly received in eachEVP_CipherPipelineEncryptInit()
,EVP_CipherPipelineUpdate()
andEVP_CipherPipelineFinal()
call.
Justification: It is expected for numpipes to be same across init, update and final operation.
Input/Output buffers
a. A set of buffers is represented by an array of buffer pointers and an array of lengths. Example:
unsigned char **out, size_t *outl
.b. iovec style: A new type that holds one buffer pointer along with its size. Example:
EVP_CIPHER_buf *out
Justification: While iovec style is better buffer representation, the EVP - provider interface in core_dispatch.h uses only primitive types.
AEAD tag
a. A new OSSL_CIPHER_PARAM of type OSSL_PARAM_OCTET_PTR,
OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG
, that uses an array of buffer pointers. This can be used withiovec_buf
if we decide with 3.b.b. Reuse
OSSL_CIPHER_PARAM_AEAD_TAG
by using it in a loop, processing one tag at a time.
Justification: Reduces cipher get/set param operations.
Future Ideas
It would be nice to have a mechanism for fetching provider with pipeline support over other providers that don't support pipeline. Maybe by using property query strings.