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