diff options
author | Salvatore Benedetto <salvatore.benedetto@intel.com> | 2016-06-22 12:49:14 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2016-06-23 06:29:56 -0400 |
commit | 802c7f1c84e4b5a6ac78635878041023fc5831b1 (patch) | |
tree | 2dee2afffbbbb2761fd15fe94af28b93974ff0cf /crypto/dh.c | |
parent | 4e5f2c400765e3a3ce512dc1ae890bac53401798 (diff) |
crypto: dh - Add DH software implementation
* Implement MPI based Diffie-Hellman under kpp API
* Test provided uses data generad by OpenSSL
Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/dh.c')
-rw-r--r-- | crypto/dh.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/crypto/dh.c b/crypto/dh.c new file mode 100644 index 000000000000..5e960fe28681 --- /dev/null +++ b/crypto/dh.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* Diffie-Hellman Key Agreement Method [RFC2631] | ||
2 | * | ||
3 | * Copyright (c) 2016, Intel Corporation | ||
4 | * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <crypto/internal/kpp.h> | ||
14 | #include <crypto/kpp.h> | ||
15 | #include <crypto/dh.h> | ||
16 | #include <linux/mpi.h> | ||
17 | |||
18 | struct dh_ctx { | ||
19 | MPI p; | ||
20 | MPI g; | ||
21 | MPI xa; | ||
22 | }; | ||
23 | |||
24 | static inline void dh_clear_params(struct dh_ctx *ctx) | ||
25 | { | ||
26 | mpi_free(ctx->p); | ||
27 | mpi_free(ctx->g); | ||
28 | ctx->p = NULL; | ||
29 | ctx->g = NULL; | ||
30 | } | ||
31 | |||
32 | static void dh_free_ctx(struct dh_ctx *ctx) | ||
33 | { | ||
34 | dh_clear_params(ctx); | ||
35 | mpi_free(ctx->xa); | ||
36 | ctx->xa = NULL; | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * If base is g we compute the public key | ||
41 | * ya = g^xa mod p; [RFC2631 sec 2.1.1] | ||
42 | * else if base if the counterpart public key we compute the shared secret | ||
43 | * ZZ = yb^xa mod p; [RFC2631 sec 2.1.1] | ||
44 | */ | ||
45 | static int _compute_val(const struct dh_ctx *ctx, MPI base, MPI val) | ||
46 | { | ||
47 | /* val = base^xa mod p */ | ||
48 | return mpi_powm(val, base, ctx->xa, ctx->p); | ||
49 | } | ||
50 | |||
51 | static inline struct dh_ctx *dh_get_ctx(struct crypto_kpp *tfm) | ||
52 | { | ||
53 | return kpp_tfm_ctx(tfm); | ||
54 | } | ||
55 | |||
56 | static int dh_check_params_length(unsigned int p_len) | ||
57 | { | ||
58 | return (p_len < 1536) ? -EINVAL : 0; | ||
59 | } | ||
60 | |||
61 | static int dh_set_params(struct dh_ctx *ctx, struct dh *params) | ||
62 | { | ||
63 | if (unlikely(!params->p || !params->g)) | ||
64 | return -EINVAL; | ||
65 | |||
66 | if (dh_check_params_length(params->p_size << 3)) | ||
67 | return -EINVAL; | ||
68 | |||
69 | ctx->p = mpi_read_raw_data(params->p, params->p_size); | ||
70 | if (!ctx->p) | ||
71 | return -EINVAL; | ||
72 | |||
73 | ctx->g = mpi_read_raw_data(params->g, params->g_size); | ||
74 | if (!ctx->g) { | ||
75 | mpi_free(ctx->p); | ||
76 | return -EINVAL; | ||
77 | } | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int dh_set_secret(struct crypto_kpp *tfm, void *buf, unsigned int len) | ||
83 | { | ||
84 | struct dh_ctx *ctx = dh_get_ctx(tfm); | ||
85 | struct dh params; | ||
86 | |||
87 | if (crypto_dh_decode_key(buf, len, ¶ms) < 0) | ||
88 | return -EINVAL; | ||
89 | |||
90 | if (dh_set_params(ctx, ¶ms) < 0) | ||
91 | return -EINVAL; | ||
92 | |||
93 | ctx->xa = mpi_read_raw_data(params.key, params.key_size); | ||
94 | if (!ctx->xa) { | ||
95 | dh_clear_params(ctx); | ||
96 | return -EINVAL; | ||
97 | } | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | static int dh_compute_value(struct kpp_request *req) | ||
103 | { | ||
104 | struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); | ||
105 | struct dh_ctx *ctx = dh_get_ctx(tfm); | ||
106 | MPI base, val = mpi_alloc(0); | ||
107 | int ret = 0; | ||
108 | int sign; | ||
109 | |||
110 | if (!val) | ||
111 | return -ENOMEM; | ||
112 | |||
113 | if (unlikely(!ctx->xa)) { | ||
114 | ret = -EINVAL; | ||
115 | goto err_free_val; | ||
116 | } | ||
117 | |||
118 | if (req->src) { | ||
119 | base = mpi_read_raw_from_sgl(req->src, req->src_len); | ||
120 | if (!base) { | ||
121 | ret = EINVAL; | ||
122 | goto err_free_val; | ||
123 | } | ||
124 | } else { | ||
125 | base = ctx->g; | ||
126 | } | ||
127 | |||
128 | ret = _compute_val(ctx, base, val); | ||
129 | if (ret) | ||
130 | goto err_free_base; | ||
131 | |||
132 | ret = mpi_write_to_sgl(val, req->dst, &req->dst_len, &sign); | ||
133 | if (ret) | ||
134 | goto err_free_base; | ||
135 | |||
136 | if (sign < 0) | ||
137 | ret = -EBADMSG; | ||
138 | err_free_base: | ||
139 | if (req->src) | ||
140 | mpi_free(base); | ||
141 | err_free_val: | ||
142 | mpi_free(val); | ||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | static int dh_max_size(struct crypto_kpp *tfm) | ||
147 | { | ||
148 | struct dh_ctx *ctx = dh_get_ctx(tfm); | ||
149 | |||
150 | return mpi_get_size(ctx->p); | ||
151 | } | ||
152 | |||
153 | static void dh_exit_tfm(struct crypto_kpp *tfm) | ||
154 | { | ||
155 | struct dh_ctx *ctx = dh_get_ctx(tfm); | ||
156 | |||
157 | dh_free_ctx(ctx); | ||
158 | } | ||
159 | |||
160 | static struct kpp_alg dh = { | ||
161 | .set_secret = dh_set_secret, | ||
162 | .generate_public_key = dh_compute_value, | ||
163 | .compute_shared_secret = dh_compute_value, | ||
164 | .max_size = dh_max_size, | ||
165 | .exit = dh_exit_tfm, | ||
166 | .base = { | ||
167 | .cra_name = "dh", | ||
168 | .cra_driver_name = "dh-generic", | ||
169 | .cra_priority = 100, | ||
170 | .cra_module = THIS_MODULE, | ||
171 | .cra_ctxsize = sizeof(struct dh_ctx), | ||
172 | }, | ||
173 | }; | ||
174 | |||
175 | static int dh_init(void) | ||
176 | { | ||
177 | return crypto_register_kpp(&dh); | ||
178 | } | ||
179 | |||
180 | static void dh_exit(void) | ||
181 | { | ||
182 | crypto_unregister_kpp(&dh); | ||
183 | } | ||
184 | |||
185 | module_init(dh_init); | ||
186 | module_exit(dh_exit); | ||
187 | MODULE_ALIAS_CRYPTO("dh"); | ||
188 | MODULE_LICENSE("GPL"); | ||
189 | MODULE_DESCRIPTION("DH generic algorithm"); | ||