TLS verification

This commit is contained in:
Sergey Lyubka committed 2025-02-10 15:36:29 +00:00
1 parent ef8e7419fa
commit b50081a83b
14 files changed
+5281 -337

No files matched your search

+2234 -146
View File
File diff suppressed because it is too large. Load diff
+63 -41
View File
@@ -1132,6 +1132,12 @@ bool mg_path_is_sane(const struct mg_str path);
MG_U8P(p)[0] = ((n) >> 8U) & 255; \
MG_U8P(p)[1] = (n) &255; \
} while (0)
#define MG_STORE_BE24(p, n) \
do { \
MG_U8P(p)[0] = ((n) >> 16U) & 255; \
MG_U8P(p)[1] = ((n) >> 8U) & 255; \
MG_U8P(p)[2] = (n) &255; \
} while (0)
#define MG_REG(x) ((volatile uint32_t *) (x))[0]
#define MG_BIT(x) (((uint32_t) 1U) << (x))
@@ -1260,11 +1266,25 @@ typedef struct {
unsigned char buffer[64];
} mg_sha256_ctx;
void mg_sha256_init(mg_sha256_ctx *);
void mg_sha256_update(mg_sha256_ctx *, const unsigned char *data, size_t len);
void mg_sha256_final(unsigned char digest[32], mg_sha256_ctx *);
void mg_sha256(uint8_t dst[32], uint8_t *data, size_t datasz);
void mg_hmac_sha256(uint8_t dst[32], uint8_t *key, size_t keysz, uint8_t *data,
size_t datasz);
typedef struct {
uint64_t state[8];
uint8_t buffer[128];
uint64_t bitlen[2];
uint32_t datalen;
} mg_sha384_ctx;
void mg_sha384_init(mg_sha384_ctx *ctx);
void mg_sha384_update(mg_sha384_ctx *ctx, const uint8_t *data, size_t len);
void mg_sha384_final(uint8_t digest[48], mg_sha384_ctx *ctx);
void mg_sha384(uint8_t dst[48], uint8_t *data, size_t datasz);
#ifndef TLS_X15519_H
#define TLS_X15519_H
@@ -2108,6 +2128,13 @@ PORTABLE_8439_DECL size_t mg_chacha20_poly1305_decrypt(
}
#endif
#endif
#ifndef TLS_RSA_H
#define TLS_RSA_H
int mg_rsa_mod_pow(const uint8_t *mod, size_t modsz, const uint8_t *exp, size_t expsz, const uint8_t *msg, size_t msgsz, uint8_t *out, size_t outsz);
#endif // TLS_RSA_H
struct mg_connection;
@@ -2938,7 +2965,7 @@ enum {
// Set if PHY LEDs are connected to ground
MG_PHY_LEDS_ACTIVE_HIGH = (1 << 0),
// Set when PHY clocks MAC. Otherwise, MAC clocks PHY
MG_PHY_CLOCKS_MAC = (1 << 1),
MG_PHY_CLOCKS_MAC = (1 << 1)
};
enum { MG_PHY_SPEED_10M, MG_PHY_SPEED_100M, MG_PHY_SPEED_1000M };
@@ -3193,46 +3220,6 @@ struct mg_tcpip_driver_tms570_data {
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_W5500) && MG_ENABLE_DRIVER_W5500
#endif
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC7) && MG_ENABLE_DRIVER_XMC7
struct mg_tcpip_driver_xmc7_data {
int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
uint8_t phy_addr;
};
#ifndef MG_TCPIP_PHY_ADDR
#define MG_TCPIP_PHY_ADDR 0
#endif
#ifndef MG_DRIVER_MDC_CR
#define MG_DRIVER_MDC_CR 3
#endif
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_xmc7_data driver_data_; \
static struct mg_tcpip_if mif_; \
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
mif_.driver = &mg_tcpip_driver_xmc7; \
mif_.driver_data = &driver_data_; \
MG_SET_MAC_ADDRESS(mif_.mac); \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: xmc7, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
#endif
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC
struct mg_tcpip_driver_xmc_data {
@@ -3279,6 +3266,41 @@ struct mg_tcpip_driver_xmc_data {
#endif
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC7) && MG_ENABLE_DRIVER_XMC7
struct mg_tcpip_driver_xmc7_data {
int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5
uint8_t phy_addr;
};
#ifndef MG_TCPIP_PHY_ADDR
#define MG_TCPIP_PHY_ADDR 0
#endif
#ifndef MG_DRIVER_MDC_CR
#define MG_DRIVER_MDC_CR 3
#endif
#define MG_TCPIP_DRIVER_INIT(mgr) \
do { \
static struct mg_tcpip_driver_xmc7_data driver_data_; \
static struct mg_tcpip_if mif_; \
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
mif_.ip = MG_TCPIP_IP; \
mif_.mask = MG_TCPIP_MASK; \
mif_.gw = MG_TCPIP_GW; \
mif_.driver = &mg_tcpip_driver_xmc7; \
mif_.driver_data = &driver_data_; \
MG_SET_MAC_ADDRESS(mif_.mac); \
mg_tcpip_init(mgr, &mif_); \
MG_INFO(("Driver: xmc7, MAC: %M", mg_print_mac, mif_.mac)); \
} while (0)
#endif
#ifdef __cplusplus
}
#endif
+1 -1
View File
@@ -12,7 +12,7 @@ enum {
// Set if PHY LEDs are connected to ground
MG_PHY_LEDS_ACTIVE_HIGH = (1 << 0),
// Set when PHY clocks MAC. Otherwise, MAC clocks PHY
MG_PHY_CLOCKS_MAC = (1 << 1),
MG_PHY_CLOCKS_MAC = (1 << 1)
};
enum { MG_PHY_SPEED_10M, MG_PHY_SPEED_100M, MG_PHY_SPEED_1000M };
+171
View File
@@ -137,6 +137,13 @@ void mg_sha256_final(unsigned char digest[32], mg_sha256_ctx *ctx) {
}
}
void mg_sha256(uint8_t dst[32], uint8_t *data, size_t datasz) {
mg_sha256_ctx ctx;
mg_sha256_init(&ctx);
mg_sha256_update(&ctx, data, datasz);
mg_sha256_final(dst, &ctx);
}
void mg_hmac_sha256(uint8_t dst[32], uint8_t *key, size_t keysz, uint8_t *data,
size_t datasz) {
mg_sha256_ctx ctx;
@@ -165,3 +172,167 @@ void mg_hmac_sha256(uint8_t dst[32], uint8_t *key, size_t keysz, uint8_t *data,
mg_sha256_update(&ctx, dst, 32);
mg_sha256_final(dst, &ctx);
}
//=====================================
// TODO: rename macros
#define ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTR64(x, 28) ^ ROTR64(x, 34) ^ ROTR64(x, 39))
#define EP1(x) (ROTR64(x, 14) ^ ROTR64(x, 18) ^ ROTR64(x, 41))
#define SIG0(x) (ROTR64(x, 1) ^ ROTR64(x, 8) ^ ((x) >> 7))
#define SIG1(x) (ROTR64(x, 19) ^ ROTR64(x, 61) ^ ((x) >> 6))
static const uint64_t mg_sha256_k2[80] = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
0x5fcb6fab3ad6faec, 0x6c44198c4a475817};
static void mg_sha384_transform(mg_sha384_ctx *ctx, const uint8_t data[]) {
uint64_t m[80];
uint64_t a, b, c, d, e, f, g, h;
int i, j;
for (i = 0, j = 0; i < 16; ++i, j += 8)
m[i] = ((uint64_t) data[j] << 56) | ((uint64_t) data[j + 1] << 48) |
((uint64_t) data[j + 2] << 40) | ((uint64_t) data[j + 3] << 32) |
((uint64_t) data[j + 4] << 24) | ((uint64_t) data[j + 5] << 16) |
((uint64_t) data[j + 6] << 8) | ((uint64_t) data[j + 7]);
for (; i < 80; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
a = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
f = ctx->state[5];
g = ctx->state[6];
h = ctx->state[7];
for (i = 0; i < 80; ++i) {
uint64_t t1 = h + EP1(e) + CH(e, f, g) + mg_sha256_k2[i] + m[i];
uint64_t t2 = EP0(a) + MAJ(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
ctx->state[5] += f;
ctx->state[6] += g;
ctx->state[7] += h;
}
void mg_sha384_init(mg_sha384_ctx *ctx) {
ctx->datalen = 0;
ctx->bitlen[0] = 0;
ctx->bitlen[1] = 0;
ctx->state[0] = 0xcbbb9d5dc1059ed8;
ctx->state[1] = 0x629a292a367cd507;
ctx->state[2] = 0x9159015a3070dd17;
ctx->state[3] = 0x152fecd8f70e5939;
ctx->state[4] = 0x67332667ffc00b31;
ctx->state[5] = 0x8eb44a8768581511;
ctx->state[6] = 0xdb0c2e0d64f98fa7;
ctx->state[7] = 0x47b5481dbefa4fa4;
}
void mg_sha384_update(mg_sha384_ctx *ctx, const uint8_t *data, size_t len) {
size_t i;
for (i = 0; i < len; ++i) {
ctx->buffer[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 128) {
mg_sha384_transform(ctx, ctx->buffer);
ctx->bitlen[1] += 1024;
if (ctx->bitlen[1] < 1024) ctx->bitlen[0]++;
ctx->datalen = 0;
}
}
}
void mg_sha384_final(uint8_t hash[48], mg_sha384_ctx *ctx) {
size_t i = ctx->datalen;
if (ctx->datalen < 112) {
ctx->buffer[i++] = 0x80;
while (i < 112) ctx->buffer[i++] = 0x00;
} else {
ctx->buffer[i++] = 0x80;
while (i < 128) ctx->buffer[i++] = 0x00;
mg_sha384_transform(ctx, ctx->buffer);
memset(ctx->buffer, 0, 112);
}
ctx->bitlen[1] += ctx->datalen * 8;
if (ctx->bitlen[1] < ctx->datalen * 8) ctx->bitlen[0]++;
ctx->buffer[127] = (uint8_t) (ctx->bitlen[1]);
ctx->buffer[126] = (uint8_t) (ctx->bitlen[1] >> 8);
ctx->buffer[125] = (uint8_t) (ctx->bitlen[1] >> 16);
ctx->buffer[124] = (uint8_t) (ctx->bitlen[1] >> 24);
ctx->buffer[123] = (uint8_t) (ctx->bitlen[1] >> 32);
ctx->buffer[122] = (uint8_t) (ctx->bitlen[1] >> 40);
ctx->buffer[121] = (uint8_t) (ctx->bitlen[1] >> 48);
ctx->buffer[120] = (uint8_t) (ctx->bitlen[1] >> 56);
ctx->buffer[119] = (uint8_t) (ctx->bitlen[0]);
ctx->buffer[118] = (uint8_t) (ctx->bitlen[0] >> 8);
ctx->buffer[117] = (uint8_t) (ctx->bitlen[0] >> 16);
ctx->buffer[116] = (uint8_t) (ctx->bitlen[0] >> 24);
ctx->buffer[115] = (uint8_t) (ctx->bitlen[0] >> 32);
ctx->buffer[114] = (uint8_t) (ctx->bitlen[0] >> 40);
ctx->buffer[113] = (uint8_t) (ctx->bitlen[0] >> 48);
ctx->buffer[112] = (uint8_t) (ctx->bitlen[0] >> 56);
mg_sha384_transform(ctx, ctx->buffer);
for (i = 0; i < 6; ++i) {
hash[i * 8] = (uint8_t) ((ctx->state[i] >> 56) & 0xff);
hash[i * 8 + 1] = (uint8_t) ((ctx->state[i] >> 48) & 0xff);
hash[i * 8 + 2] = (uint8_t) ((ctx->state[i] >> 40) & 0xff);
hash[i * 8 + 3] = (uint8_t) ((ctx->state[i] >> 32) & 0xff);
hash[i * 8 + 4] = (uint8_t) ((ctx->state[i] >> 24) & 0xff);
hash[i * 8 + 5] = (uint8_t) ((ctx->state[i] >> 16) & 0xff);
hash[i * 8 + 6] = (uint8_t) ((ctx->state[i] >> 8) & 0xff);
hash[i * 8 + 7] = (uint8_t) (ctx->state[i] & 0xff);
}
}
void mg_sha384(uint8_t dst[48], uint8_t *data, size_t datasz) {
mg_sha384_ctx ctx;
mg_sha384_init(&ctx);
mg_sha384_update(&ctx, data, datasz);
mg_sha384_final(dst, &ctx);
}
+14
View File
@@ -15,8 +15,22 @@ typedef struct {
unsigned char buffer[64];
} mg_sha256_ctx;
void mg_sha256_init(mg_sha256_ctx *);
void mg_sha256_update(mg_sha256_ctx *, const unsigned char *data, size_t len);
void mg_sha256_final(unsigned char digest[32], mg_sha256_ctx *);
void mg_sha256(uint8_t dst[32], uint8_t *data, size_t datasz);
void mg_hmac_sha256(uint8_t dst[32], uint8_t *key, size_t keysz, uint8_t *data,
size_t datasz);
typedef struct {
uint64_t state[8];
uint8_t buffer[128];
uint64_t bitlen[2];
uint32_t datalen;
} mg_sha384_ctx;
void mg_sha384_init(mg_sha384_ctx *ctx);
void mg_sha384_update(mg_sha384_ctx *ctx, const uint8_t *data, size_t len);
void mg_sha384_final(uint8_t digest[48], mg_sha384_ctx *ctx);
void mg_sha384(uint8_t dst[48], uint8_t *data, size_t datasz);
+478 -146
View File
@@ -5,6 +5,7 @@
#include "tls.h"
#include "tls_aes128.h"
#include "tls_chacha20.h"
#include "tls_rsa.h"
#include "tls_uecc.h"
#include "tls_x25519.h"
#include "util.h"
@@ -81,12 +82,15 @@ struct tls_data {
int skip_verification; // perform checks on server certificate?
int cert_requested; // client received a CertificateRequest?
struct mg_str cert_der; // certificate in DER format
struct mg_str ca_der; // CA certificate
uint8_t ec_key[32]; // EC private key
char hostname[254]; // server hostname (client extension)
uint8_t certhash[32]; // certificate message hash
uint8_t pubkey[64]; // server EC public key to verify cert
uint8_t sighash[32]; // server EC public key to verify cert
int is_ec_pubkey; // EC or RSA?
uint8_t pubkey[512 + 16]; // server EC (64) or RSA (512+exp) public key to
// verify cert
size_t pubkeysz; // size of the server public key
uint8_t sighash[32]; // calculated signature verification hash
struct tls_enc enc;
};
@@ -140,6 +144,66 @@ struct mg_der_tlv {
uint8_t *value;
};
static int mg_der_parse(uint8_t *der, size_t dersz, struct mg_der_tlv *tlv) {
size_t header_len = 2;
uint32_t len = dersz < 2 ? 0 : der[1];
if (dersz < 2) return -1; // Invalid DER
tlv->type = der[0];
if (len > 0x7F) { // long-form length
uint8_t len_bytes = len & 0x7F;
if (dersz < (size_t) (2 + len_bytes)) return -1;
len = 0;
for (uint8_t i = 0; i < len_bytes; i++) {
len = (len << 8) | der[2 + i];
}
header_len += len_bytes;
}
if (dersz < header_len + len) return -1;
tlv->len = len;
tlv->value = der + header_len;
return (int) (header_len + len);
}
static int mg_der_next(struct mg_der_tlv *parent, struct mg_der_tlv *child) {
if (parent->len == 0) return 0;
int consumed = mg_der_parse(parent->value, parent->len, child);
if (consumed < 0) return -1;
parent->value += consumed;
parent->len -= (uint32_t) consumed;
return 1;
}
static int mg_der_find_oid(struct mg_der_tlv *tlv, const uint8_t *oid,
size_t oid_len, struct mg_der_tlv *found) {
struct mg_der_tlv parent, child;
parent = *tlv;
while (mg_der_next(&parent, &child) > 0) {
if (child.type == 0x06 && child.len == oid_len &&
memcmp(child.value, oid, oid_len) == 0) {
return mg_der_next(&parent, found);
} else if (child.type & 0x20) {
struct mg_der_tlv sub_parent = child;
if (mg_der_find_oid(&sub_parent, oid, oid_len, found)) return 1;
}
}
return 0;
}
#if 0
static void mg_der_debug(struct mg_der_tlv *tlv, int depth) {
MG_DEBUG(("> %.*sd=%d Type: 0x%02X, Length: %u\n", depth * 4, " ", depth,
tlv->type, tlv->len));
if (tlv->type & 0x20) { // Constructed: recurse into children
struct mg_der_tlv child;
struct mg_der_tlv parent = *tlv;
while (mg_der_next(&parent, &child) > 0) {
mg_der_debug(&child, depth + 1);
}
}
}
#endif
// parse DER into a TLV record
static int mg_der_to_tlv(uint8_t *der, size_t dersz, struct mg_der_tlv *tlv) {
if (dersz < 2) {
@@ -162,31 +226,6 @@ static int mg_der_to_tlv(uint8_t *der, size_t dersz, struct mg_der_tlv *tlv) {
return 0;
}
static int mg_der_find(uint8_t *der, size_t dersz, uint8_t *oid, size_t oidsz,
struct mg_der_tlv *tlv) {
uint8_t *p, *end;
struct mg_der_tlv child = {0, 0, NULL};
if (mg_der_to_tlv(der, dersz, tlv) < 0) {
return -1; // invalid DER
} else if (tlv->type == 6) { // found OID, check value
return (tlv->len == oidsz && memcmp(tlv->value, oid, oidsz) == 0);
} else if ((tlv->type & 0x20) == 0) {
return 0; // Primitive, but not OID: not found
}
// Constructed object: scan children
p = tlv->value;
end = tlv->value + tlv->len;
while (end > p) {
int r;
mg_der_to_tlv(p, (size_t) (end - p), &child);
r = mg_der_find(p, (size_t) (end - p), oid, oidsz, tlv);
if (r < 0) return -1; // error
if (r > 0) return 1; // found OID!
p = child.value + child.len;
}
return 0; // not found
}
// Did we receive a full TLS record in the c->rtls buffer?
static bool mg_tls_got_record(struct mg_connection *c) {
return c->rtls.len >= (size_t) TLS_RECHDR_SIZE &&
@@ -385,7 +424,7 @@ static void mg_tls_encrypt(struct mg_connection *c, const uint8_t *msg,
nonce[8] ^= (uint8_t) ((seq >> 24) & 255U);
nonce[9] ^= (uint8_t) ((seq >> 16) & 255U);
nonce[10] ^= (uint8_t) ((seq >> 8) & 255U);
nonce[11] ^= (uint8_t) ((seq) &255U);
nonce[11] ^= (uint8_t) ((seq) & 255U);
mg_iobuf_add(wio, wio->len, hdr, sizeof(hdr));
mg_iobuf_resize(wio, wio->len + encsz);
@@ -464,8 +503,7 @@ static int mg_tls_recv_record(struct mg_connection *c) {
nonce[8] ^= (uint8_t) ((seq >> 24) & 255U);
nonce[9] ^= (uint8_t) ((seq >> 16) & 255U);
nonce[10] ^= (uint8_t) ((seq >> 8) & 255U);
nonce[11] ^= (uint8_t) ((seq) &255U);
nonce[11] ^= (uint8_t) ((seq) & 255U);
#if CHACHA20
{
uint8_t *dec = (uint8_t *) calloc(1, msgsz);
@@ -553,15 +591,14 @@ static int mg_tls_server_recv_hello(struct mg_connection *c) {
uint16_t key_exchange_len;
uint8_t *key_exchange;
uint16_t n = MG_LOAD_BE16(ext + j + 2);
if (ext[j] != 0x00 ||
ext[j + 1] != 0x33) { // not a key share extension, ignore
if (MG_LOAD_BE16(ext + j) != 0x0033) { // not a key share extension, ignore
j += (uint16_t) (n + 4);
continue;
}
key_exchange_len = MG_LOAD_BE16(ext + j + 4);
key_exchange = ext + j + 6;
if (key_exchange_len >
rio->len - (uint16_t) ((size_t) key_exchange - (size_t) rio->buf) - 2)
rio->len - (uint16_t) ((size_t) key_exchange - (size_t) rio->buf))
goto fail;
for (k = 0; k < key_exchange_len;) {
uint16_t m = MG_LOAD_BE16(key_exchange + k + 2);
@@ -615,7 +652,7 @@ static void mg_tls_server_send_hello(struct mg_connection *c) {
// calculate keyshare
uint8_t x25519_pub[X25519_BYTES];
uint8_t x25519_prv[X25519_BYTES];
if (!mg_random(x25519_prv, sizeof(x25519_prv))) mg_error(c, "RNG");
if (!mg_random(x25519_prv, sizeof(x25519_prv))) mg_error(c, "RNG");
mg_tls_x25519(x25519_pub, x25519_prv, X25519_BASE_POINT, 1);
mg_tls_x25519(tls->x25519_sec, x25519_prv, tls->x25519_cli, 1);
mg_tls_hexdump("s x25519 sec", tls->x25519_sec, sizeof(tls->x25519_sec));
@@ -644,28 +681,30 @@ static void mg_tls_server_send_ext(struct mg_connection *c) {
static void mg_tls_server_send_cert(struct mg_connection *c) {
struct tls_data *tls = (struct tls_data *) c->tls;
// server DER certificate (empty)
size_t n = tls->cert_der.len;
int send_ca = !c->is_client && tls->ca_der.len > 0;
// server DER certificate + CA (optional)
size_t n = tls->cert_der.len + (send_ca ? tls->ca_der.len + 5 : 0);
uint8_t *cert = (uint8_t *) calloc(1, 13 + n);
if (cert == NULL) {
mg_error(c, "tls cert oom");
return;
}
cert[0] = 0x0b; // handshake header
cert[1] = (uint8_t) (((n + 9) >> 16) & 255U); // 3 bytes: payload length
cert[2] = (uint8_t) (((n + 9) >> 8) & 255U);
cert[3] = (uint8_t) ((n + 9) & 255U);
cert[4] = 0; // request context
cert[5] = (uint8_t) (((n + 5) >> 16) & 255U); // 3 bytes: cert (s) length
cert[6] = (uint8_t) (((n + 5) >> 8) & 255U);
cert[7] = (uint8_t) ((n + 5) & 255U);
cert[8] =
(uint8_t) (((n) >> 16) & 255U); // 3 bytes: first (and only) cert len
cert[9] = (uint8_t) (((n) >> 8) & 255U);
cert[10] = (uint8_t) (n & 255U);
cert[0] = 0x0b; // handshake header
MG_STORE_BE24(cert + 1, n + 9);
cert[4] = 0; // request context
MG_STORE_BE24(cert + 5, n + 5); // 3 bytes: cert (s) length
MG_STORE_BE24(cert + 8, tls->cert_der.len); // 3 bytes: first cert len
// bytes 11+ are certificate in DER format
memmove(cert + 11, tls->cert_der.buf, n);
cert[11 + n] = cert[12 + n] = 0; // certificate extensions (none)
memmove(cert + 11, tls->cert_der.buf, tls->cert_der.len);
MG_STORE_BE16(cert + 11 + tls->cert_der.len,
0); // certificate extensions (none)
if (send_ca) {
size_t offset = 13 + tls->cert_der.len;
MG_STORE_BE24(cert + offset, tls->ca_der.len); // 3 bytes: CA cert length
memmove(cert + offset + 3, tls->ca_der.buf,
tls->ca_der.len); // CA cert data
MG_STORE_BE16(cert + 11 + n, 0); // certificate extensions (none)
}
mg_sha256_update(&tls->sha256, cert, 13 + n);
mg_tls_encrypt(c, cert, 13 + n, MG_TLS_HANDSHAKE);
free(cert);
@@ -774,9 +813,10 @@ static void mg_tls_client_send_hello(struct mg_connection *c) {
uint8_t x25519_pub[X25519_BYTES];
// the only signature algorithm we actually support
uint8_t secp256r1_sig_algs[8] = {
0x00, 0x0d, 0x00, 0x04, 0x00, 0x02, 0x04, 0x03,
// signature algorithms we actually support:
// rsa_pkcs1_sha256, rsa_pss_rsae_sha256 and ecdsa_secp256r1_sha256
uint8_t secp256r1_sig_algs[12] = {
0x00, 0x0d, 0x00, 0x08, 0x00, 0x06, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01,
};
// all popular signature algorithms (if we don't care about verification)
uint8_t all_sig_algs[34] = {
@@ -947,106 +987,351 @@ static int mg_tls_client_recv_ext(struct mg_connection *c) {
return 0;
}
struct mg_tls_cert {
int is_ec_pubkey;
struct mg_str sn;
struct mg_str pubkey;
struct mg_str sig; // signature
uint8_t tbshash[48]; // 32b for sha256/secp256, 48b for sha384/secp384
size_t tbshashsz; // actual TBS hash size
};
static void mg_der_debug_cert_name(const char *name, struct mg_der_tlv *tlv) {
struct mg_der_tlv v;
struct mg_str cn, c, o, ou;
cn = c = o = ou = mg_str("");
if (mg_der_find_oid(tlv, (uint8_t *) "\x55\x04\x03", 3, &v))
cn = mg_str_n((const char *) v.value, v.len);
if (mg_der_find_oid(tlv, (uint8_t *) "\x55\x04\x06", 3, &v))
c = mg_str_n((const char *) v.value, v.len);
if (mg_der_find_oid(tlv, (uint8_t *) "\x55\x04\x0a", 3, &v))
o = mg_str_n((const char *) v.value, v.len);
if (mg_der_find_oid(tlv, (uint8_t *) "\x55\x04\x0b", 3, &v))
ou = mg_str_n((const char *) v.value, v.len);
MG_VERBOSE(("%s: CN=%.*s, C=%.*s, O=%.*s, OU=%.*s", name, cn.len, cn.buf,
c.len, c.buf, o.len, o.buf, ou.len, ou.buf));
}
static int mg_tls_parse_cert_der(void *buf, size_t dersz,
struct mg_tls_cert *cert) {
uint8_t *tbs, *der = (uint8_t *) buf;
size_t tbssz;
struct mg_der_tlv root, tbs_cert, field, algo; // pubkey, signature;
struct mg_der_tlv pki, pki_algo, pki_key, pki_curve, raw_sig;
// Parse outermost SEQUENCE
if (mg_der_parse(der, dersz, &root) <= 0 || root.type != 0x30) return -1;
// Parse TBSCertificate SEQUENCE
tbs = root.value;
if (mg_der_next(&root, &tbs_cert) <= 0 || tbs_cert.type != 0x30) return -1;
tbssz = (size_t) (tbs_cert.value + tbs_cert.len - tbs);
// Parse Version (optional field)
if (mg_der_next(&tbs_cert, &field) <= 0) return -1;
if (field.type == 0xa0) { // v3
if (mg_der_parse(field.value, field.len, &field) <= 0 || field.len != 1 ||
field.value[0] != 2)
return -1;
if (mg_der_next(&tbs_cert, &field) <= 0) return -1;
}
// Parse Serial Number
if (field.type != 2) return -1;
cert->sn = mg_str_n((char *) field.value, field.len);
MG_VERBOSE(("cert s/n: %M", mg_print_hex, cert->sn.len, cert->sn.buf));
// Parse signature algorithm (first occurrence)
if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
if (mg_der_next(&field, &algo) <= 0 || algo.type != 0x06) return -1;
MG_VERBOSE(("sig algo (oid): %M", mg_print_hex, algo.len, algo.value));
// Signature algorithm OID mapping
if (memcmp(algo.value, "\x2A\x86\x48\xCE\x3D\x04\x03\x02", algo.len) == 0) {
MG_VERBOSE(("sig algo: ECDSA with SHA256"));
mg_sha256(cert->tbshash, tbs, tbssz);
cert->tbshashsz = 32;
} else if (memcmp(algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B",
algo.len) == 0) {
MG_VERBOSE(("sig algo: RSA with SHA256"));
mg_sha256(cert->tbshash, tbs, tbssz);
cert->tbshashsz = 32;
} else if (memcmp(algo.value, "\x2A\x86\x48\xCE\x3D\x04\x03\x03", algo.len) ==
0) {
MG_VERBOSE(("sig algo: ECDSA with SHA384"));
mg_sha384(cert->tbshash, tbs, tbssz);
cert->tbshashsz = 48;
} else if (memcmp(algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0C",
algo.len) == 0) {
MG_VERBOSE(("sig algo: RSA with SHA384"));
mg_sha384(cert->tbshash, tbs, tbssz);
cert->tbshashsz = 48;
} else {
MG_ERROR(
("sig algo: unsupported OID: %M", mg_print_hex, algo.len, algo.value));
return -1;
}
MG_VERBOSE(("tbs hash: %M", mg_print_hex, cert->tbshashsz, cert->tbshash));
// issuer
if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
mg_der_debug_cert_name("issuer", &field);
// validity dates (before/after)
if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
if (1) {
struct mg_der_tlv before, after;
mg_der_next(&field, &before);
mg_der_next(&field, &after);
if (memcmp(after.value, "250101000000Z", after.len) < 0) {
MG_ERROR(("invalid validity dates: before=%M after=%M", mg_print_hex,
before.len, before.value, mg_print_hex, after.len,
after.value));
return -1;
}
}
// subject
if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
mg_der_debug_cert_name("subject", &field);
// subject public key info
if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
if (mg_der_next(&field, &pki) <= 0 || pki.type != 0x30) return -1;
if (mg_der_next(&pki, &pki_algo) <= 0 || pki_algo.type != 0x06) return -1;
// public key algorithm
MG_VERBOSE(("pk algo (oid): %M", mg_print_hex, pki_algo.len, pki_algo.value));
if (memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x07",
pki_algo.len) == 0) {
cert->is_ec_pubkey = 1;
MG_VERBOSE(("pk algo: ECDSA secp256r1"));
} else if (memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x08",
pki_algo.len) == 0) {
cert->is_ec_pubkey = 1;
MG_VERBOSE(("pk algo: ECDSA secp384r1"));
} else if (memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x02\x01",
pki_algo.len) == 0) {
cert->is_ec_pubkey = 1;
MG_VERBOSE(("pk algo: EC public key"));
} else if (memcmp(pki_algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01",
pki_algo.len) == 0) {
cert->is_ec_pubkey = 0;
MG_VERBOSE(("pk algo: RSA"));
} else {
MG_ERROR(("unsupported pk algo: %M", mg_print_hex, pki_algo.len,
pki_algo.value));
return -1;
}
// Parse public key
if (cert->is_ec_pubkey) {
if (mg_der_next(&pki, &pki_curve) <= 0 || pki_curve.type != 0x06) return -1;
}
if (mg_der_next(&field, &pki_key) <= 0 || pki_key.type != 0x03) return -1;
if (cert->is_ec_pubkey) { // Skip leading 0x00 and 0x04 (=uncompressed)
cert->pubkey = mg_str_n((char *) pki_key.value + 2, pki_key.len - 2);
} else { // Skip leading 0x00 byte
cert->pubkey = mg_str_n((char *) pki_key.value + 1, pki_key.len - 1);
}
// Parse signature
if (mg_der_next(&root, &field) <= 0 || field.type != 0x30) return -1;
if (mg_der_next(&root, &raw_sig) <= 0 || raw_sig.type != 0x03) return -1;
if (raw_sig.len < 1 || raw_sig.value[0] != 0x00) return -1;
cert->sig = mg_str_n((char *) raw_sig.value + 1, raw_sig.len - 1);
MG_VERBOSE(("sig: %M", mg_print_hex, cert->sig.len, cert->sig.buf));
return 0;
}
static int mg_tls_verify_cert_san(const uint8_t *der, size_t dersz,
const char *server_name) {
struct mg_der_tlv root, field, name;
if (mg_der_parse((uint8_t *) der, dersz, &root) < 0 ||
mg_der_find_oid(&root, (uint8_t *) "\x55\x1d\x11", 3, &field) < 0) {
MG_ERROR(("failed to parse certificate to extract SAN"));
return -1;
}
if (mg_der_parse(field.value, field.len, &field) < 0) {
MG_ERROR(
("certificate subject alternative names is not a constructed object"));
return -1;
}
while (mg_der_next(&field, &name) > 0) {
if (mg_match(mg_str(server_name),
mg_str_n((const char *) name.value, name.len), NULL)) {
// Found SAN that matches the host name
return 1;
}
}
return -1;
}
static int mg_tls_verify_cert_signature(const struct mg_tls_cert *cert,
const struct mg_tls_cert *issuer) {
if (issuer->is_ec_pubkey) {
uint8_t sig[128];
struct mg_der_tlv seq = {0, 0, 0}, a = {0, 0, 0}, b = {0, 0, 0};
mg_der_parse((uint8_t *) cert->sig.buf, cert->sig.len, &seq);
mg_der_next(&seq, &a);
mg_der_next(&seq, &b);
if (a.len == 0 || b.len == 0) {
MG_ERROR(("cert verification error"));
return 0;
}
if (issuer->pubkey.len == 64) {
const uint32_t N = 32;
if (a.len > N) a.value += (a.len - N), a.len = N;
if (b.len > N) b.value += (b.len - N), b.len = N;
memmove(sig, a.value, N);
memmove(sig + N, b.value, N);
return mg_uecc_verify((uint8_t *) issuer->pubkey.buf, cert->tbshash,
(unsigned) cert->tbshashsz, sig,
mg_uecc_secp256r1());
} else if (issuer->pubkey.len == 96) {
MG_DEBUG(("ignore secp386 for now"));
return 1;
} else {
MG_ERROR(("unsupported public key length: %d", issuer->pubkey.len));
return 0;
}
} else {
int r;
uint8_t sig2[256]; // 2048 bits
struct mg_der_tlv seq, modulus, exponent;
if (mg_der_parse((uint8_t *) issuer->pubkey.buf, issuer->pubkey.len,
&seq) <= 0 ||
mg_der_next(&seq, &modulus) <= 0 || modulus.type != 2 ||
mg_der_next(&seq, &exponent) <= 0 || exponent.type != 2) {
return -1;
}
mg_rsa_mod_pow(modulus.value, modulus.len, exponent.value, exponent.len,
(uint8_t *) cert->sig.buf, cert->sig.len, sig2,
sizeof(sig2));
r = memcmp(sig2 + sizeof(sig2) - cert->tbshashsz, cert->tbshash,
cert->tbshashsz);
return r == 0;
}
}
static int mg_tls_client_recv_cert(struct mg_connection *c) {
uint8_t *cert;
uint32_t certsz;
struct mg_der_tlv oid, pubkey, seq, subj;
int subj_match = 0;
struct tls_data *tls = (struct tls_data *) c->tls;
unsigned char *recv_buf;
(void) subj_match;
if (mg_tls_recv_record(c) < 0) {
return -1;
}
recv_buf = &c->rtls.buf[tls->recv_offset];
if (recv_buf[0] == MG_TLS_CERTIFICATE_REQUEST) {
MG_VERBOSE(("got certificate request"));
mg_tls_drop_message(c);
tls->cert_requested = 1;
return -1;
}
if (recv_buf[0] != MG_TLS_CERTIFICATE) {
mg_error(c, "expected server certificate but got msg 0x%02x", recv_buf[0]);
return -1;
}
if (tls->skip_verification) {
mg_tls_drop_message(c);
return 0;
}
if (tls->recv_len < 11) {
mg_error(c, "certificate list too short");
return -1;
}
cert = recv_buf + 11;
certsz = MG_LOAD_BE24(recv_buf + 8);
if (certsz > tls->recv_len - 11) {
mg_error(c, "certificate too long: %d vs %d", certsz, tls->recv_len - 11);
uint32_t full_cert_chain_len = MG_LOAD_BE24(recv_buf + 1);
uint32_t cert_chain_len = MG_LOAD_BE24(recv_buf + 5);
if (cert_chain_len != full_cert_chain_len - 4) {
MG_ERROR(("full chain length: %d, chain length: %d", full_cert_chain_len,
cert_chain_len));
mg_error(c, "certificate chain length mismatch");
return -1;
}
do {
// secp256r1 public key
if (mg_der_find(cert, certsz,
(uint8_t *) "\x2A\x86\x48\xCE\x3D\x03\x01\x07", 8,
&oid) < 0) {
mg_error(c, "certificate secp256r1 public key OID not found");
// Normally, there are 2-3 certs in a chain
struct mg_tls_cert certs[8];
int certnum = 0;
uint8_t *p = recv_buf + 8;
//uint8_t *endp = recv_buf + tls->recv_len;
uint8_t *endp = recv_buf + cert_chain_len;
int found_ca = 0;
struct mg_tls_cert ca;
memset(certs, 0, sizeof(certs));
memset(&ca, 0, sizeof(ca));
if (tls->ca_der.len > 0) {
if (mg_tls_parse_cert_der(tls->ca_der.buf, tls->ca_der.len, &ca) < 0) {
mg_error(c, "failed to parse CA certificate");
return -1;
}
if (mg_der_to_tlv(oid.value + oid.len,
(size_t) (cert + certsz - (oid.value + oid.len)),
&pubkey) < 0) {
mg_error(c, "certificate secp256r1 public key not found");
MG_VERBOSE(("CA serial: %M", mg_print_hex, ca.sn.len, ca.sn.buf));
}
while (p < endp) {
struct mg_tls_cert *ci = &certs[certnum++];
uint32_t certsz = MG_LOAD_BE24(p);
uint8_t *cert = p + 3;
uint16_t certext = MG_LOAD_BE16(cert + certsz);
if (certext != 0) {
mg_error(c, "certificate extensions are not supported");
return -1;
}
p = cert + certsz + 2;
if (mg_tls_parse_cert_der(cert, certsz, ci) < 0) {
mg_error(c, "failed to parse certificate");
return -1;
}
// expect BIT STRING, unpadded, uncompressed: [0]+[4]+32+32 content bytes
if (pubkey.type != 3 || pubkey.len != 66 || pubkey.value[0] != 0 ||
pubkey.value[1] != 4) {
mg_error(c, "unsupported public key bitstring encoding");
return -1;
}
memmove(tls->pubkey, pubkey.value + 2, pubkey.len - 2);
} while (0);
// Subject Alternative Names
do {
if (mg_der_find(cert, certsz, (uint8_t *) "\x55\x1d\x11", 3, &oid) < 0) {
mg_error(c, "certificate does not contain subject alternative names");
return -1;
}
if (mg_der_to_tlv(oid.value + oid.len,
(size_t) (cert + certsz - (oid.value + oid.len)),
&seq) < 0) {
mg_error(c, "certificate subject alternative names not found");
return -1;
}
if (mg_der_to_tlv(seq.value, seq.len, &seq) < 0) {
mg_error(
c,
"certificate subject alternative names is not a constructed object");
return -1;
}
MG_VERBOSE(("verify hostname %s", tls->hostname));
while (seq.len > 0) {
if (mg_der_to_tlv(seq.value, seq.len, &subj) < 0) {
mg_error(c, "bad subject alternative name");
if (ci == certs) {
// First certificate in the chain is peer cert, check SAN and store
// public key for further CertVerify step
if (mg_tls_verify_cert_san(cert, certsz, tls->hostname) <= 0) {
mg_error(c, "failed to verify hostname");
return -1;
}
MG_VERBOSE(("subj=%.*s", subj.len, subj.value));
if (mg_match(mg_str((const char *) tls->hostname),
mg_str_n((const char *) subj.value, subj.len), NULL)) {
subj_match = 1;
break;
memmove(tls->pubkey, ci->pubkey.buf, ci->pubkey.len);
tls->pubkeysz = ci->pubkey.len;
} else {
if (!mg_tls_verify_cert_signature(ci - 1, ci)) {
mg_error(c, "failed to verify certificate chain");
return -1;
}
seq.len = (uint32_t) (seq.value + seq.len - (subj.value + subj.len));
seq.value = subj.value + subj.len;
}
if (!subj_match) {
mg_error(c, "certificate did not match the hostname");
if (ca.pubkey.len == ci->pubkey.len &&
memcmp(ca.pubkey.buf, ci->pubkey.buf, ca.pubkey.len) == 0) {
found_ca = 1;
break;
}
if (certnum == sizeof(certs) / sizeof(certs[0]) - 1) {
mg_error(c, "too many certificates in the chain");
return -1;
}
} while (0);
}
if (!found_ca && tls->ca_der.len > 0) {
if (certnum < 1 ||
!mg_tls_verify_cert_signature(&certs[certnum - 1], &ca)) {
mg_error(c, "failed to verify CA");
return -1;
} else {
MG_VERBOSE(
("CA was not in the chain, but verification with builtin CA passed"));
}
}
mg_tls_drop_message(c);
mg_tls_calc_cert_verify_hash(c, tls->sighash, 0);
@@ -1061,51 +1346,94 @@ static int mg_tls_client_recv_cert_verify(struct mg_connection *c) {
}
recv_buf = &c->rtls.buf[tls->recv_offset];
if (recv_buf[0] != MG_TLS_CERTIFICATE_VERIFY) {
mg_error(c, "expected server certificate verify but got msg 0x%02x", recv_buf[0]);
mg_error(c, "expected server certificate verify but got msg 0x%02x",
recv_buf[0]);
return -1;
}
if (tls->recv_len < 8) {
mg_error(c, "server certificate verify is too short: %d bytes",
tls->recv_len);
return -1;
}
// Ignore CertificateVerify is strict checks are not required
if (tls->skip_verification) {
mg_tls_drop_message(c);
return 0;
}
// Extract certificate signature and verify it using pubkey and sighash
do {
uint16_t sigalg = MG_LOAD_BE16(recv_buf + 4);
uint16_t siglen = MG_LOAD_BE16(recv_buf + 6);
uint8_t *sigbuf = recv_buf + 8;
if (siglen > tls->recv_len - 8) {
mg_error(c, "invalid certverify signature length: %d, expected %d", siglen,
tls->recv_len - 8);
return -1;
}
MG_VERBOSE(("certificate verification, algo=%04x, siglen=%d", sigalg, siglen));
if (sigalg == 0x0804) { // rsa_pss_rsae_sha256
uint8_t sig2[512]; // 2048 or 4096 bits
struct mg_der_tlv seq, modulus, exponent;
if (mg_der_parse(tls->pubkey, tls->pubkeysz, &seq) <= 0 ||
mg_der_next(&seq, &modulus) <= 0 || modulus.type != 2 ||
mg_der_next(&seq, &exponent) <= 0 || exponent.type != 2) {
mg_error(c, "invalid public key");
return -1;
}
mg_rsa_mod_pow(modulus.value, modulus.len, exponent.value, exponent.len,
sigbuf, siglen, sig2, sizeof(sig2));
if (sig2[sizeof(sig2) - 1] != 0xbc) {
mg_error(c, "failed to verify RSA certificate (certverify)");
return -1;
}
MG_DEBUG(("certificate verification successful (RSA)"));
} else if (sigalg == 0x0403) { // ecdsa_secp256r1_sha256
// Extract certificate signature and verify it using pubkey and sighash
uint8_t sig[64];
struct mg_der_tlv seq, a, b;
if (mg_der_to_tlv(recv_buf + 8, tls->recv_len - 8, &seq) < 0) {
struct mg_der_tlv seq, r, s;
if (mg_der_to_tlv(sigbuf, siglen, &seq) < 0) {
mg_error(c, "verification message is not an ASN.1 DER sequence");
return -1;
}
if (mg_der_to_tlv(seq.value, seq.len, &a) < 0) {
if (mg_der_to_tlv(seq.value, seq.len, &r) < 0) {
mg_error(c, "missing first part of the signature");
return -1;
}
if (mg_der_to_tlv(a.value + a.len, seq.len - a.len, &b) < 0) {
if (mg_der_to_tlv(r.value + r.len, seq.len - r.len, &s) < 0) {
mg_error(c, "missing second part of the signature");
return -1;
}
// Integers may be padded with zeroes
if (a.len > 32) {
a.value = a.value + (a.len - 32);
a.len = 32;
}
if (b.len > 32) {
b.value = b.value + (b.len - 32);
b.len = 32;
}
if (r.len > 32) r.value = r.value + (r.len - 32), r.len = 32;
if (s.len > 32) s.value = s.value + (s.len - 32), s.len = 32;
memmove(sig, a.value, a.len);
memmove(sig + 32, b.value, b.len);
memmove(sig, r.value, r.len);
memmove(sig + 32, s.value, s.len);
if (mg_uecc_verify(tls->pubkey, tls->sighash, sizeof(tls->sighash), sig,
mg_uecc_secp256r1()) != 1) {
mg_error(c, "failed to verify certificate");
mg_error(c, "failed to verify EC certificate (certverify)");
return -1;
}
} while (0);
MG_DEBUG(("certificate verification successful (EC)"));
} else {
// From
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml:
// 0805 = rsa_pss_rsae_sha384
// 0806 = rsa_pss_rsae_sha512
// 0807 = ed25519
// 0808 = ed448
// 0809 = rsa_pss_pss_sha256
// 080A = rsa_pss_pss_sha384
// 080B = rsa_pss_pss_sha512
MG_ERROR(("unsupported certverify signature scheme: %x of %d bytes", sigalg,
siglen));
return -1;
}
mg_tls_drop_message(c);
return 0;
}
@@ -1195,9 +1523,7 @@ static void mg_tls_client_handshake(struct mg_connection *c) {
c->is_tls_hs = 0;
mg_call(c, MG_EV_TLS_HS, NULL);
break;
default:
mg_error(c, "unexpected client state: %d", tls->state);
break;
default: mg_error(c, "unexpected client state: %d", tls->state); break;
}
}
@@ -1224,9 +1550,7 @@ static void mg_tls_server_handshake(struct mg_connection *c) {
tls->state = MG_TLS_STATE_SERVER_CONNECTED;
c->is_tls_hs = 0;
return;
default:
mg_error(c, "unexpected server state: %d", tls->state);
break;
default: mg_error(c, "unexpected server state: %d", tls->state); break;
}
}
@@ -1283,7 +1607,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
c->is_client ? MG_TLS_STATE_CLIENT_START : MG_TLS_STATE_SERVER_START;
tls->skip_verification = opts->skip_verification;
//tls->send.align = MG_IO_SIZE;
// tls->send.align = MG_IO_SIZE;
c->tls = tls;
c->is_tls = c->is_tls_hs = 1;
@@ -1298,9 +1622,16 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
strncpy((char *) tls->hostname, opts->name.buf, sizeof(tls->hostname) - 1);
tls->hostname[opts->name.len] = 0;
}
// server CA certificate, store serial number
if (opts->ca.len > 0) {
if (mg_parse_pem(opts->ca, mg_str_s("CERTIFICATE"), &tls->ca_der) < 0) {
MG_ERROR(("Failed to load certificate"));
return;
}
}
if (opts->cert.buf == NULL) {
MG_VERBOSE(("no certificate provided"));
MG_VERBOSE(("No certificate provided"));
return;
}
@@ -1312,7 +1643,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
// parse PEM or DER EC key
if (opts->key.buf == NULL) {
mg_error(c, "certificate provided without a private key");
mg_error(c, "Certificate provided without a private key");
return;
}
@@ -1335,7 +1666,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
} else if (mg_parse_pem(opts->key, mg_str_s("PRIVATE KEY"), &key) == 0) {
mg_error(c, "PKCS8 private key format is not supported");
} else {
mg_error(c, "expected EC PRIVATE KEY or PRIVATE KEY");
mg_error(c, "Expected EC PRIVATE KEY or PRIVATE KEY");
}
}
@@ -1344,6 +1675,7 @@ void mg_tls_free(struct mg_connection *c) {
if (tls != NULL) {
mg_iobuf_free(&tls->send);
free((void *) tls->cert_der.buf);
free((void *) tls->ca_der.buf);
}
free(c->tls);
c->tls = NULL;
+2
View File
@@ -104,10 +104,12 @@ static void initialize_state(uint32_t state[CHACHA20_STATE_WORDS],
const uint8_t key[CHACHA20_KEY_SIZE],
const uint8_t nonce[CHACHA20_NONCE_SIZE],
uint32_t counter) {
#if 0
#ifdef static_assert
static_assert(sizeof(uint32_t) == 4,
"We don't support systems that do not conform to standard of "
"uint32_t being exact 32bit wide");
#endif
#endif
state[0] = 0x61707865;
state[1] = 0x3320646e;
+1579
View File
File diff suppressed because it is too large. Load diff
+7
View File
@@ -0,0 +1,7 @@
#ifndef TLS_RSA_H
#define TLS_RSA_H
#include "arch.h"
int mg_rsa_mod_pow(const uint8_t *mod, size_t modsz, const uint8_t *exp, size_t expsz, const uint8_t *msg, size_t msgsz, uint8_t *out, size_t outsz);
#endif // TLS_RSA_H
+6
View File
@@ -42,6 +42,12 @@ bool mg_path_is_sane(const struct mg_str path);
MG_U8P(p)[0] = ((n) >> 8U) & 255; \
MG_U8P(p)[1] = (n) &255; \
} while (0)
#define MG_STORE_BE24(p, n) \
do { \
MG_U8P(p)[0] = ((n) >> 16U) & 255; \
MG_U8P(p)[1] = ((n) >> 8U) & 255; \
MG_U8P(p)[2] = (n) &255; \
} while (0)
#define MG_REG(x) ((volatile uint32_t *) (x))[0]
#define MG_BIT(x) (((uint32_t) 1U) << (x))
+1 -1
View File
@@ -209,7 +209,7 @@ mongoose.c: Makefile $(wildcard ../src/*.c) $(wildcard ../src/drivers/*.c)
cd .. && (export LC_ALL=C ; cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c src/drivers/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
mongoose.h: $(HDRS) Makefile
cd .. && (cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_ft.h src/net_lwip.h src/net_rl.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/sha256.h src/tls_x25519.h src/tls_aes128.h src/tls_uecc.h src/tls_chacha20.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/ota.h src/flash.h src/net_builtin.h src/profile.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
cd .. && (cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_ft.h src/net_lwip.h src/net_rl.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/sha256.h src/tls_x25519.h src/tls_aes128.h src/tls_uecc.h src/tls_chacha20.h src/tls_rsa.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/ota.h src/flash.h src/net_builtin.h src/profile.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
clean: clean_examples clean_refprojs clean_tutorials clean_examples_embedded
+134
View File
@@ -1,5 +1,139 @@
- Make sure your PEM file starts with a dash -
Issuer: C=US, O=Internet Security Research Group, CN=ISRG Root X1
Not Before: Mar 13 00:00:00 2024 GMT
Not After : Mar 12 23:59:59 2027 GMT
-----BEGIN CERTIFICATE-----
MIIEVzCCAj+gAwIBAgIRALBXPpFzlydw27SHyzpFKzgwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDELMAkGA1UEAxMCRTYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATZ8Z5G
h/ghcWCoJuuj+rnq2h25EqfUJtlRFLFhfHWWvyILOR/VvtEKRqotPEoJhC6+QJVV
6RlAN2Z17TJOdwRJ+HB7wxjnzvdxEP6sdNgA1O1tHHMWMxCcOrLqbGL0vbijgfgw
gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSTJ0aYA6lRaI6Y1sRCSNsj
v1iU0jAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB
AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g
BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAfYt7SiA1sgWGCIpunk46r4AExIRc
MxkKgUhNlrrv1B21hOaXN/5miE+LOTbrcmU/M9yvC6MVY730GNFoL8IhJ8j8vrOL
pMY22OP6baS1k9YMrtDTlwJHoGby04ThTUeBDksS9RiuHvicZqBedQdIF65pZuhp
eDcGBcLiYasQr/EO5gxxtLyTmgsHSOVSBcFOn9lgv7LECPq9i7mfH3mpxgrRKSxH
pOoZ0KXMcB+hHuvlklHntvcI0mMMQ0mhYj6qtMFStkF1RpCG3IPdIwpVCQqu8GV7
s8ubknRzs+3C/Bm19RFOoiPpDkwvyNfvmQ14XkyqqKK5oZ8zhD32kFRQkxa8uZSu
h4aTImFxknu39waBxIRXE4jKxlAmQc4QjFZoq1KmQqQg0J/1JF8RlFvJas1VcjLv
YlvUB2t6npO6oQjB3l+PNf0DpQH7iUx3Wz5AjQCi6L25FjyE06q6BZ/QlmtYdl/8
ZYao4SRqPEs/6cAiF+Qf5zg2UkaWtDphl1LKMuTNLotvsX99HP69V2faNyegodQ0
LyTApr/vT01YPE46vNsDLgK+4cL6TrzC/a4WcmF5SRJ938zrv/duJHLXQIku5v0+
EwOy59Hdm0PT/Er/84dDV0CSjdR/2XuZM3kpysSKLgD1cKiDA+IRguODCxfO9cyY
Ig46v9mFmBvyH04=
-----END CERTIFICATE-----
Issuer: C=US, O=Internet Security Research Group, CN=ISRG Root X1
Not Before: Mar 13 00:00:00 2024 GMT
Not After : Mar 12 23:59:59 2027 GMT
-----BEGIN CERTIFICATE-----
MIIEVzCCAj+gAwIBAgIRAIOPbGPOsTmMYgZigxXJ/d4wDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw
WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDELMAkGA1UEAxMCRTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNCzqK
a2GOtu/cX1jnxkJFVKtj9mZhSAouWXW0gQI3ULc/FnncmOyhKJdyIBwsz9V8UiBO
VHhbhBRrwJCuhezAUUE8Wod/Bk3U/mDR+mwt4X2VEIiiCFQPmRpM5uoKrNijgfgw
gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD
ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSfK1/PPCFPnQS37SssxMZw
i9LXDTAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB
AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g
BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu
Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAH3KdNEVCQdqk0LKyuNImTKdRJY1C
2uw2SJajuhqkyGPY8C+zzsufZ+mgnhnq1A2KVQOSykOEnUbx1cy637rBAihx97r+
bcwbZM6sTDIaEriR/PLk6LKs9Be0uoVxgOKDcpG9svD33J+G9Lcfv1K9luDmSTgG
6XNFIN5vfI5gs/lMPyojEMdIzK9blcl2/1vKxO8WGCcjvsQ1nJ/Pwt8LQZBfOFyV
XP8ubAp/au3dc4EKWG9MO5zcx1qT9+NXRGdVWxGvmBFRAajciMfXME1ZuGmk3/GO
koAM7ZkjZmleyokP1LGzmfJcUd9s7eeu1/9/eg5XlXd/55GtYjAM+C4DG5i7eaNq
cm2F+yxYIPt6cbbtYVNJCGfHWqHEQ4FYStUyFnv8sjyqU8ypgZaNJ9aVcWSICLOI
E1/Qv/7oKsnZCWJ926wU6RqG1OYPGOi1zuABhLw61cuPVDT28nQS/e6z95cJXq0e
K1BcaJ6fJZsmbjRgD5p3mvEf5vdQM7MCEvU0tHbsx2I5mHHJoABHb8KVBgWp/lcX
GWiWaeOyB7RP+OfDtvi2OsapxXiV7vNVs7fMlrRjY1joKaqmmycnBvAq14AEbtyL
sVfOS66B8apkeFX2NY4XPEYV4ZSCe8VHPrdrERk2wILG3T/EGmSIkCYVUMSnjmJd
VQD9F6Na/+zmXCc=
-----END CERTIFICATE-----
Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R1
Not Before: Jun 22 00:00:00 2016 GMT
Not After : Jun 22 00:00:00 2036 GMT
-----BEGIN CERTIFICATE-----
MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA
A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo
27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w
Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw
TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl
qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH
szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8
Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk
MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p
aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN
VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID
AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb
C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy
h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4
7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J
ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef
MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/
Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT
6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ
0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm
2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb
bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c
-----END CERTIFICATE-----
Issuer: OU=GlobalSign ECC Root CA - R4, O=GlobalSign, CN=GlobalSign
Not Before: Nov 13 00:00:00 2012 GMT
Not After : Jan 19 03:14:07 2038 GMT
-----BEGIN CERTIFICATE-----
MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD
VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh
bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw
MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g
UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT
BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx
uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV
HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/
+wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147
bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm
-----END CERTIFICATE-----
Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R4
Not Before: Jun 22 00:00:00 2016 GMT
Not After : Jun 22 00:00:00 2036 GMT
-----BEGIN CERTIFICATE-----
MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD
VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG
A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw
WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz
IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi
QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR
HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D
9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8
p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD
-----END CERTIFICATE-----
Issuer: C = US, O = Internet Security Research Group, CN = ISRG Root X1
Not Before: Jun 4 11:04:38 2015 GMT
Not After : Jun 4 11:04:38 2035 GMT
+1 -1
View File
@@ -1327,7 +1327,7 @@ static void test_tls(void) {
"Content-Length: %lu\n\n"
"%s",
data.len, data.buf) == 200);
#if MG_TLS == MG_TLS_BUILTIN
#if MG_TLS == MG_TLS_BUILTIN && defined(__linux__)
// fire patched server, test multiple TLS records per TCP segment handling
// skip other TLS stacks to avoid "bad client hello", we are 1.3 only
{
+590 -1
View File
@@ -16,6 +16,595 @@ static const unsigned char v1[] = {
121, 111, 117, 114, 32, 80, 69, 77, 32, 102, 105, 108, // your PEM fil
101, 32, 115, 116, 97, 114, 116, 115, 32, 119, 105, 116, // e starts wit
104, 32, 97, 32, 100, 97, 115, 104, 32, 45, 10, 10, // h a dash -..
10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, // .-----BEGIN
67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, // CERTIFICATE-
45, 45, 45, 45, 10, 77, 73, 73, 69, 86, 122, 67, // ----.MIIEVzC
67, 65, 106, 43, 103, 65, 119, 73, 66, 65, 103, 73, // CAj+gAwIBAgI
82, 65, 76, 66, 88, 80, 112, 70, 122, 108, 121, 100, // RALBXPpFzlyd
119, 50, 55, 83, 72, 121, 122, 112, 70, 75, 122, 103, // w27SHyzpFKzg
119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, // wDQYJKoZIhvc
78, 65, 81, 69, 76, 66, 81, 65, 119, 10, 84, 122, // NAQELBQAw.Tz
69, 76, 77, 65, 107, 71, 65, 49, 85, 69, 66, 104, // ELMAkGA1UEBh
77, 67, 86, 86, 77, 120, 75, 84, 65, 110, 66, 103, // MCVVMxKTAnBg
78, 86, 66, 65, 111, 84, 73, 69, 108, 117, 100, 71, // NVBAoTIEludG
86, 121, 98, 109, 86, 48, 73, 70, 78, 108, 89, 51, // VybmV0IFNlY3
86, 121, 97, 88, 82, 53, 73, 70, 74, 108, 99, 50, // VyaXR5IFJlc2
86, 104, 10, 99, 109, 78, 111, 73, 69, 100, 121, 98, // Vh.cmNoIEdyb
51, 86, 119, 77, 82, 85, 119, 69, 119, 89, 68, 86, // 3VwMRUwEwYDV
81, 81, 68, 69, 119, 120, 74, 85, 49, 74, 72, 73, // QQDEwxJU1JHI
70, 74, 118, 98, 51, 81, 103, 87, 68, 69, 119, 72, // FJvb3QgWDEwH
104, 99, 78, 77, 106, 81, 119, 77, 122, 69, 122, 77, // hcNMjQwMzEzM
68, 65, 119, 77, 68, 65, 119, 10, 87, 104, 99, 78, // DAwMDAw.WhcN
77, 106, 99, 119, 77, 122, 69, 121, 77, 106, 77, 49, // MjcwMzEyMjM1
79, 84, 85, 53, 87, 106, 65, 121, 77, 81, 115, 119, // OTU5WjAyMQsw
67, 81, 89, 68, 86, 81, 81, 71, 69, 119, 74, 86, // CQYDVQQGEwJV
85, 122, 69, 87, 77, 66, 81, 71, 65, 49, 85, 69, // UzEWMBQGA1UE
67, 104, 77, 78, 84, 71, 86, 48, 74, 51, 77, 103, // ChMNTGV0J3Mg
10, 82, 87, 53, 106, 99, 110, 108, 119, 100, 68, 69, // .RW5jcnlwdDE
76, 77, 65, 107, 71, 65, 49, 85, 69, 65, 120, 77, // LMAkGA1UEAxM
67, 82, 84, 89, 119, 100, 106, 65, 81, 66, 103, 99, // CRTYwdjAQBgc
113, 104, 107, 106, 79, 80, 81, 73, 66, 66, 103, 85, // qhkjOPQIBBgU
114, 103, 81, 81, 65, 73, 103, 78, 105, 65, 65, 84, // rgQQAIgNiAAT
90, 56, 90, 53, 71, 10, 104, 47, 103, 104, 99, 87, // Z8Z5G.h/ghcW
67, 111, 74, 117, 117, 106, 43, 114, 110, 113, 50, 104, // CoJuuj+rnq2h
50, 53, 69, 113, 102, 85, 74, 116, 108, 82, 70, 76, // 25EqfUJtlRFL
70, 104, 102, 72, 87, 87, 118, 121, 73, 76, 79, 82, // FhfHWWvyILOR
47, 86, 118, 116, 69, 75, 82, 113, 111, 116, 80, 69, // /VvtEKRqotPE
111, 74, 104, 67, 54, 43, 81, 74, 86, 86, 10, 54, // oJhC6+QJVV.6
82, 108, 65, 78, 50, 90, 49, 55, 84, 74, 79, 100, // RlAN2Z17TJOd
119, 82, 74, 43, 72, 66, 55, 119, 120, 106, 110, 122, // wRJ+HB7wxjnz
118, 100, 120, 69, 80, 54, 115, 100, 78, 103, 65, 49, // vdxEP6sdNgA1
79, 49, 116, 72, 72, 77, 87, 77, 120, 67, 99, 79, // O1tHHMWMxCcO
114, 76, 113, 98, 71, 76, 48, 118, 98, 105, 106, 103, // rLqbGL0vbijg
102, 103, 119, 10, 103, 102, 85, 119, 68, 103, 89, 68, // fgw.gfUwDgYD
86, 82, 48, 80, 65, 81, 72, 47, 66, 65, 81, 68, // VR0PAQH/BAQD
65, 103, 71, 71, 77, 66, 48, 71, 65, 49, 85, 100, // AgGGMB0GA1Ud
74, 81, 81, 87, 77, 66, 81, 71, 67, 67, 115, 71, // JQQWMBQGCCsG
65, 81, 85, 70, 66, 119, 77, 67, 66, 103, 103, 114, // AQUFBwMCBggr
66, 103, 69, 70, 66, 81, 99, 68, 10, 65, 84, 65, // BgEFBQcD.ATA
83, 66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, // SBgNVHRMBAf8
69, 67, 68, 65, 71, 65, 81, 72, 47, 65, 103, 69, // ECDAGAQH/AgE
65, 77, 66, 48, 71, 65, 49, 85, 100, 68, 103, 81, // AMB0GA1UdDgQ
87, 66, 66, 83, 84, 74, 48, 97, 89, 65, 54, 108, // WBBSTJ0aYA6l
82, 97, 73, 54, 89, 49, 115, 82, 67, 83, 78, 115, // RaI6Y1sRCSNs
106, 10, 118, 49, 105, 85, 48, 106, 65, 102, 66, 103, // j.v1iU0jAfBg
78, 86, 72, 83, 77, 69, 71, 68, 65, 87, 103, 66, // NVHSMEGDAWgB
82, 53, 116, 70, 110, 109, 101, 55, 98, 108, 53, 65, // R5tFnme7bl5A
70, 122, 103, 65, 105, 73, 121, 66, 112, 89, 57, 117, // FzgAiIyBpY9u
109, 98, 98, 106, 65, 121, 66, 103, 103, 114, 66, 103, // mbbjAyBggrBg
69, 70, 66, 81, 99, 66, 10, 65, 81, 81, 109, 77, // EFBQcB.AQQmM
67, 81, 119, 73, 103, 89, 73, 75, 119, 89, 66, 66, // CQwIgYIKwYBB
81, 85, 72, 77, 65, 75, 71, 70, 109, 104, 48, 100, // QUHMAKGFmh0d
72, 65, 54, 76, 121, 57, 52, 77, 83, 53, 112, 76, // HA6Ly94MS5pL
109, 120, 108, 98, 109, 78, 121, 76, 109, 57, 121, 90, // mxlbmNyLm9yZ
121, 56, 119, 69, 119, 89, 68, 86, 82, 48, 103, 10, // y8wEwYDVR0g.
66, 65, 119, 119, 67, 106, 65, 73, 66, 103, 90, 110, // BAwwCjAIBgZn
103, 81, 119, 66, 65, 103, 69, 119, 74, 119, 89, 68, // gQwBAgEwJwYD
86, 82, 48, 102, 66, 67, 65, 119, 72, 106, 65, 99, // VR0fBCAwHjAc
111, 66, 113, 103, 71, 73, 89, 87, 97, 72, 82, 48, // oBqgGIYWaHR0
99, 68, 111, 118, 76, 51, 103, 120, 76, 109, 77, 117, // cDovL3gxLmMu
98, 71, 86, 117, 10, 89, 51, 73, 117, 98, 51, 74, // bGVu.Y3Iub3J
110, 76, 122, 65, 78, 66, 103, 107, 113, 104, 107, 105, // nLzANBgkqhki
71, 57, 119, 48, 66, 65, 81, 115, 70, 65, 65, 79, // G9w0BAQsFAAO
67, 65, 103, 69, 65, 102, 89, 116, 55, 83, 105, 65, // CAgEAfYt7SiA
49, 115, 103, 87, 71, 67, 73, 112, 117, 110, 107, 52, // 1sgWGCIpunk4
54, 114, 52, 65, 69, 120, 73, 82, 99, 10, 77, 120, // 6r4AExIRc.Mx
107, 75, 103, 85, 104, 78, 108, 114, 114, 118, 49, 66, // kKgUhNlrrv1B
50, 49, 104, 79, 97, 88, 78, 47, 53, 109, 105, 69, // 21hOaXN/5miE
43, 76, 79, 84, 98, 114, 99, 109, 85, 47, 77, 57, // +LOTbrcmU/M9
121, 118, 67, 54, 77, 86, 89, 55, 51, 48, 71, 78, // yvC6MVY730GN
70, 111, 76, 56, 73, 104, 74, 56, 106, 56, 118, 114, // FoL8IhJ8j8vr
79, 76, 10, 112, 77, 89, 50, 50, 79, 80, 54, 98, // OL.pMY22OP6b
97, 83, 49, 107, 57, 89, 77, 114, 116, 68, 84, 108, // aS1k9YMrtDTl
119, 74, 72, 111, 71, 98, 121, 48, 52, 84, 104, 84, // wJHoGby04ThT
85, 101, 66, 68, 107, 115, 83, 57, 82, 105, 117, 72, // UeBDksS9RiuH
118, 105, 99, 90, 113, 66, 101, 100, 81, 100, 73, 70, // vicZqBedQdIF
54, 53, 112, 90, 117, 104, 112, 10, 101, 68, 99, 71, // 65pZuhp.eDcG
66, 99, 76, 105, 89, 97, 115, 81, 114, 47, 69, 79, // BcLiYasQr/EO
53, 103, 120, 120, 116, 76, 121, 84, 109, 103, 115, 72, // 5gxxtLyTmgsH
83, 79, 86, 83, 66, 99, 70, 79, 110, 57, 108, 103, // SOVSBcFOn9lg
118, 55, 76, 69, 67, 80, 113, 57, 105, 55, 109, 102, // v7LECPq9i7mf
72, 51, 109, 112, 120, 103, 114, 82, 75, 83, 120, 72, // H3mpxgrRKSxH
10, 112, 79, 111, 90, 48, 75, 88, 77, 99, 66, 43, // .pOoZ0KXMcB+
104, 72, 117, 118, 108, 107, 108, 72, 110, 116, 118, 99, // hHuvlklHntvc
73, 48, 109, 77, 77, 81, 48, 109, 104, 89, 106, 54, // I0mMMQ0mhYj6
113, 116, 77, 70, 83, 116, 107, 70, 49, 82, 112, 67, // qtMFStkF1RpC
71, 51, 73, 80, 100, 73, 119, 112, 86, 67, 81, 113, // G3IPdIwpVCQq
117, 56, 71, 86, 55, 10, 115, 56, 117, 98, 107, 110, // u8GV7.s8ubkn
82, 122, 115, 43, 51, 67, 47, 66, 109, 49, 57, 82, // Rzs+3C/Bm19R
70, 79, 111, 105, 80, 112, 68, 107, 119, 118, 121, 78, // FOoiPpDkwvyN
102, 118, 109, 81, 49, 52, 88, 107, 121, 113, 113, 75, // fvmQ14XkyqqK
75, 53, 111, 90, 56, 122, 104, 68, 51, 50, 107, 70, // K5oZ8zhD32kF
82, 81, 107, 120, 97, 56, 117, 90, 83, 117, 10, 104, // RQkxa8uZSu.h
52, 97, 84, 73, 109, 70, 120, 107, 110, 117, 51, 57, // 4aTImFxknu39
119, 97, 66, 120, 73, 82, 88, 69, 52, 106, 75, 120, // waBxIRXE4jKx
108, 65, 109, 81, 99, 52, 81, 106, 70, 90, 111, 113, // lAmQc4QjFZoq
49, 75, 109, 81, 113, 81, 103, 48, 74, 47, 49, 74, // 1KmQqQg0J/1J
70, 56, 82, 108, 70, 118, 74, 97, 115, 49, 86, 99, // F8RlFvJas1Vc
106, 76, 118, 10, 89, 108, 118, 85, 66, 50, 116, 54, // jLv.YlvUB2t6
110, 112, 79, 54, 111, 81, 106, 66, 51, 108, 43, 80, // npO6oQjB3l+P
78, 102, 48, 68, 112, 81, 72, 55, 105, 85, 120, 51, // Nf0DpQH7iUx3
87, 122, 53, 65, 106, 81, 67, 105, 54, 76, 50, 53, // Wz5AjQCi6L25
70, 106, 121, 69, 48, 54, 113, 54, 66, 90, 47, 81, // FjyE06q6BZ/Q
108, 109, 116, 89, 100, 108, 47, 56, 10, 90, 89, 97, // lmtYdl/8.ZYa
111, 52, 83, 82, 113, 80, 69, 115, 47, 54, 99, 65, // o4SRqPEs/6cA
105, 70, 43, 81, 102, 53, 122, 103, 50, 85, 107, 97, // iF+Qf5zg2Uka
87, 116, 68, 112, 104, 108, 49, 76, 75, 77, 117, 84, // WtDphl1LKMuT
78, 76, 111, 116, 118, 115, 88, 57, 57, 72, 80, 54, // NLotvsX99HP6
57, 86, 50, 102, 97, 78, 121, 101, 103, 111, 100, 81, // 9V2faNyegodQ
48, 10, 76, 121, 84, 65, 112, 114, 47, 118, 84, 48, // 0.LyTApr/vT0
49, 89, 80, 69, 52, 54, 118, 78, 115, 68, 76, 103, // 1YPE46vNsDLg
75, 43, 52, 99, 76, 54, 84, 114, 122, 67, 47, 97, // K+4cL6TrzC/a
52, 87, 99, 109, 70, 53, 83, 82, 74, 57, 51, 56, // 4WcmF5SRJ938
122, 114, 118, 47, 100, 117, 74, 72, 76, 88, 81, 73, // zrv/duJHLXQI
107, 117, 53, 118, 48, 43, 10, 69, 119, 79, 121, 53, // ku5v0+.EwOy5
57, 72, 100, 109, 48, 80, 84, 47, 69, 114, 47, 56, // 9Hdm0PT/Er/8
52, 100, 68, 86, 48, 67, 83, 106, 100, 82, 47, 50, // 4dDV0CSjdR/2
88, 117, 90, 77, 51, 107, 112, 121, 115, 83, 75, 76, // XuZM3kpysSKL
103, 68, 49, 99, 75, 105, 68, 65, 43, 73, 82, 103, // gD1cKiDA+IRg
117, 79, 68, 67, 120, 102, 79, 57, 99, 121, 89, 10, // uODCxfO9cyY.
73, 103, 52, 54, 118, 57, 109, 70, 109, 66, 118, 121, // Ig46v9mFmBvy
72, 48, 52, 61, 10, 45, 45, 45, 45, 45, 69, 78, // H04=.-----EN
68, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, // D CERTIFICAT
69, 45, 45, 45, 45, 45, 10, 10, 73, 115, 115, 117, // E-----..Issu
101, 114, 58, 32, 67, 61, 85, 83, 44, 32, 79, 61, // er: C=US, O=
73, 110, 116, 101, 114, 110, 101, 116, 32, 83, 101, 99, // Internet Sec
117, 114, 105, 116, 121, 32, 82, 101, 115, 101, 97, 114, // urity Resear
99, 104, 32, 71, 114, 111, 117, 112, 44, 32, 67, 78, // ch Group, CN
61, 73, 83, 82, 71, 32, 82, 111, 111, 116, 32, 88, // =ISRG Root X
49, 10, 78, 111, 116, 32, 66, 101, 102, 111, 114, 101, // 1.Not Before
58, 32, 77, 97, 114, 32, 49, 51, 32, 48, 48, 58, // : Mar 13 00:
48, 48, 58, 48, 48, 32, 50, 48, 50, 52, 32, 71, // 00:00 2024 G
77, 84, 10, 78, 111, 116, 32, 65, 102, 116, 101, 114, // MT.Not After
32, 58, 32, 77, 97, 114, 32, 49, 50, 32, 50, 51, // : Mar 12 23
58, 53, 57, 58, 53, 57, 32, 50, 48, 50, 55, 32, // :59:59 2027
71, 77, 84, 10, 45, 45, 45, 45, 45, 66, 69, 71, // GMT.-----BEG
73, 78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, // IN CERTIFICA
84, 69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 69, // TE-----.MIIE
86, 122, 67, 67, 65, 106, 43, 103, 65, 119, 73, 66, // VzCCAj+gAwIB
65, 103, 73, 82, 65, 73, 79, 80, 98, 71, 80, 79, // AgIRAIOPbGPO
115, 84, 109, 77, 89, 103, 90, 105, 103, 120, 88, 74, // sTmMYgZigxXJ
47, 100, 52, 119, 68, 81, 89, 74, 75, 111, 90, 73, // /d4wDQYJKoZI
104, 118, 99, 78, 65, 81, 69, 76, 66, 81, 65, 119, // hvcNAQELBQAw
10, 84, 122, 69, 76, 77, 65, 107, 71, 65, 49, 85, // .TzELMAkGA1U
69, 66, 104, 77, 67, 86, 86, 77, 120, 75, 84, 65, // EBhMCVVMxKTA
110, 66, 103, 78, 86, 66, 65, 111, 84, 73, 69, 108, // nBgNVBAoTIEl
117, 100, 71, 86, 121, 98, 109, 86, 48, 73, 70, 78, // udGVybmV0IFN
108, 89, 51, 86, 121, 97, 88, 82, 53, 73, 70, 74, // lY3VyaXR5IFJ
108, 99, 50, 86, 104, 10, 99, 109, 78, 111, 73, 69, // lc2Vh.cmNoIE
100, 121, 98, 51, 86, 119, 77, 82, 85, 119, 69, 119, // dyb3VwMRUwEw
89, 68, 86, 81, 81, 68, 69, 119, 120, 74, 85, 49, // YDVQQDEwxJU1
74, 72, 73, 70, 74, 118, 98, 51, 81, 103, 87, 68, // JHIFJvb3QgWD
69, 119, 72, 104, 99, 78, 77, 106, 81, 119, 77, 122, // EwHhcNMjQwMz
69, 122, 77, 68, 65, 119, 77, 68, 65, 119, 10, 87, // EzMDAwMDAw.W
104, 99, 78, 77, 106, 99, 119, 77, 122, 69, 121, 77, // hcNMjcwMzEyM
106, 77, 49, 79, 84, 85, 53, 87, 106, 65, 121, 77, // jM1OTU5WjAyM
81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, 69, // QswCQYDVQQGE
119, 74, 86, 85, 122, 69, 87, 77, 66, 81, 71, 65, // wJVUzEWMBQGA
49, 85, 69, 67, 104, 77, 78, 84, 71, 86, 48, 74, // 1UEChMNTGV0J
51, 77, 103, 10, 82, 87, 53, 106, 99, 110, 108, 119, // 3Mg.RW5jcnlw
100, 68, 69, 76, 77, 65, 107, 71, 65, 49, 85, 69, // dDELMAkGA1UE
65, 120, 77, 67, 82, 84, 85, 119, 100, 106, 65, 81, // AxMCRTUwdjAQ
66, 103, 99, 113, 104, 107, 106, 79, 80, 81, 73, 66, // BgcqhkjOPQIB
66, 103, 85, 114, 103, 81, 81, 65, 73, 103, 78, 105, // BgUrgQQAIgNi
65, 65, 81, 78, 67, 122, 113, 75, 10, 97, 50, 71, // AAQNCzqK.a2G
79, 116, 117, 47, 99, 88, 49, 106, 110, 120, 107, 74, // Otu/cX1jnxkJ
70, 86, 75, 116, 106, 57, 109, 90, 104, 83, 65, 111, // FVKtj9mZhSAo
117, 87, 88, 87, 48, 103, 81, 73, 51, 85, 76, 99, // uWXW0gQI3ULc
47, 70, 110, 110, 99, 109, 79, 121, 104, 75, 74, 100, // /FnncmOyhKJd
121, 73, 66, 119, 115, 122, 57, 86, 56, 85, 105, 66, // yIBwsz9V8UiB
79, 10, 86, 72, 104, 98, 104, 66, 82, 114, 119, 74, // O.VHhbhBRrwJ
67, 117, 104, 101, 122, 65, 85, 85, 69, 56, 87, 111, // CuhezAUUE8Wo
100, 47, 66, 107, 51, 85, 47, 109, 68, 82, 43, 109, // d/Bk3U/mDR+m
119, 116, 52, 88, 50, 86, 69, 73, 105, 105, 67, 70, // wt4X2VEIiiCF
81, 80, 109, 82, 112, 77, 53, 117, 111, 75, 114, 78, // QPmRpM5uoKrN
105, 106, 103, 102, 103, 119, 10, 103, 102, 85, 119, 68, // ijgfgw.gfUwD
103, 89, 68, 86, 82, 48, 80, 65, 81, 72, 47, 66, // gYDVR0PAQH/B
65, 81, 68, 65, 103, 71, 71, 77, 66, 48, 71, 65, // AQDAgGGMB0GA
49, 85, 100, 74, 81, 81, 87, 77, 66, 81, 71, 67, // 1UdJQQWMBQGC
67, 115, 71, 65, 81, 85, 70, 66, 119, 77, 67, 66, // CsGAQUFBwMCB
103, 103, 114, 66, 103, 69, 70, 66, 81, 99, 68, 10, // ggrBgEFBQcD.
65, 84, 65, 83, 66, 103, 78, 86, 72, 82, 77, 66, // ATASBgNVHRMB
65, 102, 56, 69, 67, 68, 65, 71, 65, 81, 72, 47, // Af8ECDAGAQH/
65, 103, 69, 65, 77, 66, 48, 71, 65, 49, 85, 100, // AgEAMB0GA1Ud
68, 103, 81, 87, 66, 66, 83, 102, 75, 49, 47, 80, // DgQWBBSfK1/P
80, 67, 70, 80, 110, 81, 83, 51, 55, 83, 115, 115, // PCFPnQS37Sss
120, 77, 90, 119, 10, 105, 57, 76, 88, 68, 84, 65, // xMZw.i9LXDTA
102, 66, 103, 78, 86, 72, 83, 77, 69, 71, 68, 65, // fBgNVHSMEGDA
87, 103, 66, 82, 53, 116, 70, 110, 109, 101, 55, 98, // WgBR5tFnme7b
108, 53, 65, 70, 122, 103, 65, 105, 73, 121, 66, 112, // l5AFzgAiIyBp
89, 57, 117, 109, 98, 98, 106, 65, 121, 66, 103, 103, // Y9umbbjAyBgg
114, 66, 103, 69, 70, 66, 81, 99, 66, 10, 65, 81, // rBgEFBQcB.AQ
81, 109, 77, 67, 81, 119, 73, 103, 89, 73, 75, 119, // QmMCQwIgYIKw
89, 66, 66, 81, 85, 72, 77, 65, 75, 71, 70, 109, // YBBQUHMAKGFm
104, 48, 100, 72, 65, 54, 76, 121, 57, 52, 77, 83, // h0dHA6Ly94MS
53, 112, 76, 109, 120, 108, 98, 109, 78, 121, 76, 109, // 5pLmxlbmNyLm
57, 121, 90, 121, 56, 119, 69, 119, 89, 68, 86, 82, // 9yZy8wEwYDVR
48, 103, 10, 66, 65, 119, 119, 67, 106, 65, 73, 66, // 0g.BAwwCjAIB
103, 90, 110, 103, 81, 119, 66, 65, 103, 69, 119, 74, // gZngQwBAgEwJ
119, 89, 68, 86, 82, 48, 102, 66, 67, 65, 119, 72, // wYDVR0fBCAwH
106, 65, 99, 111, 66, 113, 103, 71, 73, 89, 87, 97, // jAcoBqgGIYWa
72, 82, 48, 99, 68, 111, 118, 76, 51, 103, 120, 76, // HR0cDovL3gxL
109, 77, 117, 98, 71, 86, 117, 10, 89, 51, 73, 117, // mMubGVu.Y3Iu
98, 51, 74, 110, 76, 122, 65, 78, 66, 103, 107, 113, // b3JnLzANBgkq
104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 115, 70, // hkiG9w0BAQsF
65, 65, 79, 67, 65, 103, 69, 65, 72, 51, 75, 100, // AAOCAgEAH3Kd
78, 69, 86, 67, 81, 100, 113, 107, 48, 76, 75, 121, // NEVCQdqk0LKy
117, 78, 73, 109, 84, 75, 100, 82, 74, 89, 49, 67, // uNImTKdRJY1C
10, 50, 117, 119, 50, 83, 74, 97, 106, 117, 104, 113, // .2uw2SJajuhq
107, 121, 71, 80, 89, 56, 67, 43, 122, 122, 115, 117, // kyGPY8C+zzsu
102, 90, 43, 109, 103, 110, 104, 110, 113, 49, 65, 50, // fZ+mgnhnq1A2
75, 86, 81, 79, 83, 121, 107, 79, 69, 110, 85, 98, // KVQOSykOEnUb
120, 49, 99, 121, 54, 51, 55, 114, 66, 65, 105, 104, // x1cy637rBAih
120, 57, 55, 114, 43, 10, 98, 99, 119, 98, 90, 77, // x97r+.bcwbZM
54, 115, 84, 68, 73, 97, 69, 114, 105, 82, 47, 80, // 6sTDIaEriR/P
76, 107, 54, 76, 75, 115, 57, 66, 101, 48, 117, 111, // Lk6LKs9Be0uo
86, 120, 103, 79, 75, 68, 99, 112, 71, 57, 115, 118, // VxgOKDcpG9sv
68, 51, 51, 74, 43, 71, 57, 76, 99, 102, 118, 49, // D33J+G9Lcfv1
75, 57, 108, 117, 68, 109, 83, 84, 103, 71, 10, 54, // K9luDmSTgG.6
88, 78, 70, 73, 78, 53, 118, 102, 73, 53, 103, 115, // XNFIN5vfI5gs
47, 108, 77, 80, 121, 111, 106, 69, 77, 100, 73, 122, // /lMPyojEMdIz
75, 57, 98, 108, 99, 108, 50, 47, 49, 118, 75, 120, // K9blcl2/1vKx
79, 56, 87, 71, 67, 99, 106, 118, 115, 81, 49, 110, // O8WGCcjvsQ1n
74, 47, 80, 119, 116, 56, 76, 81, 90, 66, 102, 79, // J/Pwt8LQZBfO
70, 121, 86, 10, 88, 80, 56, 117, 98, 65, 112, 47, // FyV.XP8ubAp/
97, 117, 51, 100, 99, 52, 69, 75, 87, 71, 57, 77, // au3dc4EKWG9M
79, 53, 122, 99, 120, 49, 113, 84, 57, 43, 78, 88, // O5zcx1qT9+NX
82, 71, 100, 86, 87, 120, 71, 118, 109, 66, 70, 82, // RGdVWxGvmBFR
65, 97, 106, 99, 105, 77, 102, 88, 77, 69, 49, 90, // AajciMfXME1Z
117, 71, 109, 107, 51, 47, 71, 79, 10, 107, 111, 65, // uGmk3/GO.koA
77, 55, 90, 107, 106, 90, 109, 108, 101, 121, 111, 107, // M7ZkjZmleyok
80, 49, 76, 71, 122, 109, 102, 74, 99, 85, 100, 57, // P1LGzmfJcUd9
115, 55, 101, 101, 117, 49, 47, 57, 47, 101, 103, 53, // s7eeu1/9/eg5
88, 108, 88, 100, 47, 53, 53, 71, 116, 89, 106, 65, // XlXd/55GtYjA
77, 43, 67, 52, 68, 71, 53, 105, 55, 101, 97, 78, // M+C4DG5i7eaN
113, 10, 99, 109, 50, 70, 43, 121, 120, 89, 73, 80, // q.cm2F+yxYIP
116, 54, 99, 98, 98, 116, 89, 86, 78, 74, 67, 71, // t6cbbtYVNJCG
102, 72, 87, 113, 72, 69, 81, 52, 70, 89, 83, 116, // fHWqHEQ4FYSt
85, 121, 70, 110, 118, 56, 115, 106, 121, 113, 85, 56, // UyFnv8sjyqU8
121, 112, 103, 90, 97, 78, 74, 57, 97, 86, 99, 87, // ypgZaNJ9aVcW
83, 73, 67, 76, 79, 73, 10, 69, 49, 47, 81, 118, // SICLOI.E1/Qv
47, 55, 111, 75, 115, 110, 90, 67, 87, 74, 57, 50, // /7oKsnZCWJ92
54, 119, 85, 54, 82, 113, 71, 49, 79, 89, 80, 71, // 6wU6RqG1OYPG
79, 105, 49, 122, 117, 65, 66, 104, 76, 119, 54, 49, // Oi1zuABhLw61
99, 117, 80, 86, 68, 84, 50, 56, 110, 81, 83, 47, // cuPVDT28nQS/
101, 54, 122, 57, 53, 99, 74, 88, 113, 48, 101, 10, // e6z95cJXq0e.
75, 49, 66, 99, 97, 74, 54, 102, 74, 90, 115, 109, // K1BcaJ6fJZsm
98, 106, 82, 103, 68, 53, 112, 51, 109, 118, 69, 102, // bjRgD5p3mvEf
53, 118, 100, 81, 77, 55, 77, 67, 69, 118, 85, 48, // 5vdQM7MCEvU0
116, 72, 98, 115, 120, 50, 73, 53, 109, 72, 72, 74, // tHbsx2I5mHHJ
111, 65, 66, 72, 98, 56, 75, 86, 66, 103, 87, 112, // oABHb8KVBgWp
47, 108, 99, 88, 10, 71, 87, 105, 87, 97, 101, 79, // /lcX.GWiWaeO
121, 66, 55, 82, 80, 43, 79, 102, 68, 116, 118, 105, // yB7RP+OfDtvi
50, 79, 115, 97, 112, 120, 88, 105, 86, 55, 118, 78, // 2OsapxXiV7vN
86, 115, 55, 102, 77, 108, 114, 82, 106, 89, 49, 106, // Vs7fMlrRjY1j
111, 75, 97, 113, 109, 109, 121, 99, 110, 66, 118, 65, // oKaqmmycnBvA
113, 49, 52, 65, 69, 98, 116, 121, 76, 10, 115, 86, // q14AEbtyL.sV
102, 79, 83, 54, 54, 66, 56, 97, 112, 107, 101, 70, // fOS66B8apkeF
88, 50, 78, 89, 52, 88, 80, 69, 89, 86, 52, 90, // X2NY4XPEYV4Z
83, 67, 101, 56, 86, 72, 80, 114, 100, 114, 69, 82, // SCe8VHPrdrER
107, 50, 119, 73, 76, 71, 51, 84, 47, 69, 71, 109, // k2wILG3T/EGm
83, 73, 107, 67, 89, 86, 85, 77, 83, 110, 106, 109, // SIkCYVUMSnjm
74, 100, 10, 86, 81, 68, 57, 70, 54, 78, 97, 47, // Jd.VQD9F6Na/
43, 122, 109, 88, 67, 99, 61, 10, 45, 45, 45, 45, // +zmXCc=.----
45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, // -END CERTIFI
67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 10, // CATE-----...
73, 115, 115, 117, 101, 114, 58, 32, 67, 61, 85, 83, // Issuer: C=US
44, 32, 79, 61, 71, 111, 111, 103, 108, 101, 32, 84, // , O=Google T
114, 117, 115, 116, 32, 83, 101, 114, 118, 105, 99, 101, // rust Service
115, 32, 76, 76, 67, 44, 32, 67, 78, 61, 71, 84, // s LLC, CN=GT
83, 32, 82, 111, 111, 116, 32, 82, 49, 10, 78, 111, // S Root R1.No
116, 32, 66, 101, 102, 111, 114, 101, 58, 32, 74, 117, // t Before: Ju
110, 32, 50, 50, 32, 48, 48, 58, 48, 48, 58, 48, // n 22 00:00:0
48, 32, 50, 48, 49, 54, 32, 71, 77, 84, 10, 78, // 0 2016 GMT.N
111, 116, 32, 65, 102, 116, 101, 114, 32, 58, 32, 74, // ot After : J
117, 110, 32, 50, 50, 32, 48, 48, 58, 48, 48, 58, // un 22 00:00:
48, 48, 32, 50, 48, 51, 54, 32, 71, 77, 84, 10, // 00 2036 GMT.
45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, 67, // -----BEGIN C
69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, // ERTIFICATE--
45, 45, 45, 10, 77, 73, 73, 70, 86, 122, 67, 67, // ---.MIIFVzCC
65, 122, 43, 103, 65, 119, 73, 66, 65, 103, 73, 78, // Az+gAwIBAgIN
65, 103, 80, 108, 107, 50, 56, 120, 115, 66, 78, 74, // AgPlk28xsBNJ
105, 71, 117, 105, 70, 122, 65, 78, 66, 103, 107, 113, // iGuiFzANBgkq
104, 107, 105, 71, 57, 119, 48, 66, 65, 81, 119, 70, // hkiG9w0BAQwF
65, 68, 66, 72, 77, 81, 115, 119, 10, 67, 81, 89, // ADBHMQsw.CQY
68, 86, 81, 81, 71, 69, 119, 74, 86, 85, 122, 69, // DVQQGEwJVUzE
105, 77, 67, 65, 71, 65, 49, 85, 69, 67, 104, 77, // iMCAGA1UEChM
90, 82, 50, 57, 118, 90, 50, 120, 108, 73, 70, 82, // ZR29vZ2xlIFR
121, 100, 88, 78, 48, 73, 70, 78, 108, 99, 110, 90, // ydXN0IFNlcnZ
112, 89, 50, 86, 122, 73, 69, 120, 77, 81, 122, 69, // pY2VzIExMQzE
85, 10, 77, 66, 73, 71, 65, 49, 85, 69, 65, 120, // U.MBIGA1UEAx
77, 76, 82, 49, 82, 84, 73, 70, 74, 118, 98, 51, // MLR1RTIFJvb3
81, 103, 85, 106, 69, 119, 72, 104, 99, 78, 77, 84, // QgUjEwHhcNMT
89, 119, 78, 106, 73, 121, 77, 68, 65, 119, 77, 68, // YwNjIyMDAwMD
65, 119, 87, 104, 99, 78, 77, 122, 89, 119, 78, 106, // AwWhcNMzYwNj
73, 121, 77, 68, 65, 119, 10, 77, 68, 65, 119, 87, // IyMDAw.MDAwW
106, 66, 72, 77, 81, 115, 119, 67, 81, 89, 68, 86, // jBHMQswCQYDV
81, 81, 71, 69, 119, 74, 86, 85, 122, 69, 105, 77, // QQGEwJVUzEiM
67, 65, 71, 65, 49, 85, 69, 67, 104, 77, 90, 82, // CAGA1UEChMZR
50, 57, 118, 90, 50, 120, 108, 73, 70, 82, 121, 100, // 29vZ2xlIFRyd
88, 78, 48, 73, 70, 78, 108, 99, 110, 90, 112, 10, // XN0IFNlcnZp.
89, 50, 86, 122, 73, 69, 120, 77, 81, 122, 69, 85, // Y2VzIExMQzEU
77, 66, 73, 71, 65, 49, 85, 69, 65, 120, 77, 76, // MBIGA1UEAxML
82, 49, 82, 84, 73, 70, 74, 118, 98, 51, 81, 103, // R1RTIFJvb3Qg
85, 106, 69, 119, 103, 103, 73, 105, 77, 65, 48, 71, // UjEwggIiMA0G
67, 83, 113, 71, 83, 73, 98, 51, 68, 81, 69, 66, // CSqGSIb3DQEB
65, 81, 85, 65, 10, 65, 52, 73, 67, 68, 119, 65, // AQUA.A4ICDwA
119, 103, 103, 73, 75, 65, 111, 73, 67, 65, 81, 67, // wggIKAoICAQC
50, 69, 81, 75, 76, 72, 117, 79, 104, 100, 53, 115, // 2EQKLHuOhd5s
55, 51, 76, 43, 85, 80, 114, 101, 86, 112, 48, 65, // 73L+UPreVp0A
56, 111, 102, 50, 67, 43, 88, 48, 121, 66, 111, 74, // 8of2C+X0yBoJ
120, 57, 118, 97, 77, 102, 47, 118, 111, 10, 50, 55, // x9vaMf/vo.27
120, 113, 76, 112, 101, 88, 111, 52, 120, 76, 43, 83, // xqLpeXo4xL+S
118, 50, 115, 102, 110, 79, 104, 66, 50, 120, 43, 99, // v2sfnOhB2x+c
87, 88, 51, 117, 43, 53, 56, 113, 80, 112, 118, 66, // WX3u+58qPpvB
75, 74, 88, 113, 101, 113, 85, 113, 118, 52, 73, 121, // KJXqeqUqv4Iy
102, 76, 112, 76, 71, 99, 89, 57, 118, 88, 109, 88, // fLpLGcY9vXmX
55, 119, 10, 67, 108, 55, 114, 97, 75, 98, 48, 120, // 7w.Cl7raKb0x
108, 112, 72, 68, 85, 48, 81, 77, 43, 78, 79, 115, // lpHDU0QM+NOs
82, 79, 106, 121, 66, 104, 115, 83, 43, 122, 56, 67, // ROjyBhsS+z8C
90, 68, 102, 110, 87, 81, 112, 74, 83, 77, 72, 111, // ZDfnWQpJSMHo
98, 84, 83, 80, 83, 53, 103, 52, 77, 47, 83, 67, // bTSPS5g4M/SC
89, 101, 55, 122, 85, 106, 119, 10, 84, 99, 76, 67, // Ye7zUjw.TcLC
101, 111, 105, 75, 117, 55, 114, 80, 87, 82, 110, 87, // eoiKu7rPWRnW
114, 52, 43, 119, 66, 55, 67, 101, 77, 102, 71, 67, // r4+wB7CeMfGC
119, 99, 68, 102, 76, 113, 90, 116, 98, 66, 107, 79, // wcDfLqZtbBkO
116, 100, 104, 43, 74, 104, 112, 70, 65, 122, 50, 119, // tdh+JhpFAz2w
101, 97, 83, 85, 75, 75, 48, 80, 102, 121, 98, 108, // eaSUKK0Pfybl
10, 113, 65, 106, 43, 108, 117, 103, 56, 97, 74, 82, // .qAj+lug8aJR
84, 55, 111, 77, 54, 105, 67, 115, 86, 108, 103, 109, // T7oM6iCsVlgm
121, 52, 72, 113, 77, 76, 110, 88, 87, 110, 79, 117, // y4HqMLnXWnOu
110, 86, 109, 83, 80, 108, 107, 57, 111, 114, 106, 50, // nVmSPlk9orj2
88, 119, 111, 83, 80, 119, 76, 120, 65, 119, 65, 116, // XwoSPwLxAwAt
99, 118, 102, 97, 72, 10, 115, 122, 86, 115, 114, 66, // cvfaH.szVsrB
104, 81, 102, 52, 84, 103, 84, 77, 50, 83, 48, 121, // hQf4TgTM2S0y
68, 112, 77, 55, 120, 83, 109, 97, 56, 121, 116, 83, // DpM7xSma8ytS
109, 122, 74, 83, 113, 48, 83, 80, 108, 121, 52, 99, // mzJSq0SPly4c
112, 107, 57, 43, 97, 67, 69, 73, 51, 111, 110, 99, // pk9+aCEI3onc
75, 75, 105, 80, 111, 52, 90, 111, 114, 56, 10, 89, // KKiPo4Zor8.Y
47, 107, 66, 43, 88, 106, 57, 101, 49, 120, 51, 43, // /kB+Xj9e1x3+
110, 97, 72, 43, 117, 122, 102, 115, 81, 53, 53, 108, // naH+uzfsQ55l
86, 101, 48, 118, 83, 98, 118, 49, 103, 72, 82, 54, // Ve0vSbv1gHR6
120, 89, 75, 117, 52, 52, 76, 116, 99, 88, 70, 105, // xYKu44LtcXFi
108, 87, 114, 48, 54, 122, 113, 107, 85, 115, 112, 122, // lWr06zqkUspz
66, 109, 107, 10, 77, 105, 86, 79, 75, 118, 70, 108, // Bmk.MiVOKvFl
82, 78, 65, 67, 122, 113, 114, 79, 83, 98, 84, 113, // RNACzqrOSbTq
110, 51, 121, 68, 115, 69, 66, 55, 53, 48, 79, 114, // n3yDsEB750Or
112, 50, 121, 106, 106, 51, 50, 74, 103, 102, 112, 77, // p2yjj32JgfpM
112, 102, 47, 86, 106, 115, 80, 79, 83, 43, 67, 49, // pf/VjsPOS+C1
50, 76, 79, 79, 82, 99, 57, 50, 10, 119, 79, 49, // 2LOORc92.wO1
65, 75, 47, 49, 84, 68, 55, 67, 110, 49, 84, 115, // AK/1TD7Cn1Ts
78, 115, 89, 113, 105, 65, 57, 52, 120, 114, 99, 120, // NsYqiA94xrcx
51, 54, 109, 57, 55, 80, 116, 98, 102, 107, 83, 73, // 36m97PtbfkSI
83, 53, 114, 55, 54, 50, 68, 76, 56, 69, 71, 77, // S5r762DL8EGM
85, 85, 88, 76, 101, 88, 100, 89, 87, 107, 55, 48, // UUXLeXdYWk70
112, 10, 97, 68, 80, 118, 79, 109, 98, 115, 66, 52, // p.aDPvOmbsB4
111, 109, 51, 120, 80, 88, 86, 50, 86, 52, 74, 57, // om3xPXV2V4J9
53, 101, 83, 82, 81, 65, 111, 103, 66, 47, 109, 113, // 5eSRQAogB/mq
103, 104, 116, 113, 109, 120, 108, 98, 67, 108, 117, 81, // ghtqmxlbCluQ
48, 87, 69, 100, 114, 72, 98, 69, 103, 56, 81, 79, // 0WEdrHbEg8QO
66, 43, 68, 86, 114, 78, 10, 86, 106, 122, 82, 108, // B+DVrN.VjzRl
119, 87, 53, 121, 48, 118, 116, 79, 85, 117, 99, 120, // wW5y0vtOUucx
68, 47, 83, 86, 82, 78, 117, 74, 76, 68, 87, 99, // D/SVRNuJLDWc
102, 114, 48, 119, 98, 114, 77, 55, 82, 118, 49, 47, // fr0wbrM7Rv1/
111, 70, 66, 50, 65, 67, 89, 80, 84, 114, 73, 114, // oFB2ACYPTrIr
110, 113, 89, 78, 120, 103, 70, 108, 81, 73, 68, 10, // nqYNxgFlQID.
65, 81, 65, 66, 111, 48, 73, 119, 81, 68, 65, 79, // AQABo0IwQDAO
66, 103, 78, 86, 72, 81, 56, 66, 65, 102, 56, 69, // BgNVHQ8BAf8E
66, 65, 77, 67, 65, 89, 89, 119, 68, 119, 89, 68, // BAMCAYYwDwYD
86, 82, 48, 84, 65, 81, 72, 47, 66, 65, 85, 119, // VR0TAQH/BAUw
65, 119, 69, 66, 47, 122, 65, 100, 66, 103, 78, 86, // AwEB/zAdBgNV
72, 81, 52, 69, 10, 70, 103, 81, 85, 53, 75, 56, // HQ4E.FgQU5K8
114, 74, 110, 69, 97, 75, 48, 103, 110, 104, 83, 57, // rJnEaK0gnhS9
83, 90, 105, 122, 118, 56, 73, 107, 84, 99, 84, 52, // SZizv8IkTcT4
119, 68, 81, 89, 74, 75, 111, 90, 73, 104, 118, 99, // wDQYJKoZIhvc
78, 65, 81, 69, 77, 66, 81, 65, 68, 103, 103, 73, // NAQEMBQADggI
66, 65, 74, 43, 113, 81, 105, 98, 98, 10, 67, 53, // BAJ+qQibb.C5
117, 43, 47, 120, 54, 87, 107, 105, 52, 43, 111, 109, // u+/x6Wki4+om
86, 75, 97, 112, 105, 54, 73, 115, 116, 57, 119, 84, // VKapi6Ist9wT
114, 89, 103, 103, 111, 71, 120, 118, 97, 108, 51, 115, // rYggoGxval3s
66, 79, 104, 50, 90, 53, 111, 102, 109, 109, 87, 74, // BOh2Z5ofmmWJ
121, 113, 43, 98, 88, 109, 89, 79, 102, 103, 54, 76, // yq+bXmYOfg6L
69, 101, 10, 81, 107, 69, 122, 67, 122, 99, 57, 122, // Ee.QkEzCzc9z
111, 108, 119, 70, 99, 113, 49, 74, 75, 106, 80, 97, // olwFcq1JKjPa
55, 88, 83, 81, 67, 71, 89, 122, 121, 73, 48, 122, // 7XSQCGYzyI0z
122, 118, 70, 73, 111, 84, 103, 120, 81, 54, 75, 102, // zvFIoTgxQ6Kf
70, 50, 73, 53, 68, 85, 107, 122, 112, 115, 43, 71, // F2I5DUkzps+G
108, 81, 101, 98, 116, 117, 121, 10, 104, 54, 102, 56, // lQebtuy.h6f8
56, 47, 113, 66, 86, 82, 82, 105, 67, 108, 109, 112, // 8/qBVRRiClmp
73, 103, 85, 120, 80, 111, 76, 87, 55, 116, 116, 88, // IgUxPoLW7ttX
78, 76, 119, 122, 108, 100, 77, 88, 71, 43, 103, 110, // NLwzldMXG+gn
111, 111, 116, 55, 84, 105, 89, 97, 101, 108, 112, 107, // oot7TiYaelpk
116, 116, 71, 115, 78, 47, 72, 57, 111, 80, 77, 52, // ttGsN/H9oPM4
10, 55, 72, 76, 119, 69, 88, 87, 100, 121, 122, 82, // .7HLwEXWdyzR
83, 106, 101, 90, 50, 97, 120, 102, 71, 51, 52, 97, // SjeZ2axfG34a
114, 74, 52, 53, 74, 75, 51, 86, 109, 103, 82, 65, // rJ45JK3VmgRA
104, 112, 117, 111, 43, 57, 75, 52, 108, 47, 51, 119, // hpuo+9K4l/3w
86, 51, 115, 54, 77, 74, 84, 47, 75, 89, 110, 65, // V3s6MJT/KYnA
75, 57, 121, 56, 74, 10, 90, 103, 102, 73, 80, 120, // K9y8J.ZgfIPx
122, 56, 56, 78, 116, 70, 77, 78, 57, 105, 105, 77, // z88NtFMN9iiM
71, 49, 68, 53, 51, 68, 110, 48, 114, 101, 87, 86, // G1D53Dn0reWV
108, 72, 120, 89, 99, 105, 78, 117, 97, 67, 112, 43, // lHxYciNuaCp+
48, 75, 117, 101, 73, 72, 111, 73, 49, 55, 101, 107, // 0KueIHoI17ek
111, 56, 99, 100, 76, 105, 65, 54, 69, 102, 10, 77, // o8cdLiA6Ef.M
103, 102, 100, 71, 43, 82, 67, 122, 103, 119, 65, 82, // gfdG+RCzgwAR
87, 71, 65, 116, 81, 115, 103, 87, 83, 108, 52, 118, // WGAtQsgWSl4v
102, 108, 86, 121, 50, 80, 70, 80, 69, 122, 48, 116, // flVy2PFPEz0t
118, 47, 98, 97, 108, 56, 120, 97, 53, 109, 101, 76, // v/bal8xa5meL
77, 70, 114, 85, 75, 84, 88, 53, 104, 103, 85, 118, // MFrUKTX5hgUv
89, 85, 47, 10, 90, 54, 116, 71, 110, 54, 68, 47, // YU/.Z6tGn6D/
81, 113, 99, 54, 102, 49, 122, 76, 88, 98, 66, 119, // Qqc6f1zLXbBw
72, 83, 115, 48, 57, 100, 82, 50, 67, 81, 122, 114, // HSs09dR2CQzr
101, 69, 120, 90, 66, 102, 77, 122, 81, 115, 78, 104, // eExZBfMzQsNh
70, 82, 65, 98, 100, 48, 51, 79, 73, 111, 122, 85, // FRAbd03OIozU
104, 102, 74, 70, 102, 98, 100, 84, 10, 54, 117, 57, // hfJFfbdT.6u9
65, 87, 112, 81, 75, 88, 67, 66, 102, 84, 107, 66, // AWpQKXCBfTkB
100, 89, 105, 74, 50, 51, 47, 47, 79, 89, 98, 50, // dYiJ23//OYb2
77, 73, 51, 106, 83, 78, 119, 76, 103, 106, 116, 55, // MI3jSNwLgjt7
82, 69, 84, 101, 74, 57, 114, 47, 116, 83, 81, 100, // RETeJ9r/tSQd
105, 114, 112, 76, 115, 81, 66, 113, 118, 70, 65, 110, // irpLsQBqvFAn
90, 10, 48, 69, 54, 121, 111, 118, 101, 43, 55, 117, // Z.0E6yove+7u
55, 89, 47, 57, 119, 97, 76, 100, 54, 52, 78, 110, // 7Y/9waLd64Nn
72, 105, 47, 72, 109, 51, 108, 67, 88, 82, 83, 72, // Hi/Hm3lCXRSH
78, 98, 111, 84, 88, 110, 115, 53, 108, 110, 100, 99, // NboTXns5lndc
69, 90, 79, 105, 116, 72, 84, 116, 78, 67, 106, 118, // EZOitHTtNCjv
48, 120, 121, 66, 90, 109, 10, 50, 116, 73, 77, 80, // 0xyBZm.2tIMP
78, 117, 122, 106, 115, 109, 104, 68, 89, 65, 80, 101, // NuzjsmhDYAPe
120, 90, 51, 70, 76, 47, 47, 50, 119, 109, 85, 115, // xZ3FL//2wmUs
112, 79, 56, 73, 70, 103, 86, 54, 100, 116, 120, 81, // pO8IFgV6dtxQ
47, 80, 101, 69, 77, 77, 65, 51, 75, 103, 113, 108, // /PeEMMA3Kgql
98, 98, 67, 49, 106, 43, 81, 97, 51, 98, 98, 10, // bbC1j+Qa3bb.
98, 80, 54, 77, 118, 80, 74, 119, 78, 81, 122, 99, // bP6MvPJwNQzc
109, 82, 107, 49, 51, 78, 102, 73, 82, 109, 80, 86, // mRk13NfIRmPV
78, 110, 71, 117, 86, 47, 117, 51, 103, 109, 51, 99, // NnGuV/u3gm3c
10, 45, 45, 45, 45, 45, 69, 78, 68, 32, 67, 69, // .-----END CE
82, 84, 73, 70, 73, 67, 65, 84, 69, 45, 45, 45, // RTIFICATE---
45, 45, 10, 10, 10, 73, 115, 115, 117, 101, 114, 58, // --...Issuer:
32, 79, 85, 61, 71, 108, 111, 98, 97, 108, 83, 105, // OU=GlobalSi
103, 110, 32, 69, 67, 67, 32, 82, 111, 111, 116, 32, // gn ECC Root
67, 65, 32, 45, 32, 82, 52, 44, 32, 79, 61, 71, // CA - R4, O=G
108, 111, 98, 97, 108, 83, 105, 103, 110, 44, 32, 67, // lobalSign, C
78, 61, 71, 108, 111, 98, 97, 108, 83, 105, 103, 110, // N=GlobalSign
10, 78, 111, 116, 32, 66, 101, 102, 111, 114, 101, 58, // .Not Before:
32, 78, 111, 118, 32, 49, 51, 32, 48, 48, 58, 48, // Nov 13 00:0
48, 58, 48, 48, 32, 50, 48, 49, 50, 32, 71, 77, // 0:00 2012 GM
84, 10, 78, 111, 116, 32, 65, 102, 116, 101, 114, 32, // T.Not After
58, 32, 74, 97, 110, 32, 49, 57, 32, 48, 51, 58, // : Jan 19 03:
49, 52, 58, 48, 55, 32, 50, 48, 51, 56, 32, 71, // 14:07 2038 G
77, 84, 10, 45, 45, 45, 45, 45, 66, 69, 71, 73, // MT.-----BEGI
78, 32, 67, 69, 82, 84, 73, 70, 73, 67, 65, 84, // N CERTIFICAT
69, 45, 45, 45, 45, 45, 10, 77, 73, 73, 66, 51, // E-----.MIIB3
68, 67, 67, 65, 89, 79, 103, 65, 119, 73, 66, 65, // DCCAYOgAwIBA
103, 73, 78, 65, 103, 80, 108, 102, 118, 85, 47, 107, // gINAgPlfvU/k
47, 50, 108, 67, 83, 71, 121, 112, 106, 65, 75, 66, // /2lCSGypjAKB
103, 103, 113, 104, 107, 106, 79, 80, 81, 81, 68, 65, // ggqhkjOPQQDA
106, 66, 81, 77, 83, 81, 119, 73, 103, 89, 68, 10, // jBQMSQwIgYD.
86, 81, 81, 76, 69, 120, 116, 72, 98, 71, 57, 105, // VQQLExtHbG9i
89, 87, 120, 84, 97, 87, 100, 117, 73, 69, 86, 68, // YWxTaWduIEVD
81, 121, 66, 83, 98, 50, 57, 48, 73, 69, 78, 66, // QyBSb290IENB
73, 67, 48, 103, 85, 106, 81, 120, 69, 122, 65, 82, // IC0gUjQxEzAR
66, 103, 78, 86, 66, 65, 111, 84, 67, 107, 100, 115, // BgNVBAoTCkds
98, 50, 74, 104, 10, 98, 70, 78, 112, 90, 50, 52, // b2Jh.bFNpZ24
120, 69, 122, 65, 82, 66, 103, 78, 86, 66, 65, 77, // xEzARBgNVBAM
84, 67, 107, 100, 115, 98, 50, 74, 104, 98, 70, 78, // TCkdsb2JhbFN
112, 90, 50, 52, 119, 72, 104, 99, 78, 77, 84, 73, // pZ24wHhcNMTI
120, 77, 84, 69, 122, 77, 68, 65, 119, 77, 68, 65, // xMTEzMDAwMDA
119, 87, 104, 99, 78, 77, 122, 103, 119, 10, 77, 84, // wWhcNMzgw.MT
69, 53, 77, 68, 77, 120, 78, 68, 65, 51, 87, 106, // E5MDMxNDA3Wj
66, 81, 77, 83, 81, 119, 73, 103, 89, 68, 86, 81, // BQMSQwIgYDVQ
81, 76, 69, 120, 116, 72, 98, 71, 57, 105, 89, 87, // QLExtHbG9iYW
120, 84, 97, 87, 100, 117, 73, 69, 86, 68, 81, 121, // xTaWduIEVDQy
66, 83, 98, 50, 57, 48, 73, 69, 78, 66, 73, 67, // BSb290IENBIC
48, 103, 10, 85, 106, 81, 120, 69, 122, 65, 82, 66, // 0g.UjQxEzARB
103, 78, 86, 66, 65, 111, 84, 67, 107, 100, 115, 98, // gNVBAoTCkdsb
50, 74, 104, 98, 70, 78, 112, 90, 50, 52, 120, 69, // 2JhbFNpZ24xE
122, 65, 82, 66, 103, 78, 86, 66, 65, 77, 84, 67, // zARBgNVBAMTC
107, 100, 115, 98, 50, 74, 104, 98, 70, 78, 112, 90, // kdsb2JhbFNpZ
50, 52, 119, 87, 84, 65, 84, 10, 66, 103, 99, 113, // 24wWTAT.Bgcq
104, 107, 106, 79, 80, 81, 73, 66, 66, 103, 103, 113, // hkjOPQIBBggq
104, 107, 106, 79, 80, 81, 77, 66, 66, 119, 78, 67, // hkjOPQMBBwNC
65, 65, 83, 52, 120, 110, 110, 84, 106, 50, 119, 108, // AAS4xnnTj2wl
68, 112, 56, 117, 79, 82, 107, 99, 65, 54, 83, 117, // Dp8uORkcA6Su
109, 117, 85, 53, 66, 119, 107, 87, 121, 109, 79, 120, // muU5BwkWymOx
10, 117, 89, 98, 52, 105, 108, 102, 66, 86, 56, 53, // .uYb4ilfBV85
67, 43, 110, 79, 104, 57, 50, 86, 67, 47, 120, 55, // C+nOh92VC/x7
66, 65, 76, 74, 117, 99, 119, 55, 47, 120, 121, 72, // BALJucw7/xyH
108, 71, 75, 83, 113, 50, 88, 69, 47, 113, 78, 83, // lGKSq2XE/qNS
53, 122, 111, 119, 100, 111, 48, 73, 119, 81, 68, 65, // 5zowdo0IwQDA
79, 66, 103, 78, 86, 10, 72, 81, 56, 66, 65, 102, // OBgNV.HQ8BAf
56, 69, 66, 65, 77, 67, 65, 89, 89, 119, 68, 119, // 8EBAMCAYYwDw
89, 68, 86, 82, 48, 84, 65, 81, 72, 47, 66, 65, // YDVR0TAQH/BA
85, 119, 65, 119, 69, 66, 47, 122, 65, 100, 66, 103, // UwAwEB/zAdBg
78, 86, 72, 81, 52, 69, 70, 103, 81, 85, 86, 76, // NVHQ4EFgQUVL
66, 55, 114, 85, 87, 52, 52, 107, 66, 47, 10, 43, // B7rUW44kB/.+
119, 112, 117, 43, 55, 52, 122, 121, 84, 121, 106, 104, // wpu+74zyTyjh
78, 85, 119, 67, 103, 89, 73, 75, 111, 90, 73, 122, // NUwCgYIKoZIz
106, 48, 69, 65, 119, 73, 68, 82, 119, 65, 119, 82, // j0EAwIDRwAwR
65, 73, 103, 73, 107, 57, 48, 99, 114, 108, 103, 114, // AIgIk90crlgr
47, 72, 109, 110, 75, 65, 87, 66, 86, 66, 102, 119, // /HmnKAWBVBfw
49, 52, 55, 10, 98, 109, 70, 48, 55, 55, 52, 66, // 147.bmF0774B
120, 76, 52, 89, 83, 70, 108, 104, 103, 106, 73, 67, // xL4YSFlhgjIC
73, 67, 97, 100, 86, 71, 78, 65, 51, 106, 100, 103, // ICadVGNA3jdg
85, 77, 47, 73, 50, 79, 50, 100, 103, 113, 52, 51, // UM/I2O2dgq43
109, 76, 121, 106, 106, 48, 120, 77, 113, 84, 81, 114, // mLyjj0xMqTQr
98, 79, 47, 55, 108, 90, 115, 109, 10, 45, 45, 45, // bO/7lZsm.---
45, 45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, // --END CERTIF
73, 67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, // ICATE-----..
10, 73, 115, 115, 117, 101, 114, 58, 32, 67, 61, 85, // .Issuer: C=U
83, 44, 32, 79, 61, 71, 111, 111, 103, 108, 101, 32, // S, O=Google
84, 114, 117, 115, 116, 32, 83, 101, 114, 118, 105, 99, // Trust Servic
101, 115, 32, 76, 76, 67, 44, 32, 67, 78, 61, 71, // es LLC, CN=G
84, 83, 32, 82, 111, 111, 116, 32, 82, 52, 10, 78, // TS Root R4.N
111, 116, 32, 66, 101, 102, 111, 114, 101, 58, 32, 74, // ot Before: J
117, 110, 32, 50, 50, 32, 48, 48, 58, 48, 48, 58, // un 22 00:00:
48, 48, 32, 50, 48, 49, 54, 32, 71, 77, 84, 10, // 00 2016 GMT.
78, 111, 116, 32, 65, 102, 116, 101, 114, 32, 58, 32, // Not After :
74, 117, 110, 32, 50, 50, 32, 48, 48, 58, 48, 48, // Jun 22 00:00
58, 48, 48, 32, 50, 48, 51, 54, 32, 71, 77, 84, // :00 2036 GMT
10, 45, 45, 45, 45, 45, 66, 69, 71, 73, 78, 32, // .-----BEGIN
67, 69, 82, 84, 73, 70, 73, 67, 65, 84, 69, 45, // CERTIFICATE-
45, 45, 45, 45, 10, 77, 73, 73, 67, 67, 84, 67, // ----.MIICCTC
67, 65, 89, 54, 103, 65, 119, 73, 66, 65, 103, 73, // CAY6gAwIBAgI
78, 65, 103, 80, 108, 119, 71, 106, 118, 89, 120, 113, // NAgPlwGjvYxq
99, 99, 112, 66, 81, 85, 106, 65, 75, 66, 103, 103, // ccpBQUjAKBgg
113, 104, 107, 106, 79, 80, 81, 81, 68, 65, 122, 66, // qhkjOPQQDAzB
72, 77, 81, 115, 119, 67, 81, 89, 68, 10, 86, 81, // HMQswCQYD.VQ
81, 71, 69, 119, 74, 86, 85, 122, 69, 105, 77, 67, // QGEwJVUzEiMC
65, 71, 65, 49, 85, 69, 67, 104, 77, 90, 82, 50, // AGA1UEChMZR2
57, 118, 90, 50, 120, 108, 73, 70, 82, 121, 100, 88, // 9vZ2xlIFRydX
78, 48, 73, 70, 78, 108, 99, 110, 90, 112, 89, 50, // N0IFNlcnZpY2
86, 122, 73, 69, 120, 77, 81, 122, 69, 85, 77, 66, // VzIExMQzEUMB
73, 71, 10, 65, 49, 85, 69, 65, 120, 77, 76, 82, // IG.A1UEAxMLR
49, 82, 84, 73, 70, 74, 118, 98, 51, 81, 103, 85, // 1RTIFJvb3QgU
106, 81, 119, 72, 104, 99, 78, 77, 84, 89, 119, 78, // jQwHhcNMTYwN
106, 73, 121, 77, 68, 65, 119, 77, 68, 65, 119, 87, // jIyMDAwMDAwW
104, 99, 78, 77, 122, 89, 119, 78, 106, 73, 121, 77, // hcNMzYwNjIyM
68, 65, 119, 77, 68, 65, 119, 10, 87, 106, 66, 72, // DAwMDAw.WjBH
77, 81, 115, 119, 67, 81, 89, 68, 86, 81, 81, 71, // MQswCQYDVQQG
69, 119, 74, 86, 85, 122, 69, 105, 77, 67, 65, 71, // EwJVUzEiMCAG
65, 49, 85, 69, 67, 104, 77, 90, 82, 50, 57, 118, // A1UEChMZR29v
90, 50, 120, 108, 73, 70, 82, 121, 100, 88, 78, 48, // Z2xlIFRydXN0
73, 70, 78, 108, 99, 110, 90, 112, 89, 50, 86, 122, // IFNlcnZpY2Vz
10, 73, 69, 120, 77, 81, 122, 69, 85, 77, 66, 73, // .IExMQzEUMBI
71, 65, 49, 85, 69, 65, 120, 77, 76, 82, 49, 82, // GA1UEAxMLR1R
84, 73, 70, 74, 118, 98, 51, 81, 103, 85, 106, 81, // TIFJvb3QgUjQ
119, 100, 106, 65, 81, 66, 103, 99, 113, 104, 107, 106, // wdjAQBgcqhkj
79, 80, 81, 73, 66, 66, 103, 85, 114, 103, 81, 81, // OPQIBBgUrgQQ
65, 73, 103, 78, 105, 10, 65, 65, 84, 122, 100, 72, // AIgNi.AATzdH
79, 110, 97, 73, 116, 103, 114, 107, 79, 52, 78, 99, // OnaItgrkO4Nc
87, 66, 77, 72, 116, 76, 83, 90, 51, 55, 119, 87, // WBMHtLSZ37wW
72, 79, 53, 116, 53, 71, 118, 87, 118, 86, 89, 82, // HO5t5GvWvVYR
103, 49, 114, 107, 68, 100, 99, 47, 101, 74, 107, 84, // g1rkDdc/eJkT
66, 97, 54, 122, 122, 117, 104, 88, 121, 105, 10, 81, // Ba6zzuhXyi.Q
72, 89, 55, 113, 99, 97, 52, 82, 57, 103, 113, 53, // HY7qca4R9gq5
53, 75, 82, 97, 110, 80, 112, 115, 88, 73, 53, 110, // 5KRanPpsXI5n
121, 109, 102, 111, 112, 106, 84, 88, 49, 53, 89, 104, // ymfopjTX15Yh
109, 85, 80, 111, 89, 82, 108, 66, 116, 72, 99, 105, // mUPoYRlBtHci
56, 110, 72, 99, 56, 105, 77, 97, 105, 47, 108, 120, // 8nHc8iMai/lx
75, 118, 82, 10, 72, 89, 113, 106, 81, 106, 66, 65, // KvR.HYqjQjBA
77, 65, 52, 71, 65, 49, 85, 100, 68, 119, 69, 66, // MA4GA1UdDwEB
47, 119, 81, 69, 65, 119, 73, 66, 104, 106, 65, 80, // /wQEAwIBhjAP
66, 103, 78, 86, 72, 82, 77, 66, 65, 102, 56, 69, // BgNVHRMBAf8E
66, 84, 65, 68, 65, 81, 72, 47, 77, 66, 48, 71, // BTADAQH/MB0G
65, 49, 85, 100, 68, 103, 81, 87, 10, 66, 66, 83, // A1UdDgQW.BBS
65, 84, 78, 98, 114, 100, 80, 57, 74, 78, 113, 80, // ATNbrdP9JNqP
86, 50, 80, 121, 49, 80, 115, 86, 113, 56, 74, 81, // V2Py1PsVq8JQ
100, 106, 68, 65, 75, 66, 103, 103, 113, 104, 107, 106, // djDAKBggqhkj
79, 80, 81, 81, 68, 65, 119, 78, 112, 65, 68, 66, // OPQQDAwNpADB
109, 65, 106, 69, 65, 54, 69, 68, 47, 103, 57, 52, // mAjEA6ED/g94
68, 10, 57, 74, 43, 117, 72, 88, 113, 110, 76, 114, // D.9J+uHXqnLr
109, 118, 84, 47, 97, 68, 72, 81, 52, 116, 104, 81, // mvT/aDHQ4thQ
69, 100, 48, 100, 108, 113, 55, 65, 47, 67, 114, 56, // Ed0dlq7A/Cr8
100, 101, 86, 108, 53, 99, 49, 82, 120, 89, 73, 105, // deVl5c1RxYIi
103, 76, 57, 122, 67, 50, 76, 55, 70, 56, 65, 106, // gL9zC2L7F8Aj
69, 65, 56, 71, 69, 56, 10, 112, 47, 83, 103, 103, // EA8GE8.p/Sgg
117, 77, 104, 49, 89, 81, 100, 99, 52, 97, 99, 76, // uMh1YQdc4acL
97, 47, 75, 78, 74, 118, 120, 110, 55, 107, 106, 78, // a/KNJvxn7kjN
117, 75, 56, 89, 65, 79, 100, 103, 76, 79, 97, 86, // uK8YAOdgLOaV
115, 106, 104, 52, 114, 115, 85, 101, 99, 114, 78, 73, // sjh4rsUecrNI
100, 83, 85, 116, 85, 108, 68, 10, 45, 45, 45, 45, // dSUtUlD.----
45, 69, 78, 68, 32, 67, 69, 82, 84, 73, 70, 73, // -END CERTIFI
67, 65, 84, 69, 45, 45, 45, 45, 45, 10, 10, 10, // CATE-----...
73, 115, 115, 117, 101, 114, 58, 32, 67, 32, 61, 32, // Issuer: C =
85, 83, 44, 32, 79, 32, 61, 32, 73, 110, 116, 101, // US, O = Inte
114, 110, 101, 116, 32, 83, 101, 99, 117, 114, 105, 116, // rnet Securit
@@ -2556,7 +3145,7 @@ static const struct packed_file {
size_t size;
time_t mtime;
} packed_files[] = {
{"/certs/ca.pem", v1, sizeof(v1), 1696845443},
{"/certs/ca.pem", v1, sizeof(v1), 1739200860},
{NULL, NULL, 0, 0}
};