OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [crypto/] [Cipher.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* Cipher.java -- Interface to a cryptographic cipher.
2
   Copyright (C) 2004, 2006  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.crypto;
40
 
41
import gnu.java.security.Engine;
42
 
43
import java.nio.ByteBuffer;
44
import java.nio.ReadOnlyBufferException;
45
 
46
import java.security.AlgorithmParameters;
47
import java.security.InvalidAlgorithmParameterException;
48
import java.security.InvalidKeyException;
49
import java.security.Key;
50
import java.security.NoSuchAlgorithmException;
51
import java.security.NoSuchProviderException;
52
import java.security.Provider;
53
import java.security.SecureRandom;
54
import java.security.Security;
55
import java.security.cert.Certificate;
56
import java.security.cert.X509Certificate;
57
import java.security.spec.AlgorithmParameterSpec;
58
import java.util.StringTokenizer;
59
 
60
/**
61
 * <p>This class implements a cryptographic cipher for transforming
62
 * data.</p>
63
 *
64
 * <p>Ciphers cannot be instantiated directly; rather one of the
65
 * <code>getInstance</code> must be used to instantiate a given
66
 * <i>transformation</i>, optionally with a specific provider.</p>
67
 *
68
 * <p>A transformation is of the form:</p>
69
 *
70
 * <ul>
71
 * <li><i>algorithm</i>/<i>mode</i>/<i>padding</i>, or</li>
72
 * <li><i>algorithm</i>
73
 * </ul>
74
 *
75
 * <p>where <i>algorithm</i> is the base name of a cryptographic cipher
76
 * (such as "AES"), <i>mode</i> is the abbreviated name of a block
77
 * cipher mode (such as "CBC" for cipher block chaining mode), and
78
 * <i>padding</i> is the name of a padding scheme (such as
79
 * "PKCS5Padding"). If only the algorithm name is supplied, then the
80
 * provider-specific default mode and padding will be used.</p>
81
 *
82
 * <p>An example transformation is:</p>
83
 *
84
 * <blockquote><code>Cipher c =
85
 * Cipher.getInstance("AES/CBC/PKCS5Padding");</code></blockquote>
86
 *
87
 * <p>Finally, when requesting a block cipher in stream cipher mode
88
 * (such as <acronym title="Advanced Encryption Standard">AES</acronym>
89
 * in OFB or CFB mode) the number of bits to be processed
90
 * at a time may be specified by appending it to the name of the mode;
91
 * e.g. <code>"AES/OFB8/NoPadding"</code>. If no such number is
92
 * specified a provider-specific default value is used.</p>
93
 *
94
 * @author Casey Marshall (csm@gnu.org)
95
 * @see java.security.KeyGenerator
96
 * @see javax.crypto.SecretKey
97
 */
98
public class Cipher
99
{
100
 
101
  // Constants and variables.
102
  // ------------------------------------------------------------------------
103
 
104
  private static final String SERVICE = "Cipher";
105
 
106
  /**
107
   * The decryption operation mode.
108
   */
109
  public static final int DECRYPT_MODE = 2;
110
 
111
  /**
112
   * The encryption operation mode.
113
   */
114
  public static final int ENCRYPT_MODE = 1;
115
 
116
  /**
117
   * Constant for when the key to be unwrapped is a private key.
118
   */
119
  public static final int PRIVATE_KEY = 2;
120
 
121
  /**
122
   * Constant for when the key to be unwrapped is a public key.
123
   */
124
  public static final int PUBLIC_KEY = 1;
125
 
126
  /**
127
   * Constant for when the key to be unwrapped is a secret key.
128
   */
129
  public static final int SECRET_KEY = 3;
130
 
131
  /**
132
   * The key unwrapping operation mode.
133
   */
134
  public static final int UNWRAP_MODE = 4;
135
 
136
  /**
137
   * The key wrapping operation mode.
138
   */
139
  public static final int WRAP_MODE = 3;
140
 
141
  /**
142
   * The uninitialized state. This state signals that any of the
143
   * <code>init</code> methods have not been called, and therefore no
144
   * transformations can be done.
145
   */
146
  private static final int INITIAL_STATE = 0;
147
 
148
  /** The underlying cipher service provider interface. */
149
  private CipherSpi cipherSpi;
150
 
151
  /** The provider from which this instance came. */
152
  private Provider provider;
153
 
154
  /** The transformation requested. */
155
  private String transformation;
156
 
157
  /** Our current state (encrypting, wrapping, etc.) */
158
  private int state;
159
 
160
  /**
161
   * Creates a new cipher instance for the given transformation.
162
   * <p>
163
   * The installed providers are tried in order for an implementation, and the
164
   * first appropriate instance is returned. If no installed provider can
165
   * provide the implementation, an appropriate exception is thrown.
166
   *
167
   * @param transformation The transformation to create.
168
   * @return An appropriate cipher for this transformation.
169
   * @throws NoSuchAlgorithmException If no installed provider can supply the
170
   *           appropriate cipher or mode.
171
   * @throws NoSuchPaddingException If no installed provider can supply the
172
   *           appropriate padding.
173
   */
174
  public static final Cipher getInstance(String transformation)
175
      throws NoSuchAlgorithmException, NoSuchPaddingException
176
  {
177
    Provider[] p = Security.getProviders();
178
    NoSuchAlgorithmException lastException = null;
179
    NoSuchPaddingException lastPaddingException = null;
180
    for (int i = 0; i < p.length; i++)
181
      try
182
        {
183
          return getInstance(transformation, p[i]);
184
        }
185
      catch (NoSuchAlgorithmException x)
186
        {
187
          lastException = x;
188
          lastPaddingException = null;
189
        }
190
      catch (NoSuchPaddingException x)
191
        {
192
          lastPaddingException = x;
193
        }
194
    if (lastPaddingException != null)
195
      throw lastPaddingException;
196
    if (lastException != null)
197
      throw lastException;
198
    throw new NoSuchAlgorithmException(transformation);
199
  }
200
 
201
  /**
202
   * Creates a new cipher instance for the given transformation and the named
203
   * provider.
204
   *
205
   * @param transformation The transformation to create.
206
   * @param provider The name of the provider to use.
207
   * @return An appropriate cipher for this transformation.
208
   * @throws NoSuchAlgorithmException If the provider cannot supply the
209
   *           appropriate cipher or mode.
210
   * @throws NoSuchProviderException If the named provider is not installed.
211
   * @throws NoSuchPaddingException If the provider cannot supply the
212
   *           appropriate padding.
213
   * @throws IllegalArgumentException if either <code>transformation</code> or
214
   *           <code>provider</code> is <code>null</code>.
215
   */
216
  public static final Cipher getInstance(String transformation, String provider)
217
      throws NoSuchAlgorithmException, NoSuchProviderException,
218
      NoSuchPaddingException
219
  {
220
    if (provider == null)
221
      throw new IllegalArgumentException("provider MUST NOT be null");
222
    Provider p = Security.getProvider(provider);
223
    if (p == null)
224
      throw new NoSuchProviderException(provider);
225
    return getInstance(transformation, p);
226
  }
227
 
228
  /**
229
   * Creates a new cipher instance for a given transformation from a given
230
   * provider.
231
   *
232
   * @param transformation The transformation to create.
233
   * @param provider The provider to use.
234
   * @return An appropriate cipher for this transformation.
235
   * @throws NoSuchAlgorithmException If the given provider cannot supply the
236
   *           appropriate cipher or mode.
237
   * @throws NoSuchPaddingException If the given provider cannot supply the
238
   *           appropriate padding scheme.
239
   */
240
  public static final Cipher getInstance(String transformation,
241
                                         Provider provider)
242
      throws NoSuchAlgorithmException, NoSuchPaddingException
243
  {
244
    StringBuilder sb = new StringBuilder().append("Cipher transformation [")
245
        .append(transformation).append("] from provider [")
246
        .append(provider).append("] ");
247
    Throwable cause;
248
    Object spi;
249
    CipherSpi result;
250
    if (transformation.indexOf('/') < 0)
251
      {
252
        try
253
          {
254
            spi = Engine.getInstance(SERVICE, transformation, provider);
255
            return new Cipher((CipherSpi) spi, provider, transformation);
256
          }
257
        catch (Exception e)
258
          {
259
            if (e instanceof NoSuchAlgorithmException)
260
              throw (NoSuchAlgorithmException) e;
261
            cause = e;
262
          }
263
      }
264
    else
265
      {
266
        StringTokenizer tok = new StringTokenizer(transformation, "/");
267
        if (tok.countTokens() != 3)
268
          throw new NoSuchAlgorithmException(sb.append("is malformed").toString());
269
 
270
        String alg = tok.nextToken();
271
        String mode = tok.nextToken();
272
        String pad = tok.nextToken();
273
        try
274
          {
275
            spi = Engine.getInstance(SERVICE, transformation, provider);
276
            return new Cipher((CipherSpi) spi, provider, transformation);
277
          }
278
        catch (Exception e)
279
          {
280
            cause = e;
281
          }
282
 
283
        try
284
          {
285
            spi = Engine.getInstance(SERVICE, alg + '/' + mode, provider);
286
            result = (CipherSpi) spi;
287
            result.engineSetPadding(pad);
288
            return new Cipher(result, provider, transformation);
289
          }
290
        catch (Exception e)
291
          {
292
            if (e instanceof NoSuchPaddingException)
293
              throw (NoSuchPaddingException) e;
294
            cause = e;
295
          }
296
 
297
        try
298
          {
299
            spi = Engine.getInstance(SERVICE, alg + "//" + pad, provider);
300
            result = (CipherSpi) spi;
301
            result.engineSetMode(mode);
302
            return new Cipher(result, provider, transformation);
303
          }
304
        catch (Exception e)
305
          {
306
            cause = e;
307
          }
308
 
309
        try
310
          {
311
            spi = Engine.getInstance(SERVICE, alg, provider);
312
            result = (CipherSpi) spi;
313
            result.engineSetMode(mode);
314
            result.engineSetPadding(pad);
315
            return new Cipher(result, provider, transformation);
316
          }
317
        catch (Exception e)
318
          {
319
            if (e instanceof NoSuchPaddingException)
320
              throw (NoSuchPaddingException) e;
321
            cause = e;
322
          }
323
      }
324
    sb.append("could not be created");
325
    NoSuchAlgorithmException x = new NoSuchAlgorithmException(sb.toString());
326
    x.initCause(cause);
327
    throw x;
328
  }
329
 
330
  /**
331
   * Create a cipher.
332
   *
333
   * @param cipherSpi The underlying implementation of the cipher.
334
   * @param provider  The provider of this cipher implementation.
335
   * @param transformation The transformation this cipher performs.
336
   */
337
  protected
338
  Cipher(CipherSpi cipherSpi, Provider provider, String transformation)
339
  {
340
    this.cipherSpi = cipherSpi;
341
    this.provider = provider;
342
    this.transformation = transformation;
343
    state = INITIAL_STATE;
344
  }
345
 
346
  /**
347
   * Get the name that this cipher instance was created with; this is
348
   * equivalent to the "transformation" argument given to any of the
349
   * {@link #getInstance()} methods.
350
   *
351
   * @return The cipher name.
352
   */
353
  public final String getAlgorithm()
354
  {
355
    return transformation;
356
  }
357
 
358
  /**
359
   * Return the size of blocks, in bytes, that this cipher processes.
360
   *
361
   * @return The block size.
362
   */
363
  public final int getBlockSize()
364
  {
365
    if (cipherSpi != null)
366
      {
367
        return cipherSpi.engineGetBlockSize();
368
      }
369
    return 1;
370
  }
371
 
372
  /**
373
   * Return the currently-operating {@link ExemptionMechanism}.
374
   *
375
   * @return null, currently.
376
   */
377
  public final ExemptionMechanism getExemptionMechanism()
378
  {
379
    return null;
380
  }
381
 
382
  /**
383
   * Return the <i>initialization vector</i> that this instance was
384
   * initialized with.
385
   *
386
   * @return The IV.
387
   */
388
  public final byte[] getIV()
389
  {
390
    if (cipherSpi != null)
391
      {
392
        return cipherSpi.engineGetIV();
393
      }
394
    return null;
395
  }
396
 
397
  /**
398
   * Return the {@link java.security.AlgorithmParameters} that this
399
   * instance was initialized with.
400
   *
401
   * @return The parameters.
402
   */
403
  public final AlgorithmParameters getParameters()
404
  {
405
    if (cipherSpi != null) {
406
      return cipherSpi.engineGetParameters();
407
    }
408
    return null;
409
  }
410
 
411
  /**
412
   * Return this cipher's provider.
413
   *
414
   * @return The provider.
415
   */
416
  public final Provider getProvider()
417
  {
418
    return provider;
419
  }
420
 
421
  /**
422
   * Finishes a multi-part transformation, and returns the final
423
   * transformed bytes.
424
   *
425
   * @return The final transformed bytes.
426
   * @throws java.lang.IllegalStateException If this instance has not
427
   *         been initialized, or if a <tt>doFinal</tt> call has already
428
   *         been made.
429
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
430
   *         no padding and the input is not a multiple of this cipher's
431
   *         block size.
432
   * @throws javax.crypto.BadPaddingException If this instance is
433
   *         decrypting and the padding bytes do not match this
434
   *         instance's padding scheme.
435
   */
436
  public final byte[] doFinal()
437
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException
438
  {
439
    return doFinal(new byte[0], 0, 0);
440
  }
441
 
442
  /**
443
   * Finishes a multi-part transformation or does an entire
444
   * transformation on the input, and returns the transformed bytes.
445
   *
446
   * @param input The final input bytes.
447
   * @return The final transformed bytes.
448
   * @throws java.lang.IllegalStateException If this instance has not
449
   *         been initialized, or if a <tt>doFinal</tt> call has already
450
   *         been made.
451
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
452
   *         no padding and the input is not a multiple of this cipher's
453
   *         block size.
454
   * @throws javax.crypto.BadPaddingException If this instance is
455
   *         decrypting and the padding bytes do not match this
456
   *         instance's padding scheme.
457
   */
458
  public final byte[] doFinal(byte[] input)
459
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException
460
  {
461
    return doFinal(input, 0, input.length);
462
  }
463
 
464
  /**
465
   * Finishes a multi-part transformation or does an entire
466
   * transformation on the input, and returns the transformed bytes.
467
   *
468
   * @param input       The final input bytes.
469
   * @param inputOffset The index in the input bytes to start.
470
   * @param inputLength The number of bytes to read from the input.
471
   * @return The final transformed bytes.
472
   * @throws java.lang.IllegalStateException If this instance has not
473
   *         been initialized, or if a <tt>doFinal</tt> call has already
474
   *         been made.
475
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
476
   *         no padding and the input is not a multiple of this cipher's
477
   *         block size.
478
   * @throws javax.crypto.BadPaddingException If this instance is
479
   *         decrypting and the padding bytes do not match this
480
   *         instance's padding scheme.
481
   */
482
  public final byte[] doFinal(byte[] input, int inputOffset, int inputLength)
483
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException
484
  {
485
    if (cipherSpi == null)
486
      {
487
        byte[] b = new byte[inputLength];
488
        System.arraycopy(input, inputOffset, b, 0, inputLength);
489
        return b;
490
      }
491
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
492
      {
493
        throw new IllegalStateException("neither encrypting nor decrypting");
494
      }
495
    return cipherSpi.engineDoFinal(input, inputOffset, inputLength);
496
  }
497
 
498
  /**
499
   * Finishes a multi-part transformation and stores the transformed
500
   * bytes into the given array.
501
   *
502
   * @param output       The destination for the transformed bytes.
503
   * @param outputOffset The offset in <tt>output</tt> to start storing
504
   *        bytes.
505
   * @return The number of bytes placed into the output array.
506
   * @throws java.lang.IllegalStateException If this instance has not
507
   *         been initialized, or if a <tt>doFinal</tt> call has already
508
   *         been made.
509
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
510
   *         no padding and the input is not a multiple of this cipher's
511
   *         block size.
512
   * @throws javax.crypto.BadPaddingException If this instance is
513
   *         decrypting and the padding bytes do not match this
514
   *         instance's padding scheme.
515
   * @throws javax.crypto.ShortBufferException If the output array is
516
   *         not large enough to hold the transformed bytes.
517
   */
518
  public final int doFinal(byte[] output, int outputOffset)
519
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException,
520
           ShortBufferException
521
  {
522
    if (cipherSpi == null)
523
      {
524
        return 0;
525
      }
526
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
527
      {
528
        throw new IllegalStateException("neither encrypting nor decrypting");
529
      }
530
    return cipherSpi.engineDoFinal(new byte[0], 0, 0, output, outputOffset);
531
  }
532
 
533
  /**
534
   * Finishes a multi-part transformation or transforms a portion of a
535
   * byte array, and stores the result in the given byte array.
536
   *
537
   * @param input        The input bytes.
538
   * @param inputOffset  The index in <tt>input</tt> to start.
539
   * @param inputLength  The number of bytes to transform.
540
   * @param output       The output buffer.
541
   * @param outputOffset The index in <tt>output</tt> to start.
542
   * @return The number of bytes placed into the output array.
543
   * @throws java.lang.IllegalStateException If this instance has not
544
   *         been initialized, or if a <tt>doFinal</tt> call has already
545
   *         been made.
546
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
547
   *         no padding and the input is not a multiple of this cipher's
548
   *         block size.
549
   * @throws javax.crypto.BadPaddingException If this instance is
550
   *         decrypting and the padding bytes do not match this
551
   *         instance's padding scheme.
552
   * @throws javax.crypto.ShortBufferException If the output array is
553
   *         not large enough to hold the transformed bytes.
554
   */
555
  public final int doFinal(byte[] input, int inputOffset, int inputLength,
556
                           byte[] output, int outputOffset)
557
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException,
558
           ShortBufferException
559
  {
560
    if (cipherSpi == null)
561
      {
562
        if (inputLength > output.length - outputOffset)
563
          {
564
            throw new ShortBufferException();
565
          }
566
        System.arraycopy(input, inputOffset, output, outputOffset, inputLength);
567
        return inputLength;
568
      }
569
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
570
      {
571
        throw new IllegalStateException("neither encrypting nor decrypting");
572
      }
573
    return cipherSpi.engineDoFinal(input, inputOffset, inputLength,
574
                                   output, outputOffset);
575
  }
576
 
577
  public final int doFinal(byte[] input, int inputOffset, int inputLength,
578
                           byte[] output)
579
    throws IllegalStateException, IllegalBlockSizeException, BadPaddingException,
580
           ShortBufferException
581
  {
582
    return doFinal(input, inputOffset, inputLength, output, 0);
583
  }
584
 
585
  /**
586
   * Finishes a multi-part transformation with, or completely
587
   * transforms, a byte buffer, and stores the result into the output
588
   * buffer.
589
   *
590
   * @param input  The input buffer.
591
   * @param output The output buffer.
592
   * @return The number of bytes stored into the output buffer.
593
   * @throws IllegalArgumentException If the input and output buffers
594
   *  are the same object.
595
   * @throws IllegalStateException If this cipher was not initialized
596
   *  for encryption or decryption.
597
   * @throws ReadOnlyBufferException If the output buffer is not
598
   *  writable.
599
   * @throws IllegalBlockSizeException If this cipher requires a total
600
   *  input that is a multiple of its block size to complete this
601
   *  transformation.
602
   * @throws ShortBufferException If the output buffer is not large
603
   *  enough to hold the transformed bytes.
604
   * @throws BadPaddingException If the cipher is a block cipher with
605
   *  a padding scheme, and the decrypted bytes do not end with a
606
   *  valid padding.
607
   * @since 1.5
608
   */
609
  public final int doFinal (ByteBuffer input, ByteBuffer output)
610
    throws ReadOnlyBufferException, ShortBufferException,
611
           BadPaddingException, IllegalBlockSizeException
612
  {
613
    if (input == output)
614
      throw new IllegalArgumentException
615
        ("input and output buffers cannot be the same");
616
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
617
      throw new IllegalStateException
618
        ("not initialized for encrypting or decrypting");
619
    return cipherSpi.engineDoFinal (input, output);
620
  }
621
 
622
  /**
623
   * Returns the size an output buffer needs to be if this cipher is
624
   * updated with a number of bytes.
625
   *
626
   * @param inputLength The input length.
627
   * @return The output length given this input length.
628
   * @throws java.lang.IllegalStateException If this instance has not
629
   *         been initialized, or if a <tt>doFinal</tt> call has already
630
   *         been made.
631
   */
632
  public final int getOutputSize(int inputLength) throws IllegalStateException
633
  {
634
    if (cipherSpi == null)
635
      return inputLength;
636
    return cipherSpi.engineGetOutputSize(inputLength);
637
  }
638
 
639
  /**
640
   * <p>Initialize this cipher with the public key from the given
641
   * certificate.</p>
642
   *
643
   * <p>The cipher will be initialized for encryption, decryption, key
644
   * wrapping, or key unwrapping, depending upon whether the
645
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
646
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
647
   * respectively.</p>
648
   *
649
   * <p>As per the Java 1.4 specification, if <code>cert</code> is an
650
   * instance of an {@link java.security.cert.X509Certificate} and its
651
   * <i>key usage</i> extension field is incompatible with
652
   * <code>opmode</code> then an {@link
653
   * java.security.InvalidKeyException} is thrown.</p>
654
   *
655
   * <p>If this cipher requires any random bytes (for example for an
656
   * initilization vector) than the {@link java.security.SecureRandom}
657
   * with the highest priority is used as the source of these bytes.</p>
658
   *
659
   * <p>A call to any of the <code>init</code> methods overrides the
660
   * state of the instance, and is equivalent to creating a new instance
661
   * and calling its <code>init</code> method.</p>
662
   *
663
   * @param opmode      The operation mode to use.
664
   * @param certificate The certificate.
665
   * @throws java.security.InvalidKeyException If the underlying cipher
666
   *         instance rejects the certificate's public key, or if the
667
   *         public key cannot be used as described above.
668
   */
669
  public final void init(int opmode, Certificate certificate)
670
    throws InvalidKeyException
671
  {
672
    init(opmode, certificate, new SecureRandom());
673
  }
674
 
675
  /**
676
   * <p>Initialize this cipher with the supplied key.</p>
677
   *
678
   * <p>The cipher will be initialized for encryption, decryption, key
679
   * wrapping, or key unwrapping, depending upon whether the
680
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
681
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
682
   * respectively.</p>
683
   *
684
   * <p>If this cipher requires any random bytes (for example for an
685
   * initilization vector) than the {@link java.security.SecureRandom}
686
   * with the highest priority is used as the source of these bytes.</p>
687
   *
688
   * <p>A call to any of the <code>init</code> methods overrides the
689
   * state of the instance, and is equivalent to creating a new instance
690
   * and calling its <code>init</code> method.</p>
691
   *
692
   * @param opmode The operation mode to use.
693
   * @param key    The key.
694
   * @throws java.security.InvalidKeyException If the underlying cipher
695
   *         instance rejects the given key.
696
   */
697
  public final void init(int opmode, Key key) throws InvalidKeyException
698
  {
699
    if (cipherSpi != null)
700
      {
701
        cipherSpi.engineInit(opmode, key, new SecureRandom());
702
      }
703
    state = opmode;
704
  }
705
 
706
  /**
707
   * <p>Initialize this cipher with the public key from the given
708
   * certificate and the specified source of randomness.</p>
709
   *
710
   * <p>The cipher will be initialized for encryption, decryption, key
711
   * wrapping, or key unwrapping, depending upon whether the
712
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
713
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
714
   * respectively.</p>
715
   *
716
   * <p>As per the Java 1.4 specification, if <code>cert</code> is an
717
   * instance of an {@link java.security.cert.X509Certificate} and its
718
   * <i>key usage</i> extension field is incompatible with
719
   * <code>opmode</code> then an {@link
720
   * java.security.InvalidKeyException} is thrown.</p>
721
   *
722
   * <p>If this cipher requires any random bytes (for example for an
723
   * initilization vector) than the {@link java.security.SecureRandom}
724
   * with the highest priority is used as the source of these bytes.</p>
725
   *
726
   * <p>A call to any of the <code>init</code> methods overrides the
727
   * state of the instance, and is equivalent to creating a new instance
728
   * and calling its <code>init</code> method.</p>
729
   *
730
   * @param opmode      The operation mode to use.
731
   * @param certificate The certificate.
732
   * @param random      The source of randomness.
733
   * @throws java.security.InvalidKeyException If the underlying cipher
734
   *         instance rejects the certificate's public key, or if the
735
   *         public key cannot be used as described above.
736
   */
737
  public final void
738
  init(int opmode, Certificate certificate, SecureRandom random)
739
  throws InvalidKeyException
740
  {
741
    if (certificate instanceof X509Certificate)
742
      {
743
        boolean[] keyInfo = ((X509Certificate) certificate).getKeyUsage();
744
        if (keyInfo != null)
745
          {
746
            switch (opmode)
747
              {
748
              case DECRYPT_MODE:
749
                if (!keyInfo[3])
750
                  {
751
                    throw new InvalidKeyException(
752
                      "the certificate's key cannot be used for transforming data");
753
                  }
754
                if (keyInfo[7])
755
                  {
756
                    throw new InvalidKeyException(
757
                      "the certificate's key can only be used for encryption");
758
                  }
759
                break;
760
 
761
              case ENCRYPT_MODE:
762
                if (!keyInfo[3])
763
                  {
764
                    throw new InvalidKeyException(
765
                      "the certificate's key cannot be used for transforming data");
766
                  }
767
                if (keyInfo[8])
768
                  {
769
                    throw new InvalidKeyException(
770
                      "the certificate's key can only be used for decryption");
771
                  }
772
                break;
773
 
774
              case UNWRAP_MODE:
775
                if (!keyInfo[2] || keyInfo[7])
776
                  {
777
                    throw new InvalidKeyException(
778
                      "the certificate's key cannot be used for key unwrapping");
779
                  }
780
                break;
781
 
782
              case WRAP_MODE:
783
                if (!keyInfo[2] || keyInfo[8])
784
                  {
785
                    throw new InvalidKeyException(
786
                      "the certificate's key cannot be used for key wrapping");
787
                  }
788
                break;
789
              }
790
          }
791
      }
792
    init(opmode, certificate.getPublicKey(), random);
793
  }
794
 
795
  /**
796
   * <p>Initialize this cipher with the supplied key and source of
797
   * randomness.</p>
798
   *
799
   * <p>The cipher will be initialized for encryption, decryption, key
800
   * wrapping, or key unwrapping, depending upon whether the
801
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
802
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
803
   * respectively.</p>
804
   *
805
   * <p>A call to any of the <code>init</code> methods overrides the
806
   * state of the instance, and is equivalent to creating a new instance
807
   * and calling its <code>init</code> method.</p>
808
   *
809
   * @param opmode The operation mode to use.
810
   * @param key    The key.
811
   * @param random The source of randomness to use.
812
   * @throws java.security.InvalidKeyException If the underlying cipher
813
   *         instance rejects the given key.
814
   */
815
  public final void init(int opmode, Key key, SecureRandom random)
816
    throws InvalidKeyException
817
  {
818
    if (cipherSpi != null)
819
      {
820
        cipherSpi.engineInit(opmode, key, random);
821
      }
822
    state = opmode;
823
  }
824
 
825
  /**
826
   * <p>Initialize this cipher with the supplied key and parameters.</p>
827
   *
828
   * <p>The cipher will be initialized for encryption, decryption, key
829
   * wrapping, or key unwrapping, depending upon whether the
830
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
831
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
832
   * respectively.</p>
833
   *
834
   * <p>If this cipher requires any random bytes (for example for an
835
   * initilization vector) then the {@link java.security.SecureRandom}
836
   * with the highest priority is used as the source of these bytes.</p>
837
   *
838
   * <p>A call to any of the <code>init</code> methods overrides the
839
   * state of the instance, and is equivalent to creating a new instance
840
   * and calling its <code>init</code> method.</p>
841
   *
842
   * @param opmode The operation mode to use.
843
   * @param key    The key.
844
   * @param params The algorithm parameters to initialize this instance
845
   *               with.
846
   * @throws java.security.InvalidKeyException If the underlying cipher
847
   *         instance rejects the given key.
848
   * @throws java.security.InvalidAlgorithmParameterException If the
849
   *         supplied parameters are inappropriate for this cipher.
850
   */
851
  public final void init(int opmode, Key key, AlgorithmParameters params)
852
    throws InvalidKeyException, InvalidAlgorithmParameterException
853
  {
854
    init(opmode, key, params, new SecureRandom());
855
  }
856
 
857
  /**
858
   * <p>Initialize this cipher with the supplied key and parameters.</p>
859
   *
860
   * <p>The cipher will be initialized for encryption, decryption, key
861
   * wrapping, or key unwrapping, depending upon whether the
862
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
863
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
864
   * respectively.</p>
865
   *
866
   * <p>If this cipher requires any random bytes (for example for an
867
   * initilization vector) then the {@link java.security.SecureRandom}
868
   * with the highest priority is used as the source of these bytes.</p>
869
   *
870
   * <p>A call to any of the <code>init</code> methods overrides the
871
   * state of the instance, and is equivalent to creating a new instance
872
   * and calling its <code>init</code> method.</p>
873
   *
874
   * @param opmode The operation mode to use.
875
   * @param key    The key.
876
   * @param params The algorithm parameters to initialize this instance
877
   *               with.
878
   * @throws java.security.InvalidKeyException If the underlying cipher
879
   *         instance rejects the given key.
880
   * @throws java.security.InvalidAlgorithmParameterException If the
881
   *         supplied parameters are inappropriate for this cipher.
882
   */
883
  public final void init(int opmode, Key key, AlgorithmParameterSpec params)
884
    throws InvalidKeyException, InvalidAlgorithmParameterException
885
  {
886
    init(opmode, key, params, new SecureRandom());
887
  }
888
 
889
  /**
890
   * <p>Initialize this cipher with the supplied key, parameters, and
891
   * source of randomness.</p>
892
   *
893
   * <p>The cipher will be initialized for encryption, decryption, key
894
   * wrapping, or key unwrapping, depending upon whether the
895
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
896
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
897
   * respectively.</p>
898
   *
899
   * <p>A call to any of the <code>init</code> methods overrides the
900
   * state of the instance, and is equivalent to creating a new instance
901
   * and calling its <code>init</code> method.</p>
902
   *
903
   * @param opmode The operation mode to use.
904
   * @param key    The key.
905
   * @param params The algorithm parameters to initialize this instance
906
   *               with.
907
   * @param random The source of randomness to use.
908
   * @throws java.security.InvalidKeyException If the underlying cipher
909
   *         instance rejects the given key.
910
   * @throws java.security.InvalidAlgorithmParameterException If the
911
   *         supplied parameters are inappropriate for this cipher.
912
   */
913
  public final void init(int opmode, Key key, AlgorithmParameters params,
914
                         SecureRandom random)
915
    throws InvalidKeyException, InvalidAlgorithmParameterException
916
  {
917
    if (cipherSpi != null)
918
      {
919
        cipherSpi.engineInit(opmode, key, params, random);
920
      }
921
    state = opmode;
922
  }
923
 
924
  /**
925
   * <p>Initialize this cipher with the supplied key, parameters, and
926
   * source of randomness.</p>
927
   *
928
   * <p>The cipher will be initialized for encryption, decryption, key
929
   * wrapping, or key unwrapping, depending upon whether the
930
   * <code>opmode</code> argument is {@link #ENCRYPT_MODE}, {@link
931
   * #DECRYPT_MODE}, {@link #WRAP_MODE}, or {@link #UNWRAP_MODE},
932
   * respectively.</p>
933
   *
934
   * <p>A call to any of the <code>init</code> methods overrides the
935
   * state of the instance, and is equivalent to creating a new instance
936
   * and calling its <code>init</code> method.</p>
937
   *
938
   * @param opmode The operation mode to use.
939
   * @param key    The key.
940
   * @param params The algorithm parameters to initialize this instance
941
   *               with.
942
   * @param random The source of randomness to use.
943
   * @throws java.security.InvalidKeyException If the underlying cipher
944
   *         instance rejects the given key.
945
   * @throws java.security.InvalidAlgorithmParameterException If the
946
   *         supplied parameters are inappropriate for this cipher.
947
   */
948
  public final void init(int opmode, Key key, AlgorithmParameterSpec params,
949
                         SecureRandom random)
950
    throws InvalidKeyException, InvalidAlgorithmParameterException
951
  {
952
    if (cipherSpi != null)
953
      {
954
        cipherSpi.engineInit(opmode, key, params, random);
955
      }
956
    state = opmode;
957
  }
958
 
959
  /**
960
   * Unwrap a previously-wrapped key.
961
   *
962
   * @param wrappedKey          The wrapped key.
963
   * @param wrappedKeyAlgorithm The algorithm with which the key was
964
   *        wrapped.
965
   * @param wrappedKeyType      The type of key (public, private, or
966
   *        secret) that this wrapped key respresents.
967
   * @return The unwrapped key.
968
   * @throws java.lang.IllegalStateException If this instance has not be
969
   *         initialized for unwrapping.
970
   * @throws java.security.InvalidKeyException If <code>wrappedKey</code>
971
   *         is not a wrapped key, if the algorithm cannot unwrap this
972
   *         key, or if the unwrapped key's type differs from the
973
   *         specified type.
974
   * @throws java.security.NoSuchAlgorithmException If
975
   *         <code>wrappedKeyAlgorithm</code> is not a valid algorithm
976
   *         name.
977
   */
978
  public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
979
                          int wrappedKeyType)
980
    throws IllegalStateException, InvalidKeyException, NoSuchAlgorithmException
981
  {
982
    if (cipherSpi == null)
983
      {
984
        return null;
985
      }
986
    if (state != UNWRAP_MODE)
987
      {
988
        throw new IllegalStateException("instance is not for unwrapping");
989
      }
990
    return cipherSpi.engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
991
                                  wrappedKeyType);
992
  }
