1 package org.bouncycastle.jcajce.provider.symmetric.util; 2 3 import java.security.spec.AlgorithmParameterSpec; 4 5 import javax.crypto.spec.PBEKeySpec; 6 import javax.crypto.spec.PBEParameterSpec; 7 8 import org.bouncycastle.crypto.CipherParameters; 9 import org.bouncycastle.crypto.PBEParametersGenerator; 10 // BEGIN android-removed 11 // import org.bouncycastle.crypto.digests.GOST3411Digest; 12 // import org.bouncycastle.crypto.digests.MD2Digest; 13 // import org.bouncycastle.crypto.digests.MD5Digest; 14 // import org.bouncycastle.crypto.digests.RIPEMD160Digest; 15 // import org.bouncycastle.crypto.digests.SHA1Digest; 16 // import org.bouncycastle.crypto.digests.SHA256Digest; 17 // import org.bouncycastle.crypto.digests.TigerDigest; 18 // END android-removed 19 // BEGIN android-added 20 import org.bouncycastle.crypto.digests.AndroidDigestFactory; 21 // END android-added 22 import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator; 23 import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator; 24 import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator; 25 import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; 26 import org.bouncycastle.crypto.params.DESParameters; 27 import org.bouncycastle.crypto.params.KeyParameter; 28 import org.bouncycastle.crypto.params.ParametersWithIV; 29 30 public interface PBE 31 { 32 // 33 // PBE Based encryption constants - by default we do PKCS12 with SHA-1 34 // 35 static final int MD5 = 0; 36 static final int SHA1 = 1; 37 // BEGIN android-removed 38 // static final int RIPEMD160 = 2; 39 // static final int TIGER = 3; 40 // END android-removed 41 static final int SHA256 = 4; 42 // BEGIN android-removed 43 // static final int MD2 = 5; 44 // static final int GOST3411 = 6; 45 // END android-removed 46 47 static final int PKCS5S1 = 0; 48 static final int PKCS5S2 = 1; 49 static final int PKCS12 = 2; 50 static final int OPENSSL = 3; 51 static final int PKCS5S1_UTF8 = 4; 52 static final int PKCS5S2_UTF8 = 5; 53 54 /** 55 * uses the appropriate mixer to generate the key and IV if necessary. 56 */ 57 static class Util 58 { makePBEGenerator( int type, int hash)59 static private PBEParametersGenerator makePBEGenerator( 60 int type, 61 int hash) 62 { 63 PBEParametersGenerator generator; 64 65 if (type == PKCS5S1 || type == PKCS5S1_UTF8) 66 { 67 switch (hash) 68 { 69 // BEGIN android-removed 70 // case MD2: 71 // generator = new PKCS5S1ParametersGenerator(new MD2Digest()); 72 // break; 73 // END android-removed 74 case MD5: 75 // BEGIN android-changed 76 generator = new PKCS5S1ParametersGenerator(AndroidDigestFactory.getMD5()); 77 // END android-changed 78 break; 79 case SHA1: 80 // BEGIN android-changed 81 generator = new PKCS5S1ParametersGenerator(AndroidDigestFactory.getSHA1()); 82 // END android-changed 83 break; 84 default: 85 throw new IllegalStateException("PKCS5 scheme 1 only supports MD2, MD5 and SHA1."); 86 } 87 } 88 else if (type == PKCS5S2 || type == PKCS5S2_UTF8) 89 { 90 switch (hash) 91 { 92 // BEGIN android-removed 93 // case MD2: 94 // generator = new PKCS5S2ParametersGenerator(new MD2Digest()); 95 // break; 96 // END android-removed 97 case MD5: 98 // BEGIN android-changed 99 generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getMD5()); 100 // END android-changed 101 break; 102 case SHA1: 103 // BEGIN android-changed 104 generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA1()); 105 // END android-changed 106 break; 107 // BEGIN android-removed 108 // case RIPEMD160: 109 // generator = new PKCS5S2ParametersGenerator(new RIPEMD160Digest()); 110 // break; 111 // case TIGER: 112 // generator = new PKCS5S2ParametersGenerator(new TigerDigest()); 113 // break; 114 // END android-removed 115 case SHA256: 116 // BEGIN android-changed 117 generator = new PKCS5S2ParametersGenerator(AndroidDigestFactory.getSHA256()); 118 // END android-changed 119 break; 120 // BEGIN android-removed 121 // case GOST3411: 122 // generator = new PKCS5S2ParametersGenerator(new GOST3411Digest()); 123 // break; 124 // END android-removed 125 default: 126 throw new IllegalStateException("unknown digest scheme for PBE PKCS5S2 encryption."); 127 } 128 } 129 else if (type == PKCS12) 130 { 131 switch (hash) 132 { 133 // BEGIN android-removed 134 // case MD2: 135 // generator = new PKCS12ParametersGenerator(new MD2Digest()); 136 // break; 137 // END android-removed 138 case MD5: 139 // BEGIN android-changed 140 generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getMD5()); 141 // END android-changed 142 break; 143 case SHA1: 144 // BEGIN android-changed 145 generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA1()); 146 // END android-changed 147 break; 148 // BEGIN android-removed 149 // case RIPEMD160: 150 // generator = new PKCS12ParametersGenerator(new RIPEMD160Digest()); 151 // break; 152 // case TIGER: 153 // generator = new PKCS12ParametersGenerator(new TigerDigest()); 154 // break; 155 // END android-removed 156 case SHA256: 157 // BEGIN android-changed 158 generator = new PKCS12ParametersGenerator(AndroidDigestFactory.getSHA256()); 159 // END android-changed 160 break; 161 // BEGIN android-removed 162 // case GOST3411: 163 // generator = new PKCS12ParametersGenerator(new GOST3411Digest()); 164 // break; 165 // END android-removed 166 default: 167 throw new IllegalStateException("unknown digest scheme for PBE encryption."); 168 } 169 } 170 else 171 { 172 generator = new OpenSSLPBEParametersGenerator(); 173 } 174 175 return generator; 176 } 177 178 /** 179 * construct a key and iv (if necessary) suitable for use with a 180 * Cipher. 181 */ makePBEParameters( BCPBEKey pbeKey, AlgorithmParameterSpec spec, String targetAlgorithm)182 public static CipherParameters makePBEParameters( 183 BCPBEKey pbeKey, 184 AlgorithmParameterSpec spec, 185 String targetAlgorithm) 186 { 187 if ((spec == null) || !(spec instanceof PBEParameterSpec)) 188 { 189 throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key."); 190 } 191 192 PBEParameterSpec pbeParam = (PBEParameterSpec)spec; 193 PBEParametersGenerator generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest()); 194 byte[] key = pbeKey.getEncoded(); 195 CipherParameters param; 196 197 if (pbeKey.shouldTryWrongPKCS12()) 198 { 199 key = new byte[2]; 200 } 201 202 generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount()); 203 204 if (pbeKey.getIvSize() != 0) 205 { 206 param = generator.generateDerivedParameters(pbeKey.getKeySize(), pbeKey.getIvSize()); 207 } 208 else 209 { 210 param = generator.generateDerivedParameters(pbeKey.getKeySize()); 211 } 212 213 if (targetAlgorithm.startsWith("DES")) 214 { 215 if (param instanceof ParametersWithIV) 216 { 217 KeyParameter kParam = (KeyParameter)((ParametersWithIV)param).getParameters(); 218 219 DESParameters.setOddParity(kParam.getKey()); 220 } 221 else 222 { 223 KeyParameter kParam = (KeyParameter)param; 224 225 DESParameters.setOddParity(kParam.getKey()); 226 } 227 } 228 229 for (int i = 0; i != key.length; i++) 230 { 231 key[i] = 0; 232 } 233 234 return param; 235 } 236 237 /** 238 * generate a PBE based key suitable for a MAC algorithm, the 239 * key size is chosen according the MAC size, or the hashing algorithm, 240 * whichever is greater. 241 */ makePBEMacParameters( BCPBEKey pbeKey, AlgorithmParameterSpec spec)242 public static CipherParameters makePBEMacParameters( 243 BCPBEKey pbeKey, 244 AlgorithmParameterSpec spec) 245 { 246 if ((spec == null) || !(spec instanceof PBEParameterSpec)) 247 { 248 throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key."); 249 } 250 251 PBEParameterSpec pbeParam = (PBEParameterSpec)spec; 252 PBEParametersGenerator generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest()); 253 byte[] key = pbeKey.getEncoded(); 254 CipherParameters param; 255 256 if (pbeKey.shouldTryWrongPKCS12()) 257 { 258 key = new byte[2]; 259 } 260 261 generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount()); 262 263 param = generator.generateDerivedMacParameters(pbeKey.getKeySize()); 264 265 for (int i = 0; i != key.length; i++) 266 { 267 key[i] = 0; 268 } 269 270 return param; 271 } 272 273 /** 274 * construct a key and iv (if necessary) suitable for use with a 275 * Cipher. 276 */ makePBEParameters( PBEKeySpec keySpec, int type, int hash, int keySize, int ivSize)277 public static CipherParameters makePBEParameters( 278 PBEKeySpec keySpec, 279 int type, 280 int hash, 281 int keySize, 282 int ivSize) 283 { 284 PBEParametersGenerator generator = makePBEGenerator(type, hash); 285 byte[] key; 286 CipherParameters param; 287 288 key = convertPassword(type, keySpec); 289 290 generator.init(key, keySpec.getSalt(), keySpec.getIterationCount()); 291 292 if (ivSize != 0) 293 { 294 param = generator.generateDerivedParameters(keySize, ivSize); 295 } 296 else 297 { 298 param = generator.generateDerivedParameters(keySize); 299 } 300 301 for (int i = 0; i != key.length; i++) 302 { 303 key[i] = 0; 304 } 305 306 return param; 307 } 308 309 310 /** 311 * generate a PBE based key suitable for a MAC algorithm, the 312 * key size is chosen according the MAC size, or the hashing algorithm, 313 * whichever is greater. 314 */ makePBEMacParameters( PBEKeySpec keySpec, int type, int hash, int keySize)315 public static CipherParameters makePBEMacParameters( 316 PBEKeySpec keySpec, 317 int type, 318 int hash, 319 int keySize) 320 { 321 PBEParametersGenerator generator = makePBEGenerator(type, hash); 322 byte[] key; 323 CipherParameters param; 324 325 key = convertPassword(type, keySpec); 326 327 generator.init(key, keySpec.getSalt(), keySpec.getIterationCount()); 328 329 param = generator.generateDerivedMacParameters(keySize); 330 331 for (int i = 0; i != key.length; i++) 332 { 333 key[i] = 0; 334 } 335 336 return param; 337 } 338 convertPassword(int type, PBEKeySpec keySpec)339 private static byte[] convertPassword(int type, PBEKeySpec keySpec) 340 { 341 byte[] key; 342 343 if (type == PKCS12) 344 { 345 key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword()); 346 } 347 else if (type == PKCS5S2_UTF8 || type == PKCS5S1_UTF8) 348 { 349 key = PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(keySpec.getPassword()); 350 } 351 else 352 { 353 key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword()); 354 } 355 return key; 356 } 357 } 358 } 359