blob: 241b95608c192a8959aade637a6dd8e20ad6dabd [file] [log] [blame]
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -05001#include <stdint.h>
2#include <stdlib.h>
3
4#include "twofish.h"
5
6void Twofish_cfb128_encrypt(Twofish_key* keyCtx, Twofish_Byte* in,
7 Twofish_Byte* out, size_t len,
8 Twofish_Byte* ivec, int32_t *num)
9{
10 uint32_t n;
11
12 n = *num;
13
14 do {
15 while (n && len) {
16 *(out++) = ivec[n] ^= *(in++);
17 --len;
18 n = (n+1) % 16;
19 }
20 while (len>=16) {
21 Twofish_encrypt(keyCtx, ivec, ivec);
22 for (n=0; n<16; n+=sizeof(size_t)) {
Alexandre Lision907ed2e2014-02-04 10:33:09 -050023
24/*
25 * Some GCC version(s) of Android's NDK produce code that leads to a crash (SIGBUS). The
26 * offending line if the line that produces the output by xor'ing the ivec. Somehow the
27 * compiler/optimizer seems to incorrectly setup the pointers. Adding a call to an
28 * external function that uses the pointer disabled or modifies this optimzing
29 * behaviour. This debug functions as such does nothing, it just disables some
30 * optimization. Don't use a local (static) function - the compiler sees that it does
31 * nothing and optimizes again :-) .
32 */
33#ifdef ANDROID
34 Two_debugDummy(in, out, ivec);
35#endif
36 *(size_t*)(out+n) = *(size_t*)(ivec+n) ^= *(size_t*)(in+n);;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050037 }
38 len -= 16;
39 out += 16;
40 in += 16;
41 }
42 n = 0;
43 if (len) {
44 Twofish_encrypt(keyCtx, ivec, ivec);
45 while (len--) {
Alexandre Lision907ed2e2014-02-04 10:33:09 -050046 out[n] = ivec[n] ^= in[n];
47 ++n;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050048 }
49 }
50 *num = n;
51 return;
52 } while (0);
53}
54
55
56void Twofish_cfb128_decrypt(Twofish_key* keyCtx, Twofish_Byte* in,
57 Twofish_Byte* out, size_t len,
58 Twofish_Byte* ivec, int32_t *num)
59{
60 uint32_t n;
61
62 n = *num;
63
64 do {
65 while (n && len) {
66 unsigned char c;
67 *(out++) = ivec[n] ^ (c = *(in++)); ivec[n] = c;
68 --len;
69 n = (n+1) % 16;
70 }
71 while (len>=16) {
72 Twofish_encrypt(keyCtx, ivec, ivec);
73 for (n=0; n<16; n+=sizeof(size_t)) {
74 size_t t = *(size_t*)(in+n);
75 *(size_t*)(out+n) = *(size_t*)(ivec+n) ^ t;
76 *(size_t*)(ivec+n) = t;
77 }
78 len -= 16;
79 out += 16;
80 in += 16;
81 }
82 n = 0;
83 if (len) {
84 Twofish_encrypt(keyCtx, ivec, ivec);
85 while (len--) {
86 unsigned char c;
87 out[n] = ivec[n] ^ (c = in[n]); ivec[n] = c;
88 ++n;
89 }
90 }
91 *num = n;
92 return;
93 } while (0);
94}