Handle KDF internally.
[openssl.git] / crypto / ec / ec_25519.c
1 /*
2  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2016 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  */
53
54 #include <string.h>
55 #include <openssl/err.h>
56 #include <openssl/rand.h>
57 #include "ec_lcl.h"
58
59 /* Length of Curve 25519 keys */
60 #define EC_X25519_KEYLEN    32
61 /* Group degree and order bits */
62 #define EC_X25519_BITS      253
63
64 /* Copy Curve25519 public key buffer, allocating is necessary */
65 static int x25519_init_public(EC_POINT *pub, const void *src)
66 {
67     if (pub->custom_data == NULL) {
68         pub->custom_data = OPENSSL_malloc(EC_X25519_KEYLEN);
69         if (pub->custom_data == NULL)
70             return 0;
71     }
72     if (src != NULL)
73         memcpy(pub->custom_data, src, EC_X25519_KEYLEN);
74     return 1;
75 }
76
77 /* Copy Curve25519 private key buffer, allocating is necessary */
78 static int x25519_init_private(EC_KEY *dst, const void *src)
79 {
80     if (dst->custom_data == NULL) {
81         dst->custom_data = OPENSSL_secure_malloc(EC_X25519_KEYLEN);
82         if (dst->custom_data == NULL)
83             return 0;
84     }
85     if (src != NULL)
86         memcpy(dst->custom_data, src, EC_X25519_KEYLEN);
87     return 1;
88 }
89
90 static int x25519_group_init(EC_GROUP *grp)
91 {
92     return 1;
93 }
94
95 static int x25519_group_copy(EC_GROUP *dst, const EC_GROUP *src)
96 {
97     return 1;
98 }
99
100 static int x25519_group_get_degree(const EC_GROUP *src)
101 {
102     return EC_X25519_BITS;
103 }
104
105 static int x25519_group_order_bits(const EC_GROUP *src)
106 {
107     return EC_X25519_BITS;
108 }
109
110 static int x25519_set_private(EC_KEY *eckey, const BIGNUM *priv_key)
111 {
112     if (BN_num_bytes(priv_key) > EC_X25519_KEYLEN)
113         return 0;
114     if (x25519_init_private(eckey, NULL))
115         return 0;
116     /* Convert BIGNUM form private key to internal format */
117     if (BN_bn2lebinpad(priv_key, eckey->custom_data, EC_X25519_KEYLEN)
118         != EC_X25519_KEYLEN)
119         return 0;
120     return 1;
121 }
122
123 static int x25519_keycheck(const EC_KEY *eckey)
124 {
125     const char *pubkey;
126     if (eckey->pub_key == NULL)
127         return 0;
128     pubkey = eckey->pub_key->custom_data;
129     if (pubkey == NULL)
130         return 0;
131     if (eckey->custom_data != NULL) {
132         uint8_t tmp[EC_X25519_KEYLEN];
133         /* Check eckey->priv_key exists and matches eckey->custom_data */
134         if (eckey->priv_key == NULL)
135             return 0;
136         if (BN_bn2lebinpad(eckey->priv_key, tmp, EC_X25519_KEYLEN)
137             != EC_X25519_KEYLEN
138             || CRYPTO_memcmp(tmp, eckey->custom_data,
139                              EC_X25519_KEYLEN) != 0) {
140             OPENSSL_cleanse(tmp, EC_X25519_KEYLEN);
141             return 0;
142         }
143         X25519_public_from_private(tmp, eckey->custom_data);
144         if (CRYPTO_memcmp(pubkey, tmp, EC_X25519_KEYLEN) == 0)
145             return 1;
146         return 0;
147     } else {
148         return 1;
149     }
150 }
151
152 static int x25519_keygenpub(EC_KEY *eckey)
153 {
154     X25519_public_from_private(eckey->pub_key->custom_data,
155                                eckey->custom_data);
156     return 1;
157 }
158
159 static int x25519_keygen(EC_KEY *eckey)
160 {
161     unsigned char *key;
162     if (x25519_init_private(eckey, NULL) == 0)
163         return 0;
164     key = eckey->custom_data;
165     if (RAND_bytes(key, EC_X25519_KEYLEN) <= 0)
166         return 0;
167     key[0] &= 248;
168     key[31] &= 127;
169     key[31] |= 64;
170     /*
171      * Although the private key is kept as an array in eckey->custom_data
172      * Set eckey->priv_key too so existing code which uses
173      * EC_KEY_get0_private_key() still works.
174      */
175     if (eckey->priv_key == NULL)
176         eckey->priv_key = BN_secure_new();
177     if (eckey->priv_key == NULL)
178         return 0;
179     if (BN_lebin2bn(eckey->custom_data, EC_X25519_KEYLEN, eckey->priv_key) ==
180         NULL)
181         return 0;
182     if (eckey->pub_key == NULL)
183         eckey->pub_key = EC_POINT_new(eckey->group);
184     if (eckey->pub_key == NULL)
185         return 0;
186     return x25519_keygenpub(eckey);
187 }
188
189 static void x25519_keyfinish(EC_KEY *eckey)
190 {
191     OPENSSL_secure_free(eckey->custom_data);
192     eckey->custom_data = NULL;
193 }
194
195 static int x25519_keycopy(EC_KEY *dest, const EC_KEY *src)
196 {
197     if (src->custom_data == NULL)
198         return 0;
199     return x25519_init_private(dest, src->custom_data);
200 }
201
202 static int x25519_oct2priv(EC_KEY *eckey, unsigned char *buf, size_t len)
203 {
204     if (len != EC_X25519_KEYLEN)
205         return 0;
206     if (x25519_init_private(eckey, buf) == 0)
207         return 0;
208     /*
209      * Although the private key is kept as an array in eckey->custom_data
210      * Set eckey->priv_key too so existing code which uses
211      * EC_KEY_get0_private_key() still works.
212      */
213     if (eckey->priv_key == NULL)
214         eckey->priv_key = BN_secure_new();
215     if (eckey->priv_key == NULL)
216         return 0;
217     if (BN_lebin2bn(buf, EC_X25519_KEYLEN, eckey->priv_key) == NULL)
218         return 0;
219     return 1;
220 }
221
222 static size_t x25519_priv2oct(const EC_KEY *eckey,
223                               unsigned char *buf, size_t len)
224 {
225     size_t keylen = EC_X25519_KEYLEN;
226     if (eckey->custom_data == NULL)
227         return 0;
228     if (buf != NULL) {
229         if (len < keylen)
230             return 0;
231         memcpy(buf, eckey->custom_data, keylen);
232     }
233     return keylen;
234 }
235
236 static int x25519_point_init(EC_POINT *pt)
237 {
238     return x25519_init_public(pt, NULL);
239 }
240
241 static void x25519_point_finish(EC_POINT *pt)
242 {
243     OPENSSL_free(pt->custom_data);
244     pt->custom_data = NULL;
245 }
246
247 static void x25519_point_clear_finish(EC_POINT *pt)
248 {
249     OPENSSL_clear_free(pt->custom_data, EC_X25519_KEYLEN);
250     pt->custom_data = NULL;
251 }
252
253 static int x25519_point_copy(EC_POINT *dst, const EC_POINT *src)
254 {
255     memcpy(dst->custom_data, src->custom_data, EC_X25519_KEYLEN);
256     return 1;
257 }
258
259 static size_t x25519_point2oct(const EC_GROUP *grp, const EC_POINT *pt,
260                                point_conversion_form_t form,
261                                unsigned char *buf, size_t len, BN_CTX *ctx)
262 {
263     if (buf != NULL) {
264         if (len < EC_X25519_KEYLEN)
265             return 0;
266         memcpy(buf, pt->custom_data, EC_X25519_KEYLEN);
267     }
268     return EC_X25519_KEYLEN;
269 }
270
271 static int x25519_oct2point(const EC_GROUP *grp, EC_POINT *pt,
272                             const unsigned char *buf, size_t len, BN_CTX *ctx)
273 {
274     unsigned char *pubkey = pt->custom_data;
275     if (len != EC_X25519_KEYLEN)
276         return 0;
277     memcpy(pubkey, buf, EC_X25519_KEYLEN);
278     /* Mask off MSB */
279     pubkey[EC_X25519_KEYLEN - 1] &= 0x7F;
280     return 1;
281 }
282
283 static int x25519_point_cmp(const EC_GROUP *group, const EC_POINT *a,
284                             const EC_POINT *b, BN_CTX *ctx)
285 {
286     /* Shouldn't happen as initialised to non-zero */
287     if (a->custom_data == NULL || b->custom_data == NULL)
288         return -1;
289
290     if (CRYPTO_memcmp(a->custom_data, b->custom_data, EC_X25519_KEYLEN) == 0)
291         return 0;
292
293     return 1;
294 }
295
296 static int x25519_compute_key(unsigned char **psec, size_t *pseclen,
297                               const EC_POINT *pub_key, const EC_KEY *ecdh)
298 {
299     unsigned char *key;
300     int ret = -1;
301     if (ecdh->custom_data == NULL)
302         return -1;
303     key = OPENSSL_malloc(EC_X25519_KEYLEN);
304     if (key == NULL)
305         return 0;
306     if (X25519(key, ecdh->custom_data, pub_key->custom_data) == 0)
307         goto err;
308     *psec = key;
309     *pseclen = EC_X25519_KEYLEN;
310     return 1;
311
312  err:
313     OPENSSL_clear_free(key, EC_X25519_KEYLEN);
314     return ret;
315 }
316
317 const EC_METHOD *ec_x25519_meth(void)
318 {
319     static const EC_METHOD ret = {
320         EC_FLAGS_CUSTOM_CURVE | EC_FLAGS_NO_SIGN,
321         NID_undef,
322         x25519_group_init,      /* group_init */
323         0,                      /* group_finish */
324         0,                      /* group_clear_finish */
325         x25519_group_copy,      /* group_copy */
326         0,                      /* group_set_curve */
327         0,                      /* group_get_curve */
328         x25519_group_get_degree,
329         x25519_group_order_bits,
330         0,                      /* group_check_discriminant */
331         x25519_point_init,
332         x25519_point_finish,
333         x25519_point_clear_finish,
334         x25519_point_copy,
335         0,                      /* point_set_to_infinity */
336         0,                      /* set_Jprojective_coordinates_GFp */
337         0,                      /* get_Jprojective_coordinates_GFp */
338         0,                      /* point_set_affine_coordinates */
339         0,                      /* point_get_affine_coordinates */
340         0,                      /* point_set_compressed_coordinates */
341         x25519_point2oct,
342         x25519_oct2point,
343         0,                      /* simple_add */
344         0,                      /* simple_dbl */
345         0,                      /* simple_invert */
346         0,                      /* simple_is_at_infinity */
347         0,                      /* simple_is_on_curve */
348         x25519_point_cmp,
349         0,                      /* simple_make_affine */
350         0,                      /* simple_points_make_affine */
351         0,                      /* points_mul */
352         0,                      /* precompute_mult */
353         0,                      /* have_precompute_mult */
354         0,                      /* field_mul */
355         0,                      /* field_sqr */
356         0,                      /* field_div */
357         0,                      /* field_encode */
358         0,                      /* field_decode */
359         0,                      /* field_set_to_one */
360         x25519_priv2oct,
361         x25519_oct2priv,
362         x25519_set_private,
363         x25519_keygen,
364         x25519_keycheck,
365         x25519_keygenpub,
366         x25519_keycopy,
367         x25519_keyfinish,
368         x25519_compute_key
369     };
370
371     return &ret;
372 }