Activated Curve25519 support for ECDHE cipher suites.
[BearSSL] / tools / client.c
index 102d43b..ce3c6d6 100644 (file)
@@ -319,13 +319,19 @@ cc_choose(const br_ssl_client_certificate_class **pctx,
 
 static uint32_t
 cc_do_keyx(const br_ssl_client_certificate_class **pctx,
-       unsigned char *data, size_t len)
+       unsigned char *data, size_t *len)
 {
        ccert_context *zc;
+       size_t xoff, xlen;
+       uint32_t r;
 
        zc = (ccert_context *)pctx;
-       return br_ec_prime_i31.mul(data, len, zc->sk->key.ec.x,
+       r = br_ec_all_m15.mul(data, *len, zc->sk->key.ec.x,
                zc->sk->key.ec.xlen, zc->sk->key.ec.curve);
+       xoff = br_ec_all_m15.xoff(zc->sk->key.ec.curve, &xlen);
+       memmove(data, data + xoff, xlen);
+       *len = xlen;
+       return r;
 }
 
 static size_t
@@ -392,7 +398,7 @@ cc_do_sign(const br_ssl_client_certificate_class **pctx,
                        }
                        return 0;
                }
-               sig_len = br_ecdsa_i31_sign_asn1(&br_ec_prime_i31,
+               sig_len = br_ecdsa_i31_sign_asn1(&br_ec_all_m15,
                        hc, hv, &zc->sk->key.ec, data);
                if (sig_len == 0) {
                        if (zc->verbose) {
@@ -419,6 +425,12 @@ static const br_ssl_client_certificate_class ccert_vtable = {
        cc_do_sign
 };
 
+static void
+free_alpn(void *alpn)
+{
+       xfree(*(char **)alpn);
+}
+
 static void
 usage_client(void)
 {
@@ -462,6 +474,10 @@ usage_client(void)
 "   -fallback       send the TLS_FALLBACK_SCSV (i.e. claim a downgrade)\n");
        fprintf(stderr,
 "   -noreneg        prohibit renegotiations\n");
+       fprintf(stderr,
+"   -alpn name      add protocol name to list of protocols (ALPN extension)\n");
+       fprintf(stderr,
+"   -strictalpn     fail on ALPN mismatch\n");
 }
 
 /* see brssl.h */
@@ -478,6 +494,7 @@ do_client(int argc, char *argv[])
        const char *sni;
        anchor_list anchors = VEC_INIT;
        unsigned vmin, vmax;
+       VECTOR(const char *) alpn_names = VEC_INIT;
        cipher_suite *suites;
        size_t num_suites;
        uint16_t *suite_ids;
@@ -744,6 +761,16 @@ do_client(int argc, char *argv[])
                        fallback = 1;
                } else if (eqstr(arg, "-noreneg")) {
                        flags |= BR_OPT_NO_RENEGOTIATION;
+               } else if (eqstr(arg, "-alpn")) {
+                       if (++ i >= argc) {
+                               fprintf(stderr,
+                                       "ERROR: no argument for '-alpn'\n");
+                               usage_client();
+                               goto client_exit_error;
+                       }
+                       VEC_ADD(alpn_names, xstrdup(argv[i]));
+               } else if (eqstr(arg, "-strictalpn")) {
+                       flags |= BR_OPT_FAIL_ON_ALPN_MISMATCH;
                } else {
                        fprintf(stderr, "ERROR: unknown option: '%s'\n", arg);
                        usage_client();
@@ -915,6 +942,15 @@ do_client(int argc, char *argv[])
                                &br_sslrec_in_gcm_vtable,
                                &br_sslrec_out_gcm_vtable);
                }
+               if ((req & REQ_CHAPOL) != 0) {
+                       br_ssl_engine_set_chacha20(&cc.eng,
+                               &br_chacha20_ct_run);
+                       br_ssl_engine_set_poly1305(&cc.eng,
+                               &br_poly1305_ctmul_run);
+                       br_ssl_engine_set_chapol(&cc.eng,
+                               &br_sslrec_in_chapol_vtable,
+                               &br_sslrec_out_chapol_vtable);
+               }
                if ((req & REQ_3DESCBC) != 0) {
                        br_ssl_engine_set_des_cbc(&cc.eng,
                                &br_des_ct_cbcenc_vtable,
@@ -927,17 +963,17 @@ do_client(int argc, char *argv[])
                        br_ssl_client_set_rsapub(&cc, &br_rsa_i31_public);
                }
                if ((req & REQ_ECDHE_RSA) != 0) {
-                       br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31);
+                       br_ssl_engine_set_ec(&cc.eng, &br_ec_all_m15);
                        br_ssl_engine_set_rsavrfy(&cc.eng,
                                &br_rsa_i31_pkcs1_vrfy);
                }
                if ((req & REQ_ECDHE_ECDSA) != 0) {
-                       br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31);
+                       br_ssl_engine_set_ec(&cc.eng, &br_ec_all_m15);
                        br_ssl_engine_set_ecdsa(&cc.eng,
                                &br_ecdsa_i31_vrfy_asn1);
                }
                if ((req & REQ_ECDH) != 0) {
-                       br_ssl_engine_set_ec(&cc.eng, &br_ec_prime_i31);
+                       br_ssl_engine_set_ec(&cc.eng, &br_ec_all_m15);
                }
        }
        if (fallback) {
@@ -971,7 +1007,7 @@ do_client(int argc, char *argv[])
        }
        br_x509_minimal_set_rsa(&xc, &br_rsa_i31_pkcs1_vrfy);
        br_x509_minimal_set_ecdsa(&xc,
-               &br_ec_prime_i31, &br_ecdsa_i31_vrfy_asn1);
+               &br_ec_all_m15, &br_ecdsa_i31_vrfy_asn1);
 
        /*
         * If there is no provided trust anchor, then certificate validation
@@ -993,6 +1029,10 @@ do_client(int argc, char *argv[])
                br_ssl_client_set_min_clienthello_len(&cc, minhello_len);
        }
        br_ssl_engine_set_all_flags(&cc.eng, flags);
+       if (VEC_LEN(alpn_names) != 0) {
+               br_ssl_engine_set_protocol_names(&cc.eng,
+                       &VEC_ELT(alpn_names, 0), VEC_LEN(alpn_names));
+       }
 
        if (chain != NULL) {
                zc.vtable = &ccert_vtable;
@@ -1048,6 +1088,7 @@ client_exit:
        xfree(suites);
        xfree(suite_ids);
        VEC_CLEAREXT(anchors, &free_ta_contents);
+       VEC_CLEAREXT(alpn_names, &free_alpn);
        free_certificates(chain, chain_len);
        free_private_key(sk);
        xfree(iobuf);