From 5b70206cb316024c6dc30ce54f585ce5cf001a56 Mon Sep 17 00:00:00 2001 From: Nicola Tuveri Date: Mon, 28 Sep 2020 08:37:13 +0300 Subject: [test][tls-provider] Implement KEM algorithm Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/13018) --- test/tls-provider.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 181 insertions(+), 22 deletions(-) (limited to 'test') diff --git a/test/tls-provider.c b/test/tls-provider.c index d890e9a04b..bcbcd710ce 100644 --- a/test/tls-provider.c +++ b/test/tls-provider.c @@ -41,7 +41,53 @@ typedef struct xorkey_st { int haspubkey; } XORKEY; -/* We define a dummy TLS group called "xorgroup" for test purposes */ + +/* Key Management for the dummy XOR KEX and KEM algorithms */ + +static OSSL_FUNC_keymgmt_new_fn xor_newdata; +static OSSL_FUNC_keymgmt_free_fn xor_freedata; +static OSSL_FUNC_keymgmt_has_fn xor_has; +static OSSL_FUNC_keymgmt_copy_fn xor_copy; +static OSSL_FUNC_keymgmt_gen_init_fn xor_gen_init; +static OSSL_FUNC_keymgmt_gen_set_params_fn xor_gen_set_params; +static OSSL_FUNC_keymgmt_gen_settable_params_fn xor_gen_settable_params; +static OSSL_FUNC_keymgmt_gen_fn xor_gen; +static OSSL_FUNC_keymgmt_gen_cleanup_fn xor_gen_cleanup; +static OSSL_FUNC_keymgmt_get_params_fn xor_get_params; +static OSSL_FUNC_keymgmt_gettable_params_fn xor_gettable_params; +static OSSL_FUNC_keymgmt_set_params_fn xor_set_params; +static OSSL_FUNC_keymgmt_settable_params_fn xor_settable_params; + +/* + * Dummy "XOR" Key Exchange algorithm. We just xor the private and public keys + * together. Don't use this! + */ + +static OSSL_FUNC_keyexch_newctx_fn xor_newctx; +static OSSL_FUNC_keyexch_init_fn xor_init; +static OSSL_FUNC_keyexch_set_peer_fn xor_set_peer; +static OSSL_FUNC_keyexch_derive_fn xor_derive; +static OSSL_FUNC_keyexch_freectx_fn xor_freectx; +static OSSL_FUNC_keyexch_dupctx_fn xor_dupctx; + +/* + * Dummy "XOR" Key Encapsulation Method. We just build a KEM over the xor KEX. + * Don't use this! + */ + +static OSSL_FUNC_kem_newctx_fn xor_newctx; +static OSSL_FUNC_kem_freectx_fn xor_freectx; +static OSSL_FUNC_kem_dupctx_fn xor_dupctx; +static OSSL_FUNC_kem_encapsulate_init_fn xor_init; +static OSSL_FUNC_kem_encapsulate_fn xor_encapsulate; +static OSSL_FUNC_kem_decapsulate_init_fn xor_init; +static OSSL_FUNC_kem_decapsulate_fn xor_decapsulate; + + +/* + * We define 2 dummy TLS groups called "xorgroup" and "xorkemgroup" for test + * purposes + */ struct tls_group_st { unsigned int group_id; /* for "tls-group-id", see provider-base(7) */ unsigned int secbits; @@ -133,16 +179,10 @@ static int tls_prov_get_capabilities(void *provctx, const char *capability, * together. Don't use this! */ -static OSSL_FUNC_keyexch_newctx_fn xor_newctx; -static OSSL_FUNC_keyexch_init_fn xor_init; -static OSSL_FUNC_keyexch_set_peer_fn xor_set_peer; -static OSSL_FUNC_keyexch_derive_fn xor_derive; -static OSSL_FUNC_keyexch_freectx_fn xor_freectx; -static OSSL_FUNC_keyexch_dupctx_fn xor_dupctx; - typedef struct { XORKEY *key; XORKEY *peerkey; + void *provctx; } PROV_XOR_CTX; static void *xor_newctx(void *provctx) @@ -152,6 +192,8 @@ static void *xor_newctx(void *provctx) if (pxorctx == NULL) return NULL; + pxorctx->provctx = provctx; + return pxorctx; } @@ -235,21 +277,136 @@ static const OSSL_ALGORITHM tls_prov_keyexch[] = { { NULL, NULL, NULL } }; -/* Key Management for the dummy XOR key exchange algorithm */ +/* + * Dummy "XOR" Key Encapsulation Method. We just build a KEM over the xor KEX. + * Don't use this! + */ -static OSSL_FUNC_keymgmt_new_fn xor_newdata; -static OSSL_FUNC_keymgmt_free_fn xor_freedata; -static OSSL_FUNC_keymgmt_has_fn xor_has; -static OSSL_FUNC_keymgmt_copy_fn xor_copy; -static OSSL_FUNC_keymgmt_gen_init_fn xor_gen_init; -static OSSL_FUNC_keymgmt_gen_set_params_fn xor_gen_set_params; -static OSSL_FUNC_keymgmt_gen_settable_params_fn xor_gen_settable_params; -static OSSL_FUNC_keymgmt_gen_fn xor_gen; -static OSSL_FUNC_keymgmt_gen_cleanup_fn xor_gen_cleanup; -static OSSL_FUNC_keymgmt_get_params_fn xor_get_params; -static OSSL_FUNC_keymgmt_gettable_params_fn xor_gettable_params; -static OSSL_FUNC_keymgmt_set_params_fn xor_set_params; -static OSSL_FUNC_keymgmt_settable_params_fn xor_settable_params; +static int xor_encapsulate(void *vpxorctx, + unsigned char *ct, size_t *ctlen, + unsigned char *ss, size_t *sslen) +{ + /* + * We are building this around a KEX: + * + * 1. we generate ephemeral keypair + * 2. we encode our ephemeral pubkey as the outgoing ct + * 3. we derive using our ephemeral privkey in combination with the peer + * pubkey from the ctx; the result is our ss. + */ + int rv = 0; + void *genctx = NULL, *derivectx = NULL; + XORKEY *ourkey = NULL; + PROV_XOR_CTX *pxorctx = vpxorctx; + + if (ct == NULL || ss == NULL) { + /* Just return sizes */ + + if (ctlen == NULL && sslen == NULL) + return 0; + if (ctlen != NULL) + *ctlen = XOR_KEY_SIZE; + if (sslen != NULL) + *sslen = XOR_KEY_SIZE; + return 1; + } + + /* 1. Generate keypair */ + genctx = xor_gen_init(pxorctx->provctx, OSSL_KEYMGMT_SELECT_KEYPAIR); + if (genctx == NULL) + goto end; + ourkey = xor_gen(genctx, NULL, NULL); + if (ourkey == NULL) + goto end; + + /* 2. Encode ephemeral pubkey as ct */ + memcpy(ct, ourkey->pubkey, XOR_KEY_SIZE); + *ctlen = XOR_KEY_SIZE; + + /* 3. Derive ss via KEX */ + derivectx = xor_newctx(pxorctx->provctx); + if (derivectx == NULL + || !xor_init(derivectx, ourkey) + || !xor_set_peer(derivectx, pxorctx->key) + || !xor_derive(derivectx, ss, sslen, XOR_KEY_SIZE)) + goto end; + + rv = 1; + + end: + xor_gen_cleanup(genctx); + xor_freedata(ourkey); + xor_freectx(derivectx); + return rv; +} + +static int xor_decapsulate(void *vpxorctx, + unsigned char *ss, size_t *sslen, + const unsigned char *ct, size_t ctlen) +{ + /* + * We are building this around a KEX: + * + * - ct is our peer's pubkey + * - decapsulate is just derive. + */ + int rv = 0; + void *derivectx = NULL; + XORKEY *peerkey = NULL; + PROV_XOR_CTX *pxorctx = vpxorctx; + + if (ss == NULL) { + /* Just return size */ + if (sslen == NULL) + return 0; + *sslen = XOR_KEY_SIZE; + return 1; + } + + if (ctlen != XOR_KEY_SIZE) + return 0; + peerkey = xor_newdata(pxorctx->provctx); + if (peerkey == NULL) + goto end; + memcpy(peerkey->pubkey, ct, XOR_KEY_SIZE); + + /* Derive ss via KEX */ + derivectx = xor_newctx(pxorctx->provctx); + if (derivectx == NULL + || !xor_init(derivectx, pxorctx->key) + || !xor_set_peer(derivectx, peerkey) + || !xor_derive(derivectx, ss, sslen, XOR_KEY_SIZE)) + goto end; + + rv = 1; + + end: + xor_freedata(peerkey); + xor_freectx(derivectx); + return rv; +} + +static const OSSL_DISPATCH xor_kem_functions[] = { + { OSSL_FUNC_KEM_NEWCTX, (void (*)(void))xor_newctx }, + { OSSL_FUNC_KEM_FREECTX, (void (*)(void))xor_freectx }, + { OSSL_FUNC_KEM_DUPCTX, (void (*)(void))xor_dupctx }, + { OSSL_FUNC_KEM_ENCAPSULATE_INIT, (void (*)(void))xor_init }, + { OSSL_FUNC_KEM_ENCAPSULATE, (void (*)(void))xor_encapsulate }, + { OSSL_FUNC_KEM_DECAPSULATE_INIT, (void (*)(void))xor_init }, + { OSSL_FUNC_KEM_DECAPSULATE, (void (*)(void))xor_decapsulate }, + { 0, NULL } +}; + +static const OSSL_ALGORITHM tls_prov_kem[] = { + /* + * Obviously this is not FIPS approved, but in order to test in conjuction + * with the FIPS provider we pretend that it is. + */ + { "XOR", "provider=tls-provider,fips=yes", xor_kem_functions }, + { NULL, NULL, NULL } +}; + +/* Key Management for the dummy XOR key exchange algorithm */ static void *xor_newdata(void *provctx) { @@ -483,6 +640,8 @@ static const OSSL_ALGORITHM *tls_prov_query(void *provctx, int operation_id, return tls_prov_keymgmt; case OSSL_OP_KEYEXCH: return tls_prov_keyexch; + case OSSL_OP_KEM: + return tls_prov_kem; } return NULL; } -- cgit v1.2.3