/****************************************************************************** * NTRU Cryptography Reference Source Code * * Copyright (C) 2009-2016 Security Innovation (SI) * * SI has dedicated the work to the public domain by waiving all of its rights * to the work worldwide under copyright law, including all related and * neighboring rights, to the extent allowed by law. * * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * You can copy, modify, distribute and perform the work, even for commercial * purposes, all without asking permission. You should have received a copy of * the creative commons license (CC0 1.0 universal) along with this program. * See the license file for more information. * * *********************************************************************************/ /****************************************************************************** * * File: ntru_crypto_hash.c * * Contents: Routines implementing the hash object abstraction. * *****************************************************************************/ #include "ntru_crypto.h" #include "ntru_crypto_hash.h" typedef uint32_t (*NTRU_CRYPTO_HASH_INIT_FN)( void *c); typedef uint32_t (*NTRU_CRYPTO_HASH_UPDATE_FN)( void *c, void const *data, uint32_t len); typedef uint32_t (*NTRU_CRYPTO_HASH_FINAL_FN)( void *c, void *md); typedef uint32_t (*NTRU_CRYPTO_HASH_DIGEST_FN)( void const *data, uint32_t len, void *md); typedef struct _NTRU_CRYPTO_HASH_ALG_PARAMS { uint8_t algid; uint16_t block_length; uint16_t digest_length; NTRU_CRYPTO_HASH_INIT_FN init; NTRU_CRYPTO_HASH_UPDATE_FN update; NTRU_CRYPTO_HASH_FINAL_FN final; NTRU_CRYPTO_HASH_DIGEST_FN digest; } NTRU_CRYPTO_HASH_ALG_PARAMS; static NTRU_CRYPTO_HASH_ALG_PARAMS const algs_params[] = { { NTRU_CRYPTO_HASH_ALGID_SHA1, SHA_1_BLK_LEN, SHA_1_MD_LEN, (NTRU_CRYPTO_HASH_INIT_FN) SHA_1_INIT_FN, (NTRU_CRYPTO_HASH_UPDATE_FN) SHA_1_UPDATE_FN, (NTRU_CRYPTO_HASH_FINAL_FN) SHA_1_FINAL_FN, (NTRU_CRYPTO_HASH_DIGEST_FN) SHA_1_DIGEST_FN, }, { NTRU_CRYPTO_HASH_ALGID_SHA256, SHA_256_BLK_LEN, SHA_256_MD_LEN, (NTRU_CRYPTO_HASH_INIT_FN) SHA_256_INIT_FN, (NTRU_CRYPTO_HASH_UPDATE_FN) SHA_256_UPDATE_FN, (NTRU_CRYPTO_HASH_FINAL_FN) SHA_256_FINAL_FN, (NTRU_CRYPTO_HASH_DIGEST_FN) SHA_256_DIGEST_FN, }, }; static int const numalgs = (sizeof(algs_params) / sizeof(algs_params[0])); /* get_alg_params * * Return a pointer to the hash algorithm parameters for the hash algorithm * specified, by looking for algid in the global algs_params table. * If not found, return NULL. */ static NTRU_CRYPTO_HASH_ALG_PARAMS const * get_alg_params( NTRU_CRYPTO_HASH_ALGID algid) /* in - the hash algorithm to find */ { int i; for (i = 0; i < numalgs; i++) { if (algs_params[i].algid == algid) { return &algs_params[i]; } } return NULL; } /* ntru_crypto_hash_set_alg * * Sets the hash algorithm for the hash context. This must be called before * any calls to ntru_crypto_hash_block_length(), * ntru_crypto_hash_digest_length(), or ntru_crypto_hash_init() are made. * * Returns NTRU_CRYPTO_HASH_OK on success. * Returns NTRU_CRYPTO_HASH_BAD_ALG if the specified algorithm is not supported. */ uint32_t ntru_crypto_hash_set_alg( NTRU_CRYPTO_HASH_ALGID algid, /* in - hash algorithm to be used */ NTRU_CRYPTO_HASH_CTX *c) /* in/out - pointer to the hash context */ { if (!c) { HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER); } c->alg_params = get_alg_params(algid); if (!c->alg_params) { HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG); } HASH_RET(NTRU_CRYPTO_HASH_OK); } /* ntru_crypto_hash_block_length * * Gets the number of bytes in an input block for the hash algorithm * specified in the hash context. The hash algorithm must have been set * in the hash context with a call to ntru_crypto_hash_set_alg() prior to * calling this function. * * Returns NTRU_CRYPTO_HASH_OK on success. * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are * passed. * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set. */ uint32_t ntru_crypto_hash_block_length( NTRU_CRYPTO_HASH_CTX *c, /* in - pointer to the hash context */ uint16_t *blk_len) /* out - address for block length in bytes */ { if (!c || !blk_len) { HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER); } if (!c->alg_params) { HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG); } *blk_len = c->alg_params->block_length; HASH_RET(NTRU_CRYPTO_HASH_OK); } /* ntru_crypto_hash_digest_length * * Gets the number of bytes needed to hold the message digest for the * hash algorithm specified in the hash context. The algorithm must have * been set in the hash context with a call to ntru_crypto_hash_set_alg() prior * to calling this function. * * Returns NTRU_CRYPTO_HASH_OK on success. * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are * passed. * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set. */ uint32_t ntru_crypto_hash_digest_length( NTRU_CRYPTO_HASH_CTX const *c, /* in - pointer to the hash context */ uint16_t *md_len) /* out - addr for digest length in bytes */ { if (!c || !md_len) { HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER); } if (!c->alg_params) { HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG); } *md_len = c->alg_params->digest_length; HASH_RET(NTRU_CRYPTO_HASH_OK); } /* ntru_crypto_hash_init * * This routine performs standard initialization of the hash state. * * Returns NTRU_CRYPTO_HASH_OK on success. * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context. * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are * passed. * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set. */ uint32_t ntru_crypto_hash_init( NTRU_CRYPTO_HASH_CTX *c) /* in/out - pointer to hash context */ { if (!c) { HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER); } if (!c->alg_params) { HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG); } return c->alg_params->init(&c->alg_ctx); } /* ntru_crypto_hash_update * * This routine processes input data and updates the hash calculation. * * Returns NTRU_CRYPTO_HASH_OK on success. * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context. * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are * passed. * Returns NTRU_CRYPTO_HASH_OVERFLOW if too much text has been fed to the * hash algorithm. The size limit is dependent on the hash algorithm, * and not all algorithms have this limit. * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set. */ uint32_t ntru_crypto_hash_update( NTRU_CRYPTO_HASH_CTX *c, /* in/out - pointer to hash context */ uint8_t const *data, /* in - pointer to input data */ uint32_t data_len) /* in - number of bytes of input data */ { if (!c || (data_len && !data)) { HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER); } if (!c->alg_params) { HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG); } return c->alg_params->update(&c->alg_ctx, data, data_len); } /* ntru_crypto_hash_final * * This routine completes the hash calculation and returns the message digest. * * Returns NTRU_CRYPTO_HASH_OK on success. * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context. * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are * passed. * Returns NTRU_CRYPTO_HASH_BAD_ALG if the algorithm has not been set. */ uint32_t ntru_crypto_hash_final( NTRU_CRYPTO_HASH_CTX *c, /* in/out - pointer to hash context */ uint8_t *md) /* out - address for message digest */ { if (!c || !md) { HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER); } if (!c->alg_params) { HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG); } return c->alg_params->final(&c->alg_ctx, md); } /* ntru_crypto_hash_digest * * This routine computes a message digest. It is assumed that the * output buffer md is large enough to hold the output (see * ntru_crypto_hash_digest_length) * * Returns NTRU_CRYPTO_HASH_OK on success. * Returns NTRU_CRYPTO_HASH_FAIL with corrupted context. * Returns NTRU_CRYPTO_HASH_BAD_PARAMETER if inappropriate NULL pointers are * passed. * Returns NTRU_CRYPTO_HASH_OVERFLOW if too much text has been fed to the * hash algorithm. The size limit is dependent on the hash algorithm, * and not all algorithms have this limit. * Returns NTRU_CRYPTO_HASH_BAD_ALG if the specified algorithm is not supported. */ uint32_t ntru_crypto_hash_digest( NTRU_CRYPTO_HASH_ALGID algid, /* in - the hash algorithm to use */ uint8_t const *data, /* in - pointer to input data */ uint32_t data_len, /* in - number of bytes of input data */ uint8_t *md) /* out - address for message digest */ { NTRU_CRYPTO_HASH_ALG_PARAMS const *alg_params = get_alg_params(algid); if (!alg_params) { HASH_RET(NTRU_CRYPTO_HASH_BAD_ALG); } if ((data_len && !data) || !md) { HASH_RET(NTRU_CRYPTO_HASH_BAD_PARAMETER); } return alg_params->digest(data, data_len, md); }