public void processServerCertificate(Certificate serverCertificate) throws IOException { if (serverCertificate.isEmpty()) { throw new TlsFatalAlert(AlertDescription.bad_certificate); } org.ripple.bouncycastle.asn1.x509.Certificate x509Cert = serverCertificate.getCertificateAt(0); SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo(); try { this.serverPublicKey = PublicKeyFactory.createKey(keyInfo); } catch (RuntimeException e) { throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e); } if (tlsSigner == null) { try { this.dhAgreePublicKey = TlsDHUtils.validateDHPublicKey((DHPublicKeyParameters) this.serverPublicKey); this.dhParameters = validateDHParameters(dhAgreePublicKey.getParameters()); } catch (ClassCastException e) { throw new TlsFatalAlert(AlertDescription.certificate_unknown, e); } TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyAgreement); } else { if (!tlsSigner.isValidPublicKey(this.serverPublicKey)) { throw new TlsFatalAlert(AlertDescription.certificate_unknown); } TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature); } super.processServerCertificate(serverCertificate); }
public DefaultTlsSignerCredentials( TlsContext context, Certificate certificate, AsymmetricKeyParameter privateKey, SignatureAndHashAlgorithm signatureAndHashAlgorithm) { if (certificate == null) { throw new IllegalArgumentException("'certificate' cannot be null"); } if (certificate.isEmpty()) { throw new IllegalArgumentException("'certificate' cannot be empty"); } if (privateKey == null) { throw new IllegalArgumentException("'privateKey' cannot be null"); } if (!privateKey.isPrivate()) { throw new IllegalArgumentException("'privateKey' must be private"); } if (TlsUtils.isTLSv12(context) && signatureAndHashAlgorithm == null) { throw new IllegalArgumentException( "'signatureAndHashAlgorithm' cannot be null for (D)TLS 1.2+"); } if (privateKey instanceof RSAKeyParameters) { this.signer = new TlsRSASigner(); } else if (privateKey instanceof DSAPrivateKeyParameters) { this.signer = new TlsDSSSigner(); } else if (privateKey instanceof ECPrivateKeyParameters) { this.signer = new TlsECDSASigner(); } else { throw new IllegalArgumentException( "'privateKey' type not supported: " + privateKey.getClass().getName()); } this.signer.init(context); this.context = context; this.certificate = certificate; this.privateKey = privateKey; this.signatureAndHashAlgorithm = signatureAndHashAlgorithm; }
protected void notifyClientCertificate(ServerHandshakeState state, Certificate clientCertificate) throws IOException { if (state.certificateRequest == null) { throw new IllegalStateException(); } if (state.clientCertificate != null) { throw new TlsFatalAlert(AlertDescription.unexpected_message); } state.clientCertificate = clientCertificate; if (clientCertificate.isEmpty()) { state.keyExchange.skipClientCredentials(); } else { /* * TODO RFC 5246 7.4.6. If the certificate_authorities list in the certificate request * message was non-empty, one of the certificates in the certificate chain SHOULD be * issued by one of the listed CAs. */ state.clientCertificateType = TlsUtils.getClientCertificateType( clientCertificate, state.serverCredentials.getCertificate()); state.keyExchange.processClientCertificate(clientCertificate); } /* * RFC 5246 7.4.6. If the client does not send any certificates, the server MAY at its * discretion either continue the handshake without client authentication, or respond with a * fatal handshake_failure alert. Also, if some aspect of the certificate chain was * unacceptable (e.g., it was not signed by a known, trusted CA), the server MAY at its * discretion either continue the handshake (considering the client unauthenticated) or send * a fatal alert. */ state.server.notifyClientCertificate(clientCertificate); }
protected DTLSTransport serverHandshake(ServerHandshakeState state, DTLSRecordLayer recordLayer) throws IOException { SecurityParameters securityParameters = state.serverContext.getSecurityParameters(); DTLSReliableHandshake handshake = new DTLSReliableHandshake(state.serverContext, recordLayer); DTLSReliableHandshake.Message clientMessage = handshake.receiveMessage(); { // NOTE: After receiving a record from the client, we discover the record layer version ProtocolVersion client_version = recordLayer.getDiscoveredPeerVersion(); // TODO Read RFCs for guidance on the expected record layer version number state.serverContext.setClientVersion(client_version); } if (clientMessage.getType() == HandshakeType.client_hello) { processClientHello(state, clientMessage.getBody()); } else { throw new TlsFatalAlert(AlertDescription.unexpected_message); } { byte[] serverHelloBody = generateServerHello(state); if (state.maxFragmentLength >= 0) { int plainTextLimit = 1 << (8 + state.maxFragmentLength); recordLayer.setPlaintextLimit(plainTextLimit); } securityParameters.cipherSuite = state.selectedCipherSuite; securityParameters.compressionAlgorithm = state.selectedCompressionMethod; securityParameters.prfAlgorithm = TlsProtocol.getPRFAlgorithm(state.serverContext, state.selectedCipherSuite); /* * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length * has a verify_data_length equal to 12. This includes all existing cipher suites. */ securityParameters.verifyDataLength = 12; handshake.sendMessage(HandshakeType.server_hello, serverHelloBody); } handshake.notifyHelloComplete(); Vector serverSupplementalData = state.server.getServerSupplementalData(); if (serverSupplementalData != null) { byte[] supplementalDataBody = generateSupplementalData(serverSupplementalData); handshake.sendMessage(HandshakeType.supplemental_data, supplementalDataBody); } state.keyExchange = state.server.getKeyExchange(); state.keyExchange.init(state.serverContext); state.serverCredentials = state.server.getCredentials(); Certificate serverCertificate = null; if (state.serverCredentials == null) { state.keyExchange.skipServerCredentials(); } else { state.keyExchange.processServerCredentials(state.serverCredentials); serverCertificate = state.serverCredentials.getCertificate(); byte[] certificateBody = generateCertificate(serverCertificate); handshake.sendMessage(HandshakeType.certificate, certificateBody); } // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes // CertificateStatus if (serverCertificate == null || serverCertificate.isEmpty()) { state.allowCertificateStatus = false; } if (state.allowCertificateStatus) { CertificateStatus certificateStatus = state.server.getCertificateStatus(); if (certificateStatus != null) { byte[] certificateStatusBody = generateCertificateStatus(state, certificateStatus); handshake.sendMessage(HandshakeType.certificate_status, certificateStatusBody); } } byte[] serverKeyExchange = state.keyExchange.generateServerKeyExchange(); if (serverKeyExchange != null) { handshake.sendMessage(HandshakeType.server_key_exchange, serverKeyExchange); } if (state.serverCredentials != null) { state.certificateRequest = state.server.getCertificateRequest(); if (state.certificateRequest != null) { state.keyExchange.validateCertificateRequest(state.certificateRequest); byte[] certificateRequestBody = generateCertificateRequest(state, state.certificateRequest); handshake.sendMessage(HandshakeType.certificate_request, certificateRequestBody); TlsUtils.trackHashAlgorithms( handshake.getHandshakeHash(), state.certificateRequest.getSupportedSignatureAlgorithms()); } } handshake.sendMessage(HandshakeType.server_hello_done, TlsUtils.EMPTY_BYTES); handshake.getHandshakeHash().sealHashAlgorithms(); clientMessage = handshake.receiveMessage(); if (clientMessage.getType() == HandshakeType.supplemental_data) { processClientSupplementalData(state, clientMessage.getBody()); clientMessage = handshake.receiveMessage(); } else { state.server.processClientSupplementalData(null); } if (state.certificateRequest == null) { state.keyExchange.skipClientCredentials(); } else { if (clientMessage.getType() == HandshakeType.certificate) { processClientCertificate(state, clientMessage.getBody()); clientMessage = handshake.receiveMessage(); } else { if (TlsUtils.isTLSv12(state.serverContext)) { /* * RFC 5246 If no suitable certificate is available, the client MUST send a * certificate message containing no certificates. * * NOTE: In previous RFCs, this was SHOULD instead of MUST. */ throw new TlsFatalAlert(AlertDescription.unexpected_message); } notifyClientCertificate(state, Certificate.EMPTY_CHAIN); } } if (clientMessage.getType() == HandshakeType.client_key_exchange) { processClientKeyExchange(state, clientMessage.getBody()); } else { throw new TlsFatalAlert(AlertDescription.unexpected_message); } TlsProtocol.establishMasterSecret(state.serverContext, state.keyExchange); recordLayer.initPendingEpoch(state.server.getCipher()); TlsHandshakeHash prepareFinishHash = handshake.prepareToFinish(); /* * RFC 5246 7.4.8 This message is only sent following a client certificate that has signing * capability (i.e., all certificates except those containing fixed Diffie-Hellman * parameters). */ if (expectCertificateVerifyMessage(state)) { byte[] certificateVerifyBody = handshake.receiveMessageBody(HandshakeType.certificate_verify); processCertificateVerify(state, certificateVerifyBody, prepareFinishHash); } // NOTE: Calculated exclusive of the actual Finished message from the client byte[] expectedClientVerifyData = TlsUtils.calculateVerifyData( state.serverContext, ExporterLabel.client_finished, TlsProtocol.getCurrentPRFHash(state.serverContext, handshake.getHandshakeHash(), null)); processFinished(handshake.receiveMessageBody(HandshakeType.finished), expectedClientVerifyData); if (state.expectSessionTicket) { NewSessionTicket newSessionTicket = state.server.getNewSessionTicket(); byte[] newSessionTicketBody = generateNewSessionTicket(state, newSessionTicket); handshake.sendMessage(HandshakeType.session_ticket, newSessionTicketBody); } // NOTE: Calculated exclusive of the Finished message itself byte[] serverVerifyData = TlsUtils.calculateVerifyData( state.serverContext, ExporterLabel.server_finished, TlsProtocol.getCurrentPRFHash(state.serverContext, handshake.getHandshakeHash(), null)); handshake.sendMessage(HandshakeType.finished, serverVerifyData); handshake.finish(); state.server.notifyHandshakeComplete(); return new DTLSTransport(recordLayer); }