1/* 2 * Copyright 2020-2021 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 = key->haspubkey; 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 memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey)); 138 139 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 140 && key->privkey != NULL) { 141 if (ossl_ecx_key_allocate_privkey(ret) == NULL) 142 goto err; 143 memcpy(ret->privkey, key->privkey, ret->keylen); 144 } 145 146 return ret; 147 148err: 149 ossl_ecx_key_free(ret); 150 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 151 return NULL; 152} 153 154#ifndef FIPS_MODULE 155ECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg, 156 const unsigned char *p, int plen, 157 int id, ecx_key_op_t op, 158 OSSL_LIB_CTX *libctx, const char *propq) 159{ 160 ECX_KEY *key = NULL; 161 unsigned char *privkey, *pubkey; 162 163 if (op != KEY_OP_KEYGEN) { 164 if (palg != NULL) { 165 int ptype; 166 167 /* Algorithm parameters must be absent */ 168 X509_ALGOR_get0(NULL, &ptype, NULL, palg); 169 if (ptype != V_ASN1_UNDEF) { 170 ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 171 return 0; 172 } 173 if (id == EVP_PKEY_NONE) 174 id = OBJ_obj2nid(palg->algorithm); 175 else if (id != OBJ_obj2nid(palg->algorithm)) { 176 ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 177 return 0; 178 } 179 } 180 181 if (p == NULL || id == EVP_PKEY_NONE || plen != KEYLENID(id)) { 182 ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 183 return 0; 184 } 185 } 186 187 key = ossl_ecx_key_new(libctx, KEYNID2TYPE(id), 1, propq); 188 if (key == NULL) { 189 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 190 return 0; 191 } 192 pubkey = key->pubkey; 193 194 if (op == KEY_OP_PUBLIC) { 195 memcpy(pubkey, p, plen); 196 } else { 197 privkey = ossl_ecx_key_allocate_privkey(key); 198 if (privkey == NULL) { 199 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 200 goto err; 201 } 202 if (op == KEY_OP_KEYGEN) { 203 if (id != EVP_PKEY_NONE) { 204 if (RAND_priv_bytes_ex(libctx, privkey, KEYLENID(id), 0) <= 0) 205 goto err; 206 if (id == EVP_PKEY_X25519) { 207 privkey[0] &= 248; 208 privkey[X25519_KEYLEN - 1] &= 127; 209 privkey[X25519_KEYLEN - 1] |= 64; 210 } else if (id == EVP_PKEY_X448) { 211 privkey[0] &= 252; 212 privkey[X448_KEYLEN - 1] |= 128; 213 } 214 } 215 } else { 216 memcpy(privkey, p, KEYLENID(id)); 217 } 218 if (!ossl_ecx_public_from_private(key)) { 219 ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY); 220 goto err; 221 } 222 } 223 224 return key; 225 err: 226 ossl_ecx_key_free(key); 227 return NULL; 228} 229 230ECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, 231 OSSL_LIB_CTX *libctx, const char *propq) 232{ 233 ECX_KEY *ecx = NULL; 234 const unsigned char *p; 235 int plen; 236 ASN1_OCTET_STRING *oct = NULL; 237 const X509_ALGOR *palg; 238 239 if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8inf)) 240 return 0; 241 242 oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen); 243 if (oct == NULL) { 244 p = NULL; 245 plen = 0; 246 } else { 247 p = ASN1_STRING_get0_data(oct); 248 plen = ASN1_STRING_length(oct); 249 } 250 251 /* 252 * EVP_PKEY_NONE means that ecx_key_op() has to figure out the key type 253 * on its own. 254 */ 255 ecx = ossl_ecx_key_op(palg, p, plen, EVP_PKEY_NONE, KEY_OP_PRIVATE, 256 libctx, propq); 257 ASN1_OCTET_STRING_free(oct); 258 return ecx; 259} 260#endif 261