1 /* arc4.c
2  *
3  * Copyright (C) 2006-2021 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL.
6  *
7  * wolfSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * wolfSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20  */
21 
22 
23 #ifdef HAVE_CONFIG_H
24     #include <config.h>
25 #endif
26 
27 #include <wolfssl/wolfcrypt/settings.h>
28 
29 #ifndef NO_RC4
30 
31 #include <wolfssl/wolfcrypt/error-crypt.h>
32 #include <wolfssl/wolfcrypt/arc4.h>
33 
34 
wc_Arc4SetKey(Arc4 * arc4,const byte * key,word32 length)35 int wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length)
36 {
37     int ret = 0;
38     word32 i;
39     word32 keyIndex = 0, stateIndex = 0;
40 
41     if (arc4 == NULL || key == NULL || length == 0) {
42         return BAD_FUNC_ARG;
43     }
44 
45 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \
46         defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V)
47     if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) {
48         return NitroxArc4SetKey(arc4, key, length);
49     }
50 #endif
51 
52     arc4->x = 1;
53     arc4->y = 0;
54 
55     for (i = 0; i < ARC4_STATE_SIZE; i++)
56         arc4->state[i] = (byte)i;
57 
58     for (i = 0; i < ARC4_STATE_SIZE; i++) {
59         word32 a = arc4->state[i];
60         stateIndex += key[keyIndex] + a;
61         stateIndex &= 0xFF;
62         arc4->state[i] = arc4->state[stateIndex];
63         arc4->state[stateIndex] = (byte)a;
64 
65         if (++keyIndex >= length)
66             keyIndex = 0;
67     }
68 
69     return ret;
70 }
71 
72 
MakeByte(word32 * x,word32 * y,byte * s)73 static WC_INLINE byte MakeByte(word32* x, word32* y, byte* s)
74 {
75     word32 a = s[*x], b;
76     *y = (*y+a) & 0xff;
77 
78     b = s[*y];
79     s[*x] = (byte)b;
80     s[*y] = (byte)a;
81     *x = (*x+1) & 0xff;
82 
83     return s[(a+b) & 0xff];
84 }
85 
86 
wc_Arc4Process(Arc4 * arc4,byte * out,const byte * in,word32 length)87 int wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length)
88 {
89     int ret = 0;
90     word32 x;
91     word32 y;
92 
93     if (arc4 == NULL || out == NULL || in == NULL) {
94         return BAD_FUNC_ARG;
95     }
96 
97 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \
98         defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V)
99     if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) {
100         return NitroxArc4Process(arc4, out, in, length);
101     }
102 #endif
103 
104     x = arc4->x;
105     y = arc4->y;
106 
107     while(length--)
108         *out++ = *in++ ^ MakeByte(&x, &y, arc4->state);
109 
110     arc4->x = (byte)x;
111     arc4->y = (byte)y;
112 
113     return ret;
114 }
115 
116 /* Initialize Arc4 for use with async device */
wc_Arc4Init(Arc4 * arc4,void * heap,int devId)117 int wc_Arc4Init(Arc4* arc4, void* heap, int devId)
118 {
119     int ret = 0;
120 
121     if (arc4 == NULL)
122         return BAD_FUNC_ARG;
123 
124     arc4->heap = heap;
125 
126 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4)
127     ret = wolfAsync_DevCtxInit(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4,
128         arc4->heap, devId);
129 #else
130     (void)devId;
131 #endif /* WOLFSSL_ASYNC_CRYPT */
132 
133     return ret;
134 }
135 
136 
137 /* Free Arc4 from use with async device */
wc_Arc4Free(Arc4 * arc4)138 void wc_Arc4Free(Arc4* arc4)
139 {
140     if (arc4 == NULL)
141         return;
142 
143 #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4)
144     wolfAsync_DevCtxFree(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4);
145 #endif /* WOLFSSL_ASYNC_CRYPT */
146 }
147 
148 #endif /* NO_RC4 */
149 
150