993
 
994
  /**
995
   * Continue a multi-part transformation on an entire byte array,
996
   * returning the transformed bytes.
997
   *
998
   * @param input The input bytes.
999
   * @return The transformed bytes.
1000
   * @throws java.lang.IllegalStateException If this cipher was not
1001
   *         initialized for encryption or decryption.
1002
   */
1003
  public final byte[] update(byte[] input) throws IllegalStateException
1004
  {
1005
    return update(input, 0, input.length);
1006
  }
1007
 
1008
  /**
1009
   * Continue a multi-part transformation on part of a byte array,
1010
   * returning the transformed bytes.
1011
   *
1012
   * @param input       The input bytes.
1013
   * @param inputOffset The index in the input to start.
1014
   * @param inputLength The number of bytes to transform.
1015
   * @return The transformed bytes.
1016
   * @throws java.lang.IllegalStateException If this cipher was not
1017
   *         initialized for encryption or decryption.
1018
   */
1019
  public final byte[] update(byte[] input, int inputOffset, int inputLength)
1020
    throws IllegalStateException
1021
  {
1022
    if (cipherSpi == null)
1023
      {
1024
        byte[] b = new byte[inputLength];
1025
        System.arraycopy(input, inputOffset, b, 0, inputLength);
1026
        return b;
1027
      }
1028
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
1029
      {
1030
        throw new IllegalStateException(
1031
          "cipher is not for encrypting or decrypting");
1032
      }
1033
    return cipherSpi.engineUpdate(input, inputOffset, inputLength);
1034
  }
