md32_common.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. /*-
  10. * This is a generic 32 bit "collector" for message digest algorithms.
  11. * Whenever needed it collects input character stream into chunks of
  12. * 32 bit values and invokes a block function that performs actual hash
  13. * calculations.
  14. *
  15. * Porting guide.
  16. *
  17. * Obligatory macros:
  18. *
  19. * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
  20. * this macro defines byte order of input stream.
  21. * HASH_CBLOCK
  22. * size of a unit chunk HASH_BLOCK operates on.
  23. * HASH_LONG
  24. * has to be at least 32 bit wide.
  25. * HASH_CTX
  26. * context structure that at least contains following
  27. * members:
  28. * typedef struct {
  29. * ...
  30. * HASH_LONG Nl,Nh;
  31. * either {
  32. * HASH_LONG data[HASH_LBLOCK];
  33. * unsigned char data[HASH_CBLOCK];
  34. * };
  35. * unsigned int num;
  36. * ...
  37. * } HASH_CTX;
  38. * data[] vector is expected to be zeroed upon first call to
  39. * HASH_UPDATE.
  40. * HASH_UPDATE
  41. * name of "Update" function, implemented here.
  42. * HASH_TRANSFORM
  43. * name of "Transform" function, implemented here.
  44. * HASH_FINAL
  45. * name of "Final" function, implemented here.
  46. * HASH_BLOCK_DATA_ORDER
  47. * name of "block" function capable of treating *unaligned* input
  48. * message in original (data) byte order, implemented externally.
  49. * HASH_MAKE_STRING
  50. * macro converting context variables to an ASCII hash string.
  51. *
  52. * MD5 example:
  53. *
  54. * #define DATA_ORDER_IS_LITTLE_ENDIAN
  55. *
  56. * #define HASH_LONG MD5_LONG
  57. * #define HASH_CTX MD5_CTX
  58. * #define HASH_CBLOCK MD5_CBLOCK
  59. * #define HASH_UPDATE MD5_Update
  60. * #define HASH_TRANSFORM MD5_Transform
  61. * #define HASH_FINAL MD5_Final
  62. * #define HASH_BLOCK_DATA_ORDER md5_block_data_order
  63. */
  64. #ifndef OSSL_CRYPTO_MD32_COMMON_H
  65. # define OSSL_CRYPTO_MD32_COMMON_H
  66. # pragma once
  67. # include <openssl/crypto.h>
  68. # if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
  69. # error "DATA_ORDER must be defined!"
  70. # endif
  71. # ifndef HASH_CBLOCK
  72. # error "HASH_CBLOCK must be defined!"
  73. # endif
  74. # ifndef HASH_LONG
  75. # error "HASH_LONG must be defined!"
  76. # endif
  77. # ifndef HASH_CTX
  78. # error "HASH_CTX must be defined!"
  79. # endif
  80. # ifndef HASH_UPDATE
  81. # error "HASH_UPDATE must be defined!"
  82. # endif
  83. # ifndef HASH_TRANSFORM
  84. # error "HASH_TRANSFORM must be defined!"
  85. # endif
  86. # ifndef HASH_FINAL
  87. # error "HASH_FINAL must be defined!"
  88. # endif
  89. # ifndef HASH_BLOCK_DATA_ORDER
  90. # error "HASH_BLOCK_DATA_ORDER must be defined!"
  91. # endif
  92. # define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
  93. #ifndef PEDANTIC
  94. # if defined(__GNUC__) && __GNUC__>=2 && \
  95. !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
  96. # if defined(__riscv_zbb) || defined(__riscv_zbkb)
  97. # if __riscv_xlen == 64
  98. # undef ROTATE
  99. # define ROTATE(x, n) ({ MD32_REG_T ret; \
  100. asm ("roriw %0, %1, %2" \
  101. : "=r"(ret) \
  102. : "r"(x), "i"(32 - (n))); ret;})
  103. # endif
  104. # if __riscv_xlen == 32
  105. # undef ROTATE
  106. # define ROTATE(x, n) ({ MD32_REG_T ret; \
  107. asm ("rori %0, %1, %2" \
  108. : "=r"(ret) \
  109. : "r"(x), "i"(32 - (n))); ret;})
  110. # endif
  111. # endif
  112. # endif
  113. #endif
  114. # if defined(DATA_ORDER_IS_BIG_ENDIAN)
  115. # define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
  116. l|=(((unsigned long)(*((c)++)))<<16), \
  117. l|=(((unsigned long)(*((c)++)))<< 8), \
  118. l|=(((unsigned long)(*((c)++))) ) )
  119. # define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
  120. *((c)++)=(unsigned char)(((l)>>16)&0xff), \
  121. *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
  122. *((c)++)=(unsigned char)(((l) )&0xff), \
  123. l)
  124. # elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
  125. # define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
  126. l|=(((unsigned long)(*((c)++)))<< 8), \
  127. l|=(((unsigned long)(*((c)++)))<<16), \
  128. l|=(((unsigned long)(*((c)++)))<<24) )
  129. # define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
  130. *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
  131. *((c)++)=(unsigned char)(((l)>>16)&0xff), \
  132. *((c)++)=(unsigned char)(((l)>>24)&0xff), \
  133. l)
  134. # endif
  135. /*
  136. * Time for some action :-)
  137. */
  138. int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len)
  139. {
  140. const unsigned char *data = data_;
  141. unsigned char *p;
  142. HASH_LONG l;
  143. size_t n;
  144. if (len == 0)
  145. return 1;
  146. l = (c->Nl + (((HASH_LONG) len) << 3)) & 0xffffffffUL;
  147. if (l < c->Nl) /* overflow */
  148. c->Nh++;
  149. c->Nh += (HASH_LONG) (len >> 29); /* might cause compiler warning on
  150. * 16-bit */
  151. c->Nl = l;
  152. n = c->num;
  153. if (n != 0) {
  154. p = (unsigned char *)c->data;
  155. if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) {
  156. memcpy(p + n, data, HASH_CBLOCK - n);
  157. HASH_BLOCK_DATA_ORDER(c, p, 1);
  158. n = HASH_CBLOCK - n;
  159. data += n;
  160. len -= n;
  161. c->num = 0;
  162. /*
  163. * We use memset rather than OPENSSL_cleanse() here deliberately.
  164. * Using OPENSSL_cleanse() here could be a performance issue. It
  165. * will get properly cleansed on finalisation so this isn't a
  166. * security problem.
  167. */
  168. memset(p, 0, HASH_CBLOCK); /* keep it zeroed */
  169. } else {
  170. memcpy(p + n, data, len);
  171. c->num += (unsigned int)len;
  172. return 1;
  173. }
  174. }
  175. n = len / HASH_CBLOCK;
  176. if (n > 0) {
  177. HASH_BLOCK_DATA_ORDER(c, data, n);
  178. n *= HASH_CBLOCK;
  179. data += n;
  180. len -= n;
  181. }
  182. if (len != 0) {
  183. p = (unsigned char *)c->data;
  184. c->num = (unsigned int)len;
  185. memcpy(p, data, len);
  186. }
  187. return 1;
  188. }
  189. void HASH_TRANSFORM(HASH_CTX *c, const unsigned char *data)
  190. {
  191. HASH_BLOCK_DATA_ORDER(c, data, 1);
  192. }
  193. int HASH_FINAL(unsigned char *md, HASH_CTX *c)
  194. {
  195. unsigned char *p = (unsigned char *)c->data;
  196. size_t n = c->num;
  197. p[n] = 0x80; /* there is always room for one */
  198. n++;
  199. if (n > (HASH_CBLOCK - 8)) {
  200. memset(p + n, 0, HASH_CBLOCK - n);
  201. n = 0;
  202. HASH_BLOCK_DATA_ORDER(c, p, 1);
  203. }
  204. memset(p + n, 0, HASH_CBLOCK - 8 - n);
  205. p += HASH_CBLOCK - 8;
  206. # if defined(DATA_ORDER_IS_BIG_ENDIAN)
  207. (void)HOST_l2c(c->Nh, p);
  208. (void)HOST_l2c(c->Nl, p);
  209. # elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
  210. (void)HOST_l2c(c->Nl, p);
  211. (void)HOST_l2c(c->Nh, p);
  212. # endif
  213. p -= HASH_CBLOCK;
  214. HASH_BLOCK_DATA_ORDER(c, p, 1);
  215. c->num = 0;
  216. OPENSSL_cleanse(p, HASH_CBLOCK);
  217. # ifndef HASH_MAKE_STRING
  218. # error "HASH_MAKE_STRING must be defined!"
  219. # else
  220. HASH_MAKE_STRING(c, md);
  221. # endif
  222. return 1;
  223. }
  224. # ifndef MD32_REG_T
  225. # if defined(__alpha) || defined(__sparcv9) || defined(__mips)
  226. # define MD32_REG_T long
  227. /*
  228. * This comment was originally written for MD5, which is why it
  229. * discusses A-D. But it basically applies to all 32-bit digests,
  230. * which is why it was moved to common header file.
  231. *
  232. * In case you wonder why A-D are declared as long and not
  233. * as MD5_LONG. Doing so results in slight performance
  234. * boost on LP64 architectures. The catch is we don't
  235. * really care if 32 MSBs of a 64-bit register get polluted
  236. * with eventual overflows as we *save* only 32 LSBs in
  237. * *either* case. Now declaring 'em long excuses the compiler
  238. * from keeping 32 MSBs zeroed resulting in 13% performance
  239. * improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
  240. * Well, to be honest it should say that this *prevents*
  241. * performance degradation.
  242. */
  243. # else
  244. /*
  245. * Above is not absolute and there are LP64 compilers that
  246. * generate better code if MD32_REG_T is defined int. The above
  247. * pre-processor condition reflects the circumstances under which
  248. * the conclusion was made and is subject to further extension.
  249. */
  250. # define MD32_REG_T int
  251. # endif
  252. # endif
  253. #endif