1 package org.bouncycastle.jce.provider; 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.MD2Digest; 12 // END android-removed 13 import org.bouncycastle.crypto.digests.MD5Digest; 14 // BEGIN android-removed 15 // import org.bouncycastle.crypto.digests.RIPEMD160Digest; 16 // END android-removed 17 import org.bouncycastle.crypto.digests.SHA1Digest; 18 import org.bouncycastle.crypto.digests.SHA256Digest; 19 // BEGIN android-removed 20 // import org.bouncycastle.crypto.digests.TigerDigest; 21 // END android-removed 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 static final int RIPEMD160 = 2; 38 static final int TIGER = 3; 39 static final int SHA256 = 4; 40 static final int MD2 = 5; 41 42 static final int PKCS5S1 = 0; 43 static final int PKCS5S2 = 1; 44 static final int PKCS12 = 2; 45 static final int OPENSSL = 3; 46 47 /** 48 * uses the appropriate mixer to generate the key and IV if necessary. 49 */ 50 static class Util 51 { makePBEGenerator( int type, int hash)52 static private PBEParametersGenerator makePBEGenerator( 53 int type, 54 int hash) 55 { 56 PBEParametersGenerator generator; 57 58 if (type == PKCS5S1) 59 { 60 switch (hash) 61 { 62 // BEGIN android-removed 63 // case MD2: 64 // generator = new PKCS5S1ParametersGenerator(new MD2Digest()); 65 // break; 66 // END android-removed 67 case MD5: 68 generator = new PKCS5S1ParametersGenerator(new MD5Digest()); 69 break; 70 case SHA1: 71 generator = new PKCS5S1ParametersGenerator(new SHA1Digest()); 72 break; 73 default: 74 throw new IllegalStateException("PKCS5 scheme 1 only supports MD2, MD5 and SHA1."); 75 } 76 } 77 else if (type == PKCS5S2) 78 { 79 generator = new PKCS5S2ParametersGenerator(); 80 } 81 else if (type == PKCS12) 82 { 83 switch (hash) 84 { 85 // BEGIN android-removed 86 // case MD2: 87 // generator = new PKCS12ParametersGenerator(new MD2Digest()); 88 // break; 89 // END android-removed 90 case MD5: 91 generator = new PKCS12ParametersGenerator(new MD5Digest()); 92 break; 93 case SHA1: 94 generator = new PKCS12ParametersGenerator(new SHA1Digest()); 95 break; 96 // BEGIN android-removed 97 // case RIPEMD160: 98 // generator = new PKCS12ParametersGenerator(new RIPEMD160Digest()); 99 // break; 100 // case TIGER: 101 // generator = new PKCS12ParametersGenerator(new TigerDigest()); 102 // break; 103 // END android-removed 104 case SHA256: 105 generator = new PKCS12ParametersGenerator(new SHA256Digest()); 106 break; 107 default: 108 throw new IllegalStateException("unknown digest scheme for PBE encryption."); 109 } 110 } 111 else 112 { 113 generator = new OpenSSLPBEParametersGenerator(); 114 } 115 116 return generator; 117 } 118 119 /** 120 * construct a key and iv (if necessary) suitable for use with a 121 * Cipher. 122 */ makePBEParameters( JCEPBEKey pbeKey, AlgorithmParameterSpec spec, String targetAlgorithm)123 static CipherParameters makePBEParameters( 124 JCEPBEKey pbeKey, 125 AlgorithmParameterSpec spec, 126 String targetAlgorithm) 127 { 128 if ((spec == null) || !(spec instanceof PBEParameterSpec)) 129 { 130 throw new IllegalArgumentException("Need a PBEParameter spec with a PBE key."); 131 } 132 133 PBEParameterSpec pbeParam = (PBEParameterSpec)spec; 134 PBEParametersGenerator generator = makePBEGenerator(pbeKey.getType(), pbeKey.getDigest()); 135 byte[] key = pbeKey.getEncoded(); 136 CipherParameters param; 137 138 if (pbeKey.shouldTryWrongPKCS12()) 139 { 140 key = new byte[2]; 141 } 142 143 generator.init(key, pbeParam.getSalt(), pbeParam.getIterationCount()); 144 145 if (pbeKey.getIvSize() != 0) 146 { 147 param = generator.generateDerivedParameters(pbeKey.getKeySize(), pbeKey.getIvSize()); 148 } 149 else 150 { 151 param = generator.generateDerivedParameters(pbeKey.getKeySize()); 152 } 153 154 if (targetAlgorithm.startsWith("DES")) 155 { 156 if (param instanceof ParametersWithIV) 157 { 158 KeyParameter kParam = (KeyParameter)((ParametersWithIV)param).getParameters(); 159 160 DESParameters.setOddParity(kParam.getKey()); 161 } 162 else 163 { 164 KeyParameter kParam = (KeyParameter)param; 165 166 DESParameters.setOddParity(kParam.getKey()); 167 } 168 } 169 170 for (int i = 0; i != key.length; i++) 171 { 172 key[i] = 0; 173 } 174 175 return param; 176 } 177 178 /** 179 * generate a PBE based key suitable for a MAC algorithm, the 180 * key size is chosen according the MAC size, or the hashing algorithm, 181 * whichever is greater. 182 */ makePBEMacParameters( JCEPBEKey pbeKey, AlgorithmParameterSpec spec)183 static CipherParameters makePBEMacParameters( 184 JCEPBEKey pbeKey, 185 AlgorithmParameterSpec spec) 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 param = generator.generateDerivedMacParameters(pbeKey.getKeySize()); 205 206 for (int i = 0; i != key.length; i++) 207 { 208 key[i] = 0; 209 } 210 211 return param; 212 } 213 214 /** 215 * construct a key and iv (if necessary) suitable for use with a 216 * Cipher. 217 */ makePBEParameters( PBEKeySpec keySpec, int type, int hash, int keySize, int ivSize)218 static CipherParameters makePBEParameters( 219 PBEKeySpec keySpec, 220 int type, 221 int hash, 222 int keySize, 223 int ivSize) 224 { 225 PBEParametersGenerator generator = makePBEGenerator(type, hash); 226 byte[] key; 227 CipherParameters param; 228 229 if (type == PKCS12) 230 { 231 key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword()); 232 } 233 else 234 { 235 key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword()); 236 } 237 238 generator.init(key, keySpec.getSalt(), keySpec.getIterationCount()); 239 240 if (ivSize != 0) 241 { 242 param = generator.generateDerivedParameters(keySize, ivSize); 243 } 244 else 245 { 246 param = generator.generateDerivedParameters(keySize); 247 } 248 249 for (int i = 0; i != key.length; i++) 250 { 251 key[i] = 0; 252 } 253 254 return param; 255 } 256 257 /** 258 * generate a PBE based key suitable for a MAC algorithm, the 259 * key size is chosen according the MAC size, or the hashing algorithm, 260 * whichever is greater. 261 */ makePBEMacParameters( PBEKeySpec keySpec, int type, int hash, int keySize)262 static CipherParameters makePBEMacParameters( 263 PBEKeySpec keySpec, 264 int type, 265 int hash, 266 int keySize) 267 { 268 PBEParametersGenerator generator = makePBEGenerator(type, hash); 269 byte[] key; 270 CipherParameters param; 271 272 if (type == PKCS12) 273 { 274 key = PBEParametersGenerator.PKCS12PasswordToBytes(keySpec.getPassword()); 275 } 276 else 277 { 278 key = PBEParametersGenerator.PKCS5PasswordToBytes(keySpec.getPassword()); 279 } 280 281 generator.init(key, keySpec.getSalt(), keySpec.getIterationCount()); 282 283 param = generator.generateDerivedMacParameters(keySize); 284 285 for (int i = 0; i != key.length; i++) 286 { 287 key[i] = 0; 288 } 289 290 return param; 291 } 292 } 293 } 294