1035
 
1036
  /**
1037
   * Continue a multi-part transformation on part of a byte array,
1038
   * placing the transformed bytes into the given array.
1039
   *
1040
   * @param input       The input bytes.
1041
   * @param inputOffset The index in the input to start.
1042
   * @param inputLength The number of bytes to transform.
1043
   * @param output      The output byte array.
1044
   * @return The number of transformed bytes.
1045
   * @throws java.lang.IllegalStateException If this cipher was not
1046
   *         initialized for encryption or decryption.
1047
   * @throws javax.security.ShortBufferException If there is not enough
1048
   *         room in the output array to hold the transformed bytes.
1049
   */
1050
  public final int update(byte[] input, int inputOffset, int inputLength,
1051
                          byte[] output)
1052
    throws IllegalStateException, ShortBufferException
1053
  {
1054
    return update(input, inputOffset, inputLength, output, 0);
1055
  }
1056
 
1057
  /**
1058
   * Continue a multi-part transformation on part of a byte array,
1059
   * placing the transformed bytes into the given array.
1060
   *
1061
   * @param input        The input bytes.
1062
   * @param inputOffset  The index in the input to start.
1063
   * @param inputLength  The number of bytes to transform.
1064
   * @param output       The output byte array.
1065
   * @param outputOffset The index in the output array to start.
1066
   * @return The number of transformed bytes.
1067
   * @throws java.lang.IllegalStateException If this cipher was not
1068
   *         initialized for encryption or decryption.
1069
   * @throws javax.security.ShortBufferException If there is not enough
1070
   *         room in the output array to hold the transformed bytes.
1071
   */
