1 | Handling AlgorithmIdentifier and its parameters with provider operations
|
---|
2 | ========================================================================
|
---|
3 |
|
---|
4 | Quick background
|
---|
5 | ----------------
|
---|
6 |
|
---|
7 | We currently only support passing the AlgorithmIdentifier (`X509_ALGOR`)
|
---|
8 | parameter field to symmetric cipher provider implementations. We currently
|
---|
9 | only support getting full AlgorithmIdentifier (`X509_ALGOR`) from signature
|
---|
10 | provider implementations.
|
---|
11 |
|
---|
12 | We do support passing them to legacy implementations of other types of
|
---|
13 | operation algorithms as well, but it's done in a way that can't be supported
|
---|
14 | with providers, because it involves sharing specific structures between
|
---|
15 | libcrypto and the backend implementation.
|
---|
16 |
|
---|
17 | For a longer background and explanation, see
|
---|
18 | [Background / tl;dr](#background-tldr) at the end of this design.
|
---|
19 |
|
---|
20 | Establish OSSL_PARAM keys that any algorithms may become aware of
|
---|
21 | -----------------------------------------------------------------
|
---|
22 |
|
---|
23 | We already have known parameter keys:
|
---|
24 |
|
---|
25 | - "algor_id_param", also known as the macro `OSSL_CIPHER_PARAM_ALGORITHM_ID_PARAMS`.
|
---|
26 |
|
---|
27 | This is currently only specified for `EVP_CIPHER`, in support of
|
---|
28 | `EVP_CIPHER_param_to_asn1()` and `EVP_CIPHER_asn1_to_param()`
|
---|
29 |
|
---|
30 | - "algorithm-id", also known as the macro `OSSL_SIGNATURE_PARAM_ALGORITHM_ID`.
|
---|
31 |
|
---|
32 | This design proposes:
|
---|
33 |
|
---|
34 | 1. Adding a parameter key "algorithm-id-params", to replace "algor_id_param",
|
---|
35 | and deprecate the latter.
|
---|
36 | 2. Making both "algorithm-id" and "algorithm-id-params" generically available,
|
---|
37 | rather than only tied to `EVP_SIGNATURE` ("algorithm-id") or `EVP_CIPHER`
|
---|
38 | ("algor_id_param").
|
---|
39 |
|
---|
40 | This way, these parameters can be used in the exact same manner with other
|
---|
41 | operations, with the value of the AlgorithmIdentifier as well as its
|
---|
42 | parameters as octet strings, to be used and interpreted by applications and
|
---|
43 | provider implementations alike in whatever way they see fit.
|
---|
44 |
|
---|
45 | Applications can choose to add these in an `OSSL_PARAM` array, to be passed
|
---|
46 | with the multitude of initialization functions that take such an array, or
|
---|
47 | using specific operation `OSSL_PARAM` setters and getters (such as
|
---|
48 | `EVP_PKEY_CTX_set_params`), or using other available convenience functions
|
---|
49 | (see below).
|
---|
50 |
|
---|
51 | These parameter will have to be documented in the following files:
|
---|
52 |
|
---|
53 | - `doc/man7/provider-asym_cipher.pod`
|
---|
54 | - `doc/man7/provider-cipher.pod`
|
---|
55 | - `doc/man7/provider-digest.pod`
|
---|
56 | - `doc/man7/provider-kdf.pod`
|
---|
57 | - `doc/man7/provider-kem.pod`
|
---|
58 | - `doc/man7/provider-keyexch.pod`
|
---|
59 | - `doc/man7/provider-mac.pod`
|
---|
60 | - `doc/man7/provider-signature.pod`
|
---|
61 |
|
---|
62 | That should cover all algorithms that are, or should be possible to fetch by
|
---|
63 | AlgorithmIdentifier.algorithm, and for which there's potentially a relevant
|
---|
64 | AlgorithmIdentifier.parameters field.
|
---|
65 |
|
---|
66 | We may arguably want to consider `doc/man7/provider-keymgmt.pod` too, but
|
---|
67 | an AlgorithmIdentifier that's attached directly to a key is usually part of
|
---|
68 | a PrivKeyInfo or SubjectPublicKeyInfo structure, and those are handled by
|
---|
69 | encoders and decoders as those see fit, and there's no tangible reason why
|
---|
70 | that would have to change.
|
---|
71 |
|
---|
72 | Public convenience API
|
---|
73 | ----------------------
|
---|
74 |
|
---|
75 | For convenience, the following set of functions would be added to pass the
|
---|
76 | AlgorithmIdentifier parameter data to diverse operations, or to retrieve
|
---|
77 | such parameter data from them.
|
---|
78 |
|
---|
79 | ``` C
|
---|
80 | /*
|
---|
81 | * These two would essentially be aliases for EVP_CIPHER_param_to_asn1()
|
---|
82 | * and EVP_CIPHER_asn1_to_param().
|
---|
83 | */
|
---|
84 | EVP_CIPHER_CTX_set_algor_params(EVP_CIPHER_CTX *ctx, const X509_ALGOR *alg);
|
---|
85 | EVP_CIPHER_CTX_get_algor_params(EVP_CIPHER_CTX *ctx, X509_ALGOR *alg);
|
---|
86 | EVP_CIPHER_CTX_get_algor(EVP_CIPHER_CTX *ctx, X509_ALGOR **alg);
|
---|
87 |
|
---|
88 | EVP_MD_CTX_set_algor_params(EVP_MD_CTX *ctx, const X509_ALGOR *alg);
|
---|
89 | EVP_MD_CTX_get_algor_params(EVP_MD_CTX *ctx, X509_ALGOR *alg);
|
---|
90 | EVP_MD_CTX_get_algor(EVP_MD_CTX *ctx, X509_ALGOR **alg);
|
---|
91 |
|
---|
92 | EVP_MAC_CTX_set_algor_params(EVP_MAC_CTX *ctx, const X509_ALGOR *alg);
|
---|
93 | EVP_MAC_CTX_get_algor_params(EVP_MAC_CTX *ctx, X509_ALGOR *alg);
|
---|
94 | EVP_MAC_CTX_get_algor(EVP_MAC_CTX *ctx, X509_ALGOR **alg);
|
---|
95 |
|
---|
96 | EVP_KDF_CTX_set_algor_params(EVP_KDF_CTX *ctx, const X509_ALGOR *alg);
|
---|
97 | EVP_KDF_CTX_get_algor_params(EVP_KDF_CTX *ctx, X509_ALGOR *alg);
|
---|
98 | EVP_KDF_CTX_get_algor(EVP_KDF_CTX *ctx, X509_ALGOR **alg);
|
---|
99 |
|
---|
100 | EVP_PKEY_CTX_set_algor_params(EVP_PKEY_CTX *ctx, const X509_ALGOR *alg);
|
---|
101 | EVP_PKEY_CTX_get_algor_params(EVP_PKEY_CTX *ctx, X509_ALGOR *alg);
|
---|
102 | EVP_PKEY_CTX_get_algor(EVP_PKEY_CTX *ctx, X509_ALGOR **alg);
|
---|
103 | ```
|
---|
104 |
|
---|
105 | Note that all might not need to be added immediately, depending on if they
|
---|
106 | are considered useful or not. For future proofing, however, they should
|
---|
107 | probably all be added.
|
---|
108 |
|
---|
109 | Requirements on the providers
|
---|
110 | -----------------------------
|
---|
111 |
|
---|
112 | Providers that implement ciphers or any operation that uses asymmetric keys
|
---|
113 | will have to implement support for passing AlgorithmIdentifier parameter
|
---|
114 | data, and will have to process that data in whatever manner that's necessary
|
---|
115 | to meet the standards for that operation.
|
---|
116 |
|
---|
117 | Fallback strategies
|
---|
118 | -------------------
|
---|
119 |
|
---|
120 | There are no possible fallback strategies, which is fine, considering that
|
---|
121 | current provider functionality doesn't support passing AlgorithmIdentifier
|
---|
122 | parameter data at all (except for `EVP_CIPHER`), and therefore do not work
|
---|
123 | at all when such parameter data needs to be passed.
|
---|
124 |
|
---|
125 | -----
|
---|
126 |
|
---|
127 | -----
|
---|
128 |
|
---|
129 | Background / tl;dr
|
---|
130 | ------------------
|
---|
131 |
|
---|
132 | ### AlgorithmIdenfier parameter and how it's used
|
---|
133 |
|
---|
134 | OpenSSL has historically done a few tricks to not have to pass
|
---|
135 | AlgorithmIdenfier parameter data to the backend implementations of
|
---|
136 | cryptographic operations:
|
---|
137 |
|
---|
138 | - In some cases, they were passed as part of the lower level key structure
|
---|
139 | (for example, the `RSA` structure can also carry RSA-PSS parameters).
|
---|
140 | - In the `EVP_CIPHER` case, there is functionality to pass the parameter
|
---|
141 | data specifically.
|
---|
142 | - For asymmetric key operations, PKCS#7 and CMS support was added as
|
---|
143 | `EVP_PKEY` ctrls.
|
---|
144 |
|
---|
145 | With providers, some of that support was retained, but not others. Most
|
---|
146 | crucially, the `EVP_PKEY` ctrls for PKCS#7 and CMS were not retained,
|
---|
147 | because the way they were implemented violated the principle that provider
|
---|
148 | implementations *MUST NOT* share complex OpenSSL specific structures with
|
---|
149 | libcrypto.
|
---|
150 |
|
---|
151 | ### Usage examples
|
---|
152 |
|
---|
153 | Quite a lot of the available examples today revolve around CMS, with a
|
---|
154 | number of RFCs that specify what parameters should be passed with certain
|
---|
155 | operations / algorithms. This list is not exhaustive, the reader is
|
---|
156 | encouraged to research further usages.
|
---|
157 |
|
---|
158 | - [DSA](https://www.rfc-editor.org/rfc/rfc3370#section-3.1) signatures
|
---|
159 | typically have the domain parameters *p*, *q* and *g*.
|
---|
160 | - [RC2 key wrap](https://www.rfc-editor.org/rfc/rfc3370#section-4.3.2)
|
---|
161 | - [PBKDF2](https://www.rfc-editor.org/rfc/rfc3370#section-4.4.1)
|
---|
162 | - [3DES-CBC](https://www.rfc-editor.org/rfc/rfc3370#section-5.1)
|
---|
163 | - [RC2-CBC](https://www.rfc-editor.org/rfc/rfc3370#section-5.2)
|
---|
164 |
|
---|
165 | - [GOST 28147-89](https://www.rfc-editor.org/rfc/rfc4490.html#section-5.1)
|
---|
166 |
|
---|
167 | - [RSA-OAEP](https://www.rfc-editor.org/rfc/rfc8017#appendix-A.2.1)
|
---|
168 | - [RSA-PSS](https://www.rfc-editor.org/rfc/rfc8017#appendix-A.2.3)
|
---|
169 |
|
---|
170 | - [XOR-MD5](https://www.rfc-editor.org/rfc/rfc6210.html) is experimental,
|
---|
171 | but it does demonstrate the possibility of a parametrized hash algorithm.
|
---|
172 |
|
---|
173 | Some of it can be claimed to already have support in OpenSSL. However, this
|
---|
174 | is with old libcrypto code that has special knowledge of the algorithms that
|
---|
175 | are involved.
|
---|