1238384Sjkim/* pmeth_fn.c */ 2280304Sjkim/* 3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4280304Sjkim * 2006. 5238384Sjkim */ 6238384Sjkim/* ==================================================================== 7238384Sjkim * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 8238384Sjkim * 9238384Sjkim * Redistribution and use in source and binary forms, with or without 10238384Sjkim * modification, are permitted provided that the following conditions 11238384Sjkim * are met: 12238384Sjkim * 13238384Sjkim * 1. Redistributions of source code must retain the above copyright 14280304Sjkim * notice, this list of conditions and the following disclaimer. 15238384Sjkim * 16238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 17238384Sjkim * notice, this list of conditions and the following disclaimer in 18238384Sjkim * the documentation and/or other materials provided with the 19238384Sjkim * distribution. 20238384Sjkim * 21238384Sjkim * 3. All advertising materials mentioning features or use of this 22238384Sjkim * software must display the following acknowledgment: 23238384Sjkim * "This product includes software developed by the OpenSSL Project 24238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25238384Sjkim * 26238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27238384Sjkim * endorse or promote products derived from this software without 28238384Sjkim * prior written permission. For written permission, please contact 29238384Sjkim * licensing@OpenSSL.org. 30238384Sjkim * 31238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 32238384Sjkim * nor may "OpenSSL" appear in their names without prior written 33238384Sjkim * permission of the OpenSSL Project. 34238384Sjkim * 35238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 36238384Sjkim * acknowledgment: 37238384Sjkim * "This product includes software developed by the OpenSSL Project 38238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39238384Sjkim * 40238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 52238384Sjkim * ==================================================================== 53238384Sjkim * 54238384Sjkim * This product includes cryptographic software written by Eric Young 55238384Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 56238384Sjkim * Hudson (tjh@cryptsoft.com). 57238384Sjkim * 58238384Sjkim */ 59238384Sjkim 60238384Sjkim#include <stdio.h> 61238384Sjkim#include <stdlib.h> 62238384Sjkim#include "cryptlib.h" 63238384Sjkim#include <openssl/objects.h> 64238384Sjkim#include <openssl/evp.h> 65238384Sjkim#include "evp_locl.h" 66238384Sjkim 67238384Sjkim#define M_check_autoarg(ctx, arg, arglen, err) \ 68280304Sjkim if (ctx->pmeth->flags & EVP_PKEY_FLAG_AUTOARGLEN) \ 69280304Sjkim { \ 70280304Sjkim size_t pksize = (size_t)EVP_PKEY_size(ctx->pkey); \ 71280304Sjkim if (!arg) \ 72280304Sjkim { \ 73280304Sjkim *arglen = pksize; \ 74280304Sjkim return 1; \ 75280304Sjkim } \ 76280304Sjkim else if (*arglen < pksize) \ 77280304Sjkim { \ 78280304Sjkim EVPerr(err, EVP_R_BUFFER_TOO_SMALL); /*ckerr_ignore*/\ 79280304Sjkim return 0; \ 80280304Sjkim } \ 81280304Sjkim } 82238384Sjkim 83238384Sjkimint EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) 84280304Sjkim{ 85280304Sjkim int ret; 86280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) { 87280304Sjkim EVPerr(EVP_F_EVP_PKEY_SIGN_INIT, 88280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 89280304Sjkim return -2; 90280304Sjkim } 91280304Sjkim ctx->operation = EVP_PKEY_OP_SIGN; 92280304Sjkim if (!ctx->pmeth->sign_init) 93280304Sjkim return 1; 94280304Sjkim ret = ctx->pmeth->sign_init(ctx); 95280304Sjkim if (ret <= 0) 96280304Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 97280304Sjkim return ret; 98280304Sjkim} 99238384Sjkim 100238384Sjkimint EVP_PKEY_sign(EVP_PKEY_CTX *ctx, 101280304Sjkim unsigned char *sig, size_t *siglen, 102280304Sjkim const unsigned char *tbs, size_t tbslen) 103280304Sjkim{ 104280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) { 105280304Sjkim EVPerr(EVP_F_EVP_PKEY_SIGN, 106280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 107280304Sjkim return -2; 108280304Sjkim } 109280304Sjkim if (ctx->operation != EVP_PKEY_OP_SIGN) { 110280304Sjkim EVPerr(EVP_F_EVP_PKEY_SIGN, EVP_R_OPERATON_NOT_INITIALIZED); 111280304Sjkim return -1; 112280304Sjkim } 113280304Sjkim M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN) 114280304Sjkim return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen); 115280304Sjkim} 116238384Sjkim 117238384Sjkimint EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) 118280304Sjkim{ 119280304Sjkim int ret; 120280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) { 121280304Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY_INIT, 122280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 123280304Sjkim return -2; 124280304Sjkim } 125280304Sjkim ctx->operation = EVP_PKEY_OP_VERIFY; 126280304Sjkim if (!ctx->pmeth->verify_init) 127280304Sjkim return 1; 128280304Sjkim ret = ctx->pmeth->verify_init(ctx); 129280304Sjkim if (ret <= 0) 130280304Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 131280304Sjkim return ret; 132280304Sjkim} 133238384Sjkim 134238384Sjkimint EVP_PKEY_verify(EVP_PKEY_CTX *ctx, 135280304Sjkim const unsigned char *sig, size_t siglen, 136280304Sjkim const unsigned char *tbs, size_t tbslen) 137280304Sjkim{ 138280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) { 139280304Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY, 140280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 141280304Sjkim return -2; 142280304Sjkim } 143280304Sjkim if (ctx->operation != EVP_PKEY_OP_VERIFY) { 144280304Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY, EVP_R_OPERATON_NOT_INITIALIZED); 145280304Sjkim return -1; 146280304Sjkim } 147280304Sjkim return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen); 148280304Sjkim} 149238384Sjkim 150238384Sjkimint EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) 151280304Sjkim{ 152280304Sjkim int ret; 153280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) { 154280304Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT, 155280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 156280304Sjkim return -2; 157280304Sjkim } 158280304Sjkim ctx->operation = EVP_PKEY_OP_VERIFYRECOVER; 159280304Sjkim if (!ctx->pmeth->verify_recover_init) 160280304Sjkim return 1; 161280304Sjkim ret = ctx->pmeth->verify_recover_init(ctx); 162280304Sjkim if (ret <= 0) 163280304Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 164280304Sjkim return ret; 165280304Sjkim} 166238384Sjkim 167238384Sjkimint EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, 168280304Sjkim unsigned char *rout, size_t *routlen, 169280304Sjkim const unsigned char *sig, size_t siglen) 170280304Sjkim{ 171280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) { 172280304Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER, 173280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 174280304Sjkim return -2; 175280304Sjkim } 176280304Sjkim if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) { 177280304Sjkim EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER, EVP_R_OPERATON_NOT_INITIALIZED); 178280304Sjkim return -1; 179280304Sjkim } 180280304Sjkim M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER) 181280304Sjkim return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen); 182280304Sjkim} 183238384Sjkim 184238384Sjkimint EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) 185280304Sjkim{ 186280304Sjkim int ret; 187280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) { 188280304Sjkim EVPerr(EVP_F_EVP_PKEY_ENCRYPT_INIT, 189280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 190280304Sjkim return -2; 191280304Sjkim } 192280304Sjkim ctx->operation = EVP_PKEY_OP_ENCRYPT; 193280304Sjkim if (!ctx->pmeth->encrypt_init) 194280304Sjkim return 1; 195280304Sjkim ret = ctx->pmeth->encrypt_init(ctx); 196280304Sjkim if (ret <= 0) 197280304Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 198280304Sjkim return ret; 199280304Sjkim} 200238384Sjkim 201238384Sjkimint EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, 202280304Sjkim unsigned char *out, size_t *outlen, 203280304Sjkim const unsigned char *in, size_t inlen) 204280304Sjkim{ 205280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) { 206280304Sjkim EVPerr(EVP_F_EVP_PKEY_ENCRYPT, 207280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 208280304Sjkim return -2; 209280304Sjkim } 210280304Sjkim if (ctx->operation != EVP_PKEY_OP_ENCRYPT) { 211280304Sjkim EVPerr(EVP_F_EVP_PKEY_ENCRYPT, EVP_R_OPERATON_NOT_INITIALIZED); 212280304Sjkim return -1; 213280304Sjkim } 214280304Sjkim M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT) 215280304Sjkim return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen); 216280304Sjkim} 217238384Sjkim 218238384Sjkimint EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx) 219280304Sjkim{ 220280304Sjkim int ret; 221280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) { 222280304Sjkim EVPerr(EVP_F_EVP_PKEY_DECRYPT_INIT, 223280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 224280304Sjkim return -2; 225280304Sjkim } 226280304Sjkim ctx->operation = EVP_PKEY_OP_DECRYPT; 227280304Sjkim if (!ctx->pmeth->decrypt_init) 228280304Sjkim return 1; 229280304Sjkim ret = ctx->pmeth->decrypt_init(ctx); 230280304Sjkim if (ret <= 0) 231280304Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 232280304Sjkim return ret; 233280304Sjkim} 234238384Sjkim 235238384Sjkimint EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, 236280304Sjkim unsigned char *out, size_t *outlen, 237280304Sjkim const unsigned char *in, size_t inlen) 238280304Sjkim{ 239280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) { 240280304Sjkim EVPerr(EVP_F_EVP_PKEY_DECRYPT, 241280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 242280304Sjkim return -2; 243280304Sjkim } 244280304Sjkim if (ctx->operation != EVP_PKEY_OP_DECRYPT) { 245280304Sjkim EVPerr(EVP_F_EVP_PKEY_DECRYPT, EVP_R_OPERATON_NOT_INITIALIZED); 246280304Sjkim return -1; 247280304Sjkim } 248280304Sjkim M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT) 249280304Sjkim return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen); 250280304Sjkim} 251238384Sjkim 252238384Sjkimint EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) 253280304Sjkim{ 254280304Sjkim int ret; 255280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) { 256280304Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT, 257280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 258280304Sjkim return -2; 259280304Sjkim } 260280304Sjkim ctx->operation = EVP_PKEY_OP_DERIVE; 261280304Sjkim if (!ctx->pmeth->derive_init) 262280304Sjkim return 1; 263280304Sjkim ret = ctx->pmeth->derive_init(ctx); 264280304Sjkim if (ret <= 0) 265280304Sjkim ctx->operation = EVP_PKEY_OP_UNDEFINED; 266280304Sjkim return ret; 267280304Sjkim} 268238384Sjkim 269238384Sjkimint EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) 270280304Sjkim{ 271280304Sjkim int ret; 272280304Sjkim if (!ctx || !ctx->pmeth 273280304Sjkim || !(ctx->pmeth->derive || ctx->pmeth->encrypt || ctx->pmeth->decrypt) 274280304Sjkim || !ctx->pmeth->ctrl) { 275280304Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, 276280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 277280304Sjkim return -2; 278280304Sjkim } 279280304Sjkim if (ctx->operation != EVP_PKEY_OP_DERIVE 280280304Sjkim && ctx->operation != EVP_PKEY_OP_ENCRYPT 281280304Sjkim && ctx->operation != EVP_PKEY_OP_DECRYPT) { 282280304Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, 283280304Sjkim EVP_R_OPERATON_NOT_INITIALIZED); 284280304Sjkim return -1; 285280304Sjkim } 286238384Sjkim 287280304Sjkim ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer); 288238384Sjkim 289280304Sjkim if (ret <= 0) 290280304Sjkim return ret; 291238384Sjkim 292280304Sjkim if (ret == 2) 293280304Sjkim return 1; 294238384Sjkim 295280304Sjkim if (!ctx->pkey) { 296280304Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET); 297280304Sjkim return -1; 298280304Sjkim } 299238384Sjkim 300280304Sjkim if (ctx->pkey->type != peer->type) { 301280304Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_KEY_TYPES); 302280304Sjkim return -1; 303280304Sjkim } 304238384Sjkim 305280304Sjkim /* 306280304Sjkim * ran@cryptocom.ru: For clarity. The error is if parameters in peer are 307280304Sjkim * present (!missing) but don't match. EVP_PKEY_cmp_parameters may return 308280304Sjkim * 1 (match), 0 (don't match) and -2 (comparison is not defined). -1 309280304Sjkim * (different key types) is impossible here because it is checked earlier. 310280304Sjkim * -2 is OK for us here, as well as 1, so we can check for 0 only. 311280304Sjkim */ 312280304Sjkim if (!EVP_PKEY_missing_parameters(peer) && 313280304Sjkim !EVP_PKEY_cmp_parameters(ctx->pkey, peer)) { 314280304Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_PARAMETERS); 315280304Sjkim return -1; 316280304Sjkim } 317238384Sjkim 318280304Sjkim if (ctx->peerkey) 319280304Sjkim EVP_PKEY_free(ctx->peerkey); 320280304Sjkim ctx->peerkey = peer; 321238384Sjkim 322280304Sjkim ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer); 323238384Sjkim 324280304Sjkim if (ret <= 0) { 325280304Sjkim ctx->peerkey = NULL; 326280304Sjkim return ret; 327280304Sjkim } 328238384Sjkim 329280304Sjkim CRYPTO_add(&peer->references, 1, CRYPTO_LOCK_EVP_PKEY); 330280304Sjkim return 1; 331280304Sjkim} 332238384Sjkim 333238384Sjkimint EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen) 334280304Sjkim{ 335280304Sjkim if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) { 336280304Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE, 337280304Sjkim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 338280304Sjkim return -2; 339280304Sjkim } 340280304Sjkim if (ctx->operation != EVP_PKEY_OP_DERIVE) { 341280304Sjkim EVPerr(EVP_F_EVP_PKEY_DERIVE, EVP_R_OPERATON_NOT_INITIALIZED); 342280304Sjkim return -1; 343280304Sjkim } 344280304Sjkim M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE) 345280304Sjkim return ctx->pmeth->derive(ctx, key, pkeylen); 346280304Sjkim} 347