Verification method not firing after second ClientHello with OpenSSL memory BIOs
I am writing a native DTLS module for NodeJS using OpenSSL. It uses memory BIOs so node's own sockets can be used to control the flow of data. Everything seems to be working but I am running into some problems with the DOS mitigation.
According to the spec, the initial ClientHello sent to the server should be rejected and the server will send a HelloVerifyRequest containing a cookie to be resent back from the client. This all works fine but when the client sends back the second ClientHello, for some reason the DTLSv1_listen() call is causing my cookie generation method to fire a second time instead of the cookie verification method. Strangely enough, if I send back the second HelloVerifyRequest (exact same length and content as the first) I end up with a ClientHello that seems to trigger the verification method.
Here's a small test I've written to illustrate the kind of thing I'm doing (not exactly, skipped some stuff like importing the cert/key, result code checking for read/writes after calling handshake, freeing memory etc).
TEST(New, Test) {
// Init context
auto ctx = SSL_CTX_new(DTLS_method());
SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, (int ok, X509_STORE_CTX * context) { return 1; });
SSL_CTX_set_cookie_generate_cb(ctx, (SSL * ssl, unsigned char * cookie, unsigned int * cookie_len) {
return 1;
});
SSL_CTX_set_cookie_verify_cb(ctx, (SSL * ssl, const unsigned char * cookie, unsigned int cookie_len) {
return 1;
});
// Init connections
auto client = SSL_new(ctx);
auto client_rbio = BIO_new(BIO_s_mem());
auto client_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(client, client_rbio, client_wbio);
SSL_set_connect_state(client);
auto server = SSL_new(ctx);
auto server_rbio = BIO_new(BIO_s_mem());
auto server_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(server, server_rbio, server_wbio);
SSL_set_accept_state(server);
std::vector<unsigned char> data;
// Client Hello, no cookie
SSL_do_handshake(client);
auto data_len = BIO_ctrl_pending(client_wbio);
data.resize(data_len);
BIO_read(client_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 1);
// Hello Verify Request
BIO_write(server_rbio, data.data(), data.size());
DTLSv1_listen(server, NULL);
data_len = BIO_ctrl_pending(server_wbio);
data.resize(data_len);
BIO_read(server_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 3);
// Client Hello, with cookie
BIO_write(client_rbio, data.data(), data.size());
SSL_do_handshake(client);
data_len = BIO_ctrl_pending(client_wbio);
data.resize(data_len);
BIO_read(client_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 1);
// Should be pass...?
BIO_write(server_rbio, data.data(), data.size());
ASSERT_EQ(DTLSv1_listen(server, NULL), 1);
}
The last assert fails -- it is -1 in this example, 0 in my actual code (and subsequent BIO_read gets me data[13]=3 aka HelloVerifyRequest) but the important thing to note here is that if you attach a debugger and put a breakpoint on the verification lambda it will not be hit.
c++ openssl dtls
add a comment |
I am writing a native DTLS module for NodeJS using OpenSSL. It uses memory BIOs so node's own sockets can be used to control the flow of data. Everything seems to be working but I am running into some problems with the DOS mitigation.
According to the spec, the initial ClientHello sent to the server should be rejected and the server will send a HelloVerifyRequest containing a cookie to be resent back from the client. This all works fine but when the client sends back the second ClientHello, for some reason the DTLSv1_listen() call is causing my cookie generation method to fire a second time instead of the cookie verification method. Strangely enough, if I send back the second HelloVerifyRequest (exact same length and content as the first) I end up with a ClientHello that seems to trigger the verification method.
Here's a small test I've written to illustrate the kind of thing I'm doing (not exactly, skipped some stuff like importing the cert/key, result code checking for read/writes after calling handshake, freeing memory etc).
TEST(New, Test) {
// Init context
auto ctx = SSL_CTX_new(DTLS_method());
SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, (int ok, X509_STORE_CTX * context) { return 1; });
SSL_CTX_set_cookie_generate_cb(ctx, (SSL * ssl, unsigned char * cookie, unsigned int * cookie_len) {
return 1;
});
SSL_CTX_set_cookie_verify_cb(ctx, (SSL * ssl, const unsigned char * cookie, unsigned int cookie_len) {
return 1;
});
// Init connections
auto client = SSL_new(ctx);
auto client_rbio = BIO_new(BIO_s_mem());
auto client_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(client, client_rbio, client_wbio);
SSL_set_connect_state(client);
auto server = SSL_new(ctx);
auto server_rbio = BIO_new(BIO_s_mem());
auto server_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(server, server_rbio, server_wbio);
SSL_set_accept_state(server);
std::vector<unsigned char> data;
// Client Hello, no cookie
SSL_do_handshake(client);
auto data_len = BIO_ctrl_pending(client_wbio);
data.resize(data_len);
BIO_read(client_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 1);
// Hello Verify Request
BIO_write(server_rbio, data.data(), data.size());
DTLSv1_listen(server, NULL);
data_len = BIO_ctrl_pending(server_wbio);
data.resize(data_len);
BIO_read(server_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 3);
// Client Hello, with cookie
BIO_write(client_rbio, data.data(), data.size());
SSL_do_handshake(client);
data_len = BIO_ctrl_pending(client_wbio);
data.resize(data_len);
BIO_read(client_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 1);
// Should be pass...?
BIO_write(server_rbio, data.data(), data.size());
ASSERT_EQ(DTLSv1_listen(server, NULL), 1);
}
The last assert fails -- it is -1 in this example, 0 in my actual code (and subsequent BIO_read gets me data[13]=3 aka HelloVerifyRequest) but the important thing to note here is that if you attach a debugger and put a breakpoint on the verification lambda it will not be hit.
c++ openssl dtls
add a comment |
I am writing a native DTLS module for NodeJS using OpenSSL. It uses memory BIOs so node's own sockets can be used to control the flow of data. Everything seems to be working but I am running into some problems with the DOS mitigation.
According to the spec, the initial ClientHello sent to the server should be rejected and the server will send a HelloVerifyRequest containing a cookie to be resent back from the client. This all works fine but when the client sends back the second ClientHello, for some reason the DTLSv1_listen() call is causing my cookie generation method to fire a second time instead of the cookie verification method. Strangely enough, if I send back the second HelloVerifyRequest (exact same length and content as the first) I end up with a ClientHello that seems to trigger the verification method.
Here's a small test I've written to illustrate the kind of thing I'm doing (not exactly, skipped some stuff like importing the cert/key, result code checking for read/writes after calling handshake, freeing memory etc).
TEST(New, Test) {
// Init context
auto ctx = SSL_CTX_new(DTLS_method());
SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, (int ok, X509_STORE_CTX * context) { return 1; });
SSL_CTX_set_cookie_generate_cb(ctx, (SSL * ssl, unsigned char * cookie, unsigned int * cookie_len) {
return 1;
});
SSL_CTX_set_cookie_verify_cb(ctx, (SSL * ssl, const unsigned char * cookie, unsigned int cookie_len) {
return 1;
});
// Init connections
auto client = SSL_new(ctx);
auto client_rbio = BIO_new(BIO_s_mem());
auto client_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(client, client_rbio, client_wbio);
SSL_set_connect_state(client);
auto server = SSL_new(ctx);
auto server_rbio = BIO_new(BIO_s_mem());
auto server_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(server, server_rbio, server_wbio);
SSL_set_accept_state(server);
std::vector<unsigned char> data;
// Client Hello, no cookie
SSL_do_handshake(client);
auto data_len = BIO_ctrl_pending(client_wbio);
data.resize(data_len);
BIO_read(client_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 1);
// Hello Verify Request
BIO_write(server_rbio, data.data(), data.size());
DTLSv1_listen(server, NULL);
data_len = BIO_ctrl_pending(server_wbio);
data.resize(data_len);
BIO_read(server_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 3);
// Client Hello, with cookie
BIO_write(client_rbio, data.data(), data.size());
SSL_do_handshake(client);
data_len = BIO_ctrl_pending(client_wbio);
data.resize(data_len);
BIO_read(client_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 1);
// Should be pass...?
BIO_write(server_rbio, data.data(), data.size());
ASSERT_EQ(DTLSv1_listen(server, NULL), 1);
}
The last assert fails -- it is -1 in this example, 0 in my actual code (and subsequent BIO_read gets me data[13]=3 aka HelloVerifyRequest) but the important thing to note here is that if you attach a debugger and put a breakpoint on the verification lambda it will not be hit.
c++ openssl dtls
I am writing a native DTLS module for NodeJS using OpenSSL. It uses memory BIOs so node's own sockets can be used to control the flow of data. Everything seems to be working but I am running into some problems with the DOS mitigation.
According to the spec, the initial ClientHello sent to the server should be rejected and the server will send a HelloVerifyRequest containing a cookie to be resent back from the client. This all works fine but when the client sends back the second ClientHello, for some reason the DTLSv1_listen() call is causing my cookie generation method to fire a second time instead of the cookie verification method. Strangely enough, if I send back the second HelloVerifyRequest (exact same length and content as the first) I end up with a ClientHello that seems to trigger the verification method.
Here's a small test I've written to illustrate the kind of thing I'm doing (not exactly, skipped some stuff like importing the cert/key, result code checking for read/writes after calling handshake, freeing memory etc).
TEST(New, Test) {
// Init context
auto ctx = SSL_CTX_new(DTLS_method());
SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, (int ok, X509_STORE_CTX * context) { return 1; });
SSL_CTX_set_cookie_generate_cb(ctx, (SSL * ssl, unsigned char * cookie, unsigned int * cookie_len) {
return 1;
});
SSL_CTX_set_cookie_verify_cb(ctx, (SSL * ssl, const unsigned char * cookie, unsigned int cookie_len) {
return 1;
});
// Init connections
auto client = SSL_new(ctx);
auto client_rbio = BIO_new(BIO_s_mem());
auto client_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(client, client_rbio, client_wbio);
SSL_set_connect_state(client);
auto server = SSL_new(ctx);
auto server_rbio = BIO_new(BIO_s_mem());
auto server_wbio = BIO_new(BIO_s_mem());
SSL_set_bio(server, server_rbio, server_wbio);
SSL_set_accept_state(server);
std::vector<unsigned char> data;
// Client Hello, no cookie
SSL_do_handshake(client);
auto data_len = BIO_ctrl_pending(client_wbio);
data.resize(data_len);
BIO_read(client_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 1);
// Hello Verify Request
BIO_write(server_rbio, data.data(), data.size());
DTLSv1_listen(server, NULL);
data_len = BIO_ctrl_pending(server_wbio);
data.resize(data_len);
BIO_read(server_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 3);
// Client Hello, with cookie
BIO_write(client_rbio, data.data(), data.size());
SSL_do_handshake(client);
data_len = BIO_ctrl_pending(client_wbio);
data.resize(data_len);
BIO_read(client_wbio, data.data(), data.size());
ASSERT_EQ(data[13], 1);
// Should be pass...?
BIO_write(server_rbio, data.data(), data.size());
ASSERT_EQ(DTLSv1_listen(server, NULL), 1);
}
The last assert fails -- it is -1 in this example, 0 in my actual code (and subsequent BIO_read gets me data[13]=3 aka HelloVerifyRequest) but the important thing to note here is that if you attach a debugger and put a breakpoint on the verification lambda it will not be hit.
c++ openssl dtls
c++ openssl dtls
edited Dec 31 '18 at 7:52
Ulrich Eckhardt
12.7k11737
12.7k11737
asked Dec 31 '18 at 7:01
Robert FelizardoRobert Felizardo
62
62
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
You could try using nodejs-dtls
Sample usage can be found in
IOTBroker. cloud nodejs client
Take a look at CoAP and MQTT-SN protocols
BR
Yulian Oifa
Mobius Software
This is definitely an alternative but not really what I'm looking for. I'd like to leverage the OpenSSL shipped with node.
– Robert Felizardo
Jan 9 at 2:27
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53984560%2fverification-method-not-firing-after-second-clienthello-with-openssl-memory-bios%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You could try using nodejs-dtls
Sample usage can be found in
IOTBroker. cloud nodejs client
Take a look at CoAP and MQTT-SN protocols
BR
Yulian Oifa
Mobius Software
This is definitely an alternative but not really what I'm looking for. I'd like to leverage the OpenSSL shipped with node.
– Robert Felizardo
Jan 9 at 2:27
add a comment |
You could try using nodejs-dtls
Sample usage can be found in
IOTBroker. cloud nodejs client
Take a look at CoAP and MQTT-SN protocols
BR
Yulian Oifa
Mobius Software
This is definitely an alternative but not really what I'm looking for. I'd like to leverage the OpenSSL shipped with node.
– Robert Felizardo
Jan 9 at 2:27
add a comment |
You could try using nodejs-dtls
Sample usage can be found in
IOTBroker. cloud nodejs client
Take a look at CoAP and MQTT-SN protocols
BR
Yulian Oifa
Mobius Software
You could try using nodejs-dtls
Sample usage can be found in
IOTBroker. cloud nodejs client
Take a look at CoAP and MQTT-SN protocols
BR
Yulian Oifa
Mobius Software
answered Jan 7 at 18:15
Yulian OifaYulian Oifa
373
373
This is definitely an alternative but not really what I'm looking for. I'd like to leverage the OpenSSL shipped with node.
– Robert Felizardo
Jan 9 at 2:27
add a comment |
This is definitely an alternative but not really what I'm looking for. I'd like to leverage the OpenSSL shipped with node.
– Robert Felizardo
Jan 9 at 2:27
This is definitely an alternative but not really what I'm looking for. I'd like to leverage the OpenSSL shipped with node.
– Robert Felizardo
Jan 9 at 2:27
This is definitely an alternative but not really what I'm looking for. I'd like to leverage the OpenSSL shipped with node.
– Robert Felizardo
Jan 9 at 2:27
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53984560%2fverification-method-not-firing-after-second-clienthello-with-openssl-memory-bios%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown