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/GCTR.java
41161 views
1
/*
2
* Copyright (c) 2013, 2020, 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
/*
27
* (C) Copyright IBM Corp. 2013
28
*/
29
30
package com.sun.crypto.provider;
31
32
import java.nio.ByteBuffer;
33
import java.nio.ByteOrder;
34
import javax.crypto.IllegalBlockSizeException;
35
import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;
36
37
/**
38
* This class represents the GCTR function defined in NIST 800-38D
39
* under section 6.5. With a given cipher object and initial counter
40
* block, a counter mode operation is performed. Blocksize is limited
41
* to 16 bytes.
42
*
43
* If any invariant is broken, failures can occur because the
44
* AESCrypt.encryptBlock method can be intrinsified on the HotSpot VM
45
* (see JDK-8067648 for details).
46
*
47
* The counter mode operations can be intrinsified and parallelized
48
* by using CounterMode.implCrypt() if HotSpot VM supports it on the
49
* architecture.
50
*
51
* <p>This function is used in the implementation of GCM mode.
52
*
53
* @since 1.8
54
*/
55
final class GCTR extends CounterMode {
56
57
// Maximum buffer size rotating ByteBuffer->byte[] intrinsic copy
58
private static final int MAX_LEN = 1024;
59
60
GCTR(SymmetricCipher cipher, byte[] initialCounterBlk) {
61
super(cipher);
62
if (initialCounterBlk.length != AES_BLOCK_SIZE) {
63
throw new RuntimeException("length of initial counter block (" +
64
initialCounterBlk.length + ") not equal to AES_BLOCK_SIZE (" +
65
AES_BLOCK_SIZE + ")");
66
}
67
68
iv = initialCounterBlk;
69
reset();
70
}
71
72
@Override
73
String getFeedback() {
74
return "GCTR";
75
}
76
77
// return the number of blocks until the lower 32 bits roll over
78
private long blocksUntilRollover() {
79
ByteBuffer buf = ByteBuffer.wrap(counter, counter.length - 4, 4);
80
buf.order(ByteOrder.BIG_ENDIAN);
81
long ctr32 = 0xFFFFFFFFL & buf.getInt();
82
long blocksLeft = (1L << 32) - ctr32;
83
return blocksLeft;
84
}
85
86
// input must be multiples of 128-bit blocks when calling update
87
int update(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) {
88
if (inLen - inOfs > in.length) {
89
throw new RuntimeException("input length out of bound");
90
}
91
if (inLen < 0 || inLen % AES_BLOCK_SIZE != 0) {
92
throw new RuntimeException("input length unsupported");
93
}
94
if (out.length - outOfs < inLen) {
95
throw new RuntimeException("output buffer too small");
96
}
97
98
long blocksLeft = blocksUntilRollover();
99
int numOfCompleteBlocks = inLen / AES_BLOCK_SIZE;
100
if (numOfCompleteBlocks >= blocksLeft) {
101
// Counter Mode encryption cannot be used because counter will
102
// roll over incorrectly. Use GCM-specific code instead.
103
byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
104
for (int i = 0; i < numOfCompleteBlocks; i++) {
105
embeddedCipher.encryptBlock(counter, 0, encryptedCntr, 0);
106
for (int n = 0; n < AES_BLOCK_SIZE; n++) {
107
int index = (i * AES_BLOCK_SIZE + n);
108
out[outOfs + index] =
109
(byte) ((in[inOfs + index] ^ encryptedCntr[n]));
110
}
111
GaloisCounterMode.increment32(counter);
112
}
113
return inLen;
114
} else {
115
return encrypt(in, inOfs, inLen, out, outOfs);
116
}
117
}
118
119
// input must be multiples of AES blocks, 128-bit, when calling update
120
int update(byte[] in, int inOfs, int inLen, ByteBuffer dst) {
121
if (inLen - inOfs > in.length) {
122
throw new RuntimeException("input length out of bound");
123
}
124
if (inLen < 0 || inLen % AES_BLOCK_SIZE != 0) {
125
throw new RuntimeException("input length unsupported");
126
}
127
// See GaloisCounterMode. decryptFinal(bytebuffer, bytebuffer) for
128
// details on the check for 'dst' having enough space for the result.
129
130
long blocksLeft = blocksUntilRollover();
131
int numOfCompleteBlocks = inLen / AES_BLOCK_SIZE;
132
if (numOfCompleteBlocks >= blocksLeft) {
133
// Counter Mode encryption cannot be used because counter will
134
// roll over incorrectly. Use GCM-specific code instead.
135
byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
136
for (int i = 0; i < numOfCompleteBlocks; i++) {
137
embeddedCipher.encryptBlock(counter, 0, encryptedCntr, 0);
138
for (int n = 0; n < AES_BLOCK_SIZE; n++) {
139
int index = (i * AES_BLOCK_SIZE + n);
140
dst.put((byte) ((in[inOfs + index] ^ encryptedCntr[n])));
141
}
142
GaloisCounterMode.increment32(counter);
143
}
144
return inLen;
145
} else {
146
int len = inLen - inLen % AES_BLOCK_SIZE;
147
int processed = len;
148
byte[] out = new byte[Math.min(MAX_LEN, len)];
149
int offset = inOfs;
150
while (processed > MAX_LEN) {
151
encrypt(in, offset, MAX_LEN, out, 0);
152
dst.put(out, 0, MAX_LEN);
153
processed -= MAX_LEN;
154
offset += MAX_LEN;
155
}
156
encrypt(in, offset, processed, out, 0);
157
// If dst is less than blocksize, insert only what it can. Extra
158
// bytes would cause buffers with enough size to fail with a
159
// short buffer
160
dst.put(out, 0, Math.min(dst.remaining(), processed));
161
return len;
162
}
163
}
164
165
// input operates on multiples of AES blocks, 128-bit, when calling update.
166
// The remainder is left in the src buffer.
167
int update(ByteBuffer src, ByteBuffer dst) {
168
long blocksLeft = blocksUntilRollover();
169
int numOfCompleteBlocks = src.remaining() / AES_BLOCK_SIZE;
170
if (numOfCompleteBlocks >= blocksLeft) {
171
// Counter Mode encryption cannot be used because counter will
172
// roll over incorrectly. Use GCM-specific code instead.
173
byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
174
for (int i = 0; i < numOfCompleteBlocks; i++) {
175
embeddedCipher.encryptBlock(counter, 0, encryptedCntr, 0);
176
for (int n = 0; n < AES_BLOCK_SIZE; n++) {
177
dst.put((byte) (src.get() ^ encryptedCntr[n]));
178
}
179
GaloisCounterMode.increment32(counter);
180
}
181
return numOfCompleteBlocks * AES_BLOCK_SIZE;
182
}
183
184
int len = src.remaining() - (src.remaining() % AES_BLOCK_SIZE);
185
int processed = len;
186
byte[] in = new byte[Math.min(MAX_LEN, len)];
187
while (processed > MAX_LEN) {
188
src.get(in, 0, MAX_LEN);
189
encrypt(in, 0, MAX_LEN, in, 0);
190
dst.put(in, 0, MAX_LEN);
191
processed -= MAX_LEN;
192
}
193
src.get(in, 0, processed);
194
encrypt(in, 0, processed, in, 0);
195
dst.put(in, 0, processed);
196
return len;
197
}
198
199
// input can be arbitrary size when calling doFinal
200
int doFinal(byte[] in, int inOfs, int inLen, byte[] out,
201
int outOfs) throws IllegalBlockSizeException {
202
try {
203
if (inLen < 0) {
204
throw new IllegalBlockSizeException("Negative input size!");
205
} else if (inLen > 0) {
206
int lastBlockSize = inLen % AES_BLOCK_SIZE;
207
int completeBlkLen = inLen - lastBlockSize;
208
// process the complete blocks first
209
update(in, inOfs, completeBlkLen, out, outOfs);
210
if (lastBlockSize != 0) {
211
// do the last partial block
212
byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
213
embeddedCipher.encryptBlock(counter, 0, encryptedCntr, 0);
214
for (int n = 0; n < lastBlockSize; n++) {
215
out[outOfs + completeBlkLen + n] =
216
(byte) ((in[inOfs + completeBlkLen + n] ^
217
encryptedCntr[n]));
218
}
219
}
220
}
221
} finally {
222
reset();
223
}
224
return inLen;
225
}
226
227
// src can be arbitrary size when calling doFinal
228
int doFinal(ByteBuffer src, ByteBuffer dst) {
229
int len = src.remaining();
230
int lastBlockSize = len % AES_BLOCK_SIZE;
231
try {
232
update(src, dst);
233
if (lastBlockSize != 0) {
234
// do the last partial block
235
byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
236
embeddedCipher.encryptBlock(counter, 0, encryptedCntr, 0);
237
for (int n = 0; n < lastBlockSize; n++) {
238
dst.put((byte) (src.get() ^ encryptedCntr[n]));
239
}
240
}
241
} finally {
242
reset();
243
}
244
return len;
245
}
246
}
247
248