1/*
2 * An implementation of the ARCFOUR algorithm
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19/*
20 * The ARCFOUR algorithm was publicly disclosed on 94/09.
21 *
22 * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
23 */
24
25#include "common.h"
26
27#if defined(MBEDTLS_ARC4_C)
28
29#include "mbedtls/arc4.h"
30#include "mbedtls/platform_util.h"
31
32#include <string.h>
33
34#include "mbedtls/platform.h"
35
36#if !defined(MBEDTLS_ARC4_ALT)
37
38void mbedtls_arc4_init(mbedtls_arc4_context *ctx)
39{
40 memset(ctx, 0, sizeof(mbedtls_arc4_context));
41}
42
43void mbedtls_arc4_free(mbedtls_arc4_context *ctx)
44{
45 if (ctx == NULL) {
46 return;
47 }
48
49 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_arc4_context));
50}
51
52/*
53 * ARC4 key schedule
54 */
55void mbedtls_arc4_setup(mbedtls_arc4_context *ctx, const unsigned char *key,
56 unsigned int keylen)
57{
58 int i, j, a;
59 unsigned int k;
60 unsigned char *m;
61
62 ctx->x = 0;
63 ctx->y = 0;
64 m = ctx->m;
65
66 for (i = 0; i < 256; i++) {
67 m[i] = (unsigned char) i;
68 }
69
70 j = k = 0;
71
72 for (i = 0; i < 256; i++, k++) {
73 if (k >= keylen) {
74 k = 0;
75 }
76
77 a = m[i];
78 j = (j + a + key[k]) & 0xFF;
79 m[i] = m[j];
80 m[j] = (unsigned char) a;
81 }
82}
83
84/*
85 * ARC4 cipher function
86 */
87int mbedtls_arc4_crypt(mbedtls_arc4_context *ctx, size_t length, const unsigned char *input,
88 unsigned char *output)
89{
90 int x, y, a, b;
91 size_t i;
92 unsigned char *m;
93
94 x = ctx->x;
95 y = ctx->y;
96 m = ctx->m;
97
98 for (i = 0; i < length; i++) {
99 x = (x + 1) & 0xFF; a = m[x];
100 y = (y + a) & 0xFF; b = m[y];
101
102 m[x] = (unsigned char) b;
103 m[y] = (unsigned char) a;
104
105 output[i] = (unsigned char)
106 (input[i] ^ m[(unsigned char) (a + b)]);
107 }
108
109 ctx->x = x;
110 ctx->y = y;
111
112 return 0;
113}
114
115#endif /* !MBEDTLS_ARC4_ALT */
116
117#if defined(MBEDTLS_SELF_TEST)
118/*
119 * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
120 *
121 * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
122 */
123static const unsigned char arc4_test_key[3][8] =
124{
125 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
126 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
127 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
128};
129
130static const unsigned char arc4_test_pt[3][8] =
131{
132 { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
133 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
134 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
135};
136
137static const unsigned char arc4_test_ct[3][8] =
138{
139 { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
140 { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
141 { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
142};
143
144/*
145 * Checkup routine
146 */
147int mbedtls_arc4_self_test(int verbose)
148{
149 int i, ret = 0;
150 unsigned char ibuf[8];
151 unsigned char obuf[8];
152 mbedtls_arc4_context ctx;
153
154 mbedtls_arc4_init(&ctx);
155
156 for (i = 0; i < 3; i++) {
157 if (verbose != 0) {
158 mbedtls_printf(" ARC4 test #%d: ", i + 1);
159 }
160
161 memcpy(ibuf, arc4_test_pt[i], 8);
162
163 mbedtls_arc4_setup(&ctx, arc4_test_key[i], 8);
164 mbedtls_arc4_crypt(&ctx, 8, ibuf, obuf);
165
166 if (memcmp(obuf, arc4_test_ct[i], 8) != 0) {
167 if (verbose != 0) {
168 mbedtls_printf("failed\n");
169 }
170
171 ret = 1;
172 goto exit;
173 }
174
175 if (verbose != 0) {
176 mbedtls_printf("passed\n");
177 }
178 }
179
180 if (verbose != 0) {
181 mbedtls_printf("\n");
182 }
183
184exit:
185 mbedtls_arc4_free(&ctx);
186
187 return ret;
188}
189
190#endif /* MBEDTLS_SELF_TEST */
191
192#endif /* MBEDTLS_ARC4_C */
193