Commit 3653d0c2 authored by Matt Caswell's avatar Matt Caswell
Browse files

Implement EVP_MD_fetch()

parent 8a73348b
Loading
Loading
Loading
Loading
+92 −0
Original line number Diff line number Diff line
@@ -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 */
@@ -296,3 +297,94 @@ 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;

    if ((md = EVP_MD_meth_new(mdtype, NID_undef)) == NULL)
        return NULL;

    for (; fns->function_id != 0; fns++) {
        int fncnt = 0;

        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_CLEANCTX:
            if (md->cleanctx != NULL)
                break;
            md->cleanctx = OSSL_get_OP_digest_cleanctx(fns);
            fncnt++;
            break;
        case OSSL_FUNC_DIGEST_FREECTX:
            if (md->freectx != NULL)
                break;
            md->freectx = OSSL_get_OP_digest_freectx(fns);
            fncnt++;
            break;
        }
        if ((fncnt != 0 && fncnt != 6) || (fncnt == 0 && md->digest == 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);
}
+26 −1
Original line number Diff line number Diff line
@@ -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)
@@ -331,6 +332,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,10 +349,28 @@ 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)
{
    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)
{
    md->block_size = blocksize;
+18 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
 */

#include <openssl/evp.h>
#include <openssl/core_numbers.h>
#include "internal/refcount.h"

/*
@@ -172,7 +173,11 @@ extern const EVP_KDF_METHOD sshkdf_kdf_meth;
extern const EVP_KDF_METHOD ss_kdf_meth;

struct evp_md_st {
    /* nid */
    int type;

    /* Legacy structure members */
    /* TODO(3.0): Remove these */
    int pkey_type;
    int md_size;
    unsigned long flags;
@@ -185,6 +190,19 @@ struct evp_md_st {
    int ctx_size;               /* how big does the ctx->md_data need to be */
    /* control function */
    int (*md_ctrl) (EVP_MD_CTX *ctx, int cmd, int p1, void *p2);

    /* New structure members */
    /* TODO(3.0): Remove above comment when legacy has gone */
    OSSL_PROVIDER *prov;
    CRYPTO_REF_COUNT refcnt;
    CRYPTO_RWLOCK *lock;
    OSSL_OP_digest_newctx_fn *newctx;
    OSSL_OP_digest_init_fn *dinit;
    OSSL_OP_digest_update_fn *dupdate;
    OSSL_OP_digest_final_fn *dfinal;
    OSSL_OP_digest_digest_fn *digest;
    OSSL_OP_digest_freectx_fn *freectx;

} /* EVP_MD */ ;

struct evp_cipher_st {
+22 −0
Original line number Diff line number Diff line
@@ -72,6 +72,28 @@ OSSL_CORE_MAKE_FUNC(const OSSL_ALGORITHM *,provider_query_operation,
                    (const OSSL_PROVIDER *, int operation_id,
                     const int *no_store))

/* Digests */

# define OSSL_OP_DIGEST                     1

# define OSSL_FUNC_DIGEST_NEWCTX            1
# define OSSL_FUNC_DIGEST_INIT              2
# define OSSL_FUNC_DIGEST_UPDDATE           3
# define OSSL_FUNC_DIGEST_FINAL             4
# define OSSL_FUNC_DIGEST_DIGEST            5
# define OSSL_FUNC_DIGEST_FREECTX           6

OSSL_CORE_MAKE_FUNC(void *, OP_digest_newctx, (void))
OSSL_CORE_MAKE_FUNC(int, OP_digest_init, (void *vctx))
OSSL_CORE_MAKE_FUNC(int, OP_digest_update,
                    (void *vctx, unsigned char *in, size_t inl))
OSSL_CORE_MAKE_FUNC(int, OP_digest_final,
                    (void *vctx, unsigned char *out, size_t *outl))
OSSL_CORE_MAKE_FUNC(int, OP_digest_digest,
                    (unsigned char *in, size_t inl, unsigned char *out,
                     size_t *out_l))
OSSL_CORE_MAKE_FUNC(void, OP_digest_cleanctx, (void *vctx))
OSSL_CORE_MAKE_FUNC(void, OP_digest_freectx, (void *vctx))

# ifdef __cplusplus
}
+4 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ extern "C" {
# ifndef EVP_MD
EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type);
EVP_MD *EVP_MD_meth_dup(const EVP_MD *md);
int EVP_MD_upref(EVP_MD *md);
void EVP_MD_meth_free(EVP_MD *md);

int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize);
@@ -561,6 +562,9 @@ __owur int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md,
__owur int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md,
                              size_t len);

__owur EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
                            const char *properties);

int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify);
int EVP_read_pw_string_min(char *buf, int minlen, int maxlen,
                           const char *prompt, int verify);
Loading