├── CREDITS ├── clean.sh ├── php_scrypt.stub.php ├── tests ├── scrypt_pickparams_success.phpt ├── scrypt_error_stacktrace.phpt ├── scrypt_pickparams_errors.phpt ├── scrypt_errors.phpt └── scrypt_vectors.phpt ├── crypto ├── README ├── crypto_scrypt.h ├── sha256.h ├── params.h ├── sysendian.h ├── crypto_scrypt-nosse.c ├── crypto_scrypt-sse.c ├── sha256.c └── params.c ├── config.w32 ├── .gitignore ├── php_scrypt_legacy_arginfo.h ├── VS2008 ├── VS2008.sln ├── VS2008.vcproj └── stdint.h ├── .github └── workflows │ └── ci.yaml ├── php-scrypt.sublime-project ├── LICENSE ├── php_scrypt_arginfo.h ├── php_scrypt.h ├── config.m4 ├── php_scrypt_utils.h ├── php_scrypt_utils.c ├── README.md ├── scrypt.php ├── package.xml └── php_scrypt.c /CREDITS: -------------------------------------------------------------------------------- 1 | scrypt 2 | Dominic Black -------------------------------------------------------------------------------- /clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | find . -name \*.gcno -o -name \*.gcda | xargs rm -f 4 | find . -name \*.lo -o -name \*.o | xargs rm -f 5 | find . -name \*.la -o -name \*.a | xargs rm -f 6 | find . -name \*.so | xargs rm -f 7 | find . -name .libs -a -type d|xargs rm -rf 8 | rm -f libphp.la modules/* libs/* 9 | -------------------------------------------------------------------------------- /php_scrypt.stub.php: -------------------------------------------------------------------------------- 1 | 5 | --FILE-- 6 | 16 | --EXPECT-- 17 | array 18 | integer 19 | integer 20 | integer 21 | -------------------------------------------------------------------------------- /crypto/README: -------------------------------------------------------------------------------- 1 | The source code under this directory is taken from the client for the 2 | Tarsnap online backup system (and released under the 2-clause BSD license 3 | with permission of the author); keeping this code in sync with the Tarsnap 4 | code is highly desirable and explains why there is some functionality 5 | included here which is not actually used by the scrypt file encryption 6 | utility. 7 | 8 | It has been modified to use PHP's internal memory functions and to report 9 | more developer friendly error messages incase of invalid parameters. -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | ARG_ENABLE("scrypt", "whether to enable scrypt support", "no"); 2 | 3 | if (PHP_SCRYPT != "no") { 4 | if (CHECK_HEADER_ADD_INCLUDE("crypto/crypto_scrypt.h", "CFLAGS_SCRYPT", PHP_SCRYPT + ";" + configure_module_dirname)) { 5 | EXTENSION("scrypt", "php_scrypt.c php_scrypt_utils.c"); 6 | 7 | ADD_SOURCES(configure_module_dirname + "\\crypto", "sha256.c crypto_scrypt-nosse.c params.c", "scrypt"); 8 | 9 | ADD_EXTENSION_DEP('scrypt', 'hash'); 10 | } else { 11 | WARNING("scrypt not enabled, headers not found"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/scrypt_error_stacktrace.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test if senstive parameters are not shown in the stacktrace 3 | --SKIPIF-- 4 | 8 | --FILE-- 9 | 12 | --EXPECTF-- 13 | Fatal error: Uncaught Error: scrypt(): Argument #3 ($N) must be greater than 1 in %s:%d 14 | Stack trace: 15 | #0 %s(%d): scrypt(Object(SensitiveParameterValue), Object(SensitiveParameterValue), 1, 1, 1, 64) 16 | #1 {main} 17 | thrown in %s on line %d 18 | -------------------------------------------------------------------------------- /tests/scrypt_pickparams_errors.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test scrypt_pickparams() error conditions 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getMessage() . "\n"; 12 | } 13 | 14 | try { 15 | scrypt_pickparams(1024, -1, 1000); 16 | } catch (Error $e) { 17 | echo $e->getMessage() . "\n"; 18 | } 19 | 20 | try { 21 | scrypt_pickparams(1024, 0.75, -1); 22 | } catch (Error $e) { 23 | echo $e->getMessage() . "\n"; 24 | } 25 | ?> 26 | --EXPECT-- 27 | scrypt_pickparams(): Argument #1 ($max_memory) must be greater than or equal to 0 28 | scrypt_pickparams(): Argument #2 ($memory_fraction) must be greater than or equal to 0 29 | scrypt_pickparams(): Argument #3 ($max_time) must be greater than or equal to 0 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # Pecl Package Files 3 | # 4 | scrypt-*.tgz 5 | 6 | # 7 | # phpize & make related files 8 | # 9 | 10 | .deps 11 | *.dep 12 | *.lo 13 | *.la 14 | .libs 15 | ac*.m4 16 | *.cache 17 | build 18 | config.guess 19 | config.h* 20 | config.s* 21 | config.nice 22 | config.log 23 | libtool 24 | configure* 25 | install-sh 26 | ltmain.sh 27 | ltmain.sh.backup 28 | Makefile* 29 | missing 30 | mkinstalldirs 31 | run-tests.php 32 | modules 33 | 34 | # 35 | # Test Output 36 | # 37 | tests/*.diff 38 | tests/*.exp 39 | tests/*.log 40 | tests/*.out 41 | tests/*.php 42 | tests/*.sh 43 | 44 | # 45 | # Visual Studio 46 | # 47 | 48 | *.suo 49 | *.user 50 | Debug/ 51 | Release/ 52 | bin/ 53 | obj/ 54 | 55 | # 56 | # Random other things which we dont want commited 57 | # 58 | 59 | # Backups 60 | *~ 61 | 62 | # Windows thumb nails 63 | Thumbs.db 64 | 65 | # OSX store fiels 66 | .DS_Store 67 | -------------------------------------------------------------------------------- /php_scrypt_legacy_arginfo.h: -------------------------------------------------------------------------------- 1 | /* This is a generated file, edit the .stub.php file instead. 2 | * Stub hash: 8b564912a6ddca2a4134bbff80f81e82ba20805e */ 3 | 4 | ZEND_BEGIN_ARG_INFO_EX(arginfo_scrypt, 0, 0, 6) 5 | ZEND_ARG_INFO(0, password) 6 | ZEND_ARG_INFO(0, salt) 7 | ZEND_ARG_INFO(0, N) 8 | ZEND_ARG_INFO(0, r) 9 | ZEND_ARG_INFO(0, p) 10 | ZEND_ARG_INFO(0, key_length) 11 | ZEND_ARG_INFO(0, raw_output) 12 | ZEND_END_ARG_INFO() 13 | 14 | ZEND_BEGIN_ARG_INFO_EX(arginfo_scrypt_pickparams, 0, 0, 3) 15 | ZEND_ARG_INFO(0, max_memory) 16 | ZEND_ARG_INFO(0, memory_fraction) 17 | ZEND_ARG_INFO(0, max_time) 18 | ZEND_END_ARG_INFO() 19 | 20 | 21 | ZEND_FUNCTION(scrypt); 22 | ZEND_FUNCTION(scrypt_pickparams); 23 | 24 | 25 | static const zend_function_entry ext_functions[] = { 26 | ZEND_FE(scrypt, arginfo_scrypt) 27 | ZEND_FE(scrypt_pickparams, arginfo_scrypt_pickparams) 28 | ZEND_FE_END 29 | }; 30 | -------------------------------------------------------------------------------- /VS2008/VS2008.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C++ Express 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "VS2008", "VS2008.vcproj", "{B35A6700-5654-41E7-9EC4-F2A1703B8148}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {B35A6700-5654-41E7-9EC4-F2A1703B8148}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {B35A6700-5654-41E7-9EC4-F2A1703B8148}.Debug|Win32.Build.0 = Debug|Win32 14 | {B35A6700-5654-41E7-9EC4-F2A1703B8148}.Release|Win32.ActiveCfg = Release|Win32 15 | {B35A6700-5654-41E7-9EC4-F2A1703B8148}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | env: 8 | REPORT_EXIT_STATUS: 1 9 | NO_INTERACTION: 1 10 | 11 | jobs: 12 | tests: 13 | name: Tests 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | php-version: 18 | - 7.0 19 | - 7.1 20 | - 7.2 21 | - 7.3 22 | - 7.4 23 | - 8.0 24 | - 8.1 25 | - nightly 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@master 29 | - name: Install PHP ${{ matrix.php-version }} 30 | uses: shivammathur/setup-php@v2 31 | with: 32 | php-version: ${{ matrix.php-version }} 33 | coverage: none 34 | tools: none 35 | - name: Build extension 36 | run: | 37 | phpize 38 | ./configure --enable-scrypt 39 | make -j$(nproc) all 40 | - name: Run tests 41 | run: make -j$(nproc) test 42 | -------------------------------------------------------------------------------- /php-scrypt.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": "./", 6 | 7 | "file_exclude_patterns": 8 | [ 9 | "*.sublime-project", 10 | ".deps", 11 | "ac*.m4", 12 | "config.h*", 13 | "config.log", 14 | "config.nice", 15 | "config.guess", 16 | "configure*", 17 | "config.s*", 18 | "*.la", 19 | "*.lo", 20 | "*sh", 21 | "libtool", 22 | "Makefile*", 23 | "missing", 24 | "mkinstalldirs", 25 | "run-tests.php", 26 | "tests/*.diff", 27 | "tests/*.exp", 28 | "tests/*.log", 29 | "tests/*.out" 30 | ], 31 | "folder_exclude_patterns": 32 | [ 33 | ".libs", 34 | "*.cache", 35 | "build", 36 | "include", 37 | "modules" 38 | ] 39 | } 40 | ], 41 | "settings": 42 | { 43 | "tab_size": 4 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/scrypt_errors.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test scrypt() error conditions 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getMessage() . "\n"; 12 | } 13 | 14 | try { 15 | scrypt("", "", 15, 1, 1, 64); 16 | } catch (Error $e) { 17 | echo $e->getMessage() . "\n"; 18 | } 19 | 20 | try { 21 | scrypt("", "", 16, 0, 1, 64); 22 | } catch (Error $e) { 23 | echo $e->getMessage() . "\n"; 24 | } 25 | 26 | try { 27 | scrypt("", "", 16, 1, 0, 16); 28 | } catch (Error $e) { 29 | echo $e->getMessage() . "\n"; 30 | } 31 | 32 | try { 33 | scrypt("", "", 16, 1, 1, 15); 34 | } catch (Error $e) { 35 | echo $e->getMessage() . "\n"; 36 | } 37 | 38 | try { 39 | scrypt("", "", 16, 1, 1, PHP_INT_MAX); 40 | } catch (Error $e) { 41 | echo $e->getMessage() . "\n"; 42 | } 43 | 44 | ?> 45 | --EXPECT-- 46 | scrypt(): Argument #3 ($N) must be greater than 1 47 | scrypt(): Argument #3 ($N) must be a power of 2 48 | scrypt(): Argument #4 ($r) must be greater than 0 49 | scrypt(): Argument #5 ($p) must be greater than 0 50 | scrypt(): Argument #6 ($key_length) must be greater than or equal to 16 51 | scrypt(): Argument #6 ($key_length) must be less than or equal to (2^32 - 1) * 32 52 | -------------------------------------------------------------------------------- /tests/scrypt_vectors.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test scrypt KDF using test vectors. 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | memory_limit=2G 7 | --FILE-- 8 | 16 | --EXPECT-- 17 | 77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906 18 | fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640 19 | 7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887 20 | 2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4 21 | 2db1a53b0a889790797d7c75b6873ec27ad167c5f65bc83dce81c8c293c70e8c28d7f4826a3fba2b063908904ad2f750a87b85dcfc0c79599070261eed114002 22 | 2db1a53b0a889790797d7c75b6873ec27ad167c5f65bc83dce81c8c293c70e8c28d7f4826a3fba2b063908904ad2f750a87b85dcfc0c79599070261eed114002 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Original Scrypt Implementation; 2 | Copyright (c) 2009 Colin Percival 3 | 4 | PHP Module; 5 | Copyright (c) 2012, Dominic Black 6 | 7 | All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 12 | 13 | 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. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. 16 | -------------------------------------------------------------------------------- /php_scrypt_arginfo.h: -------------------------------------------------------------------------------- 1 | /* This is a generated file, edit the .stub.php file instead. 2 | * Stub hash: 8b564912a6ddca2a4134bbff80f81e82ba20805e */ 3 | 4 | ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_scrypt, 0, 6, MAY_BE_STRING|MAY_BE_FALSE) 5 | ZEND_ARG_TYPE_INFO(0, password, IS_STRING, 0) 6 | ZEND_ARG_TYPE_INFO(0, salt, IS_STRING, 0) 7 | ZEND_ARG_TYPE_INFO(0, N, IS_LONG, 0) 8 | ZEND_ARG_TYPE_INFO(0, r, IS_LONG, 0) 9 | ZEND_ARG_TYPE_INFO(0, p, IS_LONG, 0) 10 | ZEND_ARG_TYPE_INFO(0, key_length, IS_LONG, 0) 11 | ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, raw_output, _IS_BOOL, 0, "false") 12 | ZEND_END_ARG_INFO() 13 | 14 | ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_scrypt_pickparams, 0, 3, MAY_BE_ARRAY|MAY_BE_FALSE) 15 | ZEND_ARG_TYPE_INFO(0, max_memory, IS_LONG, 0) 16 | ZEND_ARG_TYPE_INFO(0, memory_fraction, IS_DOUBLE, 0) 17 | ZEND_ARG_TYPE_INFO(0, max_time, IS_DOUBLE, 0) 18 | ZEND_END_ARG_INFO() 19 | 20 | 21 | ZEND_FUNCTION(scrypt); 22 | ZEND_FUNCTION(scrypt_pickparams); 23 | 24 | 25 | static const zend_function_entry ext_functions[] = { 26 | ZEND_FE(scrypt, arginfo_scrypt) 27 | ZEND_FE(scrypt_pickparams, arginfo_scrypt_pickparams) 28 | ZEND_FE_END 29 | }; 30 | 31 | static void register_php_scrypt_symbols(int module_number) 32 | { 33 | 34 | #if (PHP_VERSION_ID >= 80200) 35 | zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "scrypt", sizeof("scrypt") - 1), 0, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); 36 | 37 | zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "scrypt", sizeof("scrypt") - 1), 1, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); 38 | #endif 39 | } 40 | -------------------------------------------------------------------------------- /php_scrypt.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2012 Dominic Black 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef PHP_SCRYPT_HEADER 28 | #define PHP_SCRYPT_HEADER 1 29 | #define PHP_SCRYPT_VERSION "2.0.1" 30 | #define PHP_SCRYPT_EXTNAME "scrypt" 31 | 32 | extern zend_module_entry scrypt_module_entry; 33 | #define phpext_scrypt_ptr &scrypt_module_entry 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_ENABLE(scrypt, whether to enable scrypt support, 2 | [ --enable-scrypt Enable scrypt support]) 3 | 4 | if test $PHP_SCRYPT != "no"; then 5 | PHP_ADD_INCLUDE(crypto) 6 | PHP_ADD_BUILD_DIR(crypto) 7 | 8 | PHP_SUBST(SCRYPT_SHARED_LIBADD) 9 | PHP_CHECK_LIBRARY(rt, clock_gettime, [PHP_ADD_LIBRARY(rt,, SCRYPT_SHARED_LIBADD)]) 10 | 11 | AH_TEMPLATE(HAVE_SYSCTL_HW_USERMEM, [Define if the hw.usermem property exists in sysctl.]) 12 | if sysctl hw.usermem >/dev/null 2>/dev/null; then 13 | AC_DEFINE(HAVE_SYSCTL_HW_USERMEM, 1) 14 | fi 15 | 16 | AH_TEMPLATE(HAVE_CLOCK_GETTIME, [See if we have the clock_gettime function.]) 17 | AH_TEMPLATE(HAVE_STRUCT_SYSINFO, [Define if the sysinfo struct exists.]) 18 | AH_TEMPLATE(HAVE_STRUCT_SYSINFO_TOTALRAM, [Define if the sysinfo struct has a member for the total amount of RAM.]) 19 | 20 | AC_SEARCH_LIBS([clock_gettime], [rt], [AC_DEFINE(HAVE_CLOCK_GETTIME, 1)]) 21 | AC_CHECK_MEMBER([struct sysinfo.uptime], [AC_DEFINE(HAVE_STRUCT_SYSINFO)]) 22 | AC_CHECK_MEMBER([struct sysinfo.totalram], [AC_DEFINE(HAVE_STRUCT_SYSINFO_TOTALRAM)]) 23 | 24 | version=nosse 25 | if test "$(uname -m)" == 'x86_64' || test "$(uname -m)" == 'i386' || test "$(uname -m)" == 'i686'; then 26 | if test "$(uname)" == 'Darwin'; then 27 | sysctl -a | grep -iq "^machdep.cpu.features.\+sse2" 28 | else 29 | grep -iq "^flags.\+sse2" /proc/cpuinfo 30 | fi 31 | if test $? == 0; then 32 | version=sse 33 | CFLAGS="$CFLAGS -msse -msse2" 34 | fi 35 | fi 36 | AC_DEFINE(HAVE_SCRYPT, 1, [Whether you have scrypt]) 37 | PHP_NEW_EXTENSION(scrypt, php_scrypt.c php_scrypt_utils.c crypto/sha256.c crypto/crypto_scrypt-$version.c crypto/params.c, $ext_shared) 38 | 39 | ifdef([PHP_ADD_EXTENSION_DEP], 40 | [ 41 | PHP_ADD_EXTENSION_DEP(scrypt, hash) 42 | ]) 43 | fi 44 | -------------------------------------------------------------------------------- /crypto/crypto_scrypt.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | #ifndef _CRYPTO_SCRYPT_H_ 30 | #define _CRYPTO_SCRYPT_H_ 31 | 32 | #ifdef PHP_WIN32 33 | # include "win32/php_stdint.h" 34 | #else 35 | # include 36 | #endif 37 | 38 | /** 39 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 40 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 41 | * p, buflen) and write the result into buf. The parameters r, p, and buflen 42 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 43 | * must be a power of 2 greater than 1. 44 | * 45 | * Return 0 on success; or -1 on error. 46 | */ 47 | int crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, 48 | uint32_t, uint32_t, uint8_t *, size_t); 49 | 50 | #endif /* !_CRYPTO_SCRYPT_H_ */ 51 | -------------------------------------------------------------------------------- /php_scrypt_utils.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2012 Dominic Black 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef PHP_SCRYPT_UTILS_H 28 | #define PHP_SCRYPT_UTILS_H 1 29 | 30 | #ifdef HAVE_CONFIG_H 31 | #include "config.h" 32 | #endif 33 | 34 | #ifdef PHP_WIN32 35 | #include "zend_config.w32.h" 36 | #endif 37 | #include "php.h" 38 | #ifdef PHP_WIN32 39 | # include "win32/php_stdint.h" 40 | #else 41 | # include 42 | #endif 43 | 44 | /* 45 | * Casts a long into a uint64_t. 46 | * 47 | * Throws a php error if the value is out of bounds and will return 0. 48 | */ 49 | uint64_t clampAndCast64(uint32_t argNum, const char *argName, long value, long min); 50 | 51 | /* 52 | * Casts a long into a uint32_t. 53 | * 54 | * Throws an exception if the value is out of bounds and will return -1. 55 | */ 56 | uint32_t clampAndCast32(uint32_t argNum, const char *argName, long value, long min); 57 | 58 | /* 59 | * Checks if the givn number is a power of two 60 | */ 61 | uint64_t isPowerOfTwo(uint64_t N); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /crypto/sha256.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2005,2007,2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * $FreeBSD: src/lib/libmd/sha256.h,v 1.2 2006/01/17 15:35:56 phk Exp $ 27 | */ 28 | 29 | #ifndef _SHA256_H_ 30 | #define _SHA256_H_ 31 | 32 | #include 33 | 34 | #ifdef PHP_WIN32 35 | # include "win32/php_stdint.h" 36 | #else 37 | # include 38 | #endif 39 | 40 | typedef struct SHA256Context { 41 | uint32_t state[8]; 42 | uint32_t count[2]; 43 | unsigned char buf[64]; 44 | } SHA256_CTX; 45 | 46 | typedef struct HMAC_SHA256Context { 47 | SHA256_CTX ictx; 48 | SHA256_CTX octx; 49 | } HMAC_SHA256_CTX; 50 | 51 | void SHA256_Init_SCRYPT(SHA256_CTX *); 52 | void SHA256_Update_SCRYPT(SHA256_CTX *, const void *, size_t); 53 | void SHA256_Final_SCRYPT(unsigned char [32], SHA256_CTX *); 54 | void HMAC_SHA256_Init_SCRYPT(HMAC_SHA256_CTX *, const void *, size_t); 55 | void HMAC_SHA256_Update_SCRYPT(HMAC_SHA256_CTX *, const void *, size_t); 56 | void HMAC_SHA256_Final_SCRYPT(unsigned char [32], HMAC_SHA256_CTX *); 57 | 58 | /** 59 | * PBKDF2_SHA256_SCRYPT(passwd, passwdlen, salt, saltlen, c, buf, dkLen): 60 | * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and 61 | * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). 62 | */ 63 | void PBKDF2_SHA256_SCRYPT(const uint8_t *, size_t, const uint8_t *, size_t, 64 | uint64_t, uint8_t *, size_t); 65 | 66 | #endif /* !_SHA256_H_ */ 67 | -------------------------------------------------------------------------------- /crypto/params.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | 30 | #include 31 | 32 | /** 33 | * The parameters maxmem, maxmemfrac, and maxtime used by all of these 34 | * functions are defined as follows: 35 | * maxmem - maximum number of bytes of storage to use for V array (which is 36 | * by far the largest consumer of memory). If this value is set to 0, no 37 | * maximum will be enforced; any other value less than 1 MiB will be 38 | * treated as 1 MiB. 39 | * maxmemfrac - maximum fraction of available storage to use for the V array, 40 | * where "available storage" is defined as the minimum out of the 41 | * RLIMIT_AS, RLIMIT_DATA. and RLIMIT_RSS resource limits (if any are 42 | * set). If this value is set to 0 or more than 0.5 it will be treated 43 | * as 0.5; and this value will never cause a limit of less than 1 MiB to 44 | * be enforced. 45 | * maxtime - maximum amount of CPU time to spend computing the derived keys, 46 | * in seconds. This limit is only approximately enforced; the CPU 47 | * performance is estimated and parameter limits are chosen accordingly. 48 | * For the encryption functions, the parameters to the scrypt key derivation 49 | * function are chosen to make the key as strong as possible subject to the 50 | * specified limits; for the decryption functions, the parameters used are 51 | * compared to the computed limits and an error is returned if decrypting 52 | * the data would take too much memory or CPU time. 53 | */ 54 | 55 | int pickparams(size_t maxmem, double maxmemfrac, double maxtime, int * logN, uint32_t * r, uint32_t * p); 56 | int checkparams(size_t maxmem, double maxmemfrac, double maxtime, int logN, uint32_t r, uint32_t p); -------------------------------------------------------------------------------- /php_scrypt_utils.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2012 Dominic Black 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #include "php_scrypt_utils.h" 28 | #include "php_scrypt.h" 29 | #include "zend_exceptions.h" 30 | 31 | /* 32 | * Casts a long into a uint64_t. 33 | * 34 | * Throws a php error if the value is out of bounds and will return 0. 35 | */ 36 | uint64_t clampAndCast64(uint32_t argNum, const char *argName, long value, long min) 37 | { 38 | if (value <= min) 39 | { 40 | #if PHP_VERSION_ID >= 80000 41 | zend_argument_error(NULL, argNum, "must be greater than %ld", min); 42 | #else 43 | zend_throw_error(zend_ce_error, "scrypt(): Argument #%d ($%s) must be greater than %ld", argNum, argName, min); 44 | #endif 45 | return 0; 46 | } else if (value > UINT64_MAX) { 47 | #if PHP_VERSION_ID >= 80000 48 | zend_argument_error(NULL, argNum, "is too large"); 49 | #else 50 | zend_throw_error(zend_ce_error, "scrypt(): Argument #%d ($%s) is too large", argNum, argName); 51 | #endif 52 | return 0; 53 | } 54 | 55 | return (uint64_t)value; 56 | } 57 | 58 | /* 59 | * Casts a long into a uint32_t. 60 | * 61 | * Throws an exception if the value is out of bounds and will return -1. 62 | */ 63 | uint32_t clampAndCast32(uint32_t argNum, const char *argName, long value, long min) 64 | { 65 | if (value <= min) 66 | { 67 | #if PHP_VERSION_ID >= 80000 68 | zend_argument_error(NULL, argNum, "must be greater than %ld", min); 69 | #else 70 | zend_throw_error(zend_ce_error, "scrypt(): Argument #%d ($%s) must be greater than %ld", argNum, argName, min); 71 | #endif 72 | return -1; 73 | } else if (value > UINT32_MAX) { 74 | #if PHP_VERSION_ID >= 80000 75 | zend_argument_error(NULL, argNum, "is too large"); 76 | #else 77 | zend_throw_error(zend_ce_error, "scrypt(): Argument #%d ($%s) is too large", argNum, argName); 78 | #endif 79 | return -1; 80 | } 81 | 82 | return (uint32_t)value; 83 | } 84 | 85 | /* 86 | * Checks if the given number is a power of two 87 | */ 88 | uint64_t isPowerOfTwo(uint64_t N) 89 | { 90 | return N & (N - 1); 91 | } 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PHP scrypt module 2 | ================= 3 | 4 | [![Build Status](https://travis-ci.org/DomBlack/php-scrypt.svg?branch=master)](https://travis-ci.org/DomBlack/php-scrypt) 5 | 6 | This is a PHP library providing a wrapper to [Colin Percival's scrypt implementation](http://www.tarsnap.com/scrypt.html). Scrypt is a key derivation function designed to be far more secure against hardware brute-force attacks than alternative functions such as PBKDF2 or bcrypt. 7 | 8 | Details of the scrypt key derivation function are given in a paper by Colin Percival, Stronger Key Derivation via Sequential Memory-Hard Functions: [PDF](http://www.tarsnap.com/scrypt/scrypt-slides.pdf). 9 | 10 | An example class using this module can be found in; scrypt.php 11 | 12 | Join in! 13 | -------- 14 | 15 | We are happy to receive bug reports, fixes, documentation enhancements, and other improvements. 16 | 17 | Please report bugs via the [github issue tracker](http://github.com/DomBlack/php-scrypt/issues). 18 | 19 | Master [git repository](https://github.com/DomBlack/php-scrypt): 20 | 21 | git clone git://github.com/DomBlack/php-scrypt.git 22 | 23 | Authors 24 | ------- 25 | 26 | This library is written and maintained by Dominic Black, . 27 | 28 | ---- 29 | 30 | PECL Install 31 | ============ 32 | 33 | This extension is now avaible through PECL. 34 | 35 | ``` 36 | pecl install scrypt 37 | ``` 38 | 39 | Build From Source 40 | ================= 41 | 42 | Unix/OSX 43 | -------- 44 | 45 | 1. `phpize` 46 | 2. If on OSX; `export CFLAGS='-arch i386 -arch x86_64'` 47 | 3. `./configure --enable-scrypt` 48 | 4. `make` 49 | 5. `make install` 50 | 6. Add the extension to your php.ini 51 | 52 | ```` 53 | ; Enable scrypt extension module 54 | extension=scrypt.so 55 | ```` 56 | 57 | Windows 58 | ------- 59 | 60 | Using Visual Studio 2008 (or Visual C++ Express 2008) open up the attached project 61 | inside the VS2008 folder. This project assumes you have the PHP thread safe source at; 62 | `C:\phpsrcts\`, a PHP install at `C:\php\` and this source code extracted to 63 | `C:\php-scrypt\`. 64 | 65 | 1. Build the project. 66 | 2. Copy the resultant `scrypt.dll` to your ext directory in PHP. 67 | 3. Add the extension to your php.ini 68 | 69 | ```` 70 | ; Enable scrypt extension module 71 | extension=scrypt.dll 72 | ```` 73 | 74 | Legal Stuff 75 | =========== 76 | This works is licensed under the BSD 2-Clause license. 77 | 78 | Original Scrypt Implementation; 79 | Copyright (c) 2009 Colin Percival 80 | 81 | PHP Module; 82 | Copyright (c) 2012, Dominic Black 83 | 84 | All rights reserved. 85 | 86 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 87 | 88 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 89 | 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. 90 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. 91 | -------------------------------------------------------------------------------- /crypto/sysendian.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2007-2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | #ifndef _SYSENDIAN_H_ 30 | #define _SYSENDIAN_H_ 31 | 32 | /* If we don't have be64enc, the we have isn't usable. */ 33 | #if !HAVE_DECL_BE64ENC 34 | #undef HAVE_SYS_ENDIAN_H 35 | #endif 36 | 37 | #ifdef HAVE_SYS_ENDIAN_H 38 | 39 | #include 40 | 41 | #else 42 | 43 | #ifdef PHP_WIN32 44 | # include "win32/php_stdint.h" 45 | #else 46 | # include 47 | #endif 48 | 49 | static inline uint32_t 50 | be32dec(const void *pp) 51 | { 52 | const uint8_t *p = (uint8_t const *)pp; 53 | 54 | return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + 55 | ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); 56 | } 57 | 58 | static inline void 59 | be32enc(void *pp, uint32_t x) 60 | { 61 | uint8_t * p = (uint8_t *)pp; 62 | 63 | p[3] = x & 0xff; 64 | p[2] = (x >> 8) & 0xff; 65 | p[1] = (x >> 16) & 0xff; 66 | p[0] = (x >> 24) & 0xff; 67 | } 68 | 69 | static inline uint64_t 70 | be64dec(const void *pp) 71 | { 72 | const uint8_t *p = (uint8_t const *)pp; 73 | 74 | return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) + 75 | ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) + 76 | ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) + 77 | ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56)); 78 | } 79 | 80 | static inline void 81 | be64enc(void *pp, uint64_t x) 82 | { 83 | uint8_t * p = (uint8_t *)pp; 84 | 85 | p[7] = x & 0xff; 86 | p[6] = (x >> 8) & 0xff; 87 | p[5] = (x >> 16) & 0xff; 88 | p[4] = (x >> 24) & 0xff; 89 | p[3] = (x >> 32) & 0xff; 90 | p[2] = (x >> 40) & 0xff; 91 | p[1] = (x >> 48) & 0xff; 92 | p[0] = (x >> 56) & 0xff; 93 | } 94 | 95 | static inline uint32_t 96 | le32dec(const void *pp) 97 | { 98 | const uint8_t *p = (uint8_t const *)pp; 99 | 100 | return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + 101 | ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); 102 | } 103 | 104 | static inline void 105 | le32enc(void *pp, uint32_t x) 106 | { 107 | uint8_t * p = (uint8_t *)pp; 108 | 109 | p[0] = x & 0xff; 110 | p[1] = (x >> 8) & 0xff; 111 | p[2] = (x >> 16) & 0xff; 112 | p[3] = (x >> 24) & 0xff; 113 | } 114 | 115 | static inline uint64_t 116 | le64dec(const void *pp) 117 | { 118 | const uint8_t *p = (uint8_t const *)pp; 119 | 120 | return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) + 121 | ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) + 122 | ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) + 123 | ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56)); 124 | } 125 | 126 | static inline void 127 | le64enc(void *pp, uint64_t x) 128 | { 129 | uint8_t * p = (uint8_t *)pp; 130 | 131 | p[0] = x & 0xff; 132 | p[1] = (x >> 8) & 0xff; 133 | p[2] = (x >> 16) & 0xff; 134 | p[3] = (x >> 24) & 0xff; 135 | p[4] = (x >> 32) & 0xff; 136 | p[5] = (x >> 40) & 0xff; 137 | p[6] = (x >> 48) & 0xff; 138 | p[7] = (x >> 56) & 0xff; 139 | } 140 | #endif /* !HAVE_SYS_ENDIAN_H */ 141 | 142 | #endif /* !_SYSENDIAN_H_ */ 143 | -------------------------------------------------------------------------------- /VS2008/VS2008.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 26 | 29 | 32 | 35 | 38 | 41 | 55 | 58 | 61 | 64 | 74 | 77 | 80 | 83 | 86 | 89 | 92 | 95 | 96 | 104 | 107 | 110 | 113 | 116 | 119 | 130 | 133 | 136 | 139 | 148 | 151 | 154 | 157 | 160 | 163 | 166 | 169 | 170 | 171 | 172 | 173 | 174 | 177 | 180 | 181 | 184 | 185 | 188 | 189 | 192 | 193 | 196 | 197 | 198 | 201 | 204 | 205 | 206 | 209 | 210 | 213 | 214 | 217 | 218 | 221 | 222 | 223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /scrypt.php: -------------------------------------------------------------------------------- 1 | 14 | * @license http://www.opensource.org/licenses/BSD-2-Clause BSD 2-Clause License 15 | * @link http://github.com/DomBlack/php-scrypt 16 | */ 17 | 18 | /** 19 | * This class abstracts away from scrypt module, allowing for easy use. 20 | * 21 | * You can create a new hash for a password by calling Password::hash($password) 22 | * 23 | * You can check a password by calling Password::check($password, $hash) 24 | * 25 | * @category Security 26 | * @package Scrypt 27 | * @author Dominic Black 28 | * @license http://www.opensource.org/licenses/BSD-2-Clause BSD 2-Clause License 29 | * @link http://github.com/DomBlack/php-scrypt 30 | */ 31 | abstract class Password 32 | { 33 | 34 | /** 35 | * 36 | * @var int The key length 37 | */ 38 | private static $_keyLength = 32; 39 | 40 | /** 41 | * Get the byte-length of the given string 42 | * 43 | * @param string $str Input string 44 | * 45 | * @return int 46 | */ 47 | protected static function strlen( $str ) { 48 | static $isShadowed = null; 49 | 50 | if ($isShadowed === null) { 51 | $isShadowed = extension_loaded('mbstring') && 52 | ini_get('mbstring.func_overload') & 2; 53 | } 54 | 55 | if ($isShadowed) { 56 | return mb_strlen($str, '8bit'); 57 | } else { 58 | return strlen($str); 59 | } 60 | } 61 | 62 | /** 63 | * Generates a random salt 64 | * 65 | * @param int $length The length of the salt 66 | * 67 | * @return string The salt 68 | */ 69 | public static function generateSalt($length = 8) 70 | { 71 | $buffer = ''; 72 | $buffer_valid = false; 73 | if (function_exists('random_bytes')) { 74 | try { 75 | $buffer = random_bytes($length); 76 | $buffer_valid = true; 77 | } catch (Exception $ignored) { } 78 | } 79 | 80 | if (!$buffer_valid && function_exists('mcrypt_create_iv') && !defined('PHALANGER')) { 81 | $buffer = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); 82 | if ($buffer) { 83 | $buffer_valid = true; 84 | } 85 | } 86 | 87 | if (!$buffer_valid && is_readable('/dev/urandom')) { 88 | $f = fopen('/dev/urandom', 'r'); 89 | $read = static::strlen($buffer); 90 | while ($read < $length) { 91 | $buffer .= fread($f, $length - $read); 92 | $read = static::strlen($buffer); 93 | } 94 | fclose($f); 95 | if ($read >= $length) { 96 | $buffer_valid = true; 97 | } 98 | } 99 | 100 | if (!$buffer_valid) { 101 | throw new Exception("No suitable random number generator available"); 102 | } 103 | 104 | $salt = str_replace(array('+', '$'), array('.', ''), base64_encode($buffer)); 105 | 106 | return $salt; 107 | } 108 | 109 | /** 110 | * Create a password hash 111 | * 112 | * @param string $password The clear text password 113 | * @param string $salt The salt to use, or null to generate a random one 114 | * @param int $N The CPU difficultly (must be a power of 2, > 1) 115 | * @param int $r The memory difficultly 116 | * @param int $p The parallel difficultly 117 | * 118 | * @return string The hashed password 119 | */ 120 | public static function hash($password, $salt = false, $N = 16384, $r = 8, $p = 1) 121 | { 122 | if ($N == 0 || ($N & ($N - 1)) != 0) { 123 | throw new \InvalidArgumentException("N must be > 0 and a power of 2"); 124 | } 125 | 126 | if ($N > PHP_INT_MAX / 128 / $r) { 127 | throw new \InvalidArgumentException("Parameter N is too large"); 128 | } 129 | 130 | if ($r > PHP_INT_MAX / 128 / $p) { 131 | throw new \InvalidArgumentException("Parameter r is too large"); 132 | } 133 | 134 | if ($salt === false) { 135 | $salt = self::generateSalt(); 136 | } else { 137 | // Remove dollar signs from the salt, as we use that as a separator. 138 | $salt = str_replace(array('+', '$'), array('.', ''), base64_encode($salt)); 139 | } 140 | 141 | $hash = scrypt($password, $salt, $N, $r, $p, self::$_keyLength); 142 | 143 | return $N . '$' . $r . '$' . $p . '$' . $salt . '$' . $hash; 144 | } 145 | 146 | /** 147 | * Check a clear text password against a hash 148 | * 149 | * @param string $password The clear text password 150 | * @param string $hash The hashed password 151 | * 152 | * @return boolean If the clear text matches 153 | */ 154 | public static function check($password, $hash) 155 | { 156 | // Is there actually a hash? 157 | if (!$hash) { 158 | return false; 159 | } 160 | 161 | list ($N, $r, $p, $salt, $hash) = explode('$', $hash); 162 | 163 | // No empty fields? 164 | if (empty($N) or empty($r) or empty($p) or empty($salt) or empty($hash)) { 165 | return false; 166 | } 167 | 168 | // Are numeric values numeric? 169 | if (!is_numeric($N) or !is_numeric($r) or !is_numeric($p)) { 170 | return false; 171 | } 172 | 173 | $calculated = scrypt($password, $salt, $N, $r, $p, self::$_keyLength); 174 | 175 | // Use compareStrings to avoid timeing attacks 176 | return self::compareStrings($hash, $calculated); 177 | } 178 | 179 | /** 180 | * Zend Framework (http://framework.zend.com/) 181 | * 182 | * @link http://github.com/zendframework/zf2 for the canonical source repository 183 | * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) 184 | * @license http://framework.zend.com/license/new-bsd New BSD License 185 | * 186 | * Compare two strings to avoid timing attacks 187 | * 188 | * C function memcmp() internally used by PHP, exits as soon as a difference 189 | * is found in the two buffers. That makes possible of leaking 190 | * timing information useful to an attacker attempting to iteratively guess 191 | * the unknown string (e.g. password). 192 | * 193 | * @param string $expected 194 | * @param string $actual 195 | * 196 | * @return boolean If the two strings match. 197 | */ 198 | public static function compareStrings($expected, $actual) 199 | { 200 | $expected = (string) $expected; 201 | $actual = (string) $actual; 202 | $lenExpected = static::strlen($expected); 203 | $lenActual = static::strlen($actual); 204 | $len = min($lenExpected, $lenActual); 205 | 206 | $result = 0; 207 | for ($i = 0; $i < $len; $i ++) { 208 | $result |= ord($expected[$i]) ^ ord($actual[$i]); 209 | } 210 | $result |= $lenExpected ^ $lenActual; 211 | 212 | return ($result === 0); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | scrypt 13 | pecl.php.net 14 | Scrypt hashing function 15 | A PHP wrapper to Colin Percival's scrypt implementation. 16 | 17 | Dominic Black 18 | dom 19 | thephenix@gmail.com 20 | yes 21 | 22 | 23 | Máté Kocsis 24 | kocsismate 25 | kocsismate@woohoolabs.com 26 | yes 27 | 28 | 2023-05-07 29 | 30 | 2.0.1 31 | 2.0.0 32 | 33 | 34 | stable 35 | stable 36 | 37 | BSD 2-Clause 38 | 39 | Check CPU architecture before attempting to enable SSE (#76) 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 7.0 80 | 81 | 82 | 1.4.0 83 | 84 | 85 | 86 | scrypt 87 | 88 | 89 | 90 | 91 | 92 | 93 | 2.0.1 94 | 2.0.0 95 | 96 | 97 | stable 98 | stable 99 | 100 | 2023-05-07 101 | BSD 2-Clause 102 | 103 | Check CPU architecture before attempting to enable SSE (#76) 104 | 105 | 106 | 107 | 108 | 2.0.0 109 | 2.0.0 110 | 111 | 112 | stable 113 | stable 114 | 115 | 2022-09-06 116 | BSD 2-Clause 117 | 118 | Increased PHP version requirement to 7.0 (#67, #69) 119 | Improved parameter reflection and validation (#63, #64) 120 | Fixed memory leak in scrypt() (#68) 121 | Fixed compilation warning (#69) 122 | Added support for sensitive parameters on PHP 8.2+ (#70) 123 | 124 | 125 | 126 | 127 | 1.4.3 128 | 1.4.3 129 | 130 | 131 | stable 132 | stable 133 | 134 | 2022-08-17 135 | BSD 2-Clause 136 | 137 | Added PHP 8 support (#56, #59) 138 | Fixed compilation warning (#65) 139 | 140 | 141 | 142 | 143 | 1.4.2 144 | 1.4.2 145 | 146 | 147 | stable 148 | stable 149 | 150 | 2016-05-18 151 | BSD 2-Clause 152 | 153 | Fixed memory leak in PHP 7 (#48) 154 | Weak CSPRNG on salts in the example file (#44) 155 | 156 | 157 | 158 | 159 | 1.4.1 160 | 1.4.1 161 | 162 | 163 | stable 164 | stable 165 | 166 | 2016-05-18 167 | BSD 2-Clause 168 | 169 | Fixed issue on RHEL 6 in x86_64 with PHP 7 (#46) 170 | 171 | 172 | 173 | 174 | 1.4 175 | 1.4 176 | 177 | 178 | stable 179 | stable 180 | 181 | 2016-05-18 182 | BSD 2-Clause 183 | 184 | Added PHP 7 support (#39, #40, #45) 185 | Removed support for PHP 5.2 as Travis no longer supports testing it. 186 | 187 | 188 | 189 | 190 | 1.3 191 | 1.3 192 | 193 | 194 | stable 195 | stable 196 | 197 | 2015-08-09 198 | BSD 2-Clause 199 | 200 | Fixed install pecl install on machines which do not support SSE extensions (#37). 201 | Added a segfault catch for when an invalid N was passed in (#31). 202 | 203 | 204 | 205 | 206 | 1.2 207 | 1.2 208 | 209 | 210 | stable 211 | stable 212 | 213 | 2013-07-15 214 | BSD 2-Clause 215 | 216 | Initial release to PECL, plus various changes to the example PHP file 217 | 218 | 219 | 220 | 221 | 1.1 222 | 1.1 223 | 224 | 225 | stable 226 | stable 227 | 228 | 2012-07-17 229 | BSD 2-Clause 230 | 231 | Addition of scrypt_pickparams function 232 | 233 | 234 | 235 | 236 | 1.0 237 | 1.0 238 | 239 | 240 | stable 241 | stable 242 | 243 | 2012-07-12 244 | BSD 2-Clause 245 | 246 | Initial release 247 | 248 | 249 | 250 | 251 | -------------------------------------------------------------------------------- /php_scrypt.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2012 Dominic Black 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #ifdef HAVE_CONFIG_H 28 | #include "config.h" 29 | #endif 30 | 31 | #include "php.h" 32 | #include "php_version.h" 33 | #include "zend_exceptions.h" 34 | 35 | #ifdef PHP_WIN32 36 | #include "zend_config.w32.h" 37 | #endif 38 | 39 | #include "ext/hash/php_hash.h" 40 | #include "php_scrypt_utils.h" 41 | #include "php_scrypt.h" 42 | #include "crypto/crypto_scrypt.h" 43 | #include "crypto/params.h" 44 | #if PHP_MAJOR_VERSION >= 8 45 | #include "zend_attributes.h" 46 | #include "php_scrypt_arginfo.h" 47 | #else 48 | #include "php_scrypt_legacy_arginfo.h" 49 | #endif 50 | #include "math.h" 51 | 52 | #if PHP_VERSION_ID < 80000 53 | #define RETURN_THROWS() do { ZEND_ASSERT(EG(exception)); (void) return_value; return; } while (0) 54 | #endif 55 | 56 | typedef size_t strsize_t; 57 | 58 | static const zend_module_dep scrypt_deps[] = { 59 | ZEND_MOD_REQUIRED("hash") 60 | ZEND_MOD_END 61 | }; 62 | 63 | static PHP_MINIT_FUNCTION(scrypt) 64 | { 65 | #if PHP_VERSION_ID >= 80200 66 | register_php_scrypt_symbols(module_number); 67 | #endif 68 | 69 | return SUCCESS; 70 | } 71 | 72 | zend_module_entry scrypt_module_entry = { 73 | STANDARD_MODULE_HEADER_EX, 74 | NULL, 75 | scrypt_deps, 76 | PHP_SCRYPT_EXTNAME, 77 | ext_functions, 78 | PHP_MINIT(scrypt), 79 | NULL, 80 | NULL, 81 | NULL, 82 | NULL, 83 | PHP_SCRYPT_VERSION, 84 | STANDARD_MODULE_PROPERTIES 85 | }; 86 | 87 | #ifdef COMPILE_DL_SCRYPT 88 | ZEND_GET_MODULE(scrypt) 89 | #endif 90 | 91 | /* 92 | * Returns the scrypt hash for the given password. 93 | * 94 | * Where; 95 | * string $password The user's password 96 | * string $salt The user's salt 97 | * long $N The CPU difficultly (must be a power of 2, greater than 1) 98 | * int $r The memory difficulty 99 | * int $p The parallel difficulty 100 | * int $keyLength The length of hash 101 | * 102 | * The parameters $r, $p must satisfy; $r * $p < 2^30 103 | * The parameter $keyLength must satisfy; $keyLength <= (2^32 - 1) * 32. 104 | * The parameter $N must be a power of 2 greater than 1. 105 | * 106 | * This function will return a hex encoded version of the binary hash. 107 | */ 108 | PHP_FUNCTION(scrypt) 109 | { 110 | /* Variables for PHP's parameters */ 111 | unsigned char *password; 112 | strsize_t password_len; 113 | 114 | unsigned char *salt; 115 | strsize_t salt_len; 116 | 117 | long phpN; 118 | long phpR; 119 | long phpP; 120 | long keyLength; 121 | 122 | zend_bool raw_output; 123 | 124 | /* Casted variables for scrypt */ 125 | uint64_t cryptN; 126 | uint32_t cryptR; 127 | uint32_t cryptP; 128 | 129 | /* Output variables */ 130 | char *hex; 131 | unsigned char *buf; 132 | 133 | int result; 134 | 135 | /* Get the parameters for this call */ 136 | raw_output = 0; 137 | if (zend_parse_parameters_throw( 138 | ZEND_NUM_ARGS(), "ssllll|b", 139 | &password, &password_len, &salt, &salt_len, 140 | &phpN, &phpR, &phpP, &keyLength, &raw_output 141 | ) == FAILURE) 142 | { 143 | RETURN_THROWS(); 144 | } 145 | 146 | /* Checks on the parameters */ 147 | 148 | cryptN = clampAndCast64(3, "N", phpN, 1); 149 | if (EG(exception)) { 150 | RETURN_THROWS(); 151 | } 152 | cryptR = clampAndCast32(4, "r", phpR, 0); 153 | if (EG(exception)) { 154 | RETURN_THROWS(); 155 | } 156 | cryptP = clampAndCast32(5, "p", phpP, 0); 157 | if (EG(exception)) { 158 | RETURN_THROWS(); 159 | } 160 | 161 | if (isPowerOfTwo(cryptN) != 0) { 162 | #if PHP_VERSION_ID >= 80000 163 | zend_argument_error(NULL, 3, "must be a power of 2"); 164 | #else 165 | zend_throw_error(zend_ce_error, "scrypt(): Argument #3 ($N) must be a power of 2"); 166 | #endif 167 | RETURN_THROWS(); 168 | } 169 | 170 | if (keyLength < 16) { 171 | #if PHP_VERSION_ID >= 80000 172 | zend_argument_error(NULL, 6, "must be greater than or equal to 16"); 173 | #else 174 | zend_throw_error(zend_ce_error, "scrypt(): Argument #6 ($key_length) must be greater than or equal to 16"); 175 | #endif 176 | RETURN_THROWS(); 177 | } 178 | 179 | if (keyLength > (powl(2, 32) - 1) * 32) { 180 | #if PHP_VERSION_ID >= 80000 181 | zend_argument_error(NULL, 6, "must be less than or equal to (2^32 - 1) * 32"); 182 | #else 183 | zend_throw_error(zend_ce_error, "scrypt(): Argument #6 ($key_length) must be less than or equal to (2^32 - 1) * 32"); 184 | #endif 185 | RETURN_THROWS(); 186 | } 187 | 188 | /* Allocate the memory for the output of the key */ 189 | buf = (unsigned char*)safe_emalloc(1, keyLength, 1); 190 | 191 | /* Call the scrypt function */ 192 | result = crypto_scrypt( 193 | password, password_len, salt, salt_len, /* Input */ 194 | cryptN, cryptR, cryptP, /* Settings */ 195 | buf, keyLength /* Output */ 196 | ); 197 | 198 | /* Check the crypto returned the hash we wanted. */ 199 | if (result != 0) { 200 | efree(buf); 201 | RETURN_FALSE; 202 | } 203 | 204 | if (!raw_output) { 205 | /* Encode the output in hex */ 206 | hex = (char*) safe_emalloc(2, keyLength, 1); 207 | php_hash_bin2hex(hex, buf, keyLength); 208 | efree(buf); 209 | hex[keyLength*2] = '\0'; 210 | RETVAL_STRINGL(hex, keyLength * 2); 211 | efree(hex); 212 | } else { 213 | buf[keyLength] = '\0'; 214 | RETVAL_STRINGL((char *)buf, keyLength); 215 | efree(buf); 216 | } 217 | } 218 | 219 | /* 220 | * Returns N, r and p picked automatically for use with the scrypt function. 221 | * 222 | * Where; 223 | * long $maxMem Maximum amount of memory to use 224 | * double $memFrac Maximum fraction of available memory to use 225 | * double $maxTime Maximum CPU time to use 226 | */ 227 | PHP_FUNCTION(scrypt_pickparams) 228 | { 229 | long maxmem; 230 | double memfrac, maxtime; 231 | 232 | int cryptN; 233 | uint32_t cryptR; 234 | uint32_t cryptP; 235 | 236 | long phpN, phpP, phpR; 237 | 238 | int rc; 239 | 240 | /* Get the parameters for this call */ 241 | if (zend_parse_parameters_throw( 242 | ZEND_NUM_ARGS(), "ldd", 243 | &maxmem, &memfrac, &maxtime 244 | ) == FAILURE) 245 | { 246 | RETURN_THROWS(); 247 | } 248 | 249 | if (maxmem < 0) { 250 | #if PHP_VERSION_ID >= 80000 251 | zend_argument_error(NULL, 1, "must be greater than or equal to 0"); 252 | #else 253 | zend_throw_error(zend_ce_error, "scrypt_pickparams(): Argument #1 ($max_memory) must be greater than or equal to 0"); 254 | #endif 255 | RETURN_THROWS(); 256 | } 257 | 258 | if (memfrac < 0) { 259 | #if PHP_VERSION_ID >= 80000 260 | zend_argument_error(NULL, 2, "must be greater than or equal to 0"); 261 | #else 262 | zend_throw_error(zend_ce_error, "scrypt_pickparams(): Argument #2 ($memory_fraction) must be greater than or equal to 0"); 263 | #endif 264 | RETURN_THROWS(); 265 | } 266 | 267 | if (maxtime < 0) { 268 | #if PHP_VERSION_ID >= 80000 269 | zend_argument_error(NULL, 3, "must be greater than or equal to 0"); 270 | #else 271 | zend_throw_error(zend_ce_error, "scrypt_pickparams(): Argument #3 ($max_time) must be greater than or equal to 0"); 272 | #endif 273 | RETURN_THROWS(); 274 | } 275 | 276 | rc = pickparams((size_t) maxmem, memfrac, maxtime, &cryptN, &cryptR, &cryptP); 277 | 278 | if (rc != 0) { 279 | php_error_docref(NULL, E_WARNING, "Could not determine scrypt parameters."); 280 | RETURN_FALSE; 281 | } 282 | 283 | phpN = (long) cryptN; 284 | phpR = (long) cryptR; 285 | phpP = (long) cryptP; 286 | 287 | array_init(return_value); 288 | add_assoc_long(return_value, "n", phpN); 289 | add_assoc_long(return_value, "r", phpR); 290 | add_assoc_long(return_value, "p", phpP); 291 | } 292 | -------------------------------------------------------------------------------- /VS2008/stdint.h: -------------------------------------------------------------------------------- 1 | // ISO C9x compliant stdint.h for Microsoft Visual Studio 2 | // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 3 | // 4 | // Copyright (c) 2006-2008 Alexander Chemeris 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // 1. Redistributions of source code must retain the above copyright notice, 10 | // this list of conditions and the following disclaimer. 11 | // 12 | // 2. Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // 16 | // 3. The name of the author may be used to endorse or promote products 17 | // derived from this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 22 | // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 25 | // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 27 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | /////////////////////////////////////////////////////////////////////////////// 31 | 32 | #ifndef _MSC_VER // [ 33 | #error "Use this header only with Microsoft Visual C++ compilers!" 34 | #endif // _MSC_VER ] 35 | 36 | #ifndef _MSC_STDINT_H_ // [ 37 | #define _MSC_STDINT_H_ 38 | 39 | #if _MSC_VER > 1000 40 | #pragma once 41 | #endif 42 | 43 | #include 44 | 45 | // For Visual Studio 6 in C++ mode and for many Visual Studio versions when 46 | // compiling for ARM we should wrap include with 'extern "C++" {}' 47 | // or compiler give many errors like this: 48 | // error C2733: second C linkage of overloaded function 'wmemchr' not allowed 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | # include 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | // Define _W64 macros to mark types changing their size, like intptr_t. 58 | #ifndef _W64 59 | # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 60 | # define _W64 __w64 61 | # else 62 | # define _W64 63 | # endif 64 | #endif 65 | 66 | 67 | // 7.18.1 Integer types 68 | 69 | // 7.18.1.1 Exact-width integer types 70 | 71 | // Visual Studio 6 and Embedded Visual C++ 4 doesn't 72 | // realize that, e.g. char has the same size as __int8 73 | // so we give up on __intX for them. 74 | #if (_MSC_VER < 1300) 75 | typedef signed char int8_t; 76 | typedef signed short int16_t; 77 | typedef signed int int32_t; 78 | typedef unsigned char uint8_t; 79 | typedef unsigned short uint16_t; 80 | typedef unsigned int uint32_t; 81 | #else 82 | typedef signed __int8 int8_t; 83 | typedef signed __int16 int16_t; 84 | typedef signed __int32 int32_t; 85 | typedef unsigned __int8 uint8_t; 86 | typedef unsigned __int16 uint16_t; 87 | typedef unsigned __int32 uint32_t; 88 | #endif 89 | typedef signed __int64 int64_t; 90 | typedef unsigned __int64 uint64_t; 91 | 92 | 93 | // 7.18.1.2 Minimum-width integer types 94 | typedef int8_t int_least8_t; 95 | typedef int16_t int_least16_t; 96 | typedef int32_t int_least32_t; 97 | typedef int64_t int_least64_t; 98 | typedef uint8_t uint_least8_t; 99 | typedef uint16_t uint_least16_t; 100 | typedef uint32_t uint_least32_t; 101 | typedef uint64_t uint_least64_t; 102 | 103 | // 7.18.1.3 Fastest minimum-width integer types 104 | typedef int8_t int_fast8_t; 105 | typedef int16_t int_fast16_t; 106 | typedef int32_t int_fast32_t; 107 | typedef int64_t int_fast64_t; 108 | typedef uint8_t uint_fast8_t; 109 | typedef uint16_t uint_fast16_t; 110 | typedef uint32_t uint_fast32_t; 111 | typedef uint64_t uint_fast64_t; 112 | 113 | // 7.18.1.4 Integer types capable of holding object pointers 114 | #ifdef _WIN64 // [ 115 | typedef signed __int64 intptr_t; 116 | typedef unsigned __int64 uintptr_t; 117 | #else // _WIN64 ][ 118 | typedef _W64 signed int intptr_t; 119 | typedef _W64 unsigned int uintptr_t; 120 | #endif // _WIN64 ] 121 | 122 | // 7.18.1.5 Greatest-width integer types 123 | typedef int64_t intmax_t; 124 | typedef uint64_t uintmax_t; 125 | 126 | 127 | // 7.18.2 Limits of specified-width integer types 128 | 129 | #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 130 | 131 | // 7.18.2.1 Limits of exact-width integer types 132 | #define INT8_MIN ((int8_t)_I8_MIN) 133 | #define INT8_MAX _I8_MAX 134 | #define INT16_MIN ((int16_t)_I16_MIN) 135 | #define INT16_MAX _I16_MAX 136 | #define INT32_MIN ((int32_t)_I32_MIN) 137 | #define INT32_MAX _I32_MAX 138 | #define INT64_MIN ((int64_t)_I64_MIN) 139 | #define INT64_MAX _I64_MAX 140 | #define UINT8_MAX _UI8_MAX 141 | #define UINT16_MAX _UI16_MAX 142 | #define UINT32_MAX _UI32_MAX 143 | #define UINT64_MAX _UI64_MAX 144 | 145 | // 7.18.2.2 Limits of minimum-width integer types 146 | #define INT_LEAST8_MIN INT8_MIN 147 | #define INT_LEAST8_MAX INT8_MAX 148 | #define INT_LEAST16_MIN INT16_MIN 149 | #define INT_LEAST16_MAX INT16_MAX 150 | #define INT_LEAST32_MIN INT32_MIN 151 | #define INT_LEAST32_MAX INT32_MAX 152 | #define INT_LEAST64_MIN INT64_MIN 153 | #define INT_LEAST64_MAX INT64_MAX 154 | #define UINT_LEAST8_MAX UINT8_MAX 155 | #define UINT_LEAST16_MAX UINT16_MAX 156 | #define UINT_LEAST32_MAX UINT32_MAX 157 | #define UINT_LEAST64_MAX UINT64_MAX 158 | 159 | // 7.18.2.3 Limits of fastest minimum-width integer types 160 | #define INT_FAST8_MIN INT8_MIN 161 | #define INT_FAST8_MAX INT8_MAX 162 | #define INT_FAST16_MIN INT16_MIN 163 | #define INT_FAST16_MAX INT16_MAX 164 | #define INT_FAST32_MIN INT32_MIN 165 | #define INT_FAST32_MAX INT32_MAX 166 | #define INT_FAST64_MIN INT64_MIN 167 | #define INT_FAST64_MAX INT64_MAX 168 | #define UINT_FAST8_MAX UINT8_MAX 169 | #define UINT_FAST16_MAX UINT16_MAX 170 | #define UINT_FAST32_MAX UINT32_MAX 171 | #define UINT_FAST64_MAX UINT64_MAX 172 | 173 | // 7.18.2.4 Limits of integer types capable of holding object pointers 174 | #ifdef _WIN64 // [ 175 | # define INTPTR_MIN INT64_MIN 176 | # define INTPTR_MAX INT64_MAX 177 | # define UINTPTR_MAX UINT64_MAX 178 | #else // _WIN64 ][ 179 | # define INTPTR_MIN INT32_MIN 180 | # define INTPTR_MAX INT32_MAX 181 | # define UINTPTR_MAX UINT32_MAX 182 | #endif // _WIN64 ] 183 | 184 | // 7.18.2.5 Limits of greatest-width integer types 185 | #define INTMAX_MIN INT64_MIN 186 | #define INTMAX_MAX INT64_MAX 187 | #define UINTMAX_MAX UINT64_MAX 188 | 189 | // 7.18.3 Limits of other integer types 190 | 191 | #ifdef _WIN64 // [ 192 | # define PTRDIFF_MIN _I64_MIN 193 | # define PTRDIFF_MAX _I64_MAX 194 | #else // _WIN64 ][ 195 | # define PTRDIFF_MIN _I32_MIN 196 | # define PTRDIFF_MAX _I32_MAX 197 | #endif // _WIN64 ] 198 | 199 | #define SIG_ATOMIC_MIN INT_MIN 200 | #define SIG_ATOMIC_MAX INT_MAX 201 | 202 | #ifndef SIZE_MAX // [ 203 | # ifdef _WIN64 // [ 204 | # define SIZE_MAX _UI64_MAX 205 | # else // _WIN64 ][ 206 | # define SIZE_MAX _UI32_MAX 207 | # endif // _WIN64 ] 208 | #endif // SIZE_MAX ] 209 | 210 | // WCHAR_MIN and WCHAR_MAX are also defined in 211 | #ifndef WCHAR_MIN // [ 212 | # define WCHAR_MIN 0 213 | #endif // WCHAR_MIN ] 214 | #ifndef WCHAR_MAX // [ 215 | # define WCHAR_MAX _UI16_MAX 216 | #endif // WCHAR_MAX ] 217 | 218 | #define WINT_MIN 0 219 | #define WINT_MAX _UI16_MAX 220 | 221 | #endif // __STDC_LIMIT_MACROS ] 222 | 223 | 224 | // 7.18.4 Limits of other integer types 225 | 226 | #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 227 | 228 | // 7.18.4.1 Macros for minimum-width integer constants 229 | 230 | #define INT8_C(val) val##i8 231 | #define INT16_C(val) val##i16 232 | #define INT32_C(val) val##i32 233 | #define INT64_C(val) val##i64 234 | 235 | #define UINT8_C(val) val##ui8 236 | #define UINT16_C(val) val##ui16 237 | #define UINT32_C(val) val##ui32 238 | #define UINT64_C(val) val##ui64 239 | 240 | // 7.18.4.2 Macros for greatest-width integer constants 241 | #define INTMAX_C INT64_C 242 | #define UINTMAX_C UINT64_C 243 | 244 | #endif // __STDC_CONSTANT_MACROS ] 245 | 246 | 247 | #endif // _MSC_STDINT_H_ ] -------------------------------------------------------------------------------- /crypto/crypto_scrypt-nosse.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | 30 | #include "php.h" 31 | #ifdef PHP_WIN32 32 | #include "zend_config.w32.h" 33 | #endif 34 | 35 | #include 36 | #ifdef PHP_WIN32 37 | # include "win32/php_stdint.h" 38 | #else 39 | # include 40 | #endif 41 | #include 42 | #include 43 | 44 | #include "sha256.h" 45 | #include "sysendian.h" 46 | 47 | #include "crypto_scrypt.h" 48 | #include "php_scrypt.h" 49 | 50 | static void blkcpy(uint8_t *, uint8_t *, size_t); 51 | static void blkxor(uint8_t *, uint8_t *, size_t); 52 | static void salsa20_8(uint8_t[64]); 53 | static void blockmix_salsa8(uint8_t *, uint8_t *, size_t); 54 | static uint64_t integerify(uint8_t *, size_t); 55 | static void smix(uint8_t *, size_t, uint64_t, uint8_t *, uint8_t *); 56 | 57 | static void 58 | blkcpy(uint8_t * dest, uint8_t * src, size_t len) 59 | { 60 | size_t i; 61 | 62 | for (i = 0; i < len; i++) 63 | dest[i] = src[i]; 64 | } 65 | 66 | static void 67 | blkxor(uint8_t * dest, uint8_t * src, size_t len) 68 | { 69 | size_t i; 70 | 71 | for (i = 0; i < len; i++) 72 | dest[i] ^= src[i]; 73 | } 74 | 75 | /** 76 | * salsa20_8(B): 77 | * Apply the salsa20/8 core to the provided block. 78 | */ 79 | static void 80 | salsa20_8(uint8_t B[64]) 81 | { 82 | uint32_t B32[16]; 83 | uint32_t x[16]; 84 | size_t i; 85 | 86 | /* Convert little-endian values in. */ 87 | for (i = 0; i < 16; i++) 88 | B32[i] = le32dec(&B[i * 4]); 89 | 90 | /* Compute x = doubleround^4(B32). */ 91 | for (i = 0; i < 16; i++) 92 | x[i] = B32[i]; 93 | for (i = 0; i < 8; i += 2) { 94 | #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) 95 | /* Operate on columns. */ 96 | x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); 97 | x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); 98 | 99 | x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); 100 | x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); 101 | 102 | x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); 103 | x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); 104 | 105 | x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); 106 | x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); 107 | 108 | /* Operate on rows. */ 109 | x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); 110 | x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); 111 | 112 | x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); 113 | x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); 114 | 115 | x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); 116 | x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); 117 | 118 | x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); 119 | x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); 120 | #undef R 121 | } 122 | 123 | /* Compute B32 = B32 + x. */ 124 | for (i = 0; i < 16; i++) 125 | B32[i] += x[i]; 126 | 127 | /* Convert little-endian values out. */ 128 | for (i = 0; i < 16; i++) 129 | le32enc(&B[4 * i], B32[i]); 130 | } 131 | 132 | /** 133 | * blockmix_salsa8(B, Y, r): 134 | * Compute B = BlockMix_{salsa20/8, r}(B). The input B must be 128r bytes in 135 | * length; the temporary space Y must also be the same size. 136 | */ 137 | static void 138 | blockmix_salsa8(uint8_t * B, uint8_t * Y, size_t r) 139 | { 140 | uint8_t X[64]; 141 | size_t i; 142 | 143 | /* 1: X <-- B_{2r - 1} */ 144 | blkcpy(X, &B[(2 * r - 1) * 64], 64); 145 | 146 | /* 2: for i = 0 to 2r - 1 do */ 147 | for (i = 0; i < 2 * r; i++) { 148 | /* 3: X <-- H(X \xor B_i) */ 149 | blkxor(X, &B[i * 64], 64); 150 | salsa20_8(X); 151 | 152 | /* 4: Y_i <-- X */ 153 | blkcpy(&Y[i * 64], X, 64); 154 | } 155 | 156 | /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ 157 | for (i = 0; i < r; i++) 158 | blkcpy(&B[i * 64], &Y[(i * 2) * 64], 64); 159 | for (i = 0; i < r; i++) 160 | blkcpy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64); 161 | } 162 | 163 | /** 164 | * integerify(B, r): 165 | * Return the result of parsing B_{2r-1} as a little-endian integer. 166 | */ 167 | static uint64_t 168 | integerify(uint8_t * B, size_t r) 169 | { 170 | uint8_t * X = &B[(2 * r - 1) * 64]; 171 | 172 | return (le64dec(X)); 173 | } 174 | 175 | /** 176 | * smix(B, r, N, V, XY): 177 | * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; the 178 | * temporary storage V must be 128rN bytes in length; the temporary storage 179 | * XY must be 256r bytes in length. The value N must be a power of 2. 180 | */ 181 | static void 182 | smix(uint8_t * B, size_t r, uint64_t N, uint8_t * V, uint8_t * XY) 183 | { 184 | uint8_t * X = XY; 185 | uint8_t * Y = &XY[128 * r]; 186 | uint64_t i; 187 | uint64_t j; 188 | 189 | /* 1: X <-- B */ 190 | blkcpy(X, B, 128 * r); 191 | 192 | /* 2: for i = 0 to N - 1 do */ 193 | for (i = 0; i < N; i++) { 194 | /* 3: V_i <-- X */ 195 | blkcpy(&V[i * (128 * r)], X, 128 * r); 196 | 197 | /* 4: X <-- H(X) */ 198 | blockmix_salsa8(X, Y, r); 199 | } 200 | 201 | /* 6: for i = 0 to N - 1 do */ 202 | for (i = 0; i < N; i++) { 203 | /* 7: j <-- Integerify(X) mod N */ 204 | j = integerify(X, r) & (N - 1); 205 | 206 | /* 8: X <-- H(X \xor V_j) */ 207 | blkxor(X, &V[j * (128 * r)], 128 * r); 208 | blockmix_salsa8(X, Y, r); 209 | } 210 | 211 | /* 10: B' <-- X */ 212 | blkcpy(B, X, 128 * r); 213 | } 214 | 215 | /** 216 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 217 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 218 | * p, buflen) and write the result into buf. The parameters r, p, and buflen 219 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 220 | * must be a power of 2. 221 | * 222 | * Return 0 on success; or -1 on error. 223 | */ 224 | int 225 | crypto_scrypt(const uint8_t * passwd, size_t passwdlen, 226 | const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p, 227 | uint8_t * buf, size_t buflen) 228 | { 229 | uint8_t * B; 230 | uint8_t * V; 231 | uint8_t * XY; 232 | uint32_t i; 233 | 234 | /* Sanity-check parameters. */ 235 | #if SIZE_MAX > UINT32_MAX 236 | if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { 237 | php_error_docref(NULL, E_WARNING, "Invalid Parameters: $keyLength too big"); 238 | errno = EFBIG; 239 | goto err0; 240 | } 241 | #endif 242 | if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { 243 | errno = EFBIG; 244 | php_error_docref(NULL, E_WARNING, "Invalid Parameters; $r * $p is >= 2^30"); 245 | goto err0; 246 | } 247 | if (((N & (N - 1)) != 0) || (N == 0)) { 248 | errno = EINVAL; 249 | php_error_docref(NULL, E_WARNING, "Invalid Parameters; $N is not a power of two greater than 1"); 250 | goto err0; 251 | } 252 | if ((r > SIZE_MAX / 128 / p) || 253 | #if SIZE_MAX / 256 <= UINT32_MAX 254 | (r > SIZE_MAX / 256) || 255 | #endif 256 | (N > SIZE_MAX / 128 / r)) { 257 | errno = ENOMEM; 258 | php_error_docref(NULL, E_WARNING, "Invalid Parameters"); 259 | goto err0; 260 | } 261 | 262 | /* Allocate memory. */ 263 | if ((B = safe_emalloc(128, r * p, 0)) == NULL) 264 | goto err0; 265 | if ((XY = safe_emalloc(256, r, 0)) == NULL) 266 | goto err1; 267 | if ((V = safe_emalloc(128, r * N, 0)) == NULL) 268 | goto err2; 269 | 270 | /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ 271 | PBKDF2_SHA256_SCRYPT(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); 272 | 273 | /* 2: for i = 0 to p - 1 do */ 274 | for (i = 0; i < p; i++) { 275 | /* 3: B_i <-- MF(B_i, N) */ 276 | smix(&B[i * 128 * r], r, N, V, XY); 277 | } 278 | 279 | /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ 280 | PBKDF2_SHA256_SCRYPT(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); 281 | 282 | /* Free memory. */ 283 | efree(V); 284 | efree(XY); 285 | efree(B); 286 | 287 | /* Success! */ 288 | return (0); 289 | 290 | err2: 291 | efree(XY); 292 | err1: 293 | efree(B); 294 | err0: 295 | /* Failure! */ 296 | return (-1); 297 | } 298 | -------------------------------------------------------------------------------- /crypto/crypto_scrypt-sse.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | #include "php.h" 30 | #ifdef PHP_WIN32 31 | #include "zend_config.w32.h" 32 | #endif 33 | 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include "sha256.h" 44 | #include "sysendian.h" 45 | 46 | #include "crypto_scrypt.h" 47 | #include "php_scrypt.h" 48 | 49 | static void blkcpy(void *, void *, size_t); 50 | static void blkxor(void *, void *, size_t); 51 | static void salsa20_8(__m128i [4]); 52 | static void blockmix_salsa8(__m128i *, __m128i *, __m128i *, size_t); 53 | static uint64_t integerify(void *, size_t); 54 | static void smix(uint8_t *, size_t, uint64_t, void *, void *); 55 | 56 | static void 57 | blkcpy(void * dest, void * src, size_t len) 58 | { 59 | __m128i * D = dest; 60 | __m128i * S = src; 61 | size_t L = len / 16; 62 | size_t i; 63 | 64 | for (i = 0; i < L; i++) 65 | D[i] = S[i]; 66 | } 67 | 68 | static void 69 | blkxor(void * dest, void * src, size_t len) 70 | { 71 | __m128i * D = dest; 72 | __m128i * S = src; 73 | size_t L = len / 16; 74 | size_t i; 75 | 76 | for (i = 0; i < L; i++) 77 | D[i] = _mm_xor_si128(D[i], S[i]); 78 | } 79 | 80 | /** 81 | * salsa20_8(B): 82 | * Apply the salsa20/8 core to the provided block. 83 | */ 84 | static void 85 | salsa20_8(__m128i B[4]) 86 | { 87 | __m128i X0, X1, X2, X3; 88 | __m128i T; 89 | size_t i; 90 | 91 | X0 = B[0]; 92 | X1 = B[1]; 93 | X2 = B[2]; 94 | X3 = B[3]; 95 | 96 | for (i = 0; i < 8; i += 2) { 97 | /* Operate on "columns". */ 98 | T = _mm_add_epi32(X0, X3); 99 | X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 7)); 100 | X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 25)); 101 | T = _mm_add_epi32(X1, X0); 102 | X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9)); 103 | X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23)); 104 | T = _mm_add_epi32(X2, X1); 105 | X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 13)); 106 | X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 19)); 107 | T = _mm_add_epi32(X3, X2); 108 | X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18)); 109 | X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14)); 110 | 111 | /* Rearrange data. */ 112 | X1 = _mm_shuffle_epi32(X1, 0x93); 113 | X2 = _mm_shuffle_epi32(X2, 0x4E); 114 | X3 = _mm_shuffle_epi32(X3, 0x39); 115 | 116 | /* Operate on "rows". */ 117 | T = _mm_add_epi32(X0, X1); 118 | X3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 7)); 119 | X3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 25)); 120 | T = _mm_add_epi32(X3, X0); 121 | X2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9)); 122 | X2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23)); 123 | T = _mm_add_epi32(X2, X3); 124 | X1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 13)); 125 | X1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 19)); 126 | T = _mm_add_epi32(X1, X2); 127 | X0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18)); 128 | X0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14)); 129 | 130 | /* Rearrange data. */ 131 | X1 = _mm_shuffle_epi32(X1, 0x39); 132 | X2 = _mm_shuffle_epi32(X2, 0x4E); 133 | X3 = _mm_shuffle_epi32(X3, 0x93); 134 | } 135 | 136 | B[0] = _mm_add_epi32(B[0], X0); 137 | B[1] = _mm_add_epi32(B[1], X1); 138 | B[2] = _mm_add_epi32(B[2], X2); 139 | B[3] = _mm_add_epi32(B[3], X3); 140 | } 141 | 142 | /** 143 | * blockmix_salsa8(Bin, Bout, X, r): 144 | * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r 145 | * bytes in length; the output Bout must also be the same size. The 146 | * temporary space X must be 64 bytes. 147 | */ 148 | static void 149 | blockmix_salsa8(__m128i * Bin, __m128i * Bout, __m128i * X, size_t r) 150 | { 151 | size_t i; 152 | 153 | /* 1: X <-- B_{2r - 1} */ 154 | blkcpy(X, &Bin[8 * r - 4], 64); 155 | 156 | /* 2: for i = 0 to 2r - 1 do */ 157 | for (i = 0; i < r; i++) { 158 | /* 3: X <-- H(X \xor B_i) */ 159 | blkxor(X, &Bin[i * 8], 64); 160 | salsa20_8(X); 161 | 162 | /* 4: Y_i <-- X */ 163 | /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ 164 | blkcpy(&Bout[i * 4], X, 64); 165 | 166 | /* 3: X <-- H(X \xor B_i) */ 167 | blkxor(X, &Bin[i * 8 + 4], 64); 168 | salsa20_8(X); 169 | 170 | /* 4: Y_i <-- X */ 171 | /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ 172 | blkcpy(&Bout[(r + i) * 4], X, 64); 173 | } 174 | } 175 | 176 | /** 177 | * integerify(B, r): 178 | * Return the result of parsing B_{2r-1} as a little-endian integer. 179 | */ 180 | static uint64_t 181 | integerify(void * B, size_t r) 182 | { 183 | uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64); 184 | 185 | return (((uint64_t)(X[13]) << 32) + X[0]); 186 | } 187 | 188 | /** 189 | * smix(B, r, N, V, XY): 190 | * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; 191 | * the temporary storage V must be 128rN bytes in length; the temporary 192 | * storage XY must be 256r + 64 bytes in length. The value N must be a 193 | * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a 194 | * multiple of 64 bytes. 195 | */ 196 | static void 197 | smix(uint8_t * B, size_t r, uint64_t N, void * V, void * XY) 198 | { 199 | __m128i * X = XY; 200 | __m128i * Y = (void *)((uintptr_t)(XY) + 128 * r); 201 | __m128i * Z = (void *)((uintptr_t)(XY) + 256 * r); 202 | uint32_t * X32 = (void *)X; 203 | uint64_t i, j; 204 | size_t k; 205 | 206 | /* 1: X <-- B */ 207 | for (k = 0; k < 2 * r; k++) { 208 | for (i = 0; i < 16; i++) { 209 | X32[k * 16 + i] = 210 | le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]); 211 | } 212 | } 213 | 214 | /* 2: for i = 0 to N - 1 do */ 215 | for (i = 0; i < N; i += 2) { 216 | /* 3: V_i <-- X */ 217 | blkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r); 218 | 219 | /* 4: X <-- H(X) */ 220 | blockmix_salsa8(X, Y, Z, r); 221 | 222 | /* 3: V_i <-- X */ 223 | blkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r), 224 | Y, 128 * r); 225 | 226 | /* 4: X <-- H(X) */ 227 | blockmix_salsa8(Y, X, Z, r); 228 | } 229 | 230 | /* 6: for i = 0 to N - 1 do */ 231 | for (i = 0; i < N; i += 2) { 232 | /* 7: j <-- Integerify(X) mod N */ 233 | j = integerify(X, r) & (N - 1); 234 | 235 | /* 8: X <-- H(X \xor V_j) */ 236 | blkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r); 237 | blockmix_salsa8(X, Y, Z, r); 238 | 239 | /* 7: j <-- Integerify(X) mod N */ 240 | j = integerify(Y, r) & (N - 1); 241 | 242 | /* 8: X <-- H(X \xor V_j) */ 243 | blkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r); 244 | blockmix_salsa8(Y, X, Z, r); 245 | } 246 | 247 | /* 10: B' <-- X */ 248 | for (k = 0; k < 2 * r; k++) { 249 | for (i = 0; i < 16; i++) { 250 | le32enc(&B[(k * 16 + (i * 5 % 16)) * 4], 251 | X32[k * 16 + i]); 252 | } 253 | } 254 | } 255 | 256 | /** 257 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 258 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 259 | * p, buflen) and write the result into buf. The parameters r, p, and buflen 260 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 261 | * must be a power of 2 greater than 1. 262 | * 263 | * Return 0 on success; or -1 on error. 264 | */ 265 | int 266 | crypto_scrypt(const uint8_t * passwd, size_t passwdlen, 267 | const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p, 268 | uint8_t * buf, size_t buflen) 269 | { 270 | void * B0, * V0, * XY0; 271 | uint8_t * B; 272 | uint32_t * V; 273 | uint32_t * XY; 274 | uint32_t i; 275 | 276 | /* Sanity-check parameters. */ 277 | #if SIZE_MAX > UINT32_MAX 278 | if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { 279 | php_error_docref(NULL, E_WARNING, "Invalid Parameters: $keyLength too big"); 280 | errno = EFBIG; 281 | goto err0; 282 | } 283 | #endif 284 | if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { 285 | errno = EFBIG; 286 | php_error_docref(NULL, E_WARNING, "Invalid Parameters; $r * $p is >= 2^30"); 287 | goto err0; 288 | } 289 | if (((N & (N - 1)) != 0) || (N == 0)) { 290 | errno = EINVAL; 291 | php_error_docref(NULL, E_WARNING, "Invalid Parameters; $N is not a power of two greater than 1"); 292 | goto err0; 293 | } 294 | if ((r > SIZE_MAX / 128 / p) || 295 | #if SIZE_MAX / 256 <= UINT32_MAX 296 | (r > (SIZE_MAX - 64) / 256) || 297 | #endif 298 | (N > SIZE_MAX / 128 / r)) { 299 | php_error_docref(NULL, E_WARNING, "Invalid Parameters"); 300 | errno = ENOMEM; 301 | goto err0; 302 | } 303 | 304 | /* Allocate memory. */ 305 | #ifdef HAVE_POSIX_MEMALIGN 306 | if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0) 307 | goto err0; 308 | B = (uint8_t *)(B0); 309 | if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0) 310 | goto err1; 311 | XY = (uint32_t *)(XY0); 312 | #ifndef MAP_ANON 313 | if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0) 314 | goto err2; 315 | V = (uint32_t *)(V0); 316 | #endif 317 | #else 318 | if ((B0 = malloc(128 * r * p + 63)) == NULL) 319 | goto err0; 320 | B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63)); 321 | if ((XY0 = malloc(256 * r + 64 + 63)) == NULL) 322 | goto err1; 323 | XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63)); 324 | #ifndef MAP_ANON 325 | if ((V0 = malloc(128 * r * N + 63)) == NULL) 326 | goto err2; 327 | V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63)); 328 | #endif 329 | #endif 330 | #ifdef MAP_ANON 331 | if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE, 332 | #ifdef MAP_NOCORE 333 | MAP_ANON | MAP_PRIVATE | MAP_NOCORE, 334 | #else 335 | MAP_ANON | MAP_PRIVATE, 336 | #endif 337 | -1, 0)) == MAP_FAILED) 338 | goto err2; 339 | V = (uint32_t *)(V0); 340 | #endif 341 | 342 | /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ 343 | PBKDF2_SHA256_SCRYPT(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); 344 | 345 | /* 2: for i = 0 to p - 1 do */ 346 | for (i = 0; i < p; i++) { 347 | /* 3: B_i <-- MF(B_i, N) */ 348 | smix(&B[i * 128 * r], r, N, V, XY); 349 | } 350 | 351 | /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ 352 | PBKDF2_SHA256_SCRYPT(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); 353 | 354 | /* Free memory. */ 355 | #ifdef MAP_ANON 356 | if (munmap(V0, 128 * r * N)) 357 | goto err2; 358 | #else 359 | free(V0); 360 | #endif 361 | free(XY0); 362 | free(B0); 363 | 364 | /* Success! */ 365 | return (0); 366 | 367 | err2: 368 | free(XY0); 369 | err1: 370 | free(B0); 371 | err0: 372 | /* Failure! */ 373 | return (-1); 374 | } 375 | -------------------------------------------------------------------------------- /crypto/sha256.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2005,2007,2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #include "php.h" 28 | 29 | #include 30 | #ifdef PHP_WIN32 31 | # include "win32/php_stdint.h" 32 | #else 33 | # include 34 | #endif 35 | #include 36 | 37 | #include "sysendian.h" 38 | 39 | #include "sha256.h" 40 | 41 | /* 42 | * Encode a length len/4 vector of (uint32_t) into a length len vector of 43 | * (unsigned char) in big-endian form. Assumes len is a multiple of 4. 44 | */ 45 | static void 46 | be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len) 47 | { 48 | size_t i; 49 | 50 | for (i = 0; i < len / 4; i++) 51 | be32enc(dst + i * 4, src[i]); 52 | } 53 | 54 | /* 55 | * Decode a big-endian length len vector of (unsigned char) into a length 56 | * len/4 vector of (uint32_t). Assumes len is a multiple of 4. 57 | */ 58 | static void 59 | be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len) 60 | { 61 | size_t i; 62 | 63 | for (i = 0; i < len / 4; i++) 64 | dst[i] = be32dec(src + i * 4); 65 | } 66 | 67 | /* Elementary functions used by SHA256 */ 68 | #define Ch(x, y, z) ((x & (y ^ z)) ^ z) 69 | #define Maj(x, y, z) ((x & (y | z)) | (y & z)) 70 | #define SHR(x, n) (x >> n) 71 | #define ROTR(x, n) ((x >> n) | (x << (32 - n))) 72 | #define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) 73 | #define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) 74 | #define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) 75 | #define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) 76 | 77 | /* SHA256 round function */ 78 | #define RND(a, b, c, d, e, f, g, h, k) \ 79 | t0 = h + S1(e) + Ch(e, f, g) + k; \ 80 | t1 = S0(a) + Maj(a, b, c); \ 81 | d += t0; \ 82 | h = t0 + t1; 83 | 84 | /* Adjusted round function for rotating state */ 85 | #define RNDr(S, W, i, k) \ 86 | RND(S[(64 - i) % 8], S[(65 - i) % 8], \ 87 | S[(66 - i) % 8], S[(67 - i) % 8], \ 88 | S[(68 - i) % 8], S[(69 - i) % 8], \ 89 | S[(70 - i) % 8], S[(71 - i) % 8], \ 90 | W[i] + k) 91 | 92 | /* 93 | * SHA256 block compression function. The 256-bit state is transformed via 94 | * the 512-bit input block to produce a new state. 95 | */ 96 | static void 97 | SHA256_Transform(uint32_t * state, const unsigned char block[64]) 98 | { 99 | uint32_t W[64]; 100 | uint32_t S[8]; 101 | uint32_t t0, t1; 102 | int i; 103 | 104 | /* 1. Prepare message schedule W. */ 105 | be32dec_vect(W, block, 64); 106 | for (i = 16; i < 64; i++) 107 | W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16]; 108 | 109 | /* 2. Initialize working variables. */ 110 | memcpy(S, state, 32); 111 | 112 | /* 3. Mix. */ 113 | RNDr(S, W, 0, 0x428a2f98); 114 | RNDr(S, W, 1, 0x71374491); 115 | RNDr(S, W, 2, 0xb5c0fbcf); 116 | RNDr(S, W, 3, 0xe9b5dba5); 117 | RNDr(S, W, 4, 0x3956c25b); 118 | RNDr(S, W, 5, 0x59f111f1); 119 | RNDr(S, W, 6, 0x923f82a4); 120 | RNDr(S, W, 7, 0xab1c5ed5); 121 | RNDr(S, W, 8, 0xd807aa98); 122 | RNDr(S, W, 9, 0x12835b01); 123 | RNDr(S, W, 10, 0x243185be); 124 | RNDr(S, W, 11, 0x550c7dc3); 125 | RNDr(S, W, 12, 0x72be5d74); 126 | RNDr(S, W, 13, 0x80deb1fe); 127 | RNDr(S, W, 14, 0x9bdc06a7); 128 | RNDr(S, W, 15, 0xc19bf174); 129 | RNDr(S, W, 16, 0xe49b69c1); 130 | RNDr(S, W, 17, 0xefbe4786); 131 | RNDr(S, W, 18, 0x0fc19dc6); 132 | RNDr(S, W, 19, 0x240ca1cc); 133 | RNDr(S, W, 20, 0x2de92c6f); 134 | RNDr(S, W, 21, 0x4a7484aa); 135 | RNDr(S, W, 22, 0x5cb0a9dc); 136 | RNDr(S, W, 23, 0x76f988da); 137 | RNDr(S, W, 24, 0x983e5152); 138 | RNDr(S, W, 25, 0xa831c66d); 139 | RNDr(S, W, 26, 0xb00327c8); 140 | RNDr(S, W, 27, 0xbf597fc7); 141 | RNDr(S, W, 28, 0xc6e00bf3); 142 | RNDr(S, W, 29, 0xd5a79147); 143 | RNDr(S, W, 30, 0x06ca6351); 144 | RNDr(S, W, 31, 0x14292967); 145 | RNDr(S, W, 32, 0x27b70a85); 146 | RNDr(S, W, 33, 0x2e1b2138); 147 | RNDr(S, W, 34, 0x4d2c6dfc); 148 | RNDr(S, W, 35, 0x53380d13); 149 | RNDr(S, W, 36, 0x650a7354); 150 | RNDr(S, W, 37, 0x766a0abb); 151 | RNDr(S, W, 38, 0x81c2c92e); 152 | RNDr(S, W, 39, 0x92722c85); 153 | RNDr(S, W, 40, 0xa2bfe8a1); 154 | RNDr(S, W, 41, 0xa81a664b); 155 | RNDr(S, W, 42, 0xc24b8b70); 156 | RNDr(S, W, 43, 0xc76c51a3); 157 | RNDr(S, W, 44, 0xd192e819); 158 | RNDr(S, W, 45, 0xd6990624); 159 | RNDr(S, W, 46, 0xf40e3585); 160 | RNDr(S, W, 47, 0x106aa070); 161 | RNDr(S, W, 48, 0x19a4c116); 162 | RNDr(S, W, 49, 0x1e376c08); 163 | RNDr(S, W, 50, 0x2748774c); 164 | RNDr(S, W, 51, 0x34b0bcb5); 165 | RNDr(S, W, 52, 0x391c0cb3); 166 | RNDr(S, W, 53, 0x4ed8aa4a); 167 | RNDr(S, W, 54, 0x5b9cca4f); 168 | RNDr(S, W, 55, 0x682e6ff3); 169 | RNDr(S, W, 56, 0x748f82ee); 170 | RNDr(S, W, 57, 0x78a5636f); 171 | RNDr(S, W, 58, 0x84c87814); 172 | RNDr(S, W, 59, 0x8cc70208); 173 | RNDr(S, W, 60, 0x90befffa); 174 | RNDr(S, W, 61, 0xa4506ceb); 175 | RNDr(S, W, 62, 0xbef9a3f7); 176 | RNDr(S, W, 63, 0xc67178f2); 177 | 178 | /* 4. Mix local working variables into global state */ 179 | for (i = 0; i < 8; i++) 180 | state[i] += S[i]; 181 | 182 | /* Clean the stack. */ 183 | memset(W, 0, 256); 184 | memset(S, 0, 32); 185 | t0 = t1 = 0; 186 | } 187 | 188 | static unsigned char PAD[64] = { 189 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 191 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 193 | }; 194 | 195 | /* Add padding and terminating bit-count. */ 196 | static void 197 | SHA256_Pad(SHA256_CTX * ctx) 198 | { 199 | unsigned char len[8]; 200 | uint32_t r, plen; 201 | 202 | /* 203 | * Convert length to a vector of bytes -- we do this now rather 204 | * than later because the length will change after we pad. 205 | */ 206 | be32enc_vect(len, ctx->count, 8); 207 | 208 | /* Add 1--64 bytes so that the resulting length is 56 mod 64 */ 209 | r = (ctx->count[1] >> 3) & 0x3f; 210 | plen = (r < 56) ? (56 - r) : (120 - r); 211 | SHA256_Update_SCRYPT(ctx, PAD, (size_t)plen); 212 | 213 | /* Add the terminating bit-count */ 214 | SHA256_Update_SCRYPT(ctx, len, 8); 215 | } 216 | 217 | /* SHA-256 initialization. Begins a SHA-256 operation. */ 218 | void 219 | SHA256_Init_SCRYPT(SHA256_CTX * ctx) 220 | { 221 | 222 | /* Zero bits processed so far */ 223 | ctx->count[0] = ctx->count[1] = 0; 224 | 225 | /* Magic initialization constants */ 226 | ctx->state[0] = 0x6A09E667; 227 | ctx->state[1] = 0xBB67AE85; 228 | ctx->state[2] = 0x3C6EF372; 229 | ctx->state[3] = 0xA54FF53A; 230 | ctx->state[4] = 0x510E527F; 231 | ctx->state[5] = 0x9B05688C; 232 | ctx->state[6] = 0x1F83D9AB; 233 | ctx->state[7] = 0x5BE0CD19; 234 | } 235 | 236 | /* Add bytes into the hash */ 237 | void 238 | SHA256_Update_SCRYPT(SHA256_CTX * ctx, const void *in, size_t len) 239 | { 240 | uint32_t bitlen[2]; 241 | uint32_t r; 242 | const unsigned char *src = in; 243 | 244 | /* Number of bytes left in the buffer from previous updates */ 245 | r = (ctx->count[1] >> 3) & 0x3f; 246 | 247 | /* Convert the length into a number of bits */ 248 | bitlen[1] = ((uint32_t)len) << 3; 249 | bitlen[0] = (uint32_t)(len >> 29); 250 | 251 | /* Update number of bits */ 252 | if ((ctx->count[1] += bitlen[1]) < bitlen[1]) 253 | ctx->count[0]++; 254 | ctx->count[0] += bitlen[0]; 255 | 256 | /* Handle the case where we don't need to perform any transforms */ 257 | if (len < 64 - r) { 258 | memcpy(&ctx->buf[r], src, len); 259 | return; 260 | } 261 | 262 | /* Finish the current block */ 263 | memcpy(&ctx->buf[r], src, 64 - r); 264 | SHA256_Transform(ctx->state, ctx->buf); 265 | src += 64 - r; 266 | len -= 64 - r; 267 | 268 | /* Perform complete blocks */ 269 | while (len >= 64) { 270 | SHA256_Transform(ctx->state, src); 271 | src += 64; 272 | len -= 64; 273 | } 274 | 275 | /* Copy left over data into buffer */ 276 | memcpy(ctx->buf, src, len); 277 | } 278 | 279 | /* 280 | * SHA-256 finalization. Pads the input data, exports the hash value, 281 | * and clears the context state. 282 | */ 283 | void 284 | SHA256_Final_SCRYPT(unsigned char digest[32], SHA256_CTX * ctx) 285 | { 286 | 287 | /* Add padding */ 288 | SHA256_Pad(ctx); 289 | 290 | /* Write the hash */ 291 | be32enc_vect(digest, ctx->state, 32); 292 | 293 | /* Clear the context state */ 294 | memset((void *)ctx, 0, sizeof(*ctx)); 295 | } 296 | 297 | /* Initialize an HMAC-SHA256 operation with the given key. */ 298 | void 299 | HMAC_SHA256_Init_SCRYPT(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) 300 | { 301 | unsigned char pad[64]; 302 | unsigned char khash[32]; 303 | const unsigned char * K = _K; 304 | size_t i; 305 | 306 | /* If Klen > 64, the key is really SHA256(K). */ 307 | if (Klen > 64) { 308 | SHA256_Init_SCRYPT(&ctx->ictx); 309 | SHA256_Update_SCRYPT(&ctx->ictx, K, Klen); 310 | SHA256_Final_SCRYPT(khash, &ctx->ictx); 311 | K = khash; 312 | Klen = 32; 313 | } 314 | 315 | /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ 316 | SHA256_Init_SCRYPT(&ctx->ictx); 317 | memset(pad, 0x36, 64); 318 | for (i = 0; i < Klen; i++) 319 | pad[i] ^= K[i]; 320 | 321 | SHA256_Update_SCRYPT(&ctx->ictx, pad, 64); 322 | 323 | /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ 324 | SHA256_Init_SCRYPT(&ctx->octx); 325 | memset(pad, 0x5c, 64); 326 | for (i = 0; i < Klen; i++) 327 | pad[i] ^= K[i]; 328 | SHA256_Update_SCRYPT(&ctx->octx, pad, 64); 329 | 330 | /* Clean the stack. */ 331 | memset(khash, 0, 32); 332 | } 333 | 334 | /* Add bytes to the HMAC-SHA256 operation. */ 335 | void 336 | HMAC_SHA256_Update_SCRYPT(HMAC_SHA256_CTX * ctx, const void *in, size_t len) 337 | { 338 | 339 | /* Feed data to the inner SHA256 operation. */ 340 | SHA256_Update_SCRYPT(&ctx->ictx, in, len); 341 | } 342 | 343 | /* Finish an HMAC-SHA256 operation. */ 344 | void 345 | HMAC_SHA256_Final_SCRYPT(unsigned char digest[32], HMAC_SHA256_CTX * ctx) 346 | { 347 | unsigned char ihash[32]; 348 | 349 | /* Finish the inner SHA256 operation. */ 350 | SHA256_Final_SCRYPT(ihash, &ctx->ictx); 351 | 352 | /* Feed the inner hash to the outer SHA256 operation. */ 353 | SHA256_Update_SCRYPT(&ctx->octx, ihash, 32); 354 | 355 | /* Finish the outer SHA256 operation. */ 356 | SHA256_Final_SCRYPT(digest, &ctx->octx); 357 | 358 | /* Clean the stack. */ 359 | memset(ihash, 0, 32); 360 | } 361 | 362 | /** 363 | * PBKDF2_SHA256_SCRYPT(passwd, passwdlen, salt, saltlen, c, buf, dkLen): 364 | * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and 365 | * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). 366 | */ 367 | void 368 | PBKDF2_SHA256_SCRYPT(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, 369 | size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) 370 | { 371 | HMAC_SHA256_CTX PShctx, hctx; 372 | size_t i; 373 | uint8_t ivec[4]; 374 | uint8_t U[32]; 375 | uint8_t T[32]; 376 | uint64_t j; 377 | int k; 378 | size_t clen; 379 | 380 | /* Compute HMAC state after processing P and S. */ 381 | HMAC_SHA256_Init_SCRYPT(&PShctx, passwd, passwdlen); 382 | 383 | HMAC_SHA256_Update_SCRYPT(&PShctx, salt, saltlen); 384 | 385 | /* Iterate through the blocks. */ 386 | for (i = 0; i * 32 < dkLen; i++) { 387 | /* Generate INT(i + 1). */ 388 | be32enc(ivec, (uint32_t)(i + 1)); 389 | 390 | /* Compute U_1 = PRF(P, S || INT(i)). */ 391 | memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); 392 | HMAC_SHA256_Update_SCRYPT(&hctx, ivec, 4); 393 | HMAC_SHA256_Final_SCRYPT(U, &hctx); 394 | 395 | /* T_i = U_1 ... */ 396 | memcpy(T, U, 32); 397 | 398 | for (j = 2; j <= c; j++) { 399 | /* Compute U_j. */ 400 | HMAC_SHA256_Init_SCRYPT(&hctx, passwd, passwdlen); 401 | HMAC_SHA256_Update_SCRYPT(&hctx, U, 32); 402 | HMAC_SHA256_Final_SCRYPT(U, &hctx); 403 | 404 | /* ... xor U_j ... */ 405 | for (k = 0; k < 32; k++) 406 | T[k] ^= U[k]; 407 | } 408 | 409 | /* Copy as many bytes as necessary into buf. */ 410 | clen = dkLen - i * 32; 411 | if (clen > 32) 412 | clen = 32; 413 | memcpy(&buf[i * 32], T, clen); 414 | } 415 | 416 | /* Clean PShctx, since we never called _Final on it. */ 417 | memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX)); 418 | } 419 | -------------------------------------------------------------------------------- /crypto/params.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * This file was originally written by Colin Percival as part of the Tarsnap 27 | * online backup system. 28 | */ 29 | 30 | #include 31 | #ifdef PHP_WIN32 32 | # include "win32/time.h" 33 | # include "win32/php_stdint.h" 34 | #else 35 | # include 36 | # include 37 | #endif 38 | #include 39 | #include 40 | #ifndef PHP_WIN32 41 | # include 42 | # include 43 | #endif 44 | #include 45 | 46 | #ifdef HAVE_CONFIG_H 47 | #include "config.h" 48 | #endif 49 | #ifdef HAVE_SYS_PARAM_H 50 | #include 51 | #endif 52 | #ifdef HAVE_SYSCTL_HW_USERMEM 53 | #include 54 | #endif 55 | #ifdef HAVE_SYS_SYSINFO_H 56 | #include 57 | #define HAVE_SYSINFO 58 | #endif 59 | 60 | #include "params.h" 61 | 62 | #include "crypto/crypto_scrypt.h" 63 | 64 | static int memtouse(size_t, double, size_t *); 65 | static int scryptenc_cpuperf(double * opps); 66 | 67 | int 68 | pickparams(size_t maxmem, double maxmemfrac, double maxtime, 69 | int * logN, uint32_t * r, uint32_t * p) 70 | { 71 | size_t memlimit; 72 | double opps; 73 | double opslimit; 74 | double maxN, maxrp; 75 | int rc; 76 | 77 | /* Figure out how much memory to use. */ 78 | if (memtouse(maxmem, maxmemfrac, &memlimit)) 79 | return (1); 80 | 81 | /* Figure out how fast the CPU is. */ 82 | if ((rc = scryptenc_cpuperf(&opps)) != 0) 83 | return (rc); 84 | opslimit = opps * maxtime; 85 | 86 | /* Allow a minimum of 2^15 salsa20/8 cores. */ 87 | if (opslimit < 32768) 88 | opslimit = 32768; 89 | 90 | /* Fix r = 8 for now. */ 91 | *r = 8; 92 | 93 | /* 94 | * The memory limit requires that 128Nr <= memlimit, while the CPU 95 | * limit requires that 4Nrp <= opslimit. If opslimit < memlimit/32, 96 | * opslimit imposes the stronger limit on N. 97 | */ 98 | #ifdef DEBUG 99 | fprintf(stderr, "Requiring 128Nr <= %zu, 4Nrp <= %f\n", 100 | memlimit, opslimit); 101 | #endif 102 | if (opslimit < memlimit/32) { 103 | /* Set p = 1 and choose N based on the CPU limit. */ 104 | *p = 1; 105 | maxN = opslimit / (*r * 4); 106 | for (*logN = 1; *logN < 63; *logN += 1) { 107 | if ((uint64_t)(1) << *logN > maxN / 2) 108 | break; 109 | } 110 | } else { 111 | /* Set N based on the memory limit. */ 112 | maxN = memlimit / (*r * 128); 113 | for (*logN = 1; *logN < 63; *logN += 1) { 114 | if ((uint64_t)(1) << *logN > maxN / 2) 115 | break; 116 | } 117 | 118 | /* Choose p based on the CPU limit. */ 119 | maxrp = (opslimit / 4) / ((uint64_t)(1) << *logN); 120 | if (maxrp > 0x3fffffff) 121 | maxrp = 0x3fffffff; 122 | *p = (uint32_t)(maxrp) / *r; 123 | } 124 | 125 | #ifdef DEBUG 126 | fprintf(stderr, "N = %zu r = %d p = %d\n", 127 | (size_t)(1) << *logN, (int)(*r), (int)(*p)); 128 | #endif 129 | 130 | /* Success! */ 131 | return (0); 132 | } 133 | 134 | int 135 | checkparams(size_t maxmem, double maxmemfrac, double maxtime, 136 | int logN, uint32_t r, uint32_t p) 137 | { 138 | size_t memlimit; 139 | double opps; 140 | double opslimit; 141 | uint64_t N; 142 | int rc; 143 | 144 | /* Figure out the maximum amount of memory we can use. */ 145 | if (memtouse(maxmem, maxmemfrac, &memlimit)) 146 | return (1); 147 | 148 | /* Figure out how fast the CPU is. */ 149 | if ((rc = scryptenc_cpuperf(&opps)) != 0) 150 | return (rc); 151 | opslimit = opps * maxtime; 152 | 153 | /* Sanity-check values. */ 154 | if ((logN < 1) || (logN > 63)) 155 | return (7); 156 | if ((uint64_t)(r) * (uint64_t)(p) >= 0x40000000) 157 | return (7); 158 | 159 | /* Check limits. */ 160 | N = (uint64_t)(1) << logN; 161 | if ((memlimit / N) / r < 128) 162 | return (9); 163 | if ((opslimit / N) / (r * p) < 4) 164 | return (10); 165 | 166 | /* Success! */ 167 | return (0); 168 | } 169 | 170 | #ifdef HAVE_CLOCK_GETTIME 171 | 172 | static clock_t clocktouse; 173 | 174 | static int 175 | getclockres(double * resd) 176 | { 177 | struct timespec res; 178 | 179 | /* 180 | * Try clocks in order of preference until we find one which works. 181 | * (We assume that if clock_getres works, clock_gettime will, too.) 182 | * The use of if/else/if/else/if/else rather than if/elif/elif/else 183 | * is ugly but legal, and allows us to #ifdef things appropriately. 184 | */ 185 | #ifdef CLOCK_VIRTUAL 186 | if (clock_getres(CLOCK_VIRTUAL, &res) == 0) 187 | clocktouse = CLOCK_VIRTUAL; 188 | else 189 | #endif 190 | #ifdef CLOCK_MONOTONIC 191 | if (clock_getres(CLOCK_MONOTONIC, &res) == 0) 192 | clocktouse = CLOCK_MONOTONIC; 193 | else 194 | #endif 195 | if (clock_getres(CLOCK_REALTIME, &res) == 0) 196 | clocktouse = CLOCK_REALTIME; 197 | else 198 | return (-1); 199 | 200 | /* Convert clock resolution to a double. */ 201 | *resd = res.tv_sec + res.tv_nsec * 0.000000001; 202 | 203 | return (0); 204 | } 205 | 206 | static int 207 | getclocktime(struct timespec * ts) 208 | { 209 | 210 | if (clock_gettime(clocktouse, ts)) 211 | return (-1); 212 | 213 | return (0); 214 | } 215 | 216 | #else 217 | static int 218 | getclockres(double * resd) 219 | { 220 | 221 | *resd = 1.0 / CLOCKS_PER_SEC; 222 | 223 | return (0); 224 | } 225 | 226 | static int 227 | getclocktime(struct timespec * ts) 228 | { 229 | struct timeval tv; 230 | 231 | if (gettimeofday(&tv, NULL)) 232 | return (-1); 233 | ts->tv_sec = tv.tv_sec; 234 | ts->tv_nsec = tv.tv_usec * 1000; 235 | 236 | return (0); 237 | } 238 | #endif 239 | 240 | static int 241 | getclockdiff(struct timespec * st, double * diffd) 242 | { 243 | struct timespec en; 244 | 245 | if (getclocktime(&en)) 246 | return (1); 247 | *diffd = (en.tv_nsec - st->tv_nsec) * 0.000000001 + 248 | (en.tv_sec - st->tv_sec); 249 | 250 | return (0); 251 | } 252 | 253 | /** 254 | * scryptenc_cpuperf(opps): 255 | * Estimate the number of salsa20/8 cores which can be executed per second, 256 | * and return the value via opps. 257 | */ 258 | static int 259 | scryptenc_cpuperf(double * opps) 260 | { 261 | struct timespec st; 262 | double resd, diffd; 263 | uint64_t i = 0; 264 | 265 | /* Get the clock resolution. */ 266 | if (getclockres(&resd)) 267 | return (2); 268 | 269 | #ifdef DEBUG 270 | fprintf(stderr, "Clock resolution is %f\n", resd); 271 | #endif 272 | 273 | /* Loop until the clock ticks. */ 274 | if (getclocktime(&st)) 275 | return (2); 276 | do { 277 | /* Do an scrypt. */ 278 | if (crypto_scrypt(NULL, 0, NULL, 0, 16, 1, 1, NULL, 0)) 279 | return (3); 280 | 281 | /* Has the clock ticked? */ 282 | if (getclockdiff(&st, &diffd)) 283 | return (2); 284 | if (diffd > 0) 285 | break; 286 | } while (1); 287 | 288 | /* Could how many scryps we can do before the next tick. */ 289 | if (getclocktime(&st)) 290 | return (2); 291 | do { 292 | /* Do an scrypt. */ 293 | if (crypto_scrypt(NULL, 0, NULL, 0, 128, 1, 1, NULL, 0)) 294 | return (3); 295 | 296 | /* We invoked the salsa20/8 core 512 times. */ 297 | i += 512; 298 | 299 | /* Check if we have looped for long enough. */ 300 | if (getclockdiff(&st, &diffd)) 301 | return (2); 302 | if (diffd > resd) 303 | break; 304 | } while (1); 305 | 306 | #ifdef DEBUG 307 | fprintf(stderr, "%ju salsa20/8 cores performed in %f seconds\n", 308 | (uintmax_t)i, diffd); 309 | #endif 310 | 311 | /* We can do approximately i salsa20/8 cores per diffd seconds. */ 312 | *opps = i / diffd; 313 | return (0); 314 | } 315 | 316 | #ifdef HAVE_SYSCTL_HW_USERMEM 317 | static int 318 | memlimit_sysctl_hw_usermem(size_t * memlimit) 319 | { 320 | int mib[2]; 321 | uint8_t usermembuf[8]; 322 | size_t usermemlen = 8; 323 | uint64_t usermem; 324 | 325 | /* Ask the kernel how much RAM we have. */ 326 | mib[0] = CTL_HW; 327 | mib[1] = HW_USERMEM; 328 | if (sysctl(mib, 2, usermembuf, &usermemlen, NULL, 0)) 329 | return (1); 330 | 331 | /* 332 | * Parse as either a uint64_t or a uint32_t based on the length of 333 | * output the kernel reports having copied out. It appears that all 334 | * systems providing a sysctl interface for reading integers copy 335 | * them out as system-endian values, so we don't need to worry about 336 | * parsing them. 337 | */ 338 | if (usermemlen == sizeof(uint64_t)) 339 | usermem = *(uint64_t *)usermembuf; 340 | else if (usermemlen == sizeof(uint32_t)) 341 | usermem = *(uint32_t *)usermembuf; 342 | else 343 | return (1); 344 | 345 | /* Return the sysctl value, but clamp to SIZE_MAX if necessary. */ 346 | #if UINT64_MAX > SIZE_MAX 347 | if (usermem > SIZE_MAX) 348 | *memlimit = SIZE_MAX; 349 | else 350 | *memlimit = usermem; 351 | #else 352 | *memlimit = usermem; 353 | #endif 354 | 355 | /* Success! */ 356 | return (0); 357 | } 358 | #endif 359 | 360 | /* If we don't HAVE_STRUCT_SYSINFO, we can't use sysinfo. */ 361 | #ifndef HAVE_STRUCT_SYSINFO 362 | #undef HAVE_SYSINFO 363 | #endif 364 | 365 | /* If we don't HAVE_STRUCT_SYSINFO_TOTALRAM, we can't use sysinfo. */ 366 | #ifndef HAVE_STRUCT_SYSINFO_TOTALRAM 367 | #undef HAVE_SYSINFO 368 | #endif 369 | 370 | #ifdef HAVE_SYSINFO 371 | static int 372 | memlimit_sysinfo(size_t * memlimit) 373 | { 374 | struct sysinfo info; 375 | uint64_t totalmem; 376 | 377 | /* Get information from the kernel. */ 378 | if (sysinfo(&info)) 379 | return (1); 380 | totalmem = info.totalram; 381 | 382 | /* If we're on a modern kernel, adjust based on mem_unit. */ 383 | #ifdef HAVE_STRUCT_SYSINFO_MEM_UNIT 384 | totalmem = totalmem * info.mem_unit; 385 | #endif 386 | 387 | /* Return the value, but clamp to SIZE_MAX if necessary. */ 388 | #if UINT64_MAX > SIZE_MAX 389 | if (totalmem > SIZE_MAX) 390 | *memlimit = SIZE_MAX; 391 | else 392 | *memlimit = totalmem; 393 | #else 394 | *memlimit = totalmem; 395 | #endif 396 | 397 | /* Success! */ 398 | return (0); 399 | } 400 | #endif /* HAVE_SYSINFO */ 401 | 402 | #ifdef _WIN32 403 | static int 404 | memlimit_rlimit(size_t * memlimit) 405 | { 406 | return (0); 407 | } 408 | #else 409 | static int 410 | memlimit_rlimit(size_t * memlimit) 411 | { 412 | struct rlimit rl; 413 | uint64_t memrlimit; 414 | 415 | /* Find the least of... */ 416 | memrlimit = (uint64_t)(-1); 417 | 418 | /* ... RLIMIT_AS... */ 419 | #ifdef RLIMIT_AS 420 | if (getrlimit(RLIMIT_AS, &rl)) 421 | return (1); 422 | if ((rl.rlim_cur != RLIM_INFINITY) && 423 | ((uint64_t)rl.rlim_cur < memrlimit)) 424 | memrlimit = rl.rlim_cur; 425 | #endif 426 | 427 | #ifdef RLIMIT_DATA 428 | /* ... RLIMIT_DATA... */ 429 | if (getrlimit(RLIMIT_DATA, &rl)) 430 | return (1); 431 | if ((rl.rlim_cur != RLIM_INFINITY) && 432 | ((uint64_t)rl.rlim_cur < memrlimit)) 433 | memrlimit = rl.rlim_cur; 434 | #endif 435 | 436 | /* ... and RLIMIT_RSS. */ 437 | #ifdef RLIMIT_RSS 438 | if (getrlimit(RLIMIT_RSS, &rl)) 439 | return (1); 440 | if ((rl.rlim_cur != RLIM_INFINITY) && 441 | ((uint64_t)rl.rlim_cur < memrlimit)) 442 | memrlimit = rl.rlim_cur; 443 | #endif 444 | 445 | /* Return the value, but clamp to SIZE_MAX if necessary. */ 446 | #if UINT64_MAX > SIZE_MAX 447 | if (memrlimit > SIZE_MAX) 448 | *memlimit = SIZE_MAX; 449 | else 450 | *memlimit = memrlimit; 451 | #else 452 | *memlimit = memrlimit; 453 | #endif 454 | 455 | /* Success! */ 456 | return (0); 457 | } 458 | #endif 459 | 460 | #ifdef _SC_PHYS_PAGES 461 | 462 | /* Some systems define _SC_PAGESIZE instead of _SC_PAGE_SIZE. */ 463 | #ifndef _SC_PAGE_SIZE 464 | #define _SC_PAGE_SIZE _SC_PAGESIZE 465 | #endif 466 | 467 | static int 468 | memlimit_sysconf(size_t * memlimit) 469 | { 470 | long pagesize; 471 | long physpages; 472 | uint64_t totalmem; 473 | 474 | /* Set errno to 0 in order to distinguish "no limit" from "error". */ 475 | errno = 0; 476 | 477 | /* Read the two limits. */ 478 | if (((pagesize = sysconf(_SC_PAGE_SIZE)) == -1) || 479 | ((physpages = sysconf(_SC_PHYS_PAGES)) == -1)) { 480 | /* Did an error occur? */ 481 | if (errno != 0) 482 | return (1); 483 | 484 | /* If not, there is no limit. */ 485 | totalmem = (uint64_t)(-1); 486 | } else { 487 | /* Compute the limit. */ 488 | totalmem = (uint64_t)(pagesize) * (uint64_t)(physpages); 489 | } 490 | 491 | /* Return the value, but clamp to SIZE_MAX if necessary. */ 492 | #if UINT64_MAX > SIZE_MAX 493 | if (totalmem > SIZE_MAX) 494 | *memlimit = SIZE_MAX; 495 | else 496 | *memlimit = totalmem; 497 | #else 498 | *memlimit = totalmem; 499 | #endif 500 | 501 | /* Success! */ 502 | return (0); 503 | } 504 | #endif 505 | 506 | int 507 | memtouse(size_t maxmem, double maxmemfrac, size_t * memlimit) 508 | { 509 | size_t sysctl_memlimit, sysinfo_memlimit, rlimit_memlimit; 510 | size_t sysconf_memlimit; 511 | size_t memlimit_min; 512 | size_t memavail; 513 | 514 | /* Get memory limits. */ 515 | #ifdef HAVE_SYSCTL_HW_USERMEM 516 | if (memlimit_sysctl_hw_usermem(&sysctl_memlimit)) 517 | return (1); 518 | #else 519 | sysctl_memlimit = (size_t)(-1); 520 | #endif 521 | #ifdef HAVE_SYSINFO 522 | if (memlimit_sysinfo(&sysinfo_memlimit)) 523 | return (1); 524 | #else 525 | sysinfo_memlimit = (size_t)(-1); 526 | #endif 527 | if (memlimit_rlimit(&rlimit_memlimit)) 528 | return (1); 529 | #ifdef _SC_PHYS_PAGES 530 | if (memlimit_sysconf(&sysconf_memlimit)) 531 | return (1); 532 | #else 533 | sysconf_memlimit = (size_t)(-1); 534 | #endif 535 | 536 | #ifdef DEBUG 537 | fprintf(stderr, "Memory limits are %zu %zu %zu %zu\n", 538 | sysctl_memlimit, sysinfo_memlimit, rlimit_memlimit, 539 | sysconf_memlimit); 540 | #endif 541 | 542 | /* Find the smallest of them. */ 543 | memlimit_min = (size_t)(-1); 544 | if (memlimit_min > sysctl_memlimit) 545 | memlimit_min = sysctl_memlimit; 546 | if (memlimit_min > sysinfo_memlimit) 547 | memlimit_min = sysinfo_memlimit; 548 | if (memlimit_min > rlimit_memlimit) 549 | memlimit_min = rlimit_memlimit; 550 | if (memlimit_min > sysconf_memlimit) 551 | memlimit_min = sysconf_memlimit; 552 | 553 | /* Only use the specified fraction of the available memory. */ 554 | if ((maxmemfrac > 0.5) || (maxmemfrac == 0.0)) 555 | maxmemfrac = 0.5; 556 | memavail = maxmemfrac * memlimit_min; 557 | 558 | /* Don't use more than the specified maximum. */ 559 | if ((maxmem > 0) && (memavail > maxmem)) 560 | memavail = maxmem; 561 | 562 | /* But always allow at least 1 MiB. */ 563 | if (memavail < 1048576) 564 | memavail = 1048576; 565 | 566 | #ifdef DEBUG 567 | fprintf(stderr, "Allowing up to %zu memory to be used\n", memavail); 568 | #endif 569 | 570 | /* Return limit via the provided pointer. */ 571 | *memlimit = memavail; 572 | return (0); 573 | } 574 | --------------------------------------------------------------------------------