Shamir Secret Sharing library in CCF (#810)

This commit is contained in:
Julien Maffre 2020-02-07 09:15:54 +00:00 коммит произвёл GitHub
Родитель 7f7657fe95
Коммит 6729fc0b4f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
20 изменённых файлов: 2092 добавлений и 1 удалений

21
3rdparty/sss/LICENSE поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2017 Daan Sprenkels <hello@dsprenkels.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

29
3rdparty/sss/Makefile поставляемый Normal file
Просмотреть файл

@ -0,0 +1,29 @@
CFLAGS = -Wall -g -O2
SRCS = hazmat.c randombytes.c sss.c tweetnacl.c
OBJS := ${SRCS:.c=.o}
all: libsss.a
libsss.a: randombytes/librandombytes.a $(OBJS)
$(AR) -rcs libsss.a $^
randombytes/librandombytes.a:
$(MAKE) -C randombytes librandombytes.a
# Force unrolling loops on hazmat.c
hazmat.o: CFLAGS += -funroll-loops
%.out: %.o randombytes/librandombytes.a
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS)
$(MEMCHECK) ./$@
test_hazmat.out: $(OBJS)
test_sss.out: $(OBJS)
.PHONY: check
check: test_hazmat.out test_sss.out
.PHONY: clean
clean:
$(MAKE) -C randombytes $@
$(RM) *.o *.gch *.a *.out

