OpenSSL для 64-битной Windows и "без общего шифра"

Я только что скомпилировал и установил OpenSSL для 64-битной Windows. Я создал самозаверяющий сертификат и закрытый ключ с помощью команды:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 10000 -nodes

Сейчас я тестирую пример "Simple TLS Server", найденный в OpenSSL Wiki с Firefox, и несколько модификаций для поддержки Winsock, но я продолжаю получать сообщение об ошибке

11216:error:1417A0C1:SSL routines:tls_post_process_client_hello:no shared cipher:ssl\statem\statem_srvr.c:1422:

(первое число всегда меняется) во время выполнения функции SSL_accept(). Я проверил список (11) шифров, отправленных Firefox (v 43.0.1) в своем клиенте TLS v1.2 Hello при подключении к какому-либо HTTPS-серверу с помощью Wireshark (поскольку захват на localhost затруднен), и сравнил его с поддерживаемыми моей установкой OpenSSL (найдена с помощью openssl.exe ciphers -s -tls1_2 -V). В результате есть общие шифры, так чего мне не хватает?!

Блок, содержащий строку 1422 файла statem_srvr.c, выглядит следующим образом, начиная с 1420:

if (cipher == NULL) {
    SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
           SSL_R_NO_SHARED_CIPHER);
    goto f_err;
}

Изменения в исходном коде перед циклом while и в заголовках:

#pragma comment(lib,"Ws2_32.lib")
#include <stdio.h>
#include <winerror.h>
#include <WinSock2.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/applink.c>

а также

int sock;
SSL_CTX *ctx;

WSADATA WsaDat;
if (WSAStartup(MAKEWORD(2, 2), &WsaDat) != 0) perror("Winsock fatal startup error");
init_openssl();
ctx = create_context();
configure_context(ctx);

sock = create_socket(4433);

Редактировать: это то, что происходит, когда я пытаюсь подключиться к серверу, используя s_client с TLSv1.2:

CONNECTED(000000F0)
23368:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:ssl\record\rec_layer_s3.c:1362:SSL alert number 40
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 176 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1473536238
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no
---

3 ответа

Решение

Оказывается, возникла проблема с поиском сертификата и закрытого ключа. Задача решена.

Комментарий EJP решил мою проблему. В моем случае я создал объект SSL с SSL_CTX, но установил сертификат и ключ для SSL_CTX после того, как создал объект ssl, поэтому сертификат и ключ никогда не копировались в объект SSL. Перемещение моего сертификата и кода ключа до того, как я создал свой объект SSL, решило проблему.

Неправильный способ:

/*Create SSL Context*/
SSL_CTX *ctx = SSL_CTX_new(TLS_server_method());

/*Create SSL Object*/
SSL *ssl = SSL_new(ctx);

/*Load certs into SSL server*/ //<---WRONG; SHOULD NOT BE HERE
if (!SSL_CTX_use_certificate_file(ctx, "C:\\Users\\dzmf39\\Documents\\PPH1261726\\TLS\\tls_cert.pem", SSL_FILETYPE_PEM)) {
    fprintf(stderr, "Error while loading SSL Server Certificate.\n");
    return 0;
}

if (!SSL_CTX_use_PrivateKey_file(ctx, "C:\\Users\\dzmf39\\Documents\\PPH1261726\\TLS\\tls_key.pem", SSL_FILETYPE_PEM)) {
    ERR_print_errors_fp(stderr);
    return 0;
}

SSL_do_handshake(ssl); //Throws handshake error

Правильно

/*Create SSL Context*/
SSL_CTX *ctx = SSL_CTX_new(TLS_server_method());

/*Load certs into SSL server*/ //<---CORRECT; GOES BEFORE SSL object creation
if (!SSL_CTX_use_certificate_file(ctx, "C:\\Users\\dzmf39\\Documents\\PPH1261726\\TLS\\tls_cert.pem", SSL_FILETYPE_PEM)) {
    fprintf(stderr, "Error while loading SSL Server Certificate.\n");
    return 0;
}

if (!SSL_CTX_use_PrivateKey_file(ctx, "C:\\Users\\dzmf39\\Documents\\PPH1261726\\TLS\\tls_key.pem", SSL_FILETYPE_PEM)) {
    ERR_print_errors_fp(stderr);
    return 0;
}

/*Create SSL Object*/
SSL *ssl = SSL_new(ctx);

SSL_do_handshake(ssl);

Существуют другие методы, в которых вы можете добавить ключ непосредственно к объекту SSL, и в этом случае это не будет применяться, но я не пошел по этому пути.

Я также столкнулся с той же проблемой. Я также решил это:

берофе (это ошибка)

SSL_CTX_new
SSL_new
SSL_CTX_use_certificate_chain_file
SSL_CTX_use_PrivateKey_file

после (это нормально)

SSL_CTX_new
SSL_CTX_use_certificate_chain_file
SSL_CTX_use_PrivateKey_file
SSL_new
Другие вопросы по тегам