Latest update
This commit is contained in:
@@ -17,7 +17,8 @@
|
||||
|
||||
# include <unistd.h>
|
||||
|
||||
# if _POSIX_VERSION >= 200112L
|
||||
# if _POSIX_VERSION >= 200112L \
|
||||
&& (_POSIX_VERSION < 200809L || defined(__GLIBC__))
|
||||
|
||||
# include <pthread.h>
|
||||
|
||||
|
||||
+1
-1
@@ -1077,7 +1077,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
* is not only slower but also makes each bit vulnerable to
|
||||
* EM (and likely other) side-channel attacks like One&Done
|
||||
* (for details see "One&Done: A Single-Decryption EM-Based
|
||||
* Attack on OpenSSL’s Constant-Time Blinded RSA" by M. Alam,
|
||||
* Attack on OpenSSL's Constant-Time Blinded RSA" by M. Alam,
|
||||
* H. Khan, M. Dey, N. Sinha, R. Callan, A. Zajic, and
|
||||
* M. Prvulovic, in USENIX Security'18)
|
||||
*/
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]=cmac.c cm_ameth.c cm_pmeth.c
|
||||
SOURCE[../../libcrypto]=cmac.c cm_ameth.c cm_meth.c
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/cmac.h>
|
||||
#include "internal/asn1_int.h"
|
||||
|
||||
/*
|
||||
@@ -25,8 +24,8 @@ static int cmac_size(const EVP_PKEY *pkey)
|
||||
|
||||
static void cmac_key_free(EVP_PKEY *pkey)
|
||||
{
|
||||
CMAC_CTX *cmctx = EVP_PKEY_get0(pkey);
|
||||
CMAC_CTX_free(cmctx);
|
||||
EVP_MAC_CTX *cmctx = EVP_PKEY_get0(pkey);
|
||||
EVP_MAC_CTX_free(cmctx);
|
||||
}
|
||||
|
||||
const EVP_PKEY_ASN1_METHOD cmac_asn1_meth = {
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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 <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/cmac.h>
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
/* local CMAC pkey structure */
|
||||
|
||||
/* typedef EVP_MAC_IMPL */
|
||||
struct evp_mac_impl_st {
|
||||
/* tmpcipher and tmpengine are set to NULL after a CMAC_Init call */
|
||||
const EVP_CIPHER *tmpcipher; /* cached CMAC cipher */
|
||||
const ENGINE *tmpengine; /* cached CMAC cipher engine */
|
||||
CMAC_CTX *ctx;
|
||||
};
|
||||
|
||||
static EVP_MAC_IMPL *cmac_new(void)
|
||||
{
|
||||
EVP_MAC_IMPL *cctx;
|
||||
|
||||
if ((cctx = OPENSSL_zalloc(sizeof(*cctx))) == NULL
|
||||
|| (cctx->ctx = CMAC_CTX_new()) == NULL) {
|
||||
OPENSSL_free(cctx);
|
||||
cctx = NULL;
|
||||
}
|
||||
|
||||
return cctx;
|
||||
}
|
||||
|
||||
static void cmac_free(EVP_MAC_IMPL *cctx)
|
||||
{
|
||||
if (cctx != NULL) {
|
||||
CMAC_CTX_free(cctx->ctx);
|
||||
OPENSSL_free(cctx);
|
||||
}
|
||||
}
|
||||
|
||||
static int cmac_copy(EVP_MAC_IMPL *cdst, EVP_MAC_IMPL *csrc)
|
||||
{
|
||||
if (!CMAC_CTX_copy(cdst->ctx, csrc->ctx))
|
||||
return 0;
|
||||
|
||||
cdst->tmpengine = csrc->tmpengine;
|
||||
cdst->tmpcipher = csrc->tmpcipher;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t cmac_size(EVP_MAC_IMPL *cctx)
|
||||
{
|
||||
return EVP_CIPHER_CTX_block_size(CMAC_CTX_get0_cipher_ctx(cctx->ctx));
|
||||
}
|
||||
|
||||
static int cmac_init(EVP_MAC_IMPL *cctx)
|
||||
{
|
||||
int rv = CMAC_Init(cctx->ctx, NULL, 0, cctx->tmpcipher,
|
||||
(ENGINE *)cctx->tmpengine);
|
||||
cctx->tmpcipher = NULL;
|
||||
cctx->tmpengine = NULL;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int cmac_update(EVP_MAC_IMPL *cctx, const unsigned char *data,
|
||||
size_t datalen)
|
||||
{
|
||||
return CMAC_Update(cctx->ctx, data, datalen);
|
||||
}
|
||||
|
||||
static int cmac_final(EVP_MAC_IMPL *cctx, unsigned char *out)
|
||||
{
|
||||
size_t hlen;
|
||||
|
||||
return CMAC_Final(cctx->ctx, out, &hlen);
|
||||
}
|
||||
|
||||
static int cmac_ctrl(EVP_MAC_IMPL *cctx, int cmd, va_list args)
|
||||
{
|
||||
switch (cmd) {
|
||||
case EVP_MAC_CTRL_SET_KEY:
|
||||
{
|
||||
const unsigned char *key = va_arg(args, const unsigned char *);
|
||||
size_t keylen = va_arg(args, size_t);
|
||||
int rv = CMAC_Init(cctx->ctx, key, keylen, cctx->tmpcipher,
|
||||
(ENGINE *)cctx->tmpengine);
|
||||
|
||||
cctx->tmpcipher = NULL;
|
||||
cctx->tmpengine = NULL;
|
||||
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
case EVP_MAC_CTRL_SET_CIPHER:
|
||||
cctx->tmpcipher = va_arg(args, const EVP_CIPHER *);
|
||||
break;
|
||||
case EVP_MAC_CTRL_SET_ENGINE:
|
||||
cctx->tmpengine = va_arg(args, const ENGINE *);
|
||||
break;
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cmac_ctrl_int(EVP_MAC_IMPL *hctx, int cmd, ...)
|
||||
{
|
||||
int rv;
|
||||
va_list args;
|
||||
|
||||
va_start(args, cmd);
|
||||
rv = cmac_ctrl(hctx, cmd, args);
|
||||
va_end(args);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int cmac_ctrl_str_cb(void *hctx, int cmd, void *buf, size_t buflen)
|
||||
{
|
||||
return cmac_ctrl_int(hctx, cmd, buf, buflen);
|
||||
}
|
||||
|
||||
static int cmac_ctrl_str(EVP_MAC_IMPL *cctx, const char *type,
|
||||
const char *value)
|
||||
{
|
||||
if (!value)
|
||||
return 0;
|
||||
if (strcmp(type, "cipher") == 0) {
|
||||
const EVP_CIPHER *c = EVP_get_cipherbyname(value);
|
||||
|
||||
if (c == NULL)
|
||||
return 0;
|
||||
return cmac_ctrl_int(cctx, EVP_MAC_CTRL_SET_CIPHER, c);
|
||||
}
|
||||
if (strcmp(type, "key") == 0)
|
||||
return EVP_str2ctrl(cmac_ctrl_str_cb, cctx, EVP_MAC_CTRL_SET_KEY,
|
||||
value);
|
||||
if (strcmp(type, "hexkey") == 0)
|
||||
return EVP_hex2ctrl(cmac_ctrl_str_cb, cctx, EVP_MAC_CTRL_SET_KEY,
|
||||
value);
|
||||
return -2;
|
||||
}
|
||||
|
||||
const EVP_MAC cmac_meth = {
|
||||
EVP_MAC_CMAC,
|
||||
cmac_new,
|
||||
cmac_copy,
|
||||
cmac_free,
|
||||
cmac_size,
|
||||
cmac_init,
|
||||
cmac_update,
|
||||
cmac_final,
|
||||
cmac_ctrl,
|
||||
cmac_ctrl_str
|
||||
};
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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 <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/cmac.h>
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
/* The context structure and "key" is simply a CMAC_CTX */
|
||||
|
||||
static int pkey_cmac_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
ctx->data = CMAC_CTX_new();
|
||||
if (ctx->data == NULL)
|
||||
return 0;
|
||||
ctx->keygen_info_count = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_cmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
||||
{
|
||||
if (!pkey_cmac_init(dst))
|
||||
return 0;
|
||||
if (!CMAC_CTX_copy(dst->data, src->data))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pkey_cmac_cleanup(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
CMAC_CTX_free(ctx->data);
|
||||
}
|
||||
|
||||
static int pkey_cmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
CMAC_CTX *cmkey = CMAC_CTX_new();
|
||||
CMAC_CTX *cmctx = ctx->data;
|
||||
if (cmkey == NULL)
|
||||
return 0;
|
||||
if (!CMAC_CTX_copy(cmkey, cmctx)) {
|
||||
CMAC_CTX_free(cmkey);
|
||||
return 0;
|
||||
}
|
||||
EVP_PKEY_assign(pkey, EVP_PKEY_CMAC, cmkey);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
|
||||
{
|
||||
if (!CMAC_Update(EVP_MD_CTX_pkey_ctx(ctx)->data, data, count))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
|
||||
{
|
||||
EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
|
||||
EVP_MD_CTX_set_update_fn(mctx, int_update);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
|
||||
EVP_MD_CTX *mctx)
|
||||
{
|
||||
return CMAC_Final(ctx->data, sig, siglen);
|
||||
}
|
||||
|
||||
static int pkey_cmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
{
|
||||
CMAC_CTX *cmctx = ctx->data;
|
||||
switch (type) {
|
||||
|
||||
case EVP_PKEY_CTRL_SET_MAC_KEY:
|
||||
if (!p2 || p1 < 0)
|
||||
return 0;
|
||||
if (!CMAC_Init(cmctx, p2, p1, NULL, NULL))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_CIPHER:
|
||||
if (!CMAC_Init(cmctx, NULL, 0, p2, ctx->engine))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_MD:
|
||||
if (ctx->pkey && !CMAC_CTX_copy(ctx->data,
|
||||
(CMAC_CTX *)ctx->pkey->pkey.ptr))
|
||||
return 0;
|
||||
if (!CMAC_Init(cmctx, NULL, 0, NULL, NULL))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_cmac_ctrl_str(EVP_PKEY_CTX *ctx,
|
||||
const char *type, const char *value)
|
||||
{
|
||||
if (!value) {
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(type, "cipher") == 0) {
|
||||
const EVP_CIPHER *c;
|
||||
c = EVP_get_cipherbyname(value);
|
||||
if (!c)
|
||||
return 0;
|
||||
return pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_CIPHER, -1, (void *)c);
|
||||
}
|
||||
if (strcmp(type, "key") == 0)
|
||||
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
|
||||
if (strcmp(type, "hexkey") == 0)
|
||||
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
|
||||
return -2;
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD cmac_pkey_meth = {
|
||||
EVP_PKEY_CMAC,
|
||||
EVP_PKEY_FLAG_SIGCTX_CUSTOM,
|
||||
pkey_cmac_init,
|
||||
pkey_cmac_copy,
|
||||
pkey_cmac_cleanup,
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
pkey_cmac_keygen,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
cmac_signctx_init,
|
||||
cmac_signctx,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_cmac_ctrl,
|
||||
pkey_cmac_ctrl_str
|
||||
};
|
||||
@@ -327,6 +327,12 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
|
||||
if (mctx == NULL)
|
||||
goto err;
|
||||
|
||||
/* make sure L > N, otherwise we'll get trapped in an infinite loop */
|
||||
if (L <= N) {
|
||||
DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (evpmd == NULL) {
|
||||
if (N == 160)
|
||||
evpmd = EVP_sha1();
|
||||
|
||||
+46
-14
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/bn_int.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/sha.h>
|
||||
#include "dsa_locl.h"
|
||||
@@ -23,6 +24,8 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
|
||||
DSA_SIG *sig, DSA *dsa);
|
||||
static int dsa_init(DSA *dsa);
|
||||
static int dsa_finish(DSA *dsa);
|
||||
static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q,
|
||||
BN_CTX *ctx);
|
||||
|
||||
static DSA_METHOD openssl_dsa_meth = {
|
||||
"OpenSSL DSA method",
|
||||
@@ -178,9 +181,9 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
|
||||
{
|
||||
BN_CTX *ctx = NULL;
|
||||
BIGNUM *k, *kinv = NULL, *r = *rp;
|
||||
BIGNUM *l, *m;
|
||||
BIGNUM *l;
|
||||
int ret = 0;
|
||||
int q_bits;
|
||||
int q_bits, q_words;
|
||||
|
||||
if (!dsa->p || !dsa->q || !dsa->g) {
|
||||
DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PARAMETERS);
|
||||
@@ -189,8 +192,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
|
||||
|
||||
k = BN_new();
|
||||
l = BN_new();
|
||||
m = BN_new();
|
||||
if (k == NULL || l == NULL || m == NULL)
|
||||
if (k == NULL || l == NULL)
|
||||
goto err;
|
||||
|
||||
if (ctx_in == NULL) {
|
||||
@@ -201,9 +203,9 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
|
||||
|
||||
/* Preallocate space */
|
||||
q_bits = BN_num_bits(dsa->q);
|
||||
if (!BN_set_bit(k, q_bits)
|
||||
|| !BN_set_bit(l, q_bits)
|
||||
|| !BN_set_bit(m, q_bits))
|
||||
q_words = bn_get_top(dsa->q);
|
||||
if (!bn_wexpand(k, q_words + 2)
|
||||
|| !bn_wexpand(l, q_words + 2))
|
||||
goto err;
|
||||
|
||||
/* Get random k */
|
||||
@@ -238,14 +240,17 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
|
||||
* small timing information leakage. We then choose the sum that is
|
||||
* one bit longer than the modulus.
|
||||
*
|
||||
* TODO: revisit the BN_copy aiming for a memory access agnostic
|
||||
* conditional copy.
|
||||
* There are some concerns about the efficacy of doing this. More
|
||||
* specificly refer to the discussion starting with:
|
||||
* https://github.com/openssl/openssl/pull/7486#discussion_r228323705
|
||||
* The fix is to rework BN so these gymnastics aren't required.
|
||||
*/
|
||||
if (!BN_add(l, k, dsa->q)
|
||||
|| !BN_add(m, l, dsa->q)
|
||||
|| !BN_copy(k, BN_num_bits(l) > q_bits ? l : m))
|
||||
|| !BN_add(k, l, dsa->q))
|
||||
goto err;
|
||||
|
||||
BN_consttime_swap(BN_is_bit_set(l, q_bits), k, l, q_words + 2);
|
||||
|
||||
if ((dsa)->meth->bn_mod_exp != NULL) {
|
||||
if (!dsa->meth->bn_mod_exp(dsa, r, dsa->g, k, dsa->p, ctx,
|
||||
dsa->method_mont_p))
|
||||
@@ -258,8 +263,8 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
|
||||
if (!BN_mod(r, r, dsa->q, ctx))
|
||||
goto err;
|
||||
|
||||
/* Compute part of 's = inv(k) (m + xr) mod q' */
|
||||
if ((kinv = BN_mod_inverse(NULL, k, dsa->q, ctx)) == NULL)
|
||||
/* Compute part of 's = inv(k) (m + xr) mod q' */
|
||||
if ((kinv = dsa_mod_inverse_fermat(k, dsa->q, ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
BN_clear_free(*kinvp);
|
||||
@@ -273,7 +278,6 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
|
||||
BN_CTX_free(ctx);
|
||||
BN_clear_free(k);
|
||||
BN_clear_free(l);
|
||||
BN_clear_free(m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -393,3 +397,31 @@ static int dsa_finish(DSA *dsa)
|
||||
BN_MONT_CTX_free(dsa->method_mont_p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the inverse of k modulo q.
|
||||
* Since q is prime, Fermat's Little Theorem applies, which reduces this to
|
||||
* mod-exp operation. Both the exponent and modulus are public information
|
||||
* so a mod-exp that doesn't leak the base is sufficient. A newly allocated
|
||||
* BIGNUM is returned which the caller must free.
|
||||
*/
|
||||
static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *res = NULL;
|
||||
BIGNUM *r, *e;
|
||||
|
||||
if ((r = BN_new()) == NULL)
|
||||
return NULL;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if ((e = BN_CTX_get(ctx)) != NULL
|
||||
&& BN_set_word(r, 2)
|
||||
&& BN_sub(e, q, r)
|
||||
&& BN_mod_exp_mont(r, k, e, q, ctx, NULL))
|
||||
res = r;
|
||||
else
|
||||
BN_free(r);
|
||||
BN_CTX_end(ctx);
|
||||
return res;
|
||||
}
|
||||
@@ -699,7 +699,7 @@ static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
|
||||
if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
|
||||
return 0;
|
||||
|
||||
if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_62) <= 0)
|
||||
if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0)
|
||||
return 0;
|
||||
|
||||
kdf_md = EVP_get_digestbynid(kdfmd_nid);
|
||||
@@ -864,7 +864,7 @@ static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
|
||||
ecdh_nid = NID_dh_cofactor_kdf;
|
||||
|
||||
if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
|
||||
kdf_type = EVP_PKEY_ECDH_KDF_X9_62;
|
||||
kdf_type = EVP_PKEY_ECDH_KDF_X9_63;
|
||||
if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
|
||||
goto err;
|
||||
} else
|
||||
|
||||
+3
-3
@@ -206,8 +206,8 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
|
||||
*/
|
||||
cardinality_bits = BN_num_bits(cardinality);
|
||||
group_top = bn_get_top(cardinality);
|
||||
if ((bn_wexpand(k, group_top + 1) == NULL)
|
||||
|| (bn_wexpand(lambda, group_top + 1) == NULL)) {
|
||||
if ((bn_wexpand(k, group_top + 2) == NULL)
|
||||
|| (bn_wexpand(lambda, group_top + 2) == NULL)) {
|
||||
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
@@ -244,7 +244,7 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
|
||||
* k := scalar + 2*cardinality
|
||||
*/
|
||||
kbit = BN_is_bit_set(lambda, cardinality_bits);
|
||||
BN_consttime_swap(kbit, k, lambda, group_top + 1);
|
||||
BN_consttime_swap(kbit, k, lambda, group_top + 2);
|
||||
|
||||
group_top = bn_get_top(group->field);
|
||||
if ((bn_wexpand(s->X, group_top) == NULL)
|
||||
|
||||
@@ -209,7 +209,7 @@ static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx,
|
||||
if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
|
||||
goto err;
|
||||
/* Do KDF stuff */
|
||||
if (!ECDH_KDF_X9_62(key, *keylen, ktmp, ktmplen,
|
||||
if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen,
|
||||
dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
|
||||
goto err;
|
||||
rv = 1;
|
||||
@@ -281,7 +281,7 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
case EVP_PKEY_CTRL_EC_KDF_TYPE:
|
||||
if (p1 == -2)
|
||||
return dctx->kdf_type;
|
||||
if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62)
|
||||
if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63)
|
||||
return -2;
|
||||
dctx->kdf_type = p1;
|
||||
return 1;
|
||||
|
||||
+18
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -10,12 +10,13 @@
|
||||
#include <string.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "ec_lcl.h"
|
||||
|
||||
/* Key derivation function from X9.62/SECG */
|
||||
/* Key derivation function from X9.63/SECG */
|
||||
/* Way more than we will ever need */
|
||||
#define ECDH_KDF_MAX (1 << 30)
|
||||
|
||||
int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
|
||||
int ecdh_KDF_X9_63(unsigned char *out, size_t outlen,
|
||||
const unsigned char *Z, size_t Zlen,
|
||||
const unsigned char *sinfo, size_t sinfolen,
|
||||
const EVP_MD *md)
|
||||
@@ -66,3 +67,17 @@ int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
|
||||
EVP_MD_CTX_free(mctx);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*-
|
||||
* The old name for ecdh_KDF_X9_63
|
||||
* Retained for ABI compatibility
|
||||
*/
|
||||
#if OPENSSL_API_COMPAT < 0x10200000L
|
||||
int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
|
||||
const unsigned char *Z, size_t Zlen,
|
||||
const unsigned char *sinfo, size_t sinfolen,
|
||||
const EVP_MD *md)
|
||||
{
|
||||
return ecdh_KDF_X9_63(out, outlen, Z, Zlen, sinfo, sinfolen, md);
|
||||
}
|
||||
#endif
|
||||
@@ -740,6 +740,11 @@ EVP_F_EVP_DIGESTFINALXOF:174:EVP_DigestFinalXOF
|
||||
EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex
|
||||
EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex
|
||||
EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate
|
||||
EVP_F_EVP_MAC_CTRL:209:EVP_MAC_ctrl
|
||||
EVP_F_EVP_MAC_CTRL_STR:210:EVP_MAC_ctrl_str
|
||||
EVP_F_EVP_MAC_CTX_COPY:211:EVP_MAC_CTX_copy
|
||||
EVP_F_EVP_MAC_CTX_NEW:213:EVP_MAC_CTX_new
|
||||
EVP_F_EVP_MAC_INIT:212:EVP_MAC_init
|
||||
EVP_F_EVP_MD_CTX_COPY_EX:110:EVP_MD_CTX_copy_ex
|
||||
EVP_F_EVP_MD_SIZE:162:EVP_MD_size
|
||||
EVP_F_EVP_OPENINIT:102:EVP_OpenInit
|
||||
@@ -802,6 +807,7 @@ EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen
|
||||
EVP_F_PKCS5_V2_PBE_KEYIVGEN:118:PKCS5_v2_PBE_keyivgen
|
||||
EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN:164:PKCS5_v2_PBKDF2_keyivgen
|
||||
EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN:180:PKCS5_v2_scrypt_keyivgen
|
||||
EVP_F_PKEY_MAC_INIT:214:pkey_mac_init
|
||||
EVP_F_PKEY_SET_TYPE:158:pkey_set_type
|
||||
EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth
|
||||
EVP_F_RC5_CTRL:125:rc5_ctrl
|
||||
|
||||
@@ -12,7 +12,8 @@ SOURCE[../../libcrypto]=\
|
||||
evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
|
||||
e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
|
||||
e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
|
||||
e_chacha20_poly1305.c cmeth_lib.c
|
||||
e_chacha20_poly1305.c cmeth_lib.c \
|
||||
mac_lib.c c_allm.c pkey_mac.c
|
||||
|
||||
INCLUDE[e_aes.o]=.. ../modes
|
||||
INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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 <openssl/evp.h>
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
void openssl_add_all_macs_int(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_CMAC
|
||||
EVP_add_mac(&cmac_meth);
|
||||
#endif
|
||||
EVP_add_mac(&hmac_meth);
|
||||
#ifndef OPENSSL_NO_SIPHASH
|
||||
EVP_add_mac(&siphash_meth);
|
||||
#endif
|
||||
}
|
||||
@@ -54,6 +54,11 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0),
|
||||
"EVP_EncryptFinal_ex"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTUPDATE, 0), "EVP_EncryptUpdate"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL, 0), "EVP_MAC_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL_STR, 0), "EVP_MAC_ctrl_str"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_COPY, 0), "EVP_MAC_CTX_copy"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_NEW, 0), "EVP_MAC_CTX_new"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_INIT, 0), "EVP_MAC_init"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_CTX_COPY_EX, 0), "EVP_MD_CTX_copy_ex"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_SIZE, 0), "EVP_MD_size"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_OPENINIT, 0), "EVP_OpenInit"},
|
||||
@@ -145,6 +150,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
|
||||
"PKCS5_v2_PBKDF2_keyivgen"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, 0),
|
||||
"PKCS5_v2_scrypt_keyivgen"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_MAC_INIT, 0), "pkey_mac_init"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_SET_TYPE, 0), "pkey_set_type"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_RC2_MAGIC_TO_METH, 0), "rc2_magic_to_meth"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_RC5_CTRL, 0), "rc5_ctrl"},
|
||||
|
||||
@@ -526,3 +526,30 @@ int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags)
|
||||
{
|
||||
return (ctx->flags & flags);
|
||||
}
|
||||
|
||||
int EVP_str2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen),
|
||||
void *ctx, int cmd, const char *value)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(value);
|
||||
if (len > INT_MAX)
|
||||
return -1;
|
||||
return cb(ctx, cmd, (void *)value, len);
|
||||
}
|
||||
|
||||
int EVP_hex2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen),
|
||||
void *ctx, int cmd, const char *hex)
|
||||
{
|
||||
unsigned char *bin;
|
||||
long binlen;
|
||||
int rv = -1;
|
||||
|
||||
bin = OPENSSL_hexstr2buf(hex, &binlen);
|
||||
if (bin == NULL)
|
||||
return 0;
|
||||
if (binlen <= INT_MAX)
|
||||
rv = cb(ctx, cmd, bin, binlen);
|
||||
OPENSSL_free(bin);
|
||||
return rv;
|
||||
}
|
||||
@@ -41,6 +41,11 @@ struct evp_cipher_ctx_st {
|
||||
unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */
|
||||
} /* EVP_CIPHER_CTX */ ;
|
||||
|
||||
struct evp_mac_ctx_st {
|
||||
const EVP_MAC *meth; /* Method structure */
|
||||
void *data; /* Individual method data */
|
||||
} /* EVP_MAC_CTX */;
|
||||
|
||||
int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
|
||||
int passlen, ASN1_TYPE *param,
|
||||
const EVP_CIPHER *c, const EVP_MD *md,
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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 <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ossl_typ.h>
|
||||
#include "internal/nelem.h"
|
||||
#include "internal/evp_int.h"
|
||||
#include "evp_locl.h"
|
||||
|
||||
EVP_MAC_CTX *EVP_MAC_CTX_new_id(int id)
|
||||
{
|
||||
const EVP_MAC *mac = EVP_get_macbynid(id);
|
||||
|
||||
if (mac == NULL)
|
||||
return NULL;
|
||||
return EVP_MAC_CTX_new(mac);
|
||||
}
|
||||
|
||||
EVP_MAC_CTX *EVP_MAC_CTX_new(const EVP_MAC *mac)
|
||||
{
|
||||
EVP_MAC_CTX *ctx = OPENSSL_zalloc(sizeof(EVP_MAC_CTX));
|
||||
|
||||
if (ctx == NULL || (ctx->data = mac->new()) == NULL) {
|
||||
EVPerr(EVP_F_EVP_MAC_CTX_NEW, ERR_R_MALLOC_FAILURE);
|
||||
OPENSSL_free(ctx);
|
||||
ctx = NULL;
|
||||
} else {
|
||||
ctx->meth = mac;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx)
|
||||
{
|
||||
if (ctx != NULL && ctx->data != NULL) {
|
||||
ctx->meth->free(ctx->data);
|
||||
ctx->data = NULL;
|
||||
}
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
int EVP_MAC_CTX_copy(EVP_MAC_CTX *dst, EVP_MAC_CTX *src)
|
||||
{
|
||||
EVP_MAC_IMPL *macdata;
|
||||
|
||||
if (src->data != NULL && !dst->meth->copy(dst->data, src->data))
|
||||
return 0;
|
||||
|
||||
macdata = dst->data;
|
||||
*dst = *src;
|
||||
dst->data = macdata;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const EVP_MAC *EVP_MAC_CTX_mac(EVP_MAC_CTX *ctx)
|
||||
{
|
||||
return ctx->meth;
|
||||
}
|
||||
|
||||
size_t EVP_MAC_size(EVP_MAC_CTX *ctx)
|
||||
{
|
||||
if (ctx->data != NULL)
|
||||
return ctx->meth->size(ctx->data);
|
||||
/* If the MAC hasn't been initialized yet, we return zero */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EVP_MAC_init(EVP_MAC_CTX *ctx)
|
||||
{
|
||||
return ctx->meth->init(ctx->data);
|
||||
}
|
||||
|
||||
int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen)
|
||||
{
|
||||
return ctx->meth->update(ctx->data, data, datalen);
|
||||
}
|
||||
|
||||
int EVP_MAC_final(EVP_MAC_CTX *ctx, unsigned char *out, size_t *poutlen)
|
||||
{
|
||||
int l = ctx->meth->size(ctx->data);
|
||||
|
||||
if (l < 0)
|
||||
return 0;
|
||||
if (poutlen != NULL)
|
||||
*poutlen = l;
|
||||
if (out == NULL)
|
||||
return 1;
|
||||
return ctx->meth->final(ctx->data, out);
|
||||
}
|
||||
|
||||
int EVP_MAC_ctrl(EVP_MAC_CTX *ctx, int cmd, ...)
|
||||
{
|
||||
int ok = -1;
|
||||
va_list args;
|
||||
|
||||
va_start(args, cmd);
|
||||
ok = EVP_MAC_vctrl(ctx, cmd, args);
|
||||
va_end(args);
|
||||
|
||||
if (ok == -2)
|
||||
EVPerr(EVP_F_EVP_MAC_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
int EVP_MAC_vctrl(EVP_MAC_CTX *ctx, int cmd, va_list args)
|
||||
{
|
||||
int ok = 1;
|
||||
|
||||
if (ctx == NULL || ctx->meth == NULL)
|
||||
return -2;
|
||||
|
||||
switch (cmd) {
|
||||
#if 0
|
||||
case ...:
|
||||
/* code */
|
||||
ok = 1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
if (ctx->meth->ctrl != NULL)
|
||||
ok = ctx->meth->ctrl(ctx->data, cmd, args);
|
||||
else
|
||||
ok = -2;
|
||||
break;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
int EVP_MAC_ctrl_str(EVP_MAC_CTX *ctx, const char *type, const char *value)
|
||||
{
|
||||
int ok = 1;
|
||||
|
||||
if (ctx == NULL || ctx->meth == NULL || ctx->meth->ctrl_str == NULL) {
|
||||
EVPerr(EVP_F_EVP_MAC_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
|
||||
return -2;
|
||||
}
|
||||
|
||||
ok = ctx->meth->ctrl_str(ctx->data, type, value);
|
||||
|
||||
if (ok == -2)
|
||||
EVPerr(EVP_F_EVP_MAC_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
|
||||
return ok;
|
||||
}
|
||||
|
||||
int EVP_MAC_str2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *value)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(value);
|
||||
if (len > INT_MAX)
|
||||
return -1;
|
||||
return EVP_MAC_ctrl(ctx, cmd, value, len);
|
||||
}
|
||||
|
||||
int EVP_MAC_hex2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *hex)
|
||||
{
|
||||
unsigned char *bin;
|
||||
long binlen;
|
||||
int rv = -1;
|
||||
|
||||
bin = OPENSSL_hexstr2buf(hex, &binlen);
|
||||
if (bin == NULL)
|
||||
return 0;
|
||||
if (binlen <= INT_MAX)
|
||||
rv = EVP_MAC_ctrl(ctx, cmd, bin, (size_t)binlen);
|
||||
OPENSSL_free(bin);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int EVP_MAC_nid(const EVP_MAC *mac)
|
||||
{
|
||||
return mac->type;
|
||||
}
|
||||
+74
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -55,6 +55,22 @@ int EVP_add_digest(const EVP_MD *md)
|
||||
return r;
|
||||
}
|
||||
|
||||
int EVP_add_mac(const EVP_MAC *m)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (m == NULL)
|
||||
return 0;
|
||||
|
||||
r = OBJ_NAME_add(OBJ_nid2sn(m->type), OBJ_NAME_TYPE_MAC_METH,
|
||||
(const char *)m);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
r = OBJ_NAME_add(OBJ_nid2ln(m->type), OBJ_NAME_TYPE_MAC_METH,
|
||||
(const char *)m);
|
||||
return r;
|
||||
}
|
||||
|
||||
const EVP_CIPHER *EVP_get_cipherbyname(const char *name)
|
||||
{
|
||||
const EVP_CIPHER *cp;
|
||||
@@ -77,8 +93,20 @@ const EVP_MD *EVP_get_digestbyname(const char *name)
|
||||
return cp;
|
||||
}
|
||||
|
||||
const EVP_MAC *EVP_get_macbyname(const char *name)
|
||||
{
|
||||
const EVP_MAC *mp;
|
||||
|
||||
if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL))
|
||||
return NULL;
|
||||
|
||||
mp = (const EVP_MAC *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MAC_METH);
|
||||
return mp;
|
||||
}
|
||||
|
||||
void evp_cleanup_int(void)
|
||||
{
|
||||
OBJ_NAME_cleanup(OBJ_NAME_TYPE_MAC_METH);
|
||||
OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH);
|
||||
OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH);
|
||||
/*
|
||||
@@ -178,3 +206,48 @@ void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md,
|
||||
dc.arg = arg;
|
||||
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
|
||||
}
|
||||
|
||||
struct doall_mac {
|
||||
void *arg;
|
||||
void (*fn) (const EVP_MAC *ciph,
|
||||
const char *from, const char *to, void *arg);
|
||||
};
|
||||
|
||||
static void do_all_mac_fn(const OBJ_NAME *nm, void *arg)
|
||||
{
|
||||
struct doall_mac *dc = arg;
|
||||
|
||||
if (nm->alias)
|
||||
dc->fn(NULL, nm->name, nm->data, dc->arg);
|
||||
else
|
||||
dc->fn((const EVP_MAC *)nm->data, nm->name, NULL, dc->arg);
|
||||
}
|
||||
|
||||
void EVP_MAC_do_all(void (*fn)
|
||||
(const EVP_MAC *ciph, const char *from, const char *to,
|
||||
void *x), void *arg)
|
||||
{
|
||||
struct doall_mac dc;
|
||||
|
||||
/* Ignore errors */
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL);
|
||||
|
||||
dc.fn = fn;
|
||||
dc.arg = arg;
|
||||
OBJ_NAME_do_all(OBJ_NAME_TYPE_MAC_METH, do_all_mac_fn, &dc);
|
||||
}
|
||||
|
||||
void EVP_MAC_do_all_sorted(void (*fn)
|
||||
(const EVP_MAC *ciph, const char *from,
|
||||
const char *to, void *x), void *arg)
|
||||
{
|
||||
struct doall_mac dc;
|
||||
|
||||
/* Ignore errors */
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL);
|
||||
|
||||
dc.fn = fn;
|
||||
dc.arg = arg;
|
||||
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MAC_METH, do_all_mac_fn, &dc);
|
||||
}
|
||||
|
||||
+5
-3
@@ -319,7 +319,7 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
|
||||
{
|
||||
#ifndef OPENSSL_NO_CMAC
|
||||
EVP_PKEY *ret = EVP_PKEY_new();
|
||||
CMAC_CTX *cmctx = CMAC_CTX_new();
|
||||
EVP_MAC_CTX *cmctx = EVP_MAC_CTX_new_id(EVP_MAC_CMAC);
|
||||
|
||||
if (ret == NULL
|
||||
|| cmctx == NULL
|
||||
@@ -328,7 +328,9 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!CMAC_Init(cmctx, priv, len, cipher, e)) {
|
||||
if (EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_ENGINE, e) <= 0
|
||||
|| EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_CIPHER, cipher) <= 0
|
||||
|| EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_KEY, priv, len) <= 0) {
|
||||
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_KEY_SETUP_FAILED);
|
||||
goto err;
|
||||
}
|
||||
@@ -338,7 +340,7 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
|
||||
|
||||
err:
|
||||
EVP_PKEY_free(ret);
|
||||
CMAC_CTX_free(cmctx);
|
||||
EVP_MAC_CTX_free(cmctx);
|
||||
return NULL;
|
||||
#else
|
||||
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY,
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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 <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
/* MAC PKEY context structure */
|
||||
|
||||
typedef struct {
|
||||
EVP_MAC_CTX *ctx;
|
||||
|
||||
/*
|
||||
* We know of two MAC types:
|
||||
*
|
||||
* 1. those who take a secret in raw form, i.e. raw data as a
|
||||
* ASN1_OCTET_STRING embedded in a EVP_PKEY. So far, that's
|
||||
* all of them but CMAC.
|
||||
* 2. those who take a secret with associated cipher in very generic
|
||||
* form, i.e. a complete EVP_MAC_CTX embedded in a PKEY. So far,
|
||||
* only CMAC does this.
|
||||
*
|
||||
* (one might wonder why the second form isn't used for all)
|
||||
*/
|
||||
#define MAC_TYPE_RAW 1 /* HMAC like MAC type (all but CMAC so far) */
|
||||
#define MAC_TYPE_MAC 2 /* CMAC like MAC type (only CMAC known so far) */
|
||||
int type;
|
||||
|
||||
/* The following is only used for MAC_TYPE_RAW implementations */
|
||||
struct {
|
||||
const EVP_MD *md; /* temp storage of MD */
|
||||
ASN1_OCTET_STRING ktmp; /* temp storage for key */
|
||||
} raw_data;
|
||||
} MAC_PKEY_CTX;
|
||||
|
||||
static int pkey_mac_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx;
|
||||
int nid = ctx->pmeth->pkey_id;
|
||||
|
||||
if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) {
|
||||
EVPerr(EVP_F_PKEY_MAC_INIT, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We're being smart and using the same base NIDs for PKEY and for MAC */
|
||||
hctx->ctx = EVP_MAC_CTX_new_id(nid);
|
||||
if (hctx->ctx == NULL) {
|
||||
OPENSSL_free(hctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nid == EVP_PKEY_CMAC) {
|
||||
hctx->type = MAC_TYPE_MAC;
|
||||
} else {
|
||||
hctx->type = MAC_TYPE_RAW;
|
||||
hctx->raw_data.ktmp.type = V_ASN1_OCTET_STRING;
|
||||
}
|
||||
|
||||
EVP_PKEY_CTX_set_data(ctx, hctx);
|
||||
ctx->keygen_info_count = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx);
|
||||
|
||||
static int pkey_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
||||
{
|
||||
MAC_PKEY_CTX *sctx, *dctx;
|
||||
|
||||
if (!pkey_mac_init(dst))
|
||||
return 0;
|
||||
|
||||
sctx = EVP_PKEY_CTX_get_data(src);
|
||||
dctx = EVP_PKEY_CTX_get_data(dst);
|
||||
|
||||
if (!EVP_MAC_CTX_copy(dctx->ctx, sctx->ctx))
|
||||
goto err;
|
||||
|
||||
switch (dctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
dctx->raw_data.md = sctx->raw_data.md;
|
||||
if (ASN1_STRING_get0_data(&sctx->raw_data.ktmp) != NULL &&
|
||||
!ASN1_STRING_copy(&dctx->raw_data.ktmp, &sctx->raw_data.ktmp))
|
||||
goto err;
|
||||
break;
|
||||
case MAC_TYPE_MAC:
|
||||
/* Nothing more to do */
|
||||
break;
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
err:
|
||||
pkey_mac_cleanup (dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
|
||||
if (hctx != NULL) {
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
OPENSSL_clear_free(hctx->raw_data.ktmp.data,
|
||||
hctx->raw_data.ktmp.length);
|
||||
break;
|
||||
}
|
||||
EVP_MAC_CTX_free(hctx->ctx);
|
||||
OPENSSL_free(hctx);
|
||||
EVP_PKEY_CTX_set_data(ctx, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
int nid = ctx->pmeth->pkey_id;
|
||||
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
{
|
||||
ASN1_OCTET_STRING *hkey = NULL;
|
||||
|
||||
if (!hctx->raw_data.ktmp.data)
|
||||
return 0;
|
||||
hkey = ASN1_OCTET_STRING_dup(&hctx->raw_data.ktmp);
|
||||
if (!hkey)
|
||||
return 0;
|
||||
EVP_PKEY_assign(pkey, nid, hkey);
|
||||
}
|
||||
break;
|
||||
case MAC_TYPE_MAC:
|
||||
{
|
||||
EVP_MAC_CTX *cmkey = EVP_MAC_CTX_new_id(nid);
|
||||
|
||||
if (cmkey == NULL)
|
||||
return 0;
|
||||
if (!EVP_MAC_CTX_copy(cmkey, hctx->ctx)) {
|
||||
EVP_MAC_CTX_free(cmkey);
|
||||
return 0;
|
||||
}
|
||||
EVP_PKEY_assign(pkey, nid, cmkey);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
|
||||
|
||||
if (!EVP_MAC_update(hctx->ctx, data, count))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
ASN1_OCTET_STRING *key = NULL;
|
||||
int rv = 1;
|
||||
/*
|
||||
* For MACs with the EVP_PKEY_FLAG_SIGCTX_CUSTOM flag set and that
|
||||
* gets the key passed as an ASN.1 OCTET STRING, we set the key here,
|
||||
* as this may be only time it's set during a DigestSign.
|
||||
*
|
||||
* MACs that pass around the key in form of EVP_MAC_CTX are setting
|
||||
* the key through other mechanisms. (this is only CMAC for now)
|
||||
*/
|
||||
int set_key =
|
||||
hctx->type == MAC_TYPE_RAW
|
||||
&& (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0;
|
||||
|
||||
if (set_key) {
|
||||
if (EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx))
|
||||
!= EVP_MAC_nid(EVP_MAC_CTX_mac(hctx->ctx)))
|
||||
return 0;
|
||||
key = EVP_PKEY_get0(EVP_PKEY_CTX_get0_pkey(ctx));
|
||||
if (key == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Some MACs don't support this control... that's fine */
|
||||
EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_FLAGS,
|
||||
EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT));
|
||||
|
||||
EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
|
||||
EVP_MD_CTX_set_update_fn(mctx, int_update);
|
||||
|
||||
if (set_key)
|
||||
rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, key->data,
|
||||
key->length);
|
||||
return rv > 0;
|
||||
}
|
||||
|
||||
static int pkey_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
|
||||
size_t *siglen, EVP_MD_CTX *mctx)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
|
||||
return EVP_MAC_final(hctx->ctx, sig, siglen);
|
||||
}
|
||||
|
||||
static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
|
||||
switch (type) {
|
||||
|
||||
case EVP_PKEY_CTRL_CIPHER:
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
return -2; /* The raw types don't support ciphers */
|
||||
case MAC_TYPE_MAC:
|
||||
{
|
||||
int rv;
|
||||
|
||||
if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
|
||||
ctx->engine)) < 0
|
||||
|| (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_CIPHER,
|
||||
p2)) < 0
|
||||
|| !(rv = EVP_MAC_init(hctx->ctx)))
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_MD:
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
hctx->raw_data.md = p2;
|
||||
break;
|
||||
case MAC_TYPE_MAC:
|
||||
if (ctx->pkey != NULL
|
||||
&& !EVP_MAC_CTX_copy(hctx->ctx,
|
||||
(EVP_MAC_CTX *)ctx->pkey->pkey.ptr))
|
||||
return 0;
|
||||
if (!EVP_MAC_init(hctx->ctx))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_SET_DIGEST_SIZE:
|
||||
return EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_SIZE, (size_t)p1);
|
||||
|
||||
case EVP_PKEY_CTRL_SET_MAC_KEY:
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
if ((!p2 && p1 > 0) || (p1 < -1))
|
||||
return 0;
|
||||
if (!ASN1_OCTET_STRING_set(&hctx->raw_data.ktmp, p2, p1))
|
||||
return 0;
|
||||
break;
|
||||
case MAC_TYPE_MAC:
|
||||
if (!EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, p2, p1))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_DIGESTINIT:
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
/* Ensure that we have attached the implementation */
|
||||
if (!EVP_MAC_init(hctx->ctx))
|
||||
return 0;
|
||||
{
|
||||
int rv;
|
||||
ASN1_OCTET_STRING *key =
|
||||
(ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
|
||||
|
||||
if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
|
||||
ctx->engine)) < 0
|
||||
|| (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_MD,
|
||||
hctx->raw_data.md)) < 0
|
||||
|| (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY,
|
||||
key->data, key->length)) < 0)
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
case MAC_TYPE_MAC:
|
||||
return -2; /* The mac types don't support ciphers */
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx,
|
||||
const char *type, const char *value)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
|
||||
return EVP_MAC_ctrl_str(hctx->ctx, type, value);
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD cmac_pkey_meth = {
|
||||
EVP_PKEY_CMAC,
|
||||
EVP_PKEY_FLAG_SIGCTX_CUSTOM,
|
||||
pkey_mac_init,
|
||||
pkey_mac_copy,
|
||||
pkey_mac_cleanup,
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
pkey_mac_keygen,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_signctx_init,
|
||||
pkey_mac_signctx,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_ctrl,
|
||||
pkey_mac_ctrl_str
|
||||
};
|
||||
|
||||
const EVP_PKEY_METHOD hmac_pkey_meth = {
|
||||
EVP_PKEY_HMAC,
|
||||
0,
|
||||
pkey_mac_init,
|
||||
pkey_mac_copy,
|
||||
pkey_mac_cleanup,
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
pkey_mac_keygen,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_signctx_init,
|
||||
pkey_mac_signctx,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_ctrl,
|
||||
pkey_mac_ctrl_str
|
||||
};
|
||||
|
||||
const EVP_PKEY_METHOD siphash_pkey_meth = {
|
||||
EVP_PKEY_SIPHASH,
|
||||
EVP_PKEY_FLAG_SIGCTX_CUSTOM,
|
||||
pkey_mac_init,
|
||||
pkey_mac_copy,
|
||||
pkey_mac_cleanup,
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
pkey_mac_keygen,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_signctx_init,
|
||||
pkey_mac_signctx,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_ctrl,
|
||||
pkey_mac_ctrl_str
|
||||
};
|
||||
@@ -1,3 +1,3 @@
|
||||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]=\
|
||||
hmac.c hm_ameth.c hm_pmeth.c
|
||||
hmac.c hm_ameth.c hm_meth.c
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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 <string.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ossl_typ.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
/* local HMAC context structure */
|
||||
|
||||
/* typedef EVP_MAC_IMPL */
|
||||
struct evp_mac_impl_st {
|
||||
/* tmpmd and tmpengine are set to NULL after a CMAC_Init call */
|
||||
const EVP_MD *tmpmd; /* HMAC digest */
|
||||
const ENGINE *tmpengine; /* HMAC digest engine */
|
||||
HMAC_CTX *ctx; /* HMAC context */
|
||||
};
|
||||
|
||||
static EVP_MAC_IMPL *hmac_new(void)
|
||||
{
|
||||
EVP_MAC_IMPL *hctx;
|
||||
|
||||
if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL
|
||||
|| (hctx->ctx = HMAC_CTX_new()) == NULL) {
|
||||
OPENSSL_free(hctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hctx;
|
||||
}
|
||||
|
||||
static void hmac_free(EVP_MAC_IMPL *hctx)
|
||||
{
|
||||
if (hctx != NULL) {
|
||||
HMAC_CTX_free(hctx->ctx);
|
||||
OPENSSL_free(hctx);
|
||||
}
|
||||
}
|
||||
|
||||
static int hmac_copy(EVP_MAC_IMPL *hdst, EVP_MAC_IMPL *hsrc)
|
||||
{
|
||||
if (!HMAC_CTX_copy(hdst->ctx, hsrc->ctx))
|
||||
return 0;
|
||||
|
||||
hdst->tmpengine = hsrc->tmpengine;
|
||||
hdst->tmpmd = hsrc->tmpmd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t hmac_size(EVP_MAC_IMPL *hctx)
|
||||
{
|
||||
return HMAC_size(hctx->ctx);
|
||||
}
|
||||
|
||||
static int hmac_init(EVP_MAC_IMPL *hctx)
|
||||
{
|
||||
int rv = 1;
|
||||
|
||||
/* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */
|
||||
if (hctx->tmpmd != NULL)
|
||||
rv = HMAC_Init_ex(hctx->ctx, NULL, 0, hctx->tmpmd,
|
||||
(ENGINE * )hctx->tmpengine);
|
||||
hctx->tmpengine = NULL;
|
||||
hctx->tmpmd = NULL;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int hmac_update(EVP_MAC_IMPL *hctx, const unsigned char *data,
|
||||
size_t datalen)
|
||||
{
|
||||
return HMAC_Update(hctx->ctx, data, datalen);
|
||||
}
|
||||
|
||||
static int hmac_final(EVP_MAC_IMPL *hctx, unsigned char *out)
|
||||
{
|
||||
unsigned int hlen;
|
||||
|
||||
return HMAC_Final(hctx->ctx, out, &hlen);
|
||||
}
|
||||
|
||||
static int hmac_ctrl(EVP_MAC_IMPL *hctx, int cmd, va_list args)
|
||||
{
|
||||
switch (cmd) {
|
||||
case EVP_MAC_CTRL_SET_FLAGS:
|
||||
{
|
||||
unsigned long flags = va_arg(args, unsigned long);
|
||||
|
||||
HMAC_CTX_set_flags(hctx->ctx, flags);
|
||||
}
|
||||
break;
|
||||
case EVP_MAC_CTRL_SET_KEY:
|
||||
{
|
||||
const unsigned char *key = va_arg(args, const unsigned char *);
|
||||
size_t keylen = va_arg(args, size_t);
|
||||
int rv = HMAC_Init_ex(hctx->ctx, key, keylen, hctx->tmpmd,
|
||||
(ENGINE *)hctx->tmpengine);
|
||||
|
||||
hctx->tmpengine = NULL;
|
||||
hctx->tmpmd = NULL;
|
||||
return rv;
|
||||
}
|
||||
break;
|
||||
case EVP_MAC_CTRL_SET_MD:
|
||||
hctx->tmpmd = va_arg(args, const EVP_MD *);
|
||||
break;
|
||||
case EVP_MAC_CTRL_SET_ENGINE:
|
||||
hctx->tmpengine = va_arg(args, const ENGINE *);
|
||||
break;
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int hmac_ctrl_int(EVP_MAC_IMPL *hctx, int cmd, ...)
|
||||
{
|
||||
int rv;
|
||||
va_list args;
|
||||
|
||||
va_start(args, cmd);
|
||||
rv = hmac_ctrl(hctx, cmd, args);
|
||||
va_end(args);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int hmac_ctrl_str_cb(void *hctx, int cmd, void *buf, size_t buflen)
|
||||
{
|
||||
return hmac_ctrl_int(hctx, cmd, buf, buflen);
|
||||
}
|
||||
|
||||
static int hmac_ctrl_str(EVP_MAC_IMPL *hctx, const char *type,
|
||||
const char *value)
|
||||
{
|
||||
if (!value)
|
||||
return 0;
|
||||
if (strcmp(type, "digest") == 0) {
|
||||
const EVP_MD *d = EVP_get_digestbyname(value);
|
||||
|
||||
if (d == NULL)
|
||||
return 0;
|
||||
return hmac_ctrl_int(hctx, EVP_MAC_CTRL_SET_MD, d);
|
||||
}
|
||||
if (strcmp(type, "key") == 0)
|
||||
return EVP_str2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY,
|
||||
value);
|
||||
if (strcmp(type, "hexkey") == 0)
|
||||
return EVP_hex2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY,
|
||||
value);
|
||||
return -2;
|
||||
}
|
||||
|
||||
const EVP_MAC hmac_meth = {
|
||||
EVP_MAC_HMAC,
|
||||
hmac_new,
|
||||
hmac_copy,
|
||||
hmac_free,
|
||||
hmac_size,
|
||||
hmac_init,
|
||||
hmac_update,
|
||||
hmac_final,
|
||||
hmac_ctrl,
|
||||
hmac_ctrl_str
|
||||
};
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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 <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/err.h>
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
/* HMAC pkey context structure */
|
||||
|
||||
typedef struct {
|
||||
const EVP_MD *md; /* MD for HMAC use */
|
||||
ASN1_OCTET_STRING ktmp; /* Temp storage for key */
|
||||
HMAC_CTX *ctx;
|
||||
} HMAC_PKEY_CTX;
|
||||
|
||||
static int pkey_hmac_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
HMAC_PKEY_CTX *hctx;
|
||||
|
||||
if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) {
|
||||
CRYPTOerr(CRYPTO_F_PKEY_HMAC_INIT, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
hctx->ktmp.type = V_ASN1_OCTET_STRING;
|
||||
hctx->ctx = HMAC_CTX_new();
|
||||
if (hctx->ctx == NULL) {
|
||||
OPENSSL_free(hctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->data = hctx;
|
||||
ctx->keygen_info_count = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx);
|
||||
|
||||
static int pkey_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
||||
{
|
||||
HMAC_PKEY_CTX *sctx, *dctx;
|
||||
|
||||
/* allocate memory for dst->data and a new HMAC_CTX in dst->data->ctx */
|
||||
if (!pkey_hmac_init(dst))
|
||||
return 0;
|
||||
sctx = EVP_PKEY_CTX_get_data(src);
|
||||
dctx = EVP_PKEY_CTX_get_data(dst);
|
||||
dctx->md = sctx->md;
|
||||
if (!HMAC_CTX_copy(dctx->ctx, sctx->ctx))
|
||||
goto err;
|
||||
if (sctx->ktmp.data) {
|
||||
if (!ASN1_OCTET_STRING_set(&dctx->ktmp,
|
||||
sctx->ktmp.data, sctx->ktmp.length))
|
||||
goto err;
|
||||
}
|
||||
return 1;
|
||||
err:
|
||||
/* release HMAC_CTX in dst->data->ctx and memory allocated for dst->data */
|
||||
pkey_hmac_cleanup (dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pkey_hmac_cleanup(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
|
||||
if (hctx != NULL) {
|
||||
HMAC_CTX_free(hctx->ctx);
|
||||
OPENSSL_clear_free(hctx->ktmp.data, hctx->ktmp.length);
|
||||
OPENSSL_free(hctx);
|
||||
EVP_PKEY_CTX_set_data(ctx, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_hmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
ASN1_OCTET_STRING *hkey = NULL;
|
||||
HMAC_PKEY_CTX *hctx = ctx->data;
|
||||
if (!hctx->ktmp.data)
|
||||
return 0;
|
||||
hkey = ASN1_OCTET_STRING_dup(&hctx->ktmp);
|
||||
if (!hkey)
|
||||
return 0;
|
||||
EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, hkey);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
|
||||
{
|
||||
HMAC_PKEY_CTX *hctx = EVP_MD_CTX_pkey_ctx(ctx)->data;
|
||||
if (!HMAC_Update(hctx->ctx, data, count))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int hmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
|
||||
{
|
||||
HMAC_PKEY_CTX *hctx = ctx->data;
|
||||
HMAC_CTX_set_flags(hctx->ctx,
|
||||
EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT));
|
||||
EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
|
||||
EVP_MD_CTX_set_update_fn(mctx, int_update);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int hmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
|
||||
EVP_MD_CTX *mctx)
|
||||
{
|
||||
unsigned int hlen;
|
||||
HMAC_PKEY_CTX *hctx = ctx->data;
|
||||
int l = EVP_MD_CTX_size(mctx);
|
||||
|
||||
if (l < 0)
|
||||
return 0;
|
||||
*siglen = l;
|
||||
if (!sig)
|
||||
return 1;
|
||||
|
||||
if (!HMAC_Final(hctx->ctx, sig, &hlen))
|
||||
return 0;
|
||||
*siglen = (size_t)hlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
{
|
||||
HMAC_PKEY_CTX *hctx = ctx->data;
|
||||
ASN1_OCTET_STRING *key;
|
||||
switch (type) {
|
||||
|
||||
case EVP_PKEY_CTRL_SET_MAC_KEY:
|
||||
if ((!p2 && p1 > 0) || (p1 < -1))
|
||||
return 0;
|
||||
if (!ASN1_OCTET_STRING_set(&hctx->ktmp, p2, p1))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_MD:
|
||||
hctx->md = p2;
|
||||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_DIGESTINIT:
|
||||
key = (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
|
||||
if (!HMAC_Init_ex(hctx->ctx, key->data, key->length, hctx->md,
|
||||
ctx->engine))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_hmac_ctrl_str(EVP_PKEY_CTX *ctx,
|
||||
const char *type, const char *value)
|
||||
{
|
||||
if (!value) {
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(type, "key") == 0)
|
||||
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
|
||||
if (strcmp(type, "hexkey") == 0)
|
||||
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
|
||||
return -2;
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD hmac_pkey_meth = {
|
||||
EVP_PKEY_HMAC,
|
||||
0,
|
||||
pkey_hmac_init,
|
||||
pkey_hmac_copy,
|
||||
pkey_hmac_cleanup,
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
pkey_hmac_keygen,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
hmac_signctx_init,
|
||||
hmac_signctx,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_hmac_ctrl,
|
||||
pkey_hmac_ctrl_str
|
||||
};
|
||||
@@ -41,5 +41,13 @@
|
||||
__owur int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
|
||||
const BIGNUM *x, BN_CTX *ctx);
|
||||
|
||||
/*-
|
||||
* ECDH Key Derivation Function as defined in ANSI X9.63
|
||||
*/
|
||||
int ecdh_KDF_X9_63(unsigned char *out, size_t outlen,
|
||||
const unsigned char *Z, size_t Zlen,
|
||||
const unsigned char *sinfo, size_t sinfolen,
|
||||
const EVP_MD *md);
|
||||
|
||||
# endif /* OPENSSL_NO_EC */
|
||||
#endif
|
||||
@@ -112,6 +112,35 @@ extern const EVP_PKEY_METHOD hkdf_pkey_meth;
|
||||
extern const EVP_PKEY_METHOD poly1305_pkey_meth;
|
||||
extern const EVP_PKEY_METHOD siphash_pkey_meth;
|
||||
|
||||
/* struct evp_mac_impl_st is defined by the implementation */
|
||||
typedef struct evp_mac_impl_st EVP_MAC_IMPL;
|
||||
struct evp_mac_st {
|
||||
int type;
|
||||
EVP_MAC_IMPL *(*new) (void);
|
||||
int (*copy) (EVP_MAC_IMPL *macdst, EVP_MAC_IMPL *macsrc);
|
||||
void (*free) (EVP_MAC_IMPL *macctx);
|
||||
size_t (*size) (EVP_MAC_IMPL *macctx);
|
||||
int (*init) (EVP_MAC_IMPL *macctx);
|
||||
int (*update) (EVP_MAC_IMPL *macctx, const unsigned char *data,
|
||||
size_t datalen);
|
||||
int (*final) (EVP_MAC_IMPL *macctx, unsigned char *out);
|
||||
int (*ctrl) (EVP_MAC_IMPL *macctx, int cmd, va_list args);
|
||||
int (*ctrl_str) (EVP_MAC_IMPL *macctx, const char *type, const char *value);
|
||||
};
|
||||
|
||||
extern const EVP_MAC cmac_meth;
|
||||
extern const EVP_MAC hmac_meth;
|
||||
extern const EVP_MAC siphash_meth;
|
||||
|
||||
/*
|
||||
* This function is internal for now, but can be made external when needed.
|
||||
* The documentation would read:
|
||||
*
|
||||
* EVP_add_mac() adds the MAC implementation C<mac> to the internal
|
||||
* object database.
|
||||
*/
|
||||
int EVP_add_mac(const EVP_MAC *mac);
|
||||
|
||||
struct evp_md_st {
|
||||
int type;
|
||||
int pkey_type;
|
||||
@@ -423,6 +452,7 @@ struct evp_pkey_st {
|
||||
|
||||
void openssl_add_all_ciphers_int(void);
|
||||
void openssl_add_all_digests_int(void);
|
||||
void openssl_add_all_macs_int(void);
|
||||
void evp_cleanup_int(void);
|
||||
void evp_app_cleanup_int(void);
|
||||
|
||||
|
||||
@@ -235,6 +235,23 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static CRYPTO_ONCE add_all_macs = CRYPTO_ONCE_STATIC_INIT;
|
||||
DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_macs)
|
||||
{
|
||||
/*
|
||||
* OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
|
||||
* pulling in all the macs during static linking
|
||||
*/
|
||||
#ifndef OPENSSL_NO_AUTOALGINIT
|
||||
# ifdef OPENSSL_INIT_DEBUG
|
||||
fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_macs: "
|
||||
"openssl_add_all_macs_int()\n");
|
||||
# endif
|
||||
openssl_add_all_macs_int();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
DEFINE_RUN_ONCE_STATIC(ossl_init_no_add_algs)
|
||||
{
|
||||
/* Do nothing */
|
||||
@@ -619,6 +636,14 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
|
||||
&& !RUN_ONCE(&add_all_digests, ossl_init_add_all_digests))
|
||||
return 0;
|
||||
|
||||
if ((opts & OPENSSL_INIT_NO_ADD_ALL_MACS)
|
||||
&& !RUN_ONCE(&add_all_macs, ossl_init_no_add_algs))
|
||||
return 0;
|
||||
|
||||
if ((opts & OPENSSL_INIT_ADD_ALL_MACS)
|
||||
&& !RUN_ONCE(&add_all_macs, ossl_init_add_all_macs))
|
||||
return 0;
|
||||
|
||||
if ((opts & OPENSSL_INIT_ATFORK)
|
||||
&& !openssl_init_fork_handlers())
|
||||
return 0;
|
||||
|
||||
+13
-1
@@ -175,6 +175,18 @@ static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
HKDF_PKEY_CTX *kctx = ctx->data;
|
||||
|
||||
OPENSSL_clear_free(kctx->key, kctx->key_len);
|
||||
OPENSSL_clear_free(kctx->salt, kctx->salt_len);
|
||||
OPENSSL_cleanse(kctx->info, kctx->info_len);
|
||||
memset(kctx, 0, sizeof(*kctx));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
|
||||
size_t *keylen)
|
||||
{
|
||||
@@ -236,7 +248,7 @@ const EVP_PKEY_METHOD hkdf_pkey_meth = {
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
pkey_hkdf_derive_init,
|
||||
pkey_hkdf_derive,
|
||||
pkey_hkdf_ctrl,
|
||||
pkey_hkdf_ctrl_str
|
||||
|
||||
+102
-39
@@ -374,6 +374,13 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
|
||||
max_entropylen += drbg->max_noncelen;
|
||||
}
|
||||
|
||||
drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
|
||||
if (drbg->reseed_next_counter) {
|
||||
drbg->reseed_next_counter++;
|
||||
if(!drbg->reseed_next_counter)
|
||||
drbg->reseed_next_counter = 1;
|
||||
}
|
||||
|
||||
if (drbg->get_entropy != NULL)
|
||||
entropylen = drbg->get_entropy(drbg, &entropy, min_entropy,
|
||||
min_entropylen, max_entropylen, 0);
|
||||
@@ -401,27 +408,13 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
|
||||
drbg->state = DRBG_READY;
|
||||
drbg->reseed_gen_counter = 1;
|
||||
drbg->reseed_time = time(NULL);
|
||||
if (drbg->reseed_prop_counter > 0) {
|
||||
if (drbg->parent == NULL)
|
||||
drbg->reseed_prop_counter++;
|
||||
else
|
||||
drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter;
|
||||
}
|
||||
tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
|
||||
|
||||
end:
|
||||
if (entropy != NULL && drbg->cleanup_entropy != NULL)
|
||||
drbg->cleanup_entropy(drbg, entropy, entropylen);
|
||||
if (nonce != NULL && drbg->cleanup_nonce != NULL)
|
||||
drbg->cleanup_nonce(drbg, nonce, noncelen);
|
||||
if (drbg->pool != NULL) {
|
||||
if (drbg->state == DRBG_READY) {
|
||||
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
|
||||
RAND_R_ERROR_ENTROPY_POOL_WAS_IGNORED);
|
||||
drbg->state = DRBG_ERROR;
|
||||
}
|
||||
rand_pool_free(drbg->pool);
|
||||
drbg->pool = NULL;
|
||||
}
|
||||
if (drbg->state == DRBG_READY)
|
||||
return 1;
|
||||
return 0;
|
||||
@@ -498,6 +491,14 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
|
||||
}
|
||||
|
||||
drbg->state = DRBG_ERROR;
|
||||
|
||||
drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
|
||||
if (drbg->reseed_next_counter) {
|
||||
drbg->reseed_next_counter++;
|
||||
if(!drbg->reseed_next_counter)
|
||||
drbg->reseed_next_counter = 1;
|
||||
}
|
||||
|
||||
if (drbg->get_entropy != NULL)
|
||||
entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
|
||||
drbg->min_entropylen,
|
||||
@@ -515,12 +516,7 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
|
||||
drbg->state = DRBG_READY;
|
||||
drbg->reseed_gen_counter = 1;
|
||||
drbg->reseed_time = time(NULL);
|
||||
if (drbg->reseed_prop_counter > 0) {
|
||||
if (drbg->parent == NULL)
|
||||
drbg->reseed_prop_counter++;
|
||||
else
|
||||
drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter;
|
||||
}
|
||||
tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
|
||||
|
||||
end:
|
||||
if (entropy != NULL && drbg->cleanup_entropy != NULL)
|
||||
@@ -625,14 +621,8 @@ int rand_drbg_restart(RAND_DRBG *drbg,
|
||||
}
|
||||
}
|
||||
|
||||
/* check whether a given entropy pool was cleared properly during reseed */
|
||||
if (drbg->pool != NULL) {
|
||||
drbg->state = DRBG_ERROR;
|
||||
RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR);
|
||||
rand_pool_free(drbg->pool);
|
||||
drbg->pool = NULL;
|
||||
return 0;
|
||||
}
|
||||
rand_pool_free(drbg->pool);
|
||||
drbg->pool = NULL;
|
||||
|
||||
return drbg->state == DRBG_READY;
|
||||
}
|
||||
@@ -691,8 +681,11 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
|
||||
|| now - drbg->reseed_time >= drbg->reseed_time_interval)
|
||||
reseed_required = 1;
|
||||
}
|
||||
if (drbg->reseed_prop_counter > 0 && drbg->parent != NULL) {
|
||||
if (drbg->reseed_prop_counter != drbg->parent->reseed_prop_counter)
|
||||
if (drbg->parent != NULL) {
|
||||
unsigned int reseed_counter = tsan_load(&drbg->reseed_prop_counter);
|
||||
if (reseed_counter > 0
|
||||
&& tsan_load(&drbg->parent->reseed_prop_counter)
|
||||
!= reseed_counter)
|
||||
reseed_required = 1;
|
||||
}
|
||||
|
||||
@@ -764,7 +757,8 @@ int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
|
||||
RAND_DRBG_get_nonce_fn get_nonce,
|
||||
RAND_DRBG_cleanup_nonce_fn cleanup_nonce)
|
||||
{
|
||||
if (drbg->state != DRBG_UNINITIALISED)
|
||||
if (drbg->state != DRBG_UNINITIALISED
|
||||
|| drbg->parent != NULL)
|
||||
return 0;
|
||||
drbg->get_entropy = get_entropy;
|
||||
drbg->cleanup_entropy = cleanup_entropy;
|
||||
@@ -942,7 +936,7 @@ static RAND_DRBG *drbg_setup(RAND_DRBG *parent, int drbg_type)
|
||||
goto err;
|
||||
|
||||
/* enable seed propagation */
|
||||
drbg->reseed_prop_counter = 1;
|
||||
tsan_store(&drbg->reseed_prop_counter, 1);
|
||||
|
||||
/*
|
||||
* Ignore instantiation error to support just-in-time instantiation.
|
||||
@@ -1031,11 +1025,53 @@ static int drbg_bytes(unsigned char *out, int count)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculates the minimum length of a full entropy buffer
|
||||
* which is necessary to seed (i.e. instantiate) the DRBG
|
||||
* successfully.
|
||||
*
|
||||
* NOTE: There is a copy of this function in drbgtest.c.
|
||||
* If you change anything here, you need to update
|
||||
* the copy accordingly.
|
||||
*/
|
||||
static size_t rand_drbg_seedlen(RAND_DRBG *drbg)
|
||||
{
|
||||
/*
|
||||
* If no os entropy source is available then RAND_seed(buffer, bufsize)
|
||||
* is expected to succeed if and only if the buffer length satisfies
|
||||
* the following requirements, which follow from the calculations
|
||||
* in RAND_DRBG_instantiate().
|
||||
*/
|
||||
size_t min_entropy = drbg->strength;
|
||||
size_t min_entropylen = drbg->min_entropylen;
|
||||
|
||||
/*
|
||||
* Extra entropy for the random nonce in the absence of a
|
||||
* get_nonce callback, see comment in RAND_DRBG_instantiate().
|
||||
*/
|
||||
if (drbg->min_noncelen > 0 && drbg->get_nonce == NULL) {
|
||||
min_entropy += drbg->strength / 2;
|
||||
min_entropylen += drbg->min_noncelen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert entropy requirement from bits to bytes
|
||||
* (dividing by 8 without rounding upwards, because
|
||||
* all entropy requirements are divisible by 8).
|
||||
*/
|
||||
min_entropy >>= 3;
|
||||
|
||||
/* Return a value that satisfies both requirements */
|
||||
return min_entropy > min_entropylen ? min_entropy : min_entropylen;
|
||||
}
|
||||
|
||||
/* Implements the default OpenSSL RAND_add() method */
|
||||
static int drbg_add(const void *buf, int num, double randomness)
|
||||
{
|
||||
int ret = 0;
|
||||
RAND_DRBG *drbg = RAND_DRBG_get0_master();
|
||||
size_t buflen;
|
||||
size_t seedlen;
|
||||
|
||||
if (drbg == NULL)
|
||||
return 0;
|
||||
@@ -1043,7 +1079,37 @@ static int drbg_add(const void *buf, int num, double randomness)
|
||||
if (num < 0 || randomness < 0.0)
|
||||
return 0;
|
||||
|
||||
if (randomness > (double)RAND_DRBG_STRENGTH) {
|
||||
rand_drbg_lock(drbg);
|
||||
seedlen = rand_drbg_seedlen(drbg);
|
||||
|
||||
buflen = (size_t)num;
|
||||
|
||||
if (buflen < seedlen || randomness < (double) seedlen) {
|
||||
#if defined(OPENSSL_RAND_SEED_NONE)
|
||||
/*
|
||||
* If no os entropy source is available, a reseeding will fail
|
||||
* inevitably. So we use a trick to mix the buffer contents into
|
||||
* the DRBG state without forcing a reseeding: we generate a
|
||||
* dummy random byte, using the buffer content as additional data.
|
||||
* Note: This won't work with RAND_DRBG_FLAG_CTR_NO_DF.
|
||||
*/
|
||||
unsigned char dummy[1];
|
||||
|
||||
ret = RAND_DRBG_generate(drbg, dummy, sizeof(dummy), 0, buf, buflen);
|
||||
rand_drbg_unlock(drbg);
|
||||
return ret;
|
||||
#else
|
||||
/*
|
||||
* If an os entropy source is avaible then we declare the buffer content
|
||||
* as additional data by setting randomness to zero and trigger a regular
|
||||
* reseeding.
|
||||
*/
|
||||
randomness = 0.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
if (randomness > (double)seedlen) {
|
||||
/*
|
||||
* The purpose of this check is to bound |randomness| by a
|
||||
* relatively small value in order to prevent an integer
|
||||
@@ -1052,13 +1118,10 @@ static int drbg_add(const void *buf, int num, double randomness)
|
||||
* not bits, so this value corresponds to eight times the
|
||||
* security strength.
|
||||
*/
|
||||
randomness = (double)RAND_DRBG_STRENGTH;
|
||||
randomness = (double)seedlen;
|
||||
}
|
||||
|
||||
rand_drbg_lock(drbg);
|
||||
ret = rand_drbg_restart(drbg, buf,
|
||||
(size_t)(unsigned int)num,
|
||||
(size_t)(8*randomness));
|
||||
ret = rand_drbg_restart(drbg, buf, buflen, (size_t)(8 * randomness));
|
||||
rand_drbg_unlock(drbg);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
# include <openssl/hmac.h>
|
||||
# include <openssl/ec.h>
|
||||
# include <openssl/rand_drbg.h>
|
||||
# include "internal/tsan_assist.h"
|
||||
|
||||
# include "internal/numbers.h"
|
||||
|
||||
/* How many times to read the TSC as a randomness source. */
|
||||
# define TSC_READ_COUNT 4
|
||||
@@ -256,7 +259,8 @@ struct rand_drbg_st {
|
||||
* is added by RAND_add() or RAND_seed() will have an immediate effect on
|
||||
* the output of RAND_bytes() resp. RAND_priv_bytes().
|
||||
*/
|
||||
unsigned int reseed_prop_counter;
|
||||
TSAN_QUALIFIER unsigned int reseed_prop_counter;
|
||||
unsigned int reseed_next_counter;
|
||||
|
||||
size_t seedlen;
|
||||
DRBG_STATUS state;
|
||||
|
||||
@@ -151,6 +151,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
|
||||
pool->entropy_requested = entropy;
|
||||
} else {
|
||||
pool = rand_pool_new(entropy, min_len, max_len);
|
||||
if (pool == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (drbg->parent) {
|
||||
@@ -172,6 +174,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
|
||||
prediction_resistance,
|
||||
NULL, 0) != 0)
|
||||
bytes = bytes_needed;
|
||||
drbg->reseed_next_counter
|
||||
= tsan_load(&drbg->parent->reseed_prop_counter);
|
||||
rand_drbg_unlock(drbg->parent);
|
||||
|
||||
rand_pool_add_end(pool, bytes, 8 * bytes);
|
||||
@@ -200,7 +204,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
|
||||
}
|
||||
|
||||
err:
|
||||
rand_pool_free(pool);
|
||||
if (drbg->pool == NULL)
|
||||
rand_pool_free(pool);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -213,8 +218,6 @@ void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
|
||||
{
|
||||
if (drbg->pool == NULL)
|
||||
OPENSSL_secure_clear_free(out, outlen);
|
||||
else
|
||||
drbg->pool = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -539,6 +542,8 @@ unsigned char *rand_pool_detach(RAND_POOL *pool)
|
||||
{
|
||||
unsigned char *ret = pool->buffer;
|
||||
pool->buffer = NULL;
|
||||
pool->len = 0;
|
||||
pool->entropy = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+29
-9
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/rand_drbg.h>
|
||||
#include <openssl/buffer.h>
|
||||
|
||||
#ifdef OPENSSL_SYS_VMS
|
||||
@@ -48,7 +49,7 @@
|
||||
# define S_ISREG(m) ((m) & S_IFREG)
|
||||
# endif
|
||||
|
||||
#define RAND_FILE_SIZE 1024
|
||||
#define RAND_BUF_SIZE 1024
|
||||
#define RFILE ".rnd"
|
||||
|
||||
#ifdef OPENSSL_SYS_VMS
|
||||
@@ -74,7 +75,16 @@ static __FILE_ptr32 (*const vms_fopen)(const char *, const char *, ...) =
|
||||
*/
|
||||
int RAND_load_file(const char *file, long bytes)
|
||||
{
|
||||
unsigned char buf[RAND_FILE_SIZE];
|
||||
/*
|
||||
* The load buffer size exceeds the chunk size by the comfortable amount
|
||||
* of 'RAND_DRBG_STRENGTH' bytes (not bits!). This is done on purpose
|
||||
* to avoid calling RAND_add() with a small final chunk. Instead, such
|
||||
* a small final chunk will be added together with the previous chunk
|
||||
* (unless it's the only one).
|
||||
*/
|
||||
#define RAND_LOAD_BUF_SIZE (RAND_BUF_SIZE + RAND_DRBG_STRENGTH)
|
||||
unsigned char buf[RAND_LOAD_BUF_SIZE];
|
||||
|
||||
#ifndef OPENSSL_NO_POSIX_IO
|
||||
struct stat sb;
|
||||
#endif
|
||||
@@ -98,8 +108,12 @@ int RAND_load_file(const char *file, long bytes)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!S_ISREG(sb.st_mode) && bytes < 0)
|
||||
bytes = 256;
|
||||
if (bytes < 0) {
|
||||
if (S_ISREG(sb.st_mode))
|
||||
bytes = sb.st_size;
|
||||
else
|
||||
bytes = RAND_DRBG_STRENGTH;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* On VMS, setbuf() will only take 32-bit pointers, and a compilation
|
||||
@@ -124,9 +138,9 @@ int RAND_load_file(const char *file, long bytes)
|
||||
|
||||
for ( ; ; ) {
|
||||
if (bytes > 0)
|
||||
n = (bytes < RAND_FILE_SIZE) ? (int)bytes : RAND_FILE_SIZE;
|
||||
n = (bytes <= RAND_LOAD_BUF_SIZE) ? (int)bytes : RAND_BUF_SIZE;
|
||||
else
|
||||
n = RAND_FILE_SIZE;
|
||||
n = RAND_LOAD_BUF_SIZE;
|
||||
i = fread(buf, 1, n, in);
|
||||
#ifdef EINTR
|
||||
if (ferror(in) && errno == EINTR){
|
||||
@@ -148,12 +162,18 @@ int RAND_load_file(const char *file, long bytes)
|
||||
|
||||
OPENSSL_cleanse(buf, sizeof(buf));
|
||||
fclose(in);
|
||||
if (!RAND_status()) {
|
||||
RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_RESEED_ERROR);
|
||||
ERR_add_error_data(2, "Filename=", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RAND_write_file(const char *file)
|
||||
{
|
||||
unsigned char buf[RAND_FILE_SIZE];
|
||||
unsigned char buf[RAND_BUF_SIZE];
|
||||
int ret = -1;
|
||||
FILE *out = NULL;
|
||||
#ifndef OPENSSL_NO_POSIX_IO
|
||||
@@ -222,9 +242,9 @@ int RAND_write_file(const char *file)
|
||||
chmod(file, 0600);
|
||||
#endif
|
||||
|
||||
ret = fwrite(buf, 1, RAND_FILE_SIZE, out);
|
||||
ret = fwrite(buf, 1, RAND_BUF_SIZE, out);
|
||||
fclose(out);
|
||||
OPENSSL_cleanse(buf, RAND_FILE_SIZE);
|
||||
OPENSSL_cleanse(buf, RAND_BUF_SIZE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+128
-1
@@ -163,6 +163,133 @@ void *RSA_get_ex_data(const RSA *r, int idx)
|
||||
return CRYPTO_get_ex_data(&r->ex_data, idx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Define a scaling constant for our fixed point arithmetic.
|
||||
* This value must be a power of two because the base two logarithm code
|
||||
* makes this assumption. The exponent must also be a multiple of three so
|
||||
* that the scale factor has an exact cube root. Finally, the scale factor
|
||||
* should not be so large that a multiplication of two scaled numbers
|
||||
* overflows a 64 bit unsigned integer.
|
||||
*/
|
||||
static const unsigned int scale = 1 << 18;
|
||||
static const unsigned int cbrt_scale = 1 << (2 * 18 / 3);
|
||||
|
||||
/* Define some constants, none exceed 32 bits */
|
||||
static const unsigned int log_2 = 0x02c5c8; /* scale * log(2) */
|
||||
static const unsigned int log_e = 0x05c551; /* scale * log2(M_E) */
|
||||
static const unsigned int c1_923 = 0x07b126; /* scale * 1.923 */
|
||||
static const unsigned int c4_690 = 0x12c28f; /* scale * 4.690 */
|
||||
|
||||
/*
|
||||
* Multiply two scale integers together and rescale the result.
|
||||
*/
|
||||
static ossl_inline uint64_t mul2(uint64_t a, uint64_t b)
|
||||
{
|
||||
return a * b / scale;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the cube root of a 64 bit scaled integer.
|
||||
* Although the cube root of a 64 bit number does fit into a 32 bit unsigned
|
||||
* integer, this is not guaranteed after scaling, so this function has a
|
||||
* 64 bit return. This uses the shifting nth root algorithm with some
|
||||
* algebraic simplifications.
|
||||
*/
|
||||
static uint64_t icbrt64(uint64_t x)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
uint64_t b;
|
||||
int s;
|
||||
|
||||
for (s = 63; s >= 0; s -= 3) {
|
||||
r <<= 1;
|
||||
b = 3 * r * (r + 1) + 1;
|
||||
if ((x >> s) >= b) {
|
||||
x -= b << s;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
return r * cbrt_scale;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the natural logarithm of a 64 bit scaled integer.
|
||||
* This is done by calculating a base two logarithm and scaling.
|
||||
* The maximum logarithm (base 2) is 64 and this reduces base e, so
|
||||
* a 32 bit result should not overflow. The argument passed must be
|
||||
* greater than unity so we don't need to handle negative results.
|
||||
*/
|
||||
static uint32_t ilog_e(uint64_t v)
|
||||
{
|
||||
uint32_t i, r = 0;
|
||||
|
||||
/*
|
||||
* Scale down the value into the range 1 .. 2.
|
||||
*
|
||||
* If fractional numbers need to be processed, another loop needs
|
||||
* to go here that checks v < scale and if so multiplies it by 2 and
|
||||
* reduces r by scale. This also means making r signed.
|
||||
*/
|
||||
while (v >= 2 * scale) {
|
||||
v >>= 1;
|
||||
r += scale;
|
||||
}
|
||||
for (i = scale / 2; i != 0; i /= 2) {
|
||||
v = mul2(v, v);
|
||||
if (v >= 2 * scale) {
|
||||
v >>= 1;
|
||||
r += i;
|
||||
}
|
||||
}
|
||||
r = (r * (uint64_t)scale) / log_e;
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* NIST SP 800-56B rev 2 Appendix D: Maximum Security Strength Estimates for IFC
|
||||
* Modulus Lengths.
|
||||
*
|
||||
* E = \frac{1.923 \sqrt[3]{nBits \cdot log_e(2)}
|
||||
* \cdot(log_e(nBits \cdot log_e(2))^{2/3} - 4.69}{log_e(2)}
|
||||
* The two cube roots are merged together here.
|
||||
*/
|
||||
static uint16_t rsa_compute_security_bits(int n)
|
||||
{
|
||||
uint64_t x;
|
||||
uint32_t lx;
|
||||
uint16_t y;
|
||||
|
||||
/* Look for common values as listed in SP 800-56B rev 2 Appendix D */
|
||||
switch (n) {
|
||||
case 2048:
|
||||
return 112;
|
||||
case 3072:
|
||||
return 128;
|
||||
case 4096:
|
||||
return 152;
|
||||
case 6144:
|
||||
return 176;
|
||||
case 8192:
|
||||
return 200;
|
||||
}
|
||||
/*
|
||||
* The first incorrect result (i.e. not accurate or off by one low) occurs
|
||||
* for n = 699668. The true value here is 1200. Instead of using this n
|
||||
* as the check threshold, the smallest n such that the correct result is
|
||||
* 1200 is used instead.
|
||||
*/
|
||||
if (n >= 687737)
|
||||
return 1200;
|
||||
if (n < 8)
|
||||
return 0;
|
||||
|
||||
x = n * (uint64_t)log_2;
|
||||
lx = ilog_e(x);
|
||||
y = (uint16_t)((mul2(c1_923, icbrt64(mul2(mul2(x, lx), lx))) - c4_690)
|
||||
/ log_2);
|
||||
return (y + 4) & ~7;
|
||||
}
|
||||
|
||||
int RSA_security_bits(const RSA *rsa)
|
||||
{
|
||||
int bits = BN_num_bits(rsa->n);
|
||||
@@ -174,7 +301,7 @@ int RSA_security_bits(const RSA *rsa)
|
||||
if (ex_primes <= 0 || (ex_primes + 2) > rsa_multip_cap(bits))
|
||||
return 0;
|
||||
}
|
||||
return BN_security_bits(bits, -1);
|
||||
return rsa_compute_security_bits(bits);
|
||||
}
|
||||
|
||||
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
|
||||
|
||||
+20
-3
@@ -49,6 +49,9 @@ struct OPENSSL_s390xcap_st {
|
||||
|
||||
extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P;
|
||||
|
||||
/* Max number of 64-bit words currently returned by STFLE */
|
||||
# define S390X_STFLE_MAX 3
|
||||
|
||||
/* convert facility bit number or function code to bit mask */
|
||||
# define S390X_CAPBIT(i) (1ULL << (63 - (i) % 64))
|
||||
|
||||
@@ -68,9 +71,15 @@ extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P;
|
||||
# define S390X_KMA 0xb0
|
||||
|
||||
/* Facility Bit Numbers */
|
||||
# define S390X_VX 129
|
||||
# define S390X_VXD 134
|
||||
# define S390X_VXE 135
|
||||
# define S390X_MSA 17 /* message-security-assist */
|
||||
# define S390X_STCKF 25 /* store-clock-fast */
|
||||
# define S390X_MSA5 57 /* message-security-assist-ext. 5 */
|
||||
# define S390X_MSA3 76 /* message-security-assist-ext. 3 */
|
||||
# define S390X_MSA4 77 /* message-security-assist-ext. 4 */
|
||||
# define S390X_VX 129 /* vector */
|
||||
# define S390X_VXD 134 /* vector packed decimal */
|
||||
# define S390X_VXE 135 /* vector enhancements 1 */
|
||||
# define S390X_MSA8 146 /* message-security-assist-ext. 8 */
|
||||
|
||||
/* Function Codes */
|
||||
|
||||
@@ -78,6 +87,9 @@ extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P;
|
||||
# define S390X_QUERY 0
|
||||
|
||||
/* kimd/klmd */
|
||||
# define S390X_SHA_1 1
|
||||
# define S390X_SHA_256 2
|
||||
# define S390X_SHA_512 3
|
||||
# define S390X_SHA3_224 32
|
||||
# define S390X_SHA3_256 33
|
||||
# define S390X_SHA3_384 34
|
||||
@@ -91,7 +103,12 @@ extern struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P;
|
||||
# define S390X_AES_192 19
|
||||
# define S390X_AES_256 20
|
||||
|
||||
/* km */
|
||||
# define S390X_XTS_AES_128 50
|
||||
# define S390X_XTS_AES_256 52
|
||||
|
||||
/* prno */
|
||||
# define S390X_SHA_512_DRNG 3
|
||||
# define S390X_TRNG 114
|
||||
|
||||
/* Register 0 Flags */
|
||||
|
||||
@@ -13,15 +13,51 @@
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/ctype.h"
|
||||
#include "s390x_arch.h"
|
||||
|
||||
#define LEN 128
|
||||
#define STR_(S) #S
|
||||
#define STR(S) STR_(S)
|
||||
|
||||
#define TOK_FUNC(NAME) \
|
||||
(sscanf(tok_begin, \
|
||||
" " STR(NAME) " : %" STR(LEN) "[^:] : " \
|
||||
"%" STR(LEN) "s %" STR(LEN) "s ", \
|
||||
tok[0], tok[1], tok[2]) == 2) { \
|
||||
\
|
||||
off = (tok[0][0] == '~') ? 1 : 0; \
|
||||
if (sscanf(tok[0] + off, "%llx", &cap->NAME[0]) != 1) \
|
||||
goto ret; \
|
||||
if (off) \
|
||||
cap->NAME[0] = ~cap->NAME[0]; \
|
||||
\
|
||||
off = (tok[1][0] == '~') ? 1 : 0; \
|
||||
if (sscanf(tok[1] + off, "%llx", &cap->NAME[1]) != 1) \
|
||||
goto ret; \
|
||||
if (off) \
|
||||
cap->NAME[1] = ~cap->NAME[1]; \
|
||||
}
|
||||
|
||||
#define TOK_CPU(NAME) \
|
||||
(sscanf(tok_begin, \
|
||||
" %" STR(LEN) "s %" STR(LEN) "s ", \
|
||||
tok[0], tok[1]) == 1 \
|
||||
&& !strcmp(tok[0], #NAME)) { \
|
||||
memcpy(cap, &NAME, sizeof(*cap)); \
|
||||
}
|
||||
|
||||
static sigjmp_buf ill_jmp;
|
||||
static void ill_handler(int sig)
|
||||
{
|
||||
siglongjmp(ill_jmp, sig);
|
||||
}
|
||||
|
||||
static const char *env;
|
||||
static int parse_env(struct OPENSSL_s390xcap_st *cap);
|
||||
|
||||
void OPENSSL_s390x_facilities(void);
|
||||
void OPENSSL_s390x_functions(void);
|
||||
void OPENSSL_vx_probe(void);
|
||||
|
||||
struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P;
|
||||
@@ -30,6 +66,7 @@ void OPENSSL_cpuid_setup(void)
|
||||
{
|
||||
sigset_t oset;
|
||||
struct sigaction ill_act, oact;
|
||||
struct OPENSSL_s390xcap_st cap;
|
||||
|
||||
if (OPENSSL_s390xcap_P.stfle[0])
|
||||
return;
|
||||
@@ -37,6 +74,12 @@ void OPENSSL_cpuid_setup(void)
|
||||
/* set a bit that will not be tested later */
|
||||
OPENSSL_s390xcap_P.stfle[0] |= S390X_CAPBIT(0);
|
||||
|
||||
env = getenv("OPENSSL_s390xcap");
|
||||
if (env != NULL) {
|
||||
if (!parse_env(&cap))
|
||||
env = NULL;
|
||||
}
|
||||
|
||||
memset(&ill_act, 0, sizeof(ill_act));
|
||||
ill_act.sa_handler = ill_handler;
|
||||
sigfillset(&ill_act.sa_mask);
|
||||
@@ -51,6 +94,12 @@ void OPENSSL_cpuid_setup(void)
|
||||
if (sigsetjmp(ill_jmp, 1) == 0)
|
||||
OPENSSL_s390x_facilities();
|
||||
|
||||
if (env != NULL) {
|
||||
OPENSSL_s390xcap_P.stfle[0] &= cap.stfle[0];
|
||||
OPENSSL_s390xcap_P.stfle[1] &= cap.stfle[1];
|
||||
OPENSSL_s390xcap_P.stfle[2] &= cap.stfle[2];
|
||||
}
|
||||
|
||||
/* protection against disabled vector facility */
|
||||
if ((OPENSSL_s390xcap_P.stfle[2] & S390X_CAPBIT(S390X_VX))
|
||||
&& (sigsetjmp(ill_jmp, 1) == 0)) {
|
||||
@@ -64,4 +113,470 @@ void OPENSSL_cpuid_setup(void)
|
||||
sigaction(SIGFPE, &oact, NULL);
|
||||
sigaction(SIGILL, &oact, NULL);
|
||||
sigprocmask(SIG_SETMASK, &oset, NULL);
|
||||
|
||||
OPENSSL_s390x_functions();
|
||||
|
||||
if (env != NULL) {
|
||||
OPENSSL_s390xcap_P.kimd[0] &= cap.kimd[0];
|
||||
OPENSSL_s390xcap_P.kimd[1] &= cap.kimd[1];
|
||||
OPENSSL_s390xcap_P.klmd[0] &= cap.klmd[0];
|
||||
OPENSSL_s390xcap_P.klmd[1] &= cap.klmd[1];
|
||||
OPENSSL_s390xcap_P.km[0] &= cap.km[0];
|
||||
OPENSSL_s390xcap_P.km[1] &= cap.km[1];
|
||||
OPENSSL_s390xcap_P.kmc[0] &= cap.kmc[0];
|
||||
OPENSSL_s390xcap_P.kmc[1] &= cap.kmc[1];
|
||||
OPENSSL_s390xcap_P.kmac[0] &= cap.kmac[0];
|
||||
OPENSSL_s390xcap_P.kmac[1] &= cap.kmac[1];
|
||||
OPENSSL_s390xcap_P.kmctr[0] &= cap.kmctr[0];
|
||||
OPENSSL_s390xcap_P.kmctr[1] &= cap.kmctr[1];
|
||||
OPENSSL_s390xcap_P.kmo[0] &= cap.kmo[0];
|
||||
OPENSSL_s390xcap_P.kmo[1] &= cap.kmo[1];
|
||||
OPENSSL_s390xcap_P.kmf[0] &= cap.kmf[0];
|
||||
OPENSSL_s390xcap_P.kmf[1] &= cap.kmf[1];
|
||||
OPENSSL_s390xcap_P.prno[0] &= cap.prno[0];
|
||||
OPENSSL_s390xcap_P.prno[1] &= cap.prno[1];
|
||||
OPENSSL_s390xcap_P.kma[0] &= cap.kma[0];
|
||||
OPENSSL_s390xcap_P.kma[1] &= cap.kma[1];
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_env(struct OPENSSL_s390xcap_st *cap)
|
||||
{
|
||||
/*-
|
||||
* CPU model data
|
||||
* (only the STFLE- and QUERY-bits relevant to libcrypto are set)
|
||||
*/
|
||||
|
||||
/*-
|
||||
* z900 (2000) - z/Architecture POP SA22-7832-00
|
||||
* Facility detection would fail on real hw (no STFLE).
|
||||
*/
|
||||
static const struct OPENSSL_s390xcap_st z900 = {
|
||||
.stfle = {0ULL, 0ULL, 0ULL, 0ULL},
|
||||
.kimd = {0ULL, 0ULL},
|
||||
.klmd = {0ULL, 0ULL},
|
||||
.km = {0ULL, 0ULL},
|
||||
.kmc = {0ULL, 0ULL},
|
||||
.kmac = {0ULL, 0ULL},
|
||||
.kmctr = {0ULL, 0ULL},
|
||||
.kmo = {0ULL, 0ULL},
|
||||
.kmf = {0ULL, 0ULL},
|
||||
.prno = {0ULL, 0ULL},
|
||||
.kma = {0ULL, 0ULL},
|
||||
};
|
||||
|
||||
/*-
|
||||
* z990 (2003) - z/Architecture POP SA22-7832-02
|
||||
* Implements MSA. Facility detection would fail on real hw (no STFLE).
|
||||
*/
|
||||
static const struct OPENSSL_s390xcap_st z990 = {
|
||||
.stfle = {S390X_CAPBIT(S390X_MSA),
|
||||
0ULL, 0ULL, 0ULL},
|
||||
.kimd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1),
|
||||
0ULL},
|
||||
.klmd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1),
|
||||
0ULL},
|
||||
.km = {S390X_CAPBIT(S390X_QUERY),
|
||||
0ULL},
|
||||
.kmc = {S390X_CAPBIT(S390X_QUERY),
|
||||
0ULL},
|
||||
.kmac = {S390X_CAPBIT(S390X_QUERY),
|
||||
0ULL},
|
||||
.kmctr = {0ULL, 0ULL},
|
||||
.kmo = {0ULL, 0ULL},
|
||||
.kmf = {0ULL, 0ULL},
|
||||
.prno = {0ULL, 0ULL},
|
||||
.kma = {0ULL, 0ULL},
|
||||
};
|
||||
|
||||
/*-
|
||||
* z9 (2005) - z/Architecture POP SA22-7832-04
|
||||
* Implements MSA and MSA1.
|
||||
*/
|
||||
static const struct OPENSSL_s390xcap_st z9 = {
|
||||
.stfle = {S390X_CAPBIT(S390X_MSA)
|
||||
| S390X_CAPBIT(S390X_STCKF),
|
||||
0ULL, 0ULL, 0ULL},
|
||||
.kimd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256),
|
||||
0ULL},
|
||||
.klmd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256),
|
||||
0ULL},
|
||||
.km = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128),
|
||||
0ULL},
|
||||
.kmc = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128),
|
||||
0ULL},
|
||||
.kmac = {S390X_CAPBIT(S390X_QUERY),
|
||||
0ULL},
|
||||
.kmctr = {0ULL, 0ULL},
|
||||
.kmo = {0ULL, 0ULL},
|
||||
.kmf = {0ULL, 0ULL},
|
||||
.prno = {0ULL, 0ULL},
|
||||
.kma = {0ULL, 0ULL},
|
||||
};
|
||||
|
||||
/*-
|
||||
* z10 (2008) - z/Architecture POP SA22-7832-06
|
||||
* Implements MSA and MSA1-2.
|
||||
*/
|
||||
static const struct OPENSSL_s390xcap_st z10 = {
|
||||
.stfle = {S390X_CAPBIT(S390X_MSA)
|
||||
| S390X_CAPBIT(S390X_STCKF),
|
||||
0ULL, 0ULL, 0ULL},
|
||||
.kimd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256)
|
||||
| S390X_CAPBIT(S390X_SHA_512),
|
||||
0ULL},
|
||||
.klmd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256)
|
||||
| S390X_CAPBIT(S390X_SHA_512),
|
||||
0ULL},
|
||||
.km = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmc = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmac = {S390X_CAPBIT(S390X_QUERY),
|
||||
0ULL},
|
||||
.kmctr = {0ULL, 0ULL},
|
||||
.kmo = {0ULL, 0ULL},
|
||||
.kmf = {0ULL, 0ULL},
|
||||
.prno = {0ULL, 0ULL},
|
||||
.kma = {0ULL, 0ULL},
|
||||
};
|
||||
|
||||
/*-
|
||||
* z196 (2010) - z/Architecture POP SA22-7832-08
|
||||
* Implements MSA and MSA1-4.
|
||||
*/
|
||||
static const struct OPENSSL_s390xcap_st z196 = {
|
||||
.stfle = {S390X_CAPBIT(S390X_MSA)
|
||||
| S390X_CAPBIT(S390X_STCKF),
|
||||
S390X_CAPBIT(S390X_MSA3)
|
||||
| S390X_CAPBIT(S390X_MSA4),
|
||||
0ULL, 0ULL},
|
||||
.kimd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256)
|
||||
| S390X_CAPBIT(S390X_SHA_512),
|
||||
S390X_CAPBIT(S390X_GHASH)},
|
||||
.klmd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256)
|
||||
| S390X_CAPBIT(S390X_SHA_512),
|
||||
0ULL},
|
||||
.km = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256)
|
||||
| S390X_CAPBIT(S390X_XTS_AES_128)
|
||||
| S390X_CAPBIT(S390X_XTS_AES_256),
|
||||
0ULL},
|
||||
.kmc = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmac = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmctr = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmo = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmf = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.prno = {0ULL, 0ULL},
|
||||
.kma = {0ULL, 0ULL},
|
||||
};
|
||||
|
||||
/*-
|
||||
* zEC12 (2012) - z/Architecture POP SA22-7832-09
|
||||
* Implements MSA and MSA1-4.
|
||||
*/
|
||||
static const struct OPENSSL_s390xcap_st zEC12 = {
|
||||
.stfle = {S390X_CAPBIT(S390X_MSA)
|
||||
| S390X_CAPBIT(S390X_STCKF),
|
||||
S390X_CAPBIT(S390X_MSA3)
|
||||
| S390X_CAPBIT(S390X_MSA4),
|
||||
0ULL, 0ULL},
|
||||
.kimd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256)
|
||||
| S390X_CAPBIT(S390X_SHA_512),
|
||||
S390X_CAPBIT(S390X_GHASH)},
|
||||
.klmd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256)
|
||||
| S390X_CAPBIT(S390X_SHA_512),
|
||||
0ULL},
|
||||
.km = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256)
|
||||
| S390X_CAPBIT(S390X_XTS_AES_128)
|
||||
| S390X_CAPBIT(S390X_XTS_AES_256),
|
||||
0ULL},
|
||||
.kmc = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmac = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmctr = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmo = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmf = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.prno = {0ULL, 0ULL},
|
||||
.kma = {0ULL, 0ULL},
|
||||
};
|
||||
|
||||
/*-
|
||||
* z13 (2015) - z/Architecture POP SA22-7832-10
|
||||
* Implements MSA and MSA1-5.
|
||||
*/
|
||||
static const struct OPENSSL_s390xcap_st z13 = {
|
||||
.stfle = {S390X_CAPBIT(S390X_MSA)
|
||||
| S390X_CAPBIT(S390X_STCKF)
|
||||
| S390X_CAPBIT(S390X_MSA5),
|
||||
S390X_CAPBIT(S390X_MSA3)
|
||||
| S390X_CAPBIT(S390X_MSA4),
|
||||
S390X_CAPBIT(S390X_VX),
|
||||
0ULL},
|
||||
.kimd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256)
|
||||
| S390X_CAPBIT(S390X_SHA_512),
|
||||
S390X_CAPBIT(S390X_GHASH)},
|
||||
.klmd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256)
|
||||
| S390X_CAPBIT(S390X_SHA_512),
|
||||
0ULL},
|
||||
.km = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256)
|
||||
| S390X_CAPBIT(S390X_XTS_AES_128)
|
||||
| S390X_CAPBIT(S390X_XTS_AES_256),
|
||||
0ULL},
|
||||
.kmc = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmac = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmctr = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmo = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmf = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.prno = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_512_DRNG),
|
||||
0ULL},
|
||||
.kma = {0ULL, 0ULL},
|
||||
};
|
||||
|
||||
/*-
|
||||
* z14 (2017) - z/Architecture POP SA22-7832-11
|
||||
* Implements MSA and MSA1-8.
|
||||
*/
|
||||
static const struct OPENSSL_s390xcap_st z14 = {
|
||||
.stfle = {S390X_CAPBIT(S390X_MSA)
|
||||
| S390X_CAPBIT(S390X_STCKF)
|
||||
| S390X_CAPBIT(S390X_MSA5),
|
||||
S390X_CAPBIT(S390X_MSA3)
|
||||
| S390X_CAPBIT(S390X_MSA4),
|
||||
S390X_CAPBIT(S390X_VX)
|
||||
| S390X_CAPBIT(S390X_VXD)
|
||||
| S390X_CAPBIT(S390X_VXE)
|
||||
| S390X_CAPBIT(S390X_MSA8),
|
||||
0ULL},
|
||||
.kimd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256)
|
||||
| S390X_CAPBIT(S390X_SHA_512)
|
||||
| S390X_CAPBIT(S390X_SHA3_224)
|
||||
| S390X_CAPBIT(S390X_SHA3_256)
|
||||
| S390X_CAPBIT(S390X_SHA3_384)
|
||||
| S390X_CAPBIT(S390X_SHA3_512)
|
||||
| S390X_CAPBIT(S390X_SHAKE_128)
|
||||
| S390X_CAPBIT(S390X_SHAKE_256),
|
||||
S390X_CAPBIT(S390X_GHASH)},
|
||||
.klmd = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_1)
|
||||
| S390X_CAPBIT(S390X_SHA_256)
|
||||
| S390X_CAPBIT(S390X_SHA_512)
|
||||
| S390X_CAPBIT(S390X_SHA3_224)
|
||||
| S390X_CAPBIT(S390X_SHA3_256)
|
||||
| S390X_CAPBIT(S390X_SHA3_384)
|
||||
| S390X_CAPBIT(S390X_SHA3_512)
|
||||
| S390X_CAPBIT(S390X_SHAKE_128)
|
||||
| S390X_CAPBIT(S390X_SHAKE_256),
|
||||
0ULL},
|
||||
.km = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256)
|
||||
| S390X_CAPBIT(S390X_XTS_AES_128)
|
||||
| S390X_CAPBIT(S390X_XTS_AES_256),
|
||||
0ULL},
|
||||
.kmc = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmac = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmctr = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmo = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.kmf = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
.prno = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_SHA_512_DRNG),
|
||||
S390X_CAPBIT(S390X_TRNG)},
|
||||
.kma = {S390X_CAPBIT(S390X_QUERY)
|
||||
| S390X_CAPBIT(S390X_AES_128)
|
||||
| S390X_CAPBIT(S390X_AES_192)
|
||||
| S390X_CAPBIT(S390X_AES_256),
|
||||
0ULL},
|
||||
};
|
||||
|
||||
char *tok_begin, *tok_end, *buff, tok[S390X_STFLE_MAX][LEN + 1];
|
||||
int rc, off, i, n;
|
||||
|
||||
buff = malloc(strlen(env) + 1);
|
||||
if (buff == NULL)
|
||||
return 0;
|
||||
|
||||
rc = 0;
|
||||
memset(cap, ~0, sizeof(*cap));
|
||||
strcpy(buff, env);
|
||||
|
||||
tok_begin = buff + strspn(buff, ";");
|
||||
strtok(tok_begin, ";");
|
||||
tok_end = strtok(NULL, ";");
|
||||
|
||||
while (tok_begin != NULL) {
|
||||
/* stfle token */
|
||||
if ((n = sscanf(tok_begin,
|
||||
" stfle : %" STR(LEN) "[^:] : "
|
||||
"%" STR(LEN) "[^:] : %" STR(LEN) "s ",
|
||||
tok[0], tok[1], tok[2]))) {
|
||||
for (i = 0; i < n; i++) {
|
||||
off = (tok[i][0] == '~') ? 1 : 0;
|
||||
if (sscanf(tok[i] + off, "%llx", &cap->stfle[i]) != 1)
|
||||
goto ret;
|
||||
if (off)
|
||||
cap->stfle[i] = ~cap->stfle[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* query function tokens */
|
||||
else if TOK_FUNC(kimd)
|
||||
else if TOK_FUNC(klmd)
|
||||
else if TOK_FUNC(km)
|
||||
else if TOK_FUNC(kmc)
|
||||
else if TOK_FUNC(kmac)
|
||||
else if TOK_FUNC(kmctr)
|
||||
else if TOK_FUNC(kmo)
|
||||
else if TOK_FUNC(kmf)
|
||||
else if TOK_FUNC(prno)
|
||||
else if TOK_FUNC(kma)
|
||||
|
||||
/* CPU model tokens */
|
||||
else if TOK_CPU(z900)
|
||||
else if TOK_CPU(z990)
|
||||
else if TOK_CPU(z9)
|
||||
else if TOK_CPU(z10)
|
||||
else if TOK_CPU(z196)
|
||||
else if TOK_CPU(zEC12)
|
||||
else if TOK_CPU(z13)
|
||||
else if TOK_CPU(z14)
|
||||
|
||||
/* whitespace(ignored) or invalid tokens */
|
||||
else {
|
||||
while (*tok_begin != '\0') {
|
||||
if (!ossl_isspace(*tok_begin))
|
||||
goto ret;
|
||||
tok_begin++;
|
||||
}
|
||||
}
|
||||
|
||||
tok_begin = tok_end;
|
||||
tok_end = strtok(NULL, ";");
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
ret:
|
||||
free(buff);
|
||||
return rc;
|
||||
}
|
||||
+21
-10
@@ -38,7 +38,26 @@ OPENSSL_s390x_facilities:
|
||||
stg %r0,S390X_STFLE+8(%r4) # wipe capability vectors
|
||||
stg %r0,S390X_STFLE+16(%r4)
|
||||
stg %r0,S390X_STFLE+24(%r4)
|
||||
stg %r0,S390X_KIMD(%r4)
|
||||
|
||||
.long 0xb2b04000 # stfle 0(%r4)
|
||||
brc 8,.Ldone
|
||||
lghi %r0,1
|
||||
.long 0xb2b04000 # stfle 0(%r4)
|
||||
brc 8,.Ldone
|
||||
lghi %r0,2
|
||||
.long 0xb2b04000 # stfle 0(%r4)
|
||||
.Ldone:
|
||||
br $ra
|
||||
.size OPENSSL_s390x_facilities,.-OPENSSL_s390x_facilities
|
||||
|
||||
.globl OPENSSL_s390x_functions
|
||||
.type OPENSSL_s390x_functions,\@function
|
||||
.align 16
|
||||
OPENSSL_s390x_functions:
|
||||
lghi %r0,0
|
||||
larl %r4,OPENSSL_s390xcap_P
|
||||
|
||||
stg %r0,S390X_KIMD(%r4) # wipe capability vectors
|
||||
stg %r0,S390X_KIMD+8(%r4)
|
||||
stg %r0,S390X_KLMD(%r4)
|
||||
stg %r0,S390X_KLMD+8(%r4)
|
||||
@@ -59,14 +78,6 @@ OPENSSL_s390x_facilities:
|
||||
stg %r0,S390X_KMA(%r4)
|
||||
stg %r0,S390X_KMA+8(%r4)
|
||||
|
||||
.long 0xb2b04000 # stfle 0(%r4)
|
||||
brc 8,.Ldone
|
||||
lghi %r0,1
|
||||
.long 0xb2b04000 # stfle 0(%r4)
|
||||
brc 8,.Ldone
|
||||
lghi %r0,2
|
||||
.long 0xb2b04000 # stfle 0(%r4)
|
||||
.Ldone:
|
||||
lmg %r2,%r3,S390X_STFLE(%r4)
|
||||
tmhl %r2,0x4000 # check for message-security-assist
|
||||
jz .Lret
|
||||
@@ -123,7 +134,7 @@ OPENSSL_s390x_facilities:
|
||||
|
||||
.Lret:
|
||||
br $ra
|
||||
.size OPENSSL_s390x_facilities,.-OPENSSL_s390x_facilities
|
||||
.size OPENSSL_s390x_functions,.-OPENSSL_s390x_functions
|
||||
|
||||
.globl OPENSSL_rdtsc
|
||||
.type OPENSSL_rdtsc,\@function
|
||||
|
||||
@@ -533,30 +533,28 @@ my @A = map([ "v".$_.".16b", "v".($_+1).".16b", "v".($_+2).".16b",
|
||||
(0, 5, 10, 15, 20));
|
||||
|
||||
my @C = map("v$_.16b", (25..31));
|
||||
my @D = @C[4,5,6,2,3];
|
||||
|
||||
$code.=<<___;
|
||||
.type KeccakF1600_ce,%function
|
||||
.align 5
|
||||
KeccakF1600_ce:
|
||||
mov x9,#12
|
||||
mov x9,#24
|
||||
adr x10,iotas
|
||||
b .Loop_ce
|
||||
.align 4
|
||||
.Loop_ce:
|
||||
___
|
||||
for($i=0; $i<2; $i++) {
|
||||
$code.=<<___;
|
||||
////////////////////////////////////////////////// Theta
|
||||
eor3 $C[0],$A[0][0],$A[1][0],$A[2][0]
|
||||
eor3 $C[1],$A[0][1],$A[1][1],$A[2][1]
|
||||
eor3 $C[2],$A[0][2],$A[1][2],$A[2][2]
|
||||
eor3 $C[3],$A[0][3],$A[1][3],$A[2][3]
|
||||
eor3 $C[4],$A[0][4],$A[1][4],$A[2][4]
|
||||
eor3 $C[0],$C[0], $A[3][0],$A[4][0]
|
||||
eor3 $C[1],$C[1], $A[3][1],$A[4][1]
|
||||
eor3 $C[2],$C[2], $A[3][2],$A[4][2]
|
||||
eor3 $C[3],$C[3], $A[3][3],$A[4][3]
|
||||
eor3 $C[4],$C[4], $A[3][4],$A[4][4]
|
||||
eor3 $C[0],$A[4][0],$A[3][0],$A[2][0]
|
||||
eor3 $C[1],$A[4][1],$A[3][1],$A[2][1]
|
||||
eor3 $C[2],$A[4][2],$A[3][2],$A[2][2]
|
||||
eor3 $C[3],$A[4][3],$A[3][3],$A[2][3]
|
||||
eor3 $C[4],$A[4][4],$A[3][4],$A[2][4]
|
||||
eor3 $C[0],$C[0], $A[1][0],$A[0][0]
|
||||
eor3 $C[1],$C[1], $A[1][1],$A[0][1]
|
||||
eor3 $C[2],$C[2], $A[1][2],$A[0][2]
|
||||
eor3 $C[3],$C[3], $A[1][3],$A[0][3]
|
||||
eor3 $C[4],$C[4], $A[1][4],$A[0][4]
|
||||
|
||||
rax1 $C[5],$C[0],$C[2] // D[1]
|
||||
rax1 $C[6],$C[1],$C[3] // D[2]
|
||||
@@ -565,81 +563,75 @@ $code.=<<___;
|
||||
rax1 $C[4],$C[4],$C[1] // D[0]
|
||||
|
||||
////////////////////////////////////////////////// Theta+Rho+Pi
|
||||
xar $C[0], $A[1][1],$C[5],#64-$rhotates[1][1] // C[0]=A[0][1]
|
||||
xar $A[1][1],$A[1][4],$C[3],#64-$rhotates[1][4]
|
||||
xar $A[1][4],$A[4][2],$C[6],#64-$rhotates[4][2]
|
||||
xar $A[4][2],$A[2][4],$C[3],#64-$rhotates[2][4]
|
||||
xar $A[2][4],$A[4][0],$C[4],#64-$rhotates[4][0]
|
||||
xar $C[0], $A[0][1],$D[1],#64-$rhotates[0][1] // C[0]=A[2][0]
|
||||
|
||||
xar $A[4][0],$A[0][2],$C[6],#64-$rhotates[0][2]
|
||||
xar $A[0][1],$A[1][1],$D[1],#64-$rhotates[1][1]
|
||||
xar $A[1][1],$A[1][4],$D[4],#64-$rhotates[1][4]
|
||||
xar $A[1][4],$A[4][2],$D[2],#64-$rhotates[4][2]
|
||||
xar $A[4][2],$A[2][4],$D[4],#64-$rhotates[2][4]
|
||||
xar $A[2][4],$A[4][0],$D[0],#64-$rhotates[4][0]
|
||||
|
||||
xar $A[0][2],$A[2][2],$C[6],#64-$rhotates[2][2]
|
||||
xar $A[2][2],$A[2][3],$C[2],#64-$rhotates[2][3]
|
||||
xar $A[2][3],$A[3][4],$C[3],#64-$rhotates[3][4]
|
||||
xar $A[3][4],$A[4][3],$C[2],#64-$rhotates[4][3]
|
||||
xar $A[4][3],$A[3][0],$C[4],#64-$rhotates[3][0]
|
||||
xar $C[1], $A[0][2],$D[2],#64-$rhotates[0][2] // C[1]=A[4][0]
|
||||
|
||||
xar $A[3][0],$A[0][4],$C[3],#64-$rhotates[0][4]
|
||||
xar $A[0][2],$A[2][2],$D[2],#64-$rhotates[2][2]
|
||||
xar $A[2][2],$A[2][3],$D[3],#64-$rhotates[2][3]
|
||||
xar $A[2][3],$A[3][4],$D[4],#64-$rhotates[3][4]
|
||||
xar $A[3][4],$A[4][3],$D[3],#64-$rhotates[4][3]
|
||||
xar $A[4][3],$A[3][0],$D[0],#64-$rhotates[3][0]
|
||||
|
||||
eor $A[0][0],$A[0][0],$C[4]
|
||||
ldr x11,[x10],#8
|
||||
xar $A[3][0],$A[0][4],$D[4],#64-$rhotates[0][4]
|
||||
|
||||
xar $C[1], $A[3][3],$C[2],#64-$rhotates[3][3] // C[1]=A[0][3]
|
||||
xar $A[3][3],$A[3][2],$C[6],#64-$rhotates[3][2]
|
||||
xar $A[3][2],$A[2][1],$C[5],#64-$rhotates[2][1]
|
||||
xar $A[2][1],$A[1][2],$C[6],#64-$rhotates[1][2]
|
||||
xar $A[1][2],$A[2][0],$C[4],#64-$rhotates[2][0]
|
||||
xar $D[4], $A[4][4],$D[4],#64-$rhotates[4][4] // D[4]=A[0][4]
|
||||
xar $A[4][4],$A[4][1],$D[1],#64-$rhotates[4][1]
|
||||
xar $A[1][3],$A[1][3],$D[3],#64-$rhotates[1][3] // A[1][3]=A[4][1]
|
||||
xar $A[0][4],$A[3][1],$D[1],#64-$rhotates[3][1] // A[0][4]=A[1][3]
|
||||
xar $A[3][1],$A[1][0],$D[0],#64-$rhotates[1][0]
|
||||
|
||||
xar $A[2][0],$A[0][1],$C[5],#64-$rhotates[0][1] // *
|
||||
xar $A[1][0],$A[0][3],$D[3],#64-$rhotates[0][3]
|
||||
|
||||
xar $A[0][4],$A[4][4],$C[3],#64-$rhotates[4][4]
|
||||
xar $A[4][4],$A[4][1],$C[5],#64-$rhotates[4][1]
|
||||
xar $A[4][1],$A[1][3],$C[2],#64-$rhotates[1][3]
|
||||
xar $A[1][3],$A[3][1],$C[5],#64-$rhotates[3][1]
|
||||
xar $A[3][1],$A[1][0],$C[4],#64-$rhotates[1][0]
|
||||
eor $A[0][0],$A[0][0],$D[0]
|
||||
|
||||
xar $C[2], $A[0][3],$C[2],#64-$rhotates[0][3] // C[2]=A[1][0]
|
||||
xar $D[3], $A[3][3],$D[3],#64-$rhotates[3][3] // D[3]=A[0][3]
|
||||
xar $A[0][3],$A[3][2],$D[2],#64-$rhotates[3][2] // A[0][3]=A[3][3]
|
||||
xar $D[1], $A[2][1],$D[1],#64-$rhotates[2][1] // D[1]=A[3][2]
|
||||
xar $D[2], $A[1][2],$D[2],#64-$rhotates[1][2] // D[2]=A[2][1]
|
||||
xar $D[0], $A[2][0],$D[0],#64-$rhotates[2][0] // D[0]=A[1][2]
|
||||
|
||||
////////////////////////////////////////////////// Chi+Iota
|
||||
dup $C[6],x11 // borrow C[6]
|
||||
bcax $C[3], $A[0][0],$A[0][2],$C[0] // *
|
||||
bcax $A[0][1],$C[0], $C[1], $A[0][2] // *
|
||||
bcax $A[0][2],$A[0][2],$A[0][4],$C[1]
|
||||
bcax $A[0][3],$C[1], $A[0][0],$A[0][4]
|
||||
bcax $A[0][4],$A[0][4],$C[0], $A[0][0]
|
||||
|
||||
bcax $A[1][0],$C[2], $A[1][2],$A[1][1] // *
|
||||
bcax $C[0], $A[1][1],$A[1][3],$A[1][2] // *
|
||||
bcax $A[1][2],$A[1][2],$A[1][4],$A[1][3]
|
||||
bcax $A[1][3],$A[1][3],$C[2], $A[1][4]
|
||||
bcax $A[1][4],$A[1][4],$A[1][1],$C[2]
|
||||
|
||||
eor $A[0][0],$C[3],$C[6] // Iota
|
||||
|
||||
bcax $C[1], $A[2][0],$A[2][2],$A[2][1] // *
|
||||
bcax $C[2], $A[2][1],$A[2][3],$A[2][2] // *
|
||||
bcax $A[2][2],$A[2][2],$A[2][4],$A[2][3]
|
||||
bcax $A[2][3],$A[2][3],$A[2][0],$A[2][4]
|
||||
bcax $A[2][4],$A[2][4],$A[2][1],$A[2][0]
|
||||
|
||||
bcax $C[3], $A[3][0],$A[3][2],$A[3][1] // *
|
||||
bcax $C[4], $A[3][1],$A[3][3],$A[3][2] // *
|
||||
bcax $A[3][2],$A[3][2],$A[3][4],$A[3][3]
|
||||
bcax $A[3][3],$A[3][3],$A[3][0],$A[3][4]
|
||||
bcax $A[3][4],$A[3][4],$A[3][1],$A[3][0]
|
||||
|
||||
bcax $C[5], $A[4][0],$A[4][2],$A[4][1] // *
|
||||
bcax $C[6], $A[4][1],$A[4][3],$A[4][2] // *
|
||||
bcax $A[4][0],$C[1], $A[4][2],$A[1][3] // A[1][3]=A[4][1]
|
||||
bcax $A[4][1],$A[1][3],$A[4][3],$A[4][2] // A[1][3]=A[4][1]
|
||||
bcax $A[4][2],$A[4][2],$A[4][4],$A[4][3]
|
||||
bcax $A[4][3],$A[4][3],$A[4][0],$A[4][4]
|
||||
bcax $A[4][4],$A[4][4],$A[4][1],$A[4][0]
|
||||
___
|
||||
( $A[1][1], $C[0]) = ( $C[0], $A[1][1]);
|
||||
($A[2][0],$A[2][1], $C[1],$C[2]) = ($C[1],$C[2], $A[2][0],$A[2][1]);
|
||||
($A[3][0],$A[3][1], $C[3],$C[4]) = ($C[3],$C[4], $A[3][0],$A[3][1]);
|
||||
($A[4][0],$A[4][1], $C[5],$C[6]) = ($C[5],$C[6], $A[4][0],$A[4][1]);
|
||||
}
|
||||
$code.=<<___;
|
||||
bcax $A[4][3],$A[4][3],$C[1], $A[4][4]
|
||||
bcax $A[4][4],$A[4][4],$A[1][3],$C[1] // A[1][3]=A[4][1]
|
||||
|
||||
ld1r {$C[1]},[x10],#8
|
||||
|
||||
bcax $A[3][2],$D[1], $A[3][4],$A[0][3] // A[0][3]=A[3][3]
|
||||
bcax $A[3][3],$A[0][3],$A[3][0],$A[3][4] // A[0][3]=A[3][3]
|
||||
bcax $A[3][4],$A[3][4],$A[3][1],$A[3][0]
|
||||
bcax $A[3][0],$A[3][0],$D[1], $A[3][1]
|
||||
bcax $A[3][1],$A[3][1],$A[0][3],$D[1] // A[0][3]=A[3][3]
|
||||
|
||||
bcax $A[2][0],$C[0], $A[2][2],$D[2]
|
||||
bcax $A[2][1],$D[2], $A[2][3],$A[2][2]
|
||||
bcax $A[2][2],$A[2][2],$A[2][4],$A[2][3]
|
||||
bcax $A[2][3],$A[2][3],$C[0], $A[2][4]
|
||||
bcax $A[2][4],$A[2][4],$D[2], $C[0]
|
||||
|
||||
bcax $A[1][2],$D[0], $A[1][4],$A[0][4] // A[0][4]=A[1][3]
|
||||
bcax $A[1][3],$A[0][4],$A[1][0],$A[1][4] // A[0][4]=A[1][3]
|
||||
bcax $A[1][4],$A[1][4],$A[1][1],$A[1][0]
|
||||
bcax $A[1][0],$A[1][0],$D[0], $A[1][1]
|
||||
bcax $A[1][1],$A[1][1],$A[0][4],$D[0] // A[0][4]=A[1][3]
|
||||
|
||||
bcax $A[0][3],$D[3], $A[0][0],$D[4]
|
||||
bcax $A[0][4],$D[4], $A[0][1],$A[0][0]
|
||||
bcax $A[0][0],$A[0][0],$A[0][2],$A[0][1]
|
||||
bcax $A[0][1],$A[0][1],$D[3], $A[0][2]
|
||||
bcax $A[0][2],$A[0][2],$D[4], $D[3]
|
||||
|
||||
eor $A[0][0],$A[0][0],$C[1]
|
||||
|
||||
subs x9,x9,#1
|
||||
bne .Loop_ce
|
||||
|
||||
@@ -857,7 +849,7 @@ foreach(split("\n",$code)) {
|
||||
|
||||
s/\`([^\`]*)\`/eval($1)/ge;
|
||||
|
||||
m/\bdup\b/ and s/\.16b/.2d/g or
|
||||
m/\bld1r\b/ and s/\.16b/.2d/g or
|
||||
s/\b(eor3|rax1|xar|bcax)\s+(v.*)/unsha3($1,$2)/ge;
|
||||
|
||||
print $_,"\n";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]=\
|
||||
siphash.c \
|
||||
siphash_pmeth.c \
|
||||
siphash_meth.c \
|
||||
siphash_ameth.c
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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 <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include "internal/siphash.h"
|
||||
#include "siphash_local.h"
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
/* local SIPHASH structure is actually a SIPHASH */
|
||||
|
||||
struct evp_mac_impl_st {
|
||||
SIPHASH ctx;
|
||||
};
|
||||
|
||||
static EVP_MAC_IMPL *siphash_new(void)
|
||||
{
|
||||
return OPENSSL_zalloc(sizeof(EVP_MAC_IMPL));
|
||||
}
|
||||
|
||||
static void siphash_free(EVP_MAC_IMPL *sctx)
|
||||
{
|
||||
OPENSSL_free(sctx);
|
||||
}
|
||||
|
||||
static int siphash_copy(EVP_MAC_IMPL *sdst, EVP_MAC_IMPL *ssrc)
|
||||
{
|
||||
*sdst = *ssrc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t siphash_size(EVP_MAC_IMPL *sctx)
|
||||
{
|
||||
return SipHash_hash_size(&sctx->ctx);
|
||||
}
|
||||
|
||||
static int siphash_init(EVP_MAC_IMPL *sctx)
|
||||
{
|
||||
/* Not much to do here, actual initialization happens through controls */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int siphash_update(EVP_MAC_IMPL *sctx, const unsigned char *data,
|
||||
size_t datalen)
|
||||
{
|
||||
SipHash_Update(&sctx->ctx, data, datalen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int siphash_final(EVP_MAC_IMPL *sctx, unsigned char *out)
|
||||
{
|
||||
size_t hlen = siphash_size(sctx);
|
||||
|
||||
return SipHash_Final(&sctx->ctx, out, hlen);
|
||||
}
|
||||
|
||||
static int siphash_ctrl(EVP_MAC_IMPL *sctx, int cmd, va_list args)
|
||||
{
|
||||
switch (cmd) {
|
||||
case EVP_MAC_CTRL_SET_SIZE:
|
||||
{
|
||||
size_t size = va_arg(args, size_t);
|
||||
|
||||
return SipHash_set_hash_size(&sctx->ctx, size);
|
||||
}
|
||||
break;
|
||||
case EVP_MAC_CTRL_SET_KEY:
|
||||
{
|
||||
const unsigned char *key = va_arg(args, const unsigned char *);
|
||||
size_t keylen = va_arg(args, size_t);
|
||||
|
||||
if (key == NULL || keylen != SIPHASH_KEY_SIZE)
|
||||
return 0;
|
||||
|
||||
return SipHash_Init(&sctx->ctx, key, 0, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int siphash_ctrl_int(EVP_MAC_IMPL *sctx, int cmd, ...)
|
||||
{
|
||||
int rv;
|
||||
va_list args;
|
||||
|
||||
va_start(args, cmd);
|
||||
rv = siphash_ctrl(sctx, cmd, args);
|
||||
va_end(args);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int siphash_ctrl_str_cb(void *ctx, int cmd, void *buf, size_t buflen)
|
||||
{
|
||||
return siphash_ctrl_int(ctx, cmd, buf, buflen);
|
||||
}
|
||||
|
||||
static int siphash_ctrl_str(EVP_MAC_IMPL *ctx,
|
||||
const char *type, const char *value)
|
||||
{
|
||||
if (value == NULL)
|
||||
return 0;
|
||||
if (strcmp(type, "digestsize") == 0) {
|
||||
size_t hash_size = atoi(value);
|
||||
|
||||
return siphash_ctrl_int(ctx, EVP_MAC_CTRL_SET_SIZE, hash_size);
|
||||
}
|
||||
if (strcmp(type, "key") == 0)
|
||||
return EVP_str2ctrl(siphash_ctrl_str_cb, ctx, EVP_MAC_CTRL_SET_KEY,
|
||||
value);
|
||||
if (strcmp(type, "hexkey") == 0)
|
||||
return EVP_hex2ctrl(siphash_ctrl_str_cb, ctx, EVP_MAC_CTRL_SET_KEY,
|
||||
value);
|
||||
return -2;
|
||||
}
|
||||
|
||||
const EVP_MAC siphash_meth = {
|
||||
EVP_MAC_SIPHASH,
|
||||
siphash_new,
|
||||
siphash_copy,
|
||||
siphash_free,
|
||||
siphash_size,
|
||||
siphash_init,
|
||||
siphash_update,
|
||||
siphash_final,
|
||||
siphash_ctrl,
|
||||
siphash_ctrl_str
|
||||
};
|
||||
@@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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 <stdio.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include "internal/siphash.h"
|
||||
#include "siphash_local.h"
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
/* SIPHASH pkey context structure */
|
||||
|
||||
typedef struct siphash_pkey_ctx_st {
|
||||
ASN1_OCTET_STRING ktmp; /* Temp storage for key */
|
||||
SIPHASH ctx;
|
||||
} SIPHASH_PKEY_CTX;
|
||||
|
||||
static int pkey_siphash_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
SIPHASH_PKEY_CTX *pctx;
|
||||
|
||||
if ((pctx = OPENSSL_zalloc(sizeof(*pctx))) == NULL) {
|
||||
CRYPTOerr(CRYPTO_F_PKEY_SIPHASH_INIT, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
pctx->ktmp.type = V_ASN1_OCTET_STRING;
|
||||
|
||||
EVP_PKEY_CTX_set_data(ctx, pctx);
|
||||
EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pkey_siphash_cleanup(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
|
||||
if (pctx != NULL) {
|
||||
OPENSSL_clear_free(pctx->ktmp.data, pctx->ktmp.length);
|
||||
OPENSSL_clear_free(pctx, sizeof(*pctx));
|
||||
EVP_PKEY_CTX_set_data(ctx, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_siphash_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
|
||||
{
|
||||
SIPHASH_PKEY_CTX *sctx, *dctx;
|
||||
|
||||
/* allocate memory for dst->data and a new SIPHASH_CTX in dst->data->ctx */
|
||||
if (!pkey_siphash_init(dst))
|
||||
return 0;
|
||||
sctx = EVP_PKEY_CTX_get_data(src);
|
||||
dctx = EVP_PKEY_CTX_get_data(dst);
|
||||
if (ASN1_STRING_get0_data(&sctx->ktmp) != NULL &&
|
||||
!ASN1_STRING_copy(&dctx->ktmp, &sctx->ktmp)) {
|
||||
/* cleanup and free the SIPHASH_PKEY_CTX in dst->data */
|
||||
pkey_siphash_cleanup(dst);
|
||||
return 0;
|
||||
}
|
||||
memcpy(&dctx->ctx, &sctx->ctx, sizeof(SIPHASH));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_siphash_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
ASN1_OCTET_STRING *key;
|
||||
SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
|
||||
if (ASN1_STRING_get0_data(&pctx->ktmp) == NULL)
|
||||
return 0;
|
||||
key = ASN1_OCTET_STRING_dup(&pctx->ktmp);
|
||||
if (key == NULL)
|
||||
return 0;
|
||||
return EVP_PKEY_assign_SIPHASH(pkey, key);
|
||||
}
|
||||
|
||||
static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
|
||||
{
|
||||
SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
|
||||
|
||||
SipHash_Update(&pctx->ctx, data, count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int siphash_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
|
||||
{
|
||||
SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
const unsigned char* key;
|
||||
size_t len;
|
||||
|
||||
key = EVP_PKEY_get0_siphash(EVP_PKEY_CTX_get0_pkey(ctx), &len);
|
||||
if (key == NULL || len != SIPHASH_KEY_SIZE)
|
||||
return 0;
|
||||
EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
|
||||
EVP_MD_CTX_set_update_fn(mctx, int_update);
|
||||
return SipHash_Init(&pctx->ctx, key, 0, 0);
|
||||
}
|
||||
static int siphash_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
|
||||
EVP_MD_CTX *mctx)
|
||||
{
|
||||
SIPHASH_PKEY_CTX *pctx = ctx->data;
|
||||
|
||||
*siglen = SipHash_hash_size(&pctx->ctx);
|
||||
if (sig != NULL)
|
||||
return SipHash_Final(&pctx->ctx, sig, *siglen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_siphash_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
{
|
||||
SIPHASH_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
const unsigned char *key;
|
||||
size_t len;
|
||||
|
||||
switch (type) {
|
||||
|
||||
case EVP_PKEY_CTRL_MD:
|
||||
/* ignore */
|
||||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_SET_DIGEST_SIZE:
|
||||
return SipHash_set_hash_size(&pctx->ctx, p1);
|
||||
|
||||
case EVP_PKEY_CTRL_SET_MAC_KEY:
|
||||
case EVP_PKEY_CTRL_DIGESTINIT:
|
||||
if (type == EVP_PKEY_CTRL_SET_MAC_KEY) {
|
||||
/* user explicitly setting the key */
|
||||
key = p2;
|
||||
len = p1;
|
||||
} else {
|
||||
/* user indirectly setting the key via EVP_DigestSignInit */
|
||||
key = EVP_PKEY_get0_siphash(EVP_PKEY_CTX_get0_pkey(ctx), &len);
|
||||
}
|
||||
if (key == NULL || len != SIPHASH_KEY_SIZE ||
|
||||
!ASN1_OCTET_STRING_set(&pctx->ktmp, key, len))
|
||||
return 0;
|
||||
/* use default rounds (2,4) */
|
||||
return SipHash_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp),
|
||||
0, 0);
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_siphash_ctrl_str(EVP_PKEY_CTX *ctx,
|
||||
const char *type, const char *value)
|
||||
{
|
||||
if (value == NULL)
|
||||
return 0;
|
||||
if (strcmp(type, "digestsize") == 0) {
|
||||
size_t hash_size = atoi(value);
|
||||
|
||||
return pkey_siphash_ctrl(ctx, EVP_PKEY_CTRL_SET_DIGEST_SIZE, hash_size,
|
||||
NULL);
|
||||
}
|
||||
if (strcmp(type, "key") == 0)
|
||||
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
|
||||
if (strcmp(type, "hexkey") == 0)
|
||||
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
|
||||
return -2;
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD siphash_pkey_meth = {
|
||||
EVP_PKEY_SIPHASH,
|
||||
EVP_PKEY_FLAG_SIGCTX_CUSTOM, /* we don't deal with a separate MD */
|
||||
pkey_siphash_init,
|
||||
pkey_siphash_copy,
|
||||
pkey_siphash_cleanup,
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
pkey_siphash_keygen,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
siphash_signctx_init,
|
||||
siphash_signctx,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_siphash_ctrl,
|
||||
pkey_siphash_ctrl_str
|
||||
};
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "internal/sm2.h"
|
||||
#include "internal/sm2err.h"
|
||||
#include "internal/ec_int.h" /* ecdh_KDF_X9_63() */
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bn.h>
|
||||
@@ -203,7 +204,7 @@ int sm2_encrypt(const EC_KEY *key,
|
||||
}
|
||||
|
||||
/* X9.63 with no salt happens to match the KDF used in SM2 */
|
||||
if (!ECDH_KDF_X9_62(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
|
||||
if (!ecdh_KDF_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
|
||||
digest)) {
|
||||
SM2err(SM2_F_SM2_ENCRYPT, ERR_R_EVP_LIB);
|
||||
goto done;
|
||||
@@ -344,7 +345,7 @@ int sm2_decrypt(const EC_KEY *key,
|
||||
|
||||
if (BN_bn2binpad(x2, x2y2, field_size) < 0
|
||||
|| BN_bn2binpad(y2, x2y2 + field_size, field_size) < 0
|
||||
|| !ECDH_KDF_X9_62(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
|
||||
|| !ecdh_KDF_X9_63(msg_mask, msg_len, x2y2, 2 * field_size, NULL, 0,
|
||||
digest)) {
|
||||
SM2err(SM2_F_SM2_DECRYPT, ERR_R_INTERNAL_ERROR);
|
||||
goto done;
|
||||
|
||||
@@ -517,15 +517,14 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
|
||||
/* check_purpose() makes the callback as needed */
|
||||
if (purpose > 0 && !check_purpose(ctx, x, purpose, i, must_be_ca))
|
||||
return 0;
|
||||
/* Check pathlen if not self issued */
|
||||
if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
|
||||
&& (x->ex_pathlen != -1)
|
||||
&& (plen > (x->ex_pathlen + proxy_path_length + 1))) {
|
||||
/* Check pathlen */
|
||||
if ((i > 1) && (x->ex_pathlen != -1)
|
||||
&& (plen > (x->ex_pathlen + proxy_path_length))) {
|
||||
if (!verify_cb_cert(ctx, x, i, X509_V_ERR_PATH_LENGTH_EXCEEDED))
|
||||
return 0;
|
||||
}
|
||||
/* Increment path length if not self issued */
|
||||
if (!(x->ex_flags & EXFLAG_SI))
|
||||
/* Increment path length if not a self issued intermediate CA */
|
||||
if (i > 0 && (x->ex_flags & EXFLAG_SI) == 0)
|
||||
plen++;
|
||||
/*
|
||||
* If this certificate is a proxy certificate, the next certificate
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include "internal/x509_int.h"
|
||||
#include "ext_dat.h"
|
||||
@@ -435,6 +436,27 @@ int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc)
|
||||
return X509_V_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return nonzero if the GeneralSubtree has valid 'minimum' field
|
||||
* (must be absent or 0) and valid 'maximum' field (must be absent).
|
||||
*/
|
||||
static int nc_minmax_valid(GENERAL_SUBTREE *sub) {
|
||||
BIGNUM *bn = NULL;
|
||||
int ok = 1;
|
||||
|
||||
if (sub->maximum)
|
||||
ok = 0;
|
||||
|
||||
if (sub->minimum) {
|
||||
bn = ASN1_INTEGER_to_BN(sub->minimum, NULL);
|
||||
if (bn == NULL || !BN_is_zero(bn))
|
||||
ok = 0;
|
||||
BN_free(bn);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
|
||||
{
|
||||
GENERAL_SUBTREE *sub;
|
||||
@@ -449,7 +471,7 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
|
||||
sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i);
|
||||
if (gen->type != sub->base->type)
|
||||
continue;
|
||||
if (sub->minimum || sub->maximum)
|
||||
if (!nc_minmax_valid(sub))
|
||||
return X509_V_ERR_SUBTREE_MINMAX;
|
||||
/* If we already have a match don't bother trying any more */
|
||||
if (match == 2)
|
||||
@@ -472,7 +494,7 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
|
||||
sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i);
|
||||
if (gen->type != sub->base->type)
|
||||
continue;
|
||||
if (sub->minimum || sub->maximum)
|
||||
if (!nc_minmax_valid(sub))
|
||||
return X509_V_ERR_SUBTREE_MINMAX;
|
||||
|
||||
r = nc_match_single(gen, sub->base);
|
||||
|
||||
Reference in New Issue
Block a user