'没有共享密码' EDH-RSA-DES-CBC3-SHA出错

时间:2015-04-23 18:39:39

标签: c openssl

我想用密码EDH-RSA-DES-CBC3-SHA测试TLS 1.0连接。

我使用openssl s_server和s_client进行测试。工作良好。连接和数据交换都很好。

  

openssl s_server -accept 4433 -cert server.pem -key serverkey.pem -cipher EDH-RSA-DES-CBC3-SHA -tls1

     

openssl s_client -connect 127.0.0.1:443 -cipher EDH-RSA-DES-CBC3-SHA -tls1

     

共享密码:EDH-RSA-DES-CBC3-SHA

现在,我有另一个简单的OpenSSL服务器代码。使用this和s_client,连接失败,服务器抛出以下内容:

  

3077613304:错误:1408A0C1:SSL例程:SSL3_GET_CLIENT_HELLO:无共享密码:s3_srvr.c:1361

我检查s_server / s_client使用的库和我的服务器应用程序使用的库是否相同如下:

cat /proc/9515/maps | awk '{print $6}' | grep '\.so' | sort | uniq | grep -e ssl -e libcrypto

  

/usr/lib/libcrypto.so.1.0.1e

     

/usr/lib/libssl.so.1.0.1e

但是,对于像AES128-SHA这样的其他密码的,从s_client到我的服务器应用程序的连接都没问题。

以下是我在服务器代码中设置ctx的方法:

SSL_CTX* InitServerCTX(void)
{
    SSL_CTX *ctx = NULL;
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings(); 

    ctx = SSL_CTX_new(TLSv1_server_method());
    SSL_CTX_set_cipher_list(ctx,"EDH-RSA-DES-CBC3-SHA"); // Returns 1

    SSL_CTX_use_certificate_chain_file(ctx, "server.pem");
    SSL_CTX_use_PrivateKey_file(ctx, "serverkey.pem", SSL_FILETYPE_PEM);

    return ctx;
}

为什么我的服务器应用程序会出现'没有共享密码'错误和s_server对同一个客户端没问题?

2 个答案:

答案 0 :(得分:4)

@ Cmidid的回答是正确的。这里有更多信息,包括IETF DH组和通过DH回调选择组大小。

用C ++编写,但很容易转换回C。

using DH_ptr = std::unique_ptr<DH, decltype(&::DH_free)>;
using BIO_MEM_ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
using BIO_FILE_ptr = std::unique_ptr<BIO, decltype(&::BIO_free)>;
using SSL_CTX_ptr = std::unique_ptr<SSL_CTX, decltype(&::SSL_CTX_free)>;

SSL_CTX* CreateServerContext(const string & domain)
{
    const SSL_METHOD* method = SSLv23_server_method();
    ASSERT(method != NULL);

    SSL_CTX_ptr t(SSL_CTX_new(method), ::SSL_CTX_free);
    ASSERT(t.get() != NULL);

    long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
            flags |= SSL_OP_NO_COMPRESSION;
            flags |= SSL_OP_SAFARI_ECDHE_ECDSA_BUG;
            flags |= SSL_OP_CIPHER_SERVER_PREFERENCE;

    SSL_CTX_set_options(t.get(), flags);

    string ciphers = "HIGH:!aNULL:!RC4:!MD5";
    rc = SSL_CTX_set_cipher_list(t.get(), ciphers.c_str());    
    ...

    LogDebug("GetServerContext: setting DH callback");
    SSL_CTX_set_tmp_dh_callback(t.get(), DhCallback);

    LogDebug("GetServerContext: setting ECDH callback");
    SSL_CTX_set_tmp_ecdh_callback(t.get(), EcdhCallback);
    ...

    return t.release();
}

DH* DhCallback(SSL *ssl, int is_export, int keylength)
{
    UNUSED(ssl);
    UNUSED(is_export);

#if defined(ALLOW_DH_1024_PARAMS)
    if (keylength <= 1024 + 4)
        return DH1024();
    else
#endif

    if (keylength <= 1536 + 4)
        return DH1536();
    else if (keylength <= 2048 + 4)
        return DH2048();
    else if (keylength <= 3072 + 4)
        return DH3072();
    else if (keylength <= 4096 + 4)
        return DH4096();

    return DH4096();
}

#if defined(ALLOW_DH_1024_PARAMS)
static DH* DH1024()
{
    static const char g_dh1024_sz[] = "-----BEGIN DH PARAMETERS-----\n"
    "MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR\n"
    "Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL\n"
    "/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC\n"
    "-----END DH PARAMETERS-----";

    static DH_ptr dh(NULL, NULL);

    if (dh.get())
        return dh.get();

    BIO_MEM_ptr bio(BIO_new_mem_buf((void*) g_dh1024_sz, (int) sizeof(g_dh1024_sz)), ::BIO_free);
    ASSERT(bio.get());

    dh = DH_ptr(PEM_read_bio_DHparams(bio.get(), NULL, NULL, NULL), ::DH_free);
    unsigned long err = ERR_get_error();

    ASSERT(dh.get());
    return dh.get();
}
#endif

