Skip to content

Commit 136badb

Browse files
author
Valerie Peng
committed
8248268: Support KWP in addition to KW
Reviewed-by: xuelei
1 parent 3482cb8 commit 136badb

File tree

18 files changed

+2223
-675
lines changed

18 files changed

+2223
-675
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package com.sun.crypto.provider;
27+
28+
import java.util.Arrays;
29+
import java.security.*;
30+
import java.security.spec.*;
31+
import javax.crypto.*;
32+
import javax.crypto.spec.*;
33+
import static com.sun.crypto.provider.KWUtil.*;
34+
35+
/**
36+
* This class implement the AES KeyWrap mode of operation as defined in
37+
* <a href=https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf>
38+
* "Recommendation for Block Cipher Modes of Operation: Methods for Key Wrapping"</a>
39+
* and represents AES cipher in KW mode.
40+
*/
41+
class AESKeyWrap extends FeedbackCipher {
42+
43+
// default integrity check value (icv) if iv is not supplied
44+
private static final byte[] ICV1 = { // SEMI_BLKSIZE long
45+
(byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6,
46+
(byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6
47+
};
48+
49+
AESKeyWrap() {
50+
super(new AESCrypt());
51+
}
52+
53+
/**
54+
* Gets the name of this feedback mode.
55+
*
56+
* @return the string <code>KW</code>
57+
*/
58+
@Override
59+
String getFeedback() {
60+
return "KW";
61+
}
62+
63+
/**
64+
* Save the current content of this cipher.
65+
*/
66+
@Override
67+
void save() {
68+
throw new UnsupportedOperationException("save not supported");
69+
};
70+
71+
/**
72+
* Restores the content of this cipher to the previous saved one.
73+
*/
74+
@Override
75+
void restore() {
76+
throw new UnsupportedOperationException("restore not supported");
77+
};
78+
79+
/**
80+
* Initializes the cipher in the specified mode with the given key
81+
* and iv.
82+
*
83+
* @param decrypting flag indicating encryption or decryption
84+
* @param algorithm the algorithm name
85+
* @param key the key
86+
* @param iv the iv
87+
*
88+
* @exception InvalidKeyException if the given key is inappropriate for
89+
* initializing this cipher
90+
* @exception InvalidAlgorithmParameterException if the given iv is
91+
* non-null and not the right length
92+
*/
93+
@Override
94+
void init(boolean decrypting, String algorithm, byte[] key, byte[] iv)
95+
throws InvalidKeyException, InvalidAlgorithmParameterException {
96+
if (key == null) {
97+
throw new InvalidKeyException("Invalid null key");
98+
}
99+
if (iv != null && iv.length != SEMI_BLKSIZE) {
100+
throw new InvalidAlgorithmParameterException("Invalid IV");
101+
}
102+
embeddedCipher.init(decrypting, algorithm, key);
103+
// iv is retrieved from IvParameterSpec.getIV() which is already cloned
104+
this.iv = (iv == null? ICV1 : iv);
105+
}
106+
107+
/**
108+
* Resets the iv to its original value.
109+
* This is used when doFinal is called in the Cipher class, so that the
110+
* cipher can be reused (with its original iv).
111+
*/
112+
@Override
113+
void reset() {
114+
throw new UnsupportedOperationException("reset not supported");
115+
};
116+
117+
118+
// no support for multi-part encryption
119+
@Override
120+
int encrypt(byte[] pt, int ptOfs, int ptLen, byte[] ct, int ctOfs) {
121+
throw new UnsupportedOperationException("multi-part not supported");
122+
};
123+
124+
// no support for multi-part decryption
125+
@Override
126+
int decrypt(byte[] ct, int ctOfs, int ctLen, byte[] pt, int ptOfs) {
127+
throw new UnsupportedOperationException("multi-part not supported");
128+
};
129+
130+
/**
131+
* Performs single-part encryption operation.
132+
*
133+
* <p>The input <code>pt</code>, starting at <code>0</code>
134+
* and ending at <code>ptLen-1</code>, is encrypted.
135+
* The result is stored in place into <code>pt</code>, starting at
136+
* <code>0</code>.
137+
*
138+
* <p>The subclass that implements Cipher should ensure that
139+
* <code>init</code> has been called before this method is called.
140+
*
141+
* @param pt the input buffer with the data to be encrypted
142+
* @param dummy1 the offset in <code>pt</code> which is always 0
143+
* @param ptLen the length of the input data
144+
* @param dummy2 the output buffer for the encryption which is always pt
145+
* @param dummy3 the offset in the output buffer which is always 0
146+
* @return the number of bytes placed into <code>pt</code>
147+
*/
148+
@Override
149+
int encryptFinal(byte[] pt, int dummy1, int ptLen, byte[] dummy2,
150+
int dummy3) throws IllegalBlockSizeException {
151+
// adjust the min value since pt contains the first semi-block
152+
if (ptLen < MIN_INPUTLEN || (ptLen % SEMI_BLKSIZE) != 0) {
153+
throw new IllegalBlockSizeException("data should" +
154+
" be at least 16 bytes and multiples of 8");
155+
}
156+
return W(iv, pt, ptLen, embeddedCipher);
157+
}
158+
159+
/**
160+
* Performs single-part decryption operation.
161+
*
162+
* <p>The input <code>ct</code>, starting at <code>0</code>
163+
* and ending at <code>ctLen-1</code>, is decrypted.
164+
* The result is stored in place into <code>ct</code>, starting at
165+
* <code>0</code>.
166+
*
167+
* <p>NOTE: Purpose of this special impl is for minimizing array
168+
* copying, those unused arguments are named as dummyN.
169+
*
170+
* <p>The subclass that implements Cipher should ensure that
171+
* <code>init</code> has been called before this method is called.
172+
*
173+
* @param ct the input buffer with the data to be decrypted
174+
* @param dummy1 the offset in <code>ct</code> which is always 0
175+
* @param ctLen the length of the input data
176+
* @param dummy2 the output buffer for the decryption which is always ct
177+
* @param dummy3 the offset in the output buffer which is always 0
178+
* @return the number of bytes placed into <code>ct</code>
179+
*/
180+
@Override
181+
int decryptFinal(byte[] ct, int dummy1, int ctLen, byte[] dummy2,
182+
int dummy3) throws IllegalBlockSizeException {
183+
if (ctLen < MIN_INPUTLEN || (ctLen % SEMI_BLKSIZE) != 0) {
184+
throw new IllegalBlockSizeException
185+
("data should be at least 24 bytes and multiples of 8");
186+
}
187+
byte[] ivOut = new byte[SEMI_BLKSIZE];
188+
ctLen = W_INV(ct, ctLen, ivOut, embeddedCipher);
189+
190+
// check against icv and fail if not match
191+
if (!MessageDigest.isEqual(ivOut, this.iv)) {
192+
throw new IllegalBlockSizeException("Integrity check failed");
193+
}
194+
return ctLen;
195+
}
196+
}

0 commit comments

Comments
 (0)