Botan
1.11.15
|
00001 /* 00002 * RC6 00003 * (C) 1999-2007 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/block_utils.h> 00009 #include <botan/rc6.h> 00010 00011 namespace Botan { 00012 00013 BOTAN_REGISTER_BLOCK_CIPHER_NOARGS(RC6); 00014 00015 /* 00016 * RC6 Encryption 00017 */ 00018 void RC6::encrypt_n(const byte in[], byte out[], size_t blocks) const 00019 { 00020 for(size_t i = 0; i != blocks; ++i) 00021 { 00022 u32bit A = load_le<u32bit>(in, 0); 00023 u32bit B = load_le<u32bit>(in, 1); 00024 u32bit C = load_le<u32bit>(in, 2); 00025 u32bit D = load_le<u32bit>(in, 3); 00026 00027 B += S[0]; D += S[1]; 00028 00029 for(size_t j = 0; j != 20; j += 4) 00030 { 00031 u32bit T1, T2; 00032 00033 T1 = rotate_left(B*(2*B+1), 5); 00034 T2 = rotate_left(D*(2*D+1), 5); 00035 A = rotate_left(A ^ T1, T2 % 32) + S[2*j+2]; 00036 C = rotate_left(C ^ T2, T1 % 32) + S[2*j+3]; 00037 00038 T1 = rotate_left(C*(2*C+1), 5); 00039 T2 = rotate_left(A*(2*A+1), 5); 00040 B = rotate_left(B ^ T1, T2 % 32) + S[2*j+4]; 00041 D = rotate_left(D ^ T2, T1 % 32) + S[2*j+5]; 00042 00043 T1 = rotate_left(D*(2*D+1), 5); 00044 T2 = rotate_left(B*(2*B+1), 5); 00045 C = rotate_left(C ^ T1, T2 % 32) + S[2*j+6]; 00046 A = rotate_left(A ^ T2, T1 % 32) + S[2*j+7]; 00047 00048 T1 = rotate_left(A*(2*A+1), 5); 00049 T2 = rotate_left(C*(2*C+1), 5); 00050 D = rotate_left(D ^ T1, T2 % 32) + S[2*j+8]; 00051 B = rotate_left(B ^ T2, T1 % 32) + S[2*j+9]; 00052 } 00053 00054 A += S[42]; C += S[43]; 00055 00056 store_le(out, A, B, C, D); 00057 00058 in += BLOCK_SIZE; 00059 out += BLOCK_SIZE; 00060 } 00061 } 00062 00063 /* 00064 * RC6 Decryption 00065 */ 00066 void RC6::decrypt_n(const byte in[], byte out[], size_t blocks) const 00067 { 00068 for(size_t i = 0; i != blocks; ++i) 00069 { 00070 u32bit A = load_le<u32bit>(in, 0); 00071 u32bit B = load_le<u32bit>(in, 1); 00072 u32bit C = load_le<u32bit>(in, 2); 00073 u32bit D = load_le<u32bit>(in, 3); 00074 00075 C -= S[43]; A -= S[42]; 00076 00077 for(size_t j = 0; j != 20; j += 4) 00078 { 00079 u32bit T1, T2; 00080 00081 T1 = rotate_left(A*(2*A+1), 5); 00082 T2 = rotate_left(C*(2*C+1), 5); 00083 B = rotate_right(B - S[41 - 2*j], T1 % 32) ^ T2; 00084 D = rotate_right(D - S[40 - 2*j], T2 % 32) ^ T1; 00085 00086 T1 = rotate_left(D*(2*D+1), 5); 00087 T2 = rotate_left(B*(2*B+1), 5); 00088 A = rotate_right(A - S[39 - 2*j], T1 % 32) ^ T2; 00089 C = rotate_right(C - S[38 - 2*j], T2 % 32) ^ T1; 00090 00091 T1 = rotate_left(C*(2*C+1), 5); 00092 T2 = rotate_left(A*(2*A+1), 5); 00093 D = rotate_right(D - S[37 - 2*j], T1 % 32) ^ T2; 00094 B = rotate_right(B - S[36 - 2*j], T2 % 32) ^ T1; 00095 00096 T1 = rotate_left(B*(2*B+1), 5); 00097 T2 = rotate_left(D*(2*D+1), 5); 00098 C = rotate_right(C - S[35 - 2*j], T1 % 32) ^ T2; 00099 A = rotate_right(A - S[34 - 2*j], T2 % 32) ^ T1; 00100 } 00101 00102 D -= S[1]; B -= S[0]; 00103 00104 store_le(out, A, B, C, D); 00105 00106 in += BLOCK_SIZE; 00107 out += BLOCK_SIZE; 00108 } 00109 } 00110 00111 /* 00112 * RC6 Key Schedule 00113 */ 00114 void RC6::key_schedule(const byte key[], size_t length) 00115 { 00116 S.resize(44); 00117 00118 const size_t WORD_KEYLENGTH = (((length - 1) / 4) + 1); 00119 const size_t MIX_ROUNDS = 3 * std::max(WORD_KEYLENGTH, S.size()); 00120 00121 S[0] = 0xB7E15163; 00122 for(size_t i = 1; i != S.size(); ++i) 00123 S[i] = S[i-1] + 0x9E3779B9; 00124 00125 secure_vector<u32bit> K(8); 00126 00127 for(s32bit i = length-1; i >= 0; --i) 00128 K[i/4] = (K[i/4] << 8) + key[i]; 00129 00130 u32bit A = 0, B = 0; 00131 for(size_t i = 0; i != MIX_ROUNDS; ++i) 00132 { 00133 A = rotate_left(S[i % S.size()] + A + B, 3); 00134 B = rotate_left(K[i % WORD_KEYLENGTH] + A + B, (A + B) % 32); 00135 S[i % S.size()] = A; 00136 K[i % WORD_KEYLENGTH] = B; 00137 } 00138 } 00139 00140 void RC6::clear() 00141 { 00142 zap(S); 00143 } 00144 00145 }