md5.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #include "os.h"
  2. #include <libsec.h>
  3. /*
  4. * rfc1321 requires that I include this. The code is new. The constants
  5. * all come from the rfc (hence the copyright). We trade a table for the
  6. * macros in rfc. The total size is a lot less. -- presotto
  7. *
  8. * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
  9. * rights reserved.
  10. *
  11. * License to copy and use this software is granted provided that it
  12. * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
  13. * Algorithm" in all material mentioning or referencing this software
  14. * or this function.
  15. *
  16. * License is also granted to make and use derivative works provided
  17. * that such works are identified as "derived from the RSA Data
  18. * Security, Inc. MD5 Message-Digest Algorithm" in all material
  19. * mentioning or referencing the derived work.
  20. *
  21. * RSA Data Security, Inc. makes no representations concerning either
  22. * the merchantability of this software or the suitability of this
  23. * software forany particular purpose. It is provided "as is"
  24. * without express or implied warranty of any kind.
  25. * These notices must be retained in any copies of any part of this
  26. * documentation and/or software.
  27. */
  28. static void encode(uchar*, u32int*, ulong);
  29. static void decode(u32int*, uchar*, ulong);
  30. extern void _md5block(uchar*, ulong, u32int*);
  31. MD5state*
  32. md5(uchar *p, ulong len, uchar *digest, MD5state *s)
  33. {
  34. u32int x[16];
  35. uchar buf[128];
  36. int i;
  37. uchar *e;
  38. if(s == nil){
  39. s = malloc(sizeof(*s));
  40. if(s == nil)
  41. return nil;
  42. memset(s, 0, sizeof(*s));
  43. s->malloced = 1;
  44. }
  45. if(s->seeded == 0){
  46. /* seed the state, these constants would look nicer big-endian */
  47. s->state[0] = 0x67452301;
  48. s->state[1] = 0xefcdab89;
  49. s->state[2] = 0x98badcfe;
  50. s->state[3] = 0x10325476;
  51. s->seeded = 1;
  52. }
  53. /* fill out the partial 64 byte block from previous calls */
  54. if(s->blen){
  55. i = 64 - s->blen;
  56. if(len < i)
  57. i = len;
  58. memmove(s->buf + s->blen, p, i);
  59. len -= i;
  60. s->blen += i;
  61. p += i;
  62. if(s->blen == 64){
  63. _md5block(s->buf, s->blen, s->state);
  64. s->len += s->blen;
  65. s->blen = 0;
  66. }
  67. }
  68. /* do 64 byte blocks */
  69. i = len & ~0x3f;
  70. if(i){
  71. _md5block(p, i, s->state);
  72. s->len += i;
  73. len -= i;
  74. p += i;
  75. }
  76. /* save the left overs if not last call */
  77. if(digest == 0){
  78. if(len){
  79. memmove(s->buf, p, len);
  80. s->blen += len;
  81. }
  82. return s;
  83. }
  84. /*
  85. * this is the last time through, pad what's left with 0x80,
  86. * 0's, and the input count to create a multiple of 64 bytes
  87. */
  88. if(s->blen){
  89. p = s->buf;
  90. len = s->blen;
  91. } else {
  92. memmove(buf, p, len);
  93. p = buf;
  94. }
  95. s->len += len;
  96. e = p + len;
  97. if(len < 56)
  98. i = 56 - len;
  99. else
  100. i = 120 - len;
  101. memset(e, 0, i);
  102. *e = 0x80;
  103. len += i;
  104. /* append the count */
  105. x[0] = s->len<<3;
  106. x[1] = s->len>>29;
  107. encode(p+len, x, 8);
  108. /* digest the last part */
  109. _md5block(p, len+8, s->state);
  110. s->len += len;
  111. /* return result and free state */
  112. encode(digest, s->state, MD5dlen);
  113. if(s->malloced == 1)
  114. free(s);
  115. return nil;
  116. }
  117. /*
  118. * encodes input (u32int) into output (uchar). Assumes len is
  119. * a multiple of 4.
  120. */
  121. static void
  122. encode(uchar *output, u32int *input, ulong len)
  123. {
  124. u32int x;
  125. uchar *e;
  126. for(e = output + len; output < e;) {
  127. x = *input++;
  128. *output++ = x;
  129. *output++ = x >> 8;
  130. *output++ = x >> 16;
  131. *output++ = x >> 24;
  132. }
  133. }