mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
df8ab0aa0c
redbean will now set Referer-Policy to no-referrer-when-downgrade on text/html responses by default. There's better explanations on the bits of security redbean is offering. In short, it's 128+ for modern clients and 112+ for legacy. If the -B flag is used then it's 192+ for modern and 150+ for non-EC.
269 lines
9 KiB
C
269 lines
9 KiB
C
/*-*- 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 2016-2018 INRIA and Microsoft Corporation │
|
|
│ │
|
|
│ 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 "libc/bits/bits.h"
|
|
#include "third_party/mbedtls/endian.h"
|
|
|
|
asm(".ident\t\"\\n\\n\
|
|
Everest (Apache 2.0)\\n\
|
|
Copyright 2016-2018 INRIA and Microsoft Corporation\"");
|
|
asm(".include \"libc/disclaimer.inc\"");
|
|
|
|
#define DW(x) (uint128_t)(x)
|
|
#define EQ(x, y) ((((x ^ y) | (~(x ^ y) + 1)) >> 63) - 1)
|
|
#define GTE(x, y) (((x ^ ((x ^ y) | ((x - y) ^ y))) >> 63) - 1)
|
|
|
|
forceinline void HaclBignumCopy(uint64_t o[5], uint64_t p[5]) {
|
|
for (unsigned i = 0; i < 5; ++i) {
|
|
o[i] = p[i];
|
|
}
|
|
}
|
|
|
|
forceinline void HaclBignumFsum(uint64_t o[5], uint64_t p[5]) {
|
|
for (unsigned i = 0; i < 5; ++i) {
|
|
o[i] += p[i];
|
|
}
|
|
}
|
|
|
|
forceinline void HaclBignumTrunc(uint64_t o[5], uint128_t p[5]) {
|
|
for (unsigned i = 0; i < 5; ++i) {
|
|
o[i] = p[i];
|
|
}
|
|
}
|
|
|
|
forceinline void HaclBignumCarry(uint64_t p[5]) {
|
|
for (unsigned i = 0; i < 4; ++i) {
|
|
p[i + 1] += p[i] >> 51;
|
|
p[i] &= 0x7ffffffffffff;
|
|
}
|
|
}
|
|
|
|
forceinline void HaclBignumCarryWide(uint128_t p[5]) {
|
|
for (unsigned i = 0; i < 4; ++i) {
|
|
p[i + 1] += p[i] >> 51;
|
|
p[i] &= 0x7ffffffffffff;
|
|
}
|
|
}
|
|
|
|
static void HaclBignumFmulReduce(uint128_t o[5], uint64_t p[5], uint64_t q[5]) {
|
|
uint64_t t;
|
|
unsigned i, j;
|
|
for (i = 0;; ++i) {
|
|
for (j = 0; j < 5; ++j) {
|
|
o[j] += DW(p[j]) * q[i];
|
|
}
|
|
if (i == 4) break;
|
|
t = p[4] * 19;
|
|
p[4] = p[3];
|
|
p[3] = p[2];
|
|
p[2] = p[1];
|
|
p[1] = p[0];
|
|
p[0] = t;
|
|
}
|
|
}
|
|
|
|
static void HaclBignumFmul(uint64_t o[5], uint64_t p[5], uint64_t q[5]) {
|
|
uint128_t t[5] = {0};
|
|
uint64_t u[5] = {p[0], p[1], p[2], p[3], p[4]};
|
|
HaclBignumFmulReduce(t, u, q);
|
|
HaclBignumCarryWide(t);
|
|
t[0] += DW(19) * (uint64_t)(t[4] >> 51);
|
|
HaclBignumTrunc(o, t);
|
|
o[1] += o[0] >> 51;
|
|
o[4] &= 0x7ffffffffffff;
|
|
o[0] &= 0x7ffffffffffff;
|
|
}
|
|
|
|
static void HaclBignumFsquare(uint128_t t[5], uint64_t p[5]) {
|
|
t[0] = DW(p[0] * 1) * p[0] + DW(p[4] * 38) * p[1] + DW(p[2] * 38) * p[3];
|
|
t[1] = DW(p[0] * 2) * p[1] + DW(p[4] * 38) * p[2] + DW(p[3] * 19) * p[3];
|
|
t[2] = DW(p[0] * 2) * p[2] + DW(p[1] * 01) * p[1] + DW(p[4] * 38) * p[3];
|
|
t[3] = DW(p[0] * 2) * p[3] + DW(p[1] * 02) * p[2] + DW(p[4]) * (p[4] * 19);
|
|
t[4] = DW(p[0] * 2) * p[4] + DW(p[1] * 02) * p[3] + DW(p[2]) * p[2];
|
|
}
|
|
|
|
static void HaclBignumFsqa(uint64_t o[5], uint32_t n) {
|
|
uint128_t t[5];
|
|
for (unsigned i = 0; i < n; ++i) {
|
|
HaclBignumFsquare(t, o);
|
|
HaclBignumCarryWide(t);
|
|
t[0] += DW(19) * (uint64_t)(t[4] >> 51);
|
|
HaclBignumTrunc(o, t);
|
|
o[1] += o[0] >> 51;
|
|
o[4] &= 0x7ffffffffffff;
|
|
o[0] &= 0x7ffffffffffff;
|
|
}
|
|
}
|
|
|
|
static void HaclBignumFsqr(uint64_t o[5], uint64_t p[5], uint32_t n) {
|
|
HaclBignumCopy(o, p);
|
|
HaclBignumFsqa(o, n);
|
|
}
|
|
|
|
static void HaclBignumCrecip(uint64_t o[5], uint64_t z[5]) {
|
|
uint64_t b[4][5];
|
|
HaclBignumFsqr(b[0], z, 1);
|
|
HaclBignumFsqr(b[1], b[0], 2);
|
|
HaclBignumFmul(b[2], b[1], z);
|
|
HaclBignumFmul(b[0], b[2], b[0]);
|
|
HaclBignumFsqr(b[1], b[0], 1);
|
|
HaclBignumFmul(b[2], b[1], b[2]);
|
|
HaclBignumFsqr(b[1], b[2], 5);
|
|
HaclBignumFmul(b[2], b[1], b[2]);
|
|
HaclBignumFsqr(b[1], b[2], 10);
|
|
HaclBignumFmul(b[3], b[1], b[2]);
|
|
HaclBignumFsqr(b[1], b[3], 20);
|
|
HaclBignumFmul(b[1], b[1], b[3]);
|
|
HaclBignumFsqa(b[1], 10);
|
|
HaclBignumFmul(b[2], b[1], b[2]);
|
|
HaclBignumFsqr(b[1], b[2], 50);
|
|
HaclBignumFmul(b[3], b[1], b[2]);
|
|
HaclBignumFsqr(b[1], b[3], 100);
|
|
HaclBignumFmul(b[1], b[1], b[3]);
|
|
HaclBignumFsqa(b[1], 50);
|
|
HaclBignumFmul(b[1], b[1], b[2]);
|
|
HaclBignumFsqa(b[1], 5);
|
|
HaclBignumFmul(o, b[1], b[0]);
|
|
}
|
|
|
|
static void HaclBignumFdif(uint64_t a[5], uint64_t b[5]) {
|
|
a[0] = b[0] + 0x3fffffffffff68 - a[0];
|
|
a[1] = b[1] + 0x3ffffffffffff8 - a[1];
|
|
a[2] = b[2] + 0x3ffffffffffff8 - a[2];
|
|
a[3] = b[3] + 0x3ffffffffffff8 - a[3];
|
|
a[4] = b[4] + 0x3ffffffffffff8 - a[4];
|
|
}
|
|
|
|
static void HaclBignumFscalar(uint64_t o[5], uint64_t p[5], uint64_t s) {
|
|
unsigned i;
|
|
uint128_t t[5];
|
|
for (i = 0; i < 5; ++i) t[i] = DW(p[i]) * s;
|
|
HaclBignumCarryWide(t);
|
|
t[0] += DW(19) * (uint64_t)(t[4] >> 51);
|
|
t[4] &= 0x7ffffffffffff;
|
|
HaclBignumTrunc(o, t);
|
|
}
|
|
|
|
static void HaclEcPointSwap(uint64_t a[2][5], uint64_t b[2][5], uint64_t m) {
|
|
unsigned i, j;
|
|
uint64_t x, y;
|
|
for (i = 0; i < 2; ++i) {
|
|
for (j = 0; j < 5; ++j) {
|
|
x = a[i][j] ^ (-m & (a[i][j] ^ b[i][j]));
|
|
y = b[i][j] ^ (-m & (a[i][j] ^ b[i][j]));
|
|
a[i][j] = x;
|
|
b[i][j] = y;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void HaclEcFormatFexpand(uint64_t o[5], uint8_t p[32]) {
|
|
o[0] = READ64LE(p + 000) >> 00 & 0x7ffffffffffff;
|
|
o[1] = READ64LE(p + 006) >> 03 & 0x7ffffffffffff;
|
|
o[2] = READ64LE(p + 014) >> 06 & 0x7ffffffffffff;
|
|
o[3] = READ64LE(p + 023) >> 01 & 0x7ffffffffffff;
|
|
o[4] = READ64LE(p + 030) >> 12 & 0x7ffffffffffff;
|
|
}
|
|
|
|
static void HaclEcFormatFcontract(uint8_t o[32], uint64_t p[5]) {
|
|
uint64_t m;
|
|
HaclBignumCarry(p);
|
|
p[0] += 19 * (p[4] >> 51);
|
|
p[4] &= 0x7ffffffffffff;
|
|
HaclBignumCarry(p);
|
|
p[0] += 19 * (p[4] >> 51);
|
|
p[1] += p[0] >> 51;
|
|
p[0] &= 0x7ffffffffffff;
|
|
p[1] &= 0x7ffffffffffff;
|
|
p[4] &= 0x7ffffffffffff;
|
|
m = GTE(p[0], 0x7ffffffffffed);
|
|
m &= EQ(p[1], 0x7ffffffffffff);
|
|
m &= EQ(p[2], 0x7ffffffffffff);
|
|
m &= EQ(p[3], 0x7ffffffffffff);
|
|
m &= EQ(p[4], 0x7ffffffffffff);
|
|
p[0] -= 0x7ffffffffffed & m;
|
|
p[1] -= 0x7ffffffffffff & m;
|
|
p[2] -= 0x7ffffffffffff & m;
|
|
p[3] -= 0x7ffffffffffff & m;
|
|
p[4] -= 0x7ffffffffffff & m;
|
|
Write64le(o + 000, p[1] << 51 | p[0] >> 00);
|
|
Write64le(o + 010, p[2] << 38 | p[1] >> 13);
|
|
Write64le(o + 020, p[3] << 25 | p[2] >> 26);
|
|
Write64le(o + 030, p[4] << 12 | p[3] >> 39);
|
|
}
|
|
|
|
static void HaclEcFormatScalarOfPoint(uint8_t o[32], uint64_t p[2][5]) {
|
|
uint64_t t[2][5];
|
|
HaclBignumCrecip(t[0], p[1]);
|
|
HaclBignumFmul(t[1], p[0], t[0]);
|
|
HaclEcFormatFcontract(o, t[1]);
|
|
}
|
|
|
|
static void HaclEcAddAndDoubleFmonty(uint64_t xz2[2][5], uint64_t xz3[2][5],
|
|
uint64_t xz[2][5], uint64_t xzprime[2][5],
|
|
uint64_t qx[5]) {
|
|
uint64_t b[7][5];
|
|
HaclBignumCopy(b[0], xz[0]);
|
|
HaclBignumFsum(xz[0], xz[1]);
|
|
HaclBignumFdif(xz[1], b[0]);
|
|
HaclBignumCopy(b[0], xzprime[0]);
|
|
HaclBignumFsum(xzprime[0], xzprime[1]);
|
|
HaclBignumFdif(xzprime[1], b[0]);
|
|
HaclBignumFmul(b[4], xzprime[0], xz[1]);
|
|
HaclBignumFmul(b[5], xz[0], xzprime[1]);
|
|
HaclBignumCopy(b[0], b[4]);
|
|
HaclBignumFsum(b[4], b[5]);
|
|
HaclBignumFdif(b[5], b[0]);
|
|
HaclBignumFsqr(xz3[0], b[4], 1);
|
|
HaclBignumFsqr(b[6], b[5], 1);
|
|
HaclBignumFmul(xz3[1], b[6], qx);
|
|
HaclBignumFsqr(b[2], xz[0], 1);
|
|
HaclBignumFsqr(b[3], xz[1], 1);
|
|
HaclBignumFmul(xz2[0], b[2], b[3]);
|
|
HaclBignumFdif(b[3], b[2]);
|
|
HaclBignumFscalar(b[1], b[3], 121665);
|
|
HaclBignumFsum(b[1], b[2]);
|
|
HaclBignumFmul(xz2[1], b[1], b[3]);
|
|
}
|
|
|
|
/**
|
|
* Computes elliptic curve 25519.
|
|
*/
|
|
void curve25519(uint8_t mypublic[32], const uint8_t secret[32],
|
|
const uint8_t basepoint[32]) {
|
|
uint32_t i, j;
|
|
uint8_t e[32], s;
|
|
uint64_t q[5], t[4][2][5] = {{{1}}, {{0}, {1}}};
|
|
HaclEcFormatFexpand(q, basepoint);
|
|
for (j = 0; j < 32; ++j) e[j] = secret[j];
|
|
e[0] &= 248;
|
|
e[31] = (e[31] & 127) | 64;
|
|
HaclBignumCopy(t[1][0], q);
|
|
for (i = 32; i--;) {
|
|
for (s = e[i], j = 4; j--;) {
|
|
HaclEcPointSwap(t[0], t[1], s >> 7);
|
|
HaclEcAddAndDoubleFmonty(t[2], t[3], t[0], t[1], q);
|
|
HaclEcPointSwap(t[2], t[3], s >> 7);
|
|
s <<= 1;
|
|
HaclEcPointSwap(t[2], t[3], s >> 7);
|
|
HaclEcAddAndDoubleFmonty(t[0], t[1], t[2], t[3], q);
|
|
HaclEcPointSwap(t[0], t[1], s >> 7);
|
|
s <<= 1;
|
|
}
|
|
}
|
|
HaclEcFormatScalarOfPoint(mypublic, t[0]);
|
|
}
|