| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.ssl;  | 
 | 
 | 
 | 
import java.nio.ByteBuffer;  | 
 | 
import java.security.InvalidKeyException;  | 
 | 
import java.security.NoSuchAlgorithmException;  | 
 | 
import java.util.Arrays;  | 
 | 
import javax.crypto.Mac;  | 
 | 
import javax.crypto.SecretKey;  | 
 | 
import sun.security.ssl.CipherSuite.MacAlg;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
abstract class Authenticator { | 
 | 
    // byte array containing the additional authentication information for  | 
 | 
    // each record  | 
 | 
    protected final byte[] block;     | 
 | 
 | 
 | 
    private Authenticator(byte[] block) { | 
 | 
        this.block = block;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    static Authenticator valueOf(ProtocolVersion protocolVersion) { | 
 | 
        if (protocolVersion.useTLS13PlusSpec()) { | 
 | 
            return new TLS13Authenticator(protocolVersion);  | 
 | 
        } else if (protocolVersion.useTLS10PlusSpec()) { | 
 | 
            return new TLS10Authenticator(protocolVersion);  | 
 | 
        } else { | 
 | 
            return new SSL30Authenticator();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    @SuppressWarnings({"unchecked"}) | 
 | 
    static <T extends Authenticator & MAC> T  | 
 | 
         valueOf(ProtocolVersion protocolVersion, MacAlg macAlg,  | 
 | 
                 SecretKey key) throws NoSuchAlgorithmException,  | 
 | 
                        InvalidKeyException { | 
 | 
        if (protocolVersion.useTLS13PlusSpec()) { | 
 | 
            throw new RuntimeException("No MacAlg used in TLS 1.3"); | 
 | 
        } else if (protocolVersion.useTLS10PlusSpec()) { | 
 | 
            return (T)(new TLS10Mac(protocolVersion, macAlg, key));  | 
 | 
        } else { | 
 | 
            return (T)(new SSL30Mac(protocolVersion, macAlg, key));  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    static Authenticator nullTlsMac() { | 
 | 
        return new SSLNullMac();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    abstract boolean seqNumOverflow();  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    abstract boolean seqNumIsHuge();  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    final byte[] sequenceNumber() { | 
 | 
        return Arrays.copyOf(block, 8);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    final void increaseSequenceNumber() { | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        int k = 7;  | 
 | 
        while ((k >= 0) && (++block[k] == 0)) { | 
 | 
            k--;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    byte[] acquireAuthenticationBytes(  | 
 | 
            byte type, int length, byte[] sequence) { | 
 | 
        throw new UnsupportedOperationException("Used by AEAD algorithms only"); | 
 | 
    }  | 
 | 
 | 
 | 
    private static class SSLAuthenticator extends Authenticator { | 
 | 
        private SSLAuthenticator(byte[] block) { | 
 | 
            super(block);  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        boolean seqNumOverflow() { | 
 | 
              | 
 | 
 | 
 | 
 | 
 | 
             */  | 
 | 
            return (block.length != 0 &&  | 
 | 
                block[0] == (byte)0xFF && block[1] == (byte)0xFF &&  | 
 | 
                block[2] == (byte)0xFF && block[3] == (byte)0xFF &&  | 
 | 
                block[4] == (byte)0xFF && block[5] == (byte)0xFF &&  | 
 | 
                block[6] == (byte)0xFF);  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        boolean seqNumIsHuge() { | 
 | 
            return (block.length != 0 &&  | 
 | 
                block[0] == (byte)0xFF && block[1] == (byte)0xFF &&  | 
 | 
                block[2] == (byte)0xFF && block[3] == (byte)0xFF);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    private static class SSLNullAuthenticator extends SSLAuthenticator { | 
 | 
        private SSLNullAuthenticator() { | 
 | 
            super(new byte[8]);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    private static class SSL30Authenticator extends SSLAuthenticator { | 
 | 
        // Block size of SSL v3.0:  | 
 | 
        //     sequence number + record type + + record length  | 
 | 
        private static final int BLOCK_SIZE = 11;     | 
 | 
 | 
 | 
        private SSL30Authenticator() { | 
 | 
            super(new byte[BLOCK_SIZE]);  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        byte[] acquireAuthenticationBytes(  | 
 | 
                byte type, int length, byte[] sequence) { | 
 | 
            byte[] ad = block.clone();  | 
 | 
 | 
 | 
              | 
 | 
            increaseSequenceNumber();  | 
 | 
 | 
 | 
            ad[8] = type;  | 
 | 
            ad[9] = (byte)(length >> 8);  | 
 | 
            ad[10] = (byte)(length);  | 
 | 
 | 
 | 
            return ad;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    private static class TLS10Authenticator extends SSLAuthenticator { | 
 | 
        // Block size of TLS v1.0/1.1/1.2.  | 
 | 
        //     sequence number + record type + protocol version + record length  | 
 | 
        private static final int BLOCK_SIZE = 13;     | 
 | 
 | 
 | 
        private TLS10Authenticator(ProtocolVersion protocolVersion) { | 
 | 
            super(new byte[BLOCK_SIZE]);  | 
 | 
            block[9] = protocolVersion.major;  | 
 | 
            block[10] = protocolVersion.minor;  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        byte[] acquireAuthenticationBytes(  | 
 | 
                byte type, int length, byte[] sequence) { | 
 | 
            byte[] ad = block.clone();  | 
 | 
            if (sequence != null) { | 
 | 
                if (sequence.length != 8) { | 
 | 
                    throw new RuntimeException(  | 
 | 
                            "Insufficient explicit sequence number bytes");  | 
 | 
                }  | 
 | 
 | 
 | 
                System.arraycopy(sequence, 0, ad, 0, sequence.length);  | 
 | 
            } else {    // Otherwise, use the implicit sequence number. | 
 | 
                  | 
 | 
                increaseSequenceNumber();  | 
 | 
            }  | 
 | 
 | 
 | 
            ad[8] = type;  | 
 | 
            ad[11] = (byte)(length >> 8);  | 
 | 
            ad[12] = (byte)(length);  | 
 | 
 | 
 | 
            return ad;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    private static final class TLS13Authenticator extends SSLAuthenticator { | 
 | 
        // Block size of TLS v1.3:  | 
 | 
        //     record type + protocol version + record length + sequence number  | 
 | 
        private static final int BLOCK_SIZE = 13;     | 
 | 
 | 
 | 
        private TLS13Authenticator(ProtocolVersion protocolVersion) { | 
 | 
            super(new byte[BLOCK_SIZE]);  | 
 | 
            block[9] = ProtocolVersion.TLS12.major;  | 
 | 
            block[10] = ProtocolVersion.TLS12.minor;  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        byte[] acquireAuthenticationBytes(  | 
 | 
                byte type, int length, byte[] sequence) { | 
 | 
            byte[] ad = Arrays.copyOfRange(block, 8, 13);  | 
 | 
 | 
 | 
              | 
 | 
            increaseSequenceNumber();  | 
 | 
 | 
 | 
            ad[0] = type;  | 
 | 
            ad[3] = (byte)(length >> 8);  | 
 | 
            ad[4] = (byte)(length & 0xFF);  | 
 | 
 | 
 | 
            return ad;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    interface MAC { | 
 | 
        MacAlg macAlg();  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        byte[] compute(byte type, ByteBuffer bb,  | 
 | 
                byte[] sequence, boolean isSimulated);  | 
 | 
 | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        default byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) { | 
 | 
            return compute(type, bb, null, isSimulated);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private class MacImpl implements MAC { | 
 | 
          | 
 | 
        private final MacAlg macAlg;  | 
 | 
 | 
 | 
          | 
 | 
        private final Mac mac;  | 
 | 
 | 
 | 
        private MacImpl() { | 
 | 
            macAlg = MacAlg.M_NULL;  | 
 | 
            mac = null;  | 
 | 
        }  | 
 | 
 | 
 | 
        private MacImpl(ProtocolVersion protocolVersion, MacAlg macAlg,  | 
 | 
                SecretKey key) throws NoSuchAlgorithmException,  | 
 | 
                        InvalidKeyException { | 
 | 
            if (macAlg == null) { | 
 | 
                throw new RuntimeException("Null MacAlg"); | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            boolean useSSLMac = (protocolVersion.id < ProtocolVersion.TLS10.id);  | 
 | 
            String algorithm;  | 
 | 
            switch (macAlg) { | 
 | 
                case M_MD5:  | 
 | 
                    algorithm = useSSLMac ? "SslMacMD5" : "HmacMD5";  | 
 | 
                    break;  | 
 | 
                case M_SHA:  | 
 | 
                    algorithm = useSSLMac ? "SslMacSHA1" : "HmacSHA1";  | 
 | 
                    break;  | 
 | 
                case M_SHA256:  | 
 | 
                    algorithm = "HmacSHA256";      | 
 | 
                    break;  | 
 | 
                case M_SHA384:  | 
 | 
                    algorithm = "HmacSHA384";      | 
 | 
                    break;  | 
 | 
                default:  | 
 | 
                    throw new RuntimeException("Unknown MacAlg " + macAlg); | 
 | 
            }  | 
 | 
 | 
 | 
            Mac m = JsseJce.getMac(algorithm);  | 
 | 
            m.init(key);  | 
 | 
            this.macAlg = macAlg;  | 
 | 
            this.mac = m;  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public MacAlg macAlg() { | 
 | 
            return macAlg;  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public byte[] compute(byte type, ByteBuffer bb,  | 
 | 
                byte[] sequence, boolean isSimulated) { | 
 | 
 | 
 | 
            if (macAlg.size == 0) { | 
 | 
                return new byte[0];  | 
 | 
            }  | 
 | 
 | 
 | 
            if (!isSimulated) { | 
 | 
                  | 
 | 
                byte[] additional =  | 
 | 
                    acquireAuthenticationBytes(type, bb.remaining(), sequence);  | 
 | 
                mac.update(additional);  | 
 | 
            }  | 
 | 
            mac.update(bb);  | 
 | 
 | 
 | 
            return mac.doFinal();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    private static final  | 
 | 
            class SSLNullMac extends SSLNullAuthenticator implements MAC { | 
 | 
        private final MacImpl macImpl;  | 
 | 
        public SSLNullMac() { | 
 | 
            super();  | 
 | 
            this.macImpl = new MacImpl();  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public MacAlg macAlg() { | 
 | 
            return macImpl.macAlg;  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public byte[] compute(byte type, ByteBuffer bb,  | 
 | 
                byte[] sequence, boolean isSimulated) { | 
 | 
            return macImpl.compute(type, bb, sequence, isSimulated);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    private static final  | 
 | 
            class SSL30Mac extends SSL30Authenticator implements MAC { | 
 | 
        private final MacImpl macImpl;  | 
 | 
        public SSL30Mac(ProtocolVersion protocolVersion,  | 
 | 
                MacAlg macAlg, SecretKey key) throws NoSuchAlgorithmException,  | 
 | 
                        InvalidKeyException { | 
 | 
            super();  | 
 | 
            this.macImpl = new MacImpl(protocolVersion, macAlg, key);  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public MacAlg macAlg() { | 
 | 
            return macImpl.macAlg;  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public byte[] compute(byte type, ByteBuffer bb,  | 
 | 
                byte[] sequence, boolean isSimulated) { | 
 | 
            return macImpl.compute(type, bb, sequence, isSimulated);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    private static final  | 
 | 
            class TLS10Mac extends TLS10Authenticator implements MAC { | 
 | 
        private final MacImpl macImpl;  | 
 | 
        public TLS10Mac(ProtocolVersion protocolVersion,  | 
 | 
                MacAlg macAlg, SecretKey key) throws NoSuchAlgorithmException,  | 
 | 
                        InvalidKeyException { | 
 | 
            super(protocolVersion);  | 
 | 
            this.macImpl = new MacImpl(protocolVersion, macAlg, key);  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public MacAlg macAlg() { | 
 | 
            return macImpl.macAlg;  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public byte[] compute(byte type, ByteBuffer bb,  | 
 | 
                byte[] sequence, boolean isSimulated) { | 
 | 
            return macImpl.compute(type, bb, sequence, isSimulated);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    static final long toLong(byte[] recordEnS) { | 
 | 
        if (recordEnS != null && recordEnS.length == 8) { | 
 | 
            return ((recordEnS[0] & 0xFFL) << 56) |  | 
 | 
                   ((recordEnS[1] & 0xFFL) << 48) |  | 
 | 
                   ((recordEnS[2] & 0xFFL) << 40) |  | 
 | 
                   ((recordEnS[3] & 0xFFL) << 32) |  | 
 | 
                   ((recordEnS[4] & 0xFFL) << 24) |  | 
 | 
                   ((recordEnS[5] & 0xFFL) << 16) |  | 
 | 
                   ((recordEnS[6] & 0xFFL) <<  8) |  | 
 | 
                    (recordEnS[7] & 0xFFL);  | 
 | 
        }  | 
 | 
 | 
 | 
        return -1L;  | 
 | 
    }  | 
 | 
}  |