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