Latest update
This commit is contained in:
@@ -16,6 +16,10 @@ SOURCE[../../libcrypto]=\
|
||||
e_chacha20_poly1305.c cmeth_lib.c \
|
||||
mac_lib.c c_allm.c pkey_mac.c
|
||||
|
||||
# New design
|
||||
SOURCE[../../libcrypto]=\
|
||||
evp_fetch.c
|
||||
|
||||
INCLUDE[e_aes.o]=.. ../modes
|
||||
INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes
|
||||
INCLUDE[e_aes_cbc_hmac_sha256.o]=../modes
|
||||
|
||||
+292
-5
@@ -13,6 +13,7 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/engine.h>
|
||||
#include "internal/evp_int.h"
|
||||
#include "internal/provider.h"
|
||||
#include "evp_locl.h"
|
||||
|
||||
/* This call frees resources associated with the context */
|
||||
@@ -21,6 +22,24 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
|
||||
if (ctx == NULL)
|
||||
return 1;
|
||||
|
||||
if (ctx->digest == NULL || ctx->digest->prov == NULL)
|
||||
goto legacy;
|
||||
|
||||
if (ctx->provctx != NULL) {
|
||||
if (ctx->digest->freectx != NULL)
|
||||
ctx->digest->freectx(ctx->provctx);
|
||||
ctx->provctx = NULL;
|
||||
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
|
||||
}
|
||||
|
||||
if (ctx->pctx != NULL)
|
||||
goto legacy;
|
||||
|
||||
return 1;
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
|
||||
/*
|
||||
* Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because
|
||||
* sometimes only copies of the context are ever finalised.
|
||||
@@ -53,6 +72,23 @@ EVP_MD_CTX *EVP_MD_CTX_new(void)
|
||||
|
||||
void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
|
||||
if (ctx->digest == NULL || ctx->digest->prov == NULL)
|
||||
goto legacy;
|
||||
|
||||
EVP_MD_CTX_reset(ctx);
|
||||
|
||||
EVP_MD_meth_free(ctx->fetched_digest);
|
||||
ctx->fetched_digest = NULL;
|
||||
ctx->digest = NULL;
|
||||
|
||||
OPENSSL_free(ctx);
|
||||
return;
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
EVP_MD_CTX_reset(ctx);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
@@ -65,7 +101,12 @@ int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
|
||||
|
||||
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
|
||||
{
|
||||
EVP_MD *provmd;
|
||||
ENGINE *tmpimpl = NULL;
|
||||
|
||||
EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
|
||||
|
||||
/* TODO(3.0): Legacy work around code below. Remove this */
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
/*
|
||||
* Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
|
||||
@@ -76,6 +117,74 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
|
||||
if (ctx->engine && ctx->digest &&
|
||||
(type == NULL || (type->type == ctx->digest->type)))
|
||||
goto skip_to_init;
|
||||
|
||||
if (type != NULL && impl == NULL)
|
||||
tmpimpl = ENGINE_get_digest_engine(type->type);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If there are engines involved or if we're being used as part of
|
||||
* EVP_DigestSignInit then we should use legacy handling for now.
|
||||
*/
|
||||
if (ctx->engine != NULL
|
||||
|| impl != NULL
|
||||
|| tmpimpl != NULL
|
||||
|| ctx->pctx != NULL
|
||||
|| (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0) {
|
||||
if (ctx->digest == ctx->fetched_digest)
|
||||
ctx->digest = NULL;
|
||||
EVP_MD_meth_free(ctx->fetched_digest);
|
||||
ctx->fetched_digest = NULL;
|
||||
goto legacy;
|
||||
}
|
||||
|
||||
if (type->prov == NULL) {
|
||||
switch(type->type) {
|
||||
case NID_sha256:
|
||||
break;
|
||||
default:
|
||||
goto legacy;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->digest != NULL && ctx->digest->ctx_size > 0) {
|
||||
OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
|
||||
ctx->md_data = NULL;
|
||||
}
|
||||
|
||||
/* TODO(3.0): Start of non-legacy code below */
|
||||
|
||||
if (type->prov == NULL) {
|
||||
provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), "");
|
||||
if (provmd == NULL) {
|
||||
EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
type = provmd;
|
||||
EVP_MD_meth_free(ctx->fetched_digest);
|
||||
ctx->fetched_digest = provmd;
|
||||
}
|
||||
|
||||
ctx->digest = type;
|
||||
if (ctx->provctx == NULL) {
|
||||
ctx->provctx = ctx->digest->newctx();
|
||||
if (ctx->provctx == NULL) {
|
||||
EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->digest->dinit == NULL) {
|
||||
EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ctx->digest->dinit(ctx->provctx);
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
if (type) {
|
||||
/*
|
||||
* Ensure an ENGINE left lying around from last time is cleared (the
|
||||
@@ -90,7 +199,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
|
||||
}
|
||||
} else {
|
||||
/* Ask if an ENGINE is reserved for this job */
|
||||
impl = ENGINE_get_digest_engine(type->type);
|
||||
impl = tmpimpl;
|
||||
}
|
||||
if (impl != NULL) {
|
||||
/* There's an ENGINE for this job ... (apparently) */
|
||||
@@ -150,6 +259,20 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
|
||||
|
||||
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
|
||||
{
|
||||
if (count == 0)
|
||||
return 1;
|
||||
|
||||
if (ctx->digest == NULL || ctx->digest->prov == NULL)
|
||||
goto legacy;
|
||||
|
||||
if (ctx->digest->dupdate == NULL) {
|
||||
EVPerr(EVP_F_EVP_DIGESTUPDATE, EVP_R_UPDATE_ERROR);
|
||||
return 0;
|
||||
}
|
||||
return ctx->digest->dupdate(ctx->provctx, data, count);
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
return ctx->update(ctx, data, count);
|
||||
}
|
||||
|
||||
@@ -163,14 +286,40 @@ int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
|
||||
}
|
||||
|
||||
/* The caller can assume that this removes any secret data from the context */
|
||||
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
|
||||
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize)
|
||||
{
|
||||
int ret;
|
||||
size_t size = 0;
|
||||
|
||||
if (ctx->digest == NULL || ctx->digest->prov == NULL)
|
||||
goto legacy;
|
||||
|
||||
if (ctx->digest->dfinal == NULL) {
|
||||
EVPerr(EVP_F_EVP_DIGESTFINAL_EX, EVP_R_FINAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ctx->digest->dfinal(ctx->provctx, md, &size);
|
||||
|
||||
if (isize != NULL) {
|
||||
if (size <= UINT_MAX) {
|
||||
*isize = (int)size;
|
||||
} else {
|
||||
EVPerr(EVP_F_EVP_DIGESTFINAL_EX, EVP_R_FINAL_ERROR);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
EVP_MD_CTX_reset(ctx);
|
||||
|
||||
return ret;
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
|
||||
ret = ctx->digest->final(ctx, md);
|
||||
if (size != NULL)
|
||||
*size = ctx->digest->md_size;
|
||||
if (isize != NULL)
|
||||
*isize = ctx->digest->md_size;
|
||||
if (ctx->digest->cleanup) {
|
||||
ctx->digest->cleanup(ctx);
|
||||
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
|
||||
@@ -209,10 +358,52 @@ int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
|
||||
int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
|
||||
{
|
||||
unsigned char *tmp_buf;
|
||||
if ((in == NULL) || (in->digest == NULL)) {
|
||||
|
||||
if (in == NULL || in->digest == NULL) {
|
||||
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_INPUT_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in->digest->prov == NULL)
|
||||
goto legacy;
|
||||
|
||||
if (in->digest->dupctx == NULL) {
|
||||
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_NOT_ABLE_TO_COPY_CTX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_reset(out);
|
||||
if (out->fetched_digest != NULL)
|
||||
EVP_MD_meth_free(out->fetched_digest);
|
||||
*out = *in;
|
||||
/* NULL out pointers in case of error */
|
||||
out->pctx = NULL;
|
||||
out->provctx = NULL;
|
||||
|
||||
if (in->fetched_digest != NULL)
|
||||
EVP_MD_upref(in->fetched_digest);
|
||||
|
||||
out->provctx = in->digest->dupctx(in->provctx);
|
||||
if (out->provctx == NULL) {
|
||||
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_NOT_ABLE_TO_COPY_CTX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */
|
||||
EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
|
||||
if (in->pctx != NULL) {
|
||||
out->pctx = EVP_PKEY_CTX_dup(in->pctx);
|
||||
if (out->pctx == NULL) {
|
||||
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_NOT_ABLE_TO_COPY_CTX);
|
||||
EVP_MD_CTX_reset(out);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
/* TODO(3.0): Remove legacy code below */
|
||||
legacy:
|
||||
#ifndef OPENSSL_NO_ENGINE
|
||||
/* Make sure it's safe to copy a digest context using an ENGINE */
|
||||
if (in->engine && !ENGINE_init(in->engine)) {
|
||||
@@ -296,3 +487,99 @@ int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *evp_md_from_dispatch(int mdtype, const OSSL_DISPATCH *fns,
|
||||
OSSL_PROVIDER *prov)
|
||||
{
|
||||
EVP_MD *md = NULL;
|
||||
int fncnt = 0;
|
||||
|
||||
if ((md = EVP_MD_meth_new(mdtype, NID_undef)) == NULL)
|
||||
return NULL;
|
||||
|
||||
for (; fns->function_id != 0; fns++) {
|
||||
switch (fns->function_id) {
|
||||
case OSSL_FUNC_DIGEST_NEWCTX:
|
||||
if (md->newctx != NULL)
|
||||
break;
|
||||
md->newctx = OSSL_get_OP_digest_newctx(fns);
|
||||
fncnt++;
|
||||
break;
|
||||
case OSSL_FUNC_DIGEST_INIT:
|
||||
if (md->dinit != NULL)
|
||||
break;
|
||||
md->dinit = OSSL_get_OP_digest_init(fns);
|
||||
fncnt++;
|
||||
break;
|
||||
case OSSL_FUNC_DIGEST_UPDDATE:
|
||||
if (md->dupdate != NULL)
|
||||
break;
|
||||
md->dupdate = OSSL_get_OP_digest_update(fns);
|
||||
fncnt++;
|
||||
break;
|
||||
case OSSL_FUNC_DIGEST_FINAL:
|
||||
if (md->dfinal != NULL)
|
||||
break;
|
||||
md->dfinal = OSSL_get_OP_digest_final(fns);
|
||||
fncnt++;
|
||||
break;
|
||||
case OSSL_FUNC_DIGEST_DIGEST:
|
||||
if (md->digest != NULL)
|
||||
break;
|
||||
md->digest = OSSL_get_OP_digest_digest(fns);
|
||||
/* We don't increment fnct for this as it is stand alone */
|
||||
break;
|
||||
case OSSL_FUNC_DIGEST_FREECTX:
|
||||
if (md->freectx != NULL)
|
||||
break;
|
||||
md->freectx = OSSL_get_OP_digest_freectx(fns);
|
||||
fncnt++;
|
||||
break;
|
||||
case OSSL_FUNC_DIGEST_DUPCTX:
|
||||
if (md->dupctx != NULL)
|
||||
break;
|
||||
md->dupctx = OSSL_get_OP_digest_dupctx(fns);
|
||||
break;
|
||||
case OSSL_FUNC_DIGEST_SIZE:
|
||||
if (md->size != NULL)
|
||||
break;
|
||||
md->size = OSSL_get_OP_digest_size(fns);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((fncnt != 0 && fncnt != 5)
|
||||
|| (fncnt == 0 && md->digest == NULL)
|
||||
|| md->size == NULL) {
|
||||
/*
|
||||
* In order to be a consistent set of functions we either need the
|
||||
* whole set of init/update/final etc functions or none of them.
|
||||
* The "digest" function can standalone. We at least need one way to
|
||||
* generate digests.
|
||||
*/
|
||||
EVP_MD_meth_free(md);
|
||||
return NULL;
|
||||
}
|
||||
md->prov = prov;
|
||||
if (prov != NULL)
|
||||
ossl_provider_upref(prov);
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
static int evp_md_upref(void *md)
|
||||
{
|
||||
return EVP_MD_upref(md);
|
||||
}
|
||||
|
||||
static void evp_md_free(void *md)
|
||||
{
|
||||
EVP_MD_meth_free(md);
|
||||
}
|
||||
|
||||
EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
|
||||
const char *properties)
|
||||
{
|
||||
return evp_generic_fetch(ctx, OSSL_OP_DIGEST, algorithm, properties,
|
||||
evp_md_from_dispatch, evp_md_upref,
|
||||
evp_md_free);
|
||||
}
|
||||
+13
-1
@@ -486,6 +486,16 @@ static int aria_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aria_gcm_cleanup(EVP_CIPHER_CTX *ctx)
|
||||
{
|
||||
EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX, ctx);
|
||||
|
||||
if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(ctx))
|
||||
OPENSSL_free(gctx->iv);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aria_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
const unsigned char *iv, int enc)
|
||||
{
|
||||
@@ -727,6 +737,8 @@ static int aria_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||
}
|
||||
}
|
||||
|
||||
#define aria_ccm_cleanup NULL
|
||||
|
||||
#define ARIA_AUTH_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \
|
||||
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
|
||||
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
|
||||
@@ -739,7 +751,7 @@ static const EVP_CIPHER aria_##keylen##_##mode = { \
|
||||
ARIA_AUTH_FLAGS|EVP_CIPH_##MODE##_MODE, \
|
||||
aria_##mode##_init_key, \
|
||||
aria_##mode##_cipher, \
|
||||
NULL, \
|
||||
aria_##mode##_cleanup, \
|
||||
sizeof(EVP_ARIA_##MODE##_CTX), \
|
||||
NULL,NULL,aria_##mode##_ctrl,NULL }; \
|
||||
const EVP_CIPHER *EVP_aria_##keylen##_##mode(void) \
|
||||
|
||||
@@ -54,7 +54,9 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
|
||||
"EVP_DecryptFinal_ex"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTUPDATE, 0), "EVP_DecryptUpdate"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTFINALXOF, 0), "EVP_DigestFinalXOF"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTFINAL_EX, 0), "EVP_DigestFinal_ex"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTINIT_EX, 0), "EVP_DigestInit_ex"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTUPDATE, 0), "EVP_DigestUpdate"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTDECRYPTUPDATE, 0),
|
||||
"evp_EncryptDecryptUpdate"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0),
|
||||
@@ -219,6 +221,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
|
||||
"expecting a poly1305 key"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_SIPHASH_KEY),
|
||||
"expecting a siphash key"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FINAL_ERROR), "final error"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FIPS_MODE_NOT_SUPPORTED),
|
||||
"fips mode not supported"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GET_RAW_KEY_FAILED), "get raw key failed"},
|
||||
@@ -246,6 +249,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_METHOD_NOT_SUPPORTED),
|
||||
"method not supported"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MISSING_PARAMETERS), "missing parameters"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NOT_ABLE_TO_COPY_CTX),
|
||||
"not able to copy ctx"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NOT_XOF_OR_INVALID_LENGTH),
|
||||
"not XOF or invalid length"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_CIPHER_SET), "no cipher set"},
|
||||
@@ -293,6 +298,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
|
||||
"unsupported private key algorithm"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_SALT_TYPE),
|
||||
"unsupported salt type"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UPDATE_ERROR), "update error"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRAP_MODE_NOT_ALLOWED),
|
||||
"wrap mode not allowed"},
|
||||
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRONG_FINAL_BLOCK_LENGTH),
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <openssl/ossl_typ.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/core.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/thread_once.h"
|
||||
#include "internal/asn1_int.h"
|
||||
#include "internal/property.h"
|
||||
#include "internal/core.h"
|
||||
#include "internal/evp_int.h" /* evp_locl.h needs it */
|
||||
#include "evp_locl.h"
|
||||
|
||||
/* The OpenSSL library context index for the default method store */
|
||||
static int default_method_store_index = -1;
|
||||
|
||||
static void default_method_store_free(void *vstore)
|
||||
{
|
||||
ossl_method_store_free(vstore);
|
||||
}
|
||||
|
||||
static void *default_method_store_new(void)
|
||||
{
|
||||
return ossl_method_store_new();
|
||||
}
|
||||
|
||||
|
||||
static const OPENSSL_CTX_METHOD default_method_store_method = {
|
||||
default_method_store_new,
|
||||
default_method_store_free,
|
||||
};
|
||||
|
||||
static int default_method_store_init(void)
|
||||
{
|
||||
default_method_store_index =
|
||||
openssl_ctx_new_index(&default_method_store_method);
|
||||
|
||||
return default_method_store_index != -1;
|
||||
}
|
||||
|
||||
static CRYPTO_ONCE default_method_store_init_flag = CRYPTO_ONCE_STATIC_INIT;
|
||||
DEFINE_RUN_ONCE_STATIC(do_default_method_store_init)
|
||||
{
|
||||
return OPENSSL_init_crypto(0, NULL)
|
||||
&& default_method_store_init();
|
||||
}
|
||||
|
||||
/* Data to be passed through ossl_method_construct() */
|
||||
struct method_data_st {
|
||||
const char *name;
|
||||
int nid;
|
||||
OSSL_METHOD_CONSTRUCT_METHOD *mcm;
|
||||
void *(*method_from_dispatch)(int nid, const OSSL_DISPATCH *,
|
||||
OSSL_PROVIDER *);
|
||||
int (*refcnt_up_method)(void *method);
|
||||
void (*destruct_method)(void *method);
|
||||
};
|
||||
|
||||
/*
|
||||
* Generic routines to fetch / create EVP methods with ossl_method_construct()
|
||||
*/
|
||||
static void *alloc_tmp_method_store(void)
|
||||
{
|
||||
return ossl_method_store_new();
|
||||
}
|
||||
|
||||
static void dealloc_tmp_method_store(void *store)
|
||||
{
|
||||
if (store != NULL)
|
||||
ossl_method_store_free(store);
|
||||
}
|
||||
|
||||
static
|
||||
struct OSSL_METHOD_STORE *get_default_method_store(OPENSSL_CTX *libctx)
|
||||
{
|
||||
if (!RUN_ONCE(&default_method_store_init_flag,
|
||||
do_default_method_store_init))
|
||||
return NULL;
|
||||
return openssl_ctx_get_data(libctx, default_method_store_index);
|
||||
}
|
||||
|
||||
static void *get_method_from_store(OPENSSL_CTX *libctx, void *store,
|
||||
const char *propquery, void *data)
|
||||
{
|
||||
struct method_data_st *methdata = data;
|
||||
void *method = NULL;
|
||||
|
||||
if (store == NULL
|
||||
&& (store = get_default_method_store(libctx)) == NULL)
|
||||
return NULL;
|
||||
|
||||
(void)ossl_method_store_fetch(store, methdata->nid, propquery, &method);
|
||||
|
||||
if (method != NULL
|
||||
&& !methdata->refcnt_up_method(method)) {
|
||||
method = NULL;
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
static int put_method_in_store(OPENSSL_CTX *libctx, void *store,
|
||||
const char *propdef, void *method,
|
||||
void *data)
|
||||
{
|
||||
struct method_data_st *methdata = data;
|
||||
|
||||
if (store == NULL
|
||||
&& (store = get_default_method_store(libctx)) == NULL)
|
||||
return 0;
|
||||
|
||||
if (methdata->refcnt_up_method(method)
|
||||
&& ossl_method_store_add(store, methdata->nid, propdef, method,
|
||||
methdata->destruct_method))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *construct_method(const OSSL_DISPATCH *fns, OSSL_PROVIDER *prov,
|
||||
void *data)
|
||||
{
|
||||
struct method_data_st *methdata = data;
|
||||
void *method = NULL;
|
||||
|
||||
if (methdata->nid == NID_undef) {
|
||||
/* Create a new NID for that name on the fly */
|
||||
ASN1_OBJECT tmpobj;
|
||||
|
||||
/* This is the same as OBJ_create() but without requiring a OID */
|
||||
tmpobj.nid = OBJ_new_nid(1);
|
||||
tmpobj.sn = tmpobj.ln = methdata->name;
|
||||
tmpobj.flags = ASN1_OBJECT_FLAG_DYNAMIC;
|
||||
tmpobj.length = 0;
|
||||
tmpobj.data = NULL;
|
||||
|
||||
methdata->nid = OBJ_add_object(&tmpobj);
|
||||
}
|
||||
|
||||
if (methdata->nid == NID_undef)
|
||||
return NULL;
|
||||
|
||||
method = methdata->method_from_dispatch(methdata->nid, fns, prov);
|
||||
if (method == NULL)
|
||||
return NULL;
|
||||
return method;
|
||||
}
|
||||
|
||||
static void destruct_method(void *method, void *data)
|
||||
{
|
||||
struct method_data_st *methdata = data;
|
||||
|
||||
methdata->destruct_method(method);
|
||||
}
|
||||
|
||||
void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
|
||||
const char *algorithm, const char *properties,
|
||||
void *(*new_method)(int nid, const OSSL_DISPATCH *fns,
|
||||
OSSL_PROVIDER *prov),
|
||||
int (*upref_method)(void *),
|
||||
void (*free_method)(void *))
|
||||
{
|
||||
int nid = OBJ_sn2nid(algorithm);
|
||||
void *method = NULL;
|
||||
|
||||
if (nid == NID_undef
|
||||
|| !ossl_method_store_cache_get(NULL, nid, properties, &method)) {
|
||||
OSSL_METHOD_CONSTRUCT_METHOD mcm = {
|
||||
alloc_tmp_method_store,
|
||||
dealloc_tmp_method_store,
|
||||
get_method_from_store,
|
||||
put_method_in_store,
|
||||
construct_method,
|
||||
destruct_method
|
||||
};
|
||||
struct method_data_st mcmdata;
|
||||
|
||||
mcmdata.nid = nid;
|
||||
mcmdata.mcm = &mcm;
|
||||
mcmdata.method_from_dispatch = new_method;
|
||||
mcmdata.destruct_method = free_method;
|
||||
mcmdata.refcnt_up_method = upref_method;
|
||||
mcmdata.destruct_method = free_method;
|
||||
method = ossl_method_construct(libctx, operation_id, algorithm,
|
||||
properties, 0 /* !force_cache */,
|
||||
&mcm, &mcmdata);
|
||||
ossl_method_store_cache_set(NULL, nid, properties, method);
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
+30
-1
@@ -12,6 +12,7 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/objects.h>
|
||||
#include "internal/evp_int.h"
|
||||
#include "internal/provider.h"
|
||||
#include "evp_locl.h"
|
||||
|
||||
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
|
||||
@@ -316,6 +317,10 @@ int EVP_MD_size(const EVP_MD *md)
|
||||
EVPerr(EVP_F_EVP_MD_SIZE, EVP_R_MESSAGE_DIGEST_IS_NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (md->prov != NULL && md->size != NULL)
|
||||
return (int)md->size();
|
||||
|
||||
return md->md_size;
|
||||
}
|
||||
|
||||
@@ -331,6 +336,12 @@ EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type)
|
||||
if (md != NULL) {
|
||||
md->type = md_type;
|
||||
md->pkey_type = pkey_type;
|
||||
md->lock = CRYPTO_THREAD_lock_new();
|
||||
if (md->lock == NULL) {
|
||||
OPENSSL_free(md);
|
||||
return NULL;
|
||||
}
|
||||
md->refcnt = 1;
|
||||
}
|
||||
return md;
|
||||
}
|
||||
@@ -342,9 +353,27 @@ EVP_MD *EVP_MD_meth_dup(const EVP_MD *md)
|
||||
memcpy(to, md, sizeof(*to));
|
||||
return to;
|
||||
}
|
||||
|
||||
int EVP_MD_upref(EVP_MD *md)
|
||||
{
|
||||
int ref = 0;
|
||||
|
||||
CRYPTO_UP_REF(&md->refcnt, &ref, md->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EVP_MD_meth_free(EVP_MD *md)
|
||||
{
|
||||
OPENSSL_free(md);
|
||||
if (md != NULL) {
|
||||
int i;
|
||||
|
||||
CRYPTO_DOWN_REF(&md->refcnt, &i, md->lock);
|
||||
if (i > 0)
|
||||
return;
|
||||
ossl_provider_free(md->prov);
|
||||
CRYPTO_THREAD_lock_free(md->lock);
|
||||
OPENSSL_free(md);
|
||||
}
|
||||
}
|
||||
int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize)
|
||||
{
|
||||
|
||||
+15
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -19,6 +19,10 @@ struct evp_md_ctx_st {
|
||||
EVP_PKEY_CTX *pctx;
|
||||
/* Update function: usually copied from EVP_MD */
|
||||
int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
|
||||
|
||||
/* Provider ctx */
|
||||
void *provctx;
|
||||
EVP_MD *fetched_digest;
|
||||
} /* EVP_MD_CTX */ ;
|
||||
|
||||
struct evp_cipher_ctx_st {
|
||||
@@ -76,3 +80,13 @@ typedef struct evp_pbe_st EVP_PBE_CTL;
|
||||
DEFINE_STACK_OF(EVP_PBE_CTL)
|
||||
|
||||
int is_partially_overlapping(const void *ptr1, const void *ptr2, int len);
|
||||
|
||||
#include <openssl/ossl_typ.h>
|
||||
#include <openssl/core.h>
|
||||
|
||||
void *evp_generic_fetch(OPENSSL_CTX *ctx, int operation_id,
|
||||
const char *algorithm, const char *properties,
|
||||
void *(*new_method)(int nid, const OSSL_DISPATCH *fns,
|
||||
OSSL_PROVIDER *prov),
|
||||
int (*upref_method)(void *),
|
||||
void (*free_method)(void *));
|
||||
@@ -31,6 +31,7 @@ static const EVP_KDF_METHOD *standard_methods[] = {
|
||||
&tls1_prf_kdf_meth,
|
||||
&hkdf_kdf_meth,
|
||||
&sshkdf_kdf_meth,
|
||||
&ss_kdf_meth
|
||||
};
|
||||
|
||||
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
|
||||
|
||||
@@ -82,6 +82,8 @@ int EVP_MAC_init(EVP_MAC_CTX *ctx)
|
||||
|
||||
int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen)
|
||||
{
|
||||
if (datalen == 0)
|
||||
return 1;
|
||||
return ctx->meth->update(ctx->data, data, datalen);
|
||||
}
|
||||
|
||||
|
||||
@@ -396,6 +396,11 @@ int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
|
||||
pkey->pmeth_engine = e;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey)
|
||||
{
|
||||
return pkey->engine;
|
||||
}
|
||||
#endif
|
||||
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
|
||||
{
|
||||
|
||||
@@ -52,6 +52,10 @@ int EVP_PBE_scrypt(const char *pass, size_t passlen,
|
||||
pass = empty;
|
||||
passlen = 0;
|
||||
}
|
||||
if (salt == NULL) {
|
||||
salt = (const unsigned char *)empty;
|
||||
saltlen = 0;
|
||||
}
|
||||
if (maxmem == 0)
|
||||
maxmem = SCRYPT_MAX_MEM;
|
||||
|
||||
|
||||
@@ -231,9 +231,9 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
int rv;
|
||||
|
||||
if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
|
||||
ctx->engine)) < 0
|
||||
ctx->engine)) <= 0
|
||||
|| (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_CIPHER,
|
||||
p2)) < 0
|
||||
p2)) <= 0
|
||||
|| !(rv = EVP_MAC_init(hctx->ctx)))
|
||||
return rv;
|
||||
}
|
||||
@@ -275,7 +275,7 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
return 0;
|
||||
break;
|
||||
case MAC_TYPE_MAC:
|
||||
if (!EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, p2, p1))
|
||||
if (EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, p2, p1) <= 0)
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
@@ -296,11 +296,11 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
(ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
|
||||
|
||||
if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
|
||||
ctx->engine)) < 0
|
||||
ctx->engine)) <= 0
|
||||
|| (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_MD,
|
||||
hctx->raw_data.md)) < 0
|
||||
hctx->raw_data.md)) <= 0
|
||||
|| (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY,
|
||||
key->data, key->length)) < 0)
|
||||
key->data, key->length)) <= 0)
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user