rc4.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /**
  2. * @file rc4.c
  3. * @brief RC4 encryption algorithm
  4. *
  5. * @section License
  6. *
  7. * SPDX-License-Identifier: GPL-2.0-or-later
  8. *
  9. * Copyright (C) 2010-2023 Oryx Embedded SARL. All rights reserved.
  10. *
  11. * This file is part of CycloneCRYPTO Open.
  12. *
  13. * This program is free software; you can redistribute it and/or
  14. * modify it under the terms of the GNU General Public License
  15. * as published by the Free Software Foundation; either version 2
  16. * of the License, or (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software Foundation,
  25. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  26. *
  27. * @author Oryx Embedded SARL (www.oryx-embedded.com)
  28. * @version 2.2.4
  29. **/
  30. //Switch to the appropriate trace level
  31. #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
  32. //Dependencies
  33. #include "core/crypto.h"
  34. #include "cipher/rc4.h"
  35. //Check crypto library configuration
  36. #if (RC4_SUPPORT == ENABLED)
  37. //Common interface for encryption algorithms
  38. const CipherAlgo rc4CipherAlgo =
  39. {
  40. "RC4",
  41. sizeof(Rc4Context),
  42. CIPHER_ALGO_TYPE_STREAM,
  43. 0,
  44. (CipherAlgoInit) rc4Init,
  45. (CipherAlgoEncryptStream) rc4Cipher,
  46. (CipherAlgoDecryptStream) rc4Cipher,
  47. NULL,
  48. NULL,
  49. (CipherAlgoDeinit) rc4Deinit
  50. };
  51. /**
  52. * @brief Initialize an RC4 context using the supplied key
  53. * @param[in] context Pointer to the RC4 context to initialize
  54. * @param[in] key Pointer to the key
  55. * @param[in] length Length of the key
  56. * @return Error code
  57. **/
  58. error_t rc4Init(Rc4Context *context, const uint8_t *key, size_t length)
  59. {
  60. uint_t i;
  61. uint_t j;
  62. uint8_t temp;
  63. //Check parameters
  64. if(context == NULL || key == NULL)
  65. return WINDOWS_ERROR_INVALID_PARAMETER;
  66. //Clear context
  67. context->i = 0;
  68. context->j = 0;
  69. //Initialize the S array with identity permutation
  70. for(i = 0; i < 256; i++)
  71. {
  72. context->s[i] = i;
  73. }
  74. //S is then processed for 256 iterations
  75. for(i = 0, j = 0; i < 256; i++)
  76. {
  77. //Randomize the permutations using the supplied key
  78. j = (j + context->s[i] + key[i % length]) % 256;
  79. //Swap the values of S[i] and S[j]
  80. temp = context->s[i];
  81. context->s[i] = context->s[j];
  82. context->s[j] = temp;
  83. }
  84. //RC4 context successfully initialized
  85. return SUCCESS;
  86. }
  87. /**
  88. * @brief Encrypt/decrypt data with the RC4 algorithm
  89. * @param[in] context Pointer to the RC4 context
  90. * @param[in] input Pointer to the data to encrypt/decrypt
  91. * @param[in] output Pointer to the resulting data
  92. * @param[in] length Length of the input data
  93. **/
  94. void rc4Cipher(Rc4Context *context, const uint8_t *input, uint8_t *output,
  95. size_t length)
  96. {
  97. uint8_t temp;
  98. //Restore context
  99. uint_t i = context->i;
  100. uint_t j = context->j;
  101. uint8_t *s = context->s;
  102. //Encryption loop
  103. while(length > 0)
  104. {
  105. //Adjust indices
  106. i = (i + 1) % 256;
  107. j = (j + s[i]) % 256;
  108. //Swap the values of S[i] and S[j]
  109. temp = s[i];
  110. s[i] = s[j];
  111. s[j] = temp;
  112. //Valid input and output?
  113. if(input != NULL && output != NULL)
  114. {
  115. //XOR the input data with the RC4 stream
  116. *output = *input ^ s[(s[i] + s[j]) % 256];
  117. //Increment data pointers
  118. input++;
  119. output++;
  120. }
  121. //Remaining bytes to process
  122. length--;
  123. }
  124. //Save context
  125. context->i = i;
  126. context->j = j;
  127. }
  128. /**
  129. * @brief Release RC4 context
  130. * @param[in] context Pointer to the RC4 context
  131. **/
  132. void rc4Deinit(Rc4Context *context)
  133. {
  134. //Clear RC4 context
  135. osMemset(context, 0, sizeof(Rc4Context));
  136. }
  137. #endif
  138. void rc4_encryption(uint8_t *data, size_t data_length, const uint8_t *key, size_t key_length) {
  139. uint8_t S[256];
  140. uint8_t T[256];
  141. uint8_t temp;
  142. size_t i, j, k;
  143. // 初始化S盒和T盒
  144. for (i = 0; i < 256; i++) {
  145. S[i] = i;
  146. T[i] = key[i % key_length];
  147. }
  148. // 初始置换
  149. j = 0;
  150. for (i = 0; i < 256; i++) {
  151. j = (j + S[i] + T[i]) % 256;
  152. temp = S[i];
  153. S[i] = S[j];
  154. S[j] = temp;
  155. }
  156. // 生成伪随机数流并加密/解密数据
  157. i = 0;
  158. j = 0;
  159. for (k = 0; k < data_length; k++) {
  160. i = (i + 1) % 256;
  161. j = (j + S[i]) % 256;
  162. temp = S[i];
  163. S[i] = S[j];
  164. S[j] = temp;
  165. uint8_t key_byte = S[(S[i] + S[j]) % 256];
  166. data[k] ^= key_byte;
  167. }
  168. }
  169. void rc4_decrypt(uint8_t *data, size_t data_length, const uint8_t *key, size_t key_length) {
  170. rc4_encryption(data, data_length, key, key_length);
  171. }