| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.ssl;  | 
 | 
 | 
 | 
import java.io.IOException;  | 
 | 
import java.nio.ByteBuffer;  | 
 | 
import java.util.List;  | 
 | 
import sun.security.ssl.SSLExtension.ExtensionConsumer;  | 
 | 
import sun.security.ssl.SSLHandshake.HandshakeMessage;  | 
 | 
import sun.security.ssl.SignatureAlgorithmsExtension.SignatureSchemesSpec;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
final class CertSignAlgsExtension { | 
 | 
    static final HandshakeProducer chNetworkProducer =  | 
 | 
            new CHCertSignatureSchemesProducer();  | 
 | 
    static final ExtensionConsumer chOnLoadConsumer =  | 
 | 
            new CHCertSignatureSchemesConsumer();  | 
 | 
    static final HandshakeConsumer chOnTradeConsumer =  | 
 | 
            new CHCertSignatureSchemesUpdate();  | 
 | 
 | 
 | 
    static final HandshakeProducer crNetworkProducer =  | 
 | 
            new CRCertSignatureSchemesProducer();  | 
 | 
    static final ExtensionConsumer crOnLoadConsumer =  | 
 | 
            new CRCertSignatureSchemesConsumer();  | 
 | 
    static final HandshakeConsumer crOnTradeConsumer =  | 
 | 
            new CRCertSignatureSchemesUpdate();  | 
 | 
 | 
 | 
    static final SSLStringizer ssStringizer =  | 
 | 
            new CertSignatureSchemesStringizer();  | 
 | 
 | 
 | 
    private static final  | 
 | 
            class CertSignatureSchemesStringizer implements SSLStringizer { | 
 | 
        @Override  | 
 | 
        public String toString(ByteBuffer buffer) { | 
 | 
            try { | 
 | 
                return (new SignatureSchemesSpec(buffer)).toString();  | 
 | 
            } catch (IOException ioe) { | 
 | 
                  | 
 | 
                return ioe.getMessage();  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final  | 
 | 
            class CHCertSignatureSchemesProducer implements HandshakeProducer { | 
 | 
          | 
 | 
        private CHCertSignatureSchemesProducer() { | 
 | 
            // blank  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public byte[] produce(ConnectionContext context,  | 
 | 
                HandshakeMessage message) throws IOException { | 
 | 
              | 
 | 
            ClientHandshakeContext chc = (ClientHandshakeContext)context;  | 
 | 
 | 
 | 
              | 
 | 
            if (!chc.sslConfig.isAvailable(  | 
 | 
                    SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT)) { | 
 | 
                if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                    SSLLogger.fine(  | 
 | 
                            "Ignore unavailable " +  | 
 | 
                            "signature_algorithms_cert extension");  | 
 | 
                }  | 
 | 
 | 
 | 
                return null;      | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            if (chc.localSupportedSignAlgs == null) { | 
 | 
                chc.localSupportedSignAlgs =  | 
 | 
                    SignatureScheme.getSupportedAlgorithms(  | 
 | 
                            chc.algorithmConstraints, chc.activeProtocols);  | 
 | 
            }  | 
 | 
 | 
 | 
            int vectorLen = SignatureScheme.sizeInRecord() *  | 
 | 
                    chc.localSupportedSignAlgs.size();  | 
 | 
            byte[] extData = new byte[vectorLen + 2];  | 
 | 
            ByteBuffer m = ByteBuffer.wrap(extData);  | 
 | 
            Record.putInt16(m, vectorLen);  | 
 | 
            for (SignatureScheme ss : chc.localSupportedSignAlgs) { | 
 | 
                Record.putInt16(m, ss.id);  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            chc.handshakeExtensions.put(  | 
 | 
                    SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT,  | 
 | 
                    new SignatureSchemesSpec(chc.localSupportedSignAlgs));  | 
 | 
 | 
 | 
            return extData;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final  | 
 | 
            class CHCertSignatureSchemesConsumer implements ExtensionConsumer { | 
 | 
          | 
 | 
        private CHCertSignatureSchemesConsumer() { | 
 | 
            // blank  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public void consume(ConnectionContext context,  | 
 | 
            HandshakeMessage message, ByteBuffer buffer) throws IOException { | 
 | 
              | 
 | 
            ServerHandshakeContext shc = (ServerHandshakeContext)context;  | 
 | 
 | 
 | 
              | 
 | 
            if (!shc.sslConfig.isAvailable(  | 
 | 
                    SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT)) { | 
 | 
                if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                    SSLLogger.fine(  | 
 | 
                            "Ignore unavailable " +  | 
 | 
                            "signature_algorithms_cert extension");  | 
 | 
                }  | 
 | 
                return;       | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            SignatureSchemesSpec spec;  | 
 | 
            try { | 
 | 
                spec = new SignatureSchemesSpec(buffer);  | 
 | 
            } catch (IOException ioe) { | 
 | 
                shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);  | 
 | 
                return;       | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            shc.handshakeExtensions.put(  | 
 | 
                    SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT, spec);  | 
 | 
 | 
 | 
            // No impact on session resumption.  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final class CHCertSignatureSchemesUpdate  | 
 | 
            implements HandshakeConsumer { | 
 | 
          | 
 | 
        private CHCertSignatureSchemesUpdate() { | 
 | 
            // blank  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public void consume(ConnectionContext context,  | 
 | 
                HandshakeMessage message) throws IOException { | 
 | 
              | 
 | 
            ServerHandshakeContext shc = (ServerHandshakeContext)context;  | 
 | 
 | 
 | 
            SignatureSchemesSpec spec = (SignatureSchemesSpec)  | 
 | 
                    shc.handshakeExtensions.get(  | 
 | 
                            SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT);  | 
 | 
            if (spec == null) { | 
 | 
                  | 
 | 
                return;  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            List<SignatureScheme> schemes =  | 
 | 
                    SignatureScheme.getSupportedAlgorithms(  | 
 | 
                            shc.algorithmConstraints, shc.negotiatedProtocol,  | 
 | 
                            spec.signatureSchemes);  | 
 | 
            shc.peerRequestedCertSignSchemes = schemes;  | 
 | 
            shc.handshakeSession.setPeerSupportedSignatureAlgorithms(schemes);  | 
 | 
 | 
 | 
            if (!shc.isResumption && shc.negotiatedProtocol.useTLS13PlusSpec()) { | 
 | 
                if (shc.sslConfig.clientAuthType !=  | 
 | 
                        ClientAuthType.CLIENT_AUTH_NONE) { | 
 | 
                    shc.handshakeProducers.putIfAbsent(  | 
 | 
                            SSLHandshake.CERTIFICATE_REQUEST.id,  | 
 | 
                            SSLHandshake.CERTIFICATE_REQUEST);  | 
 | 
                }  | 
 | 
                shc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,  | 
 | 
                        SSLHandshake.CERTIFICATE);  | 
 | 
                shc.handshakeProducers.putIfAbsent(  | 
 | 
                        SSLHandshake.CERTIFICATE_VERIFY.id,  | 
 | 
                        SSLHandshake.CERTIFICATE_VERIFY);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final  | 
 | 
            class CRCertSignatureSchemesProducer implements HandshakeProducer { | 
 | 
          | 
 | 
        private CRCertSignatureSchemesProducer() { | 
 | 
            // blank  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public byte[] produce(ConnectionContext context,  | 
 | 
                HandshakeMessage message) throws IOException { | 
 | 
              | 
 | 
            ServerHandshakeContext shc = (ServerHandshakeContext)context;  | 
 | 
 | 
 | 
              | 
 | 
            if (!shc.sslConfig.isAvailable(  | 
 | 
                    SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT)) { | 
 | 
                if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                    SSLLogger.fine(  | 
 | 
                            "Ignore unavailable " +  | 
 | 
                            "signature_algorithms_cert extension");  | 
 | 
                }  | 
 | 
                return null;      | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            if (shc.localSupportedSignAlgs == null) { | 
 | 
                shc.localSupportedSignAlgs =  | 
 | 
                    SignatureScheme.getSupportedAlgorithms(  | 
 | 
                            shc.algorithmConstraints, shc.activeProtocols);  | 
 | 
            }  | 
 | 
 | 
 | 
            int vectorLen = SignatureScheme.sizeInRecord() *  | 
 | 
                    shc.localSupportedSignAlgs.size();  | 
 | 
            byte[] extData = new byte[vectorLen + 2];  | 
 | 
            ByteBuffer m = ByteBuffer.wrap(extData);  | 
 | 
            Record.putInt16(m, vectorLen);  | 
 | 
            for (SignatureScheme ss : shc.localSupportedSignAlgs) { | 
 | 
                Record.putInt16(m, ss.id);  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            shc.handshakeExtensions.put(  | 
 | 
                    SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT,  | 
 | 
                    new SignatureSchemesSpec(shc.localSupportedSignAlgs));  | 
 | 
 | 
 | 
            return extData;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final  | 
 | 
            class CRCertSignatureSchemesConsumer implements ExtensionConsumer { | 
 | 
          | 
 | 
        private CRCertSignatureSchemesConsumer() { | 
 | 
            // blank  | 
 | 
        }  | 
 | 
        @Override  | 
 | 
        public void consume(ConnectionContext context,  | 
 | 
            HandshakeMessage message, ByteBuffer buffer) throws IOException { | 
 | 
              | 
 | 
            ClientHandshakeContext chc = (ClientHandshakeContext)context;  | 
 | 
 | 
 | 
              | 
 | 
            if (!chc.sslConfig.isAvailable(  | 
 | 
                    SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT)) { | 
 | 
                if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { | 
 | 
                    SSLLogger.fine(  | 
 | 
                            "Ignore unavailable " +  | 
 | 
                            "signature_algorithms_cert extension");  | 
 | 
                }  | 
 | 
                return;       | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            SignatureSchemesSpec spec;  | 
 | 
            try { | 
 | 
                spec = new SignatureSchemesSpec(buffer);  | 
 | 
            } catch (IOException ioe) { | 
 | 
                chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);  | 
 | 
                return;       | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            chc.handshakeExtensions.put(  | 
 | 
                    SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT, spec);  | 
 | 
 | 
 | 
            // No impact on session resumption.  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final class CRCertSignatureSchemesUpdate  | 
 | 
            implements HandshakeConsumer { | 
 | 
          | 
 | 
        private CRCertSignatureSchemesUpdate() { | 
 | 
            // blank  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public void consume(ConnectionContext context,  | 
 | 
                HandshakeMessage message) throws IOException { | 
 | 
              | 
 | 
            ClientHandshakeContext chc = (ClientHandshakeContext)context;  | 
 | 
 | 
 | 
            SignatureSchemesSpec spec = (SignatureSchemesSpec)  | 
 | 
                    chc.handshakeExtensions.get(  | 
 | 
                            SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT);  | 
 | 
            if (spec == null) { | 
 | 
                  | 
 | 
                return;  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            List<SignatureScheme> schemes =  | 
 | 
                    SignatureScheme.getSupportedAlgorithms(  | 
 | 
                            chc.algorithmConstraints, chc.negotiatedProtocol,  | 
 | 
                            spec.signatureSchemes);  | 
 | 
            chc.peerRequestedCertSignSchemes = schemes;  | 
 | 
            chc.handshakeSession.setPeerSupportedSignatureAlgorithms(schemes);  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |