open-quantum-safe / openssl

UNSUPPORTED Fork of OpenSSL 1.1.1 that includes prototype quantum-resistant algorithms and ciphersuites based on liboqs PLEASE SWITCH TO OQS-Provider for OpenSSL 3
https://openquantumsafe.org/
Other
296 stars 126 forks source link

How to choose algortihm for KEX/GEM of my choice? #156

Closed ReverseControl closed 4 years ago

ReverseControl commented 4 years ago

It is unclear, and seemingly impossible after trying hard, to select a quantum algorithm for KEM/KEX of my choice, or at all for that matter. The example given with the internal TLS server/client designed for testing works like a charm, but if I wanted to choose a quantum algorithm for KEM/KEX say for a vpn, or generate the parameters to use one for a configuration file, there seems to be no way of doing this. With the OQS-Openssl_1.0.2 one can specify the ciphersuite and that takes care of it because in that version the ciphersuite definition includes the KEM/KEX, but in OpenSSL 1.1.1 KEM/KEX is no longer in the ciphersuite, and creating "curves" for the Qalgorithms using the OpenSSL API for EC is no go.

Even the demos for nginx/curl/httpd do not mention how to choose one over the others. Could you please advice on how to do this?

Thank you.

xvzcf commented 4 years ago

For TLS 1.3, the OQS key-exchange algorithms only pretend to be elliptic curves in the ssl layer, so that an algorithm can be negotiated using the supported_groups and key_share TLS 1.3 extensions. They haven't been added to the EC API since they aren't really elliptic curves, and cannot be manipulated as such.

Thus, you should be able to specify a PQ key-exchange by passing an OQS algorithm name to an option/directive through which an EC curve/group can be named. This option will vary based on the application, but, for example, to use frodo640aes:

1) In OpenSSL s_client, you can pass the -curves frodo640aes option. This will instruct s_client to allow only frodo640aes for key-exchange. 2) In OpenSSL s_server: You can again pass the -curves frodo640aes option. Again, this means s_server will allow only frodo640aes for key-exchange. 3) In nginx: You can specify ssl_ecdh_curve frodo640aes in the nginx.conf file (as seen here). nginx will then allow only frodo640aes for key-exchange. 4) In httpd: You can specify SSLOpenSSLConfCmd Curves frodo640aes in the httpd-ssl.conf file (as seen here) 4) In OpenVPN, after consulting this page, I believe the ecdh-curve frodo640aes option should do the trick. I have not tried it however.

Now, if, for example, you want to support both frodo640aes and kyber512, and no more, you can replace frodo640aes above with frodo640aes:kyber512. The "Key Exchange" section here gives a full list of the OQS key-exchange algorithm names you can specify.

N.B: OpenSSL 1.1.1 has implementations of both the TLS 1.2 and TLS 1.3 protocols, and it is in TLS 1.2 that "ciphersuite" refers to "signature algorithm + key exchange method + symmetric authenticated encryption scheme". In OQS-OpenSSL 1.1.1, we have added post-quantum key-exchange algorithms to the TLS 1.3 protocol only.

ReverseControl commented 4 years ago

I tested with OpenVPN, it does not work. No Quantum KEMs/KEXs "curves" are recognized. The server uses the below curves as expected, I tested, but with "kyber512" and "frodo640aes" as per your example I get:

openvpn   --ecdh-curve kyber512 --config openvpn.conf 
Thu Mar  5 22:54:42 2020 OpenVPN 2.4.8 x86_64-pc-linux-musl [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [MH/PKTINFO] [AEAD] built on Mar  4 2020
Thu Mar  5 22:54:42 2020 library versions: OpenSSL 1.1.1d  10 Sep 2019, LZO 2.10
Thu Mar  5 22:54:42 2020 Failed to use supplied curve (kyber512), using secp384r1 instead.
Thu Mar  5 22:54:42 2020 ECDH curve secp384r1 added

The function that get's called in OpenVPN to handle the ecdh-curve parameter uses OpenSSL code, but apparently is not able to find the curves nid by name . See below:

EDIT 1: I found the problem:

  1. openvpn calls tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name)

