pmeth_fn.c revision 296341
128328Ssos/* pmeth_fn.c */
228328Ssos/*
328328Ssos * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
428328Ssos * 2006.
528328Ssos */
628328Ssos/* ====================================================================
728328Ssos * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
828328Ssos *
928328Ssos * Redistribution and use in source and binary forms, with or without
1028328Ssos * modification, are permitted provided that the following conditions
1128328Ssos * are met:
1228328Ssos *
1328328Ssos * 1. Redistributions of source code must retain the above copyright
1428328Ssos *    notice, this list of conditions and the following disclaimer.
1597748Sschweikh *
1628328Ssos * 2. Redistributions in binary form must reproduce the above copyright
1728328Ssos *    notice, this list of conditions and the following disclaimer in
1828328Ssos *    the documentation and/or other materials provided with the
1928328Ssos *    distribution.
2028328Ssos *
2128328Ssos * 3. All advertising materials mentioning features or use of this
2228328Ssos *    software must display the following acknowledgment:
2328328Ssos *    "This product includes software developed by the OpenSSL Project
2428328Ssos *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2528328Ssos *
2628328Ssos * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2728328Ssos *    endorse or promote products derived from this software without
2828328Ssos *    prior written permission. For written permission, please contact
2983551Sdillon *    licensing@OpenSSL.org.
3083551Sdillon *
3183551Sdillon * 5. Products derived from this software may not be called "OpenSSL"
3228328Ssos *    nor may "OpenSSL" appear in their names without prior written
3366834Sphk *    permission of the OpenSSL Project.
3428328Ssos *
3528328Ssos * 6. Redistributions of any form whatsoever must retain the following
3628328Ssos *    acknowledgment:
3728328Ssos *    "This product includes software developed by the OpenSSL Project
3828328Ssos *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3928328Ssos *
4028328Ssos * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4128328Ssos * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4228328Ssos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4328328Ssos * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4428328Ssos * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4528328Ssos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4677475Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4728328Ssos * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4828328Ssos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4928328Ssos * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5028328Ssos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5128328Ssos * OF THE POSSIBILITY OF SUCH DAMAGE.
5228328Ssos * ====================================================================
5328328Ssos *
5428328Ssos * This product includes cryptographic software written by Eric Young
5528328Ssos * (eay@cryptsoft.com).  This product includes software written by Tim
5628328Ssos * Hudson (tjh@cryptsoft.com).
5728328Ssos *
5828328Ssos */
5928328Ssos
6028328Ssos#include <stdio.h>
6128328Ssos#include <stdlib.h>
6228328Ssos#include "cryptlib.h"
6328328Ssos#include <openssl/objects.h>
6428328Ssos#include <openssl/evp.h>
6550141Syokota#include "evp_locl.h"
6628328Ssos
6728328Ssos#define M_check_autoarg(ctx, arg, arglen, err) \
6828328Ssos        if (ctx->pmeth->flags & EVP_PKEY_FLAG_AUTOARGLEN) \
6928328Ssos                { \
7028328Ssos                size_t pksize = (size_t)EVP_PKEY_size(ctx->pkey); \
7128328Ssos                if (!arg) \
7228328Ssos                        { \
7328328Ssos                        *arglen = pksize; \
7428328Ssos                        return 1; \
7528328Ssos                        } \
7628328Ssos                else if (*arglen < pksize) \
7728328Ssos                        { \
7828328Ssos                        EVPerr(err, EVP_R_BUFFER_TOO_SMALL); /*ckerr_ignore*/\
7928328Ssos                        return 0; \
8028328Ssos                        } \
8128328Ssos                }
8228328Ssos
8328328Ssosint EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx)
8428328Ssos{
8528328Ssos    int ret;
8628328Ssos    if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
8728328Ssos        EVPerr(EVP_F_EVP_PKEY_SIGN_INIT,
8828328Ssos               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
8928328Ssos        return -2;
9028328Ssos    }
9128328Ssos    ctx->operation = EVP_PKEY_OP_SIGN;
9228328Ssos    if (!ctx->pmeth->sign_init)
9328328Ssos        return 1;
9428328Ssos    ret = ctx->pmeth->sign_init(ctx);
9528328Ssos    if (ret <= 0)
9628328Ssos        ctx->operation = EVP_PKEY_OP_UNDEFINED;
9728328Ssos    return ret;
9828328Ssos}
9928328Ssos
10028328Ssosint EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
10128328Ssos                  unsigned char *sig, size_t *siglen,
10228328Ssos                  const unsigned char *tbs, size_t tbslen)
10328328Ssos{
10428328Ssos    if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
10528328Ssos        EVPerr(EVP_F_EVP_PKEY_SIGN,
10628328Ssos               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
10728328Ssos        return -2;
10828328Ssos    }
10928328Ssos    if (ctx->operation != EVP_PKEY_OP_SIGN) {
11028328Ssos        EVPerr(EVP_F_EVP_PKEY_SIGN, EVP_R_OPERATON_NOT_INITIALIZED);
11128328Ssos        return -1;
11228328Ssos    }
11328328Ssos    M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN)
11428328Ssos        return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen);
11528328Ssos}
11628328Ssos
11728328Ssosint EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx)
11828328Ssos{
11928328Ssos    int ret;
12028328Ssos    if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) {
12128328Ssos        EVPerr(EVP_F_EVP_PKEY_VERIFY_INIT,
12228328Ssos               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
12328328Ssos        return -2;
12428328Ssos    }
12528328Ssos    ctx->operation = EVP_PKEY_OP_VERIFY;
12628328Ssos    if (!ctx->pmeth->verify_init)
12728328Ssos        return 1;
12828328Ssos    ret = ctx->pmeth->verify_init(ctx);
12928328Ssos    if (ret <= 0)
13028328Ssos        ctx->operation = EVP_PKEY_OP_UNDEFINED;
13128328Ssos    return ret;
13228328Ssos}
13328328Ssos
13428328Ssosint EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
13528328Ssos                    const unsigned char *sig, size_t siglen,
13628328Ssos                    const unsigned char *tbs, size_t tbslen)
13728328Ssos{
13828328Ssos    if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) {
13928328Ssos        EVPerr(EVP_F_EVP_PKEY_VERIFY,
14028328Ssos               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
14128328Ssos        return -2;
14228328Ssos    }
14328328Ssos    if (ctx->operation != EVP_PKEY_OP_VERIFY) {
14428328Ssos        EVPerr(EVP_F_EVP_PKEY_VERIFY, EVP_R_OPERATON_NOT_INITIALIZED);
14528328Ssos        return -1;
14628328Ssos    }
14728328Ssos    return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen);
14828328Ssos}
14928328Ssos
15028328Ssosint EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx)
15128328Ssos{
15228328Ssos    int ret;
15328328Ssos    if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
15428328Ssos        EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT,
15528328Ssos               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
15628328Ssos        return -2;
15728328Ssos    }
15828328Ssos    ctx->operation = EVP_PKEY_OP_VERIFYRECOVER;
15928328Ssos    if (!ctx->pmeth->verify_recover_init)
16028328Ssos        return 1;
16128328Ssos    ret = ctx->pmeth->verify_recover_init(ctx);
16228328Ssos    if (ret <= 0)
16328328Ssos        ctx->operation = EVP_PKEY_OP_UNDEFINED;
16428328Ssos    return ret;
16528328Ssos}
16628328Ssos
16728328Ssosint EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
16828328Ssos                            unsigned char *rout, size_t *routlen,
16928328Ssos                            const unsigned char *sig, size_t siglen)
17028328Ssos{
17128328Ssos    if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
17228328Ssos        EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER,
17328328Ssos               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
17428328Ssos        return -2;
17528328Ssos    }
17628328Ssos    if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) {
17728328Ssos        EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER, EVP_R_OPERATON_NOT_INITIALIZED);
17828328Ssos        return -1;
17928328Ssos    }
18028328Ssos    M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER)
18128328Ssos        return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen);
18228328Ssos}
18328328Ssos
18428328Ssosint EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx)
18528328Ssos{
18628328Ssos    int ret;
18728328Ssos    if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
18828328Ssos        EVPerr(EVP_F_EVP_PKEY_ENCRYPT_INIT,
18928328Ssos               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
19028328Ssos        return -2;
19128328Ssos    }
19228328Ssos    ctx->operation = EVP_PKEY_OP_ENCRYPT;
19328328Ssos    if (!ctx->pmeth->encrypt_init)
19428328Ssos        return 1;
19528328Ssos    ret = ctx->pmeth->encrypt_init(ctx);
19628328Ssos    if (ret <= 0)
19728328Ssos        ctx->operation = EVP_PKEY_OP_UNDEFINED;
19828328Ssos    return ret;
19928328Ssos}
20028328Ssos
20128328Ssosint EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
20228328Ssos                     unsigned char *out, size_t *outlen,
20328328Ssos                     const unsigned char *in, size_t inlen)
20428328Ssos{
20528328Ssos    if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
20628328Ssos        EVPerr(EVP_F_EVP_PKEY_ENCRYPT,
20728328Ssos               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
20828328Ssos        return -2;
20928328Ssos    }
21028328Ssos    if (ctx->operation != EVP_PKEY_OP_ENCRYPT) {
21128328Ssos        EVPerr(EVP_F_EVP_PKEY_ENCRYPT, EVP_R_OPERATON_NOT_INITIALIZED);
21228328Ssos        return -1;
21328328Ssos    }
21428328Ssos    M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT)
21528328Ssos        return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen);
21628328Ssos}
21728328Ssos
21828328Ssosint EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx)
21928328Ssos{
22028328Ssos    int ret;
22128328Ssos    if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
22228328Ssos        EVPerr(EVP_F_EVP_PKEY_DECRYPT_INIT,
22328328Ssos               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
22428328Ssos        return -2;
22528328Ssos    }
22628328Ssos    ctx->operation = EVP_PKEY_OP_DECRYPT;
22728328Ssos    if (!ctx->pmeth->decrypt_init)
22828328Ssos        return 1;
22928328Ssos    ret = ctx->pmeth->decrypt_init(ctx);
23028328Ssos    if (ret <= 0)
23128328Ssos        ctx->operation = EVP_PKEY_OP_UNDEFINED;
23228328Ssos    return ret;
23328328Ssos}
23428328Ssos
23528328Ssosint EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
23628328Ssos                     unsigned char *out, size_t *outlen,
23728328Ssos                     const unsigned char *in, size_t inlen)
23828328Ssos{
23928328Ssos    if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
24028328Ssos        EVPerr(EVP_F_EVP_PKEY_DECRYPT,
24128328Ssos               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
24228328Ssos        return -2;
24328328Ssos    }
24428328Ssos    if (ctx->operation != EVP_PKEY_OP_DECRYPT) {
24528328Ssos        EVPerr(EVP_F_EVP_PKEY_DECRYPT, EVP_R_OPERATON_NOT_INITIALIZED);
246        return -1;
247    }
248    M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT)
249        return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
250}
251
252int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
253{
254    int ret;
255    if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
256        EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT,
257               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
258        return -2;
259    }
260    ctx->operation = EVP_PKEY_OP_DERIVE;
261    if (!ctx->pmeth->derive_init)
262        return 1;
263    ret = ctx->pmeth->derive_init(ctx);
264    if (ret <= 0)
265        ctx->operation = EVP_PKEY_OP_UNDEFINED;
266    return ret;
267}
268
269int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
270{
271    int ret;
272    if (!ctx || !ctx->pmeth
273        || !(ctx->pmeth->derive || ctx->pmeth->encrypt || ctx->pmeth->decrypt)
274        || !ctx->pmeth->ctrl) {
275        EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
276               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
277        return -2;
278    }
279    if (ctx->operation != EVP_PKEY_OP_DERIVE
280        && ctx->operation != EVP_PKEY_OP_ENCRYPT
281        && ctx->operation != EVP_PKEY_OP_DECRYPT) {
282        EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
283               EVP_R_OPERATON_NOT_INITIALIZED);
284        return -1;
285    }
286
287    ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
288
289    if (ret <= 0)
290        return ret;
291
292    if (ret == 2)
293        return 1;
294
295    if (!ctx->pkey) {
296        EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET);
297        return -1;
298    }
299
300    if (ctx->pkey->type != peer->type) {
301        EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_KEY_TYPES);
302        return -1;
303    }
304
305    /*
306     * ran@cryptocom.ru: For clarity.  The error is if parameters in peer are
307     * present (!missing) but don't match.  EVP_PKEY_cmp_parameters may return
308     * 1 (match), 0 (don't match) and -2 (comparison is not defined).  -1
309     * (different key types) is impossible here because it is checked earlier.
310     * -2 is OK for us here, as well as 1, so we can check for 0 only.
311     */
312    if (!EVP_PKEY_missing_parameters(peer) &&
313        !EVP_PKEY_cmp_parameters(ctx->pkey, peer)) {
314        EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_PARAMETERS);
315        return -1;
316    }
317
318    if (ctx->peerkey)
319        EVP_PKEY_free(ctx->peerkey);
320    ctx->peerkey = peer;
321
322    ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
323
324    if (ret <= 0) {
325        ctx->peerkey = NULL;
326        return ret;
327    }
328
329    CRYPTO_add(&peer->references, 1, CRYPTO_LOCK_EVP_PKEY);
330    return 1;
331}
332
333int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen)
334{
335    if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
336        EVPerr(EVP_F_EVP_PKEY_DERIVE,
337               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
338        return -2;
339    }
340    if (ctx->operation != EVP_PKEY_OP_DERIVE) {
341        EVPerr(EVP_F_EVP_PKEY_DERIVE, EVP_R_OPERATON_NOT_INITIALIZED);
342        return -1;
343    }
344    M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE)
345        return ctx->pmeth->derive(ctx, key, pkeylen);
346}
347