170
3rdparty/sss/README.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,170 @@
# Shamir secret sharing library
[![Build Status](https://travis-ci.org/dsprenkels/sss.svg?branch=master)](https://travis-ci.org/dsprenkels/sss)
`sss` is a library that exposes an API to split secret data buffers into
a number of different _shares_. With the possession of some or all of these
shares, the original secret can be restored. It is the schoolbook example of
a cryptographic _threshold scheme_. ([demo])
## Table of contents
1. [Introduction](#introduction)
2. [Download](#download)
3. [Usage](#usage)
1. [Example](#example)
4. [Bindings](#bindings)
5. [Technical details](#technical-details)
6. [Comparison of secret sharing libraries](#comparison-of-secret-sharing-libraries)
7. [Questions](#questions)
## Introduction
An example use case is a beer brewery which has a vault which contains their
precious super secret recipe. The 5 board members of this brewery do not trust
all the others well enough that they won't secretly break into the vault and
sell the recipe to a competitor. So they split the code into 5 shares, and
allow 4 shares to restore the original code. Now they are sure that the
majority of the staff will know when the vault is opened, but they can still
open the vault when one of the staff members is abroad or sick at home.
As often with crypto libraries, there is a lot of Shamir secret sharing code
around that *does not meet cryptographic standards* (a.k.a. is insecure).
Some details—like integrity checks and side-channel resistance—are often
forgotten. But these slip-ups can often fully compromise the security of the
scheme.
With this in mind, I have made this library to:
- Be side channel resistant
- Secure the shared secret with a MAC
- Use the platform (OS) randomness source
It should be safe to use this library in "the real world", but note that until
the release of version 1.0 the API may be changed without backward
compatibility.
## Download
Currently, I have not packaged this library yet, but I expect to do so very
soon. If you are planning to use the library, please drop me an email and I will
freeze the API spec. So for now you should use the following command to get the
code:
```shell
git clone --recursive https://github.com/dsprenkels/sss.git
```
## Usage
Secrets are provided as arrays of 64 bytes long. This should be big enough to
store generally small secrets. If you wish to split larger chunks of data, you
can use symmetric encryption and split the key instead. Shares are generated
from secret data using `sss_create_shares` and shares can be combined again
using the `sss_combine_shares` functions. The shares are a octet strings of
113 bytes each.
### Example
```c
#include "sss.h"
#include "randombytes.h"
#include <assert.h>
#include <string.h>
int main()
{
uint8_t data[sss_MLEN], restored[sss_MLEN];
sss_Share shares[5];
size_t idx;
int tmp;
/* Create a message [42, 42, ..., 42] */
for (idx = 0; idx < sizeof(data), ++idx) {
data[idx] = 42;
}
/* Split the secret into 5 shares (with a recombination theshold of 4) */
sss_create_shares(shares, data, 5, 4);
/* Combine some of the shares to restore the original secret */
tmp = sss_combine_shares(restored, shares, 4);
assert(tmp == 0);
assert(memcmp(restored, data, sss_MLEN) == 0);
}
```
## Bindings
I have currently written bindings for the following languages:
- [Node.js](https://github.com/dsprenkels/sss-node)
- [Go](https://github.com/dsprenkels/sss-go)
- [Rust](https://github.com/dsprenkels/sss-rs)
## Technical details
Shamir secret sharing works by generating a polynomial (e.g. _33x³ + 8x² + 29x +
42_). The lowest term is the term is the secret and is just filled in. All the
other terms are generated randomly. Then we can pick points on the polynomial
by filling in values for _x_. Each point is put in a share. Afterwards, with _k_
points we can use interpolation to restore a _k_-degree polynomial.
In practice there is a wrapper around the secret-sharing part (this is
done because of crypto-technical reasons). This wrapper uses the
Salsa20/Poly1305 authenticated encryption scheme. Because of this, the
shares are always a little bit larger than the original data.
This library uses a custom [`randombytes`][randombytes] function to generate a
random encapsulation key, which talks directly to the operating system. When
using the high level API, you are not allowed to choose your own key. It _must_
be uniformly random, because regularities in secret-shared can be exploited.
With the low level API (`hazmat.h`) you _can_ choose to secret-share a piece of
data of exactly 32 bytes. This produces a set of shares that are much shorter
than the high-level shares (namely 33 bytes each). However, keep in mind that
this module is called `hazmat.h` (for "hazardous materials") for a reason.
Please only use this if you _really_ know what you are doing. Raw "textbook"
Shamir secret sharing is only safe when using a uniformly random secret (with
128 bits of entropy). Note also that it is entirely insecure for integrity.
Please do not use the low-level API unless you _really_ have no other choice.
## Comparison of secret-sharing libraries
If you would like your library to be added here, please open a pull request. :)
| Library | Side-channels | Tamper-resistant | Secret length |
|-----------------|---------------|------------------|---------------|
| [B. Poettering] | Insecure¹ | Insecure | 128 bytes |
| [libgfshare] | Insecure² | Insecure | ∞ |
| [blockstack] | ??³ | Insecure | 160 bytes |
| [sssa-golang] | Secure | Secure⁴ | ∞ |
| [sssa-ruby] | ??³ | Secure⁴ | ∞ |
| [snipsco] | Secure | Insecure | Note⁶ |
| [dsprenkels] | Secure | Secure⁵ | 64 bytes |
### Notes
1. Uses the GNU gmp library.
2. Uses lookup tables for GF(256) multiplication.
3. This library is implemented in a high level scripting library which does not
guarantee that its basic operators execute in constant-time.
4. Uses randomized *x*-coordinates.
5. Uses randomized *y*-coordinates.
6. When using the [snipsco] library you will have to specify your own prime.
Computation time is _O(p²)_, so on a normal computer you will be limited to
a secret size of ~1024 bytes.
[B. Poettering]: http://point-at-infinity.org/ssss/
[libgfshare]: http://www.digital-scurf.org/software/libgfshare
[blockstack]: https://github.com/blockstack/secret-sharing
[sssa-golang]: https://github.com/SSSaaS/sssa-golang
[sssa-ruby]: https://github.com/SSSaaS/sssa-ruby
[snipsco]: https://github.com/snipsco/rust-threshold-secret-sharing
[dsprenkels]: https://github.com/dsprenkels/sss
## Questions
Feel free to send me an email on my Github associated e-mail address.
[demo]: https://dsprenkels.com/sss/
[randombytes]: https://github.com/dsprenkels/randombytes

359
3rdparty/sss/hazmat.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,359 @@
/*
* Implementation of the hazardous parts of the SSS library
*
* Author: Daan Sprenkels <hello@dsprenkels.com>
*
* This code contains the actual Shamir secret sharing functionality. The
* implementation of this code is based on the idea that the user likes to
* generate/combine 32 shares (in GF(2^8) at the same time, because a 256 bit
* key will be exactly 32 bytes. Therefore we bitslice all the input and
* unbitslice the output right before returning.
*
* This bitslice approach optimizes natively on all architectures that are 32
* bit or more. Care is taken to use not too many registers, to ensure that no
* values have to be leaked to the stack.
*
* All functions in this module are implemented constant time and constant
* lookup operations, as all proper crypto code must be.
*/
#include "randombytes.h"
#include "hazmat.h"
#include <assert.h>
#include <string.h>
typedef struct {
uint8_t x;
uint8_t y;
} ByteShare;
extern void
FIPS202_SHAKE256(const unsigned char *in, unsigned long long inLen,
unsigned char *out, unsigned long long outLen);
static void
bitslice(uint32_t r[8], const uint8_t x[32])
{
size_t bit_idx, arr_idx;
uint32_t cur;
memset(r, 0, sizeof(uint32_t[8]));
for (arr_idx = 0; arr_idx < 32; arr_idx++) {
cur = (uint32_t) x[arr_idx];
for (bit_idx = 0; bit_idx < 8; bit_idx++) {
r[bit_idx] |= ((cur & (1 << bit_idx)) >> bit_idx) << arr_idx;
}
}
}
static void
unbitslice(uint8_t r[32], const uint32_t x[8])
{
size_t bit_idx, arr_idx;
uint32_t cur;
memset(r, 0, sizeof(uint8_t[32]));
for (bit_idx = 0; bit_idx < 8; bit_idx++) {
cur = (uint32_t) x[bit_idx];
for (arr_idx = 0; arr_idx < 32; arr_idx++) {
r[arr_idx] |= ((cur & (1 << arr_idx)) >> arr_idx) << bit_idx;
}
}
}
static void
bitslice_setall(uint32_t r[8], const uint8_t x)
{
size_t idx;
for (idx = 0; idx < 8; idx++) {
r[idx] = ((int32_t) ((x & (1 << idx)) << (31 - idx))) >> 31;
}
}
/*
* Add (XOR) `r` with `x` and store the result in `r`.
*/
static void
gf256_add(uint32_t r[8], const uint32_t x[8])
{
size_t idx;
for (idx = 0; idx < 8; idx++) r[idx] ^= x[idx];
}
/*
* Safely multiply two bitsliced polynomials in GF(2^8) reduced by
* x^8 + x^4 + x^3 + x + 1. `r` and `a` may overlap, but overlapping of `r`
* and `b` will produce an incorrect result! If you need to square a polynomial
* use `gf256_square` instead.
*/
static void
gf256_mul(uint32_t r[8], const uint32_t a[8], const uint32_t b[8])
{
/* This function implements Russian Peasant multiplication on two
* bitsliced polynomials.
*
* I personally think that these kinds of long lists of operations
* are often a bit ugly. A double for loop would be nicer and would
* take up a lot less lines of code.
* However, some compilers seem to fail in optimizing these kinds of
* loops. So we will just have to do this by hand.
*/
uint32_t a2[8];
memcpy(a2, a, sizeof(uint32_t[8]));
r[0] = a2[0] & b[0]; /* add (assignment, because r is 0) */
r[1] = a2[1] & b[0];
r[2] = a2[2] & b[0];
r[3] = a2[3] & b[0];
r[4] = a2[4] & b[0];
r[5] = a2[5] & b[0];
r[6] = a2[6] & b[0];
r[7] = a2[7] & b[0];
a2[0] ^= a2[7]; /* reduce */
a2[2] ^= a2[7];
a2[3] ^= a2[7];
r[0] ^= a2[7] & b[1]; /* add */
r[1] ^= a2[0] & b[1];
r[2] ^= a2[1] & b[1];
r[3] ^= a2[2] & b[1];
r[4] ^= a2[3] & b[1];
r[5] ^= a2[4] & b[1];
r[6] ^= a2[5] & b[1];
r[7] ^= a2[6] & b[1];
a2[7] ^= a2[6]; /* reduce */
a2[1] ^= a2[6];
a2[2] ^= a2[6];
r[0] ^= a2[6] & b[2]; /* add */
r[1] ^= a2[7] & b[2];
r[2] ^= a2[0] & b[2];
r[3] ^= a2[1] & b[2];
r[4] ^= a2[2] & b[2];
r[5] ^= a2[3] & b[2];
r[6] ^= a2[4] & b[2];
r[7] ^= a2[5] & b[2];
a2[6] ^= a2[5]; /* reduce */
a2[0] ^= a2[5];
a2[1] ^= a2[5];
r[0] ^= a2[5] & b[3]; /* add */
r[1] ^= a2[6] & b[3];
r[2] ^= a2[7] & b[3];
r[3] ^= a2[0] & b[3];
r[4] ^= a2[1] & b[3];
r[5] ^= a2[2] & b[3];
r[6] ^= a2[3] & b[3];
r[7] ^= a2[4] & b[3];
a2[5] ^= a2[4]; /* reduce */
a2[7] ^= a2[4];
a2[0] ^= a2[4];
r[0] ^= a2[4] & b[4]; /* add */
r[1] ^= a2[5] & b[4];
r[2] ^= a2[6] & b[4];
r[3] ^= a2[7] & b[4];
r[4] ^= a2[0] & b[4];
r[5] ^= a2[1] & b[4];
r[6] ^= a2[2] & b[4];
r[7] ^= a2[3] & b[4];
a2[4] ^= a2[3]; /* reduce */
a2[6] ^= a2[3];
a2[7] ^= a2[3];
r[0] ^= a2[3] & b[5]; /* add */
r[1] ^= a2[4] & b[5];
r[2] ^= a2[5] & b[5];
r[3] ^= a2[6] & b[5];
r[4] ^= a2[7] & b[5];
r[5] ^= a2[0] & b[5];
r[6] ^= a2[1] & b[5];
r[7] ^= a2[2] & b[5];
a2[3] ^= a2[2]; /* reduce */
a2[5] ^= a2[2];
a2[6] ^= a2[2];
r[0] ^= a2[2] & b[6]; /* add */
r[1] ^= a2[3] & b[6];
r[2] ^= a2[4] & b[6];
r[3] ^= a2[5] & b[6];
r[4] ^= a2[6] & b[6];
r[5] ^= a2[7] & b[6];
r[6] ^= a2[0] & b[6];
r[7] ^= a2[1] & b[6];
a2[2] ^= a2[1]; /* reduce */
a2[4] ^= a2[1];
a2[5] ^= a2[1];
r[0] ^= a2[1] & b[7]; /* add */
r[1] ^= a2[2] & b[7];
r[2] ^= a2[3] & b[7];
r[3] ^= a2[4] & b[7];
r[4] ^= a2[5] & b[7];
r[5] ^= a2[6] & b[7];
r[6] ^= a2[7] & b[7];
r[7] ^= a2[0] & b[7];
}
/*
* Square `x` in GF(2^8) and write the result to `r`. `r` and `x` may overlap.
*/
static void
gf256_square(uint32_t r[8], const uint32_t x[8])
{
uint32_t r8, r10, r12, r14;
/* Use the Freshman's Dream rule to square the polynomial
* Assignments are done from 7 downto 0, because this allows the user
* to execute this function in-place (e.g. `gf256_square(r, r);`).
*/
r14 = x[7];
r12 = x[6];
r10 = x[5];
r8 = x[4];
r[6] = x[3];
r[4] = x[2];
r[2] = x[1];
r[0] = x[0];
/* Reduce with x^8 + x^4 + x^3 + x + 1 until order is less than 8 */
r[7] = r14; /* r[7] was 0 */
r[6] ^= r14;
r10 ^= r14;
/* Skip, because r13 is always 0 */
r[4] ^= r12;
r[5] = r12; /* r[5] was 0 */
r[7] ^= r12;
r8 ^= r12;
/* Skip, because r11 is always 0 */
r[2] ^= r10;
r[3] = r10; /* r[3] was 0 */
r[5] ^= r10;
r[6] ^= r10;
r[1] = r14; /* r[1] was 0 */
r[2] ^= r14; /* Substitute r9 by r14 because they will always be equal*/
r[4] ^= r14;
r[5] ^= r14;
r[0] ^= r8;
r[1] ^= r8;
r[3] ^= r8;
r[4] ^= r8;
}
/*
* Invert `x` in GF(2^8) and write the result to `r`
*/
static void
gf256_inv(uint32_t r[8], uint32_t x[8])
{
uint32_t y[8], z[8];
gf256_square(y, x); // y = x^2
gf256_square(y, y); // y = x^4
gf256_square(r, y); // r = x^8
gf256_mul(z, r, x); // z = x^9
gf256_square(r, r); // r = x^16
gf256_mul(r, r, z); // r = x^25
gf256_square(r, r); // r = x^50
gf256_square(z, r); // z = x^100
gf256_square(z, z); // z = x^200
gf256_mul(r, r, z); // r = x^250
gf256_mul(r, r, y); // r = x^254
}
/*
* Create `k` key shares of the key given in `key`. The caller has to ensure
* that the array `out` has enough space to hold at least `n` sss_Keyshare
* structs.
*/
void
sss_create_keyshares(sss_Keyshare *out,
const uint8_t key[32],
uint8_t n,
uint8_t k)
{
/* Check if the parameters are valid */
assert(n != 0);
assert(k != 0);
assert(k <= n);
uint8_t share_idx, coeff_idx, unbitsliced_x;
uint32_t poly0[8], poly[k-1][8], x[8], y[8], xpow[8], tmp[8];
/* Put the secret in the bottom part of the polynomial */
bitslice(poly0, key);
/* Generate the other terms of the polynomial */
randombytes((void*) poly, sizeof(poly));
for (share_idx = 0; share_idx < n; share_idx++) {
/* x value is in 1..n */
unbitsliced_x = share_idx + 1;
out[share_idx][0] = unbitsliced_x;
bitslice_setall(x, unbitsliced_x);
/* Calculate y */
memset(y, 0, sizeof(y));
memset(xpow, 0, sizeof(xpow));
xpow[0] = ~0;
gf256_add(y, poly0);
for (coeff_idx = 0; coeff_idx < (k-1); coeff_idx++) {
gf256_mul(xpow, xpow, x);
gf256_mul(tmp, xpow, poly[coeff_idx]);
gf256_add(y, tmp);
}
unbitslice(&out[share_idx][1], y);
}
}
/*
* Restore the `k` sss_Keyshare structs given in `shares` and write the result
* to `key`.
*/
void sss_combine_keyshares(uint8_t key[32],
const sss_Keyshare *key_shares,
uint8_t k)
{
size_t share_idx, idx1, idx2;
uint32_t xs[k][8], ys[k][8];
uint32_t num[8], denom[8], tmp[8];
uint32_t secret[8] = {0};
/* Collect the x and y values */
for (share_idx = 0; share_idx < k; share_idx++) {
bitslice_setall(xs[share_idx], key_shares[share_idx][0]);
bitslice(ys[share_idx], &key_shares[share_idx][1]);
}
/* Use Lagrange basis polynomials to calculate the secret coefficient */
for (idx1 = 0; idx1 < k; idx1++) {
memset(num, 0, sizeof(num));
memset(denom, 0, sizeof(denom));
num[0] = ~0; /* num is the numerator (=1) */
denom[0] = ~0; /* denom is the numerator (=1) */
for (idx2 = 0; idx2 < k; idx2++) {
if (idx1 == idx2) continue;
gf256_mul(num, num, xs[idx2]);
memcpy(tmp, xs[idx1], sizeof(uint32_t[8]));
gf256_add(tmp, xs[idx2]);
gf256_mul(denom, denom, tmp);
}
gf256_inv(tmp, denom); /* inverted denominator */
gf256_mul(num, num, tmp); /* basis polynomial */
gf256_mul(num, num, ys[idx1]); /* scaled coefficient */
gf256_add(secret, num);
}
unbitslice(key, secret);
}

70
3rdparty/sss/hazmat.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,70 @@
/*
* Low level API for Daan Sprenkels' Shamir secret sharing library
* Copyright (c) 2017 Daan Sprenkels <hello@dsprenkels.com>
*
* Usage of this API is hazardous and is only reserved for beings with a
* good understanding of the Shamir secret sharing scheme and who know how
* crypto code is implemented. If you are unsure about this, use the
* intermediate level API. You have been warned!
*/
#ifndef sss_HAZMAT_H_
#define sss_HAZMAT_H_
#include <inttypes.h>
#define sss_KEYSHARE_LEN 33 /* 1 + 32 */
/*
* One share of a cryptographic key which is shared using Shamir's
* the `sss_create_keyshares` function.
*/
typedef uint8_t sss_Keyshare[sss_KEYSHARE_LEN];
/*
* Share the secret given in `key` into `n` shares with a treshold value given
* in `k`. The resulting shares are written to `out`.
*
* The share generation that is done in this function is only secure if the key
* that is given is indeed a cryptographic key. This means that it should be
* randomly and uniformly generated string of 32 bytes.
*
* Also, for performance reasons, this function assumes that both `n` and `k`
* are *public* values.
*
* If you are looking for a function that *just* creates shares of arbitrary
* data, you should use the `sss_create_shares` function in `sss.h`.
*/
void sss_create_keyshares(sss_Keyshare *out,
const uint8_t key[32],
uint8_t n,
uint8_t k);
/*
* Combine the `k` shares provided in `shares` and write the resulting key to
* `key`. The amount of shares used to restore a secret may be larger than the
* threshold needed to restore them.
*
* This function does *not* do *any* checking for integrity. If any of the
* shares not original, this will result in an invalid resored value.
* All values written to `key` should be treated as secret. Even if some of the
* shares that were provided as input were incorrect, the resulting key *still*
* allows an attacker to gain information about the real key.
*
* This function treats `shares` and `key` as secret values. `k` is treated as
* a public value (for performance reasons).
*
* If you are looking for a function that combines shares of arbitrary
* data, you should use the `sss_combine_shares` function in `sss.h`.
*/
void sss_combine_keyshares(uint8_t key[32],
const sss_Keyshare *shares,
uint8_t k);
#endif /* sss_HAZMAT_H_ */

8
3rdparty/sss/randombytes.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the Apache 2.0 License.
#pragma once
#include <stddef.h>
extern int randombytes(unsigned char* data, size_t len);

133
3rdparty/sss/sss.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,133 @@
/*
* AEAD wrapper around the Secret shared data
*
* Author: Daan Sprenkels <hello@dsprenkels.com>
*
* This module implements a AEAD wrapper around some secret shared data,
* allowing the data to be in any format. (Directly secret-sharing requires the
* message to be picked uniformly in the message space.)
*
* The NaCl cryptographic library is used for the encryption. The encryption
* scheme that is used for wrapping the message is salsa20/poly1305. Because
* we are using an ephemeral key, we are using a zero'd nonce.
*/
#include "randombytes.h"
#include "tweetnacl.h"
#include "sss.h"
#include "tweetnacl.h"
#include <assert.h>
#include <string.h>
/*
* These assertions may be considered overkill, but would if the tweetnacl API
* ever change we *really* want to prevent buffer overflow vulnerabilities.
*/
#if crypto_secretbox_KEYBYTES != 32
# error "crypto_secretbox_KEYBYTES size is invalid"
#endif
/*
* Nonce for the `crypto_secretbox` authenticated encryption.
* The nonce is constant (zero), because we are using an ephemeral key.
*/
static const unsigned char nonce[crypto_secretbox_NONCEBYTES] = { 0 };
/*
* Return a pointer to the ciphertext part of this Share
*/
static uint8_t* get_ciphertext(const sss_Share *share)
{
return (uint8_t*) &(*share)[sss_KEYSHARE_LEN];
}
/*
* Return a pointer to the Keyshare part of this Share
*/
static sss_Keyshare* get_keyshare(const sss_Share *share)
{
return (sss_Keyshare*) &share[0];
}
/*
* Create `n` shares with theshold `k` and write them to `out`
*/
void sss_create_shares(sss_Share *out, const unsigned char *data,
uint8_t n, uint8_t k)
{
unsigned char key[32];
unsigned char m[crypto_secretbox_ZEROBYTES + sss_MLEN] = { 0 };
unsigned long long mlen = sizeof(m); /* length includes zero-bytes */
unsigned char c[mlen];
int tmp;
sss_Keyshare keyshares[n];
size_t idx;
/* Generate a random encryption key */
randombytes(key, sizeof(key));
/* AEAD encrypt the data with the key */
memcpy(&m[crypto_secretbox_ZEROBYTES], data, sss_MLEN);
tmp = crypto_secretbox(c, m, mlen, nonce, key);
assert(tmp == 0); /* should always happen */
/* Generate KeyShares */
sss_create_keyshares(keyshares, key, n, k);
/* Build regular shares */
for (idx = 0; idx < n; idx++) {
memcpy(get_keyshare(&out[idx]), &keyshares[idx][0],
sss_KEYSHARE_LEN);
memcpy(get_ciphertext(&out[idx]),
&c[crypto_secretbox_BOXZEROBYTES], sss_CLEN);
}
}
/*
* Combine `k` shares pointed to by `shares` and write the result to `data`
*
* This function returns -1 if any of the shares were corrupted or if the number
* of shares was too low. It is not possible to detect which of these errors
* did occur.
*/
int sss_combine_shares(uint8_t *data, const sss_Share *shares, uint8_t k)
{
unsigned char key[crypto_secretbox_KEYBYTES];
unsigned char c[crypto_secretbox_BOXZEROBYTES + sss_CLEN] = { 0 };
unsigned long long clen = sizeof(c);
unsigned char m[clen];
sss_Keyshare keyshares[k];
size_t idx;
int ret = 0;
/* Check if all ciphertexts are the same */
if (k < 1) return -1;
for (idx = 1; idx < k; idx++) {
if (memcmp(get_ciphertext(&shares[0]),
get_ciphertext(&shares[idx]), sss_CLEN) != 0) {
return -1;
}
}
/* Restore the key */
for (idx = 0; idx < k; idx++) {
memcpy(&keyshares[idx], get_keyshare(&shares[idx]),
sss_KEYSHARE_LEN);
}
sss_combine_keyshares(key, keyshares, k);
/* Decrypt the ciphertext */
memcpy(&c[crypto_secretbox_BOXZEROBYTES],
&shares[0][sss_KEYSHARE_LEN], sss_CLEN);
ret |= crypto_secretbox_open(m, c, clen, nonce, key);
memcpy(data, &m[crypto_secretbox_ZEROBYTES], sss_MLEN);
return ret;
}

70
3rdparty/sss/sss.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,70 @@
/*
* Intermediate level API for Daan Sprenkels' Shamir secret sharing library
* Copyright (c) 2017 Daan Sprenkels <hello@dsprenkels.com>
*/
#ifndef sss_SSS_H_
#define sss_SSS_H_
#include "hazmat.h"
#include "tweetnacl.h"
#include <inttypes.h>
#ifndef sss_MLEN
/*
Length of the message (must be known at compile-time)
*/
#define sss_MLEN sizeof(uint8_t[64])
#endif
/*
* Length of the ciphertext, including the message authentication code
*/
#define sss_CLEN (sss_MLEN + 16)
/*
* Length of a SSS share
*/
#define sss_SHARE_LEN (sss_CLEN + sss_KEYSHARE_LEN)
/*
* One share of a secret which is shared using Shamir's
* the `sss_create_shares` function.
*/
typedef uint8_t sss_Share[sss_SHARE_LEN];
/*
* Create `n` shares of the secret data `data`. Share such that `k` or more
* shares will be able to restore the secret.
*
* This function will put the resulting shares in the array pointed to by
* `out`. The caller has to guarantee that this array will fit at least `n`
* instances of `sss_Share`.
*/
void sss_create_shares(sss_Share *out,
const uint8_t *data,
uint8_t n,
uint8_t k);
/*
* Combine the `k` shares pointed to by `shares` and put the resulting secret
* data in `data`. The caller has to ensure that the `data` array will fit
* at least `sss_MLEN` (default: 64) bytes.
*
* On success, this function will return 0. If combining the secret fails,
* this function will return a nonzero return code. On failure, the value
* in `data` may have been altered, but must still be considered secret.
*/
int sss_combine_shares(uint8_t *data,
const sss_Share *shares,
uint8_t k);
#endif /* sss_SSS_H_ */

38
3rdparty/sss/test_hazmat.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,38 @@
#include "hazmat.h"
#include <assert.h>
#include <string.h>
static void test_key_shares()
{
uint8_t key[32], restored[32];
sss_Keyshare key_shares[256];
size_t idx;
for (idx = 0; idx < 32; idx++) {
key[idx] = idx;
}
sss_create_keyshares(key_shares, key, 1, 1);
sss_combine_keyshares(restored, key_shares, 1);
assert(memcmp(key, restored, 32) == 0);
sss_create_keyshares(key_shares, key, 3, 2);
sss_combine_keyshares(restored, &key_shares[1], 2);
assert(memcmp(key, restored, 32) == 0);
sss_create_keyshares(key_shares, key, 255, 127);
sss_combine_keyshares(restored, &key_shares[128], 127);
assert(memcmp(key, restored, 32) == 0);
sss_create_keyshares(key_shares, key, 255, 255);
sss_combine_keyshares(restored, key_shares, 255);
assert(memcmp(key, restored, 32) == 0);
}
int main()
{
test_key_shares();
return 0;
}

35
3rdparty/sss/test_sss.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,35 @@
#include "sss.h"
#include <assert.h>
#include <string.h>
int main()
{
unsigned char data[sss_MLEN] = { 42 }, restored[sss_MLEN];
sss_Share shares[256];
int tmp;
/* Normal operation */
sss_create_shares(shares, data, 1, 1);
tmp = sss_combine_shares(restored, shares, 1);
assert(tmp == 0);
assert(memcmp(restored, data, sss_MLEN) == 0);
/* A lot of shares */
sss_create_shares(shares, data, 255, 255);
tmp = sss_combine_shares(restored, shares, 255);
assert(tmp == 0);
assert(memcmp(restored, data, sss_MLEN) == 0);
/* Not enough shares to restore secret */
sss_create_shares(shares, data, 100, 100);
tmp = sss_combine_shares(restored, shares, 99);
assert(tmp == -1);
/* Too many secrets should also restore the secret */
sss_create_shares(shares, data, 200, 100);
tmp = sss_combine_shares(restored, shares, 200);
assert(tmp == 0);
assert(memcmp(restored, data, sss_MLEN) == 0);
return 0;
}

810
3rdparty/sss/tweetnacl.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,810 @@
#include "tweetnacl.h"
#define FOR(i,n) for (i = 0;i < n;++i)
#define sv static void
typedef unsigned char u8;
typedef unsigned long u32;
typedef unsigned long long u64;
typedef long long i64;
typedef i64 gf[16];
extern void randombytes(u8 *,u64);
static const u8
_0[16],
_9[32] = {9};
static const gf
gf0,
gf1 = {1},
_121665 = {0xDB41,1},
D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203},
D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406},
X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169},
Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666},
I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
static u32 L32(u32 x,int c) { return (x << c) | ((x&0xffffffff) >> (32 - c)); }
static u32 ld32(const u8 *x)
{
u32 u = x[3];
u = (u<<8)|x[2];
u = (u<<8)|x[1];
return (u<<8)|x[0];
}
static u64 dl64(const u8 *x)
{
u64 i,u=0;
FOR(i,8) u=(u<<8)|x[i];
return u;
}
sv st32(u8 *x,u32 u)
{
int i;
FOR(i,4) { x[i] = u; u >>= 8; }
}
sv ts64(u8 *x,u64 u)
{
int i;
for (i = 7;i >= 0;--i) { x[i] = u; u >>= 8; }
}
static int vn(const u8 *x,const u8 *y,int n)
{
u32 i,d = 0;
FOR(i,n) d |= x[i]^y[i];
return (1 & ((d - 1) >> 8)) - 1;
}
int crypto_verify_16(const u8 *x,const u8 *y)
{
return vn(x,y,16);
}
int crypto_verify_32(const u8 *x,const u8 *y)
{
return vn(x,y,32);
}
sv core(u8 *out,const u8 *in,const u8 *k,const u8 *c,int h)
{
u32 w[16],x[16],y[16],t[4];
int i,j,m;
FOR(i,4) {
x[5*i] = ld32(c+4*i);
x[1+i] = ld32(k+4*i);
x[6+i] = ld32(in+4*i);
x[11+i] = ld32(k+16+4*i);
}
FOR(i,16) y[i] = x[i];
FOR(i,20) {
FOR(j,4) {
FOR(m,4) t[m] = x[(5*j+4*m)%16];
t[1] ^= L32(t[0]+t[3], 7);
t[2] ^= L32(t[1]+t[0], 9);
t[3] ^= L32(t[2]+t[1],13);
t[0] ^= L32(t[3]+t[2],18);
FOR(m,4) w[4*j+(j+m)%4] = t[m];
}
FOR(m,16) x[m] = w[m];
}
if (h) {
FOR(i,16) x[i] += y[i];
FOR(i,4) {
x[5*i] -= ld32(c+4*i);
x[6+i] -= ld32(in+4*i);
}
FOR(i,4) {
st32(out+4*i,x[5*i]);
st32(out+16+4*i,x[6+i]);
}
} else
FOR(i,16) st32(out + 4 * i,x[i] + y[i]);
}
int crypto_core_salsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c)
{
core(out,in,k,c,0);
return 0;
}
int crypto_core_hsalsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c)
{
core(out,in,k,c,1);
return 0;
}
static const u8 sigma[16] = "expand 32-byte k";
int crypto_stream_salsa20_xor(u8 *c,const u8 *m,u64 b,const u8 *n,const u8 *k)
{
u8 z[16],x[64];
u32 u,i;
if (!b) return 0;
FOR(i,16) z[i] = 0;
FOR(i,8) z[i] = n[i];
while (b >= 64) {
crypto_core_salsa20(x,z,k,sigma);
FOR(i,64) c[i] = (m?m[i]:0) ^ x[i];
u = 1;
for (i = 8;i < 16;++i) {
u += (u32) z[i];
z[i] = u;
u >>= 8;
}
b -= 64;
c += 64;
if (m) m += 64;
}
if (b) {
crypto_core_salsa20(x,z,k,sigma);
FOR(i,b) c[i] = (m?m[i]:0) ^ x[i];
}
return 0;
}
int crypto_stream_salsa20(u8 *c,u64 d,const u8 *n,const u8 *k)
{
return crypto_stream_salsa20_xor(c,0,d,n,k);
}
int crypto_stream(u8 *c,u64 d,const u8 *n,const u8 *k)
{
u8 s[32];
crypto_core_hsalsa20(s,n,k,sigma);
return crypto_stream_salsa20(c,d,n+16,s);
}
int crypto_stream_xor(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
{
u8 s[32];
crypto_core_hsalsa20(s,n,k,sigma);
return crypto_stream_salsa20_xor(c,m,d,n+16,s);
}
sv add1305(u32 *h,const u32 *c)
{
u32 j,u = 0;
FOR(j,17) {
u += h[j] + c[j];
h[j] = u & 255;
u >>= 8;
}
}
static const u32 minusp[17] = {
5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252
} ;
int crypto_onetimeauth(u8 *out,const u8 *m,u64 n,const u8 *k)
{
u32 s,i,j,u,x[17],r[17],h[17],c[17],g[17];
FOR(j,17) r[j]=h[j]=0;
FOR(j,16) r[j]=k[j];
r[3]&=15;
r[4]&=252;
r[7]&=15;
r[8]&=252;
r[11]&=15;
r[12]&=252;
r[15]&=15;
while (n > 0) {
FOR(j,17) c[j] = 0;
for (j = 0;(j < 16) && (j < n);++j) c[j] = m[j];
c[j] = 1;
m += j; n -= j;
add1305(h,c);
FOR(i,17) {
x[i] = 0;
FOR(j,17) x[i] += h[j] * ((j <= i) ? r[i - j] : 320 * r[i + 17 - j]);
}
FOR(i,17) h[i] = x[i];
u = 0;
FOR(j,16) {
u += h[j];
h[j] = u & 255;
u >>= 8;
}
u += h[16]; h[16] = u & 3;
u = 5 * (u >> 2);
FOR(j,16) {
u += h[j];
h[j] = u & 255;
u >>= 8;
}
u += h[16]; h[16] = u;
}
FOR(j,17) g[j] = h[j];
add1305(h,minusp);
s = -(h[16] >> 7);
FOR(j,17) h[j] ^= s & (g[j] ^ h[j]);
FOR(j,16) c[j] = k[j + 16];
c[16] = 0;
add1305(h,c);
FOR(j,16) out[j] = h[j];
return 0;
}
int crypto_onetimeauth_verify(const u8 *h,const u8 *m,u64 n,const u8 *k)
{
u8 x[16];
crypto_onetimeauth(x,m,n,k);
return crypto_verify_16(h,x);
}
int crypto_secretbox(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
{
int i;
if (d < 32) return -1;
crypto_stream_xor(c,m,d,n,k);
crypto_onetimeauth(c + 16,c + 32,d - 32,c);
FOR(i,16) c[i] = 0;
return 0;
}
int crypto_secretbox_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k)
{
int i;
u8 x[32];
if (d < 32) return -1;
crypto_stream(x,32,n,k);
if (crypto_onetimeauth_verify(c + 16,c + 32,d - 32,x) != 0) return -1;
crypto_stream_xor(m,c,d,n,k);
FOR(i,32) m[i] = 0;
return 0;
}
sv set25519(gf r, const gf a)
{
int i;
FOR(i,16) r[i]=a[i];
}
sv car25519(gf o)
{
int i;
i64 c;
FOR(i,16) {
o[i]+=(1LL<<16);
c=o[i]>>16;
o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15);
o[i]-=c<<16;
}
}
sv sel25519(gf p,gf q,int b)
{
i64 t,i,c=~(b-1);
FOR(i,16) {
t= c&(p[i]^q[i]);
p[i]^=t;
q[i]^=t;
}
}
sv pack25519(u8 *o,const gf n)
{
int i,j,b;
gf m,t;
FOR(i,16) t[i]=n[i];
car25519(t);
car25519(t);
car25519(t);
FOR(j,2) {
m[0]=t[0]-0xffed;
for(i=1;i<15;i++) {
m[i]=t[i]-0xffff-((m[i-1]>>16)&1);
m[i-1]&=0xffff;
}
m[15]=t[15]-0x7fff-((m[14]>>16)&1);
b=(m[15]>>16)&1;
m[14]&=0xffff;
sel25519(t,m,1-b);
}
FOR(i,16) {
o[2*i]=t[i]&0xff;
o[2*i+1]=t[i]>>8;
}
}
static int neq25519(const gf a, const gf b)
{
u8 c[32],d[32];
pack25519(c,a);
pack25519(d,b);
return crypto_verify_32(c,d);
}
static u8 par25519(const gf a)
{
u8 d[32];
pack25519(d,a);
return d[0]&1;
}
sv unpack25519(gf o, const u8 *n)
{
int i;
FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8);
o[15]&=0x7fff;
}
sv A(gf o,const gf a,const gf b)
{
int i;
FOR(i,16) o[i]=a[i]+b[i];
}
sv Z(gf o,const gf a,const gf b)
{
int i;
FOR(i,16) o[i]=a[i]-b[i];
}
sv M(gf o,const gf a,const gf b)
{
i64 i,j,t[31];
FOR(i,31) t[i]=0;
FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j];
FOR(i,15) t[i]+=38*t[i+16];
FOR(i,16) o[i]=t[i];
car25519(o);
car25519(o);
}
sv S(gf o,const gf a)
{
M(o,a,a);
}
sv inv25519(gf o,const gf i)
{
gf c;
int a;
FOR(a,16) c[a]=i[a];
for(a=253;a>=0;a--) {
S(c,c);
if(a!=2&&a!=4) M(c,c,i);
}
FOR(a,16) o[a]=c[a];
}
sv pow2523(gf o,const gf i)
{
gf c;
int a;
FOR(a,16) c[a]=i[a];
for(a=250;a>=0;a--) {
S(c,c);
if(a!=1) M(c,c,i);
}
FOR(a,16) o[a]=c[a];
}
int crypto_scalarmult(u8 *q,const u8 *n,const u8 *p)
{
u8 z[32];
i64 x[80],r,i;
gf a,b,c,d,e,f;
FOR(i,31) z[i]=n[i];
z[31]=(n[31]&127)|64;
z[0]&=248;
unpack25519(x,p);
FOR(i,16) {
b[i]=x[i];
d[i]=a[i]=c[i]=0;
}
a[0]=d[0]=1;
for(i=254;i>=0;--i) {
r=(z[i>>3]>>(i&7))&1;
sel25519(a,b,r);
sel25519(c,d,r);
A(e,a,c);
Z(a,a,c);
A(c,b,d);
Z(b,b,d);
S(d,e);
S(f,a);
M(a,c,a);
M(c,b,e);
A(e,a,c);
Z(a,a,c);
S(b,a);
Z(c,d,f);
M(a,c,_121665);
A(a,a,d);
M(c,c,a);
M(a,d,f);
M(d,b,x);
S(b,e);
sel25519(a,b,r);
sel25519(c,d,r);
}
FOR(i,16) {
x[i+16]=a[i];
x[i+32]=c[i];
x[i+48]=b[i];
x[i+64]=d[i];
}
inv25519(x+32,x+32);
M(x+16,x+16,x+32);
pack25519(q,x+16);
return 0;
}
int crypto_scalarmult_base(u8 *q,const u8 *n)
{
return crypto_scalarmult(q,n,_9);
}
int crypto_box_keypair(u8 *y,u8 *x)
{
randombytes(x,32);
return crypto_scalarmult_base(y,x);
}
int crypto_box_beforenm(u8 *k,const u8 *y,const u8 *x)
{
u8 s[32];
crypto_scalarmult(s,x,y);
return crypto_core_hsalsa20(k,_0,s,sigma);
}
int crypto_box_afternm(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
{
return crypto_secretbox(c,m,d,n,k);
}
int crypto_box_open_afternm(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k)
{
return crypto_secretbox_open(m,c,d,n,k);
}
int crypto_box(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *y,const u8 *x)
{
u8 k[32];
crypto_box_beforenm(k,y,x);
return crypto_box_afternm(c,m,d,n,k);
}
int crypto_box_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *y,const u8 *x)
{
u8 k[32];
crypto_box_beforenm(k,y,x);
return crypto_box_open_afternm(m,c,d,n,k);
}
static u64 R(u64 x,int c) { return (x >> c) | (x << (64 - c)); }
static u64 Ch(u64 x,u64 y,u64 z) { return (x & y) ^ (~x & z); }
static u64 Maj(u64 x,u64 y,u64 z) { return (x & y) ^ (x & z) ^ (y & z); }
static u64 Sigma0(u64 x) { return R(x,28) ^ R(x,34) ^ R(x,39); }
static u64 Sigma1(u64 x) { return R(x,14) ^ R(x,18) ^ R(x,41); }
static u64 sigma0(u64 x) { return R(x, 1) ^ R(x, 8) ^ (x >> 7); }
static u64 sigma1(u64 x) { return R(x,19) ^ R(x,61) ^ (x >> 6); }
static const u64 K[80] =
{
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
};
int crypto_hashblocks(u8 *x,const u8 *m,u64 n)
{
u64 z[8],b[8],a[8],w[16],t;
int i,j;
FOR(i,8) z[i] = a[i] = dl64(x + 8 * i);
while (n >= 128) {
FOR(i,16) w[i] = dl64(m + 8 * i);
FOR(i,80) {
FOR(j,8) b[j] = a[j];
t = a[7] + Sigma1(a[4]) + Ch(a[4],a[5],a[6]) + K[i] + w[i%16];
b[7] = t + Sigma0(a[0]) + Maj(a[0],a[1],a[2]);
b[3] += t;
FOR(j,8) a[(j+1)%8] = b[j];
if (i%16 == 15)
FOR(j,16)
w[j] += w[(j+9)%16] + sigma0(w[(j+1)%16]) + sigma1(w[(j+14)%16]);
}
FOR(i,8) { a[i] += z[i]; z[i] = a[i]; }
m += 128;
n -= 128;
}
FOR(i,8) ts64(x+8*i,z[i]);
return n;
}
static const u8 iv[64] = {
0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08,
0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b,
0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b,
0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1,
0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1,
0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f,
0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b,
0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79
} ;
int crypto_hash(u8 *out,const u8 *m,u64 n)
{
u8 h[64],x[256];
u64 i,b = n;
FOR(i,64) h[i] = iv[i];
crypto_hashblocks(h,m,n);
m += n;
n &= 127;
m -= n;
FOR(i,256) x[i] = 0;
FOR(i,n) x[i] = m[i];
x[n] = 128;
n = 256-128*(n<112);
x[n-9] = b >> 61;
ts64(x+n-8,b<<3);
crypto_hashblocks(h,x,n);
FOR(i,64) out[i] = h[i];
return 0;
}
sv add(gf p[4],gf q[4])
{
gf a,b,c,d,t,e,f,g,h;
Z(a, p[1], p[0]);
Z(t, q[1], q[0]);
M(a, a, t);
A(b, p[0], p[1]);
A(t, q[0], q[1]);
M(b, b, t);
M(c, p[3], q[3]);
M(c, c, D2);
M(d, p[2], q[2]);
A(d, d, d);
Z(e, b, a);
Z(f, d, c);
A(g, d, c);
A(h, b, a);
M(p[0], e, f);
M(p[1], h, g);
M(p[2], g, f);
M(p[3], e, h);
}
sv cswap(gf p[4],gf q[4],u8 b)
{
int i;
FOR(i,4)
sel25519(p[i],q[i],b);
}
sv pack(u8 *r,gf p[4])
{
gf tx, ty, zi;
inv25519(zi, p[2]);
M(tx, p[0], zi);
M(ty, p[1], zi);
pack25519(r, ty);
r[31] ^= par25519(tx) << 7;
}
sv scalarmult(gf p[4],gf q[4],const u8 *s)
{
int i;
set25519(p[0],gf0);
set25519(p[1],gf1);
set25519(p[2],gf1);
set25519(p[3],gf0);
for (i = 255;i >= 0;--i) {
u8 b = (s[i/8]>>(i&7))&1;
cswap(p,q,b);
add(q,p);
add(p,p);
cswap(p,q,b);
}
}
sv scalarbase(gf p[4],const u8 *s)
{
gf q[4];
set25519(q[0],X);
set25519(q[1],Y);
set25519(q[2],gf1);
M(q[3],X,Y);
scalarmult(p,q,s);
}
int crypto_sign_keypair(u8 *pk, u8 *sk)
{
u8 d[64];
gf p[4];
int i;
randombytes(sk, 32);
crypto_hash(d, sk, 32);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
scalarbase(p,d);
pack(pk,p);
FOR(i,32) sk[32 + i] = pk[i];
return 0;
}
static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10};
sv modL(u8 *r,i64 x[64])
{
i64 carry,i,j;
for (i = 63;i >= 32;--i) {
carry = 0;
for (j = i - 32;j < i - 12;++j) {
x[j] += carry - 16 * x[i] * L[j - (i - 32)];
carry = (x[j] + 128) >> 8;
x[j] -= carry << 8;
}
x[j] += carry;
x[i] = 0;
}
carry = 0;
FOR(j,32) {
x[j] += carry - (x[31] >> 4) * L[j];
carry = x[j] >> 8;
x[j] &= 255;
}
FOR(j,32) x[j] -= carry * L[j];
FOR(i,32) {
x[i+1] += x[i] >> 8;
r[i] = x[i] & 255;
}
}
sv reduce(u8 *r)
{
i64 x[64],i;
FOR(i,64) x[i] = (u64) r[i];
FOR(i,64) r[i] = 0;
modL(r,x);
}
int crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 n,const u8 *sk)
{
u8 d[64],h[64],r[64];
i64 i,j,x[64];
gf p[4];
crypto_hash(d, sk, 32);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
*smlen = n+64;
FOR(i,n) sm[64 + i] = m[i];
FOR(i,32) sm[32 + i] = d[32 + i];
crypto_hash(r, sm+32, n+32);
reduce(r);
scalarbase(p,r);
pack(sm,p);
FOR(i,32) sm[i+32] = sk[i+32];
crypto_hash(h,sm,n + 64);
reduce(h);
FOR(i,64) x[i] = 0;
FOR(i,32) x[i] = (u64) r[i];
FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j];
modL(sm + 32,x);
return 0;
}
static int unpackneg(gf r[4],const u8 p[32])
{
gf t, chk, num, den, den2, den4, den6;
set25519(r[2],gf1);
unpack25519(r[1],p);
S(num,r[1]);
M(den,num,D);
Z(num,num,r[2]);
A(den,r[2],den);
S(den2,den);
S(den4,den2);
M(den6,den4,den2);
M(t,den6,num);
M(t,t,den);
pow2523(t,t);
M(t,t,num);
M(t,t,den);
M(t,t,den);
M(r[0],t,den);
S(chk,r[0]);
M(chk,chk,den);
if (neq25519(chk, num)) M(r[0],r[0],I);
S(chk,r[0]);
M(chk,chk,den);
if (neq25519(chk, num)) return -1;
if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]);
M(r[3],r[0],r[1]);
return 0;
}
int crypto_sign_open(u8 *m,u64 *mlen,const u8 *sm,u64 n,const u8 *pk)
{
int i;
u8 t[32],h[64];
gf p[4],q[4];
*mlen = -1;
if (n < 64) return -1;
if (unpackneg(q,pk)) return -1;
FOR(i,n) m[i] = sm[i];
FOR(i,32) m[i+32] = pk[i];
crypto_hash(h,m,n);
reduce(h);
scalarmult(p,q,h);
scalarbase(q,sm + 32);
add(p,q);
pack(t,p);
n -= 64;
if (crypto_verify_32(sm, t)) {
FOR(i,n) m[i] = 0;
return -1;
}
FOR(i,n) m[i] = sm[i + 64];
*mlen = n;
return 0;
}

