Path: blob/master/src/java.base/share/classes/com/sun/crypto/provider/AESKeyWrap.java
41161 views
/*1* Copyright (c) 2021, 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*/2425package com.sun.crypto.provider;2627import java.util.Arrays;28import java.security.*;29import java.security.spec.*;30import javax.crypto.*;31import javax.crypto.spec.*;32import static com.sun.crypto.provider.KWUtil.*;3334/**35* This class implement the AES KeyWrap mode of operation as defined in36* <a href=https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf>37* "Recommendation for Block Cipher Modes of Operation: Methods for Key Wrapping"</a>38* and represents AES cipher in KW mode.39*/40class AESKeyWrap extends FeedbackCipher {4142// default integrity check value (icv) if iv is not supplied43private static final byte[] ICV1 = { // SEMI_BLKSIZE long44(byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA6,45(byte) 0xA6, (byte) 0xA6, (byte) 0xA6, (byte) 0xA646};4748AESKeyWrap() {49super(new AESCrypt());50}5152/**53* Gets the name of this feedback mode.54*55* @return the string <code>KW</code>56*/57@Override58String getFeedback() {59return "KW";60}6162/**63* Save the current content of this cipher.64*/65@Override66void save() {67throw new UnsupportedOperationException("save not supported");68};6970/**71* Restores the content of this cipher to the previous saved one.72*/73@Override74void restore() {75throw new UnsupportedOperationException("restore not supported");76};7778/**79* Initializes the cipher in the specified mode with the given key80* and iv.81*82* @param decrypting flag indicating encryption or decryption83* @param algorithm the algorithm name84* @param key the key85* @param iv the iv86*87* @exception InvalidKeyException if the given key is inappropriate for88* initializing this cipher89* @exception InvalidAlgorithmParameterException if the given iv is90* non-null and not the right length91*/92@Override93void init(boolean decrypting, String algorithm, byte[] key, byte[] iv)94throws InvalidKeyException, InvalidAlgorithmParameterException {95if (key == null) {96throw new InvalidKeyException("Invalid null key");97}98if (iv != null && iv.length != SEMI_BLKSIZE) {99throw new InvalidAlgorithmParameterException("Invalid IV");100}101embeddedCipher.init(decrypting, algorithm, key);102// iv is retrieved from IvParameterSpec.getIV() which is already cloned103this.iv = (iv == null? ICV1 : iv);104}105106/**107* Resets the iv to its original value.108* This is used when doFinal is called in the Cipher class, so that the109* cipher can be reused (with its original iv).110*/111@Override112void reset() {113throw new UnsupportedOperationException("reset not supported");114};115116117// no support for multi-part encryption118@Override119int encrypt(byte[] pt, int ptOfs, int ptLen, byte[] ct, int ctOfs) {120throw new UnsupportedOperationException("multi-part not supported");121};122123// no support for multi-part decryption124@Override125int decrypt(byte[] ct, int ctOfs, int ctLen, byte[] pt, int ptOfs) {126throw new UnsupportedOperationException("multi-part not supported");127};128129/**130* Performs single-part encryption operation.131*132* <p>The input <code>pt</code>, starting at <code>0</code>133* and ending at <code>ptLen-1</code>, is encrypted.134* The result is stored in place into <code>pt</code>, starting at135* <code>0</code>.136*137* <p>The subclass that implements Cipher should ensure that138* <code>init</code> has been called before this method is called.139*140* @param pt the input buffer with the data to be encrypted141* @param dummy1 the offset in <code>pt</code> which is always 0142* @param ptLen the length of the input data143* @param dummy2 the output buffer for the encryption which is always pt144* @param dummy3 the offset in the output buffer which is always 0145* @return the number of bytes placed into <code>pt</code>146*/147@Override148int encryptFinal(byte[] pt, int dummy1, int ptLen, byte[] dummy2,149int dummy3) throws IllegalBlockSizeException {150// adjust the min value since pt contains the first semi-block151if (ptLen < MIN_INPUTLEN || (ptLen % SEMI_BLKSIZE) != 0) {152throw new IllegalBlockSizeException("data should" +153" be at least 16 bytes and multiples of 8");154}155return W(iv, pt, ptLen, embeddedCipher);156}157158/**159* Performs single-part decryption operation.160*161* <p>The input <code>ct</code>, starting at <code>0</code>162* and ending at <code>ctLen-1</code>, is decrypted.163* The result is stored in place into <code>ct</code>, starting at164* <code>0</code>.165*166* <p>NOTE: Purpose of this special impl is for minimizing array167* copying, those unused arguments are named as dummyN.168*169* <p>The subclass that implements Cipher should ensure that170* <code>init</code> has been called before this method is called.171*172* @param ct the input buffer with the data to be decrypted173* @param dummy1 the offset in <code>ct</code> which is always 0174* @param ctLen the length of the input data175* @param dummy2 the output buffer for the decryption which is always ct176* @param dummy3 the offset in the output buffer which is always 0177* @return the number of bytes placed into <code>ct</code>178*/179@Override180int decryptFinal(byte[] ct, int dummy1, int ctLen, byte[] dummy2,181int dummy3) throws IllegalBlockSizeException {182if (ctLen < MIN_INPUTLEN || (ctLen % SEMI_BLKSIZE) != 0) {183throw new IllegalBlockSizeException184("data should be at least 24 bytes and multiples of 8");185}186byte[] ivOut = new byte[SEMI_BLKSIZE];187ctLen = W_INV(ct, ctLen, ivOut, embeddedCipher);188189// check against icv and fail if not match190if (!MessageDigest.isEqual(ivOut, this.iv)) {191throw new IllegalBlockSizeException("Integrity check failed");192}193return ctLen;194}195}196197198