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 * (C) Copyright IBM Corp. 2013 27 */ 28 29 package com.sun.crypto.provider; 30 31 import java.util.Arrays; 32 import java.security.*; 33 import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE; 34 35 /** 36 * 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. 38 * block H. Given input of 128-bit blocks, it will process and output 39 * a 128-bit block. 40 * 41 * <p>This function is used in the implementation of GCM mode. 42 * 43 * @since 1.8 44 */ 45 final class GHASH { 46 47 private static final byte P128 = (byte) 0xe1; //reduction polynomial 48 49 private static boolean getBit(byte[] b, int pos) { 50 int p = pos / 8; 51 pos %= 8; 52 int i = (b[p] >>> (7 - pos)) & 1; 53 return i != 0; 54 } 55 56 private static void shift(byte[] b) { 57 byte temp, temp2; 58 temp2 = 0; 59 for (int i = 0; i < b.length; i++) { 60 temp = (byte) ((b[i] & 0x01) << 7); 61 b[i] = (byte) ((b[i] & 0xff) >>> 1); 62 b[i] = (byte) (b[i] | temp2); 63 temp2 = temp; 64 } 65 } 66 67 // Given block X and Y, returns the muliplication of X * Y 68 private static byte[] blockMult(byte[] x, byte[] y) { 69 if (x.length != AES_BLOCK_SIZE || y.length != AES_BLOCK_SIZE) { 70 throw new RuntimeException("illegal input sizes"); 71 } 72 byte[] z = new byte[AES_BLOCK_SIZE]; 73 byte[] v = y.clone(); 74 // calculate Z1-Z127 and V1-V127 75 for (int i = 0; i < 127; i++) { 76 // Zi+1 = Zi if bit i of x is 0 77 if (getBit(x, i)) { 78 for (int n = 0; n < z.length; n++) { 79 z[n] ^= v[n]; 80 } 81 } 82 boolean lastBitOfV = getBit(v, 127); 83 shift(v); 84 if (lastBitOfV) v[0] ^= P128; 85 } 86 // calculate Z128 87 if (getBit(x, 127)) { 88 for (int n = 0; n < z.length; n++) { 89 z[n] ^= v[n]; 90 } 91 } 92 return z; 93 } 94 95 // hash subkey H; should not change after the object has been constructed 96 private final byte[] subkeyH; 97 98 // buffer for storing hash 99 private byte[] state; 100 101 // variables for save/restore calls 102 private byte[] stateSave = null; 103 104 /** 105 * Initializes the cipher in the specified mode with the given key 106 * and iv. 107 * 108 * @param subkeyH the hash subkey 109 * 110 * @exception ProviderException if the given key is inappropriate for 111 * initializing this digest 112 */ 113 GHASH(byte[] subkeyH) throws ProviderException { 114 if ((subkeyH == null) || subkeyH.length != AES_BLOCK_SIZE) { 115 throw new ProviderException("Internal error"); 116 } 117 this.subkeyH = subkeyH; 118 this.state = new byte[AES_BLOCK_SIZE]; 119 } 120 121 /** 122 * 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 124 * this object for different data w/ the same H. 125 */ 126 void reset() { 127 Arrays.fill(state, (byte) 0); 128 } 129 130 /** 131 * Save the current snapshot of this GHASH object. 132 */ 133 void save() { 134 stateSave = state.clone(); 135 } 136 137 /** 138 * Restores this object using the saved snapshot. 139 */ 140 void restore() { 141 state = stateSave; 142 } 143 144 private void processBlock(byte[] data, int ofs) { 145 if (data.length - ofs < AES_BLOCK_SIZE) { 146 throw new RuntimeException("need complete block"); 147 } 148 for (int n = 0; n < state.length; n++) { 149 state[n] ^= data[ofs + n]; 150 } 151 state = blockMult(state, subkeyH); 152 } 153 154 void update(byte[] in) { 155 update(in, 0, in.length); 156 } 157 158 void update(byte[] in, int inOfs, int inLen) { 159 if (inLen - inOfs > in.length) { 160 throw new RuntimeException("input length out of bound"); 161 } 162 if (inLen % AES_BLOCK_SIZE != 0) { 163 throw new RuntimeException("input length unsupported"); 164 } 165 166 for (int i = inOfs; i < (inOfs + inLen); i += AES_BLOCK_SIZE) { 167 processBlock(in, i); 168 } 169 } 170 171 byte[] digest() { 172 try { 173 return state.clone(); 174 } finally { 175 reset(); 176 } 177 } 178 }