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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [crypto/] [jce/] [cipher/] [CipherAdapter.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* CipherAdapter.java --
2
   Copyright (C) 2002, 2003, 2006  Free Software Foundation, Inc.
3
 
4
This file is a 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 of the License, or (at
9
your option) 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; if not, write to the Free Software
18
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19
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 gnu.javax.crypto.jce.cipher;
40
 
41
import gnu.java.security.Registry;
42
import gnu.javax.crypto.cipher.CipherFactory;
43
import gnu.javax.crypto.cipher.IBlockCipher;
44
import gnu.javax.crypto.jce.spec.BlockCipherParameterSpec;
45
import gnu.javax.crypto.mode.IMode;
46
import gnu.javax.crypto.mode.ModeFactory;
47
import gnu.javax.crypto.pad.IPad;
48
import gnu.javax.crypto.pad.PadFactory;
49
import gnu.javax.crypto.pad.WrongPaddingException;
50
 
51
import java.security.AlgorithmParameters;
52
import java.security.InvalidAlgorithmParameterException;
53
import java.security.InvalidKeyException;
54
import java.security.Key;
55
import java.security.NoSuchAlgorithmException;
56
import java.security.SecureRandom;
57
import java.security.spec.AlgorithmParameterSpec;
58
import java.security.spec.InvalidParameterSpecException;
59
import java.util.HashMap;
60
import java.util.Iterator;
61
import java.util.Map;
62
 
63
import javax.crypto.BadPaddingException;
64
import javax.crypto.Cipher;
65
import javax.crypto.CipherSpi;
66
import javax.crypto.IllegalBlockSizeException;
67
import javax.crypto.NoSuchPaddingException;
68
import javax.crypto.ShortBufferException;
69
import javax.crypto.spec.IvParameterSpec;
70
 
71
/**
72
 * The implementation of a generic {@link Cipher} <i>Adapter</i> class to wrap
73
 * GNU cipher instances.
74
 * <p>
75
 * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for
76
 * the {@link Cipher} class, which provides the functionality of symmetric-key
77
 * block ciphers, such as the AES.
78
 * <p>
79
 * This base class defines all of the abstract methods in {@link CipherSpi},
80
 * but does not define the (non-abstract) key wrapping functions that extended
81
 * the base cipher SPI, and these methods thus immediately throw an
82
 * {@link UnsupportedOperationException}. If a cipher implementation provides
83
 * this functionality, or if it in fact accepts parameters other than the key
84
 * and the initialization vector, the subclass should override those methods.
85
 * Otherwise a subclass need only call the {@link #CipherAdapter(String)}
86
 * constructor with the name of the cipher.
87
 */
88
class CipherAdapter
89
    extends CipherSpi
90
{
91
  /** Our cipher instance. */
92
  protected IBlockCipher cipher;
93
  /** Our mode instance. */
94
  protected IMode mode;
95
  /** Our padding instance. */
96
  protected IPad pad;
97
  /** The current key size. */
98
  protected int keyLen;
99
  /** Our attributes map. */
100
  protected Map attributes;
101
  /** An incomplete block. */
102
  protected byte[] partBlock;
103
  /** The number of bytes in {@link #partBlock}. */
104
  protected int partLen;
105
  /** The length of blocks we are processing. */
106
  protected int blockLen;
107
 
108
  /**
109
   * Protected constructor to be called by subclasses. The cipher name argument
110
   * should be the appropriate one listed in {@link Registry}. The basic cipher
111
   * instance is created, along with an instance of the
112
   * {@link gnu.javax.crypto.mode.ECB} mode and no padding.
113
   *
114
   * @param cipherName The cipher to instantiate.
115
   * @param blockLen The block length to use.
116
   */
117
  protected CipherAdapter(String cipherName, int blockLen)
118
  {
119
    cipher = CipherFactory.getInstance(cipherName);
120
    attributes = new HashMap();
121
    this.blockLen = blockLen;
122
    mode = ModeFactory.getInstance("ECB", cipher, blockLen);
123
    attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, Integer.valueOf(blockLen));
124
  }
125
 
126
  /**
127
   * Creates a new cipher adapter with the default block size.
128
   *
129
   * @param cipherName The cipher to instantiate.
130
   */
131
  protected CipherAdapter(String cipherName)
132
  {
133
    cipher = CipherFactory.getInstance(cipherName);
134
    blockLen = cipher.defaultBlockSize();
135
    attributes = new HashMap();
136
    mode = ModeFactory.getInstance("ECB", cipher, blockLen);
137
    attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, Integer.valueOf(blockLen));
138
  }
139
 
140
  protected void engineSetMode(String modeName) throws NoSuchAlgorithmException
