sha512.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * Definitions likely to be helpful to multiple SHA-512 implementations.
  3. */
  4. /*
  5. * The 'extra' structure used by SHA-512 implementations is used to
  6. * include information about how to check if a given implementation is
  7. * available at run time, and whether we've already checked.
  8. */
  9. struct sha512_extra_mutable;
  10. struct sha512_extra {
  11. /* Pointer to the initial state (distinguishes SHA-384 from -512) */
  12. const uint64_t *initial_state;
  13. /* Function to check availability. Might be expensive, so we don't
  14. * want to call it more than once. */
  15. bool (*check_available)(void);
  16. /* Point to a writable substructure. */
  17. struct sha512_extra_mutable *mut;
  18. };
  19. struct sha512_extra_mutable {
  20. bool checked_availability;
  21. bool is_available;
  22. };
  23. static inline bool check_availability(const struct sha512_extra *extra)
  24. {
  25. if (!extra->mut->checked_availability) {
  26. extra->mut->is_available = extra->check_available();
  27. extra->mut->checked_availability = true;
  28. }
  29. return extra->mut->is_available;
  30. }
  31. /*
  32. * Macro to define a pair of SHA-{384,512} vtables together with their
  33. * 'extra' structure.
  34. */
  35. #define SHA512_VTABLES(impl_c, impl_display) \
  36. static struct sha512_extra_mutable sha512_ ## impl_c ## _extra_mut; \
  37. static const struct sha512_extra sha384_ ## impl_c ## _extra = { \
  38. /* WINSCP */ \
  39. /*.initial_state =*/ sha384_initial_state, \
  40. /*.check_available =*/ sha512_ ## impl_c ## _available, \
  41. /*.mut =*/ &sha512_ ## impl_c ## _extra_mut, \
  42. }; \
  43. static const struct sha512_extra sha512_ ## impl_c ## _extra = { \
  44. /* WINSCP */ \
  45. /*.initial_state =*/ sha512_initial_state, \
  46. /*.check_available =*/ sha512_ ## impl_c ## _available, \
  47. /*.mut =*/ &sha512_ ## impl_c ## _extra_mut, \
  48. }; \
  49. const ssh_hashalg ssh_sha384_ ## impl_c = { \
  50. /* WINSCP */ \
  51. /*.new =*/ sha512_ ## impl_c ## _new, \
  52. /*.reset =*/ sha512_ ## impl_c ## _reset, \
  53. /*.copyfrom =*/ sha512_ ## impl_c ## _copyfrom, \
  54. /*.digest =*/ sha384_ ## impl_c ## _digest, \
  55. /*.free =*/ sha512_ ## impl_c ## _free, \
  56. /*.hlen =*/ 48, \
  57. /*.blocklen =*/ 128, \
  58. HASHALG_NAMES_ANNOTATED("SHA-384", impl_display), \
  59. /*.extra =*/ &sha384_ ## impl_c ## _extra, \
  60. }; \
  61. const ssh_hashalg ssh_sha512_ ## impl_c = { \
  62. /* WINSCP */ \
  63. /*.new =*/ sha512_ ## impl_c ## _new, \
  64. /*.reset =*/ sha512_ ## impl_c ## _reset, \
  65. /*.copyfrom =*/ sha512_ ## impl_c ## _copyfrom, \
  66. /*.digest =*/ sha512_ ## impl_c ## _digest, \
  67. /*.free =*/ sha512_ ## impl_c ## _free, \
  68. /*.hlen =*/ 64, \
  69. /*.blocklen =*/ 128, \
  70. HASHALG_NAMES_ANNOTATED("SHA-512", impl_display), \
  71. /*.extra =*/ &sha512_ ## impl_c ## _extra, \
  72. }
  73. extern const uint64_t sha512_initial_state[8];
  74. extern const uint64_t sha384_initial_state[8];
  75. extern const uint64_t sha512_round_constants[80];
  76. #define SHA512_ROUNDS 80
  77. typedef struct sha512_block sha512_block;
  78. struct sha512_block {
  79. uint8_t block[128];
  80. size_t used;
  81. uint64_t lenhi, lenlo;
  82. };
  83. static inline void sha512_block_setup(sha512_block *blk)
  84. {
  85. blk->used = 0;
  86. blk->lenhi = blk->lenlo = 0;
  87. }
  88. static inline bool sha512_block_write(
  89. sha512_block *blk, const void **vdata, size_t *len)
  90. {
  91. size_t blkleft = sizeof(blk->block) - blk->used;
  92. size_t chunk = *len < blkleft ? *len : blkleft;
  93. const uint8_t *p = *vdata;
  94. memcpy(blk->block + blk->used, p, chunk);
  95. *vdata = p + chunk;
  96. *len -= chunk;
  97. blk->used += chunk;
  98. { // WINSCP
  99. size_t chunkbits = chunk << 3;
  100. blk->lenlo += chunkbits;
  101. blk->lenhi += (blk->lenlo < chunkbits);
  102. if (blk->used == sizeof(blk->block)) {
  103. blk->used = 0;
  104. return true;
  105. }
  106. return false;
  107. } // WINSCP
  108. }
  109. static inline void sha512_block_pad(sha512_block *blk, BinarySink *bs)
  110. {
  111. uint64_t final_lenhi = blk->lenhi;
  112. uint64_t final_lenlo = blk->lenlo;
  113. size_t pad = 127 & (111 - blk->used);
  114. put_byte(bs, 0x80);
  115. put_padding(bs, pad, 0);
  116. put_uint64(bs, final_lenhi);
  117. put_uint64(bs, final_lenlo);
  118. assert(blk->used == 0 && "Should have exactly hit a block boundary");
  119. }