Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

370 rader
12 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/aead.h>
  57. #include <assert.h>
  58. #include <openssl/cipher.h>
  59. #include <openssl/err.h>
  60. #include <openssl/md5.h>
  61. #include <openssl/mem.h>
  62. #include <openssl/obj.h>
  63. #include <openssl/rc4.h>
  64. #include "internal.h"
  65. static int rc4_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
  66. const uint8_t *iv, int enc) {
  67. RC4_KEY *rc4key = (RC4_KEY *)ctx->cipher_data;
  68. RC4_set_key(rc4key, EVP_CIPHER_CTX_key_length(ctx), key);
  69. return 1;
  70. }
  71. static int rc4_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
  72. size_t in_len) {
  73. RC4_KEY *rc4key = (RC4_KEY *)ctx->cipher_data;
  74. RC4(rc4key, in_len, in, out);
  75. return 1;
  76. }
  77. static const EVP_CIPHER rc4 = {
  78. NID_rc4, 1 /* block_size */, 16 /* key_size */,
  79. 0 /* iv_len */, sizeof(RC4_KEY), EVP_CIPH_VARIABLE_LENGTH,
  80. NULL /* app_data */, rc4_init_key, rc4_cipher,
  81. NULL /* cleanup */, NULL /* ctrl */, };
  82. const EVP_CIPHER *EVP_rc4(void) { return &rc4; }
  83. struct aead_rc4_md5_tls_ctx {
  84. RC4_KEY rc4;
  85. MD5_CTX head, tail, md;
  86. size_t payload_length;
  87. unsigned char tag_len;
  88. };
  89. static int
  90. aead_rc4_md5_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
  91. size_t tag_len) {
  92. struct aead_rc4_md5_tls_ctx *rc4_ctx;
  93. size_t i;
  94. uint8_t hmac_key[MD5_CBLOCK];
  95. if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
  96. tag_len = MD5_DIGEST_LENGTH;
  97. }
  98. if (tag_len > MD5_DIGEST_LENGTH) {
  99. OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_init, CIPHER_R_TOO_LARGE);
  100. return 0;
  101. }
  102. /* The keys consists of |MD5_DIGEST_LENGTH| bytes of HMAC(MD5) key followed
  103. * by some number of bytes of RC4 key. */
  104. if (key_len <= MD5_DIGEST_LENGTH) {
  105. OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_init, CIPHER_R_BAD_KEY_LENGTH);
  106. return 0;
  107. }
  108. rc4_ctx = OPENSSL_malloc(sizeof(struct aead_rc4_md5_tls_ctx));
  109. if (rc4_ctx == NULL) {
  110. OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_init, ERR_R_MALLOC_FAILURE);
  111. return 0;
  112. }
  113. memset(rc4_ctx, 0, sizeof(struct aead_rc4_md5_tls_ctx));
  114. RC4_set_key(&rc4_ctx->rc4, key_len - MD5_DIGEST_LENGTH,
  115. key + MD5_DIGEST_LENGTH);
  116. memset(hmac_key, 0, sizeof(hmac_key));
  117. memcpy(hmac_key, key, MD5_DIGEST_LENGTH);
  118. for (i = 0; i < sizeof(hmac_key); i++) {
  119. hmac_key[i] ^= 0x36;
  120. }
  121. MD5_Init(&rc4_ctx->head);
  122. MD5_Update(&rc4_ctx->head, hmac_key, sizeof(hmac_key));
  123. for (i = 0; i < sizeof(hmac_key); i++) {
  124. hmac_key[i] ^= 0x36 ^ 0x5c;
  125. }
  126. MD5_Init(&rc4_ctx->tail);
  127. MD5_Update(&rc4_ctx->tail, hmac_key, sizeof(hmac_key));
  128. rc4_ctx->tag_len = tag_len;
  129. ctx->aead_state = rc4_ctx;
  130. return 1;
  131. }
  132. static void aead_rc4_md5_tls_cleanup(EVP_AEAD_CTX *ctx) {
  133. struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
  134. OPENSSL_cleanse(rc4_ctx, sizeof(struct aead_rc4_md5_tls_ctx));
  135. OPENSSL_free(rc4_ctx);
  136. }
  137. #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
  138. #define STITCHED_CALL
  139. /* rc4_md5_enc is defined in rc4_md5-x86_64.pl */
  140. void rc4_md5_enc(RC4_KEY *key, const void *in0, void *out, MD5_CTX *ctx,
  141. const void *inp, size_t blocks);
  142. #endif
  143. static int aead_rc4_md5_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
  144. size_t *out_len, size_t max_out_len,
  145. const uint8_t *nonce, size_t nonce_len,
  146. const uint8_t *in, size_t in_len,
  147. const uint8_t *ad, size_t ad_len) {
  148. struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
  149. MD5_CTX md;
  150. #if defined(STITCHED_CALL)
  151. size_t rc4_off, md5_off, blocks;
  152. extern unsigned int OPENSSL_ia32cap_P[];
  153. #else
  154. const size_t rc4_off = 0;
  155. const size_t md5_off = 0;
  156. #endif
  157. uint8_t digest[MD5_DIGEST_LENGTH];
  158. if (in_len + rc4_ctx->tag_len < in_len) {
  159. OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_TOO_LARGE);
  160. return 0;
  161. }
  162. if (nonce_len != 0) {
  163. OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_IV_TOO_LARGE);
  164. return 0;
  165. }
  166. if (max_out_len < in_len + rc4_ctx->tag_len) {
  167. OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_BUFFER_TOO_SMALL);
  168. return 0;
  169. }
  170. if (nonce_len != 0) {
  171. OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_TOO_LARGE);
  172. return 0;
  173. }
  174. memcpy(&md, &rc4_ctx->head, sizeof(MD5_CTX));
  175. /* The MAC's payload begins with the additional data. See
  176. * https://tools.ietf.org/html/rfc5246#section-6.2.3.1 */
  177. MD5_Update(&md, ad, ad_len);
  178. #if defined(STITCHED_CALL)
  179. /* 32 is $MOD from rc4_md5-x86_64.pl. */
  180. rc4_off = 32 - 1 - (rc4_ctx->rc4.x & (32 - 1));
  181. md5_off = MD5_CBLOCK - md.num;
  182. /* Ensure RC4 is behind MD5. */
  183. if (rc4_off > md5_off) {
  184. md5_off += MD5_CBLOCK;
  185. }
  186. assert(md5_off >= rc4_off);
  187. if (in_len > md5_off && (blocks = (in_len - md5_off) / MD5_CBLOCK) &&
  188. (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
  189. /* Process the initial portions of the plaintext normally. */
  190. MD5_Update(&md, in, md5_off);
  191. RC4(&rc4_ctx->rc4, rc4_off, in, out);
  192. /* Process the next |blocks| blocks of plaintext with stitched routines. */
  193. rc4_md5_enc(&rc4_ctx->rc4, in + rc4_off, out + rc4_off, &md, in + md5_off,
  194. blocks);
  195. blocks *= MD5_CBLOCK;
  196. rc4_off += blocks;
  197. md5_off += blocks;
  198. md.Nh += blocks >> 29;
  199. md.Nl += blocks <<= 3;
  200. if (md.Nl < (unsigned int)blocks) {
  201. md.Nh++;
  202. }
  203. } else {
  204. rc4_off = 0;
  205. md5_off = 0;
  206. }
  207. #endif
  208. /* Finish computing the MAC. */
  209. MD5_Update(&md, in + md5_off, in_len - md5_off);
  210. MD5_Final(digest, &md);
  211. memcpy(&md, &rc4_ctx->tail, sizeof(MD5_CTX));
  212. MD5_Update(&md, digest, sizeof(digest));
  213. if (rc4_ctx->tag_len == MD5_DIGEST_LENGTH) {
  214. MD5_Final(out + in_len, &md);
  215. } else {
  216. MD5_Final(digest, &md);
  217. memcpy(out + in_len, digest, rc4_ctx->tag_len);
  218. }
  219. /* Encrypt the remainder of the plaintext and the MAC. */
  220. RC4(&rc4_ctx->rc4, in_len - rc4_off, in + rc4_off, out + rc4_off);
  221. RC4(&rc4_ctx->rc4, MD5_DIGEST_LENGTH, out + in_len, out + in_len);
  222. *out_len = in_len + rc4_ctx->tag_len;
  223. return 1;
  224. }
  225. static int aead_rc4_md5_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
  226. size_t *out_len, size_t max_out_len,
  227. const uint8_t *nonce, size_t nonce_len,
  228. const uint8_t *in, size_t in_len,
  229. const uint8_t *ad, size_t ad_len) {
  230. struct aead_rc4_md5_tls_ctx *rc4_ctx = ctx->aead_state;
  231. MD5_CTX md;
  232. size_t plaintext_len;
  233. #if defined(STITCHED_CALL)
  234. unsigned int l;
  235. size_t rc4_off, md5_off, blocks;
  236. extern unsigned int OPENSSL_ia32cap_P[];
  237. #else
  238. const size_t rc4_off = 0;
  239. const size_t md5_off = 0;
  240. #endif
  241. uint8_t digest[MD5_DIGEST_LENGTH];
  242. if (in_len < rc4_ctx->tag_len) {
  243. OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_open, CIPHER_R_BAD_DECRYPT);
  244. return 0;
  245. }
  246. plaintext_len = in_len - rc4_ctx->tag_len;
  247. if (nonce_len != 0) {
  248. OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_seal, CIPHER_R_TOO_LARGE);
  249. return 0;
  250. }
  251. if (max_out_len < plaintext_len) {
  252. OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_open, CIPHER_R_BUFFER_TOO_SMALL);
  253. return 0;
  254. }
  255. memcpy(&md, &rc4_ctx->head, sizeof(MD5_CTX));
  256. /* The MAC's payload begins with the additional data. See
  257. * https://tools.ietf.org/html/rfc5246#section-6.2.3.1 */
  258. MD5_Update(&md, ad, ad_len);
  259. #if defined(STITCHED_CALL)
  260. rc4_off = 32 - 1 - (rc4_ctx->rc4.x & (32 - 1));
  261. md5_off = MD5_CBLOCK - md.num;
  262. /* Ensure MD5 is a full block behind RC4 so it has plaintext to operate on in
  263. * both normal and stitched routines. */
  264. if (md5_off > rc4_off) {
  265. rc4_off += 2 * MD5_CBLOCK;
  266. } else {
  267. rc4_off += MD5_CBLOCK;
  268. }
  269. if (in_len > rc4_off && (blocks = (in_len - rc4_off) / MD5_CBLOCK) &&
  270. (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) {
  271. /* Decrypt the initial portion of the ciphertext and digest the plaintext
  272. * normally. */
  273. RC4(&rc4_ctx->rc4, rc4_off, in, out);
  274. MD5_Update(&md, out, md5_off);
  275. /* Decrypt and digest the next |blocks| blocks of ciphertext with the
  276. * stitched routines. */
  277. rc4_md5_enc(&rc4_ctx->rc4, in + rc4_off, out + rc4_off, &md, out + md5_off,
  278. blocks);
  279. blocks *= MD5_CBLOCK;
  280. rc4_off += blocks;
  281. md5_off += blocks;
  282. l = (md.Nl + (blocks << 3)) & 0xffffffffU;
  283. if (l < md.Nl) {
  284. md.Nh++;
  285. }
  286. md.Nl = l;
  287. md.Nh += blocks >> 29;
  288. } else {
  289. md5_off = 0;
  290. rc4_off = 0;
  291. }
  292. #endif
  293. /* Process the remainder of the input. */
  294. RC4(&rc4_ctx->rc4, in_len - rc4_off, in + rc4_off, out + rc4_off);
  295. MD5_Update(&md, out + md5_off, plaintext_len - md5_off);
  296. MD5_Final(digest, &md);
  297. /* Calculate HMAC and verify it */
  298. memcpy(&md, &rc4_ctx->tail, sizeof(MD5_CTX));
  299. MD5_Update(&md, digest, MD5_DIGEST_LENGTH);
  300. MD5_Final(digest, &md);
  301. if (CRYPTO_memcmp(out + plaintext_len, digest, rc4_ctx->tag_len)) {
  302. OPENSSL_PUT_ERROR(CIPHER, aead_rc4_md5_tls_open, CIPHER_R_BAD_DECRYPT);
  303. return 0;
  304. }
  305. *out_len = plaintext_len;
  306. return 1;
  307. }
  308. static const EVP_AEAD aead_rc4_md5_tls = {
  309. 16 + MD5_DIGEST_LENGTH, /* key len (RC4 + MD5) */
  310. 0, /* nonce len */
  311. MD5_DIGEST_LENGTH, /* overhead */
  312. MD5_DIGEST_LENGTH, /* max tag length */
  313. aead_rc4_md5_tls_init, aead_rc4_md5_tls_cleanup,
  314. aead_rc4_md5_tls_seal, aead_rc4_md5_tls_open,
  315. };
  316. const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; }