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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* Cascade.java --
2
   Copyright (C) 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.assembly;
40
 
41
import java.math.BigInteger;
42
import java.security.InvalidKeyException;
43
import java.util.Collections;
44
import java.util.HashMap;
45
import java.util.HashSet;
46
import java.util.Iterator;
47
import java.util.LinkedList;
48
import java.util.Map;
49
import java.util.Set;
50
 
51
/**
52
 * A <i>Cascade</i> Cipher is the concatenation of two or more block ciphers
53
 * each with independent keys. Plaintext is input to the first stage; the output
54
 * of stage <code>i</code> is input to stage <code>i + 1</code>; and the
55
 * output of the last stage is the <i>Cascade</i>'s ciphertext output.
56
 * <p>
57
 * In the simplest case, all stages in a <code>Cascade</code> have <i>k</i>-bit
58
 * keys, and the stage inputs and outputs are all n-bit quantities. The stage
59
 * ciphers may differ (general cascade of ciphers), or all be identical (cascade
60
 * of identical ciphers).
61
 * <p>
62
 * The term "block ciphers" used above refers to implementations of
63
 * {@link gnu.javax.crypto.mode.IMode}, including the
64
 * {@link gnu.javax.crypto.mode.ECB} mode which basically exposes a
65
 * symmetric-key block cipher algorithm as a <i>Mode</i> of Operations.
66
 * <p>
67
 * References:
68
 * <ol>
69
 * <li><a href="http://www.cacr.math.uwaterloo.ca/hac">[HAC]</a>: Handbook of
70
 * Applied Cryptography.<br>
71
 * CRC Press, Inc. ISBN 0-8493-8523-7, 1997<br>
72
 * Menezes, A., van Oorschot, P. and S. Vanstone.</li>
73
 * </ol>
74
 */
