Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// Sources/CCryptoBoringSSL directory. The source repository is at
// https://boringssl.googlesource.com/boringssl.
//
// BoringSSL Commit: 035e720641f385e82c72b7b0a9e1d89e58cb5ed5
// BoringSSL Commit: 0226f30467f540a3f62ef48d453f93927da199b6

import PackageDescription

Expand Down
1 change: 0 additions & 1 deletion Sources/CCryptoBoringSSL/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,6 @@ add_library(CCryptoBoringSSL STATIC
"crypto/x509/x_req.cc"
"crypto/x509/x_sig.cc"
"crypto/x509/x_spki.cc"
"crypto/x509/x_val.cc"
"crypto/x509/x_x509.cc"
"crypto/x509/x_x509a.cc"
"crypto/xwing/xwing.cc"
Expand Down
123 changes: 72 additions & 51 deletions Sources/CCryptoBoringSSL/crypto/asn1/a_bitstr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <CCryptoBoringSSL_bytestring.h>
#include <CCryptoBoringSSL_err.h>
#include <CCryptoBoringSSL_mem.h>
#include <CCryptoBoringSSL_span.h>

#include "../internal.h"
#include "internal.h"
Expand Down Expand Up @@ -110,76 +111,96 @@ int asn1_marshal_bit_string(CBB *out, const ASN1_BIT_STRING *in,
CBB_flush(out);
}

ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
const unsigned char **pp, long len) {
ASN1_BIT_STRING *ret = NULL;
const unsigned char *p;
unsigned char *s;
int padding;
uint8_t padding_mask;

if (len < 1) {
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);
goto err;
return 0;
}

if (len > INT_MAX) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
goto err;
if (padding > 7) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
return 0;
}

if ((a == NULL) || ((*a) == NULL)) {
if ((ret = ASN1_BIT_STRING_new()) == NULL) {
return NULL;
// 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(&copy, &last) || (last & padding_mask) != 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING);
return 0;
}
} else {
ret = (*a);
}

p = *pp;
padding = *(p++);
len--;
if (padding > 7) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
goto err;
if (!ASN1_STRING_set(out, CBS_data(&cbs), CBS_len(&cbs))) {
return 0;
}

// Unused bits in a BIT STRING must be zero.
padding_mask = (1 << padding) - 1;
if (padding != 0 && (len < 1 || (p[len - 1] & padding_mask) != 0)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_PADDING);
goto err;
}
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;
}

// We do this to preserve the settings. If we modify the settings, via
// the _set_bit function, we will recalculate on output
ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); // clear
ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); // set
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;
}

if (len > 0) {
s = reinterpret_cast<uint8_t *>(OPENSSL_memdup(p, len));
if (s == NULL) {
goto err;
ASN1_BIT_STRING *ret = nullptr;
if (a == nullptr || *a == nullptr) {
if ((ret = ASN1_BIT_STRING_new()) == nullptr) {
return nullptr;
}
p += len;
} else {
s = NULL;
ret = *a;
}

ret->length = (int)len;
OPENSSL_free(ret->data);
ret->data = s;
ret->type = V_ASN1_BIT_STRING;
if (a != NULL) {
(*a) = ret;
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;
}
*pp = p;

if (a != nullptr) {
*a = ret;
}
*pp += len;
return ret;
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret))) {
ASN1_BIT_STRING_free(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 NULL;
return asn1_parse_bit_string_contents(child, out);
}

// These next 2 functions from Goetz Babin-Ebell <[email protected]>
Expand Down
11 changes: 4 additions & 7 deletions Sources/CCryptoBoringSSL/crypto/asn1/a_bool.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@


int i2d_ASN1_BOOLEAN(ASN1_BOOLEAN a, unsigned char **outp) {
CBB cbb;
if (!CBB_init(&cbb, 3) || //
!CBB_add_asn1_bool(&cbb, a != ASN1_BOOLEAN_FALSE)) {
CBB_cleanup(&cbb);
return -1;
}
return CBB_finish_i2d(&cbb, outp);
return bssl::I2DFromCBB(
/*initial_capacity=*/3, outp, [&](CBB *cbb) -> bool {
return CBB_add_asn1_bool(cbb, a != ASN1_BOOLEAN_FALSE);
});
}

ASN1_BOOLEAN d2i_ASN1_BOOLEAN(ASN1_BOOLEAN *out, const unsigned char **inp,
Expand Down
17 changes: 17 additions & 0 deletions Sources/CCryptoBoringSSL/crypto/asn1/a_gentm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,23 @@ int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d) {
return 1;
}

int asn1_parse_generalized_time(CBS *cbs, ASN1_GENERALIZEDTIME *out,
CBS_ASN1_TAG tag) {
tag = tag == 0 ? CBS_ASN1_GENERALIZEDTIME : tag;
CBS child;
if (!CBS_get_asn1(cbs, &child, tag) ||
!CBS_parse_generalized_time(&child, nullptr,
/*allow_timezone_offset=*/0)) {
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_GENERALIZEDTIME;
return 1;
}

int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d) {
return asn1_generalizedtime_to_tm(NULL, d);
}
Expand Down
96 changes: 60 additions & 36 deletions Sources/CCryptoBoringSSL/crypto/asn1/a_int.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <CCryptoBoringSSL_bytestring.h>
#include <CCryptoBoringSSL_err.h>
#include <CCryptoBoringSSL_mem.h>
#include <CCryptoBoringSSL_span.h>

#include "../internal.h"
#include "internal.h"
Expand Down Expand Up @@ -146,32 +147,13 @@ int i2c_ASN1_INTEGER(const ASN1_INTEGER *in, unsigned char **outp) {
return len;
}

ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp,
long len) {
// This function can handle lengths up to INT_MAX - 1, but the rest of the
// legacy ASN.1 code mixes integer types, so avoid exposing it to
// ASN1_INTEGERS with larger lengths.
if (len < 0 || len > INT_MAX / 2) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
return NULL;
}