272
3rdparty/sss/tweetnacl.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,272 @@
#ifndef TWEETNACL_H
#define TWEETNACL_H
#define crypto_auth_PRIMITIVE "hmacsha512256"
#define crypto_auth crypto_auth_hmacsha512256
#define crypto_auth_verify crypto_auth_hmacsha512256_verify
#define crypto_auth_BYTES crypto_auth_hmacsha512256_BYTES
#define crypto_auth_KEYBYTES crypto_auth_hmacsha512256_KEYBYTES
#define crypto_auth_IMPLEMENTATION crypto_auth_hmacsha512256_IMPLEMENTATION
#define crypto_auth_VERSION crypto_auth_hmacsha512256_VERSION
#define crypto_auth_hmacsha512256_tweet_BYTES 32
#define crypto_auth_hmacsha512256_tweet_KEYBYTES 32
extern int crypto_auth_hmacsha512256_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
extern int crypto_auth_hmacsha512256_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
#define crypto_auth_hmacsha512256_tweet_VERSION "-"
#define crypto_auth_hmacsha512256 crypto_auth_hmacsha512256_tweet
#define crypto_auth_hmacsha512256_verify crypto_auth_hmacsha512256_tweet_verify
#define crypto_auth_hmacsha512256_BYTES crypto_auth_hmacsha512256_tweet_BYTES
#define crypto_auth_hmacsha512256_KEYBYTES crypto_auth_hmacsha512256_tweet_KEYBYTES
#define crypto_auth_hmacsha512256_VERSION crypto_auth_hmacsha512256_tweet_VERSION
#define crypto_auth_hmacsha512256_IMPLEMENTATION "crypto_auth/hmacsha512256/tweet"
#define crypto_box_PRIMITIVE "curve25519xsalsa20poly1305"
#define crypto_box crypto_box_curve25519xsalsa20poly1305
#define crypto_box_open crypto_box_curve25519xsalsa20poly1305_open
#define crypto_box_keypair crypto_box_curve25519xsalsa20poly1305_keypair
#define crypto_box_beforenm crypto_box_curve25519xsalsa20poly1305_beforenm
#define crypto_box_afternm crypto_box_curve25519xsalsa20poly1305_afternm
#define crypto_box_open_afternm crypto_box_curve25519xsalsa20poly1305_open_afternm
#define crypto_box_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES
#define crypto_box_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES
#define crypto_box_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES
#define crypto_box_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_NONCEBYTES
#define crypto_box_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_ZEROBYTES
#define crypto_box_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES
#define crypto_box_IMPLEMENTATION crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION
#define crypto_box_VERSION crypto_box_curve25519xsalsa20poly1305_VERSION
#define crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES 32
#define crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES 32
#define crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES 32
#define crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES 24
#define crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES 32
#define crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES 16
extern int crypto_box_curve25519xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *);
extern int crypto_box_curve25519xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *,const unsigned char *);
extern int crypto_box_curve25519xsalsa20poly1305_tweet_keypair(unsigned char *,unsigned char *);
extern int crypto_box_curve25519xsalsa20poly1305_tweet_beforenm(unsigned char *,const unsigned char *,const unsigned char *);
extern int crypto_box_curve25519xsalsa20poly1305_tweet_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
extern int crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
#define crypto_box_curve25519xsalsa20poly1305_tweet_VERSION "-"
#define crypto_box_curve25519xsalsa20poly1305 crypto_box_curve25519xsalsa20poly1305_tweet
#define crypto_box_curve25519xsalsa20poly1305_open crypto_box_curve25519xsalsa20poly1305_tweet_open
#define crypto_box_curve25519xsalsa20poly1305_keypair crypto_box_curve25519xsalsa20poly1305_tweet_keypair
#define crypto_box_curve25519xsalsa20poly1305_beforenm crypto_box_curve25519xsalsa20poly1305_tweet_beforenm
#define crypto_box_curve25519xsalsa20poly1305_afternm crypto_box_curve25519xsalsa20poly1305_tweet_afternm
#define crypto_box_curve25519xsalsa20poly1305_open_afternm crypto_box_curve25519xsalsa20poly1305_tweet_open_afternm
#define crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_PUBLICKEYBYTES
#define crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES crypto_box_curve25519xsalsa20poly1305_tweet_SECRETKEYBYTES
#define crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BEFORENMBYTES
#define crypto_box_curve25519xsalsa20poly1305_NONCEBYTES crypto_box_curve25519xsalsa20poly1305_tweet_NONCEBYTES
#define crypto_box_curve25519xsalsa20poly1305_ZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_ZEROBYTES
#define crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES crypto_box_curve25519xsalsa20poly1305_tweet_BOXZEROBYTES
#define crypto_box_curve25519xsalsa20poly1305_VERSION crypto_box_curve25519xsalsa20poly1305_tweet_VERSION
#define crypto_box_curve25519xsalsa20poly1305_IMPLEMENTATION "crypto_box/curve25519xsalsa20poly1305/tweet"
#define crypto_core_PRIMITIVE "salsa20"
#define crypto_core crypto_core_salsa20
#define crypto_core_OUTPUTBYTES crypto_core_salsa20_OUTPUTBYTES
#define crypto_core_INPUTBYTES crypto_core_salsa20_INPUTBYTES
#define crypto_core_KEYBYTES crypto_core_salsa20_KEYBYTES
#define crypto_core_CONSTBYTES crypto_core_salsa20_CONSTBYTES
#define crypto_core_IMPLEMENTATION crypto_core_salsa20_IMPLEMENTATION
#define crypto_core_VERSION crypto_core_salsa20_VERSION
#define crypto_core_salsa20_tweet_OUTPUTBYTES 64
#define crypto_core_salsa20_tweet_INPUTBYTES 16
#define crypto_core_salsa20_tweet_KEYBYTES 32
#define crypto_core_salsa20_tweet_CONSTBYTES 16
extern int crypto_core_salsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *);
#define crypto_core_salsa20_tweet_VERSION "-"
#define crypto_core_salsa20 crypto_core_salsa20_tweet
#define crypto_core_salsa20_OUTPUTBYTES crypto_core_salsa20_tweet_OUTPUTBYTES
#define crypto_core_salsa20_INPUTBYTES crypto_core_salsa20_tweet_INPUTBYTES
#define crypto_core_salsa20_KEYBYTES crypto_core_salsa20_tweet_KEYBYTES
#define crypto_core_salsa20_CONSTBYTES crypto_core_salsa20_tweet_CONSTBYTES
#define crypto_core_salsa20_VERSION crypto_core_salsa20_tweet_VERSION
#define crypto_core_salsa20_IMPLEMENTATION "crypto_core/salsa20/tweet"
#define crypto_core_hsalsa20_tweet_OUTPUTBYTES 32
#define crypto_core_hsalsa20_tweet_INPUTBYTES 16
#define crypto_core_hsalsa20_tweet_KEYBYTES 32
#define crypto_core_hsalsa20_tweet_CONSTBYTES 16
extern int crypto_core_hsalsa20_tweet(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *);
#define crypto_core_hsalsa20_tweet_VERSION "-"
#define crypto_core_hsalsa20 crypto_core_hsalsa20_tweet
#define crypto_core_hsalsa20_OUTPUTBYTES crypto_core_hsalsa20_tweet_OUTPUTBYTES
#define crypto_core_hsalsa20_INPUTBYTES crypto_core_hsalsa20_tweet_INPUTBYTES
#define crypto_core_hsalsa20_KEYBYTES crypto_core_hsalsa20_tweet_KEYBYTES
#define crypto_core_hsalsa20_CONSTBYTES crypto_core_hsalsa20_tweet_CONSTBYTES
#define crypto_core_hsalsa20_VERSION crypto_core_hsalsa20_tweet_VERSION
#define crypto_core_hsalsa20_IMPLEMENTATION "crypto_core/hsalsa20/tweet"
#define crypto_hashblocks_PRIMITIVE "sha512"
#define crypto_hashblocks crypto_hashblocks_sha512
#define crypto_hashblocks_STATEBYTES crypto_hashblocks_sha512_STATEBYTES
#define crypto_hashblocks_BLOCKBYTES crypto_hashblocks_sha512_BLOCKBYTES
#define crypto_hashblocks_IMPLEMENTATION crypto_hashblocks_sha512_IMPLEMENTATION
#define crypto_hashblocks_VERSION crypto_hashblocks_sha512_VERSION
#define crypto_hashblocks_sha512_tweet_STATEBYTES 64
#define crypto_hashblocks_sha512_tweet_BLOCKBYTES 128
extern int crypto_hashblocks_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long);
#define crypto_hashblocks_sha512_tweet_VERSION "-"
#define crypto_hashblocks_sha512 crypto_hashblocks_sha512_tweet
#define crypto_hashblocks_sha512_STATEBYTES crypto_hashblocks_sha512_tweet_STATEBYTES
#define crypto_hashblocks_sha512_BLOCKBYTES crypto_hashblocks_sha512_tweet_BLOCKBYTES
#define crypto_hashblocks_sha512_VERSION crypto_hashblocks_sha512_tweet_VERSION
#define crypto_hashblocks_sha512_IMPLEMENTATION "crypto_hashblocks/sha512/tweet"
#define crypto_hashblocks_sha256_tweet_STATEBYTES 32
#define crypto_hashblocks_sha256_tweet_BLOCKBYTES 64
extern int crypto_hashblocks_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long);
#define crypto_hashblocks_sha256_tweet_VERSION "-"
#define crypto_hashblocks_sha256 crypto_hashblocks_sha256_tweet
#define crypto_hashblocks_sha256_STATEBYTES crypto_hashblocks_sha256_tweet_STATEBYTES
#define crypto_hashblocks_sha256_BLOCKBYTES crypto_hashblocks_sha256_tweet_BLOCKBYTES
#define crypto_hashblocks_sha256_VERSION crypto_hashblocks_sha256_tweet_VERSION
#define crypto_hashblocks_sha256_IMPLEMENTATION "crypto_hashblocks/sha256/tweet"
#define crypto_hash_PRIMITIVE "sha512"
#define crypto_hash crypto_hash_sha512
#define crypto_hash_BYTES crypto_hash_sha512_BYTES
#define crypto_hash_IMPLEMENTATION crypto_hash_sha512_IMPLEMENTATION
#define crypto_hash_VERSION crypto_hash_sha512_VERSION
#define crypto_hash_sha512_tweet_BYTES 64
extern int crypto_hash_sha512_tweet(unsigned char *,const unsigned char *,unsigned long long);
#define crypto_hash_sha512_tweet_VERSION "-"
#define crypto_hash_sha512 crypto_hash_sha512_tweet
#define crypto_hash_sha512_BYTES crypto_hash_sha512_tweet_BYTES
#define crypto_hash_sha512_VERSION crypto_hash_sha512_tweet_VERSION
#define crypto_hash_sha512_IMPLEMENTATION "crypto_hash/sha512/tweet"
#define crypto_hash_sha256_tweet_BYTES 32
extern int crypto_hash_sha256_tweet(unsigned char *,const unsigned char *,unsigned long long);
#define crypto_hash_sha256_tweet_VERSION "-"
#define crypto_hash_sha256 crypto_hash_sha256_tweet
#define crypto_hash_sha256_BYTES crypto_hash_sha256_tweet_BYTES
#define crypto_hash_sha256_VERSION crypto_hash_sha256_tweet_VERSION
#define crypto_hash_sha256_IMPLEMENTATION "crypto_hash/sha256/tweet"
#define crypto_onetimeauth_PRIMITIVE "poly1305"
#define crypto_onetimeauth crypto_onetimeauth_poly1305
#define crypto_onetimeauth_verify crypto_onetimeauth_poly1305_verify
#define crypto_onetimeauth_BYTES crypto_onetimeauth_poly1305_BYTES
#define crypto_onetimeauth_KEYBYTES crypto_onetimeauth_poly1305_KEYBYTES
#define crypto_onetimeauth_IMPLEMENTATION crypto_onetimeauth_poly1305_IMPLEMENTATION
#define crypto_onetimeauth_VERSION crypto_onetimeauth_poly1305_VERSION
#define crypto_onetimeauth_poly1305_tweet_BYTES 16
#define crypto_onetimeauth_poly1305_tweet_KEYBYTES 32
extern int crypto_onetimeauth_poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
extern int crypto_onetimeauth_poly1305_tweet_verify(const unsigned char *,const unsigned char *,unsigned long long,const unsigned char *);
#define crypto_onetimeauth_poly1305_tweet_VERSION "-"
#define crypto_onetimeauth_poly1305 crypto_onetimeauth_poly1305_tweet
#define crypto_onetimeauth_poly1305_verify crypto_onetimeauth_poly1305_tweet_verify
#define crypto_onetimeauth_poly1305_BYTES crypto_onetimeauth_poly1305_tweet_BYTES
#define crypto_onetimeauth_poly1305_KEYBYTES crypto_onetimeauth_poly1305_tweet_KEYBYTES
#define crypto_onetimeauth_poly1305_VERSION crypto_onetimeauth_poly1305_tweet_VERSION
#define crypto_onetimeauth_poly1305_IMPLEMENTATION "crypto_onetimeauth/poly1305/tweet"
#define crypto_scalarmult_PRIMITIVE "curve25519"
#define crypto_scalarmult crypto_scalarmult_curve25519
#define crypto_scalarmult_base crypto_scalarmult_curve25519_base
#define crypto_scalarmult_BYTES crypto_scalarmult_curve25519_BYTES
#define crypto_scalarmult_SCALARBYTES crypto_scalarmult_curve25519_SCALARBYTES
#define crypto_scalarmult_IMPLEMENTATION crypto_scalarmult_curve25519_IMPLEMENTATION
#define crypto_scalarmult_VERSION crypto_scalarmult_curve25519_VERSION
#define crypto_scalarmult_curve25519_tweet_BYTES 32
#define crypto_scalarmult_curve25519_tweet_SCALARBYTES 32
extern int crypto_scalarmult_curve25519_tweet(unsigned char *,const unsigned char *,const unsigned char *);
extern int crypto_scalarmult_curve25519_tweet_base(unsigned char *,const unsigned char *);
#define crypto_scalarmult_curve25519_tweet_VERSION "-"
#define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tweet
#define crypto_scalarmult_curve25519_base crypto_scalarmult_curve25519_tweet_base
#define crypto_scalarmult_curve25519_BYTES crypto_scalarmult_curve25519_tweet_BYTES
#define crypto_scalarmult_curve25519_SCALARBYTES crypto_scalarmult_curve25519_tweet_SCALARBYTES
#define crypto_scalarmult_curve25519_VERSION crypto_scalarmult_curve25519_tweet_VERSION
#define crypto_scalarmult_curve25519_IMPLEMENTATION "crypto_scalarmult/curve25519/tweet"
#define crypto_secretbox_PRIMITIVE "xsalsa20poly1305"
#define crypto_secretbox crypto_secretbox_xsalsa20poly1305
#define crypto_secretbox_open crypto_secretbox_xsalsa20poly1305_open
#define crypto_secretbox_KEYBYTES crypto_secretbox_xsalsa20poly1305_KEYBYTES
#define crypto_secretbox_NONCEBYTES crypto_secretbox_xsalsa20poly1305_NONCEBYTES
#define crypto_secretbox_ZEROBYTES crypto_secretbox_xsalsa20poly1305_ZEROBYTES
#define crypto_secretbox_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES
#define crypto_secretbox_IMPLEMENTATION crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION
#define crypto_secretbox_VERSION crypto_secretbox_xsalsa20poly1305_VERSION
#define crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES 32
#define crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES 24
#define crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES 32
#define crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES 16
extern int crypto_secretbox_xsalsa20poly1305_tweet(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
extern int crypto_secretbox_xsalsa20poly1305_tweet_open(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
#define crypto_secretbox_xsalsa20poly1305_tweet_VERSION "-"
#define crypto_secretbox_xsalsa20poly1305 crypto_secretbox_xsalsa20poly1305_tweet
#define crypto_secretbox_xsalsa20poly1305_open crypto_secretbox_xsalsa20poly1305_tweet_open
#define crypto_secretbox_xsalsa20poly1305_KEYBYTES crypto_secretbox_xsalsa20poly1305_tweet_KEYBYTES
#define crypto_secretbox_xsalsa20poly1305_NONCEBYTES crypto_secretbox_xsalsa20poly1305_tweet_NONCEBYTES
#define crypto_secretbox_xsalsa20poly1305_ZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_ZEROBYTES
#define crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES crypto_secretbox_xsalsa20poly1305_tweet_BOXZEROBYTES
#define crypto_secretbox_xsalsa20poly1305_VERSION crypto_secretbox_xsalsa20poly1305_tweet_VERSION
#define crypto_secretbox_xsalsa20poly1305_IMPLEMENTATION "crypto_secretbox/xsalsa20poly1305/tweet"
#define crypto_sign_PRIMITIVE "ed25519"
#define crypto_sign crypto_sign_ed25519
#define crypto_sign_open crypto_sign_ed25519_open
#define crypto_sign_keypair crypto_sign_ed25519_keypair
#define crypto_sign_BYTES crypto_sign_ed25519_BYTES
#define crypto_sign_PUBLICKEYBYTES crypto_sign_ed25519_PUBLICKEYBYTES
#define crypto_sign_SECRETKEYBYTES crypto_sign_ed25519_SECRETKEYBYTES
#define crypto_sign_IMPLEMENTATION crypto_sign_ed25519_IMPLEMENTATION
#define crypto_sign_VERSION crypto_sign_ed25519_VERSION
#define crypto_sign_ed25519_tweet_BYTES 64
#define crypto_sign_ed25519_tweet_PUBLICKEYBYTES 32
#define crypto_sign_ed25519_tweet_SECRETKEYBYTES 64
extern int crypto_sign_ed25519_tweet(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
extern int crypto_sign_ed25519_tweet_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
extern int crypto_sign_ed25519_tweet_keypair(unsigned char *,unsigned char *);
#define crypto_sign_ed25519_tweet_VERSION "-"
#define crypto_sign_ed25519 crypto_sign_ed25519_tweet
#define crypto_sign_ed25519_open crypto_sign_ed25519_tweet_open
#define crypto_sign_ed25519_keypair crypto_sign_ed25519_tweet_keypair
#define crypto_sign_ed25519_BYTES crypto_sign_ed25519_tweet_BYTES
#define crypto_sign_ed25519_PUBLICKEYBYTES crypto_sign_ed25519_tweet_PUBLICKEYBYTES
#define crypto_sign_ed25519_SECRETKEYBYTES crypto_sign_ed25519_tweet_SECRETKEYBYTES
#define crypto_sign_ed25519_VERSION crypto_sign_ed25519_tweet_VERSION
#define crypto_sign_ed25519_IMPLEMENTATION "crypto_sign/ed25519/tweet"
#define crypto_stream_PRIMITIVE "xsalsa20"
#define crypto_stream crypto_stream_xsalsa20
#define crypto_stream_xor crypto_stream_xsalsa20_xor
#define crypto_stream_KEYBYTES crypto_stream_xsalsa20_KEYBYTES
#define crypto_stream_NONCEBYTES crypto_stream_xsalsa20_NONCEBYTES
#define crypto_stream_IMPLEMENTATION crypto_stream_xsalsa20_IMPLEMENTATION
#define crypto_stream_VERSION crypto_stream_xsalsa20_VERSION
#define crypto_stream_xsalsa20_tweet_KEYBYTES 32
#define crypto_stream_xsalsa20_tweet_NONCEBYTES 24
extern int crypto_stream_xsalsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
extern int crypto_stream_xsalsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
#define crypto_stream_xsalsa20_tweet_VERSION "-"
#define crypto_stream_xsalsa20 crypto_stream_xsalsa20_tweet
#define crypto_stream_xsalsa20_xor crypto_stream_xsalsa20_tweet_xor
#define crypto_stream_xsalsa20_KEYBYTES crypto_stream_xsalsa20_tweet_KEYBYTES
#define crypto_stream_xsalsa20_NONCEBYTES crypto_stream_xsalsa20_tweet_NONCEBYTES
#define crypto_stream_xsalsa20_VERSION crypto_stream_xsalsa20_tweet_VERSION
#define crypto_stream_xsalsa20_IMPLEMENTATION "crypto_stream/xsalsa20/tweet"
#define crypto_stream_salsa20_tweet_KEYBYTES 32
#define crypto_stream_salsa20_tweet_NONCEBYTES 8
extern int crypto_stream_salsa20_tweet(unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
extern int crypto_stream_salsa20_tweet_xor(unsigned char *,const unsigned char *,unsigned long long,const unsigned char *,const unsigned char *);
#define crypto_stream_salsa20_tweet_VERSION "-"
#define crypto_stream_salsa20 crypto_stream_salsa20_tweet
#define crypto_stream_salsa20_xor crypto_stream_salsa20_tweet_xor
#define crypto_stream_salsa20_KEYBYTES crypto_stream_salsa20_tweet_KEYBYTES
#define crypto_stream_salsa20_NONCEBYTES crypto_stream_salsa20_tweet_NONCEBYTES
#define crypto_stream_salsa20_VERSION crypto_stream_salsa20_tweet_VERSION
#define crypto_stream_salsa20_IMPLEMENTATION "crypto_stream/salsa20/tweet"
#define crypto_verify_PRIMITIVE "16"
#define crypto_verify crypto_verify_16
#define crypto_verify_BYTES crypto_verify_16_BYTES
#define crypto_verify_IMPLEMENTATION crypto_verify_16_IMPLEMENTATION
#define crypto_verify_VERSION crypto_verify_16_VERSION
#define crypto_verify_16_tweet_BYTES 16
extern int crypto_verify_16_tweet(const unsigned char *,const unsigned char *);
#define crypto_verify_16_tweet_VERSION "-"
#define crypto_verify_16 crypto_verify_16_tweet
#define crypto_verify_16_BYTES crypto_verify_16_tweet_BYTES
#define crypto_verify_16_VERSION crypto_verify_16_tweet_VERSION
#define crypto_verify_16_IMPLEMENTATION "crypto_verify/16/tweet"
#define crypto_verify_32_tweet_BYTES 32
extern int crypto_verify_32_tweet(const unsigned char *,const unsigned char *);
#define crypto_verify_32_tweet_VERSION "-"
#define crypto_verify_32 crypto_verify_32_tweet
#define crypto_verify_32_BYTES crypto_verify_32_tweet_BYTES
#define crypto_verify_32_VERSION crypto_verify_32_tweet_VERSION
#define crypto_verify_32_IMPLEMENTATION "crypto_verify/32/tweet"
#endif

Просмотреть файл

@ -82,6 +82,7 @@ if("sgx" IN_LIST TARGET)
http_parser.enclave
lua.enclave
secp256k1.enclave
sss.enclave
)
set_property(TARGET ccf.enclave PROPERTY POSITION_INDEPENDENT_CODE ON)
@ -138,6 +139,7 @@ if("virtual" IN_LIST TARGET)
http_parser.host
lua.host
secp256k1.host
sss.host
${CMAKE_THREAD_LIBS_INIT}
)

Просмотреть файл

@ -137,6 +137,15 @@
}
}
},
{
"component": {
"type": "git",
"git": {
"repositoryUrl": "https://github.com/dsprenkels/sss",
"commitHash": "dc8c3a9a1089e962b32ecdcc940ae11bd2b69e4b"
}
}
},
],
"Version": 1
}