141
  {
142
    if (modeName.length() >= 3
143
        && modeName.substring(0, 3).equalsIgnoreCase("CFB"))
144
      {
145
        if (modeName.length() > 3)
146
          {
147
            try
148
              {
149
                int bs = Integer.parseInt(modeName.substring(3));
150
                attributes.put(IMode.MODE_BLOCK_SIZE, Integer.valueOf(bs / 8));
151
              }
152
            catch (NumberFormatException nfe)
153
              {
154
                throw new NoSuchAlgorithmException(modeName);
155
              }
156
            modeName = "CFB";
157
          }
158
      }
159
    else
160
      attributes.remove(IMode.MODE_BLOCK_SIZE);
161
    mode = ModeFactory.getInstance(modeName, cipher, blockLen);
162
    if (mode == null)
163
      throw new NoSuchAlgorithmException(modeName);
164
  }
165
 
166
  protected void engineSetPadding(String padName) throws NoSuchPaddingException
167
  {
168
    if (padName.equalsIgnoreCase("NoPadding"))
169
      {
170
        pad = null;
171
        return;
172
      }
173
    pad = PadFactory.getInstance(padName);
174
    if (pad == null)
175
      throw new NoSuchPaddingException(padName);
176
  }
177
 
178
  protected int engineGetBlockSize()
179
  {
180
    if (cipher != null)
181
      return blockLen;
182
    return 0;
183
  }
184
 
185
  protected int engineGetOutputSize(int inputLen)
186
  {
187
    final int blockSize = mode.currentBlockSize();
188
    return ((inputLen + partLen) / blockSize) * blockSize;
189
  }
190
 
191
  protected byte[] engineGetIV()
192
  {
193
    byte[] iv = (byte[]) attributes.get(IMode.IV);
194
    if (iv == null)
195
      return null;
196
    return (byte[]) iv.clone();
197
  }
198
 
199
  protected AlgorithmParameters engineGetParameters()
200
  {
201
    byte[] iv = (byte[]) attributes.get(IMode.IV);
202
    int cipherBlockSize = cipher.currentBlockSize();
203
    BlockCipherParameterSpec spec = new BlockCipherParameterSpec(iv,
204
                                                                 cipherBlockSize,
205
                                                                 keyLen);
206
    AlgorithmParameters params;
207
    try
208
      {
209
        params = AlgorithmParameters.getInstance("BlockCipherParameters");
210
        params.init(spec);
211
      }
212
    catch (NoSuchAlgorithmException nsae)
213
      {
214
        return null;
215
      }
216
    catch (InvalidParameterSpecException ipse)
217
      {
218
        return null;
219
      }
220
    return params;
221
  }
222
 
223
  protected void engineInit(int opmode, Key key, SecureRandom random)
224
      throws InvalidKeyException
225
  {
226
    try
227
      {
228
        engineInit(opmode, key, (AlgorithmParameterSpec) null, random);
229
      }
230
    catch (InvalidAlgorithmParameterException e)
231
      {
232
        throw new InvalidKeyException(e.getMessage(), e);
233
      }
234
  }
235
 
236
  /**
237
   * Executes initialization logic after all parameters have been handled by the
238
   * engineInit()s.
239
   *
240
   * @param opmode the desired mode of operation for this instance.
241
   * @param key the key material to use for initialization.
242
   * @param random a source of randmoness to use if/when needed.
243
   * @throws InvalidKeyException if <code>key</code> is invalid or the cipher
244
   *           needs extra parameters which can not be derived from
245
   *           <code>key</code>; e.g. an IV.
246
   */
247
  private void engineInitHandler(int opmode, Key key, SecureRandom random)
248
      throws InvalidKeyException
249
  {
250
    switch (opmode)
251
      {
252
      case Cipher.ENCRYPT_MODE:
253
        attributes.put(IMode.STATE, Integer.valueOf(IMode.ENCRYPTION));
254
        break;
255
      case Cipher.DECRYPT_MODE:
256
        attributes.put(IMode.STATE, Integer.valueOf(IMode.DECRYPTION));
257
        break;
258
      }
259
    if (! key.getFormat().equalsIgnoreCase("RAW"))
260
      throw new InvalidKeyException("bad key format " + key.getFormat());
261
    byte[] kb = key.getEncoded();
262
    int kbLength = kb.length;
263
    if (keyLen == 0)
264
      {
265
        // no key-size given; instead key-material is provided in kb --which
266
        // can be more than what we need.  if we don't cull this down to what
267
        // the cipher likes/wants we may get an InvalidKeyException.
268
        //
269
        // try to find the largest key-size value that is less than or equal
270
        // to kbLength
271
        for (Iterator it = cipher.keySizes(); it.hasNext();)
272
          {
273
            int aKeySize = ((Integer) it.next()).intValue();
274
            if (aKeySize == kbLength)
275
              {
276
                keyLen = aKeySize;
277
                break;
278
              }
279
            else if (aKeySize < kbLength)
280
              keyLen = aKeySize;
281
            else // all remaining key-sizes are longer than kb.length
282
              break;
283
          }
284
      }
285
    if (keyLen == 0)
286
      {
287
        // we were unable to find a key-size, among those advertised by the
288
        // cipher, that is less than or equal to the length of the kb array.
289
        // set keyLen to kbLength.  either the cipher implementation will throw
290
        // an InvalidKeyException, or it is implemented in a way which can deal
291
        // with an unsupported key-size.
292
        keyLen = kbLength;
293
      }
294
    if (keyLen < kbLength)
295
      {
296
        byte[] kbb = kb;
297
        kb = new byte[keyLen];
298
        System.arraycopy(kbb, 0, kb, 0, keyLen);
299
      }
300
    attributes.put(IBlockCipher.KEY_MATERIAL, kb);
301
    reset();
302
  }
