You've already forked linux-packaging-mono
Imported Upstream version 4.8.0.309
Former-commit-id: 5f9c6ae75f295e057a7d2971f3a6df4656fa8850
This commit is contained in:
parent
ee1447783b
commit
94b2861243
25
external/boringssl/crypto/bytestring/CMakeLists.txt
vendored
Normal file
25
external/boringssl/crypto/bytestring/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
include_directories(../../include)
|
||||
|
||||
add_library(
|
||||
bytestring
|
||||
|
||||
OBJECT
|
||||
|
||||
asn1_compat.c
|
||||
ber.c
|
||||
cbs.c
|
||||
cbb.c
|
||||
)
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
add_executable(
|
||||
bytestring_test
|
||||
|
||||
bytestring_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(bytestring_test crypto)
|
||||
add_dependencies(all_tests bytestring_test)
|
||||
endif()
|
51
external/boringssl/crypto/bytestring/asn1_compat.c
vendored
Normal file
51
external/boringssl/crypto/bytestring/asn1_compat.c
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/* Copyright (c) 2016, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
int CBB_finish_i2d(CBB *cbb, uint8_t **outp) {
|
||||
assert(cbb->base->can_resize);
|
||||
|
||||
uint8_t *der;
|
||||
size_t der_len;
|
||||
if (!CBB_finish(cbb, &der, &der_len)) {
|
||||
CBB_cleanup(cbb);
|
||||
return -1;
|
||||
}
|
||||
if (der_len > INT_MAX) {
|
||||
OPENSSL_free(der);
|
||||
return -1;
|
||||
}
|
||||
if (outp != NULL) {
|
||||
if (*outp == NULL) {
|
||||
*outp = der;
|
||||
der = NULL;
|
||||
} else {
|
||||
memcpy(*outp, der, der_len);
|
||||
*outp += der_len;
|
||||
}
|
||||
}
|
||||
OPENSSL_free(der);
|
||||
return (int)der_len;
|
||||
}
|
263
external/boringssl/crypto/bytestring/ber.c
vendored
Normal file
263
external/boringssl/crypto/bytestring/ber.c
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
/* kMaxDepth is a just a sanity limit. The code should be such that the length
|
||||
* of the input being processes always decreases. None the less, a very large
|
||||
* input could otherwise cause the stack to overflow. */
|
||||
static const unsigned kMaxDepth = 2048;
|
||||
|
||||
/* is_string_type returns one if |tag| is a string type and zero otherwise. It
|
||||
* ignores the constructed bit. */
|
||||
static int is_string_type(unsigned tag) {
|
||||
if ((tag & 0xc0) != 0) {
|
||||
return 0;
|
||||
}
|
||||
switch (tag & 0x1f) {
|
||||
case CBS_ASN1_BITSTRING:
|
||||
case CBS_ASN1_OCTETSTRING:
|
||||
case CBS_ASN1_UTF8STRING:
|
||||
case CBS_ASN1_NUMERICSTRING:
|
||||
case CBS_ASN1_PRINTABLESTRING:
|
||||
case CBS_ASN1_T16STRING:
|
||||
case CBS_ASN1_VIDEOTEXSTRING:
|
||||
case CBS_ASN1_IA5STRING:
|
||||
case CBS_ASN1_GRAPHICSTRING:
|
||||
case CBS_ASN1_VISIBLESTRING:
|
||||
case CBS_ASN1_GENERALSTRING:
|
||||
case CBS_ASN1_UNIVERSALSTRING:
|
||||
case CBS_ASN1_BMPSTRING:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
|
||||
* depending on whether an indefinite length element or constructed string was
|
||||
* found. The value of |orig_in| is not changed. It returns one on success (i.e.
|
||||
* |*ber_found| was set) and zero on error. */
|
||||
static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
CBS in;
|
||||
|
||||
if (depth > kMaxDepth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
|
||||
*ber_found = 0;
|
||||
|
||||
while (CBS_len(&in) > 0) {
|
||||
CBS contents;
|
||||
unsigned tag;
|
||||
size_t header_len;
|
||||
|
||||
if (!CBS_get_any_ber_asn1_element(&in, &contents, &tag, &header_len)) {
|
||||
return 0;
|
||||
}
|
||||
if (CBS_len(&contents) == header_len &&
|
||||
header_len > 0 &&
|
||||
CBS_data(&contents)[header_len-1] == 0x80) {
|
||||
/* Found an indefinite-length element. */
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
if (is_string_type(tag)) {
|
||||
/* Constructed strings are only legal in BER and require conversion. */
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
if (!CBS_skip(&contents, header_len) ||
|
||||
!cbs_find_ber(&contents, ber_found, depth + 1)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* is_eoc returns true if |header_len| and |contents|, as returned by
|
||||
* |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value. */
|
||||
static char is_eoc(size_t header_len, CBS *contents) {
|
||||
return header_len == 2 && CBS_len(contents) == 2 &&
|
||||
memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
|
||||
}
|
||||
|
||||
/* cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
|
||||
* |string_tag| is non-zero, then all elements must match |string_tag| up to the
|
||||
* constructed bit and primitive element bodies are written to |out| without
|
||||
* element headers. This is used when concatenating the fragments of a
|
||||
* constructed string. If |looking_for_eoc| is set then any EOC elements found
|
||||
* will cause the function to return after consuming it. It returns one on
|
||||
* success and zero on error. */
|
||||
static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
|
||||
char looking_for_eoc, unsigned depth) {
|
||||
assert(!(string_tag & CBS_ASN1_CONSTRUCTED));
|
||||
|
||||
if (depth > kMaxDepth) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (CBS_len(in) > 0) {
|
||||
CBS contents;
|
||||
unsigned tag, child_string_tag = string_tag;
|
||||
size_t header_len;
|
||||
CBB *out_contents, out_contents_storage;
|
||||
|
||||
if (!CBS_get_any_ber_asn1_element(in, &contents, &tag, &header_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_eoc(header_len, &contents)) {
|
||||
return looking_for_eoc;
|
||||
}
|
||||
|
||||
if (string_tag != 0) {
|
||||
/* This is part of a constructed string. All elements must match
|
||||
* |string_tag| up to the constructed bit and get appended to |out|
|
||||
* without a child element. */
|
||||
if ((tag & ~CBS_ASN1_CONSTRUCTED) != string_tag) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = out;
|
||||
} else {
|
||||
unsigned out_tag = tag;
|
||||
if ((tag & CBS_ASN1_CONSTRUCTED) && is_string_type(tag)) {
|
||||
/* If a constructed string, clear the constructed bit and inform
|
||||
* children to concatenate bodies. */
|
||||
out_tag &= ~CBS_ASN1_CONSTRUCTED;
|
||||
child_string_tag = out_tag;
|
||||
}
|
||||
if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
|
||||
return 0;
|
||||
}
|
||||
out_contents = &out_contents_storage;
|
||||
}
|
||||
|
||||
if (CBS_len(&contents) == header_len && header_len > 0 &&
|
||||
CBS_data(&contents)[header_len - 1] == 0x80) {
|
||||
/* This is an indefinite length element. */
|
||||
if (!cbs_convert_ber(in, out_contents, child_string_tag,
|
||||
1 /* looking for eoc */, depth + 1) ||
|
||||
!CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CBS_skip(&contents, header_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
/* Recurse into children. */
|
||||
if (!cbs_convert_ber(&contents, out_contents, child_string_tag,
|
||||
0 /* not looking for eoc */, depth + 1)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* Copy primitive contents as-is. */
|
||||
if (!CBB_add_bytes(out_contents, CBS_data(&contents),
|
||||
CBS_len(&contents))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CBB_flush(out)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return looking_for_eoc == 0;
|
||||
}
|
||||
|
||||
int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) {
|
||||
CBB cbb;
|
||||
|
||||
/* First, do a quick walk to find any indefinite-length elements. Most of the
|
||||
* time we hope that there aren't any and thus we can quickly return. */
|
||||
char conversion_needed;
|
||||
if (!cbs_find_ber(in, &conversion_needed, 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!conversion_needed) {
|
||||
*out = NULL;
|
||||
*out_len = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!CBB_init(&cbb, CBS_len(in)) ||
|
||||
!cbs_convert_ber(in, &cbb, 0, 0, 0) ||
|
||||
!CBB_finish(&cbb, out, out_len)) {
|
||||
CBB_cleanup(&cbb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage,
|
||||
unsigned outer_tag, unsigned inner_tag) {
|
||||
assert(!(outer_tag & CBS_ASN1_CONSTRUCTED));
|
||||
assert(!(inner_tag & CBS_ASN1_CONSTRUCTED));
|
||||
assert(is_string_type(inner_tag));
|
||||
|
||||
if (CBS_peek_asn1_tag(in, outer_tag)) {
|
||||
/* Normal implicitly-tagged string. */
|
||||
*out_storage = NULL;
|
||||
return CBS_get_asn1(in, out, outer_tag);
|
||||
}
|
||||
|
||||
/* Otherwise, try to parse an implicitly-tagged constructed string.
|
||||
* |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep
|
||||
* of nesting. */
|
||||
CBB result;
|
||||
CBS child;
|
||||
if (!CBB_init(&result, CBS_len(in)) ||
|
||||
!CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (CBS_len(&child) > 0) {
|
||||
CBS chunk;
|
||||
if (!CBS_get_asn1(&child, &chunk, inner_tag) ||
|
||||
!CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
if (!CBB_finish(&result, &data, &len)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
CBS_init(out, data, len);
|
||||
*out_storage = data;
|
||||
return 1;
|
||||
|
||||
err:
|
||||
CBB_cleanup(&result);
|
||||
return 0;
|
||||
}
|
825
external/boringssl/crypto/bytestring/bytestring_test.cc
vendored
Normal file
825
external/boringssl/crypto/bytestring/bytestring_test.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
445
external/boringssl/crypto/bytestring/cbb.c
vendored
Normal file
445
external/boringssl/crypto/bytestring/cbb.c
vendored
Normal file
@@ -0,0 +1,445 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/mem.h>
|
||||
|
||||
|
||||
void CBB_zero(CBB *cbb) {
|
||||
memset(cbb, 0, sizeof(CBB));
|
||||
}
|
||||
|
||||
static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
|
||||
/* This assumes that |cbb| has already been zeroed. */
|
||||
struct cbb_buffer_st *base;
|
||||
|
||||
base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
|
||||
if (base == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
base->buf = buf;
|
||||
base->len = 0;
|
||||
base->cap = cap;
|
||||
base->can_resize = 1;
|
||||
|
||||
cbb->base = base;
|
||||
cbb->is_top_level = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_init(CBB *cbb, size_t initial_capacity) {
|
||||
CBB_zero(cbb);
|
||||
|
||||
uint8_t *buf = OPENSSL_malloc(initial_capacity);
|
||||
if (initial_capacity > 0 && buf == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cbb_init(cbb, buf, initial_capacity)) {
|
||||
OPENSSL_free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
|
||||
CBB_zero(cbb);
|
||||
|
||||
if (!cbb_init(cbb, buf, len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cbb->base->can_resize = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CBB_cleanup(CBB *cbb) {
|
||||
if (cbb->base) {
|
||||
/* Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They
|
||||
* are implicitly discarded when the parent is flushed or cleaned up. */
|
||||
assert(cbb->is_top_level);
|
||||
|
||||
if (cbb->base->can_resize) {
|
||||
OPENSSL_free(cbb->base->buf);
|
||||
}
|
||||
OPENSSL_free(cbb->base);
|
||||
}
|
||||
cbb->base = NULL;
|
||||
}
|
||||
|
||||
static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
|
||||
size_t len) {
|
||||
size_t newlen;
|
||||
|
||||
if (base == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
newlen = base->len + len;
|
||||
if (newlen < base->len) {
|
||||
/* Overflow */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (newlen > base->cap) {
|
||||
size_t newcap = base->cap * 2;
|
||||
uint8_t *newbuf;
|
||||
|
||||
if (!base->can_resize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (newcap < base->cap || newcap < newlen) {
|
||||
newcap = newlen;
|
||||
}
|
||||
newbuf = OPENSSL_realloc(base->buf, newcap);
|
||||
if (newbuf == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
base->buf = newbuf;
|
||||
base->cap = newcap;
|
||||
}
|
||||
|
||||
if (out) {
|
||||
*out = base->buf + base->len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
|
||||
size_t len) {
|
||||
if (!cbb_buffer_reserve(base, out, len)) {
|
||||
return 0;
|
||||
}
|
||||
/* This will not overflow or |cbb_buffer_reserve| would have failed. */
|
||||
base->len += len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
|
||||
size_t len_len) {
|
||||
uint8_t *buf;
|
||||
size_t i;
|
||||
|
||||
if (len_len == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (!cbb_buffer_add(base, &buf, len_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = len_len - 1; i < len_len; i--) {
|
||||
buf[i] = v;
|
||||
v >>= 8;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
|
||||
if (!cbb->is_top_level) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) {
|
||||
/* |out_data| and |out_len| can only be NULL if the CBB is fixed. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (out_data != NULL) {
|
||||
*out_data = cbb->base->buf;
|
||||
}
|
||||
if (out_len != NULL) {
|
||||
*out_len = cbb->base->len;
|
||||
}
|
||||
cbb->base->buf = NULL;
|
||||
CBB_cleanup(cbb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* CBB_flush recurses and then writes out any pending length prefix. The
|
||||
* current length of the underlying base is taken to be the length of the
|
||||
* length-prefixed data. */
|
||||
int CBB_flush(CBB *cbb) {
|
||||
size_t child_start, i, len;
|
||||
|
||||
if (cbb->base == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cbb->child == NULL || cbb->child->pending_len_len == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
child_start = cbb->child->offset + cbb->child->pending_len_len;
|
||||
|
||||
if (!CBB_flush(cbb->child) ||
|
||||
child_start < cbb->child->offset ||
|
||||
cbb->base->len < child_start) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = cbb->base->len - child_start;
|
||||
|
||||
if (cbb->child->pending_is_asn1) {
|
||||
/* For ASN.1 we assume that we'll only need a single byte for the length.
|
||||
* If that turned out to be incorrect, we have to move the contents along
|
||||
* in order to make space. */
|
||||
size_t len_len;
|
||||
uint8_t initial_length_byte;
|
||||
|
||||
assert (cbb->child->pending_len_len == 1);
|
||||
|
||||
if (len > 0xfffffffe) {
|
||||
/* Too large. */
|
||||
return 0;
|
||||
} else if (len > 0xffffff) {
|
||||
len_len = 5;
|
||||
initial_length_byte = 0x80 | 4;
|
||||
} else if (len > 0xffff) {
|
||||
len_len = 4;
|
||||
initial_length_byte = 0x80 | 3;
|
||||
} else if (len > 0xff) {
|
||||
len_len = 3;
|
||||
initial_length_byte = 0x80 | 2;
|
||||
} else if (len > 0x7f) {
|
||||
len_len = 2;
|
||||
initial_length_byte = 0x80 | 1;
|
||||
} else {
|
||||
len_len = 1;
|
||||
initial_length_byte = len;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
if (len_len != 1) {
|
||||
/* We need to move the contents along in order to make space. */
|
||||
size_t extra_bytes = len_len - 1;
|
||||
if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
|
||||
return 0;
|
||||
}
|
||||
memmove(cbb->base->buf + child_start + extra_bytes,
|
||||
cbb->base->buf + child_start, len);
|
||||
}
|
||||
cbb->base->buf[cbb->child->offset++] = initial_length_byte;
|
||||
cbb->child->pending_len_len = len_len - 1;
|
||||
}
|
||||
|
||||
for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len;
|
||||
i--) {
|
||||
cbb->base->buf[cbb->child->offset + i] = len;
|
||||
len >>= 8;
|
||||
}
|
||||
if (len != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cbb->child->base = NULL;
|
||||
cbb->child = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uint8_t *CBB_data(const CBB *cbb) {
|
||||
assert(cbb->child == NULL);
|
||||
return cbb->base->buf + cbb->offset + cbb->pending_len_len;
|
||||
}
|
||||
|
||||
size_t CBB_len(const CBB *cbb) {
|
||||
assert(cbb->child == NULL);
|
||||
assert(cbb->offset + cbb->pending_len_len <= cbb->base->len);
|
||||
|
||||
return cbb->base->len - cbb->offset - cbb->pending_len_len;
|
||||
}
|
||||
|
||||
static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
|
||||
size_t len_len) {
|
||||
uint8_t *prefix_bytes;
|
||||
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t offset = cbb->base->len;
|
||||
if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(prefix_bytes, 0, len_len);
|
||||
memset(out_contents, 0, sizeof(CBB));
|
||||
out_contents->base = cbb->base;
|
||||
cbb->child = out_contents;
|
||||
cbb->child->offset = offset;
|
||||
cbb->child->pending_len_len = len_len;
|
||||
cbb->child->pending_is_asn1 = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
|
||||
return cbb_add_length_prefixed(cbb, out_contents, 1);
|
||||
}
|
||||
|
||||
int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
|
||||
return cbb_add_length_prefixed(cbb, out_contents, 2);
|
||||
}
|
||||
|
||||
int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
|
||||
return cbb_add_length_prefixed(cbb, out_contents, 3);
|
||||
}
|
||||
|
||||
int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
|
||||
if ((tag & 0x1f) == 0x1f) {
|
||||
/* Long form identifier octets are not supported. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CBB_flush(cbb) ||
|
||||
!CBB_add_u8(cbb, tag)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t offset = cbb->base->len;
|
||||
if (!CBB_add_u8(cbb, 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(out_contents, 0, sizeof(CBB));
|
||||
out_contents->base = cbb->base;
|
||||
cbb->child = out_contents;
|
||||
cbb->child->offset = offset;
|
||||
cbb->child->pending_len_len = 1;
|
||||
cbb->child->pending_is_asn1 = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
|
||||
uint8_t *dest;
|
||||
|
||||
if (!CBB_flush(cbb) ||
|
||||
!cbb_buffer_add(cbb->base, &dest, len)) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(dest, data, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
|
||||
if (!CBB_flush(cbb) ||
|
||||
!cbb_buffer_add(cbb->base, out_data, len)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) {
|
||||
if (!CBB_flush(cbb) ||
|
||||
!cbb_buffer_reserve(cbb->base, out_data, len)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_did_write(CBB *cbb, size_t len) {
|
||||
size_t newlen = cbb->base->len + len;
|
||||
if (cbb->child != NULL ||
|
||||
newlen < cbb->base->len ||
|
||||
newlen > cbb->base->cap) {
|
||||
return 0;
|
||||
}
|
||||
cbb->base->len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBB_add_u8(CBB *cbb, uint8_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cbb_buffer_add_u(cbb->base, value, 1);
|
||||
}
|
||||
|
||||
int CBB_add_u16(CBB *cbb, uint16_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cbb_buffer_add_u(cbb->base, value, 2);
|
||||
}
|
||||
|
||||
int CBB_add_u24(CBB *cbb, uint32_t value) {
|
||||
if (!CBB_flush(cbb)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cbb_buffer_add_u(cbb->base, value, 3);
|
||||
}
|
||||
|
||||
void CBB_discard_child(CBB *cbb) {
|
||||
if (cbb->child == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
cbb->base->len = cbb->child->offset;
|
||||
|
||||
cbb->child->base = NULL;
|
||||
cbb->child = NULL;
|
||||
}
|
||||
|
||||
int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
|
||||
CBB child;
|
||||
size_t i;
|
||||
int started = 0;
|
||||
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
uint8_t byte = (value >> 8*(7-i)) & 0xff;
|
||||
if (!started) {
|
||||
if (byte == 0) {
|
||||
/* Don't encode leading zeros. */
|
||||
continue;
|
||||
}
|
||||
/* If the high bit is set, add a padding byte to make it
|
||||
* unsigned. */
|
||||
if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
|
||||
return 0;
|
||||
}
|
||||
started = 1;
|
||||
}
|
||||
if (!CBB_add_u8(&child, byte)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 0 is encoded as a single 0, not the empty string. */
|
||||
if (!started && !CBB_add_u8(&child, 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return CBB_flush(cbb);
|
||||
}
|
440
external/boringssl/crypto/bytestring/cbs.c
vendored
Normal file
440
external/boringssl/crypto/bytestring/cbs.c
vendored
Normal file
@@ -0,0 +1,440 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/buf.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/bytestring.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
|
||||
cbs->data = data;
|
||||
cbs->len = len;
|
||||
}
|
||||
|
||||
static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
|
||||
if (cbs->len < n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*p = cbs->data;
|
||||
cbs->data += n;
|
||||
cbs->len -= n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_skip(CBS *cbs, size_t len) {
|
||||
const uint8_t *dummy;
|
||||
return cbs_get(cbs, &dummy, len);
|
||||
}
|
||||
|
||||
const uint8_t *CBS_data(const CBS *cbs) {
|
||||
return cbs->data;
|
||||
}
|
||||
|
||||
size_t CBS_len(const CBS *cbs) {
|
||||
return cbs->len;
|
||||
}
|
||||
|
||||
int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
|
||||
OPENSSL_free(*out_ptr);
|
||||
*out_ptr = NULL;
|
||||
*out_len = 0;
|
||||
|
||||
if (cbs->len == 0) {
|
||||
return 1;
|
||||
}
|
||||
*out_ptr = BUF_memdup(cbs->data, cbs->len);
|
||||
if (*out_ptr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
*out_len = cbs->len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_strdup(const CBS *cbs, char **out_ptr) {
|
||||
if (*out_ptr != NULL) {
|
||||
OPENSSL_free(*out_ptr);
|
||||
}
|
||||
*out_ptr = BUF_strndup((const char*)cbs->data, cbs->len);
|
||||
return (*out_ptr != NULL);
|
||||
}
|
||||
|
||||
int CBS_contains_zero_byte(const CBS *cbs) {
|
||||
return memchr(cbs->data, 0, cbs->len) != NULL;
|
||||
}
|
||||
|
||||
int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
|
||||
if (len != cbs->len) {
|
||||
return 0;
|
||||
}
|
||||
return CRYPTO_memcmp(cbs->data, data, len) == 0;
|
||||
}
|
||||
|
||||
static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
|
||||
uint32_t result = 0;
|
||||
size_t i;
|
||||
const uint8_t *data;
|
||||
|
||||
if (!cbs_get(cbs, &data, len)) {
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
result <<= 8;
|
||||
result |= data[i];
|
||||
}
|
||||
*out = result;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_u8(CBS *cbs, uint8_t *out) {
|
||||
const uint8_t *v;
|
||||
if (!cbs_get(cbs, &v, 1)) {
|
||||
return 0;
|
||||
}
|
||||
*out = *v;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_u16(CBS *cbs, uint16_t *out) {
|
||||
uint32_t v;
|
||||
if (!cbs_get_u(cbs, &v, 2)) {
|
||||
return 0;
|
||||
}
|
||||
*out = v;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_u24(CBS *cbs, uint32_t *out) {
|
||||
return cbs_get_u(cbs, out, 3);
|
||||
}
|
||||
|
||||
int CBS_get_u32(CBS *cbs, uint32_t *out) {
|
||||
return cbs_get_u(cbs, out, 4);
|
||||
}
|
||||
|
||||
int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
|
||||
if (cbs->len == 0) {
|
||||
return 0;
|
||||
}
|
||||
*out = cbs->data[cbs->len - 1];
|
||||
cbs->len--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
|
||||
const uint8_t *v;
|
||||
if (!cbs_get(cbs, &v, len)) {
|
||||
return 0;
|
||||
}
|
||||
CBS_init(out, v, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) {
|
||||
const uint8_t *v;
|
||||
if (!cbs_get(cbs, &v, len)) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(out, v, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
|
||||
uint32_t len;
|
||||
if (!cbs_get_u(cbs, &len, len_len)) {
|
||||
return 0;
|
||||
}
|
||||
return CBS_get_bytes(cbs, out, len);
|
||||
}
|
||||
|
||||
int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
|
||||
return cbs_get_length_prefixed(cbs, out, 1);
|
||||
}
|
||||
|
||||
int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
|
||||
return cbs_get_length_prefixed(cbs, out, 2);
|
||||
}
|
||||
|
||||
int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
|
||||
return cbs_get_length_prefixed(cbs, out, 3);
|
||||
}
|
||||
|
||||
static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
||||
size_t *out_header_len, int ber_ok) {
|
||||
uint8_t tag, length_byte;
|
||||
CBS header = *cbs;
|
||||
CBS throwaway;
|
||||
|
||||
if (out == NULL) {
|
||||
out = &throwaway;
|
||||
}
|
||||
|
||||
if (!CBS_get_u8(&header, &tag) ||
|
||||
!CBS_get_u8(&header, &length_byte)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag
|
||||
* number no greater than 30.
|
||||
*
|
||||
* If the number portion is 31 (0x1f, the largest value that fits in the
|
||||
* allotted bits), then the tag is more than one byte long and the
|
||||
* continuation bytes contain the tag number. This parser only supports tag
|
||||
* numbers less than 31 (and thus single-byte tags). */
|
||||
if ((tag & 0x1f) == 0x1f) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (out_tag != NULL) {
|
||||
*out_tag = tag;
|
||||
}
|
||||
|
||||
size_t len;
|
||||
/* The format for the length encoding is specified in ITU-T X.690 section
|
||||
* 8.1.3. */
|
||||
if ((length_byte & 0x80) == 0) {
|
||||
/* Short form length. */
|
||||
len = ((size_t) length_byte) + 2;
|
||||
if (out_header_len != NULL) {
|
||||
*out_header_len = 2;
|
||||
}
|
||||
} else {
|
||||
/* The high bit indicate that this is the long form, while the next 7 bits
|
||||
* encode the number of subsequent octets used to encode the length (ITU-T
|
||||
* X.690 clause 8.1.3.5.b). */
|
||||
const size_t num_bytes = length_byte & 0x7f;
|
||||
uint32_t len32;
|
||||
|
||||
if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
|
||||
/* indefinite length */
|
||||
if (out_header_len != NULL) {
|
||||
*out_header_len = 2;
|
||||
}
|
||||
return CBS_get_bytes(cbs, out, 2);
|
||||
}
|
||||
|
||||
/* ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
|
||||
* used as the first byte of the length. If this parser encounters that
|
||||
* value, num_bytes will be parsed as 127, which will fail the check below.
|
||||
*/
|
||||
if (num_bytes == 0 || num_bytes > 4) {
|
||||
return 0;
|
||||
}
|
||||
if (!cbs_get_u(&header, &len32, num_bytes)) {
|
||||
return 0;
|
||||
}
|
||||
/* ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
|
||||
* with the minimum number of octets. */
|
||||
if (len32 < 128) {
|
||||
/* Length should have used short-form encoding. */
|
||||
return 0;
|
||||
}
|
||||
if ((len32 >> ((num_bytes-1)*8)) == 0) {
|
||||
/* Length should have been at least one byte shorter. */
|
||||
return 0;
|
||||
}
|
||||
len = len32;
|
||||
if (len + 2 + num_bytes < len) {
|
||||
/* Overflow. */
|
||||
return 0;
|
||||
}
|
||||
len += 2 + num_bytes;
|
||||
if (out_header_len != NULL) {
|
||||
*out_header_len = 2 + num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
return CBS_get_bytes(cbs, out, len);
|
||||
}
|
||||
|
||||
int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
||||
size_t *out_header_len) {
|
||||
return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
|
||||
0 /* DER only */);
|
||||
}
|
||||
|
||||
int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
||||
size_t *out_header_len) {
|
||||
return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
|
||||
1 /* BER allowed */);
|
||||
}
|
||||
|
||||
static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value,
|
||||
int skip_header) {
|
||||
size_t header_len;
|
||||
unsigned tag;
|
||||
CBS throwaway;
|
||||
|
||||
if (out == NULL) {
|
||||
out = &throwaway;
|
||||
}
|
||||
|
||||
if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
|
||||
tag != tag_value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (skip_header && !CBS_skip(out, header_len)) {
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
|
||||
return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
|
||||
}
|
||||
|
||||
int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
|
||||
return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
|
||||
}
|
||||
|
||||
int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
|
||||
if (CBS_len(cbs) < 1) {
|
||||
return 0;
|
||||
}
|
||||
return CBS_data(cbs)[0] == tag_value;
|
||||
}
|
||||
|
||||
int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
|
||||
CBS bytes;
|
||||
const uint8_t *data;
|
||||
size_t i, len;
|
||||
|
||||
if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out = 0;
|
||||
data = CBS_data(&bytes);
|
||||
len = CBS_len(&bytes);
|
||||
|
||||
if (len == 0) {
|
||||
/* An INTEGER is encoded with at least one octet. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((data[0] & 0x80) != 0) {
|
||||
/* Negative number. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) {
|
||||
/* Extra leading zeros. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((*out >> 56) != 0) {
|
||||
/* Too large to represent as a uint64_t. */
|
||||
return 0;
|
||||
}
|
||||
*out <<= 8;
|
||||
*out |= data[i];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) {
|
||||
int present = 0;
|
||||
|
||||
if (CBS_peek_asn1_tag(cbs, tag)) {
|
||||
if (!CBS_get_asn1(cbs, out, tag)) {
|
||||
return 0;
|
||||
}
|
||||
present = 1;
|
||||
}
|
||||
|
||||
if (out_present != NULL) {
|
||||
*out_present = present;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
|
||||
unsigned tag) {
|
||||
CBS child;
|
||||
int present;
|
||||
if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
|
||||
return 0;
|
||||
}
|
||||
if (present) {
|
||||
if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
|
||||
CBS_len(&child) != 0) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
CBS_init(out, NULL, 0);
|
||||
}
|
||||
if (out_present) {
|
||||
*out_present = present;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag,
|
||||
uint64_t default_value) {
|
||||
CBS child;
|
||||
int present;
|
||||
if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
|
||||
return 0;
|
||||
}
|
||||
if (present) {
|
||||
if (!CBS_get_asn1_uint64(&child, out) ||
|
||||
CBS_len(&child) != 0) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
*out = default_value;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
|
||||
int default_value) {
|
||||
CBS child, child2;
|
||||
int present;
|
||||
if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
|
||||
return 0;
|
||||
}
|
||||
if (present) {
|
||||
uint8_t boolean;
|
||||
|
||||
if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
|
||||
CBS_len(&child2) != 1 ||
|
||||
CBS_len(&child) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean = CBS_data(&child2)[0];
|
||||
if (boolean == 0) {
|
||||
*out = 0;
|
||||
} else if (boolean == 0xff) {
|
||||
*out = 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
*out = default_value;
|
||||
}
|
||||
return 1;
|
||||
}
|
75
external/boringssl/crypto/bytestring/internal.h
vendored
Normal file
75
external/boringssl/crypto/bytestring/internal.h
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#ifndef OPENSSL_HEADER_BYTESTRING_INTERNAL_H
|
||||
#define OPENSSL_HEADER_BYTESTRING_INTERNAL_H
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* CBS_asn1_ber_to_der reads a BER element from |in|. If it finds
|
||||
* indefinite-length elements or constructed strings then it converts the BER
|
||||
* data to DER and sets |*out| and |*out_length| to describe a malloced buffer
|
||||
* containing the DER data. Additionally, |*in| will be advanced over the BER
|
||||
* element.
|
||||
*
|
||||
* If it doesn't find any indefinite-length elements or constructed strings then
|
||||
* it sets |*out| to NULL and |*in| is unmodified.
|
||||
*
|
||||
* This function should successfully process any valid BER input, however it
|
||||
* will not convert all of BER's deviations from DER. BER is ambiguous between
|
||||
* implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed
|
||||
* strings. Implicitly-tagged strings must be parsed with
|
||||
* |CBS_get_ber_implicitly_tagged_string| instead of |CBS_get_asn1|. The caller
|
||||
* must also account for BER variations in the contents of a primitive.
|
||||
*
|
||||
* It returns one on success and zero otherwise. */
|
||||
OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len);
|
||||
|
||||
/* CBS_get_asn1_implicit_string parses a BER string of primitive type
|
||||
* |inner_tag| implicitly-tagged with |outer_tag|. It sets |out| to the
|
||||
* contents. If concatenation was needed, it sets |*out_storage| to a buffer
|
||||
* which the caller must release with |OPENSSL_free|. Otherwise, it sets
|
||||
* |*out_storage| to NULL.
|
||||
*
|
||||
* This function does not parse all of BER. It requires the string be
|
||||
* definite-length. Constructed strings are allowed, but all children of the
|
||||
* outermost element must be primitive. The caller should use
|
||||
* |CBS_asn1_ber_to_der| before running this function.
|
||||
*
|
||||
* It returns one on success and zero otherwise. */
|
||||
OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out,
|
||||
uint8_t **out_storage,
|
||||
unsigned outer_tag,
|
||||
unsigned inner_tag);
|
||||
|
||||
/* CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized
|
||||
* with |CBB_init|. If |outp| is not NULL then the result is written to |*outp|
|
||||
* and |*outp| is advanced just past the output. It returns the number of bytes
|
||||
* in the result, whether written or not, or a negative value on error. On
|
||||
* error, it calls |CBB_cleanup| on |cbb|.
|
||||
*
|
||||
* This function may be used to help implement legacy i2d ASN.1 functions. */
|
||||
int CBB_finish_i2d(CBB *cbb, uint8_t **outp);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_BYTESTRING_INTERNAL_H */
|
Reference in New Issue
Block a user