]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/ec/ecx_meth.c
Add ASN1_STRING_get0_data(), deprecate ASN1_STRING_data().
[thirdparty/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_get0_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 };