jdk/src/java.base/share/classes/com/sun/crypto/provider/GHASH.java
changeset 28851 e4c16ed7bffa
parent 25859 3317bb8137f4
child 31462 1d0b519af651
equal deleted inserted replaced
28850:4996a75e8bfb 28851:e4c16ed7bffa
     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     }
   167             processBlock(in, i);
   196             processBlock(in, i);
   168         }
   197         }
   169     }
   198     }
   170 
   199 
   171     byte[] digest() {
   200     byte[] digest() {
   172         try {
   201         byte[] result = new byte[AES_BLOCK_SIZE];
   173             return state.clone();
   202         putLong(result, 0, state0);
   174         } finally {
   203         putLong(result, 8, state1);
   175             reset();
   204         reset();
   176         }
   205         return result;
   177     }
   206     }
   178 }
   207 }