Crypto++
|
00001 // rc2.cpp - written and placed in the public domain by Wei Dai 00002 00003 #include "pch.h" 00004 #include "rc2.h" 00005 #include "misc.h" 00006 #include "argnames.h" 00007 00008 NAMESPACE_BEGIN(CryptoPP) 00009 00010 void RC2::Base::UncheckedSetKey(const byte *key, unsigned int keyLen, const NameValuePairs ¶ms) 00011 { 00012 AssertValidKeyLength(keyLen); 00013 00014 int effectiveLen = params.GetIntValueWithDefault(Name::EffectiveKeyLength(), DEFAULT_EFFECTIVE_KEYLENGTH); 00015 if (effectiveLen > MAX_EFFECTIVE_KEYLENGTH) 00016 throw InvalidArgument("RC2: effective key length parameter exceeds maximum"); 00017 00018 static const unsigned char PITABLE[256] = { 00019 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157, 00020 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162, 00021 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50, 00022 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130, 00023 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220, 00024 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38, 00025 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3, 00026 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215, 00027 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42, 00028 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236, 00029 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57, 00030 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49, 00031 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201, 00032 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169, 00033 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46, 00034 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173}; 00035 00036 SecByteBlock L(128); 00037 memcpy(L, key, keyLen); 00038 00039 int i; 00040 for (i=keyLen; i<128; i++) 00041 L[i] = PITABLE[(L[i-1] + L[i-keyLen]) & 255]; 00042 00043 unsigned int T8 = (effectiveLen+7) / 8; 00044 byte TM = 255 >> ((8-(effectiveLen%8))%8); 00045 L[128-T8] = PITABLE[L[128-T8] & TM]; 00046 00047 for (i=127-T8; i>=0; i--) 00048 L[i] = PITABLE[L[i+1] ^ L[i+T8]]; 00049 00050 for (i=0; i<64; i++) 00051 K[i] = L[2*i] + (L[2*i+1] << 8); 00052 } 00053 00054 typedef BlockGetAndPut<word16, LittleEndian> Block; 00055 00056 void RC2::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 00057 { 00058 word16 R0, R1, R2, R3; 00059 Block::Get(inBlock)(R0)(R1)(R2)(R3); 00060 00061 for (int i = 0; i < 16; i++) 00062 { 00063 R0 += (R1 & ~R3) + (R2 & R3) + K[4*i+0]; 00064 R0 = rotlFixed(R0, 1); 00065 00066 R1 += (R2 & ~R0) + (R3 & R0) + K[4*i+1]; 00067 R1 = rotlFixed(R1, 2); 00068 00069 R2 += (R3 & ~R1) + (R0 & R1) + K[4*i+2]; 00070 R2 = rotlFixed(R2, 3); 00071 00072 R3 += (R0 & ~R2) + (R1 & R2) + K[4*i+3]; 00073 R3 = rotlFixed(R3, 5); 00074 00075 if (i == 4 || i == 10) 00076 { 00077 R0 += K[R3 & 63]; 00078 R1 += K[R0 & 63]; 00079 R2 += K[R1 & 63]; 00080 R3 += K[R2 & 63]; 00081 } 00082 } 00083 00084 Block::Put(xorBlock, outBlock)(R0)(R1)(R2)(R3); 00085 } 00086 00087 void RC2::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 00088 { 00089 word16 R0, R1, R2, R3; 00090 Block::Get(inBlock)(R0)(R1)(R2)(R3); 00091 00092 for (int i = 15; i >= 0; i--) 00093 { 00094 if (i == 4 || i == 10) 00095 { 00096 R3 -= K[R2 & 63]; 00097 R2 -= K[R1 & 63]; 00098 R1 -= K[R0 & 63]; 00099 R0 -= K[R3 & 63]; 00100 } 00101 00102 R3 = rotrFixed(R3, 5); 00103 R3 -= (R0 & ~R2) + (R1 & R2) + K[4*i+3]; 00104 00105 R2 = rotrFixed(R2, 3); 00106 R2 -= (R3 & ~R1) + (R0 & R1) + K[4*i+2]; 00107 00108 R1 = rotrFixed(R1, 2); 00109 R1 -= (R2 & ~R0) + (R3 & R0) + K[4*i+1]; 00110 00111 R0 = rotrFixed(R0, 1); 00112 R0 -= (R1 & ~R3) + (R2 & R3) + K[4*i+0]; 00113 } 00114 00115 Block::Put(xorBlock, outBlock)(R0)(R1)(R2)(R3); 00116 } 00117 00118 NAMESPACE_END