1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <string.h> 11e1051a39Sopenharmony_ci#include <openssl/core_names.h> 12e1051a39Sopenharmony_ci#include <openssl/params.h> 13e1051a39Sopenharmony_ci#include <openssl/ec.h> 14e1051a39Sopenharmony_ci#include <openssl/rand.h> 15e1051a39Sopenharmony_ci#include <openssl/err.h> 16e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 17e1051a39Sopenharmony_ci# include <openssl/x509.h> 18e1051a39Sopenharmony_ci#endif 19e1051a39Sopenharmony_ci#include "crypto/ecx.h" 20e1051a39Sopenharmony_ci#include "ecx_backend.h" 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ci/* 23e1051a39Sopenharmony_ci * The intention with the "backend" source file is to offer backend support 24e1051a39Sopenharmony_ci * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider 25e1051a39Sopenharmony_ci * implementations alike. 26e1051a39Sopenharmony_ci */ 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_ciint ossl_ecx_public_from_private(ECX_KEY *key) 29e1051a39Sopenharmony_ci{ 30e1051a39Sopenharmony_ci switch (key->type) { 31e1051a39Sopenharmony_ci case ECX_KEY_TYPE_X25519: 32e1051a39Sopenharmony_ci ossl_x25519_public_from_private(key->pubkey, key->privkey); 33e1051a39Sopenharmony_ci break; 34e1051a39Sopenharmony_ci case ECX_KEY_TYPE_ED25519: 35e1051a39Sopenharmony_ci if (!ossl_ed25519_public_from_private(key->libctx, key->pubkey, 36e1051a39Sopenharmony_ci key->privkey, key->propq)) { 37e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY); 38e1051a39Sopenharmony_ci return 0; 39e1051a39Sopenharmony_ci } 40e1051a39Sopenharmony_ci break; 41e1051a39Sopenharmony_ci case ECX_KEY_TYPE_X448: 42e1051a39Sopenharmony_ci ossl_x448_public_from_private(key->pubkey, key->privkey); 43e1051a39Sopenharmony_ci break; 44e1051a39Sopenharmony_ci case ECX_KEY_TYPE_ED448: 45e1051a39Sopenharmony_ci if (!ossl_ed448_public_from_private(key->libctx, key->pubkey, 46e1051a39Sopenharmony_ci key->privkey, key->propq)) { 47e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY); 48e1051a39Sopenharmony_ci return 0; 49e1051a39Sopenharmony_ci } 50e1051a39Sopenharmony_ci break; 51e1051a39Sopenharmony_ci } 52e1051a39Sopenharmony_ci return 1; 53e1051a39Sopenharmony_ci} 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_ciint ossl_ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[], 56e1051a39Sopenharmony_ci int include_private) 57e1051a39Sopenharmony_ci{ 58e1051a39Sopenharmony_ci size_t privkeylen = 0, pubkeylen = 0; 59e1051a39Sopenharmony_ci const OSSL_PARAM *param_priv_key = NULL, *param_pub_key; 60e1051a39Sopenharmony_ci unsigned char *pubkey; 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci if (ecx == NULL) 63e1051a39Sopenharmony_ci return 0; 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_ci param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); 66e1051a39Sopenharmony_ci if (include_private) 67e1051a39Sopenharmony_ci param_priv_key = 68e1051a39Sopenharmony_ci OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ci if (param_pub_key == NULL && param_priv_key == NULL) 71e1051a39Sopenharmony_ci return 0; 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci if (param_priv_key != NULL) { 74e1051a39Sopenharmony_ci if (!OSSL_PARAM_get_octet_string(param_priv_key, 75e1051a39Sopenharmony_ci (void **)&ecx->privkey, ecx->keylen, 76e1051a39Sopenharmony_ci &privkeylen)) 77e1051a39Sopenharmony_ci return 0; 78e1051a39Sopenharmony_ci if (privkeylen != ecx->keylen) { 79e1051a39Sopenharmony_ci /* 80e1051a39Sopenharmony_ci * Invalid key length. We will clear what we've received now. We 81e1051a39Sopenharmony_ci * can't leave it to ossl_ecx_key_free() because that will call 82e1051a39Sopenharmony_ci * OPENSSL_secure_clear_free() and assume the correct key length 83e1051a39Sopenharmony_ci */ 84e1051a39Sopenharmony_ci OPENSSL_secure_clear_free(ecx->privkey, privkeylen); 85e1051a39Sopenharmony_ci ecx->privkey = NULL; 86e1051a39Sopenharmony_ci return 0; 87e1051a39Sopenharmony_ci } 88e1051a39Sopenharmony_ci } 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci pubkey = ecx->pubkey; 92e1051a39Sopenharmony_ci if (param_pub_key != NULL 93e1051a39Sopenharmony_ci && !OSSL_PARAM_get_octet_string(param_pub_key, 94e1051a39Sopenharmony_ci (void **)&pubkey, 95e1051a39Sopenharmony_ci sizeof(ecx->pubkey), &pubkeylen)) 96e1051a39Sopenharmony_ci return 0; 97e1051a39Sopenharmony_ci 98e1051a39Sopenharmony_ci if ((param_pub_key != NULL && pubkeylen != ecx->keylen)) 99e1051a39Sopenharmony_ci return 0; 100e1051a39Sopenharmony_ci 101e1051a39Sopenharmony_ci if (param_pub_key == NULL && !ossl_ecx_public_from_private(ecx)) 102e1051a39Sopenharmony_ci return 0; 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_ci ecx->haspubkey = 1; 105e1051a39Sopenharmony_ci 106e1051a39Sopenharmony_ci return 1; 107e1051a39Sopenharmony_ci} 108e1051a39Sopenharmony_ci 109e1051a39Sopenharmony_ciECX_KEY *ossl_ecx_key_dup(const ECX_KEY *key, int selection) 110e1051a39Sopenharmony_ci{ 111e1051a39Sopenharmony_ci ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret)); 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_ci if (ret == NULL) { 114e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 115e1051a39Sopenharmony_ci return NULL; 116e1051a39Sopenharmony_ci } 117e1051a39Sopenharmony_ci 118e1051a39Sopenharmony_ci ret->lock = CRYPTO_THREAD_lock_new(); 119e1051a39Sopenharmony_ci if (ret->lock == NULL) { 120e1051a39Sopenharmony_ci OPENSSL_free(ret); 121e1051a39Sopenharmony_ci return NULL; 122e1051a39Sopenharmony_ci } 123e1051a39Sopenharmony_ci 124e1051a39Sopenharmony_ci ret->libctx = key->libctx; 125e1051a39Sopenharmony_ci ret->haspubkey = key->haspubkey; 126e1051a39Sopenharmony_ci ret->keylen = key->keylen; 127e1051a39Sopenharmony_ci ret->type = key->type; 128e1051a39Sopenharmony_ci ret->references = 1; 129e1051a39Sopenharmony_ci 130e1051a39Sopenharmony_ci if (key->propq != NULL) { 131e1051a39Sopenharmony_ci ret->propq = OPENSSL_strdup(key->propq); 132e1051a39Sopenharmony_ci if (ret->propq == NULL) 133e1051a39Sopenharmony_ci goto err; 134e1051a39Sopenharmony_ci } 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) 137e1051a39Sopenharmony_ci memcpy(ret->pubkey, key->pubkey, sizeof(ret->pubkey)); 138e1051a39Sopenharmony_ci 139e1051a39Sopenharmony_ci if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0 140e1051a39Sopenharmony_ci && key->privkey != NULL) { 141e1051a39Sopenharmony_ci if (ossl_ecx_key_allocate_privkey(ret) == NULL) 142e1051a39Sopenharmony_ci goto err; 143e1051a39Sopenharmony_ci memcpy(ret->privkey, key->privkey, ret->keylen); 144e1051a39Sopenharmony_ci } 145e1051a39Sopenharmony_ci 146e1051a39Sopenharmony_ci return ret; 147e1051a39Sopenharmony_ci 148e1051a39Sopenharmony_cierr: 149e1051a39Sopenharmony_ci ossl_ecx_key_free(ret); 150e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 151e1051a39Sopenharmony_ci return NULL; 152e1051a39Sopenharmony_ci} 153e1051a39Sopenharmony_ci 154e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 155e1051a39Sopenharmony_ciECX_KEY *ossl_ecx_key_op(const X509_ALGOR *palg, 156e1051a39Sopenharmony_ci const unsigned char *p, int plen, 157e1051a39Sopenharmony_ci int id, ecx_key_op_t op, 158e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 159e1051a39Sopenharmony_ci{ 160e1051a39Sopenharmony_ci ECX_KEY *key = NULL; 161e1051a39Sopenharmony_ci unsigned char *privkey, *pubkey; 162e1051a39Sopenharmony_ci 163e1051a39Sopenharmony_ci if (op != KEY_OP_KEYGEN) { 164e1051a39Sopenharmony_ci if (palg != NULL) { 165e1051a39Sopenharmony_ci int ptype; 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_ci /* Algorithm parameters must be absent */ 168e1051a39Sopenharmony_ci X509_ALGOR_get0(NULL, &ptype, NULL, palg); 169e1051a39Sopenharmony_ci if (ptype != V_ASN1_UNDEF) { 170e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 171e1051a39Sopenharmony_ci return 0; 172e1051a39Sopenharmony_ci } 173e1051a39Sopenharmony_ci if (id == EVP_PKEY_NONE) 174e1051a39Sopenharmony_ci id = OBJ_obj2nid(palg->algorithm); 175e1051a39Sopenharmony_ci else if (id != OBJ_obj2nid(palg->algorithm)) { 176e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 177e1051a39Sopenharmony_ci return 0; 178e1051a39Sopenharmony_ci } 179e1051a39Sopenharmony_ci } 180e1051a39Sopenharmony_ci 181e1051a39Sopenharmony_ci if (p == NULL || id == EVP_PKEY_NONE || plen != KEYLENID(id)) { 182e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING); 183e1051a39Sopenharmony_ci return 0; 184e1051a39Sopenharmony_ci } 185e1051a39Sopenharmony_ci } 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_ci key = ossl_ecx_key_new(libctx, KEYNID2TYPE(id), 1, propq); 188e1051a39Sopenharmony_ci if (key == NULL) { 189e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 190e1051a39Sopenharmony_ci return 0; 191e1051a39Sopenharmony_ci } 192e1051a39Sopenharmony_ci pubkey = key->pubkey; 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_ci if (op == KEY_OP_PUBLIC) { 195e1051a39Sopenharmony_ci memcpy(pubkey, p, plen); 196e1051a39Sopenharmony_ci } else { 197e1051a39Sopenharmony_ci privkey = ossl_ecx_key_allocate_privkey(key); 198e1051a39Sopenharmony_ci if (privkey == NULL) { 199e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); 200e1051a39Sopenharmony_ci goto err; 201e1051a39Sopenharmony_ci } 202e1051a39Sopenharmony_ci if (op == KEY_OP_KEYGEN) { 203e1051a39Sopenharmony_ci if (id != EVP_PKEY_NONE) { 204e1051a39Sopenharmony_ci if (RAND_priv_bytes_ex(libctx, privkey, KEYLENID(id), 0) <= 0) 205e1051a39Sopenharmony_ci goto err; 206e1051a39Sopenharmony_ci if (id == EVP_PKEY_X25519) { 207e1051a39Sopenharmony_ci privkey[0] &= 248; 208e1051a39Sopenharmony_ci privkey[X25519_KEYLEN - 1] &= 127; 209e1051a39Sopenharmony_ci privkey[X25519_KEYLEN - 1] |= 64; 210e1051a39Sopenharmony_ci } else if (id == EVP_PKEY_X448) { 211e1051a39Sopenharmony_ci privkey[0] &= 252; 212e1051a39Sopenharmony_ci privkey[X448_KEYLEN - 1] |= 128; 213e1051a39Sopenharmony_ci } 214e1051a39Sopenharmony_ci } 215e1051a39Sopenharmony_ci } else { 216e1051a39Sopenharmony_ci memcpy(privkey, p, KEYLENID(id)); 217e1051a39Sopenharmony_ci } 218e1051a39Sopenharmony_ci if (!ossl_ecx_public_from_private(key)) { 219e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EC, EC_R_FAILED_MAKING_PUBLIC_KEY); 220e1051a39Sopenharmony_ci goto err; 221e1051a39Sopenharmony_ci } 222e1051a39Sopenharmony_ci } 223e1051a39Sopenharmony_ci 224e1051a39Sopenharmony_ci return key; 225e1051a39Sopenharmony_ci err: 226e1051a39Sopenharmony_ci ossl_ecx_key_free(key); 227e1051a39Sopenharmony_ci return NULL; 228e1051a39Sopenharmony_ci} 229e1051a39Sopenharmony_ci 230e1051a39Sopenharmony_ciECX_KEY *ossl_ecx_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf, 231e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx, const char *propq) 232e1051a39Sopenharmony_ci{ 233e1051a39Sopenharmony_ci ECX_KEY *ecx = NULL; 234e1051a39Sopenharmony_ci const unsigned char *p; 235e1051a39Sopenharmony_ci int plen; 236e1051a39Sopenharmony_ci ASN1_OCTET_STRING *oct = NULL; 237e1051a39Sopenharmony_ci const X509_ALGOR *palg; 238e1051a39Sopenharmony_ci 239e1051a39Sopenharmony_ci if (!PKCS8_pkey_get0(NULL, &p, &plen, &palg, p8inf)) 240e1051a39Sopenharmony_ci return 0; 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ci oct = d2i_ASN1_OCTET_STRING(NULL, &p, plen); 243e1051a39Sopenharmony_ci if (oct == NULL) { 244e1051a39Sopenharmony_ci p = NULL; 245e1051a39Sopenharmony_ci plen = 0; 246e1051a39Sopenharmony_ci } else { 247e1051a39Sopenharmony_ci p = ASN1_STRING_get0_data(oct); 248e1051a39Sopenharmony_ci plen = ASN1_STRING_length(oct); 249e1051a39Sopenharmony_ci } 250e1051a39Sopenharmony_ci 251e1051a39Sopenharmony_ci /* 252e1051a39Sopenharmony_ci * EVP_PKEY_NONE means that ecx_key_op() has to figure out the key type 253e1051a39Sopenharmony_ci * on its own. 254e1051a39Sopenharmony_ci */ 255e1051a39Sopenharmony_ci ecx = ossl_ecx_key_op(palg, p, plen, EVP_PKEY_NONE, KEY_OP_PRIVATE, 256e1051a39Sopenharmony_ci libctx, propq); 257e1051a39Sopenharmony_ci ASN1_OCTET_STRING_free(oct); 258e1051a39Sopenharmony_ci return ecx; 259e1051a39Sopenharmony_ci} 260e1051a39Sopenharmony_ci#endif 261