rsaenh: Fix failing tests on Windows ME.
[wine] / dlls / rsaenh / rc4.c
1 /*
2  * dlls/rsaenh/rc4.c
3  * RC4 functions
4  *
5  * Copyright 2004 Michael Jung
6  * Based on public domain code by Tom St Denis (tomstdenis@iahu.ca)
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 /*
24  * This file contains code from the LibTomCrypt cryptographic 
25  * library written by Tom St Denis (tomstdenis@iahu.ca). LibTomCrypt
26  * is in the public domain. The code in this file is tailored to
27  * special requirements. Take a look at http://libtomcrypt.org for the
28  * original version. 
29  */
30
31 #include "tomcrypt.h"
32
33 int rc4_start(prng_state *prng)
34 {
35     /* set keysize to zero */
36     prng->rc4.x = 0;
37     
38     return CRYPT_OK;
39 }
40
41 int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
42 {
43     /* trim as required */
44     if (prng->rc4.x + len > 256) {
45        if (prng->rc4.x == 256) {
46           /* I can't possibly accept another byte, ok maybe a mint wafer... */
47           return CRYPT_OK;
48        } else {
49           /* only accept part of it */
50           len = 256 - prng->rc4.x;
51        }       
52     }
53
54     while (len--) {
55        prng->rc4.buf[prng->rc4.x++] = *buf++;
56     }
57
58     return CRYPT_OK;
59 }
60
61 int rc4_ready(prng_state *prng)
62 {
63     unsigned char key[256], tmp, *s;
64     int keylen, x, y, j;
65
66     /* extract the key */
67     s = prng->rc4.buf;
68     memcpy(key, s, 256);
69     keylen = prng->rc4.x;
70
71     /* make RC4 perm and shuffle */
72     for (x = 0; x < 256; x++) {
73         s[x] = x;
74     }
75
76     for (j = x = y = 0; x < 256; x++) {
77         y = (y + prng->rc4.buf[x] + key[j++]) & 255;
78         if (j == keylen) {
79            j = 0; 
80         }
81         tmp = s[x]; s[x] = s[y]; s[y] = tmp;
82     }
83     prng->rc4.x = 0;
84     prng->rc4.y = 0;
85
86     return CRYPT_OK;
87 }
88
89 unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng)
90 {
91    unsigned char x, y, *s, tmp;
92    unsigned long n;
93
94    n = len;
95    x = prng->rc4.x;
96    y = prng->rc4.y;
97    s = prng->rc4.buf;
98    while (len--) {
99       x = (x + 1) & 255;
100       y = (y + s[x]) & 255;
101       tmp = s[x]; s[x] = s[y]; s[y] = tmp;
102       tmp = (s[x] + s[y]) & 255;
103       *buf++ ^= s[tmp];
104    }
105    prng->rc4.x = x;
106    prng->rc4.y = y;
107    return n;
108 }