Botan
1.11.15
|
00001 /* 00002 * RC5 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/rc5.h> 00010 #include <botan/parsing.h> 00011 00012 namespace Botan { 00013 00014 BOTAN_REGISTER_BLOCK_CIPHER_1LEN(RC5, 12); 00015 00016 /* 00017 * RC5 Encryption 00018 */ 00019 void RC5::encrypt_n(const byte in[], byte out[], size_t blocks) const 00020 { 00021 for(size_t i = 0; i != blocks; ++i) 00022 { 00023 u32bit A = load_le<u32bit>(in, 0); 00024 u32bit B = load_le<u32bit>(in, 1); 00025 00026 A += S[0]; B += S[1]; 00027 for(size_t j = 0; j != rounds; j += 4) 00028 { 00029 A = rotate_left(A ^ B, B % 32) + S[2*j+2]; 00030 B = rotate_left(B ^ A, A % 32) + S[2*j+3]; 00031 00032 A = rotate_left(A ^ B, B % 32) + S[2*j+4]; 00033 B = rotate_left(B ^ A, A % 32) + S[2*j+5]; 00034 00035 A = rotate_left(A ^ B, B % 32) + S[2*j+6]; 00036 B = rotate_left(B ^ A, A % 32) + S[2*j+7]; 00037 00038 A = rotate_left(A ^ B, B % 32) + S[2*j+8]; 00039 B = rotate_left(B ^ A, A % 32) + S[2*j+9]; 00040 } 00041 00042 store_le(out, A, B); 00043 00044 in += BLOCK_SIZE; 00045 out += BLOCK_SIZE; 00046 } 00047 } 00048 00049 /* 00050 * RC5 Decryption 00051 */ 00052 void RC5::decrypt_n(const byte in[], byte out[], size_t blocks) const 00053 { 00054 for(size_t i = 0; i != blocks; ++i) 00055 { 00056 u32bit A = load_le<u32bit>(in, 0); 00057 u32bit B = load_le<u32bit>(in, 1); 00058 00059 for(size_t j = rounds; j != 0; j -= 4) 00060 { 00061 B = rotate_right(B - S[2*j+1], A % 32) ^ A; 00062 A = rotate_right(A - S[2*j ], B % 32) ^ B; 00063 00064 B = rotate_right(B - S[2*j-1], A % 32) ^ A; 00065 A = rotate_right(A - S[2*j-2], B % 32) ^ B; 00066 00067 B = rotate_right(B - S[2*j-3], A % 32) ^ A; 00068 A = rotate_right(A - S[2*j-4], B % 32) ^ B; 00069 00070 B = rotate_right(B - S[2*j-5], A % 32) ^ A; 00071 A = rotate_right(A - S[2*j-6], B % 32) ^ B; 00072 } 00073 B -= S[1]; A -= S[0]; 00074 00075 store_le(out, A, B); 00076 00077 in += BLOCK_SIZE; 00078 out += BLOCK_SIZE; 00079 } 00080 } 00081 00082 /* 00083 * RC5 Key Schedule 00084 */ 00085 void RC5::key_schedule(const byte key[], size_t length) 00086 { 00087 S.resize(2*rounds + 2); 00088 00089 const size_t WORD_KEYLENGTH = (((length - 1) / 4) + 1); 00090 const size_t MIX_ROUNDS = 3 * std::max(WORD_KEYLENGTH, S.size()); 00091 00092 S[0] = 0xB7E15163; 00093 for(size_t i = 1; i != S.size(); ++i) 00094 S[i] = S[i-1] + 0x9E3779B9; 00095 00096 secure_vector<u32bit> K(8); 00097 00098 for(s32bit i = length-1; i >= 0; --i) 00099 K[i/4] = (K[i/4] << 8) + key[i]; 00100 00101 u32bit A = 0, B = 0; 00102 00103 for(size_t i = 0; i != MIX_ROUNDS; ++i) 00104 { 00105 A = rotate_left(S[i % S.size()] + A + B, 3); 00106 B = rotate_left(K[i % WORD_KEYLENGTH] + A + B, (A + B) % 32); 00107 S[i % S.size()] = A; 00108 K[i % WORD_KEYLENGTH] = B; 00109 } 00110 } 00111 00112 void RC5::clear() 00113 { 00114 zap(S); 00115 } 00116 00117 /* 00118 * Return the name of this type 00119 */ 00120 std::string RC5::name() const 00121 { 00122 return "RC5(" + std::to_string(rounds) + ")"; 00123 } 00124 00125 /* 00126 * RC5 Constructor 00127 */ 00128 RC5::RC5(size_t r) : rounds(r) 00129 { 00130 if(rounds < 8 || rounds > 32 || (rounds % 4 != 0)) 00131 throw Invalid_Argument("RC5: Invalid number of rounds " + 00132 std::to_string(rounds)); 00133 } 00134 00135 }