75
public class Cascade
76
{
77
  public static final String DIRECTION = "gnu.crypto.assembly.cascade.direction";
78
 
79
  /** The map of Stages chained in this cascade. */
80
  protected HashMap stages;
81
 
82
  /** The ordered list of Stage UIDs to their attribute maps. */
83
  protected LinkedList stageKeys;
84
 
85
  /** The current operational direction of this instance. */
86
  protected Direction wired;
87
 
88
  /** The curently set block-size for this instance. */
89
  protected int blockSize;
90
 
91
  public Cascade()
92
  {
93
    super();
94
 
95
    stages = new HashMap(3);
96
    stageKeys = new LinkedList();
97
    wired = null;
98
    blockSize = 0;
99
  }
100
 
101
  /**
102
   * Returns the Least Common Multiple of two integers.
103
   *
104
   * @param a the first integer.
105
   * @param b the second integer.
106
   * @return the LCM of <code>abs(a)</code> and <code>abs(b)</code>.
107
   */
108
  private static final int lcm(int a, int b)
109
  {
110
    BigInteger A = BigInteger.valueOf(a * 1L);
111
    BigInteger B = BigInteger.valueOf(b * 1L);
112
    return A.multiply(B).divide(A.gcd(B)).abs().intValue();
113
  }
114
 
115
  /**
116
   * Adds to the end of the current chain, a designated {@link Stage}.
117
   *
118
   * @param stage the {@link Stage} to append to the chain.
119
   * @return a unique identifier for this stage, within this cascade.
120
   * @throws IllegalStateException if the instance is already initialised.
121
   * @throws IllegalArgumentException if the designated stage is already in the
122
   *           chain, or it has incompatible characteristics with the current
123
   *           elements already in the chain.
124
   */
125
  public Object append(Stage stage) throws IllegalArgumentException
126
  {
127
    return insert(size(), stage);
128
  }
129
 
130
  /**
131
   * Adds to the begining of the current chain, a designated {@link Stage}.
132
   *
133
   * @param stage the {@link Stage} to prepend to the chain.
134
   * @return a unique identifier for this stage, within this cascade.
135
   * @throws IllegalStateException if the instance is already initialised.
136
   * @throws IllegalArgumentException if the designated stage is already in the
137
   *           chain, or it has incompatible characteristics with the current
138
   *           elements already in the chain.
139
   */
140
  public Object prepend(Stage stage) throws IllegalArgumentException
141
  {
142
    return insert(0, stage);
143
  }
144
 
145
  /**
146
   * Inserts a {@link Stage} into the current chain, at the specified index
147
   * (zero-based) position.
148
   *
149
   * @param stage the {@link Stage} to insert into the chain.
150
   * @return a unique identifier for this stage, within this cascade.
151
   * @throws IllegalArgumentException if the designated stage is already in the
152
   *           chain, or it has incompatible characteristics with the current
153
   *           elements already in the chain.
154
   * @throws IllegalStateException if the instance is already initialised.
155
   * @throws IndexOutOfBoundsException if <code>index</code> is less than
156
   *           <code>0</code> or greater than the current size of this
157
   *           cascade.
158
   */
159
  public Object insert(int index, Stage stage) throws IllegalArgumentException,
160
      IndexOutOfBoundsException
161
  {
162
    if (stages.containsValue(stage))
163
      throw new IllegalArgumentException();
164
    if (wired != null || stage == null)
165
      throw new IllegalStateException();
166
    if (index < 0 || index > size())
167
      throw new IndexOutOfBoundsException();
168
    // check that there is a non-empty set of common block-sizes
169
    Set set = stage.blockSizes();
170
    if (stages.isEmpty())
171
      {
172
        if (set.isEmpty())
173
          throw new IllegalArgumentException("1st stage with no block sizes");
174
      }
175
    else
176
      {
177
        Set common = this.blockSizes();
178
        common.retainAll(set);
179
        if (common.isEmpty())
180
          throw new IllegalArgumentException("no common block sizes found");
181
      }
182
    Object result = new Object();
183
    stageKeys.add(index, result);
184
    stages.put(result, stage);
185
    return result;
186
  }
187
 
188
  /**
189
   * Returns the current number of stages in this chain.
190
   *
191
   * @return the current count of stages in this chain.
192
   */
193
  public int size()
194
  {
195
    return stages.size();
196
  }
197
 
198
  /**
199
   * Returns an {@link Iterator} over the stages contained in this instance.
200
   * Each element of this iterator is a concrete implementation of a {@link
201
   * Stage}.
202
   *
203
   * @return an {@link Iterator} over the stages contained in this instance.
204
   *         Each element of the returned iterator is a concrete instance of a
205
   *         {@link Stage}.
206
   */
207
  public Iterator stages()
208
  {
209
    LinkedList result = new LinkedList();
210
    for (Iterator it = stageKeys.listIterator(); it.hasNext();)
211
      result.addLast(stages.get(it.next()));
212
    return result.listIterator();
213
  }
214
 
215
  /**
216
   * Returns the {@link Set} of supported block sizes for this
217
   * <code>Cascade</code> that are common to all of its chained stages. Each
218
   * element in the returned {@link Set} is an instance of {@link Integer}.
219
   *
220
   * @return a {@link Set} of supported block sizes common to all the stages of
221
   *         the chain.
222
   */
223
  public Set blockSizes()
224
  {
225
    HashSet result = null;
226
    for (Iterator it = stages.values().iterator(); it.hasNext();)
227
      {
228
        Stage aStage = (Stage) it.next();
229
        if (result == null) // first time
230
          result = new HashSet(aStage.blockSizes());
231
        else
232
          result.retainAll(aStage.blockSizes());
233
      }
234
    return result == null ? Collections.EMPTY_SET : result;
235
  }
236
 
237
  /**
238
   * Initialises the chain for operation with specific characteristics.
239
   *
240
   * @param attributes a set of name-value pairs that describes the desired
241
   *          future behaviour of this instance.
242
   * @throws IllegalStateException if the chain, or any of its stages, is
243
   *           already initialised.
244
   * @throws InvalidKeyException if the intialisation data provided with the
245
   *           stage is incorrect or causes an invalid key to be generated.
246
   * @see Direction#FORWARD
247
   * @see Direction#REVERSED
248
   */
249
  public void init(Map attributes) throws InvalidKeyException
250
  {
251
    if (wired != null)
252
      throw new IllegalStateException();
253
    Direction flow = (Direction) attributes.get(DIRECTION);
254
    if (flow == null)
255
      flow = Direction.FORWARD;
256
    int optimalSize = 0;
257
    for (Iterator it = stageKeys.listIterator(); it.hasNext();)
258
      {
259
        Object id = it.next();
260
        Map attr = (Map) attributes.get(id);
261
        attr.put(Stage.DIRECTION, flow);
262
        Stage stage = (Stage) stages.get(id);
263
        stage.init(attr);
264
        optimalSize = optimalSize == 0 ? stage.currentBlockSize()
265
                                       : lcm(optimalSize,
266
                                             stage.currentBlockSize());
267
      }
268
    if (flow == Direction.REVERSED) // reverse order
269
      Collections.reverse(stageKeys);
270
    wired = flow;
271
    blockSize = optimalSize;
272
  }
273
 
274
  /**
275
   * Returns the currently set block size for the chain.
276
   *
277
   * @return the current block size for the chain.
278
   * @throws IllegalStateException if the instance is not initialised.
279
   */
280
  public int currentBlockSize()
281
  {
282
    if (wired == null)
283
      throw new IllegalStateException();
284
    return blockSize;
285
  }
286
 
287
  /**
288
   * Resets the chain for re-initialisation and use with other characteristics.
289
   * This method always succeeds.
290
   */
291
  public void reset()
292
  {
293
    for (Iterator it = stageKeys.listIterator(); it.hasNext();)
294
      ((Stage) stages.get(it.next())).reset();
295
    if (wired == Direction.REVERSED) // reverse it back
296
      Collections.reverse(stageKeys);
297
    wired = null;
298
    blockSize = 0;
299
  }
300
 
301
  /**
302
   * Processes exactly one block of <i>plaintext</i> (if initialised in the
303
   * {@link Direction#FORWARD} state) or <i>ciphertext</i> (if initialised in
304
   * the {@link Direction#REVERSED} state).
305
   *
306
   * @param in the plaintext.
307
   * @param inOffset index of <code>in</code> from which to start considering
308
   *          data.
309
   * @param out the ciphertext.
310
   * @param outOffset index of <code>out</code> from which to store result.
311
   * @throws IllegalStateException if the instance is not initialised.
312
   */
313
  public void update(byte[] in, int inOffset, byte[] out, int outOffset)
314
  {
315
    if (wired == null)
316
      throw new IllegalStateException();
317
    int stageBlockSize, j, i = stages.size();
318
    for (Iterator it = stageKeys.listIterator(); it.hasNext();)
319
      {
320
        Stage stage = (Stage) stages.get(it.next());
321
        stageBlockSize = stage.currentBlockSize();
322
        for (j = 0; j < blockSize; j += stageBlockSize)
323
          stage.update(in, inOffset + j, out, outOffset + j);
324
        i--;
325
        if (i > 0)
326
          System.arraycopy(out, outOffset, in, inOffset, blockSize);
327
      }
328
  }
329
 
330
  /**
331
   * Conducts a simple <i>correctness</i> test that consists of basic symmetric
332
   * encryption / decryption test(s) for all supported block and key sizes of
333
   * underlying block cipher(s) wrapped by Mode leafs. The test also includes
334
   * one (1) variable key Known Answer Test (KAT) for each block cipher.
335
   *
336
   * @return <code>true</code> if the implementation passes simple
337
   *         <i>correctness</i> tests. Returns <code>false</code> otherwise.
338
   */
339
  public boolean selfTest()
340
  {
341
    for (Iterator it = stageKeys.listIterator(); it.hasNext();)
342
      {
343
        if (! ((Stage) stages.get(it.next())).selfTest())
344
          return false;
345
      }
346
    return true;
347
  }
348
}

powered by: WebSVN 2.1.0

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