forked from openssh/openssh-portable
-
-
Notifications
You must be signed in to change notification settings - Fork 45
/
cipher-ctr-mt-provider.c
390 lines (335 loc) · 11.8 KB
/
cipher-ctr-mt-provider.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
/*
* OpenSSH Multi-threaded AES-CTR Cipher Provider for OpenSSL 3
*
* Author: Chris Rapier <[email protected]>
* Copyright (c) 2022 Pittsburgh Supercomputing Center. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* based on vienere.c from https://github.com/provider-corner/vigenere by
* Richard Levitte provided under a CC0 Public License. */
#include "includes.h"
/* only for systems with OSSL 3.0+ */
#ifdef WITH_OPENSSL3
#include <sys/types.h>
#include <string.h>
#include <openssl/core.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/err.h>
#include "xmalloc.h"
#include "ossl3-provider-err.h"
#include "num.h"
#include "cipher-ctr-mt-functions.h"
#define ERR_HANDLE(ctx) ((ctx)->provctx->proverr_handle)
/* forward declartion of cipher functions */
/* cipher context functions */
OSSL_FUNC_cipher_newctx_fn aes_mt_newctx_256;
OSSL_FUNC_cipher_newctx_fn aes_mt_newctx_192;
OSSL_FUNC_cipher_newctx_fn aes_mt_newctx_128;
OSSL_FUNC_cipher_freectx_fn aes_mt_freectx;
/* param related function*/
static OSSL_FUNC_cipher_get_params_fn aes_mt_get_params_256;
static OSSL_FUNC_cipher_get_params_fn aes_mt_get_params_192;
static OSSL_FUNC_cipher_get_params_fn aes_mt_get_params_128;
static OSSL_FUNC_cipher_gettable_params_fn aes_mt_gettable_params;
static OSSL_FUNC_cipher_set_ctx_params_fn aes_mt_set_ctx_params;
static OSSL_FUNC_cipher_get_ctx_params_fn aes_mt_get_ctx_params;
static OSSL_FUNC_cipher_settable_ctx_params_fn aes_mt_settable_ctx_params;
static OSSL_FUNC_cipher_gettable_ctx_params_fn aes_mt_gettable_ctx_params;
/* en/decipher functions */
OSSL_FUNC_cipher_encrypt_init_fn aes_mt_start_threads;
OSSL_FUNC_cipher_decrypt_init_fn aes_mt_start_threads;
OSSL_FUNC_cipher_update_fn aes_mt_do_cipher;
/* provider context */
static OSSL_FUNC_provider_query_operation_fn aes_mt_prov_query;
static OSSL_FUNC_provider_get_reason_strings_fn aes_mt_prov_reasons;
static OSSL_FUNC_provider_teardown_fn aes_mt_prov_teardown;
static OSSL_FUNC_provider_get_params_fn aes_mt_prov_get_params;
OSSL_provider_init_fn OSSL_provider_init; /* need this? */
/* error functions */
OSSL_FUNC_core_new_error_fn *c_new_error;
OSSL_FUNC_core_set_error_debug_fn *c_set_error_debug;
OSSL_FUNC_core_vset_error_fn *c_vset_error;
OSSL_FUNC_core_set_error_mark_fn *c_set_error_mark;
OSSL_FUNC_core_clear_last_error_mark_fn *c_clear_last_error_mark;
OSSL_FUNC_core_pop_error_to_mark_fn *c_pop_error_to_mark;
/* Errors used in this provider */
#define AES_MT_E_MALLOC 1
#define AES_MT_ONGOING_OPERATION 2
#define AES_MT_BAD_KEYLEN 3
/* typedef for function pointers */
typedef void(*fptr_t)(void);
/* all of the various arrays we need */
/* BAD_KEYLEN isn't being used at the moment */
const OSSL_ITEM reasons[] = {
{ AES_MT_E_MALLOC, "Memory allocation failure" },
{ AES_MT_ONGOING_OPERATION, "Operation underway" },
{ AES_MT_BAD_KEYLEN, "Only 256, 192, and 128 Key lengths are supported" },
{ 0, NULL } /* Termination */
};
/* function mapping for 256|192|128 key lengths */
const OSSL_DISPATCH aes_mt_funcs_256[] = {
{ OSSL_FUNC_CIPHER_NEWCTX, (fptr_t)aes_mt_newctx_256 } ,
{ OSSL_FUNC_CIPHER_FREECTX, (fptr_t)aes_mt_freectx },
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (fptr_t)aes_mt_start_threads },
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (fptr_t)aes_mt_start_threads },
{ OSSL_FUNC_CIPHER_UPDATE, (fptr_t)aes_mt_do_cipher },
{ OSSL_FUNC_CIPHER_GET_PARAMS, (fptr_t)aes_mt_get_params_256 },
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (fptr_t)aes_mt_gettable_params },
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (fptr_t)aes_mt_get_ctx_params },
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
(fptr_t)aes_mt_gettable_ctx_params },
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (fptr_t)aes_mt_set_ctx_params },
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
(fptr_t)aes_mt_settable_ctx_params },
{ 0, NULL }
};
const OSSL_DISPATCH aes_mt_funcs_192[] = {
{ OSSL_FUNC_CIPHER_NEWCTX, (fptr_t)aes_mt_newctx_192 } ,
{ OSSL_FUNC_CIPHER_FREECTX, (fptr_t)aes_mt_freectx },
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (fptr_t)aes_mt_start_threads },
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (fptr_t)aes_mt_start_threads },
{ OSSL_FUNC_CIPHER_UPDATE, (fptr_t)aes_mt_do_cipher },
{ OSSL_FUNC_CIPHER_GET_PARAMS, (fptr_t)aes_mt_get_params_192 },
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (fptr_t)aes_mt_gettable_params },
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (fptr_t)aes_mt_get_ctx_params },
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
(fptr_t)aes_mt_gettable_ctx_params },
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (fptr_t)aes_mt_set_ctx_params },
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
(fptr_t)aes_mt_settable_ctx_params },
{ 0, NULL }
};
const OSSL_DISPATCH aes_mt_funcs_128[] = {
{ OSSL_FUNC_CIPHER_NEWCTX, (fptr_t)aes_mt_newctx_128 } ,
{ OSSL_FUNC_CIPHER_FREECTX, (fptr_t)aes_mt_freectx },
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (fptr_t)aes_mt_start_threads },
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (fptr_t)aes_mt_start_threads },
{ OSSL_FUNC_CIPHER_UPDATE, (fptr_t)aes_mt_do_cipher },
{ OSSL_FUNC_CIPHER_GET_PARAMS, (fptr_t)aes_mt_get_params_128 },
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (fptr_t)aes_mt_gettable_params },
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (fptr_t)aes_mt_get_ctx_params },
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
(fptr_t)aes_mt_gettable_ctx_params },
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (fptr_t)aes_mt_set_ctx_params },
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
(fptr_t)aes_mt_settable_ctx_params },
{ 0, NULL }
};
/* the ciphers found in this provider */
const OSSL_ALGORITHM aes_mt_ciphers[] = {
{ "aes_ctr_mt_256", "provider=hpnssh", aes_mt_funcs_256, NULL },
{ "aes_ctr_mt_192", "provider=hpnssh", aes_mt_funcs_192, NULL },
{ "aes_ctr_mt_128", "provider=hpnssh", aes_mt_funcs_128, NULL },
{ NULL, NULL, NULL, NULL }
};
/* function mapping for provider methods */
const OSSL_DISPATCH provider_functions[] = {
{ OSSL_FUNC_PROVIDER_TEARDOWN, (fptr_t)aes_mt_prov_teardown },
{ OSSL_FUNC_PROVIDER_QUERY_OPERATION, (fptr_t)aes_mt_prov_query },
{ OSSL_FUNC_PROVIDER_GET_PARAMS, (fptr_t)aes_mt_prov_get_params },
{ OSSL_FUNC_PROVIDER_GET_REASON_STRINGS, (fptr_t)aes_mt_prov_reasons },
{ 0, NULL }
};
static const OSSL_PARAM ctx_get_param_table[] = {
{ "keylen", OSSL_PARAM_UNSIGNED_INTEGER, NULL, sizeof(size_t), 0 },
{ NULL, 0, NULL, 0, 0 },
};
static const OSSL_PARAM cipher_get_param_table[] = {
{ "blocksize", OSSL_PARAM_UNSIGNED_INTEGER, NULL, sizeof(size_t), 0 },
{ "keylen", OSSL_PARAM_UNSIGNED_INTEGER, NULL, sizeof(size_t), 0 },
{ NULL, 0, NULL, 0, 0 },
};
static const OSSL_PARAM cipher_set_param_table[] = {
{ "keylen", OSSL_PARAM_UNSIGNED_INTEGER, NULL, sizeof(size_t), 0 },
{ NULL, 0, NULL, 0, 0 },
};
/* provider functions start here */
static void provider_ctx_free(struct provider_ctx_st *ctx)
{
if (ctx != NULL)
proverr_free_handle(ctx->proverr_handle);
free(ctx);
}
static struct provider_ctx_st *provider_ctx_new(const OSSL_CORE_HANDLE *core,
const OSSL_DISPATCH *in)
{
struct provider_ctx_st *ctx;
if ((ctx = malloc(sizeof(*ctx))) != NULL
&& (ctx->proverr_handle = proverr_new_handle(core, in)) != NULL) {
ctx->core_handle = core;
} else {
provider_ctx_free(ctx);
ctx = NULL;
}
return ctx;
}
/* returns the appropriate algo table for the requested function
* in this case we should only be working with OP_CIPHER */
const OSSL_ALGORITHM *aes_mt_prov_query(void *provctx, int operation_id,
int *no_store)
{
switch (operation_id) {
case OSSL_OP_CIPHER:
return aes_mt_ciphers;
}
return NULL;
}
const OSSL_ITEM *aes_mt_prov_reasons(void *provctx)
{
return reasons;
}
static int aes_mt_prov_get_params(void *provctx, OSSL_PARAM *params)
{
OSSL_PARAM *p;
int ok = 1;
char *VERSION="1.0";
char *BUILDTYPE="[email protected]";
for(p = params; p->key != NULL; p++)
if (strcasecmp(p->key, "version") == 0) {
*(const void **)p->data = VERSION;
p->return_size = strlen(VERSION);
} else if (strcasecmp(p->key, "buildinfo") == 0
&& BUILDTYPE[0] != '\0') {
*(const void **)p->data = BUILDTYPE;
p->return_size = strlen(BUILDTYPE);
}
return ok;
}
/* The function that tears down this provider */
static void aes_mt_prov_teardown(void *vprovctx)
{
provider_ctx_free(vprovctx);
}
int OSSL_provider_init(const OSSL_CORE_HANDLE *core,
const OSSL_DISPATCH *in,
const OSSL_DISPATCH **out,
void **vprovctx)
{
if ((*vprovctx = provider_ctx_new(core, in)) == NULL)
return 0;
*out = provider_functions;
return 1;
}
/* parameter functions for 256|192|128 bit key lengths */
static int aes_mt_get_params_256(OSSL_PARAM params[])
{
OSSL_PARAM *p;
int ok = 1;
for (p = params; p->key != NULL; p++) {
if (strcasecmp(p->key, "blocksize") == 0)
if (provnum_set_size_t(p, AES_BLOCK_SIZE) < 0) {
ok = 0;
continue;
}
if (strcasecmp(p->key, "keylen") == 0) {
size_t keyl = 32;
if (provnum_set_size_t(p, keyl) < 0) {
ok = 0;
continue;
}
}
}
return ok;
}
static int aes_mt_get_params_192(OSSL_PARAM params[])
{
OSSL_PARAM *p;
int ok = 1;
for (p = params; p->key != NULL; p++) {
if (strcasecmp(p->key, "blocksize") == 0)
if (provnum_set_size_t(p, AES_BLOCK_SIZE) < 0) {
ok = 0;
continue;
}
if (strcasecmp(p->key, "keylen") == 0) {
size_t keyl = 24;
if (provnum_set_size_t(p, keyl) < 0) {
ok = 0;
continue;
}
}
}
return ok;
}
static int aes_mt_get_params_128(OSSL_PARAM params[])
{
OSSL_PARAM *p;
int ok = 1;
for (p = params; p->key != NULL; p++) {
if (strcasecmp(p->key, "blocksize") == 0)
if (provnum_set_size_t(p, AES_BLOCK_SIZE) < 0) {
ok = 0;
continue;
}
if (strcasecmp(p->key, "keylen") == 0) {
size_t keyl = 16;
if (provnum_set_size_t(p, keyl) < 0) {
ok = 0;
continue;
}
}
}
return ok;
}
/* Parameters that libcrypto can get from this implementation */
static const OSSL_PARAM *aes_mt_gettable_params(void *provctx)
{
return cipher_get_param_table;
}
static const OSSL_PARAM *aes_mt_gettable_ctx_params(void *cctx, void *provctx)
{
return ctx_get_param_table;
}
static int aes_mt_get_ctx_params(void *vctx, OSSL_PARAM params[])
{
struct aes_mt_ctx_st *ctx = vctx;
int ok = 1;
if (ctx->keylen > 0) {
OSSL_PARAM *p;
for (p = params; p->key != NULL; p++)
if (strcasecmp(p->key, "keylen") == 0
&& provnum_set_size_t(p, ctx->keylen) < 0) {
ok = 0;
continue;
}
}
return ok;
}
/* Parameters that libcrypto can send to this implementation */
static const OSSL_PARAM *aes_mt_settable_ctx_params(void *cctx, void *provctx)
{
return cipher_set_param_table;
}
static int aes_mt_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
struct aes_mt_ctx_st *ctx = vctx;
const OSSL_PARAM *p;
int ok = 1;
if (ctx->ongoing) {
ERR_raise(ERR_HANDLE(ctx), AES_MT_ONGOING_OPERATION);
return 0;
}
for (p = params; p->key != NULL; p++)
if (strcasecmp(p->key, "keylen") == 0) {
size_t keyl = 0;
if (provnum_get_size_t(&keyl, p) < 0) {
ok = 0;
continue;
}
ctx->keylen = keyl;
}
return ok;
}
#endif /*WITH_OPENSSL3*/