123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*
- * Definitions likely to be helpful to multiple SHA-512 implementations.
- */
- /*
- * The 'extra' structure used by SHA-512 implementations is used to
- * include information about how to check if a given implementation is
- * available at run time, and whether we've already checked.
- */
- struct sha512_extra_mutable;
- struct sha512_extra {
- /* Pointer to the initial state (distinguishes SHA-384 from -512) */
- const uint64_t *initial_state;
- /* Function to check availability. Might be expensive, so we don't
- * want to call it more than once. */
- bool (*check_available)(void);
- /* Point to a writable substructure. */
- struct sha512_extra_mutable *mut;
- };
- struct sha512_extra_mutable {
- bool checked_availability;
- bool is_available;
- };
- static inline bool check_availability(const struct sha512_extra *extra)
- {
- if (!extra->mut->checked_availability) {
- extra->mut->is_available = extra->check_available();
- extra->mut->checked_availability = true;
- }
- return extra->mut->is_available;
- }
- /*
- * Macro to define a pair of SHA-{384,512} vtables together with their
- * 'extra' structure.
- */
- #define SHA512_VTABLES(impl_c, impl_display) \
- static struct sha512_extra_mutable sha512_ ## impl_c ## _extra_mut; \
- static const struct sha512_extra sha384_ ## impl_c ## _extra = { \
- .initial_state = sha384_initial_state, \
- .check_available = sha512_ ## impl_c ## _available, \
- .mut = &sha512_ ## impl_c ## _extra_mut, \
- }; \
- static const struct sha512_extra sha512_ ## impl_c ## _extra = { \
- .initial_state = sha512_initial_state, \
- .check_available = sha512_ ## impl_c ## _available, \
- .mut = &sha512_ ## impl_c ## _extra_mut, \
- }; \
- const ssh_hashalg ssh_sha384_ ## impl_c = { \
- .new = sha512_ ## impl_c ## _new, \
- .reset = sha512_ ## impl_c ## _reset, \
- .copyfrom = sha512_ ## impl_c ## _copyfrom, \
- .digest = sha384_ ## impl_c ## _digest, \
- .free = sha512_ ## impl_c ## _free, \
- .hlen = 48, \
- .blocklen = 128, \
- HASHALG_NAMES_ANNOTATED("SHA-384", impl_display), \
- .extra = &sha384_ ## impl_c ## _extra, \
- }; \
- const ssh_hashalg ssh_sha512_ ## impl_c = { \
- .new = sha512_ ## impl_c ## _new, \
- .reset = sha512_ ## impl_c ## _reset, \
- .copyfrom = sha512_ ## impl_c ## _copyfrom, \
- .digest = sha512_ ## impl_c ## _digest, \
- .free = sha512_ ## impl_c ## _free, \
- .hlen = 64, \
- .blocklen = 128, \
- HASHALG_NAMES_ANNOTATED("SHA-512", impl_display), \
- .extra = &sha512_ ## impl_c ## _extra, \
- }
- extern const uint64_t sha512_initial_state[8];
- extern const uint64_t sha384_initial_state[8];
- extern const uint64_t sha512_round_constants[80];
- #define SHA512_ROUNDS 80
- typedef struct sha512_block sha512_block;
- struct sha512_block {
- uint8_t block[128];
- size_t used;
- uint64_t lenhi, lenlo;
- };
- static inline void sha512_block_setup(sha512_block *blk)
- {
- blk->used = 0;
- blk->lenhi = blk->lenlo = 0;
- }
- static inline bool sha512_block_write(
- sha512_block *blk, const void **vdata, size_t *len)
- {
- size_t blkleft = sizeof(blk->block) - blk->used;
- size_t chunk = *len < blkleft ? *len : blkleft;
- const uint8_t *p = *vdata;
- memcpy(blk->block + blk->used, p, chunk);
- *vdata = p + chunk;
- *len -= chunk;
- blk->used += chunk;
- size_t chunkbits = chunk << 3;
- blk->lenlo += chunkbits;
- blk->lenhi += (blk->lenlo < chunkbits);
- if (blk->used == sizeof(blk->block)) {
- blk->used = 0;
- return true;
- }
- return false;
- }
- static inline void sha512_block_pad(sha512_block *blk, BinarySink *bs)
- {
- uint64_t final_lenhi = blk->lenhi;
- uint64_t final_lenlo = blk->lenlo;
- size_t pad = 127 & (111 - blk->used);
- put_byte(bs, 0x80);
- put_padding(bs, pad, 0);
- put_uint64(bs, final_lenhi);
- put_uint64(bs, final_lenlo);
- assert(blk->used == 0 && "Should have exactly hit a block boundary");
- }
|