Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/com/sun/crypto/provider/AESKeyWrapPadded.java
41161 views
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 With Padding mode of operation as
37
* defined in
38
* <a href=https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf>
39
* "Recommendation for Block Cipher Modes of Operation: Methods for Key Wrapping"</a>
40
* and represents AES cipher in KWP mode.
41
*/
42
class AESKeyWrapPadded extends FeedbackCipher {
43
44
// default integrity check value (icv) if iv is not supplied
45
private static final byte[] ICV2 = { // SEMI_BLKSIZE/2 long
46
(byte) 0xA6, (byte) 0x59, (byte) 0x59, (byte) 0xA6,
47
};
48
49
private static final byte[] PAD_BLK = new byte[SEMI_BLKSIZE - 1];
50
51
// set the first semiblock of dest with iv and inLen
52
private static void setIvAndLen(byte[] dest, byte[] iv, int inLen) {
53
assert(dest.length >= SEMI_BLKSIZE) : "buffer needs at least 8 bytes";
54
55
System.arraycopy(iv, 0, dest, 0, iv.length);
56
dest[4] = (byte) ((inLen >>> 24) & 0xFF);
57
dest[5] = (byte) ((inLen >>> 16) & 0xFF);
58
dest[6] = (byte) ((inLen >>> 8) & 0xFF);
59
dest[7] = (byte) (inLen & 0xFF);
60
}
61
62
// validate the recovered internal ivAndLen semiblock against iv and
63
// return the recovered input length
64
private static int validateIV(byte[] ivAndLen, byte[] iv)
65
throws IllegalBlockSizeException {
66
// check against iv and fail if not match
67
int match = 0;
68
for (int i = 0; i < ICV2.length; i++) {
69
match |= (ivAndLen[i] ^ iv[i]);
70
}
71
if (match != 0) {
72
throw new IllegalBlockSizeException("Integrity check failed");
73
}
74
int outLen = ivAndLen[4];
75
76
for (int k = 5; k < SEMI_BLKSIZE; k++) {
77
if (outLen != 0) {
78
outLen <<= 8;
79
}
80
outLen |= ivAndLen[k] & 0xFF;
81
}
82
return outLen;
83
}
84
85
AESKeyWrapPadded() {
86
super(new AESCrypt());
87
}
88
89
/**
90
* Gets the name of this feedback mode.
91
*
92
* @return the string <code>KW</code>
93
*/
94
@Override
95
String getFeedback() {
96
return "KWP";
97
}
98
99
/**
100
* Save the current content of this cipher.
101
*/
102
@Override
103
void save() {
104
throw new UnsupportedOperationException("save not supported");
105
};
106
107
/**
108
* Restores the content of this cipher to the previous saved one.
109
*/
110
@Override
111
void restore() {
112
throw new UnsupportedOperationException("restore not supported");
113
};
114
115
/**
116
* Initializes the cipher in the specified mode with the given key
117
* and iv.
118
*
119
* @param decrypting flag indicating encryption or decryption
120
* @param algorithm the algorithm name
121
* @param key the key
122
* @param iv the iv
123
*
124
* @exception InvalidKeyException if the given key is inappropriate for
125
* initializing this cipher
126
* @exception InvalidAlgorithmParameterException if the given iv is
127
* non-null and not the right length
128
*/
129
@Override
130
void init(boolean decrypting, String algorithm, byte[] key, byte[] iv)
131
throws InvalidKeyException, InvalidAlgorithmParameterException {
132
if (key == null) {
133
throw new InvalidKeyException("Invalid null key");
134
}
135
if (iv != null && iv.length != ICV2.length) {
136
throw new InvalidAlgorithmParameterException("Invalid IV length");
137
}
138
embeddedCipher.init(decrypting, algorithm, key);
139
// iv is retrieved from IvParameterSpec.getIV() which is already cloned
140
this.iv = (iv == null? ICV2 : iv);
141
}
142
143
/**
144
* Resets the iv to its original value.
145
* This is used when doFinal is called in the Cipher class, so that the
146
* cipher can be reused (with its original iv).
147
*/
148
@Override
149
void reset() {
150
throw new UnsupportedOperationException("reset not supported");
151
};
152
153
// no support for multi-part encryption
154
@Override
155
int encrypt(byte[] pt, int ptOfs, int ptLen, byte[] ct, int ctOfs) {
156
throw new UnsupportedOperationException("multi-part not supported");
157
};
158
159
// no support for multi-part decryption
160
@Override
161
int decrypt(byte[] ct, int ctOfs, int ctLen, byte[] pt, int ptOfs) {
162
throw new UnsupportedOperationException("multi-part not supported");
163
};
164
165
/**
166
* Performs single-part encryption operation.
167
*
168
* <p>The input <code>pt</code>, starting at <code>0</code>
169
* and ending at <code>ptLen-1</code>, is encrypted.
170
* The result is stored in place into <code>pt</code>, starting at
171
* <code>0</code>.
172
*
173
* <p>The subclass that implements Cipher should ensure that
174
* <code>init</code> has been called before this method is called.
175
*
176
* @param pt the input buffer with the data to be encrypted
177
* @param dummy1 the offset in <code>pt</code> which is always 0
178
* @param ptLen the length of the input data
179
* @param dummy2 the output buffer for the encryption which is always pt
180
* @param dummy3 the offset in the output buffer which is always 0
181
* @return the number of bytes placed into <code>pt</code>
182
*/
183
@Override
184
int encryptFinal(byte[] pt, int dummy1, int ptLen, byte[] dummy2,
185
int dummy3) throws IllegalBlockSizeException {
186
int actualLen = ptLen - SEMI_BLKSIZE;
187
if (actualLen < 1) {
188
throw new IllegalBlockSizeException
189
("data should have at least 1 byte");
190
}
191
192
if (ptLen % SEMI_BLKSIZE != 0) {
193
int rem = SEMI_BLKSIZE - (ptLen % SEMI_BLKSIZE);
194
System.arraycopy(PAD_BLK, 0, pt, ptLen, rem);
195
ptLen += rem;
196
}
197
198
if (ptLen <= BLKSIZE) {
199
// overwrite the first semiblock with iv and input length
200
setIvAndLen(pt, iv, actualLen);
201
embeddedCipher.encryptBlock(pt, 0, pt, 0);
202
} else {
203
byte[] ivAndLen = new byte[SEMI_BLKSIZE];
204
setIvAndLen(ivAndLen, iv, actualLen);
205
ptLen = W(ivAndLen, pt, ptLen, embeddedCipher);
206
}
207
return ptLen;
208
}
209
210
/**
211
* Performs single-part decryption operation.
212
*
213
* <p>The input <code>ct</code>, starting at <code>0</code>
214
* and ending at <code>ctLen-1</code>, is decrypted.
215
* The result is stored in place into <code>ct</code>, starting at
216
* <code>0</code>.
217
*
218
* <p>The subclass that implements Cipher should ensure that
219
* <code>init</code> has been called before this method is called.
220
*
221
* @param ct the input buffer with the data to be decrypted
222
* @param dummy1 the offset in <code>ct</code> which is always 0
223
* @param ctLen the length of the input data
224
* @param dummy2 the output buffer for the decryption which is always ct
225
* @param dummy3 the offset in the output buffer which is always 0
226
* @return the number of bytes placed into <code>ct</code>
227
*/
228
@Override
229
int decryptFinal(byte[] ct, int dummy1, int ctLen, byte[] dummy2,
230
int dummy3) throws IllegalBlockSizeException {
231
if (ctLen < BLKSIZE || ctLen % SEMI_BLKSIZE != 0) {
232
throw new IllegalBlockSizeException
233
("data should be at least 16 bytes and multiples of 8");
234
}
235
236
byte[] ivAndLen = new byte[SEMI_BLKSIZE];
237
if (ctLen == BLKSIZE) {
238
embeddedCipher.decryptBlock(ct, 0, ct, 0);
239
System.arraycopy(ct, 0, ivAndLen, 0, SEMI_BLKSIZE);
240
System.arraycopy(ct, SEMI_BLKSIZE, ct, 0, SEMI_BLKSIZE);
241
ctLen -= SEMI_BLKSIZE;
242
} else {
243
ctLen = W_INV(ct, ctLen, ivAndLen, embeddedCipher);
244
}
245
246
int outLen = validateIV(ivAndLen, this.iv);
247
// check padding bytes
248
int padLen = ctLen - outLen;
249
if (padLen < 0 || padLen >= SEMI_BLKSIZE) {
250
throw new IllegalBlockSizeException("Invalid KWP pad length " +
251
padLen);
252
}
253
for (int k = padLen; k > 0; k--) {
254
if (ct[ctLen - k] != 0) {
255
throw new IllegalBlockSizeException("Invalid KWP pad value");
256
}
257
}
258
return outLen;
259
}
260
}
261
262