1072
  public final int update(byte[] input, int inputOffset, int inputLength,
1073
                          byte[] output, int outputOffset)
1074
    throws IllegalStateException, ShortBufferException
1075
  {
1076
    if (cipherSpi == null)
1077
      {
1078
        if (inputLength > output.length - outputOffset)
1079
          {
1080
            throw new ShortBufferException();
1081
          }
1082
        System.arraycopy(input, inputOffset, output, outputOffset, inputLength);
1083
        return inputLength;
1084
      }
1085
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
1086
      {
1087
        throw new IllegalStateException(
1088
          "cipher is not for encrypting or decrypting");
1089
      }
1090
    return cipherSpi.engineUpdate(input, inputOffset, inputLength,
1091
                                  output, outputOffset);
1092
  }
1093
 
1094
  /**
1095
   * Continue a multi-part transformation on a byte buffer, storing
1096
   * the transformed bytes into another buffer.
1097
   *
1098
   * @param input  The input buffer.
1099
   * @param output The output buffer.
1100
   * @return The number of bytes stored in <i>output</i>.
1101
   * @throws IllegalArgumentException If the two buffers are the same
1102
   *  object.
1103
   * @throws IllegalStateException If this cipher was not initialized
1104
   *  for encrypting or decrypting.
1105
   * @throws ReadOnlyBufferException If the output buffer is not
1106
   *  writable.
1107
   * @throws ShortBufferException If the output buffer does not have
1108
   *  enough available space for the transformed bytes.
1109
   * @since 1.5
1110
   */
