1 /* pmeth_fn.c */
   2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
   3  * project 2006.
   4  */
   5 /* ====================================================================
   6  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
   7  *
   8  * Redistribution and use in source and binary forms, with or without
   9  * modification, are permitted provided that the following conditions
  10  * are met:
  11  *
  12  * 1. Redistributions of source code must retain the above copyright
  13  *    notice, this list of conditions and the following disclaimer.
  14  *
  15  * 2. Redistributions in binary form must reproduce the above copyright
  16  *    notice, this list of conditions and the following disclaimer in
  17  *    the documentation and/or other materials provided with the
  18  *    distribution.
  19  *
  20  * 3. All advertising materials mentioning features or use of this
  21  *    software must display the following acknowledgment:
  22  *    "This product includes software developed by the OpenSSL Project
  23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  24  *
  25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  26  *    endorse or promote products derived from this software without
  27  *    prior written permission. For written permission, please contact
  28  *    licensing@OpenSSL.org.
  29  *
  30  * 5. Products derived from this software may not be called "OpenSSL"
  31  *    nor may "OpenSSL" appear in their names without prior written
  32  *    permission of the OpenSSL Project.
  33  *
  34  * 6. Redistributions of any form whatsoever must retain the following
  35  *    acknowledgment:
  36  *    "This product includes software developed by the OpenSSL Project
  37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  38  *
  39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  50  * OF THE POSSIBILITY OF SUCH DAMAGE.
  51  * ====================================================================
  52  *
  53  * This product includes cryptographic software written by Eric Young
  54  * (eay@cryptsoft.com).  This product includes software written by Tim
  55  * Hudson (tjh@cryptsoft.com).
  56  *
  57  */
  58 
  59 #include <stdio.h>
  60 #include <stdlib.h>
  61 #include "cryptlib.h"
  62 #include <openssl/objects.h>
  63 #include <openssl/evp.h>
  64 #include "evp_locl.h"
  65 
  66 #define M_check_autoarg(ctx, arg, arglen, err) \
  67         if (ctx->pmeth->flags & EVP_PKEY_FLAG_AUTOARGLEN) \
  68                 { \
  69                 size_t pksize = (size_t)EVP_PKEY_size(ctx->pkey); \
  70                 if (!arg) \
  71                         { \
  72                         *arglen = pksize; \
  73                         return 1; \
  74                         } \
  75                 else if (*arglen < pksize) \
  76                         { \
  77                         EVPerr(err, EVP_R_BUFFER_TOO_SMALL); /*ckerr_ignore*/\
  78                         return 0; \
  79                         } \
  80                 }
  81 
  82 int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx)
  83         {
  84         int ret;
  85         if (!ctx || !ctx->pmeth || !ctx->pmeth->sign)
  86                 {
  87                 EVPerr(EVP_F_EVP_PKEY_SIGN_INIT,
  88                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
  89                 return -2;
  90                 }
  91         ctx->operation = EVP_PKEY_OP_SIGN;
  92         if (!ctx->pmeth->sign_init)
  93                 return 1;
  94         ret = ctx->pmeth->sign_init(ctx);
  95         if (ret <= 0)
  96                 ctx->operation = EVP_PKEY_OP_UNDEFINED;
  97         return ret;
  98         }
  99 
 100 int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
 101                         unsigned char *sig, size_t *siglen,
 102                         const unsigned char *tbs, size_t tbslen)
 103         {
 104         if (!ctx || !ctx->pmeth || !ctx->pmeth->sign)
 105                 {
 106                 EVPerr(EVP_F_EVP_PKEY_SIGN,
 107                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 108                 return -2;
 109                 }
 110         if (ctx->operation != EVP_PKEY_OP_SIGN)
 111                 {
 112                 EVPerr(EVP_F_EVP_PKEY_SIGN, EVP_R_OPERATON_NOT_INITIALIZED);
 113                 return -1;
 114                 }
 115         M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN)
 116         return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen);
 117         }
 118 
 119 int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx)
 120         {
 121         int ret;
 122         if (!ctx || !ctx->pmeth || !ctx->pmeth->verify)
 123                 {
 124                 EVPerr(EVP_F_EVP_PKEY_VERIFY_INIT,
 125                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 126                 return -2;
 127                 }
 128         ctx->operation = EVP_PKEY_OP_VERIFY;
 129         if (!ctx->pmeth->verify_init)
 130                 return 1;
 131         ret = ctx->pmeth->verify_init(ctx);
 132         if (ret <= 0)
 133                 ctx->operation = EVP_PKEY_OP_UNDEFINED;
 134         return ret;
 135         }
 136 
 137 int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
 138                         const unsigned char *sig, size_t siglen,
 139                         const unsigned char *tbs, size_t tbslen)
 140         {
 141         if (!ctx || !ctx->pmeth || !ctx->pmeth->verify)
 142                 {
 143                 EVPerr(EVP_F_EVP_PKEY_VERIFY,
 144                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 145                 return -2;
 146                 }
 147         if (ctx->operation != EVP_PKEY_OP_VERIFY)
 148                 {
 149                 EVPerr(EVP_F_EVP_PKEY_VERIFY, EVP_R_OPERATON_NOT_INITIALIZED);
 150                 return -1;
 151                 }
 152         return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen);
 153         }
 154 
 155 int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx)
 156         {
 157         int ret;
 158         if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover)
 159                 {
 160                 EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT,
 161                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 162                 return -2;
 163                 }
 164         ctx->operation = EVP_PKEY_OP_VERIFYRECOVER;
 165         if (!ctx->pmeth->verify_recover_init)
 166                 return 1;
 167         ret = ctx->pmeth->verify_recover_init(ctx);
 168         if (ret <= 0)
 169                 ctx->operation = EVP_PKEY_OP_UNDEFINED;
 170         return ret;
 171         }
 172 
 173 int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
 174                         unsigned char *rout, size_t *routlen,
 175                         const unsigned char *sig, size_t siglen)
 176         {
 177         if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover)
 178                 {
 179                 EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER,
 180                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 181                 return -2;
 182                 }
 183         if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER)
 184                 {
 185                 EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER, EVP_R_OPERATON_NOT_INITIALIZED);
 186                 return -1;
 187                 }
 188         M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER)
 189         return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen);
 190         }
 191 
 192 int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx)
 193         {
 194         int ret;
 195         if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt)
 196                 {
 197                 EVPerr(EVP_F_EVP_PKEY_ENCRYPT_INIT,
 198                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 199                 return -2;
 200                 }
 201         ctx->operation = EVP_PKEY_OP_ENCRYPT;
 202         if (!ctx->pmeth->encrypt_init)
 203                 return 1;
 204         ret = ctx->pmeth->encrypt_init(ctx);
 205         if (ret <= 0)
 206                 ctx->operation = EVP_PKEY_OP_UNDEFINED;
 207         return ret;
 208         }
 209 
 210 int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
 211                         unsigned char *out, size_t *outlen,
 212                         const unsigned char *in, size_t inlen)
 213         {
 214         if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt)
 215                 {
 216                 EVPerr(EVP_F_EVP_PKEY_ENCRYPT,
 217                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 218                 return -2;
 219                 }
 220         if (ctx->operation != EVP_PKEY_OP_ENCRYPT)
 221                 {
 222                 EVPerr(EVP_F_EVP_PKEY_ENCRYPT, EVP_R_OPERATON_NOT_INITIALIZED);
 223                 return -1;
 224                 }
 225         M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT)
 226         return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen);
 227         }
 228 
 229 int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx)
 230         {
 231         int ret;
 232         if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt)
 233                 {
 234                 EVPerr(EVP_F_EVP_PKEY_DECRYPT_INIT,
 235                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 236                 return -2;
 237                 }
 238         ctx->operation = EVP_PKEY_OP_DECRYPT;
 239         if (!ctx->pmeth->decrypt_init)
 240                 return 1;
 241         ret = ctx->pmeth->decrypt_init(ctx);
 242         if (ret <= 0)
 243                 ctx->operation = EVP_PKEY_OP_UNDEFINED;
 244         return ret;
 245         }
 246 
 247 int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
 248                         unsigned char *out, size_t *outlen,
 249                         const unsigned char *in, size_t inlen)
 250         {
 251         if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt)
 252                 {
 253                 EVPerr(EVP_F_EVP_PKEY_DECRYPT,
 254                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 255                 return -2;
 256                 }
 257         if (ctx->operation != EVP_PKEY_OP_DECRYPT)
 258                 {
 259                 EVPerr(EVP_F_EVP_PKEY_DECRYPT, EVP_R_OPERATON_NOT_INITIALIZED);
 260                 return -1;
 261                 }
 262         M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT)
 263         return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
 264         }
 265 
 266 
 267 int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
 268         {
 269         int ret;
 270         if (!ctx || !ctx->pmeth || !ctx->pmeth->derive)
 271                 {
 272                 EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT,
 273                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 274                 return -2;
 275                 }
 276         ctx->operation = EVP_PKEY_OP_DERIVE;
 277         if (!ctx->pmeth->derive_init)
 278                 return 1;
 279         ret = ctx->pmeth->derive_init(ctx);
 280         if (ret <= 0)
 281                 ctx->operation = EVP_PKEY_OP_UNDEFINED;
 282         return ret;
 283         }
 284 
 285 int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
 286         {
 287         int ret;
 288         if (!ctx || !ctx->pmeth || !(ctx->pmeth->derive||ctx->pmeth->encrypt||ctx->pmeth->decrypt) || !ctx->pmeth->ctrl)
 289                 {
 290                 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
 291                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 292                 return -2;
 293                 }
 294         if (ctx->operation != EVP_PKEY_OP_DERIVE && ctx->operation != EVP_PKEY_OP_ENCRYPT && ctx->operation != EVP_PKEY_OP_DECRYPT)
 295                 {
 296                 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
 297                                         EVP_R_OPERATON_NOT_INITIALIZED);
 298                 return -1;
 299                 }
 300 
 301         ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
 302 
 303         if (ret <= 0)
 304                 return ret;
 305 
 306         if (ret == 2)
 307                 return 1;
 308 
 309         if (!ctx->pkey)
 310                 {
 311                 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET);
 312                 return -1;
 313                 }
 314 
 315         if (ctx->pkey->type != peer->type)
 316                 {
 317                 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
 318                                                 EVP_R_DIFFERENT_KEY_TYPES);
 319                 return -1;
 320                 }
 321 
 322         /* ran@cryptocom.ru: For clarity.  The error is if parameters in peer are
 323          * present (!missing) but don't match.  EVP_PKEY_cmp_parameters may return
 324          * 1 (match), 0 (don't match) and -2 (comparison is not defined).  -1
 325          * (different key types) is impossible here because it is checked earlier.
 326          * -2 is OK for us here, as well as 1, so we can check for 0 only. */
 327         if (!EVP_PKEY_missing_parameters(peer) &&
 328                 !EVP_PKEY_cmp_parameters(ctx->pkey, peer))
 329                 {
 330                 EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
 331                                                 EVP_R_DIFFERENT_PARAMETERS);
 332                 return -1;
 333                 }
 334 
 335         if (ctx->peerkey)
 336                 EVP_PKEY_free(ctx->peerkey);
 337         ctx->peerkey = peer;
 338 
 339         ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
 340 
 341         if (ret <= 0)
 342                 {
 343                 ctx->peerkey = NULL;
 344                 return ret;
 345                 }
 346 
 347         CRYPTO_add(&peer->references,1,CRYPTO_LOCK_EVP_PKEY);
 348         return 1;
 349         }
 350 
 351 
 352 int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen)
 353         {
 354         if (!ctx || !ctx->pmeth || !ctx->pmeth->derive)
 355                 {
 356                 EVPerr(EVP_F_EVP_PKEY_DERIVE,
 357                         EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
 358                 return -2;
 359                 }
 360         if (ctx->operation != EVP_PKEY_OP_DERIVE)
 361                 {
 362                 EVPerr(EVP_F_EVP_PKEY_DERIVE, EVP_R_OPERATON_NOT_INITIALIZED);
 363                 return -1;
 364                 }
 365         M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE)
 366         return ctx->pmeth->derive(ctx, key, pkeylen);
 367         }