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 #if defined(MBEDTLS_SELF_TEST)
35 #if defined(MBEDTLS_PLATFORM_C)
36 #include "mbedtls/platform.h"
37 #else
38 #include <stdio.h>
39 #define mbedtls_printf printf
40 #endif /* MBEDTLS_PLATFORM_C */
41 #endif /* MBEDTLS_SELF_TEST */
42 
43 #if !defined(MBEDTLS_ARC4_ALT)
44 
mbedtls_arc4_init(mbedtls_arc4_context * ctx)45 void mbedtls_arc4_init( mbedtls_arc4_context *ctx )
46 {
47     memset( ctx, 0, sizeof( mbedtls_arc4_context ) );
48 }
49 
mbedtls_arc4_free(mbedtls_arc4_context * ctx)50 void mbedtls_arc4_free( mbedtls_arc4_context *ctx )
51 {
52     if( ctx == NULL )
53         return;
54 
55     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) );
56 }
57 
58 /*
59  * ARC4 key schedule
60  */
mbedtls_arc4_setup(mbedtls_arc4_context * ctx,const unsigned char * key,unsigned int keylen)61 void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key,
62                  unsigned int keylen )
63 {
64     int i, j, a;
65     unsigned int k;
66     unsigned char *m;
67 
68     ctx->x = 0;
69     ctx->y = 0;
70     m = ctx->m;
71 
72     for( i = 0; i < 256; i++ )
73         m[i] = (unsigned char) i;
74 
75     j = k = 0;
76 
77     for( i = 0; i < 256; i++, k++ )
78     {
79         if( k >= keylen ) k = 0;
80 
81         a = m[i];
82         j = ( j + a + key[k] ) & 0xFF;
83         m[i] = m[j];
84         m[j] = (unsigned char) a;
85     }
86 }
87 
88 /*
89  * ARC4 cipher function
90  */
mbedtls_arc4_crypt(mbedtls_arc4_context * ctx,size_t length,const unsigned char * input,unsigned char * output)91 int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input,
92                 unsigned char *output )
93 {
94     int x, y, a, b;
95     size_t i;
96     unsigned char *m;
97 
98     x = ctx->x;
99     y = ctx->y;
100     m = ctx->m;
101 
102     for( i = 0; i < length; i++ )
103     {
104         x = ( x + 1 ) & 0xFF; a = m[x];
105         y = ( y + a ) & 0xFF; b = m[y];
106 
107         m[x] = (unsigned char) b;
108         m[y] = (unsigned char) a;
109 
110         output[i] = (unsigned char)
111             ( input[i] ^ m[(unsigned char)( a + b )] );
112     }
113 
114     ctx->x = x;
115     ctx->y = y;
116 
117     return( 0 );
118 }
119 
120 #endif /* !MBEDTLS_ARC4_ALT */
121 
122 #if defined(MBEDTLS_SELF_TEST)
123 /*
124  * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
125  *
126  * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
127  */
128 static const unsigned char arc4_test_key[3][8] =
129 {
130     { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
131     { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
132     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
133 };
134 
135 static const unsigned char arc4_test_pt[3][8] =
136 {
137     { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
138     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
139     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
140 };
141 
142 static const unsigned char arc4_test_ct[3][8] =
143 {
144     { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
145     { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
146     { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
147 };
148 
149 /*
150  * Checkup routine
151  */
mbedtls_arc4_self_test(int verbose)152 int mbedtls_arc4_self_test( int verbose )
153 {
154     int i, ret = 0;
155     unsigned char ibuf[8];
156     unsigned char obuf[8];
157     mbedtls_arc4_context ctx;
158 
159     mbedtls_arc4_init( &ctx );
160 
161     for( i = 0; i < 3; i++ )
162     {
163         if( verbose != 0 )
164             mbedtls_printf( "  ARC4 test #%d: ", i + 1 );
165 
166         memcpy( ibuf, arc4_test_pt[i], 8 );
167 
168         mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 );
169         mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf );
170 
171         if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
172         {
173             if( verbose != 0 )
174                 mbedtls_printf( "failed\n" );
175 
176             ret = 1;
177             goto exit;
178         }
179 
180         if( verbose != 0 )
181             mbedtls_printf( "passed\n" );
182     }
183 
184     if( verbose != 0 )
185         mbedtls_printf( "\n" );
186 
187 exit:
188     mbedtls_arc4_free( &ctx );
189 
190     return( ret );
191 }
192 
193 #endif /* MBEDTLS_SELF_TEST */
194 
195 #endif /* MBEDTLS_ARC4_C */
196