xref: /freebsd/crypto/openssl/doc/designs/evp_skey.md (revision 4b15965daa99044daf184221b7c283bf7f2d7e66)
1EVP_SKEY Design
2===============
3
4The current API assumes that a byte buffer is always available and sufficient
5to represent a symmetric key. But for hardware-backed providers, such as
6PKCS#11 or TPM, keys generally cannot be exported and need to be represented
7via some kind of handle or id.
8
9This design proposes the use of an opaque type to represent symmetric keys. It
10doesn't cover any extra parameters (e.g. AEAD-related nonces).
11
12When a provider allows key exporting, the internal representation of the
13EVP_SKEY may be turned back into an array of bytes, that can be cached and
14become usable by any current cipher supporting symmetric keys in byte form.
15In other cases it may happen to be a set of provider-specific parameters,
16compatible only with the particular provider.
17
18For clarity, when cipher algorithms are mentioned later, the implicit
19assumption is that *any* algorithm accepting a symmetric key should be able
20to deal with an EVP_SKEY object from the same provider.
21
22Libcrypto perspective
23---------------------
24
25EVP_SKEY objects can be a wrapper around a raw key stored in an internal buffer.
26
27A wrapper EVP_SKEY object stores the key and the key length in an internal
28structure. The key management-backed EVP_SKEY object contains 2 pointers: a
29pointer to an EVP_SKEYMGMT object and an opaque pointer to a provider specific
30object that represents the key.
31EVP_SKEYMGMT specifies what parameters are acceptable by the chosen provider and
32may be used by specific algorithms of this provider. These parameters are
33represented as an array of OSSL_PARAM. We create an API to manage the lifecycle
34of EVP_SKEY objects (see below).
35
36Once an EVP_SKEY object is created it can be used in place of a raw key.
37The new APIs for this purpose are designed to match the existing ones but use
38an EVP_SKEY object as an argument. For usability reasons we keep IV and IV length
39as separate arguments in the new API even though they could have been provided as
40an element of a OSSL_PARAM array argument.
41
42There are other parameters that some but not all ciphers take. You'll find a
43substantial list in the manual for EVP_CipherInit(), and they are suitable for
44passing via OSSL_PARAM. The difference here is that *those* params are not
45provider-specific but algorithm-specific or operation-specific.
46
47Things that were previously passed to backend implementations with ctrl
48functions have become EVP_CIPHER_CTX level OSSL_PARAM items with providers.
49
50If an operation is available only from a different provider than the one that
51generated the EVP_SKEY object, then the management code will attempt an export
52(and possibly import) operation of the key, including when the target provider
53offers only legacy APIs that accept a raw key only. If export fails the
54operation fails.
55
56Provider perspective
57--------------------
58
59For dealing with opaque keys, we provide a new structure - EVP_SKEYMGMT,
60similar to EVP_KEYMGMT.
61
62On the provider end, encryption and decryption implementations will receive an
63opaque pointer similar to the provkey pointer used with asymmetric operations.
64This pointer is a result of processing an array of OSSL_PARAM by a EVP_SKEYMGMT
65operation (import, generate, etc..).
66
67Once created, the EVP_SKEY structure can be exported to the extent the provider
68and EVP_SKEYMGMT supports it. There is no guarantee that the result
69of export-import operation is the same as the initial set of the parameters.
70
71The EVP_SKEY object generally has a type, however there is a generic catchall
72secret type for key that are not tied to a specific operation. Whether a key
73is typed depends on how it was created.
74
75Relationships between Objects
76-----------------------------
77
78We have an EVP_CIPHER object associated with a particular provider. An EVP_SKEY
79object should be compatible with the particular EVP_CIPHER object (the check is
80done via comparing the providers). After that it can be used within a
81EVP_CIPHER_CTX object associated with the same EVP_CIPHER object.
82
83The way to reuse the key with another provider is through an export/import
84process. As mentioned before, it may fail. The way to reuse it with a different
85cipher context is `EVP_SKEY_up_ref`.
86
87Key management
88--------------
89
90The provider operating EVP_SKEY objects has to implement a separate symmetric
91key management to deal with the opaque object.
92
93Allocation and freeing
94----------------------
95
96EVP_SKEY object doesn't reuse the pattern 'allocate - assign', these operations
97are combined.
98
99```C
100EVP_SKEY *EVP_SKEY_generate(OSSL_LIB_CTX *libctx, const char *skeymgmtname,
101                            const char *propquery, const OSSL_PARAM *params);
102EVP_SKEY *EVP_SKEY_import(OSSL_LIB_CTX *libctx, const char *skeymgmtname,
103                          const char *propquery,
104                          int selection, const OSSL_PARAM *params);
105EVP_SKEY *EVP_SKEY_import_raw(OSSL_LIB_CTX *libctx, const char *skeymgmtname,
106                              const char *key, size_t keylen,
107                              const char *propquery);
108int EVP_SKEY_up_ref(EVP_SKEY *skey);
109void EVP_SKEY_free(EVP_SKEY *skey);
110```
111
112Exporting the key object
113------------------------
114
115```C
116int EVP_SKEY_export(const EVP_SKEY *skey, int selection,
117                    OSSL_CALLBACK *export_cb, void *export_cbarg);
118```
119
120Using EVP_SKEY in cipher operations
121-----------------------------------
122
123We provide a function
124
125```C
126int EVP_CipherInit_SKEY(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
127                        EVP_SKEY *skey, const unsigned char *iv, size_t iv_len,
128                        int enc, const OSSL_PARAM params[]);
129```
130
131similar to `EVP_CipherInit_ex2`. After call to this function, the normal
132EVP_CipherUpdate/EVP_CipherFinal API can be used.
133
134Using EVP_SKEY with EVP_MAC
135---------------------------
136
137```C
138int EVP_MAC_init_SKEY(EVP_MAC_CTX *ctx, const EVP_SKEY *skey,
139                      const OSSL_PARAM params[]);
140```
141
142similar to `EVP_MAC_init`
143
144API to derive an EVP_SKEY object
145--------------------------------
146
147This part is delayed for a while because the proposed API doesn't fit well with
148TLS KDFs deriving multiple keys simultaneously.
149