Blame view
crypto/ecdh.c
4.11 KB
3c4b23901 crypto: ecdh - Ad... |
1 2 3 4 5 6 |
/* ECDH key-agreement protocol * * Copyright (c) 2016, Intel Corporation * Authors: Salvator Benedetto <salvatore.benedetto@intel.com> * * This program is free software; you can redistribute it and/or |
c0ca1215d crypto: kpp, (ec)... |
7 |
* modify it under the terms of the GNU General Public License |
3c4b23901 crypto: ecdh - Ad... |
8 |
* as published by the Free Software Foundation; either version |
c0ca1215d crypto: kpp, (ec)... |
9 |
* 2 of the License, or (at your option) any later version. |
3c4b23901 crypto: ecdh - Ad... |
10 11 12 13 14 15 16 17 18 19 20 21 22 |
*/ #include <linux/module.h> #include <crypto/internal/kpp.h> #include <crypto/kpp.h> #include <crypto/ecdh.h> #include <linux/scatterlist.h> #include "ecc.h" struct ecdh_ctx { unsigned int curve_id; unsigned int ndigits; u64 private_key[ECC_MAX_DIGITS]; |
3c4b23901 crypto: ecdh - Ad... |
23 24 25 26 27 28 29 30 31 32 |
}; static inline struct ecdh_ctx *ecdh_get_ctx(struct crypto_kpp *tfm) { return kpp_tfm_ctx(tfm); } static unsigned int ecdh_supported_curve(unsigned int curve_id) { switch (curve_id) { |
d5c3b1789 crypto: ecc - Act... |
33 34 |
case ECC_CURVE_NIST_P192: return ECC_CURVE_NIST_P192_DIGITS; case ECC_CURVE_NIST_P256: return ECC_CURVE_NIST_P256_DIGITS; |
3c4b23901 crypto: ecdh - Ad... |
35 36 37 |
default: return 0; } } |
5527dfb6d crypto: kpp - con... |
38 39 |
static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, unsigned int len) |
3c4b23901 crypto: ecdh - Ad... |
40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
{ struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); struct ecdh params; unsigned int ndigits; if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0) return -EINVAL; ndigits = ecdh_supported_curve(params.curve_id); if (!ndigits) return -EINVAL; ctx->curve_id = params.curve_id; ctx->ndigits = ndigits; |
6755fd269 crypto: ecdh - ad... |
54 55 56 |
if (!params.key || !params.key_size) return ecc_gen_privkey(ctx->curve_id, ctx->ndigits, ctx->private_key); |
3c4b23901 crypto: ecdh - Ad... |
57 |
if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits, |
ad2695971 crypto: ecc - rem... |
58 |
(const u64 *)params.key, params.key_size) < 0) |
3c4b23901 crypto: ecdh - Ad... |
59 60 61 62 63 64 65 66 67 |
return -EINVAL; memcpy(ctx->private_key, params.key, params.key_size); return 0; } static int ecdh_compute_value(struct kpp_request *req) { |
3c4b23901 crypto: ecdh - Ad... |
68 69 |
struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); |
952035bae crypto: ecdh - fi... |
70 71 |
u64 *public_key; u64 *shared_secret = NULL; |
3c4b23901 crypto: ecdh - Ad... |
72 |
void *buf; |
952035bae crypto: ecdh - fi... |
73 74 |
size_t copied, nbytes, public_key_sz; int ret = -ENOMEM; |
3c4b23901 crypto: ecdh - Ad... |
75 76 |
nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT; |
952035bae crypto: ecdh - fi... |
77 78 79 80 81 82 |
/* Public part is a point thus it has both coordinates */ public_key_sz = 2 * nbytes; public_key = kmalloc(public_key_sz, GFP_KERNEL); if (!public_key) return -ENOMEM; |
3c4b23901 crypto: ecdh - Ad... |
83 84 |
if (req->src) { |
952035bae crypto: ecdh - fi... |
85 86 87 |
shared_secret = kmalloc(nbytes, GFP_KERNEL); if (!shared_secret) goto free_pubkey; |
95ec01ba1 crypto: ecdh - fi... |
88 89 90 91 92 93 94 95 96 97 98 99 |
/* from here on it's invalid parameters */ ret = -EINVAL; /* must have exactly two points to be on the curve */ if (public_key_sz != req->src_len) goto free_all; copied = sg_copy_to_buffer(req->src, sg_nents_for_len(req->src, public_key_sz), public_key, public_key_sz); if (copied != public_key_sz) |
952035bae crypto: ecdh - fi... |
100 |
goto free_all; |
3c4b23901 crypto: ecdh - Ad... |
101 |
|
8f44df154 crypto: ecdh - ma... |
102 |
ret = crypto_ecdh_shared_secret(ctx->curve_id, ctx->ndigits, |
952035bae crypto: ecdh - fi... |
103 104 |
ctx->private_key, public_key, shared_secret); |
3c4b23901 crypto: ecdh - Ad... |
105 |
|
952035bae crypto: ecdh - fi... |
106 |
buf = shared_secret; |
3c4b23901 crypto: ecdh - Ad... |
107 |
} else { |
7380c56d2 crypto: ecc - ren... |
108 |
ret = ecc_make_pub_key(ctx->curve_id, ctx->ndigits, |
952035bae crypto: ecdh - fi... |
109 110 111 |
ctx->private_key, public_key); buf = public_key; nbytes = public_key_sz; |
3c4b23901 crypto: ecdh - Ad... |
112 113 114 |
} if (ret < 0) |
952035bae crypto: ecdh - fi... |
115 |
goto free_all; |
3c4b23901 crypto: ecdh - Ad... |
116 |
|
95ec01ba1 crypto: ecdh - fi... |
117 118 119 120 121 |
/* might want less than we've got */ nbytes = min_t(size_t, nbytes, req->dst_len); copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, nbytes), buf, nbytes); |
3c4b23901 crypto: ecdh - Ad... |
122 |
if (copied != nbytes) |
952035bae crypto: ecdh - fi... |
123 |
ret = -EINVAL; |
3c4b23901 crypto: ecdh - Ad... |
124 |
|
952035bae crypto: ecdh - fi... |
125 126 127 128 129 |
/* fall through */ free_all: kzfree(shared_secret); free_pubkey: kfree(public_key); |
3c4b23901 crypto: ecdh - Ad... |
130 131 |
return ret; } |
d0efb48b8 crypto: ecdh - co... |
132 |
static unsigned int ecdh_max_size(struct crypto_kpp *tfm) |
3c4b23901 crypto: ecdh - Ad... |
133 134 |
{ struct ecdh_ctx *ctx = ecdh_get_ctx(tfm); |
3c4b23901 crypto: ecdh - Ad... |
135 |
|
d0efb48b8 crypto: ecdh - co... |
136 137 |
/* Public key is made of two coordinates, add one to the left shift */ return ctx->ndigits << (ECC_DIGITS_TO_BYTES_SHIFT + 1); |
3c4b23901 crypto: ecdh - Ad... |
138 |
} |
3c4b23901 crypto: ecdh - Ad... |
139 140 141 142 143 |
static struct kpp_alg ecdh = { .set_secret = ecdh_set_secret, .generate_public_key = ecdh_compute_value, .compute_shared_secret = ecdh_compute_value, .max_size = ecdh_max_size, |
3c4b23901 crypto: ecdh - Ad... |
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
.base = { .cra_name = "ecdh", .cra_driver_name = "ecdh-generic", .cra_priority = 100, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct ecdh_ctx), }, }; static int ecdh_init(void) { return crypto_register_kpp(&ecdh); } static void ecdh_exit(void) { crypto_unregister_kpp(&ecdh); } module_init(ecdh_init); module_exit(ecdh_exit); MODULE_ALIAS_CRYPTO("ecdh"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("ECDH generic algorithm"); |