]> git.ipfire.org Git - thirdparty/openssl.git/blob - doc/internal/man7/EVP_PKEY.pod
Cache legacy keys instead of downgrading them
[thirdparty/openssl.git] / doc / internal / man7 / EVP_PKEY.pod
1 =pod
2
3 =head1 NAME
4
5 EVP_PKEY - an internal description
6
7 =head1 SYNOPSIS
8
9 #include "crypto/evp.h"
10
11 typedef struct evp_pkey_st EVP_PKEY;
12
13 =head1 DESCRIPTION
14
15 I<This is not a complete description yet>
16
17 B<EVP_PKEY> is a complex type that's essentially a container for
18 private/public key pairs, but has had other uses as well.
19
20 =for comment "uses" could as well be "abuses"...
21
22 The private/public key pair that an B<EVP_PKEY> contains is refered to
23 as its "internal key" or "origin" (the reason for "origin" is
24 explained further down, in L</Export cache for provider operations>),
25 and it can take one of the following forms:
26
27 =over 4
28
29 =item legacy origin
30
31 This is the form that an B<EVP_PKEY> in OpenSSL prior to 3.0 had. The
32 internal key in the B<EVP_PKEY> is a pointer to the low-level key
33 types, such as B<RSA>, B<DSA> and B<EC>, or an engine driven
34 structure, and is governed by an associated L<EVP_PKEY_METHOD(3)> and
35 an L<EVP_PKEY_ASN1_METHOD(3)>.
36
37 The functions available through those two method structures get full
38 access to the B<EVP_PKEY> and therefore have a lot of freedom to
39 modify whatever they want. This also means that an B<EVP_PKEY> is a
40 shared structure between libcrypto and any ENGINE that serves such
41 methods.
42
43 =item provider-native origin
44
45 This is a new form in OpenSSL 3.0, which permits providers to hold the
46 key data (see L<provider-keymgmt(7)>). The internal key in the
47 B<EVP_PKEY> is a pointer to that key data held by the provider, and
48 is governed by an associated L<EVP_KEYMGMT(3)> method structure.
49
50 The functions available through the L<EVP_KEYMGMT(3)> have no access
51 to the B<EVP_PKEY>, and can therefore not make any direct changes.
52 Similarly, the key data that the B<EVP_PKEY> points at is only known
53 to the functions pointed at in the L<EVP_KEYMGMT(3)>.
54
55 =back
56
57 These two forms can never co-exist in the same B<EVP_PKEY>, the main
58 reason being that having both at the same time will create problems
59 with synchronising between the two forms, and potentially make it
60 confusing which one of the two is the origin.
61
62 =head2 Key mutability
63
64 The B<EVP_PKEY> internal keys are mutable.
65
66 This is especially visible with internal legacy keys, since they can
67 be extracted with functions like L<EVP_PKEY_get0_RSA(3)> and then
68 modified at will with functions like L<RSA_set0_key(3)>.
69
70 Internal provider native keys are also possible to be modified, if the
71 associated L<EVP_KEYMGMT(3)> implementation allows it. This is done
72 with L<EVP_PKEY_set_params(3)> and its specialised derivatives. The
73 OpenSSL providers allow it for the following:
74
75 =over 4
76
77 =item DH, EC, X25519, X448:
78
79 It's possible to set the encoded public key. This is supported in
80 particular through L<EVP_PKEY_set1_encoded_public_key(3)>.
81
82 =item EC:
83
84 It's possible to flip the ECDH cofactor mode.
85
86 =back
87
88 Every time the B<EVP_PKEY> internal key mutates, an internal dirty
89 count is incremented. The need for a dirty count is explained further
90 in L</Export cache for provider operations>.
91
92 For provider native origin keys, this doesn't require any help from
93 the L<EVP_KEYMGMT(3)>, the dirty count is maintained in the B<EVP_PKEY>
94 itself, and is incremented every time L<EVP_PKEY_set_params(3)> or its
95 specialised derivatives are called.
96 For legacy origin keys, this requires the associated
97 L<EVP_PKEY_ASN1_METHOD(3)> to implement the dirty_cnt() function. All
98 of OpenSSL's built-in L<EVP_PKEY_ASN1_METHOD(3)> implement this
99 function.
100
101 =head2 Export cache for provider operations
102
103 OpenSSL 3.0 can handle operations such as signing, encrypting, etc in
104 diverse providers, potentially others than the provider of the
105 L<EVP_KEYMGMT(3)>. Two providers, possibly from different vendors,
106 can't be expected to share internal key structures. There are
107 therefore instances where key data will need to be exported to the
108 provider that is going to perform the operation (this also implies
109 that every provider that implements a key pair based operation must
110 also implement an L<EVP_KEYMGMT(3)>).
111
112 For performance reasons, libcrypto tries to minimize the need to
113 perform such an export, so it maintains a cache of such exports in the
114 B<EVP_PKEY>. Each cache entry has two items, a pointer to the
115 provider side key data and the associated L<EVP_KEYMGMT(3)>.
116
117 I<This cache is often referred to as the "operation key cache", and
118 the key data that the cached keys came from is the "origin", and since
119 there are two forms of the latter, we have the "legacy origin" and the
120 "provider native origin".>
121
122 The export to the operation key cache can be performed independent of
123 what form the origin has.
124 For a legacy origin, this requires that the associated
125 L<EVP_PKEY_ASN1_METHOD(3)> implements the functions export_to() and
126 dirty_cnt().
127 For a provider native origin, this requires that the associated
128 L<EVP_KEYMGMT(3)> implements the OSSL_FUNC_keymgmt_export() function
129 (see L<provider-keymgmt(7)>).
130 In all cases, the receiving L<EVP_KEYMGMT(3)> (the one associated with
131 the exported key data) must implement OSSL_FUNC_keymgmt_import().
132
133 If such caching isn't supported, the operations that can be performed
134 with that key are limited to the same backend as the origin key
135 (ENGINE for legacy origin keys, provider for provider side origin
136 keys).
137
138 =head3 Exporting implementation details
139
140
141 Exporting a key to the operation cache involves the following:
142
143 =over 4
144
145 =item 1.
146
147 Check if the dirty count for the internal origin key has changed since
148 the previous time. This is done by comparing it with a copy of the
149 dirty count, which is maintained by the export function.
150
151 If the dirty count has changed, the export cache is cleared.
152
153 =item 2.
154
155 Check if there's an entry in the export cache with the same
156 L<EVP_KEYMGMT(3)> that's the same provider that an export is to be
157 made to (which is the provider that's going to perform an operation
158 for which the current B<EVP_PKEY> is going to be used).
159
160 If such an entry is found, nothing more is done, the key data and
161 L<EVP_KEYMGMT(3)> found in that export cache entry will be used for
162 the operation to be performed.
163
164 =item 3.
165
166 Export the internal origin key to the provider, using the appropriate
167 method.
168
169 For legacy origin keys, that's done with the help of the
170 L<EVP_PKEY_ASN1_METHOD(3)> export_to() function.
171
172 For provider native origin keys, that's done by retrieving the key
173 data in L<OSSL_PARAM(3)> form from the origin keys, using the
174 OSSL_FUNC_keymgmt_export() functions of the associated
175 L<EVP_KEYMGMT(3)>, and sending that data to the L<EVP_KEYMGMT(3)> of
176 the provider that's to perform the operation, using its
177 OSSL_FUNC_keymgmt_import() function.
178
179 =back
180
181 =head2 Changing a key origin
182
183 It is never possible to change the origin of a key. An B<EVP_PKEY> with a legacy
184 origin will I<never> be upgraded to become an B<EVP_PKEY> with a provider
185 native origin. Instead, we have the operation cache as described above, that
186 takes care of the needs of the diverse operation the application may want to
187 perform.
188
189 Similarly an B<EVP_PKEY> with a provider native origin, will I<never> be
190 downgraded to be I<transformed> into an B<EVP_PKEY> with a legacy origin.
191 Instead we may have a cached copy of the provider key in legacy form. Once the
192 cached copy is created it is never updated. Changes made to the provider key
193 are not reflected back in the cached legacy copy. Similarly changes made to the
194 cached legacy copy are not reflected back in the provider key.
195
196 =head1 SEE ALSO
197
198 L<provider-keymgmt(7)>
199
200 =head1 COPYRIGHT
201
202 Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
203
204 Licensed under the Apache License 2.0 (the "License"). You may not use
205 this file except in compliance with the License. You can obtain a copy
206 in the file LICENSE in the source distribution or at
207 L<https://www.openssl.org/source/license.html>.
208
209 =cut