Packages
hackney
3.0.2
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/x509_cmp.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 <string.h>
#include <openssl/asn1.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/md5.h>
#include <openssl/obj.h>
#include <openssl/sha.h>
#include <openssl/stack.h>
#include <openssl/x509.h>
#include "../internal.h"
#include "internal.h"
int X509_issuer_name_cmp(const X509 *a, const X509 *b) {
return X509_NAME_cmp(&a->issuer, &b->issuer);
}
int X509_subject_name_cmp(const X509 *a, const X509 *b) {
return X509_NAME_cmp(&a->subject, &b->subject);
}
int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) {
return X509_NAME_cmp(a->crl->issuer, b->crl->issuer);
}
int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) {
return OPENSSL_memcmp(a->crl_hash, b->crl_hash, SHA256_DIGEST_LENGTH);
}
X509_NAME *X509_get_issuer_name(const X509 *a) {
// This function is not const-correct for OpenSSL compatibility.
return const_cast<X509_NAME*>(&a->issuer);
}
uint32_t X509_issuer_name_hash(const X509 *x) {
return X509_NAME_hash(&x->issuer);
}
uint32_t X509_issuer_name_hash_old(const X509 *x) {
return X509_NAME_hash_old(&x->issuer);
}
X509_NAME *X509_get_subject_name(const X509 *a) {
// This function is not const-correct for OpenSSL compatibility.
return const_cast<X509_NAME*>(&a->subject);
}
ASN1_INTEGER *X509_get_serialNumber(X509 *a) { return &a->serialNumber; }
const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x509) {
return &x509->serialNumber;
}
uint32_t X509_subject_name_hash(const X509 *x) {
return X509_NAME_hash(&x->subject);
}
uint32_t X509_subject_name_hash_old(const X509 *x) {
return X509_NAME_hash_old(&x->subject);
}
// Compare two certificates: they must be identical for this to work. NB:
// Although "cmp" operations are generally prototyped to take "const"
// arguments (eg. for use in STACKs), the way X509 handling is - these
// operations may involve ensuring the hashes are up-to-date and ensuring
// certain cert information is cached. So this is the point where the
// "depth-first" constification tree has to halt with an evil cast.
int X509_cmp(const X509 *a, const X509 *b) {
// Fill in the |cert_hash| fields.
//
// TODO(davidben): This may fail, in which case the the hash will be all
// zeros. This produces a consistent comparison (failures are sticky), but
// not a good one. OpenSSL now returns -2, but this is not a consistent
// comparison and may cause misbehaving sorts by transitivity. For now, we
// retain the old OpenSSL behavior, which was to ignore the error. See
// https://crbug.com/boringssl/355.
x509v3_cache_extensions((X509 *)a);
x509v3_cache_extensions((X509 *)b);
return OPENSSL_memcmp(a->cert_hash, b->cert_hash, SHA256_DIGEST_LENGTH);
}
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) {
const X509_NAME_CACHE *a_cache = x509_name_get_cache(a);
if (a_cache == nullptr) {
return -2;
}
const X509_NAME_CACHE *b_cache = x509_name_get_cache(b);
if (b_cache == nullptr) {
return -2;
}
if (a_cache->canon_len < b_cache->canon_len) {
return -1;
}
if (a_cache->canon_len > b_cache->canon_len) {
return 1;
}
int ret = OPENSSL_memcmp(a_cache->canon, b_cache->canon, a_cache->canon_len);
// Canonicalize the return value so it is even possible to distinguish the
// error case from a < b, though ideally we would not have an error case.
if (ret < 0) {
return -1;
}
if (ret > 0) {
return 1;
}
return 0;
}
uint32_t X509_NAME_hash(const X509_NAME *x) {
const X509_NAME_CACHE *cache = x509_name_get_cache(x);
if (cache == nullptr) {
return 0;
}
uint8_t md[SHA_DIGEST_LENGTH];
SHA1(cache->canon, cache->canon_len, md);
return CRYPTO_load_u32_le(md);
}
// I now DER encode the name and hash it. Since I cache the DER encoding,
// this is reasonably efficient.
uint32_t X509_NAME_hash_old(const X509_NAME *x) {
const X509_NAME_CACHE *cache = x509_name_get_cache(x);
if (cache == nullptr) {
return 0;
}
uint8_t md[MD5_DIGEST_LENGTH];
MD5(cache->der, cache->der_len, md);
return CRYPTO_load_u32_le(md);
}
X509 *X509_find_by_issuer_and_serial(const STACK_OF(X509) *sk,
const X509_NAME *name,
const ASN1_INTEGER *serial) {
if (serial->type != V_ASN1_INTEGER && serial->type != V_ASN1_NEG_INTEGER) {
return nullptr;
}
for (size_t i = 0; i < sk_X509_num(sk); i++) {
X509 *x509 = sk_X509_value(sk, i);
if (ASN1_INTEGER_cmp(X509_get0_serialNumber(x509), serial) == 0 &&
X509_NAME_cmp(X509_get_issuer_name(x509), name) == 0) {
return x509;
}
}
return nullptr;
}
X509 *X509_find_by_subject(const STACK_OF(X509) *sk, const X509_NAME *name) {
for (size_t i = 0; i < sk_X509_num(sk); i++) {
X509 *x509 = sk_X509_value(sk, i);
if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0) {
return x509;
}
}
return nullptr;
}
EVP_PKEY *X509_get0_pubkey(const X509 *x) {
if (x == nullptr) {
return nullptr;
}
return X509_PUBKEY_get0(&x->key);
}
EVP_PKEY *X509_get_pubkey(const X509 *x) {
if (x == nullptr) {
return nullptr;
}
return X509_PUBKEY_get(&x->key);
}
ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) {
if (!x) {
return nullptr;
}
// This function is not const-correct for OpenSSL compatibility.
return const_cast<ASN1_BIT_STRING*>(&x->key.public_key);
}
int X509_check_private_key(const X509 *x, const EVP_PKEY *k) {
const EVP_PKEY *xk = X509_get0_pubkey(x);
if (xk == nullptr) {
return 0;
}
int ret = EVP_PKEY_cmp(xk, k);
if (ret > 0) {
return 1;
}
switch (ret) {
case 0:
OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH);
return 0;
case -1:
OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH);
return 0;
case -2:
OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
return 0;
}
return 0;
}
// Not strictly speaking an "up_ref" as a STACK doesn't have a reference
// count but it has the same effect by duping the STACK and upping the ref of
// each X509 structure.
STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain) {
STACK_OF(X509) *ret = sk_X509_dup(chain);
if (ret == nullptr) {
return nullptr;
}
for (size_t i = 0; i < sk_X509_num(ret); i++) {
X509_up_ref(sk_X509_value(ret, i));
}
return ret;
}