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