Packages
hackney
2.0.0
4.7.2
4.7.1
4.7.0
4.6.1
4.6.0
4.5.2
4.5.1
4.5.0
4.4.5
4.4.3
4.4.2
4.4.1
4.4.0
4.3.0
4.2.3
4.2.2
4.2.1
4.2.0
4.1.0
4.0.3
4.0.2
4.0.1
4.0.0
3.2.1
3.2.0
3.1.2
3.1.1
3.1.0
3.0.3
3.0.2
3.0.1
3.0.0
retired
2.0.1
2.0.0
2.0.0-beta.1
1.25.0
1.24.1
1.24.0
1.23.0
1.22.0
1.21.0
1.20.1
1.20.0
1.19.1
1.19.0
1.18.2
1.18.1
1.18.0
1.17.4
1.17.3
1.17.2
1.17.1
1.17.0
1.16.0
1.15.2
1.15.1
1.15.0
1.14.3
1.14.2
1.14.0
1.13.0
1.12.1
1.12.0
1.11.0
1.10.1
1.10.0
1.9.0
1.8.6
1.8.5
1.8.4
1.8.3
1.8.2
1.8.0
1.7.1
1.7.0
1.6.6
retired
1.6.5
1.6.4
retired
1.6.3
1.6.2
1.6.1
1.6.0
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.10
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.0
1.0.6
1.0.5
1.0.2
1.0.1
0.15.2
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
Simple HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
c_src/boringssl/crypto/x509/x_crl.cc
// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/stack.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <assert.h>
#include "../asn1/internal.h"
#include "../internal.h"
#include "internal.h"
static int X509_REVOKED_cmp(const X509_REVOKED *const *a,
const X509_REVOKED *const *b);
static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
ASN1_SEQUENCE(X509_REVOKED) = {
ASN1_SIMPLE(X509_REVOKED, serialNumber, ASN1_INTEGER),
ASN1_SIMPLE(X509_REVOKED, revocationDate, ASN1_TIME),
ASN1_SEQUENCE_OF_OPT(X509_REVOKED, extensions, X509_EXTENSION),
} ASN1_SEQUENCE_END(X509_REVOKED)
static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret,
const ASN1_INTEGER *serial, X509_NAME *issuer);
// The X509_CRL_INFO structure needs a bit of customisation. Since we cache
// the original encoding the signature won't be affected by reordering of the
// revoked field.
static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg) {
X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
if (!a || !a->revoked) {
return 1;
}
switch (operation) {
// Just set cmp function here. We don't sort because that would
// affect the output of X509_CRL_print().
case ASN1_OP_D2I_POST:
(void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp);
break;
}
return 1;
}
ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = {
ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR),
ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME),
ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0),
} ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO)
static int crl_parse_entry_extensions(X509_CRL *crl) {
long version = ASN1_INTEGER_get(crl->crl->version);
STACK_OF(X509_REVOKED) *revoked = X509_CRL_get_REVOKED(crl);
for (size_t i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
// Per RFC 5280, section 5.1, CRL entry extensions require v2.
const STACK_OF(X509_EXTENSION) *exts = rev->extensions;
if (version == X509_CRL_VERSION_1 && exts != nullptr) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
return 0;
}
// Extensions is a SEQUENCE SIZE (1..MAX), so it cannot be empty. An empty
// extensions list is encoded by omitting the OPTIONAL field.
if (exts != nullptr && sk_X509_EXTENSION_num(exts) == 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
return 0;
}
int crit;
ASN1_ENUMERATED *reason = reinterpret_cast<ASN1_ENUMERATED *>(
X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &crit, nullptr));
if (!reason && crit != -1) {
crl->flags |= EXFLAG_INVALID;
return 1;
}
if (reason) {
rev->reason = ASN1_ENUMERATED_get(reason);
ASN1_ENUMERATED_free(reason);
} else {
rev->reason = CRL_REASON_NONE;
}
// We do not support any critical CRL entry extensions.
for (size_t j = 0; j < sk_X509_EXTENSION_num(exts); j++) {
const X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, j);
if (X509_EXTENSION_get_critical(ext)) {
crl->flags |= EXFLAG_CRITICAL;
break;
}
}
}
return 1;
}
// The X509_CRL structure needs a bit of customisation. Cache some extensions
// and hash of the whole CRL.
static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg) {
X509_CRL *crl = (X509_CRL *)*pval;
int i;
switch (operation) {
case ASN1_OP_NEW_POST:
crl->idp = nullptr;
crl->akid = nullptr;
crl->flags = 0;
crl->idp_flags = 0;
break;
case ASN1_OP_D2I_POST: {
// The version must be one of v1(0) or v2(1).
long version = X509_CRL_VERSION_1;
if (crl->crl->version != nullptr) {
version = ASN1_INTEGER_get(crl->crl->version);
// Versions v1 and v2. v1 is DEFAULT, so cannot be encoded explicitly.
if (version != X509_CRL_VERSION_2) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
return 0;
}
}
// Per RFC 5280, section 5.1.2.1, extensions require v2.
if (version != X509_CRL_VERSION_2 && crl->crl->extensions != nullptr) {
OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
return 0;
}
// Extensions is a SEQUENCE SIZE (1..MAX), so it cannot be empty. An empty
// extensions list is encoded by omitting the OPTIONAL field.
if (crl->crl->extensions != nullptr &&
sk_X509_EXTENSION_num(crl->crl->extensions) == 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
return 0;
}
if (!X509_CRL_digest(crl, EVP_sha256(), crl->crl_hash, nullptr)) {
return 0;
}
crl->idp = reinterpret_cast<ISSUING_DIST_POINT *>(X509_CRL_get_ext_d2i(
crl, NID_issuing_distribution_point, &i, nullptr));
if (crl->idp != nullptr) {
if (!setup_idp(crl, crl->idp)) {
return 0;
}
} else if (i != -1) {
return 0;
}
crl->akid = reinterpret_cast<AUTHORITY_KEYID *>(
X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, &i, nullptr));
if (crl->akid == nullptr && i != -1) {
return 0;
}
// See if we have any unhandled critical CRL extensions and indicate
// this in a flag. We only currently handle IDP so anything else
// critical sets the flag. This code accesses the X509_CRL structure
// directly: applications shouldn't do this.
const STACK_OF(X509_EXTENSION) *exts = crl->crl->extensions;
for (size_t idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) {
const X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, idx);
int nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext));
if (X509_EXTENSION_get_critical(ext)) {
if (nid == NID_issuing_distribution_point ||
nid == NID_authority_key_identifier) {
continue;
}
crl->flags |= EXFLAG_CRITICAL;
break;
}
}
if (!crl_parse_entry_extensions(crl)) {
return 0;
}
break;
}
case ASN1_OP_FREE_POST:
AUTHORITY_KEYID_free(crl->akid);
ISSUING_DIST_POINT_free(crl->idp);
break;
}
return 1;
}
// Convert IDP into a more convenient form
//
// TODO(davidben): Each of these flags are already booleans, so this is not
// really more convenient. We can probably remove |idp_flags|.
static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) {
int idp_only = 0;
// Set various flags according to IDP
crl->idp_flags |= IDP_PRESENT;
if (idp->onlyuser > 0) {
idp_only++;
crl->idp_flags |= IDP_ONLYUSER;
}
if (idp->onlyCA > 0) {
idp_only++;
crl->idp_flags |= IDP_ONLYCA;
}
if (idp->onlyattr > 0) {
idp_only++;
crl->idp_flags |= IDP_ONLYATTR;
}
// Per RFC 5280, section 5.2.5, at most one of onlyContainsUserCerts,
// onlyContainsCACerts, and onlyContainsAttributeCerts may be true.
//
// TODO(crbug.com/boringssl/443): Move this check to the |ISSUING_DIST_POINT|
// parser.
if (idp_only > 1) {
crl->idp_flags |= IDP_INVALID;
}
if (idp->indirectCRL > 0) {
crl->idp_flags |= IDP_INDIRECT;
}
if (idp->onlysomereasons) {
crl->idp_flags |= IDP_REASONS;
}
// TODO(davidben): The new verifier does not support nameRelativeToCRLIssuer.
// Remove this?
return DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
}
ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = {
ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING),
} ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL)
IMPLEMENT_ASN1_FUNCTIONS_const(X509_REVOKED)
IMPLEMENT_ASN1_DUP_FUNCTION_const(X509_REVOKED)
IMPLEMENT_ASN1_FUNCTIONS_const(X509_CRL_INFO)
IMPLEMENT_ASN1_FUNCTIONS_const(X509_CRL)
IMPLEMENT_ASN1_DUP_FUNCTION_const(X509_CRL)
static int X509_REVOKED_cmp(const X509_REVOKED *const *a,
const X509_REVOKED *const *b) {
return ASN1_STRING_cmp((*a)->serialNumber, (*b)->serialNumber);
}
int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) {
X509_CRL_INFO *inf;
inf = crl->crl;
if (!inf->revoked) {
inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
}
if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
return 0;
}
asn1_encoding_clear(&inf->enc);
return 1;
}
int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *pkey) {
if (X509_ALGOR_cmp(crl->sig_alg, crl->crl->sig_alg) != 0) {
OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH);
return 0;
}
return ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO), crl->sig_alg,
crl->signature, crl->crl, pkey);
}
int X509_CRL_get0_by_serial(X509_CRL *crl, X509_REVOKED **ret,
const ASN1_INTEGER *serial) {
return crl_lookup(crl, ret, serial, nullptr);
}
int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x) {
return crl_lookup(crl, ret, X509_get_serialNumber(x),
X509_get_issuer_name(x));
}
static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm,
X509_REVOKED *rev) {
return nm == nullptr || X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)) == 0;
}
static CRYPTO_MUTEX g_crl_sort_lock = CRYPTO_MUTEX_INIT;
static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret,
const ASN1_INTEGER *serial, X509_NAME *issuer) {
// Use an assert, rather than a runtime error, because returning nothing for a
// CRL is arguably failing open, rather than closed.
assert(serial->type == V_ASN1_INTEGER || serial->type == V_ASN1_NEG_INTEGER);
X509_REVOKED rtmp, *rev;
size_t idx;
rtmp.serialNumber = (ASN1_INTEGER *)serial;
// Sort revoked into serial number order if not already sorted. Do this
// under a lock to avoid race condition.
CRYPTO_MUTEX_lock_read(&g_crl_sort_lock);
const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked);
CRYPTO_MUTEX_unlock_read(&g_crl_sort_lock);
if (!is_sorted) {
CRYPTO_MUTEX_lock_write(&g_crl_sort_lock);
if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) {
sk_X509_REVOKED_sort(crl->crl->revoked);
}
CRYPTO_MUTEX_unlock_write(&g_crl_sort_lock);
}
if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp)) {
return 0;
}
// Need to look for matching name
for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) {
rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
if (ASN1_INTEGER_cmp(rev->serialNumber, serial)) {
return 0;
}
if (crl_revoked_issuer_match(crl, issuer, rev)) {
if (ret) {
*ret = rev;
}
return 1;
}
}
return 0;
}