A clean version

This commit is contained in:
Zhi Guan
2019-06-13 21:35:40 +08:00
parent 74d7992dda
commit 3be27d5d2e
45 changed files with 5164 additions and 7645 deletions

View File

@@ -1,209 +0,0 @@
/* ====================================================================
* Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
/*
* Copyright 2012-2014 Luke Dashjr
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the standard MIT license. See COPYING for more details.
*/
#include <string.h>
#include <sys/types.h>
#include <openssl/err.h>
#include <openssl/e_os2.h>
#include <openssl/base58.h>
static const int8_t b58digits_map[] = {
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
-1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1,
22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1,
-1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46,
47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,
};
int base58_decode(const char *b58, size_t b58sz, void *bin, size_t *binszp)
{
size_t binsz = *binszp;
const unsigned char *b58u = (void*)b58;
unsigned char *binu = bin;
size_t outisz = (binsz + 3) / 4;
//uint32_t outi[outisz];
uint32_t *outi = NULL;
uint64_t t;
uint32_t c;
size_t i, j;
uint8_t bytesleft = binsz % 4;
uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
unsigned zerocount = 0;
if (!b58sz)
b58sz = strlen(b58);
if (!(outi = OPENSSL_malloc(outisz))) {
return 0;
}
memset(outi, 0, outisz * sizeof(*outi));
// Leading zeros, just count
for (i = 0; i < b58sz && b58u[i] == '1'; ++i)
++zerocount;
for ( ; i < b58sz; ++i)
{
if (b58u[i] & 0x80) {
// High-bit set on invalid digit
BASE58err(BASE58_F_BASE58_DECODE, BASE58_R_HIGHBIT_SET_ON_INVALID_DIGIT);
return 0;
}
if (b58digits_map[b58u[i]] == -1)
// Invalid base58 digit
return 0;
c = (unsigned)b58digits_map[b58u[i]];
for (j = outisz; j--; )
{
t = ((uint64_t)outi[j]) * 58 + c;
c = (t & 0x3f00000000) >> 32;
outi[j] = t & 0xffffffff;
}
if (c)
// Output number too big (carry to the next int32)
return 0;
if (outi[0] & zeromask)
// Output number too big (last int32 filled too far)
return 0;
}
j = 0;
switch (bytesleft) {
case 3:
*(binu++) = (outi[0] & 0xff0000) >> 16;
case 2:
*(binu++) = (outi[0] & 0xff00) >> 8;
case 1:
*(binu++) = (outi[0] & 0xff);
++j;
default:
break;
}
for (; j < outisz; ++j)
{
*(binu++) = (outi[j] >> 0x18) & 0xff;
*(binu++) = (outi[j] >> 0x10) & 0xff;
*(binu++) = (outi[j] >> 8) & 0xff;
*(binu++) = (outi[j] >> 0) & 0xff;
}
// Count canonical base58 byte count
binu = bin;
for (i = 0; i < binsz; ++i)
{
if (binu[i])
break;
--*binszp;
}
*binszp += zerocount;
OPENSSL_free(outi);
return 1;
}
static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
int base58_encode(const void *data, size_t binsz, char *b58, size_t *b58sz)
{
const uint8_t *bin = data;
int carry;
size_t i, j, high, zcount = 0;
size_t size;
//uint8_t buf[size];
uint8_t *buf = NULL;
while (zcount < binsz && !bin[zcount])
++zcount;
size = (binsz - zcount) * 138 / 100 + 1;
if (!(buf = OPENSSL_zalloc(size))) {
return 0;
}
for (i = zcount, high = size - 1; i < binsz; ++i, high = j)
{
for (carry = bin[i], j = size - 1; (j > high) || carry; --j)
{
carry += 256 * buf[j];
buf[j] = carry % 58;
carry /= 58;
}
}
for (j = 0; j < size && !buf[j]; ++j);
if (*b58sz <= zcount + size - j)
{
*b58sz = zcount + size - j + 1;
return 0;
}
if (zcount)
memset(b58, '1', zcount);
for (i = zcount; j < size; ++i, ++j)
b58[i] = b58digits_ordered[buf[j]];
b58[i] = '\0';
*b58sz = i + 1;
OPENSSL_free(buf);
return 1;
}

View File

@@ -1,44 +0,0 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/base58.h>
/* BEGIN ERROR CODES */
#ifndef OPENSSL_NO_ERR
# define ERR_FUNC(func) ERR_PACK(ERR_LIB_BASE58,func,0)
# define ERR_REASON(reason) ERR_PACK(ERR_LIB_BASE58,0,reason)
static ERR_STRING_DATA BASE58_str_functs[] = {
{ERR_FUNC(BASE58_F_BASE58_DECODE), "base58_decode"},
{0, NULL}
};
static ERR_STRING_DATA BASE58_str_reasons[] = {
{ERR_REASON(BASE58_R_HIGHBIT_SET_ON_INVALID_DIGIT),
"highbit set on invalid digit"},
{0, NULL}
};
#endif
int ERR_load_BASE58_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(BASE58_str_functs[0].error) == NULL) {
ERR_load_strings(0, BASE58_str_functs);
ERR_load_strings(0, BASE58_str_reasons);
}
#endif
return 1;
}

View File

@@ -1,3 +0,0 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=base58.c base58_err.c

View File

@@ -67,7 +67,6 @@ static ERR_STRING_DATA ERR_str_libraries[] = {
{ERR_PACK(ERR_LIB_SM9, 0, 0), "SM9 routines"},
{ERR_PACK(ERR_LIB_SDF, 0, 0), "SDF routines"},
{ERR_PACK(ERR_LIB_SKF, 0, 0), "SKF routines"},
{ERR_PACK(ERR_LIB_BASE58, 0, 0), "BASE58 routines"},
{0, NULL},
};
@@ -120,7 +119,6 @@ static ERR_STRING_DATA ERR_str_reasons[] = {
{ERR_R_SM9_LIB, "SM9 lib"},
{ERR_R_SDF_LIB, "SDF lib"},
{ERR_R_SKF_LIB, "SKF lib"},
{ERR_R_BASE58_LIB, "BASE58 lib"},
{ERR_R_NESTED_ASN1_ERROR, "nested asn1 error"},
{ERR_R_MISSING_ASN1_EOS, "missing asn1 eos"},

View File

@@ -87,9 +87,6 @@
#ifndef OPENSSL_NO_SKF
# include <openssl/gmskf.h>
#endif
#ifndef OPENSSL_NO_BASE58
# include <openssl/base58.h>
#endif
int err_load_crypto_strings_int(void)
@@ -179,9 +176,6 @@ int err_load_crypto_strings_int(void)
# ifndef OPENSSL_NO_SKF
ERR_load_SKF_strings() == 0 ||
# endif
# ifndef OPENSSL_NO_BASE58
ERR_load_BASE58_strings() == 0 ||
# endif
#endif
ERR_load_KDF_strings() == 0)
return 0;

View File

@@ -43,7 +43,6 @@ L SM2 include/openssl/sm2.h crypto/sm2/sm2_err.c
L SM9 include/openssl/sm9.h crypto/sm9/sm9_err.c
L SDF include/openssl/gmsdf.h crypto/sdf/sdf_err.c
L SKF include/openssl/gmskf.h crypto/skf/skf_err.c
L BASE58 include/openssl/base58.h crypto/base58/base58_err.c
# additional header files to be scanned for function names
L NONE crypto/x509/x509_vfy.h NONE

View File

@@ -1,46 +0,0 @@
AccessModifierOffset: 0
AlignEscapedNewlinesLeft: false
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortFunctionsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackParameters: false
BreakBeforeBinaryOperators: false
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 80
CommentPragmas: ''
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 0
ContinuationIndentWidth: 0
Cpp11BracedListStyle: false
DerivePointerBinding: false
IndentCaseLabels: false
IndentFunctionDeclarationAfterType: false
IndentWidth: 4
Language: Cpp
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 100
PenaltyBreakComment: 100
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 100
PenaltyExcessCharacter: 1
PenaltyReturnTypeOnItsOwnLine: 20
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: Always
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
Standard: Cpp11
TabWidth: 4
UseTab: Never

View File

@@ -1,3 +0,0 @@
bench
*.o
*.dSYM

View File

@@ -1,13 +0,0 @@
Copyright 2017 Nagravision S.A.
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.

View File

