354d3879467fa8a0ce96e4257f335fe8658ad7f6
[openssl.git] / crypto / ec / ecx_meth.c
1 /*
2  * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
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
8  */
9
10 #include <stdio.h>
11 #include "internal/cryptlib.h"
12 #include <openssl/x509.h>
13 #include <openssl/ec.h>
14 #include <openssl/rand.h>
15 #include "internal/asn1_int.h"
16 #include "internal/evp_int.h"
17 #include "ec_lcl.h"
18
19 #define X25519_KEYLEN        32
20 #define X25519_BITS          253
21 #define X25519_SECURITY_BITS 128
22
23 typedef struct {
24     unsigned char pubkey[X25519_KEYLEN];
25     unsigned char *privkey;
26 } X25519_KEY;
27
28 typedef enum {
29     X25519_PUBLIC,
30     X25519_PRIVATE,
31     X25519_KEYGEN
32 } ecx_key_op_t;
33
34 /* Setup EVP_PKEY using public, private or generation */
35 static int ecx_key_op(EVP_PKEY *pkey, X509_ALGOR *palg,
36                       const unsigned char *p, int plen, ecx_key_op_t op)
37 {
38     X25519_KEY *xkey;
39
40     if (op != X25519_KEYGEN) {
41         if (palg != NULL) {
42             int ptype;
43
44             /* Algorithm parameters must be absent */
45             X509_ALGOR_get0(NULL, &ptype, NULL, palg);
46             if (ptype != V_ASN1_UNDEF) {
47                 ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
48                 return 0;
49             }
50         }
51
52         if (p == NULL || plen != X25519_KEYLEN) {
53             ECerr(EC_F_ECX_KEY_OP, EC_R_INVALID_ENCODING);
54             return 0;
55         }
56     }
57
58     xkey = OPENSSL_zalloc(sizeof(*xkey));
59     if (xkey == NULL) {
60         ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
61         return 0;
62     }
63
64     if (op == X25519_PUBLIC) {
65         memcpy(xkey->pubkey, p, plen);
66     } else {
67         xkey->privkey = OPENSSL_secure_malloc(X25519_KEYLEN);
68         if (xkey->privkey == NULL) {
69             ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
70             OPENSSL_free(xkey);
71             return 0;
72         }
73         if (op == X25519_KEYGEN) {
74             if (RAND_bytes(xkey->privkey, X25519_KEYLEN) <= 0) {
75                 OPENSSL_secure_free(xkey->privkey);
76                 OPENSSL_free(xkey);
77                 return 0;
78             }
79             xkey->privkey[0] &= 248;
80             xkey->privkey[31] &= 127;
81             xkey->privkey[31] |= 64;
82         } else {
83             memcpy(xkey->privkey, p, X25519_KEYLEN);
84         }
85         X25519_public_from_private(xkey->pubkey, xkey->privkey);
86     }
87
88     EVP_PKEY_assign(pkey, NID_X25519, xkey);
89     return 1;
90 }
91
92 static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
93 {
94     const X25519_KEY *xkey = pkey->pkey.ptr;
95     unsigned char *penc;
96
97     if (xkey == NULL) {
98         ECerr(EC_F_ECX_PUB_ENCODE, EC_R_INVALID_KEY);
99         return 0;
100     }
101
102     penc = OPENSSL_memdup(xkey->pubkey, X25519_KEYLEN);
103     if (penc == NULL) {
104         ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
105         return 0;
106     }
107
108     if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(NID_X25519), V_ASN1_UNDEF,
109                                 NULL, penc, X25519_KEYLEN)) {
110         OPENSSL_free(penc);
111         ECerr(EC_F_ECX_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
112         return 0;
113     }
114     return 1;
115 }
116
117 static int ecx_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
118 {
119     const unsigned char *p;
120     int pklen;
121     X509_ALGOR *palg;
122
123     if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
124         return 0;
125     return ecx_key_op(pkey, palg, p, pklen, X25519_PUBLIC);
126 }
127
128 static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
129 {
130     const X25519_KEY *akey = a->pkey.ptr;
131     const X25519_KEY *bkey = b->pkey.ptr;
132
133     if (akey == NULL || bkey == NULL)
134         return -2;
135     return !CRYPTO_memcmp(akey->pubkey, bkey->pubkey, X25519_KEYLEN);
136 }
137
138 static int ecx_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
139 {
140     const unsigned char *p;
141     int plen;
142     ASN1_OCTET_STRING *oct = NULL;
143     X509_ALGOR *palg;
144     int rv;
145
146     if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8))
147         return 0;
148
149     oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen);
150     if (oct == NULL) {
151         p = NULL;
152         plen = 0;
153     } else {
154         p = ASN1_STRING_data(oct);
155         plen = ASN1_STRING_length(oct);
156     }
157
158     rv = ecx_key_op(pkey, palg, p, plen, X25519_PRIVATE);
159     ASN1_OCTET_STRING_free(oct);
160     return rv;
161 }
162
163 static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
164 {
165     const X25519_KEY *xkey = pkey->pkey.ptr;
166     ASN1_OCTET_STRING oct;
167     unsigned char *penc = NULL;
168     int penclen;
169
170     if (xkey == NULL || xkey->privkey == NULL) {
171         ECerr(EC_F_ECX_PRIV_ENCODE, EC_R_INVALID_PRIVATE_KEY);
172         return 0;
173     }
174
175     oct.data = xkey->privkey;
176     oct.length = X25519_KEYLEN;
177     oct.flags = 0;
178
179     penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
180     if (penclen < 0) {
181         ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
182         return 0;
183     }
184
185     if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X25519), 0,
186                          V_ASN1_UNDEF, NULL, penc, penclen)) {
187         OPENSSL_clear_free(penc, penclen);
188         ECerr(EC_F_ECX_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
189         return 0;
190     }
191
192     return 1;
193 }
194
195 static int ecx_size(const EVP_PKEY *pkey)
196 {
197     return X25519_KEYLEN;
198 }
199
200 static int ecx_bits(const EVP_PKEY *pkey)
201 {
202     return X25519_BITS;
203 }
204
205 static int ecx_security_bits(const EVP_PKEY *pkey)
206 {
207     return X25519_SECURITY_BITS;
208 }
209
210 static void ecx_free(EVP_PKEY *pkey)
211 {
212     X25519_KEY *xkey = pkey->pkey.ptr;
213
214     if (xkey)
215         OPENSSL_secure_free(xkey->privkey);
216     OPENSSL_free(xkey);
217 }
218
219 /* "parameters" are always equal */
220 static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
221 {
222     return 1;
223 }
224
225 static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
226                          ASN1_PCTX *ctx, ecx_key_op_t op)
227 {
228     const X25519_KEY *xkey = pkey->pkey.ptr;
229
230     if (op == X25519_PRIVATE) {
231         if (xkey == NULL || xkey->privkey == NULL) {
232             if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
233                 return 0;
234             return 1;
235         }
236         if (BIO_printf(bp, "%*sX25519 Private-Key:\n", indent, "") <= 0)
237             return 0;
238         if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
239             return 0;
240         if (ASN1_buf_print(bp, xkey->privkey, X25519_KEYLEN, indent + 4) == 0)
241             return 0;
242     } else {
243         if (xkey == NULL) {
244             if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
245                 return 0;
246             return 1;
247         }
248         if (BIO_printf(bp, "%*sX25519 Public-Key:\n", indent, "") <= 0)
249             return 0;
250     }
251     if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
252         return 0;
253     if (ASN1_buf_print(bp, xkey->pubkey, X25519_KEYLEN, indent + 4) == 0)
254         return 0;
255     return 1;
256 }
257
258 static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
259                           ASN1_PCTX *ctx)
260 {
261     return ecx_key_print(bp, pkey, indent, ctx, X25519_PRIVATE);
262 }
263
264 static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
265                          ASN1_PCTX *ctx)
266 {
267     return ecx_key_print(bp, pkey, indent, ctx, X25519_PUBLIC);
268 }
269
270 static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
271 {
272     switch (op) {
273
274     case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
275         return ecx_key_op(pkey, NULL, arg2, arg1, X25519_PUBLIC);
276
277     case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
278         if (pkey->pkey.ptr != NULL) {
279             const X25519_KEY *xkey = pkey->pkey.ptr;
280             unsigned char **ppt = arg2;
281             *ppt = OPENSSL_memdup(xkey->pubkey, X25519_KEYLEN);
282             if (*ppt != NULL)
283                 return X25519_KEYLEN;
284         }
285         return 0;
286
287     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
288         *(int *)arg2 = NID_sha256;
289         return 2;
290
291     default:
292         return -2;
293
294     }
295 }
296
297 const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
298     NID_X25519,
299     NID_X25519,
300     0,
301     "X25519",
302     "OpenSSL X25519 algorithm",
303
304     ecx_pub_decode,
305     ecx_pub_encode,
306     ecx_pub_cmp,
307     ecx_pub_print,
308
309     ecx_priv_decode,
310     ecx_priv_encode,
311     ecx_priv_print,
312
313     ecx_size,
314     ecx_bits,
315     ecx_security_bits,
316
317     0, 0, 0, 0,
318     ecx_cmp_parameters,
319     0, 0,
320
321     ecx_free,
322     ecx_ctrl,
323     NULL,
324     NULL
325 };
326
327 static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
328 {
329     return ecx_key_op(pkey, NULL, NULL, 0, X25519_KEYGEN);
330 }
331
332 static int pkey_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
333                            size_t *keylen)
334 {
335     const X25519_KEY *pkey, *peerkey;
336
337     if (ctx->pkey == NULL || ctx->peerkey == NULL) {
338         ECerr(EC_F_PKEY_ECX_DERIVE, EC_R_KEYS_NOT_SET);
339         return 0;
340     }
341     pkey = ctx->pkey->pkey.ptr;
342     peerkey = ctx->peerkey->pkey.ptr;
343     if (pkey == NULL || pkey->privkey == NULL) {
344         ECerr(EC_F_PKEY_ECX_DERIVE, EC_R_INVALID_PRIVATE_KEY);
345         return 0;
346     }
347     if (peerkey == NULL) {
348         ECerr(EC_F_PKEY_ECX_DERIVE, EC_R_INVALID_PEER_KEY);
349         return 0;
350     }
351     *keylen = X25519_KEYLEN;
352     if (key != NULL && X25519(key, pkey->privkey, peerkey->pubkey) == 0)
353         return 0;
354     return 1;
355 }
356
357 static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
358 {
359     /* Only need to handle peer key for derivation */
360     if (type == EVP_PKEY_CTRL_PEER_KEY)
361         return 1;
362     return -2;
363 }
364
365 const EVP_PKEY_METHOD ecx25519_pkey_meth = {
366     NID_X25519,
367     0, 0, 0, 0, 0, 0, 0,
368     pkey_ecx_keygen,
369     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
370     pkey_ecx_derive,
371     pkey_ecx_ctrl,
372     0
373 };