2 * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (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/core_names.h>
12 #include <openssl/params.h>
13 #include <openssl/ec.h>
14 #include <openssl/rand.h>
15 #include <openssl/err.h>
17 # include <openssl/x509.h>
19 #include "crypto/ecx.h"
20 #include "ecx_backend.h"
23 * The intention with the "backend" source file is to offer backend support
24 * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
25 * implementations alike.
28 int ossl_ecx_public_from_private(ECX_KEY
*key
)
31 case ECX_KEY_TYPE_X25519
:
32 ossl_x25519_public_from_private(key
->pubkey
, key
->privkey
);
34 case ECX_KEY_TYPE_ED25519
:
35 if (!ossl_ed25519_public_from_private(key
->libctx
, key
->pubkey
,
36 key
->privkey
, key
->propq
)) {
37 ERR_raise(ERR_LIB_EC
, EC_R_FAILED_MAKING_PUBLIC_KEY
);
41 case ECX_KEY_TYPE_X448
:
42 ossl_x448_public_from_private(key
->pubkey
, key
->privkey
);
44 case ECX_KEY_TYPE_ED448
:
45 if (!ossl_ed448_public_from_private(key
->libctx
, key
->pubkey
,
46 key
->privkey
, key
->propq
)) {
47 ERR_raise(ERR_LIB_EC
, EC_R_FAILED_MAKING_PUBLIC_KEY
);
55 int ossl_ecx_key_fromdata(ECX_KEY
*ecx
, const OSSL_PARAM params
[],
58 size_t privkeylen
= 0, pubkeylen
= 0;
59 const OSSL_PARAM
*param_priv_key
= NULL
, *param_pub_key
;
60 unsigned char *pubkey
;
65 param_pub_key
= OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_PUB_KEY
);
68 OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_PRIV_KEY
);
70 if (param_pub_key
== NULL
&& param_priv_key
== NULL
)
73 if (param_priv_key
!= NULL
) {
74 if (!OSSL_PARAM_get_octet_string(param_priv_key
,
75 (void **)&ecx
->privkey
, ecx
->keylen
,
78 if (privkeylen
!= ecx
->keylen
) {
80 * Invalid key length. We will clear what we've received now. We
81 * can't leave it to ossl_ecx_key_free() because that will call
82 * OPENSSL_secure_clear_free() and assume the correct key length
84 OPENSSL_secure_clear_free(ecx
->privkey
, privkeylen
);
92 if (param_pub_key
!= NULL
93 && !OSSL_PARAM_get_octet_string(param_pub_key
,
95 sizeof(ecx
->pubkey
), &pubkeylen
))
98 if ((param_pub_key
!= NULL
&& pubkeylen
!= ecx
->keylen
))
101 if (param_pub_key
== NULL
&& !ossl_ecx_public_from_private(ecx
))
109 ECX_KEY
*ossl_ecx_key_dup(const ECX_KEY
*key
, int selection
)
111 ECX_KEY
*ret
= OPENSSL_zalloc(sizeof(*ret
));
116 ret
->libctx
= key
->libctx
;
117 ret
->haspubkey
= key
->haspubkey
;
118 ret
->keylen
= key
->keylen
;
119 ret
->type
= key
->type
;
121 if (!CRYPTO_NEW_REF(&ret
->references
, 1))
124 if (key
->propq
!= NULL
) {
125 ret
->propq
= OPENSSL_strdup(key
->propq
);
126 if (ret
->propq
== NULL
)
130 if ((selection
& OSSL_KEYMGMT_SELECT_PUBLIC_KEY
) != 0)
131 memcpy(ret
->pubkey
, key
->pubkey
, sizeof(ret
->pubkey
));
133 if ((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) != 0
134 && key
->privkey
!= NULL
) {
135 if (ossl_ecx_key_allocate_privkey(ret
) == NULL
) {
136 ERR_raise(ERR_LIB_EC
, ERR_R_EC_LIB
);
139 memcpy(ret
->privkey
, key
->privkey
, ret
->keylen
);
145 CRYPTO_FREE_REF(&ret
->references
);
146 ossl_ecx_key_free(ret
);
151 ECX_KEY
*ossl_ecx_key_op(const X509_ALGOR
*palg
,
152 const unsigned char *p
, int plen
,
153 int id
, ecx_key_op_t op
,
154 OSSL_LIB_CTX
*libctx
, const char *propq
)
157 unsigned char *privkey
, *pubkey
;
159 if (op
!= KEY_OP_KEYGEN
) {
163 /* Algorithm parameters must be absent */
164 X509_ALGOR_get0(NULL
, &ptype
, NULL
, palg
);
165 if (ptype
!= V_ASN1_UNDEF
) {
166 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_ENCODING
);
169 if (id
== EVP_PKEY_NONE
)
170 id
= OBJ_obj2nid(palg
->algorithm
);
171 else if (id
!= OBJ_obj2nid(palg
->algorithm
)) {
172 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_ENCODING
);
177 if (p
== NULL
|| id
== EVP_PKEY_NONE
|| plen
!= KEYLENID(id
)) {
178 ERR_raise(ERR_LIB_EC
, EC_R_INVALID_ENCODING
);
183 key
= ossl_ecx_key_new(libctx
, KEYNID2TYPE(id
), 1, propq
);
185 ERR_raise(ERR_LIB_EC
, ERR_R_EC_LIB
);
188 pubkey
= key
->pubkey
;
190 if (op
== KEY_OP_PUBLIC
) {
191 memcpy(pubkey
, p
, plen
);
193 privkey
= ossl_ecx_key_allocate_privkey(key
);
194 if (privkey
== NULL
) {
195 ERR_raise(ERR_LIB_EC
, ERR_R_EC_LIB
);
198 if (op
== KEY_OP_KEYGEN
) {
199 if (id
!= EVP_PKEY_NONE
) {
200 if (RAND_priv_bytes_ex(libctx
, privkey
, KEYLENID(id
), 0) <= 0)
202 if (id
== EVP_PKEY_X25519
) {
204 privkey
[X25519_KEYLEN
- 1] &= 127;
205 privkey
[X25519_KEYLEN
- 1] |= 64;
206 } else if (id
== EVP_PKEY_X448
) {
208 privkey
[X448_KEYLEN
- 1] |= 128;
212 memcpy(privkey
, p
, KEYLENID(id
));
214 if (!ossl_ecx_public_from_private(key
)) {
215 ERR_raise(ERR_LIB_EC
, EC_R_FAILED_MAKING_PUBLIC_KEY
);
222 ossl_ecx_key_free(key
);
226 ECX_KEY
*ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO
*p8inf
,
227 OSSL_LIB_CTX
*libctx
, const char *propq
)
230 const unsigned char *p
;
232 ASN1_OCTET_STRING
*oct
= NULL
;
233 const X509_ALGOR
*palg
;
235 if (!PKCS8_pkey_get0(NULL
, &p
, &plen
, &palg
, p8inf
))
238 oct
= d2i_ASN1_OCTET_STRING(NULL
, &p
, plen
);
243 p
= ASN1_STRING_get0_data(oct
);
244 plen
= ASN1_STRING_length(oct
);
248 * EVP_PKEY_NONE means that ecx_key_op() has to figure out the key type
251 ecx
= ossl_ecx_key_op(palg
, p
, plen
, EVP_PKEY_NONE
, KEY_OP_PRIVATE
,
253 ASN1_OCTET_STRING_free(oct
);