Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

285 Zeilen
9.3 KiB

  1. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  2. * All rights reserved.
  3. *
  4. * This package is an SSL implementation written
  5. * by Eric Young (eay@cryptsoft.com).
  6. * The implementation was written so as to conform with Netscapes SSL.
  7. *
  8. * This library is free for commercial and non-commercial use as long as
  9. * the following conditions are aheared to. The following conditions
  10. * apply to all code found in this distribution, be it the RC4, RSA,
  11. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  12. * included with this distribution is covered by the same copyright terms
  13. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  14. *
  15. * Copyright remains Eric Young's, and as such any Copyright notices in
  16. * the code are not to be removed.
  17. * If this package is used in a product, Eric Young should be given attribution
  18. * as the author of the parts of the library used.
  19. * This can be in the form of a textual message at program startup or
  20. * in documentation (online or textual) provided with the package.
  21. *
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions
  24. * are met:
  25. * 1. Redistributions of source code must retain the copyright
  26. * notice, this list of conditions and the following disclaimer.
  27. * 2. Redistributions in binary form must reproduce the above copyright
  28. * notice, this list of conditions and the following disclaimer in the
  29. * documentation and/or other materials provided with the distribution.
  30. * 3. All advertising materials mentioning features or use of this software
  31. * must display the following acknowledgement:
  32. * "This product includes cryptographic software written by
  33. * Eric Young (eay@cryptsoft.com)"
  34. * The word 'cryptographic' can be left out if the rouines from the library
  35. * being used are not cryptographic related :-).
  36. * 4. If you include any Windows specific code (or a derivative thereof) from
  37. * the apps directory (application code) you must include an acknowledgement:
  38. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  39. *
  40. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  41. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  43. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  44. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  45. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  46. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  48. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  49. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  50. * SUCH DAMAGE.
  51. *
  52. * The licence and distribution terms for any publically available version or
  53. * derivative of this code cannot be changed. i.e. this code cannot simply be
  54. * copied and put under another distribution licence
  55. * [including the GNU Public Licence.] */
  56. #include <openssl/rc4.h>
  57. #if defined(OPENSSL_NO_ASM) || \
  58. (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86))
  59. #if defined(OPENSSL_64_BIT)
  60. #define RC4_CHUNK uint64_t
  61. #elif defined(OPENSSL_32_BIT)
  62. #define RC4_CHUNK uint32_t
  63. #else
  64. #error "Unknown word size"
  65. #endif
  66. /* RC4 as implemented from a posting from
  67. * Newsgroups: sci.crypt
  68. * From: sterndark@netcom.com (David Sterndark)
  69. * Subject: RC4 Algorithm revealed.
  70. * Message-ID: <sternCvKL4B.Hyy@netcom.com>
  71. * Date: Wed, 14 Sep 1994 06:35:31 GMT */
  72. void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) {
  73. uint32_t *d;
  74. uint32_t x, y, tx, ty;
  75. size_t i;
  76. x = key->x;
  77. y = key->y;
  78. d = key->data;
  79. #define RC4_STEP \
  80. (x = (x + 1) & 0xff, tx = d[x], y = (tx + y) & 0xff, ty = d[y], d[y] = tx, \
  81. d[x] = ty, (RC4_CHUNK)d[(tx + ty) & 0xff])
  82. if ((((size_t)in & (sizeof(RC4_CHUNK) - 1)) |
  83. ((size_t)out & (sizeof(RC4_CHUNK) - 1))) == 0) {
  84. RC4_CHUNK ichunk, otp;
  85. const union {
  86. long one;
  87. char little;
  88. } is_endian = {1};
  89. /* I reckon we can afford to implement both endian
  90. * cases and to decide which way to take at run-time
  91. * because the machine code appears to be very compact
  92. * and redundant 1-2KB is perfectly tolerable (i.e.
  93. * in case the compiler fails to eliminate it:-). By
  94. * suggestion from Terrel Larson <terr@terralogic.net>
  95. * who also stands for the is_endian union:-)
  96. *
  97. * Special notes.
  98. *
  99. * - is_endian is declared automatic as doing otherwise
  100. * (declaring static) prevents gcc from eliminating
  101. * the redundant code;
  102. * - compilers (those I've tried) don't seem to have
  103. * problems eliminating either the operators guarded
  104. * by "if (sizeof(RC4_CHUNK)==8)" or the condition
  105. * expressions themselves so I've got 'em to replace
  106. * corresponding #ifdefs from the previous version;
  107. * - I chose to let the redundant switch cases when
  108. * sizeof(RC4_CHUNK)!=8 be (were also #ifdefed
  109. * before);
  110. * - in case you wonder "&(sizeof(RC4_CHUNK)*8-1)" in
  111. * [LB]ESHFT guards against "shift is out of range"
  112. * warnings when sizeof(RC4_CHUNK)!=8
  113. *
  114. * <appro@fy.chalmers.se> */
  115. if (!is_endian.little) { /* BIG-ENDIAN CASE */
  116. #define BESHFT(c) \
  117. (((sizeof(RC4_CHUNK) - (c) - 1) * 8) & (sizeof(RC4_CHUNK) * 8 - 1))
  118. for (; len & (0 - sizeof(RC4_CHUNK)); len -= sizeof(RC4_CHUNK)) {
  119. ichunk = *(RC4_CHUNK *)in;
  120. otp = RC4_STEP << BESHFT(0);
  121. otp |= RC4_STEP << BESHFT(1);
  122. otp |= RC4_STEP << BESHFT(2);
  123. otp |= RC4_STEP << BESHFT(3);
  124. #if defined(OPENSSL_64_BIT)
  125. otp |= RC4_STEP << BESHFT(4);
  126. otp |= RC4_STEP << BESHFT(5);
  127. otp |= RC4_STEP << BESHFT(6);
  128. otp |= RC4_STEP << BESHFT(7);
  129. #endif
  130. *(RC4_CHUNK *)out = otp ^ ichunk;
  131. in += sizeof(RC4_CHUNK);
  132. out += sizeof(RC4_CHUNK);
  133. }
  134. } else { /* LITTLE-ENDIAN CASE */
  135. #define LESHFT(c) (((c) * 8) & (sizeof(RC4_CHUNK) * 8 - 1))
  136. for (; len & (0 - sizeof(RC4_CHUNK)); len -= sizeof(RC4_CHUNK)) {
  137. ichunk = *(RC4_CHUNK *)in;
  138. otp = RC4_STEP;
  139. otp |= RC4_STEP << 8;
  140. otp |= RC4_STEP << 16;
  141. otp |= RC4_STEP << 24;
  142. #if defined(OPENSSL_64_BIT)
  143. otp |= RC4_STEP << LESHFT(4);
  144. otp |= RC4_STEP << LESHFT(5);
  145. otp |= RC4_STEP << LESHFT(6);
  146. otp |= RC4_STEP << LESHFT(7);
  147. #endif
  148. *(RC4_CHUNK *)out = otp ^ ichunk;
  149. in += sizeof(RC4_CHUNK);
  150. out += sizeof(RC4_CHUNK);
  151. }
  152. }
  153. }
  154. #define LOOP(in, out) \
  155. x = ((x + 1) & 0xff); \
  156. tx = d[x]; \
  157. y = (tx + y) & 0xff; \
  158. d[x] = ty = d[y]; \
  159. d[y] = tx; \
  160. (out) = d[(tx + ty) & 0xff] ^ (in);
  161. #ifndef RC4_INDEX
  162. #define RC4_LOOP(a, b, i) LOOP(*((a)++), *((b)++))
  163. #else
  164. #define RC4_LOOP(a, b, i) LOOP(a[i], b[i])
  165. #endif
  166. i = len >> 3;
  167. if (i) {
  168. for (;;) {
  169. RC4_LOOP(in, out, 0);
  170. RC4_LOOP(in, out, 1);
  171. RC4_LOOP(in, out, 2);
  172. RC4_LOOP(in, out, 3);
  173. RC4_LOOP(in, out, 4);
  174. RC4_LOOP(in, out, 5);
  175. RC4_LOOP(in, out, 6);
  176. RC4_LOOP(in, out, 7);
  177. #ifdef RC4_INDEX
  178. in += 8;
  179. out += 8;
  180. #endif
  181. if (--i == 0) {
  182. break;
  183. }
  184. }
  185. }
  186. i = len & 0x07;
  187. if (i) {
  188. for (;;) {
  189. RC4_LOOP(in, out, 0);
  190. if (--i == 0) {
  191. break;
  192. }
  193. RC4_LOOP(in, out, 1);
  194. if (--i == 0) {
  195. break;
  196. }
  197. RC4_LOOP(in, out, 2);
  198. if (--i == 0) {
  199. break;
  200. }
  201. RC4_LOOP(in, out, 3);
  202. if (--i == 0) {
  203. break;
  204. }
  205. RC4_LOOP(in, out, 4);
  206. if (--i == 0) {
  207. break;
  208. }
  209. RC4_LOOP(in, out, 5);
  210. if (--i == 0) {
  211. break;
  212. }
  213. RC4_LOOP(in, out, 6);
  214. if (--i == 0) {
  215. break;
  216. }
  217. }
  218. }
  219. key->x = x;
  220. key->y = y;
  221. }
  222. void RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key) {
  223. uint32_t tmp;
  224. int id1, id2;
  225. uint32_t *d;
  226. unsigned int i;
  227. d = &rc4key->data[0];
  228. rc4key->x = 0;
  229. rc4key->y = 0;
  230. id1 = id2 = 0;
  231. #define SK_LOOP(d, n) \
  232. { \
  233. tmp = d[(n)]; \
  234. id2 = (key[id1] + tmp + id2) & 0xff; \
  235. if (++id1 == len) \
  236. id1 = 0; \
  237. d[(n)] = d[id2]; \
  238. d[id2] = tmp; \
  239. }
  240. for (i = 0; i < 256; i++) {
  241. d[i] = i;
  242. }
  243. for (i = 0; i < 256; i += 4) {
  244. SK_LOOP(d, i + 0);
  245. SK_LOOP(d, i + 1);
  246. SK_LOOP(d, i + 2);
  247. SK_LOOP(d, i + 3);
  248. }
  249. }
  250. #else
  251. /* In this case several functions are provided by asm code. However, one cannot
  252. * control asm symbol visibility with command line flags and such so they are
  253. * always hidden and wrapped by these C functions, which can be so
  254. * controlled. */
  255. void asm_RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out);
  256. void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) {
  257. asm_RC4(key, len, in, out);
  258. }
  259. void asm_RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key);
  260. void RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key) {
  261. asm_RC4_set_key(rc4key, len, key);
  262. }
  263. #endif /* OPENSSL_NO_ASM || (!OPENSSL_X86_64 && !OPENSSL_X86) */