1238384Sjkim/* pmeth_fn.c */ 2238384Sjkim/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3238384Sjkim * project 2006. 4238384Sjkim */ 5238384Sjkim/* ==================================================================== 6238384Sjkim * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7238384Sjkim * 8238384Sjkim * Redistribution and use in source and binary forms, with or without 9238384Sjkim * modification, are permitted provided that the following conditions 10238384Sjkim * are met: 11238384Sjkim * 12238384Sjkim * 1. Redistributions of source code must retain the above copyright 13238384Sjkim * notice, this list of conditions and the following disclaimer. 14238384Sjkim * 15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 16238384Sjkim * notice, this list of conditions and the following disclaimer in 17238384Sjkim * the documentation and/or other materials provided with the 18238384Sjkim * distribution. 19238384Sjkim * 20238384Sjkim * 3. All advertising materials mentioning features or use of this 21238384Sjkim * software must display the following acknowledgment: 22238384Sjkim * "This product includes software developed by the OpenSSL Project 23238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24238384Sjkim * 25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26238384Sjkim * endorse or promote products derived from this software without 27238384Sjkim * prior written permission. For written permission, please contact 28238384Sjkim * licensing@OpenSSL.org. 29238384Sjkim * 30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 31238384Sjkim * nor may "OpenSSL" appear in their names without prior written 32238384Sjkim * permission of the OpenSSL Project. 33238384Sjkim * 34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 35238384Sjkim * acknowledgment: 36238384Sjkim * "This product includes software developed by the OpenSSL Project 37238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38238384Sjkim * 39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 51238384Sjkim * ==================================================================== 52238384Sjkim * 53238384Sjkim * This product includes cryptographic software written by Eric Young 54238384Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 55238384Sjkim * Hudson (tjh@cryptsoft.com). 56238384Sjkim * 57238384Sjkim */ 58238384Sjkim 59238384Sjkim#include <stdio.h> 60238384Sjkim#include <stdlib.h> 61238384Sjkim#include "cryptlib.h" 62238384Sjkim#include <openssl/objects.h> 63238384Sjkim#include <openssl/evp.h> 64238384Sjkim#include "evp_locl.h" 65238384Sjkim 66238384Sjkim#define M_check_autoarg(ctx, arg, arglen, err) \ 67238384Sjkim if (ctx->pmeth->flags & EVP_PKEY_FLAG_AUTOARGLEN) \ 68238384Sjkim { \ 69238384Sjkim size_t pksize = (size_t)EVP_PKEY_size(ctx->pkey); \ 70238384Sjkim if (!arg) \ 71238384Sjkim { \ 72238384Sjkim *arglen = pksize; \ 73238384Sjkim return 1; \ 74238384Sjkim } \ 75238384Sjkim else if (*arglen < pksize) \ 76238384Sjkim { \ 77238384Sjkim EVPerr(err, EVP_R_BUFFER_TOO_SMALL); /*ckerr_ignore*/\ 78238384Sjkim return 0; \ 79238384Sjkim } \ 80238384Sjkim } 81238384Sjkim 82238384Sjkimint EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) 83238384Sjkim { 84238384Sjkim int ret; 85238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) 86238384Sjkim { 87238384Sjkim EVPerr(EVP_F_EVP_PKEY_SIGN_INIT, 88238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 89238384Sjkim return -2; 90238384Sjkim } 91238384Sjkim ctx->operation = EVP_PKEY_OP_SIGN; 92238384Sjkim if (!ctx->pmeth->sign_init) 93238384Sjkim return 1; 94238384Sjkim ret = ctx->pmeth->sign_init(ctx); 95238384Sjkim if (ret <= 0) 96238384Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 97238384Sjkim return ret; 98238384Sjkim } 99238384Sjkim 100238384Sjkimint EVP_PKEY_sign(EVP_PKEY_CTX *ctx, 101238384Sjkim unsigned char *sig, size_t *siglen, 102238384Sjkim const unsigned char *tbs, size_t tbslen) 103238384Sjkim { 104238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) 105238384Sjkim { 106238384Sjkim EVPerr(EVP_F_EVP_PKEY_SIGN, 107238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 108238384Sjkim return -2; 109238384Sjkim } 110238384Sjkim if (ctx->operation != EVP_PKEY_OP_SIGN) 111238384Sjkim { 112238384Sjkim EVPerr(EVP_F_EVP_PKEY_SIGN, EVP_R_OPERATON_NOT_INITIALIZED); 113238384Sjkim return -1; 114238384Sjkim } 115238384Sjkim M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN) 116238384Sjkim return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen); 117238384Sjkim } 118238384Sjkim 119238384Sjkimint EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) 120238384Sjkim { 121238384Sjkim int ret; 122238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) 123238384Sjkim { 124238384Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY_INIT, 125238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 126238384Sjkim return -2; 127238384Sjkim } 128238384Sjkim ctx->operation = EVP_PKEY_OP_VERIFY; 129238384Sjkim if (!ctx->pmeth->verify_init) 130238384Sjkim return 1; 131238384Sjkim ret = ctx->pmeth->verify_init(ctx); 132238384Sjkim if (ret <= 0) 133238384Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 134238384Sjkim return ret; 135238384Sjkim } 136238384Sjkim 137238384Sjkimint EVP_PKEY_verify(EVP_PKEY_CTX *ctx, 138238384Sjkim const unsigned char *sig, size_t siglen, 139238384Sjkim const unsigned char *tbs, size_t tbslen) 140238384Sjkim { 141238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) 142238384Sjkim { 143238384Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY, 144238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 145238384Sjkim return -2; 146238384Sjkim } 147238384Sjkim if (ctx->operation != EVP_PKEY_OP_VERIFY) 148238384Sjkim { 149238384Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY, EVP_R_OPERATON_NOT_INITIALIZED); 150238384Sjkim return -1; 151238384Sjkim } 152238384Sjkim return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen); 153238384Sjkim } 154238384Sjkim 155238384Sjkimint EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) 156238384Sjkim { 157238384Sjkim int ret; 158238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) 159238384Sjkim { 160238384Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT, 161238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 162238384Sjkim return -2; 163238384Sjkim } 164238384Sjkim ctx->operation = EVP_PKEY_OP_VERIFYRECOVER; 165238384Sjkim if (!ctx->pmeth->verify_recover_init) 166238384Sjkim return 1; 167238384Sjkim ret = ctx->pmeth->verify_recover_init(ctx); 168238384Sjkim if (ret <= 0) 169238384Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 170238384Sjkim return ret; 171238384Sjkim } 172238384Sjkim 173238384Sjkimint EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, 174238384Sjkim unsigned char *rout, size_t *routlen, 175238384Sjkim const unsigned char *sig, size_t siglen) 176238384Sjkim { 177238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) 178238384Sjkim { 179238384Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER, 180238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 181238384Sjkim return -2; 182238384Sjkim } 183238384Sjkim if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) 184238384Sjkim { 185238384Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER, EVP_R_OPERATON_NOT_INITIALIZED); 186238384Sjkim return -1; 187238384Sjkim } 188238384Sjkim M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER) 189238384Sjkim return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen); 190238384Sjkim } 191238384Sjkim 192238384Sjkimint EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) 193238384Sjkim { 194238384Sjkim int ret; 195238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) 196238384Sjkim { 197238384Sjkim EVPerr(EVP_F_EVP_PKEY_ENCRYPT_INIT, 198238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 199238384Sjkim return -2; 200238384Sjkim } 201238384Sjkim ctx->operation = EVP_PKEY_OP_ENCRYPT; 202238384Sjkim if (!ctx->pmeth->encrypt_init) 203238384Sjkim return 1; 204238384Sjkim ret = ctx->pmeth->encrypt_init(ctx); 205238384Sjkim if (ret <= 0) 206238384Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 207238384Sjkim return ret; 208238384Sjkim } 209238384Sjkim 210238384Sjkimint EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, 211238384Sjkim unsigned char *out, size_t *outlen, 212238384Sjkim const unsigned char *in, size_t inlen) 213238384Sjkim { 214238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) 215238384Sjkim { 216238384Sjkim EVPerr(EVP_F_EVP_PKEY_ENCRYPT, 217238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 218238384Sjkim return -2; 219238384Sjkim } 220238384Sjkim if (ctx->operation != EVP_PKEY_OP_ENCRYPT) 221238384Sjkim { 222238384Sjkim EVPerr(EVP_F_EVP_PKEY_ENCRYPT, EVP_R_OPERATON_NOT_INITIALIZED); 223238384Sjkim return -1; 224238384Sjkim } 225238384Sjkim M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT) 226238384Sjkim return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen); 227238384Sjkim } 228238384Sjkim 229238384Sjkimint EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx) 230238384Sjkim { 231238384Sjkim int ret; 232238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) 233238384Sjkim { 234238384Sjkim EVPerr(EVP_F_EVP_PKEY_DECRYPT_INIT, 235238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 236238384Sjkim return -2; 237238384Sjkim } 238238384Sjkim ctx->operation = EVP_PKEY_OP_DECRYPT; 239238384Sjkim if (!ctx->pmeth->decrypt_init) 240238384Sjkim return 1; 241238384Sjkim ret = ctx->pmeth->decrypt_init(ctx); 242238384Sjkim if (ret <= 0) 243238384Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 244238384Sjkim return ret; 245238384Sjkim } 246238384Sjkim 247238384Sjkimint EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, 248238384Sjkim unsigned char *out, size_t *outlen, 249238384Sjkim const unsigned char *in, size_t inlen) 250238384Sjkim { 251238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) 252238384Sjkim { 253238384Sjkim EVPerr(EVP_F_EVP_PKEY_DECRYPT, 254238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 255238384Sjkim return -2; 256238384Sjkim } 257238384Sjkim if (ctx->operation != EVP_PKEY_OP_DECRYPT) 258238384Sjkim { 259238384Sjkim EVPerr(EVP_F_EVP_PKEY_DECRYPT, EVP_R_OPERATON_NOT_INITIALIZED); 260238384Sjkim return -1; 261238384Sjkim } 262238384Sjkim M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT) 263238384Sjkim return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen); 264238384Sjkim } 265238384Sjkim 266238384Sjkim 267238384Sjkimint EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) 268238384Sjkim { 269238384Sjkim int ret; 270238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) 271238384Sjkim { 272238384Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT, 273238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 274238384Sjkim return -2; 275238384Sjkim } 276238384Sjkim ctx->operation = EVP_PKEY_OP_DERIVE; 277238384Sjkim if (!ctx->pmeth->derive_init) 278238384Sjkim return 1; 279238384Sjkim ret = ctx->pmeth->derive_init(ctx); 280238384Sjkim if (ret <= 0) 281238384Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 282238384Sjkim return ret; 283238384Sjkim } 284238384Sjkim 285238384Sjkimint EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) 286238384Sjkim { 287238384Sjkim int ret; 288238384Sjkim if (!ctx || !ctx->pmeth || !(ctx->pmeth->derive||ctx->pmeth->encrypt||ctx->pmeth->decrypt) || !ctx->pmeth->ctrl) 289238384Sjkim { 290238384Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, 291238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 292238384Sjkim return -2; 293238384Sjkim } 294238384Sjkim if (ctx->operation != EVP_PKEY_OP_DERIVE && ctx->operation != EVP_PKEY_OP_ENCRYPT && ctx->operation != EVP_PKEY_OP_DECRYPT) 295238384Sjkim { 296238384Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, 297238384Sjkim EVP_R_OPERATON_NOT_INITIALIZED); 298238384Sjkim return -1; 299238384Sjkim } 300238384Sjkim 301238384Sjkim ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer); 302238384Sjkim 303238384Sjkim if (ret <= 0) 304238384Sjkim return ret; 305238384Sjkim 306238384Sjkim if (ret == 2) 307238384Sjkim return 1; 308238384Sjkim 309238384Sjkim if (!ctx->pkey) 310238384Sjkim { 311238384Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET); 312238384Sjkim return -1; 313238384Sjkim } 314238384Sjkim 315238384Sjkim if (ctx->pkey->type != peer->type) 316238384Sjkim { 317238384Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, 318238384Sjkim EVP_R_DIFFERENT_KEY_TYPES); 319238384Sjkim return -1; 320238384Sjkim } 321238384Sjkim 322238384Sjkim /* ran@cryptocom.ru: For clarity. The error is if parameters in peer are 323238384Sjkim * present (!missing) but don't match. EVP_PKEY_cmp_parameters may return 324238384Sjkim * 1 (match), 0 (don't match) and -2 (comparison is not defined). -1 325238384Sjkim * (different key types) is impossible here because it is checked earlier. 326238384Sjkim * -2 is OK for us here, as well as 1, so we can check for 0 only. */ 327238384Sjkim if (!EVP_PKEY_missing_parameters(peer) && 328238384Sjkim !EVP_PKEY_cmp_parameters(ctx->pkey, peer)) 329238384Sjkim { 330238384Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, 331238384Sjkim EVP_R_DIFFERENT_PARAMETERS); 332238384Sjkim return -1; 333238384Sjkim } 334238384Sjkim 335238384Sjkim if (ctx->peerkey) 336238384Sjkim EVP_PKEY_free(ctx->peerkey); 337238384Sjkim ctx->peerkey = peer; 338238384Sjkim 339238384Sjkim ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer); 340238384Sjkim 341238384Sjkim if (ret <= 0) 342238384Sjkim { 343238384Sjkim ctx->peerkey = NULL; 344238384Sjkim return ret; 345238384Sjkim } 346238384Sjkim 347238384Sjkim CRYPTO_add(&peer->references,1,CRYPTO_LOCK_EVP_PKEY); 348238384Sjkim return 1; 349238384Sjkim } 350238384Sjkim 351238384Sjkim 352238384Sjkimint EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen) 353238384Sjkim { 354238384Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) 355238384Sjkim { 356238384Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE, 357238384Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 358238384Sjkim return -2; 359238384Sjkim } 360238384Sjkim if (ctx->operation != EVP_PKEY_OP_DERIVE) 361238384Sjkim { 362238384Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE, EVP_R_OPERATON_NOT_INITIALIZED); 363238384Sjkim return -1; 364238384Sjkim } 365238384Sjkim M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE) 366238384Sjkim return ctx->pmeth->derive(ctx, key, pkeylen); 367238384Sjkim } 368238384Sjkim 369