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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* TripleDESKeyWrap.java -- FIXME: briefly describe file purpose
2
   Copyright (C) 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 gnu.javax.crypto.kwa;
40
 
41
import gnu.java.security.Registry;
42
import gnu.java.security.hash.Sha160;
43
import gnu.javax.crypto.assembly.Assembly;
44
import gnu.javax.crypto.assembly.Cascade;
45
import gnu.javax.crypto.assembly.Direction;
46
import gnu.javax.crypto.assembly.Stage;
47
import gnu.javax.crypto.assembly.Transformer;
48
import gnu.javax.crypto.assembly.TransformerException;
49
import gnu.javax.crypto.cipher.IBlockCipher;
50
import gnu.javax.crypto.cipher.TripleDES;
51
import gnu.javax.crypto.mode.IMode;
52
import gnu.javax.crypto.mode.ModeFactory;
53
 
54
import java.security.InvalidKeyException;
55
import java.security.SecureRandom;
56
import java.util.Arrays;
57
import java.util.HashMap;
58
import java.util.Map;
59
 
60
/**
61
 * The GNU implementation of the Triple DES Key Wrap Algorithm as described in
62
 * [1].
63
 * <p>
64
 * <b>IMPORTANT</b>: This class is NOT thread safe.
65
 * <p>
66
 * References:
67
 * <ol>
68
 * <li><a href="http://www.rfc-archive.org/getrfc.php?rfc=3217">Triple-DES and
69
 * RC2 Key Wrapping</a>.</li>
70
 * <li><a href="http://www.w3.org/TR/xmlenc-core/">XML Encryption Syntax and
71
 * Processing</a>.</li>
72
 * </ol>
73
 */
74
public class TripleDESKeyWrap
75
    extends BaseKeyWrappingAlgorithm