Просмотреть файл

@ -242,6 +242,7 @@ endfunction()
include(${CCF_DIR}/cmake/crypto.cmake)
include(${CCF_DIR}/cmake/secp256k1.cmake)
include(${CCF_DIR}/cmake/quickjs.cmake)
include(${CCF_DIR}/cmake/sss.cmake)
find_package(CURL REQUIRED)

30
cmake/sss.cmake Normal file
Просмотреть файл

@ -0,0 +1,30 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
set(SSS_PREFIX
${CCF_DIR}/3rdparty/sss
CACHE PATH "Prefix to the Shamir Secret Sharing (sss) library"
)
message(STATUS "Using sss at ${SSS_PREFIX}")
set(SSS_SRC ${SSS_PREFIX}/sss.c ${SSS_PREFIX}/hazmat.c
${SSS_PREFIX}/tweetnacl.c
)
if("sgx" IN_LIST TARGET)
add_library(sss.enclave STATIC ${SSS_SRC})
set_property(TARGET sss.enclave PROPERTY POSITION_INDEPENDENT_CODE ON)
install(
TARGETS sss.enclave
EXPORT ccf
DESTINATION lib
)
endif()
add_library(sss.host STATIC ${SSS_SRC})
set_property(TARGET sss.host PROPERTY POSITION_INDEPENDENT_CODE ON)
install(
TARGETS sss.host
EXPORT ccf
DESTINATION lib
)

