2015-01-22 11:40:55 +08:00
|
|
|
/*
|
2016-05-18 03:38:09 +08:00
|
|
|
* Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
|
2006-04-08 00:42:09 +08:00
|
|
|
*
|
2018-12-06 20:40:06 +08:00
|
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
2016-05-18 03:38:09 +08:00
|
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
|
|
* in the file LICENSE in the source distribution or at
|
|
|
|
* https://www.openssl.org/source/license.html
|
2006-04-08 00:42:09 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2006-04-17 20:08:22 +08:00
|
|
|
#include <openssl/objects.h>
|
2006-04-08 00:42:09 +08:00
|
|
|
#include <openssl/evp.h>
|
2019-06-27 17:48:17 +08:00
|
|
|
#include "internal/cryptlib.h"
|
2019-09-28 06:45:33 +08:00
|
|
|
#include "crypto/evp.h"
|
2019-08-30 20:33:10 +08:00
|
|
|
#include "internal/provider.h"
|
2019-09-28 06:45:40 +08:00
|
|
|
#include "evp_local.h"
|
2006-04-16 02:50:56 +08:00
|
|
|
|
2019-08-30 20:33:10 +08:00
|
|
|
static EVP_SIGNATURE *evp_signature_new(OSSL_PROVIDER *prov)
|
|
|
|
{
|
|
|
|
EVP_SIGNATURE *signature = OPENSSL_zalloc(sizeof(EVP_SIGNATURE));
|
|
|
|
|
|
|
|
signature->lock = CRYPTO_THREAD_lock_new();
|
|
|
|
if (signature->lock == NULL) {
|
|
|
|
OPENSSL_free(signature);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
signature->prov = prov;
|
|
|
|
ossl_provider_up_ref(prov);
|
|
|
|
signature->refcnt = 1;
|
|
|
|
|
|
|
|
return signature;
|
|
|
|
}
|
|
|
|
|
In provider implemented methods, save the name number, not the name string
Multiple names per implementation is already supported in the namemap,
but hasn't been used yet. However, as soon as we have multiple names,
we will get an issue with what name should be saved in the method.
The solution is to not save the name itself, but rather the number
it's associated with. This number is supposed to be unique for each
set of names, and we assume that algorithm names are globally unique,
i.e. there can be no name overlap between different algorithm types.
Incidently, it was also found that the 'get' function used by
ossl_construct_method() doesn't need all the parameters it was given;
most of what it needs, it can now get through the data structure given
by the caller of ossl_construct_method(). As a consequence,
ossl_construct_method() itself doesn't need all the parameters it was
given either.
There are some added internal functions that are expected to disappear
as soon as legacy code is removed, such as evp_first_name() and
ossl_namemap_num2name().
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9897)
2019-09-14 22:22:19 +08:00
|
|
|
static void *evp_signature_from_dispatch(int name_id,
|
2019-08-30 20:33:10 +08:00
|
|
|
const OSSL_DISPATCH *fns,
|
|
|
|
OSSL_PROVIDER *prov,
|
|
|
|
void *vkeymgmt_data)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Signature functions cannot work without a key, and key management
|
|
|
|
* from the same provider to manage its keys. We therefore fetch
|
|
|
|
* a key management method using the same algorithm and properties
|
|
|
|
* and pass that down to evp_generic_fetch to be passed on to our
|
|
|
|
* evp_signature_from_dispatch, which will attach the key management
|
|
|
|
* method to the newly created key exchange method as long as the
|
|
|
|
* provider matches.
|
|
|
|
*/
|
|
|
|
struct keymgmt_data_st *keymgmt_data = vkeymgmt_data;
|
In provider implemented methods, save the name number, not the name string
Multiple names per implementation is already supported in the namemap,
but hasn't been used yet. However, as soon as we have multiple names,
we will get an issue with what name should be saved in the method.
The solution is to not save the name itself, but rather the number
it's associated with. This number is supposed to be unique for each
set of names, and we assume that algorithm names are globally unique,
i.e. there can be no name overlap between different algorithm types.
Incidently, it was also found that the 'get' function used by
ossl_construct_method() doesn't need all the parameters it was given;
most of what it needs, it can now get through the data structure given
by the caller of ossl_construct_method(). As a consequence,
ossl_construct_method() itself doesn't need all the parameters it was
given either.
There are some added internal functions that are expected to disappear
as soon as legacy code is removed, such as evp_first_name() and
ossl_namemap_num2name().
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9897)
2019-09-14 22:22:19 +08:00
|
|
|
EVP_KEYMGMT *keymgmt =
|
|
|
|
evp_keymgmt_fetch_by_number(keymgmt_data->ctx, name_id,
|
|
|
|
keymgmt_data->properties);
|
2019-08-30 20:33:10 +08:00
|
|
|
EVP_SIGNATURE *signature = NULL;
|
2019-09-02 23:48:26 +08:00
|
|
|
int ctxfncnt = 0, signfncnt = 0, verifyfncnt = 0, verifyrecfncnt = 0;
|
2019-09-17 00:14:21 +08:00
|
|
|
int digsignfncnt = 0, digverifyfncnt = 0;
|
|
|
|
int gparamfncnt = 0, sparamfncnt = 0, gmdparamfncnt = 0, smdparamfncnt = 0;
|
2019-08-30 20:33:10 +08:00
|
|
|
|
|
|
|
if (keymgmt == NULL || EVP_KEYMGMT_provider(keymgmt) != prov) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_NO_KEYMGMT_AVAILABLE);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
In provider implemented methods, save the name number, not the name string
Multiple names per implementation is already supported in the namemap,
but hasn't been used yet. However, as soon as we have multiple names,
we will get an issue with what name should be saved in the method.
The solution is to not save the name itself, but rather the number
it's associated with. This number is supposed to be unique for each
set of names, and we assume that algorithm names are globally unique,
i.e. there can be no name overlap between different algorithm types.
Incidently, it was also found that the 'get' function used by
ossl_construct_method() doesn't need all the parameters it was given;
most of what it needs, it can now get through the data structure given
by the caller of ossl_construct_method(). As a consequence,
ossl_construct_method() itself doesn't need all the parameters it was
given either.
There are some added internal functions that are expected to disappear
as soon as legacy code is removed, such as evp_first_name() and
ossl_namemap_num2name().
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9897)
2019-09-14 22:22:19 +08:00
|
|
|
if ((signature = evp_signature_new(prov)) == NULL) {
|
2019-08-30 20:33:10 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
In provider implemented methods, save the name number, not the name string
Multiple names per implementation is already supported in the namemap,
but hasn't been used yet. However, as soon as we have multiple names,
we will get an issue with what name should be saved in the method.
The solution is to not save the name itself, but rather the number
it's associated with. This number is supposed to be unique for each
set of names, and we assume that algorithm names are globally unique,
i.e. there can be no name overlap between different algorithm types.
Incidently, it was also found that the 'get' function used by
ossl_construct_method() doesn't need all the parameters it was given;
most of what it needs, it can now get through the data structure given
by the caller of ossl_construct_method(). As a consequence,
ossl_construct_method() itself doesn't need all the parameters it was
given either.
There are some added internal functions that are expected to disappear
as soon as legacy code is removed, such as evp_first_name() and
ossl_namemap_num2name().
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9897)
2019-09-14 22:22:19 +08:00
|
|
|
signature->name_id = name_id;
|
2019-08-30 20:33:10 +08:00
|
|
|
signature->keymgmt = keymgmt;
|
|
|
|
keymgmt = NULL; /* avoid double free on failure below */
|
|
|
|
|
|
|
|
for (; fns->function_id != 0; fns++) {
|
|
|
|
switch (fns->function_id) {
|
|
|
|
case OSSL_FUNC_SIGNATURE_NEWCTX:
|
|
|
|
if (signature->newctx != NULL)
|
|
|
|
break;
|
|
|
|
signature->newctx = OSSL_get_OP_signature_newctx(fns);
|
2019-09-02 23:48:26 +08:00
|
|
|
ctxfncnt++;
|
2019-08-30 20:33:10 +08:00
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_SIGN_INIT:
|
|
|
|
if (signature->sign_init != NULL)
|
|
|
|
break;
|
|
|
|
signature->sign_init = OSSL_get_OP_signature_sign_init(fns);
|
2019-09-02 23:48:26 +08:00
|
|
|
signfncnt++;
|
2019-08-30 20:33:10 +08:00
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_SIGN:
|
|
|
|
if (signature->sign != NULL)
|
|
|
|
break;
|
|
|
|
signature->sign = OSSL_get_OP_signature_sign(fns);
|
2019-09-02 23:48:26 +08:00
|
|
|
signfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_VERIFY_INIT:
|
|
|
|
if (signature->verify_init != NULL)
|
|
|
|
break;
|
|
|
|
signature->verify_init = OSSL_get_OP_signature_verify_init(fns);
|
|
|
|
verifyfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_VERIFY:
|
|
|
|
if (signature->verify != NULL)
|
|
|
|
break;
|
|
|
|
signature->verify = OSSL_get_OP_signature_verify(fns);
|
|
|
|
verifyfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT:
|
|
|
|
if (signature->verify_recover_init != NULL)
|
|
|
|
break;
|
|
|
|
signature->verify_recover_init
|
|
|
|
= OSSL_get_OP_signature_verify_recover_init(fns);
|
|
|
|
verifyrecfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_VERIFY_RECOVER:
|
|
|
|
if (signature->verify_recover != NULL)
|
|
|
|
break;
|
|
|
|
signature->verify_recover
|
|
|
|
= OSSL_get_OP_signature_verify_recover(fns);
|
|
|
|
verifyrecfncnt++;
|
2019-08-30 20:33:10 +08:00
|
|
|
break;
|
2019-09-17 00:14:21 +08:00
|
|
|
case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT:
|
|
|
|
if (signature->digest_sign_init != NULL)
|
|
|
|
break;
|
|
|
|
signature->digest_sign_init
|
|
|
|
= OSSL_get_OP_signature_digest_sign_init(fns);
|
|
|
|
digsignfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE:
|
|
|
|
if (signature->digest_sign_update != NULL)
|
|
|
|
break;
|
|
|
|
signature->digest_sign_update
|
|
|
|
= OSSL_get_OP_signature_digest_sign_update(fns);
|
|
|
|
digsignfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL:
|
|
|
|
if (signature->digest_sign_final != NULL)
|
|
|
|
break;
|
|
|
|
signature->digest_sign_final
|
|
|
|
= OSSL_get_OP_signature_digest_sign_final(fns);
|
|
|
|
digsignfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT:
|
|
|
|
if (signature->digest_verify_init != NULL)
|
|
|
|
break;
|
|
|
|
signature->digest_verify_init
|
|
|
|
= OSSL_get_OP_signature_digest_verify_init(fns);
|
|
|
|
digverifyfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE:
|
|
|
|
if (signature->digest_verify_update != NULL)
|
|
|
|
break;
|
|
|
|
signature->digest_verify_update
|
|
|
|
= OSSL_get_OP_signature_digest_verify_update(fns);
|
|
|
|
digverifyfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL:
|
|
|
|
if (signature->digest_verify_final != NULL)
|
|
|
|
break;
|
|
|
|
signature->digest_verify_final
|
|
|
|
= OSSL_get_OP_signature_digest_verify_final(fns);
|
|
|
|
digverifyfncnt++;
|
|
|
|
break;
|
2019-08-30 20:33:10 +08:00
|
|
|
case OSSL_FUNC_SIGNATURE_FREECTX:
|
|
|
|
if (signature->freectx != NULL)
|
|
|
|
break;
|
|
|
|
signature->freectx = OSSL_get_OP_signature_freectx(fns);
|
2019-09-02 23:48:26 +08:00
|
|
|
ctxfncnt++;
|
2019-08-30 20:33:10 +08:00
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_DUPCTX:
|
|
|
|
if (signature->dupctx != NULL)
|
|
|
|
break;
|
|
|
|
signature->dupctx = OSSL_get_OP_signature_dupctx(fns);
|
|
|
|
break;
|
2019-09-04 19:46:02 +08:00
|
|
|
case OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS:
|
|
|
|
if (signature->get_ctx_params != NULL)
|
2019-08-30 20:33:10 +08:00
|
|
|
break;
|
2019-09-04 19:46:02 +08:00
|
|
|
signature->get_ctx_params
|
|
|
|
= OSSL_get_OP_signature_get_ctx_params(fns);
|
|
|
|
gparamfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS:
|
|
|
|
if (signature->gettable_ctx_params != NULL)
|
|
|
|
break;
|
|
|
|
signature->gettable_ctx_params
|
|
|
|
= OSSL_get_OP_signature_gettable_ctx_params(fns);
|
|
|
|
gparamfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS:
|
|
|
|
if (signature->set_ctx_params != NULL)
|
|
|
|
break;
|
|
|
|
signature->set_ctx_params
|
|
|
|
= OSSL_get_OP_signature_set_ctx_params(fns);
|
|
|
|
sparamfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS:
|
|
|
|
if (signature->settable_ctx_params != NULL)
|
|
|
|
break;
|
|
|
|
signature->settable_ctx_params
|
|
|
|
= OSSL_get_OP_signature_settable_ctx_params(fns);
|
|
|
|
sparamfncnt++;
|
2019-08-30 20:33:10 +08:00
|
|
|
break;
|
2019-09-17 00:14:21 +08:00
|
|
|
case OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS:
|
|
|
|
if (signature->get_ctx_md_params != NULL)
|
|
|
|
break;
|
|
|
|
signature->get_ctx_md_params
|
|
|
|
= OSSL_get_OP_signature_get_ctx_md_params(fns);
|
|
|
|
gmdparamfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS:
|
|
|
|
if (signature->gettable_ctx_md_params != NULL)
|
|
|
|
break;
|
|
|
|
signature->gettable_ctx_md_params
|
|
|
|
= OSSL_get_OP_signature_gettable_ctx_md_params(fns);
|
|
|
|
gmdparamfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS:
|
|
|
|
if (signature->set_ctx_md_params != NULL)
|
|
|
|
break;
|
|
|
|
signature->set_ctx_md_params
|
|
|
|
= OSSL_get_OP_signature_set_ctx_md_params(fns);
|
|
|
|
smdparamfncnt++;
|
|
|
|
break;
|
|
|
|
case OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS:
|
|
|
|
if (signature->settable_ctx_md_params != NULL)
|
|
|
|
break;
|
|
|
|
signature->settable_ctx_md_params
|
|
|
|
= OSSL_get_OP_signature_settable_ctx_md_params(fns);
|
|
|
|
smdparamfncnt++;
|
|
|
|
break;
|
2019-08-30 20:33:10 +08:00
|
|
|
}
|
|
|
|
}
|
2019-09-02 23:48:26 +08:00
|
|
|
if (ctxfncnt != 2
|
2019-09-17 00:14:21 +08:00
|
|
|
|| (signfncnt == 0
|
|
|
|
&& verifyfncnt == 0
|
|
|
|
&& verifyrecfncnt == 0
|
|
|
|
&& digsignfncnt == 0
|
|
|
|
&& digverifyfncnt == 0)
|
|
|
|
|| (signfncnt != 0 && signfncnt != 2)
|
|
|
|
|| (verifyfncnt != 0 && verifyfncnt != 2)
|
|
|
|
|| (verifyrecfncnt != 0 && verifyrecfncnt != 2)
|
|
|
|
|| (digsignfncnt != 0 && digsignfncnt != 3)
|
|
|
|
|| (digverifyfncnt != 0 && digverifyfncnt != 3)
|
2019-09-04 19:46:02 +08:00
|
|
|
|| (gparamfncnt != 0 && gparamfncnt != 2)
|
2019-09-17 00:14:21 +08:00
|
|
|
|| (sparamfncnt != 0 && sparamfncnt != 2)
|
|
|
|
|| (gmdparamfncnt != 0 && gmdparamfncnt != 2)
|
|
|
|
|| (smdparamfncnt != 0 && smdparamfncnt != 2)) {
|
2019-08-30 20:33:10 +08:00
|
|
|
/*
|
|
|
|
* In order to be a consistent set of functions we must have at least
|
2019-09-17 00:14:21 +08:00
|
|
|
* a set of context functions (newctx and freectx) as well as a set of
|
|
|
|
* "signature" functions:
|
|
|
|
* (sign_init, sign) or
|
|
|
|
* (verify_init verify) or
|
|
|
|
* (verify_recover_init, verify_recover) or
|
|
|
|
* (digest_sign_init, digest_sign_update, digest_sign_final) or
|
|
|
|
* (digest_verify_init, digest_verify_update, digest_verify_final).
|
|
|
|
*
|
|
|
|
* set_ctx_params and settable_ctx_params are optional, but if one of
|
|
|
|
* them is present then the other one must also be present. The same
|
|
|
|
* applies to get_ctx_params and gettable_ctx_params. The same rules
|
|
|
|
* apply to the "md_params" functions. The dupctx function is optional.
|
2019-08-30 20:33:10 +08:00
|
|
|
*/
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return signature;
|
|
|
|
err:
|
|
|
|
EVP_SIGNATURE_free(signature);
|
|
|
|
EVP_KEYMGMT_free(keymgmt);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EVP_SIGNATURE_free(EVP_SIGNATURE *signature)
|
|
|
|
{
|
|
|
|
if (signature != NULL) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
CRYPTO_DOWN_REF(&signature->refcnt, &i, signature->lock);
|
|
|
|
if (i > 0)
|
|
|
|
return;
|
|
|
|
EVP_KEYMGMT_free(signature->keymgmt);
|
|
|
|
ossl_provider_free(signature->prov);
|
|
|
|
CRYPTO_THREAD_lock_free(signature->lock);
|
|
|
|
OPENSSL_free(signature);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_SIGNATURE_up_ref(EVP_SIGNATURE *signature)
|
|
|
|
{
|
|
|
|
int ref = 0;
|
|
|
|
|
|
|
|
CRYPTO_UP_REF(&signature->refcnt, &ref, signature->lock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
OSSL_PROVIDER *EVP_SIGNATURE_provider(const EVP_SIGNATURE *signature)
|
|
|
|
{
|
|
|
|
return signature->prov;
|
|
|
|
}
|
|
|
|
|
|
|
|
EVP_SIGNATURE *EVP_SIGNATURE_fetch(OPENSSL_CTX *ctx, const char *algorithm,
|
|
|
|
const char *properties)
|
|
|
|
{
|
|
|
|
struct keymgmt_data_st keymgmt_data;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A signature operation cannot work without a key, so we need key
|
|
|
|
* management from the same provider to manage its keys.
|
|
|
|
*/
|
|
|
|
keymgmt_data.ctx = ctx;
|
|
|
|
keymgmt_data.properties = properties;
|
|
|
|
return evp_generic_fetch(ctx, OSSL_OP_SIGNATURE, algorithm, properties,
|
|
|
|
evp_signature_from_dispatch, &keymgmt_data,
|
|
|
|
(int (*)(void *))EVP_SIGNATURE_up_ref,
|
|
|
|
(void (*)(void *))EVP_SIGNATURE_free);
|
|
|
|
}
|
|
|
|
|
2019-09-02 23:48:26 +08:00
|
|
|
static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature,
|
|
|
|
int operation)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-09-02 23:48:26 +08:00
|
|
|
int ret = 0;
|
2019-08-30 20:33:10 +08:00
|
|
|
void *provkey = NULL;
|
|
|
|
|
|
|
|
if (ctx == NULL) {
|
|
|
|
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
2015-01-22 11:40:55 +08:00
|
|
|
return -2;
|
|
|
|
}
|
2019-08-30 20:33:10 +08:00
|
|
|
|
2019-09-05 06:13:25 +08:00
|
|
|
evp_pkey_ctx_free_old_ops(ctx);
|
2019-09-02 23:48:26 +08:00
|
|
|
ctx->operation = operation;
|
2019-08-30 20:33:10 +08:00
|
|
|
|
|
|
|
if (ctx->engine != NULL)
|
|
|
|
goto legacy;
|
|
|
|
|
|
|
|
if (signature != NULL) {
|
|
|
|
if (!EVP_SIGNATURE_up_ref(signature))
|
|
|
|
goto err;
|
|
|
|
} else {
|
|
|
|
int nid = ctx->pkey != NULL ? ctx->pkey->type : ctx->pmeth->pkey_id;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* TODO(3.0): Check for legacy handling. Remove this once all all
|
|
|
|
* algorithms are moved to providers.
|
|
|
|
*/
|
|
|
|
if (ctx->pkey != NULL) {
|
|
|
|
switch (ctx->pkey->type) {
|
2019-08-30 20:33:37 +08:00
|
|
|
case NID_dsa:
|
|
|
|
break;
|
2019-08-30 20:33:10 +08:00
|
|
|
default:
|
|
|
|
goto legacy;
|
|
|
|
}
|
|
|
|
signature = EVP_SIGNATURE_fetch(NULL, OBJ_nid2sn(nid), NULL);
|
|
|
|
} else {
|
|
|
|
goto legacy;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (signature == NULL) {
|
|
|
|
EVPerr(0, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-05 06:13:25 +08:00
|
|
|
ctx->op.sig.signature = signature;
|
2019-08-30 20:33:10 +08:00
|
|
|
if (ctx->pkey != NULL) {
|
|
|
|
provkey = evp_keymgmt_export_to_provider(ctx->pkey, signature->keymgmt);
|
|
|
|
if (provkey == NULL) {
|
|
|
|
EVPerr(0, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2019-09-05 06:13:25 +08:00
|
|
|
ctx->op.sig.sigprovctx = signature->newctx(ossl_provider_ctx(signature->prov));
|
|
|
|
if (ctx->op.sig.sigprovctx == NULL) {
|
2019-08-30 20:33:10 +08:00
|
|
|
/* The provider key can stay in the cache */
|
|
|
|
EVPerr(0, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2019-09-02 23:48:26 +08:00
|
|
|
switch (operation) {
|
|
|
|
case EVP_PKEY_OP_SIGN:
|
|
|
|
if (signature->sign_init == NULL) {
|
|
|
|
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
ret = -2;
|
|
|
|
goto err;
|
|
|
|
}
|
2019-09-05 06:13:25 +08:00
|
|
|
ret = signature->sign_init(ctx->op.sig.sigprovctx, provkey);
|
2019-09-02 23:48:26 +08:00
|
|
|
break;
|
|
|
|
case EVP_PKEY_OP_VERIFY:
|
|
|
|
if (signature->verify_init == NULL) {
|
|
|
|
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
ret = -2;
|
|
|
|
goto err;
|
|
|
|
}
|
2019-09-05 06:13:25 +08:00
|
|
|
ret = signature->verify_init(ctx->op.sig.sigprovctx, provkey);
|
2019-09-02 23:48:26 +08:00
|
|
|
break;
|
|
|
|
case EVP_PKEY_OP_VERIFYRECOVER:
|
|
|
|
if (signature->verify_recover_init == NULL) {
|
|
|
|
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
ret = -2;
|
|
|
|
goto err;
|
|
|
|
}
|
2019-09-05 06:13:25 +08:00
|
|
|
ret = signature->verify_recover_init(ctx->op.sig.sigprovctx, provkey);
|
2019-09-02 23:48:26 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
EVPerr(0, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret <= 0) {
|
2019-09-05 06:13:25 +08:00
|
|
|
signature->freectx(ctx->op.sig.sigprovctx);
|
|
|
|
ctx->op.sig.sigprovctx = NULL;
|
2019-09-02 23:48:26 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
return 1;
|
2019-08-30 20:33:10 +08:00
|
|
|
|
|
|
|
legacy:
|
2019-09-02 23:48:26 +08:00
|
|
|
if (ctx->pmeth == NULL
|
|
|
|
|| (operation == EVP_PKEY_OP_SIGN && ctx->pmeth->sign == NULL)
|
|
|
|
|| (operation == EVP_PKEY_OP_VERIFY && ctx->pmeth->verify == NULL)
|
|
|
|
|| (operation == EVP_PKEY_OP_VERIFYRECOVER
|
|
|
|
&& ctx->pmeth->verify_recover == NULL)) {
|
2019-08-30 20:33:10 +08:00
|
|
|
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2019-09-02 23:48:26 +08:00
|
|
|
switch (operation) {
|
|
|
|
case EVP_PKEY_OP_SIGN:
|
|
|
|
if (ctx->pmeth->sign_init == NULL)
|
|
|
|
return 1;
|
|
|
|
ret = ctx->pmeth->sign_init(ctx);
|
|
|
|
break;
|
|
|
|
case EVP_PKEY_OP_VERIFY:
|
|
|
|
if (ctx->pmeth->verify_init == NULL)
|
|
|
|
return 1;
|
|
|
|
ret = ctx->pmeth->verify_init(ctx);
|
|
|
|
break;
|
|
|
|
case EVP_PKEY_OP_VERIFYRECOVER:
|
|
|
|
if (ctx->pmeth->verify_recover_init == NULL)
|
|
|
|
return 1;
|
|
|
|
ret = ctx->pmeth->verify_recover_init(ctx);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
EVPerr(0, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
goto err;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ret <= 0)
|
2019-09-02 23:48:26 +08:00
|
|
|
goto err;
|
2015-01-22 11:40:55 +08:00
|
|
|
return ret;
|
2019-09-02 23:48:26 +08:00
|
|
|
|
|
|
|
err:
|
|
|
|
ctx->operation = EVP_PKEY_OP_UNDEFINED;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_sign_init_ex(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature)
|
|
|
|
{
|
|
|
|
return evp_pkey_signature_init(ctx, signature, EVP_PKEY_OP_SIGN);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2006-04-08 00:42:09 +08:00
|
|
|
|
2019-08-30 20:33:10 +08:00
|
|
|
int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx)
|
|
|
|
{
|
2019-09-02 23:48:26 +08:00
|
|
|
return evp_pkey_signature_init(ctx, NULL, EVP_PKEY_OP_SIGN);
|
2019-08-30 20:33:10 +08:00
|
|
|
}
|
|
|
|
|
2006-04-08 00:42:09 +08:00
|
|
|
int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
|
2015-01-22 11:40:55 +08:00
|
|
|
unsigned char *sig, size_t *siglen,
|
|
|
|
const unsigned char *tbs, size_t tbslen)
|
|
|
|
{
|
2019-08-30 20:33:10 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (ctx == NULL) {
|
|
|
|
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
2015-01-22 11:40:55 +08:00
|
|
|
return -2;
|
|
|
|
}
|
2019-08-30 20:33:10 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ctx->operation != EVP_PKEY_OP_SIGN) {
|
2019-08-30 20:33:10 +08:00
|
|
|
EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2019-08-30 20:33:10 +08:00
|
|
|
|
2019-09-05 06:13:25 +08:00
|
|
|
if (ctx->op.sig.sigprovctx == NULL)
|
2019-08-30 20:33:10 +08:00
|
|
|
goto legacy;
|
|
|
|
|
2019-09-05 06:13:25 +08:00
|
|
|
ret = ctx->op.sig.signature->sign(ctx->op.sig.sigprovctx, sig, siglen,
|
|
|
|
SIZE_MAX, tbs, tbslen);
|
2019-08-30 20:33:10 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
legacy:
|
|
|
|
|
|
|
|
if (ctx->pmeth == NULL || ctx->pmeth->sign == NULL) {
|
|
|
|
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN)
|
|
|
|
return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen);
|
|
|
|
}
|
2006-04-08 00:42:09 +08:00
|
|
|
|
2019-09-02 23:48:26 +08:00
|
|
|
int EVP_PKEY_verify_init_ex(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature)
|
|
|
|
{
|
|
|
|
return evp_pkey_signature_init(ctx, signature, EVP_PKEY_OP_VERIFY);
|
|
|
|
}
|
|
|
|
|
2006-04-08 01:28:56 +08:00
|
|
|
int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-09-02 23:48:26 +08:00
|
|
|
return evp_pkey_signature_init(ctx, NULL, EVP_PKEY_OP_VERIFY);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2006-04-08 00:42:09 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
|
2015-01-22 11:40:55 +08:00
|
|
|
const unsigned char *sig, size_t siglen,
|
|
|
|
const unsigned char *tbs, size_t tbslen)
|
|
|
|
{
|
2019-09-02 23:48:26 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (ctx == NULL) {
|
|
|
|
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
2015-01-22 11:40:55 +08:00
|
|
|
return -2;
|
|
|
|
}
|
2019-09-02 23:48:26 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ctx->operation != EVP_PKEY_OP_VERIFY) {
|
2019-09-02 23:48:26 +08:00
|
|
|
EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2019-09-02 23:48:26 +08:00
|
|
|
|
2019-09-05 06:13:25 +08:00
|
|
|
if (ctx->op.sig.sigprovctx == NULL)
|
2019-09-02 23:48:26 +08:00
|
|
|
goto legacy;
|
|
|
|
|
2019-09-05 06:13:25 +08:00
|
|
|
ret = ctx->op.sig.signature->verify(ctx->op.sig.sigprovctx, sig, siglen,
|
|
|
|
tbs, tbslen);
|
2019-09-02 23:48:26 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
legacy:
|
|
|
|
if (ctx->pmeth == NULL || ctx->pmeth->verify == NULL) {
|
|
|
|
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen);
|
|
|
|
}
|
2006-04-08 00:42:09 +08:00
|
|
|
|
2019-09-02 23:48:26 +08:00
|
|
|
int EVP_PKEY_verify_recover_init_ex(EVP_PKEY_CTX *ctx, EVP_SIGNATURE *signature)
|
|
|
|
{
|
|
|
|
return evp_pkey_signature_init(ctx, signature, EVP_PKEY_OP_VERIFYRECOVER);
|
|
|
|
}
|
|
|
|
|
2006-04-08 01:28:56 +08:00
|
|
|
int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-09-02 23:48:26 +08:00
|
|
|
return evp_pkey_signature_init(ctx, NULL, EVP_PKEY_OP_VERIFYRECOVER);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2006-04-08 00:42:09 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
|
2015-01-22 11:40:55 +08:00
|
|
|
unsigned char *rout, size_t *routlen,
|
|
|
|
const unsigned char *sig, size_t siglen)
|
|
|
|
{
|
2019-09-02 23:48:26 +08:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (ctx == NULL) {
|
|
|
|
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
2015-01-22 11:40:55 +08:00
|
|
|
return -2;
|
|
|
|
}
|
2019-09-02 23:48:26 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) {
|
2019-09-02 23:48:26 +08:00
|
|
|
EVPerr(0, EVP_R_OPERATON_NOT_INITIALIZED);
|
2015-01-22 11:40:55 +08:00
|
|
|
return -1;
|
|
|
|
}
|
2019-09-02 23:48:26 +08:00
|
|
|
|
2019-09-05 06:13:25 +08:00
|
|
|
if (ctx->op.sig.sigprovctx == NULL)
|
2019-09-02 23:48:26 +08:00
|
|
|
goto legacy;
|
|
|
|
|
2019-09-05 06:13:25 +08:00
|
|
|
ret = ctx->op.sig.signature->verify_recover(ctx->op.sig.sigprovctx, rout,
|
|
|
|
routlen,
|
|
|
|
(rout == NULL ? 0 : *routlen),
|
|
|
|
sig, siglen);
|
2019-09-02 23:48:26 +08:00
|
|
|
return ret;
|
|
|
|
legacy:
|
|
|
|
if (ctx->pmeth == NULL || ctx->pmeth->verify_recover == NULL) {
|
|
|
|
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
return -2;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER)
|
|
|
|
return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen);
|
|
|
|
}
|
2006-04-08 00:42:09 +08:00
|
|
|
|
2006-04-08 01:28:56 +08:00
|
|
|
int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_ENCRYPT_INIT,
|
|
|
|
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
ctx->operation = EVP_PKEY_OP_ENCRYPT;
|
|
|
|
if (!ctx->pmeth->encrypt_init)
|
|
|
|
return 1;
|
|
|
|
ret = ctx->pmeth->encrypt_init(ctx);
|
|
|
|
if (ret <= 0)
|
|
|
|
ctx->operation = EVP_PKEY_OP_UNDEFINED;
|
|
|
|
return ret;
|
|
|
|
}
|
2006-04-08 00:42:09 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
|
2015-01-22 11:40:55 +08:00
|
|
|
unsigned char *out, size_t *outlen,
|
|
|
|
const unsigned char *in, size_t inlen)
|
|
|
|
{
|
|
|
|
if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_ENCRYPT,
|
|
|
|
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (ctx->operation != EVP_PKEY_OP_ENCRYPT) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_ENCRYPT, EVP_R_OPERATON_NOT_INITIALIZED);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT)
|
|
|
|
return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen);
|
|
|
|
}
|
2006-04-08 00:42:09 +08:00
|
|
|
|
2006-04-08 01:28:56 +08:00
|
|
|
int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_DECRYPT_INIT,
|
|
|
|
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
ctx->operation = EVP_PKEY_OP_DECRYPT;
|
|
|
|
if (!ctx->pmeth->decrypt_init)
|
|
|
|
return 1;
|
|
|
|
ret = ctx->pmeth->decrypt_init(ctx);
|
|
|
|
if (ret <= 0)
|
|
|
|
ctx->operation = EVP_PKEY_OP_UNDEFINED;
|
|
|
|
return ret;
|
|
|
|
}
|
2006-04-08 00:42:09 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
|
2015-01-22 11:40:55 +08:00
|
|
|
unsigned char *out, size_t *outlen,
|
|
|
|
const unsigned char *in, size_t inlen)
|
|
|
|
{
|
|
|
|
if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_DECRYPT,
|
|
|
|
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (ctx->operation != EVP_PKEY_OP_DECRYPT) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_DECRYPT, EVP_R_OPERATON_NOT_INITIALIZED);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT)
|
|
|
|
return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
|
|
|
|
}
|