jdk/src/share/classes/sun/security/ssl/CipherBox.java
changeset 16067 36055e4b5305
parent 16045 9d08c3b9a6a0
child 16126 aad71cf676d7
equal deleted inserted replaced
16066:b9fb0d9c58ec 16067:36055e4b5305
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 2011, 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
    27 package sun.security.ssl;
    27 package sun.security.ssl;
    28 
    28 
    29 import java.io.ByteArrayInputStream;
    29 import java.io.ByteArrayInputStream;
    30 import java.io.IOException;
    30 import java.io.IOException;
    31 import java.util.Hashtable;
    31 import java.util.Hashtable;
    32 import java.util.Arrays;
       
    33 
    32 
    34 import java.security.*;
    33 import java.security.*;
    35 import javax.crypto.*;
    34 import javax.crypto.*;
    36 import javax.crypto.spec.IvParameterSpec;
    35 import javax.crypto.spec.IvParameterSpec;
    37 import javax.crypto.spec.GCMParameterSpec;
       
    38 
    36 
    39 import java.nio.*;
    37 import java.nio.*;
    40 
    38 
    41 import sun.security.ssl.CipherSuite.*;
    39 import sun.security.ssl.CipherSuite.*;
    42 import static sun.security.ssl.CipherSuite.*;
    40 import static sun.security.ssl.CipherSuite.*;
    43 import static sun.security.ssl.CipherSuite.CipherType.*;
       
    44 
    41 
    45 import sun.misc.HexDumpEncoder;
    42 import sun.misc.HexDumpEncoder;
    46 
    43 
    47 
    44 
    48 /**
    45 /**
   103 
   100 
   104     // cipher object
   101     // cipher object
   105     private final Cipher cipher;
   102     private final Cipher cipher;
   106 
   103 
   107     /**
   104     /**
       
   105      * Cipher blocksize, 0 for stream ciphers
       
   106      */
       
   107     private int blockSize;
       
   108 
       
   109     /**
   108      * secure random
   110      * secure random
   109      */
   111      */
   110     private SecureRandom random;
   112     private SecureRandom random;
   111 
   113 
   112     /**
   114     /**
   113      * fixed IV, the implicit nonce of AEAD cipher suite, only apply to
   115      * Is the cipher of CBC mode?
   114      * AEAD cipher suites
   116      */
   115      */
   117     private final boolean isCBCMode;
   116     private final byte[] fixedIv;
       
   117 
       
   118     /**
       
   119      * the key, reserved only for AEAD cipher initialization
       
   120      */
       
   121     private final Key key;
       
   122 
       
   123     /**
       
   124      * the operation mode, reserved for AEAD cipher initialization
       
   125      */
       
   126     private final int mode;
       
   127 
       
   128     /**
       
   129      * the authentication tag size, only apply to AEAD cipher suites
       
   130      */
       
   131     private final int tagSize;
       
   132 
       
   133     /**
       
   134      * the record IV length, only apply to AEAD cipher suites
       
   135      */
       
   136     private final int recordIvSize;
       
   137 
       
   138     /**
       
   139      * cipher type
       
   140      */
       
   141     private final CipherType cipherType;
       
   142 
   118 
   143     /**
   119     /**
   144      * Fixed masks of various block size, as the initial decryption IVs
   120      * Fixed masks of various block size, as the initial decryption IVs
   145      * for TLS 1.1 or later.
   121      * for TLS 1.1 or later.
   146      *
   122      *
   154      * NULL cipherbox. Identity operation, no encryption.
   130      * NULL cipherbox. Identity operation, no encryption.
   155      */
   131      */
   156     private CipherBox() {
   132     private CipherBox() {
   157         this.protocolVersion = ProtocolVersion.DEFAULT;
   133         this.protocolVersion = ProtocolVersion.DEFAULT;
   158         this.cipher = null;
   134         this.cipher = null;
   159         this.cipherType = STREAM_CIPHER;
   135         this.isCBCMode = false;
   160         this.fixedIv = new byte[0];
       
   161         this.key = null;
       
   162         this.mode = Cipher.ENCRYPT_MODE;    // choose at random
       
   163         this.random = null;
       
   164         this.tagSize = 0;
       
   165         this.recordIvSize = 0;
       
   166     }
   136     }
   167 
   137 
   168     /**
   138     /**
   169      * Construct a new CipherBox using the cipher transformation.
   139      * Construct a new CipherBox using the cipher transformation.
   170      *
   140      *
   175             SecretKey key, IvParameterSpec iv, SecureRandom random,
   145             SecretKey key, IvParameterSpec iv, SecureRandom random,
   176             boolean encrypt) throws NoSuchAlgorithmException {
   146             boolean encrypt) throws NoSuchAlgorithmException {
   177         try {
   147         try {
   178             this.protocolVersion = protocolVersion;
   148             this.protocolVersion = protocolVersion;
   179             this.cipher = JsseJce.getCipher(bulkCipher.transformation);
   149             this.cipher = JsseJce.getCipher(bulkCipher.transformation);
   180             this.mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
   150             int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
   181 
   151 
   182             if (random == null) {
   152             if (random == null) {
   183                 random = JsseJce.getSecureRandom();
   153                 random = JsseJce.getSecureRandom();
   184             }
   154             }
   185             this.random = random;
   155             this.random = random;
   186             this.cipherType = bulkCipher.cipherType;
   156             this.isCBCMode = bulkCipher.isCBCMode;
   187 
   157 
   188             /*
   158             /*
   189              * RFC 4346 recommends two algorithms used to generated the
   159              * RFC 4346 recommends two algorithms used to generated the
   190              * per-record IV. The implementation uses the algorithm (2)(b),
   160              * per-record IV. The implementation uses the algorithm (2)(b),
   191              * as described at section 6.2.3.2 of RFC 4346.
   161              * as described at section 6.2.3.2 of RFC 4346.
   199                     mode == Cipher.DECRYPT_MODE &&
   169                     mode == Cipher.DECRYPT_MODE &&
   200                     protocolVersion.v >= ProtocolVersion.TLS11.v) {
   170                     protocolVersion.v >= ProtocolVersion.TLS11.v) {
   201                 iv = getFixedMask(bulkCipher.ivSize);
   171                 iv = getFixedMask(bulkCipher.ivSize);
   202             }
   172             }
   203 
   173 
   204             if (cipherType == AEAD_CIPHER) {
   174             cipher.init(mode, key, iv, random);
   205                 // AEAD must completely initialize the cipher for each packet,
   175 
   206                 // and so we save initialization parameters for packet
   176             // Do not call getBlockSize until after init()
   207                 // processing time.
   177             // otherwise we would disrupt JCE delayed provider selection
   208 
   178             blockSize = cipher.getBlockSize();
   209                 // Set the tag size for AEAD cipher
   179             // some providers implement getBlockSize() incorrectly
   210                 tagSize = bulkCipher.tagSize;
   180             if (blockSize == 1) {
   211 
   181                 blockSize = 0;
   212                 // Reserve the key for AEAD cipher initialization
       
   213                 this.key = key;
       
   214 
       
   215                 fixedIv = iv.getIV();
       
   216                 if (fixedIv == null ||
       
   217                         fixedIv.length != bulkCipher.fixedIvSize) {
       
   218                     throw new RuntimeException("Improper fixed IV for AEAD");
       
   219                 }
       
   220 
       
   221                 // Set the record IV length for AEAD cipher
       
   222                 recordIvSize = bulkCipher.ivSize - bulkCipher.fixedIvSize;
       
   223 
       
   224                 // DON'T initialize the cipher for AEAD!
       
   225             } else {
       
   226                 // CBC only requires one initialization during its lifetime
       
   227                 // (future packets/IVs set the proper CBC state), so we can
       
   228                 // initialize now.
       
   229 
       
   230                 // Zeroize the variables that only apply to AEAD cipher
       
   231                 this.tagSize = 0;
       
   232                 this.fixedIv = new byte[0];
       
   233                 this.recordIvSize = 0;
       
   234                 this.key = null;
       
   235 
       
   236                 // Initialize the cipher
       
   237                 cipher.init(mode, key, iv, random);
       
   238             }
   182             }
   239         } catch (NoSuchAlgorithmException e) {
   183         } catch (NoSuchAlgorithmException e) {
   240             throw e;
   184             throw e;
   241         } catch (Exception e) {
   185         } catch (Exception e) {
   242             throw new NoSuchAlgorithmException
   186             throw new NoSuchAlgorithmException
   289         if (cipher == null) {
   233         if (cipher == null) {
   290             return len;
   234             return len;
   291         }
   235         }
   292 
   236 
   293         try {
   237         try {
   294             int blockSize = cipher.getBlockSize();
   238             if (blockSize != 0) {
   295             if (cipherType == BLOCK_CIPHER) {
   239                 // TLSv1.1 needs a IV block
       
   240                 if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
       
   241                     // generate a random number
       
   242                     byte[] prefix = new byte[blockSize];
       
   243                     random.nextBytes(prefix);
       
   244 
       
   245                     // move forward the plaintext
       
   246                     System.arraycopy(buf, offset,
       
   247                                      buf, offset + prefix.length, len);
       
   248 
       
   249                     // prefix the plaintext
       
   250                     System.arraycopy(prefix, 0,
       
   251                                      buf, offset, prefix.length);
       
   252 
       
   253                     len += prefix.length;
       
   254                 }
       
   255 
   296                 len = addPadding(buf, offset, len, blockSize);
   256                 len = addPadding(buf, offset, len, blockSize);
   297             }
   257             }
   298 
       
   299             if (debug != null && Debug.isOn("plaintext")) {
   258             if (debug != null && Debug.isOn("plaintext")) {
   300                 try {
   259                 try {
   301                     HexDumpEncoder hd = new HexDumpEncoder();
   260                     HexDumpEncoder hd = new HexDumpEncoder();
   302 
   261 
   303                     System.out.println(
   262                     System.out.println(
   306                     hd.encodeBuffer(
   265                     hd.encodeBuffer(
   307                         new ByteArrayInputStream(buf, offset, len),
   266                         new ByteArrayInputStream(buf, offset, len),
   308                         System.out);
   267                         System.out);
   309                 } catch (IOException e) { }
   268                 } catch (IOException e) { }
   310             }
   269             }
   311 
   270             int newLen = cipher.update(buf, offset, len, buf, offset);
   312 
   271             if (newLen != len) {
   313             if (cipherType == AEAD_CIPHER) {
   272                 // catch BouncyCastle buffering error
   314                 try {
   273                 throw new RuntimeException("Cipher buffering error " +
   315                     return cipher.doFinal(buf, offset, len, buf, offset);
   274                     "in JCE provider " + cipher.getProvider().getName());
   316                 } catch (IllegalBlockSizeException | BadPaddingException ibe) {
   275             }
   317                     // unlikely to happen
   276             return newLen;
   318                     throw new RuntimeException(
       
   319                         "Cipher error in AEAD mode in JCE provider " +
       
   320                         cipher.getProvider().getName(), ibe);
       
   321                 }
       
   322             } else {
       
   323                 int newLen = cipher.update(buf, offset, len, buf, offset);
       
   324                 if (newLen != len) {
       
   325                     // catch BouncyCastle buffering error
       
   326                     throw new RuntimeException("Cipher buffering error " +
       
   327                         "in JCE provider " + cipher.getProvider().getName());
       
   328                 }
       
   329                 return newLen;
       
   330             }
       
   331         } catch (ShortBufferException e) {
   277         } catch (ShortBufferException e) {
   332             // unlikely to happen, we should have enough buffer space here
       
   333             throw new ArrayIndexOutOfBoundsException(e.toString());
   278             throw new ArrayIndexOutOfBoundsException(e.toString());
   334         }
   279         }
   335     }
   280     }
   336 
   281 
   337     /*
   282     /*
   341      * The byte buffers position and limit initially define the amount
   286      * The byte buffers position and limit initially define the amount
   342      * to encrypt.  On return, the position and limit are
   287      * to encrypt.  On return, the position and limit are
   343      * set to last position padded/encrypted.  The limit may have changed
   288      * set to last position padded/encrypted.  The limit may have changed
   344      * because of the added padding bytes.
   289      * because of the added padding bytes.
   345      */
   290      */
   346     int encrypt(ByteBuffer bb, int outLimit) {
   291     int encrypt(ByteBuffer bb) {
   347 
   292 
   348         int len = bb.remaining();
   293         int len = bb.remaining();
   349 
   294 
   350         if (cipher == null) {
   295         if (cipher == null) {
   351             bb.position(bb.limit());
   296             bb.position(bb.limit());
   352             return len;
   297             return len;
   353         }
   298         }
   354 
   299 
   355         int pos = bb.position();
   300         try {
   356 
   301             int pos = bb.position();
   357         int blockSize = cipher.getBlockSize();
   302 
   358         if (cipherType == BLOCK_CIPHER) {
   303             if (blockSize != 0) {
   359             // addPadding adjusts pos/limit
   304                 // TLSv1.1 needs a IV block
   360             len = addPadding(bb, blockSize);
   305                 if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
   361             bb.position(pos);
   306                     // generate a random number
   362         }
   307                     byte[] prefix = new byte[blockSize];
   363 
   308                     random.nextBytes(prefix);
   364         if (debug != null && Debug.isOn("plaintext")) {
   309 
   365             try {
   310                     // move forward the plaintext
   366                 HexDumpEncoder hd = new HexDumpEncoder();
   311                     byte[] buf = null;
   367 
   312                     int limit = bb.limit();
   368                 System.out.println(
   313                     if (bb.hasArray()) {
   369                     "Padded plaintext before ENCRYPTION:  len = "
   314                         int arrayOffset = bb.arrayOffset();
   370                     + len);
   315                         buf = bb.array();
   371                 hd.encodeBuffer(bb.duplicate(), System.out);
   316                         System.arraycopy(buf, arrayOffset + pos,
   372 
   317                             buf, arrayOffset + pos + prefix.length,
   373             } catch (IOException e) { }
   318                             limit - pos);
   374         }
   319                         bb.limit(limit + prefix.length);
   375 
   320                     } else {
   376         /*
   321                         buf = new byte[limit - pos];
   377          * Encrypt "in-place".  This does not add its own padding.
   322                         bb.get(buf, 0, limit - pos);
   378          */
   323                         bb.position(pos + prefix.length);
   379         ByteBuffer dup = bb.duplicate();
   324                         bb.limit(limit + prefix.length);
   380         if (cipherType == AEAD_CIPHER) {
   325                         bb.put(buf);
   381             try {
       
   382                 int outputSize = cipher.getOutputSize(dup.remaining());
       
   383                 if (outputSize > bb.remaining()) {
       
   384                     // need to expand the limit of the output buffer for
       
   385                     // the authentication tag.
       
   386                     //
       
   387                     // DON'T worry about the buffer's capacity, we have
       
   388                     // reserved space for the authentication tag.
       
   389                     if (outLimit < pos + outputSize) {
       
   390                         // unlikely to happen
       
   391                         throw new ShortBufferException(
       
   392                                     "need more space in output buffer");
       
   393                     }
   326                     }
   394                     bb.limit(pos + outputSize);
   327                     bb.position(pos);
       
   328 
       
   329                     // prefix the plaintext
       
   330                     bb.put(prefix);
       
   331                     bb.position(pos);
   395                 }
   332                 }
   396                 int newLen = cipher.doFinal(dup, bb);
   333 
   397                 if (newLen != outputSize) {
   334                 // addPadding adjusts pos/limit
   398                     throw new RuntimeException(
   335                 len = addPadding(bb, blockSize);
   399                             "Cipher buffering error in JCE provider " +
   336                 bb.position(pos);
   400                             cipher.getProvider().getName());
   337             }
   401                 }
   338             if (debug != null && Debug.isOn("plaintext")) {
   402                 return newLen;
   339                 try {
   403             } catch (IllegalBlockSizeException |
   340                     HexDumpEncoder hd = new HexDumpEncoder();
   404                            BadPaddingException | ShortBufferException ibse) {
   341 
   405                 // unlikely to happen
   342                     System.out.println(
   406                 throw new RuntimeException(
   343                         "Padded plaintext before ENCRYPTION:  len = "
   407                         "Cipher error in AEAD mode in JCE provider " +
   344                         + len);
   408                         cipher.getProvider().getName(), ibse);
   345                     hd.encodeBuffer(bb, System.out);
   409             }
   346 
   410         } else {
   347                 } catch (IOException e) { }
   411             int newLen;
   348                 /*
   412             try {
   349                  * reset back to beginning
   413                 newLen = cipher.update(dup, bb);
   350                  */
   414             } catch (ShortBufferException sbe) {
   351                 bb.position(pos);
   415                 // unlikely to happen
   352             }
   416                 throw new RuntimeException("Cipher buffering error " +
   353 
   417                     "in JCE provider " + cipher.getProvider().getName());
   354             /*
   418             }
   355              * Encrypt "in-place".  This does not add its own padding.
       
   356              */
       
   357             ByteBuffer dup = bb.duplicate();
       
   358             int newLen = cipher.update(dup, bb);
   419 
   359 
   420             if (bb.position() != dup.position()) {
   360             if (bb.position() != dup.position()) {
   421                 throw new RuntimeException("bytebuffer padding error");
   361                 throw new RuntimeException("bytebuffer padding error");
   422             }
   362             }
   423 
   363 
   425                 // catch BouncyCastle buffering error
   365                 // catch BouncyCastle buffering error
   426                 throw new RuntimeException("Cipher buffering error " +
   366                 throw new RuntimeException("Cipher buffering error " +
   427                     "in JCE provider " + cipher.getProvider().getName());
   367                     "in JCE provider " + cipher.getProvider().getName());
   428             }
   368             }
   429             return newLen;
   369             return newLen;
       
   370         } catch (ShortBufferException e) {
       
   371             RuntimeException exc = new RuntimeException(e.toString());
       
   372             exc.initCause(e);
       
   373             throw exc;
   430         }
   374         }
   431     }
   375     }
   432 
   376 
   433 
   377 
   434     /*
   378     /*
   452         if (cipher == null) {
   396         if (cipher == null) {
   453             return len;
   397             return len;
   454         }
   398         }
   455 
   399 
   456         try {
   400         try {
   457             int newLen;
   401             int newLen = cipher.update(buf, offset, len, buf, offset);
   458             if (cipherType == AEAD_CIPHER) {
   402             if (newLen != len) {
   459                 try {
   403                 // catch BouncyCastle buffering error
   460                     newLen = cipher.doFinal(buf, offset, len, buf, offset);
   404                 throw new RuntimeException("Cipher buffering error " +
   461                 } catch (IllegalBlockSizeException ibse) {
   405                     "in JCE provider " + cipher.getProvider().getName());
   462                     // unlikely to happen
       
   463                     throw new RuntimeException(
       
   464                         "Cipher error in AEAD mode in JCE provider " +
       
   465                         cipher.getProvider().getName(), ibse);
       
   466                 }
       
   467             } else {
       
   468                 newLen = cipher.update(buf, offset, len, buf, offset);
       
   469                 if (newLen != len) {
       
   470                     // catch BouncyCastle buffering error
       
   471                     throw new RuntimeException("Cipher buffering error " +
       
   472                         "in JCE provider " + cipher.getProvider().getName());
       
   473                 }
       
   474             }
   406             }
   475             if (debug != null && Debug.isOn("plaintext")) {
   407             if (debug != null && Debug.isOn("plaintext")) {
   476                 try {
   408                 try {
   477                     HexDumpEncoder hd = new HexDumpEncoder();
   409                     HexDumpEncoder hd = new HexDumpEncoder();
   478 
   410 
   482                     hd.encodeBuffer(
   414                     hd.encodeBuffer(
   483                         new ByteArrayInputStream(buf, offset, newLen),
   415                         new ByteArrayInputStream(buf, offset, newLen),
   484                         System.out);
   416                         System.out);
   485                 } catch (IOException e) { }
   417                 } catch (IOException e) { }
   486             }
   418             }
   487 
   419             if (blockSize != 0) {
   488             if (cipherType == BLOCK_CIPHER) {
       
   489                 int blockSize = cipher.getBlockSize();
       
   490                 newLen = removePadding(buf, offset, newLen,
   420                 newLen = removePadding(buf, offset, newLen,
   491                              blockSize, protocolVersion);
   421                              blockSize, protocolVersion);
   492 
   422 
   493                 if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
   423                 if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
   494                     if (newLen < blockSize) {
   424                     if (newLen < blockSize) {
   495                         throw new BadPaddingException("invalid explicit IV");
   425                         throw new BadPaddingException("invalid explicit IV");
   496                     }
   426                     }
       
   427 
       
   428                     // discards the first cipher block, the IV component.
       
   429                     System.arraycopy(buf, offset + blockSize,
       
   430                                      buf, offset, newLen - blockSize);
       
   431 
       
   432                     newLen -= blockSize;
   497                 }
   433                 }
   498             }
   434             }
   499             return newLen;
   435             return newLen;
   500         } catch (ShortBufferException e) {
   436         } catch (ShortBufferException e) {
   501             // unlikely to happen, we should have enough buffer space here
       
   502             throw new ArrayIndexOutOfBoundsException(e.toString());
   437             throw new ArrayIndexOutOfBoundsException(e.toString());
   503         }
   438         }
   504     }
   439     }
   505 
   440 
   506 
   441 
   526             /*
   461             /*
   527              * Decrypt "in-place".
   462              * Decrypt "in-place".
   528              */
   463              */
   529             int pos = bb.position();
   464             int pos = bb.position();
   530             ByteBuffer dup = bb.duplicate();
   465             ByteBuffer dup = bb.duplicate();
   531             int newLen;
   466             int newLen = cipher.update(dup, bb);
   532             if (cipherType == AEAD_CIPHER) {
   467             if (newLen != len) {
   533                 try {
   468                 // catch BouncyCastle buffering error
   534                     newLen = cipher.doFinal(dup, bb);
   469                 throw new RuntimeException("Cipher buffering error " +
   535                 } catch (IllegalBlockSizeException ibse) {
   470                     "in JCE provider " + cipher.getProvider().getName());
   536                     // unlikely to happen
   471             }
   537                     throw new RuntimeException(
       
   538                         "Cipher error in AEAD mode \"" + ibse.getMessage() +
       
   539                         " \"in JCE provider " + cipher.getProvider().getName());
       
   540                 }
       
   541             } else {
       
   542                 newLen = cipher.update(dup, bb);
       
   543                 if (newLen != len) {
       
   544                     // catch BouncyCastle buffering error
       
   545                     throw new RuntimeException("Cipher buffering error " +
       
   546                         "in JCE provider " + cipher.getProvider().getName());
       
   547                 }
       
   548             }
       
   549 
       
   550             // reset the limit to the end of the decryted data
       
   551             bb.limit(pos + newLen);
       
   552 
   472 
   553             if (debug != null && Debug.isOn("plaintext")) {
   473             if (debug != null && Debug.isOn("plaintext")) {
       
   474                 bb.position(pos);
   554                 try {
   475                 try {
   555                     HexDumpEncoder hd = new HexDumpEncoder();
   476                     HexDumpEncoder hd = new HexDumpEncoder();
   556 
   477 
   557                     System.out.println(
   478                     System.out.println(
   558                         "Padded plaintext after DECRYPTION:  len = "
   479                         "Padded plaintext after DECRYPTION:  len = "
   559                         + newLen);
   480                         + newLen);
   560 
   481 
   561                     hd.encodeBuffer(
   482                     hd.encodeBuffer(bb, System.out);
   562                         (ByteBuffer)bb.duplicate().position(pos), System.out);
       
   563                 } catch (IOException e) { }
   483                 } catch (IOException e) { }
   564             }
   484             }
   565 
   485 
   566             /*
   486             /*
   567              * Remove the block padding.
   487              * Remove the block padding.
   568              */
   488              */
   569             if (cipherType == BLOCK_CIPHER) {
   489             if (blockSize != 0) {
   570                 int blockSize = cipher.getBlockSize();
       
   571                 bb.position(pos);
   490                 bb.position(pos);
   572                 newLen = removePadding(bb, blockSize, protocolVersion);
   491                 newLen = removePadding(bb, blockSize, protocolVersion);
   573 
   492 
   574                 // check the explicit IV of TLS v1.1 or later
       
   575                 if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
   493                 if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
   576                     if (newLen < blockSize) {
   494                     if (newLen < blockSize) {
   577                         throw new BadPaddingException("invalid explicit IV");
   495                         throw new BadPaddingException("invalid explicit IV");
   578                     }
   496                     }
   579 
   497 
       
   498                     // discards the first cipher block, the IV component.
       
   499                     byte[] buf = null;
       
   500                     int limit = bb.limit();
       
   501                     if (bb.hasArray()) {
       
   502                         int arrayOffset = bb.arrayOffset();
       
   503                         buf = bb.array();
       
   504                         System.arraycopy(buf, arrayOffset + pos + blockSize,
       
   505                             buf, arrayOffset + pos, limit - pos - blockSize);
       
   506                         bb.limit(limit - blockSize);
       
   507                     } else {
       
   508                         buf = new byte[limit - pos - blockSize];
       
   509                         bb.position(pos + blockSize);
       
   510                         bb.get(buf);
       
   511                         bb.position(pos);
       
   512                         bb.put(buf);
       
   513                         bb.limit(limit - blockSize);
       
   514                     }
       
   515 
   580                     // reset the position to the end of the decrypted data
   516                     // reset the position to the end of the decrypted data
   581                     bb.position(bb.limit());
   517                     limit = bb.limit();
       
   518                     bb.position(limit);
   582                 }
   519                 }
   583             }
   520             }
   584             return newLen;
   521             return newLen;
   585         } catch (ShortBufferException e) {
   522         } catch (ShortBufferException e) {
   586             // unlikely to happen, we should have enough buffer space here
   523             RuntimeException exc = new RuntimeException(e.toString());
   587             throw new ArrayIndexOutOfBoundsException(e.toString());
   524             exc.initCause(e);
       
   525             throw exc;
   588         }
   526         }
   589     }
   527     }
   590 
   528 
   591     private static int addPadding(byte[] buf, int offset, int len,
   529     private static int addPadding(byte[] buf, int offset, int len,
   592             int blockSize) {
   530             int blockSize) {
   755         try {
   693         try {
   756             if (cipher != null) {
   694             if (cipher != null) {
   757                 // ignore return value.
   695                 // ignore return value.
   758                 cipher.doFinal();
   696                 cipher.doFinal();
   759             }
   697             }
   760         } catch (Exception e) {
   698         } catch (GeneralSecurityException e) {
   761             // swallow all types of exceptions.
   699             // swallow for now.
   762         }
   700         }
   763     }
   701     }
   764 
   702 
   765     /*
   703     /*
   766      * Does the cipher use CBC mode?
   704      * Does the cipher use CBC mode?
   767      *
   705      *
   768      * @return true if the cipher use CBC mode, false otherwise.
   706      * @return true if the cipher use CBC mode, false otherwise.
   769      */
   707      */
   770     boolean isCBCMode() {
   708     boolean isCBCMode() {
   771         return cipherType == BLOCK_CIPHER;
   709         return isCBCMode;
   772     }
       
   773 
       
   774     /*
       
   775      * Does the cipher use AEAD mode?
       
   776      *
       
   777      * @return true if the cipher use AEAD mode, false otherwise.
       
   778      */
       
   779     boolean isAEADMode() {
       
   780         return cipherType == AEAD_CIPHER;
       
   781     }
       
   782 
       
   783     /*
       
   784      * Is the cipher null?
       
   785      *
       
   786      * @return true if the cipher is null, false otherwise.
       
   787      */
       
   788     boolean isNullCipher() {
       
   789         return cipher == null;
       
   790     }
       
   791 
       
   792     /*
       
   793      * Gets the explicit nonce/IV size of the cipher.
       
   794      *
       
   795      * The returned value is the SecurityParameters.record_iv_length in
       
   796      * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
       
   797      * size of explicit nonce for AEAD mode.
       
   798      *
       
   799      * @return the explicit nonce size of the cipher.
       
   800      */
       
   801     int getExplicitNonceSize() {
       
   802         switch (cipherType) {
       
   803             case BLOCK_CIPHER:
       
   804                 // For block ciphers, the explicit IV length is of length
       
   805                 // SecurityParameters.record_iv_length, which is equal to
       
   806                 // the SecurityParameters.block_size.
       
   807                 if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
       
   808                     return cipher.getBlockSize();
       
   809                 }
       
   810                 break;
       
   811             case AEAD_CIPHER:
       
   812                 return recordIvSize;
       
   813                         // It is also the length of sequence number, which is
       
   814                         // used as the nonce_explicit for AEAD cipher suites.
       
   815         }
       
   816 
       
   817         return 0;
       
   818     }
       
   819 
       
   820     /*
       
   821      * Applies the explicit nonce/IV to this cipher. This method is used to
       
   822      * decrypt an SSL/TLS input record.
       
   823      *
       
   824      * The returned value is the SecurityParameters.record_iv_length in
       
   825      * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
       
   826      * size of explicit nonce for AEAD mode.
       
   827      *
       
   828      * @param  authenticator the authenticator to get the additional
       
   829      *         authentication data
       
   830      * @param  contentType the content type of the input record
       
   831      * @param  bb the byte buffer to get the explicit nonce from
       
   832      *
       
   833      * @return the explicit nonce size of the cipher.
       
   834      */
       
   835     int applyExplicitNonce(Authenticator authenticator, byte contentType,
       
   836             ByteBuffer bb) throws BadPaddingException {
       
   837         switch (cipherType) {
       
   838             case BLOCK_CIPHER:
       
   839                 // For block ciphers, the explicit IV length is of length
       
   840                 // SecurityParameters.record_iv_length, which is equal to
       
   841                 // the SecurityParameters.block_size.
       
   842                 if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
       
   843                     return cipher.getBlockSize();
       
   844                 }
       
   845                 break;
       
   846             case AEAD_CIPHER:
       
   847                 if (bb.remaining() < (recordIvSize + tagSize)) {
       
   848                     throw new BadPaddingException(
       
   849                                         "invalid AEAD cipher fragment");
       
   850                 }
       
   851 
       
   852                 // initialize the AEAD cipher for the unique IV
       
   853                 byte[] iv = Arrays.copyOf(fixedIv,
       
   854                                     fixedIv.length + recordIvSize);
       
   855                 bb.get(iv, fixedIv.length, recordIvSize);
       
   856                 bb.position(bb.position() - recordIvSize);
       
   857                 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
       
   858                 try {
       
   859                     cipher.init(mode, key, spec, random);
       
   860                 } catch (InvalidKeyException |
       
   861                             InvalidAlgorithmParameterException ikae) {
       
   862                     // unlikely to happen
       
   863                     throw new RuntimeException(
       
   864                                 "invalid key or spec in GCM mode", ikae);
       
   865                 }
       
   866 
       
   867                 // update the additional authentication data
       
   868                 byte[] aad = authenticator.acquireAuthenticationBytes(
       
   869                         contentType, bb.remaining() - recordIvSize - tagSize);
       
   870                 cipher.updateAAD(aad);
       
   871 
       
   872                 return recordIvSize;
       
   873                         // It is also the length of sequence number, which is
       
   874                         // used as the nonce_explicit for AEAD cipher suites.
       
   875         }
       
   876 
       
   877        return 0;
       
   878     }
       
   879 
       
   880     /*
       
   881      * Applies the explicit nonce/IV to this cipher. This method is used to
       
   882      * decrypt an SSL/TLS input record.
       
   883      *
       
   884      * The returned value is the SecurityParameters.record_iv_length in
       
   885      * RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
       
   886      * size of explicit nonce for AEAD mode.
       
   887      *
       
   888      * @param  authenticator the authenticator to get the additional
       
   889      *         authentication data
       
   890      * @param  contentType the content type of the input record
       
   891      * @param  buf the byte array to get the explicit nonce from
       
   892      * @param  offset the offset of the byte buffer
       
   893      * @param  cipheredLength the ciphered fragment length of the output
       
   894      *         record, it is the TLSCiphertext.length in RFC 4346/5246.
       
   895      *
       
   896      * @return the explicit nonce size of the cipher.
       
   897      */
       
   898     int applyExplicitNonce(Authenticator authenticator,
       
   899             byte contentType, byte[] buf, int offset,
       
   900             int cipheredLength) throws BadPaddingException {
       
   901 
       
   902         ByteBuffer bb = ByteBuffer.wrap(buf, offset, cipheredLength);
       
   903 
       
   904         return applyExplicitNonce(authenticator, contentType, bb);
       
   905     }
       
   906 
       
   907     /*
       
   908      * Creates the explicit nonce/IV to this cipher. This method is used to
       
   909      * encrypt an SSL/TLS output record.
       
   910      *
       
   911      * The size of the returned array is the SecurityParameters.record_iv_length
       
   912      * in RFC 4346/5246.  It is the size of explicit IV for CBC mode, and the
       
   913      * size of explicit nonce for AEAD mode.
       
   914      *
       
   915      * @param  authenticator the authenticator to get the additional
       
   916      *         authentication data
       
   917      * @param  contentType the content type of the input record
       
   918      * @param  fragmentLength the fragment length of the output record, it is
       
   919      *         the TLSCompressed.length in RFC 4346/5246.
       
   920      *
       
   921      * @return the explicit nonce of the cipher.
       
   922      */
       
   923     byte[] createExplicitNonce(Authenticator authenticator,
       
   924             byte contentType, int fragmentLength) {
       
   925 
       
   926         byte[] nonce = new byte[0];
       
   927         switch (cipherType) {
       
   928             case BLOCK_CIPHER:
       
   929                 if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
       
   930                     // For block ciphers, the explicit IV length is of length
       
   931                     // SecurityParameters.record_iv_length, which is equal to
       
   932                     // the SecurityParameters.block_size.
       
   933                     //
       
   934                     // Generate a random number as the explicit IV parameter.
       
   935                     nonce = new byte[cipher.getBlockSize()];
       
   936                     random.nextBytes(nonce);
       
   937                 }
       
   938                 break;
       
   939             case AEAD_CIPHER:
       
   940                 // To be unique and aware of overflow-wrap, sequence number
       
   941                 // is used as the nonce_explicit of AEAD cipher suites.
       
   942                 nonce = authenticator.sequenceNumber();
       
   943 
       
   944                 // initialize the AEAD cipher for the unique IV
       
   945                 byte[] iv = Arrays.copyOf(fixedIv,
       
   946                                             fixedIv.length + nonce.length);
       
   947                 System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length);
       
   948                 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
       
   949                 try {
       
   950                     cipher.init(mode, key, spec, random);
       
   951                 } catch (InvalidKeyException |
       
   952                             InvalidAlgorithmParameterException ikae) {
       
   953                     // unlikely to happen
       
   954                     throw new RuntimeException(
       
   955                                 "invalid key or spec in GCM mode", ikae);
       
   956                 }
       
   957 
       
   958                 // update the additional authentication data
       
   959                 byte[] aad = authenticator.acquireAuthenticationBytes(
       
   960                                                 contentType, fragmentLength);
       
   961                 cipher.updateAAD(aad);
       
   962                 break;
       
   963         }
       
   964 
       
   965         return nonce;
       
   966     }
       
   967 
       
   968     /*
       
   969      * Is this cipher available?
       
   970      *
       
   971      * This method can only be called by CipherSuite.BulkCipher.isAvailable()
       
   972      * to test the availability of a cipher suites.  Please DON'T use it in
       
   973      * other places, otherwise, the behavior may be unexpected because we may
       
   974      * initialize AEAD cipher improperly in the method.
       
   975      */
       
   976     Boolean isAvailable() {
       
   977         // We won't know whether a cipher for a particular key size is
       
   978         // available until the cipher is successfully initialized.
       
   979         //
       
   980         // We do not initialize AEAD cipher in the constructor.  Need to
       
   981         // initialize the cipher to ensure that the AEAD mode for a
       
   982         // particular key size is supported.
       
   983         if (cipherType == AEAD_CIPHER) {
       
   984             try {
       
   985                 Authenticator authenticator =
       
   986                     new Authenticator(protocolVersion);
       
   987                 byte[] nonce = authenticator.sequenceNumber();
       
   988                 byte[] iv = Arrays.copyOf(fixedIv,
       
   989                                             fixedIv.length + nonce.length);
       
   990                 System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length);
       
   991                 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
       
   992 
       
   993                 cipher.init(mode, key, spec, random);
       
   994             } catch (Exception e) {
       
   995                 return Boolean.FALSE;
       
   996             }
       
   997         }   // Otherwise, we have initialized the cipher in the constructor.
       
   998 
       
   999         return Boolean.TRUE;
       
  1000     }
   710     }
  1001 }
   711 }