Test that EVP_default_properties_is_fips_enabled() works early
[openssl.git] / test / tls-provider.c
1 /*
2  * Copyright 2019-2020 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 <string.h>
11 #include <openssl/core_names.h>
12 #include <openssl/core_dispatch.h>
13 #include <openssl/rand.h>
14 #include <openssl/params.h>
15 /* For TLS1_3_VERSION */
16 #include <openssl/ssl.h>
17
18 int tls_provider_init(const OSSL_CORE_HANDLE *handle,
19                       const OSSL_DISPATCH *in,
20                       const OSSL_DISPATCH **out,
21                       void **provctx);
22
23 #define XOR_KEY_SIZE 32
24
25 /*
26  * Top secret. This algorithm only works if no one knows what this number is.
27  * Please don't tell anyone what it is.
28  * 
29  * This algorithm is for testing only - don't really use it!
30  */
31 static const unsigned char private_constant[XOR_KEY_SIZE] = {
32     0xd3, 0x6b, 0x54, 0xec, 0x5b, 0xac, 0x89, 0x96, 0x8c, 0x2c, 0x66, 0xa5,
33     0x67, 0x0d, 0xe3, 0xdd, 0x43, 0x69, 0xbc, 0x83, 0x3d, 0x60, 0xc7, 0xb8,
34     0x2b, 0x1c, 0x5a, 0xfd, 0xb5, 0xcd, 0xd0, 0xf8
35 };
36
37 typedef struct xorkey_st {
38     unsigned char privkey[XOR_KEY_SIZE];
39     unsigned char pubkey[XOR_KEY_SIZE];
40     int hasprivkey;
41     int haspubkey;
42 } XORKEY;
43
44 /* We define a dummy TLS group called "xorgroup" for test purposes */
45
46 static unsigned int group_id = 0; /* IANA reserved for private use */
47 static unsigned int secbits = 128;
48 static unsigned int mintls = TLS1_3_VERSION;
49 static unsigned int maxtls = 0;
50 static unsigned int mindtls = -1;
51 static unsigned int maxdtls = -1;
52
53 #define GROUP_NAME "xorgroup"
54 #define GROUP_NAME_INTERNAL "xorgroup-int"
55 #define ALGORITHM "XOR"
56
57 static const OSSL_PARAM xor_group_params[] = {
58     OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME,
59                            GROUP_NAME, sizeof(GROUP_NAME)),
60     OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL,
61                            GROUP_NAME_INTERNAL, sizeof(GROUP_NAME_INTERNAL)),
62     OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_ALG, ALGORITHM,
63                            sizeof(ALGORITHM)),
64     OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_ID, &group_id),
65     OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS, &secbits),
66     OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS, &mintls),
67     OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, &maxtls),
68     OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, &mindtls),
69     OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, &maxdtls),
70     OSSL_PARAM_END
71 };
72
73 static int tls_prov_get_capabilities(void *provctx, const char *capability,
74                                      OSSL_CALLBACK *cb, void *arg)
75 {
76     /* We're only adding one group so we only call the callback once */
77     if (strcmp(capability, "TLS-GROUP") == 0)
78         return cb(xor_group_params, arg);
79
80     /* We don't support this capability */
81     return 0;
82 }
83
84 /*
85  * Dummy "XOR" Key Exchange algorithm. We just xor the private and public keys
86  * together. Don't use this!
87  */
88
89 static OSSL_FUNC_keyexch_newctx_fn xor_newctx;
90 static OSSL_FUNC_keyexch_init_fn xor_init;
91 static OSSL_FUNC_keyexch_set_peer_fn xor_set_peer;
92 static OSSL_FUNC_keyexch_derive_fn xor_derive;
93 static OSSL_FUNC_keyexch_freectx_fn xor_freectx;
94 static OSSL_FUNC_keyexch_dupctx_fn xor_dupctx;
95
96 typedef struct {
97     XORKEY *key;
98     XORKEY *peerkey;
99 } PROV_XOR_CTX;
100
101 static void *xor_newctx(void *provctx)
102 {
103     PROV_XOR_CTX *pxorctx = OPENSSL_zalloc(sizeof(PROV_XOR_CTX));
104
105     if (pxorctx == NULL)
106         return NULL;
107
108     return pxorctx;
109 }
110
111 static int xor_init(void *vpxorctx, void *vkey)
112 {
113     PROV_XOR_CTX *pxorctx = (PROV_XOR_CTX *)vpxorctx;
114
115     if (pxorctx == NULL || vkey == NULL)
116         return 0;
117     pxorctx->key = vkey;
118     return 1;
119 }
120
121 static int xor_set_peer(void *vpxorctx, void *vpeerkey)
122 {
123     PROV_XOR_CTX *pxorctx = (PROV_XOR_CTX *)vpxorctx;
124
125     if (pxorctx == NULL || vpeerkey == NULL)
126         return 0;
127     pxorctx->peerkey = vpeerkey;
128     return 1;
129 }
130
131 static int xor_derive(void *vpxorctx, unsigned char *secret, size_t *secretlen,
132                       size_t outlen)
133 {
134     PROV_XOR_CTX *pxorctx = (PROV_XOR_CTX *)vpxorctx;
135     int i;
136
137     if (pxorctx->key == NULL || pxorctx->peerkey == NULL)
138         return 0;
139
140     *secretlen = XOR_KEY_SIZE;
141     if (secret == NULL)
142         return 1;
143
144     if (outlen < XOR_KEY_SIZE)
145         return 0;
146
147     for (i = 0; i < XOR_KEY_SIZE; i++)
148         secret[i] = pxorctx->key->privkey[i] ^ pxorctx->peerkey->pubkey[i];
149
150     return 1;
151 }
152
153 static void xor_freectx(void *pxorctx)
154 {
155     OPENSSL_free(pxorctx);
156 }
157
158 static void *xor_dupctx(void *vpxorctx)
159 {
160     PROV_XOR_CTX *srcctx = (PROV_XOR_CTX *)vpxorctx;
161     PROV_XOR_CTX *dstctx;
162
163     dstctx = OPENSSL_zalloc(sizeof(*srcctx));
164     if (dstctx == NULL)
165         return NULL;
166
167     *dstctx = *srcctx;
168
169     return dstctx;
170 }
171
172 static const OSSL_DISPATCH xor_keyexch_functions[] = {
173     { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))xor_newctx },
174     { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))xor_init },
175     { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))xor_derive },
176     { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))xor_set_peer },
177     { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))xor_freectx },
178     { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))xor_dupctx },
179     { 0, NULL }
180 };
181
182 static const OSSL_ALGORITHM tls_prov_keyexch[] = {
183     /*
184      * Obviously this is not FIPS approved, but in order to test in conjuction
185      * with the FIPS provider we pretend that it is.
186      */
187     { "XOR", "provider=tls-provider,fips=yes", xor_keyexch_functions },
188     { NULL, NULL, NULL }
189 };
190
191 /* Key Management for the dummy XOR key exchange algorithm */
192
193 static OSSL_FUNC_keymgmt_new_fn xor_newdata;
194 static OSSL_FUNC_keymgmt_free_fn xor_freedata;
195 static OSSL_FUNC_keymgmt_has_fn xor_has;
196 static OSSL_FUNC_keymgmt_copy_fn xor_copy;
197 static OSSL_FUNC_keymgmt_gen_init_fn xor_gen_init;
198 static OSSL_FUNC_keymgmt_gen_set_params_fn xor_gen_set_params;
199 static OSSL_FUNC_keymgmt_gen_settable_params_fn xor_gen_settable_params;
200 static OSSL_FUNC_keymgmt_gen_fn xor_gen;
201 static OSSL_FUNC_keymgmt_gen_cleanup_fn xor_gen_cleanup;
202 static OSSL_FUNC_keymgmt_get_params_fn xor_get_params;
203 static OSSL_FUNC_keymgmt_gettable_params_fn xor_gettable_params;
204 static OSSL_FUNC_keymgmt_set_params_fn xor_set_params;
205 static OSSL_FUNC_keymgmt_settable_params_fn xor_settable_params;
206
207 static void *xor_newdata(void *provctx)
208 {
209     return OPENSSL_zalloc(sizeof(XORKEY));
210 }
211
212 static void xor_freedata(void *keydata)
213 {
214     OPENSSL_free(keydata);
215 }
216
217 static int xor_has(void *vkey, int selection)
218 {
219     XORKEY *key = vkey;
220     int ok = 0;
221
222     if (key != NULL) {
223         ok = 1;
224
225         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
226             ok = ok && key->haspubkey;
227         if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
228             ok = ok && key->hasprivkey;
229     }
230     return ok;
231 }
232
233 static int xor_copy(void *vtokey, const void *vfromkey, int selection)
234 {
235     XORKEY *tokey = vtokey;
236     const XORKEY *fromkey = vfromkey;
237     int ok = 0;
238
239     if (tokey != NULL && fromkey != NULL) {
240         ok = 1;
241
242         if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
243             if (fromkey->haspubkey) {
244                 memcpy(tokey->pubkey, fromkey->pubkey, XOR_KEY_SIZE);
245                 tokey->haspubkey = 1;
246             } else {
247                 tokey->haspubkey = 0;
248             }
249         }
250         if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
251             if (fromkey->hasprivkey) {
252                 memcpy(tokey->privkey, fromkey->privkey, XOR_KEY_SIZE);
253                 tokey->hasprivkey = 1;
254             } else {
255                 tokey->hasprivkey = 0;
256             }
257         }
258     }
259     return ok;
260 }
261
262 static ossl_inline int xor_get_params(void *vkey, OSSL_PARAM params[])
263 {
264     XORKEY *key = vkey;
265     OSSL_PARAM *p;
266
267     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
268         && !OSSL_PARAM_set_int(p, XOR_KEY_SIZE))
269         return 0;
270
271     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
272         && !OSSL_PARAM_set_int(p, secbits))
273         return 0;
274
275     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_TLS_ENCODED_PT)) != NULL) {
276         if (p->data_type != OSSL_PARAM_OCTET_STRING)
277             return 0;
278         p->return_size = XOR_KEY_SIZE;
279         if (p->data != NULL && p->data_size >= XOR_KEY_SIZE)
280             memcpy(p->data, key->pubkey, XOR_KEY_SIZE);
281     }
282
283     return 1;
284 }
285
286 static const OSSL_PARAM xor_params[] = {
287     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
288     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
289     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_TLS_ENCODED_PT, NULL, 0),
290     OSSL_PARAM_END
291 };
292
293 static const OSSL_PARAM *xor_gettable_params(void *provctx)
294 {
295     return xor_params;
296 }
297
298 static int xor_set_params(void *vkey, const OSSL_PARAM params[])
299 {
300     XORKEY *key = vkey;
301     const OSSL_PARAM *p;
302
303     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_TLS_ENCODED_PT);
304     if (p != NULL) {
305         if (p->data_type != OSSL_PARAM_OCTET_STRING
306                 || p->data_size != XOR_KEY_SIZE)
307             return 0;
308         memcpy(key->pubkey, p->data, XOR_KEY_SIZE);
309         key->haspubkey = 1;
310     }
311
312     return 1;
313 }
314
315 static const OSSL_PARAM xor_known_settable_params[] = {
316     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_TLS_ENCODED_PT, NULL, 0),
317     OSSL_PARAM_END
318 };
319
320 static const OSSL_PARAM *xor_settable_params(void *provctx)
321 {
322     return xor_known_settable_params;
323 }
324
325 struct xor_gen_ctx {
326     int selection;
327     OPENSSL_CTX *libctx;
328 };
329
330 static void *xor_gen_init(void *provctx, int selection)
331 {
332     struct xor_gen_ctx *gctx = NULL;
333
334     if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR
335                       | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) == 0)
336         return NULL;
337
338     if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL)
339         gctx->selection = selection;
340
341     /* Our provctx is really just an OPENSSL_CTX */
342     gctx->libctx = (OPENSSL_CTX *)provctx;
343
344     return gctx;
345 }
346
347 static int xor_gen_set_params(void *genctx, const OSSL_PARAM params[])
348 {
349     struct xor_gen_ctx *gctx = genctx;
350     const OSSL_PARAM *p;
351
352     if (gctx == NULL)
353         return 0;
354
355     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
356     if (p != NULL) {
357         if (p->data_type != OSSL_PARAM_UTF8_STRING
358                 || strcmp(p->data, GROUP_NAME_INTERNAL) != 0)
359             return 0;
360     }
361
362     return 1;
363 }
364
365 static const OSSL_PARAM *xor_gen_settable_params(void *provctx)
366 {
367     static OSSL_PARAM settable[] = {
368         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
369         OSSL_PARAM_END
370     };
371     return settable;
372 }
373
374 static void *xor_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
375 {
376     struct xor_gen_ctx *gctx = genctx;
377     XORKEY *key = OPENSSL_zalloc(sizeof(*key));
378     size_t i;
379
380     if (key == NULL)
381         return NULL;
382
383     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
384         if (RAND_bytes_ex(gctx->libctx, key->privkey, XOR_KEY_SIZE) <= 0) {
385             OPENSSL_free(key);
386             return NULL;
387         }
388         for (i = 0; i < XOR_KEY_SIZE; i++)
389             key->pubkey[i] = key->privkey[i] ^ private_constant[i];
390         key->hasprivkey = 1;
391         key->haspubkey = 1;
392     }
393
394     return key;
395 }
396
397 static void xor_gen_cleanup(void *genctx)
398 {
399     OPENSSL_free(genctx);
400 }
401
402 static const OSSL_DISPATCH xor_keymgmt_functions[] = {
403     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))xor_newdata },
404     { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))xor_gen_init },
405     { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))xor_gen_set_params },
406     { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
407       (void (*)(void))xor_gen_settable_params },
408     { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))xor_gen },
409     { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))xor_gen_cleanup },
410     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))xor_get_params },
411     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))xor_gettable_params },
412     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))xor_set_params },
413     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))xor_settable_params },
414     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))xor_has },
415     { OSSL_FUNC_KEYMGMT_COPY, (void (*)(void))xor_copy },
416     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))xor_freedata },
417     { 0, NULL }
418 };
419
420 static const OSSL_ALGORITHM tls_prov_keymgmt[] = {
421     /*
422      * Obviously this is not FIPS approved, but in order to test in conjuction
423      * with the FIPS provider we pretend that it is.
424      */
425     { "XOR", "provider=tls-provider,fips=yes", xor_keymgmt_functions },
426     { NULL, NULL, NULL }
427 };
428
429 static const OSSL_ALGORITHM *tls_prov_query(void *provctx, int operation_id,
430                                             int *no_cache)
431 {
432     *no_cache = 0;
433     switch (operation_id) {
434     case OSSL_OP_KEYMGMT:
435         return tls_prov_keymgmt;
436     case OSSL_OP_KEYEXCH:
437         return tls_prov_keyexch;
438     }
439     return NULL;
440 }
441
442 /* Functions we provide to the core */
443 static const OSSL_DISPATCH tls_prov_dispatch_table[] = {
444     { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OPENSSL_CTX_free },
445     { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))tls_prov_query },
446     { OSSL_FUNC_PROVIDER_GET_CAPABILITIES, (void (*)(void))tls_prov_get_capabilities },
447     { 0, NULL }
448 };
449
450 int tls_provider_init(const OSSL_CORE_HANDLE *handle,
451                       const OSSL_DISPATCH *in,
452                       const OSSL_DISPATCH **out,
453                       void **provctx)
454 {
455     OPENSSL_CTX *libctx = OPENSSL_CTX_new();
456
457     *provctx = libctx;
458
459     /*
460      * Randomise the group_id we're going to use to ensure we don't interoperate
461      * with anything but ourselves.
462      */
463     if (!RAND_bytes_ex(libctx, (unsigned char *)&group_id, sizeof(group_id)))
464         return 0;
465     /*
466      * Ensure group_id is within the IANA Reserved for private use range
467      * (65024-65279)
468      */
469     group_id %= 65279 - 65024;
470     group_id += 65024;
471
472     *out = tls_prov_dispatch_table;
473     return 1;
474 }