1/* 2 * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. 3 * 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 8 */ 9 10#include <string.h> 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> 16#ifndef FIPS_MODULE 17# include <openssl/x509.h> 18#endif 19#include "crypto/ecx.h" 20#include "ecx_backend.h" 21 22/* 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. 26 */ 27 28int ossl_ecx_public_from_private(ECX_KEY *key) 29{ 30 switch (key->type) { 31 case ECX_KEY_TYPE_X25519: 32 ossl_x25519_public_from_private(key->pubkey, key->privkey); 33 break; 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); 38 return 0; 39 } 40 break; 41 case ECX_KEY_TYPE_X448: 42 ossl_x448_public_from_private(key->pubkey, key->privkey); 43 break; 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); 48 return 0; 49 } 50 break; 51 } 52 return 1; 53} 54 55int ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[], 56 int include_private) 57{ 58 size_t privkeylen = 0, pubkeylen = 0; 59 const OSSL_PARAM *param_priv_key = NULL, *param_pub_key; 60 unsigned char *pubkey; 61 62 if (ecx == NULL) 63 return 0; 64 65 param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); 66 if (include_private) 67 param_priv_key = 68 OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); 69 70 if (param_pub_key == NULL && param_priv_key == NULL) 71 return 0; 72 73 if (param_priv_key != NULL) { 74 if (!OSSL_PARAM_get_octet_string(param_priv_key, 75 (void **)&ecx->privkey, ecx->keylen, 76 &privkeylen)) 77 return 0; 78 if (privkeylen != ecx->keylen) { 79 /* 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 83 */ 84 OPENSSL_secure_clear_free(ecx->privkey, privkeylen); 85 ecx->privkey = NULL; 86 return 0; 87 } 88 } 89 90 91 pubkey = ecx->pubkey; 92 if (param_pub_key != NULL 93 && !OSSL_PARAM_get_octet_string(param_pub_key, 94 (void **)&pubkey, 95 sizeof(ecx->pubkey), &pubkeylen)) 96 return 0; 97 98 if ((param_pub_key != NULL && pubkeylen != ecx->keylen)) 99 return 0; 100 101 if (param_pub_key == NULL && !ossl_ecx_public_from_private(ecx)) 102 return 0; 103 104 ecx->haspubkey = 1; 105 106 return 1; 107} 108 109ECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key, int selection) 110{ 111 ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); 112 113 if (ret == NULL) { 114 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 115 return NULL; 116 } 117 118 ret->lock = CRYPTO_THREAD_lock_new(); 119 if (ret->lock == NULL) { 120 OPENSSL_free(ret); 121 return NULL; 122 } 123 124 ret->libctx = key->libctx; 125 ret->haspubkey = 0; 126 ret->keylen = key->keylen; 127 ret->type = key->type; 128 ret->references = 1; 129 130 if (key->propq != NULL) { 131 ret->propq = OPENSSL_strdup(key->propq); 132 if (ret->propq == NULL) 133 goto err; 134 } 135 136 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0 137 && key->haspubkey == 1) { 138 memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey)); 139 ret->haspubkey = 1; 140 } 141 142 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 143 && key->privkey != NULL) { 144 if (ossl_ecx_key_allocate_privkey(ret) == NULL) 145 goto err; 146 memcpy(ret->privkey, key->privkey, ret->keylen); 147 } 148 149 return ret; 150 151err: 152 ossl_ecx_key_free(ret); 153 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 154 return NULL; 155} 156 157#ifndef FIPS_MODULE 158ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg, 159 const unsigned char *p, int plen, 160 int id, ecx_key_op_t op, 161 OSSL_LIB_CTX *libctx, const char *propq) 162{ 163 ECX_KEY *key = NULL; 164 unsigned char *privkey, *pubkey; 165 166 if (op != KEY_OP_KEYGEN) { 167 if (palg != NULL) { 168 int ptype; 169 170 /* Algorithm parameters must be absent */ 171 X509_ALGOR_get0(NULL, &ptype, NULL, palg); 172 if (ptype != V_ASN1_UNDEF) { 173 ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 174 return 0; 175 } 176 if (id == EVP_PKEY_NONE) 177 id = OBJ_obj2nid(palg->algorithm); 178 else if (id != OBJ_obj2nid(palg->algorithm)) { 179 ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 180 return 0; 181 } 182 } 183 184 if (p == NULL || id == EVP_PKEY_NONE || plen != KEYLENID(id)) { 185 ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 186 return 0; 187 } 188 } 189 190 key = ossl_ecx_key_new(libctx, KEYNID2TYPE(id), 1, propq); 191 if (key == NULL) { 192 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 193 return 0; 194 } 195 pubkey = key->pubkey; 196 197 if (op == KEY_OP_PUBLIC) { 198 memcpy(pubkey, p, plen); 199 } else { 200 privkey = ossl_ecx_key_allocate_privkey(key); 201 if (privkey == NULL) { 202 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 203 goto err; 204 } 205 if (op == KEY_OP_KEYGEN) { 206 if (id != EVP_PKEY_NONE) { 207 if (RAND_priv_bytes_ex(libctx, privkey, KEYLENID(id), 0) <= 0) 208 goto err; 209 if (id == EVP_PKEY_X25519) { 210 privkey[0] &= 248; 211 privkey[X25519_KEYLEN - 1] &= 127; 212 privkey[X25519_KEYLEN - 1] |= 64; 213 } else if (id == EVP_PKEY_X448) { 214 privkey[0] &= 252; 215 privkey[X448_KEYLEN - 1] |= 128; 216 } 217 } 218 } else { 219 memcpy(privkey, p, KEYLENID(id)); 220 } 221 if (!ossl_ecx_public_from_private(key)) { 222 ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY); 223 goto err; 224 } 225 } 226 227 return key; 228 err: 229 ossl_ecx_key_free(key); 230 return NULL; 231} 232 233ECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, 234 OSSL_LIB_CTX *libctx, const char *propq) 235{ 236 ECX_KEY *ecx = NULL; 237 const unsigned char *p; 238 int plen; 239 ASN1_OCTET_STRING *oct = NULL; 240 const X509_ALGOR *palg; 241 242 if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8inf)) 243 return 0; 244 245 oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen); 246 if (oct == NULL) { 247 p = NULL; 248 plen = 0; 249 } else { 250 p = ASN1_STRING_get0_data(oct); 251 plen = ASN1_STRING_length(oct); 252 } 253 254 /* 255 * EVP_PKEY_NONE means that ecx_key_op() has to figure out the key type 256 * on its own. 257 */ 258 ecx = ossl_ecx_key_op(palg, p, plen, EVP_PKEY_NONE, KEY_OP_PRIVATE, 259 libctx, propq); 260 ASN1_OCTET_STRING_free(oct); 261 return ecx; 262} 263#endif 264