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