Packages
hackney
2.0.1
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_pubkey.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/x509.h>
#include <limits.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/span.h>
#include "../asn1/internal.h"
#include "../bytestring/internal.h"
#include "../evp/internal.h"
#include "../internal.h"
#include "../mem_internal.h"
#include "internal.h"
void x509_pubkey_init(X509_PUBKEY *key) {
OPENSSL_memset(key, 0, sizeof(X509_PUBKEY));
x509_algor_init(&key->algor);
asn1_string_init(&key->public_key, V_ASN1_BIT_STRING);
}
X509_PUBKEY *X509_PUBKEY_new(void) {
bssl::UniquePtr<X509_PUBKEY> ret = bssl::MakeUnique<X509_PUBKEY>();
if (ret == nullptr) {
return nullptr;
}
x509_pubkey_init(ret.get());
return ret.release();
}
void x509_pubkey_cleanup(X509_PUBKEY *key) {
x509_algor_cleanup(&key->algor);
asn1_string_cleanup(&key->public_key);
EVP_PKEY_free(key->pkey);
}
void X509_PUBKEY_free(X509_PUBKEY *key) {
if (key != nullptr) {
x509_pubkey_cleanup(key);
OPENSSL_free(key);
}
}
static void x509_pubkey_changed(X509_PUBKEY *pub,
bssl::Span<const EVP_PKEY_ALG *const> algs) {
EVP_PKEY_free(pub->pkey);
pub->pkey = nullptr;
// Re-encode the |X509_PUBKEY| to DER and parse it with EVP's APIs. If the
// operation fails, clear errors. An |X509_PUBKEY| whose key we cannot parse
// is still a valid SPKI. It just cannot be converted to an |EVP_PKEY|.
bssl::ScopedCBB cbb;
if (!CBB_init(cbb.get(), 64) || !x509_marshal_public_key(cbb.get(), pub)) {
ERR_clear_error();
return;
}
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_from_subject_public_key_info(
CBB_data(cbb.get()), CBB_len(cbb.get()), algs.data(), algs.size()));
if (pkey == nullptr) {
ERR_clear_error();
return;
}
pub->pkey = pkey.release();
}
int x509_parse_public_key(CBS *cbs, X509_PUBKEY *out,
bssl::Span<const EVP_PKEY_ALG *const> algs) {
CBS seq;
if (!CBS_get_asn1(cbs, &seq, CBS_ASN1_SEQUENCE) ||
!x509_parse_algorithm(&seq, &out->algor) ||
!asn1_parse_bit_string(&seq, &out->public_key, /*tag=*/0) ||
CBS_len(&seq) != 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
return 0;
}
x509_pubkey_changed(out, algs);
return 1;
}
static int x509_parse_public_key_default(CBS *cbs, X509_PUBKEY *out) {
return x509_parse_public_key(cbs, out, bssl::GetDefaultEVPAlgorithms());
}
int x509_marshal_public_key(CBB *cbb, const X509_PUBKEY *in) {
CBB seq;
return CBB_add_asn1(cbb, &seq, CBS_ASN1_SEQUENCE) &&
x509_marshal_algorithm(&seq, &in->algor) &&
asn1_marshal_bit_string(&seq, &in->public_key, /*tag=*/0) &&
CBB_flush(cbb);
}
X509_PUBKEY *d2i_X509_PUBKEY(X509_PUBKEY **out, const uint8_t **inp, long len) {
return bssl::D2IFromCBS(
out, inp, len, [](CBS *cbs) -> bssl::UniquePtr<X509_PUBKEY> {
bssl::UniquePtr<X509_PUBKEY> ret(X509_PUBKEY_new());
if (ret == nullptr || !x509_parse_public_key_default(cbs, ret.get())) {
return nullptr;
}
return ret;
});
}
int i2d_X509_PUBKEY(const X509_PUBKEY *key, uint8_t **outp) {
return bssl::I2DFromCBB(/*initial_capacity=*/32, outp, [&](CBB *cbb) -> bool {
return x509_marshal_public_key(cbb, key);
});
}
// TODO(crbug.com/42290417): Remove this when |X509| and |X509_REQ| no longer
// depend on the tables.
IMPLEMENT_EXTERN_ASN1_SIMPLE(X509_PUBKEY, X509_PUBKEY_new, X509_PUBKEY_free,
CBS_ASN1_SEQUENCE, x509_parse_public_key_default,
i2d_X509_PUBKEY)
int x509_pubkey_set1(X509_PUBKEY *key, EVP_PKEY *pkey) {
bssl::ScopedCBB cbb;
if (!CBB_init(cbb.get(), 64) ||
!EVP_marshal_public_key(cbb.get(), pkey)) {
OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR);
return 0;
}
CBS cbs;
CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get()));
// TODO(crbug.com/42290364): Use an |EVP_PKEY_ALG| derived from |pkey|.
// |X509_PUBKEY_get0| does not currently work when setting, say, an
// |EVP_PKEY_RSA_PSS| key.
return x509_parse_public_key(&cbs, key, bssl::GetDefaultEVPAlgorithms());
}
int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) {
bssl::UniquePtr<X509_PUBKEY> new_key(X509_PUBKEY_new());
if (new_key == nullptr || !x509_pubkey_set1(new_key.get(), pkey)) {
return 0;
}
X509_PUBKEY_free(*x);
*x = new_key.release();
return 1;
}
EVP_PKEY *X509_PUBKEY_get0(const X509_PUBKEY *key) {
if (key == nullptr) {
return nullptr;
}
if (key->pkey == nullptr) {
OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR);
return nullptr;
}
return key->pkey;
}
EVP_PKEY *X509_PUBKEY_get(const X509_PUBKEY *key) {
EVP_PKEY *pkey = X509_PUBKEY_get0(key);
if (pkey != nullptr) {
EVP_PKEY_up_ref(pkey);
}
return pkey;
}
int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *obj, int param_type,
void *param_value, uint8_t *key, int key_len) {
if (!X509_ALGOR_set0(&pub->algor, obj, param_type, param_value)) {
return 0;
}
ASN1_STRING_set0(&pub->public_key, key, key_len);
// Set the number of unused bits to zero.
pub->public_key.flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
pub->public_key.flags |= ASN1_STRING_FLAG_BITS_LEFT;
x509_pubkey_changed(pub, bssl::GetDefaultEVPAlgorithms());
return 1;
}
int X509_PUBKEY_get0_param(ASN1_OBJECT **out_obj, const uint8_t **out_key,
int *out_key_len, X509_ALGOR **out_alg,
X509_PUBKEY *pub) {
if (out_obj != nullptr) {
*out_obj = pub->algor.algorithm;
}
if (out_key != nullptr) {
*out_key = pub->public_key.data;
*out_key_len = pub->public_key.length;
}
if (out_alg != nullptr) {
*out_alg = &pub->algor;
}
return 1;
}
const ASN1_BIT_STRING *X509_PUBKEY_get0_public_key(const X509_PUBKEY *pub) {
return &pub->public_key;
}