1*e05b8d4eStb /* $OpenBSD: pmeth_lib.c,v 1.42 2025/01/20 12:57:28 tb Exp $ */ 2f1535dc8Sdjm /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3f1535dc8Sdjm * project 2006. 4f1535dc8Sdjm */ 5f1535dc8Sdjm /* ==================================================================== 6f1535dc8Sdjm * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7f1535dc8Sdjm * 8f1535dc8Sdjm * Redistribution and use in source and binary forms, with or without 9f1535dc8Sdjm * modification, are permitted provided that the following conditions 10f1535dc8Sdjm * are met: 11f1535dc8Sdjm * 12f1535dc8Sdjm * 1. Redistributions of source code must retain the above copyright 13f1535dc8Sdjm * notice, this list of conditions and the following disclaimer. 14f1535dc8Sdjm * 15f1535dc8Sdjm * 2. Redistributions in binary form must reproduce the above copyright 16f1535dc8Sdjm * notice, this list of conditions and the following disclaimer in 17f1535dc8Sdjm * the documentation and/or other materials provided with the 18f1535dc8Sdjm * distribution. 19f1535dc8Sdjm * 20f1535dc8Sdjm * 3. All advertising materials mentioning features or use of this 21f1535dc8Sdjm * software must display the following acknowledgment: 22f1535dc8Sdjm * "This product includes software developed by the OpenSSL Project 23f1535dc8Sdjm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24f1535dc8Sdjm * 25f1535dc8Sdjm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26f1535dc8Sdjm * endorse or promote products derived from this software without 27f1535dc8Sdjm * prior written permission. For written permission, please contact 28f1535dc8Sdjm * licensing@OpenSSL.org. 29f1535dc8Sdjm * 30f1535dc8Sdjm * 5. Products derived from this software may not be called "OpenSSL" 31f1535dc8Sdjm * nor may "OpenSSL" appear in their names without prior written 32f1535dc8Sdjm * permission of the OpenSSL Project. 33f1535dc8Sdjm * 34f1535dc8Sdjm * 6. Redistributions of any form whatsoever must retain the following 35f1535dc8Sdjm * acknowledgment: 36f1535dc8Sdjm * "This product includes software developed by the OpenSSL Project 37f1535dc8Sdjm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38f1535dc8Sdjm * 39f1535dc8Sdjm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40f1535dc8Sdjm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41f1535dc8Sdjm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42f1535dc8Sdjm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43f1535dc8Sdjm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44f1535dc8Sdjm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45f1535dc8Sdjm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46f1535dc8Sdjm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47f1535dc8Sdjm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48f1535dc8Sdjm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49f1535dc8Sdjm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50f1535dc8Sdjm * OF THE POSSIBILITY OF SUCH DAMAGE. 51f1535dc8Sdjm * ==================================================================== 52f1535dc8Sdjm * 53f1535dc8Sdjm * This product includes cryptographic software written by Eric Young 54f1535dc8Sdjm * (eay@cryptsoft.com). This product includes software written by Tim 55f1535dc8Sdjm * Hudson (tjh@cryptsoft.com). 56f1535dc8Sdjm * 57f1535dc8Sdjm */ 58f1535dc8Sdjm 59e604f303Stb #include <limits.h> 60f1535dc8Sdjm #include <stdio.h> 61f1535dc8Sdjm #include <stdlib.h> 62a8913c44Sjsing #include <string.h> 63a8913c44Sjsing 648cf4d6a6Sjsing #include <openssl/opensslconf.h> 658cf4d6a6Sjsing 66a7b8f3c1Sdoug #include <openssl/err.h> 67f1535dc8Sdjm #include <openssl/evp.h> 68b6ab114eSjsing #include <openssl/objects.h> 69e604f303Stb #include <openssl/x509v3.h> 70b6ab114eSjsing 71c9675a23Stb #include "asn1_local.h" 72c9675a23Stb #include "evp_local.h" 73f1535dc8Sdjm 74343fdb86Sjsing extern const EVP_PKEY_METHOD cmac_pkey_meth; 75343fdb86Sjsing extern const EVP_PKEY_METHOD dh_pkey_meth; 76343fdb86Sjsing extern const EVP_PKEY_METHOD dsa_pkey_meth; 77343fdb86Sjsing extern const EVP_PKEY_METHOD ec_pkey_meth; 78c93606bbSjsing extern const EVP_PKEY_METHOD ed25519_pkey_meth; 79c7411d0fStb extern const EVP_PKEY_METHOD hkdf_pkey_meth; 80343fdb86Sjsing extern const EVP_PKEY_METHOD hmac_pkey_meth; 81343fdb86Sjsing extern const EVP_PKEY_METHOD rsa_pkey_meth; 82343fdb86Sjsing extern const EVP_PKEY_METHOD rsa_pss_pkey_meth; 83baa34b12Stb extern const EVP_PKEY_METHOD tls1_prf_pkey_meth; 84c93606bbSjsing extern const EVP_PKEY_METHOD x25519_pkey_meth; 85f1535dc8Sdjm 86469689ecSjsing static const EVP_PKEY_METHOD *pkey_methods[] = { 8790f161ccSmiod &cmac_pkey_meth, 88469689ecSjsing &dh_pkey_meth, 89469689ecSjsing &dsa_pkey_meth, 90469689ecSjsing &ec_pkey_meth, 91c93606bbSjsing &ed25519_pkey_meth, 92c7411d0fStb &hkdf_pkey_meth, 93469689ecSjsing &hmac_pkey_meth, 94469689ecSjsing &rsa_pkey_meth, 95469689ecSjsing &rsa_pss_pkey_meth, 96baa34b12Stb &tls1_prf_pkey_meth, 97c93606bbSjsing &x25519_pkey_meth, 98f1535dc8Sdjm }; 99f1535dc8Sdjm 10020c8931aStb #define N_PKEY_METHODS (sizeof(pkey_methods) / sizeof(pkey_methods[0])) 101f1535dc8Sdjm 102d4370d4fStb static const EVP_PKEY_METHOD * 103d4370d4fStb evp_pkey_method_find(int nid) 104f1535dc8Sdjm { 10520c8931aStb size_t i; 106f7631d64Sjsing 10720c8931aStb for (i = 0; i < N_PKEY_METHODS; i++) { 10820c8931aStb const EVP_PKEY_METHOD *pmeth = pkey_methods[i]; 109d4370d4fStb if (pmeth->pkey_id == nid) 110469689ecSjsing return pmeth; 111f1535dc8Sdjm } 112469689ecSjsing 113f1535dc8Sdjm return NULL; 114f1535dc8Sdjm } 115f1535dc8Sdjm 116f7631d64Sjsing static EVP_PKEY_CTX * 117d4370d4fStb evp_pkey_ctx_new(EVP_PKEY *pkey, int nid) 118f1535dc8Sdjm { 119d506f566Stb EVP_PKEY_CTX *pkey_ctx = NULL; 120f1535dc8Sdjm const EVP_PKEY_METHOD *pmeth; 121f7631d64Sjsing 122d4370d4fStb if (nid == -1) { 123d506f566Stb if (pkey == NULL || pkey->ameth == NULL) 124f1535dc8Sdjm return NULL; 125d4370d4fStb nid = pkey->ameth->pkey_id; 126f1535dc8Sdjm } 127f1535dc8Sdjm 128d4370d4fStb if ((pmeth = evp_pkey_method_find(nid)) == NULL) { 1295067ae9fSbeck EVPerror(EVP_R_UNSUPPORTED_ALGORITHM); 130d506f566Stb goto err; 131f1535dc8Sdjm } 132f1535dc8Sdjm 133d506f566Stb if ((pkey_ctx = calloc(1, sizeof(*pkey_ctx))) == NULL) { 134d506f566Stb EVPerror(ERR_R_MALLOC_FAILURE); 135d506f566Stb goto err; 136d506f566Stb } 137d506f566Stb pkey_ctx->pmeth = pmeth; 138d506f566Stb pkey_ctx->operation = EVP_PKEY_OP_UNDEFINED; 139d506f566Stb if ((pkey_ctx->pkey = pkey) != NULL) 140d506f566Stb EVP_PKEY_up_ref(pkey_ctx->pkey); 141d506f566Stb 142d506f566Stb if (pmeth->init != NULL) { 143d506f566Stb if (pmeth->init(pkey_ctx) <= 0) 144d506f566Stb goto err; 145d506f566Stb } 146d506f566Stb 147d506f566Stb return pkey_ctx; 148d506f566Stb 149d506f566Stb err: 150d506f566Stb EVP_PKEY_CTX_free(pkey_ctx); 151f1535dc8Sdjm 152f1535dc8Sdjm return NULL; 153f1535dc8Sdjm } 154f1535dc8Sdjm 155f7631d64Sjsing EVP_PKEY_CTX * 1568b753e6bStb EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *engine) 157f1535dc8Sdjm { 158592331b2Stb return evp_pkey_ctx_new(pkey, -1); 159f1535dc8Sdjm } 1609bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_new); 161f1535dc8Sdjm 162f7631d64Sjsing EVP_PKEY_CTX * 163d4370d4fStb EVP_PKEY_CTX_new_id(int nid, ENGINE *engine) 164f1535dc8Sdjm { 165d4370d4fStb return evp_pkey_ctx_new(NULL, nid); 166f1535dc8Sdjm } 1679bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_new_id); 168f1535dc8Sdjm 169f7631d64Sjsing EVP_PKEY_CTX * 170f7631d64Sjsing EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) 171f1535dc8Sdjm { 172451a4610Stb EVP_PKEY_CTX *rctx = NULL; 173f7631d64Sjsing 174451a4610Stb if (pctx->pmeth == NULL || pctx->pmeth->copy == NULL) 175451a4610Stb goto err; 176451a4610Stb if ((rctx = calloc(1, sizeof(*rctx))) == NULL) { 177451a4610Stb EVPerror(ERR_R_MALLOC_FAILURE); 178451a4610Stb goto err; 179451a4610Stb } 180f1535dc8Sdjm 181f1535dc8Sdjm rctx->pmeth = pctx->pmeth; 182f1535dc8Sdjm 183451a4610Stb if ((rctx->pkey = pctx->pkey) != NULL) 184451a4610Stb EVP_PKEY_up_ref(rctx->pkey); 185451a4610Stb if ((rctx->peerkey = pctx->peerkey) != NULL) 186451a4610Stb EVP_PKEY_up_ref(rctx->peerkey); 187f1535dc8Sdjm 188f1535dc8Sdjm rctx->operation = pctx->operation; 189f1535dc8Sdjm 190451a4610Stb if (pctx->pmeth->copy(rctx, pctx) <= 0) 191451a4610Stb goto err; 192451a4610Stb 193f1535dc8Sdjm return rctx; 194f1535dc8Sdjm 195451a4610Stb err: 196f1535dc8Sdjm EVP_PKEY_CTX_free(rctx); 197f1535dc8Sdjm return NULL; 198f1535dc8Sdjm } 1999bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_dup); 200f1535dc8Sdjm 201f7631d64Sjsing void 202f7631d64Sjsing EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) 203f1535dc8Sdjm { 204f1535dc8Sdjm if (ctx == NULL) 205f1535dc8Sdjm return; 206f1535dc8Sdjm if (ctx->pmeth && ctx->pmeth->cleanup) 207f1535dc8Sdjm ctx->pmeth->cleanup(ctx); 208f1535dc8Sdjm EVP_PKEY_free(ctx->pkey); 209f1535dc8Sdjm EVP_PKEY_free(ctx->peerkey); 2106f3a6cb1Sbeck free(ctx); 211f1535dc8Sdjm } 2129bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_free); 213f1535dc8Sdjm 214f7631d64Sjsing int 215f7631d64Sjsing EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, 216f7631d64Sjsing int p1, void *p2) 217f1535dc8Sdjm { 218f1535dc8Sdjm int ret; 219f7631d64Sjsing 220f7631d64Sjsing if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) { 2215067ae9fSbeck EVPerror(EVP_R_COMMAND_NOT_SUPPORTED); 222f1535dc8Sdjm return -2; 223f1535dc8Sdjm } 224f1535dc8Sdjm if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype)) 225f1535dc8Sdjm return -1; 226f1535dc8Sdjm 227f7631d64Sjsing if (ctx->operation == EVP_PKEY_OP_UNDEFINED) { 2285067ae9fSbeck EVPerror(EVP_R_NO_OPERATION_SET); 229f1535dc8Sdjm return -1; 230f1535dc8Sdjm } 231f1535dc8Sdjm 232f7631d64Sjsing if ((optype != -1) && !(ctx->operation & optype)) { 2335067ae9fSbeck EVPerror(EVP_R_INVALID_OPERATION); 234f1535dc8Sdjm return -1; 235f1535dc8Sdjm } 236f1535dc8Sdjm 237f1535dc8Sdjm ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2); 238f1535dc8Sdjm 239f1535dc8Sdjm if (ret == -2) 2405067ae9fSbeck EVPerror(EVP_R_COMMAND_NOT_SUPPORTED); 241f1535dc8Sdjm 242f1535dc8Sdjm return ret; 243f1535dc8Sdjm 244f1535dc8Sdjm } 2459bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_ctrl); 246f1535dc8Sdjm 247*e05b8d4eStb /* 248*e05b8d4eStb * This is practically unused and would best be a part of the openssl(1) code, 249*e05b8d4eStb * but, unfortunately, openssl-ruby exposes this directly in an interface and 250*e05b8d4eStb * it's currently the only way to do RSA-PSS in Ruby. 251*e05b8d4eStb */ 252f7631d64Sjsing int 253f7631d64Sjsing EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *name, const char *value) 254f1535dc8Sdjm { 255f7631d64Sjsing if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) { 2565067ae9fSbeck EVPerror(EVP_R_COMMAND_NOT_SUPPORTED); 257f1535dc8Sdjm return -2; 258f1535dc8Sdjm } 259f7631d64Sjsing if (!strcmp(name, "digest")) { 26026d13399Sjsing return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_SIG, 26126d13399Sjsing EVP_PKEY_CTRL_MD, value); 26226d13399Sjsing } 26326d13399Sjsing return ctx->pmeth->ctrl_str(ctx, name, value); 26426d13399Sjsing } 2659bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_ctrl_str); 26626d13399Sjsing 26726d13399Sjsing int 268e604f303Stb EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str) 269e604f303Stb { 270e604f303Stb size_t len; 271e604f303Stb 272e604f303Stb if ((len = strlen(str)) > INT_MAX) 273e604f303Stb return -1; 274e604f303Stb 275e604f303Stb return ctx->pmeth->ctrl(ctx, cmd, len, (void *)str); 276e604f303Stb } 277e604f303Stb 278e604f303Stb int 279e604f303Stb EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hexstr) 280e604f303Stb { 281e604f303Stb unsigned char *hex = NULL; 282e604f303Stb long length; 283e604f303Stb int ret = 0; 284e604f303Stb 285e604f303Stb if ((hex = string_to_hex(hexstr, &length)) == NULL) 286e604f303Stb goto err; 287e604f303Stb if (length < 0 || length > INT_MAX) { 288e604f303Stb ret = -1; 289e604f303Stb goto err; 290e604f303Stb } 291e604f303Stb 292e604f303Stb ret = ctx->pmeth->ctrl(ctx, cmd, length, hex); 293e604f303Stb 294e604f303Stb err: 295e604f303Stb free(hex); 296e604f303Stb return ret; 297e604f303Stb } 298e604f303Stb 299e604f303Stb int 30026d13399Sjsing EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md_name) 30126d13399Sjsing { 302f1535dc8Sdjm const EVP_MD *md; 30326d13399Sjsing 30426d13399Sjsing if ((md = EVP_get_digestbyname(md_name)) == NULL) { 3055067ae9fSbeck EVPerror(EVP_R_INVALID_DIGEST); 306f1535dc8Sdjm return 0; 307f1535dc8Sdjm } 30826d13399Sjsing return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, 0, (void *)md); 309f1535dc8Sdjm } 310f1535dc8Sdjm 311f7631d64Sjsing int 312f7631d64Sjsing EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx) 313f1535dc8Sdjm { 314f1535dc8Sdjm return ctx->operation; 315f1535dc8Sdjm } 3169bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_get_operation); 317f1535dc8Sdjm 318f7631d64Sjsing void 319f7631d64Sjsing EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen) 320f1535dc8Sdjm { 321f1535dc8Sdjm ctx->keygen_info = dat; 322f1535dc8Sdjm ctx->keygen_info_count = datlen; 323f1535dc8Sdjm } 3249bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_set0_keygen_info); 325f1535dc8Sdjm 326f7631d64Sjsing void 327f7631d64Sjsing EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data) 328f1535dc8Sdjm { 329f1535dc8Sdjm ctx->data = data; 330f1535dc8Sdjm } 3319bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_set_data); 332f1535dc8Sdjm 333f7631d64Sjsing void * 334f7631d64Sjsing EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx) 335f1535dc8Sdjm { 336f1535dc8Sdjm return ctx->data; 337f1535dc8Sdjm } 3389bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_get_data); 339f1535dc8Sdjm 340f7631d64Sjsing EVP_PKEY * 341f7631d64Sjsing EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) 342f1535dc8Sdjm { 343f1535dc8Sdjm return ctx->pkey; 344f1535dc8Sdjm } 3459bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_get0_pkey); 346f1535dc8Sdjm 347f7631d64Sjsing EVP_PKEY * 348f7631d64Sjsing EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx) 349f1535dc8Sdjm { 350f1535dc8Sdjm return ctx->peerkey; 351f1535dc8Sdjm } 3529bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_get0_peerkey); 353f1535dc8Sdjm 354f7631d64Sjsing void 355f7631d64Sjsing EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data) 356f1535dc8Sdjm { 357f1535dc8Sdjm ctx->app_data = data; 358f1535dc8Sdjm } 3599bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_set_app_data); 360f1535dc8Sdjm 361f7631d64Sjsing void * 362f7631d64Sjsing EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx) 363f1535dc8Sdjm { 364f1535dc8Sdjm return ctx->app_data; 365f1535dc8Sdjm } 3669bac3682Sbeck LCRYPTO_ALIAS(EVP_PKEY_CTX_get_app_data); 367