summaryrefslogtreecommitdiffstats
path: root/doc/designs
diff options
context:
space:
mode:
authorslontis <shane.lontis@oracle.com>2023-07-13 14:32:02 +1000
committerTomas Mraz <tomas@openssl.org>2023-11-02 15:56:12 +0100
commit04b53878ea498582a6c2cfa93c570584818bbe47 (patch)
tree7d0a17f084f4c7d680d82ba59ba39c314fc48cd8 /doc/designs
parentf62fec64049959cee6b80043cd697d0e7357a24a (diff)
Add design notes for XOF API.
Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/21443)
Diffstat (limited to 'doc/designs')
-rw-r--r--doc/designs/xof.md268
1 files changed, 268 insertions, 0 deletions
diff --git a/doc/designs/xof.md b/doc/designs/xof.md
new file mode 100644
index 0000000000..d7fe7ade87
--- /dev/null
+++ b/doc/designs/xof.md
@@ -0,0 +1,268 @@
+XOF Design
+==========
+
+XOF Definition
+--------------
+
+An extendable output function (XOF) is defined as a variable-length hash
+function on a message in which the output can be extended to any desired length.
+
+At a minimum an XOF needs to support the following pseudo-code
+
+```text
+xof = xof.new();
+xof.absorb(bytes1);
+xof.absorb(bytes2);
+xof.finalize();
+out1 = xof.squeeze(10);
+out2 = xof.squeeze(1000);
+```
+
+### Rules
+
+- absorb can be called multiple times
+- finalize ends the absorb process (by adding padding bytes and doing a final
+ absorb). absorb must not be called once the finalize is done unless a reset
+ happens.
+- finalize may be done as part of the first squeeze operation
+- squeeze can be called multiple times.
+
+OpenSSL XOF Requirements
+------------------------
+
+The current OpenSSL implementation of XOF only supports a single call to squeeze.
+The assumption exists in both the high level call to EVP_DigestFinalXOF() as
+well as in the lower level SHA3_squeeze() operation (Of which there is a generic
+c version, as well as assembler code for different platforms).
+
+A decision has to be made as to whether a new API is required, as well as
+considering how the change may affect existing applications.
+The changes introduced should have a minimal affect on other related functions
+that share the same code (e.g SHAKE and SHA3 share functionality).
+Older providers that have not been updated to support this change should produce
+an error if a newer core is used that supports multiple squeeze operations.
+
+API Discussion of Squeeze
+-------------------------
+
+### Squeeze
+
+Currently EVP_DigestFinalXOF() uses a flag to check that it is only invoked once.
+It returns an error if called more than once. When initially written it also did
+a reset, but that code was removed as it was deemed to be incorrect.
+
+If we remove the flag check, then the core code will potentially call low level
+squeeze code in a older provider that does not handle returning correct data for
+multiple calls. To counter this the provider needs a mechanism to indicate that
+multiple calls are allowed. This could just be a new gettable flag (having a
+separate provider function should not be necessary).
+
+#### Proposal 1
+
+Change EVP_DigestFinalXOF(ctx, out, outlen) to handle multiple calls.
+Possibly have EVP_DigestSqueeze() just as an alias method?
+Changing the code at this level should be a simple matter of removing the
+flag check.
+
+##### Pros
+
+ - New API is not required
+
+##### Cons
+
+ - Final seems like a strange name to call multiple times.
+
+#### Proposal 2 (Proposed Solution)
+
+Keep EVP_DigestFinalXOF() as a one shot function and create a new API to handle
+the multi squeeze case e.g.
+
+```text
+EVP_DigestSqueeze(ctx, out, outlen).
+```
+
+##### Pros
+
+ - Seems like a better name.
+ - The existing function does not change, so it is not affected by logic that
+ needs to run for the multi squeeze case.
+ - The behaviour of the existing API is the same.
+ - At least one other toolkit uses this approach.
+
+##### Cons
+
+ - Adds an extra API.
+ - The interaction between the 2 API's needs to be clearly documented.
+ - A call to EVP_DigestSqueeze() after EVP_DigestFinalXOF() would fail since
+ EVP_DigestFinalXOF() indicates no more output can be retrieved.
+ - A call to EVP_DigestFinalXOF() after the EVP_DigestSqueeze() would fail.
+
+#### Proposal 3
+
+Create a completely new type e.g. EVP_XOF_MD to implement XOF digests
+
+##### Pros
+
+ - This would separate the XOF operations so that the interface consisted
+ mainly of Init, Absorb and Squeeze API's
+ - DigestXOF could then be deprecated.
+
+##### Cons
+
+ - XOF operations are required for Post Quantum signatures which currently use
+ an EVP_MD object. This would then complicate the Signature API also.
+ - Duplication of the EVP_MD code (although all legacy/engine code would be
+ removed).
+
+Choosing a name for the API that allows multiple output calls
+-------------------------------------------------------------
+
+Currently OpenSSL only uses XOF's which use a sponge construction (which uses
+the terms absorb and squeeze).
+There will be other XOF's that do not use the sponge construction such as Blake2.
+
+The proposed API name to use is EVP_DigestSqueeze.
+The alternate name suggested was EVP_DigestExtract.
+The terms extract and expand are used by HKDF so I think this name would be
+confusing.
+
+API Discussion of other XOF API'S
+---------------------------------
+
+### Init
+
+The digest can be initialized as normal using:
+
+```text
+md = EVP_MD_fetch(libctx, "SHAKE256", propq);
+ctx = EVP_MD_CTX_new();
+EVP_DigestInit_ex2(ctx, md, NULL);
+```
+
+### Absorb
+
+Absorb can be done by multiple calls to:
+
+```text
+EVP_DigestUpdate(ctx, in, inlen);
+```
+
+#### Proposal:
+
+Do we want to have an Alias function?
+
+```text
+EVP_DigestAbsorb(ctx, in, inlen);
+```
+
+(The consensus was that this is not required).
+
+### Finalize
+
+The finalize is just done as part of the squeeze operation.
+
+### Reset
+
+A reset can be done by calling:
+
+```text
+EVP_DigestInit_ex2(ctx, NULL, NULL);
+```
+
+### State Copy
+
+The internal state can be copied by calling:
+
+```text
+EVP_MD_CTX_copy_ex(ctx, newctx);
+```
+
+Low Level squeeze changes
+--------------------------
+
+### Description
+
+The existing one shot squeeze method is:
+
+```text
+SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t outlen, size_t r)
+```
+
+It contains an opaque object for storing the state B<A>, that can be used to
+output to B<out>. After every B<r> bits, the state B<A> is updated internally
+by calling KeccakF1600().
+
+Unless you are using a multiple of B<r> as the B<outlen>, the function has no
+way of knowing where to start from if another call to SHA_squeeze() was
+attempted. The method also avoids doing a final call to KeccakF1600() currently
+since it was assumed that it was not required for a one shot operation.
+
+### Solution 1
+
+Modify the SHA3_squeeze code to accept a input/output parameter to track the
+position within the state B<A>.
+See <https://github.com/openssl/openssl/pull/13470>
+
+#### Pros
+
+ - Change in C code is minimal. it just needs to pass this additional parameter.
+ - There are no additional memory copies of buffered results.
+
+#### Cons
+
+ - The logic in the c reference has many if clauses.
+ - This C code also needs to be written in assembler, the logic would also be
+ different in different assembler routines due to the internal format of the
+ state A being different.
+ - The general SHA3 case would be slower unless code was duplicated.
+
+### Solution 2
+
+Leave SHA3_squeeze() as it is and buffer calls to the SHA3_squeeze() function
+inside the final. See <https://github.com/openssl/openssl/pull/7921>
+
+#### Pros
+
+ - Change is mainly in C code.
+
+#### Cons
+
+ - Because of the one shot nature of the SHA3_squeeze() it still needs to call
+ the KeccakF1600() function directly.
+ - The Assembler function for KeccakF1600() needs to be exposed. This function
+ was not intended to be exposed since the internal format of the state B<A>
+ can be different on different platform architectures.
+ - When should this internal buffer state be cleared?
+
+### Solution 3
+
+Perform a one-shot squeeze on the original absorbed data and throw away the
+first part of the output buffer,
+
+#### Pros
+
+ - Very simple.
+
+#### Cons
+
+ - Incredibly slow.
+ - More of a hack than a real solution.
+
+### Solution 4 (Proposed Solution)
+
+An alternative approach to solution 2 is to modify the SHA3_squeeze() slightly
+so that it can pass in a boolean that handles the call to KeccakF1600()
+correctly for multiple calls.
+
+#### Pros
+
+ - C code is fairly simple to implement.
+ - The state data remains as an opaque blob.
+ - For larger values of outlen SHA3_squeeze() may use the out buffer directly.
+
+#### Cons
+
+ - Requires small assembler change to pass the boolean and handle the call to
+ KeccakF1600().
+ - Uses memcpy to store partial results for a single blob of squeezed data of
+ size 'r' bytes.