303
 
304
  protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
305
                            SecureRandom random) throws InvalidKeyException,
306
      InvalidAlgorithmParameterException
307
  {
308
    if (params == null)
309
      {
310
        // All cipher modes require parameters (like an IV) except ECB. When
311
        // these cant be derived from the given key then it must be generated
312
        // randomly if in ENCRYPT or WRAP mode. Parameters that have defaults
313
        // for our cipher must be set to these defaults.
314
        if (! mode.name().toLowerCase().startsWith(Registry.ECB_MODE + "("))
315
          {
316
            switch (opmode)
317
              {
318
              case Cipher.ENCRYPT_MODE:
319
              case Cipher.WRAP_MODE:
320
                byte[] iv = new byte[blockLen];
321
                random.nextBytes(iv);
322
                attributes.put(IMode.IV, iv);
323
                break;
324
              default:
325
                throw new InvalidAlgorithmParameterException(
326
                    "Required algorithm parameters are missing for mode: "
327
                    + mode.name());
328
              }
329
          }
330
        // Add default for block length etc.
331
        blockLen = cipher.defaultBlockSize();
332
        attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE,
333
                       Integer.valueOf(blockLen));
334
        keyLen = 0;
335
      }
336
    else if (params instanceof BlockCipherParameterSpec)
337
      {
338
        BlockCipherParameterSpec bcps = (BlockCipherParameterSpec) params;
339
        blockLen = bcps.getBlockSize();
340
        attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, Integer.valueOf(blockLen));
341
        attributes.put(IMode.IV, bcps.getIV());
342
        keyLen = bcps.getKeySize();
343
      }
344
    else if (params instanceof IvParameterSpec)
345
      {
346
        // The size of the IV must match the block size
347
        if (((IvParameterSpec) params).getIV().length != cipher.defaultBlockSize())
348
          {
349
            throw new InvalidAlgorithmParameterException();
350
          }
351
 
352
        attributes.put(IMode.IV, ((IvParameterSpec) params).getIV());
353
        blockLen = cipher.defaultBlockSize();
354
        attributes.put(IBlockCipher.CIPHER_BLOCK_SIZE, Integer.valueOf(blockLen));
355
        keyLen = 0;
356
      }
357
    engineInitHandler(opmode, key, random);
358
  }
359
 
360
  protected void engineInit(int opmode, Key key, AlgorithmParameters params,
361
                            SecureRandom random) throws InvalidKeyException,
362
      InvalidAlgorithmParameterException
363
  {
364
    AlgorithmParameterSpec spec = null;
365
    try
366
      {
367
        if (params != null)
368
          spec = params.getParameterSpec(BlockCipherParameterSpec.class);
369
      }
370
    catch (InvalidParameterSpecException ignored)
371
      {
372
      }
373
    engineInit(opmode, key, spec, random);
374
  }
375
 
376
  protected byte[] engineUpdate(byte[] input, int inOff, int inLen)
377
  {
378
    if (inLen == 0) // nothing to process
379
      return new byte[0];
380
    final int blockSize = mode.currentBlockSize();
381
    int blockCount = (partLen + inLen) / blockSize;
382
 
383
    // always keep data for unpadding in padded decryption mode;
384
    // might even be a complete block
385
    if (pad != null
386
        && ((Integer) attributes.get(IMode.STATE)).intValue() == IMode.DECRYPTION
387
        && (partLen + inLen) % blockSize == 0)
388
      blockCount--;
389
 
390
    final byte[] out = new byte[blockCount * blockSize];
391
    try
392
      {
393
        engineUpdate(input, inOff, inLen, out, 0);
394
      }
395
    catch (ShortBufferException x) // should not happen
396
      {
397
        x.printStackTrace(System.err);
398
      }
399
    return out;
400
  }
401
 
402
  protected int engineUpdate(byte[] in, int inOff, int inLen, byte[] out,
403
                             int outOff) throws ShortBufferException
