1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Diffie-Hellman Key Agreement Method [RFC2631] 3 * 4 * Copyright (c) 2016, Intel Corporation 5 * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com> 6 */ 7 8 #include <linux/module.h> 9 #include <crypto/internal/kpp.h> 10 #include <crypto/kpp.h> 11 #include <crypto/dh.h> 12 #include <linux/mpi.h> 13 14 struct dh_ctx { 15 MPI p; /* Value is guaranteed to be set. */ 16 MPI q; /* Value is optional. */ 17 MPI g; /* Value is guaranteed to be set. */ 18 MPI xa; /* Value is guaranteed to be set. */ 19 }; 20 21 static void dh_clear_ctx(struct dh_ctx *ctx) 22 { 23 mpi_free(ctx->p); 24 mpi_free(ctx->q); 25 mpi_free(ctx->g); 26 mpi_free(ctx->xa); 27 memset(ctx, 0, sizeof(*ctx)); 28 } 29 30 /* 31 * If base is g we compute the public key 32 * ya = g^xa mod p; [RFC2631 sec 2.1.1] 33 * else if base if the counterpart public key we compute the shared secret 34 * ZZ = yb^xa mod p; [RFC2631 sec 2.1.1] 35 */ 36 static int _compute_val(const struct dh_ctx *ctx, MPI base, MPI val) 37 { 38 /* val = base^xa mod p */ 39 return mpi_powm(val, base, ctx->xa, ctx->p); 40 } 41 42 static inline struct dh_ctx *dh_get_ctx(struct crypto_kpp *tfm) 43 { 44 return kpp_tfm_ctx(tfm); 45 } 46 47 static int dh_check_params_length(unsigned int p_len) 48 { 49 return (p_len < 1536) ? -EINVAL : 0; 50 } 51 52 static int dh_set_params(struct dh_ctx *ctx, struct dh *params) 53 { 54 if (dh_check_params_length(params->p_size << 3)) 55 return -EINVAL; 56 57 ctx->p = mpi_read_raw_data(params->p, params->p_size); 58 if (!ctx->p) 59 return -EINVAL; 60 61 if (params->q && params->q_size) { 62 ctx->q = mpi_read_raw_data(params->q, params->q_size); 63 if (!ctx->q) 64 return -EINVAL; 65 } 66 67 ctx->g = mpi_read_raw_data(params->g, params->g_size); 68 if (!ctx->g) 69 return -EINVAL; 70 71 return 0; 72 } 73 74 static int dh_set_secret(struct crypto_kpp *tfm, const void *buf, 75 unsigned int len) 76 { 77 struct dh_ctx *ctx = dh_get_ctx(tfm); 78 struct dh params; 79 80 /* Free the old MPI key if any */ 81 dh_clear_ctx(ctx); 82 83 if (crypto_dh_decode_key(buf, len, ¶ms) < 0) 84 goto err_clear_ctx; 85 86 if (dh_set_params(ctx, ¶ms) < 0) 87 goto err_clear_ctx; 88 89 ctx->xa = mpi_read_raw_data(params.key, params.key_size); 90 if (!ctx->xa) 91 goto err_clear_ctx; 92 93 return 0; 94 95 err_clear_ctx: 96 dh_clear_ctx(ctx); 97 return -EINVAL; 98 } 99 100 /* 101 * SP800-56A public key verification: 102 * 103 * * If Q is provided as part of the domain paramenters, a full validation 104 * according to SP800-56A section 5.6.2.3.1 is performed. 105 * 106 * * If Q is not provided, a partial validation according to SP800-56A section 107 * 5.6.2.3.2 is performed. 108 */ 109 static int dh_is_pubkey_valid(struct dh_ctx *ctx, MPI y) 110 { 111 if (unlikely(!ctx->p)) 112 return -EINVAL; 113 114 /* 115 * Step 1: Verify that 2 <= y <= p - 2. 116 * 117 * The upper limit check is actually y < p instead of y < p - 1 118 * as the mpi_sub_ui function is yet missing. 119 */ 120 if (mpi_cmp_ui(y, 1) < 1 || mpi_cmp(y, ctx->p) >= 0) 121 return -EINVAL; 122 123 /* Step 2: Verify that 1 = y^q mod p */ 124 if (ctx->q) { 125 MPI val = mpi_alloc(0); 126 int ret; 127 128 if (!val) 129 return -ENOMEM; 130 131 ret = mpi_powm(val, y, ctx->q, ctx->p); 132 133 if (ret) { 134 mpi_free(val); 135 return ret; 136 } 137 138 ret = mpi_cmp_ui(val, 1); 139 140 mpi_free(val); 141 142 if (ret != 0) 143 return -EINVAL; 144 } 145 146 return 0; 147 } 148 149 static int dh_compute_value(struct kpp_request *req) 150 { 151 struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 152 struct dh_ctx *ctx = dh_get_ctx(tfm); 153 MPI base, val = mpi_alloc(0); 154 int ret = 0; 155 int sign; 156 157 if (!val) 158 return -ENOMEM; 159 160 if (unlikely(!ctx->xa)) { 161 ret = -EINVAL; 162 goto err_free_val; 163 } 164 165 if (req->src) { 166 base = mpi_read_raw_from_sgl(req->src, req->src_len); 167 if (!base) { 168 ret = -EINVAL; 169 goto err_free_val; 170 } 171 ret = dh_is_pubkey_valid(ctx, base); 172 if (ret) 173 goto err_free_base; 174 } else { 175 base = ctx->g; 176 } 177 178 ret = _compute_val(ctx, base, val); 179 if (ret) 180 goto err_free_base; 181 182 ret = mpi_write_to_sgl(val, req->dst, req->dst_len, &sign); 183 if (ret) 184 goto err_free_base; 185 186 if (sign < 0) 187 ret = -EBADMSG; 188 err_free_base: 189 if (req->src) 190 mpi_free(base); 191 err_free_val: 192 mpi_free(val); 193 return ret; 194 } 195 196 static unsigned int dh_max_size(struct crypto_kpp *tfm) 197 { 198 struct dh_ctx *ctx = dh_get_ctx(tfm); 199 200 return mpi_get_size(ctx->p); 201 } 202 203 static void dh_exit_tfm(struct crypto_kpp *tfm) 204 { 205 struct dh_ctx *ctx = dh_get_ctx(tfm); 206 207 dh_clear_ctx(ctx); 208 } 209 210 static struct kpp_alg dh = { 211 .set_secret = dh_set_secret, 212 .generate_public_key = dh_compute_value, 213 .compute_shared_secret = dh_compute_value, 214 .max_size = dh_max_size, 215 .exit = dh_exit_tfm, 216 .base = { 217 .cra_name = "dh", 218 .cra_driver_name = "dh-generic", 219 .cra_priority = 100, 220 .cra_module = THIS_MODULE, 221 .cra_ctxsize = sizeof(struct dh_ctx), 222 }, 223 }; 224 225 static int dh_init(void) 226 { 227 return crypto_register_kpp(&dh); 228 } 229 230 static void dh_exit(void) 231 { 232 crypto_unregister_kpp(&dh); 233 } 234 235 subsys_initcall(dh_init); 236 module_exit(dh_exit); 237 MODULE_ALIAS_CRYPTO("dh"); 238 MODULE_LICENSE("GPL"); 239 MODULE_DESCRIPTION("DH generic algorithm"); 240