1111
  public final int update (ByteBuffer input, ByteBuffer output)
1112
    throws ReadOnlyBufferException, ShortBufferException
1113
  {
1114
    if (input == output)
1115
      throw new IllegalArgumentException
1116
        ("input and output buffers must be different");
1117
    if (state != ENCRYPT_MODE && state != DECRYPT_MODE)
1118
      throw new IllegalStateException
1119
        ("not initialized for encryption or decryption");
1120
    return cipherSpi.engineUpdate (input, output);
1121
  }
1122
 
1123
  /**
1124
   * Wrap a key.
1125
   *
1126
   * @param key The key to wrap.
1127
   * @return The wrapped key.
1128
   * @throws java.lang.IllegalStateException If this instance was not
1129
   *         initialized for key wrapping.
1130
   * @throws javax.crypto.IllegalBlockSizeException If this instance has
1131
   *         no padding and the key is not a multiple of the block size.
1132
   * @throws java.security.InvalidKeyException If this instance cannot
1133
   *         wrap this key.
1134
   */
1135
  public final byte[] wrap(Key key)
1136
    throws IllegalStateException, IllegalBlockSizeException, InvalidKeyException
1137
  {
1138
    if (cipherSpi == null)
1139
      {
1140
        return null;
1141
      }
1142
    if (state != WRAP_MODE)
1143
      {
1144
        throw new IllegalStateException("instance is not for key wrapping");
1145
      }
1146
    return cipherSpi.engineWrap(key);
1147
  }
1148
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.