Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java
38922 views
1
/*
2
* Copyright (c) 2013, 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.security.*;
33
import javax.crypto.*;
34
import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;
35
36
/**
37
* This class represents the GCTR function defined in NIST 800-38D
38
* under section 6.5. It needs to be constructed w/ an initialized
39
* cipher object, and initial counter block(ICB). Given an input X
40
* of arbitrary length, it processes and returns an output which has
41
* the same length as X. The invariants of this class are:
42
*
43
* (1) The length of intialCounterBlk (and also of its clones, e.g.,
44
* fields counter and counterSave) is equal to AES_BLOCK_SIZE.
45
*
46
* (2) After construction, the field counter never becomes null, it
47
* always contains a byte array of length AES_BLOCK_SIZE.
48
*
49
* If any invariant is broken, failures can occur because the
50
* AESCrypt.encryptBlock method can be intrinsified on the HotSpot VM
51
* (see JDK-8067648 for details).
52
*
53
* <p>This function is used in the implementation of GCM mode.
54
*
55
* @since 1.8
56
*/
57
final class GCTR {
58
59
// these fields should not change after the object has been constructed
60
private final SymmetricCipher aes;
61
private final byte[] icb;
62
63
// the current counter value
64
private byte[] counter;
65
66
// needed for save/restore calls
67
private byte[] counterSave = null;
68
69
// NOTE: cipher should already be initialized
70
GCTR(SymmetricCipher cipher, byte[] initialCounterBlk) {
71
this.aes = cipher;
72
if (initialCounterBlk.length != AES_BLOCK_SIZE) {
73
throw new RuntimeException("length of initial counter block (" + initialCounterBlk.length +
74
") not equal to AES_BLOCK_SIZE (" + AES_BLOCK_SIZE + ")");
75
}
76
this.icb = initialCounterBlk;
77
this.counter = icb.clone();
78
}
79
80
// input must be multiples of 128-bit blocks when calling update
81
int update(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) {
82
if (inLen - inOfs > in.length) {
83
throw new RuntimeException("input length out of bound");
84
}
85
if (inLen < 0 || inLen % AES_BLOCK_SIZE != 0) {
86
throw new RuntimeException("input length unsupported");
87
}
88
if (out.length - outOfs < inLen) {
89
throw new RuntimeException("output buffer too small");
90
}
91
92
byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
93
94
int numOfCompleteBlocks = inLen / AES_BLOCK_SIZE;
95
for (int i = 0; i < numOfCompleteBlocks; i++) {
96
aes.encryptBlock(counter, 0, encryptedCntr, 0);
97
for (int n = 0; n < AES_BLOCK_SIZE; n++) {
98
int index = (i * AES_BLOCK_SIZE + n);
99
out[outOfs + index] =
100
(byte) ((in[inOfs + index] ^ encryptedCntr[n]));
101
}
102
GaloisCounterMode.increment32(counter);
103
}
104
return inLen;
105
}
106
107
// input can be arbitrary size when calling doFinal
108
protected int doFinal(byte[] in, int inOfs, int inLen, byte[] out,
109
int outOfs) throws IllegalBlockSizeException {
110
try {
111
if (inLen < 0) {
112
throw new IllegalBlockSizeException("Negative input size!");
113
} else if (inLen > 0) {
114
int lastBlockSize = inLen % AES_BLOCK_SIZE;
115
int completeBlkLen = inLen - lastBlockSize;
116
// process the complete blocks first
117
update(in, inOfs, completeBlkLen, out, outOfs);
118
if (lastBlockSize != 0) {
119
// do the last partial block
120
byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];
121
aes.encryptBlock(counter, 0, encryptedCntr, 0);
122
for (int n = 0; n < lastBlockSize; n++) {
123
out[outOfs + completeBlkLen + n] =
124
(byte) ((in[inOfs + completeBlkLen + n] ^
125
encryptedCntr[n]));
126
}
127
}
128
}
129
} finally {
130
reset();
131
}
132
return inLen;
133
}
134
135
/**
136
* Resets the content of this object to when it's first constructed.
137
*/
138
void reset() {
139
System.arraycopy(icb, 0, counter, 0, icb.length);
140
counterSave = null;
141
}
142
143
/**
144
* Save the current content of this object.
145
*/
146
void save() {
147
this.counterSave = this.counter.clone();
148
}
149
150
/**
151
* Restores the content of this object to the previous saved one.
152
*/
153
void restore() {
154
if (this.counterSave != null) {
155
this.counter = this.counterSave;
156
}
157
}
158
}
159
160