Просмотреть файл

@ -35,6 +35,13 @@
#include <chrono>
#include <fmt/format_header_only.h>
#include <nlohmann/json.hpp>
extern "C"
{
#include "tls/randombytes.h"
#include <sss/sss.h>
}
#include <stdexcept>
#include <unordered_set>
#include <vector>

Просмотреть файл

@ -48,6 +48,12 @@ namespace tls
return data;
}
void random(unsigned char* data, size_t len) override
{
if (mbedtls_ctr_drbg_random(&drbg, data, len) != 0)
throw std::logic_error("Couldn't create random data");
}
static int rng(void* ctx, unsigned char* output, size_t len)
{
return mbedtls_ctr_drbg_random(ctx, output, len);

Просмотреть файл

@ -33,6 +33,7 @@ namespace tls
virtual void* get_data() = 0;
virtual rng_func_t get_rng() = 0;
virtual std::vector<uint8_t> random(size_t len) = 0;
virtual void random(unsigned char* data, size_t len) = 0;
virtual ~Entropy() {}
};
@ -274,6 +275,12 @@ namespace tls
return std::vector<uint8_t>(buf, buf + len);
}
void random(unsigned char* data, size_t len) override
{
if (rdrand_get_bytes(len, data) < len)
throw std::logic_error("Couldn't create random data");
}
static int rng(void*, unsigned char* output, size_t len)
{
if (rdrand_get_bytes(len, output) < len)

14
src/tls/randombytes.h Normal file
Просмотреть файл

@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the Apache 2.0 License.
#pragma once
#include "entropy.h"
#include <stddef.h>
void randombytes(void* buf, size_t n)
{
auto entropy = tls::create_entropy();
entropy->random((unsigned char*)buf, n);
}