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/**
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @file rc5.c
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   RC5 code by Tom St Denis
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tomcrypt.h"
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef RC5
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectconst struct ltc_cipher_descriptor rc5_desc =
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    "rc5",
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    2,
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    8, 128, 8, 12,
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &rc5_setup,
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &rc5_ecb_encrypt,
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &rc5_ecb_decrypt,
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &rc5_test,
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &rc5_done,
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &rc5_keysize,
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project};
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic const ulong32 stab[50] = {
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL,
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL,
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL,
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL,
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL,
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL, 0xe96a3d2fUL, 0x87a1b6e8UL, 0x25d930a1UL, 0xc410aa5aUL,
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project0x62482413UL, 0x007f9dccUL
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project};
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /**
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    Initialize the RC5 block cipher
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    @param key The symmetric key you wish to pass
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    @param keylen The key length in bytes
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    @param num_rounds The number of rounds desired (0 for default)
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    @param skey The key in as scheduled by this function.
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    @return CRYPT_OK if successful
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int _rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ulong32 L[64], *S, A, B, i, j, v, s, t, l;
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(skey != NULL);
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(key  != NULL);
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* test parameters */
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (num_rounds == 0) {
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       num_rounds = rc5_desc.default_rounds;
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (num_rounds < 12 || num_rounds > 24) {
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       return CRYPT_INVALID_ROUNDS;
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* key must be between 64 and 1024 bits */
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (keylen < 8 || keylen > 128) {
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       return CRYPT_INVALID_KEYSIZE;
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    skey->rc5.rounds = num_rounds;
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    S = skey->rc5.K;
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* copy the key into the L array */
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (A = i = j = 0; i < (ulong32)keylen; ) {
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        A = (A << 8) | ((ulong32)(key[i++] & 255));
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        if ((i & 3) == 0) {
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           L[j++] = BSWAP(A);
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           A = 0;
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        }
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if ((keylen & 3) != 0) {
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       A <<= (ulong32)((8 * (4 - (keylen&3))));
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       L[j++] = BSWAP(A);
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* setup the S array */
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    t = (ulong32)(2 * (num_rounds + 1));
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    XMEMCPY(S, stab, t * sizeof(*S));
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* mix buffer */
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    s = 3 * MAX(t, j);
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    l = j;
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (A = B = i = j = v = 0; v < s; v++) {
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        A = S[i] = ROLc(S[i] + A + B, 3);
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        B = L[j] = ROL(L[j] + A + B, (A+B));
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        if (++i == t) { i = 0; }
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        if (++j == l) { j = 0; }
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int x;
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   x = _rc5_setup(key, keylen, num_rounds, skey);
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   burn_stack(sizeof(ulong32) * 122 + sizeof(int));
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return x;
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Encrypts a block of text with RC5
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param pt The input plaintext (8 bytes)
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param ct The output ciphertext (8 bytes)
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param skey The key as scheduled
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int _rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   ulong32 A, B, *K;
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int r;
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(skey != NULL);
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(pt   != NULL);
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(ct   != NULL);
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LOAD32L(A, &pt[0]);
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LOAD32L(B, &pt[4]);
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   A += skey->rc5.K[0];
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   B += skey->rc5.K[1];
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   K  = skey->rc5.K + 2;
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if ((skey->rc5.rounds & 1) == 0) {
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (r = 0; r < skey->rc5.rounds; r += 2) {
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          A = ROL(A ^ B, B) + K[0];
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          B = ROL(B ^ A, A) + K[1];
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          A = ROL(A ^ B, B) + K[2];
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          B = ROL(B ^ A, A) + K[3];
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          K += 4;
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   } else {
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (r = 0; r < skey->rc5.rounds; r++) {
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          A = ROL(A ^ B, B) + K[0];
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          B = ROL(B ^ A, A) + K[1];
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          K += 2;
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   STORE32L(A, &ct[0]);
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   STORE32L(B, &ct[4]);
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_OK;
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int err = _rc5_ecb_encrypt(pt, ct, skey);
171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   burn_stack(sizeof(ulong32) * 2 + sizeof(int));
172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return err;
173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Decrypts a block of text with RC5
178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param ct The input ciphertext (8 bytes)
179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param pt The output plaintext (8 bytes)
180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @param skey The key as scheduled
181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful
182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int _rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else
186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   ulong32 A, B, *K;
190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int r;
191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(skey != NULL);
192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(pt   != NULL);
193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(ct   != NULL);
194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LOAD32L(A, &ct[0]);
196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LOAD32L(B, &ct[4]);
197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   K = skey->rc5.K + (skey->rc5.rounds << 1);
198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if ((skey->rc5.rounds & 1) == 0) {
200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       K -= 2;
201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       for (r = skey->rc5.rounds - 1; r >= 0; r -= 2) {
202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          B = ROR(B - K[3], A) ^ A;
203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          A = ROR(A - K[2], B) ^ B;
204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          B = ROR(B - K[1], A) ^ A;
205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          A = ROR(A - K[0], B) ^ B;
206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          K -= 4;
207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        }
208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   } else {
209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (r = skey->rc5.rounds - 1; r >= 0; r--) {
210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          B = ROR(B - K[1], A) ^ A;
211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          A = ROR(A - K[0], B) ^ B;
212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          K -= 2;
213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   A -= skey->rc5.K[0];
216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   B -= skey->rc5.K[1];
217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   STORE32L(A, &pt[0]);
218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   STORE32L(B, &pt[4]);
219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_OK;
221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int err = _rc5_ecb_decrypt(ct, pt, skey);
227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   burn_stack(sizeof(ulong32) * 2 + sizeof(int));
228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return err;
229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Performs a self-test of the RC5 block cipher
234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc5_test(void)
237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project #ifndef LTC_TEST
239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_NOP;
240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project #else
241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   static const struct {
242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       unsigned char key[16], pt[8], ct[8];
243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   } tests[] = {
244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   {
245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       { 0x91, 0x5f, 0x46, 0x19, 0xbe, 0x41, 0xb2, 0x51,
246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         0x63, 0x55, 0xa5, 0x01, 0x10, 0xa9, 0xce, 0x91 },
247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       { 0x21, 0xa5, 0xdb, 0xee, 0x15, 0x4b, 0x8f, 0x6d },
248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       { 0xf7, 0xc0, 0x13, 0xac, 0x5b, 0x2b, 0x89, 0x52 }
249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   },
250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   {
251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       { 0x78, 0x33, 0x48, 0xe7, 0x5a, 0xeb, 0x0f, 0x2f,
252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         0xd7, 0xb1, 0x69, 0xbb, 0x8d, 0xc1, 0x67, 0x87 },
253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       { 0xF7, 0xC0, 0x13, 0xAC, 0x5B, 0x2B, 0x89, 0x52 },
254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 }
255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   },
256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   {
257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       { 0xDC, 0x49, 0xdb, 0x13, 0x75, 0xa5, 0x58, 0x4f,
258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         0x64, 0x85, 0xb4, 0x13, 0xb5, 0xf1, 0x2b, 0xaf },
259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 },
260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       { 0x65, 0xc1, 0x78, 0xb2, 0x84, 0xd1, 0x97, 0xcc }
261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   };
263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   unsigned char tmp[2][8];
264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int x, y, err;
265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   symmetric_key key;
266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* setup key */
269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      if ((err = rc5_setup(tests[x].key, 16, 12, &key)) != CRYPT_OK) {
270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         return err;
271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* encrypt and decrypt */
274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      rc5_ecb_encrypt(tests[x].pt, tmp[0], &key);
275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      rc5_ecb_decrypt(tmp[0], tmp[1], &key);
276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* compare */
278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      if (XMEMCMP(tmp[0], tests[x].ct, 8) != 0 || XMEMCMP(tmp[1], tests[x].pt, 8) != 0) {
279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project         return CRYPT_FAIL_TESTVECTOR;
280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      }
281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (y = 0; y < 8; y++) tmp[0][y] = 0;
284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (y = 0; y < 1000; y++) rc5_ecb_encrypt(tmp[0], tmp[0], &key);
285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (y = 0; y < 1000; y++) rc5_ecb_decrypt(tmp[0], tmp[0], &key);
286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_OK;
289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  #endif
290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** Terminate the context
293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param skey    The scheduled key
294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid rc5_done(symmetric_key *skey)
296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Gets suitable key size
301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The 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.
302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if the input key size is acceptable.
303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint rc5_keysize(int *keysize)
305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(keysize != NULL);
307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (*keysize < 8) {
308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return CRYPT_INVALID_KEYSIZE;
309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   } else if (*keysize > 128) {
310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      *keysize = 128;
311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_OK;
313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/ciphers/rc5.c,v $ */
321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.12 $ */
322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/11/08 23:01:06 $ */
323