Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/crypto/provider/GCTR.java
38922 views
/*1* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* (C) Copyright IBM Corp. 201327*/2829package com.sun.crypto.provider;3031import java.security.*;32import javax.crypto.*;33import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;3435/**36* This class represents the GCTR function defined in NIST 800-38D37* under section 6.5. It needs to be constructed w/ an initialized38* cipher object, and initial counter block(ICB). Given an input X39* of arbitrary length, it processes and returns an output which has40* the same length as X. The invariants of this class are:41*42* (1) The length of intialCounterBlk (and also of its clones, e.g.,43* fields counter and counterSave) is equal to AES_BLOCK_SIZE.44*45* (2) After construction, the field counter never becomes null, it46* always contains a byte array of length AES_BLOCK_SIZE.47*48* If any invariant is broken, failures can occur because the49* AESCrypt.encryptBlock method can be intrinsified on the HotSpot VM50* (see JDK-8067648 for details).51*52* <p>This function is used in the implementation of GCM mode.53*54* @since 1.855*/56final class GCTR {5758// these fields should not change after the object has been constructed59private final SymmetricCipher aes;60private final byte[] icb;6162// the current counter value63private byte[] counter;6465// needed for save/restore calls66private byte[] counterSave = null;6768// NOTE: cipher should already be initialized69GCTR(SymmetricCipher cipher, byte[] initialCounterBlk) {70this.aes = cipher;71if (initialCounterBlk.length != AES_BLOCK_SIZE) {72throw new RuntimeException("length of initial counter block (" + initialCounterBlk.length +73") not equal to AES_BLOCK_SIZE (" + AES_BLOCK_SIZE + ")");74}75this.icb = initialCounterBlk;76this.counter = icb.clone();77}7879// input must be multiples of 128-bit blocks when calling update80int update(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) {81if (inLen - inOfs > in.length) {82throw new RuntimeException("input length out of bound");83}84if (inLen < 0 || inLen % AES_BLOCK_SIZE != 0) {85throw new RuntimeException("input length unsupported");86}87if (out.length - outOfs < inLen) {88throw new RuntimeException("output buffer too small");89}9091byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];9293int numOfCompleteBlocks = inLen / AES_BLOCK_SIZE;94for (int i = 0; i < numOfCompleteBlocks; i++) {95aes.encryptBlock(counter, 0, encryptedCntr, 0);96for (int n = 0; n < AES_BLOCK_SIZE; n++) {97int index = (i * AES_BLOCK_SIZE + n);98out[outOfs + index] =99(byte) ((in[inOfs + index] ^ encryptedCntr[n]));100}101GaloisCounterMode.increment32(counter);102}103return inLen;104}105106// input can be arbitrary size when calling doFinal107protected int doFinal(byte[] in, int inOfs, int inLen, byte[] out,108int outOfs) throws IllegalBlockSizeException {109try {110if (inLen < 0) {111throw new IllegalBlockSizeException("Negative input size!");112} else if (inLen > 0) {113int lastBlockSize = inLen % AES_BLOCK_SIZE;114int completeBlkLen = inLen - lastBlockSize;115// process the complete blocks first116update(in, inOfs, completeBlkLen, out, outOfs);117if (lastBlockSize != 0) {118// do the last partial block119byte[] encryptedCntr = new byte[AES_BLOCK_SIZE];120aes.encryptBlock(counter, 0, encryptedCntr, 0);121for (int n = 0; n < lastBlockSize; n++) {122out[outOfs + completeBlkLen + n] =123(byte) ((in[inOfs + completeBlkLen + n] ^124encryptedCntr[n]));125}126}127}128} finally {129reset();130}131return inLen;132}133134/**135* Resets the content of this object to when it's first constructed.136*/137void reset() {138System.arraycopy(icb, 0, counter, 0, icb.length);139counterSave = null;140}141142/**143* Save the current content of this object.144*/145void save() {146this.counterSave = this.counter.clone();147}148149/**150* Restores the content of this object to the previous saved one.151*/152void restore() {153if (this.counterSave != null) {154this.counter = this.counterSave;155}156}157}158159160