cifs_md4.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Cryptographic API.
  4. *
  5. * MD4 Message Digest Algorithm (RFC1320).
  6. *
  7. * Implementation derived from Andrew Tridgell and Steve French's
  8. * CIFS MD4 implementation, and the cryptoapi implementation
  9. * originally based on the public domain implementation written
  10. * by Colin Plumb in 1993.
  11. *
  12. * Copyright (c) Andrew Tridgell 1997-1998.
  13. * Modified by Steve French ([email protected]) 2002
  14. * Copyright (c) Cryptoapi developers.
  15. * Copyright (c) 2002 David S. Miller ([email protected])
  16. * Copyright (c) 2002 James Morris <[email protected]>
  17. *
  18. */
  19. #include <linux/init.h>
  20. #include <linux/kernel.h>
  21. #include <linux/module.h>
  22. #include <linux/string.h>
  23. #include <linux/types.h>
  24. #include <asm/byteorder.h>
  25. #include "md4.h"
  26. MODULE_LICENSE("GPL");
  27. static inline u32 lshift(u32 x, unsigned int s)
  28. {
  29. x &= 0xFFFFFFFF;
  30. return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
  31. }
  32. static inline u32 F(u32 x, u32 y, u32 z)
  33. {
  34. return (x & y) | ((~x) & z);
  35. }
  36. static inline u32 G(u32 x, u32 y, u32 z)
  37. {
  38. return (x & y) | (x & z) | (y & z);
  39. }
  40. static inline u32 H(u32 x, u32 y, u32 z)
  41. {
  42. return x ^ y ^ z;
  43. }
  44. #define ROUND1(a,b,c,d,k,s) (a = lshift(a + F(b,c,d) + k, s))
  45. #define ROUND2(a,b,c,d,k,s) (a = lshift(a + G(b,c,d) + k + (u32)0x5A827999,s))
  46. #define ROUND3(a,b,c,d,k,s) (a = lshift(a + H(b,c,d) + k + (u32)0x6ED9EBA1,s))
  47. static void md4_transform(u32 *hash, u32 const *in)
  48. {
  49. u32 a, b, c, d;
  50. a = hash[0];
  51. b = hash[1];
  52. c = hash[2];
  53. d = hash[3];
  54. ROUND1(a, b, c, d, in[0], 3);
  55. ROUND1(d, a, b, c, in[1], 7);
  56. ROUND1(c, d, a, b, in[2], 11);
  57. ROUND1(b, c, d, a, in[3], 19);
  58. ROUND1(a, b, c, d, in[4], 3);
  59. ROUND1(d, a, b, c, in[5], 7);
  60. ROUND1(c, d, a, b, in[6], 11);
  61. ROUND1(b, c, d, a, in[7], 19);
  62. ROUND1(a, b, c, d, in[8], 3);
  63. ROUND1(d, a, b, c, in[9], 7);
  64. ROUND1(c, d, a, b, in[10], 11);
  65. ROUND1(b, c, d, a, in[11], 19);
  66. ROUND1(a, b, c, d, in[12], 3);
  67. ROUND1(d, a, b, c, in[13], 7);
  68. ROUND1(c, d, a, b, in[14], 11);
  69. ROUND1(b, c, d, a, in[15], 19);
  70. ROUND2(a, b, c, d, in[0], 3);
  71. ROUND2(d, a, b, c, in[4], 5);
  72. ROUND2(c, d, a, b, in[8], 9);
  73. ROUND2(b, c, d, a, in[12], 13);
  74. ROUND2(a, b, c, d, in[1], 3);
  75. ROUND2(d, a, b, c, in[5], 5);
  76. ROUND2(c, d, a, b, in[9], 9);
  77. ROUND2(b, c, d, a, in[13], 13);
  78. ROUND2(a, b, c, d, in[2], 3);
  79. ROUND2(d, a, b, c, in[6], 5);
  80. ROUND2(c, d, a, b, in[10], 9);
  81. ROUND2(b, c, d, a, in[14], 13);
  82. ROUND2(a, b, c, d, in[3], 3);
  83. ROUND2(d, a, b, c, in[7], 5);
  84. ROUND2(c, d, a, b, in[11], 9);
  85. ROUND2(b, c, d, a, in[15], 13);
  86. ROUND3(a, b, c, d, in[0], 3);
  87. ROUND3(d, a, b, c, in[8], 9);
  88. ROUND3(c, d, a, b, in[4], 11);
  89. ROUND3(b, c, d, a, in[12], 15);
  90. ROUND3(a, b, c, d, in[2], 3);
  91. ROUND3(d, a, b, c, in[10], 9);
  92. ROUND3(c, d, a, b, in[6], 11);
  93. ROUND3(b, c, d, a, in[14], 15);
  94. ROUND3(a, b, c, d, in[1], 3);
  95. ROUND3(d, a, b, c, in[9], 9);
  96. ROUND3(c, d, a, b, in[5], 11);
  97. ROUND3(b, c, d, a, in[13], 15);
  98. ROUND3(a, b, c, d, in[3], 3);
  99. ROUND3(d, a, b, c, in[11], 9);
  100. ROUND3(c, d, a, b, in[7], 11);
  101. ROUND3(b, c, d, a, in[15], 15);
  102. hash[0] += a;
  103. hash[1] += b;
  104. hash[2] += c;
  105. hash[3] += d;
  106. }
  107. static inline void md4_transform_helper(struct md4_ctx *ctx)
  108. {
  109. le32_to_cpu_array(ctx->block, ARRAY_SIZE(ctx->block));
  110. md4_transform(ctx->hash, ctx->block);
  111. }
  112. int cifs_md4_init(struct md4_ctx *mctx)
  113. {
  114. memset(mctx, 0, sizeof(struct md4_ctx));
  115. mctx->hash[0] = 0x67452301;
  116. mctx->hash[1] = 0xefcdab89;
  117. mctx->hash[2] = 0x98badcfe;
  118. mctx->hash[3] = 0x10325476;
  119. mctx->byte_count = 0;
  120. return 0;
  121. }
  122. EXPORT_SYMBOL_GPL(cifs_md4_init);
  123. int cifs_md4_update(struct md4_ctx *mctx, const u8 *data, unsigned int len)
  124. {
  125. const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
  126. mctx->byte_count += len;
  127. if (avail > len) {
  128. memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
  129. data, len);
  130. return 0;
  131. }
  132. memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
  133. data, avail);
  134. md4_transform_helper(mctx);
  135. data += avail;
  136. len -= avail;
  137. while (len >= sizeof(mctx->block)) {
  138. memcpy(mctx->block, data, sizeof(mctx->block));
  139. md4_transform_helper(mctx);
  140. data += sizeof(mctx->block);
  141. len -= sizeof(mctx->block);
  142. }
  143. memcpy(mctx->block, data, len);
  144. return 0;
  145. }
  146. EXPORT_SYMBOL_GPL(cifs_md4_update);
  147. int cifs_md4_final(struct md4_ctx *mctx, u8 *out)
  148. {
  149. const unsigned int offset = mctx->byte_count & 0x3f;
  150. char *p = (char *)mctx->block + offset;
  151. int padding = 56 - (offset + 1);
  152. *p++ = 0x80;
  153. if (padding < 0) {
  154. memset(p, 0x00, padding + sizeof(u64));
  155. md4_transform_helper(mctx);
  156. p = (char *)mctx->block;
  157. padding = 56;
  158. }
  159. memset(p, 0, padding);
  160. mctx->block[14] = mctx->byte_count << 3;
  161. mctx->block[15] = mctx->byte_count >> 29;
  162. le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
  163. sizeof(u64)) / sizeof(u32));
  164. md4_transform(mctx->hash, mctx->block);
  165. cpu_to_le32_array(mctx->hash, ARRAY_SIZE(mctx->hash));
  166. memcpy(out, mctx->hash, sizeof(mctx->hash));
  167. memset(mctx, 0, sizeof(*mctx));
  168. return 0;
  169. }
  170. EXPORT_SYMBOL_GPL(cifs_md4_final);