1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomCrypt is a library that provides various cryptographic
4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithms in a highly modular and flexible manner.
5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express
7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works.
8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**********************************************************************\
12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project* To commemorate the 1996 RSA Data Security Conference, the following  *
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project* code is released into the public domain by its author.  Prost!       *
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*                                                                      *
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project* This cipher uses 16-bit words and little-endian byte ordering.       *
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project* I wonder which processor it was optimized for?                       *
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*                                                                      *
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project* Thanks to CodeView, SoftIce, and D86 for helping bring this code to  *
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project* the public.                                                          *
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project\**********************************************************************/
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include <tomcrypt.h>
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @file rc2.c
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Implementation of RC2
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef RC2
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectconst struct ltc_cipher_descriptor rc2_desc = {
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   "rc2",
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   12, 8, 128, 8, 16,
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &rc2_setup,
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &rc2_ecb_encrypt,
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &rc2_ecb_decrypt,
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &rc2_test,
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &rc2_done,
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &rc2_keysize,
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project};
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* 256-entry permutation table, probably derived somehow from pi */
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic const unsigned char permute[256] = {
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157,
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162,
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         23,154, 89,245,135,179, 79, 19, 97, 69,109,141,  9,129,125, 50,
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130,
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220,
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38,
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        111,191, 14,218, 70,105,  7, 87, 39,242, 29,155,188,148, 67,  3,
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        248, 17,199,246,144,239, 62,231,  6,195,213, 47,200,102, 30,215,
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42,
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        150, 26,210,113, 90, 21, 73,116, 75,159,208, 94,  4, 24,164,236,
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57,
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        153,124, 58,133, 35,184,180,122,252,  2, 54, 91, 37, 85,151, 49,
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         45, 93,250,152,227,138,146,174,  5,223, 41, 16,103,108,186,201,
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        211,  0,230,207,225,158,168, 44, 99, 22,  1, 63, 88,226,137,169,
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46,
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project};
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /**
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    Initialize the RC2 block cipher
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    @param key The symmetric key you wish to pass
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    @param keylen The key length in bytes
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    @param num_rounds The number of rounds desired (0 for default)
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    @param skey The key in as scheduled by this function.
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    @return CRYPT_OK if successful
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   unsigned *xkey = skey->rc2.xkey;
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   unsigned char tmp[128];
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   unsigned T8, TM;
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int i, bits;
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(key  != NULL);
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(skey != NULL);
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (keylen < 8 || keylen > 128) {
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return CRYPT_INVALID_KEYSIZE;
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (num_rounds != 0 && num_rounds != 16) {
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return CRYPT_INVALID_ROUNDS;
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   for (i = 0; i < keylen; i++) {
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       tmp[i] = key[i] & 255;
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Phase 1: Expand input key to 128 bytes */
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (keylen < 128) {
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        for (i = keylen; i < 128; i++) {
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255];
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        }
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Phase 2 - reduce effective key size to "bits" */
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    bits = keylen<<3;
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    T8   = (unsigned)(bits+7)>>3;
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    TM   = (255 >> (unsigned)(7 & -bits));
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    tmp[128 - T8] = permute[tmp[128 - T8] & TM];
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 127 - T8; i >= 0; i--) {
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]];
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Phase 3 - copy to xkey in little-endian order */
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 0; i < 64; i++) {
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        xkey[i] =  (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8);
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    zeromem(tmp, sizeof(tmp));
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**********************************************************************\
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project* Encrypt an 8-byte block of plaintext using the given key.            *
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project\**********************************************************************/
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Encrypts a block of text with RC2
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param pt The input plaintext (8 bytes)
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param ct The output ciphertext (8 bytes)
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param skey The key as scheduled
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int _rc2_ecb_encrypt( const unsigned char *pt,
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            unsigned char *ct,
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            symmetric_key *skey)
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc2_ecb_encrypt( const unsigned char *pt,
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            unsigned char *ct,
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            symmetric_key *skey)
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    unsigned *xkey;
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    unsigned x76, x54, x32, x10, i;
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(pt  != NULL);
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(ct != NULL);
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(skey   != NULL);
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    xkey = skey->rc2.xkey;
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    x76 = ((unsigned)pt[7] << 8) + (unsigned)pt[6];
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    x54 = ((unsigned)pt[5] << 8) + (unsigned)pt[4];
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    x32 = ((unsigned)pt[3] << 8) + (unsigned)pt[2];
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    x10 = ((unsigned)pt[1] << 8) + (unsigned)pt[0];
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 0; i < 16; i++) {
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF;
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x10 = ((x10 << 1) | (x10 >> 15));
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF;
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x32 = ((x32 << 2) | (x32 >> 14));
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF;
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x54 = ((x54 << 3) | (x54 >> 13));
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF;
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x76 = ((x76 << 5) | (x76 >> 11));
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        if (i == 4 || i == 10) {
168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            x10 = (x10 + xkey[x76 & 63]) & 0xFFFF;
169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            x32 = (x32 + xkey[x10 & 63]) & 0xFFFF;
170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            x54 = (x54 + xkey[x32 & 63]) & 0xFFFF;
171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            x76 = (x76 + xkey[x54 & 63]) & 0xFFFF;
172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        }
173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ct[0] = (unsigned char)x10;
176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ct[1] = (unsigned char)(x10 >> 8);
177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ct[2] = (unsigned char)x32;
178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ct[3] = (unsigned char)(x32 >> 8);
179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ct[4] = (unsigned char)x54;
180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ct[5] = (unsigned char)(x54 >> 8);
181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ct[6] = (unsigned char)x76;
182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ct[7] = (unsigned char)(x76 >> 8);
183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc2_ecb_encrypt( const unsigned char *pt,
189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            unsigned char *ct,
190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            symmetric_key *skey)
191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int err = _rc2_ecb_encrypt(pt, ct, skey);
193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 5);
194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return err;
195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**********************************************************************\
199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project* Decrypt an 8-byte block of ciphertext using the given key.           *
200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project\**********************************************************************/
201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Decrypts a block of text with RC2
203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param ct The input ciphertext (8 bytes)
204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param pt The output plaintext (8 bytes)
205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param skey The key as scheduled
206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful
207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int _rc2_ecb_decrypt( const unsigned char *ct,
210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            unsigned char *pt,
211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            symmetric_key *skey)
212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else
213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc2_ecb_decrypt( const unsigned char *ct,
214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            unsigned char *pt,
215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            symmetric_key *skey)
216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    unsigned x76, x54, x32, x10;
219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    unsigned *xkey;
220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int i;
221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(pt  != NULL);
223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(ct != NULL);
224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(skey   != NULL);
225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    xkey = skey->rc2.xkey;
227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    x76 = ((unsigned)ct[7] << 8) + (unsigned)ct[6];
229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    x54 = ((unsigned)ct[5] << 8) + (unsigned)ct[4];
230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    x32 = ((unsigned)ct[3] << 8) + (unsigned)ct[2];
231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    x10 = ((unsigned)ct[1] << 8) + (unsigned)ct[0];
232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 15; i >= 0; i--) {
234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        if (i == 4 || i == 10) {
235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            x76 = (x76 - xkey[x54 & 63]) & 0xFFFF;
236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            x54 = (x54 - xkey[x32 & 63]) & 0xFFFF;
237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            x32 = (x32 - xkey[x10 & 63]) & 0xFFFF;
238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            x10 = (x10 - xkey[x76 & 63]) & 0xFFFF;
239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        }
240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x76 = ((x76 << 11) | (x76 >> 5));
242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF;
243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x54 = ((x54 << 13) | (x54 >> 3));
245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF;
246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x32 = ((x32 << 14) | (x32 >> 2));
248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF;
249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x10 = ((x10 << 15) | (x10 >> 1));
251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF;
252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    pt[0] = (unsigned char)x10;
255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    pt[1] = (unsigned char)(x10 >> 8);
256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    pt[2] = (unsigned char)x32;
257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    pt[3] = (unsigned char)(x32 >> 8);
258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    pt[4] = (unsigned char)x54;
259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    pt[5] = (unsigned char)(x54 >> 8);
260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    pt[6] = (unsigned char)x76;
261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    pt[7] = (unsigned char)(x76 >> 8);
262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc2_ecb_decrypt( const unsigned char *ct,
268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            unsigned char *pt,
269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project                            symmetric_key *skey)
270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int err = _rc2_ecb_decrypt(ct, pt, skey);
272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 4 + sizeof(int));
273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return err;
274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Performs a self-test of the RC2 block cipher
279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc2_test(void)
282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project #ifndef LTC_TEST
284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_NOP;
285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project #else
286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   static const struct {
287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        int keylen;
288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        unsigned char key[16], pt[8], ct[8];
289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   } tests[] = {
290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 8,
292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     { 0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2 }
296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   },
298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 16,
299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f,
300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 },
301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     { 0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6 }
303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  };
305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int x, y, err;
306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    symmetric_key skey;
307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    unsigned char tmp[2][8];
308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        zeromem(tmp, sizeof(tmp));
311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        if ((err = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) {
312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           return err;
313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        }
314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        rc2_ecb_encrypt(tests[x].pt, tmp[0], &skey);
316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        rc2_ecb_decrypt(tmp[0], tmp[1], &skey);
317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        if (XMEMCMP(tmp[0], tests[x].ct, 8) != 0 || XMEMCMP(tmp[1], tests[x].pt, 8) != 0) {
319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           return CRYPT_FAIL_TESTVECTOR;
320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        }
321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (y = 0; y < 8; y++) tmp[0][y] = 0;
324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (y = 0; y < 1000; y++) rc2_ecb_encrypt(tmp[0], tmp[0], &skey);
325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (y = 0; y < 1000; y++) rc2_ecb_decrypt(tmp[0], tmp[0], &skey);
326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   #endif
330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
331f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
332f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** Terminate the context
333f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param skey    The scheduled key
334f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
335f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid rc2_done(symmetric_key *skey)
336f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
337f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
338f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
339f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
340f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Gets suitable key size
341f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param keysize [in/out] The length of the recommended key (in bytes).  This function will store the suitable size back in this variable.
342f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if the input key size is acceptable.
343f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
344f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc2_keysize(int *keysize)
345f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
346f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(keysize != NULL);
347f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (*keysize < 8) {
348f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       return CRYPT_INVALID_KEYSIZE;
349f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   } else if (*keysize > 128) {
350f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       *keysize = 128;
351f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
352f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_OK;
353f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
354f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
355f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
356f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
357f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
358f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
359f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
360f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/ciphers/rc2.c,v $ */
361f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.12 $ */
362f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/11/08 23:01:06 $ */
363