jdk/src/share/classes/sun/security/ssl/EngineInputRecord.java
changeset 16045 9d08c3b9a6a0
parent 14664 e71aa0962e70
child 16067 36055e4b5305
equal deleted inserted replaced
16044:85f90a877d17 16045:9d08c3b9a6a0
     1 /*
     1 /*
     2  * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2012, 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
   176 
   176 
   177         return len;
   177         return len;
   178     }
   178     }
   179 
   179 
   180     /*
   180     /*
   181      * Verifies and removes the MAC value.  Returns true if
   181      * Pass the data down if it's internally cached, otherwise
   182      * the MAC checks out OK.
   182      * do it here.
   183      *
   183      *
   184      * On entry:
   184      * If internal data, data is decrypted internally.
   185      *     position = beginning of app/MAC data
   185      *
   186      *     limit = end of MAC data.
   186      * If external data(app), return a new ByteBuffer with data to
   187      *
   187      * process.
   188      * On return:
   188      */
   189      *     position = beginning of app data
   189     ByteBuffer decrypt(Authenticator authenticator,
   190      *     limit = end of app data
   190             CipherBox box, ByteBuffer bb) throws BadPaddingException {
   191      */
   191 
   192     boolean checkMAC(MAC signer, ByteBuffer bb) {
       
   193         if (internalData) {
   192         if (internalData) {
   194             return checkMAC(signer);
   193             decrypt(authenticator, box);    // MAC is checked during decryption
   195         }
   194             return tmpBB;
   196 
   195         }
   197         int len = signer.MAClen();
   196 
   198         if (len == 0) { // no mac
   197         BadPaddingException bpe = null;
   199             return true;
   198         if (!box.isNullCipher()) {
   200         }
   199             try {
   201 
   200                 // apply explicit nonce for AEAD/CBC cipher suites if needed
   202         /*
   201                 int nonceSize =
   203          * Grab the original limit
   202                     box.applyExplicitNonce(authenticator, contentType(), bb);
   204          */
   203 
   205         int lim = bb.limit();
   204                 // decrypt the content
   206 
   205                 if (box.isAEADMode()) {
   207         /*
   206                     // DON'T encrypt the nonce_explicit for AEAD mode
   208          * Delineate the area to apply a MAC on.
   207                     bb.position(bb.position() + nonceSize);
   209          */
   208                 }   // The explicit IV for CBC mode can be decrypted.
   210         int macData = lim - len;
   209 
   211         bb.limit(macData);
   210                 box.decrypt(bb);
   212 
   211                 bb.position(nonceSize); // We don't actually remove the nonce.
   213         byte[] mac = signer.compute(contentType(), bb);
   212             } catch (BadPaddingException e) {
   214 
   213                 // RFC 2246 states that decryption_failed should be used
   215         if (len != mac.length) {
   214                 // for this purpose. However, that allows certain attacks,
   216             throw new RuntimeException("Internal MAC error");
   215                 // so we just send bad record MAC. We also need to make
   217         }
   216                 // sure to always check the MAC to avoid a timing attack
   218 
   217                 // for the same issue. See paper by Vaudenay et al and the
   219         /*
   218                 // update in RFC 4346/5246.
   220          * Delineate the MAC values, position was already set
   219                 //
   221          * by doing the compute above.
   220                 // Failover to message authentication code checking.
   222          *
   221                 bpe = new BadPaddingException("invalid padding");
   223          * We could zero the MAC area, but not much useful information
   222             }
   224          * there anyway.
   223         }
   225          */
   224 
   226         bb.position(macData);
   225         // Requires message authentication code for null, stream and block
   227         bb.limit(lim);
   226         // cipher suites.
   228 
   227         if (authenticator instanceof MAC) {
   229         try {
   228             MAC signer = (MAC)authenticator;
   230             for (int i = 0; i < len; i++) {
   229             int macLen = signer.MAClen();
   231                 if (bb.get() != mac[i]) {  // No BB.equals(byte []); !
   230             if (macLen != 0) {
   232                     return false;
   231                 if (bb.remaining() < macLen) {
       
   232                     // negative data length, something is wrong
       
   233                     throw new BadPaddingException("bad record");
       
   234                 }
       
   235 
       
   236                 int position = bb.position();
       
   237                 int limit = bb.limit();
       
   238                 int macOffset = limit - macLen;
       
   239 
       
   240                 bb.limit(macOffset);
       
   241                 byte[] hash = signer.compute(contentType(), bb);
       
   242                 if (hash == null || macLen != hash.length) {
       
   243                     // something is wrong with MAC implementation
       
   244                     throw new RuntimeException("Internal MAC error");
       
   245                 }
       
   246 
       
   247                 bb.position(macOffset);
       
   248                 bb.limit(limit);
       
   249 
       
   250                 try {
       
   251                     for (byte b : hash) {       // No BB.equals(byte []); !
       
   252                         if (bb.get() != b) {
       
   253                             throw new BadPaddingException("bad record MAC");
       
   254                         }
       
   255                     }
       
   256                 } finally {
       
   257                     // reset to the data
       
   258                     bb.position(position);
       
   259                     bb.limit(macOffset);
   233                 }
   260                 }
   234             }
   261             }
   235             return true;
   262         }
   236         } finally {
   263 
   237             /*
   264         // Is it a failover?
   238              * Position to the data.
   265         if (bpe != null) {
   239              */
   266             throw bpe;
   240             bb.rewind();
   267         }
   241             bb.limit(macData);
       
   242         }
       
   243     }
       
   244 
       
   245     /*
       
   246      * Pass the data down if it's internally cached, otherwise
       
   247      * do it here.
       
   248      *
       
   249      * If internal data, data is decrypted internally.
       
   250      *
       
   251      * If external data(app), return a new ByteBuffer with data to
       
   252      * process.
       
   253      */
       
   254     ByteBuffer decrypt(CipherBox box, ByteBuffer bb)
       
   255             throws BadPaddingException {
       
   256 
       
   257         if (internalData) {
       
   258             decrypt(box);
       
   259             return tmpBB;
       
   260         }
       
   261 
       
   262         box.decrypt(bb);
       
   263         bb.rewind();
       
   264 
   268 
   265         return bb.slice();
   269         return bb.slice();
   266     }
   270     }
   267 
   271 
   268     /*
   272     /*
   336         assert(len > 0);
   340         assert(len > 0);
   337 
   341 
   338         if (debug != null && Debug.isOn("packet")) {
   342         if (debug != null && Debug.isOn("packet")) {
   339             try {
   343             try {
   340                 HexDumpEncoder hd = new HexDumpEncoder();
   344                 HexDumpEncoder hd = new HexDumpEncoder();
   341                 srcBB.limit(srcPos + len);
       
   342                 ByteBuffer bb = srcBB.duplicate();  // Use copy of BB
   345                 ByteBuffer bb = srcBB.duplicate();  // Use copy of BB
       
   346                 bb.limit(srcPos + len);
   343 
   347 
   344                 System.out.println("[Raw read (bb)]: length = " + len);
   348                 System.out.println("[Raw read (bb)]: length = " + len);
   345                 hd.encodeBuffer(bb, System.out);
   349                 hd.encodeBuffer(bb, System.out);
   346             } catch (IOException e) { }
   350             } catch (IOException e) { }
   347         }
   351         }