summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk13
-rw-r--r--rules.mk70
-rw-r--r--src/crypto/bio/bio.c140
-rw-r--r--src/crypto/bio/bio_test.cc81
-rw-r--r--src/crypto/x509v3/v3_utl.c2
-rw-r--r--src/include/openssl/bio.h15
6 files changed, 315 insertions, 6 deletions
diff --git a/Android.mk b/Android.mk
index cebeb2c..ffbdbc0 100644
--- a/Android.mk
+++ b/Android.mk
@@ -13,6 +13,7 @@ LOCAL_MODULE := libcrypto_static
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
LOCAL_SDK_VERSION := 9
+LOCAL_CFLAGS = -Wno-unused-parameters
# sha256-armv4.S does not compile with clang.
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
ifeq ($(TARGET_ARCH),arm64)
@@ -29,7 +30,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libcrypto
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION
+LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -Wno-unused-parameters
LOCAL_SDK_VERSION := 9
# sha256-armv4.S does not compile with clang.
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
@@ -48,6 +49,7 @@ LOCAL_CPP_EXTENSION := cc
LOCAL_MODULE := bssl
LOCAL_MODULE_TAGS := optional
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/sources.mk
+LOCAL_CFLAGS = -Wno-unused-parameters
LOCAL_SHARED_LIBRARIES=libcrypto libssl
include $(LOCAL_PATH)/sources.mk
LOCAL_SRC_FILES = $(tool_sources)
@@ -59,6 +61,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libcrypto_static
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
+LOCAL_CFLAGS = -Wno-unused-parameters
# Windows and Macs both have problems with assembly files
ifneq ($(HOST_OS),linux)
LOCAL_CFLAGS += -DOPENSSL_NO_ASM
@@ -73,7 +76,7 @@ LOCAL_MODULE := libcrypto-host
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_MULTILIB := both
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION
+LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -Wno-unused-parameters
# Windows and Macs both have problems with assembly files
ifneq ($(HOST_OS),linux)
LOCAL_CFLAGS += -DOPENSSL_NO_ASM
@@ -91,6 +94,7 @@ LOCAL_MODULE := libssl_static
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
LOCAL_SDK_VERSION := 9
+LOCAL_CFLAGS = -Wno-unused-parameters
include $(LOCAL_PATH)/ssl-sources.mk
include $(BUILD_STATIC_LIBRARY)
@@ -100,7 +104,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libssl
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION
+LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -Wno-unused-parameters
LOCAL_SHARED_LIBRARIES=libcrypto
LOCAL_SDK_VERSION := 9
include $(LOCAL_PATH)/ssl-sources.mk
@@ -112,6 +116,7 @@ LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libssl_static-host
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
+LOCAL_CFLAGS = -Wno-unused-parameters
include $(LOCAL_PATH)/ssl-sources.mk
include $(BUILD_HOST_STATIC_LIBRARY)
@@ -122,7 +127,7 @@ LOCAL_MODULE := libssl-host
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
LOCAL_MULTILIB := both
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION
+LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -Wno-unused-parameters
LOCAL_SHARED_LIBRARIES += libcrypto-host
include $(LOCAL_PATH)/ssl-sources.mk
include $(BUILD_HOST_SHARED_LIBRARY)
diff --git a/rules.mk b/rules.mk
new file mode 100644
index 0000000..5f4960b
--- /dev/null
+++ b/rules.mk
@@ -0,0 +1,70 @@
+# Copyright (C) 2015 The Android Open Source Project.
+#
+# 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.
+
+# This file is not used in the Android build process! It's used only by Trusty.
+
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+LOCAL_PATH := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+TARGET_ARCH := $(ARCH)
+TARGET_2ND_ARCH := $(ARCH)
+
+# Reset local variables
+LOCAL_CFLAGS :=
+LOCAL_C_INCLUDES :=
+LOCAL_SRC_FILES_$(TARGET_ARCH) :=
+LOCAL_SRC_FILES_$(TARGET_2ND_ARCH) :=
+LOCAL_CFLAGS_$(TARGET_ARCH) :=
+LOCAL_CFLAGS_$(TARGET_2ND_ARCH) :=
+LOCAL_ADDITIONAL_DEPENDENCIES :=
+
+# get target_c_flags, target_c_includes, target_src_files
+MODULE_SRCDEPS += $(LOCAL_DIR)/crypto-sources.mk
+include $(LOCAL_DIR)/crypto-sources.mk
+
+# Some files in BoringSSL use OS functions that aren't supported by Trusty. The
+# easiest way to deal with them is not to include them. As long as no path to
+# the functions defined in these files exists, the linker will be happy. If
+# such a path is created, it'll be a link-time error and something more complex
+# may need to be considered.
+LOCAL_SRC_FILES := $(filter-out android_compat_hacks.c,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out src/crypto/bio/connect.c,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out src/crypto/bio/fd.c,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out src/crypto/bio/file.c,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out src/crypto/bio/socket.c,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out src/crypto/bio/socket_helper.c,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out src/crypto/directory_posix.c,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out src/crypto/rand/urandom.c,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out src/crypto/time_support.c,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out src/crypto/x509/by_dir.c,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out src/crypto/x509v3/v3_utl.c,$(LOCAL_SRC_FILES))
+
+# BoringSSL detects Trusty based on this define and does things like switch to
+# no-op threading functions.
+MODULE_CFLAGS += -DTRUSTY
+
+MODULE_SRCS += $(addprefix $(LOCAL_DIR)/,$(LOCAL_SRC_FILES))
+MODULE_SRCS += $(addprefix $(LOCAL_DIR)/,$(LOCAL_SRC_FILES_$(ARCH)))
+LOCAL_C_INCLUDES := src/crypto src/include
+
+GLOBAL_INCLUDES += $(addprefix $(LOCAL_DIR)/,$(LOCAL_C_INCLUDES))
+
+MODULE_DEPS := \
+ lib/openssl-stubs \
+ lib/libc-trusty
+
+include make/module.mk
diff --git a/src/crypto/bio/bio.c b/src/crypto/bio/bio.c
index 48c1466..694a11c 100644
--- a/src/crypto/bio/bio.c
+++ b/src/crypto/bio/bio.c
@@ -56,6 +56,7 @@
#include <openssl/bio.h>
+#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <string.h>
@@ -459,3 +460,142 @@ static int print_bio(const char *str, size_t len, void *bio) {
void BIO_print_errors(BIO *bio) {
ERR_print_errors_cb(print_bio, bio);
}
+
+/* bio_read_all reads everything from |bio| and prepends |prefix| to it. On
+ * success, |*out| is set to an allocated buffer (which should be freed with
+ * |OPENSSL_free|), |*out_len| is set to its length and one is returned. The
+ * buffer will contain |prefix| followed by the contents of |bio|. On failure,
+ * zero is returned.
+ *
+ * The function will fail if the size of the output would equal or exceed
+ * |max_len|. */
+static int bio_read_all(BIO *bio, uint8_t **out, size_t *out_len,
+ const uint8_t *prefix, size_t prefix_len,
+ size_t max_len) {
+ static const size_t kChunkSize = 4096;
+
+ size_t len = prefix_len + kChunkSize;
+ if (len > max_len) {
+ len = max_len;
+ }
+ if (len < prefix_len) {
+ return 0;
+ }
+ *out = OPENSSL_malloc(len);
+ if (*out == NULL) {
+ return 0;
+ }
+ memcpy(*out, prefix, prefix_len);
+ size_t done = prefix_len;
+
+ for (;;) {
+ if (done == len) {
+ OPENSSL_free(*out);
+ return 0;
+ }
+ const size_t todo = len - done;
+ assert(todo < INT_MAX);
+ const int n = BIO_read(bio, *out + done, todo);
+ if (n == 0) {
+ *out_len = done;
+ return 1;
+ } else if (n == -1) {
+ OPENSSL_free(*out);
+ return 0;
+ }
+
+ done += n;
+ if (len < max_len && len - done < kChunkSize / 2) {
+ len += kChunkSize;
+ if (len > max_len) {
+ len = max_len;
+ }
+ uint8_t *new_buf = OPENSSL_realloc(*out, len);
+ if (new_buf == NULL) {
+ OPENSSL_free(*out);
+ return 0;
+ }
+ *out = new_buf;
+ }
+ }
+}
+
+int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) {
+ uint8_t header[6];
+
+ static const size_t kInitialHeaderLen = 2;
+ if (BIO_read(bio, header, kInitialHeaderLen) != kInitialHeaderLen) {
+ return 0;
+ }
+
+ const uint8_t tag = header[0];
+ const uint8_t length_byte = header[1];
+
+ if ((tag & 0x1f) == 0x1f) {
+ /* Long form tags are not supported. */
+ return 0;
+ }
+
+ size_t len, header_len;
+ if ((length_byte & 0x80) == 0) {
+ /* Short form length. */
+ len = length_byte;
+ header_len = kInitialHeaderLen;
+ } else {
+ const size_t num_bytes = length_byte & 0x7f;
+
+ if ((tag & 0x20 /* constructed */) != 0 && num_bytes == 0) {
+ /* indefinite length. */
+ return bio_read_all(bio, out, out_len, header, kInitialHeaderLen,
+ max_len);
+ }
+
+ if (num_bytes == 0 || num_bytes > 4) {
+ return 0;
+ }
+
+ if (BIO_read(bio, header + kInitialHeaderLen, num_bytes) != num_bytes) {
+ return 0;
+ }
+ header_len = kInitialHeaderLen + num_bytes;
+
+ uint32_t len32 = 0;
+ unsigned i;
+ for (i = 0; i < num_bytes; i++) {
+ len32 <<= 8;
+ len32 |= header[kInitialHeaderLen + i];
+ }
+
+ 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 + header_len < len ||
+ len + header_len > max_len) {
+ return 0;
+ }
+ len += header_len;
+ *out_len = len;
+
+ *out = OPENSSL_malloc(len);
+ if (*out == NULL) {
+ return 0;
+ }
+ memcpy(*out, header, header_len);
+ if (BIO_read(bio, (*out) + header_len, len - header_len) !=
+ len - header_len) {
+ OPENSSL_free(*out);
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/src/crypto/bio/bio_test.cc b/src/crypto/bio/bio_test.cc
index 4c88df5..e0193f8 100644
--- a/src/crypto/bio/bio_test.cc
+++ b/src/crypto/bio/bio_test.cc
@@ -329,6 +329,84 @@ static bool TestPrintf() {
return true;
}
+static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len,
+ size_t expected_len, size_t max_len) {
+ ScopedBIO bio(BIO_new_mem_buf(const_cast<uint8_t*>(data), data_len));
+
+ uint8_t *out;
+ size_t out_len;
+ int ok = BIO_read_asn1(bio.get(), &out, &out_len, max_len);
+ if (!ok) {
+ out = nullptr;
+ }
+ ScopedOpenSSLBytes out_storage(out);
+
+ if (should_succeed != (ok == 1)) {
+ return false;
+ }
+
+ if (should_succeed &&
+ (out_len != expected_len || memcmp(data, out, expected_len) != 0)) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestASN1() {
+ static const uint8_t kData1[] = {0x30, 2, 1, 2, 0, 0};
+ static const uint8_t kData2[] = {0x30, 3, 1, 2}; /* truncated */
+ static const uint8_t kData3[] = {0x30, 0x81, 1, 1}; /* should be short len */
+ static const uint8_t kData4[] = {0x30, 0x82, 0, 1, 1}; /* zero padded. */
+
+ if (!ReadASN1(true, kData1, sizeof(kData1), 4, 100) ||
+ !ReadASN1(false, kData2, sizeof(kData2), 0, 100) ||
+ !ReadASN1(false, kData3, sizeof(kData3), 0, 100) ||
+ !ReadASN1(false, kData4, sizeof(kData4), 0, 100)) {
+ return false;
+ }
+
+ static const size_t kLargePayloadLen = 8000;
+ static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8,
+ kLargePayloadLen & 0xff};
+ ScopedOpenSSLBytes large(reinterpret_cast<uint8_t *>(
+ OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen)));
+ memset(large.get() + sizeof(kLargePrefix), 0, kLargePayloadLen);
+ memcpy(large.get(), kLargePrefix, sizeof(kLargePrefix));
+
+ if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
+ sizeof(kLargePrefix) + kLargePayloadLen,
+ kLargePayloadLen * 2)) {
+ fprintf(stderr, "Large payload test failed.\n");
+ return false;
+ }
+
+ if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
+ sizeof(kLargePrefix) + kLargePayloadLen,
+ kLargePayloadLen - 1)) {
+ fprintf(stderr, "max_len test failed.\n");
+ return false;
+ }
+
+ static const uint8_t kIndefPrefix[] = {0x30, 0x80};
+ memcpy(large.get(), kIndefPrefix, sizeof(kIndefPrefix));
+ if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
+ sizeof(kLargePrefix) + kLargePayloadLen,
+ kLargePayloadLen*2)) {
+ fprintf(stderr, "indefinite length test failed.\n");
+ return false;
+ }
+
+ if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
+ sizeof(kLargePrefix) + kLargePayloadLen,
+ kLargePayloadLen-1)) {
+ fprintf(stderr, "indefinite length, max_len test failed.\n");
+ return false;
+ }
+
+ return true;
+}
+
int main(void) {
CRYPTO_library_init();
ERR_load_crypto_strings();
@@ -350,7 +428,8 @@ int main(void) {
if (!TestSocketConnect() ||
!TestPrintf() ||
- !TestZeroCopyBioPairs()) {
+ !TestZeroCopyBioPairs() ||
+ !TestASN1()) {
return 1;
}
diff --git a/src/crypto/x509v3/v3_utl.c b/src/crypto/x509v3/v3_utl.c
index 27a91ff..d79f0de 100644
--- a/src/crypto/x509v3/v3_utl.c
+++ b/src/crypto/x509v3/v3_utl.c
@@ -879,9 +879,9 @@ static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
if (astrlen < 0)
return -1;
rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
- OPENSSL_free(astr);
if (rv > 0 && peername)
*peername = BUF_strndup((char *)astr, astrlen);
+ OPENSSL_free(astr);
}
return rv;
}
diff --git a/src/include/openssl/bio.h b/src/include/openssl/bio.h
index b70b42f..a37077c 100644
--- a/src/include/openssl/bio.h
+++ b/src/include/openssl/bio.h
@@ -338,6 +338,21 @@ OPENSSL_EXPORT int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len,
* using human readable strings where possible. */
OPENSSL_EXPORT void BIO_print_errors(BIO *bio);
+/* BIO_read_asn1 reads a single ASN.1 object from |bio|. If successful it sets
+ * |*out| to be an allocated buffer (that should be freed with |OPENSSL_free|),
+ * |*out_size| to the length, in bytes, of that buffer and returns one.
+ * Otherwise it returns zero.
+ *
+ * If the length of the object is greater than |max_len| or 2^32 then the
+ * function will fail. Long-form tags are not supported. If the length of the
+ * object is indefinite the full contents of |bio| are read, unless it would be
+ * greater than |max_len|, in which case the function fails.
+ *
+ * If the function fails then some unknown amount of data may have been read
+ * from |bio|. */
+OPENSSL_EXPORT int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len,
+ size_t max_len);
+
/* Memory BIOs.
*