LIBS=../../libcrypto
-$COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c
+$COMMON=digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c evp_utils.c
SOURCE[../../libcrypto]=$COMMON\
encode.c evp_key.c evp_cnf.c \
e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
{
+ int ok = evp_do_param(c->cipher, &keylen, sizeof(keylen),
+ OSSL_CIPHER_PARAM_KEYLEN, OSSL_PARAM_INTEGER,
+ evp_do_ciph_ctx_setparams, c->provctx);
+
+ if (ok != -2)
+ return ok;
+
+ /* TODO(3.0) legacy code follows */
if (c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH)
return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL);
if (EVP_CIPHER_CTX_key_length(c) == keylen)
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
{
+ int ok;
+
if (pad)
ctx->flags &= ~EVP_CIPH_NO_PADDING;
else
ctx->flags |= EVP_CIPH_NO_PADDING;
- if (ctx->cipher != NULL && ctx->cipher->prov != NULL) {
- OSSL_PARAM params[] = {
- OSSL_PARAM_int(OSSL_CIPHER_PARAM_PADDING, NULL),
- OSSL_PARAM_END
- };
-
- params[0].data = &pad;
-
- if (ctx->cipher->ctx_set_params == NULL) {
- EVPerr(EVP_F_EVP_CIPHER_CTX_SET_PADDING, EVP_R_CTRL_NOT_IMPLEMENTED);
- return 0;
- }
-
- if (!ctx->cipher->ctx_set_params(ctx->provctx, params))
- return 0;
- }
-
- return 1;
+ ok = evp_do_param(ctx->cipher, &pad, sizeof(pad),
+ OSSL_CIPHER_PARAM_PADDING, OSSL_PARAM_INTEGER,
+ evp_do_ciph_ctx_setparams, ctx->provctx);
+ return ok != 0;
}
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
{
- int ret;
+ int ret = -2; /* Unsupported */
if (!ctx->cipher) {
EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET);
return 0;
}
+ if (ctx->cipher->prov == NULL)
+ goto legacy;
+
+ switch (type) {
+ case EVP_CTRL_SET_KEY_LENGTH:
+ ret = evp_do_param(ctx->cipher, &arg, sizeof(arg),
+ OSSL_CIPHER_PARAM_KEYLEN, OSSL_PARAM_INTEGER,
+ evp_do_ciph_ctx_setparams, ctx->provctx);
+ break;
+ case EVP_CTRL_GET_IV:
+ ret = evp_do_param(ctx->cipher, ptr, arg,
+ OSSL_CIPHER_PARAM_IV, OSSL_PARAM_OCTET_STRING,
+ evp_do_ciph_ctx_getparams, ctx->provctx);
+ break;
+ case EVP_CTRL_RAND_KEY: /* Used by DES */
+ case EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS: /* Used by DASYNC */
+ case EVP_CTRL_INIT: /* TODO(3.0) Purely legacy, no provider counterpart */
+ ret = -2; /* Unsupported */
+ break;
+ }
+ return ret;
+
+ legacy:
if (!ctx->cipher->ctrl) {
EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED);
return 0;
break;
cipher->dupctx = OSSL_get_OP_cipher_dupctx(fns);
break;
- case OSSL_FUNC_CIPHER_KEY_LENGTH:
- if (cipher->key_length != NULL)
- break;
- cipher->key_length = OSSL_get_OP_cipher_key_length(fns);
- break;
- case OSSL_FUNC_CIPHER_IV_LENGTH:
- if (cipher->iv_length != NULL)
- break;
- cipher->iv_length = OSSL_get_OP_cipher_iv_length(fns);
- break;
- case OSSL_FUNC_CIPHER_BLOCK_SIZE:
- if (cipher->blocksize != NULL)
- break;
- cipher->blocksize = OSSL_get_OP_cipher_block_size(fns);
- break;
case OSSL_FUNC_CIPHER_GET_PARAMS:
if (cipher->get_params != NULL)
break;
}
if ((fnciphcnt != 0 && fnciphcnt != 3 && fnciphcnt != 4)
|| (fnciphcnt == 0 && cipher->ccipher == NULL)
- || fnctxcnt != 2
- || cipher->blocksize == NULL
- || cipher->iv_length == NULL
- || cipher->key_length == NULL) {
+ || fnctxcnt != 2) {
/*
* In order to be a consistent set of functions we must have at least
* a complete set of "encrypt" functions, or a complete set of "decrypt"
int EVP_CIPHER_block_size(const EVP_CIPHER *cipher)
{
- if (cipher->prov != NULL) {
- if (cipher->blocksize != NULL)
- return cipher->blocksize();
- /* We default to a block size of 1 */
- return 1;
- }
- return cipher->block_size;
+ int v = cipher->block_size;
+ int ok = evp_do_param(cipher, &v, sizeof(v),
+ OSSL_CIPHER_PARAM_BLOCK_SIZE, OSSL_PARAM_INTEGER,
+ evp_do_ciph_getparams, NULL);
+
+ return ok != 0 ? v : -1;
}
int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx)
unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher)
{
- return cipher->flags;
+ unsigned long v = cipher->flags;
+ int ok = evp_do_param(cipher, &v, sizeof(v),
+ OSSL_CIPHER_PARAM_FLAGS, OSSL_PARAM_UNSIGNED_INTEGER,
+ evp_do_ciph_getparams, NULL);
+
+ return ok != 0 ? v : 0;
}
void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx)
int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher)
{
- if (cipher->prov != NULL) {
- if (cipher->iv_length != NULL)
- return (int)cipher->iv_length();
- return 0;
- }
+ int v = cipher->iv_len;
+ int ok = evp_do_param(cipher, &v, sizeof(v),
+ OSSL_CIPHER_PARAM_IVLEN, OSSL_PARAM_UNSIGNED_INTEGER,
+ evp_do_ciph_getparams, NULL);
- return cipher->iv_len;
+ return ok != 0 ? v: -1;
}
int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx)
return ctx->oiv;
}
+/*
+ * OSSL_PARAM_OCTET_PTR gets us the pointer to the running IV in the provider
+ */
const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx)
{
- return ctx->iv;
+ const unsigned char *v = ctx->iv;
+ int ok = evp_do_param(ctx->cipher, &v, sizeof(ctx->iv),
+ OSSL_CIPHER_PARAM_IV, OSSL_PARAM_OCTET_PTR,
+ evp_do_ciph_ctx_getparams, ctx->provctx);
+
+ return ok != 0 ? v: NULL;
}
unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx)
{
- return ctx->iv;
+ unsigned char *v = ctx->iv;
+ int ok = evp_do_param(ctx->cipher, &v, sizeof(ctx->iv),
+ OSSL_CIPHER_PARAM_IV, OSSL_PARAM_OCTET_PTR,
+ evp_do_ciph_ctx_getparams, ctx->provctx);
+
+ return ok != 0 ? v: NULL;
}
unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx)
int EVP_CIPHER_CTX_num(const EVP_CIPHER_CTX *ctx)
{
- return ctx->num;
+ int v = ctx->num;
+ int ok = evp_do_param(ctx->cipher, &v, sizeof(v),
+ OSSL_CIPHER_PARAM_NUM, OSSL_PARAM_INTEGER,
+ evp_do_ciph_ctx_getparams, ctx->provctx);
+
+ return ok != 0 ? v: -1;
}
-void EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num)
+int EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num)
{
+ int ok = evp_do_param(ctx->cipher, &num, sizeof(num),
+ OSSL_CIPHER_PARAM_NUM, OSSL_PARAM_INTEGER,
+ evp_do_ciph_ctx_setparams, ctx->provctx);
+
ctx->num = num;
+ return ok != 0;
}
int EVP_CIPHER_key_length(const EVP_CIPHER *cipher)
{
- if (cipher->prov != NULL) {
- if (cipher->key_length != NULL)
- return (int)cipher->key_length();
- return -1;
- }
+ int v = cipher->key_len;
+ int ok = evp_do_param(cipher, &v, sizeof(v),
+ OSSL_CIPHER_PARAM_KEYLEN, OSSL_PARAM_INTEGER,
+ evp_do_ciph_getparams, NULL);
- return cipher->key_len;
+ return ok != 0 ? v: -1;
}
int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx)
{
- /*
- * TODO(3.0): This may need to change if/when we introduce variable length
- * key ciphers into the providers.
- */
- if (ctx->cipher != NULL && ctx->cipher->prov != NULL)
- return EVP_CIPHER_key_length(ctx->cipher);
- return ctx->key_len;
+ int v = ctx->key_len;
+ int ok = evp_do_param(ctx->cipher, &v, sizeof(v),
+ OSSL_CIPHER_PARAM_KEYLEN, OSSL_PARAM_INTEGER,
+ evp_do_ciph_ctx_getparams, ctx->provctx);
+
+ return ok != 0 ? v: -1;
}
int EVP_CIPHER_nid(const EVP_CIPHER *cipher)
int EVP_CIPHER_mode(const EVP_CIPHER *cipher)
{
- if (cipher->prov != NULL) {
- int mode;
+ int v = EVP_CIPHER_flags(cipher) & EVP_CIPH_MODE;
+ int ok = evp_do_param(cipher, &v, sizeof(v),
+ OSSL_CIPHER_PARAM_MODE, OSSL_PARAM_INTEGER,
+ evp_do_ciph_getparams, NULL);
- /* Cipher comes from a provider - so ask the provider for the mode */
- OSSL_PARAM params[] = {
- OSSL_PARAM_int(OSSL_CIPHER_PARAM_MODE, NULL),
- OSSL_PARAM_END
- };
-
- params[0].data = &mode;
-
- if (cipher->get_params == NULL) {
- EVPerr(EVP_F_EVP_CIPHER_MODE, EVP_R_CTRL_NOT_IMPLEMENTED);
- return 0;
- }
-
- if (!cipher->get_params(params))
- return 0;
-
- return mode;
- }
- return EVP_CIPHER_flags(cipher) & EVP_CIPH_MODE;
+ return ok != 0 ? v: 0;
}
OSSL_PROVIDER *prov),
int (*up_ref_method)(void *),
void (*free_method)(void *));
+
+/* Helper functions to avoid duplicating code */
+
+/*
+ * The callbacks implement different ways to pass a params array to the
+ * provider. They will return one of these values:
+ *
+ * -2 if the method doesn't come from a provider
+ * (evp_do_param will return this to the called)
+ * -1 if the provider doesn't offer the desired function
+ * (evp_do_param will raise an error and return 0)
+ * or the return value from the desired function
+ * (evp_do_param will return it to the caller)
+ */
+int evp_do_ciph_getparams(const void *vciph, void *ignored,
+ OSSL_PARAM params[]);
+int evp_do_ciph_ctx_getparams(const void *vciph, void *provctx,
+ OSSL_PARAM params[]);
+int evp_do_ciph_ctx_setparams(const void *vciph, void *provctx,
+ OSSL_PARAM params[]);
+
+/*-
+ * prepares a singular parameter, then calls the callback to execute.
+ *
+ * |method| points to the method used by the callback.
+ * EVP_CIPHER, EVP_MD, ...
+ * |ptr| points at the data to transfer.
+ * |sz| is the size of the data to transfer.
+ * |key| is the name of the parameter to pass.
+ * |datatype| is the data type of the parameter to pass.
+ * |cb| is the callback that actually performs the parameter passing
+ * |cb_ctx| is the cipher context
+ */
+int evp_do_param(const void *method, void *ptr, size_t sz, const char *key,
+ int datatype,
+ int (*cb)(const void *method, void *ctx, OSSL_PARAM params[]),
+ void *cb_ctx);
--- /dev/null
+/*
+ * 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
+ */
+
+/* Internal EVP utility functions */
+
+#include <openssl/core.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/asn1.h> /* evp_locl.h needs it */
+#include <openssl/safestack.h> /* evp_locl.h needs it */
+#include "internal/evp_int.h" /* evp_locl.h needs it */
+#include "evp_locl.h"
+
+int evp_do_ciph_getparams(const void *vciph, void *ignored,
+ OSSL_PARAM params[])
+{
+ const EVP_CIPHER *ciph = vciph;
+
+ if (ciph->prov == NULL)
+ return -2;
+ if (ciph->get_params == NULL)
+ return -1;
+ return ciph->get_params(params);
+}
+
+int evp_do_ciph_ctx_getparams(const void *vciph, void *provctx,
+ OSSL_PARAM params[])
+{
+ const EVP_CIPHER *ciph = vciph;
+
+ if (ciph->prov == NULL)
+ return -2;
+ if (ciph->ctx_get_params == NULL)
+ return -1;
+ return ciph->ctx_get_params(provctx, params);
+}
+
+int evp_do_ciph_ctx_setparams(const void *vciph, void *provctx,
+ OSSL_PARAM params[])
+{
+ const EVP_CIPHER *ciph = vciph;
+
+ if (ciph->prov == NULL)
+ return -2;
+ if (ciph->ctx_set_params == NULL)
+ return -1;
+ return ciph->ctx_set_params(provctx, params);
+}
+
+int evp_do_param(const void *method, void *ptr, size_t sz, const char *key,
+ int datatype,
+ int (*cb)(const void *method, void *ctx, OSSL_PARAM params[]),
+ void *cb_ctx)
+{
+ OSSL_PARAM params[2] = {
+ OSSL_PARAM_END,
+ OSSL_PARAM_END
+ };
+ int ret;
+
+ params[0].key = key;
+ params[0].data_type = datatype;
+ params[0].data = ptr;
+ params[0].data_size = sz;
+
+ ret = cb(method, cb_ctx, params);
+ if (ret == -1) {
+ EVPerr(0, EVP_R_CTRL_NOT_IMPLEMENTED);
+ ret = 0;
+ }
+ return ret;
+}
unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx);
unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_num(const EVP_CIPHER_CTX *ctx);
-void EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num);
+int EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num);
int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in);
void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data);