diff --git a/Makefile b/Makefile index 3175990d4..71fd7282e 100644 --- a/Makefile +++ b/Makefile @@ -203,6 +203,7 @@ include third_party/chibicc/test/test.mk include third_party/python/python.mk include tool/build/build.mk include tool/curl/curl.mk +include tool/ape/ape.mk include third_party/qemu/qemu.mk include examples/examples.mk include examples/pyapp/pyapp.mk diff --git a/build/config.mk b/build/config.mk index 091393c9f..18514b967 100644 --- a/build/config.mk +++ b/build/config.mk @@ -33,6 +33,7 @@ endif # - Better GDB debugging # ifeq ($(MODE), zero) +ENABLE_FTRACE = 1 CONFIG_OFLAGS ?= -g OVERRIDE_CFLAGS += -O0 OVERRIDE_CXXFLAGS += -O0 @@ -156,7 +157,7 @@ endif ifeq ($(MODE), dbg) ENABLE_FTRACE = 1 CONFIG_OFLAGS ?= -g -CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_ADDRESS__ +CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_ADDRESS__ -D__SANITIZE_UNDEFINED__ CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline CONFIG_COPTS += -fsanitize=address -fsanitize=undefined TARGET_ARCH ?= -msse3 @@ -166,7 +167,7 @@ endif ifeq ($(MODE), aarch64-dbg) ENABLE_FTRACE = 1 CONFIG_OFLAGS ?= -g -CONFIG_CPPFLAGS += -DMODE_DBG +CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__ CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline CONFIG_COPTS += -fsanitize=undefined QUOTA ?= -C64 -L300 diff --git a/libc/fmt/strerror.c b/libc/intrin/strerror.c similarity index 100% rename from libc/fmt/strerror.c rename to libc/intrin/strerror.c diff --git a/libc/fmt/strerror_r.c b/libc/intrin/strerror_r.c similarity index 100% rename from libc/fmt/strerror_r.c rename to libc/intrin/strerror_r.c diff --git a/libc/stdio/stderr.c b/libc/stdio/stderr.c index 298a06693..026cf9549 100644 --- a/libc/stdio/stderr.c +++ b/libc/stdio/stderr.c @@ -33,7 +33,7 @@ static FILE __stderr; __attribute__((__constructor__)) static void __stderr_init(void) { stderr = &__stderr; stderr->fd = STDERR_FILENO; - stderr->bufmode = _IOLBF; + stderr->bufmode = _IONBF; stderr->iomode = O_WRONLY; stderr->buf = stderr->mem; stderr->size = sizeof(stderr->mem); diff --git a/libc/str/memcasecmp.c b/libc/str/memcasecmp.c index 03569ed90..fad1dac6e 100644 --- a/libc/str/memcasecmp.c +++ b/libc/str/memcasecmp.c @@ -57,14 +57,7 @@ int memcasecmp(const void *p, const void *q, size_t n) { if ((a = p) != (b = q)) { for (i = 0; i < n; ++i) { while (i + 8 <= n) { - if ((w = (((uint64_t)a[0] << 000 | (uint64_t)a[1] << 010 | - (uint64_t)a[2] << 020 | (uint64_t)a[3] << 030 | - (uint64_t)a[4] << 040 | (uint64_t)a[5] << 050 | - (uint64_t)a[6] << 060 | (uint64_t)a[7] << 070) ^ - ((uint64_t)b[0] << 000 | (uint64_t)b[1] << 010 | - (uint64_t)b[2] << 020 | (uint64_t)b[3] << 030 | - (uint64_t)b[4] << 040 | (uint64_t)b[5] << 050 | - (uint64_t)b[6] << 060 | (uint64_t)b[7] << 070)))) { + if ((w = (READ64LE(a) ^ READ64LE(b)))) { u = __builtin_ctzll(w); i += u >> 3; break; diff --git a/net/https/getsslroots.c b/net/https/getsslroots.c index 7b5bc2fc2..8ac1bbfb0 100644 --- a/net/https/getsslroots.c +++ b/net/https/getsslroots.c @@ -18,54 +18,62 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" #include "libc/calls/struct/dirent.h" -#include "libc/errno.h" -#include "libc/log/check.h" -#include "libc/log/log.h" #include "libc/mem/mem.h" -#include "libc/runtime/runtime.h" #include "libc/str/str.h" #include "libc/sysv/consts/dt.h" #include "libc/sysv/consts/o.h" -#include "libc/x/x.h" -#include "net/https/https.h" +#include "libc/thread/thread.h" #include "third_party/mbedtls/x509_crt.h" STATIC_YOINK("ssl_root_support"); -static void FreeSslRoots(mbedtls_x509_crt *c) { - mbedtls_x509_crt_free(c); - free(c); +#define SSL_ROOT_DIR "/zip/usr/share/ssl/root" + +static struct { + pthread_once_t once; + mbedtls_x509_crt chain; +} g_ssl_roots; + +static void FreeSslRoots(void) { + mbedtls_x509_crt_free(&g_ssl_roots.chain); +} + +static void InitSslRoots(void) { + DIR *dir; + if (!(dir = opendir(SSL_ROOT_DIR))) { + perror(SSL_ROOT_DIR); + return; + } + struct dirent *ent; + while ((ent = readdir(dir))) { + if (ent->d_type != DT_REG && // + ent->d_type != DT_UNKNOWN) { + continue; + } + char path[PATH_MAX]; + strlcpy(path, SSL_ROOT_DIR "/", sizeof(path)); + strlcat(path, ent->d_name, sizeof(path)); + uint8_t *data; + int fd = open(path, O_RDONLY); // punt error to lseek + size_t size = lseek(fd, 0, SEEK_END); // punt error to calloc + if ((data = calloc(1, size + 1)) && pread(fd, data, size, 0) == size) { + if (mbedtls_x509_crt_parse(&g_ssl_roots.chain, data, size + 1)) { + tinyprint(2, path, ": error loading ssl root\n", NULL); + } + } else { + perror(path); + } + free(data); + close(fd); + } + closedir(dir); + atexit(FreeSslRoots); } /** * Returns singleton of SSL roots stored in /zip/usr/share/ssl/root/... */ mbedtls_x509_crt *GetSslRoots(void) { - int fd; - DIR *d; - uint8_t *p; - size_t n, m; - struct dirent *e; - static bool once; - char path[PATH_MAX]; - static mbedtls_x509_crt *c; - if (!once) { - if ((c = calloc(1, sizeof(*c)))) { - m = stpcpy(path, "/zip/usr/share/ssl/root/") - path; - if ((d = opendir(path))) { - while ((e = readdir(d))) { - if (e->d_type != DT_REG) continue; - if (m + (n = strlen(e->d_name)) >= ARRAYLEN(path)) continue; - memcpy(path + m, e->d_name, n + 1); - CHECK((p = xslurp(path, &n))); - CHECK_GE(mbedtls_x509_crt_parse(c, p, n + 1), 0, "%s", path); - free(p); - } - closedir(d); - } - __cxa_atexit(FreeSslRoots, c, 0); - } - once = true; - } - return c; + pthread_once(&g_ssl_roots.once, InitSslRoots); + return &g_ssl_roots.chain; } diff --git a/net/https/https.mk b/net/https/https.mk index 4380e663e..7bd9df56e 100644 --- a/net/https/https.mk +++ b/net/https/https.mk @@ -7,7 +7,7 @@ NET_HTTPS_ARTIFACTS += NET_HTTPS_A NET_HTTPS = $(NET_HTTPS_A_DEPS) $(NET_HTTPS_A) NET_HTTPS_A = o/$(MODE)/net/https/https.a NET_HTTPS_A_FILES := $(wildcard net/https/*) -NET_HTTPS_A_CERTS := $(wildcard usr/share/ssl/root/*) +NET_HTTPS_A_CERTS := $(wildcard usr/share/ssl/root/*.pem) NET_HTTPS_A_HDRS = $(filter %.h,$(NET_HTTPS_A_FILES)) NET_HTTPS_A_SRCS = $(filter %.c,$(NET_HTTPS_A_FILES)) diff --git a/third_party/mbedtls/aes.c b/third_party/mbedtls/aes.c index 797a4d90a..6f63c16ca 100644 --- a/third_party/mbedtls/aes.c +++ b/third_party/mbedtls/aes.c @@ -15,10 +15,14 @@ │ See the License for the specific language governing permissions and │ │ limitations under the License. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "third_party/mbedtls/aes.h" #include "libc/intrin/bits.h" #include "libc/nexgen32e/x86feature.h" +#include "libc/runtime/runtime.h" #include "libc/str/str.h" -#include "third_party/mbedtls/aes.h" +#include "libc/sysv/consts/auxv.h" +#include "libc/sysv/consts/hwcap.h" +#include "third_party/mbedtls/aesce.h" #include "third_party/mbedtls/aesni.h" #include "third_party/mbedtls/common.h" #include "third_party/mbedtls/error.h" @@ -471,6 +475,26 @@ static dontinline void aes_gen_tables( void ) #endif /* MBEDTLS_AES_FEWER_TABLES */ +int mbedtls_aes_uses_hardware( void ) +{ +#ifdef __x86_64__ + return( X86_HAVE( AES ) ); +#else + static char once; + static char result; + if( !once ) + { + unsigned long auxval; + auxval = getauxval( AT_HWCAP ); + result = ( !auxval || + (auxval & ( HWCAP_ASIMD | HWCAP_AES ) ) == + ( HWCAP_ASIMD | HWCAP_AES ) ); + once = 1; + } + return( result ); +#endif +} + void mbedtls_aes_init( mbedtls_aes_context *ctx ) { AES_VALIDATE( ctx != NULL ); @@ -535,8 +559,12 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, #endif ctx->rk = RK = ctx->buf; #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - if( X86_HAVE( AES ) ) + if( mbedtls_aes_uses_hardware() ) return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); +#endif +#if defined(MBEDTLS_AESCE_C) && defined(__aarch64__) + if( mbedtls_aes_uses_hardware() ) + return( mbedtls_aesce_setkey_enc( (unsigned char *) RK, key, keybits ) ); #endif for( i = 0; i < ( keybits >> 5 ); i++ ) { @@ -603,7 +631,7 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, */ #if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ) + unsigned int keybits ) { int i, j, ret; mbedtls_aes_context cty; @@ -625,10 +653,18 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, goto exit; ctx->nr = cty.nr; #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - if( X86_HAVE( AES ) ) + if( mbedtls_aes_uses_hardware() ) { mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, - (const unsigned char *) cty.rk, ctx->nr ); + (const unsigned char *) cty.rk, ctx->nr ); + goto exit; + } +#endif +#if defined(MBEDTLS_AESCE_C) && defined(__aarch64__) + if( mbedtls_aes_uses_hardware() ) + { + mbedtls_aesce_inverse_key( (unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr ); goto exit; } #endif @@ -887,9 +923,13 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || mode == MBEDTLS_AES_DECRYPT ); #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - if( X86_HAVE( AES ) ) + if( mbedtls_aes_uses_hardware() ) return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); #endif +#if defined(MBEDTLS_AESCE_C) && defined(__aarch64__) + if( mbedtls_aes_uses_hardware() ) + return mbedtls_aesce_crypt_ecb( ctx, mode, input, output ); +#endif #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) if( aes_padlock_ace ) { diff --git a/third_party/mbedtls/aes.h b/third_party/mbedtls/aes.h index fcc859138..5b17ec5f6 100644 --- a/third_party/mbedtls/aes.h +++ b/third_party/mbedtls/aes.h @@ -46,12 +46,14 @@ mbedtls_aes_context; typedef struct mbedtls_aes_xts_context { mbedtls_aes_context crypt; /*!< The AES context to use for AES block - encryption or decryption. */ + encryption or decryption. */ mbedtls_aes_context tweak; /*!< The AES context used for tweak - computation. */ + computation. */ } mbedtls_aes_xts_context; #endif /* MBEDTLS_CIPHER_MODE_XTS */ +int mbedtls_aes_uses_hardware( void ); + /** * \brief This function initializes the specified AES context. * diff --git a/third_party/mbedtls/aesce.c b/third_party/mbedtls/aesce.c new file mode 100644 index 000000000..9d2779e95 --- /dev/null +++ b/third_party/mbedtls/aesce.c @@ -0,0 +1,412 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright The Mbed TLS Contributors │ +│ │ +│ 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 │ +│ │ +│ http://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 "third_party/mbedtls/aesce.h" +#include "libc/str/str.h" +#include "third_party/aarch64/arm_neon.internal.h" + +asm(".ident\t\"\\n\\n\ +Mbed TLS (Apache 2.0)\\n\ +Copyright ARM Limited\\n\ +Copyright Mbed TLS Contributors\""); +asm(".include \"libc/disclaimer.inc\""); +// clang-format off + +/* + * Armv8-A Cryptographic Extension support functions for Aarch64 + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * 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 + * + * http://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. + */ + +#if defined(__aarch64__) && !defined(__ARM_FEATURE_CRYPTO) && \ + defined(__clang__) && __clang_major__ >= 4 +/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged. + * + * The intrinsic declaration are guarded by predefined ACLE macros in clang: + * these are normally only enabled by the -march option on the command line. + * By defining the macros ourselves we gain access to those declarations without + * requiring -march on the command line. + * + * `arm_neon.h` could be included by any header file, so we put these defines + * at the top of this file, before any includes. + */ +#define __ARM_FEATURE_CRYPTO 1 +/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions + * + * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it + * for older compilers. + */ +#define __ARM_FEATURE_AES 1 +#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG +#endif + +#if defined(MBEDTLS_AESCE_C) + +#ifdef __aarch64__ + +#if !defined(__ARM_FEATURE_AES) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG) +# if defined(__clang__) +# if __clang_major__ < 4 +# error "A more recent Clang is required for MBEDTLS_AESCE_C" +# endif +# pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function) +# define MBEDTLS_POP_TARGET_PRAGMA +# elif defined(__GNUC__) +# if __GNUC__ < 6 +# error "A more recent GCC is required for MBEDTLS_AESCE_C" +# endif +# pragma GCC push_options +# pragma GCC target ("arch=armv8-a+crypto") +# define MBEDTLS_POP_TARGET_PRAGMA +# else +# error "Only GCC and Clang supported for MBEDTLS_AESCE_C" +# endif +#endif /* !__ARM_FEATURE_AES || MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */ + +static uint8x16_t aesce_encrypt_block(uint8x16_t block, + unsigned char *keys, + int rounds) +{ + for (int i = 0; i < rounds - 1; i++) { + /* AES AddRoundKey, SubBytes, ShiftRows (in this order). + * AddRoundKey adds the round key for the previous round. */ + block = vaeseq_u8(block, vld1q_u8(keys + i * 16)); + /* AES mix columns */ + block = vaesmcq_u8(block); + } + + /* AES AddRoundKey for the previous round. + * SubBytes, ShiftRows for the final round. */ + block = vaeseq_u8(block, vld1q_u8(keys + (rounds -1) * 16)); + + /* Final round: no MixColumns */ + + /* Final AddRoundKey */ + block = veorq_u8(block, vld1q_u8(keys + rounds * 16)); + + return block; +} + +static uint8x16_t aesce_decrypt_block(uint8x16_t block, + unsigned char *keys, + int rounds) +{ + + for (int i = 0; i < rounds - 1; i++) { + /* AES AddRoundKey, SubBytes, ShiftRows */ + block = vaesdq_u8(block, vld1q_u8(keys + i * 16)); + /* AES inverse MixColumns for the next round. + * + * This means that we switch the order of the inverse AddRoundKey and + * inverse MixColumns operations. We have to do this as AddRoundKey is + * done in an atomic instruction together with the inverses of SubBytes + * and ShiftRows. + * + * It works because MixColumns is a linear operation over GF(2^8) and + * AddRoundKey is an exclusive or, which is equivalent to addition over + * GF(2^8). (The inverse of MixColumns needs to be applied to the + * affected round keys separately which has been done when the + * decryption round keys were calculated.) */ + block = vaesimcq_u8(block); + } + + /* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the + * last full round. */ + block = vaesdq_u8(block, vld1q_u8(keys + (rounds - 1) * 16)); + + /* Inverse AddRoundKey for inverting the initial round key addition. */ + block = veorq_u8(block, vld1q_u8(keys + rounds * 16)); + + return block; +} + +/* + * AES-ECB block en(de)cryption + */ +int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]) +{ + uint8x16_t block = vld1q_u8(&input[0]); + unsigned char *keys = (unsigned char *) (ctx->rk); + + if (mode == MBEDTLS_AES_ENCRYPT) { + block = aesce_encrypt_block(block, keys, ctx->nr); + } else { + block = aesce_decrypt_block(block, keys, ctx->nr); + } + vst1q_u8(&output[0], block); + + return 0; +} + +/* + * Compute decryption round keys from encryption round keys + */ +void mbedtls_aesce_inverse_key(unsigned char *invkey, + const unsigned char *fwdkey, + int nr) +{ + int i, j; + j = nr; + vst1q_u8(invkey, vld1q_u8(fwdkey + j * 16)); + for (i = 1, j--; j > 0; i++, j--) { + vst1q_u8(invkey + i * 16, + vaesimcq_u8(vld1q_u8(fwdkey + j * 16))); + } + vst1q_u8(invkey + i * 16, vld1q_u8(fwdkey + j * 16)); + +} + +static inline uint32_t aes_rot_word(uint32_t word) +{ + return (word << (32 - 8)) | (word >> 8); +} + +static inline uint32_t aes_sub_word(uint32_t in) +{ + uint8x16_t v = vreinterpretq_u8_u32(vdupq_n_u32(in)); + uint8x16_t zero = vdupq_n_u8(0); + + /* vaeseq_u8 does both SubBytes and ShiftRows. Taking the first row yields + * the correct result as ShiftRows doesn't change the first row. */ + v = vaeseq_u8(zero, v); + return vgetq_lane_u32(vreinterpretq_u32_u8(v), 0); +} + +/* + * Key expansion function + */ +static void aesce_setkey_enc(unsigned char *rk, + const unsigned char *key, + const size_t key_bit_length) +{ + static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36 }; + /* See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf + * - Section 5, Nr = Nk + 6 + * - Section 5.2, the length of round keys is Nb*(Nr+1) + */ + const uint32_t key_len_in_words = key_bit_length / 32; /* Nk */ + const size_t round_key_len_in_words = 4; /* Nb */ + const size_t rounds_needed = key_len_in_words + 6; /* Nr */ + const size_t round_keys_len_in_words = + round_key_len_in_words * (rounds_needed + 1); /* Nb*(Nr+1) */ + const uint32_t *rko_end = (uint32_t *) rk + round_keys_len_in_words; + + memcpy(rk, key, key_len_in_words * 4); + + for (uint32_t *rki = (uint32_t *) rk; + rki + key_len_in_words < rko_end; + rki += key_len_in_words) { + + size_t iteration = (rki - (uint32_t *) rk) / key_len_in_words; + uint32_t *rko; + rko = rki + key_len_in_words; + rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1])); + rko[0] ^= rcon[iteration] ^ rki[0]; + rko[1] = rko[0] ^ rki[1]; + rko[2] = rko[1] ^ rki[2]; + rko[3] = rko[2] ^ rki[3]; + if (rko + key_len_in_words > rko_end) { + /* Do not write overflow words.*/ + continue; + } + switch (key_bit_length) { + case 128: + break; + case 192: + rko[4] = rko[3] ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + break; + case 256: + rko[4] = aes_sub_word(rko[3]) ^ rki[4]; + rko[5] = rko[4] ^ rki[5]; + rko[6] = rko[5] ^ rki[6]; + rko[7] = rko[6] ^ rki[7]; + break; + } + } +} + +/* + * Key expansion, wrapper + */ +int mbedtls_aesce_setkey_enc(unsigned char *rk, + const unsigned char *key, + size_t bits) +{ + switch (bits) { + case 128: + case 192: + case 256: + aesce_setkey_enc(rk, key, bits); + break; + default: + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + return 0; +} + +#if defined(MBEDTLS_GCM_C) + +#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ == 5 +/* Some intrinsics are not available for GCC 5.X. */ +#define vreinterpretq_p64_u8(a) ((poly64x2_t) a) +#define vreinterpretq_u8_p128(a) ((uint8x16_t) a) +static inline poly64_t vget_low_p64(poly64x2_t __a) +{ + uint64x2_t tmp = (uint64x2_t) (__a); + uint64x1_t lo = vcreate_u64(vgetq_lane_u64(tmp, 0)); + return (poly64_t) (lo); +} +#endif /* !__clang__ && __GNUC__ && __GNUC__ == 5*/ + +/* vmull_p64/vmull_high_p64 wrappers. + * + * Older compilers miss some intrinsic functions for `poly*_t`. We use + * uint8x16_t and uint8x16x3_t as input/output parameters. + */ +static inline uint8x16_t pmull_low(uint8x16_t a, uint8x16_t b) +{ + return vreinterpretq_u8_p128( + vmull_p64( + (poly64_t) vget_low_p64(vreinterpretq_p64_u8(a)), + (poly64_t) vget_low_p64(vreinterpretq_p64_u8(b)))); +} + +static inline uint8x16_t pmull_high(uint8x16_t a, uint8x16_t b) +{ + return vreinterpretq_u8_p128( + vmull_high_p64(vreinterpretq_p64_u8(a), + vreinterpretq_p64_u8(b))); +} + +/* GHASH does 128b polynomial multiplication on block in GF(2^128) defined by + * `x^128 + x^7 + x^2 + x + 1`. + * + * Arm64 only has 64b->128b polynomial multipliers, we need to do 4 64b + * multiplies to generate a 128b. + * + * `poly_mult_128` executes polynomial multiplication and outputs 256b that + * represented by 3 128b due to code size optimization. + * + * Output layout: + * | | | | + * |------------|-------------|-------------| + * | ret.val[0] | h3:h2:00:00 | high 128b | + * | ret.val[1] | :m2:m1:00 | middle 128b | + * | ret.val[2] | : :l1:l0 | low 128b | + */ +static inline uint8x16x3_t poly_mult_128(uint8x16_t a, uint8x16_t b) +{ + uint8x16x3_t ret; + uint8x16_t h, m, l; /* retval high/middle/low */ + uint8x16_t c, d, e; + + h = pmull_high(a, b); /* h3:h2:00:00 = a1*b1 */ + l = pmull_low(a, b); /* : :l1:l0 = a0*b0 */ + c = vextq_u8(b, b, 8); /* :c1:c0 = b0:b1 */ + d = pmull_high(a, c); /* :d2:d1:00 = a1*b0 */ + e = pmull_low(a, c); /* :e2:e1:00 = a0*b1 */ + m = veorq_u8(d, e); /* :m2:m1:00 = d + e */ + + ret.val[0] = h; + ret.val[1] = m; + ret.val[2] = l; + return ret; +} + +/* + * Modulo reduction. + * + * See: https://www.researchgate.net/publication/285612706_Implementing_GCM_on_ARMv8 + * + * Section 4.3 + * + * Modular reduction is slightly more complex. Write the GCM modulus as f(z) = + * z^128 +r(z), where r(z) = z^7+z^2+z+ 1. The well known approach is to + * consider that z^128 ≡r(z) (mod z^128 +r(z)), allowing us to write the 256-bit + * operand to be reduced as a(z) = h(z)z^128 +l(z)≡h(z)r(z) + l(z). That is, we + * simply multiply the higher part of the operand by r(z) and add it to l(z). If + * the result is still larger than 128 bits, we reduce again. + */ +static inline uint8x16_t poly_mult_reduce(uint8x16x3_t input) +{ + uint8x16_t const ZERO = vdupq_n_u8(0); + /* use 'asm' as an optimisation barrier to prevent loading MODULO from memory */ + uint64x2_t r = vreinterpretq_u64_u8(vdupq_n_u8(0x87)); + asm ("" : "+w" (r)); + uint8x16_t const MODULO = vreinterpretq_u8_u64(vshrq_n_u64(r, 64 - 8)); + uint8x16_t h, m, l; /* input high/middle/low 128b */ + uint8x16_t c, d, e, f, g, n, o; + h = input.val[0]; /* h3:h2:00:00 */ + m = input.val[1]; /* :m2:m1:00 */ + l = input.val[2]; /* : :l1:l0 */ + c = pmull_high(h, MODULO); /* :c2:c1:00 = reduction of h3 */ + d = pmull_low(h, MODULO); /* : :d1:d0 = reduction of h2 */ + e = veorq_u8(c, m); /* :e2:e1:00 = m2:m1:00 + c2:c1:00 */ + f = pmull_high(e, MODULO); /* : :f1:f0 = reduction of e2 */ + g = vextq_u8(ZERO, e, 8); /* : :g1:00 = e1:00 */ + n = veorq_u8(d, l); /* : :n1:n0 = d1:d0 + l1:l0 */ + o = veorq_u8(n, f); /* o1:o0 = f1:f0 + n1:n0 */ + return veorq_u8(o, g); /* = o1:o0 + g1:00 */ +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + */ +void mbedtls_aesce_gcm_mult(unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16]) +{ + uint8x16_t va, vb, vc; + va = vrbitq_u8(vld1q_u8(&a[0])); + vb = vrbitq_u8(vld1q_u8(&b[0])); + vc = vrbitq_u8(poly_mult_reduce(poly_mult_128(va, vb))); + vst1q_u8(&c[0], vc); +} + +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_POP_TARGET_PRAGMA) +#if defined(__clang__) +#pragma clang attribute pop +#elif defined(__GNUC__) +#pragma GCC pop_options +#endif +#undef MBEDTLS_POP_TARGET_PRAGMA +#endif + +#endif /* MBEDTLS_HAVE_ARM64 */ + +#endif /* MBEDTLS_AESCE_C */ diff --git a/third_party/mbedtls/aesce.h b/third_party/mbedtls/aesce.h new file mode 100644 index 000000000..88a56d49d --- /dev/null +++ b/third_party/mbedtls/aesce.h @@ -0,0 +1,62 @@ +#ifndef COSMOPOLITAN_THIRD_PARTY_MBEDTLS_AESCE_H_ +#define COSMOPOLITAN_THIRD_PARTY_MBEDTLS_AESCE_H_ +#include "third_party/mbedtls/aes.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +/** + * \brief Internal AES-ECB block encryption and decryption + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx, int mode, + const unsigned char input[16], + unsigned char output[16]); + +/** + * \brief Internal GCM multiplication: c = a * b in GF(2^128) + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void mbedtls_aesce_gcm_mult(unsigned char c[16], const unsigned char a[16], + const unsigned char b[16]); + +/** + * \brief Internal round key inversion. This function computes + * decryption round keys from the encryption round keys. + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void mbedtls_aesce_inverse_key(unsigned char *invkey, + const unsigned char *fwdkey, int nr); + +/** + * \brief Internal key expansion for encryption + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aesce_setkey_enc(unsigned char *rk, const unsigned char *key, + size_t bits); + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_THIRD_PARTY_MBEDTLS_AESCE_H_ */ diff --git a/third_party/mbedtls/config.h b/third_party/mbedtls/config.h index c337dfd99..bb1fa25ec 100644 --- a/third_party/mbedtls/config.h +++ b/third_party/mbedtls/config.h @@ -26,11 +26,9 @@ /* ciphers */ #define MBEDTLS_AES_C -#ifndef TINY #define MBEDTLS_CHACHA20_C #define MBEDTLS_POLY1305_C #define MBEDTLS_CHACHAPOLY_C -#endif #ifdef MBEDTLS_SSL_PROTO_TLS1 #define MBEDTLS_DES_C #endif @@ -58,9 +56,9 @@ #define MBEDTLS_ECDSA_C #define MBEDTLS_ECDSA_DETERMINISTIC #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -#ifndef TINY #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED #define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED +#ifndef TINY #define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED #define MBEDTLS_DHM_C #define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED @@ -73,8 +71,8 @@ /* eliptic curves */ #define MBEDTLS_ECP_DP_SECP256R1_ENABLED #define MBEDTLS_ECP_DP_SECP384R1_ENABLED -#ifndef TINY #define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#ifndef TINY #define MBEDTLS_ECP_DP_CURVE448_ENABLED /*#define MBEDTLS_ECP_DP_SECP521R1_ENABLED*/ /*#define MBEDTLS_ECP_DP_BP384R1_ENABLED*/ @@ -103,10 +101,9 @@ * Hardens against against sbox side channels */ #define MBEDTLS_AESNI_C -#if defined(__x86_64__) && !defined(TINY) +#define MBEDTLS_AESCE_C #define MBEDTLS_HAVE_X86_64 #define MBEDTLS_HAVE_SSE2 -#endif #ifndef TINY /* diff --git a/third_party/mbedtls/describecode.c b/third_party/mbedtls/describecode.c new file mode 100644 index 000000000..be3e56dbe --- /dev/null +++ b/third_party/mbedtls/describecode.c @@ -0,0 +1,40 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2023 Justine Alexandra Roberts Tunney │ +│ │ +│ 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 "libc/fmt/itoa.h" +#include "libc/str/str.h" +#include "third_party/mbedtls/iana.h" + +const char *DescribeMbedtlsErrorCode(int ret) { + static _Thread_local char sslerr[64]; + char *p = sslerr; + p = stpcpy(p, "mbedtls error code "); + if (-ret <= 0xffffu) { + *p++ = '-'; + *p++ = '0'; + *p++ = 'x'; + *p++ = "0123456789abcdef"[(-ret & 0xf000) >> 12]; + *p++ = "0123456789abcdef"[(-ret & 0x0f00) >> 8]; + *p++ = "0123456789abcdef"[(-ret & 0x00f0) >> 4]; + *p++ = "0123456789abcdef"[(-ret & 0x000f) >> 0]; + *p = 0; + } else { + FormatInt32(p, ret); + } + return sslerr; +} diff --git a/third_party/mbedtls/getalertdescription.c b/third_party/mbedtls/getalertdescription.c index e86d40c12..a126be5e1 100644 --- a/third_party/mbedtls/getalertdescription.c +++ b/third_party/mbedtls/getalertdescription.c @@ -1,4 +1,4 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:4;coding:utf-8 -*-│ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:2;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright The Mbed TLS Contributors │ @@ -24,7 +24,7 @@ * @see RFC5246 §7.2 */ const char *GetAlertDescription(unsigned char x) { - static char buf[21]; + static _Thread_local char buf[21]; switch (x) { case MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY: /* 0 */ return "close_notify"; diff --git a/third_party/mbedtls/iana.h b/third_party/mbedtls/iana.h index 26e6fdc6e..3b01644eb 100644 --- a/third_party/mbedtls/iana.h +++ b/third_party/mbedtls/iana.h @@ -6,8 +6,10 @@ COSMOPOLITAN_C_START_ bool IsCipherSuiteGood(uint16_t); const char *GetCipherSuiteName(uint16_t); +const char *DescribeMbedtlsErrorCode(int); const char *GetAlertDescription(unsigned char); dontdiscard char *FormatSslClientCiphers(const mbedtls_ssl_context *); +const char *DescribeSslClientHandshakeError(const mbedtls_ssl_context *, int); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/third_party/mbedtls/mbedtls.mk b/third_party/mbedtls/mbedtls.mk index 3a493d64e..2e25a334d 100644 --- a/third_party/mbedtls/mbedtls.mk +++ b/third_party/mbedtls/mbedtls.mk @@ -25,14 +25,12 @@ THIRD_PARTY_MBEDTLS_A_DIRECTDEPS = \ LIBC_NEXGEN32E \ LIBC_RUNTIME \ LIBC_SOCK \ - LIBC_LOG \ LIBC_STDIO \ LIBC_STR \ LIBC_SYSV \ LIBC_TIME \ NET_HTTP \ THIRD_PARTY_COMPILER_RT \ - THIRD_PARTY_GDTOA \ THIRD_PARTY_ZLIB THIRD_PARTY_MBEDTLS_A_DEPS := \ diff --git a/third_party/mbedtls/sha1.c b/third_party/mbedtls/sha1.c index c8e172461..aaeb23bac 100644 --- a/third_party/mbedtls/sha1.c +++ b/third_party/mbedtls/sha1.c @@ -15,6 +15,7 @@ │ See the License for the specific language governing permissions and │ │ limitations under the License. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "third_party/mbedtls/sha1.h" #include "libc/intrin/asan.internal.h" #include "libc/intrin/bits.h" #include "libc/macros.internal.h" @@ -26,7 +27,6 @@ #include "third_party/mbedtls/error.h" #include "third_party/mbedtls/md.h" #include "third_party/mbedtls/platform.h" -#include "third_party/mbedtls/sha1.h" asm(".ident\t\"\\n\\n\ Mbed TLS (Apache 2.0)\\n\ @@ -115,30 +115,27 @@ int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, SHA1_VALIDATE_RET( ctx != NULL ); SHA1_VALIDATE_RET( (const unsigned char *)data != NULL ); - if( !IsTiny() || X86_NEED( SHA ) ) + if( X86_HAVE( SHA ) ) { - if( X86_HAVE( SHA ) ) + if( IsAsan() ) { - if( IsAsan() ) - { - __asan_verify( data, 64 ); - __asan_verify( ctx, sizeof(*ctx) ); - } - sha1_transform_ni( ctx->state, data, 1 ); - return( 0 ); + __asan_verify( data, 64 ); + __asan_verify( ctx, sizeof(*ctx) ); } - if( X86_HAVE( BMI ) && - X86_HAVE( BMI2 ) && - X86_HAVE( AVX2 ) ) + sha1_transform_ni( ctx->state, data, 1 ); + return( 0 ); + } + if( X86_HAVE( BMI ) && + X86_HAVE( BMI2 ) && + X86_HAVE( AVX2 ) ) + { + if( IsAsan() ) { - if( IsAsan() ) - { - __asan_verify( data, 64 ); - __asan_verify( ctx, sizeof(*ctx) ); - } - sha1_transform_avx2( ctx->state, data, 1 ); - return( 0 ); + __asan_verify( data, 64 ); + __asan_verify( ctx, sizeof(*ctx) ); } + sha1_transform_avx2( ctx->state, data, 1 ); + return( 0 ); } #ifdef MBEDTLS_SHA1_SMALLER @@ -413,7 +410,7 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, if( ilen >= 64 ) { - if( ( !IsTiny() || X86_NEED(SHA) ) && X86_HAVE( SHA ) ) + if( X86_HAVE( SHA ) ) { if( IsAsan() ) __asan_verify( input, ilen ); @@ -421,8 +418,7 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, input += ROUNDDOWN( ilen, 64 ); ilen -= ROUNDDOWN( ilen, 64 ); } - else if( !IsTiny() && - X86_HAVE( BMI ) && + else if( X86_HAVE( BMI ) && X86_HAVE( BMI2 ) && X86_HAVE( AVX2 ) ) { diff --git a/third_party/mbedtls/sha256.c b/third_party/mbedtls/sha256.c index 3666dfd8b..c36efb939 100644 --- a/third_party/mbedtls/sha256.c +++ b/third_party/mbedtls/sha256.c @@ -172,26 +172,23 @@ int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, SHA256_VALIDATE_RET( ctx != NULL ); SHA256_VALIDATE_RET( (const unsigned char *)data != NULL ); - if( !IsTiny() || X86_NEED( SHA ) ) + if( X86_HAVE( SHA ) && + X86_HAVE( SSE2 ) && + X86_HAVE( SSSE3 ) ) { - if( X86_HAVE( SHA ) && - X86_HAVE( SSE2 ) && - X86_HAVE( SSSE3 ) ) - { - if( IsAsan() ) - __asan_verify( data, 64 ); - sha256_transform_ni( ctx->state, data, 1 ); - return( 0 ); - } - if( X86_HAVE( BMI2 ) && - X86_HAVE( AVX ) && - X86_HAVE( AVX2 ) ) - { - if( IsAsan() ) - __asan_verify( data, 64 ); - sha256_transform_rorx( ctx->state, data, 1 ); - return( 0 ); - } + if( IsAsan() ) + __asan_verify( data, 64 ); + sha256_transform_ni( ctx->state, data, 1 ); + return( 0 ); + } + if( X86_HAVE( BMI2 ) && + X86_HAVE( AVX ) && + X86_HAVE( AVX2 ) ) + { + if( IsAsan() ) + __asan_verify( data, 64 ); + sha256_transform_rorx( ctx->state, data, 1 ); + return( 0 ); } for( i = 0; i < 8; i++ ) @@ -311,8 +308,7 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, if( ilen >= 64 ) { - if( !IsTiny() && - X86_HAVE( SHA ) && + if( X86_HAVE( SHA ) && X86_HAVE( SSE2 ) && X86_HAVE( SSSE3 ) ) { @@ -322,8 +318,7 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, input += ROUNDDOWN( ilen, 64 ); ilen -= ROUNDDOWN( ilen, 64 ); } - else if( !IsTiny() && - X86_HAVE( BMI ) && + else if( X86_HAVE( BMI ) && X86_HAVE( BMI2 ) && X86_HAVE( AVX2 ) ) { diff --git a/third_party/mbedtls/shakedescription.c b/third_party/mbedtls/shakedescription.c new file mode 100644 index 000000000..7129c329e --- /dev/null +++ b/third_party/mbedtls/shakedescription.c @@ -0,0 +1,98 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2023 Justine Alexandra Roberts Tunney │ +│ │ +│ 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 "third_party/mbedtls/iana.h" +#include "third_party/mbedtls/net_sockets.h" +#include "third_party/mbedtls/ssl.h" +#include "third_party/mbedtls/x509.h" + +const char *DescribeSslClientHandshakeError(const mbedtls_ssl_context *ssl, + int ret) { + switch (ret) { + case MBEDTLS_ERR_SSL_CONN_EOF: + return "connection eof"; + case MBEDTLS_ERR_NET_CONN_RESET: + return "connection reset"; + case MBEDTLS_ERR_SSL_TIMEOUT: + return "ssl timeout"; + case MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN: + return "no cipher chosen"; + case MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE: + return "no usable ciphersuite"; + case MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION: + return "bad ssl version"; + case MBEDTLS_ERR_SSL_INVALID_MAC: + return "bad ssl mac"; + case MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE: + return "bad key exchange"; + case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: + switch (ssl->session_negotiate->verify_result) { + case MBEDTLS_X509_BADCERT_EXPIRED: + return "the certificate validity has expired"; + case MBEDTLS_X509_BADCERT_REVOKED: + return "the certificate has been revoked (is on a crl)"; + case MBEDTLS_X509_BADCERT_CN_MISMATCH: + return "the certificate common name (cn) does not match with the " + "expected cn"; + case MBEDTLS_X509_BADCERT_NOT_TRUSTED: + return "the certificate is not correctly signed by the trusted ca"; + case MBEDTLS_X509_BADCRL_NOT_TRUSTED: + return "the crl is not correctly signed by the trusted ca"; + case MBEDTLS_X509_BADCRL_EXPIRED: + return "the crl is expired"; + case MBEDTLS_X509_BADCERT_MISSING: + return "certificate was missing"; + case MBEDTLS_X509_BADCERT_SKIP_VERIFY: + return "certificate verification was skipped"; + case MBEDTLS_X509_BADCERT_OTHER: + return "other reason (can be used by verify callback)"; + case MBEDTLS_X509_BADCERT_FUTURE: + return "the certificate validity starts in the future"; + case MBEDTLS_X509_BADCRL_FUTURE: + return "the crl is from the future"; + case MBEDTLS_X509_BADCERT_KEY_USAGE: + return "usage does not match the keyusage extension"; + case MBEDTLS_X509_BADCERT_EXT_KEY_USAGE: + return "usage does not match the extendedkeyusage extension"; + case MBEDTLS_X509_BADCERT_NS_CERT_TYPE: + return "usage does not match the nscerttype extension"; + case MBEDTLS_X509_BADCERT_BAD_MD: + return "the certificate is signed with an unacceptable hash"; + case MBEDTLS_X509_BADCERT_BAD_PK: + return "the certificate is signed with an unacceptable pk alg (eg " + "rsa vs ecdsa)"; + case MBEDTLS_X509_BADCERT_BAD_KEY: + return "the certificate is signed with an unacceptable key (eg bad " + "curve, rsa too short)"; + case MBEDTLS_X509_BADCRL_BAD_MD: + return "the crl is signed with an unacceptable hash"; + case MBEDTLS_X509_BADCRL_BAD_PK: + return "the crl is signed with an unacceptable pk alg (eg rsa vs " + "ecdsa)"; + case MBEDTLS_X509_BADCRL_BAD_KEY: + return "the crl is signed with an unacceptable key (eg bad curve, " + "rsa too short)"; + default: + return "verification failed"; + } + case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: + return GetAlertDescription(ssl->fatal_alert); + default: + return DescribeMbedtlsErrorCode(ret); + } +} diff --git a/third_party/mbedtls/ssl_ciphersuites.c b/third_party/mbedtls/ssl_ciphersuites.c index 82e71b1e8..31db8030d 100644 --- a/third_party/mbedtls/ssl_ciphersuites.c +++ b/third_party/mbedtls/ssl_ciphersuites.c @@ -15,12 +15,16 @@ │ See the License for the specific language governing permissions and │ │ limitations under the License. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "third_party/mbedtls/ssl_ciphersuites.h" #include "libc/nexgen32e/x86feature.h" +#include "libc/runtime/runtime.h" +#include "libc/sysv/consts/auxv.h" +#include "libc/sysv/consts/hwcap.h" +#include "third_party/mbedtls/aes.h" #include "third_party/mbedtls/cipher.h" #include "third_party/mbedtls/common.h" #include "third_party/mbedtls/platform.h" #include "third_party/mbedtls/ssl.h" -#include "third_party/mbedtls/ssl_ciphersuites.h" asm(".ident\t\"\\n\\n\ Mbed TLS (Apache 2.0)\\n\ @@ -1500,7 +1504,7 @@ const uint16_t *mbedtls_ssl_list_ciphersuites( void ) const uint16_t *p; uint16_t *q; - if( X86_HAVE( AES ) ) + if( mbedtls_aes_uses_hardware() ) p = ciphersuite_preference; else p = ciphersuite_preference_nehalem; diff --git a/third_party/mbedtls/ssl_msg.c b/third_party/mbedtls/ssl_msg.c index baa129a0b..6aaa1e991 100644 --- a/third_party/mbedtls/ssl_msg.c +++ b/third_party/mbedtls/ssl_msg.c @@ -5060,7 +5060,7 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) if( ssl->in_msglen != 1 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %" MBEDTLS_PRINTF_SIZET, - ssl->in_msglen ) ); + ssl->in_msglen ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } @@ -5096,7 +5096,7 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) to be packed in a single message, but Mbed TLS doesn't currently support this. */ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %" MBEDTLS_PRINTF_SIZET, - ssl->in_msglen ) ); + ssl->in_msglen ) ); return( MBEDTLS_ERR_SSL_INVALID_RECORD ); } diff --git a/third_party/zstd/programs/util.c b/third_party/zstd/programs/util.c index a966f3cc0..ee10cad4a 100644 --- a/third_party/zstd/programs/util.c +++ b/third_party/zstd/programs/util.c @@ -1683,7 +1683,7 @@ int UTIL_countCores(int logical) return numCores; } -#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__CYGWIN__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__CYGWIN__) || defined(__COSMOPOLITAN__) /* Use POSIX sysconf * see: man 3 sysconf */ diff --git a/third_party/zstd/programs/zstdcli.c b/third_party/zstd/programs/zstdcli.c index fdf323680..a1e6ffbaa 100644 --- a/third_party/zstd/programs/zstdcli.c +++ b/third_party/zstd/programs/zstdcli.c @@ -56,6 +56,7 @@ #include "libc/stdio/temp.h" #include "third_party/musl/tempnam.h" /* fprintf(), stdin, stdout, stderr */ #include "libc/errno.h" /* errno */ +#include "libc/runtime/runtime.h" #include "libc/assert.h" /* assert */ #include "third_party/zstd/programs/fileio.h" /* stdinmark, stdoutmark, ZSTD_EXTENSION */ @@ -853,6 +854,10 @@ typedef enum { zom_compress, zom_decompress, zom_test, zom_bench, zom_train, zom int main(int argCount, const char* argv[]) { +#ifndef NDEBUG + ShowCrashReports(); +#endif + int argNb, followLinks = 0, allowBlockDevices = 0, diff --git a/third_party/zstd/zstd.mk b/third_party/zstd/zstd.mk index 91a790845..e7c508cc0 100644 --- a/third_party/zstd/zstd.mk +++ b/third_party/zstd/zstd.mk @@ -110,16 +110,17 @@ THIRD_PARTY_ZSTD_A_CHECKS = \ $(THIRD_PARTY_ZSTD_A_HDRS:%=o/$(MODE)/%.ok) THIRD_PARTY_ZSTD_A_DIRECTDEPS = \ - LIBC_INTRIN \ - LIBC_NEXGEN32E \ - LIBC_STR \ - LIBC_MEM \ - LIBC_STDIO \ - LIBC_TIME \ LIBC_CALLS \ - LIBC_RUNTIME \ LIBC_FMT \ + LIBC_INTRIN \ LIBC_LOG \ + LIBC_MEM \ + LIBC_NEXGEN32E \ + LIBC_RUNTIME \ + LIBC_STDIO \ + LIBC_STR \ + LIBC_THREAD \ + LIBC_TIME \ LIBC_SYSV THIRD_PARTY_ZSTD_A_DEPS := \ @@ -144,6 +145,10 @@ $(THIRD_PARTY_ZSTD_A_OBJS): private \ -Wframe-larger-than=262144 \ -Wno-comment +$(THIRD_PARTY_ZSTD_A_OBJS): private \ + CPPFLAGS += \ + -DZSTD_MULTITHREAD + o/$(MODE)/third_party/zstd/zstd.com.dbg: \ $(THIRD_PARTY_ZSTD) \ o/$(MODE)/third_party/zstd/programs/zstdcli.o \ @@ -151,6 +156,10 @@ o/$(MODE)/third_party/zstd/zstd.com.dbg: \ $(APE_NO_MODIFY_SELF) @$(APELINK) +o/$(MODE)/third_party/zstd/lib/compress/zstd_lazy.o: private \ + CFLAGS += \ + -O3 + o/$(MODE)/third_party/zstd/lib/compress/zstd_lazy.o: \ QUOTA += -C64 diff --git a/tool/ape/ape.c b/tool/ape/ape.c new file mode 100644 index 000000000..56c80360f --- /dev/null +++ b/tool/ape/ape.c @@ -0,0 +1,412 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2023 Justine Alexandra Roberts Tunney │ +│ │ +│ 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 "libc/assert.h" +#include "libc/calls/calls.h" +#include "libc/calls/struct/iovec.h" +#include "libc/calls/struct/timeval.h" +#include "libc/dns/dns.h" +#include "libc/errno.h" +#include "libc/fmt/itoa.h" +#include "libc/fmt/magnumstrs.internal.h" +#include "libc/intrin/kprintf.h" +#include "libc/macros.internal.h" +#include "libc/mem/gc.internal.h" +#include "libc/mem/mem.h" +#include "libc/runtime/runtime.h" +#include "libc/sock/goodsocket.internal.h" +#include "libc/sock/sock.h" +#include "libc/stdio/append.h" +#include "libc/stdio/rand.h" +#include "libc/stdio/stdio.h" +#include "libc/str/slice.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/af.h" +#include "libc/sysv/consts/ipproto.h" +#include "libc/sysv/consts/sig.h" +#include "libc/sysv/consts/sock.h" +#include "net/http/http.h" +#include "net/http/url.h" +#include "net/https/https.h" +#include "third_party/getopt/getopt.internal.h" +#include "third_party/mbedtls/ctr_drbg.h" +#include "third_party/mbedtls/debug.h" +#include "third_party/mbedtls/error.h" +#include "third_party/mbedtls/iana.h" +#include "third_party/mbedtls/net_sockets.h" +#include "third_party/mbedtls/ssl.h" +#include "third_party/mbedtls/x509.h" + +/** + * @fileoverview Downloads HTTP URL to stdout. + */ + +#define HasHeader(H) (!!msg.headers[H].a) +#define HeaderData(H) (p + msg.headers[H].a) +#define HeaderLength(H) (msg.headers[H].b - msg.headers[H].a) +#define HeaderEqualCase(H, S) \ + SlicesEqualCase(S, strlen(S), HeaderData(H), HeaderLength(H)) + +static int sock; +static int outfd; +static const char *prog; +static const char *outpath; + +static wontreturn void PrintUsage(int fd, int rc) { + tinyprint(fd, "usage: ", prog, " [-iksvV] URL\n", NULL); + exit(rc); +} + +static const char *DescribeErrno(void) { + const char *reason; + if (!(reason = _strerdoc(errno))) reason = "Unknown error"; + return reason; +} + +static int GetSslEntropy(void *c, unsigned char *p, size_t n) { + if (getrandom(p, n, 0) != n) { + perror("getrandom"); + exit(1); + } + return 0; +} + +static void OnSslDebug(void *ctx, int level, const char *file, int line, + const char *message) { + char sline[12]; + char slevel[12]; + FormatInt32(sline, line); + FormatInt32(slevel, level); + tinyprint(2, file, ":", sline, ": (", slevel, ") ", message, "\n", NULL); +} + +static void WriteOutput(const void *p, size_t n) { + if (!outfd) { + if (outpath) { + if ((outfd = creat(outpath, 0644)) <= 0) { + perror(outpath); + exit(1); + } + } else { + outfd = 1; + outpath = ""; + } + } + ssize_t rc; + for (size_t i = 0; i < n; i += rc) { + rc = write(outfd, p, n); + if (rc <= 0) { + perror(outpath); + exit(1); + } + } +} + +static int TlsSend(void *c, const unsigned char *p, size_t n) { + int rc; + if ((rc = write(*(int *)c, p, n)) == -1) { + perror("TlsSend"); + exit(1); + } + return rc; +} + +static int TlsRecv(void *c, unsigned char *p, size_t n, uint32_t o) { + int r; + struct iovec v[2]; + static unsigned a, b; + static unsigned char t[4096]; + if (a < b) { + r = MIN(n, b - a); + memcpy(p, t + a, r); + if ((a += r) == b) { + a = b = 0; + } + return r; + } + v[0].iov_base = p; + v[0].iov_len = n; + v[1].iov_base = t; + v[1].iov_len = sizeof(t); + if ((r = readv(*(int *)c, v, 2)) == -1) { + perror("TlsRecv"); + exit(1); + } + if (r > n) { + b = r - n; + } + return MIN(n, r); +} + +int _curl(int argc, char *argv[]) { + + if (!NoDebug()) { + ShowCrashReports(); + } + + prog = argv[0]; + if (!prog) { + prog = "curl"; + } + + /* + * Read flags. + */ + int opt; + while ((opt = getopt(argc, argv, "hV")) != -1) { + switch (opt) { + case 'V': + ++mbedtls_debug_threshold; + break; + case 'h': + PrintUsage(1, 0); + default: + PrintUsage(2, 1); + } + } + + /* + * Get argument. + */ + const char *urlarg; + if (optind == argc) { + tinyprint(2, prog, ": missing url\n", NULL); + PrintUsage(2, 1); + } + urlarg = argv[optind]; + + /* + * Parse URL. + */ + struct Url url; + char *host, *port; + gc(ParseUrl(urlarg, -1, &url, kUrlPlus)); + gc(url.params.p); + if (url.host.n) { + if (url.scheme.n && + !(url.scheme.n == 5 && !memcasecmp(url.scheme.p, "https", 5))) { + tinyprint(2, prog, ": not an https url: ", urlarg, "\n", NULL); + exit(1); + } + host = gc(strndup(url.host.p, url.host.n)); + if (url.port.n) { + port = gc(strndup(url.port.p, url.port.n)); + } else { + port = "443"; + } + } else { + host = "127.0.0.1"; + port = "443"; + } + if (!IsAcceptableHost(host, -1)) { + tinyprint(2, prog, ": invalid host: ", urlarg, "\n", NULL); + exit(1); + } + url.fragment.p = 0, url.fragment.n = 0; + url.scheme.p = 0, url.scheme.n = 0; + url.user.p = 0, url.user.n = 0; + url.pass.p = 0, url.pass.n = 0; + url.host.p = 0, url.host.n = 0; + url.port.p = 0, url.port.n = 0; + if (!url.path.n || url.path.p[0] != '/') { + char *p = gc(malloc(1 + url.path.n)); + mempcpy(mempcpy(p, "/", 1), url.path.p, url.path.n); + url.path.p = p; + ++url.path.n; + } + + char *request = 0; + appendf(&request, + "GET %s HTTP/1.1\r\n" + "Connection: close\r\n" + "User-Agent: ape/1.1\r\n" + "Host: %s:%d\r\n" + "\r\n", + gc(EncodeUrl(&url, 0)), host, port); + + /* + * Perform DNS lookup. + */ + struct addrinfo *addr; + struct addrinfo hints = {.ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + .ai_flags = AI_NUMERICSERV}; + if (getaddrinfo(host, port, &hints, &addr) != EAI_SUCCESS) { + tinyprint(2, prog, ": could not resolve host: ", host, "\n", NULL); + exit(1); + } + + /* + * Connect to server. + */ + int ret; + if ((sock = GoodSocket(addr->ai_family, addr->ai_socktype, addr->ai_protocol, + false, &(struct timeval){-60})) == -1) { + perror("socket"); + exit(1); + } + if (connect(sock, addr->ai_addr, addr->ai_addrlen)) { + tinyprint(2, prog, ": failed to connect to ", host, " port ", port, ": ", + DescribeErrno(), "\n", NULL); + exit(1); + } + freeaddrinfo(addr); + + /* + * Setup crypto. + */ + mbedtls_ssl_config conf; + mbedtls_ssl_context ssl; + mbedtls_ctr_drbg_context drbg; + mbedtls_ssl_init(&ssl); + mbedtls_ctr_drbg_init(&drbg); + mbedtls_ssl_config_init(&conf); + _unassert(!mbedtls_ctr_drbg_seed(&drbg, GetSslEntropy, 0, "justine", 7)); + _unassert(!mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)); + mbedtls_ssl_conf_ca_chain(&conf, GetSslRoots(), 0); + mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &drbg); +#ifndef NDEBUG + mbedtls_ssl_conf_dbg(&conf, OnSslDebug, 0); +#endif + _unassert(!mbedtls_ssl_setup(&ssl, &conf)); + _unassert(!mbedtls_ssl_set_hostname(&ssl, host)); + mbedtls_ssl_set_bio(&ssl, &sock, TlsSend, 0, TlsRecv); + if ((ret = mbedtls_ssl_handshake(&ssl))) { + tinyprint(2, prog, ": ssl negotiation with ", host, + " failed: ", DescribeSslClientHandshakeError(&ssl, ret), "\n", + NULL); + exit(1); + } + + /* + * Send HTTP Message. + */ + ssize_t rc; + size_t i, n; + n = appendz(request).i; + for (i = 0; i < n; i += rc) { + rc = mbedtls_ssl_write(&ssl, request + i, n - i); + if (rc <= 0) { + tinyprint(2, prog, ": ssl send failed: ", DescribeMbedtlsErrorCode(rc), + "\n", NULL); + exit(1); + } + } + + /* + * Handle response. + */ + int t; + char *p; + ssize_t paylen; + size_t g, hdrlen; + struct HttpMessage msg; + struct HttpUnchunker u; + InitHttpMessage(&msg, kHttpResponse); + for (p = 0, hdrlen = paylen = t = i = n = 0;;) { + if (i == n) { + n += 1000; + n += n >> 1; + p = realloc(p, n); + } + if ((rc = mbedtls_ssl_read(&ssl, p + i, n - i)) < 0) { + if (rc == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { + rc = 0; + } else { + tinyprint(2, prog, ": recv failed: ", DescribeMbedtlsErrorCode(rc), + "\n", NULL); + exit(1); + } + } + g = rc; + i += g; + switch (t) { + case kHttpClientStateHeaders: + _unassert(g); + if ((rc = ParseHttpMessage(&msg, p, i)) == -1) { + tinyprint(2, prog, ": ", host, " sent bad http message\n", NULL); + exit(1); + } + if (rc) { + hdrlen = rc; + if (100 <= msg.status && msg.status <= 199) { + DestroyHttpMessage(&msg); + InitHttpMessage(&msg, kHttpResponse); + memmove(p, p + hdrlen, i - hdrlen); + i -= hdrlen; + break; + } + if (msg.status == 204 || msg.status == 304) { + goto Finished; + } + if (!HasHeader(kHttpContentLength) || + (paylen = ParseContentLength(HeaderData(kHttpContentLength), + HeaderLength(kHttpContentLength))) == + -1 || + (HasHeader(kHttpTransferEncoding) && + !HeaderEqualCase(kHttpTransferEncoding, "identity"))) { + tinyprint(2, prog, ": ", host, " sent bad transfer\n", NULL); + exit(1); + } + t = kHttpClientStateBodyLengthed; + if (paylen > i - hdrlen) { + WriteOutput(p + hdrlen, i - hdrlen); + } else { + WriteOutput(p + hdrlen, paylen); + goto Finished; + } + } + break; + case kHttpClientStateBodyLengthed: + _unassert(g); + if (i - hdrlen > paylen) { + g = hdrlen + paylen - (i - g); + } + WriteOutput(p + i - g, g); + if (i - hdrlen >= paylen) { + goto Finished; + } + break; + default: + abort(); + } + } + +/* + * Close connection. + */ +Finished: + if (close(sock)) { + tinyprint(2, prog, ": close failed: ", DescribeErrno(), "\n", NULL); + exit(1); + } + + /* + * Free memory. + */ + mbedtls_ssl_free(&ssl); + mbedtls_ctr_drbg_free(&drbg); + mbedtls_ssl_config_free(&conf); + mbedtls_ctr_drbg_free(&drbg); + free(p); + + return 0; +} diff --git a/tool/ape/ape.mk b/tool/ape/ape.mk new file mode 100644 index 000000000..e7b23e39e --- /dev/null +++ b/tool/ape/ape.mk @@ -0,0 +1,67 @@ +#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ +#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ + +PKGS += TOOL_APE + +TOOL_APE_ARTIFACTS += TOOL_APE_A +TOOL_APE = $(TOOL_APE_DEPS) $(TOOL_APE_A) +TOOL_APE_A = o/$(MODE)/tool/ape/ape.a +TOOL_APE_FILES := $(wildcard tool/ape/*) +TOOL_APE_HDRS = $(filter %.h,$(TOOL_APE_FILES)) +TOOL_APE_INCS = $(filter %.inc,$(TOOL_APE_FILES)) +TOOL_APE_SRCS = $(filter %.c,$(TOOL_APE_FILES)) +TOOL_APE_OBJS = $(TOOL_APE_SRCS:%.c=o/$(MODE)/%.o) + +TOOL_APE_DIRECTDEPS = \ + LIBC_CALLS \ + LIBC_DNS \ + LIBC_FMT \ + LIBC_INTRIN \ + LIBC_LOG \ + LIBC_MEM \ + LIBC_NEXGEN32E \ + LIBC_RUNTIME \ + LIBC_SOCK \ + LIBC_STDIO \ + LIBC_STR \ + LIBC_SYSV \ + LIBC_TIME \ + LIBC_X \ + LIBC_ZIPOS \ + NET_HTTP \ + NET_HTTPS \ + THIRD_PARTY_GETOPT \ + THIRD_PARTY_MBEDTLS + +TOOL_APE_DEPS := \ + $(call uniq,$(foreach x,$(TOOL_APE_DIRECTDEPS),$($(x)))) + +TOOL_APE_CHECKS = \ + $(TOOL_APE_A).pkg \ + $(TOOL_APE_HDRS:%=o/$(MODE)/%.ok) + +$(TOOL_APE_A): \ + tool/ape/ \ + $(TOOL_APE_A).pkg \ + $(TOOL_APE_OBJS) + +$(TOOL_APE_A).pkg: \ + $(TOOL_APE_OBJS) \ + $(foreach x,$(TOOL_APE_DIRECTDEPS),$($(x)_A).pkg) + +o/$(MODE)/tool/ape/ape.com.dbg: \ + $(TOOL_APE) \ + o/$(MODE)/tool/ape/ape.o \ + $(CRT) \ + $(APE_NO_MODIFY_SELF) + @$(APELINK) + +TOOL_APE_LIBS = $(TOOL_APE_A) +TOOL_APE_BINS = $(TOOL_APE_COMS) $(TOOL_APE_COMS:%=%.dbg) +TOOL_APE_COMS = o/$(MODE)/tool/ape/ape.com +$(TOOL_APE_OBJS): $(BUILD_FILES) tool/ape/ape.mk + +.PHONY: o/$(MODE)/tool/ape +o/$(MODE)/tool/ape: \ + $(TOOL_APE_BINS) \ + $(TOOL_APE_CHECKS) diff --git a/tool/ape/zstd.sh b/tool/ape/zstd.sh new file mode 100755 index 000000000..9bda5eebc --- /dev/null +++ b/tool/ape/zstd.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -ex +rm -rf o/samples +make -j16 o//third_party/zstd/zstd.com +o//third_party/zstd/zstd.com --maxdict=524288 -9 -T0 -B4096 --train $(find o//{examples,tool,third_party} -name \*.com) +o//third_party/zstd/zstd.com -9 --ultra -fz o//tool/curl/curl.com +o//third_party/zstd/zstd.com -D dictionary -9 --ultra -fz o//tool/curl/curl.com +o//third_party/zstd/zstd.com -9 --ultra -fz o//examples/hello.com +o//third_party/zstd/zstd.com -D dictionary -9 --ultra -fz o//examples/hello.com +o//third_party/zstd/zstd.com -9 --ultra -fz o//examples/hello2.com +o//third_party/zstd/zstd.com -D dictionary -9 --ultra -fz o//examples/hello2.com +o//third_party/zstd/zstd.com -9 --ultra -fz o//examples/hello3.com +o//third_party/zstd/zstd.com -D dictionary -9 --ultra -fz o//examples/hello3.com diff --git a/tool/build/ar.c b/tool/build/ar.c index 079ba3cec..149697eea 100644 --- a/tool/build/ar.c +++ b/tool/build/ar.c @@ -336,7 +336,6 @@ int main(int argc, char *argv[]) { struct Args args = {reballoc(0, 4096, sizeof(char *))}; struct Args names = {reballoc(0, 4096, sizeof(char *))}; struct Ints modes = {reballoc(0, 4096, sizeof(int))}; - struct Ints longnames = {reballoc(0, 256, sizeof(int))}; struct Ints sizes = {reballoc(0, 4096, sizeof(int))}; struct Ints symnames = {reballoc(0, 16384, sizeof(int))}; struct Bytes symbols = {reballoc(0, 131072, sizeof(char))}; diff --git a/tool/build/assimilate.c b/tool/build/assimilate.c index 7ca2dc82b..ed2a9833c 100644 --- a/tool/build/assimilate.c +++ b/tool/build/assimilate.c @@ -89,7 +89,6 @@ void GetOpts(int argc, char *argv[]) { g_mode = MODE_MACHO; break; case 'h': - case '?': write(1, USAGE, sizeof(USAGE) - 1); exit(0); default: diff --git a/tool/curl/curl.c b/tool/curl/curl.c index 409752b17..4ae79e7c1 100644 --- a/tool/curl/curl.c +++ b/tool/curl/curl.c @@ -7,18 +7,18 @@ │ • http://creativecommons.org/publicdomain/zero/1.0/ │ ╚─────────────────────────────────────────────────────────────────*/ #endif +#include "libc/assert.h" #include "libc/calls/calls.h" #include "libc/calls/struct/iovec.h" -#include "libc/dce.h" +#include "libc/calls/struct/timeval.h" #include "libc/dns/dns.h" #include "libc/errno.h" -#include "libc/fmt/conv.h" -#include "libc/fmt/fmt.h" -#include "libc/intrin/safemacros.internal.h" -#include "libc/log/check.h" -#include "libc/log/log.h" +#include "libc/fmt/itoa.h" +#include "libc/fmt/magnumstrs.internal.h" +#include "libc/intrin/kprintf.h" #include "libc/macros.internal.h" -#include "libc/mem/gc.h" +#include "libc/mem/gc.internal.h" +#include "libc/mem/mem.h" #include "libc/runtime/runtime.h" #include "libc/sock/goodsocket.internal.h" #include "libc/sock/sock.h" @@ -28,31 +28,20 @@ #include "libc/str/slice.h" #include "libc/str/str.h" #include "libc/sysv/consts/af.h" -#include "libc/sysv/consts/dt.h" -#include "libc/sysv/consts/ex.h" -#include "libc/sysv/consts/exit.h" #include "libc/sysv/consts/ipproto.h" -#include "libc/sysv/consts/shut.h" #include "libc/sysv/consts/sig.h" -#include "libc/sysv/consts/so.h" #include "libc/sysv/consts/sock.h" -#include "libc/sysv/consts/sol.h" -#include "libc/sysv/consts/tcp.h" -#include "libc/time/struct/tm.h" -#include "libc/x/x.h" -#include "libc/x/xsigaction.h" #include "net/http/http.h" #include "net/http/url.h" #include "net/https/https.h" -#include "net/https/sslcache.h" #include "third_party/getopt/getopt.internal.h" #include "third_party/mbedtls/ctr_drbg.h" #include "third_party/mbedtls/debug.h" #include "third_party/mbedtls/error.h" -#include "third_party/mbedtls/pk.h" +#include "third_party/mbedtls/iana.h" +#include "third_party/mbedtls/net_sockets.h" #include "third_party/mbedtls/ssl.h" -#include "third_party/mbedtls/ssl_ticket.h" -#include "tool/curl/cmd.h" +#include "third_party/mbedtls/x509.h" /** * @fileoverview Downloads HTTP URL to stdout. @@ -64,31 +53,67 @@ #define HeaderEqualCase(H, S) \ SlicesEqualCase(S, strlen(S), HeaderData(H), HeaderLength(H)) -int sock; +static int sock; +static int outfd; +static const char *prog; +static const char *outpath; -static bool TuneSocket(int fd, int a, int b, int x) { - if (!b) return false; - return setsockopt(fd, a, b, &x, sizeof(x)) != -1; +static wontreturn void PrintUsage(int fd, int rc) { + tinyprint(fd, "usage: ", prog, " [-iksvV] URL\n", NULL); + exit(rc); } -static void Write(const void *p, size_t n) { - ssize_t rc; - rc = write(1, p, n); - if (rc == -1 && errno == EPIPE) { - close(sock); - exit(128 + SIGPIPE); - } - if (rc != n) { - fprintf(stderr, "write failed: %m\n"); +static const char *DescribeErrno(void) { + const char *reason; + if (!(reason = _strerdoc(errno))) reason = "Unknown error"; + return reason; +} + +static int GetSslEntropy(void *c, unsigned char *p, size_t n) { + if (getrandom(p, n, 0) != n) { + perror("getrandom"); exit(1); } + return 0; +} + +static void OnSslDebug(void *ctx, int level, const char *file, int line, + const char *message) { + char sline[12]; + char slevel[12]; + FormatInt32(sline, line); + FormatInt32(slevel, level); + tinyprint(2, file, ":", sline, ": (", slevel, ") ", message, "\n", NULL); +} + +static void WriteOutput(const void *p, size_t n) { + if (!outfd) { + if (outpath) { + if ((outfd = creat(outpath, 0644)) <= 0) { + perror(outpath); + exit(1); + } + } else { + outfd = 1; + outpath = ""; + } + } + ssize_t rc; + for (size_t i = 0; i < n; i += rc) { + rc = write(outfd, p, n); + if (rc <= 0) { + perror(outpath); + exit(1); + } + } } static int TlsSend(void *c, const unsigned char *p, size_t n) { int rc; - NOISEF("begin send %zu", n); - CHECK_NE(-1, (rc = write(*(int *)c, p, n))); - NOISEF("end send %zu", n); + if ((rc = write(*(int *)c, p, n)) == -1) { + perror("TlsSend"); + exit(1); + } return rc; } @@ -100,27 +125,35 @@ static int TlsRecv(void *c, unsigned char *p, size_t n, uint32_t o) { if (a < b) { r = MIN(n, b - a); memcpy(p, t + a, r); - if ((a += r) == b) a = b = 0; + if ((a += r) == b) { + a = b = 0; + } return r; } v[0].iov_base = p; v[0].iov_len = n; v[1].iov_base = t; v[1].iov_len = sizeof(t); - NOISEF("begin recv %zu", n + sizeof(t) - b); - CHECK_NE(-1, (r = readv(*(int *)c, v, 2))); - NOISEF("end recv %zu", r); - if (r > n) b = r - n; + if ((r = readv(*(int *)c, v, 2)) == -1) { + perror("TlsRecv"); + exit(1); + } + if (r > n) { + b = r - n; + } return MIN(n, r); } -static wontreturn void PrintUsage(FILE *f, int rc) { - fprintf(f, "usage: %s [-iksvV] URL\n", program_invocation_name); - exit(rc); -} - int _curl(int argc, char *argv[]) { - if (!NoDebug()) ShowCrashReports(); + + if (!NoDebug()) { + ShowCrashReports(); + } + + prog = argv[0]; + if (!prog) { + prog = "curl"; + } /* * Read flags. @@ -131,18 +164,18 @@ int _curl(int argc, char *argv[]) { char **p; } headers = {0}; int method = 0; - bool authmode = MBEDTLS_SSL_VERIFY_REQUIRED; + int authmode = MBEDTLS_SSL_VERIFY_REQUIRED; + int ciphersuite = MBEDTLS_SSL_PRESET_SUITEC; bool includeheaders = false; const char *postdata = NULL; const char *agent = "hurl/1.o (https://github.com/jart/cosmopolitan)"; - __log_level = kLogWarn; - while ((opt = getopt(argc, argv, "qiksvVIX:H:A:d:")) != -1) { + while ((opt = getopt(argc, argv, "qiksvBVIX:H:A:d:o:")) != -1) { switch (opt) { case 's': case 'q': break; - case 'v': - ++__log_level; + case 'o': + outpath = optarg; break; case 'i': includeheaders = true; @@ -161,7 +194,10 @@ int _curl(int argc, char *argv[]) { postdata = optarg; break; case 'X': - CHECK((method = GetHttpMethod(optarg, strlen(optarg)))); + if (!(method = GetHttpMethod(optarg, strlen(optarg)))) { + tinyprint(2, prog, ": bad http method: ", optarg, "\n", NULL); + exit(1); + } break; case 'V': ++mbedtls_debug_threshold; @@ -169,10 +205,13 @@ int _curl(int argc, char *argv[]) { case 'k': authmode = MBEDTLS_SSL_VERIFY_NONE; break; + case 'B': + ciphersuite = MBEDTLS_SSL_PRESET_SUITEB; + break; case 'h': - PrintUsage(stdout, EXIT_SUCCESS); + PrintUsage(1, 0); default: - PrintUsage(stderr, EX_USAGE); + PrintUsage(2, 1); } } @@ -180,7 +219,10 @@ int _curl(int argc, char *argv[]) { * Get argument. */ const char *urlarg; - if (optind == argc) PrintUsage(stderr, EX_USAGE); + if (optind == argc) { + tinyprint(2, prog, ": missing url\n", NULL); + PrintUsage(2, 1); + } urlarg = argv[optind]; /* @@ -189,20 +231,20 @@ int _curl(int argc, char *argv[]) { struct Url url; char *host, *port; bool usessl = false; - _gc(ParseUrl(urlarg, -1, &url, kUrlPlus)); - _gc(url.params.p); + gc(ParseUrl(urlarg, -1, &url, kUrlPlus)); + gc(url.params.p); if (url.scheme.n) { if (url.scheme.n == 5 && !memcasecmp(url.scheme.p, "https", 5)) { usessl = true; } else if (!(url.scheme.n == 4 && !memcasecmp(url.scheme.p, "http", 4))) { - fprintf(stderr, "error: not an http/https url: %s\n", urlarg); + tinyprint(2, prog, ": not an http/https url: ", urlarg, "\n", NULL); exit(1); } } if (url.host.n) { - host = _gc(strndup(url.host.p, url.host.n)); + host = gc(strndup(url.host.p, url.host.n)); if (url.port.n) { - port = _gc(strndup(url.port.p, url.port.n)); + port = gc(strndup(url.port.p, url.port.n)); } else { port = usessl ? "443" : "80"; } @@ -211,7 +253,7 @@ int _curl(int argc, char *argv[]) { port = usessl ? "443" : "80"; } if (!IsAcceptableHost(host, -1)) { - fprintf(stderr, "error: invalid host: %s\n", urlarg); + tinyprint(2, prog, ": invalid host: ", urlarg, "\n", NULL); exit(1); } url.fragment.p = 0, url.fragment.n = 0; @@ -221,7 +263,7 @@ int _curl(int argc, char *argv[]) { url.host.p = 0, url.host.n = 0; url.port.p = 0, url.port.n = 0; if (!url.path.n || url.path.p[0] != '/') { - char *p = _gc(xmalloc(1 + url.path.n)); + char *p = gc(malloc(1 + url.path.n)); mempcpy(mempcpy(p, "/", 1), url.path.p, url.path.n); url.path.p = p; ++url.path.n; @@ -230,34 +272,87 @@ int _curl(int argc, char *argv[]) { /* * Create HTTP message. */ - if (!method) method = postdata ? kHttpPost : kHttpGet; + if (!method) { + if (postdata) { + method = kHttpPost; + } else { + method = kHttpGet; + } + } char *request = 0; appendf(&request, "%s %s HTTP/1.1\r\n" "Connection: close\r\n" "User-Agent: %s\r\n", - kHttpMethod[method], _gc(EncodeUrl(&url, 0)), agent); + kHttpMethod[method], gc(EncodeUrl(&url, 0)), agent); - bool senthost = false, sentcontenttype = false, sentcontentlength = false; + bool senthost = false; + bool sentcontenttype = false; + bool sentcontentlength = false; for (int i = 0; i < headers.n; ++i) { - appendf(&request, "%s\r\n", headers.p[i]); - if (!strncasecmp("Host:", headers.p[i], 5)) + appends(&request, headers.p[i]); + appends(&request, "\r\n"); + if (!strncasecmp("Host:", headers.p[i], 5)) { senthost = true; - else if (!strncasecmp("Content-Type:", headers.p[i], 13)) + } else if (!strncasecmp("Content-Type:", headers.p[i], 13)) { sentcontenttype = true; - else if (!strncasecmp("Content-Length:", headers.p[i], 15)) + } else if (!strncasecmp("Content-Length:", headers.p[i], 15)) { sentcontentlength = true; + } + } + if (!senthost) { + appends(&request, "Host: "); + appends(&request, host); + appendw(&request, ':'); + appends(&request, port); + appends(&request, "\r\n"); } - if (!senthost) appendf(&request, "Host: %s:%s\r\n", host, port); if (postdata) { - if (!sentcontenttype) + if (!sentcontenttype) { appends(&request, "Content-Type: application/x-www-form-urlencoded\r\n"); - if (!sentcontentlength) - appendf(&request, "Content-Length: %d\r\n", strlen(postdata)); + } + if (!sentcontentlength) { + char ibuf[21]; + FormatUint64(ibuf, strlen(postdata)); + appends(&request, "Content-Length: "); + appends(&request, ibuf); + appends(&request, "\r\n"); + } } - appendf(&request, "\r\n"); - if (postdata) appends(&request, postdata); + appends(&request, "\r\n"); + if (postdata) { + appends(&request, postdata); + } + + /* + * Perform DNS lookup. + */ + struct addrinfo *addr; + struct addrinfo hints = {.ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + .ai_flags = AI_NUMERICSERV}; + if (getaddrinfo(host, port, &hints, &addr) != EAI_SUCCESS) { + tinyprint(2, prog, ": could not resolve host: ", host, "\n", NULL); + exit(1); + } + + /* + * Connect to server. + */ + int ret; + if ((sock = GoodSocket(addr->ai_family, addr->ai_socktype, addr->ai_protocol, + false, &(struct timeval){-60})) == -1) { + perror("socket"); + exit(1); + } + if (connect(sock, addr->ai_addr, addr->ai_addrlen)) { + tinyprint(2, prog, ": failed to connect to ", host, " port ", port, ": ", + DescribeErrno(), "\n", NULL); + exit(1); + } + freeaddrinfo(addr); /* * Setup crypto. @@ -269,67 +364,58 @@ int _curl(int argc, char *argv[]) { mbedtls_ssl_init(&ssl); mbedtls_ctr_drbg_init(&drbg); mbedtls_ssl_config_init(&conf); - CHECK_EQ(0, mbedtls_ctr_drbg_seed(&drbg, GetEntropy, 0, "justine", 7)); - CHECK_EQ(0, mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT)); + _unassert(!mbedtls_ctr_drbg_seed(&drbg, GetSslEntropy, 0, "justine", 7)); + _unassert(!mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + ciphersuite)); mbedtls_ssl_conf_authmode(&conf, authmode); mbedtls_ssl_conf_ca_chain(&conf, GetSslRoots(), 0); mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &drbg); - if (!IsTiny()) mbedtls_ssl_conf_dbg(&conf, TlsDebug, 0); - CHECK_EQ(0, mbedtls_ssl_setup(&ssl, &conf)); - CHECK_EQ(0, mbedtls_ssl_set_hostname(&ssl, host)); - } - - /* - * Perform DNS lookup. - */ - struct addrinfo *addr; - struct addrinfo hints = {.ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - .ai_protocol = IPPROTO_TCP, - .ai_flags = AI_NUMERICSERV}; - CHECK_EQ(EAI_SUCCESS, getaddrinfo(host, port, &hints, &addr)); - - /* - * Connect to server. - */ - int ret; - CHECK_NE(-1, (sock = GoodSocket(addr->ai_family, addr->ai_socktype, - addr->ai_protocol, false, - &(struct timeval){-60}))); - CHECK_NE(-1, connect(sock, addr->ai_addr, addr->ai_addrlen)); - freeaddrinfo(addr); - if (usessl) { +#ifndef NDEBUG + mbedtls_ssl_conf_dbg(&conf, OnSslDebug, 0); +#endif + _unassert(!mbedtls_ssl_setup(&ssl, &conf)); + _unassert(!mbedtls_ssl_set_hostname(&ssl, host)); mbedtls_ssl_set_bio(&ssl, &sock, TlsSend, 0, TlsRecv); if ((ret = mbedtls_ssl_handshake(&ssl))) { - TlsDie("ssl handshake", ret); + tinyprint(2, prog, ": ssl negotiation with ", host, + " failed: ", DescribeSslClientHandshakeError(&ssl, ret), "\n", + NULL); + exit(1); } } /* * Send HTTP Message. */ - size_t n; + ssize_t rc; + size_t i, n; n = appendz(request).i; - if (usessl) { - ret = mbedtls_ssl_write(&ssl, request, n); - if (ret != n) TlsDie("ssl write", ret); - } else { - CHECK_EQ(n, write(sock, request, n)); + for (i = 0; i < n; i += rc) { + if (usessl) { + rc = mbedtls_ssl_write(&ssl, request + i, n - i); + if (rc <= 0) { + tinyprint(2, prog, ": ssl send failed: ", DescribeMbedtlsErrorCode(rc), + "\n", NULL); + exit(1); + } + } else { + rc = write(sock, request + i, n - i); + if (rc <= 0) { + tinyprint(2, prog, ": send failed: ", DescribeErrno(), "\n", NULL); + exit(1); + } + } } - xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0); - /* * Handle response. */ int t; char *p; - ssize_t rc; struct HttpMessage msg; struct HttpUnchunker u; - size_t g, i, hdrlen, paylen; + size_t g, hdrlen, paylen; InitHttpMessage(&msg, kHttpResponse); for (p = 0, hdrlen = paylen = t = i = n = 0;;) { if (i == n) { @@ -342,25 +428,30 @@ int _curl(int argc, char *argv[]) { if (rc == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { rc = 0; } else { - TlsDie("ssl read", rc); + tinyprint(2, prog, + ": ssl recv failed: ", DescribeMbedtlsErrorCode(rc), "\n", + NULL); + exit(1); } } } else { - CHECK_NE(-1, (rc = read(sock, p + i, n - i))); + if ((rc = read(sock, p + i, n - i)) == -1) { + tinyprint(2, prog, ": recv failed: ", DescribeErrno(), "\n", NULL); + exit(1); + } } g = rc; i += g; switch (t) { case kHttpClientStateHeaders: - CHECK(g); - CHECK_NE(-1, (rc = ParseHttpMessage(&msg, p, i))); + _unassert(g); + if ((rc = ParseHttpMessage(&msg, p, i)) == -1) { + tinyprint(2, prog, ": ", host, " sent bad http message\n", NULL); + exit(1); + } if (rc) { hdrlen = rc; if (100 <= msg.status && msg.status <= 199) { - CHECK(!HasHeader(kHttpContentLength) || - HeaderEqualCase(kHttpContentLength, "0")); - CHECK(!HasHeader(kHttpTransferEncoding) || - HeaderEqualCase(kHttpTransferEncoding, "identity")); DestroyHttpMessage(&msg); InitHttpMessage(&msg, kHttpResponse); memmove(p, p + hdrlen, i - hdrlen); @@ -368,50 +459,65 @@ int _curl(int argc, char *argv[]) { break; } if (method == kHttpHead || includeheaders) { - Write(p, hdrlen); + WriteOutput(p, hdrlen); } if (method == kHttpHead || msg.status == 204 || msg.status == 304) { goto Finished; } if (HasHeader(kHttpTransferEncoding) && !HeaderEqualCase(kHttpTransferEncoding, "identity")) { - CHECK(HeaderEqualCase(kHttpTransferEncoding, "chunked")); + if (!HeaderEqualCase(kHttpTransferEncoding, "chunked")) { + tinyprint(2, prog, ": ", host, + " sent unsupported transfer encoding\n", NULL); + exit(1); + } t = kHttpClientStateBodyChunked; memset(&u, 0, sizeof(u)); goto Chunked; } else if (HasHeader(kHttpContentLength)) { - CHECK_NE(-1, (rc = ParseContentLength( - HeaderData(kHttpContentLength), - HeaderLength(kHttpContentLength)))); + if ((rc = ParseContentLength(HeaderData(kHttpContentLength), + HeaderLength(kHttpContentLength))) == + -1) { + tinyprint(2, prog, ": ", host, " sent bad content length\n", + NULL); + exit(1); + } t = kHttpClientStateBodyLengthed; paylen = rc; if (paylen > i - hdrlen) { - Write(p + hdrlen, i - hdrlen); + WriteOutput(p + hdrlen, i - hdrlen); } else { - Write(p + hdrlen, paylen); + WriteOutput(p + hdrlen, paylen); goto Finished; } } else { t = kHttpClientStateBody; - Write(p + hdrlen, i - hdrlen); + WriteOutput(p + hdrlen, i - hdrlen); } } break; case kHttpClientStateBody: + WriteOutput(p + i - g, g); if (!g) goto Finished; - Write(p + i - g, g); break; case kHttpClientStateBodyLengthed: - CHECK(g); - if (i - hdrlen > paylen) g = hdrlen + paylen - (i - g); - Write(p + i - g, g); - if (i - hdrlen >= paylen) goto Finished; + _unassert(g); + if (i - hdrlen > paylen) { + g = hdrlen + paylen - (i - g); + } + WriteOutput(p + i - g, g); + if (i - hdrlen >= paylen) { + goto Finished; + } break; case kHttpClientStateBodyChunked: Chunked: - CHECK_NE(-1, (rc = Unchunk(&u, p + hdrlen, i - hdrlen, &paylen))); + if ((rc = Unchunk(&u, p + hdrlen, i - hdrlen, &paylen)) == -1) { + tinyprint(2, prog, ": ", host, " sent bad chunk coding\n", NULL); + exit(1); + } if (rc) { - Write(p + hdrlen, paylen); + WriteOutput(p + hdrlen, paylen); goto Finished; } break; @@ -424,7 +530,10 @@ int _curl(int argc, char *argv[]) { * Close connection. */ Finished: - CHECK_NE(-1, close(sock)); + if (close(sock)) { + tinyprint(2, prog, ": close failed: ", DescribeErrno(), "\n", NULL); + exit(1); + } /* * Free memory. diff --git a/tool/curl/curl.mk b/tool/curl/curl.mk index a0b73e953..9e681d75b 100644 --- a/tool/curl/curl.mk +++ b/tool/curl/curl.mk @@ -26,7 +26,6 @@ TOOL_CURL_DIRECTDEPS = \ LIBC_STR \ LIBC_SYSV \ LIBC_TIME \ - LIBC_X \ LIBC_ZIPOS \ NET_HTTP \ NET_HTTPS \ diff --git a/tool/curl/test.sh b/tool/curl/test.sh new file mode 100755 index 000000000..21fe3d007 --- /dev/null +++ b/tool/curl/test.sh @@ -0,0 +1,23 @@ +#!/bin/sh +m=zero +make -j16 m=$m o/$m/tool/curl/curl.com || exit +for t in expired \ + wrong.host \ + self-signed \ + untrusted-root \ + revoked \ + dh480 \ + dh512 \ + no-common-name \ + no-subject \ + incomplete-chain \ + superfish \ + captive-portal \ + edellroot \ + mitm-software \ + rc4; do + u=https://$t.badssl.com/ + echo + echo $u + o/$m/tool/curl/curl.com $u +done diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 161dbfc51..32bf5f1d1 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -77,12 +77,14 @@ #include "libc/str/str.h" #include "libc/str/strwidth.h" #include "libc/sysv/consts/af.h" +#include "libc/sysv/consts/auxv.h" #include "libc/sysv/consts/clock.h" #include "libc/sysv/consts/clone.h" #include "libc/sysv/consts/dt.h" #include "libc/sysv/consts/ex.h" #include "libc/sysv/consts/exit.h" #include "libc/sysv/consts/f.h" +#include "libc/sysv/consts/hwcap.h" #include "libc/sysv/consts/inaddr.h" #include "libc/sysv/consts/ipproto.h" #include "libc/sysv/consts/madv.h" @@ -7212,8 +7214,8 @@ static void TlsInit(void) { int suite; if (unsecure) return; - if (suiteb && !X86_HAVE(AES)) { - WARNF("(srvr) requested suite b crypto, but aes-ni is not present"); + if (suiteb && !mbedtls_aes_uses_hardware()) { + WARNF("(srvr) requested suiteb crypto, but hardware aes not present"); } if (!sslinitialized) { diff --git a/tool/tool.mk b/tool/tool.mk index f23e92388..22df104d1 100644 --- a/tool/tool.mk +++ b/tool/tool.mk @@ -3,6 +3,7 @@ .PHONY: o/$(MODE)/tool o/$(MODE)/tool: \ + o/$(MODE)/tool/ape \ o/$(MODE)/tool/args \ o/$(MODE)/tool/build \ o/$(MODE)/tool/curl \ diff --git a/usr/share/ssl/root/geotrust.pem b/usr/share/ssl/root/geotrust.pem index caf1c7d17..cf2095012 100644 --- a/usr/share/ssl/root/geotrust.pem +++ b/usr/share/ssl/root/geotrust.pem @@ -1,24 +1,4 @@ -----BEGIN CERTIFICATE----- -MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG -EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg -R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 -9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq -fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv -iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU -1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ -bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW -MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA -ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l -uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn -Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS -tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF -PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un -hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV -5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx diff --git a/usr/share/ssl/root/show.sh b/usr/share/ssl/root/show.sh new file mode 100755 index 000000000..42472e029 --- /dev/null +++ b/usr/share/ssl/root/show.sh @@ -0,0 +1,8 @@ +#!/bin/sh +for f in usr/share/ssl/root/*.pem; do + echo + echo File: $f + echo + openssl crl2pkcs7 -nocrl -certfile $f | + openssl pkcs7 -print_certs -text -noout +done