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/asn1/asn1_lib.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 "../internal.h"
#include "internal.h"
// Cross-module errors from crypto/x509/i2d_pr.c.
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE)
// Cross-module errors from crypto/x509/algorithm.c.
OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED)
OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM)
OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE)
// Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove
// these once asn1_gen.c is gone.
OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE)
OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER)
OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER)
OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR)
OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE)
OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG)
OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG)
OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE)
// Limit |ASN1_STRING|s to 64 MiB of data. Most of this module, as well as
// downstream code, does not correctly handle overflow. We cap string fields
// more tightly than strictly necessary to fit in |int|. This is not expected to
// impact real world uses of this field.
//
// In particular, this limit is small enough that the bit count of a BIT STRING
// comfortably fits in an |int|, with room for arithmetic.
#define ASN1_STRING_MAX (64 * 1024 * 1024)
static void asn1_put_length(unsigned char **pp, int length);
int ASN1_get_object(const unsigned char **inp, long *out_len, int *out_tag,
int *out_class, long in_len) {
if (in_len < 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
return 0x80;
}
CBS_ASN1_TAG tag;
CBS cbs, body;
CBS_init(&cbs, *inp, (size_t)in_len);
if (!CBS_get_any_asn1(&cbs, &body, &tag) ||
// Bound the length to comfortably fit in an int. Lengths in this
// module often switch between int and long without overflow checks.
CBS_len(&body) > INT_MAX / 2) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
return 0x80;
}
// Convert between tag representations.
int tag_class = (tag & CBS_ASN1_CLASS_MASK) >> CBS_ASN1_TAG_SHIFT;
int constructed = (tag & CBS_ASN1_CONSTRUCTED) >> CBS_ASN1_TAG_SHIFT;
int tag_number = tag & CBS_ASN1_TAG_NUMBER_MASK;
// To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags.
if (tag_class == V_ASN1_UNIVERSAL && tag_number > V_ASN1_MAX_UNIVERSAL) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
return 0x80;
}
*inp = CBS_data(&body);
*out_len = CBS_len(&body);
*out_tag = tag_number;
*out_class = tag_class;
return constructed;
}
// class 0 is constructed constructed == 2 for indefinite length constructed
void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
int xclass) {
unsigned char *p = *pp;
int i, ttag;
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
i |= (xclass & V_ASN1_PRIVATE);
if (tag < 31) {
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
} else {
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
for (i = 0, ttag = tag; ttag > 0; i++) {
ttag >>= 7;
}
ttag = i;
while (i-- > 0) {
p[i] = tag & 0x7f;
if (i != (ttag - 1)) {
p[i] |= 0x80;
}
tag >>= 7;
}
p += ttag;
}
if (constructed == 2) {
*(p++) = 0x80;
} else {
asn1_put_length(&p, length);
}
*pp = p;
}
int ASN1_put_eoc(unsigned char **pp) {
// This function is no longer used in the library, but some external code
// uses it.
unsigned char *p = *pp;
*p++ = 0;
*p++ = 0;
*pp = p;
return 2;
}
static void asn1_put_length(unsigned char **pp, int length) {
unsigned char *p = *pp;
int i, l;
if (length <= 127) {
*(p++) = (unsigned char)length;
} else {
l = length;
for (i = 0; l > 0; i++) {
l >>= 8;
}
*(p++) = i | 0x80;
l = i;
while (i-- > 0) {
p[i] = length & 0xff;
length >>= 8;
}
p += l;
}
*pp = p;
}
int ASN1_object_size(int constructed, int length, int tag) {
int ret = 1;
if (length < 0) {
return -1;
}
if (tag >= 31) {
while (tag > 0) {
tag >>= 7;
ret++;
}
}
if (constructed == 2) {
ret += 3;
} else {
ret++;
if (length > 127) {
int tmplen = length;
while (tmplen > 0) {
tmplen >>= 8;
ret++;
}
}
}
if (ret >= INT_MAX - length) {
return -1;
}
return ret + length;
}
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) {
if (str == nullptr) {
return 0;
}
if (dst == str) {
return 1;
}
if (!ASN1_STRING_set(dst, str->data, str->length)) {
return 0;
}
dst->type = str->type;
dst->flags = str->flags;
return 1;
}
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) {
ASN1_STRING *ret;
if (!str) {
return nullptr;
}
ret = ASN1_STRING_new();
if (!ret) {
return nullptr;
}
if (!ASN1_STRING_copy(ret, str)) {
ASN1_STRING_free(ret);
return nullptr;
}
return ret;
}
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, ossl_ssize_t len_s) {
const char *data = reinterpret_cast<const char *>(_data);
size_t len;
if (len_s < 0) {
if (data == nullptr) {
return 0;
}
len = strlen(data);
} else {
len = (size_t)len_s;
}
static_assert(ASN1_STRING_MAX < INT_MAX, "len will not overflow int");
if (len > ASN1_STRING_MAX) {
OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW);
return 0;
}
if (str->length <= (int)len || str->data == nullptr) {
unsigned char *c = str->data;
if (c == nullptr) {
str->data = reinterpret_cast<uint8_t *>(OPENSSL_malloc(len + 1));
} else {
str->data = reinterpret_cast<uint8_t *>(OPENSSL_realloc(c, len + 1));
}
if (str->data == nullptr) {
str->data = c;
return 0;
}
}
str->length = (int)len;
if (data != nullptr) {
OPENSSL_memcpy(str->data, data, len);
// Historically, OpenSSL would NUL-terminate most (but not all)
// |ASN1_STRING|s, in case anyone accidentally passed |str->data| into a
// function expecting a C string. We retain this behavior for compatibility,
// but code must not rely on this. See CVE-2021-3712.
str->data[len] = '\0';
}
return 1;
}
void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) {
OPENSSL_free(str->data);
str->data = reinterpret_cast<uint8_t *>(data);
str->length = len;
}
ASN1_STRING *ASN1_STRING_new(void) {
return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
}
ASN1_STRING *ASN1_STRING_type_new(int type) {
ASN1_STRING *ret;
ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
if (ret == nullptr) {
return nullptr;
}
ret->length = 0;
ret->type = type;
ret->data = nullptr;
ret->flags = 0;
return ret;
}
void asn1_string_init(ASN1_STRING *str, int type) {
OPENSSL_memset(str, 0, sizeof(ASN1_STRING));
str->type = type;
}
void asn1_string_cleanup(ASN1_STRING *str) {
OPENSSL_free(str->data);
str->data = nullptr;
}
void ASN1_STRING_free(ASN1_STRING *str) {
if (str == nullptr) {
return;
}
asn1_string_cleanup(str);
OPENSSL_free(str);
}
int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) {
// Capture padding bits and implicit truncation in BIT STRINGs.
int a_length = a->length, b_length = b->length;
uint8_t a_padding = 0, b_padding = 0;
if (a->type == V_ASN1_BIT_STRING) {
a_length = asn1_bit_string_length(a, &a_padding);
}
if (b->type == V_ASN1_BIT_STRING) {
b_length = asn1_bit_string_length(b, &b_padding);
}
if (a_length < b_length) {
return -1;
}
if (a_length > b_length) {
return 1;
}
// In a BIT STRING, the number of bits is 8 * length - padding. Invert this
// comparison so we compare by lengths.
if (a_padding > b_padding) {
return -1;
}
if (a_padding < b_padding) {
return 1;
}
int ret = OPENSSL_memcmp(a->data, b->data, a_length);
if (ret != 0) {
return ret;
}
// Comparing the type first is more natural, but this matches OpenSSL.
if (a->type < b->type) {
return -1;
}
if (a->type > b->type) {
return 1;
}
return 0;
}
int ASN1_STRING_length(const ASN1_STRING *str) { return str->length; }
int ASN1_STRING_type(const ASN1_STRING *str) { return str->type; }
unsigned char *ASN1_STRING_data(ASN1_STRING *str) { return str->data; }
const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *str) {
return str->data;
}
int asn1_parse_octet_string(CBS *cbs, ASN1_STRING *out, CBS_ASN1_TAG tag) {
tag = tag == 0 ? CBS_ASN1_OCTETSTRING : tag;
CBS child;
if (!CBS_get_asn1(cbs, &child, tag)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
return 0;
}
if (!ASN1_STRING_set(out, CBS_data(&child), CBS_len(&child))) {
return 0;
}
out->type = V_ASN1_OCTET_STRING;
return 1;
}
int asn1_marshal_octet_string(CBB *out, const ASN1_STRING *in,
CBS_ASN1_TAG tag) {
tag = tag == 0 ? CBS_ASN1_OCTETSTRING : tag;
return CBB_add_asn1_element(out, tag, ASN1_STRING_get0_data(in),
ASN1_STRING_length(in));
}
static int asn1_parse_character_string(CBS *cbs, ASN1_STRING *out,
CBS_ASN1_TAG tag, int str_type,
int (*get_char)(CBS *cbs, uint32_t *),
int bad_char_err) {
CBS child;
if (!CBS_get_asn1(cbs, &child, tag)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
return 0;
}
CBS copy = child;
while (CBS_len(©) != 0) {
uint32_t c;
if (!get_char(©, &c)) {
OPENSSL_PUT_ERROR(ASN1, bad_char_err);
return 0;
}
}
if (!ASN1_STRING_set(out, CBS_data(&child), CBS_len(&child))) {
return 0;
}
out->type = str_type;
return 1;
}
int asn1_parse_bmp_string(CBS *cbs, ASN1_BMPSTRING *out, CBS_ASN1_TAG tag) {
tag = tag == 0 ? CBS_ASN1_BMPSTRING : tag;
return asn1_parse_character_string(cbs, out, tag, V_ASN1_BMPSTRING,
&CBS_get_ucs2_be,
ASN1_R_INVALID_BMPSTRING);
}
int asn1_parse_universal_string(CBS *cbs, ASN1_UNIVERSALSTRING *out,
CBS_ASN1_TAG tag) {
tag = tag == 0 ? CBS_ASN1_UNIVERSALSTRING : tag;
return asn1_parse_character_string(cbs, out, tag, V_ASN1_UNIVERSALSTRING,
&CBS_get_utf32_be,
ASN1_R_INVALID_UNIVERSALSTRING);
}
int asn1_parse_utf8_string(CBS *cbs, ASN1_UNIVERSALSTRING *out,
CBS_ASN1_TAG tag) {
tag = tag == 0 ? CBS_ASN1_UTF8STRING : tag;
return asn1_parse_character_string(cbs, out, tag, V_ASN1_UTF8STRING,
&CBS_get_utf8, ASN1_R_INVALID_UTF8STRING);
}