1e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * All rights reserved.
3e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *
4e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * This package is an SSL implementation written
5e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * by Eric Young (eay@cryptsoft.com).
6e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * The implementation was written so as to conform with Netscapes SSL.
7e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *
8e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * This library is free for commercial and non-commercial use as long as
9e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * the following conditions are aheared to.  The following conditions
10e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * apply to all code found in this distribution, be it the RC4, RSA,
11e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * included with this distribution is covered by the same copyright terms
13e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *
15e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * Copyright remains Eric Young's, and as such any Copyright notices in
16e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * the code are not to be removed.
17e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * If this package is used in a product, Eric Young should be given attribution
18e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * as the author of the parts of the library used.
19e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * This can be in the form of a textual message at program startup or
20e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * in documentation (online or textual) provided with the package.
21e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *
22e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * Redistribution and use in source and binary forms, with or without
23e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * modification, are permitted provided that the following conditions
24e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * are met:
25e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 1. Redistributions of source code must retain the copyright
26e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *    notice, this list of conditions and the following disclaimer.
27e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
28e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *    notice, this list of conditions and the following disclaimer in the
29e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *    documentation and/or other materials provided with the distribution.
30e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 3. All advertising materials mentioning features or use of this software
31e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *    must display the following acknowledgement:
32e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *    "This product includes cryptographic software written by
33e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *     Eric Young (eay@cryptsoft.com)"
34e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *    The word 'cryptographic' can be left out if the rouines from the library
35e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *    being used are not cryptographic related :-).
36e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * 4. If you include any Windows specific code (or a derivative thereof) from
37e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *    the apps directory (application code) you must include an acknowledgement:
38e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *
40e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * SUCH DAMAGE.
51e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *
52e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * The licence and distribution terms for any publically available version or
53e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * derivative of this code cannot be changed.  i.e. this code cannot simply be
54e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * copied and put under another distribution licence
55e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * [including the GNU Public Licence.]. */
56e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
57e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/cast.h>
58e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
59e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#if defined(OPENSSL_WINDOWS)
60e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#pragma warning(push, 3)
61e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <intrin.h>
62e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#pragma warning(pop)
63e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#endif
64e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
654139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley#include "internal.h"
66e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include "../macros.h"
67e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
68e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
69e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyvoid CAST_ecb_encrypt(const uint8_t *in, uint8_t *out, const CAST_KEY *ks,
70e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                      int enc) {
71e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t d[2];
72e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
73e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  n2l(in, d[0]);
74e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  n2l(in, d[1]);
75e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (enc) {
76e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_encrypt(d, ks);
77e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  } else {
78e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_decrypt(d, ks);
79e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
80e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  l2n(d[0], out);
81e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  l2n(d[1], out);
82e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
83e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
84e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#if defined(OPENSSL_WINDOWS) && defined(_MSC_VER)
85e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#define ROTL(a, n) (_lrotl(a, n))
86e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#else
87e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#define ROTL(a, n) ((((a) << (n)) | ((a) >> ((-(n))&31))) & 0xffffffffL)
88e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#endif
89e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
90e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#define E_CAST(n, key, L, R, OP1, OP2, OP3)                                   \
91e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  {                                                                           \
92e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    uint32_t a, b, c, d;                                                      \
93e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    t = (key[n * 2] OP1 R) & 0xffffffff;                                      \
94e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    t = ROTL(t, (key[n * 2 + 1]));                                            \
95e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    a = CAST_S_table0[(t >> 8) & 0xff];                                       \
96e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    b = CAST_S_table1[(t)&0xff];                                              \
97e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    c = CAST_S_table2[(t >> 24) & 0xff];                                      \
98e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    d = CAST_S_table3[(t >> 16) & 0xff];                                      \
99e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    L ^= (((((a OP2 b)&0xffffffffL)OP3 c) & 0xffffffffL)OP1 d) & 0xffffffffL; \
100e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
101e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
102e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyvoid CAST_encrypt(uint32_t *data, const CAST_KEY *key) {
103e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t l, r, t;
104e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  const uint32_t *k;
105e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
106e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  k = &key->data[0];
107e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  l = data[0];
108e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  r = data[1];
109e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
110e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(0, k, l, r, +, ^, -);
111e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(1, k, r, l, ^, -, +);
112e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(2, k, l, r, -, +, ^);
113e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(3, k, r, l, +, ^, -);
114e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(4, k, l, r, ^, -, +);
115e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(5, k, r, l, -, +, ^);
116e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(6, k, l, r, +, ^, -);
117e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(7, k, r, l, ^, -, +);
118e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(8, k, l, r, -, +, ^);
119e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(9, k, r, l, +, ^, -);
120e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(10, k, l, r, ^, -, +);
121e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(11, k, r, l, -, +, ^);
122e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
123e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!key->short_key) {
124e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    E_CAST(12, k, l, r, +, ^, -);
125e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    E_CAST(13, k, r, l, ^, -, +);
126e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    E_CAST(14, k, l, r, -, +, ^);
127e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    E_CAST(15, k, r, l, +, ^, -);
128e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
129e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
130e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  data[1] = l & 0xffffffffL;
131e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  data[0] = r & 0xffffffffL;
132e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
133e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
134e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyvoid CAST_decrypt(uint32_t *data, const CAST_KEY *key) {
135e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t l, r, t;
136e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  const uint32_t *k;
137e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
138e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  k = &key->data[0];
139e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  l = data[0];
140e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  r = data[1];
141e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
142e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!key->short_key) {
143e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    E_CAST(15, k, l, r, +, ^, -);
144e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    E_CAST(14, k, r, l, -, +, ^);
145e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    E_CAST(13, k, l, r, ^, -, +);
146e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    E_CAST(12, k, r, l, +, ^, -);
147e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
148e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
149e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(11, k, l, r, -, +, ^);
150e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(10, k, r, l, ^, -, +);
151e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(9, k, l, r, +, ^, -);
152e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(8, k, r, l, -, +, ^);
153e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(7, k, l, r, ^, -, +);
154e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(6, k, r, l, +, ^, -);
155e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(5, k, l, r, -, +, ^);
156e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(4, k, r, l, ^, -, +);
157e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(3, k, l, r, +, ^, -);
158e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(2, k, r, l, -, +, ^);
159e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(1, k, l, r, ^, -, +);
160e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  E_CAST(0, k, r, l, +, ^, -);
161e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
162e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  data[1] = l & 0xffffffffL;
163e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  data[0] = r & 0xffffffffL;
164e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
165e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
166e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyvoid CAST_cbc_encrypt(const uint8_t *in, uint8_t *out, long length,
167e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                      const CAST_KEY *ks, uint8_t *iv, int enc) {
168e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t tin0, tin1;
169e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t tout0, tout1, xor0, xor1;
170e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  long l = length;
171e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t tin[2];
172e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
173e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (enc) {
174e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    n2l(iv, tout0);
175e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    n2l(iv, tout1);
176e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    iv -= 8;
177e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    for (l -= 8; l >= 0; l -= 8) {
178e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      n2l(in, tin0);
179e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      n2l(in, tin1);
180e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin0 ^= tout0;
181e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin1 ^= tout1;
182e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin[0] = tin0;
183e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin[1] = tin1;
184e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      CAST_encrypt(tin, ks);
185e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tout0 = tin[0];
186e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tout1 = tin[1];
187e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      l2n(tout0, out);
188e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      l2n(tout1, out);
189e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
190e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (l != -8) {
191e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      n2ln(in, tin0, tin1, l + 8);
192e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin0 ^= tout0;
193e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin1 ^= tout1;
194e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin[0] = tin0;
195e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin[1] = tin1;
196e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      CAST_encrypt(tin, ks);
197e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tout0 = tin[0];
198e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tout1 = tin[1];
199e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      l2n(tout0, out);
200e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      l2n(tout1, out);
201e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
202e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l2n(tout0, iv);
203e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l2n(tout1, iv);
204e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  } else {
205e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    n2l(iv, xor0);
206e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    n2l(iv, xor1);
207e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    iv -= 8;
208e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    for (l -= 8; l >= 0; l -= 8) {
209e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      n2l(in, tin0);
210e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      n2l(in, tin1);
211e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin[0] = tin0;
212e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin[1] = tin1;
213e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      CAST_decrypt(tin, ks);
214e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tout0 = tin[0] ^ xor0;
215e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tout1 = tin[1] ^ xor1;
216e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      l2n(tout0, out);
217e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      l2n(tout1, out);
218e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      xor0 = tin0;
219e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      xor1 = tin1;
220e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
221e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (l != -8) {
222e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      n2l(in, tin0);
223e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      n2l(in, tin1);
224e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin[0] = tin0;
225e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tin[1] = tin1;
226e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      CAST_decrypt(tin, ks);
227e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tout0 = tin[0] ^ xor0;
228e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      tout1 = tin[1] ^ xor1;
229e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      l2nn(tout0, tout1, out, l + 8);
230e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      xor0 = tin0;
231e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      xor1 = tin1;
232e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
233e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l2n(xor0, iv);
234e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l2n(xor1, iv);
235e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
236e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
237e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  tin[0] = tin[1] = 0;
238e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
239e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
240e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#define CAST_exp(l, A, a, n)   \
241e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  A[n / 4] = l;                \
242e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  a[n + 3] = (l)&0xff;         \
243e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  a[n + 2] = (l >> 8) & 0xff;  \
244e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  a[n + 1] = (l >> 16) & 0xff; \
245e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  a[n + 0] = (l >> 24) & 0xff;
246e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#define S4 CAST_S_table4
247e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#define S5 CAST_S_table5
248e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#define S6 CAST_S_table6
249e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#define S7 CAST_S_table7
250e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
251e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyvoid CAST_set_key(CAST_KEY *key, size_t len, const uint8_t *data) {
252e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t x[16];
253e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t z[16];
254e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t k[32];
255e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t X[4], Z[4];
256e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t l, *K;
257e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  size_t i;
258e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
259e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  for (i = 0; i < 16; i++) {
260e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    x[i] = 0;
261e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
262e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
263e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (len > 16) {
264e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    len = 16;
265e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
266e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
267e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  for (i = 0; i < len; i++) {
268e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    x[i] = data[i];
269e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
270e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
271e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (len <= 10) {
272e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    key->short_key = 1;
273e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  } else {
274e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    key->short_key = 0;
275e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
276e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
277e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  K = &k[0];
278e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  X[0] = ((x[0] << 24) | (x[1] << 16) | (x[2] << 8) | x[3]) & 0xffffffffL;
279e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  X[1] = ((x[4] << 24) | (x[5] << 16) | (x[6] << 8) | x[7]) & 0xffffffffL;
280e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  X[2] = ((x[8] << 24) | (x[9] << 16) | (x[10] << 8) | x[11]) & 0xffffffffL;
281e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  X[3] = ((x[12] << 24) | (x[13] << 16) | (x[14] << 8) | x[15]) & 0xffffffffL;
282e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
283e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  for (;;) {
284e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = X[0] ^ S4[x[13]] ^ S5[x[15]] ^ S6[x[12]] ^ S7[x[14]] ^ S6[x[8]];
285e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, Z, z, 0);
286e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = X[2] ^ S4[z[0]] ^ S5[z[2]] ^ S6[z[1]] ^ S7[z[3]] ^ S7[x[10]];
287e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, Z, z, 4);
288e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = X[3] ^ S4[z[7]] ^ S5[z[6]] ^ S6[z[5]] ^ S7[z[4]] ^ S4[x[9]];
289e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, Z, z, 8);
290e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = X[1] ^ S4[z[10]] ^ S5[z[9]] ^ S6[z[11]] ^ S7[z[8]] ^ S5[x[11]];
291e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, Z, z, 12);
292e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
293e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[0] = S4[z[8]] ^ S5[z[9]] ^ S6[z[7]] ^ S7[z[6]] ^ S4[z[2]];
294e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[1] = S4[z[10]] ^ S5[z[11]] ^ S6[z[5]] ^ S7[z[4]] ^ S5[z[6]];
295e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[2] = S4[z[12]] ^ S5[z[13]] ^ S6[z[3]] ^ S7[z[2]] ^ S6[z[9]];
296e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[3] = S4[z[14]] ^ S5[z[15]] ^ S6[z[1]] ^ S7[z[0]] ^ S7[z[12]];
297e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
298e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = Z[2] ^ S4[z[5]] ^ S5[z[7]] ^ S6[z[4]] ^ S7[z[6]] ^ S6[z[0]];
299e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, X, x, 0);
300e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = Z[0] ^ S4[x[0]] ^ S5[x[2]] ^ S6[x[1]] ^ S7[x[3]] ^ S7[z[2]];
301e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, X, x, 4);
302e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = Z[1] ^ S4[x[7]] ^ S5[x[6]] ^ S6[x[5]] ^ S7[x[4]] ^ S4[z[1]];
303e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, X, x, 8);
304e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = Z[3] ^ S4[x[10]] ^ S5[x[9]] ^ S6[x[11]] ^ S7[x[8]] ^ S5[z[3]];
305e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, X, x, 12);
306e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
307e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[4] = S4[x[3]] ^ S5[x[2]] ^ S6[x[12]] ^ S7[x[13]] ^ S4[x[8]];
308e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[5] = S4[x[1]] ^ S5[x[0]] ^ S6[x[14]] ^ S7[x[15]] ^ S5[x[13]];
309e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[6] = S4[x[7]] ^ S5[x[6]] ^ S6[x[8]] ^ S7[x[9]] ^ S6[x[3]];
310e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[7] = S4[x[5]] ^ S5[x[4]] ^ S6[x[10]] ^ S7[x[11]] ^ S7[x[7]];
311e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
312e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = X[0] ^ S4[x[13]] ^ S5[x[15]] ^ S6[x[12]] ^ S7[x[14]] ^ S6[x[8]];
313e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, Z, z, 0);
314e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = X[2] ^ S4[z[0]] ^ S5[z[2]] ^ S6[z[1]] ^ S7[z[3]] ^ S7[x[10]];
315e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, Z, z, 4);
316e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = X[3] ^ S4[z[7]] ^ S5[z[6]] ^ S6[z[5]] ^ S7[z[4]] ^ S4[x[9]];
317e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, Z, z, 8);
318e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = X[1] ^ S4[z[10]] ^ S5[z[9]] ^ S6[z[11]] ^ S7[z[8]] ^ S5[x[11]];
319e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, Z, z, 12);
320e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
321e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[8] = S4[z[3]] ^ S5[z[2]] ^ S6[z[12]] ^ S7[z[13]] ^ S4[z[9]];
322e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[9] = S4[z[1]] ^ S5[z[0]] ^ S6[z[14]] ^ S7[z[15]] ^ S5[z[12]];
323e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[10] = S4[z[7]] ^ S5[z[6]] ^ S6[z[8]] ^ S7[z[9]] ^ S6[z[2]];
324e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[11] = S4[z[5]] ^ S5[z[4]] ^ S6[z[10]] ^ S7[z[11]] ^ S7[z[6]];
325e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
326e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = Z[2] ^ S4[z[5]] ^ S5[z[7]] ^ S6[z[4]] ^ S7[z[6]] ^ S6[z[0]];
327e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, X, x, 0);
328e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = Z[0] ^ S4[x[0]] ^ S5[x[2]] ^ S6[x[1]] ^ S7[x[3]] ^ S7[z[2]];
329e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, X, x, 4);
330e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = Z[1] ^ S4[x[7]] ^ S5[x[6]] ^ S6[x[5]] ^ S7[x[4]] ^ S4[z[1]];
331e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, X, x, 8);
332e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    l = Z[3] ^ S4[x[10]] ^ S5[x[9]] ^ S6[x[11]] ^ S7[x[8]] ^ S5[z[3]];
333e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CAST_exp(l, X, x, 12);
334e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
335e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[12] = S4[x[8]] ^ S5[x[9]] ^ S6[x[7]] ^ S7[x[6]] ^ S4[x[3]];
336e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[13] = S4[x[10]] ^ S5[x[11]] ^ S6[x[5]] ^ S7[x[4]] ^ S5[x[7]];
337e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[14] = S4[x[12]] ^ S5[x[13]] ^ S6[x[3]] ^ S7[x[2]] ^ S6[x[8]];
338e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K[15] = S4[x[14]] ^ S5[x[15]] ^ S6[x[1]] ^ S7[x[0]] ^ S7[x[13]];
339e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (K != k) {
340e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      break;
341e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
342e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    K += 16;
343e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
344e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
345e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  for (i = 0; i < 16; i++) {
346e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    key->data[i * 2] = k[i];
347e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    key->data[i * 2 + 1] = ((k[i + 16]) + 16) & 0x1f;
348e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
349e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
350e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
351e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley/* The input and output encrypted as though 64bit cfb mode is being used. The
352e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * extra state information to record how much of the 64bit block we have used
353e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * is contained in *num. */
354e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyvoid CAST_cfb64_encrypt(const uint8_t *in, uint8_t *out, long length,
355e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                        const CAST_KEY *schedule, uint8_t *ivec, int *num,
356e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                        int enc) {
357e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t v0, v1, t;
358e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  int n = *num;
359e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  long l = length;
360e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint32_t ti[2];
361e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint8_t *iv, c, cc;
362e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
363e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  iv = ivec;
364e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (enc) {
365e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    while (l--) {
366e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      if (n == 0) {
367e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        n2l(iv, v0);
368e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        ti[0] = v0;
369e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        n2l(iv, v1);
370e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        ti[1] = v1;
371e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        CAST_encrypt((uint32_t *)ti, schedule);
372e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        iv = ivec;
373e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        t = ti[0];
374e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        l2n(t, iv);
375e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        t = ti[1];
376e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        l2n(t, iv);
377e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        iv = ivec;
378e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      }
379e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      c = *(in++) ^ iv[n];
380e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      *(out++) = c;
381e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      iv[n] = c;
382e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      n = (n + 1) & 0x07;
383e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
384e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  } else {
385e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    while (l--) {
386e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      if (n == 0) {
387e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        n2l(iv, v0);
388e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        ti[0] = v0;
389e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        n2l(iv, v1);
390e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        ti[1] = v1;
391e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        CAST_encrypt((uint32_t *)ti, schedule);
392e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        iv = ivec;
393e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        t = ti[0];
394e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        l2n(t, iv);
395e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        t = ti[1];
396e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        l2n(t, iv);
397e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        iv = ivec;
398e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      }
399e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      cc = *(in++);
400e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      c = iv[n];
401e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      iv[n] = cc;
402e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      *(out++) = c ^ cc;
403e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      n = (n + 1) & 0x07;
404e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
405e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
406e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  v0 = v1 = ti[0] = ti[1] = t = c = cc = 0;
407e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  *num = n;
408e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
409