Skip to content

Commit

Permalink
Expose SHAKE through the EVP API (#1199)
Browse files Browse the repository at this point in the history
* chkpnt: wired to EVP, compiles, need to add tests

* Tests running, all failing

* Fix tests, now only some (but not all!) SHAKE128 tests are failing

* Fix pre-existing bug in SHAKE one-shot tests

* Remove SHA128 digest test cases with \x00 in msg due to strlen usage

* Add SHAKE256 digest_text.cc NIST vectors

* Add digest and evp _extra, doc comments

* Move finalXOF to end of evp_md_st to preserve memory layout

* Add SHA3 and SHAKE to the service indicator

* SQUASHME

* Add SHAKE ACVP vectors

* Support SHAKE in EVP_Digest, add XOF functionality to modulewrapper

* Fix digest_test.cc after merge

* Add SHAKE ACVP modulewrapper JSON configs

* Clarify and add comments to digest_test.cc

* Add SHAKE monte carlo tests

* Fix SHA2 tests, account for weird golang case/switch impl

* Fix SHAKE MCTs

* Update formatting for SHAKE128 expected ACVP vectors

* Replace SHAKE256 ACVP vectors with byte-aligned vectors

* Reformat expected SHAKE-256 ACVP vectors

* Clean up TODOs

* Support sha3 in EVP_getdigestbyname

* Update crypto/fipsmodule/sha/internal.h

Co-authored-by: dkostic <[email protected]>

* Trim ACVP vectors, adjust error code in EVP_Digest

* Fix merge typo

* Add test case for successive digest finalization

* Add self check for SHA3/SHAKE

* Add SHA3-512 to self_check.c and test_fips.c

* Add SHA3 to break-kat.go, use unique input in self-check.c

* Revert "Add SHA3 to break-kat.go, use unique input in self-check.c"

This reverts commit 090e2ba.

* Revert "Add SHA3-512 to self_check.c and test_fips.c"

This reverts commit 5d23a69.

* Revert "Add self check for SHA3/SHAKE"

This reverts commit 1726039.

* Update crypto/fipsmodule/digest/digest.c

Co-authored-by: dkostic <[email protected]>

* Simplify ctx cleansing

* Refactor EVP_digest for better failure perf, add test

---------

Co-authored-by: dkostic <[email protected]>
  • Loading branch information
WillChilds-Klein and dkostic authored Oct 9, 2023
1 parent 4580d0c commit bb1aaba
Show file tree
Hide file tree
Showing 25 changed files with 591 additions and 116 deletions.
7 changes: 7 additions & 0 deletions crypto/digest_extra/digest_extra.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ static const struct nid_to_digest nid_to_digest_mapping[] = {
{NID_sha512, EVP_sha512, SN_sha512, LN_sha512},
{NID_sha512_224, EVP_sha512_224, SN_sha512_224, LN_sha512_224},
{NID_sha512_256, EVP_sha512_256, SN_sha512_256, LN_sha512_256},
{NID_sha3_224, EVP_sha3_224, SN_sha3_224, LN_sha3_224},
{NID_sha3_256, EVP_sha3_256, SN_sha3_256, LN_sha3_256},
{NID_sha3_384, EVP_sha3_384, SN_sha3_384, LN_sha3_384},
{NID_sha3_512, EVP_sha3_512, SN_sha3_512, LN_sha3_512},
{NID_shake128, EVP_shake128, SN_shake128, LN_shake128},
{NID_shake256, EVP_shake256, SN_shake256, LN_shake256},
{NID_md5_sha1, EVP_md5_sha1, SN_md5_sha1, LN_md5_sha1},
// As a remnant of signing |EVP_MD|s, OpenSSL returned the corresponding
// hash function when given a signature OID. To avoid unintended lax parsing
Expand Down Expand Up @@ -264,6 +270,7 @@ static const EVP_MD evp_md_blake2b256 = {
blake2b256_final,
BLAKE2B_CBLOCK,
sizeof(BLAKE2B_CTX),
/*finalXOf*/ NULL,
};

const EVP_MD *EVP_blake2b256(void) { return &evp_md_blake2b256; }
138 changes: 97 additions & 41 deletions crypto/digest_extra/digest_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,31 +46,37 @@ struct MD {
// one_shot_func is the convenience one-shot version of the
// digest.
uint8_t *(*one_shot_func)(const uint8_t *, size_t, uint8_t *);
// one_shot_xof_func is the convenience one-shot version of the
// digest.
uint8_t *(*one_shot_xof_func)(const uint8_t *, const size_t in_len, uint8_t *, size_t);
};

static const MD md4 = { "MD4", &EVP_md4, nullptr };
static const MD md5 = { "MD5", &EVP_md5, &MD5 };
static const MD ripemd160 = { "RIPEMD160", &EVP_ripemd160, &RIPEMD160 };
static const MD sha1 = { "SHA1", &EVP_sha1, &SHA1 };
static const MD sha224 = { "SHA224", &EVP_sha224, &SHA224 };
static const MD sha256 = { "SHA256", &EVP_sha256, &SHA256 };
static const MD sha384 = { "SHA384", &EVP_sha384, &SHA384 };
static const MD sha512 = { "SHA512", &EVP_sha512, &SHA512 };
static const MD sha512_224 = { "SHA512-224", &EVP_sha512_224, &SHA512_224 };
static const MD sha512_256 = { "SHA512-256", &EVP_sha512_256, &SHA512_256 };
static const MD sha3_224 = { "SHA3-224", &EVP_sha3_224, &SHA3_224 };
static const MD sha3_256 = { "SHA3-256", &EVP_sha3_256, &SHA3_256 };
static const MD sha3_384 = { "SHA3-384", &EVP_sha3_384, &SHA3_384 };
static const MD sha3_512 = { "SHA3-512", &EVP_sha3_512, &SHA3_512 };
static const MD md5_sha1 = { "MD5-SHA1", &EVP_md5_sha1, nullptr };
static const MD blake2b256 = { "BLAKE2b-256", &EVP_blake2b256, nullptr };
static const MD md4 = { "MD4", &EVP_md4, nullptr, nullptr };
static const MD md5 = { "MD5", &EVP_md5, &MD5, nullptr };
static const MD ripemd160 = { "RIPEMD160", &EVP_ripemd160, &RIPEMD160, nullptr };
static const MD sha1 = { "SHA1", &EVP_sha1, &SHA1, nullptr };
static const MD sha224 = { "SHA224", &EVP_sha224, &SHA224, nullptr };
static const MD sha256 = { "SHA256", &EVP_sha256, &SHA256, nullptr };
static const MD sha384 = { "SHA384", &EVP_sha384, &SHA384, nullptr };
static const MD sha512 = { "SHA512", &EVP_sha512, &SHA512, nullptr };
static const MD sha512_224 = { "SHA512-224", &EVP_sha512_224, &SHA512_224, nullptr };
static const MD sha512_256 = { "SHA512-256", &EVP_sha512_256, &SHA512_256, nullptr };
static const MD sha3_224 = { "SHA3-224", &EVP_sha3_224, &SHA3_224, nullptr };
static const MD sha3_256 = { "SHA3-256", &EVP_sha3_256, &SHA3_256, nullptr };
static const MD sha3_384 = { "SHA3-384", &EVP_sha3_384, &SHA3_384, nullptr };
static const MD sha3_512 = { "SHA3-512", &EVP_sha3_512, &SHA3_512, nullptr };
static const MD shake128 = { "shake128", &EVP_shake128, nullptr, &SHAKE128};
static const MD shake256 = { "shake256", &EVP_shake256, nullptr, &SHAKE256};
static const MD md5_sha1 = { "MD5-SHA1", &EVP_md5_sha1, nullptr, nullptr };
static const MD blake2b256 = { "BLAKE2b-256", &EVP_blake2b256, nullptr, nullptr };

struct DigestTestVector {
// md is the digest to test.
const MD &md;
// input is a NUL-terminated string to hash.
const char *input;
// repeat is the number of times to repeat input.
// for regular digest, repeat is the number of times to repeat input. for
// XOF, it is the requested output size.
size_t repeat;
// expected_hex is the expected digest in hexadecimal.
const char *expected_hex;
Expand Down Expand Up @@ -224,7 +230,26 @@ static const DigestTestVector kTestVectors[] = {
{sha3_512, "\xec\x83\xd7\x07\xa1\x41\x4a", 1, "84fd3775bac5b87e550d03ec6fe4905cc60e851a4c33a61858d4e7d8a34d471f05008b9a1d63044445df5a9fce958cb012a6ac778ecf45104b0fcb979aa4692d"},
{sha3_512, "\x0c\xe9\xf8\xc3\xa9\x90\xc2\x68\xf3\x4e\xfd\x9b\xef\xdb\x0f\x7c\x4e\xf8\x46\x6c\xfd\xb0\x11\x71\xf8\xde\x70\xdc\x5f\xef\xa9\x2a\xcb\xe9\x3d\x29\xe2\xac\x1a\x5c\x29\x79\x12\x9f\x1a\xb0\x8c\x0e\x77\xde\x79\x24\xdd\xf6\x8a\x20\x9c\xdf\xa0\xad\xc6\x2f\x85\xc1\x86\x37\xd9\xc6\xb3\x3f\x4f\xf8",
1, "b018a20fcf831dde290e4fb18c56342efe138472cbe142da6b77eea4fce52588c04c808eb32912faa345245a850346faec46c3a16d39bd2e1ddb1816bc57d2da"},


// SHAKE128 XOF tests, from NIST.
// http://csrc.nist.gov/groups/STM/cavp/secure-hashing.html
// NOTE: the |repeat| field in this struct denotes output length for XOF digests.
{shake128, "\x84\xe9\x50\x05\x18\x76\x05\x0d\xc8\x51\xfb\xd9\x9e\x62\x47\xb8", 16, "8599bd89f63a848c49ca593ec37a12c6"},
{shake128, "\xf1\x67\x51\x1e\xc8\x86\x49\x79\x30\x22\x37\xab\xea\x4c\xf7\xef", 17, "20f8938daa54b260860a104f8556278bac"},
{shake128, "\x96\xdb\xe1\x83\xec\x72\x90\x57\x0b\x82\x54\x6a\xf7\x92\xeb\x90", 18, "762b421dc6374055a061caeddcf50f5dfbb6"},
{shake128, "\x9b\xd2\xbd\x3a\x38\x4b\x9e\xf1\x41\xea\xd2\x63\x04\x96\x35\x49", 36, "3cdecb09f1673d8c823da2e02a2eeb28f32095e7c0ce8ab391811c626c472511a433845b"},
{shake128, "\x5b\x2f\x2f\x2a\xf8\x3e\x86\xd4\x2c\x4e\x98\x15\x3f\xce\x27\x79", 37, "b6e0361dbce6d4a809a2e982f1dcffa4a49781c989402bf9c603cdacbc15484261a47b050d"},


// SHAKE256 XOF tests, from NIST.
// http://csrc.nist.gov/groups/STM/cavp/secure-hashing.html
// NOTE: the |repeat| field in this struct denotes output length for XOF digests.
{shake256, "\xdc\x88\x6d\xf3\xf6\x9c\x49\x51\x3d\xe3\x62\x7e\x94\x81\xdb\x58\x71\xe8\xee\x88\xeb\x9f\x99\x61\x15\x41\x93\x0a\x8b\xc8\x85\xe0", 16, "00648afbc5e651649db1fd82936b00db"},
{shake256, "\x8d\x80\x01\xe2\xc0\x96\xf1\xb8\x8e\x7c\x92\x24\xa0\x86\xef\xd4\x79\x7f\xbf\x74\xa8\x03\x3a\x2d\x42\x2a\x2b\x6b\x8f\x67\x47\xe4", 17, "2e975f6a8a14f0704d51b13667d8195c21"},
{shake256, "\xe3\xef\x12\x7e\xad\xfa\xfa\xf4\x04\x08\xce\xbb\x28\x70\x5d\xf3\x0b\x68\xd9\x9d\xfa\x18\x93\x50\x7e\xf3\x06\x2d\x85\x46\x17\x15", 18, "7314002948c057006d4fc21e3e19c258fb5b"},
{shake256, "\xdc\x88\x6d\xf3\xf6\x9c\x49\x51\x3d\xe3\x62\x7e\x94\x81\xdb\x58\x71\xe8\xee\x88\xeb\x9f\x99\x61\x15\x41\x93\x0a\x8b\xc8\x85\xe0", 36, "00648afbc5e651649db1fd82936b00dbbc122fb4c877860d385c4950d56de7e096d613d7"},
{shake256, "\x79\x35\xb6\x8b\xb3\x34\xf3\x5d\xdc\x15\x7a\x8c\x47\x33\x49\xeb\x03\xad\x0e\x41\x53\x0d\x3c\x04\x5e\x2c\x5f\x64\x28\x50\xad\x8c", 37, "b44d25998e5cf77a83a4c0b2aae3061785adc7507d76fe07f4dcf299e04c991c922b51570f"},

// MD5-SHA1 tests.
{md5_sha1, "abc", 1,
"900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d"},
Expand All @@ -241,29 +266,44 @@ static void CompareDigest(const DigestTestVector *test,
EncodeHex(bssl::MakeConstSpan(digest, digest_len)));
}

static bool DoFinal(const DigestTestVector *test, EVP_MD_CTX *ctx, uint8_t *md_out, unsigned int *out_size) {
if (ctx->digest && (EVP_MD_flags(ctx->digest) & EVP_MD_FLAG_XOF)) {
// For XOF digests, DigestTestVector.repeat is the desired output length
*out_size = test->repeat;
return EVP_DigestFinalXOF(ctx, md_out, *out_size);
}
return EVP_DigestFinal(ctx, md_out, out_size);
}

static void TestDigest(const DigestTestVector *test) {
SCOPED_TRACE(test->md.name);
const bool is_xof = EVP_MD_flags(test->md.func()) & EVP_MD_FLAG_XOF;
const size_t repeat = is_xof ? 1 : test->repeat;
const size_t expected_output_size = is_xof
? test->repeat
: EVP_MD_size(test->md.func());

bssl::ScopedEVP_MD_CTX ctx;
// Test the input provided.
ASSERT_TRUE(EVP_DigestInit_ex(ctx.get(), test->md.func(), nullptr));
for (size_t i = 0; i < test->repeat; i++) {
for (size_t i = 0; i < repeat; i++) {
ASSERT_TRUE(EVP_DigestUpdate(ctx.get(), test->input, strlen(test->input)));
}
std::unique_ptr<uint8_t[]> digest(new uint8_t[EVP_MD_size(test->md.func())]);
std::unique_ptr<uint8_t[]> digest(new uint8_t[expected_output_size]);
unsigned digest_len;
ASSERT_TRUE(EVP_DigestFinal_ex(ctx.get(), digest.get(), &digest_len));
ASSERT_TRUE(DoFinal(test, ctx.get(), digest.get(), &digest_len));
CompareDigest(test, digest.get(), digest_len);

// Test the input one character at a time.
ASSERT_TRUE(EVP_DigestInit_ex(ctx.get(), test->md.func(), nullptr));
ASSERT_TRUE(EVP_DigestUpdate(ctx.get(), nullptr, 0));
for (size_t i = 0; i < test->repeat; i++) {
for (size_t i = 0; i < repeat; i++) {
for (const char *p = test->input; *p; p++) {
ASSERT_TRUE(EVP_DigestUpdate(ctx.get(), p, 1));
}
}
ASSERT_TRUE(EVP_DigestFinal_ex(ctx.get(), digest.get(), &digest_len));
EXPECT_EQ(EVP_MD_size(test->md.func()), digest_len);
ASSERT_TRUE(DoFinal(test, ctx.get(), digest.get(), &digest_len));
EXPECT_EQ(expected_output_size, digest_len);
CompareDigest(test, digest.get(), digest_len);

// Test with unaligned input.
Expand All @@ -274,20 +314,20 @@ static void TestDigest(const DigestTestVector *test) {
ptr++;
}
OPENSSL_memcpy(ptr, test->input, strlen(test->input));
for (size_t i = 0; i < test->repeat; i++) {
for (size_t i = 0; i < repeat; i++) {
ASSERT_TRUE(EVP_DigestUpdate(ctx.get(), ptr, strlen(test->input)));
}
ASSERT_TRUE(EVP_DigestFinal_ex(ctx.get(), digest.get(), &digest_len));
ASSERT_TRUE(DoFinal(test, ctx.get(), digest.get(), &digest_len));
CompareDigest(test, digest.get(), digest_len);

// Make a copy of the digest in the initial state.
ASSERT_TRUE(EVP_DigestInit_ex(ctx.get(), test->md.func(), nullptr));
bssl::ScopedEVP_MD_CTX copy;
ASSERT_TRUE(EVP_MD_CTX_copy_ex(copy.get(), ctx.get()));
for (size_t i = 0; i < test->repeat; i++) {
for (size_t i = 0; i < repeat; i++) {
ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input, strlen(test->input)));
}
ASSERT_TRUE(EVP_DigestFinal_ex(copy.get(), digest.get(), &digest_len));
ASSERT_TRUE(DoFinal(test, copy.get(), digest.get(), &digest_len));
CompareDigest(test, digest.get(), digest_len);

// Make a copy of the digest with half the input provided.
Expand All @@ -296,19 +336,19 @@ static void TestDigest(const DigestTestVector *test) {
ASSERT_TRUE(EVP_MD_CTX_copy_ex(copy.get(), ctx.get()));
ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input + half,
strlen(test->input) - half));
for (size_t i = 1; i < test->repeat; i++) {
for (size_t i = 1; i < repeat; i++) {
ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input, strlen(test->input)));
}
ASSERT_TRUE(EVP_DigestFinal_ex(copy.get(), digest.get(), &digest_len));
ASSERT_TRUE(DoFinal(test, copy.get(), digest.get(), &digest_len));
CompareDigest(test, digest.get(), digest_len);

// Move the digest from the initial state.
ASSERT_TRUE(EVP_DigestInit_ex(ctx.get(), test->md.func(), nullptr));
copy = std::move(ctx);
for (size_t i = 0; i < test->repeat; i++) {
for (size_t i = 0; i < repeat; i++) {
ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input, strlen(test->input)));
}
ASSERT_TRUE(EVP_DigestFinal_ex(copy.get(), digest.get(), &digest_len));
ASSERT_TRUE(DoFinal(test, copy.get(), digest.get(), &digest_len));
CompareDigest(test, digest.get(), digest_len);

// Move the digest with half the input provided.
Expand All @@ -317,20 +357,25 @@ static void TestDigest(const DigestTestVector *test) {
copy = std::move(ctx);
ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input + half,
strlen(test->input) - half));
for (size_t i = 1; i < test->repeat; i++) {
for (size_t i = 1; i < repeat; i++) {
ASSERT_TRUE(EVP_DigestUpdate(copy.get(), test->input, strlen(test->input)));
}
ASSERT_TRUE(EVP_DigestFinal_ex(copy.get(), digest.get(), &digest_len));
ASSERT_TRUE(DoFinal(test, copy.get(), digest.get(), &digest_len));
CompareDigest(test, digest.get(), digest_len);

// Digest context should be cleared by finalization
EXPECT_FALSE(DoFinal(test, copy.get(), digest.get(), &digest_len));

// Test the one-shot function.
if (test->md.one_shot_func && test->repeat == 1) {
uint8_t *out = test->md.one_shot_func((const uint8_t *)test->input,
strlen(test->input), digest.get());
// One-shot functions return their supplied buffers.
EXPECT_EQ(digest.get(), out);
CompareDigest(test, digest.get(), EVP_MD_size(test->md.func()));
}
if (is_xof || (test->md.one_shot_func && test->repeat == 1)) {
uint8_t *out = is_xof
? test->md.one_shot_xof_func((const uint8_t *)test->input, strlen(test->input),
digest.get(), expected_output_size)
: test->md.one_shot_func((const uint8_t *)test->input, strlen(test->input), digest.get());
// One-shot functions return their supplied buffers.
EXPECT_EQ(digest.get(), out);
CompareDigest(test, digest.get(), expected_output_size);
}
}

TEST(DigestTest, TestVectors) {
Expand Down Expand Up @@ -358,6 +403,17 @@ TEST(DigestTest, Getters) {
EXPECT_EQ(EVP_sha1(), EVP_get_digestbyobj(OBJ_nid2obj(NID_sha1)));
}

TEST(DigestTest, TestXOF) {
// Assert that passing null outsize pointer for EVP XOF results in error.
// Use same buffer for input/output; contents don't matter.
const size_t out_size = 16;
std::unique_ptr<uint8_t[]> digest(new uint8_t[out_size]);
EXPECT_FALSE(EVP_Digest(digest.get(), out_size, digest.get(),
/*out_len*/nullptr, EVP_shake128(), /*engine*/nullptr));
EXPECT_EQ(ERR_R_PASSED_NULL_PARAMETER, ERR_GET_REASON(ERR_peek_last_error()));
ERR_clear_error();
}

TEST(DigestTest, ASN1) {
bssl::ScopedCBB cbb;
ASSERT_TRUE(CBB_init(cbb.get(), 0));
Expand Down
4 changes: 4 additions & 0 deletions crypto/evp_extra/evp_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ static const EVP_MD *GetDigest(FileTest *t, const std::string &name) {
return EVP_sha3_384();
} else if (name == "SHA3-512") {
return EVP_sha3_512();
} else if (name == "SHAKE128") {
return EVP_shake128();
} else if (name == "SHAKE256") {
return EVP_shake256();
}
ADD_FAILURE() << "Unknown digest: " << name;
return nullptr;
Expand Down
35 changes: 29 additions & 6 deletions crypto/fipsmodule/digest/digest.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,16 @@ void EVP_MD_CTX_free(EVP_MD_CTX *ctx) {
void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) { EVP_MD_CTX_free(ctx); }

int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, uint8_t *out, size_t len) {
OPENSSL_PUT_ERROR(DIGEST, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
if (ctx->digest == NULL) {
return 0;
}
if ((EVP_MD_flags(ctx->digest) & EVP_MD_FLAG_XOF) == 0) {
OPENSSL_PUT_ERROR(DIGEST, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
ctx->digest->finalXOF(ctx, out, len);
EVP_MD_CTX_cleanse(ctx);
return 1;
}

uint32_t EVP_MD_meth_get_flags(const EVP_MD *md) { return EVP_MD_flags(md); }
Expand Down Expand Up @@ -245,6 +253,10 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, uint8_t *md_out, unsigned int *size) {
if (ctx->digest == NULL) {
return 0;
}
if (EVP_MD_flags(ctx->digest) & EVP_MD_FLAG_XOF) {
OPENSSL_PUT_ERROR(DIGEST, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}

assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
ctx->digest->final(ctx, md_out);
Expand All @@ -256,7 +268,6 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, uint8_t *md_out, unsigned int *size) {
}

int EVP_DigestFinal(EVP_MD_CTX *ctx, uint8_t *md, unsigned int *size) {

int ok = EVP_DigestFinal_ex(ctx, md, size);
EVP_MD_CTX_cleanup(ctx);
return ok;
Expand All @@ -267,11 +278,23 @@ int EVP_Digest(const void *data, size_t count, uint8_t *out_md,
EVP_MD_CTX ctx;
int ret;

if ((EVP_MD_flags(type) & EVP_MD_FLAG_XOF) && out_size == NULL) {
OPENSSL_PUT_ERROR(DIGEST, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}

EVP_MD_CTX_init(&ctx);
ret = EVP_DigestInit_ex(&ctx, type, impl) &&
EVP_DigestUpdate(&ctx, data, count) &&
EVP_DigestFinal_ex(&ctx, out_md, out_size);
EVP_MD_CTX_cleanup(&ctx);
EVP_DigestUpdate(&ctx, data, count);
if (ret == 0) {
return 0;
}

if (EVP_MD_flags(type) & EVP_MD_FLAG_XOF) {
ret &= EVP_DigestFinalXOF(&ctx, out_md, *out_size);
} else {
ret &= EVP_DigestFinal(&ctx, out_md, out_size);
}

return ret;
}
Expand Down
Loading

0 comments on commit bb1aaba

Please sign in to comment.