76
{
77
  private static final byte[] DEFAULT_IV = new byte[] {
78
     (byte) 0x4A, (byte) 0xDD, (byte) 0xA2, (byte) 0x2C,
79
     (byte) 0x79, (byte) 0xE8, (byte) 0x21, (byte) 0x05 };
80
 
81
  private Assembly asm;
82
  private HashMap asmAttributes = new HashMap();
83
  private HashMap modeAttributes = new HashMap();
84
  private Sha160 sha = new Sha160();
85
  private SecureRandom rnd;
86
 
87
  public TripleDESKeyWrap()
88
  {
89
    super(Registry.TRIPLEDES_KWA);
90
  }
91
 
92
  protected void engineInit(Map attributes) throws InvalidKeyException
93
  {
94
    rnd = (SecureRandom) attributes.get(IKeyWrappingAlgorithm.SOURCE_OF_RANDOMNESS);
95
    IMode des3CBC = ModeFactory.getInstance(Registry.CBC_MODE, new TripleDES(), 8);
96
    Stage des3CBCStage = Stage.getInstance(des3CBC, Direction.FORWARD);
97
    Cascade cascade = new Cascade();
98
    Object modeNdx = cascade.append(des3CBCStage);
99
 
100
    asmAttributes.put(modeNdx, modeAttributes);
101
 
102
    asm = new Assembly();
103
    asm.addPreTransformer(Transformer.getCascadeTransformer(cascade));
104
 
105
    modeAttributes.put(IBlockCipher.KEY_MATERIAL,
106
                       attributes.get(KEY_ENCRYPTION_KEY_MATERIAL));
107
    asmAttributes.put(Assembly.DIRECTION, Direction.FORWARD);
108
  }
109
 
110
  protected byte[] engineWrap(byte[] in, int inOffset, int length)
111
  {
112
    // The same key wrap algorithm is used for both Two-key Triple-DES and
113
    // Three-key Triple-DES keys.  When a Two-key Triple-DES key is to be
114
    // wrapped, a third DES key with the same value as the first DES key is
115
    // created.  Thus, all wrapped Triple-DES keys include three DES keys.
116
    if (length != 16 && length != 24)
117
      throw new IllegalArgumentException("Only 2- and 3-key Triple DES keys are alowed");
118
 
119
    byte[] CEK = new byte[24];
120
    if (length == 16)
121
      {
122
        System.arraycopy(in, inOffset, CEK, 0,  16);
123
        System.arraycopy(in, inOffset, CEK, 16, 8);
124
      }
125
    else
126
      System.arraycopy(in, inOffset, CEK, 0, 24);
127
 
128
    // TODO: check for the following:
129
    // However, a Two-key Triple-DES key MUST NOT be used to wrap a Three-
130
    // key Triple-DES key that is comprised of three unique DES keys.
131
 
132
    // 1. Set odd parity for each of the DES key octets comprising the
133
    //    Three-Key Triple-DES key that is to be wrapped, call the result
134
    //    CEK.
135
    TripleDES.adjustParity(CEK, 0);
136
 
137
    // 2. Compute an 8 octet key checksum value on CEK as described above in
138
    //    Section 2, call the result ICV.
139
    sha.update(CEK);
140
    byte[] hash = sha.digest();
141
    byte[] ICV = new byte[8];
142
    System.arraycopy(hash, 0, ICV, 0, 8);
143
 
144
    // 3. Let CEKICV = CEK || ICV.
145
    byte[] CEKICV = new byte[CEK.length + ICV.length];
146
    System.arraycopy(CEK, 0, CEKICV, 0,          CEK.length);
147
    System.arraycopy(ICV, 0, CEKICV, CEK.length, ICV.length);
148
 
149
    // 4. Generate 8 octets at random, call the result IV.
150
    byte[] IV = new byte[8];
151
    nextRandomBytes(IV);
152
 
153
    // 5. Encrypt CEKICV in CBC mode using the key-encryption key.  Use the
154
    //    random value generated in the previous step as the initialization
155
    //    vector (IV).  Call the ciphertext TEMP1.
156
    modeAttributes.put(IMode.IV, IV);
157
    asmAttributes.put(Assembly.DIRECTION, Direction.FORWARD);
158
    byte[] TEMP1;
159
    try
160
      {
161
        asm.init(asmAttributes);
162
        TEMP1 = asm.lastUpdate(CEKICV);
163
      }
164
    catch (TransformerException x)
165
      {
166
        throw new RuntimeException(x);
167
      }
168
 
169
    // 6. Let TEMP2 = IV || TEMP1.
170
    byte[] TEMP2 = new byte[IV.length + TEMP1.length];
171
    System.arraycopy(IV,    0, TEMP2, 0,         IV.length);
172
    System.arraycopy(TEMP1, 0, TEMP2, IV.length, TEMP1.length);
173
 
174
    // 7. Reverse the order of the octets in TEMP2.  That is, the most
175
    //    significant (first) octet is swapped with the least significant
176
    //    (last) octet, and so on.  Call the result TEMP3.
177
    byte[] TEMP3 = new byte[TEMP2.length];
178
    for (int i = 0, j = TEMP2.length - 1; i < TEMP2.length; i++, j--)
179
      TEMP3[j] = TEMP2[i];
180
 
181
    // 8. Encrypt TEMP3 in CBC mode using the key-encryption key.  Use an
182
    //    initialization vector (IV) of 0x4adda22c79e82105.  The ciphertext
183
    //    is 40 octets long.
184
    modeAttributes.put(IMode.IV, DEFAULT_IV);
185
    asmAttributes.put(Assembly.DIRECTION, Direction.FORWARD);
186
    byte[] result;
187
    try
188
      {
189
        asm.init(asmAttributes);
190
        result = asm.lastUpdate(TEMP3);
191
      }
192
    catch (TransformerException x)
193
      {
194
        throw new RuntimeException(x);
195
      }
196
    return result;
197
  }
198
 
199
  protected byte[] engineUnwrap(byte[] in, int inOffset, int length)
200
      throws KeyUnwrappingException
201
  {
202
    // 1. If the wrapped key is not 40 octets, then error.
203
    if (length != 40)
204
      throw new IllegalArgumentException("length MUST be 40");
205
 
206
    // 2. Decrypt the wrapped key in CBC mode using the key-encryption key.
207
    //    Use an initialization vector (IV) of 0x4adda22c79e82105.  Call the
208
    //    output TEMP3.
209
    modeAttributes.put(IMode.IV, DEFAULT_IV);
210
    asmAttributes.put(Assembly.DIRECTION, Direction.REVERSED);
211
    byte[] TEMP3;
212
    try
213
      {
214
        asm.init(asmAttributes);
215
        TEMP3 = asm.lastUpdate(in, inOffset, 40);
216
      }
217
    catch (TransformerException x)
218
      {
219
        throw new RuntimeException(x);
220
      }
221
 
222
    // 3. Reverse the order of the octets in TEMP3.  That is, the most
223
    //    significant (first) octet is swapped with the least significant
224
    //    (last) octet, and so on.  Call the result TEMP2.
225
    byte[] TEMP2 = new byte[40];
226
    for (int i = 0, j = 40 - 1; i < 40; i++, j--)
227
      TEMP2[j] = TEMP3[i];
228
 
229
    // 4. Decompose TEMP2 into IV and TEMP1.  IV is the most significant
230
    //    (first) 8 octets, and TEMP1 is the least significant (last) 32
231
    //    octets.
232
    byte[] IV = new byte[8];
233
    byte[] TEMP1 = new byte[32];
234
    System.arraycopy(TEMP2, 0, IV,    0, 8);
235
    System.arraycopy(TEMP2, 8, TEMP1, 0, 32);
236
 
237
    // 5. Decrypt TEMP1 in CBC mode using the key-encryption key.  Use the
238
    //    IV value from the previous step as the initialization vector.
239
    //    Call the ciphertext CEKICV.
240
    modeAttributes.put(IMode.IV, IV);
241
    asmAttributes.put(Assembly.DIRECTION, Direction.REVERSED);
242
    byte[] CEKICV;
243
    try
244
      {
245
        asm.init(asmAttributes);
246
        CEKICV = asm.lastUpdate(TEMP1, 0, 32);
247
      }
248
    catch (TransformerException x)
249
      {
250
        throw new RuntimeException(x);
251
      }
252
 
253
    // 6. Decompose CEKICV into CEK and ICV.  CEK is the most significant
254
    //    (first) 24 octets, and ICV is the least significant (last) 8
255
    //    octets.
256
    byte[] CEK = new byte[24];
257
    byte[] ICV = new byte[8];
258
    System.arraycopy(CEKICV, 0,  CEK, 0, 24);
259
    System.arraycopy(CEKICV, 24, ICV, 0, 8);
260
 
261
    // 7. Compute an 8 octet key checksum value on CEK as described above in
262
    //    Section 2.  If the computed key checksum value does not match the
263
    //    decrypted key checksum value, ICV, then error.
264
    sha.update(CEK);
265
    byte[] hash = sha.digest();
266
    byte[] computedICV = new byte[8];
267
    System.arraycopy(hash, 0, computedICV, 0, 8);
268
    if (! Arrays.equals(ICV, computedICV))
269
      throw new KeyUnwrappingException("ICV and computed ICV MUST match");
270
 
271
    // 8. Check for odd parity each of the DES key octets comprising CEK.
272
    //    If parity is incorrect, then error.
273
    if (! TripleDES.isParityAdjusted(CEK, 0))
274
      throw new KeyUnwrappingException("Triple-DES key parity MUST be adjusted");
275
 
276
    // 9. Use CEK as a Triple-DES key.
277
    return CEK;
278
  }
279
 
280
  /**
281
   * Fills the designated byte array with random data.
282
   *
283
   * @param buffer the byte array to fill with random data.
284
   */
285
  private void nextRandomBytes(byte[] buffer)
286
  {
287
    if (rnd != null)
288
      rnd.nextBytes(buffer);
289
    else
290
      getDefaultPRNG().nextBytes(buffer);
291
  }
292
}

powered by: WebSVN 2.1.0

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