CBS cbs;
CBS_init(&cbs, *inp, (size_t)len);
static int asn1_parse_integer_contents(bssl::Span<const uint8_t> in,
ASN1_INTEGER *out) {
CBS cbs = in;
int is_negative;
if (!CBS_is_valid_asn1_integer(&cbs, &is_negative)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_INTEGER);
return NULL;
}

ASN1_INTEGER *ret = NULL;
if (out == NULL || *out == NULL) {
ret = ASN1_INTEGER_new();
if (ret == NULL) {
return NULL;
}
} else {
ret = *out;
return 0;
}

// Convert to |ASN1_INTEGER|'s sign-and-magnitude representation. First,
Expand All @@ -192,33 +174,75 @@ ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp,
}
}

if (!ASN1_STRING_set(ret, CBS_data(&cbs), CBS_len(&cbs))) {
goto err;
if (!ASN1_STRING_set(out, CBS_data(&cbs), CBS_len(&cbs))) {
return 0;
}

if (is_negative) {
ret->type = V_ASN1_NEG_INTEGER;
negate_twos_complement(ret->data, ret->length);
out->type = V_ASN1_NEG_INTEGER;
negate_twos_complement(out->data, out->length);
} else {
ret->type = V_ASN1_INTEGER;
out->type = V_ASN1_INTEGER;
}

// The value should be minimally-encoded.
assert(ret->length == 0 || ret->data[0] != 0);
assert(out->length == 0 || out->data[0] != 0);
// Zero is not negative.
assert(!is_negative || ret->length > 0);
assert(!is_negative || out->length > 0);
return 1;
}

int asn1_parse_integer(CBS *cbs, ASN1_INTEGER *out, CBS_ASN1_TAG tag) {
tag = tag == 0 ? CBS_ASN1_INTEGER : tag;
CBS child;
if (!CBS_get_asn1(cbs, &child, tag)) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
return 0;
}
return asn1_parse_integer_contents(child, out);
}

int asn1_parse_enumerated(CBS *cbs, ASN1_ENUMERATED *out, CBS_ASN1_TAG tag) {
tag = tag == 0 ? CBS_ASN1_ENUMERATED : tag;
if (!asn1_parse_integer(cbs, out, tag)) {
return 0;
}
// Fix the type value.
out->type =
(out->type & V_ASN1_NEG) ? V_ASN1_NEG_ENUMERATED : V_ASN1_ENUMERATED;
return 1;
}

ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **out, const unsigned char **inp,
long len) {
if (len < 0) {
OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
return nullptr;
}

ASN1_INTEGER *ret = nullptr;
if (out == nullptr || *out == nullptr) {
ret = ASN1_INTEGER_new();
if (ret == nullptr) {
return nullptr;
}
} else {
ret = *out;
}

if (!asn1_parse_integer_contents(bssl::Span(*inp, len), ret)) {
if (ret != nullptr && (out == nullptr || *out != ret)) {
ASN1_INTEGER_free(ret);
}
return nullptr;
}

*inp += len;
if (out != NULL) {
if (out != nullptr) {
*out = ret;
}
return ret;

err:
if (ret != NULL && (out == NULL || *out != ret)) {
ASN1_INTEGER_free(ret);
}
return NULL;
}

int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t v) {
Expand Down
Loading