CyaSSL is an SSL library for devices like mbed.

Dependents:   cyassl-client Sync

Committer:
toddouska
Date:
Sat Feb 05 01:09:17 2011 +0000
Revision:
0:5045d2638c29
Beta Version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
toddouska 0:5045d2638c29 1 /* rabbit.c
toddouska 0:5045d2638c29 2 *
toddouska 0:5045d2638c29 3 * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
toddouska 0:5045d2638c29 4 *
toddouska 0:5045d2638c29 5 * This file is part of CyaSSL.
toddouska 0:5045d2638c29 6 *
toddouska 0:5045d2638c29 7 * CyaSSL is free software; you can redistribute it and/or modify
toddouska 0:5045d2638c29 8 * it under the terms of the GNU General Public License as published by
toddouska 0:5045d2638c29 9 * the Free Software Foundation; either version 2 of the License, or
toddouska 0:5045d2638c29 10 * (at your option) any later version.
toddouska 0:5045d2638c29 11 *
toddouska 0:5045d2638c29 12 * CyaSSL is distributed in the hope that it will be useful,
toddouska 0:5045d2638c29 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
toddouska 0:5045d2638c29 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
toddouska 0:5045d2638c29 15 * GNU General Public License for more details.
toddouska 0:5045d2638c29 16 *
toddouska 0:5045d2638c29 17 * You should have received a copy of the GNU General Public License
toddouska 0:5045d2638c29 18 * along with this program; if not, write to the Free Software
toddouska 0:5045d2638c29 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
toddouska 0:5045d2638c29 20 */
toddouska 0:5045d2638c29 21
toddouska 0:5045d2638c29 22
toddouska 0:5045d2638c29 23 #ifndef NO_RABBIT
toddouska 0:5045d2638c29 24
toddouska 0:5045d2638c29 25 #include "rabbit.h"
toddouska 0:5045d2638c29 26 #include "misc.c"
toddouska 0:5045d2638c29 27
toddouska 0:5045d2638c29 28
toddouska 0:5045d2638c29 29 #ifdef BIG_ENDIAN_ORDER
toddouska 0:5045d2638c29 30 #define LITTLE32(x) ByteReverseWord32(x)
toddouska 0:5045d2638c29 31 #else
toddouska 0:5045d2638c29 32 #define LITTLE32(x) (x)
toddouska 0:5045d2638c29 33 #endif
toddouska 0:5045d2638c29 34
toddouska 0:5045d2638c29 35 #define U32V(x) (word32)(x)
toddouska 0:5045d2638c29 36
toddouska 0:5045d2638c29 37
toddouska 0:5045d2638c29 38 /* Square a 32-bit unsigned integer to obtain the 64-bit result and return */
toddouska 0:5045d2638c29 39 /* the upper 32 bits XOR the lower 32 bits */
toddouska 0:5045d2638c29 40 static word32 RABBIT_g_func(word32 x)
toddouska 0:5045d2638c29 41 {
toddouska 0:5045d2638c29 42 /* Temporary variables */
toddouska 0:5045d2638c29 43 word32 a, b, h, l;
toddouska 0:5045d2638c29 44
toddouska 0:5045d2638c29 45 /* Construct high and low argument for squaring */
toddouska 0:5045d2638c29 46 a = x&0xFFFF;
toddouska 0:5045d2638c29 47 b = x>>16;
toddouska 0:5045d2638c29 48
toddouska 0:5045d2638c29 49 /* Calculate high and low result of squaring */
toddouska 0:5045d2638c29 50 h = (((U32V(a*a)>>17) + U32V(a*b))>>15) + b*b;
toddouska 0:5045d2638c29 51 l = x*x;
toddouska 0:5045d2638c29 52
toddouska 0:5045d2638c29 53 /* Return high XOR low */
toddouska 0:5045d2638c29 54 return U32V(h^l);
toddouska 0:5045d2638c29 55 }
toddouska 0:5045d2638c29 56
toddouska 0:5045d2638c29 57
toddouska 0:5045d2638c29 58 /* Calculate the next internal state */
toddouska 0:5045d2638c29 59 static void RABBIT_next_state(RabbitCtx* ctx)
toddouska 0:5045d2638c29 60 {
toddouska 0:5045d2638c29 61 /* Temporary variables */
toddouska 0:5045d2638c29 62 word32 g[8], c_old[8], i;
toddouska 0:5045d2638c29 63
toddouska 0:5045d2638c29 64 /* Save old counter values */
toddouska 0:5045d2638c29 65 for (i=0; i<8; i++)
toddouska 0:5045d2638c29 66 c_old[i] = ctx->c[i];
toddouska 0:5045d2638c29 67
toddouska 0:5045d2638c29 68 /* Calculate new counter values */
toddouska 0:5045d2638c29 69 ctx->c[0] = U32V(ctx->c[0] + 0x4D34D34D + ctx->carry);
toddouska 0:5045d2638c29 70 ctx->c[1] = U32V(ctx->c[1] + 0xD34D34D3 + (ctx->c[0] < c_old[0]));
toddouska 0:5045d2638c29 71 ctx->c[2] = U32V(ctx->c[2] + 0x34D34D34 + (ctx->c[1] < c_old[1]));
toddouska 0:5045d2638c29 72 ctx->c[3] = U32V(ctx->c[3] + 0x4D34D34D + (ctx->c[2] < c_old[2]));
toddouska 0:5045d2638c29 73 ctx->c[4] = U32V(ctx->c[4] + 0xD34D34D3 + (ctx->c[3] < c_old[3]));
toddouska 0:5045d2638c29 74 ctx->c[5] = U32V(ctx->c[5] + 0x34D34D34 + (ctx->c[4] < c_old[4]));
toddouska 0:5045d2638c29 75 ctx->c[6] = U32V(ctx->c[6] + 0x4D34D34D + (ctx->c[5] < c_old[5]));
toddouska 0:5045d2638c29 76 ctx->c[7] = U32V(ctx->c[7] + 0xD34D34D3 + (ctx->c[6] < c_old[6]));
toddouska 0:5045d2638c29 77 ctx->carry = (ctx->c[7] < c_old[7]);
toddouska 0:5045d2638c29 78
toddouska 0:5045d2638c29 79 /* Calculate the g-values */
toddouska 0:5045d2638c29 80 for (i=0;i<8;i++)
toddouska 0:5045d2638c29 81 g[i] = RABBIT_g_func(U32V(ctx->x[i] + ctx->c[i]));
toddouska 0:5045d2638c29 82
toddouska 0:5045d2638c29 83 /* Calculate new state values */
toddouska 0:5045d2638c29 84 ctx->x[0] = U32V(g[0] + rotlFixed(g[7],16) + rotlFixed(g[6], 16));
toddouska 0:5045d2638c29 85 ctx->x[1] = U32V(g[1] + rotlFixed(g[0], 8) + g[7]);
toddouska 0:5045d2638c29 86 ctx->x[2] = U32V(g[2] + rotlFixed(g[1],16) + rotlFixed(g[0], 16));
toddouska 0:5045d2638c29 87 ctx->x[3] = U32V(g[3] + rotlFixed(g[2], 8) + g[1]);
toddouska 0:5045d2638c29 88 ctx->x[4] = U32V(g[4] + rotlFixed(g[3],16) + rotlFixed(g[2], 16));
toddouska 0:5045d2638c29 89 ctx->x[5] = U32V(g[5] + rotlFixed(g[4], 8) + g[3]);
toddouska 0:5045d2638c29 90 ctx->x[6] = U32V(g[6] + rotlFixed(g[5],16) + rotlFixed(g[4], 16));
toddouska 0:5045d2638c29 91 ctx->x[7] = U32V(g[7] + rotlFixed(g[6], 8) + g[5]);
toddouska 0:5045d2638c29 92 }
toddouska 0:5045d2638c29 93
toddouska 0:5045d2638c29 94
toddouska 0:5045d2638c29 95 /* IV setup */
toddouska 0:5045d2638c29 96 static void RabbitSetIV(Rabbit* ctx, const byte* iv)
toddouska 0:5045d2638c29 97 {
toddouska 0:5045d2638c29 98 /* Temporary variables */
toddouska 0:5045d2638c29 99 word32 i0, i1, i2, i3, i;
toddouska 0:5045d2638c29 100
toddouska 0:5045d2638c29 101 /* Generate four subvectors */
toddouska 0:5045d2638c29 102 i0 = LITTLE32(*(word32*)(iv+0));
toddouska 0:5045d2638c29 103 i2 = LITTLE32(*(word32*)(iv+4));
toddouska 0:5045d2638c29 104 i1 = (i0>>16) | (i2&0xFFFF0000);
toddouska 0:5045d2638c29 105 i3 = (i2<<16) | (i0&0x0000FFFF);
toddouska 0:5045d2638c29 106
toddouska 0:5045d2638c29 107 /* Modify counter values */
toddouska 0:5045d2638c29 108 ctx->workCtx.c[0] = ctx->masterCtx.c[0] ^ i0;
toddouska 0:5045d2638c29 109 ctx->workCtx.c[1] = ctx->masterCtx.c[1] ^ i1;
toddouska 0:5045d2638c29 110 ctx->workCtx.c[2] = ctx->masterCtx.c[2] ^ i2;
toddouska 0:5045d2638c29 111 ctx->workCtx.c[3] = ctx->masterCtx.c[3] ^ i3;
toddouska 0:5045d2638c29 112 ctx->workCtx.c[4] = ctx->masterCtx.c[4] ^ i0;
toddouska 0:5045d2638c29 113 ctx->workCtx.c[5] = ctx->masterCtx.c[5] ^ i1;
toddouska 0:5045d2638c29 114 ctx->workCtx.c[6] = ctx->masterCtx.c[6] ^ i2;
toddouska 0:5045d2638c29 115 ctx->workCtx.c[7] = ctx->masterCtx.c[7] ^ i3;
toddouska 0:5045d2638c29 116
toddouska 0:5045d2638c29 117 /* Copy state variables */
toddouska 0:5045d2638c29 118 for (i=0; i<8; i++)
toddouska 0:5045d2638c29 119 ctx->workCtx.x[i] = ctx->masterCtx.x[i];
toddouska 0:5045d2638c29 120 ctx->workCtx.carry = ctx->masterCtx.carry;
toddouska 0:5045d2638c29 121
toddouska 0:5045d2638c29 122 /* Iterate the system four times */
toddouska 0:5045d2638c29 123 for (i=0; i<4; i++)
toddouska 0:5045d2638c29 124 RABBIT_next_state(&(ctx->workCtx));
toddouska 0:5045d2638c29 125 }
toddouska 0:5045d2638c29 126
toddouska 0:5045d2638c29 127
toddouska 0:5045d2638c29 128 /* Key setup */
toddouska 0:5045d2638c29 129 void RabbitSetKey(Rabbit* ctx, const byte* key, const byte* iv)
toddouska 0:5045d2638c29 130 {
toddouska 0:5045d2638c29 131 /* Temporary variables */
toddouska 0:5045d2638c29 132 word32 k0, k1, k2, k3, i;
toddouska 0:5045d2638c29 133
toddouska 0:5045d2638c29 134 /* Generate four subkeys */
toddouska 0:5045d2638c29 135 k0 = LITTLE32(*(word32*)(key+ 0));
toddouska 0:5045d2638c29 136 k1 = LITTLE32(*(word32*)(key+ 4));
toddouska 0:5045d2638c29 137 k2 = LITTLE32(*(word32*)(key+ 8));
toddouska 0:5045d2638c29 138 k3 = LITTLE32(*(word32*)(key+12));
toddouska 0:5045d2638c29 139
toddouska 0:5045d2638c29 140 /* Generate initial state variables */
toddouska 0:5045d2638c29 141 ctx->masterCtx.x[0] = k0;
toddouska 0:5045d2638c29 142 ctx->masterCtx.x[2] = k1;
toddouska 0:5045d2638c29 143 ctx->masterCtx.x[4] = k2;
toddouska 0:5045d2638c29 144 ctx->masterCtx.x[6] = k3;
toddouska 0:5045d2638c29 145 ctx->masterCtx.x[1] = U32V(k3<<16) | (k2>>16);
toddouska 0:5045d2638c29 146 ctx->masterCtx.x[3] = U32V(k0<<16) | (k3>>16);
toddouska 0:5045d2638c29 147 ctx->masterCtx.x[5] = U32V(k1<<16) | (k0>>16);
toddouska 0:5045d2638c29 148 ctx->masterCtx.x[7] = U32V(k2<<16) | (k1>>16);
toddouska 0:5045d2638c29 149
toddouska 0:5045d2638c29 150 /* Generate initial counter values */
toddouska 0:5045d2638c29 151 ctx->masterCtx.c[0] = rotlFixed(k2, 16);
toddouska 0:5045d2638c29 152 ctx->masterCtx.c[2] = rotlFixed(k3, 16);
toddouska 0:5045d2638c29 153 ctx->masterCtx.c[4] = rotlFixed(k0, 16);
toddouska 0:5045d2638c29 154 ctx->masterCtx.c[6] = rotlFixed(k1, 16);
toddouska 0:5045d2638c29 155 ctx->masterCtx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF);
toddouska 0:5045d2638c29 156 ctx->masterCtx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF);
toddouska 0:5045d2638c29 157 ctx->masterCtx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF);
toddouska 0:5045d2638c29 158 ctx->masterCtx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF);
toddouska 0:5045d2638c29 159
toddouska 0:5045d2638c29 160 /* Clear carry bit */
toddouska 0:5045d2638c29 161 ctx->masterCtx.carry = 0;
toddouska 0:5045d2638c29 162
toddouska 0:5045d2638c29 163 /* Iterate the system four times */
toddouska 0:5045d2638c29 164 for (i=0; i<4; i++)
toddouska 0:5045d2638c29 165 RABBIT_next_state(&(ctx->masterCtx));
toddouska 0:5045d2638c29 166
toddouska 0:5045d2638c29 167 /* Modify the counters */
toddouska 0:5045d2638c29 168 for (i=0; i<8; i++)
toddouska 0:5045d2638c29 169 ctx->masterCtx.c[i] ^= ctx->masterCtx.x[(i+4)&0x7];
toddouska 0:5045d2638c29 170
toddouska 0:5045d2638c29 171 /* Copy master instance to work instance */
toddouska 0:5045d2638c29 172 for (i=0; i<8; i++) {
toddouska 0:5045d2638c29 173 ctx->workCtx.x[i] = ctx->masterCtx.x[i];
toddouska 0:5045d2638c29 174 ctx->workCtx.c[i] = ctx->masterCtx.c[i];
toddouska 0:5045d2638c29 175 }
toddouska 0:5045d2638c29 176 ctx->workCtx.carry = ctx->masterCtx.carry;
toddouska 0:5045d2638c29 177
toddouska 0:5045d2638c29 178 if (iv) RabbitSetIV(ctx, iv);
toddouska 0:5045d2638c29 179 }
toddouska 0:5045d2638c29 180
toddouska 0:5045d2638c29 181
toddouska 0:5045d2638c29 182 /* Encrypt/decrypt a message of any size */
toddouska 0:5045d2638c29 183 void RabbitProcess(Rabbit* ctx, byte* output, const byte* input, word32 msglen)
toddouska 0:5045d2638c29 184 {
toddouska 0:5045d2638c29 185
toddouska 0:5045d2638c29 186 /* Encrypt/decrypt all full blocks */
toddouska 0:5045d2638c29 187 while (msglen >= 16) {
toddouska 0:5045d2638c29 188 /* Iterate the system */
toddouska 0:5045d2638c29 189 RABBIT_next_state(&(ctx->workCtx));
toddouska 0:5045d2638c29 190
toddouska 0:5045d2638c29 191 /* Encrypt/decrypt 16 bytes of data */
toddouska 0:5045d2638c29 192 *(word32*)(output+ 0) = *(word32*)(input+ 0) ^
toddouska 0:5045d2638c29 193 LITTLE32(ctx->workCtx.x[0] ^ (ctx->workCtx.x[5]>>16) ^
toddouska 0:5045d2638c29 194 U32V(ctx->workCtx.x[3]<<16));
toddouska 0:5045d2638c29 195 *(word32*)(output+ 4) = *(word32*)(input+ 4) ^
toddouska 0:5045d2638c29 196 LITTLE32(ctx->workCtx.x[2] ^ (ctx->workCtx.x[7]>>16) ^
toddouska 0:5045d2638c29 197 U32V(ctx->workCtx.x[5]<<16));
toddouska 0:5045d2638c29 198 *(word32*)(output+ 8) = *(word32*)(input+ 8) ^
toddouska 0:5045d2638c29 199 LITTLE32(ctx->workCtx.x[4] ^ (ctx->workCtx.x[1]>>16) ^
toddouska 0:5045d2638c29 200 U32V(ctx->workCtx.x[7]<<16));
toddouska 0:5045d2638c29 201 *(word32*)(output+12) = *(word32*)(input+12) ^
toddouska 0:5045d2638c29 202 LITTLE32(ctx->workCtx.x[6] ^ (ctx->workCtx.x[3]>>16) ^
toddouska 0:5045d2638c29 203 U32V(ctx->workCtx.x[1]<<16));
toddouska 0:5045d2638c29 204
toddouska 0:5045d2638c29 205 /* Increment pointers and decrement length */
toddouska 0:5045d2638c29 206 input += 16;
toddouska 0:5045d2638c29 207 output += 16;
toddouska 0:5045d2638c29 208 msglen -= 16;
toddouska 0:5045d2638c29 209 }
toddouska 0:5045d2638c29 210
toddouska 0:5045d2638c29 211 /* Encrypt/decrypt remaining data */
toddouska 0:5045d2638c29 212 if (msglen) {
toddouska 0:5045d2638c29 213
toddouska 0:5045d2638c29 214 word32 i;
toddouska 0:5045d2638c29 215 word32 tmp[4];
toddouska 0:5045d2638c29 216 byte* buffer = (byte*)tmp;
toddouska 0:5045d2638c29 217
toddouska 0:5045d2638c29 218 /* Iterate the system */
toddouska 0:5045d2638c29 219 RABBIT_next_state(&(ctx->workCtx));
toddouska 0:5045d2638c29 220
toddouska 0:5045d2638c29 221 /* Generate 16 bytes of pseudo-random data */
toddouska 0:5045d2638c29 222 tmp[0] = LITTLE32(ctx->workCtx.x[0] ^
toddouska 0:5045d2638c29 223 (ctx->workCtx.x[5]>>16) ^ U32V(ctx->workCtx.x[3]<<16));
toddouska 0:5045d2638c29 224 tmp[1] = LITTLE32(ctx->workCtx.x[2] ^
toddouska 0:5045d2638c29 225 (ctx->workCtx.x[7]>>16) ^ U32V(ctx->workCtx.x[5]<<16));
toddouska 0:5045d2638c29 226 tmp[2] = LITTLE32(ctx->workCtx.x[4] ^
toddouska 0:5045d2638c29 227 (ctx->workCtx.x[1]>>16) ^ U32V(ctx->workCtx.x[7]<<16));
toddouska 0:5045d2638c29 228 tmp[3] = LITTLE32(ctx->workCtx.x[6] ^
toddouska 0:5045d2638c29 229 (ctx->workCtx.x[3]>>16) ^ U32V(ctx->workCtx.x[1]<<16));
toddouska 0:5045d2638c29 230
toddouska 0:5045d2638c29 231 /* Encrypt/decrypt the data */
toddouska 0:5045d2638c29 232 for (i=0; i<msglen; i++)
toddouska 0:5045d2638c29 233 output[i] = input[i] ^ buffer[i];
toddouska 0:5045d2638c29 234 }
toddouska 0:5045d2638c29 235 }
toddouska 0:5045d2638c29 236
toddouska 0:5045d2638c29 237
toddouska 0:5045d2638c29 238
toddouska 0:5045d2638c29 239 #endif /* NO_RABBIT */