Initial import: ultra-small bruteforce tool, docs, and .gitignore
This commit is contained in:
85
brute/source/yescrypt/Makefile
Normal file
85
brute/source/yescrypt/Makefile
Normal file
@@ -0,0 +1,85 @@
|
||||
# Copyright 2013-2018 Alexander Peslyak
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS 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 AUTHOR OR 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.
|
||||
|
||||
CC = gcc
|
||||
LD = $(CC)
|
||||
RM = rm -f
|
||||
OMPFLAGS = -fopenmp
|
||||
OMPFLAGS_MAYBE = $(OMPFLAGS)
|
||||
#CFLAGS = -Wall -O2 -fomit-frame-pointer $(OMPFLAGS_MAYBE) -DSKIP_MEMZERO
|
||||
CFLAGS = -Wall -O2 -march=native -fomit-frame-pointer $(OMPFLAGS_MAYBE) -DSKIP_MEMZERO
|
||||
#CFLAGS = -Wall -O2 -funroll-loops -fomit-frame-pointer $(OMPFLAGS_MAYBE) -DSKIP_MEMZERO
|
||||
#CFLAGS = -Wall -O2 -march=native -funroll-loops -fomit-frame-pointer $(OMPFLAGS_MAYBE) -DSKIP_MEMZERO
|
||||
# -lrt is for userom's use of clock_gettime()
|
||||
LDFLAGS = -s -lrt $(OMPFLAGS_MAYBE)
|
||||
|
||||
PROJ = tests phc-test initrom userom
|
||||
OBJS_CORE = yescrypt-opt.o
|
||||
OBJS_COMMON = yescrypt-common.o sha256.o insecure_memzero.o
|
||||
OBJS_TESTS = $(OBJS_CORE) $(OBJS_COMMON) tests.o
|
||||
OBJS_PHC = $(OBJS_CORE) $(OBJS_COMMON) phc-test.o
|
||||
OBJS_INITROM = $(OBJS_CORE) $(OBJS_COMMON) initrom.o
|
||||
OBJS_USEROM = $(OBJS_CORE) $(OBJS_COMMON) userom.o
|
||||
OBJS_RM = yescrypt-*.o
|
||||
|
||||
all: $(PROJ)
|
||||
|
||||
check: tests phc-test
|
||||
@echo 'Running main tests'
|
||||
@time ./tests | tee TESTS-OUT
|
||||
@diff -U0 TESTS-OK TESTS-OUT && echo PASSED || echo FAILED
|
||||
@if [ -f PHC-TEST-OK-SHA256 ]; then \
|
||||
echo 'Running PHC tests'; \
|
||||
time ./phc-test > PHC-TEST-OUT; \
|
||||
sha256sum -c PHC-TEST-OK-SHA256 || shasum -a 256 -c PHC-TEST-OK-SHA256; \
|
||||
fi
|
||||
|
||||
ref:
|
||||
$(MAKE) $(PROJ) OBJS_CORE=yescrypt-ref.o
|
||||
|
||||
check-ref:
|
||||
$(MAKE) check OBJS_CORE=yescrypt-ref.o
|
||||
|
||||
tests: $(OBJS_TESTS)
|
||||
$(LD) $(LDFLAGS) $(OBJS_TESTS) -o $@
|
||||
|
||||
phc-test.o: phc.c
|
||||
$(CC) -c $(CFLAGS) -DTEST phc.c -o $@
|
||||
|
||||
phc-test: $(OBJS_PHC)
|
||||
$(LD) $(LDFLAGS) $(OBJS_PHC) -o $@
|
||||
|
||||
initrom: $(OBJS_INITROM)
|
||||
$(LD) $(LDFLAGS) $(OBJS_INITROM) -o $@
|
||||
|
||||
userom: $(OBJS_USEROM)
|
||||
$(LD) $(LDFLAGS) $(OMPFLAGS) $(OBJS_USEROM) -o $@
|
||||
|
||||
userom.o: userom.c
|
||||
$(CC) -c $(CFLAGS) $(OMPFLAGS) $*.c
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $*.c
|
||||
|
||||
yescrypt-opt.o: yescrypt-platform.c
|
||||
|
||||
clean:
|
||||
$(RM) $(PROJ)
|
||||
$(RM) $(OBJS_TESTS) $(OBJS_PHC) $(OBJS_INITROM) $(OBJS_USEROM)
|
||||
$(RM) $(OBJS_RM)
|
||||
$(RM) TESTS-OUT PHC-TEST-OUT
|
||||
217
brute/source/yescrypt/initrom.c
Normal file
217
brute/source/yescrypt/initrom.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/*-
|
||||
* Copyright 2013-2018 Alexander Peslyak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*/
|
||||
|
||||
#define YESCRYPT_FLAGS YESCRYPT_DEFAULTS
|
||||
|
||||
#define ROM_SHM_KEY 0x7965730a
|
||||
#define ROM_LOCAL_PARAM "change this before use"
|
||||
|
||||
/* Maximum parallelism factor during ROM initialization */
|
||||
#define YESCRYPT_PROM_SHM 112
|
||||
#define YESCRYPT_PROM_FILE 4
|
||||
|
||||
//#define USE_HUGEPAGE
|
||||
//#define DUMP_SHARED
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for atoi() */
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "yescrypt.h"
|
||||
|
||||
int main(int argc, const char * const *argv)
|
||||
{
|
||||
#if 0
|
||||
uint64_t rom_bytes = 112 * (1024ULL*1024*1024);
|
||||
uint64_t ram_bytes = 1 * (1024ULL*1024);
|
||||
#else
|
||||
uint64_t rom_bytes = 3 * (1024ULL*1024*1024);
|
||||
uint64_t ram_bytes = 2 * (1024ULL*1024);
|
||||
#endif
|
||||
uint32_t r, min_r;
|
||||
uint64_t NROM_log2, N_log2;
|
||||
int shmid;
|
||||
yescrypt_shared_t shared;
|
||||
yescrypt_binary_t *digest;
|
||||
const char *rom_filename = NULL;
|
||||
int rom_fd;
|
||||
|
||||
if (argc > 1)
|
||||
rom_bytes = atoi(argv[1]) * (1024ULL*1024*1024);
|
||||
if (argc > 2)
|
||||
ram_bytes = atoi(argv[2]) * (1024ULL*1024);
|
||||
if (argc > 3)
|
||||
rom_filename = argv[3];
|
||||
|
||||
if (!rom_bytes) {
|
||||
puts("Wrong ROM size requested");
|
||||
return 1;
|
||||
}
|
||||
|
||||
min_r = 9;
|
||||
if (rom_filename)
|
||||
min_r = 8 * 256;
|
||||
|
||||
NROM_log2 = 0;
|
||||
while (((rom_bytes >> NROM_log2) & 0xff) == 0)
|
||||
NROM_log2++;
|
||||
r = rom_bytes >> (7 + NROM_log2);
|
||||
while (r < min_r && NROM_log2 > 0) {
|
||||
r <<= 1;
|
||||
NROM_log2--;
|
||||
}
|
||||
rom_bytes = (uint64_t)r << (7 + NROM_log2);
|
||||
|
||||
N_log2 = 3;
|
||||
while (((uint64_t)r << (7 + N_log2)) < ram_bytes)
|
||||
N_log2++;
|
||||
ram_bytes = (uint64_t)r << (7 + N_log2);
|
||||
|
||||
printf("r=%u N=2^%u NROM=2^%u\n", r,
|
||||
(unsigned int)N_log2, (unsigned int)NROM_log2);
|
||||
|
||||
printf("Will use %.2f KiB ROM\n", rom_bytes / 1024.0);
|
||||
printf(" %.2f KiB RAM\n", ram_bytes / 1024.0);
|
||||
|
||||
shared.aligned_size = rom_bytes;
|
||||
|
||||
if (rom_filename) {
|
||||
rom_fd = open(rom_filename, O_CREAT|O_RDWR|O_EXCL,
|
||||
S_IRUSR|S_IRGRP|S_IWUSR);
|
||||
if (rom_fd < 0) {
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
if (ftruncate(rom_fd, rom_bytes)) {
|
||||
perror("ftruncate");
|
||||
close(rom_fd);
|
||||
unlink(rom_filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flags =
|
||||
#ifdef MAP_NOCORE
|
||||
MAP_NOCORE |
|
||||
#endif
|
||||
#if defined(MAP_HUGETLB) && defined(USE_HUGEPAGE)
|
||||
MAP_HUGETLB |
|
||||
#endif
|
||||
MAP_SHARED;
|
||||
void *p = mmap(NULL, rom_bytes, PROT_READ | PROT_WRITE,
|
||||
flags, rom_fd, 0);
|
||||
#if defined(MAP_HUGETLB) && defined(USE_HUGEPAGE)
|
||||
if (p == MAP_FAILED)
|
||||
p = mmap(NULL, rom_bytes, PROT_READ | PROT_WRITE,
|
||||
flags & ~MAP_HUGETLB, rom_fd, 0);
|
||||
#endif
|
||||
if (p == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
close(rom_fd);
|
||||
unlink(rom_filename);
|
||||
return 1;
|
||||
}
|
||||
close(rom_fd);
|
||||
shared.base = shared.aligned = p;
|
||||
} else {
|
||||
shmid = shmget(ROM_SHM_KEY, shared.aligned_size,
|
||||
#ifdef SHM_HUGETLB
|
||||
SHM_HUGETLB |
|
||||
#endif
|
||||
IPC_CREAT|IPC_EXCL | S_IRUSR|S_IRGRP|S_IWUSR);
|
||||
if (shmid == -1) {
|
||||
#ifdef SHM_HUGETLB
|
||||
perror("shmget");
|
||||
puts("Retrying without SHM_HUGETLB");
|
||||
shmid = shmget(ROM_SHM_KEY, shared.aligned_size,
|
||||
IPC_CREAT|IPC_EXCL | S_IRUSR|S_IRGRP|S_IWUSR);
|
||||
#endif
|
||||
if (shmid == -1) {
|
||||
perror("shmget");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
shared.base = shared.aligned = shmat(shmid, NULL, 0);
|
||||
if (shared.base == (void *)-1) {
|
||||
int save_errno = errno;
|
||||
shmctl(shmid, IPC_RMID, NULL);
|
||||
errno = save_errno;
|
||||
perror("shmat");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Initializing ROM ...");
|
||||
fflush(stdout);
|
||||
yescrypt_params_t rom_params = {
|
||||
.flags = YESCRYPT_DEFAULTS | YESCRYPT_SHARED_PREALLOCATED,
|
||||
.NROM = (uint64_t)1 << NROM_log2,
|
||||
.r = r,
|
||||
.p = rom_filename ? YESCRYPT_PROM_FILE : YESCRYPT_PROM_SHM };
|
||||
if (yescrypt_init_shared(&shared,
|
||||
(uint8_t *)ROM_LOCAL_PARAM, strlen(ROM_LOCAL_PARAM),
|
||||
&rom_params)) {
|
||||
puts(" FAILED");
|
||||
if (rom_filename)
|
||||
unlink(rom_filename);
|
||||
return 1;
|
||||
}
|
||||
#ifdef DUMP_SHARED
|
||||
fwrite(shared.aligned, shared.aligned_size, 1, stderr);
|
||||
#endif
|
||||
digest = yescrypt_digest_shared(&shared);
|
||||
printf(" DONE (%02x%02x%02x%02x)\n",
|
||||
digest->uc[0], digest->uc[1], digest->uc[2], digest->uc[3]);
|
||||
|
||||
{
|
||||
yescrypt_local_t local;
|
||||
const uint8_t *setting;
|
||||
uint8_t hash[128];
|
||||
|
||||
if (yescrypt_init_local(&local)) {
|
||||
puts("yescrypt_init_local() FAILED");
|
||||
return 1;
|
||||
}
|
||||
|
||||
yescrypt_params_t params = rom_params;
|
||||
params.flags = YESCRYPT_FLAGS;
|
||||
params.N = (uint64_t)1 << N_log2;
|
||||
params.p = 1;
|
||||
setting = yescrypt_encode_params(¶ms,
|
||||
(const uint8_t *)"WZaPV7LSUEKMo34.", 16);
|
||||
|
||||
printf("'%s'\n", (char *)yescrypt_r(&shared, &local,
|
||||
(const uint8_t *)"pleaseletmein", 13, setting, NULL,
|
||||
hash, sizeof(hash)));
|
||||
}
|
||||
|
||||
if (rom_filename && munmap(shared.base, rom_bytes)) {
|
||||
perror("munmap");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
49
brute/source/yescrypt/insecure_memzero.c
Normal file
49
brute/source/yescrypt/insecure_memzero.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/*-
|
||||
* Copyright 2014 Colin Percival
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*/
|
||||
|
||||
#ifndef SKIP_MEMZERO
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "insecure_memzero.h"
|
||||
|
||||
/* Function which does the zeroing. */
|
||||
static void
|
||||
insecure_memzero_func(volatile void * buf, size_t len)
|
||||
{
|
||||
volatile uint8_t * _buf = buf;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
_buf[i] = 0;
|
||||
}
|
||||
|
||||
/* Pointer to memory-zeroing function. */
|
||||
void (* volatile insecure_memzero_ptr)(volatile void *, size_t) =
|
||||
insecure_memzero_func;
|
||||
|
||||
#endif
|
||||
69
brute/source/yescrypt/insecure_memzero.h
Normal file
69
brute/source/yescrypt/insecure_memzero.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*-
|
||||
* Copyright 2014 Colin Percival
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*/
|
||||
|
||||
#ifndef _INSECURE_MEMZERO_H_
|
||||
#define _INSECURE_MEMZERO_H_
|
||||
|
||||
#ifdef SKIP_MEMZERO
|
||||
#define insecure_memzero(buf, len) /* empty */
|
||||
#else
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Pointer to memory-zeroing function. */
|
||||
extern void (* volatile insecure_memzero_ptr)(volatile void *, size_t);
|
||||
|
||||
/**
|
||||
* insecure_memzero(buf, len):
|
||||
* Attempt to zero ${len} bytes at ${buf} in spite of optimizing compilers'
|
||||
* best (standards-compliant) attempts to remove the buffer-zeroing. In
|
||||
* particular, to avoid performing the zeroing, a compiler would need to
|
||||
* use optimistic devirtualization; recognize that non-volatile objects do not
|
||||
* need to be treated as volatile, even if they are accessed via volatile
|
||||
* qualified pointers; and perform link-time optimization; in addition to the
|
||||
* dead-code elimination which often causes buffer-zeroing to be elided.
|
||||
*
|
||||
* Note however that zeroing a buffer does not guarantee that the data held
|
||||
* in the buffer is not stored elsewhere; in particular, there may be copies
|
||||
* held in CPU registers or in anonymous allocations on the stack, even if
|
||||
* every named variable is successfully sanitized. Solving the "wipe data
|
||||
* from the system" problem will require a C language extension which does not
|
||||
* yet exist.
|
||||
*
|
||||
* For more information, see:
|
||||
* http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html
|
||||
* http://www.daemonology.net/blog/2014-09-06-zeroing-buffers-is-insufficient.html
|
||||
*/
|
||||
static inline void
|
||||
insecure_memzero(volatile void * buf, size_t len)
|
||||
{
|
||||
|
||||
(insecure_memzero_ptr)(buf, len);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !_INSECURE_MEMZERO_H_ */
|
||||
145
brute/source/yescrypt/phc.c
Normal file
145
brute/source/yescrypt/phc.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*-
|
||||
* Copyright 2014-2016,2018 Alexander Peslyak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*/
|
||||
|
||||
#define YESCRYPT_FLAGS YESCRYPT_DEFAULTS
|
||||
#define YESCRYPT_BASE_N 8
|
||||
#define YESCRYPT_R 8
|
||||
#define YESCRYPT_P 1
|
||||
|
||||
#include "yescrypt.h"
|
||||
|
||||
#ifdef TEST
|
||||
static
|
||||
#endif
|
||||
int PHS(void *out, size_t outlen, const void *in, size_t inlen,
|
||||
const void *salt, size_t saltlen, unsigned int t_cost, unsigned int m_cost)
|
||||
{
|
||||
yescrypt_local_t local;
|
||||
yescrypt_params_t params = {
|
||||
.flags = YESCRYPT_FLAGS,
|
||||
.N = (uint64_t)YESCRYPT_BASE_N << m_cost,
|
||||
.r = YESCRYPT_R,
|
||||
.p = YESCRYPT_P,
|
||||
.t = t_cost,
|
||||
.g = 0 };
|
||||
int retval;
|
||||
|
||||
if (yescrypt_init_local(&local))
|
||||
return -1;
|
||||
retval = yescrypt_kdf(NULL, &local, in, inlen, salt, saltlen, ¶ms,
|
||||
out, outlen);
|
||||
if (yescrypt_free_local(&local))
|
||||
return -1;
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <stdio.h>
|
||||
#include <unistd.h> /* for sysconf() */
|
||||
#include <sys/times.h>
|
||||
|
||||
static void print_hex(const uint8_t *buf, size_t buflen, const char *sep)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
putchar('"');
|
||||
for (i = 0; i < buflen; i++)
|
||||
printf("\\x%02x", buf[i]);
|
||||
printf("\"%s", sep);
|
||||
}
|
||||
|
||||
static void print_PHS(const void *in, size_t inlen,
|
||||
const void *salt, size_t saltlen, unsigned int t_cost, unsigned int m_cost)
|
||||
{
|
||||
uint8_t dk[32];
|
||||
|
||||
printf("PHS(");
|
||||
print_hex(in, inlen, ", ");
|
||||
print_hex(salt, saltlen, ", ");
|
||||
printf("%u, %u) = ", t_cost, m_cost);
|
||||
|
||||
if (PHS(dk, sizeof(dk), in, inlen, salt, saltlen, t_cost, m_cost)) {
|
||||
puts("FAILED");
|
||||
return;
|
||||
}
|
||||
|
||||
print_hex(dk, sizeof(dk), "\n");
|
||||
}
|
||||
|
||||
static void print_all_PHS(unsigned int t_cost, unsigned int m_cost)
|
||||
{
|
||||
clock_t clk_tck = sysconf(_SC_CLK_TCK);
|
||||
struct tms start_tms, end_tms;
|
||||
clock_t start = times(&start_tms), end, start_v, end_v;
|
||||
const size_t count = 0x102;
|
||||
size_t inlen, i, j;
|
||||
|
||||
inlen = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
uint8_t in[128], salt[16];
|
||||
|
||||
for (j = 0; j < inlen; j++)
|
||||
in[j] = (i + j) & 0xff;
|
||||
for (j = 0; j < sizeof(salt); j++)
|
||||
salt[j] = ~(i + j) & 0xff;
|
||||
|
||||
print_PHS(in, inlen, salt, sizeof(salt), t_cost, m_cost);
|
||||
|
||||
if (++inlen > sizeof(in))
|
||||
inlen = 0;
|
||||
}
|
||||
|
||||
end = times(&end_tms);
|
||||
|
||||
start_v = start_tms.tms_utime + start_tms.tms_stime +
|
||||
start_tms.tms_cutime + start_tms.tms_cstime;
|
||||
end_v = end_tms.tms_utime + end_tms.tms_stime +
|
||||
end_tms.tms_cutime + end_tms.tms_cstime;
|
||||
|
||||
if (end == start)
|
||||
end++;
|
||||
if (end_v == start_v)
|
||||
end_v++;
|
||||
|
||||
fprintf(stderr, "m_cost=%u (%.0f KiB), t_cost=%u\n"
|
||||
"%llu c/s real, %llu c/s virtual (%llu hashes in %.2f seconds)\n",
|
||||
m_cost, (YESCRYPT_BASE_N << m_cost) * YESCRYPT_R / 8.0, t_cost,
|
||||
(unsigned long long)count * clk_tck / (end - start),
|
||||
(unsigned long long)count * clk_tck / (end_v - start_v),
|
||||
(unsigned long long)count, (double)(end - start) / clk_tck);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
#if 0
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
#endif
|
||||
|
||||
print_all_PHS(0, 0);
|
||||
print_all_PHS(0, 7);
|
||||
print_all_PHS(0, 8);
|
||||
print_all_PHS(1, 8);
|
||||
print_all_PHS(2, 8);
|
||||
print_all_PHS(3, 8);
|
||||
print_all_PHS(0, 11);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
652
brute/source/yescrypt/sha256.c
Normal file
652
brute/source/yescrypt/sha256.c
Normal file
@@ -0,0 +1,652 @@
|
||||
/*-
|
||||
* Copyright 2005-2016 Colin Percival
|
||||
* Copyright 2016-2018,2021 Alexander Peslyak
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "insecure_memzero.h"
|
||||
#include "sysendian.h"
|
||||
|
||||
#include "sha256.h"
|
||||
|
||||
#ifdef __ICC
|
||||
/* Miscompile with icc 14.0.0 (at least), so don't use restrict there */
|
||||
#define restrict
|
||||
#elif __STDC_VERSION__ >= 199901L
|
||||
/* Have restrict */
|
||||
#elif defined(__GNUC__)
|
||||
#define restrict __restrict
|
||||
#else
|
||||
#define restrict
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Encode a length len*2 vector of (uint32_t) into a length len*8 vector of
|
||||
* (uint8_t) in big-endian form.
|
||||
*/
|
||||
static void
|
||||
be32enc_vect(uint8_t * dst, const uint32_t * src, size_t len)
|
||||
{
|
||||
|
||||
/* Encode vector, two words at a time. */
|
||||
do {
|
||||
be32enc(&dst[0], src[0]);
|
||||
be32enc(&dst[4], src[1]);
|
||||
src += 2;
|
||||
dst += 8;
|
||||
} while (--len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a big-endian length len*8 vector of (uint8_t) into a length
|
||||
* len*2 vector of (uint32_t).
|
||||
*/
|
||||
static void
|
||||
be32dec_vect(uint32_t * dst, const uint8_t * src, size_t len)
|
||||
{
|
||||
|
||||
/* Decode vector, two words at a time. */
|
||||
do {
|
||||
dst[0] = be32dec(&src[0]);
|
||||
dst[1] = be32dec(&src[4]);
|
||||
src += 8;
|
||||
dst += 2;
|
||||
} while (--len);
|
||||
}
|
||||
|
||||
/* SHA256 round constants. */
|
||||
static const uint32_t Krnd[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
/* Elementary functions used by SHA256 */
|
||||
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
|
||||
#if 1 /* Explicit caching/reuse of common subexpression between rounds */
|
||||
#define Maj(x, y, z) (y ^ ((x_xor_y = x ^ y) & y_xor_z))
|
||||
#else /* Let the compiler cache/reuse or not */
|
||||
#define Maj(x, y, z) (y ^ ((x ^ y) & (y ^ z)))
|
||||
#endif
|
||||
#define SHR(x, n) (x >> n)
|
||||
#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
|
||||
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
|
||||
#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
|
||||
|
||||
/* SHA256 round function */
|
||||
#define RND(a, b, c, d, e, f, g, h, k) \
|
||||
h += S1(e) + Ch(e, f, g) + k; \
|
||||
d += h; \
|
||||
h += S0(a) + Maj(a, b, c); \
|
||||
y_xor_z = x_xor_y;
|
||||
|
||||
/* Adjusted round function for rotating state */
|
||||
#define RNDr(S, W, i, ii) \
|
||||
RND(S[(64 - i) % 8], S[(65 - i) % 8], \
|
||||
S[(66 - i) % 8], S[(67 - i) % 8], \
|
||||
S[(68 - i) % 8], S[(69 - i) % 8], \
|
||||
S[(70 - i) % 8], S[(71 - i) % 8], \
|
||||
W[i + ii] + Krnd[i + ii])
|
||||
|
||||
/* Message schedule computation */
|
||||
#define MSCH(W, ii, i) \
|
||||
W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
|
||||
|
||||
/*
|
||||
* SHA256 block compression function. The 256-bit state is transformed via
|
||||
* the 512-bit input block to produce a new state.
|
||||
*/
|
||||
static void
|
||||
SHA256_Transform(uint32_t state[static restrict 8],
|
||||
const uint8_t block[static restrict 64],
|
||||
uint32_t W[static restrict 64], uint32_t S[static restrict 8])
|
||||
{
|
||||
int i;
|
||||
|
||||
/* 1. Prepare the first part of the message schedule W. */
|
||||
be32dec_vect(W, block, 8);
|
||||
|
||||
/* 2. Initialize working variables. */
|
||||
memcpy(S, state, 32);
|
||||
|
||||
/* 3. Mix. */
|
||||
for (i = 0; i < 64; i += 16) {
|
||||
uint32_t x_xor_y, y_xor_z = S[(65 - i) % 8] ^ S[(66 - i) % 8];
|
||||
RNDr(S, W, 0, i);
|
||||
RNDr(S, W, 1, i);
|
||||
RNDr(S, W, 2, i);
|
||||
RNDr(S, W, 3, i);
|
||||
RNDr(S, W, 4, i);
|
||||
RNDr(S, W, 5, i);
|
||||
RNDr(S, W, 6, i);
|
||||
RNDr(S, W, 7, i);
|
||||
RNDr(S, W, 8, i);
|
||||
RNDr(S, W, 9, i);
|
||||
RNDr(S, W, 10, i);
|
||||
RNDr(S, W, 11, i);
|
||||
RNDr(S, W, 12, i);
|
||||
RNDr(S, W, 13, i);
|
||||
RNDr(S, W, 14, i);
|
||||
RNDr(S, W, 15, i);
|
||||
|
||||
if (i == 48)
|
||||
break;
|
||||
MSCH(W, 0, i);
|
||||
MSCH(W, 1, i);
|
||||
MSCH(W, 2, i);
|
||||
MSCH(W, 3, i);
|
||||
MSCH(W, 4, i);
|
||||
MSCH(W, 5, i);
|
||||
MSCH(W, 6, i);
|
||||
MSCH(W, 7, i);
|
||||
MSCH(W, 8, i);
|
||||
MSCH(W, 9, i);
|
||||
MSCH(W, 10, i);
|
||||
MSCH(W, 11, i);
|
||||
MSCH(W, 12, i);
|
||||
MSCH(W, 13, i);
|
||||
MSCH(W, 14, i);
|
||||
MSCH(W, 15, i);
|
||||
}
|
||||
|
||||
/* 4. Mix local working variables into global state. */
|
||||
state[0] += S[0];
|
||||
state[1] += S[1];
|
||||
state[2] += S[2];
|
||||
state[3] += S[3];
|
||||
state[4] += S[4];
|
||||
state[5] += S[5];
|
||||
state[6] += S[6];
|
||||
state[7] += S[7];
|
||||
}
|
||||
|
||||
static const uint8_t PAD[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* Add padding and terminating bit-count. */
|
||||
static void
|
||||
SHA256_Pad(SHA256_CTX * ctx, uint32_t tmp32[static restrict 72])
|
||||
{
|
||||
size_t r;
|
||||
|
||||
/* Figure out how many bytes we have buffered. */
|
||||
r = (ctx->count >> 3) & 0x3f;
|
||||
|
||||
/* Pad to 56 mod 64, transforming if we finish a block en route. */
|
||||
if (r < 56) {
|
||||
/* Pad to 56 mod 64. */
|
||||
memcpy(&ctx->buf[r], PAD, 56 - r);
|
||||
} else {
|
||||
/* Finish the current block and mix. */
|
||||
memcpy(&ctx->buf[r], PAD, 64 - r);
|
||||
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
|
||||
|
||||
/* The start of the final block is all zeroes. */
|
||||
memset(&ctx->buf[0], 0, 56);
|
||||
}
|
||||
|
||||
/* Add the terminating bit-count. */
|
||||
be64enc(&ctx->buf[56], ctx->count);
|
||||
|
||||
/* Mix in the final block. */
|
||||
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
|
||||
}
|
||||
|
||||
/* Magic initialization constants. */
|
||||
static const uint32_t initial_state[8] = {
|
||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
||||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
|
||||
};
|
||||
|
||||
/**
|
||||
* SHA256_Init(ctx):
|
||||
* Initialize the SHA256 context ${ctx}.
|
||||
*/
|
||||
void
|
||||
SHA256_Init(SHA256_CTX * ctx)
|
||||
{
|
||||
|
||||
/* Zero bits processed so far. */
|
||||
ctx->count = 0;
|
||||
|
||||
/* Initialize state. */
|
||||
memcpy(ctx->state, initial_state, sizeof(initial_state));
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA256_Update(ctx, in, len):
|
||||
* Input ${len} bytes from ${in} into the SHA256 context ${ctx}.
|
||||
*/
|
||||
static void
|
||||
_SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len,
|
||||
uint32_t tmp32[static restrict 72])
|
||||
{
|
||||
uint32_t r;
|
||||
const uint8_t * src = in;
|
||||
|
||||
/* Return immediately if we have nothing to do. */
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
/* Number of bytes left in the buffer from previous updates. */
|
||||
r = (ctx->count >> 3) & 0x3f;
|
||||
|
||||
/* Update number of bits. */
|
||||
ctx->count += (uint64_t)(len) << 3;
|
||||
|
||||
/* Handle the case where we don't need to perform any transforms. */
|
||||
if (len < 64 - r) {
|
||||
memcpy(&ctx->buf[r], src, len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finish the current block. */
|
||||
memcpy(&ctx->buf[r], src, 64 - r);
|
||||
SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);
|
||||
src += 64 - r;
|
||||
len -= 64 - r;
|
||||
|
||||
/* Perform complete blocks. */
|
||||
while (len >= 64) {
|
||||
SHA256_Transform(ctx->state, src, &tmp32[0], &tmp32[64]);
|
||||
src += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Copy left over data into buffer. */
|
||||
memcpy(ctx->buf, src, len);
|
||||
}
|
||||
|
||||
/* Wrapper function for intermediate-values sanitization. */
|
||||
void
|
||||
SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len)
|
||||
{
|
||||
uint32_t tmp32[72];
|
||||
|
||||
/* Call the real function. */
|
||||
_SHA256_Update(ctx, in, len, tmp32);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(tmp32, 288);
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA256_Final(digest, ctx):
|
||||
* Output the SHA256 hash of the data input to the context ${ctx} into the
|
||||
* buffer ${digest}.
|
||||
*/
|
||||
static void
|
||||
_SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx,
|
||||
uint32_t tmp32[static restrict 72])
|
||||
{
|
||||
|
||||
/* Add padding. */
|
||||
SHA256_Pad(ctx, tmp32);
|
||||
|
||||
/* Write the hash. */
|
||||
be32enc_vect(digest, ctx->state, 4);
|
||||
}
|
||||
|
||||
/* Wrapper function for intermediate-values sanitization. */
|
||||
void
|
||||
SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx)
|
||||
{
|
||||
uint32_t tmp32[72];
|
||||
|
||||
/* Call the real function. */
|
||||
_SHA256_Final(digest, ctx, tmp32);
|
||||
|
||||
/* Clear the context state. */
|
||||
insecure_memzero(ctx, sizeof(SHA256_CTX));
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(tmp32, 288);
|
||||
}
|
||||
|
||||
/**
|
||||
* SHA256_Buf(in, len, digest):
|
||||
* Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}.
|
||||
*/
|
||||
void
|
||||
SHA256_Buf(const void * in, size_t len, uint8_t digest[32])
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
uint32_t tmp32[72];
|
||||
|
||||
SHA256_Init(&ctx);
|
||||
_SHA256_Update(&ctx, in, len, tmp32);
|
||||
_SHA256_Final(digest, &ctx, tmp32);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(&ctx, sizeof(SHA256_CTX));
|
||||
insecure_memzero(tmp32, 288);
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Init(ctx, K, Klen):
|
||||
* Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from
|
||||
* ${K}.
|
||||
*/
|
||||
static void
|
||||
_HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen,
|
||||
uint32_t tmp32[static restrict 72], uint8_t pad[static restrict 64],
|
||||
uint8_t khash[static restrict 32])
|
||||
{
|
||||
const uint8_t * K = _K;
|
||||
size_t i;
|
||||
|
||||
/* If Klen > 64, the key is really SHA256(K). */
|
||||
if (Klen > 64) {
|
||||
SHA256_Init(&ctx->ictx);
|
||||
_SHA256_Update(&ctx->ictx, K, Klen, tmp32);
|
||||
_SHA256_Final(khash, &ctx->ictx, tmp32);
|
||||
K = khash;
|
||||
Klen = 32;
|
||||
}
|
||||
|
||||
/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
|
||||
SHA256_Init(&ctx->ictx);
|
||||
memset(pad, 0x36, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
_SHA256_Update(&ctx->ictx, pad, 64, tmp32);
|
||||
|
||||
/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
|
||||
SHA256_Init(&ctx->octx);
|
||||
memset(pad, 0x5c, 64);
|
||||
for (i = 0; i < Klen; i++)
|
||||
pad[i] ^= K[i];
|
||||
_SHA256_Update(&ctx->octx, pad, 64, tmp32);
|
||||
}
|
||||
|
||||
/* Wrapper function for intermediate-values sanitization. */
|
||||
void
|
||||
HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
|
||||
{
|
||||
uint32_t tmp32[72];
|
||||
uint8_t pad[64];
|
||||
uint8_t khash[32];
|
||||
|
||||
/* Call the real function. */
|
||||
_HMAC_SHA256_Init(ctx, _K, Klen, tmp32, pad, khash);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(tmp32, 288);
|
||||
insecure_memzero(khash, 32);
|
||||
insecure_memzero(pad, 64);
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Update(ctx, in, len):
|
||||
* Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.
|
||||
*/
|
||||
static void
|
||||
_HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len,
|
||||
uint32_t tmp32[static restrict 72])
|
||||
{
|
||||
|
||||
/* Feed data to the inner SHA256 operation. */
|
||||
_SHA256_Update(&ctx->ictx, in, len, tmp32);
|
||||
}
|
||||
|
||||
/* Wrapper function for intermediate-values sanitization. */
|
||||
void
|
||||
HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len)
|
||||
{
|
||||
uint32_t tmp32[72];
|
||||
|
||||
/* Call the real function. */
|
||||
_HMAC_SHA256_Update(ctx, in, len, tmp32);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(tmp32, 288);
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Final(digest, ctx):
|
||||
* Output the HMAC-SHA256 of the data input to the context ${ctx} into the
|
||||
* buffer ${digest}.
|
||||
*/
|
||||
static void
|
||||
_HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx,
|
||||
uint32_t tmp32[static restrict 72], uint8_t ihash[static restrict 32])
|
||||
{
|
||||
|
||||
/* Finish the inner SHA256 operation. */
|
||||
_SHA256_Final(ihash, &ctx->ictx, tmp32);
|
||||
|
||||
/* Feed the inner hash to the outer SHA256 operation. */
|
||||
_SHA256_Update(&ctx->octx, ihash, 32, tmp32);
|
||||
|
||||
/* Finish the outer SHA256 operation. */
|
||||
_SHA256_Final(digest, &ctx->octx, tmp32);
|
||||
}
|
||||
|
||||
/* Wrapper function for intermediate-values sanitization. */
|
||||
void
|
||||
HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx)
|
||||
{
|
||||
uint32_t tmp32[72];
|
||||
uint8_t ihash[32];
|
||||
|
||||
/* Call the real function. */
|
||||
_HMAC_SHA256_Final(digest, ctx, tmp32, ihash);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(tmp32, 288);
|
||||
insecure_memzero(ihash, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Buf(K, Klen, in, len, digest):
|
||||
* Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of
|
||||
* length ${Klen}, and write the result to ${digest}.
|
||||
*/
|
||||
void
|
||||
HMAC_SHA256_Buf(const void * K, size_t Klen, const void * in, size_t len,
|
||||
uint8_t digest[32])
|
||||
{
|
||||
HMAC_SHA256_CTX ctx;
|
||||
uint32_t tmp32[72];
|
||||
uint8_t tmp8[96];
|
||||
|
||||
_HMAC_SHA256_Init(&ctx, K, Klen, tmp32, &tmp8[0], &tmp8[64]);
|
||||
_HMAC_SHA256_Update(&ctx, in, len, tmp32);
|
||||
_HMAC_SHA256_Final(digest, &ctx, tmp32, &tmp8[0]);
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(&ctx, sizeof(HMAC_SHA256_CTX));
|
||||
insecure_memzero(tmp32, 288);
|
||||
insecure_memzero(tmp8, 96);
|
||||
}
|
||||
|
||||
/* Add padding and terminating bit-count, but don't invoke Transform yet. */
|
||||
static int
|
||||
SHA256_Pad_Almost(SHA256_CTX * ctx, uint8_t len[static restrict 8],
|
||||
uint32_t tmp32[static restrict 72])
|
||||
{
|
||||
uint32_t r;
|
||||
|
||||
r = (ctx->count >> 3) & 0x3f;
|
||||
if (r >= 56)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Convert length to a vector of bytes -- we do this now rather
|
||||
* than later because the length will change after we pad.
|
||||
*/
|
||||
be64enc(len, ctx->count);
|
||||
|
||||
/* Add 1--56 bytes so that the resulting length is 56 mod 64. */
|
||||
_SHA256_Update(ctx, PAD, 56 - r, tmp32);
|
||||
|
||||
/* Add the terminating bit-count. */
|
||||
ctx->buf[63] = len[7];
|
||||
_SHA256_Update(ctx, len, 7, tmp32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
|
||||
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
|
||||
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
|
||||
*/
|
||||
void
|
||||
PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
|
||||
size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
|
||||
{
|
||||
HMAC_SHA256_CTX Phctx, PShctx, hctx;
|
||||
uint32_t tmp32[72];
|
||||
union {
|
||||
uint8_t tmp8[96];
|
||||
uint32_t state[8];
|
||||
} u;
|
||||
size_t i;
|
||||
uint8_t ivec[4];
|
||||
uint8_t U[32];
|
||||
uint8_t T[32];
|
||||
uint64_t j;
|
||||
int k;
|
||||
size_t clen;
|
||||
|
||||
/* Sanity-check. */
|
||||
assert(dkLen <= 32 * (size_t)(UINT32_MAX));
|
||||
|
||||
if (c == 1 && (dkLen & 31) == 0 && (saltlen & 63) <= 51) {
|
||||
uint32_t oldcount;
|
||||
uint8_t * ivecp;
|
||||
|
||||
/* Compute HMAC state after processing P and S. */
|
||||
_HMAC_SHA256_Init(&hctx, passwd, passwdlen,
|
||||
tmp32, &u.tmp8[0], &u.tmp8[64]);
|
||||
_HMAC_SHA256_Update(&hctx, salt, saltlen, tmp32);
|
||||
|
||||
/* Prepare ictx padding. */
|
||||
oldcount = hctx.ictx.count & (0x3f << 3);
|
||||
_HMAC_SHA256_Update(&hctx, "\0\0\0", 4, tmp32);
|
||||
if ((hctx.ictx.count & (0x3f << 3)) < oldcount ||
|
||||
SHA256_Pad_Almost(&hctx.ictx, u.tmp8, tmp32))
|
||||
goto generic; /* Can't happen due to saltlen check */
|
||||
ivecp = hctx.ictx.buf + (oldcount >> 3);
|
||||
|
||||
/* Prepare octx padding. */
|
||||
hctx.octx.count += 32 << 3;
|
||||
SHA256_Pad_Almost(&hctx.octx, u.tmp8, tmp32);
|
||||
|
||||
/* Iterate through the blocks. */
|
||||
for (i = 0; i * 32 < dkLen; i++) {
|
||||
/* Generate INT(i + 1). */
|
||||
be32enc(ivecp, (uint32_t)(i + 1));
|
||||
|
||||
/* Compute U_1 = PRF(P, S || INT(i)). */
|
||||
memcpy(u.state, hctx.ictx.state, sizeof(u.state));
|
||||
SHA256_Transform(u.state, hctx.ictx.buf,
|
||||
&tmp32[0], &tmp32[64]);
|
||||
be32enc_vect(hctx.octx.buf, u.state, 4);
|
||||
memcpy(u.state, hctx.octx.state, sizeof(u.state));
|
||||
SHA256_Transform(u.state, hctx.octx.buf,
|
||||
&tmp32[0], &tmp32[64]);
|
||||
be32enc_vect(&buf[i * 32], u.state, 4);
|
||||
}
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
generic:
|
||||
/* Compute HMAC state after processing P. */
|
||||
_HMAC_SHA256_Init(&Phctx, passwd, passwdlen,
|
||||
tmp32, &u.tmp8[0], &u.tmp8[64]);
|
||||
|
||||
/* Compute HMAC state after processing P and S. */
|
||||
memcpy(&PShctx, &Phctx, sizeof(HMAC_SHA256_CTX));
|
||||
_HMAC_SHA256_Update(&PShctx, salt, saltlen, tmp32);
|
||||
|
||||
/* Iterate through the blocks. */
|
||||
for (i = 0; i * 32 < dkLen; i++) {
|
||||
/* Generate INT(i + 1). */
|
||||
be32enc(ivec, (uint32_t)(i + 1));
|
||||
|
||||
/* Compute U_1 = PRF(P, S || INT(i)). */
|
||||
memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
|
||||
_HMAC_SHA256_Update(&hctx, ivec, 4, tmp32);
|
||||
_HMAC_SHA256_Final(T, &hctx, tmp32, u.tmp8);
|
||||
|
||||
if (c > 1) {
|
||||
/* T_i = U_1 ... */
|
||||
memcpy(U, T, 32);
|
||||
|
||||
for (j = 2; j <= c; j++) {
|
||||
/* Compute U_j. */
|
||||
memcpy(&hctx, &Phctx, sizeof(HMAC_SHA256_CTX));
|
||||
_HMAC_SHA256_Update(&hctx, U, 32, tmp32);
|
||||
_HMAC_SHA256_Final(U, &hctx, tmp32, u.tmp8);
|
||||
|
||||
/* ... xor U_j ... */
|
||||
for (k = 0; k < 32; k++)
|
||||
T[k] ^= U[k];
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy as many bytes as necessary into buf. */
|
||||
clen = dkLen - i * 32;
|
||||
if (clen > 32)
|
||||
clen = 32;
|
||||
memcpy(&buf[i * 32], T, clen);
|
||||
}
|
||||
|
||||
/* Clean the stack. */
|
||||
insecure_memzero(&Phctx, sizeof(HMAC_SHA256_CTX));
|
||||
insecure_memzero(&PShctx, sizeof(HMAC_SHA256_CTX));
|
||||
insecure_memzero(U, 32);
|
||||
insecure_memzero(T, 32);
|
||||
|
||||
cleanup:
|
||||
insecure_memzero(&hctx, sizeof(HMAC_SHA256_CTX));
|
||||
insecure_memzero(tmp32, 288);
|
||||
insecure_memzero(&u, sizeof(u));
|
||||
}
|
||||
129
brute/source/yescrypt/sha256.h
Normal file
129
brute/source/yescrypt/sha256.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/*-
|
||||
* Copyright 2005-2016 Colin Percival
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*/
|
||||
|
||||
#ifndef _SHA256_H_
|
||||
#define _SHA256_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use #defines in order to avoid namespace collisions with anyone else's
|
||||
* SHA256 code (e.g., the code in OpenSSL).
|
||||
*/
|
||||
#define SHA256_Init libcperciva_SHA256_Init
|
||||
#define SHA256_Update libcperciva_SHA256_Update
|
||||
#define SHA256_Final libcperciva_SHA256_Final
|
||||
#define SHA256_Buf libcperciva_SHA256_Buf
|
||||
#define SHA256_CTX libcperciva_SHA256_CTX
|
||||
#define HMAC_SHA256_Init libcperciva_HMAC_SHA256_Init
|
||||
#define HMAC_SHA256_Update libcperciva_HMAC_SHA256_Update
|
||||
#define HMAC_SHA256_Final libcperciva_HMAC_SHA256_Final
|
||||
#define HMAC_SHA256_Buf libcperciva_HMAC_SHA256_Buf
|
||||
#define HMAC_SHA256_CTX libcperciva_HMAC_SHA256_CTX
|
||||
|
||||
/* Context structure for SHA256 operations. */
|
||||
typedef struct {
|
||||
uint32_t state[8];
|
||||
uint64_t count;
|
||||
uint8_t buf[64];
|
||||
} SHA256_CTX;
|
||||
|
||||
/**
|
||||
* SHA256_Init(ctx):
|
||||
* Initialize the SHA256 context ${ctx}.
|
||||
*/
|
||||
void SHA256_Init(SHA256_CTX *);
|
||||
|
||||
/**
|
||||
* SHA256_Update(ctx, in, len):
|
||||
* Input ${len} bytes from ${in} into the SHA256 context ${ctx}.
|
||||
*/
|
||||
void SHA256_Update(SHA256_CTX *, const void *, size_t);
|
||||
|
||||
/**
|
||||
* SHA256_Final(digest, ctx):
|
||||
* Output the SHA256 hash of the data input to the context ${ctx} into the
|
||||
* buffer ${digest}.
|
||||
*/
|
||||
void SHA256_Final(uint8_t[32], SHA256_CTX *);
|
||||
|
||||
/**
|
||||
* SHA256_Buf(in, len, digest):
|
||||
* Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}.
|
||||
*/
|
||||
void SHA256_Buf(const void *, size_t, uint8_t[32]);
|
||||
|
||||
/* Context structure for HMAC-SHA256 operations. */
|
||||
typedef struct {
|
||||
SHA256_CTX ictx;
|
||||
SHA256_CTX octx;
|
||||
} HMAC_SHA256_CTX;
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Init(ctx, K, Klen):
|
||||
* Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from
|
||||
* ${K}.
|
||||
*/
|
||||
void HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t);
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Update(ctx, in, len):
|
||||
* Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.
|
||||
*/
|
||||
void HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t);
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Final(digest, ctx):
|
||||
* Output the HMAC-SHA256 of the data input to the context ${ctx} into the
|
||||
* buffer ${digest}.
|
||||
*/
|
||||
void HMAC_SHA256_Final(uint8_t[32], HMAC_SHA256_CTX *);
|
||||
|
||||
/**
|
||||
* HMAC_SHA256_Buf(K, Klen, in, len, digest):
|
||||
* Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of
|
||||
* length ${Klen}, and write the result to ${digest}.
|
||||
*/
|
||||
void HMAC_SHA256_Buf(const void *, size_t, const void *, size_t, uint8_t[32]);
|
||||
|
||||
/**
|
||||
* PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
|
||||
* Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
|
||||
* write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
|
||||
*/
|
||||
void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,
|
||||
uint64_t, uint8_t *, size_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_SHA256_H_ */
|
||||
122
brute/source/yescrypt/sysendian.h
Normal file
122
brute/source/yescrypt/sysendian.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/*-
|
||||
* Copyright 2007-2014 Colin Percival
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*/
|
||||
|
||||
#ifndef _SYSENDIAN_H_
|
||||
#define _SYSENDIAN_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Avoid namespace collisions with BSD <sys/endian.h>. */
|
||||
#define be32dec libcperciva_be32dec
|
||||
#define be32enc libcperciva_be32enc
|
||||
#define be64enc libcperciva_be64enc
|
||||
#define le32dec libcperciva_le32dec
|
||||
#define le32enc libcperciva_le32enc
|
||||
#define le64dec libcperciva_le64dec
|
||||
#define le64enc libcperciva_le64enc
|
||||
|
||||
static inline uint32_t
|
||||
be32dec(const void * pp)
|
||||
{
|
||||
const uint8_t * p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
|
||||
((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
|
||||
}
|
||||
|
||||
static inline void
|
||||
be32enc(void * pp, uint32_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[3] = x & 0xff;
|
||||
p[2] = (x >> 8) & 0xff;
|
||||
p[1] = (x >> 16) & 0xff;
|
||||
p[0] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static inline void
|
||||
be64enc(void * pp, uint64_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[7] = x & 0xff;
|
||||
p[6] = (x >> 8) & 0xff;
|
||||
p[5] = (x >> 16) & 0xff;
|
||||
p[4] = (x >> 24) & 0xff;
|
||||
p[3] = (x >> 32) & 0xff;
|
||||
p[2] = (x >> 40) & 0xff;
|
||||
p[1] = (x >> 48) & 0xff;
|
||||
p[0] = (x >> 56) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
le32dec(const void * pp)
|
||||
{
|
||||
const uint8_t * p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +
|
||||
((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));
|
||||
}
|
||||
|
||||
static inline void
|
||||
le32enc(void * pp, uint32_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
p[2] = (x >> 16) & 0xff;
|
||||
p[3] = (x >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
le64dec(const void * pp)
|
||||
{
|
||||
const uint8_t * p = (uint8_t const *)pp;
|
||||
|
||||
return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +
|
||||
((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +
|
||||
((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +
|
||||
((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));
|
||||
}
|
||||
|
||||
static inline void
|
||||
le64enc(void * pp, uint64_t x)
|
||||
{
|
||||
uint8_t * p = (uint8_t *)pp;
|
||||
|
||||
p[0] = x & 0xff;
|
||||
p[1] = (x >> 8) & 0xff;
|
||||
p[2] = (x >> 16) & 0xff;
|
||||
p[3] = (x >> 24) & 0xff;
|
||||
p[4] = (x >> 32) & 0xff;
|
||||
p[5] = (x >> 40) & 0xff;
|
||||
p[6] = (x >> 48) & 0xff;
|
||||
p[7] = (x >> 56) & 0xff;
|
||||
}
|
||||
|
||||
#endif /* !_SYSENDIAN_H_ */
|
||||
405
brute/source/yescrypt/userom.c
Normal file
405
brute/source/yescrypt/userom.c
Normal file
@@ -0,0 +1,405 @@
|
||||
/*-
|
||||
* Copyright 2013-2018 Alexander Peslyak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*/
|
||||
|
||||
#define YESCRYPT_FLAGS YESCRYPT_DEFAULTS
|
||||
//#define YESCRYPT_FLAGS YESCRYPT_WORM
|
||||
//#define YESCRYPT_FLAGS 0
|
||||
|
||||
#define ROM_SHM_KEY 0x7965730a
|
||||
|
||||
//#define DISABLE_ROM
|
||||
//#define DUMP_LOCAL
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for atoi() */
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/shm.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <sys/times.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include "yescrypt.h"
|
||||
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
|
||||
#define NSAVE 1000
|
||||
|
||||
static uint64_t time_us(void)
|
||||
{
|
||||
struct timespec t;
|
||||
#ifdef CLOCK_MONOTONIC_RAW
|
||||
if (clock_gettime(CLOCK_MONOTONIC_RAW, &t))
|
||||
return 0;
|
||||
#else
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &t))
|
||||
return 0;
|
||||
#endif
|
||||
return 1 + (uint64_t)t.tv_sec * 1000000 + t.tv_nsec / 1000;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, const char * const *argv)
|
||||
{
|
||||
#if 0
|
||||
uint64_t rom_bytes = 112 * (1024ULL*1024*1024);
|
||||
uint64_t ram_bytes = 1 * (1024ULL*1024);
|
||||
#else
|
||||
uint64_t rom_bytes = 3 * (1024ULL*1024*1024);
|
||||
uint64_t ram_bytes = 2 * (1024ULL*1024);
|
||||
#endif
|
||||
uint32_t r, min_r;
|
||||
uint64_t NROM_log2, N_log2;
|
||||
yescrypt_shared_t shared_s;
|
||||
yescrypt_shared_t *shared = NULL;
|
||||
#ifndef DISABLE_ROM
|
||||
int shmid;
|
||||
#endif
|
||||
const char *rom_filename = NULL;
|
||||
int rom_fd;
|
||||
yescrypt_binary_t key = {.uc={
|
||||
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
|
||||
17,18,19,20,21,22,23,24,25,26,27,28,255,128,64,32}};
|
||||
|
||||
if (argc > 1)
|
||||
rom_bytes = atoi(argv[1]) * (1024ULL*1024*1024);
|
||||
if (argc > 2)
|
||||
ram_bytes = atoi(argv[2]) * (1024ULL*1024);
|
||||
if (argc > 3 && rom_bytes)
|
||||
rom_filename = argv[3];
|
||||
|
||||
r = 16;
|
||||
min_r = 9;
|
||||
if (rom_filename)
|
||||
min_r = 8 * 64;
|
||||
|
||||
NROM_log2 = 0;
|
||||
if (rom_bytes) {
|
||||
while (((rom_bytes >> NROM_log2) & 0xff) == 0)
|
||||
NROM_log2++;
|
||||
r = rom_bytes >> (7 + NROM_log2);
|
||||
while (r < min_r && NROM_log2 > 0) {
|
||||
r <<= 1;
|
||||
NROM_log2--;
|
||||
}
|
||||
rom_bytes = (uint64_t)r << (7 + NROM_log2);
|
||||
}
|
||||
|
||||
N_log2 = 0;
|
||||
while (((uint64_t)r << (7 + N_log2)) < ram_bytes)
|
||||
N_log2++;
|
||||
ram_bytes = (uint64_t)r << (7 + N_log2);
|
||||
|
||||
printf("r=%u N=2^%u NROM=2^%u\n", r,
|
||||
(unsigned int)N_log2, (unsigned int)NROM_log2);
|
||||
|
||||
#ifdef DISABLE_ROM
|
||||
rom_bytes = 0;
|
||||
#endif
|
||||
|
||||
printf("Will use %.2f KiB ROM\n", rom_bytes / 1024.0);
|
||||
printf(" %.2f KiB RAM\n", ram_bytes / 1024.0);
|
||||
|
||||
#ifndef DISABLE_ROM
|
||||
if (rom_filename) {
|
||||
rom_fd = open(rom_filename, O_RDONLY);
|
||||
if (rom_fd < 0) {
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int flags =
|
||||
#ifdef MAP_NOCORE
|
||||
MAP_NOCORE |
|
||||
#endif
|
||||
#ifdef MAP_HUGETLB
|
||||
MAP_HUGETLB |
|
||||
#endif
|
||||
MAP_SHARED;
|
||||
void *p = mmap(NULL, rom_bytes, PROT_READ, flags, rom_fd, 0);
|
||||
#ifdef MAP_HUGETLB
|
||||
if (p == MAP_FAILED)
|
||||
p = mmap(NULL, rom_bytes, PROT_READ,
|
||||
flags & ~MAP_HUGETLB, rom_fd, 0);
|
||||
#endif
|
||||
if (p == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
close(rom_fd);
|
||||
return 1;
|
||||
}
|
||||
close(rom_fd);
|
||||
|
||||
shared = &shared_s;
|
||||
shared->base = shared->aligned = p;
|
||||
shared->aligned_size = rom_bytes;
|
||||
} else if (rom_bytes) {
|
||||
shared = &shared_s;
|
||||
shared->aligned_size = rom_bytes;
|
||||
shmid = shmget(ROM_SHM_KEY, shared->aligned_size, 0);
|
||||
if (shmid == -1) {
|
||||
perror("shmget");
|
||||
return 1;
|
||||
}
|
||||
|
||||
shared->base = shared->aligned = shmat(shmid, NULL, SHM_RDONLY);
|
||||
if (shared->base == (void *)-1) {
|
||||
perror("shmat");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
yescrypt_local_t local;
|
||||
const uint8_t *setting;
|
||||
|
||||
if (yescrypt_init_local(&local)) {
|
||||
puts("yescrypt_init_local() FAILED");
|
||||
return 1;
|
||||
}
|
||||
|
||||
yescrypt_params_t params = {
|
||||
.flags = YESCRYPT_FLAGS,
|
||||
.N = (uint64_t)1 << N_log2,
|
||||
.NROM = NROM_log2 ? ((uint64_t)1 << NROM_log2) : 0,
|
||||
.r = r,
|
||||
.p = 1 };
|
||||
setting = yescrypt_encode_params(¶ms,
|
||||
(const uint8_t *)"WZaPV7LSUEKMo34.", 16);
|
||||
|
||||
{
|
||||
uint8_t hash[128];
|
||||
if (!yescrypt_r(shared, &local,
|
||||
(const uint8_t *)"pleaseletmein", 13, setting, NULL,
|
||||
hash, sizeof(hash))) {
|
||||
puts("yescrypt_r() FAILED");
|
||||
return 1;
|
||||
}
|
||||
printf("Plaintext: '%s'\n", (char *)hash);
|
||||
if (!yescrypt_r(shared, &local,
|
||||
(const uint8_t *)"pleaseletmein", 13, setting, &key,
|
||||
hash, sizeof(hash))) {
|
||||
puts("yescrypt_r() FAILED");
|
||||
return 1;
|
||||
}
|
||||
printf("Encrypted: '%s'\n", (char *)hash);
|
||||
}
|
||||
|
||||
#ifdef DUMP_LOCAL
|
||||
#if 0
|
||||
fwrite(local.aligned, local.aligned_size, 1, stderr);
|
||||
#else
|
||||
/* Skip B, dump only V */
|
||||
if (local.aligned_size >= ram_bytes + 128 * r)
|
||||
fwrite((char *)local.aligned + 128 * r, ram_bytes,
|
||||
1, stderr);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
puts("Benchmarking 1 thread ...");
|
||||
|
||||
clock_t clk_tck = sysconf(_SC_CLK_TCK);
|
||||
struct tms start_tms, end_tms;
|
||||
clock_t start = times(&start_tms), end;
|
||||
unsigned int i, n;
|
||||
unsigned long long count;
|
||||
#ifdef _OPENMP
|
||||
char save[NSAVE][128];
|
||||
unsigned int nsave = 0;
|
||||
#endif
|
||||
unsigned int seed = start * 1812433253U;
|
||||
|
||||
n = 1;
|
||||
count = 0;
|
||||
do {
|
||||
for (i = 0; i < n; i++) {
|
||||
unsigned int j = count + i;
|
||||
char p[32];
|
||||
uint8_t hash[128];
|
||||
snprintf(p, sizeof(p), "%u", seed + j);
|
||||
#ifdef _OPENMP
|
||||
const uint8_t *h =
|
||||
#endif
|
||||
yescrypt_r(shared, &local,
|
||||
(const uint8_t *)p, strlen(p),
|
||||
setting, &key, hash, sizeof(hash));
|
||||
#ifdef _OPENMP
|
||||
if (j < NSAVE) {
|
||||
save[j][0] = 0;
|
||||
strncat(save[j], (char *)h,
|
||||
sizeof(save[j]) - 1);
|
||||
nsave = j;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
count += n;
|
||||
|
||||
end = times(&end_tms);
|
||||
n <<= 1;
|
||||
} while (end - start < clk_tck * 2);
|
||||
|
||||
clock_t start_v = start_tms.tms_utime + start_tms.tms_stime +
|
||||
start_tms.tms_cutime + start_tms.tms_cstime;
|
||||
clock_t end_v = end_tms.tms_utime + end_tms.tms_stime +
|
||||
end_tms.tms_cutime + end_tms.tms_cstime;
|
||||
|
||||
printf("%llu c/s real, %llu c/s virtual "
|
||||
"(%llu hashes in %.2f seconds)\n",
|
||||
count * clk_tck / (end - start),
|
||||
count * clk_tck / (end_v - start_v),
|
||||
count, (double)(end - start) / clk_tck);
|
||||
|
||||
#ifdef _OPENMP
|
||||
unsigned int nt = omp_get_max_threads();
|
||||
|
||||
printf("Benchmarking %u thread%s ...\n",
|
||||
nt, nt == 1 ? "" : "s");
|
||||
|
||||
typedef struct {
|
||||
yescrypt_local_t local;
|
||||
uint64_t min, max, total;
|
||||
} thread_data_s;
|
||||
union {
|
||||
thread_data_s s;
|
||||
uint8_t cachelines[2][64]; /* avoid false sharing */
|
||||
} thread_data[nt]; /* tricky to align this when on stack */
|
||||
|
||||
unsigned int t;
|
||||
for (t = 0; t < nt; t++) {
|
||||
thread_data_s *td = &thread_data[t].s;
|
||||
if (yescrypt_init_local(&td->local)) {
|
||||
puts("yescrypt_init_local() FAILED");
|
||||
return 1;
|
||||
}
|
||||
td->min = ~(uint64_t)0; td->max = 0; td->total = 0;
|
||||
}
|
||||
|
||||
unsigned long long count1 = count, count_restart = 0;
|
||||
|
||||
if (!geteuid()) {
|
||||
puts("Running as root, so trying to set SCHED_RR");
|
||||
#pragma omp parallel
|
||||
{
|
||||
struct sched_param param = { .sched_priority = 1 };
|
||||
if (sched_setscheduler(getpid(), SCHED_RR, ¶m))
|
||||
perror("sched_setscheduler");
|
||||
}
|
||||
}
|
||||
|
||||
start = times(&start_tms);
|
||||
|
||||
n = count * omp_get_max_threads();
|
||||
count = 0;
|
||||
do {
|
||||
#pragma omp parallel for default(none) private(i) shared(n, shared, thread_data, setting, seed, count, save, nsave, key)
|
||||
for (i = 0; i < n; i++) {
|
||||
unsigned int j = count + i;
|
||||
char p[32];
|
||||
uint8_t hash[128];
|
||||
snprintf(p, sizeof(p), "%u", seed + j);
|
||||
thread_data_s *td = &thread_data[omp_get_thread_num()].s;
|
||||
uint64_t start1 = time_us();
|
||||
#if 1
|
||||
const char *h = (const char *)yescrypt_r(
|
||||
shared, &td->local,
|
||||
(const uint8_t *)p, strlen(p),
|
||||
setting, &key, hash, sizeof(hash));
|
||||
#else
|
||||
yescrypt_local_t local;
|
||||
yescrypt_init_local(&local);
|
||||
const char *h = (const char *)yescrypt_r(
|
||||
shared, &local,
|
||||
(const uint8_t *)p, strlen(p),
|
||||
setting, &key, hash, sizeof(hash));
|
||||
yescrypt_free_local(&local);
|
||||
#endif
|
||||
uint64_t end1 = time_us();
|
||||
if (end1 < start1)
|
||||
end1 = start1;
|
||||
uint64_t diff1 = end1 - start1;
|
||||
td->total += diff1;
|
||||
if (diff1 < td->min)
|
||||
td->min = diff1;
|
||||
if (diff1 > td->max)
|
||||
td->max = diff1;
|
||||
if (j < nsave && strcmp(save[j], h)) {
|
||||
#pragma omp critical
|
||||
printf("Mismatch at %u, %s != %s\n",
|
||||
j, save[j], h);
|
||||
}
|
||||
}
|
||||
|
||||
count += n;
|
||||
if ((count - n) < count1 && count >= count1) {
|
||||
/* Disregard our repeat of single thread's results (could be partially cached
|
||||
* by same core, but OTOH other cores not yet warmed up to full clock rate). */
|
||||
start = times(&start_tms);
|
||||
count_restart = count;
|
||||
for (t = 0; t < nt; t++) {
|
||||
thread_data_s *td = &thread_data[t].s;
|
||||
td->min = ~(uint64_t)0; td->max = 0; td->total = 0;
|
||||
}
|
||||
} else {
|
||||
n <<= 1;
|
||||
}
|
||||
|
||||
end = times(&end_tms);
|
||||
} while (end - start < clk_tck);
|
||||
|
||||
if (!count_restart)
|
||||
puts("Didn't reach single-thread's hash count");
|
||||
count -= count_restart;
|
||||
|
||||
start_v = start_tms.tms_utime + start_tms.tms_stime +
|
||||
start_tms.tms_cutime + start_tms.tms_cstime;
|
||||
end_v = end_tms.tms_utime + end_tms.tms_stime +
|
||||
end_tms.tms_cutime + end_tms.tms_cstime;
|
||||
|
||||
printf("%llu c/s real, %llu c/s virtual "
|
||||
"(%llu hashes in %.2f seconds)\n",
|
||||
count * clk_tck / (end - start),
|
||||
count * clk_tck / (end_v - start_v),
|
||||
count, (double)(end - start) / clk_tck);
|
||||
|
||||
uint64_t min = ~(uint64_t)0, max = 0, total = 0;
|
||||
for (t = 0; t < nt; t++) {
|
||||
thread_data_s *td = &thread_data[t].s;
|
||||
total += td->total;
|
||||
if (td->min < min)
|
||||
min = td->min;
|
||||
if (td->max > max)
|
||||
max = td->max;
|
||||
}
|
||||
printf("min %.3f ms, avg %.3f ms, max %.3f ms\n",
|
||||
min / 1000.0, total / 1000.0 / count, max / 1000.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rom_filename && munmap(shared->base, rom_bytes)) {
|
||||
perror("munmap");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
703
brute/source/yescrypt/yescrypt-common.c
Normal file
703
brute/source/yescrypt/yescrypt-common.c
Normal file
@@ -0,0 +1,703 @@
|
||||
/*-
|
||||
* Copyright 2013-2018 Alexander Peslyak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "insecure_memzero.h"
|
||||
#include "sha256.h"
|
||||
|
||||
#define YESCRYPT_INTERNAL
|
||||
#include "yescrypt.h"
|
||||
|
||||
#define BYTES2CHARS(bytes) ((((bytes) * 8) + 5) / 6)
|
||||
|
||||
#define HASH_SIZE sizeof(yescrypt_binary_t) /* bytes */
|
||||
#define HASH_LEN BYTES2CHARS(HASH_SIZE) /* base-64 chars */
|
||||
|
||||
/*
|
||||
* "$y$", up to 8 params of up to 6 chars each, '$', salt
|
||||
* Alternatively, but that's smaller:
|
||||
* "$7$", 3 params encoded as 1+5+5 chars, salt
|
||||
*/
|
||||
#define PREFIX_LEN (3 + 8 * 6 + 1 + BYTES2CHARS(32))
|
||||
|
||||
static const char * const itoa64 =
|
||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
static const uint8_t atoi64_partial[77] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||
64, 64, 64, 64, 64, 64, 64,
|
||||
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
||||
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
|
||||
64, 64, 64, 64, 64, 64,
|
||||
38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
|
||||
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
|
||||
};
|
||||
|
||||
static uint8_t *encode64_uint32(uint8_t *dst, size_t dstlen,
|
||||
uint32_t src, uint32_t min)
|
||||
{
|
||||
uint32_t start = 0, end = 47, chars = 1, bits = 0;
|
||||
|
||||
if (src < min)
|
||||
return NULL;
|
||||
src -= min;
|
||||
|
||||
do {
|
||||
uint32_t count = (end + 1 - start) << bits;
|
||||
if (src < count)
|
||||
break;
|
||||
if (start >= 63)
|
||||
return NULL;
|
||||
start = end + 1;
|
||||
end = start + (62 - end) / 2;
|
||||
src -= count;
|
||||
chars++;
|
||||
bits += 6;
|
||||
} while (1);
|
||||
|
||||
if (dstlen <= chars) /* require room for a NUL terminator */
|
||||
return NULL;
|
||||
|
||||
*dst++ = itoa64[start + (src >> bits)];
|
||||
|
||||
while (--chars) {
|
||||
bits -= 6;
|
||||
*dst++ = itoa64[(src >> bits) & 0x3f];
|
||||
}
|
||||
|
||||
*dst = 0; /* NUL terminate just in case */
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
static inline uint32_t atoi64(uint8_t src)
|
||||
{
|
||||
if (src >= '.' && src <= 'z')
|
||||
return atoi64_partial[src - '.'];
|
||||
|
||||
return 64;
|
||||
}
|
||||
|
||||
static const uint8_t *decode64_uint32(uint32_t *dst,
|
||||
const uint8_t *src, uint32_t min)
|
||||
{
|
||||
uint32_t start = 0, end = 47, chars = 1, bits = 0;
|
||||
uint32_t c;
|
||||
|
||||
c = atoi64(*src++);
|
||||
if (c > 63)
|
||||
goto fail;
|
||||
|
||||
*dst = min;
|
||||
while (c > end) {
|
||||
*dst += (end + 1 - start) << bits;
|
||||
start = end + 1;
|
||||
end = start + (62 - end) / 2;
|
||||
chars++;
|
||||
bits += 6;
|
||||
}
|
||||
|
||||
*dst += (c - start) << bits;
|
||||
|
||||
while (--chars) {
|
||||
c = atoi64(*src++);
|
||||
if (c > 63)
|
||||
goto fail;
|
||||
bits -= 6;
|
||||
*dst += c << bits;
|
||||
}
|
||||
|
||||
return src;
|
||||
|
||||
fail:
|
||||
*dst = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uint8_t *encode64_uint32_fixed(uint8_t *dst, size_t dstlen,
|
||||
uint32_t src, uint32_t srcbits)
|
||||
{
|
||||
uint32_t bits;
|
||||
|
||||
for (bits = 0; bits < srcbits; bits += 6) {
|
||||
if (dstlen < 2)
|
||||
return NULL;
|
||||
*dst++ = itoa64[src & 0x3f];
|
||||
dstlen--;
|
||||
src >>= 6;
|
||||
}
|
||||
|
||||
if (src || dstlen < 1)
|
||||
return NULL;
|
||||
|
||||
*dst = 0; /* NUL terminate just in case */
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
static uint8_t *encode64(uint8_t *dst, size_t dstlen,
|
||||
const uint8_t *src, size_t srclen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < srclen; ) {
|
||||
uint8_t *dnext;
|
||||
uint32_t value = 0, bits = 0;
|
||||
do {
|
||||
value |= (uint32_t)src[i++] << bits;
|
||||
bits += 8;
|
||||
} while (bits < 24 && i < srclen);
|
||||
dnext = encode64_uint32_fixed(dst, dstlen, value, bits);
|
||||
if (!dnext)
|
||||
return NULL;
|
||||
dstlen -= dnext - dst;
|
||||
dst = dnext;
|
||||
}
|
||||
|
||||
if (dstlen < 1)
|
||||
return NULL;
|
||||
|
||||
*dst = 0; /* NUL terminate just in case */
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
static const uint8_t *decode64_uint32_fixed(uint32_t *dst, uint32_t dstbits,
|
||||
const uint8_t *src)
|
||||
{
|
||||
uint32_t bits;
|
||||
|
||||
*dst = 0;
|
||||
for (bits = 0; bits < dstbits; bits += 6) {
|
||||
uint32_t c = atoi64(*src++);
|
||||
if (c > 63) {
|
||||
*dst = 0;
|
||||
return NULL;
|
||||
}
|
||||
*dst |= c << bits;
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
static const uint8_t *decode64(uint8_t *dst, size_t *dstlen,
|
||||
const uint8_t *src, size_t srclen)
|
||||
{
|
||||
size_t dstpos = 0;
|
||||
|
||||
while (dstpos <= *dstlen && srclen) {
|
||||
uint32_t value = 0, bits = 0;
|
||||
while (srclen--) {
|
||||
uint32_t c = atoi64(*src);
|
||||
if (c > 63) {
|
||||
srclen = 0;
|
||||
break;
|
||||
}
|
||||
src++;
|
||||
value |= c << bits;
|
||||
bits += 6;
|
||||
if (bits >= 24)
|
||||
break;
|
||||
}
|
||||
if (!bits)
|
||||
break;
|
||||
if (bits < 12) /* must have at least one full byte */
|
||||
goto fail;
|
||||
while (dstpos++ < *dstlen) {
|
||||
*dst++ = value;
|
||||
value >>= 8;
|
||||
bits -= 8;
|
||||
if (bits < 8) { /* 2 or 4 */
|
||||
if (value) /* must be 0 */
|
||||
goto fail;
|
||||
bits = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bits)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!srclen && dstpos <= *dstlen) {
|
||||
*dstlen = dstpos;
|
||||
return src;
|
||||
}
|
||||
|
||||
fail:
|
||||
*dstlen = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef enum { ENC = 1, DEC = -1 } encrypt_dir_t;
|
||||
|
||||
static void memxor(unsigned char *dst, unsigned char *src, size_t size)
|
||||
{
|
||||
while (size--)
|
||||
*dst++ ^= *src++;
|
||||
}
|
||||
|
||||
static void encrypt(unsigned char *data, size_t datalen,
|
||||
const yescrypt_binary_t *key, encrypt_dir_t dir)
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
unsigned char f[32 + 4];
|
||||
size_t halflen, which;
|
||||
unsigned char mask, round, target;
|
||||
|
||||
if (!datalen)
|
||||
return;
|
||||
if (datalen > 64)
|
||||
datalen = 64;
|
||||
|
||||
halflen = datalen >> 1;
|
||||
|
||||
which = 0; /* offset to half we are working on (0 or halflen) */
|
||||
mask = 0x0f; /* current half's extra nibble mask if datalen is odd */
|
||||
|
||||
round = 0;
|
||||
target = 5; /* 6 rounds due to Jacques Patarin's CRYPTO 2004 paper */
|
||||
|
||||
if (dir == DEC) {
|
||||
which = halflen; /* even round count, so swap the halves */
|
||||
mask ^= 0xff;
|
||||
|
||||
round = target;
|
||||
target = 0;
|
||||
}
|
||||
|
||||
f[32] = 0;
|
||||
f[33] = sizeof(*key);
|
||||
f[34] = datalen;
|
||||
|
||||
do {
|
||||
SHA256_Init(&ctx);
|
||||
f[35] = round;
|
||||
SHA256_Update(&ctx, &f[32], 4);
|
||||
SHA256_Update(&ctx, key, sizeof(*key));
|
||||
SHA256_Update(&ctx, &data[which], halflen);
|
||||
if (datalen & 1) {
|
||||
f[0] = data[datalen - 1] & mask;
|
||||
SHA256_Update(&ctx, f, 1);
|
||||
}
|
||||
SHA256_Final(f, &ctx);
|
||||
which ^= halflen;
|
||||
memxor(&data[which], f, halflen);
|
||||
if (datalen & 1) {
|
||||
mask ^= 0xff;
|
||||
data[datalen - 1] ^= f[halflen] & mask;
|
||||
}
|
||||
if (round == target)
|
||||
break;
|
||||
round += dir;
|
||||
} while (1);
|
||||
|
||||
/* ctx is presumably zeroized by SHA256_Final() */
|
||||
insecure_memzero(f, sizeof(f));
|
||||
}
|
||||
|
||||
uint8_t *yescrypt_r(const yescrypt_shared_t *shared, yescrypt_local_t *local,
|
||||
const uint8_t *passwd, size_t passwdlen,
|
||||
const uint8_t *setting,
|
||||
const yescrypt_binary_t *key,
|
||||
uint8_t *buf, size_t buflen)
|
||||
{
|
||||
unsigned char saltbin[64], hashbin[32];
|
||||
const uint8_t *src, *saltstr, *salt;
|
||||
uint8_t *dst;
|
||||
size_t need, prefixlen, saltstrlen, saltlen;
|
||||
yescrypt_params_t params = { .p = 1 };
|
||||
|
||||
if (setting[0] != '$' ||
|
||||
(setting[1] != '7' && setting[1] != 'y') ||
|
||||
setting[2] != '$')
|
||||
return NULL;
|
||||
src = setting + 3;
|
||||
|
||||
if (setting[1] == '7') {
|
||||
uint32_t N_log2 = atoi64(*src++);
|
||||
if (N_log2 < 1 || N_log2 > 63)
|
||||
return NULL;
|
||||
params.N = (uint64_t)1 << N_log2;
|
||||
|
||||
src = decode64_uint32_fixed(¶ms.r, 30, src);
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
src = decode64_uint32_fixed(¶ms.p, 30, src);
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
if (key)
|
||||
return NULL;
|
||||
} else {
|
||||
uint32_t flavor, N_log2;
|
||||
|
||||
src = decode64_uint32(&flavor, src, 0);
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
if (flavor < YESCRYPT_RW) {
|
||||
params.flags = flavor;
|
||||
} else if (flavor <= YESCRYPT_RW + (YESCRYPT_RW_FLAVOR_MASK >> 2)) {
|
||||
params.flags = YESCRYPT_RW + ((flavor - YESCRYPT_RW) << 2);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src = decode64_uint32(&N_log2, src, 1);
|
||||
if (!src || N_log2 > 63)
|
||||
return NULL;
|
||||
params.N = (uint64_t)1 << N_log2;
|
||||
|
||||
src = decode64_uint32(¶ms.r, src, 1);
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
if (*src != '$') {
|
||||
uint32_t have;
|
||||
|
||||
src = decode64_uint32(&have, src, 1);
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
if (have & 1) {
|
||||
src = decode64_uint32(¶ms.p, src, 2);
|
||||
if (!src)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (have & 2) {
|
||||
src = decode64_uint32(¶ms.t, src, 1);
|
||||
if (!src)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (have & 4) {
|
||||
src = decode64_uint32(¶ms.g, src, 1);
|
||||
if (!src)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (have & 8) {
|
||||
uint32_t NROM_log2;
|
||||
src = decode64_uint32(&NROM_log2, src, 1);
|
||||
if (!src || NROM_log2 > 63)
|
||||
return NULL;
|
||||
params.NROM = (uint64_t)1 << NROM_log2;
|
||||
}
|
||||
}
|
||||
|
||||
if (*src++ != '$')
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prefixlen = src - setting;
|
||||
|
||||
saltstr = src;
|
||||
src = (uint8_t *)strrchr((char *)saltstr, '$');
|
||||
if (src)
|
||||
saltstrlen = src - saltstr;
|
||||
else
|
||||
saltstrlen = strlen((char *)saltstr);
|
||||
|
||||
if (setting[1] == '7') {
|
||||
salt = saltstr;
|
||||
saltlen = saltstrlen;
|
||||
} else {
|
||||
const uint8_t *saltend;
|
||||
|
||||
saltlen = sizeof(saltbin);
|
||||
saltend = decode64(saltbin, &saltlen, saltstr, saltstrlen);
|
||||
|
||||
if (!saltend || (size_t)(saltend - saltstr) != saltstrlen)
|
||||
goto fail;
|
||||
|
||||
salt = saltbin;
|
||||
|
||||
if (key)
|
||||
encrypt(saltbin, saltlen, key, ENC);
|
||||
}
|
||||
|
||||
need = prefixlen + saltstrlen + 1 + HASH_LEN + 1;
|
||||
if (need > buflen || need < saltstrlen)
|
||||
goto fail;
|
||||
|
||||
if (yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen,
|
||||
¶ms, hashbin, sizeof(hashbin)))
|
||||
goto fail;
|
||||
|
||||
if (key) {
|
||||
insecure_memzero(saltbin, sizeof(saltbin));
|
||||
encrypt(hashbin, sizeof(hashbin), key, ENC);
|
||||
}
|
||||
|
||||
dst = buf;
|
||||
memcpy(dst, setting, prefixlen + saltstrlen);
|
||||
dst += prefixlen + saltstrlen;
|
||||
*dst++ = '$';
|
||||
|
||||
dst = encode64(dst, buflen - (dst - buf), hashbin, sizeof(hashbin));
|
||||
insecure_memzero(hashbin, sizeof(hashbin));
|
||||
if (!dst || dst >= buf + buflen)
|
||||
return NULL;
|
||||
|
||||
*dst = 0; /* NUL termination */
|
||||
|
||||
return buf;
|
||||
|
||||
fail:
|
||||
insecure_memzero(saltbin, sizeof(saltbin));
|
||||
insecure_memzero(hashbin, sizeof(hashbin));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *yescrypt(const uint8_t *passwd, const uint8_t *setting)
|
||||
{
|
||||
/* prefix, '$', hash, NUL */
|
||||
static uint8_t buf[PREFIX_LEN + 1 + HASH_LEN + 1];
|
||||
yescrypt_local_t local;
|
||||
uint8_t *retval;
|
||||
|
||||
if (yescrypt_init_local(&local))
|
||||
return NULL;
|
||||
retval = yescrypt_r(NULL, &local,
|
||||
passwd, strlen((char *)passwd), setting, NULL, buf, sizeof(buf));
|
||||
if (yescrypt_free_local(&local))
|
||||
return NULL;
|
||||
return retval;
|
||||
}
|
||||
|
||||
uint8_t *yescrypt_reencrypt(uint8_t *hash,
|
||||
const yescrypt_binary_t *from_key,
|
||||
const yescrypt_binary_t *to_key)
|
||||
{
|
||||
uint8_t *retval = NULL, *saltstart, *hashstart;
|
||||
const uint8_t *hashend;
|
||||
unsigned char saltbin[64], hashbin[32];
|
||||
size_t saltstrlen, saltlen = 0, hashlen;
|
||||
|
||||
if (strncmp((char *)hash, "$y$", 3))
|
||||
return NULL;
|
||||
|
||||
saltstart = NULL;
|
||||
hashstart = (uint8_t *)strrchr((char *)hash, '$');
|
||||
if (hashstart) {
|
||||
if (hashstart > (uint8_t *)hash) {
|
||||
saltstart = hashstart - 1;
|
||||
while (*saltstart != '$' && saltstart > hash)
|
||||
saltstart--;
|
||||
if (*saltstart == '$')
|
||||
saltstart++;
|
||||
}
|
||||
hashstart++;
|
||||
} else {
|
||||
hashstart = hash;
|
||||
}
|
||||
saltstrlen = saltstart ? (hashstart - 1 - saltstart) : 0;
|
||||
if (saltstrlen > BYTES2CHARS(64) ||
|
||||
strlen((char *)hashstart) != HASH_LEN)
|
||||
return NULL;
|
||||
|
||||
if (saltstrlen) {
|
||||
const uint8_t *saltend;
|
||||
saltlen = sizeof(saltbin);
|
||||
saltend = decode64(saltbin, &saltlen, saltstart, saltstrlen);
|
||||
if (!saltend || *saltend != '$' || saltlen < 1 || saltlen > 64)
|
||||
goto out;
|
||||
|
||||
if (from_key)
|
||||
encrypt(saltbin, saltlen, from_key, ENC);
|
||||
if (to_key)
|
||||
encrypt(saltbin, saltlen, to_key, DEC);
|
||||
}
|
||||
|
||||
hashlen = sizeof(hashbin);
|
||||
hashend = decode64(hashbin, &hashlen, hashstart, HASH_LEN);
|
||||
if (!hashend || *hashend || hashlen != sizeof(hashbin))
|
||||
goto out;
|
||||
|
||||
if (from_key)
|
||||
encrypt(hashbin, hashlen, from_key, DEC);
|
||||
if (to_key)
|
||||
encrypt(hashbin, hashlen, to_key, ENC);
|
||||
|
||||
if (saltstrlen) {
|
||||
if (!encode64(saltstart, saltstrlen + 1, saltbin, saltlen))
|
||||
goto out; /* can't happen */
|
||||
*(saltstart + saltstrlen) = '$';
|
||||
}
|
||||
|
||||
if (!encode64(hashstart, HASH_LEN + 1, hashbin, hashlen))
|
||||
goto out; /* can't happen */
|
||||
|
||||
retval = hash;
|
||||
|
||||
out:
|
||||
insecure_memzero(saltbin, sizeof(saltbin));
|
||||
insecure_memzero(hashbin, sizeof(hashbin));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static uint32_t N2log2(uint64_t N)
|
||||
{
|
||||
uint32_t N_log2;
|
||||
|
||||
if (N < 2)
|
||||
return 0;
|
||||
|
||||
N_log2 = 2;
|
||||
while (N >> N_log2 != 0)
|
||||
N_log2++;
|
||||
N_log2--;
|
||||
|
||||
if (N >> N_log2 != 1)
|
||||
return 0;
|
||||
|
||||
return N_log2;
|
||||
}
|
||||
|
||||
uint8_t *yescrypt_encode_params_r(const yescrypt_params_t *params,
|
||||
const uint8_t *src, size_t srclen,
|
||||
uint8_t *buf, size_t buflen)
|
||||
{
|
||||
uint32_t flavor, N_log2, NROM_log2, have;
|
||||
uint8_t *dst;
|
||||
|
||||
if (srclen > SIZE_MAX / 16)
|
||||
return NULL;
|
||||
|
||||
if (params->flags < YESCRYPT_RW) {
|
||||
flavor = params->flags;
|
||||
} else if ((params->flags & YESCRYPT_MODE_MASK) == YESCRYPT_RW &&
|
||||
params->flags <= (YESCRYPT_RW | YESCRYPT_RW_FLAVOR_MASK)) {
|
||||
flavor = YESCRYPT_RW + (params->flags >> 2);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
N_log2 = N2log2(params->N);
|
||||
if (!N_log2)
|
||||
return NULL;
|
||||
|
||||
NROM_log2 = N2log2(params->NROM);
|
||||
if (params->NROM && !NROM_log2)
|
||||
return NULL;
|
||||
|
||||
if ((uint64_t)params->r * (uint64_t)params->p >= (1U << 30))
|
||||
return NULL;
|
||||
|
||||
dst = buf;
|
||||
*dst++ = '$';
|
||||
*dst++ = 'y';
|
||||
*dst++ = '$';
|
||||
|
||||
dst = encode64_uint32(dst, buflen - (dst - buf), flavor, 0);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
dst = encode64_uint32(dst, buflen - (dst - buf), N_log2, 1);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
dst = encode64_uint32(dst, buflen - (dst - buf), params->r, 1);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
have = 0;
|
||||
if (params->p != 1)
|
||||
have |= 1;
|
||||
if (params->t)
|
||||
have |= 2;
|
||||
if (params->g)
|
||||
have |= 4;
|
||||
if (NROM_log2)
|
||||
have |= 8;
|
||||
|
||||
if (have) {
|
||||
dst = encode64_uint32(dst, buflen - (dst - buf), have, 1);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (params->p != 1) {
|
||||
dst = encode64_uint32(dst, buflen - (dst - buf), params->p, 2);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (params->t) {
|
||||
dst = encode64_uint32(dst, buflen - (dst - buf), params->t, 1);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (params->g) {
|
||||
dst = encode64_uint32(dst, buflen - (dst - buf), params->g, 1);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (NROM_log2) {
|
||||
dst = encode64_uint32(dst, buflen - (dst - buf), NROM_log2, 1);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dst >= buf + buflen)
|
||||
return NULL;
|
||||
|
||||
*dst++ = '$';
|
||||
|
||||
dst = encode64(dst, buflen - (dst - buf), src, srclen);
|
||||
if (!dst || dst >= buf + buflen)
|
||||
return NULL;
|
||||
|
||||
*dst = 0; /* NUL termination */
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
uint8_t *yescrypt_encode_params(const yescrypt_params_t *params,
|
||||
const uint8_t *src, size_t srclen)
|
||||
{
|
||||
/* prefix, NUL */
|
||||
static uint8_t buf[PREFIX_LEN + 1];
|
||||
return yescrypt_encode_params_r(params, src, srclen, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
int crypto_scrypt(const uint8_t *passwd, size_t passwdlen,
|
||||
const uint8_t *salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
|
||||
uint8_t *buf, size_t buflen)
|
||||
{
|
||||
yescrypt_local_t local;
|
||||
yescrypt_params_t params = { .flags = 0, .N = N, .r = r, .p = p };
|
||||
int retval;
|
||||
|
||||
if (yescrypt_init_local(&local))
|
||||
return -1;
|
||||
retval = yescrypt_kdf(NULL, &local,
|
||||
passwd, passwdlen, salt, saltlen, ¶ms, buf, buflen);
|
||||
if (yescrypt_free_local(&local))
|
||||
return -1;
|
||||
return retval;
|
||||
}
|
||||
1531
brute/source/yescrypt/yescrypt-opt.c
Normal file
1531
brute/source/yescrypt/yescrypt-opt.c
Normal file
File diff suppressed because it is too large
Load Diff
110
brute/source/yescrypt/yescrypt-platform.c
Normal file
110
brute/source/yescrypt/yescrypt-platform.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/*-
|
||||
* Copyright 2013-2018,2022 Alexander Peslyak
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*/
|
||||
|
||||
#ifdef __unix__
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <linux/mman.h> /* for MAP_HUGE_2MB */
|
||||
#endif
|
||||
|
||||
#define HUGEPAGE_THRESHOLD (32 * 1024 * 1024)
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define HUGEPAGE_SIZE (2 * 1024 * 1024)
|
||||
#else
|
||||
#undef HUGEPAGE_SIZE
|
||||
#endif
|
||||
|
||||
static void *alloc_region(yescrypt_region_t *region, size_t size)
|
||||
{
|
||||
size_t base_size = size;
|
||||
uint8_t *base, *aligned;
|
||||
#ifdef MAP_ANON
|
||||
int flags =
|
||||
#ifdef MAP_NOCORE
|
||||
MAP_NOCORE |
|
||||
#endif
|
||||
MAP_ANON | MAP_PRIVATE;
|
||||
#if defined(MAP_HUGETLB) && defined(MAP_HUGE_2MB) && defined(HUGEPAGE_SIZE)
|
||||
size_t new_size = size;
|
||||
const size_t hugepage_mask = (size_t)HUGEPAGE_SIZE - 1;
|
||||
if (size >= HUGEPAGE_THRESHOLD && size + hugepage_mask >= size) {
|
||||
flags |= MAP_HUGETLB | MAP_HUGE_2MB;
|
||||
/*
|
||||
* Linux's munmap() fails on MAP_HUGETLB mappings if size is not a multiple of
|
||||
* huge page size, so let's round up to huge page size here.
|
||||
*/
|
||||
new_size = size + hugepage_mask;
|
||||
new_size &= ~hugepage_mask;
|
||||
}
|
||||
base = mmap(NULL, new_size, PROT_READ | PROT_WRITE, flags, -1, 0);
|
||||
if (base != MAP_FAILED) {
|
||||
base_size = new_size;
|
||||
} else if (flags & MAP_HUGETLB) {
|
||||
flags &= ~(MAP_HUGETLB | MAP_HUGE_2MB);
|
||||
base = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0);
|
||||
}
|
||||
|
||||
#else
|
||||
base = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0);
|
||||
#endif
|
||||
if (base == MAP_FAILED)
|
||||
base = NULL;
|
||||
aligned = base;
|
||||
#elif defined(HAVE_POSIX_MEMALIGN)
|
||||
if ((errno = posix_memalign((void **)&base, 64, size)) != 0)
|
||||
base = NULL;
|
||||
aligned = base;
|
||||
#else
|
||||
base = aligned = NULL;
|
||||
if (size + 63 < size) {
|
||||
errno = ENOMEM;
|
||||
} else if ((base = malloc(size + 63)) != NULL) {
|
||||
aligned = base + 63;
|
||||
aligned -= (uintptr_t)aligned & 63;
|
||||
}
|
||||
#endif
|
||||
region->base = base;
|
||||
region->aligned = aligned;
|
||||
region->base_size = base ? base_size : 0;
|
||||
region->aligned_size = base ? size : 0;
|
||||
return aligned;
|
||||
}
|
||||
|
||||
static inline void init_region(yescrypt_region_t *region)
|
||||
{
|
||||
region->base = region->aligned = NULL;
|
||||
region->base_size = region->aligned_size = 0;
|
||||
}
|
||||
|
||||
static int free_region(yescrypt_region_t *region)
|
||||
{
|
||||
if (region->base) {
|
||||
#ifdef MAP_ANON
|
||||
if (munmap(region->base, region->base_size))
|
||||
return -1;
|
||||
#else
|
||||
free(region->base);
|
||||
#endif
|
||||
}
|
||||
init_region(region);
|
||||
return 0;
|
||||
}
|
||||
925
brute/source/yescrypt/yescrypt-ref.c
Normal file
925
brute/source/yescrypt/yescrypt-ref.c
Normal file
@@ -0,0 +1,925 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* Copyright 2013-2018 Alexander Peslyak
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*
|
||||
* This is the reference implementation. Its purpose is to provide a simple
|
||||
* human- and machine-readable specification that implementations intended
|
||||
* for actual use should be tested against. It is deliberately mostly not
|
||||
* optimized, and it is not meant to be used in production. Instead, use
|
||||
* yescrypt-opt.c.
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
#warning "This reference implementation is deliberately mostly not optimized, nor does it make any attempt not to leave sensitive data in memory. Use yescrypt-opt.c instead unless you're testing (against) the reference implementation on purpose."
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha256.h"
|
||||
#include "sysendian.h"
|
||||
|
||||
#define YESCRYPT_INTERNAL
|
||||
#include "yescrypt.h"
|
||||
|
||||
static void blkcpy(uint32_t *dst, const uint32_t *src, size_t count)
|
||||
{
|
||||
do {
|
||||
*dst++ = *src++;
|
||||
} while (--count);
|
||||
}
|
||||
|
||||
static void blkxor(uint32_t *dst, const uint32_t *src, size_t count)
|
||||
{
|
||||
do {
|
||||
*dst++ ^= *src++;
|
||||
} while (--count);
|
||||
}
|
||||
|
||||
/**
|
||||
* salsa20(B):
|
||||
* Apply the Salsa20 core to the provided block.
|
||||
*/
|
||||
static void salsa20(uint32_t B[16], uint32_t rounds)
|
||||
{
|
||||
uint32_t x[16];
|
||||
size_t i;
|
||||
|
||||
/* SIMD unshuffle */
|
||||
for (i = 0; i < 16; i++)
|
||||
x[i * 5 % 16] = B[i];
|
||||
|
||||
for (i = 0; i < rounds; i += 2) {
|
||||
#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
|
||||
/* Operate on columns */
|
||||
x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9);
|
||||
x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18);
|
||||
|
||||
x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9);
|
||||
x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18);
|
||||
|
||||
x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9);
|
||||
x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18);
|
||||
|
||||
x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9);
|
||||
x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18);
|
||||
|
||||
/* Operate on rows */
|
||||
x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9);
|
||||
x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18);
|
||||
|
||||
x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9);
|
||||
x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18);
|
||||
|
||||
x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9);
|
||||
x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18);
|
||||
|
||||
x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9);
|
||||
x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18);
|
||||
#undef R
|
||||
}
|
||||
|
||||
/* SIMD shuffle */
|
||||
for (i = 0; i < 16; i++)
|
||||
B[i] += x[i * 5 % 16];
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_salsa8(B, Y, r):
|
||||
* Compute B = BlockMix_{salsa20/8, r}(B). The input B must be 128r bytes in
|
||||
* length; the temporary space Y must also be the same size.
|
||||
*/
|
||||
static void blockmix_salsa8(uint32_t *B, uint32_t *Y, size_t r)
|
||||
{
|
||||
uint32_t X[16];
|
||||
size_t i;
|
||||
|
||||
/* 1: X <-- B_{2r - 1} */
|
||||
blkcpy(X, &B[(2 * r - 1) * 16], 16);
|
||||
|
||||
/* 2: for i = 0 to 2r - 1 do */
|
||||
for (i = 0; i < 2 * r; i++) {
|
||||
/* 3: X <-- H(X xor B_i) */
|
||||
blkxor(X, &B[i * 16], 16);
|
||||
salsa20(X, 8);
|
||||
|
||||
/* 4: Y_i <-- X */
|
||||
blkcpy(&Y[i * 16], X, 16);
|
||||
}
|
||||
|
||||
/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */
|
||||
for (i = 0; i < r; i++)
|
||||
blkcpy(&B[i * 16], &Y[(i * 2) * 16], 16);
|
||||
for (i = 0; i < r; i++)
|
||||
blkcpy(&B[(i + r) * 16], &Y[(i * 2 + 1) * 16], 16);
|
||||
}
|
||||
|
||||
/* These are tunable, but they must meet certain constraints */
|
||||
#define PWXsimple 2
|
||||
#define PWXgather 4
|
||||
#define PWXrounds 6
|
||||
#define Swidth 8
|
||||
|
||||
/* Derived values. Not tunable on their own. */
|
||||
#define PWXbytes (PWXgather * PWXsimple * 8)
|
||||
#define PWXwords (PWXbytes / sizeof(uint32_t))
|
||||
#define Sbytes (3 * (1 << Swidth) * PWXsimple * 8)
|
||||
#define Swords (Sbytes / sizeof(uint32_t))
|
||||
#define Smask (((1 << Swidth) - 1) * PWXsimple * 8)
|
||||
#define rmin ((PWXbytes + 127) / 128)
|
||||
|
||||
typedef struct {
|
||||
uint32_t *S;
|
||||
uint32_t (*S0)[2], (*S1)[2], (*S2)[2];
|
||||
size_t w;
|
||||
} pwxform_ctx_t;
|
||||
|
||||
/**
|
||||
* pwxform(B):
|
||||
* Transform the provided block using the provided S-boxes.
|
||||
*/
|
||||
static void pwxform(uint32_t *B, pwxform_ctx_t *ctx)
|
||||
{
|
||||
uint32_t (*X)[PWXsimple][2] = (uint32_t (*)[PWXsimple][2])B;
|
||||
uint32_t (*S0)[2] = ctx->S0, (*S1)[2] = ctx->S1, (*S2)[2] = ctx->S2;
|
||||
size_t w = ctx->w;
|
||||
size_t i, j, k;
|
||||
|
||||
/* 1: for i = 0 to PWXrounds - 1 do */
|
||||
for (i = 0; i < PWXrounds; i++) {
|
||||
/* 2: for j = 0 to PWXgather - 1 do */
|
||||
for (j = 0; j < PWXgather; j++) {
|
||||
uint32_t xl = X[j][0][0];
|
||||
uint32_t xh = X[j][0][1];
|
||||
uint32_t (*p0)[2], (*p1)[2];
|
||||
|
||||
/* 3: p0 <-- (lo(B_{j,0}) & Smask) / (PWXsimple * 8) */
|
||||
p0 = S0 + (xl & Smask) / sizeof(*S0);
|
||||
/* 4: p1 <-- (hi(B_{j,0}) & Smask) / (PWXsimple * 8) */
|
||||
p1 = S1 + (xh & Smask) / sizeof(*S1);
|
||||
|
||||
/* 5: for k = 0 to PWXsimple - 1 do */
|
||||
for (k = 0; k < PWXsimple; k++) {
|
||||
uint64_t x, s0, s1;
|
||||
|
||||
/* 6: B_{j,k} <-- (hi(B_{j,k}) * lo(B_{j,k}) + S0_{p0,k}) xor S1_{p1,k} */
|
||||
s0 = ((uint64_t)p0[k][1] << 32) + p0[k][0];
|
||||
s1 = ((uint64_t)p1[k][1] << 32) + p1[k][0];
|
||||
|
||||
xl = X[j][k][0];
|
||||
xh = X[j][k][1];
|
||||
|
||||
x = (uint64_t)xh * xl;
|
||||
x += s0;
|
||||
x ^= s1;
|
||||
|
||||
X[j][k][0] = x;
|
||||
X[j][k][1] = x >> 32;
|
||||
|
||||
/* 8: if (i != 0) and (i != PWXrounds - 1) */
|
||||
if (i != 0 && i != PWXrounds - 1) {
|
||||
/* 9: S2_w <-- B_j */
|
||||
S2[w][0] = x;
|
||||
S2[w][1] = x >> 32;
|
||||
/* 10: w <-- w + 1 */
|
||||
w++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 14: (S0, S1, S2) <-- (S2, S0, S1) */
|
||||
ctx->S0 = S2;
|
||||
ctx->S1 = S0;
|
||||
ctx->S2 = S1;
|
||||
/* 15: w <-- w mod 2^Swidth */
|
||||
ctx->w = w & ((1 << Swidth) * PWXsimple - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* blockmix_pwxform(B, ctx, r):
|
||||
* Compute B = BlockMix_pwxform{salsa20/2, ctx, r}(B). The input B must be
|
||||
* 128r bytes in length.
|
||||
*/
|
||||
static void blockmix_pwxform(uint32_t *B, pwxform_ctx_t *ctx, size_t r)
|
||||
{
|
||||
uint32_t X[PWXwords];
|
||||
size_t r1, i;
|
||||
|
||||
/* Convert 128-byte blocks to PWXbytes blocks */
|
||||
/* 1: r_1 <-- 128r / PWXbytes */
|
||||
r1 = 128 * r / PWXbytes;
|
||||
|
||||
/* 2: X <-- B'_{r_1 - 1} */
|
||||
blkcpy(X, &B[(r1 - 1) * PWXwords], PWXwords);
|
||||
|
||||
/* 3: for i = 0 to r_1 - 1 do */
|
||||
for (i = 0; i < r1; i++) {
|
||||
/* 4: if r_1 > 1 */
|
||||
if (r1 > 1) {
|
||||
/* 5: X <-- X xor B'_i */
|
||||
blkxor(X, &B[i * PWXwords], PWXwords);
|
||||
}
|
||||
|
||||
/* 7: X <-- pwxform(X) */
|
||||
pwxform(X, ctx);
|
||||
|
||||
/* 8: B'_i <-- X */
|
||||
blkcpy(&B[i * PWXwords], X, PWXwords);
|
||||
}
|
||||
|
||||
/* 10: i <-- floor((r_1 - 1) * PWXbytes / 64) */
|
||||
i = (r1 - 1) * PWXbytes / 64;
|
||||
|
||||
/* 11: B_i <-- H(B_i) */
|
||||
salsa20(&B[i * 16], 2);
|
||||
|
||||
#if 1 /* No-op with our current pwxform settings, but do it to make sure */
|
||||
/* 12: for i = i + 1 to 2r - 1 do */
|
||||
for (i++; i < 2 * r; i++) {
|
||||
/* 13: B_i <-- H(B_i xor B_{i-1}) */
|
||||
blkxor(&B[i * 16], &B[(i - 1) * 16], 16);
|
||||
salsa20(&B[i * 16], 2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* integerify(B, r):
|
||||
* Return the result of parsing B_{2r-1} as a little-endian integer.
|
||||
*/
|
||||
static uint64_t integerify(const uint32_t *B, size_t r)
|
||||
{
|
||||
/*
|
||||
* Our 32-bit words are in host byte order, and word 13 is the second word of
|
||||
* B_{2r-1} due to SIMD shuffling. The 64-bit value we return is also in host
|
||||
* byte order, as it should be.
|
||||
*/
|
||||
const uint32_t *X = &B[(2 * r - 1) * 16];
|
||||
return ((uint64_t)X[13] << 32) + X[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* p2floor(x):
|
||||
* Largest power of 2 not greater than argument.
|
||||
*/
|
||||
static uint64_t p2floor(uint64_t x)
|
||||
{
|
||||
uint64_t y;
|
||||
while ((y = x & (x - 1)))
|
||||
x = y;
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* wrap(x, i):
|
||||
* Wrap x to the range 0 to i-1.
|
||||
*/
|
||||
static uint64_t wrap(uint64_t x, uint64_t i)
|
||||
{
|
||||
uint64_t n = p2floor(i);
|
||||
return (x & (n - 1)) + (i - n);
|
||||
}
|
||||
|
||||
/**
|
||||
* smix1(B, r, N, flags, V, NROM, VROM, XY, ctx):
|
||||
* Compute first loop of B = SMix_r(B, N). The input B must be 128r bytes in
|
||||
* length; the temporary storage V must be 128rN bytes in length; the temporary
|
||||
* storage XY must be 256r bytes in length.
|
||||
*/
|
||||
static void smix1(uint32_t *B, size_t r, uint64_t N, yescrypt_flags_t flags,
|
||||
uint32_t *V, uint64_t NROM, const uint32_t *VROM,
|
||||
uint32_t *XY, pwxform_ctx_t *ctx)
|
||||
{
|
||||
size_t s = 32 * r;
|
||||
uint32_t *X = XY;
|
||||
uint32_t *Y = &XY[s];
|
||||
uint64_t i, j;
|
||||
size_t k;
|
||||
|
||||
/* 1: X <-- B */
|
||||
for (k = 0; k < 2 * r; k++)
|
||||
for (i = 0; i < 16; i++)
|
||||
X[k * 16 + i] = le32dec(&B[k * 16 + (i * 5 % 16)]);
|
||||
|
||||
/* 2: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < N; i++) {
|
||||
/* 3: V_i <-- X */
|
||||
blkcpy(&V[i * s], X, s);
|
||||
|
||||
if (VROM && i == 0) {
|
||||
/* X <-- X xor VROM_{NROM-1} */
|
||||
blkxor(X, &VROM[(NROM - 1) * s], s);
|
||||
} else if (VROM && (i & 1)) {
|
||||
/* j <-- Integerify(X) mod NROM */
|
||||
j = integerify(X, r) & (NROM - 1);
|
||||
|
||||
/* X <-- X xor VROM_j */
|
||||
blkxor(X, &VROM[j * s], s);
|
||||
} else if ((flags & YESCRYPT_RW) && i > 1) {
|
||||
/* j <-- Wrap(Integerify(X), i) */
|
||||
j = wrap(integerify(X, r), i);
|
||||
|
||||
/* X <-- X xor V_j */
|
||||
blkxor(X, &V[j * s], s);
|
||||
}
|
||||
|
||||
/* 4: X <-- H(X) */
|
||||
if (ctx)
|
||||
blockmix_pwxform(X, ctx, r);
|
||||
else
|
||||
blockmix_salsa8(X, Y, r);
|
||||
}
|
||||
|
||||
/* B' <-- X */
|
||||
for (k = 0; k < 2 * r; k++)
|
||||
for (i = 0; i < 16; i++)
|
||||
le32enc(&B[k * 16 + (i * 5 % 16)], X[k * 16 + i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* smix2(B, r, N, Nloop, flags, V, NROM, VROM, XY, ctx):
|
||||
* Compute second loop of B = SMix_r(B, N). The input B must be 128r bytes in
|
||||
* length; the temporary storage V must be 128rN bytes in length; the temporary
|
||||
* storage XY must be 256r bytes in length. The value N must be a power of 2
|
||||
* greater than 1.
|
||||
*/
|
||||
static void smix2(uint32_t *B, size_t r, uint64_t N, uint64_t Nloop,
|
||||
yescrypt_flags_t flags, uint32_t *V, uint64_t NROM,
|
||||
const uint32_t *VROM, uint32_t *XY, pwxform_ctx_t *ctx)
|
||||
{
|
||||
size_t s = 32 * r;
|
||||
uint32_t *X = XY;
|
||||
uint32_t *Y = &XY[s];
|
||||
uint64_t i, j;
|
||||
size_t k;
|
||||
|
||||
/* X <-- B */
|
||||
for (k = 0; k < 2 * r; k++)
|
||||
for (i = 0; i < 16; i++)
|
||||
X[k * 16 + i] = le32dec(&B[k * 16 + (i * 5 % 16)]);
|
||||
|
||||
/* 6: for i = 0 to N - 1 do */
|
||||
for (i = 0; i < Nloop; i++) {
|
||||
if (VROM && (i & 1)) {
|
||||
/* j <-- Integerify(X) mod NROM */
|
||||
j = integerify(X, r) & (NROM - 1);
|
||||
|
||||
/* X <-- H(X xor VROM_j) */
|
||||
blkxor(X, &VROM[j * s], s);
|
||||
} else {
|
||||
/* 7: j <-- Integerify(X) mod N */
|
||||
j = integerify(X, r) & (N - 1);
|
||||
|
||||
/* 8.1: X <-- X xor V_j */
|
||||
blkxor(X, &V[j * s], s);
|
||||
/* V_j <-- X */
|
||||
if (flags & YESCRYPT_RW)
|
||||
blkcpy(&V[j * s], X, s);
|
||||
}
|
||||
|
||||
/* 8.2: X <-- H(X) */
|
||||
if (ctx)
|
||||
blockmix_pwxform(X, ctx, r);
|
||||
else
|
||||
blockmix_salsa8(X, Y, r);
|
||||
}
|
||||
|
||||
/* 10: B' <-- X */
|
||||
for (k = 0; k < 2 * r; k++)
|
||||
for (i = 0; i < 16; i++)
|
||||
le32enc(&B[k * 16 + (i * 5 % 16)], X[k * 16 + i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* smix(B, r, N, p, t, flags, V, NROM, VROM, XY, ctx, passwd):
|
||||
* Compute B = SMix_r(B, N). The input B must be 128rp bytes in length; the
|
||||
* temporary storage V must be 128rN bytes in length; the temporary storage
|
||||
* XY must be 256r bytes in length. The value N must be a power of 2 greater
|
||||
* than 1.
|
||||
*/
|
||||
static void smix(uint32_t *B, size_t r, uint64_t N, uint32_t p, uint32_t t,
|
||||
yescrypt_flags_t flags,
|
||||
uint32_t *V, uint64_t NROM, const uint32_t *VROM,
|
||||
uint32_t *XY, pwxform_ctx_t *ctx, uint8_t *passwd)
|
||||
{
|
||||
size_t s = 32 * r;
|
||||
uint64_t Nchunk, Nloop_all, Nloop_rw, Vchunk;
|
||||
uint32_t i;
|
||||
|
||||
/* 1: n <-- N / p */
|
||||
Nchunk = N / p;
|
||||
|
||||
/* 2: Nloop_all <-- fNloop(n, t, flags) */
|
||||
Nloop_all = Nchunk;
|
||||
if (flags & YESCRYPT_RW) {
|
||||
if (t <= 1) {
|
||||
if (t)
|
||||
Nloop_all *= 2; /* 2/3 */
|
||||
Nloop_all = (Nloop_all + 2) / 3; /* 1/3, round up */
|
||||
} else {
|
||||
Nloop_all *= t - 1;
|
||||
}
|
||||
} else if (t) {
|
||||
if (t == 1)
|
||||
Nloop_all += (Nloop_all + 1) / 2; /* 1.5, round up */
|
||||
Nloop_all *= t;
|
||||
}
|
||||
|
||||
/* 6: Nloop_rw <-- 0 */
|
||||
Nloop_rw = 0;
|
||||
if (flags & YESCRYPT_INIT_SHARED) {
|
||||
Nloop_rw = Nloop_all;
|
||||
} else {
|
||||
/* 3: if YESCRYPT_RW flag is set */
|
||||
if (flags & YESCRYPT_RW) {
|
||||
/* 4: Nloop_rw <-- Nloop_all / p */
|
||||
Nloop_rw = Nloop_all / p;
|
||||
}
|
||||
}
|
||||
|
||||
/* 8: n <-- n - (n mod 2) */
|
||||
Nchunk &= ~(uint64_t)1; /* round down to even */
|
||||
/* 9: Nloop_all <-- Nloop_all + (Nloop_all mod 2) */
|
||||
Nloop_all++; Nloop_all &= ~(uint64_t)1; /* round up to even */
|
||||
/* 10: Nloop_rw <-- Nloop_rw + (Nloop_rw mod 2) */
|
||||
Nloop_rw++; Nloop_rw &= ~(uint64_t)1; /* round up to even */
|
||||
|
||||
/* 11: for i = 0 to p - 1 do */
|
||||
/* 12: u <-- in */
|
||||
for (i = 0, Vchunk = 0; i < p; i++, Vchunk += Nchunk) {
|
||||
/* 13: if i = p - 1 */
|
||||
/* 14: n <-- N - u */
|
||||
/* 15: end if */
|
||||
/* 16: v <-- u + n - 1 */
|
||||
uint64_t Np = (i < p - 1) ? Nchunk : (N - Vchunk);
|
||||
uint32_t *Bp = &B[i * s];
|
||||
uint32_t *Vp = &V[Vchunk * s];
|
||||
pwxform_ctx_t *ctx_i = NULL;
|
||||
/* 17: if YESCRYPT_RW flag is set */
|
||||
if (flags & YESCRYPT_RW) {
|
||||
ctx_i = &ctx[i];
|
||||
/* 18: SMix1_1(B_i, Sbytes / 128, S_i, no flags) */
|
||||
smix1(Bp, 1, Sbytes / 128, 0 /* no flags */,
|
||||
ctx_i->S, 0, NULL, XY, NULL);
|
||||
/* 19: S2_i <-- S_{i,0...2^Swidth-1} */
|
||||
ctx_i->S2 = (uint32_t (*)[2])ctx_i->S;
|
||||
/* 20: S1_i <-- S_{i,2^Swidth...2*2^Swidth-1} */
|
||||
ctx_i->S1 = ctx_i->S2 + (1 << Swidth) * PWXsimple;
|
||||
/* 21: S0_i <-- S_{i,2*2^Swidth...3*2^Swidth-1} */
|
||||
ctx_i->S0 = ctx_i->S1 + (1 << Swidth) * PWXsimple;
|
||||
/* 22: w_i <-- 0 */
|
||||
ctx_i->w = 0;
|
||||
/* 23: if i = 0 */
|
||||
if (i == 0) {
|
||||
/* 24: passwd <-- HMAC-SHA256(B_{0,2r-1}, passwd) */
|
||||
HMAC_SHA256_Buf(Bp + (s - 16), 64,
|
||||
passwd, 32, passwd);
|
||||
}
|
||||
}
|
||||
/* 27: SMix1_r(B_i, n, V_{u..v}, flags) */
|
||||
smix1(Bp, r, Np, flags, Vp, NROM, VROM, XY, ctx_i);
|
||||
/* 28: SMix2_r(B_i, p2floor(n), Nloop_rw, V_{u..v}, flags) */
|
||||
smix2(Bp, r, p2floor(Np), Nloop_rw, flags, Vp,
|
||||
NROM, VROM, XY, ctx_i);
|
||||
}
|
||||
|
||||
/* 30: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
uint32_t *Bp = &B[i * s];
|
||||
/* 31: SMix2_r(B_i, N, Nloop_all - Nloop_rw, V, flags excluding YESCRYPT_RW) */
|
||||
smix2(Bp, r, N, Nloop_all - Nloop_rw, flags & ~YESCRYPT_RW,
|
||||
V, NROM, VROM, XY, (flags & YESCRYPT_RW) ? &ctx[i] : NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* yescrypt_kdf_body(shared, local, passwd, passwdlen, salt, saltlen,
|
||||
* flags, N, r, p, t, NROM, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen), or a revision of scrypt as requested by flags and shared, and
|
||||
* write the result into buf.
|
||||
*
|
||||
* shared and flags may request special modes as described in yescrypt.h.
|
||||
*
|
||||
* local is the thread-local data structure, allowing optimized implementations
|
||||
* to preserve and reuse a memory allocation across calls, thereby reducing its
|
||||
* overhead (this reference implementation does not make that optimization).
|
||||
*
|
||||
* t controls computation time while not affecting peak memory usage.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*/
|
||||
static int yescrypt_kdf_body(const yescrypt_shared_t *shared,
|
||||
yescrypt_local_t *local,
|
||||
const uint8_t *passwd, size_t passwdlen,
|
||||
const uint8_t *salt, size_t saltlen,
|
||||
yescrypt_flags_t flags, uint64_t N, uint32_t r, uint32_t p, uint32_t t,
|
||||
uint64_t NROM,
|
||||
uint8_t *buf, size_t buflen)
|
||||
{
|
||||
int retval = -1;
|
||||
const uint32_t *VROM;
|
||||
size_t B_size, V_size;
|
||||
uint32_t *B, *V, *XY, *S;
|
||||
pwxform_ctx_t *pwxform_ctx;
|
||||
uint32_t sha256[8];
|
||||
uint8_t dk[sizeof(sha256)], *dkp = buf;
|
||||
uint32_t i;
|
||||
|
||||
/* Sanity-check parameters */
|
||||
switch (flags & YESCRYPT_MODE_MASK) {
|
||||
case 0: /* classic scrypt - can't have anything non-standard */
|
||||
if (flags || t || NROM)
|
||||
goto out_EINVAL;
|
||||
break;
|
||||
case YESCRYPT_WORM:
|
||||
if (flags != YESCRYPT_WORM || NROM)
|
||||
goto out_EINVAL;
|
||||
break;
|
||||
case YESCRYPT_RW:
|
||||
if (flags != (flags & YESCRYPT_KNOWN_FLAGS))
|
||||
goto out_EINVAL;
|
||||
#if PWXsimple == 2 && PWXgather == 4 && PWXrounds == 6 && Sbytes == 12288
|
||||
if ((flags & YESCRYPT_RW_FLAVOR_MASK) ==
|
||||
(YESCRYPT_ROUNDS_6 | YESCRYPT_GATHER_4 |
|
||||
YESCRYPT_SIMPLE_2 | YESCRYPT_SBOX_12K))
|
||||
break;
|
||||
#else
|
||||
#error "Unsupported pwxform settings"
|
||||
#endif
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
goto out_EINVAL;
|
||||
}
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
if (buflen > (((uint64_t)1 << 32) - 1) * 32)
|
||||
goto out_EINVAL;
|
||||
#endif
|
||||
if ((uint64_t)r * (uint64_t)p >= 1 << 30)
|
||||
goto out_EINVAL;
|
||||
if ((N & (N - 1)) != 0 || N <= 1 || r < 1 || p < 1)
|
||||
goto out_EINVAL;
|
||||
if (r > SIZE_MAX / 128 / p ||
|
||||
#if SIZE_MAX / 256 <= UINT32_MAX
|
||||
r > SIZE_MAX / 256 ||
|
||||
#endif
|
||||
N > SIZE_MAX / 128 / r)
|
||||
goto out_EINVAL;
|
||||
if (N > UINT64_MAX / ((uint64_t)t + 1))
|
||||
goto out_EINVAL;
|
||||
if (flags & YESCRYPT_RW) {
|
||||
if (N / p <= 1 || r < rmin ||
|
||||
p > SIZE_MAX / Sbytes ||
|
||||
p > SIZE_MAX / sizeof(*pwxform_ctx))
|
||||
goto out_EINVAL;
|
||||
}
|
||||
|
||||
VROM = NULL;
|
||||
if (shared) {
|
||||
uint64_t expected_size = (size_t)128 * r * NROM;
|
||||
if ((NROM & (NROM - 1)) != 0 || NROM <= 1 ||
|
||||
shared->aligned_size < expected_size)
|
||||
goto out_EINVAL;
|
||||
if (!(flags & YESCRYPT_INIT_SHARED)) {
|
||||
uint32_t *tag = (uint32_t *)
|
||||
((uint8_t *)shared->aligned + expected_size - 48);
|
||||
uint64_t tag1 = ((uint64_t)tag[1] << 32) + tag[0];
|
||||
uint64_t tag2 = ((uint64_t)tag[3] << 32) + tag[2];
|
||||
if (tag1 != YESCRYPT_ROM_TAG1 || tag2 != YESCRYPT_ROM_TAG2)
|
||||
goto out_EINVAL;
|
||||
}
|
||||
VROM = shared->aligned;
|
||||
} else {
|
||||
if (NROM)
|
||||
goto out_EINVAL;
|
||||
}
|
||||
|
||||
/* Allocate memory */
|
||||
V_size = (size_t)128 * r * N;
|
||||
if (flags & YESCRYPT_INIT_SHARED) {
|
||||
V = (uint32_t *)local->aligned;
|
||||
if (local->aligned_size < V_size) {
|
||||
if (local->base || local->aligned ||
|
||||
local->base_size || local->aligned_size)
|
||||
goto out_EINVAL;
|
||||
if ((V = malloc(V_size)) == NULL)
|
||||
return -1;
|
||||
local->base = local->aligned = V;
|
||||
local->base_size = local->aligned_size = V_size;
|
||||
}
|
||||
if (flags & YESCRYPT_ALLOC_ONLY)
|
||||
return -2; /* expected "failure" */
|
||||
} else {
|
||||
if ((V = malloc(V_size)) == NULL)
|
||||
return -1;
|
||||
}
|
||||
B_size = (size_t)128 * r * p;
|
||||
if ((B = malloc(B_size)) == NULL)
|
||||
goto free_V;
|
||||
if ((XY = malloc((size_t)256 * r)) == NULL)
|
||||
goto free_B;
|
||||
S = NULL;
|
||||
pwxform_ctx = NULL;
|
||||
if (flags & YESCRYPT_RW) {
|
||||
if ((S = malloc((size_t)Sbytes * p)) == NULL)
|
||||
goto free_XY;
|
||||
if ((pwxform_ctx = malloc(sizeof(*pwxform_ctx) * p)) == NULL)
|
||||
goto free_S;
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
HMAC_SHA256_Buf("yescrypt-prehash",
|
||||
(flags & YESCRYPT_PREHASH) ? 16 : 8,
|
||||
passwd, passwdlen, (uint8_t *)sha256);
|
||||
passwd = (uint8_t *)sha256;
|
||||
passwdlen = sizeof(sha256);
|
||||
}
|
||||
|
||||
/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1,
|
||||
(uint8_t *)B, B_size);
|
||||
|
||||
if (flags)
|
||||
blkcpy(sha256, B, sizeof(sha256) / sizeof(sha256[0]));
|
||||
|
||||
if (flags & YESCRYPT_RW) {
|
||||
for (i = 0; i < p; i++)
|
||||
pwxform_ctx[i].S = &S[i * Swords];
|
||||
smix(B, r, N, p, t, flags, V, NROM, VROM, XY, pwxform_ctx,
|
||||
(uint8_t *)sha256);
|
||||
} else {
|
||||
/* 2: for i = 0 to p - 1 do */
|
||||
for (i = 0; i < p; i++) {
|
||||
/* 3: B_i <-- MF(B_i, N) */
|
||||
smix(&B[(size_t)32 * r * i], r, N, 1, t, flags, V,
|
||||
NROM, VROM, XY, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
dkp = buf;
|
||||
if (flags && buflen < sizeof(dk)) {
|
||||
PBKDF2_SHA256(passwd, passwdlen, (uint8_t *)B, B_size, 1,
|
||||
dk, sizeof(dk));
|
||||
dkp = dk;
|
||||
}
|
||||
|
||||
/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */
|
||||
PBKDF2_SHA256(passwd, passwdlen, (uint8_t *)B, B_size, 1, buf, buflen);
|
||||
|
||||
/*
|
||||
* Except when computing classic scrypt, allow all computation so far
|
||||
* to be performed on the client. The final steps below match those of
|
||||
* SCRAM (RFC 5802), so that an extension of SCRAM (with the steps so
|
||||
* far in place of SCRAM's use of PBKDF2 and with SHA-256 in place of
|
||||
* SCRAM's use of SHA-1) would be usable with yescrypt hashes.
|
||||
*/
|
||||
if (flags && !(flags & YESCRYPT_PREHASH)) {
|
||||
/* Compute ClientKey */
|
||||
HMAC_SHA256_Buf(dkp, sizeof(dk), "Client Key", 10,
|
||||
(uint8_t *)sha256);
|
||||
/* Compute StoredKey */
|
||||
{
|
||||
size_t clen = buflen;
|
||||
if (clen > sizeof(dk))
|
||||
clen = sizeof(dk);
|
||||
SHA256_Buf((uint8_t *)sha256, sizeof(sha256), dk);
|
||||
memcpy(buf, dk, clen);
|
||||
}
|
||||
}
|
||||
|
||||
/* Success! */
|
||||
retval = 0;
|
||||
|
||||
/* Free memory */
|
||||
free(pwxform_ctx);
|
||||
free_S:
|
||||
free(S);
|
||||
free_XY:
|
||||
free(XY);
|
||||
free_B:
|
||||
free(B);
|
||||
free_V:
|
||||
if (!(flags & YESCRYPT_INIT_SHARED))
|
||||
free(V);
|
||||
|
||||
return retval;
|
||||
|
||||
out_EINVAL:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen, params,
|
||||
* buf, buflen):
|
||||
* Compute scrypt or its revision as requested by the parameters. The inputs
|
||||
* to this function are the same as those for yescrypt_kdf_body() above, with
|
||||
* the addition of g, which controls hash upgrades (0 for no upgrades so far).
|
||||
*/
|
||||
int yescrypt_kdf(const yescrypt_shared_t *shared, yescrypt_local_t *local,
|
||||
const uint8_t *passwd, size_t passwdlen,
|
||||
const uint8_t *salt, size_t saltlen,
|
||||
const yescrypt_params_t *params,
|
||||
uint8_t *buf, size_t buflen)
|
||||
{
|
||||
yescrypt_flags_t flags = params->flags;
|
||||
uint64_t N = params->N;
|
||||
uint32_t r = params->r;
|
||||
uint32_t p = params->p;
|
||||
uint32_t t = params->t;
|
||||
uint32_t g = params->g;
|
||||
uint64_t NROM = params->NROM;
|
||||
uint8_t dk[32];
|
||||
|
||||
/* Support for hash upgrades has been temporarily removed */
|
||||
if (g) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((flags & YESCRYPT_RW) &&
|
||||
p >= 1 && N / p >= 0x100 && N / p * r >= 0x20000) {
|
||||
/*
|
||||
* This reference implementation's yescrypt_kdf_body()
|
||||
* (de)allocates memory on each call, which defeats the purpose
|
||||
* of this pre-hashing. The optimized implementations, which
|
||||
* you should actually use, make the larger allocation first
|
||||
* and then reuse it. Thus, this implementation doing things
|
||||
* differently serves as a test that the computation result is
|
||||
* unaffected by such differences.
|
||||
*/
|
||||
int retval = yescrypt_kdf_body(shared, local,
|
||||
passwd, passwdlen, salt, saltlen,
|
||||
flags | YESCRYPT_PREHASH, N >> 6, r, p, 0, NROM,
|
||||
dk, sizeof(dk));
|
||||
if (retval)
|
||||
return retval;
|
||||
passwd = dk;
|
||||
passwdlen = sizeof(dk);
|
||||
}
|
||||
|
||||
return yescrypt_kdf_body(shared, local,
|
||||
passwd, passwdlen, salt, saltlen,
|
||||
flags, N, r, p, t, NROM, buf, buflen);
|
||||
}
|
||||
|
||||
int yescrypt_init_shared(yescrypt_shared_t *shared,
|
||||
const uint8_t *seed, size_t seedlen,
|
||||
const yescrypt_params_t *params)
|
||||
{
|
||||
yescrypt_flags_t flags = params->flags;
|
||||
uint64_t N = params->NROM;
|
||||
uint32_t r = params->r;
|
||||
uint32_t p = params->p;
|
||||
uint32_t t = params->t;
|
||||
yescrypt_shared_t half1, half2;
|
||||
uint8_t salt[32];
|
||||
uint32_t *tag;
|
||||
|
||||
if (!(params->flags & YESCRYPT_RW) || params->N || params->g)
|
||||
return -1;
|
||||
|
||||
if (flags & YESCRYPT_SHARED_PREALLOCATED) {
|
||||
if (!shared->aligned || !shared->aligned_size)
|
||||
return -1;
|
||||
|
||||
/* Overwrite a possible old ROM tag before we overwrite the rest */
|
||||
tag = (uint32_t *)
|
||||
((uint8_t *)shared->aligned + shared->aligned_size - 48);
|
||||
memset(tag, 0, 48);
|
||||
} else {
|
||||
shared->base = shared->aligned = NULL;
|
||||
shared->base_size = shared->aligned_size = 0;
|
||||
|
||||
if (yescrypt_kdf_body(NULL, shared, NULL, 0, NULL, 0,
|
||||
flags | YESCRYPT_INIT_SHARED | YESCRYPT_ALLOC_ONLY,
|
||||
N, r, p, t, 0, NULL, 0) != -2 || !shared->aligned)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
half1 = half2 = *shared;
|
||||
half1.aligned_size /= 2;
|
||||
half2.aligned = (uint8_t *)half2.aligned + half1.aligned_size;
|
||||
half2.aligned_size = half1.aligned_size;
|
||||
N /= 2;
|
||||
|
||||
if (yescrypt_kdf_body(NULL, &half1,
|
||||
seed, seedlen, (const uint8_t *)"yescrypt-ROMhash", 16,
|
||||
flags | YESCRYPT_INIT_SHARED, N, r, p, t, 0,
|
||||
salt, sizeof(salt)))
|
||||
goto fail;
|
||||
|
||||
if (yescrypt_kdf_body(&half1, &half2,
|
||||
seed, seedlen, salt, sizeof(salt),
|
||||
flags | YESCRYPT_INIT_SHARED, N, r, p, t, N,
|
||||
salt, sizeof(salt)))
|
||||
goto fail;
|
||||
|
||||
if (yescrypt_kdf_body(&half2, &half1,
|
||||
seed, seedlen, salt, sizeof(salt),
|
||||
flags | YESCRYPT_INIT_SHARED, N, r, p, t, N,
|
||||
salt, sizeof(salt)))
|
||||
goto fail;
|
||||
|
||||
tag = (uint32_t *)
|
||||
((uint8_t *)shared->aligned + shared->aligned_size - 48);
|
||||
tag[0] = YESCRYPT_ROM_TAG1 & 0xffffffffU;
|
||||
tag[1] = YESCRYPT_ROM_TAG1 >> 32;
|
||||
tag[2] = YESCRYPT_ROM_TAG2 & 0xffffffffU;
|
||||
tag[3] = YESCRYPT_ROM_TAG2 >> 32;
|
||||
tag[4] = le32dec(salt);
|
||||
tag[5] = le32dec(salt + 4);
|
||||
tag[6] = le32dec(salt + 8);
|
||||
tag[7] = le32dec(salt + 12);
|
||||
tag[8] = le32dec(salt + 16);
|
||||
tag[9] = le32dec(salt + 20);
|
||||
tag[10] = le32dec(salt + 24);
|
||||
tag[11] = le32dec(salt + 28);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (!(flags & YESCRYPT_SHARED_PREALLOCATED))
|
||||
free(shared->base);
|
||||
return -1;
|
||||
}
|
||||
|
||||
yescrypt_binary_t *yescrypt_digest_shared(yescrypt_shared_t *shared)
|
||||
{
|
||||
static yescrypt_binary_t digest;
|
||||
uint32_t *tag;
|
||||
uint64_t tag1, tag2;
|
||||
|
||||
if (shared->aligned_size < 48)
|
||||
return NULL;
|
||||
|
||||
tag = (uint32_t *)
|
||||
((uint8_t *)shared->aligned + shared->aligned_size - 48);
|
||||
|
||||
tag1 = ((uint64_t)tag[1] << 32) + tag[0];
|
||||
tag2 = ((uint64_t)tag[3] << 32) + tag[2];
|
||||
if (tag1 != YESCRYPT_ROM_TAG1 || tag2 != YESCRYPT_ROM_TAG2)
|
||||
return NULL;
|
||||
|
||||
le32enc(digest.uc, tag[4]);
|
||||
le32enc(digest.uc + 4, tag[5]);
|
||||
le32enc(digest.uc + 8, tag[6]);
|
||||
le32enc(digest.uc + 12, tag[7]);
|
||||
le32enc(digest.uc + 16, tag[8]);
|
||||
le32enc(digest.uc + 20, tag[9]);
|
||||
le32enc(digest.uc + 24, tag[10]);
|
||||
le32enc(digest.uc + 28, tag[11]);
|
||||
|
||||
return &digest;
|
||||
}
|
||||
|
||||
int yescrypt_free_shared(yescrypt_shared_t *shared)
|
||||
{
|
||||
free(shared->base);
|
||||
shared->base = shared->aligned = NULL;
|
||||
shared->base_size = shared->aligned_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int yescrypt_init_local(yescrypt_local_t *local)
|
||||
{
|
||||
/* The reference implementation doesn't use the local structure */
|
||||
local->base = local->aligned = NULL;
|
||||
local->base_size = local->aligned_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int yescrypt_free_local(yescrypt_local_t *local)
|
||||
{
|
||||
/* The reference implementation frees its memory in yescrypt_kdf() */
|
||||
(void)local; /* unused */
|
||||
return 0;
|
||||
}
|
||||
346
brute/source/yescrypt/yescrypt.h
Normal file
346
brute/source/yescrypt/yescrypt.h
Normal file
@@ -0,0 +1,346 @@
|
||||
/*-
|
||||
* Copyright 2009 Colin Percival
|
||||
* Copyright 2013-2018 Alexander Peslyak
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS 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 AUTHOR OR 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.
|
||||
*
|
||||
* This file was originally written by Colin Percival as part of the Tarsnap
|
||||
* online backup system.
|
||||
*/
|
||||
#ifndef _YESCRYPT_H_
|
||||
#define _YESCRYPT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> /* for size_t */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen) and write the result into buf. The parameters r, p, and buflen
|
||||
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
|
||||
* must be a power of 2 greater than 1.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* MT-safe as long as buf is local to the thread.
|
||||
*/
|
||||
extern int crypto_scrypt(const uint8_t *passwd, size_t passwdlen,
|
||||
const uint8_t *salt, size_t saltlen,
|
||||
uint64_t N, uint32_t r, uint32_t p, uint8_t *buf, size_t buflen);
|
||||
|
||||
/**
|
||||
* Internal type used by the memory allocator. Please do not use it directly.
|
||||
* Use yescrypt_shared_t and yescrypt_local_t as appropriate instead, since
|
||||
* they might differ from each other in a future version.
|
||||
*/
|
||||
typedef struct {
|
||||
void *base, *aligned;
|
||||
size_t base_size, aligned_size;
|
||||
} yescrypt_region_t;
|
||||
|
||||
/**
|
||||
* Types for shared (ROM) and thread-local (RAM) data structures.
|
||||
*/
|
||||
typedef yescrypt_region_t yescrypt_shared_t;
|
||||
typedef yescrypt_region_t yescrypt_local_t;
|
||||
|
||||
/**
|
||||
* Two 64-bit tags placed 48 bytes to the end of a ROM in host byte endianness
|
||||
* (and followed by 32 bytes of the ROM digest).
|
||||
*/
|
||||
#define YESCRYPT_ROM_TAG1 0x7470797263736579ULL /* "yescrypt" */
|
||||
#define YESCRYPT_ROM_TAG2 0x687361684d4f522dULL /* "-ROMhash" */
|
||||
|
||||
/**
|
||||
* Type and possible values for the flags argument of yescrypt_kdf(),
|
||||
* yescrypt_encode_params_r(), yescrypt_encode_params(). Most of these may be
|
||||
* OR'ed together, except that YESCRYPT_WORM stands on its own.
|
||||
* Please refer to the description of yescrypt_kdf() below for the meaning of
|
||||
* these flags.
|
||||
*/
|
||||
typedef uint32_t yescrypt_flags_t;
|
||||
/* Public */
|
||||
#define YESCRYPT_WORM 1
|
||||
#define YESCRYPT_RW 0x002
|
||||
#define YESCRYPT_ROUNDS_3 0x000
|
||||
#define YESCRYPT_ROUNDS_6 0x004
|
||||
#define YESCRYPT_GATHER_1 0x000
|
||||
#define YESCRYPT_GATHER_2 0x008
|
||||
#define YESCRYPT_GATHER_4 0x010
|
||||
#define YESCRYPT_GATHER_8 0x018
|
||||
#define YESCRYPT_SIMPLE_1 0x000
|
||||
#define YESCRYPT_SIMPLE_2 0x020
|
||||
#define YESCRYPT_SIMPLE_4 0x040
|
||||
#define YESCRYPT_SIMPLE_8 0x060
|
||||
#define YESCRYPT_SBOX_6K 0x000
|
||||
#define YESCRYPT_SBOX_12K 0x080
|
||||
#define YESCRYPT_SBOX_24K 0x100
|
||||
#define YESCRYPT_SBOX_48K 0x180
|
||||
#define YESCRYPT_SBOX_96K 0x200
|
||||
#define YESCRYPT_SBOX_192K 0x280
|
||||
#define YESCRYPT_SBOX_384K 0x300
|
||||
#define YESCRYPT_SBOX_768K 0x380
|
||||
/* Only valid for yescrypt_init_shared() */
|
||||
#define YESCRYPT_SHARED_PREALLOCATED 0x10000
|
||||
#ifdef YESCRYPT_INTERNAL
|
||||
/* Private */
|
||||
#define YESCRYPT_MODE_MASK 0x003
|
||||
#define YESCRYPT_RW_FLAVOR_MASK 0x3fc
|
||||
#define YESCRYPT_INIT_SHARED 0x01000000
|
||||
#define YESCRYPT_ALLOC_ONLY 0x08000000
|
||||
#define YESCRYPT_PREHASH 0x10000000
|
||||
#endif
|
||||
|
||||
#define YESCRYPT_RW_DEFAULTS \
|
||||
(YESCRYPT_RW | \
|
||||
YESCRYPT_ROUNDS_6 | YESCRYPT_GATHER_4 | YESCRYPT_SIMPLE_2 | \
|
||||
YESCRYPT_SBOX_12K)
|
||||
|
||||
#define YESCRYPT_DEFAULTS YESCRYPT_RW_DEFAULTS
|
||||
|
||||
#ifdef YESCRYPT_INTERNAL
|
||||
#define YESCRYPT_KNOWN_FLAGS \
|
||||
(YESCRYPT_MODE_MASK | YESCRYPT_RW_FLAVOR_MASK | \
|
||||
YESCRYPT_SHARED_PREALLOCATED | \
|
||||
YESCRYPT_INIT_SHARED | YESCRYPT_ALLOC_ONLY | YESCRYPT_PREHASH)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* yescrypt parameters combined into one struct. N, r, p are the same as in
|
||||
* classic scrypt, except that the meaning of p changes when YESCRYPT_RW is
|
||||
* set. flags, t, g, NROM are special to yescrypt.
|
||||
*/
|
||||
typedef struct {
|
||||
yescrypt_flags_t flags;
|
||||
uint64_t N;
|
||||
uint32_t r, p, t, g;
|
||||
uint64_t NROM;
|
||||
} yescrypt_params_t;
|
||||
|
||||
/**
|
||||
* A 256-bit yescrypt hash, or a hash encryption key (which may itself have
|
||||
* been derived as a yescrypt hash of a human-specified key string).
|
||||
*/
|
||||
typedef union {
|
||||
unsigned char uc[32];
|
||||
uint64_t u64[4];
|
||||
} yescrypt_binary_t;
|
||||
|
||||
/**
|
||||
* yescrypt_init_shared(shared, seed, seedlen, params):
|
||||
* Optionally allocate memory for and initialize the shared (ROM) data
|
||||
* structure. The parameters flags, NROM, r, p, and t specify how the ROM is
|
||||
* to be initialized, and seed and seedlen specify the initial seed affecting
|
||||
* the data with which the ROM is filled.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* If bit YESCRYPT_SHARED_PREALLOCATED in flags is set, then memory for the
|
||||
* ROM is assumed to have been preallocated by the caller, with shared->aligned
|
||||
* being the start address of the ROM and shared->aligned_size being its size
|
||||
* (which must be sufficient for NROM, r, p). This may be used e.g. when the
|
||||
* ROM is to be placed in a SysV shared memory segment allocated by the caller.
|
||||
*
|
||||
* MT-safe as long as shared is local to the thread.
|
||||
*/
|
||||
extern int yescrypt_init_shared(yescrypt_shared_t *shared,
|
||||
const uint8_t *seed, size_t seedlen, const yescrypt_params_t *params);
|
||||
|
||||
/**
|
||||
* yescrypt_digest_shared(shared):
|
||||
* Extract the previously stored message digest of the provided yescrypt ROM.
|
||||
*
|
||||
* Return pointer to the message digest on success; or NULL on error.
|
||||
*
|
||||
* MT-unsafe.
|
||||
*/
|
||||
extern yescrypt_binary_t *yescrypt_digest_shared(yescrypt_shared_t *shared);
|
||||
|
||||
/**
|
||||
* yescrypt_free_shared(shared):
|
||||
* Free memory that had been allocated with yescrypt_init_shared().
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* MT-safe as long as shared is local to the thread.
|
||||
*/
|
||||
extern int yescrypt_free_shared(yescrypt_shared_t *shared);
|
||||
|
||||
/**
|
||||
* yescrypt_init_local(local):
|
||||
* Initialize the thread-local (RAM) data structure. Actual memory allocation
|
||||
* is currently fully postponed until a call to yescrypt_kdf() or yescrypt_r().
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* MT-safe as long as local is local to the thread.
|
||||
*/
|
||||
extern int yescrypt_init_local(yescrypt_local_t *local);
|
||||
|
||||
/**
|
||||
* yescrypt_free_local(local):
|
||||
* Free memory that may have been allocated for an initialized thread-local
|
||||
* (RAM) data structure.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* MT-safe as long as local is local to the thread.
|
||||
*/
|
||||
extern int yescrypt_free_local(yescrypt_local_t *local);
|
||||
|
||||
/**
|
||||
* yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen, params,
|
||||
* buf, buflen):
|
||||
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
|
||||
* p, buflen), or a revision of scrypt as requested by flags and shared, and
|
||||
* write the result into buf. The parameters N, r, p, and buflen must satisfy
|
||||
* the same conditions as with crypto_scrypt(). t controls computation time
|
||||
* while not affecting peak memory usage (t = 0 is optimal unless higher N*r
|
||||
* is not affordable while higher t is). g controls hash upgrades (g = 0 for
|
||||
* no upgrades so far). shared and flags may request special modes. local is
|
||||
* the thread-local data structure, allowing to preserve and reuse a memory
|
||||
* allocation across calls, thereby reducing processing overhead.
|
||||
*
|
||||
* Return 0 on success; or -1 on error.
|
||||
*
|
||||
* Classic scrypt is available by setting shared = NULL, flags = 0, and t = 0.
|
||||
*
|
||||
* Setting YESCRYPT_WORM enables only minimal deviations from classic scrypt:
|
||||
* support for the t parameter, and pre- and post-hashing.
|
||||
*
|
||||
* Setting YESCRYPT_RW fully enables yescrypt. As a side effect of differences
|
||||
* between the algorithms, it also prevents p > 1 from growing the threads'
|
||||
* combined processing time and memory allocation (like it did with classic
|
||||
* scrypt and YESCRYPT_WORM), treating p as a divider rather than a multiplier.
|
||||
*
|
||||
* Passing a shared structure, with ROM contents previously computed by
|
||||
* yescrypt_init_shared(), enables the use of ROM and requires YESCRYPT_RW.
|
||||
*
|
||||
* In order to allow for initialization of the ROM to be split into a separate
|
||||
* program (or separate invocation of the same program), the shared->aligned
|
||||
* and shared->aligned_size fields may optionally be set by the caller directly
|
||||
* (e.g., to a mapped SysV shm segment), without using yescrypt_init_shared().
|
||||
*
|
||||
* local must be initialized with yescrypt_init_local().
|
||||
*
|
||||
* MT-safe as long as local and buf are local to the thread.
|
||||
*/
|
||||
extern int yescrypt_kdf(const yescrypt_shared_t *shared,
|
||||
yescrypt_local_t *local,
|
||||
const uint8_t *passwd, size_t passwdlen,
|
||||
const uint8_t *salt, size_t saltlen,
|
||||
const yescrypt_params_t *params,
|
||||
uint8_t *buf, size_t buflen);
|
||||
|
||||
/**
|
||||
* yescrypt_r(shared, local, passwd, passwdlen, setting, key, buf, buflen):
|
||||
* Compute and encode an scrypt or enhanced scrypt hash of passwd given the
|
||||
* parameters and salt value encoded in setting. If shared is not NULL, a ROM
|
||||
* is used and YESCRYPT_RW is required. Otherwise, whether to compute classic
|
||||
* scrypt, YESCRYPT_WORM (a slight deviation from classic scrypt), or
|
||||
* YESCRYPT_RW (time-memory tradeoff discouraging modification) is determined
|
||||
* by the setting string. shared (if not NULL) and local must be initialized
|
||||
* as described above for yescrypt_kdf(). buf must be large enough (as
|
||||
* indicated by buflen) to hold the encoded hash string.
|
||||
*
|
||||
* Return the encoded hash string on success; or NULL on error.
|
||||
*
|
||||
* MT-safe as long as local and buf are local to the thread.
|
||||
*/
|
||||
extern uint8_t *yescrypt_r(const yescrypt_shared_t *shared,
|
||||
yescrypt_local_t *local,
|
||||
const uint8_t *passwd, size_t passwdlen,
|
||||
const uint8_t *setting,
|
||||
const yescrypt_binary_t *key,
|
||||
uint8_t *buf, size_t buflen);
|
||||
|
||||
/**
|
||||
* yescrypt(passwd, setting):
|
||||
* Compute and encode an scrypt or enhanced scrypt hash of passwd given the
|
||||
* parameters and salt value encoded in setting. Whether to compute classic
|
||||
* scrypt, YESCRYPT_WORM (a slight deviation from classic scrypt), or
|
||||
* YESCRYPT_RW (time-memory tradeoff discouraging modification) is determined
|
||||
* by the setting string.
|
||||
*
|
||||
* Return the encoded hash string on success; or NULL on error.
|
||||
*
|
||||
* This is a crypt(3)-like interface, which is simpler to use than
|
||||
* yescrypt_r(), but it is not MT-safe, it does not allow for the use of a ROM,
|
||||
* and it is slower than yescrypt_r() for repeated calls because it allocates
|
||||
* and frees memory on each call.
|
||||
*
|
||||
* MT-unsafe.
|
||||
*/
|
||||
extern uint8_t *yescrypt(const uint8_t *passwd, const uint8_t *setting);
|
||||
|
||||
/**
|
||||
* yescrypt_reencrypt(hash, from_key, to_key):
|
||||
* Re-encrypt a yescrypt hash from one key to another. Either key may be NULL
|
||||
* to indicate unencrypted hash. The encoded hash string is modified in-place.
|
||||
*
|
||||
* Return the hash pointer on success; or NULL on error (in which case the hash
|
||||
* string is left unmodified).
|
||||
*
|
||||
* MT-safe as long as hash is local to the thread.
|
||||
*/
|
||||
extern uint8_t *yescrypt_reencrypt(uint8_t *hash,
|
||||
const yescrypt_binary_t *from_key,
|
||||
const yescrypt_binary_t *to_key);
|
||||
|
||||
/**
|
||||
* yescrypt_encode_params_r(params, src, srclen, buf, buflen):
|
||||
* Generate a setting string for use with yescrypt_r() and yescrypt() by
|
||||
* encoding into it the parameters flags, N, r, p, t, g, and a salt given by
|
||||
* src (of srclen bytes). buf must be large enough (as indicated by buflen)
|
||||
* to hold the setting string.
|
||||
*
|
||||
* Return the setting string on success; or NULL on error.
|
||||
*
|
||||
* MT-safe as long as buf is local to the thread.
|
||||
*/
|
||||
extern uint8_t *yescrypt_encode_params_r(const yescrypt_params_t *params,
|
||||
const uint8_t *src, size_t srclen,
|
||||
uint8_t *buf, size_t buflen);
|
||||
|
||||
/**
|
||||
* yescrypt_encode_params(params, src, srclen):
|
||||
* Generate a setting string for use with yescrypt_r() and yescrypt(). This
|
||||
* function is the same as yescrypt_encode_params_r() except that it uses a
|
||||
* static buffer and thus is not MT-safe.
|
||||
*
|
||||
* Return the setting string on success; or NULL on error.
|
||||
*
|
||||
* MT-unsafe.
|
||||
*/
|
||||
extern uint8_t *yescrypt_encode_params(const yescrypt_params_t *params,
|
||||
const uint8_t *src, size_t srclen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !_YESCRYPT_H_ */
|
||||
Reference in New Issue
Block a user