|
1 /* |
|
2 * Copyright 1997-2007 Sun Microsystems, Inc. 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. Sun designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 * have any questions. |
|
24 */ |
|
25 |
|
26 package javax.crypto; |
|
27 |
|
28 import java.util.*; |
|
29 import java.util.regex.*; |
|
30 |
|
31 import static java.util.Locale.ENGLISH; |
|
32 |
|
33 import java.security.*; |
|
34 import java.security.Provider.Service; |
|
35 import java.security.spec.AlgorithmParameterSpec; |
|
36 import java.security.spec.InvalidParameterSpecException; |
|
37 import java.security.cert.Certificate; |
|
38 import java.security.cert.X509Certificate; |
|
39 |
|
40 import javax.crypto.spec.*; |
|
41 |
|
42 import java.nio.ByteBuffer; |
|
43 import java.nio.ReadOnlyBufferException; |
|
44 |
|
45 import sun.security.util.Debug; |
|
46 import sun.security.jca.*; |
|
47 import sun.security.jca.GetInstance.Instance; |
|
48 |
|
49 /** |
|
50 * This class provides the functionality of a cryptographic cipher for |
|
51 * encryption and decryption. It forms the core of the Java Cryptographic |
|
52 * Extension (JCE) framework. |
|
53 * |
|
54 * <p>In order to create a Cipher object, the application calls the |
|
55 * Cipher's <code>getInstance</code> method, and passes the name of the |
|
56 * requested <i>transformation</i> to it. Optionally, the name of a provider |
|
57 * may be specified. |
|
58 * |
|
59 * <p>A <i>transformation</i> is a string that describes the operation (or |
|
60 * set of operations) to be performed on the given input, to produce some |
|
61 * output. A transformation always includes the name of a cryptographic |
|
62 * algorithm (e.g., <i>DES</i>), and may be followed by a feedback mode and |
|
63 * padding scheme. |
|
64 * |
|
65 * <p> A transformation is of the form:<p> |
|
66 * |
|
67 * <ul> |
|
68 * <li>"<i>algorithm/mode/padding</i>" or |
|
69 * <p> |
|
70 * <li>"<i>algorithm</i>" |
|
71 * </ul> |
|
72 * |
|
73 * <P> (in the latter case, |
|
74 * provider-specific default values for the mode and padding scheme are used). |
|
75 * For example, the following is a valid transformation:<p> |
|
76 * |
|
77 * <pre> |
|
78 * Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>"); |
|
79 * </pre> |
|
80 * |
|
81 * Using modes such as <code>CFB</code> and <code>OFB<code>, block |
|
82 * ciphers can encrypt data in units smaller than the cipher's actual |
|
83 * block size. When requesting such a mode, you may optionally specify |
|
84 * the number of bits to be processed at a time by appending this number |
|
85 * to the mode name as shown in the "<code>DES/CFB8/NoPadding</code>" and |
|
86 * "<code>DES/OFB32/PKCS5Padding</code>" transformations. If no such |
|
87 * number is specified, a provider-specific default is used. (For |
|
88 * example, the SunJCE provider uses a default of 64 bits for DES.) |
|
89 * Thus, block ciphers can be turned into byte-oriented stream ciphers by |
|
90 * using an 8 bit mode such as CFB8 or OFB8. |
|
91 * |
|
92 * @author Jan Luehe |
|
93 * @see KeyGenerator |
|
94 * @see SecretKey |
|
95 * @since 1.4 |
|
96 */ |
|
97 |
|
98 public class Cipher { |
|
99 |
|
100 private static final Debug debug = |
|
101 Debug.getInstance("jca", "Cipher"); |
|
102 |
|
103 /** |
|
104 * Constant used to initialize cipher to encryption mode. |
|
105 */ |
|
106 public static final int ENCRYPT_MODE = 1; |
|
107 |
|
108 /** |
|
109 * Constant used to initialize cipher to decryption mode. |
|
110 */ |
|
111 public static final int DECRYPT_MODE = 2; |
|
112 |
|
113 /** |
|
114 * Constant used to initialize cipher to key-wrapping mode. |
|
115 */ |
|
116 public static final int WRAP_MODE = 3; |
|
117 |
|
118 /** |
|
119 * Constant used to initialize cipher to key-unwrapping mode. |
|
120 */ |
|
121 public static final int UNWRAP_MODE = 4; |
|
122 |
|
123 /** |
|
124 * Constant used to indicate the to-be-unwrapped key is a "public key". |
|
125 */ |
|
126 public static final int PUBLIC_KEY = 1; |
|
127 |
|
128 /** |
|
129 * Constant used to indicate the to-be-unwrapped key is a "private key". |
|
130 */ |
|
131 public static final int PRIVATE_KEY = 2; |
|
132 |
|
133 /** |
|
134 * Constant used to indicate the to-be-unwrapped key is a "secret key". |
|
135 */ |
|
136 public static final int SECRET_KEY = 3; |
|
137 |
|
138 // The provider |
|
139 private Provider provider; |
|
140 |
|
141 // The provider implementation (delegate) |
|
142 private CipherSpi spi; |
|
143 |
|
144 // The transformation |
|
145 private String transformation; |
|
146 |
|
147 // Crypto permission representing the maximum allowable cryptographic |
|
148 // strength that this Cipher object can be used for. (The cryptographic |
|
149 // strength is a function of the keysize and algorithm parameters encoded |
|
150 // in the crypto permission.) |
|
151 private CryptoPermission cryptoPerm; |
|
152 |
|
153 // The exemption mechanism that needs to be enforced |
|
154 private ExemptionMechanism exmech; |
|
155 |
|
156 // Flag which indicates whether or not this cipher has been initialized |
|
157 private boolean initialized = false; |
|
158 |
|
159 // The operation mode - store the operation mode after the |
|
160 // cipher has been initialized. |
|
161 private int opmode = 0; |
|
162 |
|
163 // The OID for the KeyUsage extension in an X.509 v3 certificate |
|
164 private static final String KEY_USAGE_EXTENSION_OID = "2.5.29.15"; |
|
165 |
|
166 // next SPI to try in provider selection |
|
167 // null once provider is selected |
|
168 private CipherSpi firstSpi; |
|
169 |
|
170 // next service to try in provider selection |
|
171 // null once provider is selected |
|
172 private Service firstService; |
|
173 |
|
174 // remaining services to try in provider selection |
|
175 // null once provider is selected |
|
176 private Iterator serviceIterator; |
|
177 |
|
178 // list of transform Strings to lookup in the provider |
|
179 private List transforms; |
|
180 |
|
181 private final Object lock; |
|
182 |
|
183 /** |
|
184 * Creates a Cipher object. |
|
185 * |
|
186 * @param cipherSpi the delegate |
|
187 * @param provider the provider |
|
188 * @param transformation the transformation |
|
189 */ |
|
190 protected Cipher(CipherSpi cipherSpi, |
|
191 Provider provider, |
|
192 String transformation) { |
|
193 // See bug 4341369 & 4334690 for more info. |
|
194 // If the caller is trusted, then okey. |
|
195 // Otherwise throw a NullPointerException. |
|
196 if (!JceSecurityManager.INSTANCE.isCallerTrusted()) { |
|
197 throw new NullPointerException(); |
|
198 } |
|
199 this.spi = cipherSpi; |
|
200 this.provider = provider; |
|
201 this.transformation = transformation; |
|
202 this.cryptoPerm = CryptoAllPermission.INSTANCE; |
|
203 this.lock = null; |
|
204 } |
|
205 |
|
206 /** |
|
207 * Creates a Cipher object. Called internally and by NullCipher. |
|
208 * |
|
209 * @param cipherSpi the delegate |
|
210 * @param transformation the transformation |
|
211 */ |
|
212 Cipher(CipherSpi cipherSpi, String transformation) { |
|
213 this.spi = cipherSpi; |
|
214 this.transformation = transformation; |
|
215 this.cryptoPerm = CryptoAllPermission.INSTANCE; |
|
216 this.lock = null; |
|
217 } |
|
218 |
|
219 private Cipher(CipherSpi firstSpi, Service firstService, |
|
220 Iterator serviceIterator, String transformation, List transforms) { |
|
221 this.firstSpi = firstSpi; |
|
222 this.firstService = firstService; |
|
223 this.serviceIterator = serviceIterator; |
|
224 this.transforms = transforms; |
|
225 this.transformation = transformation; |
|
226 this.lock = new Object(); |
|
227 } |
|
228 |
|
229 private static String[] tokenizeTransformation(String transformation) |
|
230 throws NoSuchAlgorithmException { |
|
231 if (transformation == null) { |
|
232 throw new NoSuchAlgorithmException("No transformation given"); |
|
233 } |
|
234 /* |
|
235 * array containing the components of a Cipher transformation: |
|
236 * |
|
237 * index 0: algorithm component (e.g., DES) |
|
238 * index 1: feedback component (e.g., CFB) |
|
239 * index 2: padding component (e.g., PKCS5Padding) |
|
240 */ |
|
241 String[] parts = new String[3]; |
|
242 int count = 0; |
|
243 StringTokenizer parser = new StringTokenizer(transformation, "/"); |
|
244 try { |
|
245 while (parser.hasMoreTokens() && count < 3) { |
|
246 parts[count++] = parser.nextToken().trim(); |
|
247 } |
|
248 if (count == 0 || count == 2 || parser.hasMoreTokens()) { |
|
249 throw new NoSuchAlgorithmException("Invalid transformation" |
|
250 + " format:" + |
|
251 transformation); |
|
252 } |
|
253 } catch (NoSuchElementException e) { |
|
254 throw new NoSuchAlgorithmException("Invalid transformation " + |
|
255 "format:" + transformation); |
|
256 } |
|
257 if ((parts[0] == null) || (parts[0].length() == 0)) { |
|
258 throw new NoSuchAlgorithmException("Invalid transformation:" + |
|
259 "algorithm not specified-" |
|
260 + transformation); |
|
261 } |
|
262 return parts; |
|
263 } |
|
264 |
|
265 // Provider attribute name for supported chaining mode |
|
266 private final static String ATTR_MODE = "SupportedModes"; |
|
267 // Provider attribute name for supported padding names |
|
268 private final static String ATTR_PAD = "SupportedPaddings"; |
|
269 |
|
270 // constants indicating whether the provider supports |
|
271 // a given mode or padding |
|
272 private final static int S_NO = 0; // does not support |
|
273 private final static int S_MAYBE = 1; // unable to determine |
|
274 private final static int S_YES = 2; // does support |
|
275 |
|
276 /** |
|
277 * Nested class to deal with modes and paddings. |
|
278 */ |
|
279 private static class Transform { |
|
280 // transform string to lookup in the provider |
|
281 final String transform; |
|
282 // the mode/padding suffix in upper case. for example, if the algorithm |
|
283 // to lookup is "DES/CBC/PKCS5Padding" suffix is "/CBC/PKCS5PADDING" |
|
284 // if loopup is "DES", suffix is the empty string |
|
285 // needed because aliases prevent straight transform.equals() |
|
286 final String suffix; |
|
287 // value to pass to setMode() or null if no such call required |
|
288 final String mode; |
|
289 // value to pass to setPadding() or null if no such call required |
|
290 final String pad; |
|
291 Transform(String alg, String suffix, String mode, String pad) { |
|
292 this.transform = alg + suffix; |
|
293 this.suffix = suffix.toUpperCase(Locale.ENGLISH); |
|
294 this.mode = mode; |
|
295 this.pad = pad; |
|
296 } |
|
297 // set mode and padding for the given SPI |
|
298 void setModePadding(CipherSpi spi) throws NoSuchAlgorithmException, |
|
299 NoSuchPaddingException { |
|
300 if (mode != null) { |
|
301 spi.engineSetMode(mode); |
|
302 } |
|
303 if (pad != null) { |
|
304 spi.engineSetPadding(pad); |
|
305 } |
|
306 } |
|
307 // check whether the given services supports the mode and |
|
308 // padding described by this Transform |
|
309 int supportsModePadding(Service s) { |
|
310 int smode = supportsMode(s); |
|
311 if (smode == S_NO) { |
|
312 return smode; |
|
313 } |
|
314 int spad = supportsPadding(s); |
|
315 // our constants are defined so that Math.min() is a tri-valued AND |
|
316 return Math.min(smode, spad); |
|
317 } |
|
318 |
|
319 // separate methods for mode and padding |
|
320 // called directly by Cipher only to throw the correct exception |
|
321 int supportsMode(Service s) { |
|
322 return supports(s, ATTR_MODE, mode); |
|
323 } |
|
324 int supportsPadding(Service s) { |
|
325 return supports(s, ATTR_PAD, pad); |
|
326 } |
|
327 |
|
328 private static int supports(Service s, String attrName, String value) { |
|
329 if (value == null) { |
|
330 return S_YES; |
|
331 } |
|
332 String regexp = s.getAttribute(attrName); |
|
333 if (regexp == null) { |
|
334 return S_MAYBE; |
|
335 } |
|
336 return matches(regexp, value) ? S_YES : S_NO; |
|
337 } |
|
338 |
|
339 // Map<String,Pattern> for previously compiled patterns |
|
340 // XXX use ConcurrentHashMap once available |
|
341 private final static Map patternCache = |
|
342 Collections.synchronizedMap(new HashMap()); |
|
343 |
|
344 private static boolean matches(String regexp, String str) { |
|
345 Pattern pattern = (Pattern)patternCache.get(regexp); |
|
346 if (pattern == null) { |
|
347 pattern = Pattern.compile(regexp); |
|
348 patternCache.put(regexp, pattern); |
|
349 } |
|
350 return pattern.matcher(str.toUpperCase(Locale.ENGLISH)).matches(); |
|
351 } |
|
352 |
|
353 } |
|
354 |
|
355 private static List getTransforms(String transformation) |
|
356 throws NoSuchAlgorithmException { |
|
357 String[] parts = tokenizeTransformation(transformation); |
|
358 |
|
359 String alg = parts[0]; |
|
360 String mode = parts[1]; |
|
361 String pad = parts[2]; |
|
362 if ((mode != null) && (mode.length() == 0)) { |
|
363 mode = null; |
|
364 } |
|
365 if ((pad != null) && (pad.length() == 0)) { |
|
366 pad = null; |
|
367 } |
|
368 |
|
369 if ((mode == null) && (pad == null)) { |
|
370 // DES |
|
371 Transform tr = new Transform(alg, "", null, null); |
|
372 return Collections.singletonList(tr); |
|
373 } else { // if ((mode != null) && (pad != null)) { |
|
374 // DES/CBC/PKCS5Padding |
|
375 List list = new ArrayList(4); |
|
376 list.add(new Transform(alg, "/" + mode + "/" + pad, null, null)); |
|
377 list.add(new Transform(alg, "/" + mode, null, pad)); |
|
378 list.add(new Transform(alg, "//" + pad, mode, null)); |
|
379 list.add(new Transform(alg, "", mode, pad)); |
|
380 return list; |
|
381 } |
|
382 } |
|
383 |
|
384 // get the transform matching the specified service |
|
385 private static Transform getTransform(Service s, List transforms) { |
|
386 String alg = s.getAlgorithm().toUpperCase(Locale.ENGLISH); |
|
387 for (Iterator t = transforms.iterator(); t.hasNext(); ) { |
|
388 Transform tr = (Transform)t.next(); |
|
389 if (alg.endsWith(tr.suffix)) { |
|
390 return tr; |
|
391 } |
|
392 } |
|
393 return null; |
|
394 } |
|
395 |
|
396 /** |
|
397 * Returns a <code>Cipher</code> object that implements the specified |
|
398 * transformation. |
|
399 * |
|
400 * <p> This method traverses the list of registered security Providers, |
|
401 * starting with the most preferred Provider. |
|
402 * A new Cipher object encapsulating the |
|
403 * CipherSpi implementation from the first |
|
404 * Provider that supports the specified algorithm is returned. |
|
405 * |
|
406 * <p> Note that the list of registered providers may be retrieved via |
|
407 * the {@link Security#getProviders() Security.getProviders()} method. |
|
408 * |
|
409 * @param transformation the name of the transformation, e.g., |
|
410 * <i>DES/CBC/PKCS5Padding</i>. |
|
411 * See Appendix A in the |
|
412 * <a href= |
|
413 * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA"> |
|
414 * Java Cryptography Architecture Reference Guide</a> |
|
415 * for information about standard transformation names. |
|
416 * |
|
417 * @return a cipher that implements the requested transformation. |
|
418 * |
|
419 * @exception NoSuchAlgorithmException if <code>transformation</code> |
|
420 * is null, empty, in an invalid format, |
|
421 * or if no Provider supports a CipherSpi implementation for the |
|
422 * specified algorithm. |
|
423 * |
|
424 * @exception NoSuchPaddingException if <code>transformation</code> |
|
425 * contains a padding scheme that is not available. |
|
426 * |
|
427 * @see java.security.Provider |
|
428 */ |
|
429 public static final Cipher getInstance(String transformation) |
|
430 throws NoSuchAlgorithmException, NoSuchPaddingException |
|
431 { |
|
432 List transforms = getTransforms(transformation); |
|
433 List cipherServices = new ArrayList(transforms.size()); |
|
434 for (Iterator t = transforms.iterator(); t.hasNext(); ) { |
|
435 Transform transform = (Transform)t.next(); |
|
436 cipherServices.add(new ServiceId("Cipher", transform.transform)); |
|
437 } |
|
438 List services = GetInstance.getServices(cipherServices); |
|
439 // make sure there is at least one service from a signed provider |
|
440 // and that it can use the specified mode and padding |
|
441 Iterator t = services.iterator(); |
|
442 Exception failure = null; |
|
443 while (t.hasNext()) { |
|
444 Service s = (Service)t.next(); |
|
445 if (JceSecurity.canUseProvider(s.getProvider()) == false) { |
|
446 continue; |
|
447 } |
|
448 Transform tr = getTransform(s, transforms); |
|
449 if (tr == null) { |
|
450 // should never happen |
|
451 continue; |
|
452 } |
|
453 int canuse = tr.supportsModePadding(s); |
|
454 if (canuse == S_NO) { |
|
455 // does not support mode or padding we need, ignore |
|
456 continue; |
|
457 } |
|
458 if (canuse == S_YES) { |
|
459 return new Cipher(null, s, t, transformation, transforms); |
|
460 } else { // S_MAYBE, try out if it works |
|
461 try { |
|
462 CipherSpi spi = (CipherSpi)s.newInstance(null); |
|
463 tr.setModePadding(spi); |
|
464 return new Cipher(spi, s, t, transformation, transforms); |
|
465 } catch (Exception e) { |
|
466 failure = e; |
|
467 } |
|
468 } |
|
469 } |
|
470 throw new NoSuchAlgorithmException |
|
471 ("Cannot find any provider supporting " + transformation, failure); |
|
472 } |
|
473 |
|
474 /** |
|
475 * Returns a <code>Cipher</code> object that implements the specified |
|
476 * transformation. |
|
477 * |
|
478 * <p> A new Cipher object encapsulating the |
|
479 * CipherSpi implementation from the specified provider |
|
480 * is returned. The specified provider must be registered |
|
481 * in the security provider list. |
|
482 * |
|
483 * <p> Note that the list of registered providers may be retrieved via |
|
484 * the {@link Security#getProviders() Security.getProviders()} method. |
|
485 * |
|
486 * @param transformation the name of the transformation, |
|
487 * e.g., <i>DES/CBC/PKCS5Padding</i>. |
|
488 * See Appendix A in the |
|
489 * <a href= |
|
490 * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA"> |
|
491 * Java Cryptography Architecture Reference Guide</a> |
|
492 * for information about standard transformation names. |
|
493 * |
|
494 * @param provider the name of the provider. |
|
495 * |
|
496 * @return a cipher that implements the requested transformation. |
|
497 * |
|
498 * @exception NoSuchAlgorithmException if <code>transformation</code> |
|
499 * is null, empty, in an invalid format, |
|
500 * or if a CipherSpi implementation for the specified algorithm |
|
501 * is not available from the specified provider. |
|
502 * |
|
503 * @exception NoSuchProviderException if the specified provider is not |
|
504 * registered in the security provider list. |
|
505 * |
|
506 * @exception NoSuchPaddingException if <code>transformation</code> |
|
507 * contains a padding scheme that is not available. |
|
508 * |
|
509 * @exception IllegalArgumentException if the <code>provider</code> |
|
510 * is null or empty. |
|
511 * |
|
512 * @see java.security.Provider |
|
513 */ |
|
514 public static final Cipher getInstance(String transformation, |
|
515 String provider) |
|
516 throws NoSuchAlgorithmException, NoSuchProviderException, |
|
517 NoSuchPaddingException |
|
518 { |
|
519 if ((provider == null) || (provider.length() == 0)) { |
|
520 throw new IllegalArgumentException("Missing provider"); |
|
521 } |
|
522 Provider p = Security.getProvider(provider); |
|
523 if (p == null) { |
|
524 throw new NoSuchProviderException("No such provider: " + |
|
525 provider); |
|
526 } |
|
527 return getInstance(transformation, p); |
|
528 } |
|
529 |
|
530 /** |
|
531 * Returns a <code>Cipher</code> object that implements the specified |
|
532 * transformation. |
|
533 * |
|
534 * <p> A new Cipher object encapsulating the |
|
535 * CipherSpi implementation from the specified Provider |
|
536 * object is returned. Note that the specified Provider object |
|
537 * does not have to be registered in the provider list. |
|
538 * |
|
539 * @param transformation the name of the transformation, |
|
540 * e.g., <i>DES/CBC/PKCS5Padding</i>. |
|
541 * See Appendix A in the |
|
542 * <a href= |
|
543 * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppA"> |
|
544 * Java Cryptography Architecture Reference Guide</a> |
|
545 * for information about standard transformation names. |
|
546 * |
|
547 * @param provider the provider. |
|
548 * |
|
549 * @return a cipher that implements the requested transformation. |
|
550 * |
|
551 * @exception NoSuchAlgorithmException if <code>transformation</code> |
|
552 * is null, empty, in an invalid format, |
|
553 * or if a CipherSpi implementation for the specified algorithm |
|
554 * is not available from the specified Provider object. |
|
555 * |
|
556 * @exception NoSuchPaddingException if <code>transformation</code> |
|
557 * contains a padding scheme that is not available. |
|
558 * |
|
559 * @exception IllegalArgumentException if the <code>provider</code> |
|
560 * is null. |
|
561 * |
|
562 * @see java.security.Provider |
|
563 */ |
|
564 public static final Cipher getInstance(String transformation, |
|
565 Provider provider) |
|
566 throws NoSuchAlgorithmException, NoSuchPaddingException |
|
567 { |
|
568 if (provider == null) { |
|
569 throw new IllegalArgumentException("Missing provider"); |
|
570 } |
|
571 Exception failure = null; |
|
572 List transforms = getTransforms(transformation); |
|
573 boolean providerChecked = false; |
|
574 String paddingError = null; |
|
575 for (Iterator t = transforms.iterator(); t.hasNext();) { |
|
576 Transform tr = (Transform)t.next(); |
|
577 Service s = provider.getService("Cipher", tr.transform); |
|
578 if (s == null) { |
|
579 continue; |
|
580 } |
|
581 if (providerChecked == false) { |
|
582 // for compatibility, first do the lookup and then verify |
|
583 // the provider. this makes the difference between a NSAE |
|
584 // and a SecurityException if the |
|
585 // provider does not support the algorithm. |
|
586 Exception ve = JceSecurity.getVerificationResult(provider); |
|
587 if (ve != null) { |
|
588 String msg = "JCE cannot authenticate the provider " |
|
589 + provider.getName(); |
|
590 throw new SecurityException(msg, ve); |
|
591 } |
|
592 providerChecked = true; |
|
593 } |
|
594 if (tr.supportsMode(s) == S_NO) { |
|
595 continue; |
|
596 } |
|
597 if (tr.supportsPadding(s) == S_NO) { |
|
598 paddingError = tr.pad; |
|
599 continue; |
|
600 } |
|
601 try { |
|
602 CipherSpi spi = (CipherSpi)s.newInstance(null); |
|
603 tr.setModePadding(spi); |
|
604 Cipher cipher = new Cipher(spi, transformation); |
|
605 cipher.provider = s.getProvider(); |
|
606 cipher.initCryptoPermission(); |
|
607 return cipher; |
|
608 } catch (Exception e) { |
|
609 failure = e; |
|
610 } |
|
611 } |
|
612 |
|
613 // throw NoSuchPaddingException if the problem is with padding |
|
614 if (failure instanceof NoSuchPaddingException) { |
|
615 throw (NoSuchPaddingException)failure; |
|
616 } |
|
617 if (paddingError != null) { |
|
618 throw new NoSuchPaddingException |
|
619 ("Padding not supported: " + paddingError); |
|
620 } |
|
621 throw new NoSuchAlgorithmException |
|
622 ("No such algorithm: " + transformation, failure); |
|
623 } |
|
624 |
|
625 // If the requested crypto service is export-controlled, |
|
626 // determine the maximum allowable keysize. |
|
627 private void initCryptoPermission() throws NoSuchAlgorithmException { |
|
628 if (JceSecurity.isRestricted() == false) { |
|
629 cryptoPerm = CryptoAllPermission.INSTANCE; |
|
630 exmech = null; |
|
631 return; |
|
632 } |
|
633 cryptoPerm = getConfiguredPermission(transformation); |
|
634 // Instantiate the exemption mechanism (if required) |
|
635 String exmechName = cryptoPerm.getExemptionMechanism(); |
|
636 if (exmechName != null) { |
|
637 exmech = ExemptionMechanism.getInstance(exmechName); |
|
638 } |
|
639 } |
|
640 |
|
641 // max number of debug warnings to print from chooseFirstProvider() |
|
642 private static int warnCount = 10; |
|
643 |
|
644 /** |
|
645 * Choose the Spi from the first provider available. Used if |
|
646 * delayed provider selection is not possible because init() |
|
647 * is not the first method called. |
|
648 */ |
|
649 void chooseFirstProvider() { |
|
650 if (spi != null) { |
|
651 return; |
|
652 } |
|
653 synchronized (lock) { |
|
654 if (spi != null) { |
|
655 return; |
|
656 } |
|
657 if (debug != null) { |
|
658 int w = --warnCount; |
|
659 if (w >= 0) { |
|
660 debug.println("Cipher.init() not first method " |
|
661 + "called, disabling delayed provider selection"); |
|
662 if (w == 0) { |
|
663 debug.println("Further warnings of this type will " |
|
664 + "be suppressed"); |
|
665 } |
|
666 new Exception("Call trace").printStackTrace(); |
|
667 } |
|
668 } |
|
669 Exception lastException = null; |
|
670 while ((firstService != null) || serviceIterator.hasNext()) { |
|
671 Service s; |
|
672 CipherSpi thisSpi; |
|
673 if (firstService != null) { |
|
674 s = firstService; |
|
675 thisSpi = firstSpi; |
|
676 firstService = null; |
|
677 firstSpi = null; |
|
678 } else { |
|
679 s = (Service)serviceIterator.next(); |
|
680 thisSpi = null; |
|
681 } |
|
682 if (JceSecurity.canUseProvider(s.getProvider()) == false) { |
|
683 continue; |
|
684 } |
|
685 Transform tr = getTransform(s, transforms); |
|
686 if (tr == null) { |
|
687 // should never happen |
|
688 continue; |
|
689 } |
|
690 if (tr.supportsModePadding(s) == S_NO) { |
|
691 continue; |
|
692 } |
|
693 try { |
|
694 if (thisSpi == null) { |
|
695 Object obj = s.newInstance(null); |
|
696 if (obj instanceof CipherSpi == false) { |
|
697 continue; |
|
698 } |
|
699 thisSpi = (CipherSpi)obj; |
|
700 } |
|
701 tr.setModePadding(thisSpi); |
|
702 initCryptoPermission(); |
|
703 spi = thisSpi; |
|
704 provider = s.getProvider(); |
|
705 // not needed any more |
|
706 firstService = null; |
|
707 serviceIterator = null; |
|
708 transforms = null; |
|
709 return; |
|
710 } catch (Exception e) { |
|
711 lastException = e; |
|
712 } |
|
713 } |
|
714 ProviderException e = new ProviderException |
|
715 ("Could not construct CipherSpi instance"); |
|
716 if (lastException != null) { |
|
717 e.initCause(lastException); |
|
718 } |
|
719 throw e; |
|
720 } |
|
721 } |
|
722 |
|
723 private final static int I_KEY = 1; |
|
724 private final static int I_PARAMSPEC = 2; |
|
725 private final static int I_PARAMS = 3; |
|
726 private final static int I_CERT = 4; |
|
727 |
|
728 private void implInit(CipherSpi thisSpi, int type, int opmode, Key key, |
|
729 AlgorithmParameterSpec paramSpec, AlgorithmParameters params, |
|
730 SecureRandom random) throws InvalidKeyException, |
|
731 InvalidAlgorithmParameterException { |
|
732 switch (type) { |
|
733 case I_KEY: |
|
734 checkCryptoPerm(thisSpi, key); |
|
735 thisSpi.engineInit(opmode, key, random); |
|
736 break; |
|
737 case I_PARAMSPEC: |
|
738 checkCryptoPerm(thisSpi, key, paramSpec); |
|
739 thisSpi.engineInit(opmode, key, paramSpec, random); |
|
740 break; |
|
741 case I_PARAMS: |
|
742 checkCryptoPerm(thisSpi, key, params); |
|
743 thisSpi.engineInit(opmode, key, params, random); |
|
744 break; |
|
745 case I_CERT: |
|
746 checkCryptoPerm(thisSpi, key); |
|
747 thisSpi.engineInit(opmode, key, random); |
|
748 break; |
|
749 default: |
|
750 throw new AssertionError("Internal Cipher error: " + type); |
|
751 } |
|
752 } |
|
753 |
|
754 private void chooseProvider(int initType, int opmode, Key key, |
|
755 AlgorithmParameterSpec paramSpec, |
|
756 AlgorithmParameters params, SecureRandom random) |
|
757 throws InvalidKeyException, InvalidAlgorithmParameterException { |
|
758 synchronized (lock) { |
|
759 if (spi != null) { |
|
760 implInit(spi, initType, opmode, key, paramSpec, params, random); |
|
761 return; |
|
762 } |
|
763 Exception lastException = null; |
|
764 while ((firstService != null) || serviceIterator.hasNext()) { |
|
765 Service s; |
|
766 CipherSpi thisSpi; |
|
767 if (firstService != null) { |
|
768 s = firstService; |
|
769 thisSpi = firstSpi; |
|
770 firstService = null; |
|
771 firstSpi = null; |
|
772 } else { |
|
773 s = (Service)serviceIterator.next(); |
|
774 thisSpi = null; |
|
775 } |
|
776 // if provider says it does not support this key, ignore it |
|
777 if (s.supportsParameter(key) == false) { |
|
778 continue; |
|
779 } |
|
780 if (JceSecurity.canUseProvider(s.getProvider()) == false) { |
|
781 continue; |
|
782 } |
|
783 Transform tr = getTransform(s, transforms); |
|
784 if (tr == null) { |
|
785 // should never happen |
|
786 continue; |
|
787 } |
|
788 if (tr.supportsModePadding(s) == S_NO) { |
|
789 continue; |
|
790 } |
|
791 try { |
|
792 if (thisSpi == null) { |
|
793 thisSpi = (CipherSpi)s.newInstance(null); |
|
794 } |
|
795 tr.setModePadding(thisSpi); |
|
796 initCryptoPermission(); |
|
797 implInit(thisSpi, initType, opmode, key, paramSpec, |
|
798 params, random); |
|
799 provider = s.getProvider(); |
|
800 this.spi = thisSpi; |
|
801 firstService = null; |
|
802 serviceIterator = null; |
|
803 transforms = null; |
|
804 return; |
|
805 } catch (Exception e) { |
|
806 // NoSuchAlgorithmException from newInstance() |
|
807 // InvalidKeyException from init() |
|
808 // RuntimeException (ProviderException) from init() |
|
809 // SecurityException from crypto permission check |
|
810 if (lastException == null) { |
|
811 lastException = e; |
|
812 } |
|
813 } |
|
814 } |
|
815 // no working provider found, fail |
|
816 if (lastException instanceof InvalidKeyException) { |
|
817 throw (InvalidKeyException)lastException; |
|
818 } |
|
819 if (lastException instanceof InvalidAlgorithmParameterException) { |
|
820 throw (InvalidAlgorithmParameterException)lastException; |
|
821 } |
|
822 if (lastException instanceof RuntimeException) { |
|
823 throw (RuntimeException)lastException; |
|
824 } |
|
825 String kName = (key != null) ? key.getClass().getName() : "(null)"; |
|
826 throw new InvalidKeyException |
|
827 ("No installed provider supports this key: " |
|
828 + kName, lastException); |
|
829 } |
|
830 } |
|
831 |
|
832 /** |
|
833 * Returns the provider of this <code>Cipher</code> object. |
|
834 * |
|
835 * @return the provider of this <code>Cipher</code> object |
|
836 */ |
|
837 public final Provider getProvider() { |
|
838 chooseFirstProvider(); |
|
839 return this.provider; |
|
840 } |
|
841 |
|
842 /** |
|
843 * Returns the algorithm name of this <code>Cipher</code> object. |
|
844 * |
|
845 * <p>This is the same name that was specified in one of the |
|
846 * <code>getInstance</code> calls that created this <code>Cipher</code> |
|
847 * object.. |
|
848 * |
|
849 * @return the algorithm name of this <code>Cipher</code> object. |
|
850 */ |
|
851 public final String getAlgorithm() { |
|
852 return this.transformation; |
|
853 } |
|
854 |
|
855 /** |
|
856 * Returns the block size (in bytes). |
|
857 * |
|
858 * @return the block size (in bytes), or 0 if the underlying algorithm is |
|
859 * not a block cipher |
|
860 */ |
|
861 public final int getBlockSize() { |
|
862 chooseFirstProvider(); |
|
863 return spi.engineGetBlockSize(); |
|
864 } |
|
865 |
|
866 /** |
|
867 * Returns the length in bytes that an output buffer would need to be in |
|
868 * order to hold the result of the next <code>update</code> or |
|
869 * <code>doFinal</code> operation, given the input length |
|
870 * <code>inputLen</code> (in bytes). |
|
871 * |
|
872 * <p>This call takes into account any unprocessed (buffered) data from a |
|
873 * previous <code>update</code> call, and padding. |
|
874 * |
|
875 * <p>The actual output length of the next <code>update</code> or |
|
876 * <code>doFinal</code> call may be smaller than the length returned by |
|
877 * this method. |
|
878 * |
|
879 * @param inputLen the input length (in bytes) |
|
880 * |
|
881 * @return the required output buffer size (in bytes) |
|
882 * |
|
883 * @exception IllegalStateException if this cipher is in a wrong state |
|
884 * (e.g., has not yet been initialized) |
|
885 */ |
|
886 public final int getOutputSize(int inputLen) { |
|
887 |
|
888 if (!initialized && !(this instanceof NullCipher)) { |
|
889 throw new IllegalStateException("Cipher not initialized"); |
|
890 } |
|
891 if (inputLen < 0) { |
|
892 throw new IllegalArgumentException("Input size must be equal " + |
|
893 "to or greater than zero"); |
|
894 } |
|
895 chooseFirstProvider(); |
|
896 return spi.engineGetOutputSize(inputLen); |
|
897 } |
|
898 |
|
899 /** |
|
900 * Returns the initialization vector (IV) in a new buffer. |
|
901 * |
|
902 * <p>This is useful in the case where a random IV was created, |
|
903 * or in the context of password-based encryption or |
|
904 * decryption, where the IV is derived from a user-supplied password. |
|
905 * |
|
906 * @return the initialization vector in a new buffer, or null if the |
|
907 * underlying algorithm does not use an IV, or if the IV has not yet |
|
908 * been set. |
|
909 */ |
|
910 public final byte[] getIV() { |
|
911 chooseFirstProvider(); |
|
912 return spi.engineGetIV(); |
|
913 } |
|
914 |
|
915 /** |
|
916 * Returns the parameters used with this cipher. |
|
917 * |
|
918 * <p>The returned parameters may be the same that were used to initialize |
|
919 * this cipher, or may contain a combination of default and random |
|
920 * parameter values used by the underlying cipher implementation if this |
|
921 * cipher requires algorithm parameters but was not initialized with any. |
|
922 * |
|
923 * @return the parameters used with this cipher, or null if this cipher |
|
924 * does not use any parameters. |
|
925 */ |
|
926 public final AlgorithmParameters getParameters() { |
|
927 chooseFirstProvider(); |
|
928 return spi.engineGetParameters(); |
|
929 } |
|
930 |
|
931 /** |
|
932 * Returns the exemption mechanism object used with this cipher. |
|
933 * |
|
934 * @return the exemption mechanism object used with this cipher, or |
|
935 * null if this cipher does not use any exemption mechanism. |
|
936 */ |
|
937 public final ExemptionMechanism getExemptionMechanism() { |
|
938 chooseFirstProvider(); |
|
939 return exmech; |
|
940 } |
|
941 |
|
942 // |
|
943 // Crypto permission check code below |
|
944 // |
|
945 private void checkCryptoPerm(CipherSpi checkSpi, Key key) |
|
946 throws InvalidKeyException { |
|
947 if (cryptoPerm == CryptoAllPermission.INSTANCE) { |
|
948 return; |
|
949 } |
|
950 // Check if key size and default parameters are within legal limits |
|
951 AlgorithmParameterSpec params; |
|
952 try { |
|
953 params = getAlgorithmParameterSpec(checkSpi.engineGetParameters()); |
|
954 } catch (InvalidParameterSpecException ipse) { |
|
955 throw new InvalidKeyException |
|
956 ("Unsupported default algorithm parameters"); |
|
957 } |
|
958 if (!passCryptoPermCheck(checkSpi, key, params)) { |
|
959 throw new InvalidKeyException( |
|
960 "Illegal key size or default parameters"); |
|
961 } |
|
962 } |
|
963 |
|
964 private void checkCryptoPerm(CipherSpi checkSpi, Key key, |
|
965 AlgorithmParameterSpec params) throws InvalidKeyException, |
|
966 InvalidAlgorithmParameterException { |
|
967 if (cryptoPerm == CryptoAllPermission.INSTANCE) { |
|
968 return; |
|
969 } |
|
970 // Determine keysize and check if it is within legal limits |
|
971 if (!passCryptoPermCheck(checkSpi, key, null)) { |
|
972 throw new InvalidKeyException("Illegal key size"); |
|
973 } |
|
974 if ((params != null) && (!passCryptoPermCheck(checkSpi, key, params))) { |
|
975 throw new InvalidAlgorithmParameterException("Illegal parameters"); |
|
976 } |
|
977 } |
|
978 |
|
979 private void checkCryptoPerm(CipherSpi checkSpi, Key key, |
|
980 AlgorithmParameters params) |
|
981 throws InvalidKeyException, InvalidAlgorithmParameterException { |
|
982 if (cryptoPerm == CryptoAllPermission.INSTANCE) { |
|
983 return; |
|
984 } |
|
985 // Convert the specified parameters into specs and then delegate. |
|
986 AlgorithmParameterSpec pSpec; |
|
987 try { |
|
988 pSpec = getAlgorithmParameterSpec(params); |
|
989 } catch (InvalidParameterSpecException ipse) { |
|
990 throw new InvalidAlgorithmParameterException |
|
991 ("Failed to retrieve algorithm parameter specification"); |
|
992 } |
|
993 checkCryptoPerm(checkSpi, key, pSpec); |
|
994 } |
|
995 |
|
996 private boolean passCryptoPermCheck(CipherSpi checkSpi, Key key, |
|
997 AlgorithmParameterSpec params) |
|
998 throws InvalidKeyException { |
|
999 String em = cryptoPerm.getExemptionMechanism(); |
|
1000 int keySize = checkSpi.engineGetKeySize(key); |
|
1001 // Use the "algorithm" component of the cipher |
|
1002 // transformation so that the perm check would |
|
1003 // work when the key has the "aliased" algo. |
|
1004 String algComponent; |
|
1005 int index = transformation.indexOf('/'); |
|
1006 if (index != -1) { |
|
1007 algComponent = transformation.substring(0, index); |
|
1008 } else { |
|
1009 algComponent = transformation; |
|
1010 } |
|
1011 CryptoPermission checkPerm = |
|
1012 new CryptoPermission(algComponent, keySize, params, em); |
|
1013 |
|
1014 if (!cryptoPerm.implies(checkPerm)) { |
|
1015 if (debug != null) { |
|
1016 debug.println("Crypto Permission check failed"); |
|
1017 debug.println("granted: " + cryptoPerm); |
|
1018 debug.println("requesting: " + checkPerm); |
|
1019 } |
|
1020 return false; |
|
1021 } |
|
1022 if (exmech == null) { |
|
1023 return true; |
|
1024 } |
|
1025 try { |
|
1026 if (!exmech.isCryptoAllowed(key)) { |
|
1027 if (debug != null) { |
|
1028 debug.println(exmech.getName() + " isn't enforced"); |
|
1029 } |
|
1030 return false; |
|
1031 } |
|
1032 } catch (ExemptionMechanismException eme) { |
|
1033 if (debug != null) { |
|
1034 debug.println("Cannot determine whether "+ |
|
1035 exmech.getName() + " has been enforced"); |
|
1036 eme.printStackTrace(); |
|
1037 } |
|
1038 return false; |
|
1039 } |
|
1040 return true; |
|
1041 } |
|
1042 |
|
1043 // check if opmode is one of the defined constants |
|
1044 // throw InvalidParameterExeption if not |
|
1045 private static void checkOpmode(int opmode) { |
|
1046 if ((opmode < ENCRYPT_MODE) || (opmode > UNWRAP_MODE)) { |
|
1047 throw new InvalidParameterException("Invalid operation mode"); |
|
1048 } |
|
1049 } |
|
1050 |
|
1051 /** |
|
1052 * Initializes this cipher with a key. |
|
1053 * |
|
1054 * <p>The cipher is initialized for one of the following four operations: |
|
1055 * encryption, decryption, key wrapping or key unwrapping, depending |
|
1056 * on the value of <code>opmode</code>. |
|
1057 * |
|
1058 * <p>If this cipher requires any algorithm parameters that cannot be |
|
1059 * derived from the given <code>key</code>, the underlying cipher |
|
1060 * implementation is supposed to generate the required parameters itself |
|
1061 * (using provider-specific default or random values) if it is being |
|
1062 * initialized for encryption or key wrapping, and raise an |
|
1063 * <code>InvalidKeyException</code> if it is being |
|
1064 * initialized for decryption or key unwrapping. |
|
1065 * The generated parameters can be retrieved using |
|
1066 * {@link #getParameters() getParameters} or |
|
1067 * {@link #getIV() getIV} (if the parameter is an IV). |
|
1068 * |
|
1069 * <p>If this cipher (including its underlying feedback or padding scheme) |
|
1070 * requires any random bytes (e.g., for parameter generation), it will get |
|
1071 * them using the {@link SecureRandom <code>SecureRandom</code>} |
|
1072 * implementation of the highest-priority |
|
1073 * installed provider as the source of randomness. |
|
1074 * (If none of the installed providers supply an implementation of |
|
1075 * SecureRandom, a system-provided source of randomness will be used.) |
|
1076 * |
|
1077 * <p>Note that when a Cipher object is initialized, it loses all |
|
1078 * previously-acquired state. In other words, initializing a Cipher is |
|
1079 * equivalent to creating a new instance of that Cipher and initializing |
|
1080 * it. |
|
1081 * |
|
1082 * @param opmode the operation mode of this cipher (this is one of |
|
1083 * the following: |
|
1084 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, |
|
1085 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>) |
|
1086 * @param key the key |
|
1087 * |
|
1088 * @exception InvalidKeyException if the given key is inappropriate for |
|
1089 * initializing this cipher, or if this cipher is being initialized for |
|
1090 * decryption and requires algorithm parameters that cannot be |
|
1091 * determined from the given key, or if the given key has a keysize that |
|
1092 * exceeds the maximum allowable keysize (as determined from the |
|
1093 * configured jurisdiction policy files). |
|
1094 */ |
|
1095 public final void init(int opmode, Key key) throws InvalidKeyException { |
|
1096 init(opmode, key, JceSecurity.RANDOM); |
|
1097 } |
|
1098 |
|
1099 /** |
|
1100 * Initializes this cipher with a key and a source of randomness. |
|
1101 * |
|
1102 * <p>The cipher is initialized for one of the following four operations: |
|
1103 * encryption, decryption, key wrapping or key unwrapping, depending |
|
1104 * on the value of <code>opmode</code>. |
|
1105 * |
|
1106 * <p>If this cipher requires any algorithm parameters that cannot be |
|
1107 * derived from the given <code>key</code>, the underlying cipher |
|
1108 * implementation is supposed to generate the required parameters itself |
|
1109 * (using provider-specific default or random values) if it is being |
|
1110 * initialized for encryption or key wrapping, and raise an |
|
1111 * <code>InvalidKeyException</code> if it is being |
|
1112 * initialized for decryption or key unwrapping. |
|
1113 * The generated parameters can be retrieved using |
|
1114 * {@link #getParameters() getParameters} or |
|
1115 * {@link #getIV() getIV} (if the parameter is an IV). |
|
1116 * |
|
1117 * <p>If this cipher (including its underlying feedback or padding scheme) |
|
1118 * requires any random bytes (e.g., for parameter generation), it will get |
|
1119 * them from <code>random</code>. |
|
1120 * |
|
1121 * <p>Note that when a Cipher object is initialized, it loses all |
|
1122 * previously-acquired state. In other words, initializing a Cipher is |
|
1123 * equivalent to creating a new instance of that Cipher and initializing |
|
1124 * it. |
|
1125 * |
|
1126 * @param opmode the operation mode of this cipher (this is one of the |
|
1127 * following: |
|
1128 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, |
|
1129 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>) |
|
1130 * @param key the encryption key |
|
1131 * @param random the source of randomness |
|
1132 * |
|
1133 * @exception InvalidKeyException if the given key is inappropriate for |
|
1134 * initializing this cipher, or if this cipher is being initialized for |
|
1135 * decryption and requires algorithm parameters that cannot be |
|
1136 * determined from the given key, or if the given key has a keysize that |
|
1137 * exceeds the maximum allowable keysize (as determined from the |
|
1138 * configured jurisdiction policy files). |
|
1139 */ |
|
1140 public final void init(int opmode, Key key, SecureRandom random) |
|
1141 throws InvalidKeyException |
|
1142 { |
|
1143 initialized = false; |
|
1144 checkOpmode(opmode); |
|
1145 |
|
1146 if (spi != null) { |
|
1147 checkCryptoPerm(spi, key); |
|
1148 spi.engineInit(opmode, key, random); |
|
1149 } else { |
|
1150 try { |
|
1151 chooseProvider(I_KEY, opmode, key, null, null, random); |
|
1152 } catch (InvalidAlgorithmParameterException e) { |
|
1153 // should never occur |
|
1154 throw new InvalidKeyException(e); |
|
1155 } |
|
1156 } |
|
1157 |
|
1158 initialized = true; |
|
1159 this.opmode = opmode; |
|
1160 } |
|
1161 |
|
1162 /** |
|
1163 * Initializes this cipher with a key and a set of algorithm |
|
1164 * parameters. |
|
1165 * |
|
1166 * <p>The cipher is initialized for one of the following four operations: |
|
1167 * encryption, decryption, key wrapping or key unwrapping, depending |
|
1168 * on the value of <code>opmode</code>. |
|
1169 * |
|
1170 * <p>If this cipher requires any algorithm parameters and |
|
1171 * <code>params</code> is null, the underlying cipher implementation is |
|
1172 * supposed to generate the required parameters itself (using |
|
1173 * provider-specific default or random values) if it is being |
|
1174 * initialized for encryption or key wrapping, and raise an |
|
1175 * <code>InvalidAlgorithmParameterException</code> if it is being |
|
1176 * initialized for decryption or key unwrapping. |
|
1177 * The generated parameters can be retrieved using |
|
1178 * {@link #getParameters() getParameters} or |
|
1179 * {@link #getIV() getIV} (if the parameter is an IV). |
|
1180 * |
|
1181 * <p>If this cipher (including its underlying feedback or padding scheme) |
|
1182 * requires any random bytes (e.g., for parameter generation), it will get |
|
1183 * them using the {@link SecureRandom <code>SecureRandom</code>} |
|
1184 * implementation of the highest-priority |
|
1185 * installed provider as the source of randomness. |
|
1186 * (If none of the installed providers supply an implementation of |
|
1187 * SecureRandom, a system-provided source of randomness will be used.) |
|
1188 * |
|
1189 * <p>Note that when a Cipher object is initialized, it loses all |
|
1190 * previously-acquired state. In other words, initializing a Cipher is |
|
1191 * equivalent to creating a new instance of that Cipher and initializing |
|
1192 * it. |
|
1193 * |
|
1194 * @param opmode the operation mode of this cipher (this is one of the |
|
1195 * following: |
|
1196 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, |
|
1197 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>) |
|
1198 * @param key the encryption key |
|
1199 * @param params the algorithm parameters |
|
1200 * |
|
1201 * @exception InvalidKeyException if the given key is inappropriate for |
|
1202 * initializing this cipher, or its keysize exceeds the maximum allowable |
|
1203 * keysize (as determined from the configured jurisdiction policy files). |
|
1204 * @exception InvalidAlgorithmParameterException if the given algorithm |
|
1205 * parameters are inappropriate for this cipher, |
|
1206 * or this cipher is being initialized for decryption and requires |
|
1207 * algorithm parameters and <code>params</code> is null, or the given |
|
1208 * algorithm parameters imply a cryptographic strength that would exceed |
|
1209 * the legal limits (as determined from the configured jurisdiction |
|
1210 * policy files). |
|
1211 */ |
|
1212 public final void init(int opmode, Key key, AlgorithmParameterSpec params) |
|
1213 throws InvalidKeyException, InvalidAlgorithmParameterException |
|
1214 { |
|
1215 init(opmode, key, params, JceSecurity.RANDOM); |
|
1216 } |
|
1217 |
|
1218 /** |
|
1219 * Initializes this cipher with a key, a set of algorithm |
|
1220 * parameters, and a source of randomness. |
|
1221 * |
|
1222 * <p>The cipher is initialized for one of the following four operations: |
|
1223 * encryption, decryption, key wrapping or key unwrapping, depending |
|
1224 * on the value of <code>opmode</code>. |
|
1225 * |
|
1226 * <p>If this cipher requires any algorithm parameters and |
|
1227 * <code>params</code> is null, the underlying cipher implementation is |
|
1228 * supposed to generate the required parameters itself (using |
|
1229 * provider-specific default or random values) if it is being |
|
1230 * initialized for encryption or key wrapping, and raise an |
|
1231 * <code>InvalidAlgorithmParameterException</code> if it is being |
|
1232 * initialized for decryption or key unwrapping. |
|
1233 * The generated parameters can be retrieved using |
|
1234 * {@link #getParameters() getParameters} or |
|
1235 * {@link #getIV() getIV} (if the parameter is an IV). |
|
1236 * |
|
1237 * <p>If this cipher (including its underlying feedback or padding scheme) |
|
1238 * requires any random bytes (e.g., for parameter generation), it will get |
|
1239 * them from <code>random</code>. |
|
1240 * |
|
1241 * <p>Note that when a Cipher object is initialized, it loses all |
|
1242 * previously-acquired state. In other words, initializing a Cipher is |
|
1243 * equivalent to creating a new instance of that Cipher and initializing |
|
1244 * it. |
|
1245 * |
|
1246 * @param opmode the operation mode of this cipher (this is one of the |
|
1247 * following: |
|
1248 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, |
|
1249 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>) |
|
1250 * @param key the encryption key |
|
1251 * @param params the algorithm parameters |
|
1252 * @param random the source of randomness |
|
1253 * |
|
1254 * @exception InvalidKeyException if the given key is inappropriate for |
|
1255 * initializing this cipher, or its keysize exceeds the maximum allowable |
|
1256 * keysize (as determined from the configured jurisdiction policy files). |
|
1257 * @exception InvalidAlgorithmParameterException if the given algorithm |
|
1258 * parameters are inappropriate for this cipher, |
|
1259 * or this cipher is being initialized for decryption and requires |
|
1260 * algorithm parameters and <code>params</code> is null, or the given |
|
1261 * algorithm parameters imply a cryptographic strength that would exceed |
|
1262 * the legal limits (as determined from the configured jurisdiction |
|
1263 * policy files). |
|
1264 */ |
|
1265 public final void init(int opmode, Key key, AlgorithmParameterSpec params, |
|
1266 SecureRandom random) |
|
1267 throws InvalidKeyException, InvalidAlgorithmParameterException |
|
1268 { |
|
1269 initialized = false; |
|
1270 checkOpmode(opmode); |
|
1271 |
|
1272 if (spi != null) { |
|
1273 checkCryptoPerm(spi, key, params); |
|
1274 spi.engineInit(opmode, key, params, random); |
|
1275 } else { |
|
1276 chooseProvider(I_PARAMSPEC, opmode, key, params, null, random); |
|
1277 } |
|
1278 |
|
1279 initialized = true; |
|
1280 this.opmode = opmode; |
|
1281 } |
|
1282 |
|
1283 /** |
|
1284 * Initializes this cipher with a key and a set of algorithm |
|
1285 * parameters. |
|
1286 * |
|
1287 * <p>The cipher is initialized for one of the following four operations: |
|
1288 * encryption, decryption, key wrapping or key unwrapping, depending |
|
1289 * on the value of <code>opmode</code>. |
|
1290 * |
|
1291 * <p>If this cipher requires any algorithm parameters and |
|
1292 * <code>params</code> is null, the underlying cipher implementation is |
|
1293 * supposed to generate the required parameters itself (using |
|
1294 * provider-specific default or random values) if it is being |
|
1295 * initialized for encryption or key wrapping, and raise an |
|
1296 * <code>InvalidAlgorithmParameterException</code> if it is being |
|
1297 * initialized for decryption or key unwrapping. |
|
1298 * The generated parameters can be retrieved using |
|
1299 * {@link #getParameters() getParameters} or |
|
1300 * {@link #getIV() getIV} (if the parameter is an IV). |
|
1301 * |
|
1302 * <p>If this cipher (including its underlying feedback or padding scheme) |
|
1303 * requires any random bytes (e.g., for parameter generation), it will get |
|
1304 * them using the {@link SecureRandom <code>SecureRandom</code>} |
|
1305 * implementation of the highest-priority |
|
1306 * installed provider as the source of randomness. |
|
1307 * (If none of the installed providers supply an implementation of |
|
1308 * SecureRandom, a system-provided source of randomness will be used.) |
|
1309 * |
|
1310 * <p>Note that when a Cipher object is initialized, it loses all |
|
1311 * previously-acquired state. In other words, initializing a Cipher is |
|
1312 * equivalent to creating a new instance of that Cipher and initializing |
|
1313 * it. |
|
1314 * |
|
1315 * @param opmode the operation mode of this cipher (this is one of the |
|
1316 * following: <code>ENCRYPT_MODE</code>, |
|
1317 * <code>DECRYPT_MODE</code>, <code>WRAP_MODE</code> |
|
1318 * or <code>UNWRAP_MODE</code>) |
|
1319 * @param key the encryption key |
|
1320 * @param params the algorithm parameters |
|
1321 * |
|
1322 * @exception InvalidKeyException if the given key is inappropriate for |
|
1323 * initializing this cipher, or its keysize exceeds the maximum allowable |
|
1324 * keysize (as determined from the configured jurisdiction policy files). |
|
1325 * @exception InvalidAlgorithmParameterException if the given algorithm |
|
1326 * parameters are inappropriate for this cipher, |
|
1327 * or this cipher is being initialized for decryption and requires |
|
1328 * algorithm parameters and <code>params</code> is null, or the given |
|
1329 * algorithm parameters imply a cryptographic strength that would exceed |
|
1330 * the legal limits (as determined from the configured jurisdiction |
|
1331 * policy files). |
|
1332 */ |
|
1333 public final void init(int opmode, Key key, AlgorithmParameters params) |
|
1334 throws InvalidKeyException, InvalidAlgorithmParameterException |
|
1335 { |
|
1336 init(opmode, key, params, JceSecurity.RANDOM); |
|
1337 } |
|
1338 |
|
1339 /** |
|
1340 * Initializes this cipher with a key, a set of algorithm |
|
1341 * parameters, and a source of randomness. |
|
1342 * |
|
1343 * <p>The cipher is initialized for one of the following four operations: |
|
1344 * encryption, decryption, key wrapping or key unwrapping, depending |
|
1345 * on the value of <code>opmode</code>. |
|
1346 * |
|
1347 * <p>If this cipher requires any algorithm parameters and |
|
1348 * <code>params</code> is null, the underlying cipher implementation is |
|
1349 * supposed to generate the required parameters itself (using |
|
1350 * provider-specific default or random values) if it is being |
|
1351 * initialized for encryption or key wrapping, and raise an |
|
1352 * <code>InvalidAlgorithmParameterException</code> if it is being |
|
1353 * initialized for decryption or key unwrapping. |
|
1354 * The generated parameters can be retrieved using |
|
1355 * {@link #getParameters() getParameters} or |
|
1356 * {@link #getIV() getIV} (if the parameter is an IV). |
|
1357 * |
|
1358 * <p>If this cipher (including its underlying feedback or padding scheme) |
|
1359 * requires any random bytes (e.g., for parameter generation), it will get |
|
1360 * them from <code>random</code>. |
|
1361 * |
|
1362 * <p>Note that when a Cipher object is initialized, it loses all |
|
1363 * previously-acquired state. In other words, initializing a Cipher is |
|
1364 * equivalent to creating a new instance of that Cipher and initializing |
|
1365 * it. |
|
1366 * |
|
1367 * @param opmode the operation mode of this cipher (this is one of the |
|
1368 * following: <code>ENCRYPT_MODE</code>, |
|
1369 * <code>DECRYPT_MODE</code>, <code>WRAP_MODE</code> |
|
1370 * or <code>UNWRAP_MODE</code>) |
|
1371 * @param key the encryption key |
|
1372 * @param params the algorithm parameters |
|
1373 * @param random the source of randomness |
|
1374 * |
|
1375 * @exception InvalidKeyException if the given key is inappropriate for |
|
1376 * initializing this cipher, or its keysize exceeds the maximum allowable |
|
1377 * keysize (as determined from the configured jurisdiction policy files). |
|
1378 * @exception InvalidAlgorithmParameterException if the given algorithm |
|
1379 * parameters are inappropriate for this cipher, |
|
1380 * or this cipher is being initialized for decryption and requires |
|
1381 * algorithm parameters and <code>params</code> is null, or the given |
|
1382 * algorithm parameters imply a cryptographic strength that would exceed |
|
1383 * the legal limits (as determined from the configured jurisdiction |
|
1384 * policy files). |
|
1385 */ |
|
1386 public final void init(int opmode, Key key, AlgorithmParameters params, |
|
1387 SecureRandom random) |
|
1388 throws InvalidKeyException, InvalidAlgorithmParameterException |
|
1389 { |
|
1390 initialized = false; |
|
1391 checkOpmode(opmode); |
|
1392 |
|
1393 if (spi != null) { |
|
1394 checkCryptoPerm(spi, key, params); |
|
1395 spi.engineInit(opmode, key, params, random); |
|
1396 } else { |
|
1397 chooseProvider(I_PARAMS, opmode, key, null, params, random); |
|
1398 } |
|
1399 |
|
1400 initialized = true; |
|
1401 this.opmode = opmode; |
|
1402 } |
|
1403 |
|
1404 /** |
|
1405 * Initializes this cipher with the public key from the given certificate. |
|
1406 * <p> The cipher is initialized for one of the following four operations: |
|
1407 * encryption, decryption, key wrapping or key unwrapping, depending |
|
1408 * on the value of <code>opmode</code>. |
|
1409 * |
|
1410 * <p>If the certificate is of type X.509 and has a <i>key usage</i> |
|
1411 * extension field marked as critical, and the value of the <i>key usage</i> |
|
1412 * extension field implies that the public key in |
|
1413 * the certificate and its corresponding private key are not |
|
1414 * supposed to be used for the operation represented by the value |
|
1415 * of <code>opmode</code>, |
|
1416 * an <code>InvalidKeyException</code> |
|
1417 * is thrown. |
|
1418 * |
|
1419 * <p> If this cipher requires any algorithm parameters that cannot be |
|
1420 * derived from the public key in the given certificate, the underlying |
|
1421 * cipher |
|
1422 * implementation is supposed to generate the required parameters itself |
|
1423 * (using provider-specific default or ramdom values) if it is being |
|
1424 * initialized for encryption or key wrapping, and raise an <code> |
|
1425 * InvalidKeyException</code> if it is being initialized for decryption or |
|
1426 * key unwrapping. |
|
1427 * The generated parameters can be retrieved using |
|
1428 * {@link #getParameters() getParameters} or |
|
1429 * {@link #getIV() getIV} (if the parameter is an IV). |
|
1430 * |
|
1431 * <p>If this cipher (including its underlying feedback or padding scheme) |
|
1432 * requires any random bytes (e.g., for parameter generation), it will get |
|
1433 * them using the |
|
1434 * <code>SecureRandom</code> |
|
1435 * implementation of the highest-priority |
|
1436 * installed provider as the source of randomness. |
|
1437 * (If none of the installed providers supply an implementation of |
|
1438 * SecureRandom, a system-provided source of randomness will be used.) |
|
1439 * |
|
1440 * <p>Note that when a Cipher object is initialized, it loses all |
|
1441 * previously-acquired state. In other words, initializing a Cipher is |
|
1442 * equivalent to creating a new instance of that Cipher and initializing |
|
1443 * it. |
|
1444 * |
|
1445 * @param opmode the operation mode of this cipher (this is one of the |
|
1446 * following: |
|
1447 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, |
|
1448 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>) |
|
1449 * @param certificate the certificate |
|
1450 * |
|
1451 * @exception InvalidKeyException if the public key in the given |
|
1452 * certificate is inappropriate for initializing this cipher, or this |
|
1453 * cipher is being initialized for decryption or unwrapping keys and |
|
1454 * requires algorithm parameters that cannot be determined from the |
|
1455 * public key in the given certificate, or the keysize of the public key |
|
1456 * in the given certificate has a keysize that exceeds the maximum |
|
1457 * allowable keysize (as determined by the configured jurisdiction policy |
|
1458 * files). |
|
1459 */ |
|
1460 public final void init(int opmode, Certificate certificate) |
|
1461 throws InvalidKeyException |
|
1462 { |
|
1463 init(opmode, certificate, JceSecurity.RANDOM); |
|
1464 } |
|
1465 |
|
1466 /** |
|
1467 * Initializes this cipher with the public key from the given certificate |
|
1468 * and |
|
1469 * a source of randomness. |
|
1470 * |
|
1471 * <p>The cipher is initialized for one of the following four operations: |
|
1472 * encryption, decryption, key wrapping |
|
1473 * or key unwrapping, depending on |
|
1474 * the value of <code>opmode</code>. |
|
1475 * |
|
1476 * <p>If the certificate is of type X.509 and has a <i>key usage</i> |
|
1477 * extension field marked as critical, and the value of the <i>key usage</i> |
|
1478 * extension field implies that the public key in |
|
1479 * the certificate and its corresponding private key are not |
|
1480 * supposed to be used for the operation represented by the value of |
|
1481 * <code>opmode</code>, |
|
1482 * an <code>InvalidKeyException</code> |
|
1483 * is thrown. |
|
1484 * |
|
1485 * <p>If this cipher requires any algorithm parameters that cannot be |
|
1486 * derived from the public key in the given <code>certificate</code>, |
|
1487 * the underlying cipher |
|
1488 * implementation is supposed to generate the required parameters itself |
|
1489 * (using provider-specific default or random values) if it is being |
|
1490 * initialized for encryption or key wrapping, and raise an |
|
1491 * <code>InvalidKeyException</code> if it is being |
|
1492 * initialized for decryption or key unwrapping. |
|
1493 * The generated parameters can be retrieved using |
|
1494 * {@link #getParameters() getParameters} or |
|
1495 * {@link #getIV() getIV} (if the parameter is an IV). |
|
1496 * |
|
1497 * <p>If this cipher (including its underlying feedback or padding scheme) |
|
1498 * requires any random bytes (e.g., for parameter generation), it will get |
|
1499 * them from <code>random</code>. |
|
1500 * |
|
1501 * <p>Note that when a Cipher object is initialized, it loses all |
|
1502 * previously-acquired state. In other words, initializing a Cipher is |
|
1503 * equivalent to creating a new instance of that Cipher and initializing |
|
1504 * it. |
|
1505 * |
|
1506 * @param opmode the operation mode of this cipher (this is one of the |
|
1507 * following: |
|
1508 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>, |
|
1509 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>) |
|
1510 * @param certificate the certificate |
|
1511 * @param random the source of randomness |
|
1512 * |
|
1513 * @exception InvalidKeyException if the public key in the given |
|
1514 * certificate is inappropriate for initializing this cipher, or this |
|
1515 * cipher is being initialized for decryption or unwrapping keys and |
|
1516 * requires algorithm parameters that cannot be determined from the |
|
1517 * public key in the given certificate, or the keysize of the public key |
|
1518 * in the given certificate has a keysize that exceeds the maximum |
|
1519 * allowable keysize (as determined by the configured jurisdiction policy |
|
1520 * files). |
|
1521 */ |
|
1522 public final void init(int opmode, Certificate certificate, |
|
1523 SecureRandom random) |
|
1524 throws InvalidKeyException |
|
1525 { |
|
1526 initialized = false; |
|
1527 checkOpmode(opmode); |
|
1528 |
|
1529 // Check key usage if the certificate is of |
|
1530 // type X.509. |
|
1531 if (certificate instanceof java.security.cert.X509Certificate) { |
|
1532 // Check whether the cert has a key usage extension |
|
1533 // marked as a critical extension. |
|
1534 X509Certificate cert = (X509Certificate)certificate; |
|
1535 Set critSet = cert.getCriticalExtensionOIDs(); |
|
1536 |
|
1537 if (critSet != null && !critSet.isEmpty() |
|
1538 && critSet.contains(KEY_USAGE_EXTENSION_OID)) { |
|
1539 boolean[] keyUsageInfo = cert.getKeyUsage(); |
|
1540 // keyUsageInfo[2] is for keyEncipherment; |
|
1541 // keyUsageInfo[3] is for dataEncipherment. |
|
1542 if ((keyUsageInfo != null) && |
|
1543 (((opmode == Cipher.ENCRYPT_MODE) && |
|
1544 (keyUsageInfo.length > 3) && |
|
1545 (keyUsageInfo[3] == false)) || |
|
1546 ((opmode == Cipher.WRAP_MODE) && |
|
1547 (keyUsageInfo.length > 2) && |
|
1548 (keyUsageInfo[2] == false)))) { |
|
1549 throw new InvalidKeyException("Wrong key usage"); |
|
1550 } |
|
1551 } |
|
1552 } |
|
1553 |
|
1554 PublicKey publicKey = |
|
1555 (certificate==null? null:certificate.getPublicKey()); |
|
1556 |
|
1557 if (spi != null) { |
|
1558 checkCryptoPerm(spi, publicKey); |
|
1559 spi.engineInit(opmode, publicKey, random); |
|
1560 } else { |
|
1561 try { |
|
1562 chooseProvider(I_CERT, opmode, publicKey, null, null, random); |
|
1563 } catch (InvalidAlgorithmParameterException e) { |
|
1564 // should never occur |
|
1565 throw new InvalidKeyException(e); |
|
1566 } |
|
1567 } |
|
1568 |
|
1569 initialized = true; |
|
1570 this.opmode = opmode; |
|
1571 } |
|
1572 |
|
1573 /** |
|
1574 * Ensures that Cipher is in a valid state for update() and doFinal() |
|
1575 * calls - should be initialized and in ENCRYPT_MODE or DECRYPT_MODE. |
|
1576 * @throws IllegalStateException if Cipher object is not in valid state. |
|
1577 */ |
|
1578 private void checkCipherState() { |
|
1579 if (!(this instanceof NullCipher)) { |
|
1580 if (!initialized) { |
|
1581 throw new IllegalStateException("Cipher not initialized"); |
|
1582 } |
|
1583 if ((opmode != Cipher.ENCRYPT_MODE) && |
|
1584 (opmode != Cipher.DECRYPT_MODE)) { |
|
1585 throw new IllegalStateException("Cipher not initialized " + |
|
1586 "for encryption/decryption"); |
|
1587 } |
|
1588 } |
|
1589 } |
|
1590 |
|
1591 /** |
|
1592 * Continues a multiple-part encryption or decryption operation |
|
1593 * (depending on how this cipher was initialized), processing another data |
|
1594 * part. |
|
1595 * |
|
1596 * <p>The bytes in the <code>input</code> buffer are processed, and the |
|
1597 * result is stored in a new buffer. |
|
1598 * |
|
1599 * <p>If <code>input</code> has a length of zero, this method returns |
|
1600 * <code>null</code>. |
|
1601 * |
|
1602 * @param input the input buffer |
|
1603 * |
|
1604 * @return the new buffer with the result, or null if the underlying |
|
1605 * cipher is a block cipher and the input data is too short to result in a |
|
1606 * new block. |
|
1607 * |
|
1608 * @exception IllegalStateException if this cipher is in a wrong state |
|
1609 * (e.g., has not been initialized) |
|
1610 */ |
|
1611 public final byte[] update(byte[] input) { |
|
1612 checkCipherState(); |
|
1613 |
|
1614 // Input sanity check |
|
1615 if (input == null) { |
|
1616 throw new IllegalArgumentException("Null input buffer"); |
|
1617 } |
|
1618 |
|
1619 chooseFirstProvider(); |
|
1620 if (input.length == 0) { |
|
1621 return null; |
|
1622 } |
|
1623 return spi.engineUpdate(input, 0, input.length); |
|
1624 } |
|
1625 |
|
1626 /** |
|
1627 * Continues a multiple-part encryption or decryption operation |
|
1628 * (depending on how this cipher was initialized), processing another data |
|
1629 * part. |
|
1630 * |
|
1631 * <p>The first <code>inputLen</code> bytes in the <code>input</code> |
|
1632 * buffer, starting at <code>inputOffset</code> inclusive, are processed, |
|
1633 * and the result is stored in a new buffer. |
|
1634 * |
|
1635 * <p>If <code>inputLen</code> is zero, this method returns |
|
1636 * <code>null</code>. |
|
1637 * |
|
1638 * @param input the input buffer |
|
1639 * @param inputOffset the offset in <code>input</code> where the input |
|
1640 * starts |
|
1641 * @param inputLen the input length |
|
1642 * |
|
1643 * @return the new buffer with the result, or null if the underlying |
|
1644 * cipher is a block cipher and the input data is too short to result in a |
|
1645 * new block. |
|
1646 * |
|
1647 * @exception IllegalStateException if this cipher is in a wrong state |
|
1648 * (e.g., has not been initialized) |
|
1649 */ |
|
1650 public final byte[] update(byte[] input, int inputOffset, int inputLen) { |
|
1651 checkCipherState(); |
|
1652 |
|
1653 // Input sanity check |
|
1654 if (input == null || inputOffset < 0 |
|
1655 || inputLen > (input.length - inputOffset) || inputLen < 0) { |
|
1656 throw new IllegalArgumentException("Bad arguments"); |
|
1657 } |
|
1658 |
|
1659 chooseFirstProvider(); |
|
1660 if (inputLen == 0) { |
|
1661 return null; |
|
1662 } |
|
1663 return spi.engineUpdate(input, inputOffset, inputLen); |
|
1664 } |
|
1665 |
|
1666 /** |
|
1667 * Continues a multiple-part encryption or decryption operation |
|
1668 * (depending on how this cipher was initialized), processing another data |
|
1669 * part. |
|
1670 * |
|
1671 * <p>The first <code>inputLen</code> bytes in the <code>input</code> |
|
1672 * buffer, starting at <code>inputOffset</code> inclusive, are processed, |
|
1673 * and the result is stored in the <code>output</code> buffer. |
|
1674 * |
|
1675 * <p>If the <code>output</code> buffer is too small to hold the result, |
|
1676 * a <code>ShortBufferException</code> is thrown. In this case, repeat this |
|
1677 * call with a larger output buffer. Use |
|
1678 * {@link #getOutputSize(int) getOutputSize} to determine how big |
|
1679 * the output buffer should be. |
|
1680 * |
|
1681 * <p>If <code>inputLen</code> is zero, this method returns |
|
1682 * a length of zero. |
|
1683 * |
|
1684 * <p>Note: this method should be copy-safe, which means the |
|
1685 * <code>input</code> and <code>output</code> buffers can reference |
|
1686 * the same byte array and no unprocessed input data is overwritten |
|
1687 * when the result is copied into the output buffer. |
|
1688 * |
|
1689 * @param input the input buffer |
|
1690 * @param inputOffset the offset in <code>input</code> where the input |
|
1691 * starts |
|
1692 * @param inputLen the input length |
|
1693 * @param output the buffer for the result |
|
1694 * |
|
1695 * @return the number of bytes stored in <code>output</code> |
|
1696 * |
|
1697 * @exception IllegalStateException if this cipher is in a wrong state |
|
1698 * (e.g., has not been initialized) |
|
1699 * @exception ShortBufferException if the given output buffer is too small |
|
1700 * to hold the result |
|
1701 */ |
|
1702 public final int update(byte[] input, int inputOffset, int inputLen, |
|
1703 byte[] output) |
|
1704 throws ShortBufferException { |
|
1705 checkCipherState(); |
|
1706 |
|
1707 // Input sanity check |
|
1708 if (input == null || inputOffset < 0 |
|
1709 || inputLen > (input.length - inputOffset) || inputLen < 0) { |
|
1710 throw new IllegalArgumentException("Bad arguments"); |
|
1711 } |
|
1712 |
|
1713 chooseFirstProvider(); |
|
1714 if (inputLen == 0) { |
|
1715 return 0; |
|
1716 } |
|
1717 return spi.engineUpdate(input, inputOffset, inputLen, |
|
1718 output, 0); |
|
1719 } |
|
1720 |
|
1721 /** |
|
1722 * Continues a multiple-part encryption or decryption operation |
|
1723 * (depending on how this cipher was initialized), processing another data |
|
1724 * part. |
|
1725 * |
|
1726 * <p>The first <code>inputLen</code> bytes in the <code>input</code> |
|
1727 * buffer, starting at <code>inputOffset</code> inclusive, are processed, |
|
1728 * and the result is stored in the <code>output</code> buffer, starting at |
|
1729 * <code>outputOffset</code> inclusive. |
|
1730 * |
|
1731 * <p>If the <code>output</code> buffer is too small to hold the result, |
|
1732 * a <code>ShortBufferException</code> is thrown. In this case, repeat this |
|
1733 * call with a larger output buffer. Use |
|
1734 * {@link #getOutputSize(int) getOutputSize} to determine how big |
|
1735 * the output buffer should be. |
|
1736 * |
|
1737 * <p>If <code>inputLen</code> is zero, this method returns |
|
1738 * a length of zero. |
|
1739 * |
|
1740 * <p>Note: this method should be copy-safe, which means the |
|
1741 * <code>input</code> and <code>output</code> buffers can reference |
|
1742 * the same byte array and no unprocessed input data is overwritten |
|
1743 * when the result is copied into the output buffer. |
|
1744 * |
|
1745 * @param input the input buffer |
|
1746 * @param inputOffset the offset in <code>input</code> where the input |
|
1747 * starts |
|
1748 * @param inputLen the input length |
|
1749 * @param output the buffer for the result |
|
1750 * @param outputOffset the offset in <code>output</code> where the result |
|
1751 * is stored |
|
1752 * |
|
1753 * @return the number of bytes stored in <code>output</code> |
|
1754 * |
|
1755 * @exception IllegalStateException if this cipher is in a wrong state |
|
1756 * (e.g., has not been initialized) |
|
1757 * @exception ShortBufferException if the given output buffer is too small |
|
1758 * to hold the result |
|
1759 */ |
|
1760 public final int update(byte[] input, int inputOffset, int inputLen, |
|
1761 byte[] output, int outputOffset) |
|
1762 throws ShortBufferException { |
|
1763 checkCipherState(); |
|
1764 |
|
1765 // Input sanity check |
|
1766 if (input == null || inputOffset < 0 |
|
1767 || inputLen > (input.length - inputOffset) || inputLen < 0 |
|
1768 || outputOffset < 0) { |
|
1769 throw new IllegalArgumentException("Bad arguments"); |
|
1770 } |
|
1771 |
|
1772 chooseFirstProvider(); |
|
1773 if (inputLen == 0) { |
|
1774 return 0; |
|
1775 } |
|
1776 return spi.engineUpdate(input, inputOffset, inputLen, |
|
1777 output, outputOffset); |
|
1778 } |
|
1779 |
|
1780 /** |
|
1781 * Continues a multiple-part encryption or decryption operation |
|
1782 * (depending on how this cipher was initialized), processing another data |
|
1783 * part. |
|
1784 * |
|
1785 * <p>All <code>input.remaining()</code> bytes starting at |
|
1786 * <code>input.position()</code> are processed. The result is stored |
|
1787 * in the output buffer. |
|
1788 * Upon return, the input buffer's position will be equal |
|
1789 * to its limit; its limit will not have changed. The output buffer's |
|
1790 * position will have advanced by n, where n is the value returned |
|
1791 * by this method; the output buffer's limit will not have changed. |
|
1792 * |
|
1793 * <p>If <code>output.remaining()</code> bytes are insufficient to |
|
1794 * hold the result, a <code>ShortBufferException</code> is thrown. |
|
1795 * In this case, repeat this call with a larger output buffer. Use |
|
1796 * {@link #getOutputSize(int) getOutputSize} to determine how big |
|
1797 * the output buffer should be. |
|
1798 * |
|
1799 * <p>Note: this method should be copy-safe, which means the |
|
1800 * <code>input</code> and <code>output</code> buffers can reference |
|
1801 * the same block of memory and no unprocessed input data is overwritten |
|
1802 * when the result is copied into the output buffer. |
|
1803 * |
|
1804 * @param input the input ByteBuffer |
|
1805 * @param output the output ByteByffer |
|
1806 * |
|
1807 * @return the number of bytes stored in <code>output</code> |
|
1808 * |
|
1809 * @exception IllegalStateException if this cipher is in a wrong state |
|
1810 * (e.g., has not been initialized) |
|
1811 * @exception IllegalArgumentException if input and output are the |
|
1812 * same object |
|
1813 * @exception ReadOnlyBufferException if the output buffer is read-only |
|
1814 * @exception ShortBufferException if there is insufficient space in the |
|
1815 * output buffer |
|
1816 * @since 1.5 |
|
1817 */ |
|
1818 public final int update(ByteBuffer input, ByteBuffer output) |
|
1819 throws ShortBufferException { |
|
1820 checkCipherState(); |
|
1821 |
|
1822 if ((input == null) || (output == null)) { |
|
1823 throw new IllegalArgumentException("Buffers must not be null"); |
|
1824 } |
|
1825 if (input == output) { |
|
1826 throw new IllegalArgumentException("Input and output buffers must " |
|
1827 + "not be the same object, consider using buffer.duplicate()"); |
|
1828 } |
|
1829 if (output.isReadOnly()) { |
|
1830 throw new ReadOnlyBufferException(); |
|
1831 } |
|
1832 |
|
1833 chooseFirstProvider(); |
|
1834 return spi.engineUpdate(input, output); |
|
1835 } |
|
1836 |
|
1837 /** |
|
1838 * Finishes a multiple-part encryption or decryption operation, depending |
|
1839 * on how this cipher was initialized. |
|
1840 * |
|
1841 * <p>Input data that may have been buffered during a previous |
|
1842 * <code>update</code> operation is processed, with padding (if requested) |
|
1843 * being applied. |
|
1844 * The result is stored in a new buffer. |
|
1845 * |
|
1846 * <p>Upon finishing, this method resets this cipher object to the state |
|
1847 * it was in when previously initialized via a call to <code>init</code>. |
|
1848 * That is, the object is reset and available to encrypt or decrypt |
|
1849 * (depending on the operation mode that was specified in the call to |
|
1850 * <code>init</code>) more data. |
|
1851 * |
|
1852 * <p>Note: if any exception is thrown, this cipher object may need to |
|
1853 * be reset before it can be used again. |
|
1854 * |
|
1855 * @return the new buffer with the result |
|
1856 * |
|
1857 * @exception IllegalStateException if this cipher is in a wrong state |
|
1858 * (e.g., has not been initialized) |
|
1859 * @exception IllegalBlockSizeException if this cipher is a block cipher, |
|
1860 * no padding has been requested (only in encryption mode), and the total |
|
1861 * input length of the data processed by this cipher is not a multiple of |
|
1862 * block size; or if this encryption algorithm is unable to |
|
1863 * process the input data provided. |
|
1864 * @exception BadPaddingException if this cipher is in decryption mode, |
|
1865 * and (un)padding has been requested, but the decrypted data is not |
|
1866 * bounded by the appropriate padding bytes |
|
1867 */ |
|
1868 public final byte[] doFinal() |
|
1869 throws IllegalBlockSizeException, BadPaddingException { |
|
1870 checkCipherState(); |
|
1871 |
|
1872 chooseFirstProvider(); |
|
1873 return spi.engineDoFinal(null, 0, 0); |
|
1874 } |
|
1875 |
|
1876 /** |
|
1877 * Finishes a multiple-part encryption or decryption operation, depending |
|
1878 * on how this cipher was initialized. |
|
1879 * |
|
1880 * <p>Input data that may have been buffered during a previous |
|
1881 * <code>update</code> operation is processed, with padding (if requested) |
|
1882 * being applied. |
|
1883 * The result is stored in the <code>output</code> buffer, starting at |
|
1884 * <code>outputOffset</code> inclusive. |
|
1885 * |
|
1886 * <p>If the <code>output</code> buffer is too small to hold the result, |
|
1887 * a <code>ShortBufferException</code> is thrown. In this case, repeat this |
|
1888 * call with a larger output buffer. Use |
|
1889 * {@link #getOutputSize(int) getOutputSize} to determine how big |
|
1890 * the output buffer should be. |
|
1891 * |
|
1892 * <p>Upon finishing, this method resets this cipher object to the state |
|
1893 * it was in when previously initialized via a call to <code>init</code>. |
|
1894 * That is, the object is reset and available to encrypt or decrypt |
|
1895 * (depending on the operation mode that was specified in the call to |
|
1896 * <code>init</code>) more data. |
|
1897 * |
|
1898 * <p>Note: if any exception is thrown, this cipher object may need to |
|
1899 * be reset before it can be used again. |
|
1900 * |
|
1901 * @param output the buffer for the result |
|
1902 * @param outputOffset the offset in <code>output</code> where the result |
|
1903 * is stored |
|
1904 * |
|
1905 * @return the number of bytes stored in <code>output</code> |
|
1906 * |
|
1907 * @exception IllegalStateException if this cipher is in a wrong state |
|
1908 * (e.g., has not been initialized) |
|
1909 * @exception IllegalBlockSizeException if this cipher is a block cipher, |
|
1910 * no padding has been requested (only in encryption mode), and the total |
|
1911 * input length of the data processed by this cipher is not a multiple of |
|
1912 * block size; or if this encryption algorithm is unable to |
|
1913 * process the input data provided. |
|
1914 * @exception ShortBufferException if the given output buffer is too small |
|
1915 * to hold the result |
|
1916 * @exception BadPaddingException if this cipher is in decryption mode, |
|
1917 * and (un)padding has been requested, but the decrypted data is not |
|
1918 * bounded by the appropriate padding bytes |
|
1919 */ |
|
1920 public final int doFinal(byte[] output, int outputOffset) |
|
1921 throws IllegalBlockSizeException, ShortBufferException, |
|
1922 BadPaddingException { |
|
1923 checkCipherState(); |
|
1924 |
|
1925 // Input sanity check |
|
1926 if ((output == null) || (outputOffset < 0)) { |
|
1927 throw new IllegalArgumentException("Bad arguments"); |
|
1928 } |
|
1929 |
|
1930 chooseFirstProvider(); |
|
1931 return spi.engineDoFinal(null, 0, 0, output, outputOffset); |
|
1932 } |
|
1933 |
|
1934 /** |
|
1935 * Encrypts or decrypts data in a single-part operation, or finishes a |
|
1936 * multiple-part operation. The data is encrypted or decrypted, |
|
1937 * depending on how this cipher was initialized. |
|
1938 * |
|
1939 * <p>The bytes in the <code>input</code> buffer, and any input bytes that |
|
1940 * may have been buffered during a previous <code>update</code> operation, |
|
1941 * are processed, with padding (if requested) being applied. |
|
1942 * The result is stored in a new buffer. |
|
1943 * |
|
1944 * <p>Upon finishing, this method resets this cipher object to the state |
|
1945 * it was in when previously initialized via a call to <code>init</code>. |
|
1946 * That is, the object is reset and available to encrypt or decrypt |
|
1947 * (depending on the operation mode that was specified in the call to |
|
1948 * <code>init</code>) more data. |
|
1949 * |
|
1950 * <p>Note: if any exception is thrown, this cipher object may need to |
|
1951 * be reset before it can be used again. |
|
1952 * |
|
1953 * @param input the input buffer |
|
1954 * |
|
1955 * @return the new buffer with the result |
|
1956 * |
|
1957 * @exception IllegalStateException if this cipher is in a wrong state |
|
1958 * (e.g., has not been initialized) |
|
1959 * @exception IllegalBlockSizeException if this cipher is a block cipher, |
|
1960 * no padding has been requested (only in encryption mode), and the total |
|
1961 * input length of the data processed by this cipher is not a multiple of |
|
1962 * block size; or if this encryption algorithm is unable to |
|
1963 * process the input data provided. |
|
1964 * @exception BadPaddingException if this cipher is in decryption mode, |
|
1965 * and (un)padding has been requested, but the decrypted data is not |
|
1966 * bounded by the appropriate padding bytes |
|
1967 */ |
|
1968 public final byte[] doFinal(byte[] input) |
|
1969 throws IllegalBlockSizeException, BadPaddingException { |
|
1970 checkCipherState(); |
|
1971 |
|
1972 // Input sanity check |
|
1973 if (input == null) { |
|
1974 throw new IllegalArgumentException("Null input buffer"); |
|
1975 } |
|
1976 |
|
1977 chooseFirstProvider(); |
|
1978 return spi.engineDoFinal(input, 0, input.length); |
|
1979 } |
|
1980 |
|
1981 /** |
|
1982 * Encrypts or decrypts data in a single-part operation, or finishes a |
|
1983 * multiple-part operation. The data is encrypted or decrypted, |
|
1984 * depending on how this cipher was initialized. |
|
1985 * |
|
1986 * <p>The first <code>inputLen</code> bytes in the <code>input</code> |
|
1987 * buffer, starting at <code>inputOffset</code> inclusive, and any input |
|
1988 * bytes that may have been buffered during a previous <code>update</code> |
|
1989 * operation, are processed, with padding (if requested) being applied. |
|
1990 * The result is stored in a new buffer. |
|
1991 * |
|
1992 * <p>Upon finishing, this method resets this cipher object to the state |
|
1993 * it was in when previously initialized via a call to <code>init</code>. |
|
1994 * That is, the object is reset and available to encrypt or decrypt |
|
1995 * (depending on the operation mode that was specified in the call to |
|
1996 * <code>init</code>) more data. |
|
1997 * |
|
1998 * <p>Note: if any exception is thrown, this cipher object may need to |
|
1999 * be reset before it can be used again. |
|
2000 * |
|
2001 * @param input the input buffer |
|
2002 * @param inputOffset the offset in <code>input</code> where the input |
|
2003 * starts |
|
2004 * @param inputLen the input length |
|
2005 * |
|
2006 * @return the new buffer with the result |
|
2007 * |
|
2008 * @exception IllegalStateException if this cipher is in a wrong state |
|
2009 * (e.g., has not been initialized) |
|
2010 * @exception IllegalBlockSizeException if this cipher is a block cipher, |
|
2011 * no padding has been requested (only in encryption mode), and the total |
|
2012 * input length of the data processed by this cipher is not a multiple of |
|
2013 * block size; or if this encryption algorithm is unable to |
|
2014 * process the input data provided. |
|
2015 * @exception BadPaddingException if this cipher is in decryption mode, |
|
2016 * and (un)padding has been requested, but the decrypted data is not |
|
2017 * bounded by the appropriate padding bytes |
|
2018 */ |
|
2019 public final byte[] doFinal(byte[] input, int inputOffset, int inputLen) |
|
2020 throws IllegalBlockSizeException, BadPaddingException { |
|
2021 checkCipherState(); |
|
2022 |
|
2023 // Input sanity check |
|
2024 if (input == null || inputOffset < 0 |
|
2025 || inputLen > (input.length - inputOffset) || inputLen < 0) { |
|
2026 throw new IllegalArgumentException("Bad arguments"); |
|
2027 } |
|
2028 |
|
2029 chooseFirstProvider(); |
|
2030 return spi.engineDoFinal(input, inputOffset, inputLen); |
|
2031 } |
|
2032 |
|
2033 /** |
|
2034 * Encrypts or decrypts data in a single-part operation, or finishes a |
|
2035 * multiple-part operation. The data is encrypted or decrypted, |
|
2036 * depending on how this cipher was initialized. |
|
2037 * |
|
2038 * <p>The first <code>inputLen</code> bytes in the <code>input</code> |
|
2039 * buffer, starting at <code>inputOffset</code> inclusive, and any input |
|
2040 * bytes that may have been buffered during a previous <code>update</code> |
|
2041 * operation, are processed, with padding (if requested) being applied. |
|
2042 * The result is stored in the <code>output</code> buffer. |
|
2043 * |
|
2044 * <p>If the <code>output</code> buffer is too small to hold the result, |
|
2045 * a <code>ShortBufferException</code> is thrown. In this case, repeat this |
|
2046 * call with a larger output buffer. Use |
|
2047 * {@link #getOutputSize(int) getOutputSize} to determine how big |
|
2048 * the output buffer should be. |
|
2049 * |
|
2050 * <p>Upon finishing, this method resets this cipher object to the state |
|
2051 * it was in when previously initialized via a call to <code>init</code>. |
|
2052 * That is, the object is reset and available to encrypt or decrypt |
|
2053 * (depending on the operation mode that was specified in the call to |
|
2054 * <code>init</code>) more data. |
|
2055 * |
|
2056 * <p>Note: if any exception is thrown, this cipher object may need to |
|
2057 * be reset before it can be used again. |
|
2058 * |
|
2059 * <p>Note: this method should be copy-safe, which means the |
|
2060 * <code>input</code> and <code>output</code> buffers can reference |
|
2061 * the same byte array and no unprocessed input data is overwritten |
|
2062 * when the result is copied into the output buffer. |
|
2063 * |
|
2064 * @param input the input buffer |
|
2065 * @param inputOffset the offset in <code>input</code> where the input |
|
2066 * starts |
|
2067 * @param inputLen the input length |
|
2068 * @param output the buffer for the result |
|
2069 * |
|
2070 * @return the number of bytes stored in <code>output</code> |
|
2071 * |
|
2072 * @exception IllegalStateException if this cipher is in a wrong state |
|
2073 * (e.g., has not been initialized) |
|
2074 * @exception IllegalBlockSizeException if this cipher is a block cipher, |
|
2075 * no padding has been requested (only in encryption mode), and the total |
|
2076 * input length of the data processed by this cipher is not a multiple of |
|
2077 * block size; or if this encryption algorithm is unable to |
|
2078 * process the input data provided. |
|
2079 * @exception ShortBufferException if the given output buffer is too small |
|
2080 * to hold the result |
|
2081 * @exception BadPaddingException if this cipher is in decryption mode, |
|
2082 * and (un)padding has been requested, but the decrypted data is not |
|
2083 * bounded by the appropriate padding bytes |
|
2084 */ |
|
2085 public final int doFinal(byte[] input, int inputOffset, int inputLen, |
|
2086 byte[] output) |
|
2087 throws ShortBufferException, IllegalBlockSizeException, |
|
2088 BadPaddingException { |
|
2089 checkCipherState(); |
|
2090 |
|
2091 // Input sanity check |
|
2092 if (input == null || inputOffset < 0 |
|
2093 || inputLen > (input.length - inputOffset) || inputLen < 0) { |
|
2094 throw new IllegalArgumentException("Bad arguments"); |
|
2095 } |
|
2096 |
|
2097 chooseFirstProvider(); |
|
2098 return spi.engineDoFinal(input, inputOffset, inputLen, |
|
2099 output, 0); |
|
2100 } |
|
2101 |
|
2102 /** |
|
2103 * Encrypts or decrypts data in a single-part operation, or finishes a |
|
2104 * multiple-part operation. The data is encrypted or decrypted, |
|
2105 * depending on how this cipher was initialized. |
|
2106 * |
|
2107 * <p>The first <code>inputLen</code> bytes in the <code>input</code> |
|
2108 * buffer, starting at <code>inputOffset</code> inclusive, and any input |
|
2109 * bytes that may have been buffered during a previous |
|
2110 * <code>update</code> operation, are processed, with padding |
|
2111 * (if requested) being applied. |
|
2112 * The result is stored in the <code>output</code> buffer, starting at |
|
2113 * <code>outputOffset</code> inclusive. |
|
2114 * |
|
2115 * <p>If the <code>output</code> buffer is too small to hold the result, |
|
2116 * a <code>ShortBufferException</code> is thrown. In this case, repeat this |
|
2117 * call with a larger output buffer. Use |
|
2118 * {@link #getOutputSize(int) getOutputSize} to determine how big |
|
2119 * the output buffer should be. |
|
2120 * |
|
2121 * <p>Upon finishing, this method resets this cipher object to the state |
|
2122 * it was in when previously initialized via a call to <code>init</code>. |
|
2123 * That is, the object is reset and available to encrypt or decrypt |
|
2124 * (depending on the operation mode that was specified in the call to |
|
2125 * <code>init</code>) more data. |
|
2126 * |
|
2127 * <p>Note: if any exception is thrown, this cipher object may need to |
|
2128 * be reset before it can be used again. |
|
2129 * |
|
2130 * <p>Note: this method should be copy-safe, which means the |
|
2131 * <code>input</code> and <code>output</code> buffers can reference |
|
2132 * the same byte array and no unprocessed input data is overwritten |
|
2133 * when the result is copied into the output buffer. |
|
2134 * |
|
2135 * @param input the input buffer |
|
2136 * @param inputOffset the offset in <code>input</code> where the input |
|
2137 * starts |
|
2138 * @param inputLen the input length |
|
2139 * @param output the buffer for the result |
|
2140 * @param outputOffset the offset in <code>output</code> where the result |
|
2141 * is stored |
|
2142 * |
|
2143 * @return the number of bytes stored in <code>output</code> |
|
2144 * |
|
2145 * @exception IllegalStateException if this cipher is in a wrong state |
|
2146 * (e.g., has not been initialized) |
|
2147 * @exception IllegalBlockSizeException if this cipher is a block cipher, |
|
2148 * no padding has been requested (only in encryption mode), and the total |
|
2149 * input length of the data processed by this cipher is not a multiple of |
|
2150 * block size; or if this encryption algorithm is unable to |
|
2151 * process the input data provided. |
|
2152 * @exception ShortBufferException if the given output buffer is too small |
|
2153 * to hold the result |
|
2154 * @exception BadPaddingException if this cipher is in decryption mode, |
|
2155 * and (un)padding has been requested, but the decrypted data is not |
|
2156 * bounded by the appropriate padding bytes |
|
2157 */ |
|
2158 public final int doFinal(byte[] input, int inputOffset, int inputLen, |
|
2159 byte[] output, int outputOffset) |
|
2160 throws ShortBufferException, IllegalBlockSizeException, |
|
2161 BadPaddingException { |
|
2162 checkCipherState(); |
|
2163 |
|
2164 // Input sanity check |
|
2165 if (input == null || inputOffset < 0 |
|
2166 || inputLen > (input.length - inputOffset) || inputLen < 0 |
|
2167 || outputOffset < 0) { |
|
2168 throw new IllegalArgumentException("Bad arguments"); |
|
2169 } |
|
2170 |
|
2171 chooseFirstProvider(); |
|
2172 return spi.engineDoFinal(input, inputOffset, inputLen, |
|
2173 output, outputOffset); |
|
2174 } |
|
2175 |
|
2176 /** |
|
2177 * Encrypts or decrypts data in a single-part operation, or finishes a |
|
2178 * multiple-part operation. The data is encrypted or decrypted, |
|
2179 * depending on how this cipher was initialized. |
|
2180 * |
|
2181 * <p>All <code>input.remaining()</code> bytes starting at |
|
2182 * <code>input.position()</code> are processed. The result is stored |
|
2183 * in the output buffer. |
|
2184 * Upon return, the input buffer's position will be equal |
|
2185 * to its limit; its limit will not have changed. The output buffer's |
|
2186 * position will have advanced by n, where n is the value returned |
|
2187 * by this method; the output buffer's limit will not have changed. |
|
2188 * |
|
2189 * <p>If <code>output.remaining()</code> bytes are insufficient to |
|
2190 * hold the result, a <code>ShortBufferException</code> is thrown. |
|
2191 * In this case, repeat this call with a larger output buffer. Use |
|
2192 * {@link #getOutputSize(int) getOutputSize} to determine how big |
|
2193 * the output buffer should be. |
|
2194 * |
|
2195 * <p>Upon finishing, this method resets this cipher object to the state |
|
2196 * it was in when previously initialized via a call to <code>init</code>. |
|
2197 * That is, the object is reset and available to encrypt or decrypt |
|
2198 * (depending on the operation mode that was specified in the call to |
|
2199 * <code>init</code>) more data. |
|
2200 * |
|
2201 * <p>Note: if any exception is thrown, this cipher object may need to |
|
2202 * be reset before it can be used again. |
|
2203 * |
|
2204 * <p>Note: this method should be copy-safe, which means the |
|
2205 * <code>input</code> and <code>output</code> buffers can reference |
|
2206 * the same byte array and no unprocessed input data is overwritten |
|
2207 * when the result is copied into the output buffer. |
|
2208 * |
|
2209 * @param input the input ByteBuffer |
|
2210 * @param output the output ByteBuffer |
|
2211 * |
|
2212 * @return the number of bytes stored in <code>output</code> |
|
2213 * |
|
2214 * @exception IllegalStateException if this cipher is in a wrong state |
|
2215 * (e.g., has not been initialized) |
|
2216 * @exception IllegalArgumentException if input and output are the |
|
2217 * same object |
|
2218 * @exception ReadOnlyBufferException if the output buffer is read-only |
|
2219 * @exception IllegalBlockSizeException if this cipher is a block cipher, |
|
2220 * no padding has been requested (only in encryption mode), and the total |
|
2221 * input length of the data processed by this cipher is not a multiple of |
|
2222 * block size; or if this encryption algorithm is unable to |
|
2223 * process the input data provided. |
|
2224 * @exception ShortBufferException if there is insufficient space in the |
|
2225 * output buffer |
|
2226 * @exception BadPaddingException if this cipher is in decryption mode, |
|
2227 * and (un)padding has been requested, but the decrypted data is not |
|
2228 * bounded by the appropriate padding bytes |
|
2229 * @since 1.5 |
|
2230 */ |
|
2231 public final int doFinal(ByteBuffer input, ByteBuffer output) |
|
2232 throws ShortBufferException, IllegalBlockSizeException, |
|
2233 BadPaddingException { |
|
2234 checkCipherState(); |
|
2235 |
|
2236 if ((input == null) || (output == null)) { |
|
2237 throw new IllegalArgumentException("Buffers must not be null"); |
|
2238 } |
|
2239 if (input == output) { |
|
2240 throw new IllegalArgumentException("Input and output buffers must " |
|
2241 + "not be the same object, consider using buffer.duplicate()"); |
|
2242 } |
|
2243 if (output.isReadOnly()) { |
|
2244 throw new ReadOnlyBufferException(); |
|
2245 } |
|
2246 |
|
2247 chooseFirstProvider(); |
|
2248 return spi.engineDoFinal(input, output); |
|
2249 } |
|
2250 |
|
2251 /** |
|
2252 * Wrap a key. |
|
2253 * |
|
2254 * @param key the key to be wrapped. |
|
2255 * |
|
2256 * @return the wrapped key. |
|
2257 * |
|
2258 * @exception IllegalStateException if this cipher is in a wrong |
|
2259 * state (e.g., has not been initialized). |
|
2260 * |
|
2261 * @exception IllegalBlockSizeException if this cipher is a block |
|
2262 * cipher, no padding has been requested, and the length of the |
|
2263 * encoding of the key to be wrapped is not a |
|
2264 * multiple of the block size. |
|
2265 * |
|
2266 * @exception InvalidKeyException if it is impossible or unsafe to |
|
2267 * wrap the key with this cipher (e.g., a hardware protected key is |
|
2268 * being passed to a software-only cipher). |
|
2269 */ |
|
2270 public final byte[] wrap(Key key) |
|
2271 throws IllegalBlockSizeException, InvalidKeyException { |
|
2272 if (!(this instanceof NullCipher)) { |
|
2273 if (!initialized) { |
|
2274 throw new IllegalStateException("Cipher not initialized"); |
|
2275 } |
|
2276 if (opmode != Cipher.WRAP_MODE) { |
|
2277 throw new IllegalStateException("Cipher not initialized " + |
|
2278 "for wrapping keys"); |
|
2279 } |
|
2280 } |
|
2281 |
|
2282 chooseFirstProvider(); |
|
2283 return spi.engineWrap(key); |
|
2284 } |
|
2285 |
|
2286 /** |
|
2287 * Unwrap a previously wrapped key. |
|
2288 * |
|
2289 * @param wrappedKey the key to be unwrapped. |
|
2290 * |
|
2291 * @param wrappedKeyAlgorithm the algorithm associated with the wrapped |
|
2292 * key. |
|
2293 * |
|
2294 * @param wrappedKeyType the type of the wrapped key. This must be one of |
|
2295 * <code>SECRET_KEY</code>, <code>PRIVATE_KEY</code>, or |
|
2296 * <code>PUBLIC_KEY</code>. |
|
2297 * |
|
2298 * @return the unwrapped key. |
|
2299 * |
|
2300 * @exception IllegalStateException if this cipher is in a wrong state |
|
2301 * (e.g., has not been initialized). |
|
2302 * |
|
2303 * @exception NoSuchAlgorithmException if no installed providers |
|
2304 * can create keys of type <code>wrappedKeyType</code> for the |
|
2305 * <code>wrappedKeyAlgorithm</code>. |
|
2306 * |
|
2307 * @exception InvalidKeyException if <code>wrappedKey</code> does not |
|
2308 * represent a wrapped key of type <code>wrappedKeyType</code> for |
|
2309 * the <code>wrappedKeyAlgorithm</code>. |
|
2310 */ |
|
2311 public final Key unwrap(byte[] wrappedKey, |
|
2312 String wrappedKeyAlgorithm, |
|
2313 int wrappedKeyType) |
|
2314 throws InvalidKeyException, NoSuchAlgorithmException { |
|
2315 |
|
2316 if (!(this instanceof NullCipher)) { |
|
2317 if (!initialized) { |
|
2318 throw new IllegalStateException("Cipher not initialized"); |
|
2319 } |
|
2320 if (opmode != Cipher.UNWRAP_MODE) { |
|
2321 throw new IllegalStateException("Cipher not initialized " + |
|
2322 "for unwrapping keys"); |
|
2323 } |
|
2324 } |
|
2325 if ((wrappedKeyType != SECRET_KEY) && |
|
2326 (wrappedKeyType != PRIVATE_KEY) && |
|
2327 (wrappedKeyType != PUBLIC_KEY)) { |
|
2328 throw new InvalidParameterException("Invalid key type"); |
|
2329 } |
|
2330 |
|
2331 chooseFirstProvider(); |
|
2332 return spi.engineUnwrap(wrappedKey, |
|
2333 wrappedKeyAlgorithm, |
|
2334 wrappedKeyType); |
|
2335 } |
|
2336 |
|
2337 private AlgorithmParameterSpec getAlgorithmParameterSpec( |
|
2338 AlgorithmParameters params) |
|
2339 throws InvalidParameterSpecException { |
|
2340 if (params == null) { |
|
2341 return null; |
|
2342 } |
|
2343 |
|
2344 String alg = params.getAlgorithm().toUpperCase(Locale.ENGLISH); |
|
2345 |
|
2346 if (alg.equalsIgnoreCase("RC2")) { |
|
2347 return params.getParameterSpec(RC2ParameterSpec.class); |
|
2348 } |
|
2349 |
|
2350 if (alg.equalsIgnoreCase("RC5")) { |
|
2351 return params.getParameterSpec(RC5ParameterSpec.class); |
|
2352 } |
|
2353 |
|
2354 if (alg.startsWith("PBE")) { |
|
2355 return params.getParameterSpec(PBEParameterSpec.class); |
|
2356 } |
|
2357 |
|
2358 if (alg.startsWith("DES")) { |
|
2359 return params.getParameterSpec(IvParameterSpec.class); |
|
2360 } |
|
2361 return null; |
|
2362 } |
|
2363 |
|
2364 private static CryptoPermission getConfiguredPermission( |
|
2365 String transformation) throws NullPointerException, |
|
2366 NoSuchAlgorithmException { |
|
2367 if (transformation == null) throw new NullPointerException(); |
|
2368 String[] parts = tokenizeTransformation(transformation); |
|
2369 return JceSecurityManager.INSTANCE.getCryptoPermission(parts[0]); |
|
2370 } |
|
2371 |
|
2372 /** |
|
2373 * Returns the maximum key length for the specified transformation |
|
2374 * according to the installed JCE jurisdiction policy files. If |
|
2375 * JCE unlimited strength jurisdiction policy files are installed, |
|
2376 * Integer.MAX_VALUE will be returned. |
|
2377 * For more information on default key size in JCE jurisdiction |
|
2378 * policy files, please see Appendix E in the |
|
2379 * <a href= |
|
2380 * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppE"> |
|
2381 * Java Cryptography Architecture Reference Guide</a>. |
|
2382 * |
|
2383 * @param transformation the cipher transformation. |
|
2384 * @return the maximum key length in bits or Integer.MAX_VALUE. |
|
2385 * @exception NullPointerException if <code>transformation</code> is null. |
|
2386 * @exception NoSuchAlgorithmException if <code>transformation</code> |
|
2387 * is not a valid transformation, i.e. in the form of "algorithm" or |
|
2388 * "algorithm/mode/padding". |
|
2389 * @since 1.5 |
|
2390 */ |
|
2391 public static final int getMaxAllowedKeyLength(String transformation) |
|
2392 throws NoSuchAlgorithmException { |
|
2393 CryptoPermission cp = getConfiguredPermission(transformation); |
|
2394 return cp.getMaxKeySize(); |
|
2395 } |
|
2396 |
|
2397 /** |
|
2398 * Returns an AlgorithmParameterSpec object which contains |
|
2399 * the maximum cipher parameter value according to the |
|
2400 * jurisdiction policy file. If JCE unlimited strength jurisdiction |
|
2401 * policy files are installed or there is no maximum limit on the |
|
2402 * parameters for the specified transformation in the policy file, |
|
2403 * null will be returned. |
|
2404 * |
|
2405 * @param transformation the cipher transformation. |
|
2406 * @return an AlgorithmParameterSpec which holds the maximum |
|
2407 * value or null. |
|
2408 * @exception NullPointerException if <code>transformation</code> |
|
2409 * is null. |
|
2410 * @exception NoSuchAlgorithmException if <code>transformation</code> |
|
2411 * is not a valid transformation, i.e. in the form of "algorithm" or |
|
2412 * "algorithm/mode/padding". |
|
2413 * @since 1.5 |
|
2414 */ |
|
2415 public static final AlgorithmParameterSpec getMaxAllowedParameterSpec( |
|
2416 String transformation) throws NoSuchAlgorithmException { |
|
2417 CryptoPermission cp = getConfiguredPermission(transformation); |
|
2418 return cp.getAlgorithmParameterSpec(); |
|
2419 } |
|
2420 } |