Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/ssl/CertificateVerify.java
38830 views
/*1* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.ssl;2627import java.io.IOException;28import java.nio.ByteBuffer;29import java.security.*;30import java.text.MessageFormat;31import java.util.Arrays;32import java.util.Locale;33import java.util.Map;34import sun.security.ssl.SSLHandshake.HandshakeMessage;35import sun.security.ssl.X509Authentication.X509Credentials;36import sun.security.ssl.X509Authentication.X509Possession;37import sun.misc.HexDumpEncoder;3839/**40* Pack of the CertificateVerify handshake message.41*/42final class CertificateVerify {43static final SSLConsumer s30HandshakeConsumer =44new S30CertificateVerifyConsumer();45static final HandshakeProducer s30HandshakeProducer =46new S30CertificateVerifyProducer();4748static final SSLConsumer t10HandshakeConsumer =49new T10CertificateVerifyConsumer();50static final HandshakeProducer t10HandshakeProducer =51new T10CertificateVerifyProducer();5253static final SSLConsumer t12HandshakeConsumer =54new T12CertificateVerifyConsumer();55static final HandshakeProducer t12HandshakeProducer =56new T12CertificateVerifyProducer();5758static final SSLConsumer t13HandshakeConsumer =59new T13CertificateVerifyConsumer();60static final HandshakeProducer t13HandshakeProducer =61new T13CertificateVerifyProducer();6263/**64* The CertificateVerify handshake message (SSL 3.0).65*/66static final class S30CertificateVerifyMessage extends HandshakeMessage {67// signature bytes68private final byte[] signature;6970S30CertificateVerifyMessage(HandshakeContext context,71X509Possession x509Possession) throws IOException {72super(context);7374// This happens in client side only.75ClientHandshakeContext chc = (ClientHandshakeContext)context;76byte[] temproary = null;77String algorithm = x509Possession.popPrivateKey.getAlgorithm();78try {79Signature signer =80getSignature(algorithm, x509Possession.popPrivateKey);81byte[] hashes = chc.handshakeHash.digest(algorithm,82chc.handshakeSession.getMasterSecret());83signer.update(hashes);84temproary = signer.sign();85} catch (NoSuchAlgorithmException nsae) {86throw chc.conContext.fatal(Alert.INTERNAL_ERROR,87"Unsupported signature algorithm (" + algorithm +88") used in CertificateVerify handshake message", nsae);89} catch (GeneralSecurityException gse) {90throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,91"Cannot produce CertificateVerify signature", gse);92}9394this.signature = temproary;95}9697S30CertificateVerifyMessage(HandshakeContext context,98ByteBuffer m) throws IOException {99super(context);100101// This happens in server side only.102ServerHandshakeContext shc = (ServerHandshakeContext)context;103104// digitally-signed struct {105// select(SignatureAlgorithm) {106// case anonymous: struct { };107// case rsa:108// opaque md5_hash[16];109// opaque sha_hash[20];110// case dsa:111// opaque sha_hash[20];112// };113// } Signature;114if (m.remaining() < 2) {115throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,116"Invalid CertificateVerify message: no sufficient data");117}118119// read and verify the signature120this.signature = Record.getBytes16(m);121X509Credentials x509Credentials = null;122for (SSLCredentials cd : shc.handshakeCredentials) {123if (cd instanceof X509Credentials) {124x509Credentials = (X509Credentials)cd;125break;126}127}128129if (x509Credentials == null ||130x509Credentials.popPublicKey == null) {131throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,132"No X509 credentials negotiated for CertificateVerify");133}134135String algorithm = x509Credentials.popPublicKey.getAlgorithm();136try {137Signature signer =138getSignature(algorithm, x509Credentials.popPublicKey);139byte[] hashes = shc.handshakeHash.digest(algorithm,140shc.handshakeSession.getMasterSecret());141signer.update(hashes);142if (!signer.verify(signature)) {143throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,144"Invalid CertificateVerify message: invalid signature");145}146} catch (NoSuchAlgorithmException nsae) {147throw shc.conContext.fatal(Alert.INTERNAL_ERROR,148"Unsupported signature algorithm (" + algorithm +149") used in CertificateVerify handshake message", nsae);150} catch (GeneralSecurityException gse) {151throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,152"Cannot verify CertificateVerify signature", gse);153}154}155156@Override157public SSLHandshake handshakeType() {158return SSLHandshake.CERTIFICATE_VERIFY;159}160161@Override162public int messageLength() {163return 2 + signature.length; // 2: length of signature164}165166@Override167public void send(HandshakeOutStream hos) throws IOException {168hos.putBytes16(signature);169}170171@Override172public String toString() {173MessageFormat messageFormat = new MessageFormat(174"\"CertificateVerify\": '{'\n" +175" \"signature\": '{'\n" +176"{0}\n" +177" '}'\n" +178"'}'",179Locale.ENGLISH);180181HexDumpEncoder hexEncoder = new HexDumpEncoder();182Object[] messageFields = {183Utilities.indent(184hexEncoder.encodeBuffer(signature), " ")185};186187return messageFormat.format(messageFields);188}189190/*191* Get the Signature object appropriate for verification using the192* given signature algorithm.193*/194private static Signature getSignature(String algorithm,195Key key) throws GeneralSecurityException {196Signature signer = null;197switch (algorithm) {198case "RSA":199signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA);200break;201case "DSA":202signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA);203break;204case "EC":205signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA);206break;207default:208throw new SignatureException("Unrecognized algorithm: "209+ algorithm);210}211212if (signer != null) {213if (key instanceof PublicKey) {214signer.initVerify((PublicKey)(key));215} else {216signer.initSign((PrivateKey)key);217}218}219220return signer;221}222}223224/**225* The "CertificateVerify" handshake message producer.226*/227private static final228class S30CertificateVerifyProducer implements HandshakeProducer {229// Prevent instantiation of this class.230private S30CertificateVerifyProducer() {231// blank232}233234@Override235public byte[] produce(ConnectionContext context,236HandshakeMessage message) throws IOException {237// The producing happens in client side only.238ClientHandshakeContext chc = (ClientHandshakeContext)context;239240X509Possession x509Possession = null;241for (SSLPossession possession : chc.handshakePossessions) {242if (possession instanceof X509Possession) {243x509Possession = (X509Possession)possession;244break;245}246}247248if (x509Possession == null ||249x509Possession.popPrivateKey == null) {250if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {251SSLLogger.fine(252"No X.509 credentials negotiated for CertificateVerify");253}254255return null;256}257258S30CertificateVerifyMessage cvm =259new S30CertificateVerifyMessage(chc, x509Possession);260if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {261SSLLogger.fine(262"Produced CertificateVerify handshake message", cvm);263}264265// Output the handshake message.266cvm.write(chc.handshakeOutput);267chc.handshakeOutput.flush();268269// The handshake message has been delivered.270return null;271}272}273274/**275* The "CertificateVerify" handshake message consumer.276*/277private static final278class S30CertificateVerifyConsumer implements SSLConsumer {279// Prevent instantiation of this class.280private S30CertificateVerifyConsumer() {281// blank282}283284@Override285public void consume(ConnectionContext context,286ByteBuffer message) throws IOException {287// The consuming happens in server side only.288ServerHandshakeContext shc = (ServerHandshakeContext)context;289290// Clean up this consumer291shc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);292293// Ensure that the CV message follows the CKE294if (shc.handshakeConsumers.containsKey(295SSLHandshake.CLIENT_KEY_EXCHANGE.id)) {296throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,297"Unexpected CertificateVerify handshake message");298}299300S30CertificateVerifyMessage cvm =301new S30CertificateVerifyMessage(shc, message);302if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {303SSLLogger.fine(304"Consuming CertificateVerify handshake message", cvm);305}306307//308// update309//310// Need no additional validation.311312//313// produce314//315// Need no new handshake message producers here.316}317}318319/**320* The CertificateVerify handshake message (TLS 1.0/1.1).321*/322static final class T10CertificateVerifyMessage extends HandshakeMessage {323// signature bytes324private final byte[] signature;325326T10CertificateVerifyMessage(HandshakeContext context,327X509Possession x509Possession) throws IOException {328super(context);329330// This happens in client side only.331ClientHandshakeContext chc = (ClientHandshakeContext)context;332byte[] temproary = null;333String algorithm = x509Possession.popPrivateKey.getAlgorithm();334try {335Signature signer =336getSignature(algorithm, x509Possession.popPrivateKey);337byte[] hashes = chc.handshakeHash.digest(algorithm);338signer.update(hashes);339temproary = signer.sign();340} catch (NoSuchAlgorithmException nsae) {341throw chc.conContext.fatal(Alert.INTERNAL_ERROR,342"Unsupported signature algorithm (" + algorithm +343") used in CertificateVerify handshake message", nsae);344} catch (GeneralSecurityException gse) {345throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,346"Cannot produce CertificateVerify signature", gse);347}348349this.signature = temproary;350}351352T10CertificateVerifyMessage(HandshakeContext context,353ByteBuffer m) throws IOException {354super(context);355356// This happens in server side only.357ServerHandshakeContext shc = (ServerHandshakeContext)context;358359// digitally-signed struct {360// select(SignatureAlgorithm) {361// case anonymous: struct { };362// case rsa:363// opaque md5_hash[16];364// opaque sha_hash[20];365// case dsa:366// opaque sha_hash[20];367// };368// } Signature;369if (m.remaining() < 2) {370throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,371"Invalid CertificateVerify message: no sufficient data");372}373374// read and verify the signature375this.signature = Record.getBytes16(m);376X509Credentials x509Credentials = null;377for (SSLCredentials cd : shc.handshakeCredentials) {378if (cd instanceof X509Credentials) {379x509Credentials = (X509Credentials)cd;380break;381}382}383384if (x509Credentials == null ||385x509Credentials.popPublicKey == null) {386throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,387"No X509 credentials negotiated for CertificateVerify");388}389390String algorithm = x509Credentials.popPublicKey.getAlgorithm();391try {392Signature signer =393getSignature(algorithm, x509Credentials.popPublicKey);394byte[] hashes = shc.handshakeHash.digest(algorithm);395signer.update(hashes);396if (!signer.verify(signature)) {397throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,398"Invalid CertificateVerify message: invalid signature");399}400} catch (NoSuchAlgorithmException nsae) {401throw shc.conContext.fatal(Alert.INTERNAL_ERROR,402"Unsupported signature algorithm (" + algorithm +403") used in CertificateVerify handshake message", nsae);404} catch (GeneralSecurityException gse) {405throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,406"Cannot verify CertificateVerify signature", gse);407}408}409410@Override411public SSLHandshake handshakeType() {412return SSLHandshake.CERTIFICATE_VERIFY;413}414415@Override416public int messageLength() {417return 2 + signature.length; // 2: length of signature418}419420@Override421public void send(HandshakeOutStream hos) throws IOException {422hos.putBytes16(signature);423}424425@Override426public String toString() {427MessageFormat messageFormat = new MessageFormat(428"\"CertificateVerify\": '{'\n" +429" \"signature\": '{'\n" +430"{0}\n" +431" '}'\n" +432"'}'",433Locale.ENGLISH);434435HexDumpEncoder hexEncoder = new HexDumpEncoder();436Object[] messageFields = {437Utilities.indent(438hexEncoder.encodeBuffer(signature), " ")439};440441return messageFormat.format(messageFields);442}443444/*445* Get the Signature object appropriate for verification using the446* given signature algorithm.447*/448private static Signature getSignature(String algorithm,449Key key) throws GeneralSecurityException {450Signature signer = null;451switch (algorithm) {452case "RSA":453signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA);454break;455case "DSA":456signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA);457break;458case "EC":459signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA);460break;461default:462throw new SignatureException("Unrecognized algorithm: "463+ algorithm);464}465466if (signer != null) {467if (key instanceof PublicKey) {468signer.initVerify((PublicKey)(key));469} else {470signer.initSign((PrivateKey)key);471}472}473474return signer;475}476}477478/**479* The "CertificateVerify" handshake message producer.480*/481private static final482class T10CertificateVerifyProducer implements HandshakeProducer {483// Prevent instantiation of this class.484private T10CertificateVerifyProducer() {485// blank486}487488@Override489public byte[] produce(ConnectionContext context,490HandshakeMessage message) throws IOException {491// The producing happens in client side only.492ClientHandshakeContext chc = (ClientHandshakeContext)context;493X509Possession x509Possession = null;494for (SSLPossession possession : chc.handshakePossessions) {495if (possession instanceof X509Possession) {496x509Possession = (X509Possession)possession;497break;498}499}500501if (x509Possession == null ||502x509Possession.popPrivateKey == null) {503if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {504SSLLogger.fine(505"No X.509 credentials negotiated for CertificateVerify");506}507508return null;509}510511T10CertificateVerifyMessage cvm =512new T10CertificateVerifyMessage(chc, x509Possession);513if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {514SSLLogger.fine(515"Produced CertificateVerify handshake message", cvm);516}517518// Output the handshake message.519cvm.write(chc.handshakeOutput);520chc.handshakeOutput.flush();521522// The handshake message has been delivered.523return null;524}525}526527/**528* The "CertificateVerify" handshake message consumer.529*/530private static final531class T10CertificateVerifyConsumer implements SSLConsumer {532// Prevent instantiation of this class.533private T10CertificateVerifyConsumer() {534// blank535}536537@Override538public void consume(ConnectionContext context,539ByteBuffer message) throws IOException {540// The consuming happens in server side only.541ServerHandshakeContext shc = (ServerHandshakeContext)context;542543// Clean up this consumer544shc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);545546// Ensure that the CV message follows the CKE547if (shc.handshakeConsumers.containsKey(548SSLHandshake.CLIENT_KEY_EXCHANGE.id)) {549throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,550"Unexpected CertificateVerify handshake message");551}552553T10CertificateVerifyMessage cvm =554new T10CertificateVerifyMessage(shc, message);555if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {556SSLLogger.fine(557"Consuming CertificateVerify handshake message", cvm);558}559560//561// update562//563// Need no additional validation.564565//566// produce567//568// Need no new handshake message producers here. }569}570}571572/**573* The CertificateVerify handshake message (TLS 1.2).574*/575static final class T12CertificateVerifyMessage extends HandshakeMessage {576// the signature algorithm577private final SignatureScheme signatureScheme;578579// signature bytes580private final byte[] signature;581582T12CertificateVerifyMessage(HandshakeContext context,583X509Possession x509Possession) throws IOException {584super(context);585586// This happens in client side only.587ClientHandshakeContext chc = (ClientHandshakeContext)context;588Map.Entry<SignatureScheme, Signature> schemeAndSigner =589SignatureScheme.getSignerOfPreferableAlgorithm(590chc.peerRequestedSignatureSchemes,591x509Possession,592chc.negotiatedProtocol);593if (schemeAndSigner == null) {594// Unlikely, the credentials generator should have595// selected the preferable signature algorithm properly.596throw chc.conContext.fatal(Alert.INTERNAL_ERROR,597"No supported CertificateVerify signature algorithm for " +598x509Possession.popPrivateKey.getAlgorithm() +599" key");600}601602this.signatureScheme = schemeAndSigner.getKey();603byte[] temproary = null;604try {605Signature signer = schemeAndSigner.getValue();606signer.update(chc.handshakeHash.archived());607temproary = signer.sign();608} catch (SignatureException ikse) {609throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,610"Cannot produce CertificateVerify signature", ikse);611}612613this.signature = temproary;614}615616T12CertificateVerifyMessage(HandshakeContext handshakeContext,617ByteBuffer m) throws IOException {618super(handshakeContext);619620// This happens in server side only.621ServerHandshakeContext shc =622(ServerHandshakeContext)handshakeContext;623624// struct {625// SignatureAndHashAlgorithm algorithm;626// opaque signature<0..2^16-1>;627// } DigitallySigned;628if (m.remaining() < 4) {629throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,630"Invalid CertificateVerify message: no sufficient data");631}632633// SignatureAndHashAlgorithm algorithm634int ssid = Record.getInt16(m);635this.signatureScheme = SignatureScheme.valueOf(ssid);636if (signatureScheme == null) {637throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,638"Invalid signature algorithm (" + ssid +639") used in CertificateVerify handshake message");640}641642if (!shc.localSupportedSignAlgs.contains(signatureScheme)) {643throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,644"Unsupported signature algorithm (" +645signatureScheme.name +646") used in CertificateVerify handshake message");647}648649// read and verify the signature650X509Credentials x509Credentials = null;651for (SSLCredentials cd : shc.handshakeCredentials) {652if (cd instanceof X509Credentials) {653x509Credentials = (X509Credentials)cd;654break;655}656}657658if (x509Credentials == null ||659x509Credentials.popPublicKey == null) {660throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,661"No X509 credentials negotiated for CertificateVerify");662}663664// opaque signature<0..2^16-1>;665this.signature = Record.getBytes16(m);666try {667Signature signer =668signatureScheme.getVerifier(x509Credentials.popPublicKey);669signer.update(shc.handshakeHash.archived());670if (!signer.verify(signature)) {671throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,672"Invalid CertificateVerify signature");673}674} catch (NoSuchAlgorithmException |675InvalidAlgorithmParameterException nsae) {676throw shc.conContext.fatal(Alert.INTERNAL_ERROR,677"Unsupported signature algorithm (" +678signatureScheme.name +679") used in CertificateVerify handshake message", nsae);680} catch (InvalidKeyException | SignatureException ikse) {681throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,682"Cannot verify CertificateVerify signature", ikse);683}684}685686@Override687public SSLHandshake handshakeType() {688return SSLHandshake.CERTIFICATE_VERIFY;689}690691@Override692public int messageLength() {693return 4 + signature.length; // 2: signature algorithm694// +2: length of signature695}696697@Override698public void send(HandshakeOutStream hos) throws IOException {699hos.putInt16(signatureScheme.id);700hos.putBytes16(signature);701}702703@Override704public String toString() {705MessageFormat messageFormat = new MessageFormat(706"\"CertificateVerify\": '{'\n" +707" \"signature algorithm\": {0}\n" +708" \"signature\": '{'\n" +709"{1}\n" +710" '}'\n" +711"'}'",712Locale.ENGLISH);713714HexDumpEncoder hexEncoder = new HexDumpEncoder();715Object[] messageFields = {716signatureScheme.name,717Utilities.indent(718hexEncoder.encodeBuffer(signature), " ")719};720721return messageFormat.format(messageFields);722}723}724725/**726* The "CertificateVerify" handshake message producer.727*/728private static final729class T12CertificateVerifyProducer implements HandshakeProducer {730// Prevent instantiation of this class.731private T12CertificateVerifyProducer() {732// blank733}734735@Override736public byte[] produce(ConnectionContext context,737HandshakeMessage message) throws IOException {738// The producing happens in client side only.739ClientHandshakeContext chc = (ClientHandshakeContext)context;740741X509Possession x509Possession = null;742for (SSLPossession possession : chc.handshakePossessions) {743if (possession instanceof X509Possession) {744x509Possession = (X509Possession)possession;745break;746}747}748749if (x509Possession == null ||750x509Possession.popPrivateKey == null) {751if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {752SSLLogger.fine(753"No X.509 credentials negotiated for CertificateVerify");754}755756return null;757}758759T12CertificateVerifyMessage cvm =760new T12CertificateVerifyMessage(chc, x509Possession);761if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {762SSLLogger.fine(763"Produced CertificateVerify handshake message", cvm);764}765766// Output the handshake message.767cvm.write(chc.handshakeOutput);768chc.handshakeOutput.flush();769770// The handshake message has been delivered.771return null;772}773}774775/**776* The "CertificateVerify" handshake message consumer.777*/778private static final779class T12CertificateVerifyConsumer implements SSLConsumer {780// Prevent instantiation of this class.781private T12CertificateVerifyConsumer() {782// blank783}784785@Override786public void consume(ConnectionContext context,787ByteBuffer message) throws IOException {788// The consuming happens in server side only.789ServerHandshakeContext shc = (ServerHandshakeContext)context;790791// Clean up this consumer792shc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);793794// Ensure that the CV message follows the CKE795if (shc.handshakeConsumers.containsKey(796SSLHandshake.CLIENT_KEY_EXCHANGE.id)) {797throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,798"Unexpected CertificateVerify handshake message");799}800801T12CertificateVerifyMessage cvm =802new T12CertificateVerifyMessage(shc, message);803if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {804SSLLogger.fine(805"Consuming CertificateVerify handshake message", cvm);806}807808//809// update810//811// Need no additional validation.812813//814// produce815//816// Need no new handshake message producers here.817}818}819820/**821* The CertificateVerify handshake message (TLS 1.3).822*/823static final class T13CertificateVerifyMessage extends HandshakeMessage {824private static final byte[] serverSignHead = new byte[] {825// repeated 0x20 for 64 times826(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,827(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,828(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,829(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,830(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,831(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,832(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,833(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,834(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,835(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,836(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,837(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,838(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,839(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,840(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,841(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,842843// "TLS 1.3, server CertificateVerify" + 0x00844(byte)0x54, (byte)0x4c, (byte)0x53, (byte)0x20,845(byte)0x31, (byte)0x2e, (byte)0x33, (byte)0x2c,846(byte)0x20, (byte)0x73, (byte)0x65, (byte)0x72,847(byte)0x76, (byte)0x65, (byte)0x72, (byte)0x20,848(byte)0x43, (byte)0x65, (byte)0x72, (byte)0x74,849(byte)0x69, (byte)0x66, (byte)0x69, (byte)0x63,850(byte)0x61, (byte)0x74, (byte)0x65, (byte)0x56,851(byte)0x65, (byte)0x72, (byte)0x69, (byte)0x66,852(byte)0x79, (byte)0x00853};854855private static final byte[] clientSignHead = new byte[] {856// repeated 0x20 for 64 times857(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,858(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,859(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,860(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,861(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,862(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,863(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,864(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,865(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,866(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,867(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,868(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,869(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,870(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,871(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,872(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,873874// "TLS 1.3, client CertificateVerify" + 0x00875(byte)0x54, (byte)0x4c, (byte)0x53, (byte)0x20,876(byte)0x31, (byte)0x2e, (byte)0x33, (byte)0x2c,877(byte)0x20, (byte)0x63, (byte)0x6c, (byte)0x69,878(byte)0x65, (byte)0x6e, (byte)0x74, (byte)0x20,879(byte)0x43, (byte)0x65, (byte)0x72, (byte)0x74,880(byte)0x69, (byte)0x66, (byte)0x69, (byte)0x63,881(byte)0x61, (byte)0x74, (byte)0x65, (byte)0x56,882(byte)0x65, (byte)0x72, (byte)0x69, (byte)0x66,883(byte)0x79, (byte)0x00884};885886887// the signature algorithm888private final SignatureScheme signatureScheme;889890// signature bytes891private final byte[] signature;892893T13CertificateVerifyMessage(HandshakeContext context,894X509Possession x509Possession) throws IOException {895super(context);896897Map.Entry<SignatureScheme, Signature> schemeAndSigner =898SignatureScheme.getSignerOfPreferableAlgorithm(899context.peerRequestedSignatureSchemes,900x509Possession,901context.negotiatedProtocol);902if (schemeAndSigner == null) {903// Unlikely, the credentials generator should have904// selected the preferable signature algorithm properly.905throw context.conContext.fatal(Alert.INTERNAL_ERROR,906"No supported CertificateVerify signature algorithm for " +907x509Possession.popPrivateKey.getAlgorithm() +908" key");909}910911this.signatureScheme = schemeAndSigner.getKey();912913byte[] hashValue = context.handshakeHash.digest();914byte[] contentCovered;915if (context.sslConfig.isClientMode) {916contentCovered = Arrays.copyOf(clientSignHead,917clientSignHead.length + hashValue.length);918System.arraycopy(hashValue, 0, contentCovered,919clientSignHead.length, hashValue.length);920} else {921contentCovered = Arrays.copyOf(serverSignHead,922serverSignHead.length + hashValue.length);923System.arraycopy(hashValue, 0, contentCovered,924serverSignHead.length, hashValue.length);925}926927byte[] temproary = null;928try {929Signature signer = schemeAndSigner.getValue();930signer.update(contentCovered);931temproary = signer.sign();932} catch (SignatureException ikse) {933throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,934"Cannot produce CertificateVerify signature", ikse);935}936937this.signature = temproary;938}939940T13CertificateVerifyMessage(HandshakeContext context,941ByteBuffer m) throws IOException {942super(context);943944// struct {945// SignatureAndHashAlgorithm algorithm;946// opaque signature<0..2^16-1>;947// } DigitallySigned;948if (m.remaining() < 4) {949throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,950"Invalid CertificateVerify message: no sufficient data");951}952953// SignatureAndHashAlgorithm algorithm954int ssid = Record.getInt16(m);955this.signatureScheme = SignatureScheme.valueOf(ssid);956if (signatureScheme == null) {957throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,958"Invalid signature algorithm (" + ssid +959") used in CertificateVerify handshake message");960}961962if (!context.localSupportedSignAlgs.contains(signatureScheme)) {963throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,964"Unsupported signature algorithm (" +965signatureScheme.name +966") used in CertificateVerify handshake message");967}968969// read and verify the signature970X509Credentials x509Credentials = null;971for (SSLCredentials cd : context.handshakeCredentials) {972if (cd instanceof X509Credentials) {973x509Credentials = (X509Credentials)cd;974break;975}976}977978if (x509Credentials == null ||979x509Credentials.popPublicKey == null) {980throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,981"No X509 credentials negotiated for CertificateVerify");982}983984// opaque signature<0..2^16-1>;985this.signature = Record.getBytes16(m);986987byte[] hashValue = context.handshakeHash.digest();988byte[] contentCovered;989if (context.sslConfig.isClientMode) {990contentCovered = Arrays.copyOf(serverSignHead,991serverSignHead.length + hashValue.length);992System.arraycopy(hashValue, 0, contentCovered,993serverSignHead.length, hashValue.length);994} else {995contentCovered = Arrays.copyOf(clientSignHead,996clientSignHead.length + hashValue.length);997System.arraycopy(hashValue, 0, contentCovered,998clientSignHead.length, hashValue.length);999}10001001try {1002Signature signer =1003signatureScheme.getVerifier(x509Credentials.popPublicKey);1004signer.update(contentCovered);1005if (!signer.verify(signature)) {1006throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,1007"Invalid CertificateVerify signature");1008}1009} catch (NoSuchAlgorithmException |1010InvalidAlgorithmParameterException nsae) {1011throw context.conContext.fatal(Alert.INTERNAL_ERROR,1012"Unsupported signature algorithm (" +1013signatureScheme.name +1014") used in CertificateVerify handshake message", nsae);1015} catch (InvalidKeyException | SignatureException ikse) {1016throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,1017"Cannot verify CertificateVerify signature", ikse);1018}1019}10201021@Override1022public SSLHandshake handshakeType() {1023return SSLHandshake.CERTIFICATE_VERIFY;1024}10251026@Override1027public int messageLength() {1028return 4 + signature.length; // 2: signature algorithm1029// +2: length of signature1030}10311032@Override1033public void send(HandshakeOutStream hos) throws IOException {1034hos.putInt16(signatureScheme.id);1035hos.putBytes16(signature);1036}10371038@Override1039public String toString() {1040MessageFormat messageFormat = new MessageFormat(1041"\"CertificateVerify\": '{'\n" +1042" \"signature algorithm\": {0}\n" +1043" \"signature\": '{'\n" +1044"{1}\n" +1045" '}'\n" +1046"'}'",1047Locale.ENGLISH);10481049HexDumpEncoder hexEncoder = new HexDumpEncoder();1050Object[] messageFields = {1051signatureScheme.name,1052Utilities.indent(1053hexEncoder.encodeBuffer(signature), " ")1054};10551056return messageFormat.format(messageFields);1057}1058}10591060/**1061* The "CertificateVerify" handshake message producer.1062*/1063private static final1064class T13CertificateVerifyProducer implements HandshakeProducer {1065// Prevent instantiation of this class.1066private T13CertificateVerifyProducer() {1067// blank1068}10691070@Override1071public byte[] produce(ConnectionContext context,1072HandshakeMessage message) throws IOException {1073// The producing happens in handshake context only.1074HandshakeContext hc = (HandshakeContext)context;10751076X509Possession x509Possession = null;1077for (SSLPossession possession : hc.handshakePossessions) {1078if (possession instanceof X509Possession) {1079x509Possession = (X509Possession)possession;1080break;1081}1082}10831084if (x509Possession == null ||1085x509Possession.popPrivateKey == null) {1086if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1087SSLLogger.fine(1088"No X.509 credentials negotiated for CertificateVerify");1089}10901091return null;1092}10931094if (hc.sslConfig.isClientMode) {1095return onProduceCertificateVerify(1096(ClientHandshakeContext)context, x509Possession);1097} else {1098return onProduceCertificateVerify(1099(ServerHandshakeContext)context, x509Possession);1100}1101}11021103private byte[] onProduceCertificateVerify(ServerHandshakeContext shc,1104X509Possession x509Possession) throws IOException {1105T13CertificateVerifyMessage cvm =1106new T13CertificateVerifyMessage(shc, x509Possession);1107if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1108SSLLogger.fine(1109"Produced server CertificateVerify handshake message", cvm);1110}11111112// Output the handshake message.1113cvm.write(shc.handshakeOutput);1114shc.handshakeOutput.flush();11151116// The handshake message has been delivered.1117return null;1118}11191120private byte[] onProduceCertificateVerify(ClientHandshakeContext chc,1121X509Possession x509Possession) throws IOException {1122T13CertificateVerifyMessage cvm =1123new T13CertificateVerifyMessage(chc, x509Possession);1124if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1125SSLLogger.fine(1126"Produced client CertificateVerify handshake message", cvm);1127}11281129// Output the handshake message.1130cvm.write(chc.handshakeOutput);1131chc.handshakeOutput.flush();11321133// The handshake message has been delivered.1134return null;1135}1136}11371138/**1139* The "CertificateVerify" handshake message consumer.1140*/1141private static final1142class T13CertificateVerifyConsumer implements SSLConsumer {1143// Prevent instantiation of this class.1144private T13CertificateVerifyConsumer() {1145// blank1146}11471148@Override1149public void consume(ConnectionContext context,1150ByteBuffer message) throws IOException {1151// The producing happens in handshake context only.1152HandshakeContext hc = (HandshakeContext)context;11531154// Clean up this consumer1155hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);11561157T13CertificateVerifyMessage cvm =1158new T13CertificateVerifyMessage(hc, message);1159if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {1160SSLLogger.fine(1161"Consuming CertificateVerify handshake message", cvm);1162}11631164//1165// update1166//1167// Need no additional validation.11681169//1170// produce1171//1172// Need no new handshake message producers here.1173}1174}1175}117611771178