xref: /freebsd/crypto/openssl/providers/implementations/exchange/ecx_exch.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1b077aed3SPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery  */
9b077aed3SPierre Pronchery 
10b077aed3SPierre Pronchery #include <openssl/crypto.h>
11b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
12b077aed3SPierre Pronchery #include <openssl/core_names.h>
13b077aed3SPierre Pronchery #include <openssl/params.h>
14b077aed3SPierre Pronchery #include <openssl/err.h>
15b077aed3SPierre Pronchery #include <openssl/proverr.h>
16b077aed3SPierre Pronchery #include "internal/cryptlib.h"
17b077aed3SPierre Pronchery #include "crypto/ecx.h"
18b077aed3SPierre Pronchery #include "prov/implementations.h"
19b077aed3SPierre Pronchery #include "prov/providercommon.h"
20*e7be843bSPierre Pronchery #include "prov/securitycheck.h"
21b077aed3SPierre Pronchery 
22b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_newctx_fn x25519_newctx;
23b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_newctx_fn x448_newctx;
24*e7be843bSPierre Pronchery static OSSL_FUNC_keyexch_init_fn x25519_init;
25*e7be843bSPierre Pronchery static OSSL_FUNC_keyexch_init_fn x448_init;
26b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_set_peer_fn ecx_set_peer;
27b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_derive_fn ecx_derive;
28b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_freectx_fn ecx_freectx;
29b077aed3SPierre Pronchery static OSSL_FUNC_keyexch_dupctx_fn ecx_dupctx;
30*e7be843bSPierre Pronchery static OSSL_FUNC_keyexch_gettable_ctx_params_fn ecx_gettable_ctx_params;
31*e7be843bSPierre Pronchery static OSSL_FUNC_keyexch_get_ctx_params_fn ecx_get_ctx_params;
32b077aed3SPierre Pronchery 
33b077aed3SPierre Pronchery /*
34b077aed3SPierre Pronchery  * What's passed as an actual key is defined by the KEYMGMT interface.
35b077aed3SPierre Pronchery  * We happen to know that our KEYMGMT simply passes ECX_KEY structures, so
36b077aed3SPierre Pronchery  * we use that here too.
37b077aed3SPierre Pronchery  */
38b077aed3SPierre Pronchery 
39b077aed3SPierre Pronchery typedef struct {
40b077aed3SPierre Pronchery     size_t keylen;
41b077aed3SPierre Pronchery     ECX_KEY *key;
42b077aed3SPierre Pronchery     ECX_KEY *peerkey;
43b077aed3SPierre Pronchery } PROV_ECX_CTX;
44b077aed3SPierre Pronchery 
ecx_newctx(void * provctx,size_t keylen)45b077aed3SPierre Pronchery static void *ecx_newctx(void *provctx, size_t keylen)
46b077aed3SPierre Pronchery {
47b077aed3SPierre Pronchery     PROV_ECX_CTX *ctx;
48b077aed3SPierre Pronchery 
49b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
50b077aed3SPierre Pronchery         return NULL;
51b077aed3SPierre Pronchery 
52b077aed3SPierre Pronchery     ctx = OPENSSL_zalloc(sizeof(PROV_ECX_CTX));
53*e7be843bSPierre Pronchery     if (ctx == NULL)
54b077aed3SPierre Pronchery         return NULL;
55b077aed3SPierre Pronchery 
56b077aed3SPierre Pronchery     ctx->keylen = keylen;
57b077aed3SPierre Pronchery 
58b077aed3SPierre Pronchery     return ctx;
59b077aed3SPierre Pronchery }
60b077aed3SPierre Pronchery 
x25519_newctx(void * provctx)61b077aed3SPierre Pronchery static void *x25519_newctx(void *provctx)
62b077aed3SPierre Pronchery {
63b077aed3SPierre Pronchery     return ecx_newctx(provctx, X25519_KEYLEN);
64b077aed3SPierre Pronchery }
65b077aed3SPierre Pronchery 
x448_newctx(void * provctx)66b077aed3SPierre Pronchery static void *x448_newctx(void *provctx)
67b077aed3SPierre Pronchery {
68b077aed3SPierre Pronchery     return ecx_newctx(provctx, X448_KEYLEN);
69b077aed3SPierre Pronchery }
70b077aed3SPierre Pronchery 
ecx_init(void * vecxctx,void * vkey,const char * algname)71*e7be843bSPierre Pronchery static int ecx_init(void *vecxctx, void *vkey, const char *algname)
72b077aed3SPierre Pronchery {
73b077aed3SPierre Pronchery     PROV_ECX_CTX *ecxctx = (PROV_ECX_CTX *)vecxctx;
74b077aed3SPierre Pronchery     ECX_KEY *key = vkey;
75b077aed3SPierre Pronchery 
76b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
77b077aed3SPierre Pronchery         return 0;
78b077aed3SPierre Pronchery 
79b077aed3SPierre Pronchery     if (ecxctx == NULL
80b077aed3SPierre Pronchery             || key == NULL
81b077aed3SPierre Pronchery             || key->keylen != ecxctx->keylen
82b077aed3SPierre Pronchery             || !ossl_ecx_key_up_ref(key)) {
83b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
84b077aed3SPierre Pronchery         return 0;
85b077aed3SPierre Pronchery     }
86b077aed3SPierre Pronchery 
87b077aed3SPierre Pronchery     ossl_ecx_key_free(ecxctx->key);
88b077aed3SPierre Pronchery     ecxctx->key = key;
89b077aed3SPierre Pronchery 
90*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
91*e7be843bSPierre Pronchery     if (!ossl_FIPS_IND_callback(key->libctx, algname, "Init"))
92*e7be843bSPierre Pronchery         return 0;
93*e7be843bSPierre Pronchery #endif
94b077aed3SPierre Pronchery     return 1;
95b077aed3SPierre Pronchery }
96b077aed3SPierre Pronchery 
x25519_init(void * vecxctx,void * vkey,ossl_unused const OSSL_PARAM params[])97*e7be843bSPierre Pronchery static int x25519_init(void *vecxctx, void *vkey,
98*e7be843bSPierre Pronchery                        ossl_unused const OSSL_PARAM params[])
99*e7be843bSPierre Pronchery {
100*e7be843bSPierre Pronchery     return ecx_init(vecxctx, vkey, "X25519");
101*e7be843bSPierre Pronchery }
102*e7be843bSPierre Pronchery 
x448_init(void * vecxctx,void * vkey,ossl_unused const OSSL_PARAM params[])103*e7be843bSPierre Pronchery static int x448_init(void *vecxctx, void *vkey,
104*e7be843bSPierre Pronchery                      ossl_unused const OSSL_PARAM params[])
105*e7be843bSPierre Pronchery {
106*e7be843bSPierre Pronchery     return ecx_init(vecxctx, vkey, "X448");
107*e7be843bSPierre Pronchery }
108*e7be843bSPierre Pronchery 
ecx_set_peer(void * vecxctx,void * vkey)109b077aed3SPierre Pronchery static int ecx_set_peer(void *vecxctx, void *vkey)
110b077aed3SPierre Pronchery {
111b077aed3SPierre Pronchery     PROV_ECX_CTX *ecxctx = (PROV_ECX_CTX *)vecxctx;
112b077aed3SPierre Pronchery     ECX_KEY *key = vkey;
113b077aed3SPierre Pronchery 
114b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
115b077aed3SPierre Pronchery         return 0;
116b077aed3SPierre Pronchery 
117b077aed3SPierre Pronchery     if (ecxctx == NULL
118b077aed3SPierre Pronchery             || key == NULL
119b077aed3SPierre Pronchery             || key->keylen != ecxctx->keylen
120b077aed3SPierre Pronchery             || !ossl_ecx_key_up_ref(key)) {
121b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
122b077aed3SPierre Pronchery         return 0;
123b077aed3SPierre Pronchery     }
124b077aed3SPierre Pronchery     ossl_ecx_key_free(ecxctx->peerkey);
125b077aed3SPierre Pronchery     ecxctx->peerkey = key;
126b077aed3SPierre Pronchery 
127b077aed3SPierre Pronchery     return 1;
128b077aed3SPierre Pronchery }
129b077aed3SPierre Pronchery 
ecx_derive(void * vecxctx,unsigned char * secret,size_t * secretlen,size_t outlen)130b077aed3SPierre Pronchery static int ecx_derive(void *vecxctx, unsigned char *secret, size_t *secretlen,
131b077aed3SPierre Pronchery                       size_t outlen)
132b077aed3SPierre Pronchery {
133b077aed3SPierre Pronchery     PROV_ECX_CTX *ecxctx = (PROV_ECX_CTX *)vecxctx;
134b077aed3SPierre Pronchery 
135b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
136b077aed3SPierre Pronchery         return 0;
137*e7be843bSPierre Pronchery     return ossl_ecx_compute_key(ecxctx->peerkey, ecxctx->key, ecxctx->keylen,
138*e7be843bSPierre Pronchery                                 secret, secretlen, outlen);
139b077aed3SPierre Pronchery }
140b077aed3SPierre Pronchery 
ecx_freectx(void * vecxctx)141b077aed3SPierre Pronchery static void ecx_freectx(void *vecxctx)
142b077aed3SPierre Pronchery {
143b077aed3SPierre Pronchery     PROV_ECX_CTX *ecxctx = (PROV_ECX_CTX *)vecxctx;
144b077aed3SPierre Pronchery 
145b077aed3SPierre Pronchery     ossl_ecx_key_free(ecxctx->key);
146b077aed3SPierre Pronchery     ossl_ecx_key_free(ecxctx->peerkey);
147b077aed3SPierre Pronchery 
148b077aed3SPierre Pronchery     OPENSSL_free(ecxctx);
149b077aed3SPierre Pronchery }
150b077aed3SPierre Pronchery 
ecx_dupctx(void * vecxctx)151b077aed3SPierre Pronchery static void *ecx_dupctx(void *vecxctx)
152b077aed3SPierre Pronchery {
153b077aed3SPierre Pronchery     PROV_ECX_CTX *srcctx = (PROV_ECX_CTX *)vecxctx;
154b077aed3SPierre Pronchery     PROV_ECX_CTX *dstctx;
155b077aed3SPierre Pronchery 
156b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
157b077aed3SPierre Pronchery         return NULL;
158b077aed3SPierre Pronchery 
159b077aed3SPierre Pronchery     dstctx = OPENSSL_zalloc(sizeof(*srcctx));
160*e7be843bSPierre Pronchery     if (dstctx == NULL)
161b077aed3SPierre Pronchery         return NULL;
162b077aed3SPierre Pronchery 
163b077aed3SPierre Pronchery     *dstctx = *srcctx;
164b077aed3SPierre Pronchery     if (dstctx->key != NULL && !ossl_ecx_key_up_ref(dstctx->key)) {
165b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
166b077aed3SPierre Pronchery         OPENSSL_free(dstctx);
167b077aed3SPierre Pronchery         return NULL;
168b077aed3SPierre Pronchery     }
169b077aed3SPierre Pronchery 
170b077aed3SPierre Pronchery     if (dstctx->peerkey != NULL && !ossl_ecx_key_up_ref(dstctx->peerkey)) {
171b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
172b077aed3SPierre Pronchery         ossl_ecx_key_free(dstctx->key);
173b077aed3SPierre Pronchery         OPENSSL_free(dstctx);
174b077aed3SPierre Pronchery         return NULL;
175b077aed3SPierre Pronchery     }
176b077aed3SPierre Pronchery 
177b077aed3SPierre Pronchery     return dstctx;
178b077aed3SPierre Pronchery }
179b077aed3SPierre Pronchery 
ecx_gettable_ctx_params(ossl_unused void * vctx,ossl_unused void * provctx)180*e7be843bSPierre Pronchery static const OSSL_PARAM *ecx_gettable_ctx_params(ossl_unused void *vctx,
181*e7be843bSPierre Pronchery                                                  ossl_unused void *provctx)
182*e7be843bSPierre Pronchery {
183*e7be843bSPierre Pronchery     static const OSSL_PARAM known_gettable_ctx_params[] = {
184*e7be843bSPierre Pronchery         OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
185*e7be843bSPierre Pronchery         OSSL_PARAM_END
186*e7be843bSPierre Pronchery     };
187*e7be843bSPierre Pronchery     return known_gettable_ctx_params;
188*e7be843bSPierre Pronchery }
189*e7be843bSPierre Pronchery 
ecx_get_ctx_params(ossl_unused void * vctx,OSSL_PARAM params[])190*e7be843bSPierre Pronchery static int ecx_get_ctx_params(ossl_unused void *vctx, OSSL_PARAM params[])
191*e7be843bSPierre Pronchery {
192*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
193*e7be843bSPierre Pronchery     int approved = 0;
194*e7be843bSPierre Pronchery     OSSL_PARAM *p = OSSL_PARAM_locate(params,
195*e7be843bSPierre Pronchery                                       OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR);
196*e7be843bSPierre Pronchery 
197*e7be843bSPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_int(p, approved))
198*e7be843bSPierre Pronchery         return 0;
199*e7be843bSPierre Pronchery #endif
200*e7be843bSPierre Pronchery     return 1;
201*e7be843bSPierre Pronchery }
202*e7be843bSPierre Pronchery 
203b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_x25519_keyexch_functions[] = {
204b077aed3SPierre Pronchery     { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))x25519_newctx },
205*e7be843bSPierre Pronchery     { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))x25519_init },
206b077aed3SPierre Pronchery     { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ecx_derive },
207b077aed3SPierre Pronchery     { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ecx_set_peer },
208b077aed3SPierre Pronchery     { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ecx_freectx },
209b077aed3SPierre Pronchery     { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ecx_dupctx },
210*e7be843bSPierre Pronchery     { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))ecx_get_ctx_params },
211*e7be843bSPierre Pronchery     { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
212*e7be843bSPierre Pronchery       (void (*)(void))ecx_gettable_ctx_params },
213*e7be843bSPierre Pronchery     OSSL_DISPATCH_END
214b077aed3SPierre Pronchery };
215b077aed3SPierre Pronchery 
216b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_x448_keyexch_functions[] = {
217b077aed3SPierre Pronchery     { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))x448_newctx },
218*e7be843bSPierre Pronchery     { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))x448_init },
219b077aed3SPierre Pronchery     { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ecx_derive },
220b077aed3SPierre Pronchery     { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ecx_set_peer },
221b077aed3SPierre Pronchery     { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ecx_freectx },
222b077aed3SPierre Pronchery     { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ecx_dupctx },
223*e7be843bSPierre Pronchery     { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))ecx_get_ctx_params },
224*e7be843bSPierre Pronchery     { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
225*e7be843bSPierre Pronchery       (void (*)(void))ecx_gettable_ctx_params },
226*e7be843bSPierre Pronchery     OSSL_DISPATCH_END
227b077aed3SPierre Pronchery };
228