No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

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