static DH* DH1536()
{
    static const char g_dh1536_sz[] = "-----BEGIN DH PARAMETERS-----\n"
            "MIHHAoHBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR\n"
            "Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL\n"
            "/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORbPcIAfLihY78FmNpINhxV05pp\n"
            "Fj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaWbWcMNU5KvJgE8XRsCMojcyf/\n"
            "/////////wIBAg==\n"
            "-----END DH PARAMETERS-----";

    static DH_ptr dh(NULL, NULL);

    if (dh.get())
        return dh.get();

    BIO_MEM_ptr bio(BIO_new_mem_buf((void*) g_dh1536_sz, (int) sizeof(g_dh1536_sz)), ::BIO_free);
    ASSERT(bio.get());

    dh = DH_ptr(PEM_read_bio_DHparams(bio.get(), NULL, NULL, NULL), ::DH_free);
    unsigned long err = ERR_get_error();

    ASSERT(dh.get());
    return dh.get();
}

static DH* DH2048()
{
    static const char g_dh2048_sz[] = "-----BEGIN DH PARAMETERS-----\n"
            "MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n"
            "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n"
            "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n"
            "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n"
            "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n"
            "5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==\n"
            "-----END DH PARAMETERS-----";

    static DH_ptr dh(NULL, NULL);

    if (dh.get())
        return dh.get();

    BIO_MEM_ptr bio(BIO_new_mem_buf((void*) g_dh2048_sz, (int) sizeof(g_dh2048_sz)), ::BIO_free);
    ASSERT(bio.get());

    dh = DH_ptr(PEM_read_bio_DHparams(bio.get(), NULL, NULL, NULL), ::DH_free);
    unsigned long err = ERR_get_error();

    ASSERT(dh.get());
    return dh.get();
}

static DH* DH3072()
{
    static const char g_dh3072_sz[] = "-----BEGIN DH PARAMETERS-----\n"
            "MIIBiAKCAYEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n"
            "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n"
            "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n"
            "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n"
            "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n"
            "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM\n"
            "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq\n"
            "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqTrS\n"
            "yv//////////AgEC\n"
            "-----END DH PARAMETERS-----";

    static DH_ptr dh(NULL, NULL);

    if (dh.get())
        return dh.get();

    BIO_MEM_ptr bio(BIO_new_mem_buf((void*) g_dh3072_sz, (int) sizeof(g_dh3072_sz)), ::BIO_free);
    ASSERT(bio.get());

    dh = DH_ptr(PEM_read_bio_DHparams(bio.get(), NULL, NULL, NULL), ::DH_free);
    unsigned long err = ERR_get_error();

    ASSERT(dh.get());
    return dh.get();
}

static DH* DH4096()
{
    static const char g_dh4096_sz[] = "-----BEGIN DH PARAMETERS-----\n"
            "MIICCAKCAgEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n"
            "IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n"
            "awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n"
            "mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n"
            "fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n"
            "5RXSJhiY+gUQFXKOWoqqxC2tMxcNBFB6M6hVIavfHLpk7PuFBFjb7wqK6nFXXQYM\n"
            "fbOXD4Wm4eTHq/WujNsJM9cejJTgSiVhnc7j0iYa0u5r8S/6BtmKCGTYdgJzPshq\n"
            "ZFIfKxgXeyAMu+EXV3phXWx3CYjAutlG4gjiT6B05asxQ9tb/OD9EI5LgtEgqSEI\n"
            "ARpyPBKnh+bXiHGaEL26WyaZwycYavTiPBqUaDS2FQvaJYPpyirUTOjbu8LbBN6O\n"
            "+S6O/BQfvsqmKHxZR05rwF2ZspZPoJDDoiM7oYZRW+ftH2EpcM7i16+4G912IXBI\n"
            "HNAGkSfVsFqpk7TqmI2P3cGG/7fckKbAj030Nck0BjGZ//////////8CAQI=\n"
            "-----END DH PARAMETERS-----";

    static DH_ptr dh(NULL, NULL);

    if (dh.get())
        return dh.get();

    BIO_MEM_ptr bio(BIO_new_mem_buf((void*) g_dh4096_sz, (int) sizeof(g_dh4096_sz)), ::BIO_free);
    ASSERT(bio.get());

    dh = DH_ptr(PEM_read_bio_DHparams(bio.get(), NULL, NULL, NULL), ::DH_free);
    unsigned long err = ERR_get_error();

    ASSERT(dh.get());
    return dh.get();
}

答案 1 :(得分:2)

您需要创建一个DH对象并为ssl context DH设置ctx参数。更具体地说,一旦分配了DH对象,就需要设置primp p和generator g。

这样做的一种方法是使用下面的示例伪代码

这里dh512_p dh512_g分别是primo p和generator g

DH* get_dh512(const unsigned char *dh512_p,const unsigned char *dh512_g)
{
    DH *dh=NULL;
    if ((dh=DH_new()) == NULL) return(NULL);
    dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
    dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
    if ((dh->p == NULL) || (dh->g == NULL))
        return(NULL);

   return(dh);
}

然后使用回调

在函数中设置参数
//if key exchange is based on diffie hellman
DH *dh =  get_dh512(dh512_p,dh512_g)
SSL_CTX_set_tmp_dh(ctx,dh);
SSL_CTX_set_cipher_list(ctx,ciphers);

请查看以下链接,了解回拨详情http://linux.die.net/man/3/ssl_ctx_set_tmp_dh