From 9affdc735bc5731580619057405d16cf588afe9b Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Wed, 8 Jul 2015 19:54:40 +0100 Subject: Change to using libscrypt even though it has known failure modes --- COPYING | 28 ++ Makefile | 37 +-- example.lua | 5 +- lib/README | 6 - lib/crypto/crypto_aesctr.c | 123 -------- lib/crypto/crypto_aesctr.h | 59 ---- lib/crypto/crypto_scrypt-nosse.c | 337 --------------------- lib/crypto/crypto_scrypt-ref.c | 283 ------------------ lib/crypto/crypto_scrypt-sse.c | 365 ----------------------- lib/crypto/crypto_scrypt.h | 46 --- lib/crypto/sha256.c | 411 -------------------------- lib/crypto/sha256.h | 62 ---- lib/scryptenc/scryptenc.c | 605 -------------------------------------- lib/scryptenc/scryptenc.h | 112 ------- lib/scryptenc/scryptenc_cpuperf.c | 184 ------------ lib/scryptenc/scryptenc_cpuperf.h | 39 --- lib/util/memlimit.c | 301 ------------------- lib/util/memlimit.h | 42 --- lib/util/readpass.c | 142 --------- lib/util/readpass.h | 45 --- lib/util/sysendian.h | 138 --------- lib/util/warn.c | 74 ----- lib/util/warn.h | 13 - luascrypt.c | 271 +++++++---------- 24 files changed, 144 insertions(+), 3584 deletions(-) create mode 100644 COPYING delete mode 100644 lib/README delete mode 100644 lib/crypto/crypto_aesctr.c delete mode 100644 lib/crypto/crypto_aesctr.h delete mode 100644 lib/crypto/crypto_scrypt-nosse.c delete mode 100644 lib/crypto/crypto_scrypt-ref.c delete mode 100644 lib/crypto/crypto_scrypt-sse.c delete mode 100644 lib/crypto/crypto_scrypt.h delete mode 100644 lib/crypto/sha256.c delete mode 100644 lib/crypto/sha256.h delete mode 100644 lib/scryptenc/scryptenc.c delete mode 100644 lib/scryptenc/scryptenc.h delete mode 100644 lib/scryptenc/scryptenc_cpuperf.c delete mode 100644 lib/scryptenc/scryptenc_cpuperf.h delete mode 100644 lib/util/memlimit.c delete mode 100644 lib/util/memlimit.h delete mode 100644 lib/util/readpass.c delete mode 100644 lib/util/readpass.h delete mode 100644 lib/util/sysendian.h delete mode 100644 lib/util/warn.c delete mode 100644 lib/util/warn.h diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..80ff910 --- /dev/null +++ b/COPYING @@ -0,0 +1,28 @@ +Copyright 2015 Daniel Silverstone +All rights reserved. + +Based on code by Rob Kendrick + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the author nor the names of their contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. diff --git a/Makefile b/Makefile index 46171fc..070b1b2 100644 --- a/Makefile +++ b/Makefile @@ -100,43 +100,18 @@ LIBCRYPT_C := lib/crypto/crypto_aesctr.c \ lib/crypto/crypto_scrypt-ref.c \ lib/crypto/sha256.c -ifneq ($(USE_SSE),) - LIBCRYPT_C := $(subst -nosse.c$,-sse.c,$(LIBCRYPT_C)) -endif - -LIBCRYPT_O := $(subst .c$,.o,$(LIBCRYPT_C)) - -LIBSCRYPTENC_C := lib/scryptenc/scryptenc.c lib/scryptenc/scryptenc_cpuperf.c -LIBSCRYPTENC_O := $(subst .c$,.o,$(LIBSCRYPTENC_C)) - -LIBUTIL_C := lib/util/memlimit.c lib/util/readpass.c lib/util/warn.c -LIBUTIL_O := $(subst .c$,.o,$(LIBUTIL_C)) - -SCRYPT_LIBS := libcrypt.a libscryptenc.a libutil.a - CFLAGS ?= -O2 -Wall INSTALL := /usr/bin/install +SCRYPT_LIBS := -lscrypt all: lua-5.1-try lua-5.2-try clean: - $(RM) scrypt-5.1.so scrypt-5.2.so scrypt.so - $(RM) $(SCRYPT_LIBS) - $(RM) $(LIBCRYPT_O) - $(RM) $(LIBSCRYPTENC_O) - $(RM) $(LIBUTIL_O) + $(RM) scrypt-5.1.so scrypt-5.2.so scrypt.so + $(RM) luascrypt.o %.o: %.c - $(CC) $(CFLAGS) -fPIC $(LUA51_INC) -I lib/util -I lib/crypto -I lib/scryptenc -c $< -o $@ - -libcrypt.a: $(LIBCRYPT_O) - $(AR) q libcrypt.a $(LIBCRYPT_O) - -libscryptenc.a: $(LIBSCRYPTENC_O) - $(AR) q libscryptenc.a $(LIBSCRYPTENC_O) - -libutil.a: $(LIBUTIL_O) - $(AR) q libutil.a $(LIBUTIL_O) + $(CC) $(CFLAGS) -fPIC $(LUA51_INC) -c $< -o $@ lua-5.1: scrypt-5.1.so ln -s -f scrypt-5.1.so scrypt.so @@ -145,7 +120,7 @@ lua-5.1-install: lua-5.1 $(INSTALL) -d $(DESTDIR)$(LUA51_CMOD_INST) $(INSTALL) -m 755 scrypt-5.1.so $(DESTDIR)$(LUA51_CMOD_INST)/scrypt.so -scrypt-5.1.so: luascrypt.o $(SCRYPT_LIBS) +scrypt-5.1.so: luascrypt.o $(CC) $(CFLAGS) -shared -o $@ $^ $(LUA51_LIB) $(SCRYPT_LIBS) lua-5.2: scrypt-5.2.so @@ -155,7 +130,7 @@ lua-5.2-install: lua-5.2 $(INSTALL) -d $(DESTDIR)$(LUA52_CMOD_INST) $(INSTALL) -m 755 scrypt-5.2.so $(DESTDIR)$(LUA52_CMOD_INST)/scrypt.so -scrypt-5.2.so: luascrypt.o $(SCRYPT_LIBS) +scrypt-5.2.so: luascrypt.o $(CC) $(CFLAGS) -shared -o $@ $^ $(LUA51_LIB) $(SCRYPT_LIBS) diff --git a/example.lua b/example.lua index a38f811..a600ad7 100644 --- a/example.lua +++ b/example.lua @@ -14,7 +14,7 @@ time "Generate hash2" assert(hash1 ~= hash2) -- hashes are salted -local hash3 = scrypt.hash_password("Hello", 2^16, 8, 1) +local hash3 = scrypt.hash_password("Hello", 2^15, 8, 1) time "Generate hash3" assert(scrypt.verify_password(hash1, "Hello")) @@ -28,3 +28,6 @@ time "Verify hash3 with correct password" assert(scrypt.verify_password(hash3, "World") == false) time "Verify hash3 with incorrect password" + +local hash4 = scrypt.hash_password("Hello") +time "Generate hash 4, default N/r/p" diff --git a/lib/README b/lib/README deleted file mode 100644 index 3bb211e..0000000 --- a/lib/README +++ /dev/null @@ -1,6 +0,0 @@ -The source code under this directory is taken from the client for the -Tarsnap online backup system (and released under the 2-clause BSD license -with permission of the author); keeping this code in sync with the Tarsnap -code is highly desirable and explains why there is some functionality -included here which is not actually used by the scrypt file encryption -utility. diff --git a/lib/crypto/crypto_aesctr.c b/lib/crypto/crypto_aesctr.c deleted file mode 100644 index bc7479c..0000000 --- a/lib/crypto/crypto_aesctr.c +++ /dev/null @@ -1,123 +0,0 @@ -/*- - * Copyright 2007-2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#include -#include - -#include - -#include "sysendian.h" - -#include "crypto_aesctr.h" - -struct crypto_aesctr { - AES_KEY * key; - uint64_t nonce; - uint64_t bytectr; - uint8_t buf[16]; -}; - -/** - * crypto_aesctr_init(key, nonce): - * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided - * expanded key and nonce. The key provided must remain valid for the - * lifetime of the stream. - */ -struct crypto_aesctr * -crypto_aesctr_init(AES_KEY * key, uint64_t nonce) -{ - struct crypto_aesctr * stream; - - /* Allocate memory. */ - if ((stream = malloc(sizeof(struct crypto_aesctr))) == NULL) - goto err0; - - /* Initialize values. */ - stream->key = key; - stream->nonce = nonce; - stream->bytectr = 0; - - /* Success! */ - return (stream); - -err0: - /* Failure! */ - return (NULL); -} - -/** - * crypto_aesctr_stream(stream, inbuf, outbuf, buflen): - * Generate the next ${buflen} bytes of the AES-CTR stream and xor them with - * bytes from ${inbuf}, writing the result into ${outbuf}. If the buffers - * ${inbuf} and ${outbuf} overlap, they must be identical. - */ -void -crypto_aesctr_stream(struct crypto_aesctr * stream, const uint8_t * inbuf, - uint8_t * outbuf, size_t buflen) -{ - uint8_t pblk[16]; - size_t pos; - int bytemod; - - for (pos = 0; pos < buflen; pos++) { - /* How far through the buffer are we? */ - bytemod = stream->bytectr % 16; - - /* Generate a block of cipherstream if needed. */ - if (bytemod == 0) { - be64enc(pblk, stream->nonce); - be64enc(pblk + 8, stream->bytectr / 16); - AES_encrypt(pblk, stream->buf, stream->key); - } - - /* Encrypt a byte. */ - outbuf[pos] = inbuf[pos] ^ stream->buf[bytemod]; - - /* Move to the next byte of cipherstream. */ - stream->bytectr += 1; - } -} - -/** - * crypto_aesctr_free(stream): - * Free the provided stream object. - */ -void -crypto_aesctr_free(struct crypto_aesctr * stream) -{ - int i; - - /* Zero potentially sensitive information. */ - for (i = 0; i < 16; i++) - stream->buf[i] = 0; - stream->bytectr = stream->nonce = 0; - - /* Free the stream. */ - free(stream); -} diff --git a/lib/crypto/crypto_aesctr.h b/lib/crypto/crypto_aesctr.h deleted file mode 100644 index b50398f..0000000 --- a/lib/crypto/crypto_aesctr.h +++ /dev/null @@ -1,59 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ -#ifndef _CRYPTO_AESCTR_H_ -#define _CRYPTO_AESCTR_H_ - -#include - -#include - -/** - * crypto_aesctr_init(key, nonce): - * Prepare to encrypt/decrypt data with AES in CTR mode, using the provided - * expanded key and nonce. The key provided must remain valid for the - * lifetime of the stream. - */ -struct crypto_aesctr * crypto_aesctr_init(AES_KEY *, uint64_t); - -/** - * crypto_aesctr_stream(stream, inbuf, outbuf, buflen): - * Generate the next ${buflen} bytes of the AES-CTR stream and xor them with - * bytes from ${inbuf}, writing the result into ${outbuf}. If the buffers - * ${inbuf} and ${outbuf} overlap, they must be identical. - */ -void crypto_aesctr_stream(struct crypto_aesctr *, const uint8_t *, - uint8_t *, size_t); - -/** - * crypto_aesctr_free(stream): - * Free the provided stream object. - */ -void crypto_aesctr_free(struct crypto_aesctr *); - -#endif /* !_CRYPTO_AESCTR_H_ */ diff --git a/lib/crypto/crypto_scrypt-nosse.c b/lib/crypto/crypto_scrypt-nosse.c deleted file mode 100644 index 9389029..0000000 --- a/lib/crypto/crypto_scrypt-nosse.c +++ /dev/null @@ -1,337 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#include -#include - -#include -#include -#include -#include - -#include "sha256.h" -#include "sysendian.h" - -#include "crypto_scrypt.h" - -static void blkcpy(void *, void *, size_t); -static void blkxor(void *, void *, size_t); -static void salsa20_8(uint32_t[16]); -static void blockmix_salsa8(uint32_t *, uint32_t *, uint32_t *, size_t); -static uint64_t integerify(void *, size_t); -static void smix(uint8_t *, size_t, uint64_t, uint32_t *, uint32_t *); - -static void -blkcpy(void * dest, void * src, size_t len) -{ - size_t * D = dest; - size_t * S = src; - size_t L = len / sizeof(size_t); - size_t i; - - for (i = 0; i < L; i++) - D[i] = S[i]; -} - -static void -blkxor(void * dest, void * src, size_t len) -{ - size_t * D = dest; - size_t * S = src; - size_t L = len / sizeof(size_t); - size_t i; - - for (i = 0; i < L; i++) - D[i] ^= S[i]; -} - -/** - * salsa20_8(B): - * Apply the salsa20/8 core to the provided block. - */ -static void -salsa20_8(uint32_t B[16]) -{ - uint32_t x[16]; - size_t i; - - blkcpy(x, B, 64); - for (i = 0; i < 8; 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 - } - for (i = 0; i < 16; i++) - B[i] += x[i]; -} - -/** - * blockmix_salsa8(Bin, Bout, X, r): - * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r - * bytes in length; the output Bout must also be the same size. The - * temporary space X must be 64 bytes. - */ -static void -blockmix_salsa8(uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r) -{ - size_t i; - - /* 1: X <-- B_{2r - 1} */ - blkcpy(X, &Bin[(2 * r - 1) * 16], 64); - - /* 2: for i = 0 to 2r - 1 do */ - for (i = 0; i < 2 * r; i += 2) { - /* 3: X <-- H(X \xor B_i) */ - blkxor(X, &Bin[i * 16], 64); - salsa20_8(X); - - /* 4: Y_i <-- X */ - /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ - blkcpy(&Bout[i * 8], X, 64); - - /* 3: X <-- H(X \xor B_i) */ - blkxor(X, &Bin[i * 16 + 16], 64); - salsa20_8(X); - - /* 4: Y_i <-- X */ - /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ - blkcpy(&Bout[i * 8 + r * 16], X, 64); - } -} - -/** - * integerify(B, r): - * Return the result of parsing B_{2r-1} as a little-endian integer. - */ -static uint64_t -integerify(void * B, size_t r) -{ - uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64); - - return (((uint64_t)(X[1]) << 32) + X[0]); -} - -/** - * smix(B, r, N, V, XY): - * Compute 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 + 64 bytes in length. The value N must be a - * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a - * multiple of 64 bytes. - */ -static void -smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY) -{ - uint32_t * X = XY; - uint32_t * Y = &XY[32 * r]; - uint32_t * Z = &XY[64 * r]; - uint64_t i; - uint64_t j; - size_t k; - - /* 1: X <-- B */ - for (k = 0; k < 32 * r; k++) - X[k] = le32dec(&B[4 * k]); - - /* 2: for i = 0 to N - 1 do */ - for (i = 0; i < N; i += 2) { - /* 3: V_i <-- X */ - blkcpy(&V[i * (32 * r)], X, 128 * r); - - /* 4: X <-- H(X) */ - blockmix_salsa8(X, Y, Z, r); - - /* 3: V_i <-- X */ - blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r); - - /* 4: X <-- H(X) */ - blockmix_salsa8(Y, X, Z, r); - } - - /* 6: for i = 0 to N - 1 do */ - for (i = 0; i < N; i += 2) { - /* 7: j <-- Integerify(X) mod N */ - j = integerify(X, r) & (N - 1); - - /* 8: X <-- H(X \xor V_j) */ - blkxor(X, &V[j * (32 * r)], 128 * r); - blockmix_salsa8(X, Y, Z, r); - - /* 7: j <-- Integerify(X) mod N */ - j = integerify(Y, r) & (N - 1); - - /* 8: X <-- H(X \xor V_j) */ - blkxor(Y, &V[j * (32 * r)], 128 * r); - blockmix_salsa8(Y, X, Z, r); - } - - /* 10: B' <-- X */ - for (k = 0; k < 32 * r; k++) - le32enc(&B[4 * k], X[k]); -} - -/** - * 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. - */ -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) -{ - void * B0, * V0, * XY0; - uint8_t * B; - uint32_t * V; - uint32_t * XY; - uint32_t i; - - /* Sanity-check parameters. */ -#if SIZE_MAX > UINT32_MAX - if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { - errno = EFBIG; - goto err0; - } -#endif - if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { - errno = EFBIG; - goto err0; - } - if (((N & (N - 1)) != 0) || (N == 0)) { - errno = EINVAL; - goto err0; - } - if ((r > SIZE_MAX / 128 / p) || -#if SIZE_MAX / 256 <= UINT32_MAX - (r > SIZE_MAX / 256) || -#endif - (N > SIZE_MAX / 128 / r)) { - errno = ENOMEM; - goto err0; - } - - /* Allocate memory. */ -#ifdef HAVE_POSIX_MEMALIGN - if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0) - goto err0; - B = (uint8_t *)(B0); - if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0) - goto err1; - XY = (uint32_t *)(XY0); -#ifndef MAP_ANON - if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0) - goto err2; - V = (uint32_t *)(V0); -#endif -#else - if ((B0 = malloc(128 * r * p + 63)) == NULL) - goto err0; - B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63)); - if ((XY0 = malloc(256 * r + 64 + 63)) == NULL) - goto err1; - XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63)); -#ifndef MAP_ANON - if ((V0 = malloc(128 * r * N + 63)) == NULL) - goto err2; - V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63)); -#endif -#endif -#ifdef MAP_ANON - if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE, -#ifdef MAP_NOCORE - MAP_ANON | MAP_PRIVATE | MAP_NOCORE, -#else - MAP_ANON | MAP_PRIVATE, -#endif - -1, 0)) == MAP_FAILED) - goto err2; - V = (uint32_t *)(V0); -#endif - - /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ - PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); - - /* 2: for i = 0 to p - 1 do */ - for (i = 0; i < p; i++) { - /* 3: B_i <-- MF(B_i, N) */ - smix(&B[i * 128 * r], r, N, V, XY); - } - - /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ - PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); - - /* Free memory. */ -#ifdef MAP_ANON - if (munmap(V0, 128 * r * N)) - goto err2; -#else - free(V0); -#endif - free(XY0); - free(B0); - - /* Success! */ - return (0); - -err2: - free(XY0); -err1: - free(B0); -err0: - /* Failure! */ - return (-1); -} diff --git a/lib/crypto/crypto_scrypt-ref.c b/lib/crypto/crypto_scrypt-ref.c deleted file mode 100644 index 1b0d514..0000000 --- a/lib/crypto/crypto_scrypt-ref.c +++ /dev/null @@ -1,283 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#include -#include -#include -#include - -#include "sha256.h" -#include "sysendian.h" - -#include "crypto_scrypt.h" - -static void blkcpy(uint8_t *, uint8_t *, size_t); -static void blkxor(uint8_t *, uint8_t *, size_t); -static void salsa20_8(uint8_t[64]); -static void blockmix_salsa8(uint8_t *, uint8_t *, size_t); -static uint64_t integerify(uint8_t *, size_t); -static void smix(uint8_t *, size_t, uint64_t, uint8_t *, uint8_t *); - -static void -blkcpy(uint8_t * dest, uint8_t * src, size_t len) -{ - size_t i; - - for (i = 0; i < len; i++) - dest[i] = src[i]; -} - -static void -blkxor(uint8_t * dest, uint8_t * src, size_t len) -{ - size_t i; - - for (i = 0; i < len; i++) - dest[i] ^= src[i]; -} - -/** - * salsa20_8(B): - * Apply the salsa20/8 core to the provided block. - */ -static void -salsa20_8(uint8_t B[64]) -{ - uint32_t B32[16]; - uint32_t x[16]; - size_t i; - - /* Convert little-endian values in. */ - for (i = 0; i < 16; i++) - B32[i] = le32dec(&B[i * 4]); - - /* Compute x = doubleround^4(B32). */ - for (i = 0; i < 16; i++) - x[i] = B32[i]; - for (i = 0; i < 8; 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 - } - - /* Compute B32 = B32 + x. */ - for (i = 0; i < 16; i++) - B32[i] += x[i]; - - /* Convert little-endian values out. */ - for (i = 0; i < 16; i++) - le32enc(&B[4 * i], B32[i]); -} - -/** - * 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(uint8_t * B, uint8_t * Y, size_t r) -{ - uint8_t X[64]; - size_t i; - - /* 1: X <-- B_{2r - 1} */ - blkcpy(X, &B[(2 * r - 1) * 64], 64); - - /* 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 * 64], 64); - salsa20_8(X); - - /* 4: Y_i <-- X */ - blkcpy(&Y[i * 64], X, 64); - } - - /* 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 * 64], &Y[(i * 2) * 64], 64); - for (i = 0; i < r; i++) - blkcpy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64); -} - -/** - * integerify(B, r): - * Return the result of parsing B_{2r-1} as a little-endian integer. - */ -static uint64_t -integerify(uint8_t * B, size_t r) -{ - uint8_t * X = &B[(2 * r - 1) * 64]; - - return (le64dec(X)); -} - -/** - * smix(B, r, N, V, XY): - * Compute 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. - */ -static void -smix(uint8_t * B, size_t r, uint64_t N, uint8_t * V, uint8_t * XY) -{ - uint8_t * X = XY; - uint8_t * Y = &XY[128 * r]; - uint64_t i; - uint64_t j; - - /* 1: X <-- B */ - blkcpy(X, B, 128 * r); - - /* 2: for i = 0 to N - 1 do */ - for (i = 0; i < N; i++) { - /* 3: V_i <-- X */ - blkcpy(&V[i * (128 * r)], X, 128 * r); - - /* 4: X <-- H(X) */ - blockmix_salsa8(X, Y, r); - } - - /* 6: for i = 0 to N - 1 do */ - for (i = 0; i < N; i++) { - /* 7: j <-- Integerify(X) mod N */ - j = integerify(X, r) & (N - 1); - - /* 8: X <-- H(X \xor V_j) */ - blkxor(X, &V[j * (128 * r)], 128 * r); - blockmix_salsa8(X, Y, r); - } - - /* 10: B' <-- X */ - blkcpy(B, X, 128 * r); -} - -/** - * 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. - * - * Return 0 on success; or -1 on error. - */ -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) -{ - uint8_t * B; - uint8_t * V; - uint8_t * XY; - uint32_t i; - - /* Sanity-check parameters. */ -#if SIZE_MAX > UINT32_MAX - if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { - errno = EFBIG; - goto err0; - } -#endif - if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { - errno = EFBIG; - goto err0; - } - if (((N & (N - 1)) != 0) || (N == 0)) { - errno = EINVAL; - goto err0; - } - if ((r > SIZE_MAX / 128 / p) || -#if SIZE_MAX / 256 <= UINT32_MAX - (r > SIZE_MAX / 256) || -#endif - (N > SIZE_MAX / 128 / r)) { - errno = ENOMEM; - goto err0; - } - - /* Allocate memory. */ - if ((B = malloc(128 * r * p)) == NULL) - goto err0; - if ((XY = malloc(256 * r)) == NULL) - goto err1; - if ((V = malloc(128 * r * N)) == NULL) - goto err2; - - /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ - PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); - - /* 2: for i = 0 to p - 1 do */ - for (i = 0; i < p; i++) { - /* 3: B_i <-- MF(B_i, N) */ - smix(&B[i * 128 * r], r, N, V, XY); - } - - /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ - PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); - - /* Free memory. */ - free(V); - free(XY); - free(B); - - /* Success! */ - return (0); - -err2: - free(XY); -err1: - free(B); -err0: - /* Failure! */ - return (-1); -} diff --git a/lib/crypto/crypto_scrypt-sse.c b/lib/crypto/crypto_scrypt-sse.c deleted file mode 100644 index 0e6ff33..0000000 --- a/lib/crypto/crypto_scrypt-sse.c +++ /dev/null @@ -1,365 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include "sha256.h" -#include "sysendian.h" - -#include "crypto_scrypt.h" - -static void blkcpy(void *, void *, size_t); -static void blkxor(void *, void *, size_t); -static void salsa20_8(__m128i *); -static void blockmix_salsa8(__m128i *, __m128i *, __m128i *, size_t); -static uint64_t integerify(void *, size_t); -static void smix(uint8_t *, size_t, uint64_t, void *, void *); - -static void -blkcpy(void * dest, void * src, size_t len) -{ - __m128i * D = dest; - __m128i * S = src; - size_t L = len / 16; - size_t i; - - for (i = 0; i < L; i++) - D[i] = S[i]; -} - -static void -blkxor(void * dest, void * src, size_t len) -{ - __m128i * D = dest; - __m128i * S = src; - size_t L = len / 16; - size_t i; - - for (i = 0; i < L; i++) - D[i] = _mm_xor_si128(D[i], S[i]); -} - -/** - * salsa20_8(B): - * Apply the salsa20/8 core to the provided block. - */ -static void -salsa20_8(__m128i B[4]) -{ - __m128i X0, X1, X2, X3; - __m128i T; - size_t i; - - X0 = B[0]; - X1 = B[1]; - X2 = B[2]; - X3 = B[3]; - - for (i = 0; i < 8; i += 2) { - /* Operate on "columns". */ - T = _mm_add_epi32(X0, X3); - X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 7)); - X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 25)); - T = _mm_add_epi32(X1, X0); - X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9)); - X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23)); - T = _mm_add_epi32(X2, X1); - X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 13)); - X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 19)); - T = _mm_add_epi32(X3, X2); - X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18)); - X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14)); - - /* Rearrange data. */ - X1 = _mm_shuffle_epi32(X1, 0x93); - X2 = _mm_shuffle_epi32(X2, 0x4E); - X3 = _mm_shuffle_epi32(X3, 0x39); - - /* Operate on "rows". */ - T = _mm_add_epi32(X0, X1); - X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 7)); - X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 25)); - T = _mm_add_epi32(X3, X0); - X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9)); - X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23)); - T = _mm_add_epi32(X2, X3); - X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 13)); - X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 19)); - T = _mm_add_epi32(X1, X2); - X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18)); - X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14)); - - /* Rearrange data. */ - X1 = _mm_shuffle_epi32(X1, 0x39); - X2 = _mm_shuffle_epi32(X2, 0x4E); - X3 = _mm_shuffle_epi32(X3, 0x93); - } - - B[0] = _mm_add_epi32(B[0], X0); - B[1] = _mm_add_epi32(B[1], X1); - B[2] = _mm_add_epi32(B[2], X2); - B[3] = _mm_add_epi32(B[3], X3); -} - -/** - * blockmix_salsa8(Bin, Bout, X, r): - * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r - * bytes in length; the output Bout must also be the same size. The - * temporary space X must be 64 bytes. - */ -static void -blockmix_salsa8(__m128i * Bin, __m128i * Bout, __m128i * X, size_t r) -{ - size_t i; - - /* 1: X <-- B_{2r - 1} */ - blkcpy(X, &Bin[8 * r - 4], 64); - - /* 2: for i = 0 to 2r - 1 do */ - for (i = 0; i < r; i++) { - /* 3: X <-- H(X \xor B_i) */ - blkxor(X, &Bin[i * 8], 64); - salsa20_8(X); - - /* 4: Y_i <-- X */ - /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ - blkcpy(&Bout[i * 4], X, 64); - - /* 3: X <-- H(X \xor B_i) */ - blkxor(X, &Bin[i * 8 + 4], 64); - salsa20_8(X); - - /* 4: Y_i <-- X */ - /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ - blkcpy(&Bout[(r + i) * 4], X, 64); - } -} - -/** - * integerify(B, r): - * Return the result of parsing B_{2r-1} as a little-endian integer. - */ -static uint64_t -integerify(void * B, size_t r) -{ - uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64); - - return (((uint64_t)(X[13]) << 32) + X[0]); -} - -/** - * smix(B, r, N, V, XY): - * Compute 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 + 64 bytes in length. The value N must be a - * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a - * multiple of 64 bytes. - */ -static void -smix(uint8_t * B, size_t r, uint64_t N, void * V, void * XY) -{ - __m128i * X = XY; - __m128i * Y = (void *)((uintptr_t)(XY) + 128 * r); - __m128i * Z = (void *)((uintptr_t)(XY) + 256 * r); - uint32_t * X32 = (void *)X; - uint64_t i, j; - size_t k; - - /* 1: X <-- B */ - for (k = 0; k < 2 * r; k++) { - for (i = 0; i < 16; i++) { - X32[k * 16 + i] = - le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]); - } - } - - /* 2: for i = 0 to N - 1 do */ - for (i = 0; i < N; i += 2) { - /* 3: V_i <-- X */ - blkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r); - - /* 4: X <-- H(X) */ - blockmix_salsa8(X, Y, Z, r); - - /* 3: V_i <-- X */ - blkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r), - Y, 128 * r); - - /* 4: X <-- H(X) */ - blockmix_salsa8(Y, X, Z, r); - } - - /* 6: for i = 0 to N - 1 do */ - for (i = 0; i < N; i += 2) { - /* 7: j <-- Integerify(X) mod N */ - j = integerify(X, r) & (N - 1); - - /* 8: X <-- H(X \xor V_j) */ - blkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r); - blockmix_salsa8(X, Y, Z, r); - - /* 7: j <-- Integerify(X) mod N */ - j = integerify(Y, r) & (N - 1); - - /* 8: X <-- H(X \xor V_j) */ - blkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r); - blockmix_salsa8(Y, X, Z, r); - } - - /* 10: B' <-- X */ - for (k = 0; k < 2 * r; k++) { - for (i = 0; i < 16; i++) { - le32enc(&B[(k * 16 + (i * 5 % 16)) * 4], - X32[k * 16 + i]); - } - } -} - -/** - * 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. - */ -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) -{ - void * B0, * V0, * XY0; - uint8_t * B; - uint32_t * V; - uint32_t * XY; - uint32_t i; - - /* Sanity-check parameters. */ -#if SIZE_MAX > UINT32_MAX - if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { - errno = EFBIG; - goto err0; - } -#endif - if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { - errno = EFBIG; - goto err0; - } - if (((N & (N - 1)) != 0) || (N == 0)) { - errno = EINVAL; - goto err0; - } - if ((r > SIZE_MAX / 128 / p) || -#if SIZE_MAX / 256 <= UINT32_MAX - (r > (SIZE_MAX - 64) / 256) || -#endif - (N > SIZE_MAX / 128 / r)) { - errno = ENOMEM; - goto err0; - } - - /* Allocate memory. */ -#ifdef HAVE_POSIX_MEMALIGN - if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0) - goto err0; - B = (uint8_t *)(B0); - if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0) - goto err1; - XY = (uint32_t *)(XY0); -#ifndef MAP_ANON - if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0) - goto err2; - V = (uint32_t *)(V0); -#endif -#else - if ((B0 = malloc(128 * r * p + 63)) == NULL) - goto err0; - B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63)); - if ((XY0 = malloc(256 * r + 64 + 63)) == NULL) - goto err1; - XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63)); -#ifndef MAP_ANON - if ((V0 = malloc(128 * r * N + 63)) == NULL) - goto err2; - V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63)); -#endif -#endif -#ifdef MAP_ANON - if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE, -#ifdef MAP_NOCORE - MAP_ANON | MAP_PRIVATE | MAP_NOCORE, -#else - MAP_ANON | MAP_PRIVATE, -#endif - -1, 0)) == MAP_FAILED) - goto err2; - V = (uint32_t *)(V0); -#endif - - /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ - PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); - - /* 2: for i = 0 to p - 1 do */ - for (i = 0; i < p; i++) { - /* 3: B_i <-- MF(B_i, N) */ - smix(&B[i * 128 * r], r, N, V, XY); - } - - /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ - PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); - - /* Free memory. */ -#ifdef MAP_ANON - if (munmap(V0, 128 * r * N)) - goto err2; -#else - free(V0); -#endif - free(XY0); - free(B0); - - /* Success! */ - return (0); - -err2: - free(XY0); -err1: - free(B0); -err0: - /* Failure! */ - return (-1); -} diff --git a/lib/crypto/crypto_scrypt.h b/lib/crypto/crypto_scrypt.h deleted file mode 100644 index f72e1f4..0000000 --- a/lib/crypto/crypto_scrypt.h +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ -#ifndef _CRYPTO_SCRYPT_H_ -#define _CRYPTO_SCRYPT_H_ - -#include - -/** - * 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. - */ -int crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, - uint32_t, uint32_t, uint8_t *, size_t); - -#endif /* !_CRYPTO_SCRYPT_H_ */ diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c deleted file mode 100644 index d2f915f..0000000 --- a/lib/crypto/sha256.c +++ /dev/null @@ -1,411 +0,0 @@ -/*- - * Copyright 2005,2007,2009 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. - */ - -#include - -#include -#include - -#include "sysendian.h" - -#include "sha256.h" - -/* - * Encode a length len/4 vector of (uint32_t) into a length len vector of - * (unsigned char) in big-endian form. Assumes len is a multiple of 4. - */ -static void -be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len) -{ - size_t i; - - for (i = 0; i < len / 4; i++) - be32enc(dst + i * 4, src[i]); -} - -/* - * Decode a big-endian length len vector of (unsigned char) into a length - * len/4 vector of (uint32_t). Assumes len is a multiple of 4. - */ -static void -be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len) -{ - size_t i; - - for (i = 0; i < len / 4; i++) - dst[i] = be32dec(src + i * 4); -} - -/* Elementary functions used by SHA256 */ -#define Ch(x, y, z) ((x & (y ^ z)) ^ z) -#define Maj(x, y, z) ((x & (y | z)) | (y & z)) -#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) \ - t0 = h + S1(e) + Ch(e, f, g) + k; \ - t1 = S0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - -/* Adjusted round function for rotating state */ -#define RNDr(S, W, i, k) \ - 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] + k) - -/* - * 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, const unsigned char block[64]) -{ - uint32_t W[64]; - uint32_t S[8]; - uint32_t t0, t1; - int i; - - /* 1. Prepare message schedule W. */ - be32dec_vect(W, block, 64); - for (i = 16; i < 64; i++) - W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; - - /* 2. Initialize working variables. */ - memcpy(S, state, 32); - - /* 3. Mix. */ - RNDr(S, W, 0, 0x428a2f98); - RNDr(S, W, 1, 0x71374491); - RNDr(S, W, 2, 0xb5c0fbcf); - RNDr(S, W, 3, 0xe9b5dba5); - RNDr(S, W, 4, 0x3956c25b); - RNDr(S, W, 5, 0x59f111f1); - RNDr(S, W, 6, 0x923f82a4); - RNDr(S, W, 7, 0xab1c5ed5); - RNDr(S, W, 8, 0xd807aa98); - RNDr(S, W, 9, 0x12835b01); - RNDr(S, W, 10, 0x243185be); - RNDr(S, W, 11, 0x550c7dc3); - RNDr(S, W, 12, 0x72be5d74); - RNDr(S, W, 13, 0x80deb1fe); - RNDr(S, W, 14, 0x9bdc06a7); - RNDr(S, W, 15, 0xc19bf174); - RNDr(S, W, 16, 0xe49b69c1); - RNDr(S, W, 17, 0xefbe4786); - RNDr(S, W, 18, 0x0fc19dc6); - RNDr(S, W, 19, 0x240ca1cc); - RNDr(S, W, 20, 0x2de92c6f); - RNDr(S, W, 21, 0x4a7484aa); - RNDr(S, W, 22, 0x5cb0a9dc); - RNDr(S, W, 23, 0x76f988da); - RNDr(S, W, 24, 0x983e5152); - RNDr(S, W, 25, 0xa831c66d); - RNDr(S, W, 26, 0xb00327c8); - RNDr(S, W, 27, 0xbf597fc7); - RNDr(S, W, 28, 0xc6e00bf3); - RNDr(S, W, 29, 0xd5a79147); - RNDr(S, W, 30, 0x06ca6351); - RNDr(S, W, 31, 0x14292967); - RNDr(S, W, 32, 0x27b70a85); - RNDr(S, W, 33, 0x2e1b2138); - RNDr(S, W, 34, 0x4d2c6dfc); - RNDr(S, W, 35, 0x53380d13); - RNDr(S, W, 36, 0x650a7354); - RNDr(S, W, 37, 0x766a0abb); - RNDr(S, W, 38, 0x81c2c92e); - RNDr(S, W, 39, 0x92722c85); - RNDr(S, W, 40, 0xa2bfe8a1); - RNDr(S, W, 41, 0xa81a664b); - RNDr(S, W, 42, 0xc24b8b70); - RNDr(S, W, 43, 0xc76c51a3); - RNDr(S, W, 44, 0xd192e819); - RNDr(S, W, 45, 0xd6990624); - RNDr(S, W, 46, 0xf40e3585); - RNDr(S, W, 47, 0x106aa070); - RNDr(S, W, 48, 0x19a4c116); - RNDr(S, W, 49, 0x1e376c08); - RNDr(S, W, 50, 0x2748774c); - RNDr(S, W, 51, 0x34b0bcb5); - RNDr(S, W, 52, 0x391c0cb3); - RNDr(S, W, 53, 0x4ed8aa4a); - RNDr(S, W, 54, 0x5b9cca4f); - RNDr(S, W, 55, 0x682e6ff3); - RNDr(S, W, 56, 0x748f82ee); - RNDr(S, W, 57, 0x78a5636f); - RNDr(S, W, 58, 0x84c87814); - RNDr(S, W, 59, 0x8cc70208); - RNDr(S, W, 60, 0x90befffa); - RNDr(S, W, 61, 0xa4506ceb); - RNDr(S, W, 62, 0xbef9a3f7); - RNDr(S, W, 63, 0xc67178f2); - - /* 4. Mix local working variables into global state */ - for (i = 0; i < 8; i++) - state[i] += S[i]; - - /* Clean the stack. */ - memset(W, 0, 256); - memset(S, 0, 32); - t0 = t1 = 0; -} - -static unsigned char 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) -{ - unsigned char len[8]; - uint32_t r, plen; - - /* - * Convert length to a vector of bytes -- we do this now rather - * than later because the length will change after we pad. - */ - be32enc_vect(len, ctx->count, 8); - - /* Add 1--64 bytes so that the resulting length is 56 mod 64 */ - r = (ctx->count[1] >> 3) & 0x3f; - plen = (r < 56) ? (56 - r) : (120 - r); - SHA256_Update(ctx, PAD, (size_t)plen); - - /* Add the terminating bit-count */ - SHA256_Update(ctx, len, 8); -} - -/* SHA-256 initialization. Begins a SHA-256 operation. */ -void -SHA256_Init(SHA256_CTX * ctx) -{ - - /* Zero bits processed so far */ - ctx->count[0] = ctx->count[1] = 0; - - /* Magic initialization constants */ - ctx->state[0] = 0x6A09E667; - ctx->state[1] = 0xBB67AE85; - ctx->state[2] = 0x3C6EF372; - ctx->state[3] = 0xA54FF53A; - ctx->state[4] = 0x510E527F; - ctx->state[5] = 0x9B05688C; - ctx->state[6] = 0x1F83D9AB; - ctx->state[7] = 0x5BE0CD19; -} - -/* Add bytes into the hash */ -void -SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len) -{ - uint32_t bitlen[2]; - uint32_t r; - const unsigned char *src = in; - - /* Number of bytes left in the buffer from previous updates */ - r = (ctx->count[1] >> 3) & 0x3f; - - /* Convert the length into a number of bits */ - bitlen[1] = ((uint32_t)len) << 3; - bitlen[0] = (uint32_t)(len >> 29); - - /* Update number of bits */ - if ((ctx->count[1] += bitlen[1]) < bitlen[1]) - ctx->count[0]++; - ctx->count[0] += bitlen[0]; - - /* 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); - src += 64 - r; - len -= 64 - r; - - /* Perform complete blocks */ - while (len >= 64) { - SHA256_Transform(ctx->state, src); - src += 64; - len -= 64; - } - - /* Copy left over data into buffer */ - memcpy(ctx->buf, src, len); -} - -/* - * SHA-256 finalization. Pads the input data, exports the hash value, - * and clears the context state. - */ -void -SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx) -{ - - /* Add padding */ - SHA256_Pad(ctx); - - /* Write the hash */ - be32enc_vect(digest, ctx->state, 32); - - /* Clear the context state */ - memset((void *)ctx, 0, sizeof(*ctx)); -} - -/* Initialize an HMAC-SHA256 operation with the given key. */ -void -HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) -{ - unsigned char pad[64]; - unsigned char khash[32]; - const unsigned char * 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); - SHA256_Final(khash, &ctx->ictx); - 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); - - /* 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); - - /* Clean the stack. */ - memset(khash, 0, 32); -} - -/* Add bytes to the HMAC-SHA256 operation. */ -void -HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len) -{ - - /* Feed data to the inner SHA256 operation. */ - SHA256_Update(&ctx->ictx, in, len); -} - -/* Finish an HMAC-SHA256 operation. */ -void -HMAC_SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx) -{ - unsigned char ihash[32]; - - /* Finish the inner SHA256 operation. */ - SHA256_Final(ihash, &ctx->ictx); - - /* Feed the inner hash to the outer SHA256 operation. */ - SHA256_Update(&ctx->octx, ihash, 32); - - /* Finish the outer SHA256 operation. */ - SHA256_Final(digest, &ctx->octx); - - /* Clean the stack. */ - memset(ihash, 0, 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 * passwd, size_t passwdlen, const uint8_t * salt, - size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) -{ - HMAC_SHA256_CTX PShctx, hctx; - size_t i; - uint8_t ivec[4]; - uint8_t U[32]; - uint8_t T[32]; - uint64_t j; - int k; - size_t clen; - - /* Compute HMAC state after processing P and S. */ - HMAC_SHA256_Init(&PShctx, passwd, passwdlen); - HMAC_SHA256_Update(&PShctx, salt, saltlen); - - /* 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); - HMAC_SHA256_Final(U, &hctx); - - /* T_i = U_1 ... */ - memcpy(T, U, 32); - - for (j = 2; j <= c; j++) { - /* Compute U_j. */ - HMAC_SHA256_Init(&hctx, passwd, passwdlen); - HMAC_SHA256_Update(&hctx, U, 32); - HMAC_SHA256_Final(U, &hctx); - - /* ... 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 PShctx, since we never called _Final on it. */ - memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); -} diff --git a/lib/crypto/sha256.h b/lib/crypto/sha256.h deleted file mode 100644 index 289a523..0000000 --- a/lib/crypto/sha256.h +++ /dev/null @@ -1,62 +0,0 @@ -/*- - * Copyright 2005,2007,2009 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. - * - * $FreeBSD: src/lib/libmd/sha256.h,v 1.2 2006/01/17 15:35:56 phk Exp $ - */ - -#ifndef _SHA256_H_ -#define _SHA256_H_ - -#include - -#include - -typedef struct SHA256Context { - uint32_t state[8]; - uint32_t count[2]; - unsigned char buf[64]; -} SHA256_CTX; - -typedef struct HMAC_SHA256Context { - SHA256_CTX ictx; - SHA256_CTX octx; -} HMAC_SHA256_CTX; - -void SHA256_Init(SHA256_CTX *); -void SHA256_Update(SHA256_CTX *, const void *, size_t); -void SHA256_Final(unsigned char [32], SHA256_CTX *); -void HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t); -void HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t); -void HMAC_SHA256_Final(unsigned char [32], HMAC_SHA256_CTX *); - -/** - * 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); - -#endif /* !_SHA256_H_ */ diff --git a/lib/scryptenc/scryptenc.c b/lib/scryptenc/scryptenc.c deleted file mode 100644 index cf091bf..0000000 --- a/lib/scryptenc/scryptenc.c +++ /dev/null @@ -1,605 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include "crypto_aesctr.h" -#include "crypto_scrypt.h" -#include "memlimit.h" -#include "scryptenc_cpuperf.h" -#include "sha256.h" -#include "sysendian.h" - -#include "scryptenc.h" - -#define ENCBLOCK 65536 - -static int pickparams(size_t, double, double, - int *, uint32_t *, uint32_t *); -static int checkparams(size_t, double, double, int, uint32_t, uint32_t); -static int getsalt(uint8_t[32]); - -static int -pickparams(size_t maxmem, double maxmemfrac, double maxtime, - int * logN, uint32_t * r, uint32_t * p) -{ - size_t memlimit; - double opps; - double opslimit; - double maxN, maxrp; - int rc; - - /* Figure out how much memory to use. */ - if (memtouse(maxmem, maxmemfrac, &memlimit)) - return (1); - - /* Figure out how fast the CPU is. */ - if ((rc = scryptenc_cpuperf(&opps)) != 0) - return (rc); - opslimit = opps * maxtime; - - /* Allow a minimum of 2^15 salsa20/8 cores. */ - if (opslimit < 32768) - opslimit = 32768; - - /* Fix r = 8 for now. */ - *r = 8; - - /* - * The memory limit requires that 128Nr <= memlimit, while the CPU - * limit requires that 4Nrp <= opslimit. If opslimit < memlimit/32, - * opslimit imposes the stronger limit on N. - */ -#ifdef DEBUG - fprintf(stderr, "Requiring 128Nr <= %zu, 4Nrp <= %f\n", - memlimit, opslimit); -#endif - if (opslimit < memlimit/32) { - /* Set p = 1 and choose N based on the CPU limit. */ - *p = 1; - maxN = opslimit / (*r * 4); - for (*logN = 1; *logN < 63; *logN += 1) { - if ((uint64_t)(1) << *logN > maxN / 2) - break; - } - } else { - /* Set N based on the memory limit. */ - maxN = memlimit / (*r * 128); - for (*logN = 1; *logN < 63; *logN += 1) { - if ((uint64_t)(1) << *logN > maxN / 2) - break; - } - - /* Choose p based on the CPU limit. */ - maxrp = (opslimit / 4) / ((uint64_t)(1) << *logN); - if (maxrp > 0x3fffffff) - maxrp = 0x3fffffff; - *p = (uint32_t)(maxrp) / *r; - } - -#ifdef DEBUG - fprintf(stderr, "N = %zu r = %d p = %d\n", - (size_t)(1) << *logN, (int)(*r), (int)(*p)); -#endif - - /* Success! */ - return (0); -} - -static int -checkparams(size_t maxmem, double maxmemfrac, double maxtime, - int logN, uint32_t r, uint32_t p) -{ - size_t memlimit; - double opps; - double opslimit; - uint64_t N; - int rc; - - /* Figure out the maximum amount of memory we can use. */ - if (memtouse(maxmem, maxmemfrac, &memlimit)) - return (1); - - /* Figure out how fast the CPU is. */ - if ((rc = scryptenc_cpuperf(&opps)) != 0) - return (rc); - opslimit = opps * maxtime; - - /* Sanity-check values. */ - if ((logN < 1) || (logN > 63)) - return (7); - if ((uint64_t)(r) * (uint64_t)(p) >= 0x40000000) - return (7); - - /* Check limits. */ - N = (uint64_t)(1) << logN; - if ((memlimit / N) / r < 128) - return (9); - if ((opslimit / N) / (r * p) < 4) - return (10); - - /* Success! */ - return (0); -} - -static int -getsalt(uint8_t salt[32]) -{ - int fd; - ssize_t lenread; - uint8_t * buf = salt; - size_t buflen = 32; - - /* Open /dev/urandom. */ - if ((fd = open("/dev/urandom", O_RDONLY)) == -1) - goto err0; - - /* Read bytes until we have filled the buffer. */ - while (buflen > 0) { - if ((lenread = read(fd, buf, buflen)) == -1) - goto err1; - - /* The random device should never EOF. */ - if (lenread == 0) - goto err1; - - /* We're partly done. */ - buf += lenread; - buflen -= lenread; - } - - /* Close the device. */ - while (close(fd) == -1) { - if (errno != EINTR) - goto err0; - } - - /* Success! */ - return (0); - -err1: - close(fd); -err0: - /* Failure! */ - return (4); -} - -static int -scryptenc_setup(uint8_t header[96], uint8_t dk[64], - const uint8_t * passwd, size_t passwdlen, - size_t maxmem, double maxmemfrac, double maxtime) -{ - uint8_t salt[32]; - uint8_t hbuf[32]; - int logN; - uint64_t N; - uint32_t r; - uint32_t p; - SHA256_CTX ctx; - uint8_t * key_hmac = &dk[32]; - HMAC_SHA256_CTX hctx; - int rc; - - /* Pick values for N, r, p. */ - if ((rc = pickparams(maxmem, maxmemfrac, maxtime, - &logN, &r, &p)) != 0) - return (rc); - N = (uint64_t)(1) << logN; - - /* Get some salt. */ - if ((rc = getsalt(salt)) != 0) - return (rc); - - /* Generate the derived keys. */ - if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64)) - return (3); - - /* Construct the file header. */ - memcpy(header, "scrypt", 6); - header[6] = 0; - header[7] = logN; - be32enc(&header[8], r); - be32enc(&header[12], p); - memcpy(&header[16], salt, 32); - - /* Add header checksum. */ - SHA256_Init(&ctx); - SHA256_Update(&ctx, header, 48); - SHA256_Final(hbuf, &ctx); - memcpy(&header[48], hbuf, 16); - - /* Add header signature (used for verifying password). */ - HMAC_SHA256_Init(&hctx, key_hmac, 32); - HMAC_SHA256_Update(&hctx, header, 64); - HMAC_SHA256_Final(hbuf, &hctx); - memcpy(&header[64], hbuf, 32); - - /* Success! */ - return (0); -} - -static int -scryptdec_setup(const uint8_t header[96], uint8_t dk[64], - const uint8_t * passwd, size_t passwdlen, - size_t maxmem, double maxmemfrac, double maxtime) -{ - uint8_t salt[32]; - uint8_t hbuf[32]; - int logN; - uint32_t r; - uint32_t p; - uint64_t N; - SHA256_CTX ctx; - uint8_t * key_hmac = &dk[32]; - HMAC_SHA256_CTX hctx; - int rc; - - /* Parse N, r, p, salt. */ - logN = header[7]; - r = be32dec(&header[8]); - p = be32dec(&header[12]); - memcpy(salt, &header[16], 32); - - /* Verify header checksum. */ - SHA256_Init(&ctx); - SHA256_Update(&ctx, header, 48); - SHA256_Final(hbuf, &ctx); - if (memcmp(&header[48], hbuf, 16)) - return (7); - - /* - * Check whether the provided parameters are valid and whether the - * key derivation function can be computed within the allowed memory - * and CPU time. - */ - if ((rc = checkparams(maxmem, maxmemfrac, maxtime, logN, r, p)) != 0) - return (rc); - - /* Compute the derived keys. */ - N = (uint64_t)(1) << logN; - if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64)) - return (3); - - /* Check header signature (i.e., verify password). */ - HMAC_SHA256_Init(&hctx, key_hmac, 32); - HMAC_SHA256_Update(&hctx, header, 64); - HMAC_SHA256_Final(hbuf, &hctx); - if (memcmp(hbuf, &header[64], 32)) - return (11); - - /* Success! */ - return (0); -} - -/** - * scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen, - * maxmem, maxmemfrac, maxtime): - * Encrypt inbuflen bytes from inbuf, writing the resulting inbuflen + 128 - * bytes to outbuf. - */ -int -scryptenc_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf, - const uint8_t * passwd, size_t passwdlen, - size_t maxmem, double maxmemfrac, double maxtime) -{ - uint8_t dk[64]; - uint8_t hbuf[32]; - uint8_t header[96]; - uint8_t * key_enc = dk; - uint8_t * key_hmac = &dk[32]; - int rc; - HMAC_SHA256_CTX hctx; - AES_KEY key_enc_exp; - struct crypto_aesctr * AES; - - /* Generate the header and derived key. */ - if ((rc = scryptenc_setup(header, dk, passwd, passwdlen, - maxmem, maxmemfrac, maxtime)) != 0) - return (rc); - - /* Copy header into output buffer. */ - memcpy(outbuf, header, 96); - - /* Encrypt data. */ - if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp)) - return (5); - if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL) - return (6); - crypto_aesctr_stream(AES, inbuf, &outbuf[96], inbuflen); - crypto_aesctr_free(AES); - - /* Add signature. */ - HMAC_SHA256_Init(&hctx, key_hmac, 32); - HMAC_SHA256_Update(&hctx, outbuf, 96 + inbuflen); - HMAC_SHA256_Final(hbuf, &hctx); - memcpy(&outbuf[96 + inbuflen], hbuf, 32); - - /* Zero sensitive data. */ - memset(dk, 0, 64); - memset(&key_enc_exp, 0, sizeof(AES_KEY)); - - /* Success! */ - return (0); -} - -/** - * scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen, - * maxmem, maxmemfrac, maxtime): - * Decrypt inbuflen bytes fro inbuf, writing the result into outbuf and the - * decrypted data length to outlen. The allocated length of outbuf must - * be at least inbuflen. - */ -int -scryptdec_buf(const uint8_t * inbuf, size_t inbuflen, uint8_t * outbuf, - size_t * outlen, const uint8_t * passwd, size_t passwdlen, - size_t maxmem, double maxmemfrac, double maxtime) -{ - uint8_t hbuf[32]; - uint8_t dk[64]; - uint8_t * key_enc = dk; - uint8_t * key_hmac = &dk[32]; - int rc; - HMAC_SHA256_CTX hctx; - AES_KEY key_enc_exp; - struct crypto_aesctr * AES; - - /* - * All versions of the scrypt format will start with "scrypt" and - * have at least 7 bytes of header. - */ - if ((inbuflen < 7) || (memcmp(inbuf, "scrypt", 6) != 0)) - return (7); - - /* Check the format. */ - if (inbuf[6] != 0) - return (8); - - /* We must have at least 128 bytes. */ - if (inbuflen < 128) - return (7); - - /* Parse the header and generate derived keys. */ - if ((rc = scryptdec_setup(inbuf, dk, passwd, passwdlen, - maxmem, maxmemfrac, maxtime)) != 0) - return (rc); - - /* Decrypt data. */ - if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp)) - return (5); - if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL) - return (6); - crypto_aesctr_stream(AES, &inbuf[96], outbuf, inbuflen - 128); - crypto_aesctr_free(AES); - *outlen = inbuflen - 128; - - /* Verify signature. */ - HMAC_SHA256_Init(&hctx, key_hmac, 32); - HMAC_SHA256_Update(&hctx, inbuf, inbuflen - 32); - HMAC_SHA256_Final(hbuf, &hctx); - if (memcmp(hbuf, &inbuf[inbuflen - 32], 32)) - return (7); - - /* Zero sensitive data. */ - memset(dk, 0, 64); - memset(&key_enc_exp, 0, sizeof(AES_KEY)); - - /* Success! */ - return (0); -} - -/** - * scryptenc_file(infile, outfile, passwd, passwdlen, - * maxmem, maxmemfrac, maxtime): - * Read a stream from infile and encrypt it, writing the resulting stream to - * outfile. - */ -int -scryptenc_file(FILE * infile, FILE * outfile, - const uint8_t * passwd, size_t passwdlen, - size_t maxmem, double maxmemfrac, double maxtime) -{ - uint8_t buf[ENCBLOCK]; - uint8_t dk[64]; - uint8_t hbuf[32]; - uint8_t header[96]; - uint8_t * key_enc = dk; - uint8_t * key_hmac = &dk[32]; - size_t readlen; - HMAC_SHA256_CTX hctx; - AES_KEY key_enc_exp; - struct crypto_aesctr * AES; - int rc; - - /* Generate the header and derived key. */ - if ((rc = scryptenc_setup(header, dk, passwd, passwdlen, - maxmem, maxmemfrac, maxtime)) != 0) - return (rc); - - /* Hash and write the header. */ - HMAC_SHA256_Init(&hctx, key_hmac, 32); - HMAC_SHA256_Update(&hctx, header, 96); - if (fwrite(header, 96, 1, outfile) != 1) - return (12); - - /* - * Read blocks of data, encrypt them, and write them out; hash the - * data as it is produced. - */ - if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp)) - return (5); - if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL) - return (6); - do { - if ((readlen = fread(buf, 1, ENCBLOCK, infile)) == 0) - break; - crypto_aesctr_stream(AES, buf, buf, readlen); - HMAC_SHA256_Update(&hctx, buf, readlen); - if (fwrite(buf, 1, readlen, outfile) < readlen) - return (12); - } while (1); - crypto_aesctr_free(AES); - - /* Did we exit the loop due to a read error? */ - if (ferror(infile)) - return (13); - - /* Compute the final HMAC and output it. */ - HMAC_SHA256_Final(hbuf, &hctx); - if (fwrite(hbuf, 32, 1, outfile) != 1) - return (12); - - /* Zero sensitive data. */ - memset(dk, 0, 64); - memset(&key_enc_exp, 0, sizeof(AES_KEY)); - - /* Success! */ - return (0); -} - -/** - * scryptdec_file(infile, outfile, passwd, passwdlen, - * maxmem, maxmemfrac, maxtime): - * Read a stream from infile and decrypt it, writing the resulting stream to - * outfile. - */ -int -scryptdec_file(FILE * infile, FILE * outfile, - const uint8_t * passwd, size_t passwdlen, - size_t maxmem, double maxmemfrac, double maxtime) -{ - uint8_t buf[ENCBLOCK + 32]; - uint8_t header[96]; - uint8_t hbuf[32]; - uint8_t dk[64]; - uint8_t * key_enc = dk; - uint8_t * key_hmac = &dk[32]; - size_t buflen = 0; - size_t readlen; - HMAC_SHA256_CTX hctx; - AES_KEY key_enc_exp; - struct crypto_aesctr * AES; - int rc; - - /* - * Read the first 7 bytes of the file; all future version of scrypt - * are guaranteed to have at least 7 bytes of header. - */ - if (fread(header, 7, 1, infile) < 1) { - if (ferror(infile)) - return (13); - else - return (7); - } - - /* Do we have the right magic? */ - if (memcmp(header, "scrypt", 6)) - return (7); - if (header[6] != 0) - return (8); - - /* - * Read another 89 bytes of the file; version 0 of the srypt file - * format has a 96-byte header. - */ - if (fread(&header[7], 89, 1, infile) < 1) { - if (ferror(infile)) - return (13); - else - return (7); - } - - /* Parse the header and generate derived keys. */ - if ((rc = scryptdec_setup(header, dk, passwd, passwdlen, - maxmem, maxmemfrac, maxtime)) != 0) - return (rc); - - /* Start hashing with the header. */ - HMAC_SHA256_Init(&hctx, key_hmac, 32); - HMAC_SHA256_Update(&hctx, header, 96); - - /* - * We don't know how long the encrypted data block is (we can't know, - * since data can be streamed into 'scrypt enc') so we need to read - * data and decrypt all of it except the final 32 bytes, then check - * if that final 32 bytes is the correct signature. - */ - if (AES_set_encrypt_key(key_enc, 256, &key_enc_exp)) - return (5); - if ((AES = crypto_aesctr_init(&key_enc_exp, 0)) == NULL) - return (6); - do { - /* Read data until we have more than 32 bytes of it. */ - if ((readlen = fread(&buf[buflen], 1, - ENCBLOCK + 32 - buflen, infile)) == 0) - break; - buflen += readlen; - if (buflen <= 32) - continue; - - /* - * Decrypt, hash, and output everything except the last 32 - * bytes out of what we have in our buffer. - */ - HMAC_SHA256_Update(&hctx, buf, buflen - 32); - crypto_aesctr_stream(AES, buf, buf, buflen - 32); - if (fwrite(buf, 1, buflen - 32, outfile) < buflen - 32) - return (12); - - /* Move the last 32 bytes to the start of the buffer. */ - memmove(buf, &buf[buflen - 32], 32); - buflen = 32; - } while (1); - crypto_aesctr_free(AES); - - /* Did we exit the loop due to a read error? */ - if (ferror(infile)) - return (13); - - /* Did we read enough data that we *might* have a valid signature? */ - if (buflen < 32) - return (7); - - /* Verify signature. */ - HMAC_SHA256_Final(hbuf, &hctx); - if (memcmp(hbuf, buf, 32)) - return (7); - - /* Zero sensitive data. */ - memset(dk, 0, 64); - memset(&key_enc_exp, 0, sizeof(AES_KEY)); - - return (0); -} diff --git a/lib/scryptenc/scryptenc.h b/lib/scryptenc/scryptenc.h deleted file mode 100644 index 7dc3dd3..0000000 --- a/lib/scryptenc/scryptenc.h +++ /dev/null @@ -1,112 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ -#ifndef _SCRYPTENC_H_ -#define _SCRYPTENC_H_ - -#include -#include - -/** - * The parameters maxmem, maxmemfrac, and maxtime used by all of these - * functions are defined as follows: - * maxmem - maximum number of bytes of storage to use for V array (which is - * by far the largest consumer of memory). If this value is set to 0, no - * maximum will be enforced; any other value less than 1 MiB will be - * treated as 1 MiB. - * maxmemfrac - maximum fraction of available storage to use for the V array, - * where "available storage" is defined as the minimum out of the - * RLIMIT_AS, RLIMIT_DATA. and RLIMIT_RSS resource limits (if any are - * set). If this value is set to 0 or more than 0.5 it will be treated - * as 0.5; and this value will never cause a limit of less than 1 MiB to - * be enforced. - * maxtime - maximum amount of CPU time to spend computing the derived keys, - * in seconds. This limit is only approximately enforced; the CPU - * performance is estimated and parameter limits are chosen accordingly. - * For the encryption functions, the parameters to the scrypt key derivation - * function are chosen to make the key as strong as possible subject to the - * specified limits; for the decryption functions, the parameters used are - * compared to the computed limits and an error is returned if decrypting - * the data would take too much memory or CPU time. - */ -/** - * Return codes from scrypt(enc|dec)_(buf|file): - * 0 success - * 1 getrlimit or sysctl(hw.usermem) failed - * 2 clock_getres or clock_gettime failed - * 3 error computing derived key - * 4 could not read salt from /dev/urandom - * 5 error in OpenSSL - * 6 malloc failed - * 7 data is not a valid scrypt-encrypted block - * 8 unrecognized scrypt format - * 9 decrypting file would take too much memory - * 10 decrypting file would take too long - * 11 password is incorrect - * 12 error writing output file - * 13 error reading input file - */ - -/** - * scryptenc_buf(inbuf, inbuflen, outbuf, passwd, passwdlen, - * maxmem, maxmemfrac, maxtime): - * Encrypt inbuflen bytes from inbuf, writing the resulting inbuflen + 128 - * bytes to outbuf. - */ -int scryptenc_buf(const uint8_t *, size_t, uint8_t *, - const uint8_t *, size_t, size_t, double, double); - -/** - * scryptdec_buf(inbuf, inbuflen, outbuf, outlen, passwd, passwdlen, - * maxmem, maxmemfrac, maxtime): - * Decrypt inbuflen bytes from inbuf, writing the result into outbuf and the - * decrypted data length to outlen. The allocated length of outbuf must - * be at least inbuflen. - */ -int scryptdec_buf(const uint8_t *, size_t, uint8_t *, size_t *, - const uint8_t *, size_t, size_t, double, double); - -/** - * scryptenc_file(infile, outfile, passwd, passwdlen, - * maxmem, maxmemfrac, maxtime): - * Read a stream from infile and encrypt it, writing the resulting stream to - * outfile. - */ -int scryptenc_file(FILE *, FILE *, const uint8_t *, size_t, - size_t, double, double); - -/** - * scryptdec_file(infile, outfile, passwd, passwdlen, - * maxmem, maxmemfrac, maxtime): - * Read a stream from infile and decrypt it, writing the resulting stream to - * outfile. - */ -int scryptdec_file(FILE *, FILE *, const uint8_t *, size_t, - size_t, double, double); - -#endif /* !_SCRYPTENC_H_ */ diff --git a/lib/scryptenc/scryptenc_cpuperf.c b/lib/scryptenc/scryptenc_cpuperf.c deleted file mode 100644 index 27b7915..0000000 --- a/lib/scryptenc/scryptenc_cpuperf.c +++ /dev/null @@ -1,184 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#include - -#include -#include -#include - -#include "crypto_scrypt.h" - -#include "scryptenc_cpuperf.h" - -#ifdef HAVE_CLOCK_GETTIME - -static clock_t clocktouse; - -static int -getclockres(double * resd) -{ - struct timespec res; - - /* - * Try clocks in order of preference until we find one which works. - * (We assume that if clock_getres works, clock_gettime will, too.) - * The use of if/else/if/else/if/else rather than if/elif/elif/else - * is ugly but legal, and allows us to #ifdef things appropriately. - */ -#ifdef CLOCK_VIRTUAL - if (clock_getres(CLOCK_VIRTUAL, &res) == 0) - clocktouse = CLOCK_VIRTUAL; - else -#endif -#ifdef CLOCK_MONOTONIC - if (clock_getres(CLOCK_MONOTONIC, &res) == 0) - clocktouse = CLOCK_MONOTONIC; - else -#endif - if (clock_getres(CLOCK_REALTIME, &res) == 0) - clocktouse = CLOCK_REALTIME; - else - return (-1); - - /* Convert clock resolution to a double. */ - *resd = res.tv_sec + res.tv_nsec * 0.000000001; - - return (0); -} - -static int -getclocktime(struct timespec * ts) -{ - - if (clock_gettime(clocktouse, ts)) - return (-1); - - return (0); -} - -#else -static int -getclockres(double * resd) -{ - - *resd = 1.0 / CLOCKS_PER_SEC; - - return (0); -} - -static int -getclocktime(struct timespec * ts) -{ - struct timeval tv; - - if (gettimeofday(&tv, NULL)) - return (-1); - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec * 1000; - - return (0); -} -#endif - -static int -getclockdiff(struct timespec * st, double * diffd) -{ - struct timespec en; - - if (getclocktime(&en)) - return (1); - *diffd = (en.tv_nsec - st->tv_nsec) * 0.000000001 + - (en.tv_sec - st->tv_sec); - - return (0); -} - -/** - * scryptenc_cpuperf(opps): - * Estimate the number of salsa20/8 cores which can be executed per second, - * and return the value via opps. - */ -int -scryptenc_cpuperf(double * opps) -{ - struct timespec st; - double resd, diffd; - uint64_t i = 0; - - /* Get the clock resolution. */ - if (getclockres(&resd)) - return (2); - -#ifdef DEBUG - fprintf(stderr, "Clock resolution is %f\n", resd); -#endif - - /* Loop until the clock ticks. */ - if (getclocktime(&st)) - return (2); - do { - /* Do an scrypt. */ - if (crypto_scrypt(NULL, 0, NULL, 0, 16, 1, 1, NULL, 0)) - return (3); - - /* Has the clock ticked? */ - if (getclockdiff(&st, &diffd)) - return (2); - if (diffd > 0) - break; - } while (1); - - /* Could how many scryps we can do before the next tick. */ - if (getclocktime(&st)) - return (2); - do { - /* Do an scrypt. */ - if (crypto_scrypt(NULL, 0, NULL, 0, 128, 1, 1, NULL, 0)) - return (3); - - /* We invoked the salsa20/8 core 512 times. */ - i += 512; - - /* Check if we have looped for long enough. */ - if (getclockdiff(&st, &diffd)) - return (2); - if (diffd > resd) - break; - } while (1); - -#ifdef DEBUG - fprintf(stderr, "%ju salsa20/8 cores performed in %f seconds\n", - (uintmax_t)i, diffd); -#endif - - /* We can do approximately i salsa20/8 cores per diffd seconds. */ - *opps = i / diffd; - return (0); -} diff --git a/lib/scryptenc/scryptenc_cpuperf.h b/lib/scryptenc/scryptenc_cpuperf.h deleted file mode 100644 index e236fff..0000000 --- a/lib/scryptenc/scryptenc_cpuperf.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ -#ifndef _SCRYPTENC_CPUPERF_H_ -#define _SCRYPTENC_CPUPERF_H_ - -/** - * scryptenc_cpuperf(opps): - * Estimate the number of salsa20/8 cores which can be executed per second, - * and return the value via opps. - */ -int scryptenc_cpuperf(double *); - -#endif /* !_SCRYPTENC_CPUPERF_H_ */ diff --git a/lib/util/memlimit.c b/lib/util/memlimit.c deleted file mode 100644 index f1f10bf..0000000 --- a/lib/util/memlimit.c +++ /dev/null @@ -1,301 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#include -#include - -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_SYSCTL_HW_USERMEM -#include -#endif -#ifdef HAVE_SYS_SYSINFO_H -#include -#endif - -#include -#include -#include -#include - -#ifdef DEBUG -#include -#endif - -#include "memlimit.h" - -#ifdef HAVE_SYSCTL_HW_USERMEM -static int -memlimit_sysctl_hw_usermem(size_t * memlimit) -{ - int mib[2]; - uint8_t usermembuf[8]; - size_t usermemlen = 8; - uint64_t usermem; - - /* Ask the kernel how much RAM we have. */ - mib[0] = CTL_HW; - mib[1] = HW_USERMEM; - if (sysctl(mib, 2, usermembuf, &usermemlen, NULL, 0)) - return (1); - - /* - * Parse as either a uint64_t or a uint32_t based on the length of - * output the kernel reports having copied out. It appears that all - * systems providing a sysctl interface for reading integers copy - * them out as system-endian values, so we don't need to worry about - * parsing them. - */ - if (usermemlen == sizeof(uint64_t)) - usermem = *(uint64_t *)usermembuf; - else if (usermemlen == sizeof(uint32_t)) - usermem = *(uint32_t *)usermembuf; - else - return (1); - - /* Return the sysctl value, but clamp to SIZE_MAX if necessary. */ -#if UINT64_MAX > SIZE_MAX - if (usermem > SIZE_MAX) - *memlimit = SIZE_MAX; - else - *memlimit = usermem; -#else - *memlimit = usermem; -#endif - - /* Success! */ - return (0); -} -#endif - -/* If we don't HAVE_STRUCT_SYSINFO, we can't use sysinfo. */ -#ifndef HAVE_STRUCT_SYSINFO -#undef HAVE_SYSINFO -#endif - -/* If we don't HAVE_STRUCT_SYSINFO_TOTALRAM, we can't use sysinfo. */ -#ifndef HAVE_STRUCT_SYSINFO_TOTALRAM -#undef HAVE_SYSINFO -#endif - -#ifdef HAVE_SYSINFO -static int -memlimit_sysinfo(size_t * memlimit) -{ - struct sysinfo info; - uint64_t totalmem; - - /* Get information from the kernel. */ - if (sysinfo(&info)) - return (1); - totalmem = info.totalram; - - /* If we're on a modern kernel, adjust based on mem_unit. */ -#ifdef HAVE_STRUCT_SYSINFO_MEM_UNIT - totalmem = totalmem * info.mem_unit; -#endif - - /* Return the value, but clamp to SIZE_MAX if necessary. */ -#if UINT64_MAX > SIZE_MAX - if (totalmem > SIZE_MAX) - *memlimit = SIZE_MAX; - else - *memlimit = totalmem; -#else - *memlimit = totalmem; -#endif - - /* Success! */ - return (0); -} -#endif /* HAVE_SYSINFO */ - -static int -memlimit_rlimit(size_t * memlimit) -{ - struct rlimit rl; - uint64_t memrlimit; - - /* Find the least of... */ - memrlimit = (uint64_t)(-1); - - /* ... RLIMIT_AS... */ -#ifdef RLIMIT_AS - if (getrlimit(RLIMIT_AS, &rl)) - return (1); - if ((rl.rlim_cur != RLIM_INFINITY) && - ((uint64_t)rl.rlim_cur < memrlimit)) - memrlimit = rl.rlim_cur; -#endif - - /* ... RLIMIT_DATA... */ - if (getrlimit(RLIMIT_DATA, &rl)) - return (1); - if ((rl.rlim_cur != RLIM_INFINITY) && - ((uint64_t)rl.rlim_cur < memrlimit)) - memrlimit = rl.rlim_cur; - - /* ... and RLIMIT_RSS. */ -#ifdef RLIMIT_RSS - if (getrlimit(RLIMIT_RSS, &rl)) - return (1); - if ((rl.rlim_cur != RLIM_INFINITY) && - ((uint64_t)rl.rlim_cur < memrlimit)) - memrlimit = rl.rlim_cur; -#endif - - /* Return the value, but clamp to SIZE_MAX if necessary. */ -#if UINT64_MAX > SIZE_MAX - if (memrlimit > SIZE_MAX) - *memlimit = SIZE_MAX; - else - *memlimit = memrlimit; -#else - *memlimit = memrlimit; -#endif - - /* Success! */ - return (0); -} - -#ifdef _SC_PHYS_PAGES - -/* Some systems define _SC_PAGESIZE instead of _SC_PAGE_SIZE. */ -#ifndef _SC_PAGE_SIZE -#define _SC_PAGE_SIZE _SC_PAGESIZE -#endif - -static int -memlimit_sysconf(size_t * memlimit) -{ - long pagesize; - long physpages; - uint64_t totalmem; - - /* Set errno to 0 in order to distinguish "no limit" from "error". */ - errno = 0; - - /* Read the two limits. */ - if (((pagesize = sysconf(_SC_PAGE_SIZE)) == -1) || - ((physpages = sysconf(_SC_PHYS_PAGES)) == -1)) { - /* Did an error occur? */ - if (errno != 0) - return (1); - - /* If not, there is no limit. */ - totalmem = (uint64_t)(-1); - } else { - /* Compute the limit. */ - totalmem = (uint64_t)(pagesize) * (uint64_t)(physpages); - } - - /* Return the value, but clamp to SIZE_MAX if necessary. */ -#if UINT64_MAX > SIZE_MAX - if (totalmem > SIZE_MAX) - *memlimit = SIZE_MAX; - else - *memlimit = totalmem; -#else - *memlimit = totalmem; -#endif - - /* Success! */ - return (0); -} -#endif - -int -memtouse(size_t maxmem, double maxmemfrac, size_t * memlimit) -{ - size_t sysctl_memlimit, sysinfo_memlimit, rlimit_memlimit; - size_t sysconf_memlimit; - size_t memlimit_min; - size_t memavail; - - /* Get memory limits. */ -#ifdef HAVE_SYSCTL_HW_USERMEM - if (memlimit_sysctl_hw_usermem(&sysctl_memlimit)) - return (1); -#else - sysctl_memlimit = (size_t)(-1); -#endif -#ifdef HAVE_SYSINFO - if (memlimit_sysinfo(&sysinfo_memlimit)) - return (1); -#else - sysinfo_memlimit = (size_t)(-1); -#endif - if (memlimit_rlimit(&rlimit_memlimit)) - return (1); -#ifdef _SC_PHYS_PAGES - if (memlimit_sysconf(&sysconf_memlimit)) - return (1); -#else - sysconf_memlimit = (size_t)(-1); -#endif - -#ifdef DEBUG - fprintf(stderr, "Memory limits are %zu %zu %zu %zu\n", - sysctl_memlimit, sysinfo_memlimit, rlimit_memlimit, - sysconf_memlimit); -#endif - - /* Find the smallest of them. */ - memlimit_min = (size_t)(-1); - if (memlimit_min > sysctl_memlimit) - memlimit_min = sysctl_memlimit; - if (memlimit_min > sysinfo_memlimit) - memlimit_min = sysinfo_memlimit; - if (memlimit_min > rlimit_memlimit) - memlimit_min = rlimit_memlimit; - if (memlimit_min > sysconf_memlimit) - memlimit_min = sysconf_memlimit; - - /* Only use the specified fraction of the available memory. */ - if ((maxmemfrac > 0.5) || (maxmemfrac == 0.0)) - maxmemfrac = 0.5; - memavail = maxmemfrac * memlimit_min; - - /* Don't use more than the specified maximum. */ - if ((maxmem > 0) && (memavail > maxmem)) - memavail = maxmem; - - /* But always allow at least 1 MiB. */ - if (memavail < 1048576) - memavail = 1048576; - -#ifdef DEBUG - fprintf(stderr, "Allowing up to %zu memory to be used\n", memavail); -#endif - - /* Return limit via the provided pointer. */ - *memlimit = memavail; - return (0); -} diff --git a/lib/util/memlimit.h b/lib/util/memlimit.h deleted file mode 100644 index d3b4891..0000000 --- a/lib/util/memlimit.h +++ /dev/null @@ -1,42 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ -#ifndef _MEMLIMIT_H_ -#define _MEMLIMIT_H_ - -#include - -/** - * memtouse(maxmem, maxmemfrac, memlimit): - * Examine the system and return via memlimit the amount of RAM which should - * be used -- the specified fraction of the available RAM, but no more than - * maxmem, and no less than 1MiB. - */ -int memtouse(size_t, double, size_t *); - -#endif /* !_MEMLIMIT_H_ */ diff --git a/lib/util/readpass.c b/lib/util/readpass.c deleted file mode 100644 index f76fb46..0000000 --- a/lib/util/readpass.c +++ /dev/null @@ -1,142 +0,0 @@ -/*- - * Copyright 2009 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. - */ - -#include -#include -#include -#include -#include - -#include "warn.h" - -#include "readpass.h" - -#define MAXPASSLEN 2048 - -/** - * tarsnap_getpass(passwd, prompt, confirmprompt, devtty) - * If ${devtty} is non-zero, read a password from /dev/tty if possible; if - * not, read from stdin. If reading from a tty (either /dev/tty or stdin), - * disable echo and prompt the user by printing ${prompt} to stderr. If - * ${confirmprompt} is non-NULL, read a second password (prompting if a - * terminal is being used) and repeat until the user enters the same password - * twice. Return the password as a malloced NUL-terminated string via - * ${passwd}. The obscure name is to avoid namespace collisions due to the - * getpass / readpass / readpassphrase / etc. functions in various libraries. - */ -int -tarsnap_readpass(char ** passwd, const char * prompt, - const char * confirmprompt, int devtty) -{ - FILE * readfrom; - char passbuf[MAXPASSLEN]; - char confpassbuf[MAXPASSLEN]; - struct termios term, term_old; - int usingtty; - - /* - * If devtty != 0, try to open /dev/tty; if that fails, or if devtty - * is zero, we'll read the password from stdin instead. - */ - if ((devtty == 0) || ((readfrom = fopen("/dev/tty", "r")) == NULL)) - readfrom = stdin; - - /* If we're reading from a terminal, try to disable echo. */ - if ((usingtty = isatty(fileno(readfrom))) != 0) { - if (tcgetattr(fileno(readfrom), &term_old)) { - warn("Cannot read terminal settings"); - goto err1; - } - memcpy(&term, &term_old, sizeof(struct termios)); - term.c_lflag = (term.c_lflag & ~ECHO) | ECHONL; - if (tcsetattr(fileno(readfrom), TCSANOW, &term)) { - warn("Cannot set terminal settings"); - goto err1; - } - } - -retry: - /* If we have a terminal, prompt the user to enter the password. */ - if (usingtty) - fprintf(stderr, "%s: ", prompt); - - /* Read the password. */ - if (fgets(passbuf, MAXPASSLEN, readfrom) == NULL) { - warn("Cannot read password"); - goto err2; - } - - /* Confirm the password if necessary. */ - if (confirmprompt != NULL) { - if (usingtty) - fprintf(stderr, "%s: ", confirmprompt); - if (fgets(confpassbuf, MAXPASSLEN, readfrom) == NULL) { - warn("Cannot read password"); - goto err2; - } - if (strcmp(passbuf, confpassbuf)) { - fprintf(stderr, - "Passwords mismatch, please try again\n"); - goto retry; - } - } - - /* Terminate the string at the first "\r" or "\n" (if any). */ - passbuf[strcspn(passbuf, "\r\n")] = '\0'; - - /* If we changed terminal settings, reset them. */ - if (usingtty) - tcsetattr(fileno(readfrom), TCSANOW, &term_old); - - /* Close /dev/tty if we opened it. */ - if (readfrom != stdin) - fclose(readfrom); - - /* Copy the password out. */ - if ((*passwd = strdup(passbuf)) == NULL) { - warn("Cannot allocate memory"); - goto err1; - } - - /* Zero any stored passwords. */ - memset(passbuf, 0, MAXPASSLEN); - memset(confpassbuf, 0, MAXPASSLEN); - - /* Success! */ - return (0); - -err2: - /* Reset terminal settings if necessary. */ - if (usingtty) - tcsetattr(fileno(readfrom), TCSAFLUSH, &term_old); -err1: - /* Close /dev/tty if we opened it. */ - if (readfrom != stdin) - fclose(readfrom); - - /* Failure! */ - return (-1); -} diff --git a/lib/util/readpass.h b/lib/util/readpass.h deleted file mode 100644 index da57278..0000000 --- a/lib/util/readpass.h +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ -#ifndef _READPASS_H_ -#define _READPASS_H_ - -/** - * tarsnap_getpass(passwd, prompt, confirmprompt, devtty) - * If ${devtty} is non-zero, read a password from /dev/tty if possible; if - * not, read from stdin. If reading from a tty (either /dev/tty or stdin), - * disable echo and prompt the user by printing ${prompt} to stderr. If - * ${confirmprompt} is non-NULL, read a second password (prompting if a - * terminal is being used) and repeat until the user enters the same password - * twice. Return the password as a malloced NUL-terminated string via - * ${passwd}. The obscure name is to avoid namespace collisions due to the - * getpass / readpass / readpassphrase / etc. functions in various libraries. - */ -int tarsnap_readpass(char **, const char *, const char *, int); - -#endif /* !_READPASS_H_ */ diff --git a/lib/util/sysendian.h b/lib/util/sysendian.h deleted file mode 100644 index 0495194..0000000 --- a/lib/util/sysendian.h +++ /dev/null @@ -1,138 +0,0 @@ -/*- - * Copyright 2007-2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ -#ifndef _SYSENDIAN_H_ -#define _SYSENDIAN_H_ - -/* If we don't have be64enc, the we have isn't usable. */ -#if !HAVE_DECL_BE64ENC -#undef HAVE_SYS_ENDIAN_H -#endif - -#ifdef HAVE_SYS_ENDIAN_H - -#include - -#else - -#include - -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 uint64_t -be64dec(const void *pp) -{ - const uint8_t *p = (uint8_t const *)pp; - - return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) + - ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) + - ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) + - ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56)); -} - -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 /* !HAVE_SYS_ENDIAN_H */ - -#endif /* !_SYSENDIAN_H_ */ diff --git a/lib/util/warn.c b/lib/util/warn.c deleted file mode 100644 index 69f7b2d..0000000 --- a/lib/util/warn.c +++ /dev/null @@ -1,74 +0,0 @@ -/*- - * Copyright 2009 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. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#ifdef HAVE_ERR_H -/* - * Everything is provided through err.h and the associated library, so we - * don't need to do anything here. - */ -#else -#include -#include -#include -#include - -#include "warn.h" - -const char * warn_progname = "(null)"; - -void -warn(const char * fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - fprintf(stderr, "%s", warn_progname); - if (fmt != NULL) { - fprintf(stderr, ": "); - vfprintf(stderr, fmt, ap); - } - fprintf(stderr, ": %s\n", strerror(errno)); - va_end(ap); -} - -void -warnx(const char * fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - fprintf(stderr, "%s", warn_progname); - if (fmt != NULL) { - fprintf(stderr, ": "); - vfprintf(stderr, fmt, ap); - } - fprintf(stderr, "\n"); - va_end(ap); -} -#endif diff --git a/lib/util/warn.h b/lib/util/warn.h deleted file mode 100644 index 262d24b..0000000 --- a/lib/util/warn.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _WARN_H_ -#define _WARN_H_ - -#ifdef HAVE_ERR_H -#include -#else -#define NEED_WARN_PROGNAME -const char * warn_progname; -void warn(const char *, ...); -void warnx(const char *, ...); -#endif - -#endif /* !_WARN_H_ */ diff --git a/luascrypt.c b/luascrypt.c index f863381..2492cf7 100644 --- a/luascrypt.c +++ b/luascrypt.c @@ -1,208 +1,149 @@ -/* scrypt for Lua - * Copyright 2013 Rob Kendrick - * - * Heavy based on Barry Steyn's code, and distributed under the same licence: - * - * Copyright (C) 2012 Barry Steyn (http://doctrina.org/Scrypt-Authentication-For-Node.html) - * - * This source code is provided 'as-is', without any express or implied - * warranty. In no event will the author be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this source code must not be misrepresented; you must not - * claim that you wrote the original source code. If you use this source code - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original source code. +/* + * luascrypt - Lua binding to libscrypt * - * 3. This notice may not be removed or altered from any source distribution. + * Copyright 2015 Daniel Silverstone * - * Barry Steyn barry.steyn@gmail.com + * Please see the file COPYING for licence details. */ -#include -#include +#include #include +#include + +#include +#include #include #include -#include -#include -#include -#include +#include "lua.h" +#include "lauxlib.h" -#include "sha256.h" -#include "sysendian.h" -#include "crypto_scrypt.h" -#include "memlimit.h" -#include "scryptenc_cpuperf.h" +#include "libscrypt.h" -/* - * Obtains salt for password hash. This function is copied from Colin Percival's scrypt reference code - */ -static int -getsalt(uint8_t salt[32]) { +static void +luascrypt_salt_gen(char *salt, int saltlen) +{ int fd; - ssize_t lenread; - uint8_t * buf = salt; - size_t buflen = 32; - - /* Open /dev/urandom. */ - if ((fd = open("/dev/urandom", O_RDONLY)) == -1) - goto err0; - - /* Read bytes until we have filled the buffer. */ - while (buflen > 0) { - if ((lenread = read(fd, buf, buflen)) == -1) - goto err1; - - /* The random device should never EOF. */ - if (lenread == 0) - goto err1; - - /* We're partly done. */ - buf += lenread; - buflen -= lenread; - } - - /* Close the device. */ - while (close(fd) == -1) { - if (errno != EINTR) - goto err0; + /* We'd go with libscrypt's implementation, but since libscrypt's salt + * generation is time based, we cannot fully trust it to generate + * unique salts so to improve our chances we assume we have urandom + * and fall back to libscrypt's implementation if we don't. Since the + * libscrypt implementation is fast, call it, and then overwrite it + * if we can... + */ + libscrypt_salt_gen(salt, saltlen); + + fd = open("/dev/urandom", O_RDONLY); + if (fd >= 0) { + read(fd, salt, saltlen); /* Ignore errors in these two calls */ + close(fd); /* Since we have our fallback. */ } - - /* Success! */ - return (0); - -err1: - close(fd); -err0: - /* Failure! */ - return (4); } static int -ls_hash_password(lua_State *L) +luascrypt_hash_password(lua_State *L) { - const uint8_t *passwd = (const uint8_t *)luaL_checkstring(L, 1); - size_t passwdlen = lua_objlen(L, 1); - uint64_t N = luaL_checknumber(L, 2); - uint32_t r = luaL_checknumber(L, 3); - uint32_t p = luaL_checknumber(L, 4); - - uint8_t dk[64], salt[32], hbuf[32], header[96]; - uint8_t *key_hmac = &dk[32]; - - SHA256_CTX ctx; - HMAC_SHA256_CTX hctx; - - int result; - - errno = 0; - if ((result = getsalt(salt)) != 0) { - lua_pushstring(L, strerror(errno)); - lua_error(L); + // password {N, r, p} -> crypted + size_t passwd_len; + const char *passwd = luaL_checklstring(L, 1, &passwd_len); + char buffer[256]; /* This value is nasty here, but */ + char salt[16]; /* while I am not normally into magic */ + uint8_t hashbuf[64]; /* numbers, these are taken from the */ + char saltbuf[256]; /* libscrypt_hash() source. */ + char outbuf[256]; /* Icky, I know, but what can I do? */ + uint32_t N = SCRYPT_N; + uint32_t r = SCRYPT_r; + uint32_t p = SCRYPT_p; + if (lua_gettop(L) > 1) { + N = (uint32_t)luaL_checknumber(L, 2); + r = (uint32_t)luaL_checknumber(L, 3); + p = (uint32_t)luaL_checknumber(L, 4); } - errno = 0; - if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64) != 0) { - lua_pushstring(L, strerror(errno)); - lua_error(L); + /* We know that libscrypt is limited to N of 2^15 or less + * so raise an error if N is too large + */ + if (N > 32768) { + return luaL_error(L, "Unable to generate password hash: %s", + "N is too large (limited to 2^15)"); } - memcpy(header, "scrypt", 6); - header[6] = 0; - header[7] = (int)log2(N); - be32enc(&header[8], r); - be32enc(&header[12], p); - memcpy(&header[16], salt, 32); + luascrypt_salt_gen(salt, sizeof(salt)); + + if (libscrypt_scrypt((uint8_t*)passwd, passwd_len, + (uint8_t*)salt, sizeof(salt), + N, r, p, + hashbuf, sizeof(hashbuf)) < 0) { + return luaL_error(L, "Unable to generate password hash: %s", + (errno == EFBIG) ? "r and p are too large" : + (errno == EINVAL) ? "N is not a power of 2" : + (errno == ENOMEM) ? "Buffer sizes are bad" : + "Unknown error"); + } - SHA256_Init(&ctx); - SHA256_Update(&ctx, header, 48); - SHA256_Final(hbuf, &ctx); - memcpy(&header[48], hbuf, 16); + if (libscrypt_b64_encode(outbuf, (char *)hashbuf, sizeof(hashbuf)) < 0) { + return luaL_error(L, "Unable to encode password hash."); + } - HMAC_SHA256_Init(&hctx, key_hmac, 32); - HMAC_SHA256_Update(&hctx, header, 64); - HMAC_SHA256_Final(hbuf, &hctx); - memcpy(&header[64], hbuf, 32); + if (libscrypt_b64_encode(saltbuf, salt, sizeof(salt)) < 0) { + return luaL_error(L, "Unable to encode salt."); + } - lua_pushlstring(L, (const char *)header, 96); + if (libscrypt_mcf(N, r, p, saltbuf, outbuf, buffer) < 1) { + return luaL_error(L, "Unable to mcf encode password."); + } + + + /* some versions of libscrypt fail to include the final equals + * after mcf encoding -- check and if it's missing, add it back + */ + { + int oblen = strlen(outbuf); + int bulen = strlen(buffer); + if (outbuf[oblen-1] == outbuf[oblen-2] && + outbuf[oblen-1] == '=' && + buffer[bulen-1] == '=' && buffer[bulen-2] != '=') { + strcat(buffer, "="); + } + } + + lua_pushstring(L, buffer); return 1; } static int -ls_verify_password(lua_State *L) { - const uint8_t *header = (uint8_t *)luaL_checkstring(L, 1); - const uint8_t *passwd = (uint8_t *)luaL_checkstring(L, 2); - size_t headerlen = lua_objlen(L, 1); - size_t passwdlen = lua_objlen(L, 2); - - int N; - uint32_t r, p; - uint8_t dk[64], salt[32], hbuf[32]; - uint8_t *key_hmac = &dk[32]; - - HMAC_SHA256_CTX hctx; - SHA256_CTX ctx; - - if (headerlen != 96) { - lua_pushliteral(L, "password hash must be 96 bytes"); - lua_error(L); - } - - N = (uint64_t) 1 << header[7]; - r = be32dec(&header[8]); - p = be32dec(&header[12]); - memcpy(salt, &header[16], 32); - - SHA256_Init(&ctx); - SHA256_Update(&ctx, header, 48); - SHA256_Final(hbuf, &ctx); - - if (memcmp(&header[48], hbuf, 16)) { - lua_pushnil(L); - lua_pushliteral(L, "header SHA does not verify; hash corrupt"); - return 2; - } +luascrypt_verify_password(lua_State *L) +{ + // crypted password -> okbool + const char *crypted = luaL_checkstring(L, 1); + const char *passwd = luaL_checkstring(L, 2); - errno = 0; - if (crypto_scrypt(passwd, passwdlen, salt, 32, N, r, p, dk, 64) != 0) { - lua_pushstring(L, strerror(errno)); - lua_error(L); - } + /* libscrypt_check() mutates the provided crypted data, so copy it + * otherwise we damage the memory Lua holds. + */ + char *crypted_copy = (char *)lua_newuserdata(L, strlen(crypted)+1); + strcpy(crypted_copy, crypted); - HMAC_SHA256_Init(&hctx, key_hmac, 32); - HMAC_SHA256_Update(&hctx, header, 64); - HMAC_SHA256_Final(hbuf, &hctx); + int r = libscrypt_check(crypted_copy, (char *)passwd); - if (memcmp(hbuf, &header[64], 32)) { - lua_pushboolean(L, 0); - } else { - lua_pushboolean(L, 1); + if (r < 0) { + return luaL_error(L, "Unable to verify password. Bad crypt."); } + lua_pushboolean(L, r); return 1; } -static const struct luaL_Reg -ls_functions[] = { - { "hash_password", ls_hash_password }, - { "verify_password", ls_verify_password }, - +static const struct luaL_Reg +luascrypt_functions[] = { + { "hash_password", luascrypt_hash_password }, + { "verify_password", luascrypt_verify_password }, { NULL, NULL } }; int luaopen_scrypt(lua_State *L) { - - luaL_register(L, "scrypt", ls_functions); + luaL_register(L, "scrypt", luascrypt_functions); return 1; } -- cgit v1.2.1