2 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 #include <openssl/err.h>
12 #include <openssl/rand.h>
15 /* Length of Curve 25519 keys */
16 #define EC_X25519_KEYLEN 32
17 /* Group degree and order bits */
18 #define EC_X25519_BITS 253
20 /* Copy Curve25519 public key buffer, allocating is necessary */
21 static int x25519_init_public(EC_POINT *pub, const void *src)
23 if (pub->custom_data == NULL) {
24 pub->custom_data = OPENSSL_malloc(EC_X25519_KEYLEN);
25 if (pub->custom_data == NULL)
29 memcpy(pub->custom_data, src, EC_X25519_KEYLEN);
33 /* Copy Curve25519 private key buffer, allocating is necessary */
34 static int x25519_init_private(EC_KEY *dst, const void *src)
36 if (dst->custom_data == NULL) {
37 dst->custom_data = OPENSSL_secure_malloc(EC_X25519_KEYLEN);
38 if (dst->custom_data == NULL)
42 memcpy(dst->custom_data, src, EC_X25519_KEYLEN);
46 static int x25519_group_init(EC_GROUP *grp)
51 static int x25519_group_copy(EC_GROUP *dst, const EC_GROUP *src)
56 static int x25519_group_get_degree(const EC_GROUP *src)
58 return EC_X25519_BITS;
61 static int x25519_group_order_bits(const EC_GROUP *src)
63 return EC_X25519_BITS;
66 static int x25519_set_private(EC_KEY *eckey, const BIGNUM *priv_key)
68 if (BN_num_bytes(priv_key) > EC_X25519_KEYLEN)
70 if (x25519_init_private(eckey, NULL))
72 /* Convert BIGNUM form private key to internal format */
73 if (BN_bn2lebinpad(priv_key, eckey->custom_data, EC_X25519_KEYLEN)
79 static int x25519_keycheck(const EC_KEY *eckey)
82 if (eckey->pub_key == NULL)
84 pubkey = eckey->pub_key->custom_data;
87 if (eckey->custom_data != NULL) {
88 uint8_t tmp[EC_X25519_KEYLEN];
89 /* Check eckey->priv_key exists and matches eckey->custom_data */
90 if (eckey->priv_key == NULL)
92 if (BN_bn2lebinpad(eckey->priv_key, tmp, EC_X25519_KEYLEN)
94 || CRYPTO_memcmp(tmp, eckey->custom_data,
95 EC_X25519_KEYLEN) != 0) {
96 OPENSSL_cleanse(tmp, EC_X25519_KEYLEN);
99 X25519_public_from_private(tmp, eckey->custom_data);
100 if (CRYPTO_memcmp(pubkey, tmp, EC_X25519_KEYLEN) == 0)
108 static int x25519_keygenpub(EC_KEY *eckey)
110 X25519_public_from_private(eckey->pub_key->custom_data,
115 static int x25519_keygen(EC_KEY *eckey)
118 if (x25519_init_private(eckey, NULL) == 0)
120 key = eckey->custom_data;
121 if (RAND_bytes(key, EC_X25519_KEYLEN) <= 0)
127 * Although the private key is kept as an array in eckey->custom_data
128 * Set eckey->priv_key too so existing code which uses
129 * EC_KEY_get0_private_key() still works.
131 if (eckey->priv_key == NULL)
132 eckey->priv_key = BN_secure_new();
133 if (eckey->priv_key == NULL)
135 if (BN_lebin2bn(eckey->custom_data, EC_X25519_KEYLEN, eckey->priv_key) ==
138 if (eckey->pub_key == NULL)
139 eckey->pub_key = EC_POINT_new(eckey->group);
140 if (eckey->pub_key == NULL)
142 return x25519_keygenpub(eckey);
145 static void x25519_keyfinish(EC_KEY *eckey)
147 OPENSSL_secure_free(eckey->custom_data);
148 eckey->custom_data = NULL;
151 static int x25519_keycopy(EC_KEY *dest, const EC_KEY *src)
153 if (src->custom_data == NULL)
155 return x25519_init_private(dest, src->custom_data);
158 static int x25519_oct2priv(EC_KEY *eckey, unsigned char *buf, size_t len)
160 if (len != EC_X25519_KEYLEN)
162 if (x25519_init_private(eckey, buf) == 0)
165 * Although the private key is kept as an array in eckey->custom_data
166 * Set eckey->priv_key too so existing code which uses
167 * EC_KEY_get0_private_key() still works.
169 if (eckey->priv_key == NULL)
170 eckey->priv_key = BN_secure_new();
171 if (eckey->priv_key == NULL)
173 if (BN_lebin2bn(buf, EC_X25519_KEYLEN, eckey->priv_key) == NULL)
178 static size_t x25519_priv2oct(const EC_KEY *eckey,
179 unsigned char *buf, size_t len)
181 size_t keylen = EC_X25519_KEYLEN;
182 if (eckey->custom_data == NULL)
187 memcpy(buf, eckey->custom_data, keylen);
192 static int x25519_point_init(EC_POINT *pt)
194 return x25519_init_public(pt, NULL);
197 static void x25519_point_finish(EC_POINT *pt)
199 OPENSSL_free(pt->custom_data);
200 pt->custom_data = NULL;
203 static void x25519_point_clear_finish(EC_POINT *pt)
205 OPENSSL_clear_free(pt->custom_data, EC_X25519_KEYLEN);
206 pt->custom_data = NULL;
209 static int x25519_point_copy(EC_POINT *dst, const EC_POINT *src)
211 memcpy(dst->custom_data, src->custom_data, EC_X25519_KEYLEN);
215 static size_t x25519_point2oct(const EC_GROUP *grp, const EC_POINT *pt,
216 point_conversion_form_t form,
217 unsigned char *buf, size_t len, BN_CTX *ctx)
220 if (len < EC_X25519_KEYLEN)
222 memcpy(buf, pt->custom_data, EC_X25519_KEYLEN);
224 return EC_X25519_KEYLEN;
227 static int x25519_oct2point(const EC_GROUP *grp, EC_POINT *pt,
228 const unsigned char *buf, size_t len, BN_CTX *ctx)
230 unsigned char *pubkey = pt->custom_data;
231 if (len != EC_X25519_KEYLEN)
233 memcpy(pubkey, buf, EC_X25519_KEYLEN);
235 pubkey[EC_X25519_KEYLEN - 1] &= 0x7F;
239 static int x25519_point_cmp(const EC_GROUP *group, const EC_POINT *a,
240 const EC_POINT *b, BN_CTX *ctx)
242 /* Shouldn't happen as initialised to non-zero */
243 if (a->custom_data == NULL || b->custom_data == NULL)
246 if (CRYPTO_memcmp(a->custom_data, b->custom_data, EC_X25519_KEYLEN) == 0)
252 static int x25519_compute_key(unsigned char **psec, size_t *pseclen,
253 const EC_POINT *pub_key, const EC_KEY *ecdh)
257 if (ecdh->custom_data == NULL)
259 key = OPENSSL_malloc(EC_X25519_KEYLEN);
262 if (X25519(key, ecdh->custom_data, pub_key->custom_data) == 0)
265 *pseclen = EC_X25519_KEYLEN;
269 OPENSSL_clear_free(key, EC_X25519_KEYLEN);
273 const EC_METHOD *ec_x25519_meth(void)
275 static const EC_METHOD ret = {
276 EC_FLAGS_CUSTOM_CURVE | EC_FLAGS_NO_SIGN,
278 x25519_group_init, /* group_init */
279 0, /* group_finish */
280 0, /* group_clear_finish */
281 x25519_group_copy, /* group_copy */
282 0, /* group_set_curve */
283 0, /* group_get_curve */
284 x25519_group_get_degree,
285 x25519_group_order_bits,
286 0, /* group_check_discriminant */
289 x25519_point_clear_finish,
291 0, /* point_set_to_infinity */
292 0, /* set_Jprojective_coordinates_GFp */
293 0, /* get_Jprojective_coordinates_GFp */
294 0, /* point_set_affine_coordinates */
295 0, /* point_get_affine_coordinates */
296 0, /* point_set_compressed_coordinates */
301 0, /* simple_invert */
302 0, /* simple_is_at_infinity */
303 0, /* simple_is_on_curve */
305 0, /* simple_make_affine */
306 0, /* simple_points_make_affine */
308 0, /* precompute_mult */
309 0, /* have_precompute_mult */
313 0, /* field_encode */
314 0, /* field_decode */
315 0, /* field_set_to_one */