@@ -1,52 +0,0 @@
SRC=$(wildcard *.c) $(wildcard primitives/*.c)
OBJ=$(patsubst %.c, %.o, $(SRC))
CFLAGS_COMMON=-std=c89 -pedantic -Wall -Wextra -Wno-long-long -march=native
LDFLAGS=-lcrypto
VERSION_S= -DPORS_k=24 -DMERKLE_h=5 -DGRAVITY_d=1 -DGRAVITY_c=10
VERSION_M= -DPORS_k=32 -DMERKLE_h=5 -DGRAVITY_d=7 -DGRAVITY_c=15
VERSION_L= -DPORS_k=28 -DMERKLE_h=5 -DGRAVITY_d=10 -DGRAVITY_c=14
VERSION=$(VERSION_S)
CFLAGS_COMMON+=$(VERSION)
CFLAGS=$(CFLAGS_COMMON) -O3 -fomit-frame-pointer
CFLAGS_SANITIZED=$(CFLAGS_COMMON) -fsanitize=address,undefined -g
KERNEL_NAME := $(shell uname -s)
ifeq ($(KERNEL_NAME), Darwin)
CFLAGS += -I/usr/local/opt/openssl/include
LDFLAGS += -L/usr/local/opt/openssl/lib
endif
all: help
help:
@echo "Please choose a target:"
@echo "\tanalyze\t\t runs static analyzers"
@echo "\tbench\t\t runs speed benchmarks"
@echo "\tclean\t\t cleans up"
@echo "\tformat\t\t formats the code using .clang-format rules"
bench: $(SRC)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o bench
./bench
format:
clang-format -i *.c *.h
analyze:
cppcheck . --std=c89
scan-build gcc -c $(CFLAGS_SANITIZED) *.c
cppclean .
rm -f *.o
cloc:
cloc $(wildcard *.c) $(wildcard *.h)
clean:
rm -f bench *.dSYM *.o
.PHONY: clean format analyze cloc bench

View File

@@ -1,10 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#pragma once
#include <stdint.h>
int aesctr256 (uint8_t *out, const uint8_t *sk, const void *counter, int bytes);
int aesctr256_zeroiv (uint8_t *out, const uint8_t *sk, int bytes);

View File

@@ -1,41 +0,0 @@
#pragma once
#ifndef CRYPTO_BYTES
/* setting CRYPTO_BYTES to the static structure size, for simplicity,
as opposed to the actual message-dependent signature size */
#define CRYPTO_ALGNAME "Gravity-SPHINCS S"
#define CRYPTO_SECRETKEYBYTES 65568
#define CRYPTO_PUBLICKEYBYTES 32
#define CRYPTO_BYTES 15728 // 12640
#if 0
#define CRYPTO_ALGNAME "Gravity-SPHINCS M"
#define CRYPTO_SECRETKEYBYTES 2097184
#define CRYPTO_PUBLICKEYBYTES 32
#define CRYPTO_BYTES 34064 // 28929
#endif
#if 0
#define CRYPTO_ALGNAME "Gravity-SPHINCS L"
#define CRYPTO_SECRETKEYBYTES 1048608
#define CRYPTO_PUBLICKEYBYTES 32
#define CRYPTO_BYTES 38768 // 35168
#endif
#endif
int crypto_sign_keypair (unsigned char *pk, unsigned char *sk);
int crypto_sign (unsigned char *sm,
unsigned long long *smlen,
const unsigned char *m,
unsigned long long mlen,
const unsigned char *sk);
int crypto_sign_open (unsigned char *m,
unsigned long long *mlen,
const unsigned char *sm,
unsigned long long smlen,
const unsigned char *pk);

View File

@@ -1,93 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#include "batch.h"
#include "merkle.h"
int batch_init (struct batch_buf *buf) {
buf->count = 0;
return GRAVITY_OK;
}
int batch_append (struct batch_buf *buf, const uint8_t *msg, uint64_t len, uint32_t *index) {
if (buf->count == MAX_BATCH_COUNT) return GRAVITY_ERR_BATCH;
/* TODO: randomize this hash? */
hash_to_N (&buf->buf[buf->count], msg, len);
*index = buf->count;
++buf->count;
return GRAVITY_OK;
}
int batch_group (struct batch_group *group, struct batch_buf *buf) {
int height = LOG_MAX_BATCH_COUNT;
int n = 1 << height;
int offset = n - 1;
struct hash *src;
struct hash *dst;
uint32_t count;
int i;
/* Check batch count */
count = buf->count;
if (count == 0) return GRAVITY_ERR_BATCH;
group->count = count;
/* Leaves */
dst = &group->tree[offset];
hashcpyN (dst, buf->buf, count);
for (i = count; i < n; ++i) hashcpy (&dst[i], &buf->buf[0]);
/* Compress until root */
while (height > 0) {
offset >>= 1;
--height;
src = dst;
dst = &group->tree[offset];
hash_compress_pairs (dst, src, 1 << height);
}
return GRAVITY_OK;
}
int batch_extract (const struct batch_group *group, struct batch_auth *auth, uint32_t index) {
int height = LOG_MAX_BATCH_COUNT;
int n = 1 << height;
int offset = n - 1;
uint32_t count;
int i, sibling;
/* Check batch count */
count = group->count;
if (index >= count) return GRAVITY_ERR_BATCH;
/* Convert row index into tree index */
auth->index = offset + index;
/* Copy auth path */
for (i = 0; i < height; ++i) {
sibling = index ^ 1;
hashcpy (&auth->auth[i], &group->tree[offset + sibling]);
index >>= 1;
offset >>= 1;
}
return GRAVITY_OK;
}
void batch_compress_auth (struct hash *node,
const struct batch_auth *auth,
const uint8_t *msg,
uint64_t len) {
/* Compute Merkle tree root */
int height = LOG_MAX_BATCH_COUNT;
hash_to_N (node, msg, len);
merkle_compress_auth (node, auth->index, auth->auth, height);
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#pragma once
#include "hash.h"
struct batch_buf {
struct hash buf[MAX_BATCH_COUNT];
uint32_t count;
};
struct batch_group {
struct hash tree[2 * MAX_BATCH_COUNT - 1];
uint32_t count;
};
struct batch_auth {
struct hash auth[LOG_MAX_BATCH_COUNT];
uint32_t index;
};
int batch_init (struct batch_buf *buf);
int batch_append (struct batch_buf *buf, const uint8_t *msg, uint64_t len, uint32_t *index);
int batch_group (struct batch_group *group, struct batch_buf *buf);
int batch_extract (const struct batch_group *group, struct batch_auth *auth, uint32_t index);
void batch_compress_auth (struct hash *node,
const struct batch_auth *auth,
const uint8_t *msg,
uint64_t len);

View File

@@ -1,97 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#include "gravity.h"
#include "randombytes.h"
#include "sign.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#define SKLEN sizeof (struct gravity_sk)
#define PKLEN sizeof (struct gravity_pk)
#define SIGLEN sizeof (struct gravity_sign)
#define N 32
#define ROUNDS 3
int main () {
unsigned long long smlen;
unsigned long long mlen = N;
uint8_t sk[SKLEN];
uint8_t pk[PKLEN];
uint8_t m[N];
uint8_t *sm = malloc (N + SIGLEN);
struct timeval tm1, tm2;
unsigned long long usecs;
int ret = -1;
int i;
if (!sm) {
fprintf (stderr, "error: sm malloc failed\n");
ret = 1;
goto label_exit_0;
}
printf ("k\t%d\n", PORS_k);
printf ("h\t%d\n", MERKLE_h);
printf ("d\t%d\n", GRAVITY_d);
printf ("c\t%d\n", GRAVITY_c);
printf ("sk len\t%d\n", (int)SKLEN);
printf ("pk len\t%d\n", (int)PKLEN);
printf ("sig len\t%d\n", (int)SIGLEN);
#define MEASURE(s) \
do { \
gettimeofday (&tm2, NULL); \
usecs = 1000000 * (tm2.tv_sec - tm1.tv_sec) + (tm2.tv_usec - tm1.tv_usec); \
printf ("\n# %s\n", s); \
printf ("%.2f usec\n", (double)usecs); \
} while (0)
randombytes (m, N);
gettimeofday (&tm1, NULL);
if (crypto_sign_keypair (pk, sk)) {
fprintf (stderr, "error: crypto_sign_keypair failed\n");
ret = 1;
goto label_exit_2;
}
MEASURE ("crypto_sign_keypair");
for (i = 0; i < ROUNDS; ++i) {
gettimeofday (&tm1, NULL);
if (crypto_sign (sm, &smlen, m, mlen, sk)) {
fprintf (stderr, "error: crypto_sign failed\n");
ret = 1;
goto label_exit_2;
}
MEASURE ("crypto_sign");
gettimeofday (&tm1, NULL);
if (crypto_sign_open (m, &mlen, sm, smlen, pk)) {
fprintf (stderr, "error: crypto_sign_open failed\n");
ret = 1;
goto label_exit_2;
}
m[0] ^= sm[33];
MEASURE ("crypto_sign_open");
}
ret = 0;
label_exit_2:
free (sm);
label_exit_0:
return ret;
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#pragma once
#define HASH_SIZE 32
#define WOTS_LOG_ell1 6
#define WOTS_ell1 (1 << (WOTS_LOG_ell1))
#define WOTS_chksum 3
#define WOTS_ell ((WOTS_ell1) + (WOTS_chksum))
#define WOTS_w 16
/* set by compile flags */
#if 0
#define PORS_k 28
#define MERKLE_h 5
#define GRAVITY_d 10
#define GRAVITY_c 14
#endif
#define PORS_tau 16
#define PORS_t (1 << (PORS_tau))
#define MERKLE_hhh (1 << (MERKLE_h))
#define GRAVITY_ccc (1 << (GRAVITY_c))
#define GRAVITY_h ((MERKLE_h) * (GRAVITY_d) + (GRAVITY_c))
#if GRAVITY_h < 64
#define GRAVITY_mask ~(0xFFFFFFFFFFFFFFFFull << (GRAVITY_h))
#else
#define GRAVITY_mask 0xFFFFFFFFFFFFFFFFull
#endif
#define LOG_MAX_BATCH_COUNT 10
#define MAX_BATCH_COUNT (1 << (LOG_MAX_BATCH_COUNT))
#define GRAVITY_OK 0
#define GRAVITY_ERR_VERIF 1
#define GRAVITY_ERR_ALLOC 2
#define GRAVITY_ERR_BATCH 3
#define U8TO32(p) \
(((uint32_t) ((p)[0]) << 24) | ((uint32_t) ((p)[1]) << 16) | \
((uint32_t) ((p)[2]) << 8) | ((uint32_t) ((p)[3])))

View File

@@ -1,196 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#include "gravity.h"
#include <stdio.h>
#include <stdlib.h>
int gravity_gensk (struct gravity_sk *sk) {
int n = GRAVITY_ccc;
struct hash *src;
struct hash *dst = sk->cache;
struct merkle_pk mpk;
struct address address;
int i;
int res;
/* Create sub Merkle trees */
address.layer = 0;
for (i = 0; i < n; ++i) {
address.index = i * MERKLE_hhh;
res = merkle_genpk (&sk->seed, &address, &mpk);
if (res != GRAVITY_OK) return res;
hashcpy (&dst[i], &mpk.k);
}
/* Cache layers of Merkle tree */
for (i = 0; i < GRAVITY_c; ++i) {
src = dst;
dst += n;
n >>= 1;
hash_compress_pairs (dst, src, n);
}
return GRAVITY_OK;
}
int gravity_genpk (const struct gravity_sk *sk, struct gravity_pk *pk) {
hashcpy (&pk->k, &sk->cache[2 * GRAVITY_ccc - 2]);
return GRAVITY_OK;
}
int gravity_sign (const struct gravity_sk *sk, struct gravity_sign *sign, const struct hash *msg) {
struct hash buf[2];
struct address address;
struct pors_subset subset;
struct pors_sk *psk;
struct porst_pk ppk;
struct merkle_pk mpk;
struct hash h;
int layer;
int res;
#if GRAVITY_c > 0
int offset;
int n = GRAVITY_ccc;
int i, sibling;
#endif
/* Generate "randomness" from message and secret salt */
hashcpy (&buf[0], &sk->salt);
hashcpy (&buf[1], msg);
hash_2N_to_N (&sign->rand, buf);
/* Generate address and PORST indices */
pors_randsubset (&sign->rand, msg, &address.index, &subset);
/* PORST */
psk = malloc (sizeof (struct pors_sk));
if (psk == NULL) return GRAVITY_ERR_ALLOC;
address.layer = GRAVITY_d;
pors_gensk (&sk->seed, &address, psk);
res = octoporst_sign (psk, &sign->op_sign, &ppk, &subset);
/* TODO: wipe key */
free (psk);
if (res != GRAVITY_OK) return res;
/* Store PORST pubkey into h */
hashcpy (&h, &ppk.k);
/* Hyper tree */
for (layer = 0; layer < GRAVITY_d; ++layer) {
/* Sign h with Merkle tree and obtain public key */
--address.layer;
res = merkle_sign (&sk->seed, &address, &sign->merkle[layer], &h, &mpk);
if (res != GRAVITY_OK) return res;
hashcpy (&h, &mpk.k);
/* Reduce address for next layer */
address.index >>= MERKLE_h;
}
#if GRAVITY_c > 0
/* Cached Merkle tree */
offset = 0;
for (i = 0; i < GRAVITY_c; ++i) {
sibling = address.index ^ 1;
hashcpy (&sign->auth[i], &sk->cache[offset + sibling]);
address.index >>= 1;
offset += n;
n >>= 1;
}
#endif
return GRAVITY_OK;
}
int gravity_verify (const struct gravity_pk *pk,
const struct gravity_sign *sign,
const struct hash *msg) {
struct address address;
struct pors_subset subset;
struct porst_pk ppk;
struct merkle_pk mpk;
struct hash h;
int layer;
int res;
/* Generate address and PORST indices */
pors_randsubset (&sign->rand, msg, &address.index, &subset);
/* PORST */
res = octoporst_extract (&ppk, &sign->op_sign, &subset);
if (res != GRAVITY_OK) return res;
/* Store PORST pubkey into h */
hashcpy (&h, &ppk.k);
/* Hyper tree */
address.layer = GRAVITY_d;
for (layer = 0; layer < GRAVITY_d; ++layer) {
/* Obtain Merkle tree root */
--address.layer;
merkle_extract (&mpk, &address, &sign->merkle[layer], &h);
hashcpy (&h, &mpk.k);
/* Reduce address for next layer */
address.index >>= MERKLE_h;
}
#if GRAVITY_c > 0
/* Cached Merkle tree */
merkle_compress_auth (&h, address.index, sign->auth, GRAVITY_c);
#endif
if (hashcmp (&h, &pk->k)) return GRAVITY_ERR_VERIF;
return GRAVITY_OK;
}
int gravity_loadsign (struct gravity_sign *sign, const uint8_t *_sign, size_t _len) {
size_t baselen = HASH_SIZE + GRAVITY_d * sizeof (struct merkle_sign)
#if GRAVITY_c > 0
+ GRAVITY_c * HASH_SIZE
#endif
;
if (_len < baselen) return GRAVITY_ERR_VERIF;
_len -= baselen;
memcpy (&sign->rand, _sign, HASH_SIZE);
_sign += HASH_SIZE;
if (octoporst_loadsign (&sign->op_sign, _sign, _len) != GRAVITY_OK)
return GRAVITY_ERR_VERIF;
_sign += _len;
memcpy (sign->merkle, _sign, GRAVITY_d * sizeof (struct merkle_sign));
#if GRAVITY_c > 0
_sign += GRAVITY_d * sizeof (struct merkle_sign);
memcpy (sign->auth, _sign, GRAVITY_c * HASH_SIZE);
#endif
return GRAVITY_OK;
}
int gravity_signcmp (const struct gravity_sign *sign1, const struct gravity_sign *sign2) {
if (hashcmp (&sign1->rand, &sign2->rand)) return 1;
if (octoporst_signcmp (&sign1->op_sign, &sign2->op_sign)) return 1;
if (memcmp (&sign1->merkle, &sign2->merkle, GRAVITY_d * sizeof (struct merkle_sign)))
return 1;
#if GRAVITY_c > 0
if (hashcmpN (sign1->auth, sign2->auth, GRAVITY_c)) return 1;
#endif
return 0;
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#pragma once
#include "merkle.h"
#include "pors.h"
struct gravity_sk {
struct hash seed;
struct hash salt;
struct hash cache[2 * GRAVITY_ccc - 1];
};
struct gravity_pk {
struct hash k;
};
struct gravity_sign {
struct hash rand;
struct octoporst_sign op_sign;
struct merkle_sign merkle[GRAVITY_d];
#if GRAVITY_c > 0
struct hash auth[GRAVITY_c];
#endif
};
int gravity_gensk (struct gravity_sk *sk);
int gravity_genpk (const struct gravity_sk *sk, struct gravity_pk *pk);
int gravity_sign (const struct gravity_sk *sk, struct gravity_sign *sign, const struct hash *msg);
int gravity_verify (const struct gravity_pk *pk,
const struct gravity_sign *sign,
const struct hash *msg);
/* Serialization */
int gravity_loadsign (struct gravity_sign *sign, const uint8_t *_sign, size_t _len);
int gravity_signcmp (const struct gravity_sign *sign1, const struct gravity_sign *sign2);

View File

@@ -1,53 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#pragma once
#include "common.h"
#include <stdint.h>
#include <string.h>
/* TODO: portable alignment */
struct hash {
uint8_t h[HASH_SIZE];
} __attribute__ ((aligned (16)));
struct address {
uint64_t index;
uint32_t layer;
};
void hash_N_to_N (struct hash *dst, const struct hash *src);
void hash_N_to_N_chain (struct hash *dst, const struct hash *src, int chainlen);
void hash_2N_to_N (struct hash *dst, const struct hash *src);
void hash_to_N (struct hash *dst, const uint8_t *src, uint64_t srclen);
/* Compress 2*count input hashes into count output hashes, pairwise */
void hash_compress_pairs (struct hash *dst, const struct hash *src, int count);
/* Compress count hashes into a single hash */
void hash_compress_all (struct hash *dst, const struct hash *src, int count);
/* Compute count hashes in parallel */
void hash_parallel (struct hash *dst, const struct hash *src, int count);
/* Compute count hash chains of length chainlen in parallel */
void hash_parallel_chains (struct hash *dst, const struct hash *src, int count, int chainlen);
/* int hashcmp(const struct hash *a, const struct hash *b); */
#define hashcmp(a, b) memcmp ((a)->h, (b)->h, HASH_SIZE)
/* int hashcmpN(const struct hash *a, const struct hash *b, size_t count); */
#define hashcmpN(a, b, N) memcmp ((a)->h, (b)->h, (N)*HASH_SIZE)
/* void hashcpy(struct hash *dst, const struct hash *src); */
#define hashcpy(a, b) memcpy ((a)->h, (b)->h, HASH_SIZE)
/* void hashcpyN(struct hash *dst, const struct hash *src, size_t count); */
#define hashcpyN(a, b, N) memcpy ((a)->h, (b)->h, (N)*HASH_SIZE)
/* void hashzero(struct hash *dst); */
#define hashzero(a) memset ((a)->h, 0, HASH_SIZE)
/* void swap(struct hash *a, struct hash *b, struct hash *tmp); */
#define hashswap(a, b, tmp) \
do { \
(tmp) = (a); \
(a) = (b); \
(b) = (tmp); \
} while (0);

View File

@@ -1,28 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#include "ltree.h"
void ltree (struct hash *buf, int count, struct hash *root) {
struct hash *src = &buf[count];
struct hash *dst = &buf[0];
struct hash *tmp;
int newcount;
while (count > 1) {
/* Swap buffers */
hashswap (src, dst, tmp);
/* Compute all hashes at current layer */
newcount = count >> 1;
hash_compress_pairs (dst, src, newcount);
if (count & 1) {
hashcpy (&dst[newcount], &src[count - 1]);
++newcount;
}
count = newcount;
}
hashcpy (root, dst);
}

View File

@@ -1,8 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#pragma once
#include "hash.h"
void ltree (struct hash *buf, int count, struct hash *root);

View File

@@ -1,266 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#include "merkle.h"
#include <stdlib.h>
int merkle_base_address (const struct address *address, struct address *base_address) {
int index = address->index & (MERKLE_hhh - 1);
if (base_address != NULL) {
base_address->layer = address->layer;
base_address->index = address->index - index;
}
return index;
}
int merkle_genpk (const struct hash *key, const struct address *address, struct merkle_pk *pk) {
struct address base_address;
struct hash *buf;
struct wots_sk wsk;
struct lwots_pk wpk;
int j;
merkle_base_address (address, &base_address);
buf = merkle_alloc_buf (MERKLE_h);
if (buf == NULL) return GRAVITY_ERR_ALLOC;
/* Leaves */
for (j = 0; j < MERKLE_hhh; ++j) {
wots_gensk (key, &base_address, &wsk);
lwots_genpk (&wsk, &wpk);
hashcpy (&buf[j], &wpk.k);
++base_address.index;
}
/* Merkle tree */
merkle_compress_all (buf, MERKLE_h, &pk->k);
merkle_free_buf (buf);
return GRAVITY_OK;
}
int merkle_sign (const struct hash *key,
const struct address *address,
struct merkle_sign *sign,
const struct hash *msg,
struct merkle_pk *pk) {
struct address base_address;
struct hash *buf;
struct wots_sk wsk;
struct lwots_pk wpk;
int index;
int j;
index = merkle_base_address (address, &base_address);
buf = merkle_alloc_buf (MERKLE_h);
if (buf == NULL) return GRAVITY_ERR_ALLOC;
/* Leaves */
for (j = 0; j < MERKLE_hhh; ++j) {
wots_gensk (key, &base_address, &wsk);
lwots_genpk (&wsk, &wpk);
hashcpy (&buf[j], &wpk.k);
++base_address.index;
/* WOTS */
if (j == index) wots_sign (&wsk, &sign->wots, msg);
}
/* Merkle tree */
merkle_gen_auth (buf, MERKLE_h, sign->auth, index, pk == NULL ? NULL : &pk->k);
merkle_free_buf (buf);
return GRAVITY_OK;
}
void merkle_extract (struct merkle_pk *pk,
const struct address *address,
const struct merkle_sign *sign,
const struct hash *msg) {
struct lwots_pk wpk;
int index = merkle_base_address (address, NULL);
/* WOTS */
lwots_extract (&wpk, &sign->wots, msg);
/* Auth path */
merkle_compress_auth (&wpk.k, index, sign->auth, MERKLE_h);
hashcpy (&pk->k, &wpk.k);
}
/* Helper functions */
/* Alloc/free a buffer large enough to store leaves and compress them */
struct hash *merkle_alloc_buf (int height) {
int n = 1 << height;
return malloc (2 * n * HASH_SIZE);
}
void merkle_free_buf (struct hash *buf) {
/* TODO: wipe buffer? */
free (buf);
}
/* Compress leaves from level height until root */
void merkle_compress_all (struct hash *buf, int height, struct hash *root) {
int n = 1 << height;
struct hash *src = &buf[n];
struct hash *dst = &buf[0];
struct hash *tmp;
int l;
for (l = 0; l < height; ++l) {
/* Swap buffers */
hashswap (src, dst, tmp);
n >>= 1;
/* Compute all hashes at current layer */
hash_compress_pairs (dst, src, n);
}
hashcpy (root, dst);
}
/* Compute authentication path */
void merkle_gen_auth (struct hash *buf, int height, struct hash *auth, int index, struct hash *root) {
int n = 1 << height;
struct hash *src = &buf[n];
struct hash *dst = &buf[0];
struct hash *tmp;
int l, sibling;
for (l = 0; l < height; ++l) {
/* Copy auth path */
sibling = index ^ 1;
hashcpy (&auth[l], &dst[sibling]);
index >>= 1;
/* Swap buffers */
hashswap (src, dst, tmp);
n >>= 1;
/* Compute all hashes at current layer */
hash_compress_pairs (dst, src, n);
}
/* Public key */
if (root != NULL) hashcpy (root, dst);
}
/* Compress node with its auth path on height_diff levels */
int merkle_compress_auth (struct hash *node, int index, const struct hash *auth, int height_diff) {
struct hash buf[2];
int l;
for (l = 0; l < height_diff; ++l) {
if (index % 2 == 0) {
hashcpy (&buf[0], node);
hashcpy (&buf[1], &auth[l]);
} else {
hashcpy (&buf[0], &auth[l]);
hashcpy (&buf[1], node);
}
hash_2N_to_N (node, buf);
index >>= 1;
}
return index;
}
void merkle_gen_octopus (struct hash *buf,
int height,
struct hash *octopus,
int *octolen,
struct hash *root,
int *indices,
int count) {
int n = 1 << height;
struct hash *src = &buf[n];
struct hash *dst = &buf[0];
struct hash *tmp;
int i, j, l;
int len = 0;
int index, sibling;
for (l = 0; l < height; ++l) {
/* Copy auth octopus */
for (i = 0, j = 0; i < count; ++i, ++j) {
index = indices[i];
sibling = index ^ 1;
/* Check redundancy with sibling */
if (i + 1 < count && indices[i + 1] == sibling)
++i;
else
hashcpy (&octopus[len++], &dst[sibling]);
indices[j] = indices[i] >> 1;
}
/* Update count of non-redundant nodes */
count = j;
/* Swap buffers */
hashswap (src, dst, tmp);
n >>= 1;
/* Compute all hashes at current layer */
hash_compress_pairs (dst, src, n);
}
hashcpy (root, dst);
*octolen = len;
}
int merkle_compress_octopus (struct hash *nodes,
int height,
const struct hash *octopus,
int octolen,
int *indices,
int count) {
struct hash buf[2];
int i, j, l;
int len = 0;
int index;
for (l = 0; l < height; ++l) {
for (i = 0, j = 0; i < count; ++i, ++j) {
/* Select 2 values to merge */
index = indices[i];
if (index % 2 == 0) {
hashcpy (&buf[0], &nodes[i]);
if (i + 1 < count && indices[i + 1] == index + 1) {
++i;
hashcpy (&buf[1], &nodes[i]);
} else {
if (len == octolen) return GRAVITY_ERR_VERIF;
hashcpy (&buf[1], &octopus[len++]);
}
} else {
if (len == octolen) return GRAVITY_ERR_VERIF;
hashcpy (&buf[0], &octopus[len++]);
hashcpy (&buf[1], &nodes[i]);
}
/* Hash values */
hash_2N_to_N (&nodes[j], buf);
indices[j] = indices[i] >> 1;
}
/* Update count of non-redundant nodes */
count = j;
}
/* Check len */
if (len != octolen) return GRAVITY_ERR_VERIF;
return GRAVITY_OK;
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#pragma once
#include "wots.h"
struct merkle_pk {
struct hash k;
};
struct merkle_sign {
struct wots_sign wots;
struct hash auth[MERKLE_h];
};
int merkle_genpk (const struct hash *key, const struct address *address, struct merkle_pk *pk);
int merkle_sign (const struct hash *key,
const struct address *address,
struct merkle_sign *sign,
const struct hash *msg,
struct merkle_pk *pk);
void merkle_extract (struct merkle_pk *pk,
const struct address *address,
const struct merkle_sign *sign,
const struct hash *msg);
/* Helper functions */
/* Alloc/free a buffer large enough to store leaves and compress them */
struct hash *merkle_alloc_buf (int height);
void merkle_free_buf (struct hash *buf);
/* Compress leaves from level height to root */
void merkle_compress_all (struct hash *buf, int height, struct hash *root);
/* Compute authentication path */
void merkle_gen_auth (struct hash *buf, int height, struct hash *auth, int index, struct hash *root);
/* Compress node with its auth path on height_diff levels */
int merkle_compress_auth (struct hash *node, int index, const struct hash *auth, int height_diff);
/* "indices" must be sorted */
void merkle_gen_octopus (struct hash *buf,
int height,
struct hash *octopus,
int *octolen,
struct hash *root,
int *indices,
int count);
/* Compress a set of leaves with their auth path */
/* "indices" must be sorted */
int merkle_compress_octopus (struct hash *nodes,
int height,
const struct hash *octopus,
int octolen,
int *indices,
int count);

View File

@@ -1,200 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#include "pors.h"
#include "aes.h"
#include "merkle.h"
#include <stdlib.h>
/* Naive PORS without Merkle tree */
void pors_gensk (const struct hash *key, const struct address *address, struct pors_sk *sk) {
uint8_t iv[16];
iv[0] = (address->index >> 56) & 0xFF;
iv[1] = (address->index >> 48) & 0xFF;
iv[2] = (address->index >> 40) & 0xFF;
iv[3] = (address->index >> 32) & 0xFF;
iv[4] = (address->index >> 24) & 0xFF;
iv[5] = (address->index >> 16) & 0xFF;
iv[6] = (address->index >> 8) & 0xFF;
iv[7] = address->index & 0xFF;
iv[8] = (address->layer >> 24) & 0xFF;
iv[9] = (address->layer >> 16) & 0xFF;
iv[10] = (address->layer >> 8) & 0xFF;
iv[11] = address->layer & 0xFF;
/* Counter */
iv[12] = 0;
iv[13] = 0;
iv[14] = 0;
iv[15] = 0;
aesctr256 (sk->k->h, key->h, iv, PORS_t * HASH_SIZE);
}
void pors_sign (const struct pors_sk *sk, struct pors_sign *sign, const struct pors_subset *subset) {
int i;
int index;
for (i = 0; i < PORS_k; ++i) {
index = subset->s[i];
hashcpy (&sign->s[i], &sk->k[index]);
}
}
/* Naive PORST without merging of authentication paths */
int porst_genpk (const struct pors_sk *sk, struct porst_pk *pk) {
struct hash *buf = merkle_alloc_buf (PORS_tau);
if (buf == NULL) return GRAVITY_ERR_ALLOC;
/* Leaves */
hash_parallel (buf, sk->k, PORS_t);
/* Merkle tree */
merkle_compress_all (buf, PORS_tau, &pk->k);
merkle_free_buf (buf);
return GRAVITY_OK;
}
/* PORST with authentication octopus */
void sort_subset (struct pors_subset *subset) {
/* Selection sort */
int i, j, k, tmp;
for (i = 0; i + 1 < PORS_k; ++i) {
k = i;
tmp = subset->s[k];
for (j = i + 1; j < PORS_k; ++j) {
if (subset->s[j] < tmp) {
k = j;
tmp = subset->s[k];
}
}
subset->s[k] = subset->s[i];
subset->s[i] = tmp;
}
}
int octoporst_sign (const struct pors_sk *sk,
struct octoporst_sign *sign,
struct porst_pk *pk,
struct pors_subset *subset) {
struct hash *buf;
/* Sort subset */
sort_subset (subset);
/* Values */
pors_sign (sk, &sign->s, subset);
/* Authentication paths */
buf = merkle_alloc_buf (PORS_tau);
if (buf == NULL) return GRAVITY_ERR_ALLOC;
/* Leaves */
hash_parallel (buf, sk->k, PORS_t);
/* Merkle tree */
merkle_gen_octopus (buf, PORS_tau, sign->octopus, &sign->octolen, &pk->k,
subset->s, PORS_k);
merkle_free_buf (buf);
return GRAVITY_OK;
}
int octoporst_extract (struct porst_pk *pk,
const struct octoporst_sign *sign,
struct pors_subset *subset) {
struct hash tmp[PORS_k];
int res;
/* Sort subset */
sort_subset (subset);
/* Compute leaves */
hash_parallel (tmp, sign->s.s, PORS_k);
/* Auth octopus */
res = merkle_compress_octopus (tmp, PORS_tau, sign->octopus, sign->octolen,
subset->s, PORS_k);
if (res != GRAVITY_OK) return res;
hashcpy (&pk->k, &tmp[0]);
return GRAVITY_OK;
}
int octoporst_loadsign (struct octoporst_sign *sign, const uint8_t *_sign, size_t _len) {
if (_len < sizeof (struct pors_sign)) return GRAVITY_ERR_VERIF;
_len -= sizeof (struct pors_sign);
if (_len % HASH_SIZE != 0) return GRAVITY_ERR_VERIF;
_len /= HASH_SIZE;
if (_len > PORS_k * PORS_tau) return GRAVITY_ERR_VERIF;
memcpy (&sign->s, _sign, sizeof (struct pors_sign));
_sign += sizeof (struct pors_sign);
memcpy (sign->octopus, _sign, _len * HASH_SIZE);
sign->octolen = _len;
return GRAVITY_OK;
}
int octoporst_signcmp (const struct octoporst_sign *sign1,
const struct octoporst_sign *sign2) {
if (sign1->octolen != sign2->octolen) return 1;
if (hashcmpN (sign1->s.s, sign2->s.s, PORS_k)) return 1;
if (hashcmpN (sign1->octopus, sign2->octopus, sign1->octolen)) return 1;
return 0;
}
void pors_randsubset (const struct hash *rand,
const struct hash *msg,
uint64_t *address,
struct pors_subset *subset) {
#define BYTES_PER_INDEX 4
#define STREAMLEN \
((8 * (PORS_k)) + HASH_SIZE) /* count twice as many indexes as needed */
uint8_t randstream[STREAMLEN];
int index, duplicate, i, count = 0;
size_t offset = 0;
struct hash seed;
struct hash buf[2];
uint64_t addr;
uint8_t byte;
hashcpy (&buf[0], rand);
hashcpy (&buf[1], msg);
hash_2N_to_N (&seed, buf);
aesctr256_zeroiv (randstream, seed.h, STREAMLEN);
/* compute address */
addr = 0;
for (i = 0; i < HASH_SIZE; ++i) {
byte = randstream[i];
addr = (addr << 8) | byte;
addr &= GRAVITY_mask;
}
*address = addr;
while (count < PORS_k) {
/* ok to take mod since T is a power of 2 */
index = U8TO32 (randstream + HASH_SIZE + offset) % PORS_t;
offset += BYTES_PER_INDEX;
duplicate = 0;
for (i = 0; i < count; ++i)
if (subset->s[i] == index) duplicate++;
if (!duplicate) {
subset->s[count] = index;
count++;
}
}
}

View File

@@ -1,74 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#pragma once
#include "hash.h"
/* PRNG to obtain a random subset */
struct pors_subset {
int s[PORS_k];
};
void pors_randsubset (const struct hash *rand,
const struct hash *msg,
uint64_t *address,
struct pors_subset *subset);
/* Naive PORS without Merkle tree */
struct pors_sk {
struct hash k[PORS_t];
};
struct pors_pk {
struct hash k[PORS_t];
};
struct pors_keypair {
struct pors_sk sk;
struct pors_pk pk;
};
struct pors_sign {
struct hash s[PORS_k];
};
void pors_gensk (const struct hash *key, const struct address *address, struct pors_sk *sk);
void pors_sign (const struct pors_sk *sk, struct pors_sign *sign, const struct pors_subset *subset);
/* Naive PORST without merging of authentication paths */
struct porst_pk {
struct hash k;
};
struct porst_keypair {
struct pors_sk sk;
struct porst_pk pk;
};
int porst_genpk (const struct pors_sk *sk, struct porst_pk *pk);
/* PORST with authentication octopus */
struct octoporst_sign {
struct pors_sign s;
struct hash octopus[PORS_k * PORS_tau]; /* Large enough buffer */
int octolen; /* Number of elements in the octopus */
};
int octoporst_sign (const struct pors_sk *sk,
struct octoporst_sign *sign,
struct porst_pk *pk,
struct pors_subset *subset);
int octoporst_extract (struct porst_pk *pk,
const struct octoporst_sign *sign,
struct pors_subset *subset);
/* Serialization */
int octoporst_loadsign (struct octoporst_sign *sign, const uint8_t *_sign, size_t _len);
int octoporst_signcmp (const struct octoporst_sign *sign1, const struct octoporst_sign *sign2);

View File

@@ -1,61 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#include "../aes.h"
#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <string.h>
int aesctr256 (uint8_t *out, const uint8_t *sk, const void *counter, int bytes) {
static const uint8_t buffer[4096] = { 0 };
EVP_CIPHER_CTX *ctx;
int len = 0;
int ret = 0;
if (bytes == 0) return 0;
if (!(ctx = EVP_CIPHER_CTX_new ())) {
ret = -2;
goto label_exit_0;
}
if (1 != EVP_EncryptInit_ex (ctx, EVP_aes_256_ctr (), NULL, sk, counter)) {
ret = -3;
goto label_exit_1;
}
while (bytes >= (int)sizeof (buffer)) {
if (1 != EVP_EncryptUpdate (ctx, out, &len, buffer, sizeof (buffer))) {
ret = -4;
goto label_exit_1;
}
out += sizeof (buffer);
bytes -= sizeof (buffer);
}
if (bytes) {
if (1 != EVP_EncryptUpdate (ctx, out, &len, buffer, bytes)) {
ret = -4;
goto label_exit_1;
}
}
if (1 != EVP_EncryptFinal_ex (ctx, out + len, &len)) {
ret = -5;
goto label_exit_1;
}
ret = 0;
label_exit_1:
EVP_CIPHER_CTX_free (ctx);
label_exit_0:
return ret;
}
int aesctr256_zeroiv (uint8_t *out, const uint8_t *sk, int bytes) {
uint8_t counter[16] = {0};
return aesctr256(out, sk, counter, bytes);
}

View File

@@ -1,125 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#include "haraka.h"
#include <string.h>
void aesenc (uint8_t *s, const uint8_t *rk) {
uint8_t i, t, u, v[4][4];
for (i = 0; i < 16; ++i) v[((i / 4) + 4 - (i % 4)) % 4][i % 4] = sbox[s[i]];
for (i = 0; i < 4; ++i) {
t = v[i][0];
u = v[i][0] ^ v[i][1] ^ v[i][2] ^ v[i][3];
v[i][0] ^= u ^ XT (v[i][0] ^ v[i][1]);
v[i][1] ^= u ^ XT (v[i][1] ^ v[i][2]);
v[i][2] ^= u ^ XT (v[i][2] ^ v[i][3]);
v[i][3] ^= u ^ XT (v[i][3] ^ t);
}
for (i = 0; i < 16; ++i) s[i] = v[i / 4][i % 4] ^ rk[i];
}
void haraka256_256 (uint8_t *out, const uint8_t *in) {
uint8_t s0[16], s1[16];
uint32_t tmp[4];
int i;
memcpy (s0, in, 16);
memcpy (s1, in + 16, 16);
AES2 (0);
MIX2;
AES2 (4);
MIX2;
AES2 (8);
MIX2;
AES2 (12);
MIX2;
AES2 (16);
MIX2;
AES2 (20);
MIX2;
for (i = 0; i < 16; ++i) {
out[i] = in[i] ^ s0[i];
out[i + 16] = in[i + 16] ^ s1[i];
}
}
void haraka256_256_chain (uint8_t *out, const uint8_t *in, int chainlen) {
uint8_t s0[16], s1[16];
uint8_t t0[16], t1[16];
uint32_t tmp[4];
int i, j;
memcpy (s0, in, 16);
memcpy (s1, in + 16, 16);
memcpy (t0, in, 16);
memcpy (t1, in + 16, 16);
for (j = 0; j < chainlen; ++j) {
AES2 (0);
MIX2;
AES2 (4);
MIX2;
AES2 (8);
MIX2;
AES2 (12);
MIX2;
AES2 (16);
MIX2;
AES2 (20);
MIX2;
for (i = 0; i < 16; ++i) {
s0[i] = t0[i] = t0[i] ^ s0[i];
s1[i] = t1[i] = t1[i] ^ s1[i];
}
}
for (i = 0; i < 16; ++i) {
out[i] = s0[i];
out[i + 16] = s1[i];
}
}
void haraka512_256 (uint8_t *out, const uint8_t *in) {
uint8_t s0[16], s1[16], s2[16], s3[16];
uint32_t tmp[5];
int i;
memcpy (s0, in, 16);
memcpy (s1, in + 16, 16);
memcpy (s2, in + 32, 16);
memcpy (s3, in + 48, 16);
AES4 (0);
MIX4;
AES4 (8);
MIX4;
AES4 (16);
MIX4;
AES4 (24);
MIX4;
AES4 (32);
MIX4;
AES4 (40);
MIX4;
for (i = 0; i < 16; ++i) {
s0[i] = in[i] ^ s0[i];
s1[i] = in[i + 16] ^ s1[i];
s2[i] = in[i + 32] ^ s2[i];
s3[i] = in[i + 48] ^ s3[i];
}
((uint64_t *)out)[0] = ((uint64_t *)s0)[1];
((uint64_t *)out)[1] = ((uint64_t *)s1)[1];
((uint64_t *)out)[2] = ((uint64_t *)s2)[0];
((uint64_t *)out)[3] = ((uint64_t *)s3)[0];
}

View File

@@ -1,160 +0,0 @@
/*
The MIT License (MIT)
Copyright (c) 2016 Stefan Kölbl
original Haraka implementations
Copyright (c) 2017 Nagravision S.A.
changes by JP Aumasson, Guillaume Endignoux, 2017: improvements, non-ni versions
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.
*/
#pragma once
#include <stdint.h>
static const uint32_t rc[48 * 4] = {
0x75817b9d, 0xb2c5fef0, 0xe620c00a, 0x0684704c, 0x2f08f717, 0x640f6ba4,
0x88f3a06b, 0x8b66b4e1, 0x9f029114, 0xcf029d60, 0x53f28498, 0x3402de2d,
0xfd5b4f79, 0xbbf3bcaf, 0x2e7b4f08, 0x0ed6eae6, 0xbe397044, 0x79eecd1c,
0x4872448b, 0xcbcfb0cb, 0x2b8a057b, 0x8d5335ed, 0x6e9032b7, 0x7eeacdee,
0xda4fef1b, 0xe2412761, 0x5e2e7cd0, 0x67c28f43, 0x1fc70b3b, 0x675ffde2,
0xafcacc07, 0x2924d9b0, 0xb9d465ee, 0xecdb8fca, 0xe6867fe9, 0xab4d63f1,
0xad037e33, 0x5b2a404f, 0xd4b7cd64, 0x1c30bf84, 0x8df69800, 0x69028b2e,
0x941723bf, 0xb2cc0bb9, 0x5c9d2d8a, 0x4aaa9ec8, 0xde6f5572, 0xfa0478a6,
0x29129fd4, 0x0efa4f2e, 0x6b772a12, 0xdfb49f2b, 0xbb6a12ee, 0x32d611ae,
0xf449a236, 0x1ea10344, 0x9ca8eca6, 0x5f9600c9, 0x4b050084, 0xaf044988,
0x27e593ec, 0x78a2c7e3, 0x9d199c4f, 0x21025ed8, 0x82d40173, 0xb9282ecd,
0xa759c9b7, 0xbf3aaaf8, 0x10307d6b, 0x37f2efd9, 0x6186b017, 0x6260700d,
0xf6fc9ac6, 0x81c29153, 0x21300443, 0x5aca45c2, 0x36d1943a, 0x2caf92e8,
0x226b68bb, 0x9223973c, 0xe51071b4, 0x6cbab958, 0x225886eb, 0xd3bf9238,
0x24e1128d, 0x933dfddd, 0xaef0c677, 0xdb863ce5, 0xcb2212b1, 0x83e48de3,
0xffeba09c, 0xbb606268, 0xc72bf77d, 0x2db91a4e, 0xe2e4d19c, 0x734bd3dc,
0x2cb3924e, 0x4b1415c4, 0x61301b43, 0x43bb47c3, 0x16eb6899, 0x03b231dd,
0xe707eff6, 0xdba775a8, 0x7eca472c, 0x8e5e2302, 0x3c755977, 0x6df3614b,
0xb88617f9, 0x6d1be5b9, 0xd6de7d77, 0xcda75a17, 0xa946ee5d, 0x9d6c069d,
0x6ba8e9aa, 0xec6b43f0, 0x3bf327c1, 0xa2531159, 0xf957332b, 0xcb1e6950,
0x600ed0d9, 0xe4ed0353, 0x00da619c, 0x2cee0c75, 0x63a4a350, 0x80bbbabc,
0x96e90cab, 0xf0b1a5a1, 0x938dca39, 0xab0dde30, 0x5e962988, 0xae3db102,
0x2e75b442, 0x8814f3a8, 0xd554a40b, 0x17bb8f38, 0x360a16f6, 0xaeb6b779,
0x5f427fd7, 0x34bb8a5b, 0xffbaafde, 0x43ce5918, 0xcbe55438, 0x26f65241,
0x839ec978, 0xa2ca9cf7, 0xb9f3026a, 0x4ce99a54, 0x22901235, 0x40c06e28,
0x1bdff7be, 0xae51a51a, 0x48a659cf, 0xc173bc0f, 0xba7ed22b, 0xa0c1613c,
0xe9c59da1, 0x4ad6bdfd, 0x02288288, 0x756acc03, 0x848f2ad2, 0x367e4778,
0x0de7d31e, 0x2ff37238, 0xb73bd58f, 0xee36b135, 0xcf74be8b, 0x08d95c6a,
0xa3743e4a, 0x66ae1838, 0xc9d6ee98, 0x5880f434, 0x9a9369bd, 0xd0fdf4c7,
0xaefabd99, 0x593023f0, 0x6f1ecb2a, 0xa5cc637b, 0xeb606e6f, 0x329ae3d1,
0xcb7594ab, 0xa4dc93d6, 0x49e01594, 0xe00207eb, 0x65208ef8, 0x942366a6,
0xf751c880, 0x1caa0c4f, 0xe3e67e4a, 0xbd03239f, 0xdb2dc1dd, 0x02f7f57f,
};
static const uint8_t sbox[256] =
{ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe,
0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4,
0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7,
0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3,
0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09,
0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3,
0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe,
0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92,
0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c,
0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2,
0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5,
0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25,
0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86,
0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e,
0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42,
0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
#define XT(x) (((x) << 1) ^ ((((x) >> 7) & 1) * 0x1b))
#define AES2(rci) \
aesenc (s0, ((uint8_t *)rc) + 16 * (rci + 0)); \
aesenc (s1, ((uint8_t *)rc) + 16 * (rci + 1)); \
aesenc (s0, ((uint8_t *)rc) + 16 * (rci + 2)); \
aesenc (s1, ((uint8_t *)rc) + 16 * (rci + 3));
#define MIX2 \
tmp[0] = ((uint32_t *)s0)[0]; \
tmp[1] = ((uint32_t *)s1)[0]; \
tmp[2] = ((uint32_t *)s0)[1]; \
tmp[3] = ((uint32_t *)s1)[1]; \
((uint32_t *)s1)[0] = ((uint32_t *)s0)[2]; \
((uint32_t *)s1)[1] = ((uint32_t *)s1)[2]; \
((uint32_t *)s1)[2] = ((uint32_t *)s0)[3]; \
((uint32_t *)s0)[0] = tmp[0]; \
((uint32_t *)s0)[1] = tmp[1]; \
((uint32_t *)s0)[2] = tmp[2]; \
((uint32_t *)s0)[3] = tmp[3];
#define AES4(rci) \
aesenc (s0, ((uint8_t *)rc) + 16 * (rci + 0)); \
aesenc (s1, ((uint8_t *)rc) + 16 * (rci + 1)); \
aesenc (s2, ((uint8_t *)rc) + 16 * (rci + 2)); \
aesenc (s3, ((uint8_t *)rc) + 16 * (rci + 3)); \
aesenc (s0, ((uint8_t *)rc) + 16 * (rci + 4)); \
aesenc (s1, ((uint8_t *)rc) + 16 * (rci + 5)); \
aesenc (s2, ((uint8_t *)rc) + 16 * (rci + 6)); \
aesenc (s3, ((uint8_t *)rc) + 16 * (rci + 7));
#define MIX4 \
tmp[0] = ((uint32_t *)s0)[0]; \
tmp[1] = ((uint32_t *)s1)[0]; \
tmp[2] = ((uint32_t *)s0)[1]; \
tmp[3] = ((uint32_t *)s1)[1]; \
tmp[4] = ((uint32_t *)s3)[0]; \
((uint32_t *)s0)[0] = ((uint32_t *)s0)[2]; \
((uint32_t *)s0)[1] = ((uint32_t *)s1)[2]; \
((uint32_t *)s0)[2] = ((uint32_t *)s0)[3]; \
((uint32_t *)s0)[3] = ((uint32_t *)s1)[3]; \
((uint32_t *)s1)[0] = ((uint32_t *)s2)[0]; \
((uint32_t *)s1)[1] = ((uint32_t *)s3)[0]; \
((uint32_t *)s1)[2] = ((uint32_t *)s2)[1]; \
((uint32_t *)s1)[3] = ((uint32_t *)s3)[1]; \
((uint32_t *)s2)[0] = ((uint32_t *)s2)[2]; \
((uint32_t *)s2)[1] = ((uint32_t *)s3)[2]; \
((uint32_t *)s2)[2] = ((uint32_t *)s2)[3]; \
((uint32_t *)s2)[3] = ((uint32_t *)s3)[3]; \
((uint32_t *)s3)[0] = ((uint32_t *)s0)[0]; \
((uint32_t *)s3)[1] = ((uint32_t *)s2)[0]; \
((uint32_t *)s3)[2] = ((uint32_t *)s0)[1]; \
((uint32_t *)s3)[3] = ((uint32_t *)s2)[1]; \
((uint32_t *)s0)[0] = ((uint32_t *)s0)[2]; \
((uint32_t *)s0)[1] = ((uint32_t *)s2)[2]; \
((uint32_t *)s0)[2] = ((uint32_t *)s0)[3]; \
((uint32_t *)s0)[3] = ((uint32_t *)s2)[3]; \
((uint32_t *)s2)[0] = ((uint32_t *)s1)[2]; \
((uint32_t *)s2)[1] = tmp[2]; \
((uint32_t *)s2)[2] = ((uint32_t *)s1)[3]; \
((uint32_t *)s2)[3] = tmp[3]; \
((uint32_t *)s1)[0] = ((uint32_t *)s1)[0]; \
((uint32_t *)s1)[1] = tmp[0]; \
((uint32_t *)s1)[2] = tmp[4]; \
((uint32_t *)s1)[3] = tmp[1];
void haraka256_256(unsigned char *out, const unsigned char *in);
void haraka256_256_chain(unsigned char *out, const unsigned char *in, int chainlen);
void haraka512_256(unsigned char *out, const unsigned char *in);

View File

@@ -1,56 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#include "../hash.h"
#include "haraka.h"
#include <openssl/sha.h>
void hash_N_to_N(struct hash *dst, const struct hash *src)
{
haraka256_256(dst->h, src->h);
}
void hash_N_to_N_chain(struct hash *dst, const struct hash *src, int chainlen)
{
haraka256_256_chain(dst->h, src->h, chainlen);
}
void hash_2N_to_N(struct hash *dst, const struct hash *src)
{
haraka512_256(dst->h, src->h);
}
void hash_to_N(struct hash *dst, const uint8_t *src, uint64_t srclen)
{
SHA256(src, srclen, dst->h);
}
void hash_compress_pairs(struct hash *dst, const struct hash *src, int count)
{
int i = 0;
for (; i < count; ++i)
hash_2N_to_N(&dst[i], &src[2*i]);
}
void hash_compress_all(struct hash *dst, const struct hash *src, int count)
{
/* Fast implementation with a single call to a large input hash function */
hash_to_N(dst, src->h, count * HASH_SIZE);
/* TODO: implement a real L-tree with 2N->N compression function */
}
void hash_parallel(struct hash *dst, const struct hash *src, int count)
{
int i = 0;
for (; i < count; ++i)
hash_N_to_N(&dst[i], &src[i]);
}
void hash_parallel_chains(struct hash *dst, const struct hash *src, int count, int chainlen)
{
int i = 0;
for (; i < count; ++i)
hash_N_to_N_chain(&dst[i], &src[i], chainlen);
}

View File

@@ -1,13 +0,0 @@
#include "randombytes.h"
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
/* lazy unsafe emulation of SUPERCOP's randombytes() */
void randombytes (unsigned char *x, unsigned long long xlen) {
static int fd = -1;
if (fd == -1) fd = open ("/dev/urandom", O_RDONLY);
read (fd, x, xlen);
}

View File

@@ -1,4 +0,0 @@
#pragma once
void randombytes (unsigned char *x, unsigned long long xlen);

View File

@@ -1,85 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#include "gravity.h"
#include "randombytes.h"
int crypto_sign_keypair (unsigned char *pk, unsigned char *sk) {
struct gravity_sk sk_str;
struct gravity_pk pk_str;
if (!pk || !sk) return -1;
randombytes (sk_str.seed.h, HASH_SIZE);
randombytes (sk_str.salt.h, HASH_SIZE);
gravity_gensk (&sk_str);
memcpy (sk, (void *)&sk_str, sizeof (struct gravity_sk));
gravity_genpk (&sk_str, &pk_str);
memcpy (pk, pk_str.k.h, HASH_SIZE);
return 0;
}
int crypto_sign (unsigned char *sm,
unsigned long long *smlen,
const unsigned char *m,
unsigned long long mlen,
const unsigned char *sk) {
struct gravity_sk sk_str;
struct hash msg;
struct gravity_sign sig;
int ret;
if (!sm || !smlen || !m || !sk) return -1;
hash_to_N (&msg, m, mlen);
memcpy ((void *)&sk_str, sk, sizeof (struct gravity_sk));
memset ((uint8_t *)(&sig), 0, sizeof (struct gravity_sign));
ret = gravity_sign (&sk_str, &sig, &msg);
if (ret != GRAVITY_OK) return ret;
memcpy (sm + mlen, (uint8_t *)(&sig), sizeof (struct gravity_sign));
memmove (sm, m, mlen);
*smlen = mlen + sizeof (struct gravity_sign);
return 0;
}
int crypto_sign_open (unsigned char *m,
unsigned long long *mlen,
const unsigned char *sm,
unsigned long long smlen,
const unsigned char *pk) {
struct gravity_pk pk_str;
struct hash msg;
struct gravity_sign sig;
if (!m || !mlen || !sm || !pk) return -1;
if (smlen < sizeof (struct gravity_sign)) return -2;
*mlen = smlen - sizeof (struct gravity_sign);
memcpy ((void *)(&pk_str), pk, HASH_SIZE);
memcpy ((void *)&sig, sm + *mlen, sizeof (struct gravity_sign));
memcpy (m, sm, *mlen);
hash_to_N (&msg, m, *mlen);
return gravity_verify (&pk_str, &sig, &msg);
}

View File

@@ -1,18 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#pragma once
int crypto_sign_keypair (unsigned char *pk, unsigned char *sk);
int crypto_sign (unsigned char *sm,
unsigned long long *smlen,
const unsigned char *m,
unsigned long long mlen,
const unsigned char *sk);
int crypto_sign_open (unsigned char *m,
unsigned long long *mlen,
const unsigned char *sm,
unsigned long long smlen,
const unsigned char *pk);

View File

@@ -1,101 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#include "wots.h"
#include "aes.h"
#include "ltree.h"
void wots_chain (const struct hash *src, struct hash *dst, int count) {
hash_N_to_N_chain (dst, src, count);
}
/* Naive WOTS without L-tree nor masks */
void wots_gensk (const struct hash *key, const struct address *address, struct wots_sk *sk) {
uint8_t iv[16];
iv[0] = (address->index >> 56) & 0xFF;
iv[1] = (address->index >> 48) & 0xFF;
iv[2] = (address->index >> 40) & 0xFF;
iv[3] = (address->index >> 32) & 0xFF;
iv[4] = (address->index >> 24) & 0xFF;
iv[5] = (address->index >> 16) & 0xFF;
iv[6] = (address->index >> 8) & 0xFF;
iv[7] = address->index & 0xFF;
iv[8] = (address->layer >> 24) & 0xFF;
iv[9] = (address->layer >> 16) & 0xFF;
iv[10] = (address->layer >> 8) & 0xFF;
iv[11] = address->layer & 0xFF;
/* Counter */
iv[12] = 0;
iv[13] = 0;
iv[14] = 0;
iv[15] = 0;
aesctr256 (sk->k->h, key->h, iv, WOTS_ell * HASH_SIZE);
}
void wots_sign (const struct wots_sk *sk, struct wots_sign *sign, const struct hash *msg) {
int checksum = 0;
int i;
for (i = 0; i < WOTS_ell1; ++i) {
uint8_t v = msg->h[i / 2];
int a = (v >> 4) & 15;
int b = v & 15;
checksum += (WOTS_w - 1 - a) + (WOTS_w - 1 - b);
wots_chain (&sk->k[i], &sign->s[i], a);
++i;
wots_chain (&sk->k[i], &sign->s[i], b);
}
/* Checksum values */
for (i = WOTS_ell1; i < WOTS_ell; ++i) {
wots_chain (&sk->k[i], &sign->s[i], checksum & 15);
checksum >>= 4;
}
}
/* WOTS with L-tree and without masks */
void lwots_ltree (const struct wots_pk *pk, struct lwots_pk *root) {
struct hash buf[2 * WOTS_ell];
hashcpyN (buf, pk->k, WOTS_ell);
ltree (buf, WOTS_ell, &root->k);
}
void lwots_genpk (const struct wots_sk *sk, struct lwots_pk *pk) {
struct wots_pk tmp;
hash_parallel_chains (tmp.k, sk->k, WOTS_ell, WOTS_w - 1);
lwots_ltree (&tmp, pk);
}
void lwots_extract (struct lwots_pk *pk, const struct wots_sign *sign, const struct hash *msg) {
struct wots_pk tmp;
int i;
int checksum = 0;
for (i = 0; i < WOTS_ell1; ++i) {
uint8_t v = msg->h[i / 2];
int a = (v >> 4) & 15;
int b = v & 15;
checksum += (WOTS_w - 1 - a) + (WOTS_w - 1 - b);
wots_chain (&sign->s[i], &tmp.k[i], WOTS_w - 1 - a);
++i;
wots_chain (&sign->s[i], &tmp.k[i], WOTS_w - 1 - b);
}
/* Checksum values */
for (i = WOTS_ell1; i < WOTS_ell; ++i) {
wots_chain (&sign->s[i], &tmp.k[i], WOTS_w - 1 - (checksum & 15));
checksum >>= 4;
}
/* L-tree */
lwots_ltree (&tmp, pk);
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright (C) 2017 Nagravision S.A.
*/
#pragma once
#include "common.h"
#include "hash.h"
/* Naive WOTS without L-tree nor masks */
struct wots_sk {
struct hash k[WOTS_ell];
};
struct wots_pk {
struct hash k[WOTS_ell];
};
struct wots_sign {
struct hash s[WOTS_ell];
};
void wots_gensk (const struct hash *key, const struct address *address, struct wots_sk *sk);
void wots_sign (const struct wots_sk *sk, struct wots_sign *sign, const struct hash *msg);
/* WOTS with L-tree and without masks */
struct lwots_pk {
struct hash k;
};
void lwots_genpk (const struct wots_sk *sk, struct lwots_pk *pk);
void lwots_extract (struct lwots_pk *pk, const struct wots_sign *sign, const struct hash *msg);