-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
crypto: add cert check to CNNIC Whitelist #1895
Conversation
@@ -13,6 +13,9 @@ | |||
#include "util.h" | |||
#include "util-inl.h" | |||
#include "v8.h" | |||
// CNNIC Hash WhiteList is taken from | |||
// https://hg.mozilla.org/mozilla-central/raw-file/98820360ab66/security/certverifier/CNNICHashWhitelist.inc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't make cpplint
complain about the long lines?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woops, make test did not call make cpplint . I have to fix several styles.
I had typos. s/CNNNIC/CNNIC / |
"\x03\x55\x04\x03\x13\x0A\x43\x4E\x4E\x49\x43\x20\x52\x4F\x4F\x54"; | ||
const unsigned char* cnnic_p = CNNIC_ROOT_CA_SUBJECT_DATA; | ||
static X509_NAME *cnnic_name = d2i_X509_NAME(NULL, &cnnic_p, | ||
sizeof(CNNIC_ROOT_CA_SUBJECT_DATA)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style issues: star leans left and nullptr, not NULL. cnnic_p
should be static
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I think you're including the zero byte in the length now? Is that correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Styles are fixed. The length of sizeof(CNNIC_ROOT_CA_SUBJECT_DATA)
is not zero. Did I read your comment correctly?
bef171f
to
062ac11
Compare
The commit was updated according comments except the case of root_cert is |
The test of revoked case was made with something artificial change by removing one existing cert hash of www1.cnnic.cn from the whitelist as below. I'm not sure how to test this in general. diff --git a/src/CNNICHashWhitelist.inc b/src/CNNICHashWhitelist.inc
index e3c6a61..652209e 100644
--- a/src/CNNICHashWhitelist.inc
+++ b/src/CNNICHashWhitelist.inc
@@ -636,10 +636,10 @@ static const struct WhitelistedCNNICHash WhitelistedCNNICHashes[] = {
{ 0x1B, 0xEC, 0xFE, 0x78, 0xCE, 0x5E, 0x77, 0xA9, 0x77, 0xBB, 0x5F, 0xE3, 0x49, 0x91, 0x06, 0xC6,
0x4C, 0xF2, 0xB0, 0x76, 0x16, 0x59, 0x49, 0x04, 0x11, 0x17, 0xCD, 0x8A, 0xBC, 0xD9, 0x05, 0xD4 },
},
- {
- { 0x1B, 0xF4, 0x8A, 0x83, 0x3C, 0xE4, 0x05, 0x64, 0x8C, 0xC0, 0xBD, 0xD3, 0xB5, 0xB8, 0xC1, 0x8E,
- 0xB5, 0x13, 0x15, 0x34, 0x29, 0x3A, 0xB2, 0x63, 0x44, 0xB5, 0x00, 0x76, 0x48, 0x11, 0x41, 0xED },
- },
+// {
+// { 0x1B, 0xF4, 0x8A, 0x83, 0x3C, 0xE4, 0x05, 0x64, 0x8C, 0xC0, 0xBD, 0xD3, 0xB5, 0xB8, 0xC1, 0x8E,
+// 0xB5, 0x13, 0x15, 0x34, 0x29, 0x3A, 0xB2, 0x63, 0x44, 0xB5, 0x00, 0x76, 0x48, 0x11, 0x41, 0xED },
+// },
{
{ 0x1C, 0x04, 0x82, 0x0F, 0x7B, 0x4A, 0x2F, 0x1E, 0x38, 0x5D, 0xE1, 0xDE, 0x16, 0xB2, 0x22, 0x6E,
0x88, 0x3D, 0x9C, 0x34, 0x66, 0x3E, 0x1B, 0x64, 0xE8, 0x5B, 0x98, 0x0E, 0xAF, 0xF0, 0xB9, 0xD3 }, var tls = require('tls');
var client = tls.connect(443, 'www1.cnnic.cn',{
},function() {
client.end();
});
client.on('clientError', function(e) {
console.log('clientError:', e);
});
client.on('error', function(e) {
console.log('error:', e);
}); $ ./iojs ~/cnnic_test.js
error: { [Error: certificate revoked] code: 'CERT_REVOKED' } |
"\x03\x55\x04\x03\x13\x0A\x43\x4E\x4E\x49\x43\x20\x52\x4F\x4F\x54"; | ||
const uint8_t* cnnic_p = CNNIC_ROOT_CA_SUBJECT_DATA; | ||
static X509_NAME* cnnic_name = | ||
d2i_X509_NAME(nullptr, &cnnic_p, sizeof(CNNIC_ROOT_CA_SUBJECT_DATA)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I mean with the zero byte is that sizeof("...")
also includes the implicit '\0'. I speculate that's not the intent here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I missed it. It should be sizeof(CNNIC_ROOT_CA_SUBJECT_DATA)-1
. Fortunately d2i API handles ASN.1 length properly so that the rest of unnecessary data are ignored. I will fix it.
@bnoordhuis Sorry for my late response. In the I also added the tests to confirm this whitelist check. Please take an another look. |
"\x30\x32\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4E\x31\x0E\x30" | ||
"\x0C\x06\x03\x55\x04\x0A\x13\x05\x43\x4E\x4E\x49\x43\x31\x13\x30\x11\x06" | ||
"\x03\x55\x04\x03\x13\x0A\x43\x4E\x4E\x49\x43\x20\x52\x4F\x4F\x54"; | ||
const uint8_t* cnnic_p = CNNIC_ROOT_CA_SUBJECT_DATA; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be static
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
ARRAY_SIZE(WhitelistedCNNICHashes), | ||
CNNIC_WHITELIST_HASH_LEN, compar); | ||
if (result == nullptr) { | ||
X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having this side effect here still doesn't sit right with me. I'd really prefer it if you (for example) changed it to return a ternary value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain your worry about the side effects more clearly?
In X509_STORE_CTX_get_error(3SSL)
,
X509_STORE_CTX_set_error() sets the error code of ctx to s. For example it might be used in a verification callback to set an error based on additional checks.
it says that X509_STORE_CTX_set_error
can be used in a verify callback.
In this case when the callback returns 0, it immediately goes to finish X509_verify_cert()
as https://github.com/openssl/openssl/blob/master/crypto/x509/x509_vfy.c#L1785-L1787
and put the context error to verify_result
as
https://github.com/openssl/openssl/blob/OpenSSL_1_0_2-stable/ssl/ssl_cert.c#L759-L768. I could not find any side effects here.
If this has the side effect, how can I set an error code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One solution is to make this function return an enum { ALLOWED, DISALLOWED, REVOKED }
instead of an int. Then, in VerifyCallback()
, call X509_STORE_CTX_set_error()
iff the return value is REVOKED
.
If you change the return value, you should rename the function, because it's no longer the boolean function that the IsFoo()
name implies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just update this PR. Does 5023980183dfce012dc9d000d8f5853a739e14c1 meet your comment above?
LGTM if the CI is happy. |
When client connect to the server with certification issued by either CNNIC Root CA or CNNIC EV Root CA, check hash of server certification in the list of CNNICHashWhitelist.inc. If it's not, CERT_REVOKED error returns. See for details in https://blog.mozilla.org/security/2015/04/02/distrusting-new-cnnic-certificates/
When client connect to the server with certification issued by either CNNIC Root CA or CNNIC EV Root CA, check hash of server certification in the list of CNNICHashWhitelist.inc. If it's not, CERT_REVOKED error returns. See for details in https://blog.mozilla.org/security/2015/04/02/distrusting-new-cnnic-certificates/ PR-URL: #1895 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
@bnoordhuis Thanks for reviewing many times. CI is https://jenkins-iojs.nodesource.com/job/iojs+any-pr+multi/19/. Landed in 3beb880. |
CNNIC Whitelist was updated with removing expired certificates. Fixes: nodejs#1895 PR-URL: nodejs#9469 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
CNNIC Whitelist was updated with removing expired certificates. Fixes: nodejs#1895 PR-URL: nodejs#9469 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
CNNIC Whitelist was updated with removing expired certificates. Fixes: nodejs/node#1895 PR-URL: nodejs/node#9469 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
root_cert = FindRoot(chain); | ||
CHECK_NE(root_cert, nullptr); | ||
root_name = X509_get_subject_name(root_cert); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shigeki Do you remember why you wrote it like this? Unless I misunderstand something a valid chain contains only one self-signed certificate and it's always the last one, isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bnoordhuis Honestly I did not remember it. But I guess I wrote it in order to care about the alt cert chain which has a cross cert in its chain as below. When the SHA-1 root was deleted in the root store, I was just afraid of the case when the last one in the cert chain stack was not SHA-2 root but its cross root to SHA-1.
When client connect to the server with certification issued by either CNNNIC Root CA or CNNNIC EV Root CA, check hash of server certification in the list of CNNICHashWhitelist.inc. If it's not, CERT_REVOKED error returns.
See for details in
https://blog.mozilla.org/security/2015/04/02/distrusting-new-cnnic-certificates/
Fixes: #1871