Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/ssl/CertificateVerify.java
38830 views
1
/*
2
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
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
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.security.ssl;
27
28
import java.io.IOException;
29
import java.nio.ByteBuffer;
30
import java.security.*;
31
import java.text.MessageFormat;
32
import java.util.Arrays;
33
import java.util.Locale;
34
import java.util.Map;
35
import sun.security.ssl.SSLHandshake.HandshakeMessage;
36
import sun.security.ssl.X509Authentication.X509Credentials;
37
import sun.security.ssl.X509Authentication.X509Possession;
38
import sun.misc.HexDumpEncoder;
39
40
/**
41
* Pack of the CertificateVerify handshake message.
42
*/
43
final class CertificateVerify {
44
static final SSLConsumer s30HandshakeConsumer =
45
new S30CertificateVerifyConsumer();
46
static final HandshakeProducer s30HandshakeProducer =
47
new S30CertificateVerifyProducer();
48
49
static final SSLConsumer t10HandshakeConsumer =
50
new T10CertificateVerifyConsumer();
51
static final HandshakeProducer t10HandshakeProducer =
52
new T10CertificateVerifyProducer();
53
54
static final SSLConsumer t12HandshakeConsumer =
55
new T12CertificateVerifyConsumer();
56
static final HandshakeProducer t12HandshakeProducer =
57
new T12CertificateVerifyProducer();
58
59
static final SSLConsumer t13HandshakeConsumer =
60
new T13CertificateVerifyConsumer();
61
static final HandshakeProducer t13HandshakeProducer =
62
new T13CertificateVerifyProducer();
63
64
/**
65
* The CertificateVerify handshake message (SSL 3.0).
66
*/
67
static final class S30CertificateVerifyMessage extends HandshakeMessage {
68
// signature bytes
69
private final byte[] signature;
70
71
S30CertificateVerifyMessage(HandshakeContext context,
72
X509Possession x509Possession) throws IOException {
73
super(context);
74
75
// This happens in client side only.
76
ClientHandshakeContext chc = (ClientHandshakeContext)context;
77
byte[] temproary = null;
78
String algorithm = x509Possession.popPrivateKey.getAlgorithm();
79
try {
80
Signature signer =
81
getSignature(algorithm, x509Possession.popPrivateKey);
82
byte[] hashes = chc.handshakeHash.digest(algorithm,
83
chc.handshakeSession.getMasterSecret());
84
signer.update(hashes);
85
temproary = signer.sign();
86
} catch (NoSuchAlgorithmException nsae) {
87
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
88
"Unsupported signature algorithm (" + algorithm +
89
") used in CertificateVerify handshake message", nsae);
90
} catch (GeneralSecurityException gse) {
91
throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
92
"Cannot produce CertificateVerify signature", gse);
93
}
94
95
this.signature = temproary;
96
}
97
98
S30CertificateVerifyMessage(HandshakeContext context,
99
ByteBuffer m) throws IOException {
100
super(context);
101
102
// This happens in server side only.
103
ServerHandshakeContext shc = (ServerHandshakeContext)context;
104
105
// digitally-signed struct {
106
// select(SignatureAlgorithm) {
107
// case anonymous: struct { };
108
// case rsa:
109
// opaque md5_hash[16];
110
// opaque sha_hash[20];
111
// case dsa:
112
// opaque sha_hash[20];
113
// };
114
// } Signature;
115
if (m.remaining() < 2) {
116
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
117
"Invalid CertificateVerify message: no sufficient data");
118
}
119
120
// read and verify the signature
121
this.signature = Record.getBytes16(m);
122
X509Credentials x509Credentials = null;
123
for (SSLCredentials cd : shc.handshakeCredentials) {
124
if (cd instanceof X509Credentials) {
125
x509Credentials = (X509Credentials)cd;
126
break;
127
}
128
}
129
130
if (x509Credentials == null ||
131
x509Credentials.popPublicKey == null) {
132
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
133
"No X509 credentials negotiated for CertificateVerify");
134
}
135
136
String algorithm = x509Credentials.popPublicKey.getAlgorithm();
137
try {
138
Signature signer =
139
getSignature(algorithm, x509Credentials.popPublicKey);
140
byte[] hashes = shc.handshakeHash.digest(algorithm,
141
shc.handshakeSession.getMasterSecret());
142
signer.update(hashes);
143
if (!signer.verify(signature)) {
144
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
145
"Invalid CertificateVerify message: invalid signature");
146
}
147
} catch (NoSuchAlgorithmException nsae) {
148
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
149
"Unsupported signature algorithm (" + algorithm +
150
") used in CertificateVerify handshake message", nsae);
151
} catch (GeneralSecurityException gse) {
152
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
153
"Cannot verify CertificateVerify signature", gse);
154
}
155
}
156
157
@Override
158
public SSLHandshake handshakeType() {
159
return SSLHandshake.CERTIFICATE_VERIFY;
160
}
161
162
@Override
163
public int messageLength() {
164
return 2 + signature.length; // 2: length of signature
165
}
166
167
@Override
168
public void send(HandshakeOutStream hos) throws IOException {
169
hos.putBytes16(signature);
170
}
171
172
@Override
173
public String toString() {
174
MessageFormat messageFormat = new MessageFormat(
175
"\"CertificateVerify\": '{'\n" +
176
" \"signature\": '{'\n" +
177
"{0}\n" +
178
" '}'\n" +
179
"'}'",
180
Locale.ENGLISH);
181
182
HexDumpEncoder hexEncoder = new HexDumpEncoder();
183
Object[] messageFields = {
184
Utilities.indent(
185
hexEncoder.encodeBuffer(signature), " ")
186
};
187
188
return messageFormat.format(messageFields);
189
}
190
191
/*
192
* Get the Signature object appropriate for verification using the
193
* given signature algorithm.
194
*/
195
private static Signature getSignature(String algorithm,
196
Key key) throws GeneralSecurityException {
197
Signature signer = null;
198
switch (algorithm) {
199
case "RSA":
200
signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA);
201
break;
202
case "DSA":
203
signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA);
204
break;
205
case "EC":
206
signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA);
207
break;
208
default:
209
throw new SignatureException("Unrecognized algorithm: "
210
+ algorithm);
211
}
212
213
if (signer != null) {
214
if (key instanceof PublicKey) {
215
signer.initVerify((PublicKey)(key));
216
} else {
217
signer.initSign((PrivateKey)key);
218
}
219
}
220
221
return signer;
222
}
223
}
224
225
/**
226
* The "CertificateVerify" handshake message producer.
227
*/
228
private static final
229
class S30CertificateVerifyProducer implements HandshakeProducer {
230
// Prevent instantiation of this class.
231
private S30CertificateVerifyProducer() {
232
// blank
233
}
234
235
@Override
236
public byte[] produce(ConnectionContext context,
237
HandshakeMessage message) throws IOException {
238
// The producing happens in client side only.
239
ClientHandshakeContext chc = (ClientHandshakeContext)context;
240
241
X509Possession x509Possession = null;
242
for (SSLPossession possession : chc.handshakePossessions) {
243
if (possession instanceof X509Possession) {
244
x509Possession = (X509Possession)possession;
245
break;
246
}
247
}
248
249
if (x509Possession == null ||
250
x509Possession.popPrivateKey == null) {
251
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
252
SSLLogger.fine(
253
"No X.509 credentials negotiated for CertificateVerify");
254
}
255
256
return null;
257
}
258
259
S30CertificateVerifyMessage cvm =
260
new S30CertificateVerifyMessage(chc, x509Possession);
261
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
262
SSLLogger.fine(
263
"Produced CertificateVerify handshake message", cvm);
264
}
265
266
// Output the handshake message.
267
cvm.write(chc.handshakeOutput);
268
chc.handshakeOutput.flush();
269
270
// The handshake message has been delivered.
271
return null;
272
}
273
}
274
275
/**
276
* The "CertificateVerify" handshake message consumer.
277
*/
278
private static final
279
class S30CertificateVerifyConsumer implements SSLConsumer {
280
// Prevent instantiation of this class.
281
private S30CertificateVerifyConsumer() {
282
// blank
283
}
284
285
@Override
286
public void consume(ConnectionContext context,
287
ByteBuffer message) throws IOException {
288
// The consuming happens in server side only.
289
ServerHandshakeContext shc = (ServerHandshakeContext)context;
290
291
// Clean up this consumer
292
shc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);
293
294
// Ensure that the CV message follows the CKE
295
if (shc.handshakeConsumers.containsKey(
296
SSLHandshake.CLIENT_KEY_EXCHANGE.id)) {
297
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
298
"Unexpected CertificateVerify handshake message");
299
}
300
301
S30CertificateVerifyMessage cvm =
302
new S30CertificateVerifyMessage(shc, message);
303
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
304
SSLLogger.fine(
305
"Consuming CertificateVerify handshake message", cvm);
306
}
307
308
//
309
// update
310
//
311
// Need no additional validation.
312
313
//
314
// produce
315
//
316
// Need no new handshake message producers here.
317
}
318
}
319
320
/**
321
* The CertificateVerify handshake message (TLS 1.0/1.1).
322
*/
323
static final class T10CertificateVerifyMessage extends HandshakeMessage {
324
// signature bytes
325
private final byte[] signature;
326
327
T10CertificateVerifyMessage(HandshakeContext context,
328
X509Possession x509Possession) throws IOException {
329
super(context);
330
331
// This happens in client side only.
332
ClientHandshakeContext chc = (ClientHandshakeContext)context;
333
byte[] temproary = null;
334
String algorithm = x509Possession.popPrivateKey.getAlgorithm();
335
try {
336
Signature signer =
337
getSignature(algorithm, x509Possession.popPrivateKey);
338
byte[] hashes = chc.handshakeHash.digest(algorithm);
339
signer.update(hashes);
340
temproary = signer.sign();
341
} catch (NoSuchAlgorithmException nsae) {
342
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
343
"Unsupported signature algorithm (" + algorithm +
344
") used in CertificateVerify handshake message", nsae);
345
} catch (GeneralSecurityException gse) {
346
throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
347
"Cannot produce CertificateVerify signature", gse);
348
}
349
350
this.signature = temproary;
351
}
352
353
T10CertificateVerifyMessage(HandshakeContext context,
354
ByteBuffer m) throws IOException {
355
super(context);
356
357
// This happens in server side only.
358
ServerHandshakeContext shc = (ServerHandshakeContext)context;
359
360
// digitally-signed struct {
361
// select(SignatureAlgorithm) {
362
// case anonymous: struct { };
363
// case rsa:
364
// opaque md5_hash[16];
365
// opaque sha_hash[20];
366
// case dsa:
367
// opaque sha_hash[20];
368
// };
369
// } Signature;
370
if (m.remaining() < 2) {
371
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
372
"Invalid CertificateVerify message: no sufficient data");
373
}
374
375
// read and verify the signature
376
this.signature = Record.getBytes16(m);
377
X509Credentials x509Credentials = null;
378
for (SSLCredentials cd : shc.handshakeCredentials) {
379
if (cd instanceof X509Credentials) {
380
x509Credentials = (X509Credentials)cd;
381
break;
382
}
383
}
384
385
if (x509Credentials == null ||
386
x509Credentials.popPublicKey == null) {
387
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
388
"No X509 credentials negotiated for CertificateVerify");
389
}
390
391
String algorithm = x509Credentials.popPublicKey.getAlgorithm();
392
try {
393
Signature signer =
394
getSignature(algorithm, x509Credentials.popPublicKey);
395
byte[] hashes = shc.handshakeHash.digest(algorithm);
396
signer.update(hashes);
397
if (!signer.verify(signature)) {
398
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
399
"Invalid CertificateVerify message: invalid signature");
400
}
401
} catch (NoSuchAlgorithmException nsae) {
402
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
403
"Unsupported signature algorithm (" + algorithm +
404
") used in CertificateVerify handshake message", nsae);
405
} catch (GeneralSecurityException gse) {
406
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
407
"Cannot verify CertificateVerify signature", gse);
408
}
409
}
410
411
@Override
412
public SSLHandshake handshakeType() {
413
return SSLHandshake.CERTIFICATE_VERIFY;
414
}
415
416
@Override
417
public int messageLength() {
418
return 2 + signature.length; // 2: length of signature
419
}
420
421
@Override
422
public void send(HandshakeOutStream hos) throws IOException {
423
hos.putBytes16(signature);
424
}
425
426
@Override
427
public String toString() {
428
MessageFormat messageFormat = new MessageFormat(
429
"\"CertificateVerify\": '{'\n" +
430
" \"signature\": '{'\n" +
431
"{0}\n" +
432
" '}'\n" +
433
"'}'",
434
Locale.ENGLISH);
435
436
HexDumpEncoder hexEncoder = new HexDumpEncoder();
437
Object[] messageFields = {
438
Utilities.indent(
439
hexEncoder.encodeBuffer(signature), " ")
440
};
441
442
return messageFormat.format(messageFields);
443
}
444
445
/*
446
* Get the Signature object appropriate for verification using the
447
* given signature algorithm.
448
*/
449
private static Signature getSignature(String algorithm,
450
Key key) throws GeneralSecurityException {
451
Signature signer = null;
452
switch (algorithm) {
453
case "RSA":
454
signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA);
455
break;
456
case "DSA":
457
signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA);
458
break;
459
case "EC":
460
signer = JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA);
461
break;
462
default:
463
throw new SignatureException("Unrecognized algorithm: "
464
+ algorithm);
465
}
466
467
if (signer != null) {
468
if (key instanceof PublicKey) {
469
signer.initVerify((PublicKey)(key));
470
} else {
471
signer.initSign((PrivateKey)key);
472
}
473
}
474
475
return signer;
476
}
477
}
478
479
/**
480
* The "CertificateVerify" handshake message producer.
481
*/
482
private static final
483
class T10CertificateVerifyProducer implements HandshakeProducer {
484
// Prevent instantiation of this class.
485
private T10CertificateVerifyProducer() {
486
// blank
487
}
488
489
@Override
490
public byte[] produce(ConnectionContext context,
491
HandshakeMessage message) throws IOException {
492
// The producing happens in client side only.
493
ClientHandshakeContext chc = (ClientHandshakeContext)context;
494
X509Possession x509Possession = null;
495
for (SSLPossession possession : chc.handshakePossessions) {
496
if (possession instanceof X509Possession) {
497
x509Possession = (X509Possession)possession;
498
break;
499
}
500
}
501
502
if (x509Possession == null ||
503
x509Possession.popPrivateKey == null) {
504
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
505
SSLLogger.fine(
506
"No X.509 credentials negotiated for CertificateVerify");
507
}
508
509
return null;
510
}
511
512
T10CertificateVerifyMessage cvm =
513
new T10CertificateVerifyMessage(chc, x509Possession);
514
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
515
SSLLogger.fine(
516
"Produced CertificateVerify handshake message", cvm);
517
}
518
519
// Output the handshake message.
520
cvm.write(chc.handshakeOutput);
521
chc.handshakeOutput.flush();
522
523
// The handshake message has been delivered.
524
return null;
525
}
526
}
527
528
/**
529
* The "CertificateVerify" handshake message consumer.
530
*/
531
private static final
532
class T10CertificateVerifyConsumer implements SSLConsumer {
533
// Prevent instantiation of this class.
534
private T10CertificateVerifyConsumer() {
535
// blank
536
}
537
538
@Override
539
public void consume(ConnectionContext context,
540
ByteBuffer message) throws IOException {
541
// The consuming happens in server side only.
542
ServerHandshakeContext shc = (ServerHandshakeContext)context;
543
544
// Clean up this consumer
545
shc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);
546
547
// Ensure that the CV message follows the CKE
548
if (shc.handshakeConsumers.containsKey(
549
SSLHandshake.CLIENT_KEY_EXCHANGE.id)) {
550
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
551
"Unexpected CertificateVerify handshake message");
552
}
553
554
T10CertificateVerifyMessage cvm =
555
new T10CertificateVerifyMessage(shc, message);
556
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
557
SSLLogger.fine(
558
"Consuming CertificateVerify handshake message", cvm);
559
}
560
561
//
562
// update
563
//
564
// Need no additional validation.
565
566
//
567
// produce
568
//
569
// Need no new handshake message producers here. }
570
}
571
}
572
573
/**
574
* The CertificateVerify handshake message (TLS 1.2).
575
*/
576
static final class T12CertificateVerifyMessage extends HandshakeMessage {
577
// the signature algorithm
578
private final SignatureScheme signatureScheme;
579
580
// signature bytes
581
private final byte[] signature;
582
583
T12CertificateVerifyMessage(HandshakeContext context,
584
X509Possession x509Possession) throws IOException {
585
super(context);
586
587
// This happens in client side only.
588
ClientHandshakeContext chc = (ClientHandshakeContext)context;
589
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
590
SignatureScheme.getSignerOfPreferableAlgorithm(
591
chc.peerRequestedSignatureSchemes,
592
x509Possession,
593
chc.negotiatedProtocol);
594
if (schemeAndSigner == null) {
595
// Unlikely, the credentials generator should have
596
// selected the preferable signature algorithm properly.
597
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
598
"No supported CertificateVerify signature algorithm for " +
599
x509Possession.popPrivateKey.getAlgorithm() +
600
" key");
601
}
602
603
this.signatureScheme = schemeAndSigner.getKey();
604
byte[] temproary = null;
605
try {
606
Signature signer = schemeAndSigner.getValue();
607
signer.update(chc.handshakeHash.archived());
608
temproary = signer.sign();
609
} catch (SignatureException ikse) {
610
throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
611
"Cannot produce CertificateVerify signature", ikse);
612
}
613
614
this.signature = temproary;
615
}
616
617
T12CertificateVerifyMessage(HandshakeContext handshakeContext,
618
ByteBuffer m) throws IOException {
619
super(handshakeContext);
620
621
// This happens in server side only.
622
ServerHandshakeContext shc =
623
(ServerHandshakeContext)handshakeContext;
624
625
// struct {
626
// SignatureAndHashAlgorithm algorithm;
627
// opaque signature<0..2^16-1>;
628
// } DigitallySigned;
629
if (m.remaining() < 4) {
630
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
631
"Invalid CertificateVerify message: no sufficient data");
632
}
633
634
// SignatureAndHashAlgorithm algorithm
635
int ssid = Record.getInt16(m);
636
this.signatureScheme = SignatureScheme.valueOf(ssid);
637
if (signatureScheme == null) {
638
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
639
"Invalid signature algorithm (" + ssid +
640
") used in CertificateVerify handshake message");
641
}
642
643
if (!shc.localSupportedSignAlgs.contains(signatureScheme)) {
644
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
645
"Unsupported signature algorithm (" +
646
signatureScheme.name +
647
") used in CertificateVerify handshake message");
648
}
649
650
// read and verify the signature
651
X509Credentials x509Credentials = null;
652
for (SSLCredentials cd : shc.handshakeCredentials) {
653
if (cd instanceof X509Credentials) {
654
x509Credentials = (X509Credentials)cd;
655
break;
656
}
657
}
658
659
if (x509Credentials == null ||
660
x509Credentials.popPublicKey == null) {
661
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
662
"No X509 credentials negotiated for CertificateVerify");
663
}
664
665
// opaque signature<0..2^16-1>;
666
this.signature = Record.getBytes16(m);
667
try {
668
Signature signer =
669
signatureScheme.getVerifier(x509Credentials.popPublicKey);
670
signer.update(shc.handshakeHash.archived());
671
if (!signer.verify(signature)) {
672
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
673
"Invalid CertificateVerify signature");
674
}
675
} catch (NoSuchAlgorithmException |
676
InvalidAlgorithmParameterException nsae) {
677
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
678
"Unsupported signature algorithm (" +
679
signatureScheme.name +
680
") used in CertificateVerify handshake message", nsae);
681
} catch (InvalidKeyException | SignatureException ikse) {
682
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
683
"Cannot verify CertificateVerify signature", ikse);
684
}
685
}
686
687
@Override
688
public SSLHandshake handshakeType() {
689
return SSLHandshake.CERTIFICATE_VERIFY;
690
}
691
692
@Override
693
public int messageLength() {
694
return 4 + signature.length; // 2: signature algorithm
695
// +2: length of signature
696
}
697
698
@Override
699
public void send(HandshakeOutStream hos) throws IOException {
700
hos.putInt16(signatureScheme.id);
701
hos.putBytes16(signature);
702
}
703
704
@Override
705
public String toString() {
706
MessageFormat messageFormat = new MessageFormat(
707
"\"CertificateVerify\": '{'\n" +
708
" \"signature algorithm\": {0}\n" +
709
" \"signature\": '{'\n" +
710
"{1}\n" +
711
" '}'\n" +
712
"'}'",
713
Locale.ENGLISH);
714
715
HexDumpEncoder hexEncoder = new HexDumpEncoder();
716
Object[] messageFields = {
717
signatureScheme.name,
718
Utilities.indent(
719
hexEncoder.encodeBuffer(signature), " ")
720
};
721
722
return messageFormat.format(messageFields);
723
}
724
}
725
726
/**
727
* The "CertificateVerify" handshake message producer.
728
*/
729
private static final
730
class T12CertificateVerifyProducer implements HandshakeProducer {
731
// Prevent instantiation of this class.
732
private T12CertificateVerifyProducer() {
733
// blank
734
}
735
736
@Override
737
public byte[] produce(ConnectionContext context,
738
HandshakeMessage message) throws IOException {
739
// The producing happens in client side only.
740
ClientHandshakeContext chc = (ClientHandshakeContext)context;
741
742
X509Possession x509Possession = null;
743
for (SSLPossession possession : chc.handshakePossessions) {
744
if (possession instanceof X509Possession) {
745
x509Possession = (X509Possession)possession;
746
break;
747
}
748
}
749
750
if (x509Possession == null ||
751
x509Possession.popPrivateKey == null) {
752
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
753
SSLLogger.fine(
754
"No X.509 credentials negotiated for CertificateVerify");
755
}
756
757
return null;
758
}
759
760
T12CertificateVerifyMessage cvm =
761
new T12CertificateVerifyMessage(chc, x509Possession);
762
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
763
SSLLogger.fine(
764
"Produced CertificateVerify handshake message", cvm);
765
}
766
767
// Output the handshake message.
768
cvm.write(chc.handshakeOutput);
769
chc.handshakeOutput.flush();
770
771
// The handshake message has been delivered.
772
return null;
773
}
774
}
775
776
/**
777
* The "CertificateVerify" handshake message consumer.
778
*/
779
private static final
780
class T12CertificateVerifyConsumer implements SSLConsumer {
781
// Prevent instantiation of this class.
782
private T12CertificateVerifyConsumer() {
783
// blank
784
}
785
786
@Override
787
public void consume(ConnectionContext context,
788
ByteBuffer message) throws IOException {
789
// The consuming happens in server side only.
790
ServerHandshakeContext shc = (ServerHandshakeContext)context;
791
792
// Clean up this consumer
793
shc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);
794
795
// Ensure that the CV message follows the CKE
796
if (shc.handshakeConsumers.containsKey(
797
SSLHandshake.CLIENT_KEY_EXCHANGE.id)) {
798
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
799
"Unexpected CertificateVerify handshake message");
800
}
801
802
T12CertificateVerifyMessage cvm =
803
new T12CertificateVerifyMessage(shc, message);
804
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
805
SSLLogger.fine(
806
"Consuming CertificateVerify handshake message", cvm);
807
}
808
809
//
810
// update
811
//
812
// Need no additional validation.
813
814
//
815
// produce
816
//
817
// Need no new handshake message producers here.
818
}
819
}
820
821
/**
822
* The CertificateVerify handshake message (TLS 1.3).
823
*/
824
static final class T13CertificateVerifyMessage extends HandshakeMessage {
825
private static final byte[] serverSignHead = new byte[] {
826
// repeated 0x20 for 64 times
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,
842
(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,
843
844
// "TLS 1.3, server CertificateVerify" + 0x00
845
(byte)0x54, (byte)0x4c, (byte)0x53, (byte)0x20,
846
(byte)0x31, (byte)0x2e, (byte)0x33, (byte)0x2c,
847
(byte)0x20, (byte)0x73, (byte)0x65, (byte)0x72,
848
(byte)0x76, (byte)0x65, (byte)0x72, (byte)0x20,
849
(byte)0x43, (byte)0x65, (byte)0x72, (byte)0x74,
850
(byte)0x69, (byte)0x66, (byte)0x69, (byte)0x63,
851
(byte)0x61, (byte)0x74, (byte)0x65, (byte)0x56,
852
(byte)0x65, (byte)0x72, (byte)0x69, (byte)0x66,
853
(byte)0x79, (byte)0x00
854
};
855
856
private static final byte[] clientSignHead = new byte[] {
857
// repeated 0x20 for 64 times
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,
873
(byte)0x20, (byte)0x20, (byte)0x20, (byte)0x20,
874
875
// "TLS 1.3, client CertificateVerify" + 0x00
876
(byte)0x54, (byte)0x4c, (byte)0x53, (byte)0x20,
877
(byte)0x31, (byte)0x2e, (byte)0x33, (byte)0x2c,
878
(byte)0x20, (byte)0x63, (byte)0x6c, (byte)0x69,
879
(byte)0x65, (byte)0x6e, (byte)0x74, (byte)0x20,
880
(byte)0x43, (byte)0x65, (byte)0x72, (byte)0x74,
881
(byte)0x69, (byte)0x66, (byte)0x69, (byte)0x63,
882
(byte)0x61, (byte)0x74, (byte)0x65, (byte)0x56,
883
(byte)0x65, (byte)0x72, (byte)0x69, (byte)0x66,
884
(byte)0x79, (byte)0x00
885
};
886
887
888
// the signature algorithm
889
private final SignatureScheme signatureScheme;
890
891
// signature bytes
892
private final byte[] signature;
893
894
T13CertificateVerifyMessage(HandshakeContext context,
895
X509Possession x509Possession) throws IOException {
896
super(context);
897
898
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
899
SignatureScheme.getSignerOfPreferableAlgorithm(
900
context.peerRequestedSignatureSchemes,
901
x509Possession,
902
context.negotiatedProtocol);
903
if (schemeAndSigner == null) {
904
// Unlikely, the credentials generator should have
905
// selected the preferable signature algorithm properly.
906
throw context.conContext.fatal(Alert.INTERNAL_ERROR,
907
"No supported CertificateVerify signature algorithm for " +
908
x509Possession.popPrivateKey.getAlgorithm() +
909
" key");
910
}
911
912
this.signatureScheme = schemeAndSigner.getKey();
913
914
byte[] hashValue = context.handshakeHash.digest();
915
byte[] contentCovered;
916
if (context.sslConfig.isClientMode) {
917
contentCovered = Arrays.copyOf(clientSignHead,
918
clientSignHead.length + hashValue.length);
919
System.arraycopy(hashValue, 0, contentCovered,
920
clientSignHead.length, hashValue.length);
921
} else {
922
contentCovered = Arrays.copyOf(serverSignHead,
923
serverSignHead.length + hashValue.length);
924
System.arraycopy(hashValue, 0, contentCovered,
925
serverSignHead.length, hashValue.length);
926
}
927
928
byte[] temproary = null;
929
try {
930
Signature signer = schemeAndSigner.getValue();
931
signer.update(contentCovered);
932
temproary = signer.sign();
933
} catch (SignatureException ikse) {
934
throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
935
"Cannot produce CertificateVerify signature", ikse);
936
}
937
938
this.signature = temproary;
939
}
940
941
T13CertificateVerifyMessage(HandshakeContext context,
942
ByteBuffer m) throws IOException {
943
super(context);
944
945
// struct {
946
// SignatureAndHashAlgorithm algorithm;
947
// opaque signature<0..2^16-1>;
948
// } DigitallySigned;
949
if (m.remaining() < 4) {
950
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
951
"Invalid CertificateVerify message: no sufficient data");
952
}
953
954
// SignatureAndHashAlgorithm algorithm
955
int ssid = Record.getInt16(m);
956
this.signatureScheme = SignatureScheme.valueOf(ssid);
957
if (signatureScheme == null) {
958
throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
959
"Invalid signature algorithm (" + ssid +
960
") used in CertificateVerify handshake message");
961
}
962
963
if (!context.localSupportedSignAlgs.contains(signatureScheme)) {
964
throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
965
"Unsupported signature algorithm (" +
966
signatureScheme.name +
967
") used in CertificateVerify handshake message");
968
}
969
970
// read and verify the signature
971
X509Credentials x509Credentials = null;
972
for (SSLCredentials cd : context.handshakeCredentials) {
973
if (cd instanceof X509Credentials) {
974
x509Credentials = (X509Credentials)cd;
975
break;
976
}
977
}
978
979
if (x509Credentials == null ||
980
x509Credentials.popPublicKey == null) {
981
throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
982
"No X509 credentials negotiated for CertificateVerify");
983
}
984
985
// opaque signature<0..2^16-1>;
986
this.signature = Record.getBytes16(m);
987
988
byte[] hashValue = context.handshakeHash.digest();
989
byte[] contentCovered;
990
if (context.sslConfig.isClientMode) {
991
contentCovered = Arrays.copyOf(serverSignHead,
992
serverSignHead.length + hashValue.length);
993
System.arraycopy(hashValue, 0, contentCovered,
994
serverSignHead.length, hashValue.length);
995
} else {
996
contentCovered = Arrays.copyOf(clientSignHead,
997
clientSignHead.length + hashValue.length);
998
System.arraycopy(hashValue, 0, contentCovered,
999
clientSignHead.length, hashValue.length);
1000
}
1001
1002
try {
1003
Signature signer =
1004
signatureScheme.getVerifier(x509Credentials.popPublicKey);
1005
signer.update(contentCovered);
1006
if (!signer.verify(signature)) {
1007
throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1008
"Invalid CertificateVerify signature");
1009
}
1010
} catch (NoSuchAlgorithmException |
1011
InvalidAlgorithmParameterException nsae) {
1012
throw context.conContext.fatal(Alert.INTERNAL_ERROR,
1013
"Unsupported signature algorithm (" +
1014
signatureScheme.name +
1015
") used in CertificateVerify handshake message", nsae);
1016
} catch (InvalidKeyException | SignatureException ikse) {
1017
throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1018
"Cannot verify CertificateVerify signature", ikse);
1019
}
1020
}
1021
1022
@Override
1023
public SSLHandshake handshakeType() {
1024
return SSLHandshake.CERTIFICATE_VERIFY;
1025
}
1026
1027
@Override
1028
public int messageLength() {
1029
return 4 + signature.length; // 2: signature algorithm
1030
// +2: length of signature
1031
}
1032
1033
@Override
1034
public void send(HandshakeOutStream hos) throws IOException {
1035
hos.putInt16(signatureScheme.id);
1036
hos.putBytes16(signature);
1037
}
1038
1039
@Override
1040
public String toString() {
1041
MessageFormat messageFormat = new MessageFormat(
1042
"\"CertificateVerify\": '{'\n" +
1043
" \"signature algorithm\": {0}\n" +
1044
" \"signature\": '{'\n" +
1045
"{1}\n" +
1046
" '}'\n" +
1047
"'}'",
1048
Locale.ENGLISH);
1049
1050
HexDumpEncoder hexEncoder = new HexDumpEncoder();
1051
Object[] messageFields = {
1052
signatureScheme.name,
1053
Utilities.indent(
1054
hexEncoder.encodeBuffer(signature), " ")
1055
};
1056
1057
return messageFormat.format(messageFields);
1058
}
1059
}
1060
1061
/**
1062
* The "CertificateVerify" handshake message producer.
1063
*/
1064
private static final
1065
class T13CertificateVerifyProducer implements HandshakeProducer {
1066
// Prevent instantiation of this class.
1067
private T13CertificateVerifyProducer() {
1068
// blank
1069
}
1070
1071
@Override
1072
public byte[] produce(ConnectionContext context,
1073
HandshakeMessage message) throws IOException {
1074
// The producing happens in handshake context only.
1075
HandshakeContext hc = (HandshakeContext)context;
1076
1077
X509Possession x509Possession = null;
1078
for (SSLPossession possession : hc.handshakePossessions) {
1079
if (possession instanceof X509Possession) {
1080
x509Possession = (X509Possession)possession;
1081
break;
1082
}
1083
}
1084
1085
if (x509Possession == null ||
1086
x509Possession.popPrivateKey == null) {
1087
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1088
SSLLogger.fine(
1089
"No X.509 credentials negotiated for CertificateVerify");
1090
}
1091
1092
return null;
1093
}
1094
1095
if (hc.sslConfig.isClientMode) {
1096
return onProduceCertificateVerify(
1097
(ClientHandshakeContext)context, x509Possession);
1098
} else {
1099
return onProduceCertificateVerify(
1100
(ServerHandshakeContext)context, x509Possession);
1101
}
1102
}
1103
1104
private byte[] onProduceCertificateVerify(ServerHandshakeContext shc,
1105
X509Possession x509Possession) throws IOException {
1106
T13CertificateVerifyMessage cvm =
1107
new T13CertificateVerifyMessage(shc, x509Possession);
1108
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1109
SSLLogger.fine(
1110
"Produced server CertificateVerify handshake message", cvm);
1111
}
1112
1113
// Output the handshake message.
1114
cvm.write(shc.handshakeOutput);
1115
shc.handshakeOutput.flush();
1116
1117
// The handshake message has been delivered.
1118
return null;
1119
}
1120
1121
private byte[] onProduceCertificateVerify(ClientHandshakeContext chc,
1122
X509Possession x509Possession) throws IOException {
1123
T13CertificateVerifyMessage cvm =
1124
new T13CertificateVerifyMessage(chc, x509Possession);
1125
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1126
SSLLogger.fine(
1127
"Produced client CertificateVerify handshake message", cvm);
1128
}
1129
1130
// Output the handshake message.
1131
cvm.write(chc.handshakeOutput);
1132
chc.handshakeOutput.flush();
1133
1134
// The handshake message has been delivered.
1135
return null;
1136
}
1137
}
1138
1139
/**
1140
* The "CertificateVerify" handshake message consumer.
1141
*/
1142
private static final
1143
class T13CertificateVerifyConsumer implements SSLConsumer {
1144
// Prevent instantiation of this class.
1145
private T13CertificateVerifyConsumer() {
1146
// blank
1147
}
1148
1149
@Override
1150
public void consume(ConnectionContext context,
1151
ByteBuffer message) throws IOException {
1152
// The producing happens in handshake context only.
1153
HandshakeContext hc = (HandshakeContext)context;
1154
1155
// Clean up this consumer
1156
hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id);
1157
1158
T13CertificateVerifyMessage cvm =
1159
new T13CertificateVerifyMessage(hc, message);
1160
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1161
SSLLogger.fine(
1162
"Consuming CertificateVerify handshake message", cvm);
1163
}
1164
1165
//
1166
// update
1167
//
1168
// Need no additional validation.
1169
1170
//
1171
// produce
1172
//
1173
// Need no new handshake message producers here.
1174
}
1175
}
1176
}
1177
1178