package sun.security.ssl; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TimeZone; import javax.security.auth.x500.X500Principal; import javax.xml.bind.DatatypeConverter; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import org.ietf.jgss.GSSException; import org.ietf.jgss.Oid; import sun.security.ssl.HandshakeMessage.CertificateMsg; import sun.security.ssl.HandshakeMessage.CertificateRequest; import sun.security.ssl.HandshakeMessage.ServerHello; import sun.security.ssl.xml.Field; import sun.security.ssl.xml.ObjectFactory; import sun.security.ssl.xml.Packet; import sun.security.ssl.xml.Pdml; import sun.security.ssl.xml.Proto; import sun.security.x509.RDN; import sun.security.x509.X500Name; public class TlsMsgToXml { private ObjectFactory fabrique; private MessageParser parser; private static final Map CONTENT_MAP = new HashMap<>(); static { CONTENT_MAP.put(MessageParser.TYPE_CHG_CIPHER_SPEC, "changeCipherSpec"); CONTENT_MAP.put(MessageParser.TYPE_ALERT, "alert"); CONTENT_MAP.put(MessageParser.TYPE_HANDSHAKE, "handshake"); CONTENT_MAP.put(MessageParser.TYPE_APP_DATA, "appData"); } public TlsMsgToXml(MessageParser parser) { fabrique = new ObjectFactory(); this.parser = parser; } /** *

* Serializes the data of the different HandshakeMessages structures in an * xml format * * @param recordLength * Length of the record layer * @param contentType * Type of content (handshake, appdata, chgcipherspec, alert) * @param recordVersion * ProtocolVersion of the record layer * @param messageType * Type of HandshakeMessage * @param dataFromServer * True if the data comes from the server, false in the other way */ @SuppressWarnings("restriction") public OutputStream messageToXml(int recordLength, byte contentType, byte[] recordVersion, int messageType, boolean dataFromServer) { OutputStream xmlOutputStream = new ByteArrayOutputStream(); try { JAXBContext jc = JAXBContext.newInstance("sun.security.ssl.xml"); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); Pdml pdmlFile = fabrique.createPdml(); pdmlFile.setCreator("MessageParser"); pdmlFile.setDate(getDateString(System.currentTimeMillis())); pdmlFile.setVersion("0"); Packet packet = fabrique.createPacket(); Proto protoSsl = fabrique.createProto(); protoSsl.setShowname("Secure Sockets Layer"); protoSsl.setName("ssl"); protoSsl.setSize(recordLength + MessageParser.HEADER_SIZE); Field[] fieldRang2 = new Field[4]; for (int i = 0; i < 4; i++) { fieldRang2[i] = fabrique.createField(); } ProtocolVersion recVersion = ProtocolVersion.valueOf(recordVersion[0], recordVersion[1]); setField(fieldRang2[0], "ssl.record.content_type", "ContentType :" + CONTENT_MAP.get(contentType) + "(" + contentType + ")", recordLength + MessageParser.HEADER_SIZE, "", ""); setField(fieldRang2[1], "ssl.record.version", "Version :" + recVersion.toString() + " (" + String.format("%02x", recVersion.major) + "" + String.format("%02x", recVersion.minor) + ")", 2, "0x" + String.format("%02x", recVersion.major) + "" + String.format("%02x", recVersion.minor), String.format("%02x", recVersion.major) + "" + String.format("%02x", recVersion.minor)); setField(fieldRang2[2], "ssl.record.length", "Length :" + recordLength, 2, "" + recordLength + "", String.format("%04x", recordLength)); File xmlFile = new File("/tmp/ClientKey.xml"); switch (messageType) { case 0x01: clientHelloXml(fieldRang2[3], recordLength); break; case 0x02: serverHelloXml(fieldRang2[3], recordLength); break; case 0x0b: certificateXml(fieldRang2[3], recordLength, dataFromServer); break; case 0x10: rsaClientKeyExchXml(fieldRang2[3], recordLength); break; } for (int i = 0; i < 4; i++) { protoSsl.getFieldOrBlock().add(fieldRang2[i]); } packet.getProto().add(protoSsl); pdmlFile.getPacket().add(packet); if (messageType == 0x10) { marshaller.marshal(pdmlFile, xmlFile); } marshaller.marshal(pdmlFile, xmlOutputStream); } catch (JAXBException e) { System.out.println(e.getMessage()); } return xmlOutputStream; } /** *

* Serializes the client hello data * * @param clientHelloField * Field to fill with lower level informations * @param recordLength * Length of the record layer * @param fabrique * JAXB ObjectFactory */ @SuppressWarnings("restriction") private void clientHelloXml(Field clientHelloField, int recordLength) { HandshakeMessage.ClientHello clientHello = parser.getClientHello(); setField(clientHelloField, "ssl.handshake", "Handshake Protocol : Client Hello", recordLength, "", ""); List clientExtensions = clientHello.extensions.list(); int nbExtensions = clientExtensions.size(); HelloExtension[] clientExtensionsArray = new HelloExtension[nbExtensions]; clientExtensions.toArray(clientExtensionsArray); Field[] fieldRang3 = new Field[10 + nbExtensions]; for (int i = 0; i < 10 + nbExtensions; i++) { fieldRang3[i] = fabrique.createField(); } int versionMaj = clientHello.protocolVersion.major; int versionMin = clientHello.protocolVersion.minor; setField(fieldRang3[0], "ssl.handshake.type", "Handshake Type : Client Hello(1)", 1, "1", "01"); setField(fieldRang3[1], "ssl.handshake.length", "Length : " + clientHello.messageLength(), 3, "" + clientHello.messageLength(), String.format("%06x", clientHello.messageLength())); setField(fieldRang3[2], "ssl.handshake.version", "Version : " + clientHello.protocolVersion.toString() + " (0x" + String.format("%02x", versionMaj) + String.format("%02x", versionMin) + ")", 2, "0x" + String.format("%02x", versionMaj) + "" + String.format("%02X", versionMin), String.format("%02x", versionMaj) + "" + String.format("%02x", versionMin)); setField(fieldRang3[3], "", "Random", 32, "", DatatypeConverter.printHexBinary(clientHello.clnt_random.random_bytes).toLowerCase()); // Random number Field randomTime = fabrique.createField(); byte[] timeByte = Arrays.copyOfRange(clientHello.clnt_random.random_bytes, 0, 4); int time = java.nio.ByteBuffer.wrap(timeByte).getInt(); long unsignedTime = time & 0x00000000ffffffffL; String randomDate = getDateString(unsignedTime * 1000); setField(randomTime, "ssl.handshake.random_time", "gmt_unix_time: " + randomDate, 4, randomDate, "" + DatatypeConverter.printHexBinary(timeByte).toLowerCase()); Field randomBytes = fabrique.createField(); byte[] randomByte = Arrays.copyOfRange(clientHello.clnt_random.random_bytes, 4, clientHello.clnt_random.random_bytes.length); setField(randomBytes, "ssl.handshake.random_bytes", "random_bytes: " + DatatypeConverter.printHexBinary(randomByte).toLowerCase(), 28, "", DatatypeConverter.printHexBinary(randomByte).toLowerCase()); fieldRang3[3].getFieldOrBlock().add(randomTime); fieldRang3[3].getFieldOrBlock().add(randomBytes); // SessionId setField(fieldRang3[4], "ssl.handshake.session_id_length", "SessionID Length: " + clientHello.sessionId.length(), 1, "" + clientHello.sessionId.length(), String.format("%02x", clientHello.sessionId.length())); // CipherSuites int cipherNum = clientHello.getCipherSuites().size(); Collection ciphersuites = clientHello.getCipherSuites().collection(); CipherSuite[] cipherArray = new CipherSuite[cipherNum]; ciphersuites.toArray(cipherArray); setField(fieldRang3[5], "ssl.handshake.cipher_suites_length", "Cipher Suites Length: " + cipherNum * 2, 2, "" + cipherNum, String.format("%02x", cipherNum)); setField(fieldRang3[6], "ssl.handshake.ciphersuites", "CipherSuites (" + cipherNum + " suites)", cipherNum * 2, "", ""); Field[] fieldCipher = new Field[cipherNum]; for (int i = 0; i < cipherNum; i++) { fieldCipher[i] = fabrique.createField(); setField(fieldCipher[i], "ssl.handshake.ciphersuite", "Cipher Suite: " + cipherArray[i].name + " (0x" + String.format("%04x", cipherArray[i].id) + ")", 2, "0x" + String.format("%04x", cipherArray[i].id), String.format("%04x", cipherArray[i].id)); fieldRang3[6].getFieldOrBlock().add(fieldCipher[i]); } // Compression Methods int compressionLength = clientHello.compression_methods.length; setField(fieldRang3[7], "ssl.handshake.comp_methods_length", "Compression Methods Length: " + compressionLength, 1, "" + compressionLength, String.format("%02x", compressionLength)); setField(fieldRang3[8], "ssl.handshake.comp_methods", "Compression Methods (" + compressionLength + " method(s))", compressionLength, "", ""); Field[] fieldComp = new Field[compressionLength]; for (int i = 0; i < compressionLength; i++) { fieldComp[i] = fabrique.createField(); setField(fieldComp[i], "ssl.handshake.comp_method", "CompressionMethod: " + clientHello.compression_methods[i], 1, "" + clientHello.compression_methods[i], String.format("%02x", clientHello.compression_methods[i])); fieldRang3[8].getFieldOrBlock().add(fieldComp[i]); } // Extensions int extensionLength = clientHello.extensions.length() - 2; setField(fieldRang3[9], "ssl.handshake.extensions_length", "Extensions Length: " + extensionLength, 2, "" + extensionLength, String.format("%04x", extensionLength)); for (int i = 10; i < 10 + nbExtensions; i++) { setField(fieldRang3[i], "", "", clientExtensionsArray[i - 10].length(), "Extension: " + clientExtensionsArray[i - 10].type.name, DatatypeConverter .printHexBinary(getExtensionByteArray(clientExtensionsArray[i - 10])).toLowerCase()); Field[] fieldExt = new Field[3]; fieldExt[0] = fabrique.createField(); String extId = String.format("%04x", clientExtensionsArray[i - 10].type.id); setField(fieldExt[0], "ssl.handshake.extension.type", "Type: " + clientExtensionsArray[i - 10].type.name + " (0x" + extId + ")", 2, "0x" + extId, "" + extId); fieldExt[1] = fabrique.createField(); int extLen = clientExtensionsArray[i - 10].length() - 4; setField(fieldExt[1], "ssl.handshake.extension.len", "Length: " + extLen, 2, "" + extLen, String.format("%04x", extLen)); for (int j = 0; j < 3; j++) { fieldRang3[i].getFieldOrBlock().add(fieldExt[j]); } } for (int i = 0; i < 10 + nbExtensions; i++) { clientHelloField.getFieldOrBlock().add(fieldRang3[i]); } } /** *

* Serializes the server hello data * * @param serverHelloField * Field to fill with lower level informations * @param recordLength * Length of the record layer * @param fabrique * JAXB ObjectFactory */ @SuppressWarnings("restriction") private void serverHelloXml(Field serverHelloField, int recordLength) { ServerHello serverHello = parser.getServerHello(); setField(serverHelloField, "ssl.handshake", "Handshake Protocol : Server Hello", recordLength, "", ""); List serverExtensions = serverHello.extensions.list(); int nbExtensions = serverExtensions.size(); HelloExtension[] clientExtensionsArray = new HelloExtension[nbExtensions]; serverExtensions.toArray(clientExtensionsArray); Field[] fieldRang3 = new Field[8 + nbExtensions]; for (int i = 0; i < 8 + nbExtensions; i++) { fieldRang3[i] = fabrique.createField(); } int versionMaj = serverHello.protocolVersion.major; int versionMin = serverHello.protocolVersion.minor; setField(fieldRang3[0], "ssl.handshake.type", "Handshake Type : Server Hello(2)", 1, "2", "02"); setField(fieldRang3[1], "ssl.handshake.length", "Length : " + serverHello.messageLength(), 3, "" + serverHello.messageLength(), String.format("%06x", serverHello.messageLength())); setField(fieldRang3[2], "ssl.handshake.version", "Version : " + serverHello.protocolVersion.toString() + " (0x" + String.format("%02x", versionMaj) + String.format("%02x", versionMin) + ")", 2, "0x" + String.format("%02x", versionMaj) + "" + String.format("%02x", versionMin), String.format("%02x", versionMaj) + "" + String.format("%02x", versionMin)); setField(fieldRang3[3], "", "Random", 32, "", DatatypeConverter.printHexBinary(serverHello.svr_random.random_bytes).toLowerCase()); // Random number Field randomTime = fabrique.createField(); byte[] timeByte = Arrays.copyOfRange(serverHello.svr_random.random_bytes, 0, 4); int time = java.nio.ByteBuffer.wrap(timeByte).getInt(); long unsignedTime = time & 0x00000000ffffffffL; String randomDate = getDateString(unsignedTime * 1000); setField(randomTime, "ssl.handshake.random_time", "gmt_unix_time: " + randomDate, 4, randomDate, "" + DatatypeConverter.printHexBinary(timeByte).toLowerCase()); Field randomBytes = fabrique.createField(); byte[] randomByte = Arrays.copyOfRange(serverHello.svr_random.random_bytes, 4, serverHello.svr_random.random_bytes.length); setField(randomBytes, "ssl.handshake.random_bytes", "random_bytes: " + DatatypeConverter.printHexBinary(randomByte).toLowerCase(), 28, "", DatatypeConverter.printHexBinary(randomByte).toLowerCase()); fieldRang3[3].getFieldOrBlock().add(randomTime); fieldRang3[3].getFieldOrBlock().add(randomBytes); // SessionId setField(fieldRang3[4], "ssl.handshake.session_id_length", "SessionID Length: " + serverHello.sessionId.length(), 1, "" + serverHello.sessionId.length(), String.format("%02x", serverHello.sessionId.length())); // CipherSuites int cipherId = serverHello.cipherSuite.id; setField(fieldRang3[5], "ssl.handshake.ciphersuite", "Cipher Suite: " + serverHello.cipherSuite + " (0x" + String.format("%04x", cipherId) + ")", 2, "0x" + String.format("%04x", cipherId), "" + String.format("%04x", cipherId)); // Compression Methods setField(fieldRang3[6], "ssl.handshake.comp_method", "Compression Method: " + serverHello.compression_method, 1, "" + serverHello.compression_method, String.format("%02x", serverHello.compression_method)); // Extensions int extensionLength = serverHello.extensions.length() - 2; setField(fieldRang3[7], "ssl.handshake.extensions_length", "Extensions Length: " + extensionLength, 2, "" + extensionLength, String.format("%04x", extensionLength)); for (int i = 8; i < 8 + nbExtensions; i++) { setField(fieldRang3[i], "", "", clientExtensionsArray[i - 8].length(), "Extension: " + clientExtensionsArray[i - 8].type.name, DatatypeConverter .printHexBinary(getExtensionByteArray(clientExtensionsArray[i - 8])).toLowerCase()); Field[] fieldExt = new Field[3]; fieldExt[0] = fabrique.createField(); String extId = String.format("%04x", clientExtensionsArray[i - 8].type.id); setField(fieldExt[0], "ssl.handshake.extension.type", "Type: " + clientExtensionsArray[i - 8].type.name + " (0x" + extId + ")", 2, "0x" + extId, "" + extId); fieldExt[1] = fabrique.createField(); int extLen = clientExtensionsArray[i - 8].length() - 4; setField(fieldExt[1], "ssl.handshake.extension.len", "Length: " + extLen, 2, "" + extLen, String.format("%04x", extLen)); for (int j = 0; j < 3; j++) { fieldRang3[i].getFieldOrBlock().add(fieldExt[j]); } } for (int i = 0; i < 8 + nbExtensions; i++) { serverHelloField.getFieldOrBlock().add(fieldRang3[i]); } } /** *

* Serializes the certificates data * * @param certificateField * Field to fill with lower level informations * @param recordLength * Length of the record layer * @param fabrique * JAXB ObjectFactory * @param dataFromServer * True if the data comes from the server, false in the other way * */ @SuppressWarnings("restriction") private void certificateXml(Field certificateField, int recordLength, boolean dataFromServer) { setField(certificateField, "ssl.handshake", "Handshake Protocol : Certificate", recordLength, "", ""); CertificateMsg certMsg = null; if (!dataFromServer) { certMsg = parser.getCertificateServer(); } else { certMsg = parser.getCertificateClient(); } X509Certificate[] certs = certMsg.getCertificateChain(); int certsNum = certs.length; Field[] fieldRang3 = new Field[8]; for (int i = 0; i < 8; i++) { fieldRang3[i] = fabrique.createField(); } try { setField(fieldRang3[0], "ssl.handshake.type", "Handshake Type : Certificate(11)", 1, "11", "0b"); setField(fieldRang3[1], "ssl.handshake.length", "Length : " + certMsg.messageLength(), 3, "" + certMsg.messageLength(), String.format("%06x", certMsg.messageLength())); setField(fieldRang3[2], "ssl.handshake.certificates_length", "Certificates Length : " + (certMsg.messageLength() - 3), 3, "" + (certMsg.messageLength() - 3), String.format("%06x", certMsg.messageLength() - 3)); setField(fieldRang3[3], "ssl.handshake.certificates", "Certificates (" + (certMsg.messageLength() - 3) + " bytes)", certMsg.messageLength() - 3, "", ""); Field[] certField = new Field[certsNum]; for (int i = 0; i < certsNum; i++) { X509Certificate cert = certs[i]; Field certLength = fabrique.createField(); Field certContent = fabrique.createField(); setField(certLength, "ssl.handshake.certificate_length", "Certificate Length : " + cert.getEncoded().length, 3, "" + cert.getEncoded().length, String.format("%06x", cert.getEncoded().length)); setField(certContent, "ssl.handshake.certificate", "Certificate " + cert.getSubjectDN().getName(), cert.getEncoded().length, "", ""); certificateContentXml(certContent, cert, fabrique); fieldRang3[3].getFieldOrBlock().add(certLength); fieldRang3[3].getFieldOrBlock().add(certContent); } for (int i = 0; i < 8; i++) { certificateField.getFieldOrBlock().add(fieldRang3[i]); } } catch (CertificateEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** *

* Serializes the certificate data * * @param certContent * Field to fill with lower level informations * @param cert * X509Certificate extracted from the structure * {@link CertificateMsg} * @param fabrique * JAXB ObjectFactory */ @SuppressWarnings("restriction") private void certificateContentXml(Field certContent, X509Certificate cert, ObjectFactory fabrique) { try { Field[] x509content = new Field[4]; for (int i = 0; i < 4; i++) { x509content[i] = fabrique.createField(); } setField(x509content[0], "x509af.signedCertificate", "signedCertificate", cert.getTBSCertificate().length, "", ""); Field version = fabrique.createField(); setField(version, "x509af.version", "version: v" + (cert.getVersion() + 1) + " (" + cert.getVersion() + ")", 1, "" + cert.getVersion(), String.format("%02x", cert.getVersion())); Field serialNum = fabrique.createField(); setField(serialNum, "x509af.serialNumber", "serialNumber: " + cert.getSerialNumber(), cert.getSerialNumber().toByteArray().length, "" + cert.getSerialNumber(), DatatypeConverter.printHexBinary(cert.getSerialNumber().toByteArray()).toLowerCase()); Field signature = fabrique.createField(); // TODO size and bytearrays associated with signature Oid oidSig = new Oid(cert.getSigAlgOID()); byte[] oidSigByte = Arrays.copyOfRange(oidSig.getDER(), 2, oidSig.getDER().length); setField(signature, "x509af.signature", "signature (iso.2.840.113549.1.1.13)", 0, "", ""); Field algoId = fabrique.createField(); setField(algoId, "x509af.algorithm.id", "Algorithm Id: " + cert.getSigAlgOID(), oidSigByte.length, "" + cert.getSigAlgOID(), DatatypeConverter.printHexBinary(oidSigByte).toLowerCase()); signature.getFieldOrBlock().add(algoId); X500Principal qfe = cert.getIssuerX500Principal(); X500Name name = new X500Name(qfe.getEncoded()); Field issuer = fabrique.createField(); setField(issuer, "issuer: rdnSequence", "" + cert.getIssuerDN(), name.getEncoded().length, "0", DatatypeConverter.printHexBinary(name.getEncoded()).toLowerCase()); Field rdnSequence = fabrique.createField(); byte[] rdns = Arrays.copyOfRange(name.getEncoded(), 2, name.getEncoded().length); setField(rdnSequence, "x509if.rdnSequence", "rdnSequence: " + name.size() + " items (" + name.toString() + ")", rdns.length, "" + name.size(), DatatypeConverter.printHexBinary(rdns).toLowerCase()); Field[] rdnItem = new Field[name.size()]; for (int j = 0; j < name.size(); j++) { RDN item = name.rdns().get(j); rdnItem[j] = fabrique.createField(); byte[] rdnData = item.avas().get(0).getDerValue().getDataBytes(); setField(rdnItem[j], "x509if.RDNSequence_item", "RDNSequence item :" + item.size() + " item (" + item.toString() + ")", rdnData.length, "" + item.size(), DatatypeConverter.printHexBinary(rdnData).toLowerCase()); Field relativeDis = fabrique.createField(); Field id = fabrique.createField(); Oid oid = new Oid(item.avas().get(0).getObjectIdentifier().toString()); byte[] oidByte = Arrays.copyOfRange(oid.getDER(), 2, oid.getDER().length); setField(id, "x509if.id", "Id: " + item.avas().get(0).getObjectIdentifier().toString(), oidByte.length, "" + item.avas().get(0).getObjectIdentifier().toString(), DatatypeConverter.printHexBinary(oidByte).toLowerCase()); relativeDis.getFieldOrBlock().add(id); if (item.avas().get(0).getDerValue().getTag() == 0x0c) { // directoryString : UTF8 Field directoryString = fabrique.createField(); byte[] directoryStringByte = item.avas().get(0).getDerValue().toByteArray(); setField(directoryString, "x509sat.DirectoryString", "DirectoryString: uTF8String (4)", directoryStringByte.length, "4", DatatypeConverter.printHexBinary(directoryStringByte).toLowerCase()); relativeDis.getFieldOrBlock().add(directoryString); byte[] utf8StringByte = item.avas().get(0).getDerValue().getDataBytes(); Field utf8String = fabrique.createField(); setField(utf8String, "x509sat.uTF8String", "uTF8String: " + item.avas().get(0).getDerValue().getUTF8String(), utf8StringByte.length, "4", DatatypeConverter.printHexBinary(utf8StringByte).toLowerCase()); directoryString.getFieldOrBlock().add(utf8String); } else { // PrintableString Field value = fabrique.createField(); byte[] printableStringByte = item.avas().get(0).getDerValue().getDataBytes(); setField(value, "x509sat.CountryName", "CountryName: " + item.avas().get(0).getDerValue().getPrintableString(), printableStringByte.length, "" + item.avas().get(0).getDerValue().getPrintableString(), DatatypeConverter.printHexBinary(printableStringByte).toLowerCase()); } // TODO directory string and co rdnItem[j].getFieldOrBlock().add(relativeDis); rdnSequence.getFieldOrBlock().add(rdnItem[j]); } issuer.getFieldOrBlock().add(rdnSequence); Field validity = fabrique.createField(); // setField(validity, "x509af.validity","validity",cert.,"","" ); Field notBefore = fabrique.createField(); setField(notBefore, "x509af.notBefore", "notBefore: ", 0, "", ""); Field time = fabrique.createField(); setField(time, "x509af.utcTime", "utcTime: " + cert.getNotBefore().toString(), 0, "", ""); Field notAfter = fabrique.createField(); setField(notAfter, "x509af.notBefore", "notBefore: ", 0, "", ""); x509content[0].getFieldOrBlock().add(version); x509content[0].getFieldOrBlock().add(serialNum); x509content[0].getFieldOrBlock().add(signature); x509content[0].getFieldOrBlock().add(issuer); setField(x509content[1], "x509af.algorithmIdentifier", "algorithmIdentifier (iso.2.840.113549.1.1.13)", 0, "", ""); x509content[1].getFieldOrBlock().add(algoId); setField(x509content[2], "ber.bitstring.padding", "Padding: ", 0, "", ""); setField(x509content[3], "x509af.encrypted", "encrypted: " + DatatypeConverter.printHexBinary(cert.getSignature()).toLowerCase(), cert.getSignature().length, "" + DatatypeConverter.printHexBinary(cert.getSignature()).toLowerCase(), "" + DatatypeConverter.printHexBinary(cert.getSignature()).toLowerCase()); for (int i = 0; i < 4; i++) { certContent.getFieldOrBlock().add(x509content[i]); } } catch (CertificateEncodingException | IOException | GSSException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @SuppressWarnings("restriction") private void rsaClientKeyExchXml(Field keyExchField, int recordLength) { setField(keyExchField, "ssl.handshake", "Handshake Protocol : Client Key Exchange", recordLength, "", ""); RSAClientKeyExchange clientKeyExch = parser.getRsaClientKeyExchange(); int length = clientKeyExch.preMaster.getEncoded().length; Field[] fieldRang3 = new Field[3]; for (int i = 0; i < 3; i++) { fieldRang3[i] = fabrique.createField(); } setField(fieldRang3[0], "ssl.handshake.type", "Handshake Type : Client Key Exchange (16)", 1, "16", "10"); setField(fieldRang3[1], "ssl.handshake.length", "Length : " + length, 3, "" + length, String.format("%06x", length)); setField(fieldRang3[2], "", "RSA Encrypted PreMaster Secret", length, "", ""); Field lengthField = fabrique.createField(); Field premaster = fabrique.createField(); setField(lengthField, "ssl.handshake.epms_len", "Encrypted PreMaster length: " + length, 2, "" + length, String.format("%04x", length)); setField(premaster, "ssl.handshake.epms", "Encrypted PreMaster: " + DatatypeConverter.printHexBinary(clientKeyExch.preMaster.getEncoded()).toLowerCase(), 2, "" + length, String.format("%04x", length)); fieldRang3[2].getFieldOrBlock().add(lengthField); fieldRang3[2].getFieldOrBlock().add(premaster); for (int i = 0; i < 3; i++) { keyExchField.getFieldOrBlock().add(fieldRang3[i]); } } @SuppressWarnings("restriction") private void certificateRequestXml(Field certRqstField, int recordLength) { CertificateRequest certRequest = parser.getCertificateRequest(); Field[] fieldRang3 = new Field[4]; for (int i = 0; i < 4; i++) { fieldRang3[i] = fabrique.createField(); } setField(fieldRang3[0], "ssl.handshake.type", "Handshake Type : Client Key Exchange (16)", 1, "16", "10"); setField(fieldRang3[1], "ssl.handshake.length", "Length : " + certRequest.messageLength(), 3, "" + certRequest.messageLength(), String.format("%06x", certRequest.messageLength())); setField(fieldRang3[2], "ssl.handshake.cert_types_count", "Certificate types count: " + certRequest.types.length, 1, "" + certRequest.types.length, String.format("%02x", certRequest.types.length)); setField(fieldRang3[3], "ssl.handshake.cert_types", "Certificate types (" + certRequest.types.length + " types)", certRequest.types.length, "", ""); for (int i = 0; i < certRequest.types.length; i++) { Field certType = fabrique.createField(); setField(certType, "ssl.handshake.cert_type", "Certificate type: " + getCertTypes(certRequest.types[i]) + " Sign (" + certRequest.types[i] + ")", 1, "" + certRequest.types[i], String.format("%02x", certRequest.types[i])); fieldRang3[3].getFieldOrBlock().add(certType); } } /** *

* Get the byte array of the specified HelloExtension * * @param helloExt * Extension we want to turn into its byte array value * @return Extension byte array */ private byte[] getExtensionByteArray(HelloExtension helloExt) { HandshakeOutStream output = new HandshakeOutStream(null, null, null, (SSLSocketImpl) null); try { helloExt.send(output); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); byte[] emptyArray = new byte[0]; return emptyArray; } byte[] extensionContent = output.r.toByteArray(); extensionContent = Arrays.copyOfRange(extensionContent, 5, extensionContent.length); return extensionContent; } /** *

* Sets the values of the Field {@link field} * * @param field * The Field that is being set * @param name * Fill the name of the packet property (kind of ID) * @param showname * Name of the packet property that is shown to the user * @param size * Size of the packet property * @param show * Shown value of the packet property if there is one * @param value * Value of the packet property */ private void setField(Field field, String name, String showname, int size, String show, String value) { field.setShowname(showname); field.setName(name); field.setValue(value); field.setShow(show); field.setSize(size); } /** *

* Get date as a String from time in ms * * @param timeMillis * Time in ms * @return The String date */ private String getDateString(long timeMillis) { Date date = new Date(timeMillis); // the format of your date SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); // give a timezone reference for formating sdf.setTimeZone(TimeZone.getTimeZone("GMT+2")); return sdf.format(date); } private static String getCertTypes(byte type) { switch (type) { case CertificateRequest.cct_rsa_sign: return "RSA"; case CertificateRequest.cct_dss_sign: return "DSS"; case CertificateRequest.cct_rsa_fixed_dh: return "Fixed DH (RSA sig)"; case CertificateRequest.cct_dss_fixed_dh: return "Fixed DH (DSS sig)"; case CertificateRequest.cct_rsa_ephemeral_dh: return "Ephemeral DH (RSA sig)"; case CertificateRequest.cct_dss_ephemeral_dh: return "Ephemeral DH (DSS sig)"; case CertificateRequest.cct_ecdsa_sign: return "ECDSA"; case CertificateRequest.cct_rsa_fixed_ecdh: return "Fixed ECDH (RSA sig)"; case CertificateRequest.cct_ecdsa_fixed_ecdh: return "Fixed ECDH (ECDSA sig)"; default: return "Type-" + (type & 0xff); } } }