/src/boringssl/crypto/evp/p_ec.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
2 | | * project 2006. |
3 | | */ |
4 | | /* ==================================================================== |
5 | | * Copyright (c) 2006 The OpenSSL Project. All rights reserved. |
6 | | * |
7 | | * Redistribution and use in source and binary forms, with or without |
8 | | * modification, are permitted provided that the following conditions |
9 | | * are met: |
10 | | * |
11 | | * 1. Redistributions of source code must retain the above copyright |
12 | | * notice, this list of conditions and the following disclaimer. |
13 | | * |
14 | | * 2. Redistributions in binary form must reproduce the above copyright |
15 | | * notice, this list of conditions and the following disclaimer in |
16 | | * the documentation and/or other materials provided with the |
17 | | * distribution. |
18 | | * |
19 | | * 3. All advertising materials mentioning features or use of this |
20 | | * software must display the following acknowledgment: |
21 | | * "This product includes software developed by the OpenSSL Project |
22 | | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" |
23 | | * |
24 | | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
25 | | * endorse or promote products derived from this software without |
26 | | * prior written permission. For written permission, please contact |
27 | | * licensing@OpenSSL.org. |
28 | | * |
29 | | * 5. Products derived from this software may not be called "OpenSSL" |
30 | | * nor may "OpenSSL" appear in their names without prior written |
31 | | * permission of the OpenSSL Project. |
32 | | * |
33 | | * 6. Redistributions of any form whatsoever must retain the following |
34 | | * acknowledgment: |
35 | | * "This product includes software developed by the OpenSSL Project |
36 | | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" |
37 | | * |
38 | | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
39 | | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
40 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
41 | | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
42 | | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
43 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
44 | | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
45 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
46 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
47 | | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
48 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
49 | | * OF THE POSSIBILITY OF SUCH DAMAGE. |
50 | | * ==================================================================== |
51 | | * |
52 | | * This product includes cryptographic software written by Eric Young |
53 | | * (eay@cryptsoft.com). This product includes software written by Tim |
54 | | * Hudson (tjh@cryptsoft.com). */ |
55 | | |
56 | | #include <openssl/evp.h> |
57 | | |
58 | | #include <string.h> |
59 | | |
60 | | #include <openssl/bn.h> |
61 | | #include <openssl/digest.h> |
62 | | #include <openssl/ec.h> |
63 | | #include <openssl/ec_key.h> |
64 | | #include <openssl/ecdh.h> |
65 | | #include <openssl/ecdsa.h> |
66 | | #include <openssl/err.h> |
67 | | #include <openssl/mem.h> |
68 | | #include <openssl/nid.h> |
69 | | |
70 | | #include "internal.h" |
71 | | #include "../fipsmodule/ec/internal.h" |
72 | | #include "../internal.h" |
73 | | |
74 | | |
75 | | typedef struct { |
76 | | // message digest |
77 | | const EVP_MD *md; |
78 | | const EC_GROUP *gen_group; |
79 | | } EC_PKEY_CTX; |
80 | | |
81 | | |
82 | 0 | static int pkey_ec_init(EVP_PKEY_CTX *ctx) { |
83 | 0 | EC_PKEY_CTX *dctx = OPENSSL_zalloc(sizeof(EC_PKEY_CTX)); |
84 | 0 | if (!dctx) { |
85 | 0 | return 0; |
86 | 0 | } |
87 | | |
88 | 0 | ctx->data = dctx; |
89 | 0 | return 1; |
90 | 0 | } |
91 | | |
92 | 0 | static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { |
93 | 0 | if (!pkey_ec_init(dst)) { |
94 | 0 | return 0; |
95 | 0 | } |
96 | | |
97 | 0 | const EC_PKEY_CTX *sctx = src->data; |
98 | 0 | EC_PKEY_CTX *dctx = dst->data; |
99 | 0 | dctx->md = sctx->md; |
100 | 0 | dctx->gen_group = sctx->gen_group; |
101 | 0 | return 1; |
102 | 0 | } |
103 | | |
104 | 0 | static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) { |
105 | 0 | EC_PKEY_CTX *dctx = ctx->data; |
106 | 0 | if (!dctx) { |
107 | 0 | return; |
108 | 0 | } |
109 | | |
110 | 0 | OPENSSL_free(dctx); |
111 | 0 | } |
112 | | |
113 | | static int pkey_ec_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen, |
114 | 0 | const uint8_t *tbs, size_t tbslen) { |
115 | 0 | const EC_KEY *ec = ctx->pkey->pkey; |
116 | 0 | if (!sig) { |
117 | 0 | *siglen = ECDSA_size(ec); |
118 | 0 | return 1; |
119 | 0 | } else if (*siglen < (size_t)ECDSA_size(ec)) { |
120 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); |
121 | 0 | return 0; |
122 | 0 | } |
123 | | |
124 | 0 | unsigned int sltmp; |
125 | 0 | if (!ECDSA_sign(0, tbs, tbslen, sig, &sltmp, ec)) { |
126 | 0 | return 0; |
127 | 0 | } |
128 | 0 | *siglen = (size_t)sltmp; |
129 | 0 | return 1; |
130 | 0 | } |
131 | | |
132 | | static int pkey_ec_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen, |
133 | 0 | const uint8_t *tbs, size_t tbslen) { |
134 | 0 | const EC_KEY *ec_key = ctx->pkey->pkey; |
135 | 0 | return ECDSA_verify(0, tbs, tbslen, sig, siglen, ec_key); |
136 | 0 | } |
137 | | |
138 | | static int pkey_ec_derive(EVP_PKEY_CTX *ctx, uint8_t *key, |
139 | 0 | size_t *keylen) { |
140 | 0 | if (!ctx->pkey || !ctx->peerkey) { |
141 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_KEYS_NOT_SET); |
142 | 0 | return 0; |
143 | 0 | } |
144 | | |
145 | 0 | const EC_KEY *eckey = ctx->pkey->pkey; |
146 | 0 | if (!key) { |
147 | 0 | const EC_GROUP *group; |
148 | 0 | group = EC_KEY_get0_group(eckey); |
149 | 0 | *keylen = (EC_GROUP_get_degree(group) + 7) / 8; |
150 | 0 | return 1; |
151 | 0 | } |
152 | | |
153 | 0 | const EC_KEY *eckey_peer = ctx->peerkey->pkey; |
154 | 0 | const EC_POINT *pubkey = EC_KEY_get0_public_key(eckey_peer); |
155 | | |
156 | | // NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is |
157 | | // not an error, the result is truncated. |
158 | 0 | size_t outlen = *keylen; |
159 | 0 | int ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0); |
160 | 0 | if (ret < 0) { |
161 | 0 | return 0; |
162 | 0 | } |
163 | 0 | *keylen = ret; |
164 | 0 | return 1; |
165 | 0 | } |
166 | | |
167 | 0 | static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { |
168 | 0 | EC_PKEY_CTX *dctx = ctx->data; |
169 | |
|
170 | 0 | switch (type) { |
171 | 0 | case EVP_PKEY_CTRL_MD: { |
172 | 0 | const EVP_MD *md = p2; |
173 | 0 | int md_type = EVP_MD_type(md); |
174 | 0 | if (md_type != NID_sha1 && md_type != NID_sha224 && |
175 | 0 | md_type != NID_sha256 && md_type != NID_sha384 && |
176 | 0 | md_type != NID_sha512) { |
177 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_DIGEST_TYPE); |
178 | 0 | return 0; |
179 | 0 | } |
180 | 0 | dctx->md = md; |
181 | 0 | return 1; |
182 | 0 | } |
183 | | |
184 | 0 | case EVP_PKEY_CTRL_GET_MD: |
185 | 0 | *(const EVP_MD **)p2 = dctx->md; |
186 | 0 | return 1; |
187 | | |
188 | 0 | case EVP_PKEY_CTRL_PEER_KEY: |
189 | | // Default behaviour is OK |
190 | 0 | return 1; |
191 | | |
192 | 0 | case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: { |
193 | 0 | const EC_GROUP *group = EC_GROUP_new_by_curve_name(p1); |
194 | 0 | if (group == NULL) { |
195 | 0 | return 0; |
196 | 0 | } |
197 | 0 | dctx->gen_group = group; |
198 | 0 | return 1; |
199 | 0 | } |
200 | | |
201 | 0 | default: |
202 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED); |
203 | 0 | return 0; |
204 | 0 | } |
205 | 0 | } |
206 | | |
207 | 0 | static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { |
208 | 0 | EC_PKEY_CTX *dctx = ctx->data; |
209 | 0 | const EC_GROUP *group = dctx->gen_group; |
210 | 0 | if (group == NULL) { |
211 | 0 | if (ctx->pkey == NULL) { |
212 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET); |
213 | 0 | return 0; |
214 | 0 | } |
215 | 0 | group = EC_KEY_get0_group(ctx->pkey->pkey); |
216 | 0 | } |
217 | 0 | EC_KEY *ec = EC_KEY_new(); |
218 | 0 | if (ec == NULL || |
219 | 0 | !EC_KEY_set_group(ec, group) || |
220 | 0 | !EC_KEY_generate_key(ec)) { |
221 | 0 | EC_KEY_free(ec); |
222 | 0 | return 0; |
223 | 0 | } |
224 | 0 | EVP_PKEY_assign_EC_KEY(pkey, ec); |
225 | 0 | return 1; |
226 | 0 | } |
227 | | |
228 | 0 | static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { |
229 | 0 | EC_PKEY_CTX *dctx = ctx->data; |
230 | 0 | if (dctx->gen_group == NULL) { |
231 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET); |
232 | 0 | return 0; |
233 | 0 | } |
234 | 0 | EC_KEY *ec = EC_KEY_new(); |
235 | 0 | if (ec == NULL || |
236 | 0 | !EC_KEY_set_group(ec, dctx->gen_group)) { |
237 | 0 | EC_KEY_free(ec); |
238 | 0 | return 0; |
239 | 0 | } |
240 | 0 | EVP_PKEY_assign_EC_KEY(pkey, ec); |
241 | 0 | return 1; |
242 | 0 | } |
243 | | |
244 | | const EVP_PKEY_METHOD ec_pkey_meth = { |
245 | | EVP_PKEY_EC, |
246 | | pkey_ec_init, |
247 | | pkey_ec_copy, |
248 | | pkey_ec_cleanup, |
249 | | pkey_ec_keygen, |
250 | | pkey_ec_sign, |
251 | | NULL /* sign_message */, |
252 | | pkey_ec_verify, |
253 | | NULL /* verify_message */, |
254 | | NULL /* verify_recover */, |
255 | | NULL /* encrypt */, |
256 | | NULL /* decrypt */, |
257 | | pkey_ec_derive, |
258 | | pkey_ec_paramgen, |
259 | | pkey_ec_ctrl, |
260 | | }; |
261 | | |
262 | 0 | int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid) { |
263 | 0 | return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_TYPE_GEN, |
264 | 0 | EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL); |
265 | 0 | } |
266 | | |
267 | 0 | int EVP_PKEY_CTX_set_ec_param_enc(EVP_PKEY_CTX *ctx, int encoding) { |
268 | | // BoringSSL only supports named curve syntax. |
269 | 0 | if (encoding != OPENSSL_EC_NAMED_CURVE) { |
270 | 0 | OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PARAMETERS); |
271 | 0 | return 0; |
272 | 0 | } |
273 | 0 | return 1; |
274 | 0 | } |