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