2019-05-27 06:55:01 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2016-06-22 16:49:14 +00:00
|
|
|
/* Diffie-Hellman Key Agreement Method [RFC2631]
|
|
|
|
*
|
|
|
|
* Copyright (c) 2016, Intel Corporation
|
|
|
|
* Authors: Salvatore Benedetto <salvatore.benedetto@intel.com>
|
|
|
|
*/
|
|
|
|
|
2021-11-21 14:51:44 +00:00
|
|
|
#include <linux/fips.h>
|
2016-06-22 16:49:14 +00:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <crypto/internal/kpp.h>
|
|
|
|
#include <crypto/kpp.h>
|
|
|
|
#include <crypto/dh.h>
|
2022-02-21 12:10:55 +00:00
|
|
|
#include <crypto/rng.h>
|
2016-06-22 16:49:14 +00:00
|
|
|
#include <linux/mpi.h>
|
|
|
|
|
|
|
|
struct dh_ctx {
|
2018-06-27 06:15:31 +00:00
|
|
|
MPI p; /* Value is guaranteed to be set. */
|
|
|
|
MPI g; /* Value is guaranteed to be set. */
|
|
|
|
MPI xa; /* Value is guaranteed to be set. */
|
2016-06-22 16:49:14 +00:00
|
|
|
};
|
|
|
|
|
2017-11-06 02:30:44 +00:00
|
|
|
static void dh_clear_ctx(struct dh_ctx *ctx)
|
2016-06-22 16:49:14 +00:00
|
|
|
{
|
|
|
|
mpi_free(ctx->p);
|
|
|
|
mpi_free(ctx->g);
|
|
|
|
mpi_free(ctx->xa);
|
2017-11-06 02:30:44 +00:00
|
|
|
memset(ctx, 0, sizeof(*ctx));
|
2016-06-22 16:49:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If base is g we compute the public key
|
|
|
|
* ya = g^xa mod p; [RFC2631 sec 2.1.1]
|
|
|
|
* else if base if the counterpart public key we compute the shared secret
|
|
|
|
* ZZ = yb^xa mod p; [RFC2631 sec 2.1.1]
|
|
|
|
*/
|
|
|
|
static int _compute_val(const struct dh_ctx *ctx, MPI base, MPI val)
|
|
|
|
{
|
|
|
|
/* val = base^xa mod p */
|
|
|
|
return mpi_powm(val, base, ctx->xa, ctx->p);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct dh_ctx *dh_get_ctx(struct crypto_kpp *tfm)
|
|
|
|
{
|
|
|
|
return kpp_tfm_ctx(tfm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dh_check_params_length(unsigned int p_len)
|
|
|
|
{
|
2021-11-21 14:51:44 +00:00
|
|
|
if (fips_enabled)
|
|
|
|
return (p_len < 2048) ? -EINVAL : 0;
|
|
|
|
|
2016-06-22 16:49:14 +00:00
|
|
|
return (p_len < 1536) ? -EINVAL : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dh_set_params(struct dh_ctx *ctx, struct dh *params)
|
|
|
|
{
|
|
|
|
if (dh_check_params_length(params->p_size << 3))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
ctx->p = mpi_read_raw_data(params->p, params->p_size);
|
|
|
|
if (!ctx->p)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
ctx->g = mpi_read_raw_data(params->g, params->g_size);
|
2017-11-06 02:30:44 +00:00
|
|
|
if (!ctx->g)
|
2016-06-22 16:49:14 +00:00
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-02-24 23:46:58 +00:00
|
|
|
static int dh_set_secret(struct crypto_kpp *tfm, const void *buf,
|
|
|
|
unsigned int len)
|
2016-06-22 16:49:14 +00:00
|
|
|
{
|
|
|
|
struct dh_ctx *ctx = dh_get_ctx(tfm);
|
|
|
|
struct dh params;
|
|
|
|
|
2017-05-25 07:18:07 +00:00
|
|
|
/* Free the old MPI key if any */
|
2017-11-06 02:30:44 +00:00
|
|
|
dh_clear_ctx(ctx);
|
2017-05-25 07:18:07 +00:00
|
|
|
|
2016-06-22 16:49:14 +00:00
|
|
|
if (crypto_dh_decode_key(buf, len, ¶ms) < 0)
|
2017-11-06 02:30:44 +00:00
|
|
|
goto err_clear_ctx;
|
2016-06-22 16:49:14 +00:00
|
|
|
|
|
|
|
if (dh_set_params(ctx, ¶ms) < 0)
|
2017-11-06 02:30:44 +00:00
|
|
|
goto err_clear_ctx;
|
2016-06-22 16:49:14 +00:00
|
|
|
|
|
|
|
ctx->xa = mpi_read_raw_data(params.key, params.key_size);
|
2017-11-06 02:30:44 +00:00
|
|
|
if (!ctx->xa)
|
|
|
|
goto err_clear_ctx;
|
2016-06-22 16:49:14 +00:00
|
|
|
|
|
|
|
return 0;
|
2017-11-06 02:30:44 +00:00
|
|
|
|
|
|
|
err_clear_ctx:
|
|
|
|
dh_clear_ctx(ctx);
|
|
|
|
return -EINVAL;
|
2016-06-22 16:49:14 +00:00
|
|
|
}
|
|
|
|
|
2018-06-27 06:15:31 +00:00
|
|
|
/*
|
|
|
|
* SP800-56A public key verification:
|
|
|
|
*
|
2022-02-21 12:11:01 +00:00
|
|
|
* * For the safe-prime groups in FIPS mode, Q can be computed
|
|
|
|
* trivially from P and a full validation according to SP800-56A
|
|
|
|
* section 5.6.2.3.1 is performed.
|
2018-06-27 06:15:31 +00:00
|
|
|
*
|
2022-02-21 12:11:01 +00:00
|
|
|
* * For all other sets of group parameters, only a partial validation
|
|
|
|
* according to SP800-56A section 5.6.2.3.2 is performed.
|
2018-06-27 06:15:31 +00:00
|
|
|
*/
|
|
|
|
static int dh_is_pubkey_valid(struct dh_ctx *ctx, MPI y)
|
|
|
|
{
|
|
|
|
if (unlikely(!ctx->p))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Step 1: Verify that 2 <= y <= p - 2.
|
|
|
|
*
|
|
|
|
* The upper limit check is actually y < p instead of y < p - 1
|
2022-02-21 12:11:01 +00:00
|
|
|
* in order to save one mpi_sub_ui() invocation here. Note that
|
|
|
|
* p - 1 is the non-trivial element of the subgroup of order 2 and
|
|
|
|
* thus, the check on y^q below would fail if y == p - 1.
|
2018-06-27 06:15:31 +00:00
|
|
|
*/
|
|
|
|
if (mpi_cmp_ui(y, 1) < 1 || mpi_cmp(y, ctx->p) >= 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2022-02-21 12:11:01 +00:00
|
|
|
/*
|
|
|
|
* Step 2: Verify that 1 = y^q mod p
|
|
|
|
*
|
|
|
|
* For the safe-prime groups q = (p - 1)/2.
|
|
|
|
*/
|
|
|
|
if (fips_enabled) {
|
|
|
|
MPI val, q;
|
2018-06-27 06:15:31 +00:00
|
|
|
int ret;
|
|
|
|
|
2022-02-21 12:11:01 +00:00
|
|
|
val = mpi_alloc(0);
|
2018-06-27 06:15:31 +00:00
|
|
|
if (!val)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2022-02-21 12:11:01 +00:00
|
|
|
q = mpi_alloc(mpi_get_nlimbs(ctx->p));
|
|
|
|
if (!q) {
|
|
|
|
mpi_free(val);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ->p is odd, so no need to explicitly subtract one
|
|
|
|
* from it before shifting to the right.
|
|
|
|
*/
|
|
|
|
mpi_rshift(q, ctx->p, 1);
|
2018-06-27 06:15:31 +00:00
|
|
|
|
2022-02-21 12:11:01 +00:00
|
|
|
ret = mpi_powm(val, y, q, ctx->p);
|
|
|
|
mpi_free(q);
|
2018-06-27 06:15:31 +00:00
|
|
|
if (ret) {
|
|
|
|
mpi_free(val);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = mpi_cmp_ui(val, 1);
|
|
|
|
|
|
|
|
mpi_free(val);
|
|
|
|
|
|
|
|
if (ret != 0)
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-06-22 16:49:14 +00:00
|
|
|
static int dh_compute_value(struct kpp_request *req)
|
|
|
|
{
|
|
|
|
struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
|
|
|
|
struct dh_ctx *ctx = dh_get_ctx(tfm);
|
|
|
|
MPI base, val = mpi_alloc(0);
|
|
|
|
int ret = 0;
|
|
|
|
int sign;
|
|
|
|
|
|
|
|
if (!val)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
if (unlikely(!ctx->xa)) {
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto err_free_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (req->src) {
|
|
|
|
base = mpi_read_raw_from_sgl(req->src, req->src_len);
|
|
|
|
if (!base) {
|
2016-11-08 23:48:22 +00:00
|
|
|
ret = -EINVAL;
|
2016-06-22 16:49:14 +00:00
|
|
|
goto err_free_val;
|
|
|
|
}
|
2018-06-27 06:15:31 +00:00
|
|
|
ret = dh_is_pubkey_valid(ctx, base);
|
|
|
|
if (ret)
|
2018-07-10 14:22:52 +00:00
|
|
|
goto err_free_base;
|
2016-06-22 16:49:14 +00:00
|
|
|
} else {
|
|
|
|
base = ctx->g;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = _compute_val(ctx, base, val);
|
|
|
|
if (ret)
|
|
|
|
goto err_free_base;
|
|
|
|
|
2020-07-20 17:08:52 +00:00
|
|
|
if (fips_enabled) {
|
|
|
|
/* SP800-56A rev3 5.7.1.1 check: Validation of shared secret */
|
|
|
|
if (req->src) {
|
|
|
|
MPI pone;
|
|
|
|
|
|
|
|
/* z <= 1 */
|
|
|
|
if (mpi_cmp_ui(val, 1) < 1) {
|
|
|
|
ret = -EBADMSG;
|
|
|
|
goto err_free_base;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* z == p - 1 */
|
|
|
|
pone = mpi_alloc(0);
|
|
|
|
|
|
|
|
if (!pone) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto err_free_base;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = mpi_sub_ui(pone, ctx->p, 1);
|
|
|
|
if (!ret && !mpi_cmp(pone, val))
|
|
|
|
ret = -EBADMSG;
|
|
|
|
|
|
|
|
mpi_free(pone);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
goto err_free_base;
|
|
|
|
|
|
|
|
/* SP800-56A rev 3 5.6.2.1.3 key check */
|
|
|
|
} else {
|
|
|
|
if (dh_is_pubkey_valid(ctx, val)) {
|
|
|
|
ret = -EAGAIN;
|
|
|
|
goto err_free_val;
|
|
|
|
}
|
2020-07-20 17:08:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-29 11:32:21 +00:00
|
|
|
ret = mpi_write_to_sgl(val, req->dst, req->dst_len, &sign);
|
2016-06-22 16:49:14 +00:00
|
|
|
if (ret)
|
|
|
|
goto err_free_base;
|
|
|
|
|
|
|
|
if (sign < 0)
|
|
|
|
ret = -EBADMSG;
|
|
|
|
err_free_base:
|
|
|
|
if (req->src)
|
|
|
|
mpi_free(base);
|
|
|
|
err_free_val:
|
|
|
|
mpi_free(val);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-05-25 07:18:09 +00:00
|
|
|
static unsigned int dh_max_size(struct crypto_kpp *tfm)
|
2016-06-22 16:49:14 +00:00
|
|
|
{
|
|
|
|
struct dh_ctx *ctx = dh_get_ctx(tfm);
|
|
|
|
|
|
|
|
return mpi_get_size(ctx->p);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dh_exit_tfm(struct crypto_kpp *tfm)
|
|
|
|
{
|
|
|
|
struct dh_ctx *ctx = dh_get_ctx(tfm);
|
|
|
|
|
2017-11-06 02:30:44 +00:00
|
|
|
dh_clear_ctx(ctx);
|
2016-06-22 16:49:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct kpp_alg dh = {
|
|
|
|
.set_secret = dh_set_secret,
|
|
|
|
.generate_public_key = dh_compute_value,
|
|
|
|
.compute_shared_secret = dh_compute_value,
|
|
|
|
.max_size = dh_max_size,
|
|
|
|
.exit = dh_exit_tfm,
|
|
|
|
.base = {
|
|
|
|
.cra_name = "dh",
|
|
|
|
.cra_driver_name = "dh-generic",
|
|
|
|
.cra_priority = 100,
|
|
|
|
.cra_module = THIS_MODULE,
|
|
|
|
.cra_ctxsize = sizeof(struct dh_ctx),
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
crypto: dh - introduce common code for built-in safe-prime group support
Recent work on NVME in-band authentication support ([1]) needs to invoke
the "dh" KPP with the FFDHE safe-prime group parameters as specified in
RFC 7919 and generate ephemeral keys suitable for the respective group. By
coincidence, the requirements from NIST SP800-56Arev3,
sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down
to disallowing any group parameters not among the approved safe-prime
groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore,
SP800-56Arev3 specifies the respective security strength for each of the
approved safe-prime groups, which has a direct impact on the minimum key
lengths.
In this light, it's desirable to introduce built-in support for the
RFC 7919 safe-prime groups to the kernel's DH implementation, provide a
SP800-56Arev3 conforming key generation primitive for those and render
non-approved group parameters unusable in FIPS mode on the way.
As suggested ([2]) in the course of discussion to previous iterations of
this patchset, the built-in support for ffdhe groups would be best made
available in the form of templates wrapping the existing "dh"
implementation, one for each group specified by RFC 7919: ffdhe2048(dh),
ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these
templates differ only in the safe-prime constants they'd configure the
inner "dh" transforms with, they can share almost all of their
"dh"-wrapping template implementation code.
Introduce this common code to dh_generic. The actual dump of the RFC 7919
safe-prime constants will be deferred to the next patch in order to
facilitate review. The ephemeral key generation primitive mentioned above
likewise deserves a patch on its own, as does the mechanism by which
unapproved groups are rendered unusable in FIPS mode.
Define a struct dh_safe_prime container for specifying the individual
templates' associated safe-prime group constants. All ffdheXYZ(dh) template
instances will store a pointer to such a dh_safe_prime in their context
areas each. Implement the common __dh_safe_prime_create() template
instantiation helper. The intention is that the individual ffdheXYZ(dh)
crypto_templates' ->create() implementations will simply forward any calls
to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition
to the received ->create() arguments. __dh_safe_prime_create() would then
create and register a kpp_instance as appropriate, storing the given
dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh"
kpp_alg in the context area.
As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the
inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to
in turn own an inner "dh" transform, a pointer to which gets stored in the
context area. Setup and teardown are getting handled from the outer
->init_tfm() and ->exit_tfm() respectively.
In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances
configure the inner "dh" transforms with the respective group parameters,
make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill
in the P and G values before forwarding the call to the inner "dh"'s
->set_secret(). Note that the outer ->set_secret() can obtain the P value
associated with the given ffdheXYZ(dh) kpp_instance by means of the
dh_safe_prime referenced from the latter's context. The value of G OTOH
always equals constant 2 for the safe-prime groups.
Finally, make the remaining two kpp_alg primitives both operating on
kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(),
to merely forward any request to the inner "dh" implementation. However, a
kpp_request instance received from the outside cannot get simply passed
on as-is, because its associated transform (crypto_kpp_reqtfm()) will have
been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve
some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in
turn storing an inner kpp_request suitable for "dh" each. Make the outer
->generate_public_key() and ->compute_shared_secret() respectively to setup
this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req()
helper before handing it over to the "dh" implementation for further
processing. dh_safe_prime_prepare_dh_req() basically copies the outer
kpp_request received from the outside over to the inner one, but installs
the inner transform and its own ->complete() proxy callback therein. This
completion callback, the new dh_safe_prime_complete_req(), doesn't do
anything beyond completing the outer request. Note that there exist some
examples in crypto/, which would simply install the completion handler
from the outer request at the inner one in similar setups, e.g. seqiv.
However, this would mean that the user-provided completion handler won't
get called with the address of the outer kpp_request initially submitted
and the handler might not be prepared for this. Users could certainly work
around this by setting the callback ->data properly, but IMO it's cleaner
this way. Furthermore, it might make sense to extend
dh_safe_prime_complete_req() in the future and move e.g. those
post-computation FIPS checks from the generic "dh" implementation to the
ffdheXYZ(dh) templates.
[1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de
[2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au
Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 12:10:52 +00:00
|
|
|
|
|
|
|
struct dh_safe_prime {
|
|
|
|
unsigned int max_strength;
|
|
|
|
unsigned int p_size;
|
|
|
|
const char *p;
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char safe_prime_g[] = { 2 };
|
|
|
|
|
|
|
|
struct dh_safe_prime_instance_ctx {
|
|
|
|
struct crypto_kpp_spawn dh_spawn;
|
|
|
|
const struct dh_safe_prime *safe_prime;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct dh_safe_prime_tfm_ctx {
|
|
|
|
struct crypto_kpp *dh_tfm;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void dh_safe_prime_free_instance(struct kpp_instance *inst)
|
|
|
|
{
|
|
|
|
struct dh_safe_prime_instance_ctx *ctx = kpp_instance_ctx(inst);
|
|
|
|
|
|
|
|
crypto_drop_kpp(&ctx->dh_spawn);
|
|
|
|
kfree(inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct dh_safe_prime_instance_ctx *dh_safe_prime_instance_ctx(
|
|
|
|
struct crypto_kpp *tfm)
|
|
|
|
{
|
|
|
|
return kpp_instance_ctx(kpp_alg_instance(tfm));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dh_safe_prime_init_tfm(struct crypto_kpp *tfm)
|
|
|
|
{
|
|
|
|
struct dh_safe_prime_instance_ctx *inst_ctx =
|
|
|
|
dh_safe_prime_instance_ctx(tfm);
|
|
|
|
struct dh_safe_prime_tfm_ctx *tfm_ctx = kpp_tfm_ctx(tfm);
|
|
|
|
|
|
|
|
tfm_ctx->dh_tfm = crypto_spawn_kpp(&inst_ctx->dh_spawn);
|
|
|
|
if (IS_ERR(tfm_ctx->dh_tfm))
|
|
|
|
return PTR_ERR(tfm_ctx->dh_tfm);
|
|
|
|
|
2022-11-22 10:06:56 +00:00
|
|
|
kpp_set_reqsize(tfm, sizeof(struct kpp_request) +
|
|
|
|
crypto_kpp_reqsize(tfm_ctx->dh_tfm));
|
|
|
|
|
crypto: dh - introduce common code for built-in safe-prime group support
Recent work on NVME in-band authentication support ([1]) needs to invoke
the "dh" KPP with the FFDHE safe-prime group parameters as specified in
RFC 7919 and generate ephemeral keys suitable for the respective group. By
coincidence, the requirements from NIST SP800-56Arev3,
sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down
to disallowing any group parameters not among the approved safe-prime
groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore,
SP800-56Arev3 specifies the respective security strength for each of the
approved safe-prime groups, which has a direct impact on the minimum key
lengths.
In this light, it's desirable to introduce built-in support for the
RFC 7919 safe-prime groups to the kernel's DH implementation, provide a
SP800-56Arev3 conforming key generation primitive for those and render
non-approved group parameters unusable in FIPS mode on the way.
As suggested ([2]) in the course of discussion to previous iterations of
this patchset, the built-in support for ffdhe groups would be best made
available in the form of templates wrapping the existing "dh"
implementation, one for each group specified by RFC 7919: ffdhe2048(dh),
ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these
templates differ only in the safe-prime constants they'd configure the
inner "dh" transforms with, they can share almost all of their
"dh"-wrapping template implementation code.
Introduce this common code to dh_generic. The actual dump of the RFC 7919
safe-prime constants will be deferred to the next patch in order to
facilitate review. The ephemeral key generation primitive mentioned above
likewise deserves a patch on its own, as does the mechanism by which
unapproved groups are rendered unusable in FIPS mode.
Define a struct dh_safe_prime container for specifying the individual
templates' associated safe-prime group constants. All ffdheXYZ(dh) template
instances will store a pointer to such a dh_safe_prime in their context
areas each. Implement the common __dh_safe_prime_create() template
instantiation helper. The intention is that the individual ffdheXYZ(dh)
crypto_templates' ->create() implementations will simply forward any calls
to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition
to the received ->create() arguments. __dh_safe_prime_create() would then
create and register a kpp_instance as appropriate, storing the given
dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh"
kpp_alg in the context area.
As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the
inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to
in turn own an inner "dh" transform, a pointer to which gets stored in the
context area. Setup and teardown are getting handled from the outer
->init_tfm() and ->exit_tfm() respectively.
In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances
configure the inner "dh" transforms with the respective group parameters,
make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill
in the P and G values before forwarding the call to the inner "dh"'s
->set_secret(). Note that the outer ->set_secret() can obtain the P value
associated with the given ffdheXYZ(dh) kpp_instance by means of the
dh_safe_prime referenced from the latter's context. The value of G OTOH
always equals constant 2 for the safe-prime groups.
Finally, make the remaining two kpp_alg primitives both operating on
kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(),
to merely forward any request to the inner "dh" implementation. However, a
kpp_request instance received from the outside cannot get simply passed
on as-is, because its associated transform (crypto_kpp_reqtfm()) will have
been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve
some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in
turn storing an inner kpp_request suitable for "dh" each. Make the outer
->generate_public_key() and ->compute_shared_secret() respectively to setup
this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req()
helper before handing it over to the "dh" implementation for further
processing. dh_safe_prime_prepare_dh_req() basically copies the outer
kpp_request received from the outside over to the inner one, but installs
the inner transform and its own ->complete() proxy callback therein. This
completion callback, the new dh_safe_prime_complete_req(), doesn't do
anything beyond completing the outer request. Note that there exist some
examples in crypto/, which would simply install the completion handler
from the outer request at the inner one in similar setups, e.g. seqiv.
However, this would mean that the user-provided completion handler won't
get called with the address of the outer kpp_request initially submitted
and the handler might not be prepared for this. Users could certainly work
around this by setting the callback ->data properly, but IMO it's cleaner
this way. Furthermore, it might make sense to extend
dh_safe_prime_complete_req() in the future and move e.g. those
post-computation FIPS checks from the generic "dh" implementation to the
ffdheXYZ(dh) templates.
[1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de
[2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au
Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 12:10:52 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dh_safe_prime_exit_tfm(struct crypto_kpp *tfm)
|
|
|
|
{
|
|
|
|
struct dh_safe_prime_tfm_ctx *tfm_ctx = kpp_tfm_ctx(tfm);
|
|
|
|
|
|
|
|
crypto_free_kpp(tfm_ctx->dh_tfm);
|
|
|
|
}
|
|
|
|
|
2022-02-21 12:10:55 +00:00
|
|
|
static u64 __add_u64_to_be(__be64 *dst, unsigned int n, u64 val)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = n; val && i > 0; --i) {
|
|
|
|
u64 tmp = be64_to_cpu(dst[i - 1]);
|
|
|
|
|
|
|
|
tmp += val;
|
|
|
|
val = tmp >= val ? 0 : 1;
|
|
|
|
dst[i - 1] = cpu_to_be64(tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *dh_safe_prime_gen_privkey(const struct dh_safe_prime *safe_prime,
|
|
|
|
unsigned int *key_size)
|
|
|
|
{
|
|
|
|
unsigned int n, oversampling_size;
|
|
|
|
__be64 *key;
|
|
|
|
int err;
|
|
|
|
u64 h, o;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Generate a private key following NIST SP800-56Ar3,
|
|
|
|
* sec. 5.6.1.1.1 and 5.6.1.1.3 resp..
|
|
|
|
*
|
|
|
|
* 5.6.1.1.1: choose key length N such that
|
|
|
|
* 2 * ->max_strength <= N <= log2(q) + 1 = ->p_size * 8 - 1
|
|
|
|
* with q = (p - 1) / 2 for the safe-prime groups.
|
|
|
|
* Choose the lower bound's next power of two for N in order to
|
|
|
|
* avoid excessively large private keys while still
|
|
|
|
* maintaining some extra reserve beyond the bare minimum in
|
|
|
|
* most cases. Note that for each entry in safe_prime_groups[],
|
|
|
|
* the following holds for such N:
|
|
|
|
* - N >= 256, in particular it is a multiple of 2^6 = 64
|
|
|
|
* bits and
|
|
|
|
* - N < log2(q) + 1, i.e. N respects the upper bound.
|
|
|
|
*/
|
|
|
|
n = roundup_pow_of_two(2 * safe_prime->max_strength);
|
|
|
|
WARN_ON_ONCE(n & ((1u << 6) - 1));
|
|
|
|
n >>= 6; /* Convert N into units of u64. */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reserve one extra u64 to hold the extra random bits
|
|
|
|
* required as per 5.6.1.1.3.
|
|
|
|
*/
|
|
|
|
oversampling_size = (n + 1) * sizeof(__be64);
|
|
|
|
key = kmalloc(oversampling_size, GFP_KERNEL);
|
|
|
|
if (!key)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 5.6.1.1.3, step 3 (and implicitly step 4): obtain N + 64
|
|
|
|
* random bits and interpret them as a big endian integer.
|
|
|
|
*/
|
|
|
|
err = -EFAULT;
|
|
|
|
if (crypto_get_default_rng())
|
|
|
|
goto out_err;
|
|
|
|
|
|
|
|
err = crypto_rng_get_bytes(crypto_default_rng, (u8 *)key,
|
|
|
|
oversampling_size);
|
|
|
|
crypto_put_default_rng();
|
|
|
|
if (err)
|
|
|
|
goto out_err;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 5.6.1.1.3, step 5 is implicit: 2^N < q and thus,
|
|
|
|
* M = min(2^N, q) = 2^N.
|
|
|
|
*
|
|
|
|
* For step 6, calculate
|
|
|
|
* key = (key[] mod (M - 1)) + 1 = (key[] mod (2^N - 1)) + 1.
|
|
|
|
*
|
|
|
|
* In order to avoid expensive divisions, note that
|
|
|
|
* 2^N mod (2^N - 1) = 1 and thus, for any integer h,
|
|
|
|
* 2^N * h mod (2^N - 1) = h mod (2^N - 1) always holds.
|
|
|
|
* The big endian integer key[] composed of n + 1 64bit words
|
|
|
|
* may be written as key[] = h * 2^N + l, with h = key[0]
|
|
|
|
* representing the 64 most significant bits and l
|
|
|
|
* corresponding to the remaining 2^N bits. With the remark
|
|
|
|
* from above,
|
|
|
|
* h * 2^N + l mod (2^N - 1) = l + h mod (2^N - 1).
|
|
|
|
* As both, l and h are less than 2^N, their sum after
|
|
|
|
* this first reduction is guaranteed to be <= 2^(N + 1) - 2.
|
|
|
|
* Or equivalently, that their sum can again be written as
|
|
|
|
* h' * 2^N + l' with h' now either zero or one and if one,
|
|
|
|
* then l' <= 2^N - 2. Thus, all bits at positions >= N will
|
|
|
|
* be zero after a second reduction:
|
|
|
|
* h' * 2^N + l' mod (2^N - 1) = l' + h' mod (2^N - 1).
|
|
|
|
* At this point, it is still possible that
|
|
|
|
* l' + h' = 2^N - 1, i.e. that l' + h' mod (2^N - 1)
|
|
|
|
* is zero. This condition will be detected below by means of
|
|
|
|
* the final increment overflowing in this case.
|
|
|
|
*/
|
|
|
|
h = be64_to_cpu(key[0]);
|
|
|
|
h = __add_u64_to_be(key + 1, n, h);
|
|
|
|
h = __add_u64_to_be(key + 1, n, h);
|
|
|
|
WARN_ON_ONCE(h);
|
|
|
|
|
|
|
|
/* Increment to obtain the final result. */
|
|
|
|
o = __add_u64_to_be(key + 1, n, 1);
|
|
|
|
/*
|
|
|
|
* The overflow bit o from the increment is either zero or
|
|
|
|
* one. If zero, key[1:n] holds the final result in big-endian
|
|
|
|
* order. If one, key[1:n] is zero now, but needs to be set to
|
|
|
|
* one, c.f. above.
|
|
|
|
*/
|
|
|
|
if (o)
|
|
|
|
key[n] = cpu_to_be64(1);
|
|
|
|
|
|
|
|
/* n is in units of u64, convert to bytes. */
|
|
|
|
*key_size = n << 3;
|
|
|
|
/* Strip the leading extra __be64, which is (virtually) zero by now. */
|
|
|
|
memmove(key, &key[1], *key_size);
|
|
|
|
|
|
|
|
return key;
|
|
|
|
|
|
|
|
out_err:
|
|
|
|
kfree_sensitive(key);
|
|
|
|
return ERR_PTR(err);
|
|
|
|
}
|
|
|
|
|
crypto: dh - introduce common code for built-in safe-prime group support
Recent work on NVME in-band authentication support ([1]) needs to invoke
the "dh" KPP with the FFDHE safe-prime group parameters as specified in
RFC 7919 and generate ephemeral keys suitable for the respective group. By
coincidence, the requirements from NIST SP800-56Arev3,
sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down
to disallowing any group parameters not among the approved safe-prime
groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore,
SP800-56Arev3 specifies the respective security strength for each of the
approved safe-prime groups, which has a direct impact on the minimum key
lengths.
In this light, it's desirable to introduce built-in support for the
RFC 7919 safe-prime groups to the kernel's DH implementation, provide a
SP800-56Arev3 conforming key generation primitive for those and render
non-approved group parameters unusable in FIPS mode on the way.
As suggested ([2]) in the course of discussion to previous iterations of
this patchset, the built-in support for ffdhe groups would be best made
available in the form of templates wrapping the existing "dh"
implementation, one for each group specified by RFC 7919: ffdhe2048(dh),
ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these
templates differ only in the safe-prime constants they'd configure the
inner "dh" transforms with, they can share almost all of their
"dh"-wrapping template implementation code.
Introduce this common code to dh_generic. The actual dump of the RFC 7919
safe-prime constants will be deferred to the next patch in order to
facilitate review. The ephemeral key generation primitive mentioned above
likewise deserves a patch on its own, as does the mechanism by which
unapproved groups are rendered unusable in FIPS mode.
Define a struct dh_safe_prime container for specifying the individual
templates' associated safe-prime group constants. All ffdheXYZ(dh) template
instances will store a pointer to such a dh_safe_prime in their context
areas each. Implement the common __dh_safe_prime_create() template
instantiation helper. The intention is that the individual ffdheXYZ(dh)
crypto_templates' ->create() implementations will simply forward any calls
to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition
to the received ->create() arguments. __dh_safe_prime_create() would then
create and register a kpp_instance as appropriate, storing the given
dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh"
kpp_alg in the context area.
As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the
inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to
in turn own an inner "dh" transform, a pointer to which gets stored in the
context area. Setup and teardown are getting handled from the outer
->init_tfm() and ->exit_tfm() respectively.
In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances
configure the inner "dh" transforms with the respective group parameters,
make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill
in the P and G values before forwarding the call to the inner "dh"'s
->set_secret(). Note that the outer ->set_secret() can obtain the P value
associated with the given ffdheXYZ(dh) kpp_instance by means of the
dh_safe_prime referenced from the latter's context. The value of G OTOH
always equals constant 2 for the safe-prime groups.
Finally, make the remaining two kpp_alg primitives both operating on
kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(),
to merely forward any request to the inner "dh" implementation. However, a
kpp_request instance received from the outside cannot get simply passed
on as-is, because its associated transform (crypto_kpp_reqtfm()) will have
been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve
some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in
turn storing an inner kpp_request suitable for "dh" each. Make the outer
->generate_public_key() and ->compute_shared_secret() respectively to setup
this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req()
helper before handing it over to the "dh" implementation for further
processing. dh_safe_prime_prepare_dh_req() basically copies the outer
kpp_request received from the outside over to the inner one, but installs
the inner transform and its own ->complete() proxy callback therein. This
completion callback, the new dh_safe_prime_complete_req(), doesn't do
anything beyond completing the outer request. Note that there exist some
examples in crypto/, which would simply install the completion handler
from the outer request at the inner one in similar setups, e.g. seqiv.
However, this would mean that the user-provided completion handler won't
get called with the address of the outer kpp_request initially submitted
and the handler might not be prepared for this. Users could certainly work
around this by setting the callback ->data properly, but IMO it's cleaner
this way. Furthermore, it might make sense to extend
dh_safe_prime_complete_req() in the future and move e.g. those
post-computation FIPS checks from the generic "dh" implementation to the
ffdheXYZ(dh) templates.
[1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de
[2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au
Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 12:10:52 +00:00
|
|
|
static int dh_safe_prime_set_secret(struct crypto_kpp *tfm, const void *buffer,
|
|
|
|
unsigned int len)
|
|
|
|
{
|
|
|
|
struct dh_safe_prime_instance_ctx *inst_ctx =
|
|
|
|
dh_safe_prime_instance_ctx(tfm);
|
|
|
|
struct dh_safe_prime_tfm_ctx *tfm_ctx = kpp_tfm_ctx(tfm);
|
2022-02-21 12:10:57 +00:00
|
|
|
struct dh params = {};
|
2022-02-21 12:10:55 +00:00
|
|
|
void *buf = NULL, *key = NULL;
|
crypto: dh - introduce common code for built-in safe-prime group support
Recent work on NVME in-band authentication support ([1]) needs to invoke
the "dh" KPP with the FFDHE safe-prime group parameters as specified in
RFC 7919 and generate ephemeral keys suitable for the respective group. By
coincidence, the requirements from NIST SP800-56Arev3,
sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down
to disallowing any group parameters not among the approved safe-prime
groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore,
SP800-56Arev3 specifies the respective security strength for each of the
approved safe-prime groups, which has a direct impact on the minimum key
lengths.
In this light, it's desirable to introduce built-in support for the
RFC 7919 safe-prime groups to the kernel's DH implementation, provide a
SP800-56Arev3 conforming key generation primitive for those and render
non-approved group parameters unusable in FIPS mode on the way.
As suggested ([2]) in the course of discussion to previous iterations of
this patchset, the built-in support for ffdhe groups would be best made
available in the form of templates wrapping the existing "dh"
implementation, one for each group specified by RFC 7919: ffdhe2048(dh),
ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these
templates differ only in the safe-prime constants they'd configure the
inner "dh" transforms with, they can share almost all of their
"dh"-wrapping template implementation code.
Introduce this common code to dh_generic. The actual dump of the RFC 7919
safe-prime constants will be deferred to the next patch in order to
facilitate review. The ephemeral key generation primitive mentioned above
likewise deserves a patch on its own, as does the mechanism by which
unapproved groups are rendered unusable in FIPS mode.
Define a struct dh_safe_prime container for specifying the individual
templates' associated safe-prime group constants. All ffdheXYZ(dh) template
instances will store a pointer to such a dh_safe_prime in their context
areas each. Implement the common __dh_safe_prime_create() template
instantiation helper. The intention is that the individual ffdheXYZ(dh)
crypto_templates' ->create() implementations will simply forward any calls
to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition
to the received ->create() arguments. __dh_safe_prime_create() would then
create and register a kpp_instance as appropriate, storing the given
dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh"
kpp_alg in the context area.
As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the
inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to
in turn own an inner "dh" transform, a pointer to which gets stored in the
context area. Setup and teardown are getting handled from the outer
->init_tfm() and ->exit_tfm() respectively.
In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances
configure the inner "dh" transforms with the respective group parameters,
make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill
in the P and G values before forwarding the call to the inner "dh"'s
->set_secret(). Note that the outer ->set_secret() can obtain the P value
associated with the given ffdheXYZ(dh) kpp_instance by means of the
dh_safe_prime referenced from the latter's context. The value of G OTOH
always equals constant 2 for the safe-prime groups.
Finally, make the remaining two kpp_alg primitives both operating on
kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(),
to merely forward any request to the inner "dh" implementation. However, a
kpp_request instance received from the outside cannot get simply passed
on as-is, because its associated transform (crypto_kpp_reqtfm()) will have
been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve
some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in
turn storing an inner kpp_request suitable for "dh" each. Make the outer
->generate_public_key() and ->compute_shared_secret() respectively to setup
this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req()
helper before handing it over to the "dh" implementation for further
processing. dh_safe_prime_prepare_dh_req() basically copies the outer
kpp_request received from the outside over to the inner one, but installs
the inner transform and its own ->complete() proxy callback therein. This
completion callback, the new dh_safe_prime_complete_req(), doesn't do
anything beyond completing the outer request. Note that there exist some
examples in crypto/, which would simply install the completion handler
from the outer request at the inner one in similar setups, e.g. seqiv.
However, this would mean that the user-provided completion handler won't
get called with the address of the outer kpp_request initially submitted
and the handler might not be prepared for this. Users could certainly work
around this by setting the callback ->data properly, but IMO it's cleaner
this way. Furthermore, it might make sense to extend
dh_safe_prime_complete_req() in the future and move e.g. those
post-computation FIPS checks from the generic "dh" implementation to the
ffdheXYZ(dh) templates.
[1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de
[2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au
Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 12:10:52 +00:00
|
|
|
unsigned int buf_size;
|
|
|
|
int err;
|
|
|
|
|
2022-02-21 12:10:57 +00:00
|
|
|
if (buffer) {
|
|
|
|
err = __crypto_dh_decode_key(buffer, len, ¶ms);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (params.p_size || params.g_size)
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
crypto: dh - introduce common code for built-in safe-prime group support
Recent work on NVME in-band authentication support ([1]) needs to invoke
the "dh" KPP with the FFDHE safe-prime group parameters as specified in
RFC 7919 and generate ephemeral keys suitable for the respective group. By
coincidence, the requirements from NIST SP800-56Arev3,
sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down
to disallowing any group parameters not among the approved safe-prime
groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore,
SP800-56Arev3 specifies the respective security strength for each of the
approved safe-prime groups, which has a direct impact on the minimum key
lengths.
In this light, it's desirable to introduce built-in support for the
RFC 7919 safe-prime groups to the kernel's DH implementation, provide a
SP800-56Arev3 conforming key generation primitive for those and render
non-approved group parameters unusable in FIPS mode on the way.
As suggested ([2]) in the course of discussion to previous iterations of
this patchset, the built-in support for ffdhe groups would be best made
available in the form of templates wrapping the existing "dh"
implementation, one for each group specified by RFC 7919: ffdhe2048(dh),
ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these
templates differ only in the safe-prime constants they'd configure the
inner "dh" transforms with, they can share almost all of their
"dh"-wrapping template implementation code.
Introduce this common code to dh_generic. The actual dump of the RFC 7919
safe-prime constants will be deferred to the next patch in order to
facilitate review. The ephemeral key generation primitive mentioned above
likewise deserves a patch on its own, as does the mechanism by which
unapproved groups are rendered unusable in FIPS mode.
Define a struct dh_safe_prime container for specifying the individual
templates' associated safe-prime group constants. All ffdheXYZ(dh) template
instances will store a pointer to such a dh_safe_prime in their context
areas each. Implement the common __dh_safe_prime_create() template
instantiation helper. The intention is that the individual ffdheXYZ(dh)
crypto_templates' ->create() implementations will simply forward any calls
to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition
to the received ->create() arguments. __dh_safe_prime_create() would then
create and register a kpp_instance as appropriate, storing the given
dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh"
kpp_alg in the context area.
As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the
inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to
in turn own an inner "dh" transform, a pointer to which gets stored in the
context area. Setup and teardown are getting handled from the outer
->init_tfm() and ->exit_tfm() respectively.
In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances
configure the inner "dh" transforms with the respective group parameters,
make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill
in the P and G values before forwarding the call to the inner "dh"'s
->set_secret(). Note that the outer ->set_secret() can obtain the P value
associated with the given ffdheXYZ(dh) kpp_instance by means of the
dh_safe_prime referenced from the latter's context. The value of G OTOH
always equals constant 2 for the safe-prime groups.
Finally, make the remaining two kpp_alg primitives both operating on
kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(),
to merely forward any request to the inner "dh" implementation. However, a
kpp_request instance received from the outside cannot get simply passed
on as-is, because its associated transform (crypto_kpp_reqtfm()) will have
been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve
some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in
turn storing an inner kpp_request suitable for "dh" each. Make the outer
->generate_public_key() and ->compute_shared_secret() respectively to setup
this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req()
helper before handing it over to the "dh" implementation for further
processing. dh_safe_prime_prepare_dh_req() basically copies the outer
kpp_request received from the outside over to the inner one, but installs
the inner transform and its own ->complete() proxy callback therein. This
completion callback, the new dh_safe_prime_complete_req(), doesn't do
anything beyond completing the outer request. Note that there exist some
examples in crypto/, which would simply install the completion handler
from the outer request at the inner one in similar setups, e.g. seqiv.
However, this would mean that the user-provided completion handler won't
get called with the address of the outer kpp_request initially submitted
and the handler might not be prepared for this. Users could certainly work
around this by setting the callback ->data properly, but IMO it's cleaner
this way. Furthermore, it might make sense to extend
dh_safe_prime_complete_req() in the future and move e.g. those
post-computation FIPS checks from the generic "dh" implementation to the
ffdheXYZ(dh) templates.
[1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de
[2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au
Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 12:10:52 +00:00
|
|
|
|
|
|
|
params.p = inst_ctx->safe_prime->p;
|
|
|
|
params.p_size = inst_ctx->safe_prime->p_size;
|
|
|
|
params.g = safe_prime_g;
|
|
|
|
params.g_size = sizeof(safe_prime_g);
|
|
|
|
|
2022-02-21 12:10:55 +00:00
|
|
|
if (!params.key_size) {
|
|
|
|
key = dh_safe_prime_gen_privkey(inst_ctx->safe_prime,
|
|
|
|
¶ms.key_size);
|
|
|
|
if (IS_ERR(key))
|
|
|
|
return PTR_ERR(key);
|
|
|
|
params.key = key;
|
|
|
|
}
|
|
|
|
|
crypto: dh - introduce common code for built-in safe-prime group support
Recent work on NVME in-band authentication support ([1]) needs to invoke
the "dh" KPP with the FFDHE safe-prime group parameters as specified in
RFC 7919 and generate ephemeral keys suitable for the respective group. By
coincidence, the requirements from NIST SP800-56Arev3,
sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down
to disallowing any group parameters not among the approved safe-prime
groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore,
SP800-56Arev3 specifies the respective security strength for each of the
approved safe-prime groups, which has a direct impact on the minimum key
lengths.
In this light, it's desirable to introduce built-in support for the
RFC 7919 safe-prime groups to the kernel's DH implementation, provide a
SP800-56Arev3 conforming key generation primitive for those and render
non-approved group parameters unusable in FIPS mode on the way.
As suggested ([2]) in the course of discussion to previous iterations of
this patchset, the built-in support for ffdhe groups would be best made
available in the form of templates wrapping the existing "dh"
implementation, one for each group specified by RFC 7919: ffdhe2048(dh),
ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these
templates differ only in the safe-prime constants they'd configure the
inner "dh" transforms with, they can share almost all of their
"dh"-wrapping template implementation code.
Introduce this common code to dh_generic. The actual dump of the RFC 7919
safe-prime constants will be deferred to the next patch in order to
facilitate review. The ephemeral key generation primitive mentioned above
likewise deserves a patch on its own, as does the mechanism by which
unapproved groups are rendered unusable in FIPS mode.
Define a struct dh_safe_prime container for specifying the individual
templates' associated safe-prime group constants. All ffdheXYZ(dh) template
instances will store a pointer to such a dh_safe_prime in their context
areas each. Implement the common __dh_safe_prime_create() template
instantiation helper. The intention is that the individual ffdheXYZ(dh)
crypto_templates' ->create() implementations will simply forward any calls
to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition
to the received ->create() arguments. __dh_safe_prime_create() would then
create and register a kpp_instance as appropriate, storing the given
dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh"
kpp_alg in the context area.
As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the
inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to
in turn own an inner "dh" transform, a pointer to which gets stored in the
context area. Setup and teardown are getting handled from the outer
->init_tfm() and ->exit_tfm() respectively.
In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances
configure the inner "dh" transforms with the respective group parameters,
make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill
in the P and G values before forwarding the call to the inner "dh"'s
->set_secret(). Note that the outer ->set_secret() can obtain the P value
associated with the given ffdheXYZ(dh) kpp_instance by means of the
dh_safe_prime referenced from the latter's context. The value of G OTOH
always equals constant 2 for the safe-prime groups.
Finally, make the remaining two kpp_alg primitives both operating on
kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(),
to merely forward any request to the inner "dh" implementation. However, a
kpp_request instance received from the outside cannot get simply passed
on as-is, because its associated transform (crypto_kpp_reqtfm()) will have
been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve
some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in
turn storing an inner kpp_request suitable for "dh" each. Make the outer
->generate_public_key() and ->compute_shared_secret() respectively to setup
this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req()
helper before handing it over to the "dh" implementation for further
processing. dh_safe_prime_prepare_dh_req() basically copies the outer
kpp_request received from the outside over to the inner one, but installs
the inner transform and its own ->complete() proxy callback therein. This
completion callback, the new dh_safe_prime_complete_req(), doesn't do
anything beyond completing the outer request. Note that there exist some
examples in crypto/, which would simply install the completion handler
from the outer request at the inner one in similar setups, e.g. seqiv.
However, this would mean that the user-provided completion handler won't
get called with the address of the outer kpp_request initially submitted
and the handler might not be prepared for this. Users could certainly work
around this by setting the callback ->data properly, but IMO it's cleaner
this way. Furthermore, it might make sense to extend
dh_safe_prime_complete_req() in the future and move e.g. those
post-computation FIPS checks from the generic "dh" implementation to the
ffdheXYZ(dh) templates.
[1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de
[2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au
Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 12:10:52 +00:00
|
|
|
buf_size = crypto_dh_key_len(¶ms);
|
|
|
|
buf = kmalloc(buf_size, GFP_KERNEL);
|
2022-02-21 12:10:55 +00:00
|
|
|
if (!buf) {
|
|
|
|
err = -ENOMEM;
|
|
|
|
goto out;
|
|
|
|
}
|
crypto: dh - introduce common code for built-in safe-prime group support
Recent work on NVME in-band authentication support ([1]) needs to invoke
the "dh" KPP with the FFDHE safe-prime group parameters as specified in
RFC 7919 and generate ephemeral keys suitable for the respective group. By
coincidence, the requirements from NIST SP800-56Arev3,
sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down
to disallowing any group parameters not among the approved safe-prime
groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore,
SP800-56Arev3 specifies the respective security strength for each of the
approved safe-prime groups, which has a direct impact on the minimum key
lengths.
In this light, it's desirable to introduce built-in support for the
RFC 7919 safe-prime groups to the kernel's DH implementation, provide a
SP800-56Arev3 conforming key generation primitive for those and render
non-approved group parameters unusable in FIPS mode on the way.
As suggested ([2]) in the course of discussion to previous iterations of
this patchset, the built-in support for ffdhe groups would be best made
available in the form of templates wrapping the existing "dh"
implementation, one for each group specified by RFC 7919: ffdhe2048(dh),
ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these
templates differ only in the safe-prime constants they'd configure the
inner "dh" transforms with, they can share almost all of their
"dh"-wrapping template implementation code.
Introduce this common code to dh_generic. The actual dump of the RFC 7919
safe-prime constants will be deferred to the next patch in order to
facilitate review. The ephemeral key generation primitive mentioned above
likewise deserves a patch on its own, as does the mechanism by which
unapproved groups are rendered unusable in FIPS mode.
Define a struct dh_safe_prime container for specifying the individual
templates' associated safe-prime group constants. All ffdheXYZ(dh) template
instances will store a pointer to such a dh_safe_prime in their context
areas each. Implement the common __dh_safe_prime_create() template
instantiation helper. The intention is that the individual ffdheXYZ(dh)
crypto_templates' ->create() implementations will simply forward any calls
to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition
to the received ->create() arguments. __dh_safe_prime_create() would then
create and register a kpp_instance as appropriate, storing the given
dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh"
kpp_alg in the context area.
As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the
inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to
in turn own an inner "dh" transform, a pointer to which gets stored in the
context area. Setup and teardown are getting handled from the outer
->init_tfm() and ->exit_tfm() respectively.
In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances
configure the inner "dh" transforms with the respective group parameters,
make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill
in the P and G values before forwarding the call to the inner "dh"'s
->set_secret(). Note that the outer ->set_secret() can obtain the P value
associated with the given ffdheXYZ(dh) kpp_instance by means of the
dh_safe_prime referenced from the latter's context. The value of G OTOH
always equals constant 2 for the safe-prime groups.
Finally, make the remaining two kpp_alg primitives both operating on
kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(),
to merely forward any request to the inner "dh" implementation. However, a
kpp_request instance received from the outside cannot get simply passed
on as-is, because its associated transform (crypto_kpp_reqtfm()) will have
been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve
some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in
turn storing an inner kpp_request suitable for "dh" each. Make the outer
->generate_public_key() and ->compute_shared_secret() respectively to setup
this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req()
helper before handing it over to the "dh" implementation for further
processing. dh_safe_prime_prepare_dh_req() basically copies the outer
kpp_request received from the outside over to the inner one, but installs
the inner transform and its own ->complete() proxy callback therein. This
completion callback, the new dh_safe_prime_complete_req(), doesn't do
anything beyond completing the outer request. Note that there exist some
examples in crypto/, which would simply install the completion handler
from the outer request at the inner one in similar setups, e.g. seqiv.
However, this would mean that the user-provided completion handler won't
get called with the address of the outer kpp_request initially submitted
and the handler might not be prepared for this. Users could certainly work
around this by setting the callback ->data properly, but IMO it's cleaner
this way. Furthermore, it might make sense to extend
dh_safe_prime_complete_req() in the future and move e.g. those
post-computation FIPS checks from the generic "dh" implementation to the
ffdheXYZ(dh) templates.
[1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de
[2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au
Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 12:10:52 +00:00
|
|
|
|
|
|
|
err = crypto_dh_encode_key(buf, buf_size, ¶ms);
|
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
err = crypto_kpp_set_secret(tfm_ctx->dh_tfm, buf, buf_size);
|
|
|
|
out:
|
|
|
|
kfree_sensitive(buf);
|
2022-02-21 12:10:55 +00:00
|
|
|
kfree_sensitive(key);
|
crypto: dh - introduce common code for built-in safe-prime group support
Recent work on NVME in-band authentication support ([1]) needs to invoke
the "dh" KPP with the FFDHE safe-prime group parameters as specified in
RFC 7919 and generate ephemeral keys suitable for the respective group. By
coincidence, the requirements from NIST SP800-56Arev3,
sec. 5.5.2 ("Assurance of Domain-Parameter Validity") basically boil down
to disallowing any group parameters not among the approved safe-prime
groups specified in either RFC 7919 or RFC 3526 in FIPS mode. Furthermore,
SP800-56Arev3 specifies the respective security strength for each of the
approved safe-prime groups, which has a direct impact on the minimum key
lengths.
In this light, it's desirable to introduce built-in support for the
RFC 7919 safe-prime groups to the kernel's DH implementation, provide a
SP800-56Arev3 conforming key generation primitive for those and render
non-approved group parameters unusable in FIPS mode on the way.
As suggested ([2]) in the course of discussion to previous iterations of
this patchset, the built-in support for ffdhe groups would be best made
available in the form of templates wrapping the existing "dh"
implementation, one for each group specified by RFC 7919: ffdhe2048(dh),
ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and ffdhe8192(dh). As these
templates differ only in the safe-prime constants they'd configure the
inner "dh" transforms with, they can share almost all of their
"dh"-wrapping template implementation code.
Introduce this common code to dh_generic. The actual dump of the RFC 7919
safe-prime constants will be deferred to the next patch in order to
facilitate review. The ephemeral key generation primitive mentioned above
likewise deserves a patch on its own, as does the mechanism by which
unapproved groups are rendered unusable in FIPS mode.
Define a struct dh_safe_prime container for specifying the individual
templates' associated safe-prime group constants. All ffdheXYZ(dh) template
instances will store a pointer to such a dh_safe_prime in their context
areas each. Implement the common __dh_safe_prime_create() template
instantiation helper. The intention is that the individual ffdheXYZ(dh)
crypto_templates' ->create() implementations will simply forward any calls
to __dh_safe_prime_create(), passing a suitable dh_safe_prime in addition
to the received ->create() arguments. __dh_safe_prime_create() would then
create and register a kpp_instance as appropriate, storing the given
dh_safe_prime pointer alongside a crypto_kpp_spawn for the inner "dh"
kpp_alg in the context area.
As the ffdheXYZ(dh) kpp_instances are supposed to act as proxies to the
inner "dh" kpp_alg, make each of their associated crypto_kpp transforms to
in turn own an inner "dh" transform, a pointer to which gets stored in the
context area. Setup and teardown are getting handled from the outer
->init_tfm() and ->exit_tfm() respectively.
In order to achieve the overall goal and let the ffdheXYZ(dh) kpp_instances
configure the inner "dh" transforms with the respective group parameters,
make their common ->set_secret(), the new dh_safe_prime_set_secret(), fill
in the P and G values before forwarding the call to the inner "dh"'s
->set_secret(). Note that the outer ->set_secret() can obtain the P value
associated with the given ffdheXYZ(dh) kpp_instance by means of the
dh_safe_prime referenced from the latter's context. The value of G OTOH
always equals constant 2 for the safe-prime groups.
Finally, make the remaining two kpp_alg primitives both operating on
kpp_requests, i.e. ->generate_public_key() and ->compute_shared_secret(),
to merely forward any request to the inner "dh" implementation. However, a
kpp_request instance received from the outside cannot get simply passed
on as-is, because its associated transform (crypto_kpp_reqtfm()) will have
been set to the outer ffdheXYZ(dh) one. In order to handle this, reserve
some space in the outer ffdheXYZ(dh) kpp_requests' context areas for in
turn storing an inner kpp_request suitable for "dh" each. Make the outer
->generate_public_key() and ->compute_shared_secret() respectively to setup
this inner kpp_request by means of the new dh_safe_prime_prepare_dh_req()
helper before handing it over to the "dh" implementation for further
processing. dh_safe_prime_prepare_dh_req() basically copies the outer
kpp_request received from the outside over to the inner one, but installs
the inner transform and its own ->complete() proxy callback therein. This
completion callback, the new dh_safe_prime_complete_req(), doesn't do
anything beyond completing the outer request. Note that there exist some
examples in crypto/, which would simply install the completion handler
from the outer request at the inner one in similar setups, e.g. seqiv.
However, this would mean that the user-provided completion handler won't
get called with the address of the outer kpp_request initially submitted
and the handler might not be prepared for this. Users could certainly work
around this by setting the callback ->data properly, but IMO it's cleaner
this way. Furthermore, it might make sense to extend
dh_safe_prime_complete_req() in the future and move e.g. those
post-computation FIPS checks from the generic "dh" implementation to the
ffdheXYZ(dh) templates.
[1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de
[2] https://lore.kernel.org/r/20211217055227.GA20698@gondor.apana.org.au
Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 12:10:52 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dh_safe_prime_complete_req(struct crypto_async_request *dh_req,
|
|
|
|
int err)
|
|
|
|
{
|
|
|
|
struct kpp_request *req = dh_req->data;
|
|
|
|
|
|
|
|
kpp_request_complete(req, err);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct kpp_request *dh_safe_prime_prepare_dh_req(struct kpp_request *req)
|
|
|
|
{
|
|
|
|
struct dh_safe_prime_tfm_ctx *tfm_ctx =
|
|
|
|
kpp_tfm_ctx(crypto_kpp_reqtfm(req));
|
|
|
|
struct kpp_request *dh_req = kpp_request_ctx(req);
|
|
|
|
|
|
|
|
kpp_request_set_tfm(dh_req, tfm_ctx->dh_tfm);
|
|
|
|
kpp_request_set_callback(dh_req, req->base.flags,
|
|
|
|
dh_safe_prime_complete_req, req);
|
|
|
|
|
|
|
|
kpp_request_set_input(dh_req, req->src, req->src_len);
|
|
|
|
kpp_request_set_output(dh_req, req->dst, req->dst_len);
|
|
|
|
|
|
|
|
return dh_req;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dh_safe_prime_generate_public_key(struct kpp_request *req)
|
|
|
|
{
|
|
|
|
struct kpp_request *dh_req = dh_safe_prime_prepare_dh_req(req);
|
|
|
|
|
|
|
|
return crypto_kpp_generate_public_key(dh_req);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dh_safe_prime_compute_shared_secret(struct kpp_request *req)
|
|
|
|
{
|
|
|
|
struct kpp_request *dh_req = dh_safe_prime_prepare_dh_req(req);
|
|
|
|
|
|
|
|
return crypto_kpp_compute_shared_secret(dh_req);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int dh_safe_prime_max_size(struct crypto_kpp *tfm)
|
|
|
|
{
|
|
|
|
struct dh_safe_prime_tfm_ctx *tfm_ctx = kpp_tfm_ctx(tfm);
|
|
|
|
|
|
|
|
return crypto_kpp_maxsize(tfm_ctx->dh_tfm);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __maybe_unused __dh_safe_prime_create(
|
|
|
|
struct crypto_template *tmpl, struct rtattr **tb,
|
|
|
|
const struct dh_safe_prime *safe_prime)
|
|
|
|
{
|
|
|
|
struct kpp_instance *inst;
|
|
|
|
struct dh_safe_prime_instance_ctx *ctx;
|
|
|
|
const char *dh_name;
|
|
|
|
struct kpp_alg *dh_alg;
|
|
|
|
u32 mask;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_KPP, &mask);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
dh_name = crypto_attr_alg_name(tb[1]);
|
|
|
|
if (IS_ERR(dh_name))
|
|
|
|
return PTR_ERR(dh_name);
|
|
|
|
|
|
|
|
inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
|
|
|
|
if (!inst)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
ctx = kpp_instance_ctx(inst);
|
|
|
|
|
|
|
|
err = crypto_grab_kpp(&ctx->dh_spawn, kpp_crypto_instance(inst),
|
|
|
|
dh_name, 0, mask);
|
|
|
|
if (err)
|
|
|
|
goto err_free_inst;
|
|
|
|
|
|
|
|
err = -EINVAL;
|
|
|
|
dh_alg = crypto_spawn_kpp_alg(&ctx->dh_spawn);
|
|
|
|
if (strcmp(dh_alg->base.cra_name, "dh"))
|
|
|
|
goto err_free_inst;
|
|
|
|
|
|
|
|
ctx->safe_prime = safe_prime;
|
|
|
|
|
|
|
|
err = crypto_inst_setname(kpp_crypto_instance(inst),
|
|
|
|
tmpl->name, &dh_alg->base);
|
|
|
|
if (err)
|
|
|
|
goto err_free_inst;
|
|
|
|
|
|
|
|
inst->alg.set_secret = dh_safe_prime_set_secret;
|
|
|
|
inst->alg.generate_public_key = dh_safe_prime_generate_public_key;
|
|
|
|
inst->alg.compute_shared_secret = dh_safe_prime_compute_shared_secret;
|
|
|
|
inst->alg.max_size = dh_safe_prime_max_size;
|
|
|
|
inst->alg.init = dh_safe_prime_init_tfm;
|
|
|
|
inst->alg.exit = dh_safe_prime_exit_tfm;
|
|
|
|
inst->alg.base.cra_priority = dh_alg->base.cra_priority;
|
|
|
|
inst->alg.base.cra_module = THIS_MODULE;
|
|
|
|
inst->alg.base.cra_ctxsize = sizeof(struct dh_safe_prime_tfm_ctx);
|
|
|
|
|
|
|
|
inst->free = dh_safe_prime_free_instance;
|
|
|
|
|
|
|
|
err = kpp_register_instance(tmpl, inst);
|
|
|
|
if (err)
|
|
|
|
goto err_free_inst;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_free_inst:
|
|
|
|
dh_safe_prime_free_instance(inst);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
crypto: dh - implement ffdheXYZ(dh) templates
Current work on NVME in-band authentication support ([1]) needs to invoke
DH with the FFDHE safe-prime group parameters specified in RFC 7919.
Introduce a new CRYPTO_DH_RFC7919_GROUPS Kconfig option. If enabled, make
dh_generic register a couple of ffdheXYZ(dh) templates, one for each group:
ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and
ffdhe8192(dh). Their respective ->set_secret() expects a (serialized)
struct dh, just like the underlying "dh" implementation does, but with the
P and G values unset so that the safe-prime constants for the given group
can be filled in by the wrapping template.
Internally, a struct dh_safe_prime instance is being defined for each of
the ffdheXYZ(dh) templates as appropriate. In order to prepare for future
key generation, fill in the maximum security strength values as specified
by SP800-56Arev3 on the go, even though they're not needed at this point
yet.
Implement the respective ffdheXYZ(dh) crypto_template's ->create() by
simply forwarding any calls to the __dh_safe_prime_create() helper
introduced with the previous commit, passing the associated dh_safe_prime
in addition to the received ->create() arguments.
[1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de
Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 12:10:53 +00:00
|
|
|
#ifdef CONFIG_CRYPTO_DH_RFC7919_GROUPS
|
|
|
|
|
|
|
|
static const struct dh_safe_prime ffdhe2048_prime = {
|
|
|
|
.max_strength = 112,
|
|
|
|
.p_size = 256,
|
|
|
|
.p =
|
|
|
|
"\xff\xff\xff\xff\xff\xff\xff\xff\xad\xf8\x54\x58\xa2\xbb\x4a\x9a"
|
|
|
|
"\xaf\xdc\x56\x20\x27\x3d\x3c\xf1\xd8\xb9\xc5\x83\xce\x2d\x36\x95"
|
|
|
|
"\xa9\xe1\x36\x41\x14\x64\x33\xfb\xcc\x93\x9d\xce\x24\x9b\x3e\xf9"
|
|
|
|
"\x7d\x2f\xe3\x63\x63\x0c\x75\xd8\xf6\x81\xb2\x02\xae\xc4\x61\x7a"
|
|
|
|
"\xd3\xdf\x1e\xd5\xd5\xfd\x65\x61\x24\x33\xf5\x1f\x5f\x06\x6e\xd0"
|
|
|
|
"\x85\x63\x65\x55\x3d\xed\x1a\xf3\xb5\x57\x13\x5e\x7f\x57\xc9\x35"
|
|
|
|
"\x98\x4f\x0c\x70\xe0\xe6\x8b\x77\xe2\xa6\x89\xda\xf3\xef\xe8\x72"
|
|
|
|
"\x1d\xf1\x58\xa1\x36\xad\xe7\x35\x30\xac\xca\x4f\x48\x3a\x79\x7a"
|
|
|
|
"\xbc\x0a\xb1\x82\xb3\x24\xfb\x61\xd1\x08\xa9\x4b\xb2\xc8\xe3\xfb"
|
|
|
|
"\xb9\x6a\xda\xb7\x60\xd7\xf4\x68\x1d\x4f\x42\xa3\xde\x39\x4d\xf4"
|
|
|
|
"\xae\x56\xed\xe7\x63\x72\xbb\x19\x0b\x07\xa7\xc8\xee\x0a\x6d\x70"
|
|
|
|
"\x9e\x02\xfc\xe1\xcd\xf7\xe2\xec\xc0\x34\x04\xcd\x28\x34\x2f\x61"
|
|
|
|
"\x91\x72\xfe\x9c\xe9\x85\x83\xff\x8e\x4f\x12\x32\xee\xf2\x81\x83"
|
|
|
|
"\xc3\xfe\x3b\x1b\x4c\x6f\xad\x73\x3b\xb5\xfc\xbc\x2e\xc2\x20\x05"
|
|
|
|
"\xc5\x8e\xf1\x83\x7d\x16\x83\xb2\xc6\xf3\x4a\x26\xc1\xb2\xef\xfa"
|
|
|
|
"\x88\x6b\x42\x38\x61\x28\x5c\x97\xff\xff\xff\xff\xff\xff\xff\xff",
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct dh_safe_prime ffdhe3072_prime = {
|
|
|
|
.max_strength = 128,
|
|
|
|
.p_size = 384,
|
|
|
|
.p =
|
|
|
|
"\xff\xff\xff\xff\xff\xff\xff\xff\xad\xf8\x54\x58\xa2\xbb\x4a\x9a"
|
|
|
|
"\xaf\xdc\x56\x20\x27\x3d\x3c\xf1\xd8\xb9\xc5\x83\xce\x2d\x36\x95"
|
|
|
|
"\xa9\xe1\x36\x41\x14\x64\x33\xfb\xcc\x93\x9d\xce\x24\x9b\x3e\xf9"
|
|
|
|
"\x7d\x2f\xe3\x63\x63\x0c\x75\xd8\xf6\x81\xb2\x02\xae\xc4\x61\x7a"
|
|
|
|
"\xd3\xdf\x1e\xd5\xd5\xfd\x65\x61\x24\x33\xf5\x1f\x5f\x06\x6e\xd0"
|
|
|
|
"\x85\x63\x65\x55\x3d\xed\x1a\xf3\xb5\x57\x13\x5e\x7f\x57\xc9\x35"
|
|
|
|
"\x98\x4f\x0c\x70\xe0\xe6\x8b\x77\xe2\xa6\x89\xda\xf3\xef\xe8\x72"
|
|
|
|
"\x1d\xf1\x58\xa1\x36\xad\xe7\x35\x30\xac\xca\x4f\x48\x3a\x79\x7a"
|
|
|
|
"\xbc\x0a\xb1\x82\xb3\x24\xfb\x61\xd1\x08\xa9\x4b\xb2\xc8\xe3\xfb"
|
|
|
|
"\xb9\x6a\xda\xb7\x60\xd7\xf4\x68\x1d\x4f\x42\xa3\xde\x39\x4d\xf4"
|
|
|
|
"\xae\x56\xed\xe7\x63\x72\xbb\x19\x0b\x07\xa7\xc8\xee\x0a\x6d\x70"
|
|
|
|
"\x9e\x02\xfc\xe1\xcd\xf7\xe2\xec\xc0\x34\x04\xcd\x28\x34\x2f\x61"
|
|
|
|
"\x91\x72\xfe\x9c\xe9\x85\x83\xff\x8e\x4f\x12\x32\xee\xf2\x81\x83"
|
|
|
|
"\xc3\xfe\x3b\x1b\x4c\x6f\xad\x73\x3b\xb5\xfc\xbc\x2e\xc2\x20\x05"
|
|
|
|
"\xc5\x8e\xf1\x83\x7d\x16\x83\xb2\xc6\xf3\x4a\x26\xc1\xb2\xef\xfa"
|
|
|
|
"\x88\x6b\x42\x38\x61\x1f\xcf\xdc\xde\x35\x5b\x3b\x65\x19\x03\x5b"
|
|
|
|
"\xbc\x34\xf4\xde\xf9\x9c\x02\x38\x61\xb4\x6f\xc9\xd6\xe6\xc9\x07"
|
|
|
|
"\x7a\xd9\x1d\x26\x91\xf7\xf7\xee\x59\x8c\xb0\xfa\xc1\x86\xd9\x1c"
|
|
|
|
"\xae\xfe\x13\x09\x85\x13\x92\x70\xb4\x13\x0c\x93\xbc\x43\x79\x44"
|
|
|
|
"\xf4\xfd\x44\x52\xe2\xd7\x4d\xd3\x64\xf2\xe2\x1e\x71\xf5\x4b\xff"
|
|
|
|
"\x5c\xae\x82\xab\x9c\x9d\xf6\x9e\xe8\x6d\x2b\xc5\x22\x36\x3a\x0d"
|
|
|
|
"\xab\xc5\x21\x97\x9b\x0d\xea\xda\x1d\xbf\x9a\x42\xd5\xc4\x48\x4e"
|
|
|
|
"\x0a\xbc\xd0\x6b\xfa\x53\xdd\xef\x3c\x1b\x20\xee\x3f\xd5\x9d\x7c"
|
|
|
|
"\x25\xe4\x1d\x2b\x66\xc6\x2e\x37\xff\xff\xff\xff\xff\xff\xff\xff",
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct dh_safe_prime ffdhe4096_prime = {
|
|
|
|
.max_strength = 152,
|
|
|
|
.p_size = 512,
|
|
|
|
.p =
|
|
|
|
"\xff\xff\xff\xff\xff\xff\xff\xff\xad\xf8\x54\x58\xa2\xbb\x4a\x9a"
|
|
|
|
"\xaf\xdc\x56\x20\x27\x3d\x3c\xf1\xd8\xb9\xc5\x83\xce\x2d\x36\x95"
|
|
|
|
"\xa9\xe1\x36\x41\x14\x64\x33\xfb\xcc\x93\x9d\xce\x24\x9b\x3e\xf9"
|
|
|
|
"\x7d\x2f\xe3\x63\x63\x0c\x75\xd8\xf6\x81\xb2\x02\xae\xc4\x61\x7a"
|
|
|
|
"\xd3\xdf\x1e\xd5\xd5\xfd\x65\x61\x24\x33\xf5\x1f\x5f\x06\x6e\xd0"
|
|
|
|
"\x85\x63\x65\x55\x3d\xed\x1a\xf3\xb5\x57\x13\x5e\x7f\x57\xc9\x35"
|
|
|
|
"\x98\x4f\x0c\x70\xe0\xe6\x8b\x77\xe2\xa6\x89\xda\xf3\xef\xe8\x72"
|
|
|
|
"\x1d\xf1\x58\xa1\x36\xad\xe7\x35\x30\xac\xca\x4f\x48\x3a\x79\x7a"
|
|
|
|
"\xbc\x0a\xb1\x82\xb3\x24\xfb\x61\xd1\x08\xa9\x4b\xb2\xc8\xe3\xfb"
|
|
|
|
"\xb9\x6a\xda\xb7\x60\xd7\xf4\x68\x1d\x4f\x42\xa3\xde\x39\x4d\xf4"
|
|
|
|
"\xae\x56\xed\xe7\x63\x72\xbb\x19\x0b\x07\xa7\xc8\xee\x0a\x6d\x70"
|
|
|
|
"\x9e\x02\xfc\xe1\xcd\xf7\xe2\xec\xc0\x34\x04\xcd\x28\x34\x2f\x61"
|
|
|
|
"\x91\x72\xfe\x9c\xe9\x85\x83\xff\x8e\x4f\x12\x32\xee\xf2\x81\x83"
|
|
|
|
"\xc3\xfe\x3b\x1b\x4c\x6f\xad\x73\x3b\xb5\xfc\xbc\x2e\xc2\x20\x05"
|
|
|
|
"\xc5\x8e\xf1\x83\x7d\x16\x83\xb2\xc6\xf3\x4a\x26\xc1\xb2\xef\xfa"
|
|
|
|
"\x88\x6b\x42\x38\x61\x1f\xcf\xdc\xde\x35\x5b\x3b\x65\x19\x03\x5b"
|
|
|
|
"\xbc\x34\xf4\xde\xf9\x9c\x02\x38\x61\xb4\x6f\xc9\xd6\xe6\xc9\x07"
|
|
|
|
"\x7a\xd9\x1d\x26\x91\xf7\xf7\xee\x59\x8c\xb0\xfa\xc1\x86\xd9\x1c"
|
|
|
|
"\xae\xfe\x13\x09\x85\x13\x92\x70\xb4\x13\x0c\x93\xbc\x43\x79\x44"
|
|
|
|
"\xf4\xfd\x44\x52\xe2\xd7\x4d\xd3\x64\xf2\xe2\x1e\x71\xf5\x4b\xff"
|
|
|
|
"\x5c\xae\x82\xab\x9c\x9d\xf6\x9e\xe8\x6d\x2b\xc5\x22\x36\x3a\x0d"
|
|
|
|
"\xab\xc5\x21\x97\x9b\x0d\xea\xda\x1d\xbf\x9a\x42\xd5\xc4\x48\x4e"
|
|
|
|
"\x0a\xbc\xd0\x6b\xfa\x53\xdd\xef\x3c\x1b\x20\xee\x3f\xd5\x9d\x7c"
|
|
|
|
"\x25\xe4\x1d\x2b\x66\x9e\x1e\xf1\x6e\x6f\x52\xc3\x16\x4d\xf4\xfb"
|
|
|
|
"\x79\x30\xe9\xe4\xe5\x88\x57\xb6\xac\x7d\x5f\x42\xd6\x9f\x6d\x18"
|
|
|
|
"\x77\x63\xcf\x1d\x55\x03\x40\x04\x87\xf5\x5b\xa5\x7e\x31\xcc\x7a"
|
|
|
|
"\x71\x35\xc8\x86\xef\xb4\x31\x8a\xed\x6a\x1e\x01\x2d\x9e\x68\x32"
|
|
|
|
"\xa9\x07\x60\x0a\x91\x81\x30\xc4\x6d\xc7\x78\xf9\x71\xad\x00\x38"
|
|
|
|
"\x09\x29\x99\xa3\x33\xcb\x8b\x7a\x1a\x1d\xb9\x3d\x71\x40\x00\x3c"
|
|
|
|
"\x2a\x4e\xce\xa9\xf9\x8d\x0a\xcc\x0a\x82\x91\xcd\xce\xc9\x7d\xcf"
|
|
|
|
"\x8e\xc9\xb5\x5a\x7f\x88\xa4\x6b\x4d\xb5\xa8\x51\xf4\x41\x82\xe1"
|
|
|
|
"\xc6\x8a\x00\x7e\x5e\x65\x5f\x6a\xff\xff\xff\xff\xff\xff\xff\xff",
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct dh_safe_prime ffdhe6144_prime = {
|
|
|
|
.max_strength = 176,
|
|
|
|
.p_size = 768,
|
|
|
|
.p =
|
|
|
|
"\xff\xff\xff\xff\xff\xff\xff\xff\xad\xf8\x54\x58\xa2\xbb\x4a\x9a"
|
|
|
|
"\xaf\xdc\x56\x20\x27\x3d\x3c\xf1\xd8\xb9\xc5\x83\xce\x2d\x36\x95"
|
|
|
|
"\xa9\xe1\x36\x41\x14\x64\x33\xfb\xcc\x93\x9d\xce\x24\x9b\x3e\xf9"
|
|
|
|
"\x7d\x2f\xe3\x63\x63\x0c\x75\xd8\xf6\x81\xb2\x02\xae\xc4\x61\x7a"
|
|
|
|
"\xd3\xdf\x1e\xd5\xd5\xfd\x65\x61\x24\x33\xf5\x1f\x5f\x06\x6e\xd0"
|
|
|
|
"\x85\x63\x65\x55\x3d\xed\x1a\xf3\xb5\x57\x13\x5e\x7f\x57\xc9\x35"
|
|
|
|
"\x98\x4f\x0c\x70\xe0\xe6\x8b\x77\xe2\xa6\x89\xda\xf3\xef\xe8\x72"
|
|
|
|
"\x1d\xf1\x58\xa1\x36\xad\xe7\x35\x30\xac\xca\x4f\x48\x3a\x79\x7a"
|
|
|
|
"\xbc\x0a\xb1\x82\xb3\x24\xfb\x61\xd1\x08\xa9\x4b\xb2\xc8\xe3\xfb"
|
|
|
|
"\xb9\x6a\xda\xb7\x60\xd7\xf4\x68\x1d\x4f\x42\xa3\xde\x39\x4d\xf4"
|
|
|
|
"\xae\x56\xed\xe7\x63\x72\xbb\x19\x0b\x07\xa7\xc8\xee\x0a\x6d\x70"
|
|
|
|
"\x9e\x02\xfc\xe1\xcd\xf7\xe2\xec\xc0\x34\x04\xcd\x28\x34\x2f\x61"
|
|
|
|
"\x91\x72\xfe\x9c\xe9\x85\x83\xff\x8e\x4f\x12\x32\xee\xf2\x81\x83"
|
|
|
|
"\xc3\xfe\x3b\x1b\x4c\x6f\xad\x73\x3b\xb5\xfc\xbc\x2e\xc2\x20\x05"
|
|
|
|
"\xc5\x8e\xf1\x83\x7d\x16\x83\xb2\xc6\xf3\x4a\x26\xc1\xb2\xef\xfa"
|
|
|
|
"\x88\x6b\x42\x38\x61\x1f\xcf\xdc\xde\x35\x5b\x3b\x65\x19\x03\x5b"
|
|
|
|
"\xbc\x34\xf4\xde\xf9\x9c\x02\x38\x61\xb4\x6f\xc9\xd6\xe6\xc9\x07"
|
|
|
|
"\x7a\xd9\x1d\x26\x91\xf7\xf7\xee\x59\x8c\xb0\xfa\xc1\x86\xd9\x1c"
|
|
|
|
"\xae\xfe\x13\x09\x85\x13\x92\x70\xb4\x13\x0c\x93\xbc\x43\x79\x44"
|
|
|
|
"\xf4\xfd\x44\x52\xe2\xd7\x4d\xd3\x64\xf2\xe2\x1e\x71\xf5\x4b\xff"
|
|
|
|
"\x5c\xae\x82\xab\x9c\x9d\xf6\x9e\xe8\x6d\x2b\xc5\x22\x36\x3a\x0d"
|
|
|
|
"\xab\xc5\x21\x97\x9b\x0d\xea\xda\x1d\xbf\x9a\x42\xd5\xc4\x48\x4e"
|
|
|
|
"\x0a\xbc\xd0\x6b\xfa\x53\xdd\xef\x3c\x1b\x20\xee\x3f\xd5\x9d\x7c"
|
|
|
|
"\x25\xe4\x1d\x2b\x66\x9e\x1e\xf1\x6e\x6f\x52\xc3\x16\x4d\xf4\xfb"
|
|
|
|
"\x79\x30\xe9\xe4\xe5\x88\x57\xb6\xac\x7d\x5f\x42\xd6\x9f\x6d\x18"
|
|
|
|
"\x77\x63\xcf\x1d\x55\x03\x40\x04\x87\xf5\x5b\xa5\x7e\x31\xcc\x7a"
|
|
|
|
"\x71\x35\xc8\x86\xef\xb4\x31\x8a\xed\x6a\x1e\x01\x2d\x9e\x68\x32"
|
|
|
|
"\xa9\x07\x60\x0a\x91\x81\x30\xc4\x6d\xc7\x78\xf9\x71\xad\x00\x38"
|
|
|
|
"\x09\x29\x99\xa3\x33\xcb\x8b\x7a\x1a\x1d\xb9\x3d\x71\x40\x00\x3c"
|
|
|
|
"\x2a\x4e\xce\xa9\xf9\x8d\x0a\xcc\x0a\x82\x91\xcd\xce\xc9\x7d\xcf"
|
|
|
|
"\x8e\xc9\xb5\x5a\x7f\x88\xa4\x6b\x4d\xb5\xa8\x51\xf4\x41\x82\xe1"
|
|
|
|
"\xc6\x8a\x00\x7e\x5e\x0d\xd9\x02\x0b\xfd\x64\xb6\x45\x03\x6c\x7a"
|
|
|
|
"\x4e\x67\x7d\x2c\x38\x53\x2a\x3a\x23\xba\x44\x42\xca\xf5\x3e\xa6"
|
|
|
|
"\x3b\xb4\x54\x32\x9b\x76\x24\xc8\x91\x7b\xdd\x64\xb1\xc0\xfd\x4c"
|
|
|
|
"\xb3\x8e\x8c\x33\x4c\x70\x1c\x3a\xcd\xad\x06\x57\xfc\xcf\xec\x71"
|
|
|
|
"\x9b\x1f\x5c\x3e\x4e\x46\x04\x1f\x38\x81\x47\xfb\x4c\xfd\xb4\x77"
|
|
|
|
"\xa5\x24\x71\xf7\xa9\xa9\x69\x10\xb8\x55\x32\x2e\xdb\x63\x40\xd8"
|
|
|
|
"\xa0\x0e\xf0\x92\x35\x05\x11\xe3\x0a\xbe\xc1\xff\xf9\xe3\xa2\x6e"
|
|
|
|
"\x7f\xb2\x9f\x8c\x18\x30\x23\xc3\x58\x7e\x38\xda\x00\x77\xd9\xb4"
|
|
|
|
"\x76\x3e\x4e\x4b\x94\xb2\xbb\xc1\x94\xc6\x65\x1e\x77\xca\xf9\x92"
|
|
|
|
"\xee\xaa\xc0\x23\x2a\x28\x1b\xf6\xb3\xa7\x39\xc1\x22\x61\x16\x82"
|
|
|
|
"\x0a\xe8\xdb\x58\x47\xa6\x7c\xbe\xf9\xc9\x09\x1b\x46\x2d\x53\x8c"
|
|
|
|
"\xd7\x2b\x03\x74\x6a\xe7\x7f\x5e\x62\x29\x2c\x31\x15\x62\xa8\x46"
|
|
|
|
"\x50\x5d\xc8\x2d\xb8\x54\x33\x8a\xe4\x9f\x52\x35\xc9\x5b\x91\x17"
|
|
|
|
"\x8c\xcf\x2d\xd5\xca\xce\xf4\x03\xec\x9d\x18\x10\xc6\x27\x2b\x04"
|
|
|
|
"\x5b\x3b\x71\xf9\xdc\x6b\x80\xd6\x3f\xdd\x4a\x8e\x9a\xdb\x1e\x69"
|
|
|
|
"\x62\xa6\x95\x26\xd4\x31\x61\xc1\xa4\x1d\x57\x0d\x79\x38\xda\xd4"
|
|
|
|
"\xa4\x0e\x32\x9c\xd0\xe4\x0e\x65\xff\xff\xff\xff\xff\xff\xff\xff",
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct dh_safe_prime ffdhe8192_prime = {
|
|
|
|
.max_strength = 200,
|
|
|
|
.p_size = 1024,
|
|
|
|
.p =
|
|
|
|
"\xff\xff\xff\xff\xff\xff\xff\xff\xad\xf8\x54\x58\xa2\xbb\x4a\x9a"
|
|
|
|
"\xaf\xdc\x56\x20\x27\x3d\x3c\xf1\xd8\xb9\xc5\x83\xce\x2d\x36\x95"
|
|
|
|
"\xa9\xe1\x36\x41\x14\x64\x33\xfb\xcc\x93\x9d\xce\x24\x9b\x3e\xf9"
|
|
|
|
"\x7d\x2f\xe3\x63\x63\x0c\x75\xd8\xf6\x81\xb2\x02\xae\xc4\x61\x7a"
|
|
|
|
"\xd3\xdf\x1e\xd5\xd5\xfd\x65\x61\x24\x33\xf5\x1f\x5f\x06\x6e\xd0"
|
|
|
|
"\x85\x63\x65\x55\x3d\xed\x1a\xf3\xb5\x57\x13\x5e\x7f\x57\xc9\x35"
|
|
|
|
"\x98\x4f\x0c\x70\xe0\xe6\x8b\x77\xe2\xa6\x89\xda\xf3\xef\xe8\x72"
|
|
|
|
"\x1d\xf1\x58\xa1\x36\xad\xe7\x35\x30\xac\xca\x4f\x48\x3a\x79\x7a"
|
|
|
|
"\xbc\x0a\xb1\x82\xb3\x24\xfb\x61\xd1\x08\xa9\x4b\xb2\xc8\xe3\xfb"
|
|
|
|
"\xb9\x6a\xda\xb7\x60\xd7\xf4\x68\x1d\x4f\x42\xa3\xde\x39\x4d\xf4"
|
|
|
|
"\xae\x56\xed\xe7\x63\x72\xbb\x19\x0b\x07\xa7\xc8\xee\x0a\x6d\x70"
|
|
|
|
"\x9e\x02\xfc\xe1\xcd\xf7\xe2\xec\xc0\x34\x04\xcd\x28\x34\x2f\x61"
|
|
|
|
"\x91\x72\xfe\x9c\xe9\x85\x83\xff\x8e\x4f\x12\x32\xee\xf2\x81\x83"
|
|
|
|
"\xc3\xfe\x3b\x1b\x4c\x6f\xad\x73\x3b\xb5\xfc\xbc\x2e\xc2\x20\x05"
|
|
|
|
"\xc5\x8e\xf1\x83\x7d\x16\x83\xb2\xc6\xf3\x4a\x26\xc1\xb2\xef\xfa"
|
|
|
|
"\x88\x6b\x42\x38\x61\x1f\xcf\xdc\xde\x35\x5b\x3b\x65\x19\x03\x5b"
|
|
|
|
"\xbc\x34\xf4\xde\xf9\x9c\x02\x38\x61\xb4\x6f\xc9\xd6\xe6\xc9\x07"
|
|
|
|
"\x7a\xd9\x1d\x26\x91\xf7\xf7\xee\x59\x8c\xb0\xfa\xc1\x86\xd9\x1c"
|
|
|
|
"\xae\xfe\x13\x09\x85\x13\x92\x70\xb4\x13\x0c\x93\xbc\x43\x79\x44"
|
|
|
|
"\xf4\xfd\x44\x52\xe2\xd7\x4d\xd3\x64\xf2\xe2\x1e\x71\xf5\x4b\xff"
|
|
|
|
"\x5c\xae\x82\xab\x9c\x9d\xf6\x9e\xe8\x6d\x2b\xc5\x22\x36\x3a\x0d"
|
|
|
|
"\xab\xc5\x21\x97\x9b\x0d\xea\xda\x1d\xbf\x9a\x42\xd5\xc4\x48\x4e"
|
|
|
|
"\x0a\xbc\xd0\x6b\xfa\x53\xdd\xef\x3c\x1b\x20\xee\x3f\xd5\x9d\x7c"
|
|
|
|
"\x25\xe4\x1d\x2b\x66\x9e\x1e\xf1\x6e\x6f\x52\xc3\x16\x4d\xf4\xfb"
|
|
|
|
"\x79\x30\xe9\xe4\xe5\x88\x57\xb6\xac\x7d\x5f\x42\xd6\x9f\x6d\x18"
|
|
|
|
"\x77\x63\xcf\x1d\x55\x03\x40\x04\x87\xf5\x5b\xa5\x7e\x31\xcc\x7a"
|
|
|
|
"\x71\x35\xc8\x86\xef\xb4\x31\x8a\xed\x6a\x1e\x01\x2d\x9e\x68\x32"
|
|
|
|
"\xa9\x07\x60\x0a\x91\x81\x30\xc4\x6d\xc7\x78\xf9\x71\xad\x00\x38"
|
|
|
|
"\x09\x29\x99\xa3\x33\xcb\x8b\x7a\x1a\x1d\xb9\x3d\x71\x40\x00\x3c"
|
|
|
|
"\x2a\x4e\xce\xa9\xf9\x8d\x0a\xcc\x0a\x82\x91\xcd\xce\xc9\x7d\xcf"
|
|
|
|
"\x8e\xc9\xb5\x5a\x7f\x88\xa4\x6b\x4d\xb5\xa8\x51\xf4\x41\x82\xe1"
|
|
|
|
"\xc6\x8a\x00\x7e\x5e\x0d\xd9\x02\x0b\xfd\x64\xb6\x45\x03\x6c\x7a"
|
|
|
|
"\x4e\x67\x7d\x2c\x38\x53\x2a\x3a\x23\xba\x44\x42\xca\xf5\x3e\xa6"
|
|
|
|
"\x3b\xb4\x54\x32\x9b\x76\x24\xc8\x91\x7b\xdd\x64\xb1\xc0\xfd\x4c"
|
|
|
|
"\xb3\x8e\x8c\x33\x4c\x70\x1c\x3a\xcd\xad\x06\x57\xfc\xcf\xec\x71"
|
|
|
|
"\x9b\x1f\x5c\x3e\x4e\x46\x04\x1f\x38\x81\x47\xfb\x4c\xfd\xb4\x77"
|
|
|
|
"\xa5\x24\x71\xf7\xa9\xa9\x69\x10\xb8\x55\x32\x2e\xdb\x63\x40\xd8"
|
|
|
|
"\xa0\x0e\xf0\x92\x35\x05\x11\xe3\x0a\xbe\xc1\xff\xf9\xe3\xa2\x6e"
|
|
|
|
"\x7f\xb2\x9f\x8c\x18\x30\x23\xc3\x58\x7e\x38\xda\x00\x77\xd9\xb4"
|
|
|
|
"\x76\x3e\x4e\x4b\x94\xb2\xbb\xc1\x94\xc6\x65\x1e\x77\xca\xf9\x92"
|
|
|
|
"\xee\xaa\xc0\x23\x2a\x28\x1b\xf6\xb3\xa7\x39\xc1\x22\x61\x16\x82"
|
|
|
|
"\x0a\xe8\xdb\x58\x47\xa6\x7c\xbe\xf9\xc9\x09\x1b\x46\x2d\x53\x8c"
|
|
|
|
"\xd7\x2b\x03\x74\x6a\xe7\x7f\x5e\x62\x29\x2c\x31\x15\x62\xa8\x46"
|
|
|
|
"\x50\x5d\xc8\x2d\xb8\x54\x33\x8a\xe4\x9f\x52\x35\xc9\x5b\x91\x17"
|
|
|
|
"\x8c\xcf\x2d\xd5\xca\xce\xf4\x03\xec\x9d\x18\x10\xc6\x27\x2b\x04"
|
|
|
|
"\x5b\x3b\x71\xf9\xdc\x6b\x80\xd6\x3f\xdd\x4a\x8e\x9a\xdb\x1e\x69"
|
|
|
|
"\x62\xa6\x95\x26\xd4\x31\x61\xc1\xa4\x1d\x57\x0d\x79\x38\xda\xd4"
|
|
|
|
"\xa4\x0e\x32\x9c\xcf\xf4\x6a\xaa\x36\xad\x00\x4c\xf6\x00\xc8\x38"
|
|
|
|
"\x1e\x42\x5a\x31\xd9\x51\xae\x64\xfd\xb2\x3f\xce\xc9\x50\x9d\x43"
|
|
|
|
"\x68\x7f\xeb\x69\xed\xd1\xcc\x5e\x0b\x8c\xc3\xbd\xf6\x4b\x10\xef"
|
|
|
|
"\x86\xb6\x31\x42\xa3\xab\x88\x29\x55\x5b\x2f\x74\x7c\x93\x26\x65"
|
|
|
|
"\xcb\x2c\x0f\x1c\xc0\x1b\xd7\x02\x29\x38\x88\x39\xd2\xaf\x05\xe4"
|
|
|
|
"\x54\x50\x4a\xc7\x8b\x75\x82\x82\x28\x46\xc0\xba\x35\xc3\x5f\x5c"
|
|
|
|
"\x59\x16\x0c\xc0\x46\xfd\x82\x51\x54\x1f\xc6\x8c\x9c\x86\xb0\x22"
|
|
|
|
"\xbb\x70\x99\x87\x6a\x46\x0e\x74\x51\xa8\xa9\x31\x09\x70\x3f\xee"
|
|
|
|
"\x1c\x21\x7e\x6c\x38\x26\xe5\x2c\x51\xaa\x69\x1e\x0e\x42\x3c\xfc"
|
|
|
|
"\x99\xe9\xe3\x16\x50\xc1\x21\x7b\x62\x48\x16\xcd\xad\x9a\x95\xf9"
|
|
|
|
"\xd5\xb8\x01\x94\x88\xd9\xc0\xa0\xa1\xfe\x30\x75\xa5\x77\xe2\x31"
|
|
|
|
"\x83\xf8\x1d\x4a\x3f\x2f\xa4\x57\x1e\xfc\x8c\xe0\xba\x8a\x4f\xe8"
|
|
|
|
"\xb6\x85\x5d\xfe\x72\xb0\xa6\x6e\xde\xd2\xfb\xab\xfb\xe5\x8a\x30"
|
|
|
|
"\xfa\xfa\xbe\x1c\x5d\x71\xa8\x7e\x2f\x74\x1e\xf8\xc1\xfe\x86\xfe"
|
|
|
|
"\xa6\xbb\xfd\xe5\x30\x67\x7f\x0d\x97\xd1\x1d\x49\xf7\xa8\x44\x3d"
|
|
|
|
"\x08\x22\xe5\x06\xa9\xf4\x61\x4e\x01\x1e\x2a\x94\x83\x8f\xf8\x8c"
|
|
|
|
"\xd6\x8c\x8b\xb7\xc5\xc6\x42\x4c\xff\xff\xff\xff\xff\xff\xff\xff",
|
|
|
|
};
|
|
|
|
|
|
|
|
static int dh_ffdhe2048_create(struct crypto_template *tmpl,
|
|
|
|
struct rtattr **tb)
|
|
|
|
{
|
|
|
|
return __dh_safe_prime_create(tmpl, tb, &ffdhe2048_prime);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dh_ffdhe3072_create(struct crypto_template *tmpl,
|
|
|
|
struct rtattr **tb)
|
|
|
|
{
|
|
|
|
return __dh_safe_prime_create(tmpl, tb, &ffdhe3072_prime);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dh_ffdhe4096_create(struct crypto_template *tmpl,
|
|
|
|
struct rtattr **tb)
|
|
|
|
{
|
|
|
|
return __dh_safe_prime_create(tmpl, tb, &ffdhe4096_prime);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dh_ffdhe6144_create(struct crypto_template *tmpl,
|
|
|
|
struct rtattr **tb)
|
|
|
|
{
|
|
|
|
return __dh_safe_prime_create(tmpl, tb, &ffdhe6144_prime);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dh_ffdhe8192_create(struct crypto_template *tmpl,
|
|
|
|
struct rtattr **tb)
|
|
|
|
{
|
|
|
|
return __dh_safe_prime_create(tmpl, tb, &ffdhe8192_prime);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct crypto_template crypto_ffdhe_templates[] = {
|
|
|
|
{
|
|
|
|
.name = "ffdhe2048",
|
|
|
|
.create = dh_ffdhe2048_create,
|
|
|
|
.module = THIS_MODULE,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "ffdhe3072",
|
|
|
|
.create = dh_ffdhe3072_create,
|
|
|
|
.module = THIS_MODULE,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "ffdhe4096",
|
|
|
|
.create = dh_ffdhe4096_create,
|
|
|
|
.module = THIS_MODULE,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "ffdhe6144",
|
|
|
|
.create = dh_ffdhe6144_create,
|
|
|
|
.module = THIS_MODULE,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = "ffdhe8192",
|
|
|
|
.create = dh_ffdhe8192_create,
|
|
|
|
.module = THIS_MODULE,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
#else /* ! CONFIG_CRYPTO_DH_RFC7919_GROUPS */
|
|
|
|
|
|
|
|
static struct crypto_template crypto_ffdhe_templates[] = {};
|
|
|
|
|
|
|
|
#endif /* CONFIG_CRYPTO_DH_RFC7919_GROUPS */
|
|
|
|
|
|
|
|
|
2022-09-15 03:36:15 +00:00
|
|
|
static int __init dh_init(void)
|
2016-06-22 16:49:14 +00:00
|
|
|
{
|
crypto: dh - implement ffdheXYZ(dh) templates
Current work on NVME in-band authentication support ([1]) needs to invoke
DH with the FFDHE safe-prime group parameters specified in RFC 7919.
Introduce a new CRYPTO_DH_RFC7919_GROUPS Kconfig option. If enabled, make
dh_generic register a couple of ffdheXYZ(dh) templates, one for each group:
ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and
ffdhe8192(dh). Their respective ->set_secret() expects a (serialized)
struct dh, just like the underlying "dh" implementation does, but with the
P and G values unset so that the safe-prime constants for the given group
can be filled in by the wrapping template.
Internally, a struct dh_safe_prime instance is being defined for each of
the ffdheXYZ(dh) templates as appropriate. In order to prepare for future
key generation, fill in the maximum security strength values as specified
by SP800-56Arev3 on the go, even though they're not needed at this point
yet.
Implement the respective ffdheXYZ(dh) crypto_template's ->create() by
simply forwarding any calls to the __dh_safe_prime_create() helper
introduced with the previous commit, passing the associated dh_safe_prime
in addition to the received ->create() arguments.
[1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de
Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 12:10:53 +00:00
|
|
|
int err;
|
|
|
|
|
|
|
|
err = crypto_register_kpp(&dh);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
err = crypto_register_templates(crypto_ffdhe_templates,
|
|
|
|
ARRAY_SIZE(crypto_ffdhe_templates));
|
|
|
|
if (err) {
|
|
|
|
crypto_unregister_kpp(&dh);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2016-06-22 16:49:14 +00:00
|
|
|
}
|
|
|
|
|
2022-09-15 03:36:15 +00:00
|
|
|
static void __exit dh_exit(void)
|
2016-06-22 16:49:14 +00:00
|
|
|
{
|
crypto: dh - implement ffdheXYZ(dh) templates
Current work on NVME in-band authentication support ([1]) needs to invoke
DH with the FFDHE safe-prime group parameters specified in RFC 7919.
Introduce a new CRYPTO_DH_RFC7919_GROUPS Kconfig option. If enabled, make
dh_generic register a couple of ffdheXYZ(dh) templates, one for each group:
ffdhe2048(dh), ffdhe3072(dh), ffdhe4096(dh), ffdhe6144(dh) and
ffdhe8192(dh). Their respective ->set_secret() expects a (serialized)
struct dh, just like the underlying "dh" implementation does, but with the
P and G values unset so that the safe-prime constants for the given group
can be filled in by the wrapping template.
Internally, a struct dh_safe_prime instance is being defined for each of
the ffdheXYZ(dh) templates as appropriate. In order to prepare for future
key generation, fill in the maximum security strength values as specified
by SP800-56Arev3 on the go, even though they're not needed at this point
yet.
Implement the respective ffdheXYZ(dh) crypto_template's ->create() by
simply forwarding any calls to the __dh_safe_prime_create() helper
introduced with the previous commit, passing the associated dh_safe_prime
in addition to the received ->create() arguments.
[1] https://lore.kernel.org/r/20211202152358.60116-1-hare@suse.de
Signed-off-by: Nicolai Stange <nstange@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-02-21 12:10:53 +00:00
|
|
|
crypto_unregister_templates(crypto_ffdhe_templates,
|
|
|
|
ARRAY_SIZE(crypto_ffdhe_templates));
|
2016-06-22 16:49:14 +00:00
|
|
|
crypto_unregister_kpp(&dh);
|
|
|
|
}
|
|
|
|
|
2019-04-12 04:57:42 +00:00
|
|
|
subsys_initcall(dh_init);
|
2016-06-22 16:49:14 +00:00
|
|
|
module_exit(dh_exit);
|
|
|
|
MODULE_ALIAS_CRYPTO("dh");
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
MODULE_DESCRIPTION("DH generic algorithm");
|