Merge pull request #219 from dkg/pinning-non-ee-cert

Allow public key pins higher in the chain than the EE cert
This commit is contained in:
saradickinson 2016-11-12 18:59:24 +09:00 committed by GitHub
commit 4ebe5411ec
1 changed files with 22 additions and 9 deletions

View File

@ -382,10 +382,10 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
X509_STORE_CTX *store) X509_STORE_CTX *store)
{ {
getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR; getdns_return_t ret = GETDNS_RETURN_GENERIC_ERROR;
X509 *x; X509 *x, *prev;
int i, len; int i, len;
unsigned char raw[4096]; unsigned char raw[4096];
unsigned char *next = raw; unsigned char *next;
unsigned char buf[sizeof(pinset->pin)]; unsigned char buf[sizeof(pinset->pin)];
const sha256_pin_t *p; const sha256_pin_t *p;
@ -408,13 +408,6 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
/* TODO: how do we handle raw public keys? */ /* TODO: how do we handle raw public keys? */
for (i = 0; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store)); i++) { for (i = 0; i < sk_X509_num(X509_STORE_CTX_get0_untrusted(store)); i++) {
if (i > 0) {
/* TODO: how do we ensure that the certificates in
* each stage appropriately sign the previous one?
* for now, to be safe, we only examine the end-entity
* cert: */
return GETDNS_RETURN_GENERIC_ERROR;
}
x = sk_X509_value(X509_STORE_CTX_get0_untrusted(store), i); x = sk_X509_value(X509_STORE_CTX_get0_untrusted(store), i);
#if defined(STUB_DEBUG) && STUB_DEBUG #if defined(STUB_DEBUG) && STUB_DEBUG
@ -423,6 +416,24 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
X509_NAME_print_ex_fp(stderr, X509_get_subject_name(x), 1, XN_FLAG_ONELINE); X509_NAME_print_ex_fp(stderr, X509_get_subject_name(x), 1, XN_FLAG_ONELINE);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
#endif #endif
if (i > 0) {
/* we ensure that "prev" is signed by "x" */
EVP_PKEY *pkey = X509_get_pubkey(x);
int verified;
if (!pkey) {
DEBUG_STUB("%s %-35s: Could not get pubkey from cert %d (%p)\n",
STUB_DEBUG_SETUP_TLS, __FUNCTION__, i, x);
return GETDNS_RETURN_GENERIC_ERROR;
}
verified = X509_verify(prev, pkey);
EVP_PKEY_free(pkey);
if (!verified) {
DEBUG_STUB("%s %-35s: cert %d (%p) was not signed by cert %d\n",
STUB_DEBUG_SETUP_TLS, __FUNCTION__, i-1, prev, i);
return GETDNS_RETURN_GENERIC_ERROR;
}
}
/* digest the cert with sha256 */ /* digest the cert with sha256 */
len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL); len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), NULL);
if (len > sizeof(raw)) { if (len > sizeof(raw)) {
@ -430,6 +441,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
STUB_DEBUG_SETUP_TLS, __FUNCTION__, i, sizeof(raw)); STUB_DEBUG_SETUP_TLS, __FUNCTION__, i, sizeof(raw));
continue; continue;
} }
next = raw;
i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next); i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &next);
if (next - raw != len) { if (next - raw != len) {
DEBUG_STUB("%s %-35s: Pubkey %d claimed it needed %d octets, really needed "PRIsz"\n", DEBUG_STUB("%s %-35s: Pubkey %d claimed it needed %d octets, really needed "PRIsz"\n",
@ -447,6 +459,7 @@ _getdns_verify_pinset_match(const sha256_pin_t *pinset,
} else } else
DEBUG_STUB("%s %-35s: Pubkey %d did not match pin %p\n", DEBUG_STUB("%s %-35s: Pubkey %d did not match pin %p\n",
STUB_DEBUG_SETUP_TLS, __FUNCTION__, i, p); STUB_DEBUG_SETUP_TLS, __FUNCTION__, i, p);
prev = x;
} }
return ret; return ret;