2006 lines · 67.7 KB · Java
RawDownload
    }     /*     * Parse an ECDH server key exchange message.     */    ECDH_ServerKeyExchange(HandshakeInStream input, PublicKey signingKey,            byte[] clntNonce, byte[] svrNonce,            Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,            ProtocolVersion protocolVersion)            throws IOException, GeneralSecurityException {         this.protocolVersion = protocolVersion;         // read params: ServerECDHParams        int curveType = input.getInt8();        ECParameterSpec parameters;        // These parsing errors should never occur as we negotiated        // the supported curves during the exchange of the Hello messages.        if (curveType == CURVE_NAMED_CURVE) {            curveId = input.getInt16();            if (SupportedEllipticCurvesExtension.isSupported(curveId)                    == false) {                throw new SSLHandshakeException(                    "Unsupported curveId: " + curveId);            }            String curveOid =                SupportedEllipticCurvesExtension.getCurveOid(curveId);            if (curveOid == null) {                throw new SSLHandshakeException(                    "Unknown named curve: " + curveId);            }            parameters = JsseJce.getECParameterSpec(curveOid);            if (parameters == null) {                throw new SSLHandshakeException(                    "Unsupported curve: " + curveOid);            }        } else {            throw new SSLHandshakeException(                "Unsupported ECCurveType: " + curveType);        }        pointBytes = input.getBytes8();         ECPoint point = JsseJce.decodePoint(pointBytes, parameters.getCurve());        KeyFactory factory = JsseJce.getKeyFactory("EC");        publicKey = (ECPublicKey)factory.generatePublic(            new ECPublicKeySpec(point, parameters));         if (signingKey == null) {            // ECDH_anon            return;        }         // read the signature and hash algorithm        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {            int hash = input.getInt8();         // hash algorithm            int signature = input.getInt8();    // signature algorithm             preferableSignatureAlgorithm =                SignatureAndHashAlgorithm.valueOf(hash, signature, 0);             // Is it a local supported signature algorithm?            if (!localSupportedSignAlgs.contains(                    preferableSignatureAlgorithm)) {                throw new SSLHandshakeException(                        "Unsupported SignatureAndHashAlgorithm in " +                        "ServerKeyExchange message");            }        }         // read the signature        signatureBytes = input.getBytes16();         // verify the signature        Signature sig;        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {            sig = JsseJce.getSignature(                        preferableSignatureAlgorithm.getAlgorithmName());        } else {            sig = getSignature(signingKey.getAlgorithm());        }        sig.initVerify(signingKey);         updateSignature(sig, clntNonce, svrNonce);         if (sig.verify(signatureBytes) == false ) {            throw new SSLKeyException(                "Invalid signature on ECDH server key exchange message");        }    }     /*     * Get the ephemeral EC public key encapsulated in this message.     */    ECPublicKey getPublicKey() {        return publicKey;    }     private static Signature getSignature(String keyAlgorithm)            throws NoSuchAlgorithmException {        if (keyAlgorithm.equals("EC")) {            return JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA);        } else if (keyAlgorithm.equals("RSA")) {            return RSASignature.getInstance();        } else {            throw new NoSuchAlgorithmException("neither an RSA or a EC key");        }    }     private void updateSignature(Signature sig, byte clntNonce[],            byte svrNonce[]) throws SignatureException {        sig.update(clntNonce);        sig.update(svrNonce);         sig.update((byte)CURVE_NAMED_CURVE);        sig.update((byte)(curveId >> 8));        sig.update((byte)curveId);        sig.update((byte)pointBytes.length);        sig.update(pointBytes);    }     int messageLength() {        int sigLen = 0;        if (signatureBytes != null) {            sigLen = 2 + signatureBytes.length;            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {                sigLen += SignatureAndHashAlgorithm.sizeInRecord();            }        }         return 4 + pointBytes.length + sigLen;    }     void send(HandshakeOutStream s) throws IOException {        s.putInt8(CURVE_NAMED_CURVE);        s.putInt16(curveId);        s.putBytes8(pointBytes);         if (signatureBytes != null) {            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {                s.putInt8(preferableSignatureAlgorithm.getHashValue());                s.putInt8(preferableSignatureAlgorithm.getSignatureValue());            }             s.putBytes16(signatureBytes);        }    }     void print(PrintStream s) throws IOException {        s.println("*** ECDH ServerKeyExchange");         if (debug != null && Debug.isOn("verbose")) {            if (signatureBytes == null) {                s.println("Anonymous");            } else {                if (protocolVersion.v >= ProtocolVersion.TLS12.v) {                    s.println("Signature Algorithm " +                            preferableSignatureAlgorithm.getAlgorithmName());                }            }             s.println("Server key: " + publicKey);        }    }} static final class DistinguishedName {     /*     * DER encoded distinguished name.     * TLS requires that its not longer than 65535 bytes.     */    byte name[];     DistinguishedName(HandshakeInStream input) throws IOException {        name = input.getBytes16();    }     DistinguishedName(X500Principal dn) {        name = dn.getEncoded();    }     X500Principal getX500Principal() throws IOException {        try {            return new X500Principal(name);        } catch (IllegalArgumentException e) {            throw (SSLProtocolException)new SSLProtocolException(                e.getMessage()).initCause(e);        }    }     int length() {        return 2 + name.length;    }     void send(HandshakeOutStream output) throws IOException {        output.putBytes16(name);    }     void print(PrintStream output) throws IOException {        X500Principal principal = new X500Principal(name);        output.println("<" + principal.toString() + ">");    }} /* * CertificateRequest ... SERVER --> CLIENT * * Authenticated servers may ask clients to authenticate themselves * in turn, using this message. * * Prior to TLS 1.2, the structure of the message is defined as: *     struct { *         ClientCertificateType certificate_types<1..2^8-1>; *         DistinguishedName certificate_authorities<0..2^16-1>; *     } CertificateRequest; * * In TLS 1.2, the structure is changed to: *     struct { *         ClientCertificateType certificate_types<1..2^8-1>; *         SignatureAndHashAlgorithm *           supported_signature_algorithms<2^16-1>; *         DistinguishedName certificate_authorities<0..2^16-1>; *     } CertificateRequest; * */static finalclass CertificateRequest extends HandshakeMessage{    // enum ClientCertificateType    static final int   cct_rsa_sign = 1;    static final int   cct_dss_sign = 2;    static final int   cct_rsa_fixed_dh = 3;    static final int   cct_dss_fixed_dh = 4;     // The existance of these two values is a bug in the SSL specification.    // They are never used in the protocol.    static final int   cct_rsa_ephemeral_dh = 5;    static final int   cct_dss_ephemeral_dh = 6;     // From RFC 4492 (ECC)    static final int    cct_ecdsa_sign       = 64;    static final int    cct_rsa_fixed_ecdh   = 65;    static final int    cct_ecdsa_fixed_ecdh = 66;     private final static byte[] TYPES_NO_ECC = { cct_rsa_sign, cct_dss_sign };    private final static byte[] TYPES_ECC =        { cct_rsa_sign, cct_dss_sign, cct_ecdsa_sign };     byte                types [];               // 1 to 255 types    DistinguishedName   authorities [];         // 3 to 2^16 - 1        // ... "3" because that's the smallest DER-encoded X500 DN     // protocol version being established using this CertificateRequest message    ProtocolVersion protocolVersion;     // supported_signature_algorithms for TLS 1.2 or later    private Collection<SignatureAndHashAlgorithm> algorithms;     // length of supported_signature_algorithms    private int algorithmsLen;     CertificateRequest(X509Certificate ca[], KeyExchange keyExchange,            Collection<SignatureAndHashAlgorithm> signAlgs,            ProtocolVersion protocolVersion) throws IOException {         this.protocolVersion = protocolVersion;         // always use X500Principal        authorities = new DistinguishedName[ca.length];        for (int i = 0; i < ca.length; i++) {            X500Principal x500Principal = ca[i].getSubjectX500Principal();            authorities[i] = new DistinguishedName(x500Principal);        }        // we support RSA, DSS, and ECDSA client authentication and they        // can be used with all ciphersuites. If this changes, the code        // needs to be adapted to take keyExchange into account.        // We only request ECDSA client auth if we have ECC crypto available.        this.types = JsseJce.isEcAvailable() ? TYPES_ECC : TYPES_NO_ECC;         // Use supported_signature_algorithms for TLS 1.2 or later.        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {            if (signAlgs == null || signAlgs.isEmpty()) {                throw new SSLProtocolException(                        "No supported signature algorithms");            }             algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs);            algorithmsLen =                SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();        } else {            algorithms = new ArrayList<SignatureAndHashAlgorithm>();            algorithmsLen = 0;        }    }     CertificateRequest(HandshakeInStream input,            ProtocolVersion protocolVersion) throws IOException {         this.protocolVersion = protocolVersion;         // Read the certificate_types.        types = input.getBytes8();         // Read the supported_signature_algorithms for TLS 1.2 or later.        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {            algorithmsLen = input.getInt16();            if (algorithmsLen < 2) {                throw new SSLProtocolException(                        "Invalid supported_signature_algorithms field");            }             algorithms = new ArrayList<SignatureAndHashAlgorithm>();            int remains = algorithmsLen;            int sequence = 0;            while (remains > 1) {    // needs at least two bytes                int hash = input.getInt8();         // hash algorithm                int signature = input.getInt8();    // signature algorithm                 SignatureAndHashAlgorithm algorithm =                    SignatureAndHashAlgorithm.valueOf(hash, signature,                                                                ++sequence);                algorithms.add(algorithm);                remains -= 2;  // one byte for hash, one byte for signature            }             if (remains != 0) {                throw new SSLProtocolException(                        "Invalid supported_signature_algorithms field");            }        } else {            algorithms = new ArrayList<SignatureAndHashAlgorithm>();            algorithmsLen = 0;        }         // read the certificate_authorities        int len = input.getInt16();        ArrayList<DistinguishedName> v = new ArrayList<>();        while (len >= 3) {            DistinguishedName dn = new DistinguishedName(input);            v.add(dn);            len -= dn.length();        }         if (len != 0) {            throw new SSLProtocolException("Bad CertificateRequest DN length");        }         authorities = v.toArray(new DistinguishedName[v.size()]);    }     X500Principal[] getAuthorities() throws IOException {        X500Principal[] ret = new X500Principal[authorities.length];        for (int i = 0; i < authorities.length; i++) {            ret[i] = authorities[i].getX500Principal();        }        return ret;    }     Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {        return algorithms;    }     @Override    int messageType() {        return ht_certificate_request;    }     @Override    int messageLength() {        int len = 1 + types.length + 2;         if (protocolVersion.v >= ProtocolVersion.TLS12.v) {            len += algorithmsLen + 2;        }         for (int i = 0; i < authorities.length; i++) {            len += authorities[i].length();        }         return len;    }     @Override    void send(HandshakeOutStream output) throws IOException {        // put certificate_types        output.putBytes8(types);         // put supported_signature_algorithms        if (protocolVersion.v >= ProtocolVersion.TLS12.v) {            output.putInt16(algorithmsLen);            for (SignatureAndHashAlgorithm algorithm : algorithms) {                output.putInt8(algorithm.getHashValue());      // hash                output.putInt8(algorithm.getSignatureValue()); // signature            }        }         // put certificate_authorities        int len = 0;        for (int i = 0; i < authorities.length; i++) {            len += authorities[i].length();        }         output.putInt16(len);        for (int i = 0; i < authorities.length; i++) {            authorities[i].send(output);        }    }     @Override    void print(PrintStream s) throws IOException {        s.println("*** CertificateRequest");         if (debug != null && Debug.isOn("verbose")) {            s.print("Cert Types: ");            for (int i = 0; i < types.length; i++) {                switch (types[i]) {                  case cct_rsa_sign:                    s.print("RSA"); break;                  case cct_dss_sign:                    s.print("DSS"); break;                  case cct_rsa_fixed_dh:                    s.print("Fixed DH (RSA sig)"); break;                  case cct_dss_fixed_dh:                    s.print("Fixed DH (DSS sig)"); break;                  case cct_rsa_ephemeral_dh:                    s.print("Ephemeral DH (RSA sig)"); break;                  case cct_dss_ephemeral_dh:                    s.print("Ephemeral DH (DSS sig)"); break;                  case cct_ecdsa_sign:                    s.print("ECDSA"); break;                  case cct_rsa_fixed_ecdh:                    s.print("Fixed ECDH (RSA sig)"); break;                  case cct_ecdsa_fixed_ecdh:                    s.print("Fixed ECDH (ECDSA sig)"); break;                  default:                    s.print("Type-" + (types[i] & 0xff)); break;                }                if (i != types.length - 1) {                    s.print(", ");                }            }            s.println();             if (protocolVersion.v >= ProtocolVersion.TLS12.v) {                StringBuffer buffer = new StringBuffer();                boolean opened = false;                for (SignatureAndHashAlgorithm signAlg : algorithms) {                    if (opened) {                        buffer.append(", " + signAlg.getAlgorithmName());                    } else {                        buffer.append(signAlg.getAlgorithmName());                        opened = true;                    }                }                s.println("Supported Signature Algorithms: " + buffer);            }             s.println("Cert Authorities:");            if (authorities.length == 0) {                s.println("<Empty>");            } else {                for (int i = 0; i < authorities.length; i++) {                    authorities[i].print(s);                }            }        }    }}  /* * ServerHelloDone ... SERVER --> CLIENT * * When server's done sending its messages in response to the client's * "hello" (e.g. its own hello, certificate, key exchange message, perhaps * client certificate request) it sends this message to flag that it's * done that part of the handshake. */static finalclass ServerHelloDone extends HandshakeMessage{    int messageType() { return ht_server_hello_done; }     ServerHelloDone() { }     ServerHelloDone(HandshakeInStream input)    {        // nothing to do    }     int messageLength()    {        return 0;    }     void send(HandshakeOutStream s) throws IOException    {        // nothing to send    } 

Lines 1001–1500 of 2006. Previous lines