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