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. 42 * 43 * <p>This function is used in the implementation of GCM mode. 44 * 45 * @since 1.8 46 */ 47 final class GCTR { 48 49 // these fields should not change after the object has been constructed 50 private final SymmetricCipher aes; 51 private final byte[] icb; 52 53 // the current counter value 54 private byte[] counter; 55 56 // needed for save/restore calls 57 private byte[] counterSave; 58 59 // NOTE: cipher should already be initialized 60 GCTR(SymmetricCipher cipher, byte[] initialCounterBlk) { 61 this.aes = cipher; 62 this.icb = initialCounterBlk; 63 this.counter = icb.clone(); 64 } 65 66 // input must be multiples of 128-bit blocks when calling update 67 int update(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) { 68 if (inLen - inOfs > in.length) { 69 throw new RuntimeException("input length out of bound"); 70 } 71 if (inLen < 0 || inLen % AES_BLOCK_SIZE != 0) { 72 throw new RuntimeException("input length unsupported"); 73 } 74 if (out.length - outOfs < inLen) { 75 throw new RuntimeException("output buffer too small"); 76 } 77 78 byte[] encryptedCntr = new byte[AES_BLOCK_SIZE]; 79 80 int numOfCompleteBlocks = inLen / AES_BLOCK_SIZE; 81 for (int i = 0; i < numOfCompleteBlocks; i++) { 82 aes.encryptBlock(counter, 0, encryptedCntr, 0); 83 for (int n = 0; n < AES_BLOCK_SIZE; n++) { 84 int index = (i * AES_BLOCK_SIZE + n); 85 out[outOfs + index] = 86 (byte) ((in[inOfs + index] ^ encryptedCntr[n])); 87 } 88 GaloisCounterMode.increment32(counter); 89 } 90 return inLen; 91 } 92 93 // input can be arbitrary size when calling doFinal 94 protected int doFinal(byte[] in, int inOfs, int inLen, byte[] out, 95 int outOfs) throws IllegalBlockSizeException { 96 try { 97 if (inLen < 0) { 98 throw new IllegalBlockSizeException("Negative input size!"); 99 } else if (inLen > 0) { 100 int lastBlockSize = inLen % AES_BLOCK_SIZE; 101 // process the complete blocks first 102 update(in, inOfs, inLen - lastBlockSize, out, outOfs); 103 if (lastBlockSize != 0) { 104 // do the last partial block 105 byte[] encryptedCntr = new byte[AES_BLOCK_SIZE]; 106 aes.encryptBlock(counter, 0, encryptedCntr, 0); 107 108 int processed = inLen - lastBlockSize; 109 for (int n = 0; n < lastBlockSize; n++) { 110 out[outOfs + processed + n] = 111 (byte) ((in[inOfs + processed + n] ^ 112 encryptedCntr[n])); 113 } 114 } 115 } 116 } finally { 117 reset(); 118 } 119 return inLen; 120 } 121 122 /** 123 * Resets the current counter to its initial value. 124 * This is used after the doFinal() is called so this object can be 125 * reused w/o explicit re-initialization. 126 */ 127 void reset() { 128 System.arraycopy(icb, 0, counter, 0, icb.length); 129 } 130 131 /** 132 * Save the current content of this object. 133 */ 134 void save() { 135 this.counterSave = this.counter.clone(); 136 } 137 138 /** 139 * Restores the content of this object to the previous saved one. 140 */ 141 void restore() { 142 this.counter = this.counterSave; 143 } 144 }