*/
#include <string.h>
+#include <openssl/byteorder.h>
#include <openssl/core_names.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
return ctx; \
}
-#define PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags) \
- PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \
- const OSSL_DISPATCH ossl_##name##_functions[] = { \
- { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \
- { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))keccak_update }, \
- { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))keccak_final }, \
- { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))keccak_freectx }, \
- { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))keccak_dupctx }, \
- { OSSL_FUNC_DIGEST_COPYCTX, (void (*)(void))keccak_copyctx }, \
+#define PROV_FUNC_SHA3_DIGEST_COMMON(name, bitlen, blksize, dgstsize, flags) \
+ PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \
+ const OSSL_DISPATCH ossl_##name##_functions[] = { \
+ { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \
+ { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))keccak_update }, \
+ { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))keccak_final }, \
+ { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))keccak_freectx }, \
+ { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))keccak_dupctx }, \
+ { OSSL_FUNC_DIGEST_COPYCTX, (void (*)(void))keccak_copyctx }, \
+ { OSSL_FUNC_DIGEST_SERIALIZE, (void (*)(void))name##_serialize }, \
+ { OSSL_FUNC_DIGEST_DESERIALIZE, (void (*)(void))name##_deserialize }, \
PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name)
#define PROV_FUNC_SHA3_DIGEST(name, bitlen, blksize, dgstsize, flags) \
return ret;
}
+static const unsigned char keccakmagic[] = "KECCAKv1";
+#define KECCAKMAGIC_LEN (sizeof(keccakmagic) - 1)
+#define KECCAK_SERIALIZATION_LEN \
+ ( \
+ KECCAKMAGIC_LEN /* magic string */ \
+ + sizeof(uint64_t) /* impl-ID */ \
+ + sizeof(uint64_t) /* c->md_size */ \
+ + (sizeof(uint64_t) * 5 * 5) /* c->A */ \
+ + (sizeof(uint64_t) * 4) /* c->block_size, c->bufsz, c->pad, c->xof_state */ \
+ + (KECCAK1600_WIDTH / 8 - 32) /* c->buf */ \
+ )
+
+static int KECCAK_Serialize(KECCAK1600_CTX *c, int impl_id,
+ unsigned char *output, size_t *outlen)
+{
+ unsigned char *p;
+ int i, j;
+
+ if (output == NULL) {
+ if (outlen == NULL)
+ return 0;
+
+ *outlen = KECCAK_SERIALIZATION_LEN;
+ return 1;
+ }
+
+ if (outlen != NULL && *outlen < KECCAK_SERIALIZATION_LEN)
+ return 0;
+
+ p = output;
+
+ /* Magic code */
+ memcpy(p, keccakmagic, KECCAKMAGIC_LEN);
+ p += KECCAKMAGIC_LEN;
+
+ /* Additional check data */
+ p = OPENSSL_store_u64_le(p, impl_id);
+ p = OPENSSL_store_u64_le(p, c->md_size);
+
+ /* A matrix */
+ for (i = 0; i < 5; i++) {
+ for (j = 0; j < 5; j++)
+ p = OPENSSL_store_u64_le(p, c->A[i][j]);
+ }
+
+ p = OPENSSL_store_u64_le(p, c->block_size);
+ p = OPENSSL_store_u64_le(p, c->bufsz);
+ p = OPENSSL_store_u64_le(p, c->pad);
+ p = OPENSSL_store_u64_le(p, c->xof_state);
+
+ if (outlen != NULL)
+ *outlen = KECCAK_SERIALIZATION_LEN;
+
+ /* buf */
+ memcpy(p, c->buf, sizeof(c->buf));
+
+ return 1;
+}
+
+static int KECCAK_Deserialize(KECCAK1600_CTX *c, int impl_id,
+ const unsigned char *input, size_t len)
+{
+ const unsigned char *p;
+ uint64_t val;
+ int i, j;
+
+ if (c == NULL || input == NULL || len != KECCAK_SERIALIZATION_LEN)
+ return 0;
+
+ /* Magic code */
+ if (memcmp(input, keccakmagic, KECCAKMAGIC_LEN) != 0)
+ return 0;
+
+ p = input + KECCAKMAGIC_LEN;
+
+ /* Check for matching Impl ID */
+ p = OPENSSL_load_u64_le(&val, p);
+ if (val != (uint64_t)impl_id)
+ return 0;
+
+ /* Check for matching md_size */
+ p = OPENSSL_load_u64_le(&val, p);
+ if (val != (uint64_t)c->md_size)
+ return 0;
+
+ /* A matrix */
+ for (i = 0; i < 5; i++) {
+ for (j = 0; j < 5; j++) {
+ p = OPENSSL_load_u64_le(&val, p);
+ c->A[i][j] = val;
+ }
+ }
+
+ p = OPENSSL_load_u64_le(&val, p);
+ c->block_size = (size_t)val;
+ p = OPENSSL_load_u64_le(&val, p);
+ c->bufsz = (size_t)val;
+ p = OPENSSL_load_u64_le(&val, p);
+ c->pad = (unsigned char)val;
+ p = OPENSSL_load_u64_le(&val, p);
+ c->xof_state = (int)val;
+
+ /* buf */
+ memcpy(c->buf, p, sizeof(c->buf));
+
+ return 1;
+}
+
+#define IMPLEMENT_SERIALIZE_FNS(name, id) \
+ static int name##_serialize(void *vctx, unsigned char *out, \
+ size_t *outlen) \
+ { \
+ return KECCAK_Serialize(vctx, id, out, outlen); \
+ } \
+ static int name##_deserialize(void *vctx, const unsigned char *in, \
+ size_t inlen) \
+ { \
+ return KECCAK_Deserialize(vctx, id, in, inlen); \
+ }
+
static const OSSL_PARAM *shake_gettable_ctx_params(ossl_unused void *ctx,
ossl_unused void *provctx)
{
return 1;
}
-#define IMPLEMENT_SHA3_functions(bitlen) \
- SHA3_newctx(sha3, SHA3_##bitlen, sha3_##bitlen, bitlen, '\x06') \
- PROV_FUNC_SHA3_DIGEST(sha3_##bitlen, bitlen, \
- SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
- SHA3_FLAGS)
+#define KECCAK_SER_ID 0x010000
+#define SHAKE_SER_ID 0x020000
+#define SHA3_SER_ID 0x040000
+#define KMAK_SER_ID 0x080000
+
+#define IMPLEMENT_SHA3_functions(bitlen) \
+ SHA3_newctx(sha3, SHA3_##bitlen, sha3_##bitlen, bitlen, '\x06') \
+ IMPLEMENT_SERIALIZE_FNS(sha3_##bitlen, SHA3_SER_ID + bitlen) \
+ PROV_FUNC_SHA3_DIGEST(sha3_##bitlen, bitlen, \
+ SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
+ SHA3_FLAGS)
#define IMPLEMENT_KECCAK_functions(bitlen) \
SHA3_newctx(keccak, KECCAK_##bitlen, keccak_##bitlen, bitlen, '\x01') \
- PROV_FUNC_SHA3_DIGEST(keccak_##bitlen, bitlen, \
- SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
- SHA3_FLAGS)
-
-#define IMPLEMENT_SHAKE_functions(bitlen) \
- SHAKE_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, \
- 0 /* no default md length */, '\x1f') \
- PROV_FUNC_SHAKE_DIGEST(shake_##bitlen, bitlen, \
- SHA3_BLOCKSIZE(bitlen), 0, \
- SHAKE_FLAGS)
-
-#define IMPLEMENT_KMAC_functions(bitlen) \
- KMAC_newctx(keccak_kmac_##bitlen, bitlen, '\x04') \
- PROV_FUNC_SHAKE_DIGEST(keccak_kmac_##bitlen, bitlen, \
- SHA3_BLOCKSIZE(bitlen), KMAC_MDSIZE(bitlen), \
- KMAC_FLAGS)
+ IMPLEMENT_SERIALIZE_FNS(keccak_##bitlen, KECCAK_SER_ID + bitlen) \
+ PROV_FUNC_SHA3_DIGEST(keccak_##bitlen, bitlen, \
+ SHA3_BLOCKSIZE(bitlen), SHA3_MDSIZE(bitlen), \
+ SHA3_FLAGS)
+
+#define IMPLEMENT_SHAKE_functions(bitlen) \
+ SHAKE_newctx(shake, SHAKE_##bitlen, shake_##bitlen, bitlen, \
+ 0 /* no default md length */, '\x1f') \
+ IMPLEMENT_SERIALIZE_FNS(shake_##bitlen, SHAKE_SER_ID + bitlen) \
+ PROV_FUNC_SHAKE_DIGEST(shake_##bitlen, bitlen, \
+ SHA3_BLOCKSIZE(bitlen), 0, \
+ SHAKE_FLAGS)
+
+#define IMPLEMENT_KMAC_functions(bitlen) \
+ KMAC_newctx(keccak_kmac_##bitlen, bitlen, '\x04') \
+ IMPLEMENT_SERIALIZE_FNS(keccak_kmac_##bitlen, KMAK_SER_ID + bitlen) \
+ PROV_FUNC_SHAKE_DIGEST(keccak_kmac_##bitlen, bitlen, \
+ SHA3_BLOCKSIZE(bitlen), KMAC_MDSIZE(bitlen), \
+ KMAC_FLAGS)
/* ossl_sha3_224_functions */
IMPLEMENT_SHA3_functions(224)