src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java
changeset 51052 080776992b29
parent 49789 27b359322b1e
child 53721 f35a8aaabcb9
equal deleted inserted replaced
51051:4e98b465d706 51052:080776992b29
     1 /*
     1 /*
     2  * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    28 import java.util.Arrays;
    28 import java.util.Arrays;
    29 import java.io.*;
    29 import java.io.*;
    30 import java.security.*;
    30 import java.security.*;
    31 import javax.crypto.*;
    31 import javax.crypto.*;
    32 import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;
    32 import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;
       
    33 import sun.security.util.ArrayUtil;
       
    34 
    33 
    35 
    34 /**
    36 /**
    35  * This class represents ciphers in GaloisCounter (GCM) mode.
    37  * This class represents ciphers in GaloisCounter (GCM) mode.
    36  *
    38  *
    37  * <p>This mode currently should only be used w/ AES cipher.
    39  * <p>This mode currently should only be used w/ AES cipher.
   404 
   406 
   405 
   407 
   406     /**
   408     /**
   407      * Performs encryption operation.
   409      * Performs encryption operation.
   408      *
   410      *
   409      * <p>The input plain text <code>in</code>, starting at <code>inOff</code>
   411      * <p>The input plain text <code>in</code>, starting at <code>inOfs</code>
   410      * and ending at <code>(inOff + len - 1)</code>, is encrypted. The result
   412      * and ending at <code>(inOfs + len - 1)</code>, is encrypted. The result
   411      * is stored in <code>out</code>, starting at <code>outOfs</code>.
   413      * is stored in <code>out</code>, starting at <code>outOfs</code>.
   412      *
   414      *
   413      * @param in the buffer with the input data to be encrypted
   415      * @param in the buffer with the input data to be encrypted
   414      * @param inOfs the offset in <code>in</code>
   416      * @param inOfs the offset in <code>in</code>
   415      * @param len the length of the input data
   417      * @param len the length of the input data
   418      * @exception ProviderException if <code>len</code> is not
   420      * @exception ProviderException if <code>len</code> is not
   419      * a multiple of the block size
   421      * a multiple of the block size
   420      * @return the number of bytes placed into the <code>out</code> buffer
   422      * @return the number of bytes placed into the <code>out</code> buffer
   421      */
   423      */
   422     int encrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
   424     int encrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
   423         if ((len % blockSize) != 0) {
   425         ArrayUtil.blockSizeCheck(len, blockSize);
   424              throw new ProviderException("Internal error in input buffering");
       
   425         }
       
   426 
   426 
   427         checkDataLength(processed, len);
   427         checkDataLength(processed, len);
   428 
   428 
   429         processAAD();
   429         processAAD();
       
   430 
   430         if (len > 0) {
   431         if (len > 0) {
       
   432             ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
       
   433             ArrayUtil.nullAndBoundsCheck(out, outOfs, len);
       
   434 
   431             gctrPAndC.update(in, inOfs, len, out, outOfs);
   435             gctrPAndC.update(in, inOfs, len, out, outOfs);
   432             processed += len;
   436             processed += len;
   433             ghashAllToS.update(out, outOfs, len);
   437             ghashAllToS.update(out, outOfs, len);
   434         }
   438         }
       
   439 
   435         return len;
   440         return len;
   436     }
   441     }
   437 
   442 
   438     /**
   443     /**
   439      * Performs encryption operation for the last time.
   444      * Performs encryption operation for the last time.
   449         throws IllegalBlockSizeException, ShortBufferException {
   454         throws IllegalBlockSizeException, ShortBufferException {
   450         if (len > MAX_BUF_SIZE - tagLenBytes) {
   455         if (len > MAX_BUF_SIZE - tagLenBytes) {
   451             throw new ShortBufferException
   456             throw new ShortBufferException
   452                 ("Can't fit both data and tag into one buffer");
   457                 ("Can't fit both data and tag into one buffer");
   453         }
   458         }
   454         if (out.length - outOfs < (len + tagLenBytes)) {
   459         try {
       
   460             ArrayUtil.nullAndBoundsCheck(out, outOfs,
       
   461                 (len + tagLenBytes));
       
   462         } catch (ArrayIndexOutOfBoundsException aiobe) {
   455             throw new ShortBufferException("Output buffer too small");
   463             throw new ShortBufferException("Output buffer too small");
   456         }
   464         }
   457 
   465 
   458         checkDataLength(processed, len);
   466         checkDataLength(processed, len);
   459 
   467 
   460         processAAD();
   468         processAAD();
   461         if (len > 0) {
   469         if (len > 0) {
       
   470             ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
       
   471 
   462             doLastBlock(in, inOfs, len, out, outOfs, true);
   472             doLastBlock(in, inOfs, len, out, outOfs, true);
   463         }
   473         }
   464 
   474 
   465         byte[] lengthBlock =
   475         byte[] lengthBlock =
   466             getLengthBlock(sizeOfAAD, processed);
   476             getLengthBlock(sizeOfAAD, processed);
   490      * @exception ProviderException if <code>len</code> is not
   500      * @exception ProviderException if <code>len</code> is not
   491      * a multiple of the block size
   501      * a multiple of the block size
   492      * @return the number of bytes placed into the <code>out</code> buffer
   502      * @return the number of bytes placed into the <code>out</code> buffer
   493      */
   503      */
   494     int decrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
   504     int decrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
   495         if ((len % blockSize) != 0) {
   505         ArrayUtil.blockSizeCheck(len, blockSize);
   496              throw new ProviderException("Internal error in input buffering");
       
   497         }
       
   498 
   506 
   499         checkDataLength(ibuffer.size(), len);
   507         checkDataLength(ibuffer.size(), len);
   500 
   508 
   501         processAAD();
   509         processAAD();
   502 
   510 
   503         if (len > 0) {
   511         if (len > 0) {
   504             // store internally until decryptFinal is called because
   512             // store internally until decryptFinal is called because
   505             // spec mentioned that only return recovered data after tag
   513             // spec mentioned that only return recovered data after tag
   506             // is successfully verified
   514             // is successfully verified
       
   515             ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
   507             ibuffer.write(in, inOfs, len);
   516             ibuffer.write(in, inOfs, len);
   508         }
   517         }
   509         return 0;
   518         return 0;
   510     }
   519     }
   511 
   520 
   530         throws IllegalBlockSizeException, AEADBadTagException,
   539         throws IllegalBlockSizeException, AEADBadTagException,
   531         ShortBufferException {
   540         ShortBufferException {
   532         if (len < tagLenBytes) {
   541         if (len < tagLenBytes) {
   533             throw new AEADBadTagException("Input too short - need tag");
   542             throw new AEADBadTagException("Input too short - need tag");
   534         }
   543         }
       
   544 
   535         // do this check here can also catch the potential integer overflow
   545         // do this check here can also catch the potential integer overflow
   536         // scenario for the subsequent output buffer capacity check.
   546         // scenario for the subsequent output buffer capacity check.
   537         checkDataLength(ibuffer.size(), (len - tagLenBytes));
   547         checkDataLength(ibuffer.size(), (len - tagLenBytes));
   538 
   548 
   539         if (out.length - outOfs < ((ibuffer.size() + len) - tagLenBytes)) {
   549         try {
       
   550             ArrayUtil.nullAndBoundsCheck(out, outOfs,
       
   551                 (ibuffer.size() + len) - tagLenBytes);
       
   552         } catch (ArrayIndexOutOfBoundsException aiobe) {
   540             throw new ShortBufferException("Output buffer too small");
   553             throw new ShortBufferException("Output buffer too small");
   541         }
   554         }
   542 
   555 
   543         processAAD();
   556         processAAD();
       
   557 
       
   558         ArrayUtil.nullAndBoundsCheck(in, inOfs, len);
   544 
   559 
   545         // get the trailing tag bytes from 'in'
   560         // get the trailing tag bytes from 'in'
   546         byte[] tag = new byte[tagLenBytes];
   561         byte[] tag = new byte[tagLenBytes];
   547         System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes);
   562         System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes);
   548         len -= tagLenBytes;
   563         len -= tagLenBytes;
   549 
   564 
   550         if (len != 0) {
   565         if (len > 0) {
   551             ibuffer.write(in, inOfs, len);
   566             ibuffer.write(in, inOfs, len);
   552         }
   567         }
   553 
   568 
   554         // refresh 'in' to all buffered-up bytes
   569         // refresh 'in' to all buffered-up bytes
   555         in = ibuffer.toByteArray();
   570         in = ibuffer.toByteArray();