mirror of https://github.com/GOSTSec/sgminer
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
360 lines
8.2 KiB
360 lines
8.2 KiB
/*- |
|
* Copyright 2013,2014 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 <stdio.h> |
|
#include "algorithm/yescrypt_core.h" |
|
|
|
#define BYTES2CHARS(bytes) \ |
|
((((bytes) * 8) + 5) / 6) |
|
|
|
#define HASH_SIZE 32 /* bytes */ |
|
#define HASH_LEN BYTES2CHARS(HASH_SIZE) /* base-64 chars */ |
|
#define YESCRYPT_FLAGS (YESCRYPT_RW | YESCRYPT_PWXFORM) |
|
static const char * const itoa64 = |
|
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; |
|
|
|
static uint8_t * encode64_uint32(uint8_t * dst, size_t dstlen, |
|
uint32_t src, uint32_t srcbits) |
|
{ |
|
uint32_t bit; |
|
|
|
for (bit = 0; bit < srcbits; bit += 6) { |
|
if (dstlen < 1) |
|
return NULL; |
|
*dst++ = itoa64[src & 0x3f]; |
|
dstlen--; |
|
src >>= 6; |
|
} |
|
|
|
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(dst, dstlen, value, bits); |
|
if (!dnext) |
|
return NULL; |
|
dstlen -= dnext - dst; |
|
dst = dnext; |
|
} |
|
|
|
return dst; |
|
} |
|
|
|
static int decode64_one(uint32_t * dst, uint8_t src) |
|
{ |
|
const char * ptr = strchr(itoa64, src); |
|
if (ptr) { |
|
*dst = ptr - itoa64; |
|
return 0; |
|
} |
|
*dst = 0; |
|
return -1; |
|
} |
|
|
|
static const uint8_t * decode64_uint32(uint32_t * dst, uint32_t dstbits, |
|
const uint8_t * src) |
|
{ |
|
uint32_t bit; |
|
uint32_t value; |
|
|
|
value = 0; |
|
for (bit = 0; bit < dstbits; bit += 6) { |
|
uint32_t one; |
|
if (decode64_one(&one, *src)) { |
|
*dst = 0; |
|
return NULL; |
|
} |
|
src++; |
|
value |= one << bit; |
|
} |
|
|
|
*dst = value; |
|
return src; |
|
} |
|
|
|
uint8_t * |
|
yescrypt_r(const yescrypt_shared_t * shared, yescrypt_local_t * local, |
|
const uint8_t * passwd, size_t passwdlen, |
|
const uint8_t * setting, |
|
uint8_t * buf, size_t buflen) |
|
{ |
|
uint8_t hash[HASH_SIZE]; |
|
const uint8_t * src, * salt; |
|
uint8_t * dst; |
|
size_t prefixlen, saltlen, need; |
|
uint8_t version; |
|
uint64_t N; |
|
uint32_t r, p; |
|
yescrypt_flags_t flags = YESCRYPT_WORM; |
|
fflush(stdout); |
|
if (setting[0] != '$' || setting[1] != '7') |
|
{ |
|
fflush(stdout); |
|
return NULL; |
|
} |
|
fflush(stdout); |
|
src = setting + 2; |
|
fflush(stdout); |
|
switch ((version = *src)) { |
|
case '$': |
|
fflush(stdout); |
|
break; |
|
case 'X': |
|
src++; |
|
flags = YESCRYPT_RW; |
|
fflush(stdout); |
|
break; |
|
default: |
|
{ |
|
fflush(stdout); |
|
return NULL; |
|
} |
|
} |
|
|
|
fflush(stdout); |
|
if (*src != '$') { |
|
uint32_t decoded_flags; |
|
if (decode64_one(&decoded_flags, *src)) |
|
|
|
{ |
|
fflush(stdout); |
|
return NULL; |
|
} |
|
flags = decoded_flags; |
|
if (*++src != '$') |
|
{ |
|
fflush(stdout); |
|
return NULL; |
|
} |
|
} |
|
src++; |
|
|
|
{ |
|
uint32_t N_log2; |
|
if (decode64_one(&N_log2, *src)) |
|
{ |
|
return NULL; |
|
} |
|
src++; |
|
N = (uint64_t)1 << N_log2; |
|
} |
|
|
|
src = decode64_uint32(&r, 30, src); |
|
if (!src) |
|
{ |
|
return NULL; |
|
} |
|
|
|
src = decode64_uint32(&p, 30, src); |
|
if (!src) |
|
{ |
|
return NULL; |
|
} |
|
|
|
prefixlen = src - setting; |
|
|
|
salt = src; |
|
src = (uint8_t *)strrchr((char *)salt, '$'); |
|
if (src) |
|
saltlen = src - salt; |
|
else |
|
saltlen = strlen((char *)salt); |
|
|
|
need = prefixlen + saltlen + 1 + HASH_LEN + 1; |
|
if (need > buflen || need < saltlen) |
|
|
|
{ |
|
fflush(stdout); |
|
return NULL; |
|
} |
|
|
|
fflush(stdout); |
|
if (yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen, |
|
N, r, p, 0, flags, hash, sizeof(hash))) |
|
{ |
|
fflush(stdout); |
|
return NULL; |
|
} |
|
|
|
dst = buf; |
|
memcpy(dst, setting, prefixlen + saltlen); |
|
dst += prefixlen + saltlen; |
|
*dst++ = '$'; |
|
|
|
dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash)); |
|
/* Could zeroize hash[] here, but yescrypt_kdf() doesn't zeroize its |
|
* memory allocations yet anyway. */ |
|
if (!dst || dst >= buf + buflen) /* Can't happen */ |
|
{ |
|
return NULL; |
|
} |
|
|
|
*dst = 0; /* NUL termination */ |
|
fflush(stdout); |
|
return buf; |
|
} |
|
|
|
uint8_t * |
|
yescrypt(const uint8_t * passwd, const uint8_t * setting) |
|
{ |
|
static uint8_t buf[4 + 1 + 5 + 5 + BYTES2CHARS(32) + 1 + HASH_LEN + 1]; |
|
yescrypt_shared_t shared; |
|
yescrypt_local_t local; |
|
uint8_t * retval; |
|
if (yescrypt_init_shared(&shared, NULL, 0, |
|
0, 0, 0, YESCRYPT_SHARED_DEFAULTS, 0, NULL, 0)) |
|
return NULL; |
|
if (yescrypt_init_local(&local)) { |
|
yescrypt_free_shared(&shared); |
|
return NULL; |
|
} |
|
retval = yescrypt_r(&shared, &local, |
|
passwd, 80, setting, buf, sizeof(buf)); |
|
// printf("hashse='%s'\n", (char *)retval); |
|
if (yescrypt_free_local(&local)) { |
|
yescrypt_free_shared(&shared); |
|
return NULL; |
|
} |
|
if (yescrypt_free_shared(&shared)) |
|
return NULL; |
|
return retval; |
|
|
|
} |
|
|
|
uint8_t * |
|
yescrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p, |
|
yescrypt_flags_t flags, |
|
const uint8_t * src, size_t srclen, |
|
uint8_t * buf, size_t buflen) |
|
{ |
|
uint8_t * dst; |
|
size_t prefixlen = 3 + 1 + 5 + 5; |
|
size_t saltlen = BYTES2CHARS(srclen); |
|
size_t need; |
|
|
|
if (p == 1) |
|
flags &= ~YESCRYPT_PARALLEL_SMIX; |
|
|
|
if (flags) { |
|
if (flags & ~0x3f) |
|
return NULL; |
|
|
|
prefixlen++; |
|
if (flags != YESCRYPT_RW) |
|
prefixlen++; |
|
} |
|
|
|
need = prefixlen + saltlen + 1; |
|
if (need > buflen || need < saltlen || saltlen < srclen) |
|
return NULL; |
|
|
|
if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30))) |
|
return NULL; |
|
|
|
dst = buf; |
|
*dst++ = '$'; |
|
*dst++ = '7'; |
|
if (flags) { |
|
*dst++ = 'X'; /* eXperimental, subject to change */ |
|
if (flags != YESCRYPT_RW) |
|
*dst++ = itoa64[flags]; |
|
} |
|
*dst++ = '$'; |
|
|
|
*dst++ = itoa64[N_log2]; |
|
|
|
dst = encode64_uint32(dst, buflen - (dst - buf), r, 30); |
|
if (!dst) /* Can't happen */ |
|
return NULL; |
|
|
|
dst = encode64_uint32(dst, buflen - (dst - buf), p, 30); |
|
if (!dst) /* Can't happen */ |
|
return NULL; |
|
|
|
dst = encode64(dst, buflen - (dst - buf), src, srclen); |
|
if (!dst || dst >= buf + buflen) /* Can't happen */ |
|
return NULL; |
|
|
|
*dst = 0; /* NUL termination */ |
|
|
|
return buf; |
|
} |
|
|
|
uint8_t * |
|
yescrypt_gensalt(uint32_t N_log2, uint32_t r, uint32_t p, |
|
yescrypt_flags_t flags, |
|
const uint8_t * src, size_t srclen) |
|
{ |
|
static uint8_t buf[4 + 1 + 5 + 5 + BYTES2CHARS(32) + 1]; |
|
return yescrypt_gensalt_r(N_log2, r, p, flags, src, srclen, |
|
buf, sizeof(buf)); |
|
} |
|
|
|
static int |
|
yescrypt_bsty(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) |
|
{ |
|
static __thread int initialized = 0; |
|
static __thread yescrypt_shared_t shared; |
|
static __thread yescrypt_local_t local; |
|
|
|
// static __declspec(thread) int initialized = 0; |
|
// static __declspec(thread) yescrypt_shared_t shared; |
|
// static __declspec(thread) yescrypt_local_t local; |
|
|
|
int retval; |
|
if (!initialized) { |
|
/* "shared" could in fact be shared, but it's simpler to keep it private |
|
* along with "local". It's dummy and tiny anyway. */ |
|
if (yescrypt_init_shared(&shared, NULL, 0, |
|
0, 0, 0, YESCRYPT_SHARED_DEFAULTS, 0, NULL, 0)) |
|
return -1; |
|
if (yescrypt_init_local(&local)) { |
|
yescrypt_free_shared(&shared); |
|
return -1; |
|
} |
|
initialized = 1; |
|
} |
|
retval = yescrypt_kdf(&shared, &local, |
|
passwd, passwdlen, salt, saltlen, N, r, p, 0, YESCRYPT_FLAGS, |
|
buf, buflen); |
|
|
|
return retval; |
|
} |
|
|
|
void yescrypt_hash(const unsigned char *input, unsigned char *output) |
|
{ |
|
|
|
yescrypt_bsty((const uint8_t *)input, 80, (const uint8_t *) input, 80, 2048, 8, 1, (uint8_t *)output, 32); |
|
}
|
|
|