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/asn1/a_bitstr.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 <limits.h>
#include <string.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/span.h>
#include "../internal.h"
#include "internal.h"
int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, const unsigned char *d,
ossl_ssize_t len) {
return ASN1_STRING_set(x, d, len);
}
int asn1_bit_string_length(const ASN1_BIT_STRING *str,
uint8_t *out_padding_bits) {
int len = str->length;
if (str->flags & ASN1_STRING_FLAG_BITS_LEFT) {
// If the string is already empty, it cannot have padding bits.
*out_padding_bits = len == 0 ? 0 : str->flags & 0x07;
return len;
}
// TODO(https://crbug.com/boringssl/447): If we move this logic to
// |ASN1_BIT_STRING_set_bit|, can we remove this representation?
while (len > 0 && str->data[len - 1] == 0) {
len--;
}
uint8_t padding_bits = 0;
if (len > 0) {
uint8_t last = str->data[len - 1];
assert(last != 0);
for (; padding_bits < 7; padding_bits++) {
if (last & (1 << padding_bits)) {
break;
}
}
}
*out_padding_bits = padding_bits;
return len;
}
int ASN1_BIT_STRING_num_bytes(const ASN1_BIT_STRING *str, size_t *out) {
uint8_t padding_bits;
int len = asn1_bit_string_length(str, &padding_bits);
if (padding_bits != 0) {
return 0;
}
*out = len;
return 1;
}
int i2c_ASN1_BIT_STRING(const ASN1_BIT_STRING *a, unsigned char **pp) {
if (a == nullptr) {
return 0;
}
uint8_t bits;
int len = asn1_bit_string_length(a, &bits);
if (len > INT_MAX - 1) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW);
return 0;
}
int ret = 1 + len;
if (pp == nullptr) {
return ret;
}
uint8_t *p = *pp;
*(p++) = bits;
OPENSSL_memcpy(p, a->data, len);
if (len > 0) {
p[len - 1] &= (0xff << bits);
}
p += len;
*pp = p;
return ret;
}
int asn1_marshal_bit_string(CBB *out, const ASN1_BIT_STRING *in,
CBS_ASN1_TAG tag) {
int len = i2c_ASN1_BIT_STRING(in, nullptr);
if (len <= 0) {
return 0;
}
tag = tag == 0 ? CBS_ASN1_BITSTRING : tag;
CBB child;
uint8_t *ptr;
return CBB_add_asn1(out, &child, tag) && //
CBB_add_space(&child, &ptr, static_cast<size_t>(len)) && //
i2c_ASN1_BIT_STRING(in, &ptr) == len && //
CBB_flush(out);
}
static int asn1_parse_bit_string_contents(bssl::Span<const uint8_t> in,
ASN1_BIT_STRING *out) {
CBS cbs = in;
uint8_t padding;
if (!CBS_get_u8(&cbs, &padding)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
return 0;
}
if (padding > 7) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
return 0;
}
// Unused bits in a BIT STRING must be zero.
uint8_t padding_mask = (1 << padding) - 1;
if (padding != 0) {
CBS copy = cbs;
uint8_t last;
if (!CBS_get_last_u8(©, &last) || (last & padding_mask) != 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING);
return 0;
}
}
if (!ASN1_STRING_set(out, CBS_data(&cbs), CBS_len(&cbs))) {
return 0;
}
out->type = V_ASN1_BIT_STRING;
// |ASN1_STRING_FLAG_BITS_LEFT| and the bottom 3 bits encode |padding|.
out->flags &= ~0x07;
out->flags |= ASN1_STRING_FLAG_BITS_LEFT | padding;
return 1;
}
ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
const unsigned char **pp, long len) {
if (len < 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
return nullptr;
}
ASN1_BIT_STRING *ret = nullptr;
if (a == nullptr || *a == nullptr) {
if ((ret = ASN1_BIT_STRING_new()) == nullptr) {
return nullptr;
}
} else {
ret = *a;
}
if (!asn1_parse_bit_string_contents(bssl::Span(*pp, len), ret)) {
if (ret != nullptr && (a == nullptr || *a != ret)) {
ASN1_BIT_STRING_free(ret);
}
return nullptr;
}
if (a != nullptr) {
*a = ret;
}
*pp += len;
return ret;
}
int asn1_parse_bit_string(CBS *cbs, ASN1_BIT_STRING *out, CBS_ASN1_TAG tag) {
tag = tag == 0 ? CBS_ASN1_BITSTRING : tag;
CBS child;
if (!CBS_get_asn1(cbs, &child, tag)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
return 0;
}
return asn1_parse_bit_string_contents(child, out);
}
int asn1_parse_bit_string_with_bad_length(CBS *cbs, ASN1_BIT_STRING *out) {
CBS child;
CBS_ASN1_TAG tag;
size_t header_len;
int indefinite;
if (!CBS_get_any_ber_asn1_element(cbs, &child, &tag, &header_len,
/*out_ber_found=*/nullptr,
&indefinite) ||
tag != CBS_ASN1_BITSTRING || indefinite || //
!CBS_skip(&child, header_len)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
return 0;
}
return asn1_parse_bit_string_contents(child, out);
}
// These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) {
int w, v, iv;
unsigned char *c;
w = n / 8;
v = 1 << (7 - (n & 0x07));
iv = ~v;
if (!value) {
v = 0;
}
if (a == nullptr) {
return 0;
}
a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); // clear, set on write
if ((a->length < (w + 1)) || (a->data == nullptr)) {
if (!value) {
return 1; // Don't need to set
}
if (a->data == nullptr) {
c = (unsigned char *)OPENSSL_malloc(w + 1);
} else {
c = (unsigned char *)OPENSSL_realloc(a->data, w + 1);
}
if (c == nullptr) {
return 0;
}
if (w + 1 - a->length > 0) {
OPENSSL_memset(c + a->length, 0, w + 1 - a->length);
}
a->data = c;
a->length = w + 1;
}
a->data[w] = ((a->data[w]) & iv) | v;
while ((a->length > 0) && (a->data[a->length - 1] == 0)) {
a->length--;
}
return 1;
}
int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) {
int w, v;
w = n / 8;
v = 1 << (7 - (n & 0x07));
if ((a == nullptr) || (a->length < (w + 1)) || (a->data == nullptr)) {
return 0;
}
return ((a->data[w] & v) != 0);
}
// Checks if the given bit string contains only bits specified by
// the flags vector. Returns 0 if there is at least one bit set in 'a'
// which is not specified in 'flags', 1 otherwise.
// 'len' is the length of 'flags'.
int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, const unsigned char *flags,
int flags_len) {
int i, ok;
// Check if there is one bit set at all.
if (!a || !a->data) {
return 1;
}
// Check each byte of the internal representation of the bit string.
ok = 1;
for (i = 0; i < a->length && ok; ++i) {
unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
// We are done if there is an unneeded bit set.
ok = (a->data[i] & mask) == 0;
}
return ok;
}