2 * Copyright 2006-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 "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"
19 #define X25519_KEYLEN 32
20 #define X25519_BITS 253
21 #define X25519_SECURITY_BITS 128
23 #define ED25519_SIGSIZE 64
26 unsigned char pubkey
[X25519_KEYLEN
];
27 unsigned char *privkey
;
36 /* Setup EVP_PKEY using public, private or generation */
37 static int ecx_key_op(EVP_PKEY
*pkey
, int id
, const X509_ALGOR
*palg
,
38 const unsigned char *p
, int plen
, ecx_key_op_t op
)
42 if (op
!= X25519_KEYGEN
) {
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
);
54 if (p
== NULL
|| plen
!= X25519_KEYLEN
) {
55 ECerr(EC_F_ECX_KEY_OP
, EC_R_INVALID_ENCODING
);
60 xkey
= OPENSSL_zalloc(sizeof(*xkey
));
62 ECerr(EC_F_ECX_KEY_OP
, ERR_R_MALLOC_FAILURE
);
66 if (op
== X25519_PUBLIC
) {
67 memcpy(xkey
->pubkey
, p
, plen
);
69 xkey
->privkey
= OPENSSL_secure_malloc(X25519_KEYLEN
);
70 if (xkey
->privkey
== NULL
) {
71 ECerr(EC_F_ECX_KEY_OP
, ERR_R_MALLOC_FAILURE
);
75 if (op
== X25519_KEYGEN
) {
76 if (RAND_bytes(xkey
->privkey
, X25519_KEYLEN
) <= 0) {
77 OPENSSL_secure_free(xkey
->privkey
);
81 if (id
== NID_X25519
) {
82 xkey
->privkey
[0] &= 248;
83 xkey
->privkey
[31] &= 127;
84 xkey
->privkey
[31] |= 64;
87 memcpy(xkey
->privkey
, p
, X25519_KEYLEN
);
90 X25519_public_from_private(xkey
->pubkey
, xkey
->privkey
);
92 ED25519_public_from_private(xkey
->pubkey
, xkey
->privkey
);
95 EVP_PKEY_assign(pkey
, id
, xkey
);
99 static int ecx_pub_encode(X509_PUBKEY
*pk
, const EVP_PKEY
*pkey
)
101 const X25519_KEY
*xkey
= pkey
->pkey
.ptr
;
105 ECerr(EC_F_ECX_PUB_ENCODE
, EC_R_INVALID_KEY
);
109 penc
= OPENSSL_memdup(xkey
->pubkey
, X25519_KEYLEN
);
111 ECerr(EC_F_ECX_PUB_ENCODE
, ERR_R_MALLOC_FAILURE
);
115 if (!X509_PUBKEY_set0_param(pk
, OBJ_nid2obj(pkey
->ameth
->pkey_id
),
116 V_ASN1_UNDEF
, NULL
, penc
, X25519_KEYLEN
)) {
118 ECerr(EC_F_ECX_PUB_ENCODE
, ERR_R_MALLOC_FAILURE
);
124 static int ecx_pub_decode(EVP_PKEY
*pkey
, X509_PUBKEY
*pubkey
)
126 const unsigned char *p
;
130 if (!X509_PUBKEY_get0_param(NULL
, &p
, &pklen
, &palg
, pubkey
))
132 return ecx_key_op(pkey
, pkey
->ameth
->pkey_id
, palg
, p
, pklen
,
136 static int ecx_pub_cmp(const EVP_PKEY
*a
, const EVP_PKEY
*b
)
138 const X25519_KEY
*akey
= a
->pkey
.ptr
;
139 const X25519_KEY
*bkey
= b
->pkey
.ptr
;
141 if (akey
== NULL
|| bkey
== NULL
)
143 return !CRYPTO_memcmp(akey
->pubkey
, bkey
->pubkey
, X25519_KEYLEN
);
146 static int ecx_priv_decode(EVP_PKEY
*pkey
, const PKCS8_PRIV_KEY_INFO
*p8
)
148 const unsigned char *p
;
150 ASN1_OCTET_STRING
*oct
= NULL
;
151 const X509_ALGOR
*palg
;
154 if (!PKCS8_pkey_get0(NULL
, &p
, &plen
, &palg
, p8
))
157 oct
= d2i_ASN1_OCTET_STRING(NULL
, &p
, plen
);
162 p
= ASN1_STRING_get0_data(oct
);
163 plen
= ASN1_STRING_length(oct
);
166 rv
= ecx_key_op(pkey
, pkey
->ameth
->pkey_id
, palg
, p
, plen
, X25519_PRIVATE
);
167 ASN1_OCTET_STRING_free(oct
);
171 static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO
*p8
, const EVP_PKEY
*pkey
)
173 const X25519_KEY
*xkey
= pkey
->pkey
.ptr
;
174 ASN1_OCTET_STRING oct
;
175 unsigned char *penc
= NULL
;
178 if (xkey
== NULL
|| xkey
->privkey
== NULL
) {
179 ECerr(EC_F_ECX_PRIV_ENCODE
, EC_R_INVALID_PRIVATE_KEY
);
183 oct
.data
= xkey
->privkey
;
184 oct
.length
= X25519_KEYLEN
;
187 penclen
= i2d_ASN1_OCTET_STRING(&oct
, &penc
);
189 ECerr(EC_F_ECX_PRIV_ENCODE
, ERR_R_MALLOC_FAILURE
);
193 if (!PKCS8_pkey_set0(p8
, OBJ_nid2obj(pkey
->ameth
->pkey_id
), 0,
194 V_ASN1_UNDEF
, NULL
, penc
, penclen
)) {
195 OPENSSL_clear_free(penc
, penclen
);
196 ECerr(EC_F_ECX_PRIV_ENCODE
, ERR_R_MALLOC_FAILURE
);
203 static int ecx_size(const EVP_PKEY
*pkey
)
205 return X25519_KEYLEN
;
208 static int ecx_bits(const EVP_PKEY
*pkey
)
213 static int ecx_security_bits(const EVP_PKEY
*pkey
)
215 return X25519_SECURITY_BITS
;
218 static void ecx_free(EVP_PKEY
*pkey
)
220 X25519_KEY
*xkey
= pkey
->pkey
.ptr
;
223 OPENSSL_secure_free(xkey
->privkey
);
227 /* "parameters" are always equal */
228 static int ecx_cmp_parameters(const EVP_PKEY
*a
, const EVP_PKEY
*b
)
233 static int ecx_key_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
234 ASN1_PCTX
*ctx
, ecx_key_op_t op
)
236 const X25519_KEY
*xkey
= pkey
->pkey
.ptr
;
238 const char *nm
= OBJ_nid2ln(pkey
->ameth
->pkey_id
);
240 if (op
== X25519_PRIVATE
) {
241 if (xkey
== NULL
|| xkey
->privkey
== NULL
) {
242 if (BIO_printf(bp
, "%*s<INVALID PRIVATE KEY>\n", indent
, "") <= 0)
246 if (BIO_printf(bp
, "%*s%s Private-Key:\n", indent
, "", nm
) <= 0)
248 if (BIO_printf(bp
, "%*spriv:\n", indent
, "") <= 0)
250 if (ASN1_buf_print(bp
, xkey
->privkey
, X25519_KEYLEN
, indent
+ 4) == 0)
254 if (BIO_printf(bp
, "%*s<INVALID PUBLIC KEY>\n", indent
, "") <= 0)
258 if (BIO_printf(bp
, "%*s%s Public-Key:\n", indent
, "", nm
) <= 0)
261 if (BIO_printf(bp
, "%*spub:\n", indent
, "") <= 0)
263 if (ASN1_buf_print(bp
, xkey
->pubkey
, X25519_KEYLEN
, indent
+ 4) == 0)
268 static int ecx_priv_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
271 return ecx_key_print(bp
, pkey
, indent
, ctx
, X25519_PRIVATE
);
274 static int ecx_pub_print(BIO
*bp
, const EVP_PKEY
*pkey
, int indent
,
277 return ecx_key_print(bp
, pkey
, indent
, ctx
, X25519_PUBLIC
);
280 static int ecx_ctrl(EVP_PKEY
*pkey
, int op
, long arg1
, void *arg2
)
284 case ASN1_PKEY_CTRL_SET1_TLS_ENCPT
:
285 return ecx_key_op(pkey
, NID_X25519
, NULL
, arg2
, arg1
, X25519_PUBLIC
);
287 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT
:
288 if (pkey
->pkey
.ptr
!= NULL
) {
289 const X25519_KEY
*xkey
= pkey
->pkey
.ptr
;
290 unsigned char **ppt
= arg2
;
291 *ppt
= OPENSSL_memdup(xkey
->pubkey
, X25519_KEYLEN
);
293 return X25519_KEYLEN
;
297 case ASN1_PKEY_CTRL_DEFAULT_MD_NID
:
298 *(int *)arg2
= NID_sha256
;
307 const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth
= {
312 "OpenSSL X25519 algorithm",
337 static int ecd_size(const EVP_PKEY
*pkey
)
339 return ED25519_SIGSIZE
;
342 const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth
= {
347 "OpenSSL ED25519 algorithm",
372 static int pkey_ecx_keygen(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
374 return ecx_key_op(pkey
, ctx
->pmeth
->pkey_id
, NULL
, NULL
, 0, X25519_KEYGEN
);
377 static int pkey_ecx_derive(EVP_PKEY_CTX
*ctx
, unsigned char *key
,
380 const X25519_KEY
*pkey
, *peerkey
;
382 if (ctx
->pkey
== NULL
|| ctx
->peerkey
== NULL
) {
383 ECerr(EC_F_PKEY_ECX_DERIVE
, EC_R_KEYS_NOT_SET
);
386 pkey
= ctx
->pkey
->pkey
.ptr
;
387 peerkey
= ctx
->peerkey
->pkey
.ptr
;
388 if (pkey
== NULL
|| pkey
->privkey
== NULL
) {
389 ECerr(EC_F_PKEY_ECX_DERIVE
, EC_R_INVALID_PRIVATE_KEY
);
392 if (peerkey
== NULL
) {
393 ECerr(EC_F_PKEY_ECX_DERIVE
, EC_R_INVALID_PEER_KEY
);
396 *keylen
= X25519_KEYLEN
;
397 if (key
!= NULL
&& X25519(key
, pkey
->privkey
, peerkey
->pubkey
) == 0)
402 static int pkey_ecx_ctrl(EVP_PKEY_CTX
*ctx
, int type
, int p1
, void *p2
)
404 /* Only need to handle peer key for derivation */
405 if (type
== EVP_PKEY_CTRL_PEER_KEY
)
410 const EVP_PKEY_METHOD ecx25519_pkey_meth
= {
414 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
420 static int pkey_ecd_digestsign(EVP_MD_CTX
*ctx
, unsigned char *sig
,
421 size_t *siglen
, const unsigned char *tbs
,
424 const X25519_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ptr
;
427 *siglen
= ED25519_SIGSIZE
;
430 if (*siglen
< ED25519_SIGSIZE
) {
431 ECerr(EC_F_PKEY_ECD_DIGESTSIGN
, EC_R_BUFFER_TOO_SMALL
);
435 if (ED25519_sign(sig
, tbs
, tbslen
, edkey
->pubkey
, edkey
->privkey
) == 0)
437 *siglen
= ED25519_SIGSIZE
;
441 static int pkey_ecd_digestverify(EVP_MD_CTX
*ctx
, const unsigned char *sig
,
442 size_t siglen
, const unsigned char *tbs
,
445 const X25519_KEY
*edkey
= EVP_MD_CTX_pkey_ctx(ctx
)->pkey
->pkey
.ptr
;
447 if (siglen
!= ED25519_SIGSIZE
)
450 return ED25519_verify(tbs
, tbslen
, sig
, edkey
->pubkey
);
453 static int pkey_ecd_ctrl(EVP_PKEY_CTX
*ctx
, int type
, int p1
, void *p2
)
456 case EVP_PKEY_CTRL_MD
:
457 /* Only NULL allowed as digest */
460 ECerr(EC_F_PKEY_ECD_CTRL
, EC_R_INVALID_DIGEST_TYPE
);
463 case EVP_PKEY_CTRL_DIGESTINIT
:
469 const EVP_PKEY_METHOD ed25519_pkey_meth
= {
470 NID_ED25519
, EVP_PKEY_FLAG_SIGCTX_CUSTOM
,
473 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
477 pkey_ecd_digestverify