RC2Crypt.java revision 12745:f068a4ffddd2
1/* 2 * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.crypto.provider; 27 28import java.security.InvalidKeyException; 29 30/** 31 * Implementation of the RC2(tm) algorithm as described in RFC 2268. 32 * 33 * RC2 is a 16-bit based algorithm and not particularly fast on 32/64 bit 34 * architectures. Also, note that although the JVM has a 16-bit integer 35 * type (short), all expressions are evaluated either in 32 or 64 bit 36 * (int or long). Expression such as "s1 = s2 + s3" are implemented by 37 * first promoting s2 and s3 to int, performing an int addition, and 38 * then demoting the result back to short to store in s1. To avoid this 39 * fairly slow process, we use the int type throughout and manually insert 40 * "& 0xffff" where necessary. 41 * 42 * @since 1.5 43 * @author Andreas Sterbenz 44 */ 45final class RC2Crypt extends SymmetricCipher { 46 47 // PITABLE from the RFC, used in key setup 48 private static final int[] PI_TABLE = new int[] { 49 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 50 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, 51 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 52 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 53 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 54 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, 55 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 56 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, 57 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 58 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 59 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 60 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, 61 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 62 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, 63 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 64 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 65 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 66 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, 67 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 68 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, 69 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 70 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 71 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 72 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, 73 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 74 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, 75 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 76 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 77 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 78 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, 79 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 80 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad, 81 }; 82 83 // expanded key, 64 times 16-bit words 84 private final int[] expandedKey; 85 86 // effective key bits 87 private int effectiveKeyBits; 88 89 RC2Crypt() { 90 expandedKey = new int[64]; 91 } 92 93 int getBlockSize() { 94 return 8; 95 } 96 97 int getEffectiveKeyBits() { 98 return effectiveKeyBits; 99 } 100 101 /** 102 * Initializes the effective key bit size. This method is a hook to 103 * allow RC2Cipher to initialize the effective key size. 104 */ 105 void initEffectiveKeyBits(int effectiveKeyBits) { 106 this.effectiveKeyBits = effectiveKeyBits; 107 } 108 109 static void checkKey(String algorithm, int keyLength) 110 throws InvalidKeyException { 111 if (algorithm.equals("RC2") == false) { 112 throw new InvalidKeyException("Key algorithm must be RC2"); 113 } 114 if ((keyLength < 5) || (keyLength > 128)) { 115 throw new InvalidKeyException 116 ("RC2 key length must be between 40 and 1024 bit"); 117 } 118 } 119 120 void init(boolean decrypting, String algorithm, byte[] key) 121 throws InvalidKeyException { 122 int keyLength = key.length; 123 if (effectiveKeyBits == 0) { 124 effectiveKeyBits = keyLength << 3; 125 } 126 127 checkKey(algorithm, keyLength); 128 129 // key buffer, the L[] byte array from the spec 130 byte[] expandedKeyBytes = new byte[128]; 131 132 // place key into key buffer 133 System.arraycopy(key, 0, expandedKeyBytes, 0, keyLength); 134 135 // first loop 136 int t = expandedKeyBytes[keyLength - 1]; 137 for (int i = keyLength; i < 128; i++) { 138 t = PI_TABLE[(t + expandedKeyBytes[i - keyLength]) & 0xff]; 139 expandedKeyBytes[i] = (byte)t; 140 } 141 142 int t8 = (effectiveKeyBits + 7) >> 3; 143 int tm = 0xff >> (-effectiveKeyBits & 7); 144 145 // second loop, reduce search space to effective key bits 146 t = PI_TABLE[expandedKeyBytes[128 - t8] & tm]; 147 expandedKeyBytes[128 - t8] = (byte)t; 148 for (int i = 127 - t8; i >= 0; i--) { 149 t = PI_TABLE[t ^ (expandedKeyBytes[i + t8] & 0xff)]; 150 expandedKeyBytes[i] = (byte)t; 151 } 152 153 // byte to short conversion, little endian (copy into K[]) 154 for (int i = 0, j = 0; i < 64; i++, j += 2) { 155 t = (expandedKeyBytes[j ] & 0xff) 156 + ((expandedKeyBytes[j + 1] & 0xff) << 8); 157 expandedKey[i] = t; 158 } 159 } 160 161 /** 162 * Encrypt a single block. Note that in a few places we omit a "& 0xffff" 163 * and allow variables to become larger than 16 bit. This still works 164 * because there is never a 32 bit overflow. 165 */ 166 void encryptBlock(byte[] in, int inOfs, byte[] out, int outOfs) { 167 int R0 = (in[inOfs ] & 0xff) 168 + ((in[inOfs + 1] & 0xff) << 8); 169 int R1 = (in[inOfs + 2] & 0xff) 170 + ((in[inOfs + 3] & 0xff) << 8); 171 int R2 = (in[inOfs + 4] & 0xff) 172 + ((in[inOfs + 5] & 0xff) << 8); 173 int R3 = (in[inOfs + 6] & 0xff) 174 + ((in[inOfs + 7] & 0xff) << 8); 175 176 // 5 mixing rounds 177 for (int i = 0; i < 20; i += 4) { 178 R0 = (R0 + expandedKey[i ] + (R3 & R2) + (~R3 & R1)) & 0xffff; 179 R0 = (R0 << 1) | (R0 >>> 15); 180 181 R1 = (R1 + expandedKey[i + 1] + (R0 & R3) + (~R0 & R2)) & 0xffff; 182 R1 = (R1 << 2) | (R1 >>> 14); 183 184 R2 = (R2 + expandedKey[i + 2] + (R1 & R0) + (~R1 & R3)) & 0xffff; 185 R2 = (R2 << 3) | (R2 >>> 13); 186 187 R3 = (R3 + expandedKey[i + 3] + (R2 & R1) + (~R2 & R0)) & 0xffff; 188 R3 = (R3 << 5) | (R3 >>> 11); 189 } 190 191 // 1 mashing round 192 R0 += expandedKey[R3 & 0x3f]; 193 R1 += expandedKey[R0 & 0x3f]; 194 R2 += expandedKey[R1 & 0x3f]; 195 R3 += expandedKey[R2 & 0x3f]; 196 197 // 6 mixing rounds 198 for (int i = 20; i < 44; i += 4) { 199 R0 = (R0 + expandedKey[i ] + (R3 & R2) + (~R3 & R1)) & 0xffff; 200 R0 = (R0 << 1) | (R0 >>> 15); 201 202 R1 = (R1 + expandedKey[i + 1] + (R0 & R3) + (~R0 & R2)) & 0xffff; 203 R1 = (R1 << 2) | (R1 >>> 14); 204 205 R2 = (R2 + expandedKey[i + 2] + (R1 & R0) + (~R1 & R3)) & 0xffff; 206 R2 = (R2 << 3) | (R2 >>> 13); 207 208 R3 = (R3 + expandedKey[i + 3] + (R2 & R1) + (~R2 & R0)) & 0xffff; 209 R3 = (R3 << 5) | (R3 >>> 11); 210 } 211 212 // 1 mashing round 213 R0 += expandedKey[R3 & 0x3f]; 214 R1 += expandedKey[R0 & 0x3f]; 215 R2 += expandedKey[R1 & 0x3f]; 216 R3 += expandedKey[R2 & 0x3f]; 217 218 // 5 mixing rounds 219 for (int i = 44; i < 64; i += 4) { 220 R0 = (R0 + expandedKey[i ] + (R3 & R2) + (~R3 & R1)) & 0xffff; 221 R0 = (R0 << 1) | (R0 >>> 15); 222 223 R1 = (R1 + expandedKey[i + 1] + (R0 & R3) + (~R0 & R2)) & 0xffff; 224 R1 = (R1 << 2) | (R1 >>> 14); 225 226 R2 = (R2 + expandedKey[i + 2] + (R1 & R0) + (~R1 & R3)) & 0xffff; 227 R2 = (R2 << 3) | (R2 >>> 13); 228 229 R3 = (R3 + expandedKey[i + 3] + (R2 & R1) + (~R2 & R0)) & 0xffff; 230 R3 = (R3 << 5) | (R3 >>> 11); 231 } 232 233 out[outOfs ] = (byte)R0; 234 out[outOfs + 1] = (byte)(R0 >> 8); 235 out[outOfs + 2] = (byte)R1; 236 out[outOfs + 3] = (byte)(R1 >> 8); 237 out[outOfs + 4] = (byte)R2; 238 out[outOfs + 5] = (byte)(R2 >> 8); 239 out[outOfs + 6] = (byte)R3; 240 out[outOfs + 7] = (byte)(R3 >> 8); 241 } 242 243 void decryptBlock(byte[] in, int inOfs, byte[] out, int outOfs) { 244 int R0 = (in[inOfs ] & 0xff) 245 + ((in[inOfs + 1] & 0xff) << 8); 246 int R1 = (in[inOfs + 2] & 0xff) 247 + ((in[inOfs + 3] & 0xff) << 8); 248 int R2 = (in[inOfs + 4] & 0xff) 249 + ((in[inOfs + 5] & 0xff) << 8); 250 int R3 = (in[inOfs + 6] & 0xff) 251 + ((in[inOfs + 7] & 0xff) << 8); 252 253 // 5 r-mixing rounds 254 for(int i = 64; i > 44; i -= 4) { 255 R3 = ((R3 << 11) | (R3 >>> 5)) & 0xffff; 256 R3 = (R3 - expandedKey[i - 1] - (R2 & R1) - (~R2 & R0)) & 0xffff; 257 258 R2 = ((R2 << 13) | (R2 >>> 3)) & 0xffff; 259 R2 = (R2 - expandedKey[i - 2] - (R1 & R0) - (~R1 & R3)) & 0xffff; 260 261 R1 = ((R1 << 14) | (R1 >>> 2)) & 0xffff; 262 R1 = (R1 - expandedKey[i - 3] - (R0 & R3) - (~R0 & R2)) & 0xffff; 263 264 R0 = ((R0 << 15) | (R0 >>> 1)) & 0xffff; 265 R0 = (R0 - expandedKey[i - 4] - (R3 & R2) - (~R3 & R1)) & 0xffff; 266 } 267 268 // 1 r-mashing round 269 R3 = (R3 - expandedKey[R2 & 0x3f]) & 0xffff; 270 R2 = (R2 - expandedKey[R1 & 0x3f]) & 0xffff; 271 R1 = (R1 - expandedKey[R0 & 0x3f]) & 0xffff; 272 R0 = (R0 - expandedKey[R3 & 0x3f]) & 0xffff; 273 274 // 6 r-mixing rounds 275 for(int i = 44; i > 20; i -= 4) { 276 R3 = ((R3 << 11) | (R3 >>> 5)) & 0xffff; 277 R3 = (R3 - expandedKey[i - 1] - (R2 & R1) - (~R2 & R0)) & 0xffff; 278 279 R2 = ((R2 << 13) | (R2 >>> 3)) & 0xffff; 280 R2 = (R2 - expandedKey[i - 2] - (R1 & R0) - (~R1 & R3)) & 0xffff; 281 282 R1 = ((R1 << 14) | (R1 >>> 2)) & 0xffff; 283 R1 = (R1 - expandedKey[i - 3] - (R0 & R3) - (~R0 & R2)) & 0xffff; 284 285 R0 = ((R0 << 15) | (R0 >>> 1)) & 0xffff; 286 R0 = (R0 - expandedKey[i - 4] - (R3 & R2) - (~R3 & R1)) & 0xffff; 287 } 288 289 // 1 r-mashing round 290 R3 = (R3 - expandedKey[R2 & 0x3f]) & 0xffff; 291 R2 = (R2 - expandedKey[R1 & 0x3f]) & 0xffff; 292 R1 = (R1 - expandedKey[R0 & 0x3f]) & 0xffff; 293 R0 = (R0 - expandedKey[R3 & 0x3f]) & 0xffff; 294 295 // 5 r-mixing rounds 296 for(int i = 20; i > 0; i -= 4) { 297 R3 = ((R3 << 11) | (R3 >>> 5)) & 0xffff; 298 R3 = (R3 - expandedKey[i - 1] - (R2 & R1) - (~R2 & R0)) & 0xffff; 299 300 R2 = ((R2 << 13) | (R2 >>> 3)) & 0xffff; 301 R2 = (R2 - expandedKey[i - 2] - (R1 & R0) - (~R1 & R3)) & 0xffff; 302 303 R1 = ((R1 << 14) | (R1 >>> 2)) & 0xffff; 304 R1 = (R1 - expandedKey[i - 3] - (R0 & R3) - (~R0 & R2)) & 0xffff; 305 306 R0 = ((R0 << 15) | (R0 >>> 1)) & 0xffff; 307 R0 = (R0 - expandedKey[i - 4] - (R3 & R2) - (~R3 & R1)) & 0xffff; 308 } 309 310 out[outOfs ] = (byte)R0; 311 out[outOfs + 1] = (byte)(R0 >> 8); 312 out[outOfs + 2] = (byte)R1; 313 out[outOfs + 3] = (byte)(R1 >> 8); 314 out[outOfs + 4] = (byte)R2; 315 out[outOfs + 5] = (byte)(R2 >> 8); 316 out[outOfs + 6] = (byte)R3; 317 out[outOfs + 7] = (byte)(R3 >> 8); 318 } 319 320} 321