void
tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name )
{
#ifndef OPENSSL_NO_EC
    int nid = NID_undef;
    EC_KEY *ecdh = NULL;
    const char *sname = NULL;

    /* Generate a new ECDH key for each SSL session (for non-ephemeral ECDH) */
    SSL_CTX_set_options(ctx->ctx, SSL_OP_SINGLE_ECDH_USE);

    if (curve_name != NULL)
    {
        /* Use user supplied curve if given */
        msg(D_TLS_DEBUG, "Using user specified ECDH curve (%s)", curve_name);
        nid = OBJ_sn2nid(curve_name);
    }
    else
  {
  ...stuff we neve execute...
  }

    /* Translate NID back to name , just for kicks */
    sname = OBJ_nid2sn(nid);
    if (sname == NULL)
    {
        sname = "(Unknown)";
    }

    /* Create new EC key and set as ECDH key */
    if (NID_undef == nid || NULL == (ecdh = EC_KEY_new_by_curve_name(nid)))
    {
        /* Creating key failed, fall back on sane default */
        ecdh = EC_KEY_new_by_curve_name(NID_secp384r1);
        const char *source = (NULL == curve_name) ?
                             "extract curve from certificate" : "use supplied curve";
        msg(D_TLS_DEBUG_LOW,
            "Failed to %s (%s), using secp384r1 instead.", source, sname);
        sname = OBJ_nid2sn(NID_secp384r1);
    }

    if (!SSL_CTX_set_tmp_ecdh(ctx->ctx, ecdh))
    {
        crypto_msg(M_FATAL, "SSL_CTX_set_tmp_ecdh: cannot add curve");
    }

    msg(D_TLS_DEBUG_LOW, "ECDH curve %s added", sname);

    EC_KEY_free(ecdh);
#else  /* ifndef OPENSSL_NO_EC */
    msg(D_LOW, "Your OpenSSL library was built without elliptic curve support."
        " Skipping ECDH parameter loading.");
#endif /* OPENSSL_NO_EC */
}
  1. which calls OpenSSL function EC_KEY_new_by_curve_name(NID_secp384r1); [dir: ./crypto/ec/ec_key.c]
    EC_KEY *EC_KEY_new_by_curve_name(int nid)
    {
    EC_KEY *ret = EC_KEY_new();
    if (ret == NULL)
        return NULL;
    ret->group = EC_GROUP_new_by_curve_name(nid);
    if (ret->group == NULL) {
        EC_KEY_free(ret);
        return NULL;
    }
    if (ret->meth->set_group != NULL
        && ret->meth->set_group(ret, ret->group) == 0) {
        EC_KEY_free(ret);
        return NULL;
    }
    return ret;
    }
  2. which calls ``EC_GROUP_new_by_curve_name(int nid) ``` [ dir: openssl/crypto/ec/ec_curve.c]

    EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
    {
    size_t i;
    EC_GROUP *ret = NULL;
    
    if (nid <= 0)
        return NULL;
    
    for (i = 0; i < curve_list_length; i++)
        if (curve_list[i].nid == nid) {
            ret = ec_group_new_from_data(curve_list[i]);
            break;
        }
    
    if (ret == NULL) {
        ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME, EC_R_UNKNOWN_GROUP);
        return NULL;
    }
    
    return ret;
    }
    1. The problem is in curve_list, its a global array in that file containing all the curves but none of the OQS algorithms show up in that list. Hence, that loop falls through without finding anything and NULL is returned up the call chain.
typedef struct _ec_list_element_st {
    int nid;
    const EC_CURVE_DATA *data;
    const EC_METHOD *(*meth) (void);
    const char *comment;
} ec_list_element;

static const ec_list_element curve_list[] = {
    /* prime field curves */
    /* secg curves */
    {NID_secp112r1, &_EC_SECG_PRIME_112R1.h, 0,
     "SECG/WTLS curve over a 112 bit prime field"},
    {NID_secp112r2, &_EC_SECG_PRIME_112R2.h, 0,
     "SECG curve over a 112 bit prime field"},
    {NID_secp128r1, &_EC_SECG_PRIME_128R1.h, 0,
     "SECG curve over a 128 bit prime field"},
    {NID_secp128r2, &_EC_SECG_PRIME_128R2.h, 0,
     "SECG curve over a 128 bit prime field"},
    {NID_secp160k1, &_EC_SECG_PRIME_160K1.h, 0,
     "SECG curve over a 160 bit prime field"},
    {NID_secp160r1, &_EC_SECG_PRIME_160R1.h, 0,
     "SECG curve over a 160 bit prime field"},
    {NID_secp160r2, &_EC_SECG_PRIME_160R2.h, 0,
     "SECG/WTLS curve over a 160 bit prime field"},
    /* SECG secp192r1 is the same as X9.62 prime192v1 and hence omitted */
    {NID_secp192k1, &_EC_SECG_PRIME_192K1.h, 0,
     "SECG curve over a 192 bit prime field"},
    {NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0,
     "SECG curve over a 224 bit prime field"},
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
    {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
     "NIST/SECG curve over a 224 bit prime field"},
#else
    {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
     "NIST/SECG curve over a 224 bit prime field"},
#endif
    {NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0,
     "SECG curve over a 256 bit prime field"},
    /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
    {NID_secp384r1, &_EC_NIST_PRIME_384.h, 0,
     "NIST/SECG curve over a 384 bit prime field"},
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
    {NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method,
     "NIST/SECG curve over a 521 bit prime field"},
#else
    {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0,
     "NIST/SECG curve over a 521 bit prime field"},
#endif
    /* X9.62 curves */
    {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
     "NIST/X9.62/SECG curve over a 192 bit prime field"},
    {NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0,
     "X9.62 curve over a 192 bit prime field"},
    {NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, 0,
     "X9.62 curve over a 192 bit prime field"},
    {NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, 0,
     "X9.62 curve over a 239 bit prime field"},
    {NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0,
     "X9.62 curve over a 239 bit prime field"},
    {NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0,
     "X9.62 curve over a 239 bit prime field"},
    {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
#if defined(ECP_NISTZ256_ASM)
     EC_GFp_nistz256_method,
#elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
     EC_GFp_nistp256_method,
#else
     0,
#endif
     "X9.62/SECG curve over a 256 bit prime field"},
#ifndef OPENSSL_NO_EC2M
    /* characteristic two field curves */
    /* NIST/SECG curves */
    {NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0,
     "SECG curve over a 113 bit binary field"},
    {NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, 0,
     "SECG curve over a 113 bit binary field"},
    {NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, 0,
     "SECG/WTLS curve over a 131 bit binary field"},
    {NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, 0,
     "SECG curve over a 131 bit binary field"},
    {NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0,
     "NIST/SECG/WTLS curve over a 163 bit binary field"},
    {NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, 0,
     "SECG curve over a 163 bit binary field"},
    {NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0,
     "NIST/SECG curve over a 163 bit binary field"},
    {NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, 0,
     "SECG curve over a 193 bit binary field"},
    {NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, 0,
     "SECG curve over a 193 bit binary field"},
    {NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0,
     "NIST/SECG/WTLS curve over a 233 bit binary field"},
    {NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0,
     "NIST/SECG/WTLS curve over a 233 bit binary field"},
    {NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, 0,
     "SECG curve over a 239 bit binary field"},
    {NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0,
     "NIST/SECG curve over a 283 bit binary field"},
    {NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0,
     "NIST/SECG curve over a 283 bit binary field"},
    {NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0,
     "NIST/SECG curve over a 409 bit binary field"},
    {NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0,
     "NIST/SECG curve over a 409 bit binary field"},
    {NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0,
     "NIST/SECG curve over a 571 bit binary field"},
    {NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0,
     "NIST/SECG curve over a 571 bit binary field"},
    /* X9.62 curves */
    {NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, 0,
     "X9.62 curve over a 163 bit binary field"},
    {NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, 0,
     "X9.62 curve over a 163 bit binary field"},
    {NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, 0,
     "X9.62 curve over a 163 bit binary field"},
    {NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, 0,
     "X9.62 curve over a 176 bit binary field"},
    {NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, 0,
     "X9.62 curve over a 191 bit binary field"},
    {NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, 0,
     "X9.62 curve over a 191 bit binary field"},
    {NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, 0,
     "X9.62 curve over a 191 bit binary field"},
    {NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, 0,
     "X9.62 curve over a 208 bit binary field"},
    {NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, 0,
     "X9.62 curve over a 239 bit binary field"},
    {NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, 0,
     "X9.62 curve over a 239 bit binary field"},
    {NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, 0,
     "X9.62 curve over a 239 bit binary field"},
    {NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, 0,
     "X9.62 curve over a 272 bit binary field"},
    {NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, 0,
     "X9.62 curve over a 304 bit binary field"},
    {NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, 0,
     "X9.62 curve over a 359 bit binary field"},
    {NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, 0,
     "X9.62 curve over a 368 bit binary field"},
    {NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, 0,
     "X9.62 curve over a 431 bit binary field"},
    /*
     * the WAP/WTLS curves [unlike SECG, spec has its own OIDs for curves
     * from X9.62]
     */
    {NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, 0,
     "WTLS curve over a 113 bit binary field"},
    {NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0,
     "NIST/SECG/WTLS curve over a 163 bit binary field"},
    {NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0,
     "SECG curve over a 113 bit binary field"},
    {NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0,
     "X9.62 curve over a 163 bit binary field"},
#endif
    {NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0,
     "SECG/WTLS curve over a 112 bit prime field"},
    {NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0,
     "SECG/WTLS curve over a 160 bit prime field"},
    {NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0,
     "WTLS curve over a 112 bit prime field"},
    {NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0,
     "WTLS curve over a 160 bit prime field"},
#ifndef OPENSSL_NO_EC2M
    {NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0,
     "NIST/SECG/WTLS curve over a 233 bit binary field"},
    {NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0,
     "NIST/SECG/WTLS curve over a 233 bit binary field"},
#endif
    {NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0,
     "WTLS curve over a 224 bit prime field"},
#ifndef OPENSSL_NO_EC2M
    /* IPSec curves */
    {NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0,
     "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n"
     "\tNot suitable for ECDSA.\n\tQuestionable extension field!"},
    {NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0,
     "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n"
     "\tNot suitable for ECDSA.\n\tQuestionable extension field!"},
#endif
    /* brainpool curves */
    {NID_brainpoolP160r1, &_EC_brainpoolP160r1.h, 0,
     "RFC 5639 curve over a 160 bit prime field"},
    {NID_brainpoolP160t1, &_EC_brainpoolP160t1.h, 0,
     "RFC 5639 curve over a 160 bit prime field"},
    {NID_brainpoolP192r1, &_EC_brainpoolP192r1.h, 0,
     "RFC 5639 curve over a 192 bit prime field"},
    {NID_brainpoolP192t1, &_EC_brainpoolP192t1.h, 0,
     "RFC 5639 curve over a 192 bit prime field"},
    {NID_brainpoolP224r1, &_EC_brainpoolP224r1.h, 0,
     "RFC 5639 curve over a 224 bit prime field"},
    {NID_brainpoolP224t1, &_EC_brainpoolP224t1.h, 0,
     "RFC 5639 curve over a 224 bit prime field"},
    {NID_brainpoolP256r1, &_EC_brainpoolP256r1.h, 0,
     "RFC 5639 curve over a 256 bit prime field"},
    {NID_brainpoolP256t1, &_EC_brainpoolP256t1.h, 0,
     "RFC 5639 curve over a 256 bit prime field"},
    {NID_brainpoolP320r1, &_EC_brainpoolP320r1.h, 0,
     "RFC 5639 curve over a 320 bit prime field"},
    {NID_brainpoolP320t1, &_EC_brainpoolP320t1.h, 0,
     "RFC 5639 curve over a 320 bit prime field"},
    {NID_brainpoolP384r1, &_EC_brainpoolP384r1.h, 0,
     "RFC 5639 curve over a 384 bit prime field"},
    {NID_brainpoolP384t1, &_EC_brainpoolP384t1.h, 0,
     "RFC 5639 curve over a 384 bit prime field"},
    {NID_brainpoolP512r1, &_EC_brainpoolP512r1.h, 0,
     "RFC 5639 curve over a 512 bit prime field"},
    {NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0,
     "RFC 5639 curve over a 512 bit prime field"},
#ifndef OPENSSL_NO_SM2
    {NID_sm2, &_EC_sm2p256v1.h, 0,
     "SM2 curve over a 256 bit prime field"},
#endif
};
  1. It is unclear to me how to extend this table for the OQS algorithms: what the values would be and if there is any extra logic that needs to be added anywhere else to make this work like a charm.

  2. Now the openvpn curve list makes sense, it is exactly the list above.

    openvpn --show-curves
    Available Elliptic curves:
    secp112r1
    secp112r2
    secp128r1
    secp128r2
    secp160k1
    secp160r1
    secp160r2
    secp192k1
    secp224k1
    secp224r1
    secp256k1
    secp384r1
    secp521r1
    prime192v1
    prime192v2
    prime192v3
    prime239v1
    prime239v2
    prime239v3
    prime256v1
    sect113r1
    sect113r2
    sect131r1
    sect131r2
    sect163k1
    sect163r1
    sect163r2
    sect193r1
    sect193r2
    sect233k1
    sect233r1
    sect239k1
    sect283k1
    sect283r1
    sect409k1
    sect409r1
    sect571k1
    sect571r1
    c2pnb163v1
    c2pnb163v2
    c2pnb163v3
    c2pnb176v1
    c2tnb191v1
    c2tnb191v2
    c2tnb191v3
    c2pnb208w1
    c2tnb239v1
    c2tnb239v2
    c2tnb239v3
    c2pnb272w1
    c2pnb304w1
    c2tnb359v1
    c2pnb368w1
    c2tnb431r1
    wap-wsg-idm-ecid-wtls1
    wap-wsg-idm-ecid-wtls3
    wap-wsg-idm-ecid-wtls4
    wap-wsg-idm-ecid-wtls5
    wap-wsg-idm-ecid-wtls6
    wap-wsg-idm-ecid-wtls7
    wap-wsg-idm-ecid-wtls8
    wap-wsg-idm-ecid-wtls9
    wap-wsg-idm-ecid-wtls10
    wap-wsg-idm-ecid-wtls11
    wap-wsg-idm-ecid-wtls12
    Oakley-EC2N-3
    Oakley-EC2N-4
    brainpoolP160r1
    brainpoolP160t1
    brainpoolP192r1
    brainpoolP192t1
    brainpoolP224r1
    brainpoolP224t1
    brainpoolP256r1
    brainpoolP256t1
    brainpoolP320r1
    brainpoolP320t1
    brainpoolP384r1
    brainpoolP384t1
    brainpoolP512r1
    brainpoolP512t1
    SM2
ReverseControl commented 4 years ago

For the OpenSSl s_server/s_client in the 1.0.2 archived fork using TLSv1.2 I was able to verify that kyber1024 works because I can see that "random bytes" used in the exchange are the exact size it should be for that parameter per the NIST submission paper for kyber, and also because the ciphersuite for that algorithm is chosen by the server when it's the only one the client lists as available -- I wanted to make sure it chose that one.

But, nginx on TLSv1.3 under OQS-OpenSSL-1.1.1-stable is a different beast. For one thing, I am never able to see the TLS handshake in traffic, never happens...it is a mystery to me what is going on there, or if my chosen cipher suite in the nginx conf file is ever chosen. Also, the output of the openssl s_client is not exactly showing if the KEM/KEX chosen is actually used. The only thing that is clear is that the certificates are being validated; I can't say anything beyond that.

Could you please confirm or let me know I did something wrong.

Update: The reason I was not able to see the nginx traffic is silly...it turns out you have to enable docker containers to have access to your network, else all traffic is internal to docker. So open ports to the outside world with -p hostport:containerport or the whole thing with --network host. After that I was able to see the nginx traffic and it looks fine.

baentsch commented 4 years ago

May I suggest you try out OQS-nginx: When running that, openssl s_client always shows the temp k[ex] (type) chosen, e.g.:

No client certificate CA names sent
Peer signature type: Dilithium-2
Server Temp Key: saber
---
SSL handshake has read 6961 bytes and written 1383 bytes
Verification: OK

(generated by executing the example code): Use any of the KEMs supported and you will see Server Temp Key (type) changing, as well as data lengths and timings change (roughly in line with what is expected for each algorithm). You can even trigger classic EC, e.g., by passing (KEX=)X448 as the curves parameter.

ReverseControl commented 4 years ago

@baentsch Ah, yes I see that. However, I still cannot see the TLS hello in the traffic, can you see the raw packets with that key negotiated?

baentsch commented 4 years ago

@ReverseControl Yes. openssl s_client -debug.

ReverseControl commented 4 years ago

@baentsch I still cannot see the TLS handshake in traffic; that is to say, capturing traffic independent of openssl for verification.

Using the debug flag I noticed the following:

/opt/openssl/apps/openssl s_client  -curves kyber1024  -debug  -connect localhost:4433
...
...
...
---
No client certificate CA names sent
Peer signature type: Dilithium-2
Server Temp Key: kyber1024
---
SSL handshake has read 7297 bytes and written 1941 bytes
Verification error: unable to verify the first certificate
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 9472 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 21 (unable to verify the first certificate)
---
...
...
...

Is this public key meant to be the kyber2014 public key? Because the size of that key, per the NIST submission paper, is exactly 1568 bytes which is not 9472 bits.

dstebila commented 4 years ago

Is this public key meant to be the kyber2014 public key? Because the size of that key, per the NIST submission paper, is exactly 1568 bytes which is not 9472 bits.

Public key here refers to the signature scheme (which in this case is Dilithium 2) not the KEM for the key exchange.

christianpaquin commented 4 years ago

I tested with OpenVPN, it does not work. No Quantum KEMs/KEXs "curves" are recognized. The server uses the below curves as expected, I tested, but with "kyber512" and "frodo640aes" as per your example I get

OpenVPN doesn't work with our fork TLS 1.3 OpenSSL 1.1.1 fork. Even if you had the code to find the curve, you still get errors because OpenSSL is trying to parse the alg as an actual elliptic curve. More modifications would be needed on OpenVPN to make this work.

ReverseControl commented 4 years ago

The TLS1.3 OpenSSL 1.1.1 fork works just fine with nginx; i looked at the source code and it does not seem to do anything that much different than the OpenVPN source code to handle TLS, other than being much better organized and readable.

What needs to be done to make OpenVPN work with the TLS1.3 OpenSSL 1.1.1 fork? I can give it a shot to integrate it, after all nginx already uses it and it works like a charm.

christianpaquin commented 4 years ago

What needs to be done to make OpenVPN work with the TLS1.3 OpenSSL 1.1.1 fork?

This is on the list of things to investigate...

ReverseControl commented 4 years ago

Update: The reason I was not able to see the nginx traffic is silly...it turns out you have to enable docker containers to have access to your network, else all traffic is internal to docker. So open ports to the outside world with -p hostport:containerport or the whole thing with --network host. After that I was able to see the nginx traffic and it looks fine for nginx.

@christianpaquin why can't we have nice things that just work? :(