| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 | /* * 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 = {    \        /* WINSCP */ \        /*.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 = {    \        /* WINSCP */ \        /*.initial_state =*/ sha512_initial_state,                          \        /*.check_available =*/ sha512_ ## impl_c ## _available,             \        /*.mut =*/ &sha512_ ## impl_c ## _extra_mut,                        \    };                                                                  \    const ssh_hashalg ssh_sha384_ ## impl_c = {                         \        /* WINSCP */ \        /*.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 = {                         \        /* WINSCP */ \        /*.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 80typedef 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;    { // WINSCP    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;    } // WINSCP}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");}
 |