1 /* |
1 /* |
2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. |
|
3 * Copyright (c) 2015 Red Hat, Inc. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
5 * |
5 * This code is free software; you can redistribute it and/or modify it |
6 * 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 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
8 * published by the Free Software Foundation. Oracle designates this |
26 * (C) Copyright IBM Corp. 2013 |
27 * (C) Copyright IBM Corp. 2013 |
27 */ |
28 */ |
28 |
29 |
29 package com.sun.crypto.provider; |
30 package com.sun.crypto.provider; |
30 |
31 |
31 import java.util.Arrays; |
32 import java.security.ProviderException; |
32 import java.security.*; |
|
33 import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE; |
|
34 |
33 |
35 /** |
34 /** |
36 * This class represents the GHASH function defined in NIST 800-38D |
35 * This class represents the GHASH function defined in NIST 800-38D |
37 * under section 6.4. It needs to be constructed w/ a hash subkey, i.e. |
36 * under section 6.4. It needs to be constructed w/ a hash subkey, i.e. |
38 * block H. Given input of 128-bit blocks, it will process and output |
37 * block H. Given input of 128-bit blocks, it will process and output |
42 * |
41 * |
43 * @since 1.8 |
42 * @since 1.8 |
44 */ |
43 */ |
45 final class GHASH { |
44 final class GHASH { |
46 |
45 |
47 private static final byte P128 = (byte) 0xe1; //reduction polynomial |
46 private static long getLong(byte[] buffer, int offset) { |
48 |
47 long result = 0; |
49 private static boolean getBit(byte[] b, int pos) { |
48 int end = offset + 8; |
50 int p = pos / 8; |
49 for (int i = offset; i < end; ++i) { |
51 pos %= 8; |
50 result = (result << 8) + (buffer[i] & 0xFF); |
52 int i = (b[p] >>> (7 - pos)) & 1; |
51 } |
53 return i != 0; |
52 return result; |
54 } |
53 } |
55 |
54 |
56 private static void shift(byte[] b) { |
55 private static void putLong(byte[] buffer, int offset, long value) { |
57 byte temp, temp2; |
56 int end = offset + 8; |
58 temp2 = 0; |
57 for (int i = end - 1; i >= offset; --i) { |
59 for (int i = 0; i < b.length; i++) { |
58 buffer[i] = (byte) value; |
60 temp = (byte) ((b[i] & 0x01) << 7); |
59 value >>= 8; |
61 b[i] = (byte) ((b[i] & 0xff) >>> 1); |
60 } |
62 b[i] = (byte) (b[i] | temp2); |
61 } |
63 temp2 = temp; |
62 |
64 } |
63 private static final int AES_BLOCK_SIZE = 16; |
65 } |
64 |
66 |
65 // Multiplies state0, state1 by V0, V1. |
67 // Given block X and Y, returns the muliplication of X * Y |
66 private void blockMult(long V0, long V1) { |
68 private static byte[] blockMult(byte[] x, byte[] y) { |
67 long Z0 = 0; |
69 if (x.length != AES_BLOCK_SIZE || y.length != AES_BLOCK_SIZE) { |
68 long Z1 = 0; |
70 throw new RuntimeException("illegal input sizes"); |
69 long X; |
71 } |
70 |
72 byte[] z = new byte[AES_BLOCK_SIZE]; |
71 // Separate loops for processing state0 and state1. |
73 byte[] v = y.clone(); |
72 X = state0; |
74 // calculate Z1-Z127 and V1-V127 |
73 for (int i = 0; i < 64; i++) { |
75 for (int i = 0; i < 127; i++) { |
|
76 // Zi+1 = Zi if bit i of x is 0 |
74 // Zi+1 = Zi if bit i of x is 0 |
77 if (getBit(x, i)) { |
75 long mask = X >> 63; |
78 for (int n = 0; n < z.length; n++) { |
76 Z0 ^= V0 & mask; |
79 z[n] ^= v[n]; |
77 Z1 ^= V1 & mask; |
80 } |
78 |
81 } |
79 // Save mask for conditional reduction below. |
82 boolean lastBitOfV = getBit(v, 127); |
80 mask = (V1 << 63) >> 63; |
83 shift(v); |
81 |
84 if (lastBitOfV) v[0] ^= P128; |
82 // V = rightshift(V) |
85 } |
83 long carry = V0 & 1; |
|
84 V0 = V0 >>> 1; |
|
85 V1 = (V1 >>> 1) | (carry << 63); |
|
86 |
|
87 // Conditional reduction modulo P128. |
|
88 V0 ^= 0xe100000000000000L & mask; |
|
89 X <<= 1; |
|
90 } |
|
91 |
|
92 X = state1; |
|
93 for (int i = 64; i < 127; i++) { |
|
94 // Zi+1 = Zi if bit i of x is 0 |
|
95 long mask = X >> 63; |
|
96 Z0 ^= V0 & mask; |
|
97 Z1 ^= V1 & mask; |
|
98 |
|
99 // Save mask for conditional reduction below. |
|
100 mask = (V1 << 63) >> 63; |
|
101 |
|
102 // V = rightshift(V) |
|
103 long carry = V0 & 1; |
|
104 V0 = V0 >>> 1; |
|
105 V1 = (V1 >>> 1) | (carry << 63); |
|
106 |
|
107 // Conditional reduction. |
|
108 V0 ^= 0xe100000000000000L & mask; |
|
109 X <<= 1; |
|
110 } |
|
111 |
86 // calculate Z128 |
112 // calculate Z128 |
87 if (getBit(x, 127)) { |
113 long mask = X >> 63; |
88 for (int n = 0; n < z.length; n++) { |
114 Z0 ^= V0 & mask; |
89 z[n] ^= v[n]; |
115 Z1 ^= V1 & mask; |
90 } |
116 |
91 } |
117 // Save result. |
92 return z; |
118 state0 = Z0; |
|
119 state1 = Z1; |
93 } |
120 } |
94 |
121 |
95 // hash subkey H; should not change after the object has been constructed |
122 // hash subkey H; should not change after the object has been constructed |
96 private final byte[] subkeyH; |
123 private final long subkeyH0, subkeyH1; |
97 |
124 |
98 // buffer for storing hash |
125 // buffer for storing hash |
99 private byte[] state; |
126 private long state0, state1; |
100 |
127 |
101 // variables for save/restore calls |
128 // variables for save/restore calls |
102 private byte[] stateSave = null; |
129 private long stateSave0, stateSave1; |
103 |
130 |
104 /** |
131 /** |
105 * Initializes the cipher in the specified mode with the given key |
132 * Initializes the cipher in the specified mode with the given key |
106 * and iv. |
133 * and iv. |
107 * |
134 * |
112 */ |
139 */ |
113 GHASH(byte[] subkeyH) throws ProviderException { |
140 GHASH(byte[] subkeyH) throws ProviderException { |
114 if ((subkeyH == null) || subkeyH.length != AES_BLOCK_SIZE) { |
141 if ((subkeyH == null) || subkeyH.length != AES_BLOCK_SIZE) { |
115 throw new ProviderException("Internal error"); |
142 throw new ProviderException("Internal error"); |
116 } |
143 } |
117 this.subkeyH = subkeyH; |
144 this.subkeyH0 = getLong(subkeyH, 0); |
118 this.state = new byte[AES_BLOCK_SIZE]; |
145 this.subkeyH1 = getLong(subkeyH, 8); |
119 } |
146 } |
120 |
147 |
121 /** |
148 /** |
122 * Resets the GHASH object to its original state, i.e. blank w/ |
149 * Resets the GHASH object to its original state, i.e. blank w/ |
123 * the same subkey H. Used after digest() is called and to re-use |
150 * the same subkey H. Used after digest() is called and to re-use |
124 * this object for different data w/ the same H. |
151 * this object for different data w/ the same H. |
125 */ |
152 */ |
126 void reset() { |
153 void reset() { |
127 Arrays.fill(state, (byte) 0); |
154 state0 = 0; |
|
155 state1 = 0; |
128 } |
156 } |
129 |
157 |
130 /** |
158 /** |
131 * Save the current snapshot of this GHASH object. |
159 * Save the current snapshot of this GHASH object. |
132 */ |
160 */ |
133 void save() { |
161 void save() { |
134 stateSave = state.clone(); |
162 stateSave0 = state0; |
|
163 stateSave1 = state1; |
135 } |
164 } |
136 |
165 |
137 /** |
166 /** |
138 * Restores this object using the saved snapshot. |
167 * Restores this object using the saved snapshot. |
139 */ |
168 */ |
140 void restore() { |
169 void restore() { |
141 state = stateSave; |
170 state0 = stateSave0; |
|
171 state1 = stateSave1; |
142 } |
172 } |
143 |
173 |
144 private void processBlock(byte[] data, int ofs) { |
174 private void processBlock(byte[] data, int ofs) { |
145 if (data.length - ofs < AES_BLOCK_SIZE) { |
175 if (data.length - ofs < AES_BLOCK_SIZE) { |
146 throw new RuntimeException("need complete block"); |
176 throw new RuntimeException("need complete block"); |
147 } |
177 } |
148 for (int n = 0; n < state.length; n++) { |
178 state0 ^= getLong(data, ofs); |
149 state[n] ^= data[ofs + n]; |
179 state1 ^= getLong(data, ofs + 8); |
150 } |
180 blockMult(subkeyH0, subkeyH1); |
151 state = blockMult(state, subkeyH); |
|
152 } |
181 } |
153 |
182 |
154 void update(byte[] in) { |
183 void update(byte[] in) { |
155 update(in, 0, in.length); |
184 update(in, 0, in.length); |
156 } |
185 } |