1 Functions for explicitly fetched PKEY algorithms 2 ================================================ 3 4 Quick background 5 ---------------- 6 7 There are several proposed designs that end up revolving around the same 8 basic need, explicitly fetched signature algorithms. The following method 9 type is affected by this document: 10 11 - `EVP_SIGNATURE` 12 13 Public API - Add variants of `EVP_PKEY_CTX` functionality 14 --------------------------------------------------------- 15 16 Through OTC discussions, it's been determined that the most suitable APIs to 17 touch are the of `EVP_PKEY_` functions. 18 Specifically, `EVP_PKEY_sign()`, `EVP_PKEY_verify()`, `EVP_PKEY_verify_recover()` 19 and related functions. 20 They can be extended to accept an explicitly fetched algorithm of the right 21 type, and to be able to incrementally process indefinite length data streams 22 when the fetched algorithm permits it (for example, RSA-SHA256). 23 24 It must be made clear that the added functionality cannot be used to compose 25 an algorithm from different parts. For example, it's not possible to specify 26 a `EVP_SIGNATURE` "RSA" and combine it with a parameter that specifies the 27 hash "SHA256" to get the "RSA-SHA256" functionality. For an `EVP_SIGNATURE` 28 "RSA", the input is still expected to be a digest, or some other input that's 29 limited to the modulus size of the RSA pkey. 30 31 ### Making things less confusing with distinct function names 32 33 Until now, `EVP_PKEY_sign()` and friends were only expected to act on the 34 pre-computed digest of a message (under the condition that proper flags 35 and signature md are specified using functions like 36 `EVP_PKEY_CTX_set_rsa_padding()` and `EVP_PKEY_CTX_set_signature_md()`), 37 or to act as "primitive" [^1] functions (under the condition that proper 38 flags are specified, like `RSA_NO_PADDING` for RSA signatures). 39 40 This design proposes an extension to also allow full (not pre-hashed) 41 messages to be passed, in a streaming style through an *update* and a 42 *final* function. 43 44 Discussions have revealed that it is potentially confusing to conflate the 45 current functionality with streaming style functionality into the same name, 46 so this design separates those out with specific init / update / final 47 functions for that purpose. For oneshot functionality, `EVP_PKEY_sign()` 48 and `EVP_PKEY_verify()` remain supported. 49 50 [^1]: the term "primitive" is borrowed from [PKCS#1](https://www.rfc-editor.org/rfc/rfc8017#section-5) 51 52 ### Making it possible to verify with an early signature 53 54 Some more recent verification algorithms need to obtain the signature 55 before processing the data. 56 This is particularly important for streaming modes of operation. 57 This design proposes a mechanism to accommodate these algorithms 58 and modes of operation. 59 60 New public API - API Reference 61 ------------------------------ 62 63 ### For limited input size / oneshot signing with `EVP_SIGNATURE` 64 65 ``` C 66 int EVP_PKEY_sign_init_ex2(EVP_PKEY_CTX *pctx, 67 EVP_SIGNATURE *algo, 68 const OSSL_PARAM params[]); 69 ``` 70 71 ### For signing a stream with `EVP_SIGNATURE` 72 73 ``` C 74 int EVP_PKEY_sign_message_init(EVP_PKEY_CTX *pctx, 75 EVP_SIGNATURE *algo, 76 const OSSL_PARAM params[]); 77 int EVP_PKEY_sign_message_update(EVP_PKEY_CTX *ctx, 78 const unsigned char *in, 79 size_t inlen); 80 int EVP_PKEY_sign_message_final(EVP_PKEY_CTX *ctx, 81 unsigned char *sig, 82 size_t *siglen); 83 #define EVP_PKEY_sign_message(ctx,sig,siglen,tbs,tbslen) \ 84 EVP_PKEY_sign(ctx,sig,siglen,tbs,tbslen) 85 ``` 86 87 ### For limited input size / oneshot verification with `EVP_SIGNATURE` 88 89 ``` C 90 int EVP_PKEY_verify_init_ex2(EVP_PKEY_CTX *pctx, 91 EVP_SIGNATURE *algo, 92 const OSSL_PARAM params[]); 93 ``` 94 95 ### For verifying a stream with `EVP_SIGNATURE` 96 97 ``` C 98 /* Initializers */ 99 int EVP_PKEY_verify_message_init(EVP_PKEY_CTX *pctx, 100 EVP_SIGNATURE *algo, 101 const OSSL_PARAM params[]); 102 /* Signature setter */ 103 int EVP_PKEY_CTX_set_signature(EVP_PKEY_CTX *pctx, 104 unsigned char *sig, size_t siglen, 105 size_t sigsize); 106 /* Update and final */ 107 int EVP_PKEY_verify_message_update(EVP_PKEY_CTX *ctx, 108 const unsigned char *in, 109 size_t inlen); 110 int EVP_PKEY_verify_message_final(EVP_PKEY_CTX *ctx); 111 112 #define EVP_PKEY_verify_message(ctx,sig,siglen,tbs,tbslen) \ 113 EVP_PKEY_verify(ctx,sig,siglen,tbs,tbslen) 114 ``` 115 116 ### For verify_recover with `EVP_SIGNATURE` 117 118 Preliminary feedback suggests that a streaming interface is uninteresting for 119 verify_recover, so we only specify a new init function. 120 121 ``` C 122 /* Initializers */ 123 int EVP_PKEY_verify_recover_init_ex2(EVP_PKEY_CTX *pctx, 124 EVP_SIGNATURE *algo, 125 const OSSL_PARAM params[]); 126 ``` 127 128 Requirements on the providers 129 ----------------------------- 130 131 Because it's not immediately obvious from a composite algorithm name what 132 key type ("RSA", "EC", ...) it requires / supports, at least in code, allowing 133 the use of an explicitly fetched implementation of a composite algorithm 134 requires that providers cooperate by declaring what key type is required / 135 supported by each algorithm. 136 137 For non-composite operation algorithms (like "RSA"), this is not necessary, 138 see the fallback strategies below. 139 140 This is to be implemented through an added provider function that would work 141 like keymgmt's `query_operation_name` function, but would return a NULL 142 terminated array of key type name instead: 143 144 ``` C 145 # define OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPE 26 146 OSSL_CORE_MAKE_FUNC(const char **, signature_query_key_type, (void)) 147 ``` 148 149 Furthermore, the distinction of intent, i.e. whether the input is expected 150 to be a pre-hashed digest or the original message, must be passed on to the 151 provider. Because we already distinguish that with function names in the 152 public API, we use the same mapping in the provider interface. 153 154 The already existing `signature_sign` and `signature_verify` remain as they 155 are, and can be combined with message init calls. 156 157 ``` C 158 # define OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT 27 159 # define OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_UPDATE 28 160 # define OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_FINAL 29 161 OSSL_CORE_MAKE_FUNC(int, signature_sign_message_init, 162 (void *ctx, void *provkey, const OSSL_PARAM params[])) 163 OSSL_CORE_MAKE_FUNC(int, signature_sign_message_update, 164 (void *ctx, const unsigned char *in, size_t inlen)) 165 OSSL_CORE_MAKE_FUNC(int, signature_sign_message_final, 166 (void *ctx, unsigned char *sig, size_t *siglen, size_t sigsize)) 167 168 # define OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT 30 169 # define OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_UPDATE 31 170 # define OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_FINAL 32 171 OSSL_CORE_MAKE_FUNC(int, signature_verify_message_init, 172 (void *ctx, void *provkey, const OSSL_PARAM params[])) 173 OSSL_CORE_MAKE_FUNC(int, signature_verify_message_update, 174 (void *ctx, const unsigned char *in, size_t inlen)) 175 /* 176 * signature_verify_message_final requires that the signature to be verified 177 * against is specified via an OSSL_PARAM. 178 */ 179 OSSL_CORE_MAKE_FUNC(int, signature_verify_message_final, (void *ctx)) 180 ``` 181 182 Fallback strategies 183 ------------------- 184 185 Because existing providers haven't been updated to respond to the key type 186 query, some fallback strategies will be needed for the init calls that take 187 an explicitly fetched `EVP_SIGNATURE` argument (they can at least be used 188 for pre-hashed digest operations). To find out if the `EVP_PKEY` key type 189 is possible to use with the explicitly fetched algorithm, the following 190 fallback strategies may be used. 191 192 - Check if the fetched operation name matches the key type (keymgmt name) 193 of the `EVP_PKEY` that's involved in the operation. For example, this 194 is useful when someone fetched the `EVP_SIGNATURE` "RSA". This requires 195 very little modification, as this is already done with the initializer 196 functions that fetch the algorithm implicitly. 197 - Check if the fetched algorithm name matches the name returned by the 198 keymgmt's `query_operation_name` function. For example, this is useful 199 when someone fetched the `EVP_SIGNATURE` "ECDSA", for which the key type 200 to use is "EC". This requires very little modification, as this is 201 already done with the initializer functions that fetch the algorithm 202 implicitly. 203 204 If none of these strategies work out, the operation initialization should 205 fail. 206