xref: /freebsd/crypto/openssl/doc/designs/functions-for-explicitly-fetched-signature-algorithms.md (revision e7be843b4a162e68651d3911f0357ed464915629)
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