Для того, чтобы использовать OpenSSL для шифрования, но сделать свой собственный сокет IO, что вы в основном сделать, это создать BIO памяти, что читать и писать данные гнездовые, как становится доступным , и приложите это к контексту SSL.
Каждый раз, когда вы выполняете вызов SSL_write, вы выполняете вызов в память BIO, чтобы узнать, есть ли у него данные в его буфере чтения, прочитать это и отправить его. И наоборот, когда данные поступают в сокет через механизм io завершения порта, вы записываете его в BIO и вызываете SSL_read для чтения данных. SSL_read может возвращать код ошибки, указывающий его в рукопожатии, что обычно означает, что он сгенерировал больше данных для записи - которые вы обрабатываете, снова считывая BIO памяти.
Чтобы создать свою SSL сессию, я делаю это:
// This creates a SSL session, and an in, and an out, memory bio and
// attaches them to the ssl session.
SSL* conn = SSL_new(ctx);
BIO* bioIn = BIO_new(BIO_s_mem());
BIO* bioOut = BIO_new(BIO_s_mem());
SSL_set_bio(conn,bioIn,bioOut);
// This tells the ssl session to start the negotiation.
SSL_set_connect_state(conn);
Как я получаю данные из сетевого уровня:
// buf contains len bytes read from the socket.
BIO_write(bioIn,buf,len);
SendPendingHandshakeData();
TryResendBufferedData(); // see below
int cbPlainText;
while(cbPlainText = SSL_read(ssl,&plaintext,sizeof(plaintext)) >0)
{
// Send the decoded data to the application
ProcessPlaintext(plaintext,cbPlaintext);
}
Как я получаю данные приложения для отправки - вам нужно быть готовым к сбою SSL_write, потому что выполняется рукопожатие, и в этом случае вы буферизируете данные и пытаетесь отправить их снова в будущем после получения некоторых данных.
if(SSL_write(conn,buf,len) < 0)
{
StoreDataForSendingLater(buf,len);
}
SendPendingHandshakeData();
И SendPendingHandshakeData посылает какое-либо данные (рукопожатие или зашифрованный), что SSL необходимо отправить.
while(cbPending = BIO_ctrl_pending(bioOut))
{
int len = BIO_read(bioOut,buf,sizeof(buf));
SendDataViaSocket(buf,len); // you fill this in here.
}
Это процесс в двух словах. Образцы кода не закончены, поскольку я должен был извлечь их из гораздо большей библиотеки, но я считаю, что их достаточно, чтобы начать с этого использования SSL. В реальном коде, когда ошибка SSL_read/write/BIO_read/write терпит неудачу, вероятно, лучше вызвать SSL_get_error и решить, что делать на основе результата: SSL_ERROR_WANT_READ является важным и означает, что вы не могли бы SSL_write больше данных, так как вам это нужно сначала читать и отправлять ожидающие данные в bioOut BIO.
Поддерживает ли «Asio» поддержку OpenSSL? – Gabe 2010-12-10 03:51:38
Да, есть несколько примеров в ссылке, которую я опубликовал. – 2010-12-10 12:59:20