sha512-sw.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Software implementation of SHA-512.
  3. */
  4. #include "ssh.h"
  5. #include "sha512.h"
  6. static bool sha512_sw_available(void)
  7. {
  8. /* Software SHA-512 is always available */
  9. return true;
  10. }
  11. static inline uint64_t ror(uint64_t x, unsigned y)
  12. {
  13. #pragma option push -w-ngu // WINSCP
  14. return (x << (63 & -y)) | (x >> (63 & y));
  15. #pragma option pop // WINSCP
  16. }
  17. static inline uint64_t Ch(uint64_t ctrl, uint64_t if1, uint64_t if0)
  18. {
  19. return if0 ^ (ctrl & (if1 ^ if0));
  20. }
  21. static inline uint64_t Maj(uint64_t x, uint64_t y, uint64_t z)
  22. {
  23. return (x & y) | (z & (x | y));
  24. }
  25. static inline uint64_t Sigma_0(uint64_t x)
  26. {
  27. return ror(x,28) ^ ror(x,34) ^ ror(x,39);
  28. }
  29. static inline uint64_t Sigma_1(uint64_t x)
  30. {
  31. return ror(x,14) ^ ror(x,18) ^ ror(x,41);
  32. }
  33. static inline uint64_t sigma_0(uint64_t x)
  34. {
  35. return ror(x,1) ^ ror(x,8) ^ (x >> 7);
  36. }
  37. static inline uint64_t sigma_1(uint64_t x)
  38. {
  39. return ror(x,19) ^ ror(x,61) ^ (x >> 6);
  40. }
  41. static inline void sha512_sw_round(
  42. unsigned round_index, const uint64_t *schedule,
  43. uint64_t *a, uint64_t *b, uint64_t *c, uint64_t *d,
  44. uint64_t *e, uint64_t *f, uint64_t *g, uint64_t *h)
  45. {
  46. uint64_t t1 = *h + Sigma_1(*e) + Ch(*e,*f,*g) +
  47. sha512_round_constants[round_index] + schedule[round_index];
  48. uint64_t t2 = Sigma_0(*a) + Maj(*a,*b,*c);
  49. *d += t1;
  50. *h = t1 + t2;
  51. }
  52. static void sha512_sw_block(uint64_t *core, const uint8_t *block)
  53. {
  54. uint64_t w[SHA512_ROUNDS];
  55. uint64_t a,b,c,d,e,f,g,h;
  56. int t;
  57. for (t = 0; t < 16; t++)
  58. w[t] = GET_64BIT_MSB_FIRST(block + 8*t);
  59. for (t = 16; t < SHA512_ROUNDS; t++)
  60. w[t] = w[t-16] + w[t-7] + sigma_0(w[t-15]) + sigma_1(w[t-2]);
  61. a = core[0]; b = core[1]; c = core[2]; d = core[3];
  62. e = core[4]; f = core[5]; g = core[6]; h = core[7];
  63. for (t = 0; t < SHA512_ROUNDS; t+=8) {
  64. sha512_sw_round(t+0, w, &a,&b,&c,&d,&e,&f,&g,&h);
  65. sha512_sw_round(t+1, w, &h,&a,&b,&c,&d,&e,&f,&g);
  66. sha512_sw_round(t+2, w, &g,&h,&a,&b,&c,&d,&e,&f);
  67. sha512_sw_round(t+3, w, &f,&g,&h,&a,&b,&c,&d,&e);
  68. sha512_sw_round(t+4, w, &e,&f,&g,&h,&a,&b,&c,&d);
  69. sha512_sw_round(t+5, w, &d,&e,&f,&g,&h,&a,&b,&c);
  70. sha512_sw_round(t+6, w, &c,&d,&e,&f,&g,&h,&a,&b);
  71. sha512_sw_round(t+7, w, &b,&c,&d,&e,&f,&g,&h,&a);
  72. }
  73. core[0] += a; core[1] += b; core[2] += c; core[3] += d;
  74. core[4] += e; core[5] += f; core[6] += g; core[7] += h;
  75. smemclr(w, sizeof(w));
  76. }
  77. typedef struct sha512_sw {
  78. uint64_t core[8];
  79. sha512_block blk;
  80. BinarySink_IMPLEMENTATION;
  81. ssh_hash hash;
  82. } sha512_sw;
  83. static void sha512_sw_write(BinarySink *bs, const void *vp, size_t len);
  84. static ssh_hash *sha512_sw_new(const ssh_hashalg *alg)
  85. {
  86. sha512_sw *s = snew(sha512_sw);
  87. s->hash.vt = alg;
  88. BinarySink_INIT(s, sha512_sw_write);
  89. BinarySink_DELEGATE_INIT(&s->hash, s);
  90. return &s->hash;
  91. }
  92. static void sha512_sw_reset(ssh_hash *hash)
  93. {
  94. sha512_sw *s = container_of(hash, sha512_sw, hash);
  95. const struct sha512_extra *extra =
  96. (const struct sha512_extra *)hash->vt->extra;
  97. memcpy(s->core, extra->initial_state, sizeof(s->core));
  98. sha512_block_setup(&s->blk);
  99. }
  100. static void sha512_sw_copyfrom(ssh_hash *hcopy, ssh_hash *horig)
  101. {
  102. sha512_sw *copy = container_of(hcopy, sha512_sw, hash);
  103. sha512_sw *orig = container_of(horig, sha512_sw, hash);
  104. memcpy(copy, orig, sizeof(*copy));
  105. BinarySink_COPIED(copy);
  106. BinarySink_DELEGATE_INIT(&copy->hash, copy);
  107. }
  108. static void sha512_sw_free(ssh_hash *hash)
  109. {
  110. sha512_sw *s = container_of(hash, sha512_sw, hash);
  111. smemclr(s, sizeof(*s));
  112. sfree(s);
  113. }
  114. static void sha512_sw_write(BinarySink *bs, const void *vp, size_t len)
  115. {
  116. sha512_sw *s = BinarySink_DOWNCAST(bs, sha512_sw);
  117. while (len > 0)
  118. if (sha512_block_write(&s->blk, &vp, &len))
  119. sha512_sw_block(s->core, s->blk.block);
  120. }
  121. static void sha512_sw_digest(ssh_hash *hash, uint8_t *digest)
  122. {
  123. sha512_sw *s = container_of(hash, sha512_sw, hash);
  124. sha512_block_pad(&s->blk, BinarySink_UPCAST(s));
  125. { // WINSCP
  126. size_t i;
  127. for (i = 0; i < hash->vt->hlen / 8; i++)
  128. PUT_64BIT_MSB_FIRST(digest + 8*i, s->core[i]);
  129. } // WINSCP
  130. }
  131. /*
  132. * This implementation doesn't need separate digest methods for
  133. * SHA-384 and SHA-512, because the above implementation reads the
  134. * hash length out of the vtable.
  135. */
  136. #define sha384_sw_digest sha512_sw_digest
  137. SHA512_VTABLES(sw, "unaccelerated");