Use SSE2 or portable scrypt implementation according to what the CPU supports.
This commit is contained in:
parent
42e4ebe3e3
commit
cb4f3e4f06
@ -244,6 +244,7 @@ dnl Checks for headers
|
|||||||
|
|
||||||
AS_IF([test "x$EMSCRIPTEN" = "x"],[
|
AS_IF([test "x$EMSCRIPTEN" = "x"],[
|
||||||
AC_CHECK_HEADERS([emmintrin.h], [], [], [#pragma GCC target("sse2")])
|
AC_CHECK_HEADERS([emmintrin.h], [], [], [#pragma GCC target("sse2")])
|
||||||
|
AC_CHECK_HEADERS([pmmintrin.h], [], [], [#pragma GCC target("sse3")])
|
||||||
AC_CHECK_HEADERS([tmmintrin.h], [], [], [#pragma GCC target("ssse3")])
|
AC_CHECK_HEADERS([tmmintrin.h], [], [], [#pragma GCC target("ssse3")])
|
||||||
AC_CHECK_HEADERS([smmintrin.h], [], [], [#pragma GCC target("sse4.1")])
|
AC_CHECK_HEADERS([smmintrin.h], [], [], [#pragma GCC target("sse4.1")])
|
||||||
AC_CHECK_HEADERS([immintrin.h], [], [], [#pragma GCC target("avx")])
|
AC_CHECK_HEADERS([immintrin.h], [], [], [#pragma GCC target("avx")])
|
||||||
|
@ -22,86 +22,85 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "crypto_scrypt.h"
|
#include "crypto_scrypt.h"
|
||||||
|
#include "runtime.h"
|
||||||
#define escrypt_kdf escrypt_kdf_nosse
|
|
||||||
|
|
||||||
#define BYTES2CHARS(bytes) \
|
#define BYTES2CHARS(bytes) \
|
||||||
((((bytes) * 8) + 5) / 6)
|
((((bytes) * 8) + 5) / 6)
|
||||||
|
|
||||||
#define HASH_SIZE 32 /* bytes */
|
#define HASH_SIZE 32 /* bytes */
|
||||||
#define HASH_LEN BYTES2CHARS(HASH_SIZE) /* base-64 chars */
|
#define HASH_LEN BYTES2CHARS(HASH_SIZE) /* base-64 chars */
|
||||||
|
|
||||||
static const char * const itoa64 =
|
static const char * const itoa64 =
|
||||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
static uint8_t * encode64_uint32(uint8_t * dst, size_t dstlen,
|
static uint8_t * encode64_uint32(uint8_t * dst, size_t dstlen,
|
||||||
uint32_t src, uint32_t srcbits)
|
uint32_t src, uint32_t srcbits)
|
||||||
{
|
{
|
||||||
uint32_t bit;
|
uint32_t bit;
|
||||||
|
|
||||||
for (bit = 0; bit < srcbits; bit += 6) {
|
for (bit = 0; bit < srcbits; bit += 6) {
|
||||||
if (dstlen < 1)
|
if (dstlen < 1)
|
||||||
return NULL;
|
return NULL;
|
||||||
*dst++ = itoa64[src & 0x3f];
|
*dst++ = itoa64[src & 0x3f];
|
||||||
dstlen--;
|
dstlen--;
|
||||||
src >>= 6;
|
src >>= 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t * encode64(uint8_t * dst, size_t dstlen,
|
static uint8_t * encode64(uint8_t * dst, size_t dstlen,
|
||||||
const uint8_t * src, size_t srclen)
|
const uint8_t * src, size_t srclen)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < srclen; ) {
|
for (i = 0; i < srclen; ) {
|
||||||
uint8_t * dnext;
|
uint8_t * dnext;
|
||||||
uint32_t value = 0, bits = 0;
|
uint32_t value = 0, bits = 0;
|
||||||
do {
|
do {
|
||||||
value |= (uint32_t)src[i++] << bits;
|
value |= (uint32_t)src[i++] << bits;
|
||||||
bits += 8;
|
bits += 8;
|
||||||
} while (bits < 24 && i < srclen);
|
} while (bits < 24 && i < srclen);
|
||||||
dnext = encode64_uint32(dst, dstlen, value, bits);
|
dnext = encode64_uint32(dst, dstlen, value, bits);
|
||||||
if (!dnext)
|
if (!dnext)
|
||||||
return NULL;
|
return NULL;
|
||||||
dstlen -= dnext - dst;
|
dstlen -= dnext - dst;
|
||||||
dst = dnext;
|
dst = dnext;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode64_one(uint32_t * dst, uint8_t src)
|
static int decode64_one(uint32_t * dst, uint8_t src)
|
||||||
{
|
{
|
||||||
const char * ptr = strchr(itoa64, src);
|
const char * ptr = strchr(itoa64, src);
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
*dst = ptr - itoa64;
|
*dst = ptr - itoa64;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*dst = 0;
|
*dst = 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t * decode64_uint32(uint32_t * dst, uint32_t dstbits,
|
static const uint8_t * decode64_uint32(uint32_t * dst, uint32_t dstbits,
|
||||||
const uint8_t * src)
|
const uint8_t * src)
|
||||||
{
|
{
|
||||||
uint32_t bit;
|
uint32_t bit;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
|
|
||||||
value = 0;
|
value = 0;
|
||||||
for (bit = 0; bit < dstbits; bit += 6) {
|
for (bit = 0; bit < dstbits; bit += 6) {
|
||||||
uint32_t one;
|
uint32_t one;
|
||||||
if (decode64_one(&one, *src)) {
|
if (decode64_one(&one, *src)) {
|
||||||
*dst = 0;
|
*dst = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
src++;
|
src++;
|
||||||
value |= one << bit;
|
value |= one << bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
*dst = value;
|
*dst = value;
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *
|
uint8_t *
|
||||||
@ -110,64 +109,68 @@ escrypt_r(escrypt_local_t * local,
|
|||||||
const uint8_t * setting,
|
const uint8_t * setting,
|
||||||
uint8_t * buf, size_t buflen)
|
uint8_t * buf, size_t buflen)
|
||||||
{
|
{
|
||||||
uint8_t hash[HASH_SIZE];
|
uint8_t hash[HASH_SIZE];
|
||||||
const uint8_t * src, * salt;
|
escrypt_kdf_t escrypt_kdf;
|
||||||
uint8_t * dst;
|
const uint8_t * src, * salt;
|
||||||
size_t prefixlen, saltlen, need;
|
uint8_t * dst;
|
||||||
uint64_t N;
|
size_t prefixlen, saltlen, need;
|
||||||
uint32_t r, p;
|
uint64_t N;
|
||||||
|
uint32_t r, p;
|
||||||
|
|
||||||
if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$')
|
if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$')
|
||||||
return NULL;
|
return NULL;
|
||||||
src = setting + 3;
|
src = setting + 3;
|
||||||
|
|
||||||
{
|
{
|
||||||
uint32_t N_log2;
|
uint32_t N_log2;
|
||||||
if (decode64_one(&N_log2, *src))
|
if (decode64_one(&N_log2, *src))
|
||||||
return NULL;
|
return NULL;
|
||||||
src++;
|
src++;
|
||||||
N = (uint64_t)1 << N_log2;
|
N = (uint64_t)1 << N_log2;
|
||||||
}
|
}
|
||||||
|
|
||||||
src = decode64_uint32(&r, 30, src);
|
src = decode64_uint32(&r, 30, src);
|
||||||
if (!src)
|
if (!src)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
src = decode64_uint32(&p, 30, src);
|
src = decode64_uint32(&p, 30, src);
|
||||||
if (!src)
|
if (!src)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
prefixlen = src - setting;
|
prefixlen = src - setting;
|
||||||
|
|
||||||
salt = src;
|
salt = src;
|
||||||
src = (uint8_t *)strrchr((char *)salt, '$');
|
src = (uint8_t *)strrchr((char *)salt, '$');
|
||||||
if (src)
|
if (src)
|
||||||
saltlen = src - salt;
|
saltlen = src - salt;
|
||||||
else
|
else
|
||||||
saltlen = strlen((char *)salt);
|
saltlen = strlen((char *)salt);
|
||||||
|
|
||||||
need = prefixlen + saltlen + 1 + HASH_LEN + 1;
|
need = prefixlen + saltlen + 1 + HASH_LEN + 1;
|
||||||
if (need > buflen || need < saltlen)
|
if (need > buflen || need < saltlen)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
|
escrypt_kdf =
|
||||||
N, r, p, hash, sizeof(hash)))
|
sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
|
||||||
return NULL;
|
if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen,
|
||||||
|
N, r, p, hash, sizeof(hash))) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
dst = buf;
|
dst = buf;
|
||||||
memcpy(dst, setting, prefixlen + saltlen);
|
memcpy(dst, setting, prefixlen + saltlen);
|
||||||
dst += prefixlen + saltlen;
|
dst += prefixlen + saltlen;
|
||||||
*dst++ = '$';
|
*dst++ = '$';
|
||||||
|
|
||||||
dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash));
|
dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash));
|
||||||
/* Could zeroize hash[] here, but escrypt_kdf() doesn't zeroize its
|
/* Could zeroize hash[] here, but escrypt_kdf() doesn't zeroize its
|
||||||
* memory allocations yet anyway. */
|
* memory allocations yet anyway. */
|
||||||
if (!dst || dst >= buf + buflen) /* Can't happen */
|
if (!dst || dst >= buf + buflen) /* Can't happen */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*dst = 0; /* NUL termination */
|
*dst = 0; /* NUL termination */
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *
|
uint8_t *
|
||||||
@ -175,40 +178,40 @@ escrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p,
|
|||||||
const uint8_t * src, size_t srclen,
|
const uint8_t * src, size_t srclen,
|
||||||
uint8_t * buf, size_t buflen)
|
uint8_t * buf, size_t buflen)
|
||||||
{
|
{
|
||||||
uint8_t * dst;
|
uint8_t * dst;
|
||||||
size_t prefixlen = 3 + 1 + 5 + 5;
|
size_t prefixlen = 3 + 1 + 5 + 5;
|
||||||
size_t saltlen = BYTES2CHARS(srclen);
|
size_t saltlen = BYTES2CHARS(srclen);
|
||||||
size_t need;
|
size_t need;
|
||||||
|
|
||||||
need = prefixlen + saltlen + 1;
|
need = prefixlen + saltlen + 1;
|
||||||
if (need > buflen || need < saltlen || saltlen < srclen)
|
if (need > buflen || need < saltlen || saltlen < srclen)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30)))
|
if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dst = buf;
|
dst = buf;
|
||||||
*dst++ = '$';
|
*dst++ = '$';
|
||||||
*dst++ = '7';
|
*dst++ = '7';
|
||||||
*dst++ = '$';
|
*dst++ = '$';
|
||||||
|
|
||||||
*dst++ = itoa64[N_log2];
|
*dst++ = itoa64[N_log2];
|
||||||
|
|
||||||
dst = encode64_uint32(dst, buflen - (dst - buf), r, 30);
|
dst = encode64_uint32(dst, buflen - (dst - buf), r, 30);
|
||||||
if (!dst) /* Can't happen */
|
if (!dst) /* Can't happen */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dst = encode64_uint32(dst, buflen - (dst - buf), p, 30);
|
dst = encode64_uint32(dst, buflen - (dst - buf), p, 30);
|
||||||
if (!dst) /* Can't happen */
|
if (!dst) /* Can't happen */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
dst = encode64(dst, buflen - (dst - buf), src, srclen);
|
dst = encode64(dst, buflen - (dst - buf), src, srclen);
|
||||||
if (!dst || dst >= buf + buflen) /* Can't happen */
|
if (!dst || dst >= buf + buflen) /* Can't happen */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*dst = 0; /* NUL termination */
|
*dst = 0; /* NUL termination */
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -216,14 +219,17 @@ 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,
|
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
|
||||||
uint8_t * buf, size_t buflen)
|
uint8_t * buf, size_t buflen)
|
||||||
{
|
{
|
||||||
escrypt_local_t local;
|
escrypt_kdf_t escrypt_kdf;
|
||||||
int retval;
|
escrypt_local_t local;
|
||||||
|
int retval;
|
||||||
|
|
||||||
if (escrypt_init_local(&local))
|
if (escrypt_init_local(&local))
|
||||||
return -1;
|
return -1;
|
||||||
retval = escrypt_kdf(&local,
|
escrypt_kdf =
|
||||||
passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen);
|
sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
|
||||||
if (escrypt_free_local(&local))
|
retval = escrypt_kdf(&local,
|
||||||
return -1;
|
passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen);
|
||||||
return retval;
|
if (escrypt_free_local(&local))
|
||||||
|
return -1;
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,12 @@ extern int escrypt_free_local(escrypt_local_t * __local);
|
|||||||
extern void *alloc_region(escrypt_region_t * region, size_t size);
|
extern void *alloc_region(escrypt_region_t * region, size_t size);
|
||||||
extern int free_region(escrypt_region_t * region);
|
extern int free_region(escrypt_region_t * region);
|
||||||
|
|
||||||
|
typedef int (*escrypt_kdf_t)(escrypt_local_t * __local,
|
||||||
|
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);
|
||||||
|
|
||||||
extern int escrypt_kdf_nosse(escrypt_local_t * __local,
|
extern int escrypt_kdf_nosse(escrypt_local_t * __local,
|
||||||
const uint8_t * __passwd, size_t __passwdlen,
|
const uint8_t * __passwd, size_t __passwdlen,
|
||||||
const uint8_t * __salt, size_t __saltlen,
|
const uint8_t * __salt, size_t __saltlen,
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "crypto_scrypt.h"
|
#include "crypto_scrypt.h"
|
||||||
|
#include "runtime.h"
|
||||||
|
|
||||||
void *
|
void *
|
||||||
alloc_region(escrypt_region_t * region, size_t size)
|
alloc_region(escrypt_region_t * region, size_t size)
|
||||||
|
@ -66,8 +66,18 @@ _sodium_runtime_intel_cpu_features(CPUFeatures * const cpu_features)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
_cpuid(cpu_info, 0x00000001);
|
_cpuid(cpu_info, 0x00000001);
|
||||||
|
|
||||||
|
#ifndef HAVE_EMMINTRIN_H
|
||||||
cpu_features->has_sse2 = ((cpu_info[3] & CPUID_SSE2) != 0x0);
|
cpu_features->has_sse2 = ((cpu_info[3] & CPUID_SSE2) != 0x0);
|
||||||
|
#else
|
||||||
|
cpu_features->has_sse2 = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_PMMINTRIN_H
|
||||||
cpu_features->has_sse3 = ((cpu_info[2] & CPUIDECX_SSE3) != 0x0);
|
cpu_features->has_sse3 = ((cpu_info[2] & CPUIDECX_SSE3) != 0x0);
|
||||||
|
#else
|
||||||
|
cpu_features->has_sse3 = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user