404
  {
405
    if (inLen == 0) // nothing to process
406
      return 0;
407
    final int blockSize = mode.currentBlockSize();
408
    int blockCount = (partLen + inLen) / blockSize;
409
 
410
    // always keep data for unpadding in padded decryption mode;
411
    // might even be a complete block
412
    if (pad != null
413
        && ((Integer) attributes.get(IMode.STATE)).intValue() == IMode.DECRYPTION
414
        && (partLen + inLen) % blockSize == 0)
415
      blockCount--;
416
 
417
    final int result = blockCount * blockSize;
418
    if (result > out.length - outOff)
419
      throw new ShortBufferException();
420
    if (blockCount == 0) // not enough bytes for even 1 block
421
      {
422
        System.arraycopy(in, inOff, partBlock, partLen, inLen);
423
        partLen += inLen;
424
        return 0;
425
      }
426
    final byte[] buf;
427
    // we have enough bytes for at least 1 block
428
    if (partLen == 0) // if no cached bytes use input
429
      buf = in;
430
    else // prefix input with cached bytes
431
      {
432
        buf = new byte[partLen + inLen];
433
        System.arraycopy(partBlock, 0, buf, 0, partLen);
434
        if (in != null && inLen > 0)
435
          System.arraycopy(in, inOff, buf, partLen, inLen);
436
        inOff = 0;
437
      }
438
    for (int i = 0; i < blockCount; i++) // update blockCount * blockSize
439
      {
440
        mode.update(buf, inOff, out, outOff);
441
        inOff += blockSize;
442
        outOff += blockSize;
443
      }
444
    partLen += inLen - result;
445
    if (partLen > 0) // cache remaining bytes from buf
446
      System.arraycopy(buf, inOff, partBlock, 0, partLen);
447
    return result;
448
  }
449
 
450
  protected byte[] engineDoFinal(byte[] input, int off, int len)
451
      throws IllegalBlockSizeException, BadPaddingException
452
  {
453
    final byte[] result;
454
    final byte[] buf = engineUpdate(input, off, len);
455
    if (pad != null)
456
      {
457
        switch (((Integer) attributes.get(IMode.STATE)).intValue())
458
          {
459
          case IMode.ENCRYPTION:
460
            byte[] padding = pad.pad(partBlock, 0, partLen);
461
            byte[] buf2 = engineUpdate(padding, 0, padding.length);
462
            result = new byte[buf.length + buf2.length];
463
            System.arraycopy(buf, 0, result, 0, buf.length);
464
            System.arraycopy(buf2, 0, result, buf.length, buf2.length);
465
            break;
466
          case IMode.DECRYPTION:
467
            int padLen;
468
            byte[] buf3 = new byte[buf.length + partLen];
469
            try
470
              {
471
                if (partLen != mode.currentBlockSize())
472
                  throw new WrongPaddingException();
473
                System.arraycopy(buf, 0, buf3, 0, buf.length);
474
                mode.update(partBlock, 0, buf3, buf.length);
475
                padLen = pad.unpad(buf3, 0, buf3.length);
476
              }
477
            catch (WrongPaddingException wpe)
478
              {
479
                throw new BadPaddingException(wpe.getMessage());
480
              }
481
            result = new byte[buf3.length - padLen];
482
            System.arraycopy(buf3, 0, result, 0, result.length);
483
            break;
484
          default:
485
            throw new IllegalStateException();
486
          }
487
      }
488
    else
489
      {
490
        if (partLen > 0)
491
          throw new IllegalBlockSizeException(partLen + " trailing bytes");
492
        result = buf;
493
      }
494
 
495
    try
496
      {
497
        reset();
498
      }
499
    catch (InvalidKeyException ike)
500
      {
501
        // Should not happen; if we initialized it with the current
502
        // parameters before, we should be able to do it again.
503
        throw new Error(ike);
504
      }
505
    return result;
506
  }
507
 
508
  protected int engineDoFinal(byte[] in, int inOff, int inLen, byte[] out,
509
                              int outOff) throws BadPaddingException,
510
      IllegalBlockSizeException, ShortBufferException
511
  {
512
    byte[] buf = engineDoFinal(in, inOff, inLen);
513
    if (out.length + outOff < buf.length)
514
      throw new ShortBufferException();
515
    System.arraycopy(buf, 0, out, outOff, buf.length);
516
    return buf.length;
517
  }
518
 
519
  private void reset() throws InvalidKeyException
520
  {
521
    mode.reset();
522
    mode.init(attributes);
523
    if (pad != null)
524
      {
525
        pad.reset();
526
        pad.init(blockLen);
527
      }
528
    partBlock = new byte[blockLen];
529
    partLen = 0;
530
  }
531
}

powered by: WebSVN 2.1.0

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