171 protected void engineInit(int opmode, Key key, |
172 protected void engineInit(int opmode, Key key, |
172 AlgorithmParameterSpec params, |
173 AlgorithmParameterSpec params, |
173 SecureRandom random) |
174 SecureRandom random) |
174 throws InvalidKeyException, InvalidAlgorithmParameterException { |
175 throws InvalidKeyException, InvalidAlgorithmParameterException { |
175 |
176 |
176 if ((key == null) || |
177 if (key == null) { |
177 (key.getEncoded() == null) || |
178 throw new InvalidKeyException("Null key"); |
178 !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) { |
179 } |
179 throw new InvalidKeyException("Missing password"); |
180 |
180 } |
181 byte[] passwdBytes = key.getEncoded(); |
181 |
182 char[] passwdChars = null; |
182 // TBD: consolidate the salt, ic and IV parameter checks below |
183 PBEKeySpec pbeSpec; |
183 |
184 try { |
184 // Extract salt and iteration count from the key, if present |
185 if ((passwdBytes == null) || |
185 if (key instanceof javax.crypto.interfaces.PBEKey) { |
186 !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) { |
186 salt = ((javax.crypto.interfaces.PBEKey)key).getSalt(); |
187 throw new InvalidKeyException("Missing password"); |
187 if (salt != null && salt.length < 8) { |
|
188 throw new InvalidAlgorithmParameterException( |
|
189 "Salt must be at least 8 bytes long"); |
|
190 } |
188 } |
191 iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount(); |
189 |
192 if (iCount == 0) { |
190 // TBD: consolidate the salt, ic and IV parameter checks below |
193 iCount = DEFAULT_COUNT; |
191 |
194 } else if (iCount < 0) { |
192 // Extract salt and iteration count from the key, if present |
195 throw new InvalidAlgorithmParameterException( |
193 if (key instanceof javax.crypto.interfaces.PBEKey) { |
196 "Iteration count must be a positive number"); |
194 salt = ((javax.crypto.interfaces.PBEKey)key).getSalt(); |
|
195 if (salt != null && salt.length < 8) { |
|
196 throw new InvalidAlgorithmParameterException( |
|
197 "Salt must be at least 8 bytes long"); |
|
198 } |
|
199 iCount = ((javax.crypto.interfaces.PBEKey)key).getIterationCount(); |
|
200 if (iCount == 0) { |
|
201 iCount = DEFAULT_COUNT; |
|
202 } else if (iCount < 0) { |
|
203 throw new InvalidAlgorithmParameterException( |
|
204 "Iteration count must be a positive number"); |
|
205 } |
197 } |
206 } |
198 } |
207 |
199 |
208 // Extract salt, iteration count and IV from the params, if present |
200 // Extract salt, iteration count and IV from the params, if present |
209 if (params == null) { |
201 if (params == null) { |
210 if (salt == null) { |
202 if (salt == null) { |
211 // generate random salt and use default iteration count |
203 // generate random salt and use default iteration count |
212 salt = new byte[DEFAULT_SALT_LENGTH]; |
204 salt = new byte[DEFAULT_SALT_LENGTH]; |
213 random.nextBytes(salt); |
205 random.nextBytes(salt); |
214 iCount = DEFAULT_COUNT; |
206 iCount = DEFAULT_COUNT; |
215 } |
207 } |
216 if ((opmode == Cipher.ENCRYPT_MODE) || |
208 if ((opmode == Cipher.ENCRYPT_MODE) || |
|
209 (opmode == Cipher.WRAP_MODE)) { |
217 (opmode == Cipher.WRAP_MODE)) { |
210 // generate random IV |
218 // generate random IV |
211 byte[] ivBytes = new byte[blkSize]; |
219 byte[] ivBytes = new byte[blkSize]; |
212 random.nextBytes(ivBytes); |
220 random.nextBytes(ivBytes); |
213 ivSpec = new IvParameterSpec(ivBytes); |
221 ivSpec = new IvParameterSpec(ivBytes); |
214 } |
222 } |
215 } else { |
223 } else { |
216 if (!(params instanceof PBEParameterSpec)) { |
224 if (!(params instanceof PBEParameterSpec)) { |
217 throw new InvalidAlgorithmParameterException |
225 throw new InvalidAlgorithmParameterException |
218 ("Wrong parameter type: PBE expected"); |
226 ("Wrong parameter type: PBE expected"); |
219 } |
227 } |
220 // salt and iteration count from the params take precedence |
228 // salt and iteration count from the params take precedence |
221 byte[] specSalt = ((PBEParameterSpec) params).getSalt(); |
229 byte[] specSalt = ((PBEParameterSpec) params).getSalt(); |
222 if (specSalt != null && specSalt.length < 8) { |
230 if (specSalt != null && specSalt.length < 8) { |
223 throw new InvalidAlgorithmParameterException( |
231 throw new InvalidAlgorithmParameterException( |
224 "Salt must be at least 8 bytes long"); |
232 "Salt must be at least 8 bytes long"); |
225 } |
233 } |
226 salt = specSalt; |
234 salt = specSalt; |
227 int specICount = ((PBEParameterSpec) params).getIterationCount(); |
235 int specICount = ((PBEParameterSpec) params).getIterationCount(); |
228 if (specICount == 0) { |
236 if (specICount == 0) { |
229 specICount = DEFAULT_COUNT; |
237 specICount = DEFAULT_COUNT; |
230 } else if (specICount < 0) { |
238 } else if (specICount < 0) { |
231 throw new InvalidAlgorithmParameterException( |
239 throw new InvalidAlgorithmParameterException( |
232 "Iteration count must be a positive number"); |
240 "Iteration count must be a positive number"); |
233 } |
241 } |
234 iCount = specICount; |
242 iCount = specICount; |
235 |
243 |
236 AlgorithmParameterSpec specParams = |
244 AlgorithmParameterSpec specParams = |
237 ((PBEParameterSpec) params).getParameterSpec(); |
245 ((PBEParameterSpec) params).getParameterSpec(); |
238 if (specParams != null) { |
246 if (specParams != null) { |
239 if (specParams instanceof IvParameterSpec) { |
247 if (specParams instanceof IvParameterSpec) { |
240 ivSpec = (IvParameterSpec)specParams; |
248 ivSpec = (IvParameterSpec)specParams; |
|
249 } else { |
|
250 throw new InvalidAlgorithmParameterException( |
|
251 "Wrong parameter type: IV expected"); |
|
252 } |
|
253 } else if ((opmode == Cipher.ENCRYPT_MODE) || |
|
254 (opmode == Cipher.WRAP_MODE)) { |
|
255 // generate random IV |
|
256 byte[] ivBytes = new byte[blkSize]; |
|
257 random.nextBytes(ivBytes); |
|
258 ivSpec = new IvParameterSpec(ivBytes); |
241 } else { |
259 } else { |
242 throw new InvalidAlgorithmParameterException( |
260 throw new InvalidAlgorithmParameterException( |
243 "Wrong parameter type: IV expected"); |
261 "Missing parameter type: IV expected"); |
244 } |
262 } |
245 } else if ((opmode == Cipher.ENCRYPT_MODE) || |
|
246 (opmode == Cipher.WRAP_MODE)) { |
|
247 // generate random IV |
|
248 byte[] ivBytes = new byte[blkSize]; |
|
249 random.nextBytes(ivBytes); |
|
250 ivSpec = new IvParameterSpec(ivBytes); |
|
251 } else { |
|
252 throw new InvalidAlgorithmParameterException( |
|
253 "Missing parameter type: IV expected"); |
|
254 } |
263 } |
255 } |
264 |
256 |
265 passwdChars = new char[passwdBytes.length]; |
257 SecretKeySpec cipherKey = null; |
266 for (int i = 0; i < passwdChars.length; i++) |
258 byte[] derivedKey = null; |
267 passwdChars[i] = (char) (passwdBytes[i] & 0x7f); |
259 byte[] passwdBytes = key.getEncoded(); |
268 |
260 char[] passwdChars = new char[passwdBytes.length]; |
269 pbeSpec = new PBEKeySpec(passwdChars, salt, iCount, keyLength); |
261 |
|
262 for (int i=0; i<passwdChars.length; i++) |
|
263 passwdChars[i] = (char) (passwdBytes[i] & 0x7f); |
|
264 |
|
265 PBEKeySpec pbeSpec = |
|
266 new PBEKeySpec(passwdChars, salt, iCount, keyLength); |
|
267 // password char[] was cloned in PBEKeySpec constructor, |
270 // password char[] was cloned in PBEKeySpec constructor, |
268 // so we can zero it out here |
271 // so we can zero it out here |
269 java.util.Arrays.fill(passwdChars, ' '); |
272 } finally { |
270 java.util.Arrays.fill(passwdBytes, (byte)0x00); |
273 if (passwdChars != null) Arrays.fill(passwdChars, '\0'); |
|
274 if (passwdBytes != null) Arrays.fill(passwdBytes, (byte)0x00); |
|
275 } |
271 |
276 |
272 SecretKey s = null; |
277 SecretKey s = null; |
273 |
278 |
274 try { |
279 try { |
275 s = kdf.engineGenerateSecret(pbeSpec); |
280 s = kdf.engineGenerateSecret(pbeSpec); |