arc4.c 4.76 KB
Newer Older
1 2 3
/*
 *  An implementation of the ARCFOUR algorithm
 *
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
4
 *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakker's avatar
Paul Bakker committed
5
 *
6
 *  This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker's avatar
Paul Bakker committed
7
 *
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
/*
 *  The ARCFOUR algorithm was publicly disclosed on 94/09.
 *
 *  http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
 */

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
28
#if !defined(MBEDTLS_CONFIG_FILE)
29
#include "mbedtls/config.h"
30
#else
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
31
#include MBEDTLS_CONFIG_FILE
32
#endif
33

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
34
#if defined(MBEDTLS_ARC4_C)
35

36
#include "mbedtls/arc4.h"
37

38 39
#include <string.h>

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
40 41
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
42
#include "mbedtls/platform.h"
43
#else
44
#include <stdio.h>
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
45 46 47
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
48

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
49
#if !defined(MBEDTLS_ARC4_ALT)
50

51
/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
52
static void mbedtls_zeroize( void *v, size_t n ) {
53 54 55
    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
56
void mbedtls_arc4_init( mbedtls_arc4_context *ctx )
57
{
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
58
    memset( ctx, 0, sizeof( mbedtls_arc4_context ) );
59 60
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
61
void mbedtls_arc4_free( mbedtls_arc4_context *ctx )
62 63 64 65
{
    if( ctx == NULL )
        return;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
66
    mbedtls_zeroize( ctx, sizeof( mbedtls_arc4_context ) );
67 68
}

69 70 71
/*
 * ARC4 key schedule
 */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
72
void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key,
73
                 unsigned int keylen )
74
{
75 76
    int i, j, a;
    unsigned int k;
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
    unsigned char *m;

    ctx->x = 0;
    ctx->y = 0;
    m = ctx->m;

    for( i = 0; i < 256; i++ )
        m[i] = (unsigned char) i;

    j = k = 0;

    for( i = 0; i < 256; i++, k++ )
    {
        if( k >= keylen ) k = 0;

        a = m[i];
        j = ( j + a + key[k] ) & 0xFF;
        m[i] = m[j];
        m[j] = (unsigned char) a;
    }
}

/*
 * ARC4 cipher function
 */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
102
int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input,
103
                unsigned char *output )
104
{
105 106
    int x, y, a, b;
    size_t i;
107 108 109 110 111 112
    unsigned char *m;

    x = ctx->x;
    y = ctx->y;
    m = ctx->m;

113
    for( i = 0; i < length; i++ )
114 115 116 117 118 119 120
    {
        x = ( x + 1 ) & 0xFF; a = m[x];
        y = ( y + a ) & 0xFF; b = m[y];

        m[x] = (unsigned char) b;
        m[y] = (unsigned char) a;

121 122
        output[i] = (unsigned char)
            ( input[i] ^ m[(unsigned char)( a + b )] );
123 124 125 126
    }

    ctx->x = x;
    ctx->y = y;
127 128

    return( 0 );
129 130
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
131
#endif /* !MBEDTLS_ARC4_ALT */
132

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
133
#if defined(MBEDTLS_SELF_TEST)
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
/*
 * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994:
 *
 * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
 */
static const unsigned char arc4_test_key[3][8] =
{
    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
};

static const unsigned char arc4_test_pt[3][8] =
{
    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
};

static const unsigned char arc4_test_ct[3][8] =
{
    { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
    { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
    { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
};

/*
 * Checkup routine
 */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
163
int mbedtls_arc4_self_test( int verbose )
164
{
165
    int i, ret = 0;
166 167
    unsigned char ibuf[8];
    unsigned char obuf[8];
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
168
    mbedtls_arc4_context ctx;
169

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
170
    mbedtls_arc4_init( &ctx );
171

172 173 174
    for( i = 0; i < 3; i++ )
    {
        if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
175
            mbedtls_printf( "  ARC4 test #%d: ", i + 1 );
176

177
        memcpy( ibuf, arc4_test_pt[i], 8 );
178

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
179 180
        mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 );
        mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf );
181

182
        if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
183 184
        {
            if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
185
                mbedtls_printf( "failed\n" );
186

187 188
            ret = 1;
            goto exit;
189 190 191
        }

        if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
192
            mbedtls_printf( "passed\n" );
193 194 195
    }

    if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
196
        mbedtls_printf( "\n" );
197

198
exit:
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
199
    mbedtls_arc4_free( &ctx );
200 201

    return( ret );
202 203
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
204
#endif /* MBEDTLS_SELF_TEST */
205

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
206
#endif /* MBEDTLS_ARC4_C */