├── CHANGES ├── COMPARISON ├── Makefile ├── PARAMETERS ├── PERFORMANCE ├── PHC-TEST-OK-SHA256 ├── README ├── TESTS-OK ├── initrom.c ├── insecure_memzero.c ├── insecure_memzero.h ├── phc.c ├── sha256.c ├── sha256.h ├── sysendian.h ├── tests.c ├── userom.c ├── yescrypt-common.c ├── yescrypt-opt.c ├── yescrypt-platform.c ├── yescrypt-ref.c └── yescrypt.h /CHANGES: -------------------------------------------------------------------------------- 1 | Changes made since 1.1.0 (2019/06/30). 2 | 3 | Use AVX512VL XOP-like bit rotates for faster Salsa20 on supporting CPUs. 4 | 5 | Implemented a little-known SHA-2 Maj() optimization proposed by Wei Dai. 6 | 7 | Minor code cleanups and documentation updates. 8 | 9 | 10 | Changes made between 1.0.3 (2018/06/13) and 1.1.0 (2019/06/30). 11 | 12 | Merged yescrypt-opt.c and yescrypt-simd.c into one source file, which is 13 | a closer match to -simd but is called -opt (and -simd is now gone). 14 | With this change, performance of SIMD builds should be almost unchanged, 15 | while scalar builds should be faster than before on register-rich 64-bit 16 | architectures but may be slower than before on register-starved 32-bit 17 | architectures (this shortcoming may be addressed later). This also 18 | happens to make SSE prefetch available even in otherwise-scalar builds 19 | and it paves the way for adding SIMD support on big-endian architectures 20 | (previously, -simd assumed little-endian). 21 | 22 | Added x32 ABI support (x86-64 with 32-bit pointers). 23 | 24 | 25 | Changes made between 1.0.2 (2018/06/06) and 1.0.3 (2018/06/13). 26 | 27 | In SMix1, optimized out the indexing of V for the sequential writes. 28 | 29 | 30 | Changes made between 1.0.1 (2018/04/22) and 1.0.2 (2018/06/06). 31 | 32 | Don't use MAP_POPULATE anymore because new multi-threaded benchmarks on 33 | RHEL6'ish and RHEL7'ish systems revealed that it sometimes has adverse 34 | effect far in excess of its occasional positive effect. 35 | 36 | In the SIMD code, we now reuse the same buffer for BlockMix_pwxform's 37 | input and output in SMix2. This might slightly improve cache hit rate 38 | and thus performance. 39 | 40 | Also in the SIMD code, a compiler memory barrier has been added between 41 | sub-blocks to ensure that none of the writes into what was S2 during 42 | processing of the previous sub-block are postponed until after a read 43 | from S0 or S1 in the inline asm code for the current sub-block. This 44 | potential problem was never observed so far due to other constraints 45 | that we have, but strictly speaking those constraints were insufficient 46 | to guarantee it couldn't occur. 47 | 48 | 49 | Changes made between 1.0.0 (2018/03/09) and 1.0.1 (2018/04/22). 50 | 51 | The included documentation has been improved, most notably adding new 52 | text files PARAMETERS (guidelines on parameter selection, and currently 53 | recommended parameter sets by use case) and COMPARISON (comparison to 54 | scrypt and Argon2). 55 | 56 | Code cleanups have been made, including removal of AVX2 support, which 57 | was deliberately temporarily preserved for the 1.0.0 release, but which 58 | almost always hurt performance with currently recommended low-level 59 | yescrypt parameters on Intel & AMD CPUs tested so far. (The low-level 60 | parameters are chosen with consideration for relative performance of 61 | defensive vs. offensive implementations on different hardware, and not 62 | only for seemingly best performance on CPUs. It is possible to change 63 | them such that AVX2 would be worthwhile, and this might happen in the 64 | future, but currently this wouldn't be obviously beneficial overall.) 65 | 66 | 67 | Changes made between 0.8.1 (2015/10/25) and 1.0.0 (2018/03/09). 68 | 69 | Hash string encoding has been finalized under the "$y$" prefix for both 70 | native yescrypt and classic scrypt hashes, using a new variable-length 71 | and extremely compact encoding of (ye)scrypt's many parameters. (Also 72 | still recognized under the "$7$" prefix is the previously used encoding 73 | for classic scrypt hashes, which is fixed-length and not so compact.) 74 | 75 | Optional format-preserving salt and hash (re-)encryption has been added, 76 | using the Luby-Rackoff construction with SHA-256 as the PRF. 77 | 78 | Support for hash upgrades has been temporarily excluded to allow for its 79 | finalization at a later time and based on actual needs (e.g., will 3x 80 | ROM size upgrades be in demand now that Intel went from 4 to 6 memory 81 | channels in their server CPUs, bringing a factor of 3 into RAM sizes?) 82 | 83 | ROM initialization has been sped up through a new simplified algorithm. 84 | 85 | ROM tags (magic constant values) and digests (values that depend on the 86 | entire computation of the ROM contents) have been added to the last 87 | block of ROM. (The placement of these tags/digests is such that nested 88 | ROMs are possible, to allow for ROM size upgrades later.) 89 | 90 | The last block of ROM is now checked for the tag and is always used for 91 | hash computation before a secret-dependent memory access is first made. 92 | This ensures that hashes won't be computed with a partially initialized 93 | ROM or with one initialized using different machine word endianness, and 94 | that they will be consistently miscomputed if the ROM digest is other 95 | than what the caller expected. This in turn helps early detection of 96 | problems with ROM initialization even if the calling application fails 97 | to check for them. This also helps mitigate cache-timing attacks when 98 | the attacker doesn't know the contents of the last block of ROM. 99 | 100 | Many implementation changes have been made, such as for performance, 101 | portability, security (intentional reuse and thus rewrite of memory 102 | where practical and optional zeroization elsewhere), and coding style. 103 | This includes addition of optional SSE2 inline assembly code (a macro 104 | with 8 instructions) to yescrypt-simd.c, which tends to slightly 105 | outperform compiler-generated code, including AVX(2)-enabled code, for 106 | yescrypt's currently recommended settings. This is no surprise since 107 | yescrypt was designed to fit the 64-bit mode extended SSE2 instruction 108 | set perfectly (including SSE2's lack of 3-register instructions), so for 109 | its optimal implementation AVX would merely result in extra instruction 110 | prefixes and not provide any benefit (except for the uses of Salsa20 111 | inherited from scrypt, but those are infrequent). 112 | 113 | The auxiliary files inherited from scrypt have been sync'ed with scrypt 114 | 1.2.1, and the implementation of PBKDF2 has been further optimized, 115 | especially for its use in (ye)scrypt where the "iteration count" is 1 116 | but the output size is relatively large. (The speedup is measurable at 117 | realistically low settings for yescrypt, such as at 2 MiB of memory.) 118 | 119 | The included tests have been revised and test vectors regenerated to 120 | account for the ROM initialization/use updates and hash (re-)encryption. 121 | 122 | The PHC test vectors have been compacted into a single SHA-256 hash of 123 | the expected output of phc.c, but have otherwise remained unchanged as 124 | none of the incompatible changes have affected the subset of yescrypt 125 | exposed via the PHS() interface for the Password Hashing Competition. 126 | 127 | The specification document and extra programs that were included with 128 | the PHC submission and its updates are now excluded from this release. 129 | 130 | The rest of documentation files have been updated for the 1.0.0 release. 131 | 132 | 133 | Changes made between 0.7.1 (2015/01/31) and 0.8.1 (2015/10/25). 134 | 135 | pwxform became stateful, through writes to its S-boxes. This further 136 | discourages TMTO attacks on yescrypt as a whole, as well as on pwxform 137 | S-boxes separately. It also increases the total size of the S-boxes by 138 | a factor of 1.5 (8 KiB to 12 KiB by default) and it puts the previously 139 | mostly idle L1 cache write ports on CPUs to use. 140 | 141 | Salsa20/8 in BlockMix_pwxform has been replaced with Salsa20/2. 142 | 143 | An extra HMAC-SHA256 update of the password buffer (which is eventually 144 | passed into the final PBKDF2 invocation) is now performed right after 145 | the pwxform S-boxes initialization. 146 | 147 | Nloop_rw rounding has been adjusted to be the same as Nloop_all's. 148 | This avoids an unnecessary invocation of SMix2 with Nloop = 2, which 149 | would otherwise have occurred in some cases. 150 | 151 | t is now halved per hash upgrade (rather than reset to 0 right away on 152 | the very first upgrade, like it was in 0.7.1). 153 | 154 | Minor corrections and improvements to the specification and the code 155 | have been made. 156 | 157 | 158 | Changes made between 0.6.4 (2015/01/30) and 0.7.1 (2015/01/31). 159 | 160 | The YESCRYPT_PARALLEL_SMIX and YESCRYPT_PWXFORM flags have been removed, 161 | with the corresponding functionality enabled along with the YESCRYPT_RW 162 | flag. This change has simplified the SIMD implementation a little bit 163 | (eliminating specialized code for some flag combinations that are no 164 | longer possible), and it should help simplify documentation, analysis, 165 | testing, and benchmarking (fewer combinations of settings to test). 166 | 167 | Adjustments to pre- and post-hashing have been made to address subtle 168 | issues and non-intuitive behavior, as well as in some cases to reduce 169 | impact of garbage collector attacks. 170 | 171 | Support for hash upgrades has been added (the g parameter). 172 | 173 | Extra tests have been written and test vectors re-generated. 174 | 175 | 176 | Changes made between 0.5.2 (2014/03/31) and 0.6.4 (2015/01/30). 177 | 178 | Dropped support for ROM access frequency mask since it made little sense 179 | when supporting only one ROM at a time. (It'd make sense with two ROMs, 180 | for simultaneous use of a ROM-in-RAM and a ROM-on-SSD. With just one 181 | ROM, the mask could still be used for a ROM-on-SSD, but only in lieu of 182 | a ROM-in-RAM, which would arguably be unreasonable.) 183 | 184 | Simplified the API by having it accept NULL for the "shared" parameter 185 | to indicate no ROM in use. (Previously, a dummy "shared" structure had 186 | to be created.) 187 | 188 | Completed the specification of pwxform, BlockMix_pwxform, Salsa20 SIMD 189 | shuffling, and potential endianness conversion. (No change to these has 190 | been made - they have just been specified in the included document more 191 | completely.) 192 | 193 | Provided rationale for the default compile-time settings for pwxform. 194 | 195 | Revised the reference and optimized implementations' source code to more 196 | closely match the current specification document in terms of identifier 197 | names, compile-time constant expressions, source code comments, and in 198 | some cases the ordering of source code lines. None of these changes 199 | affect the computed hash values, hence the test vectors have remained 200 | the same. 201 | -------------------------------------------------------------------------------- /COMPARISON: -------------------------------------------------------------------------------- 1 | Comparison of yescrypt to scrypt and Argon2. 2 | 3 | yescrypt's advantages: 4 | 5 | + Greater resistance to offline attacks (increasing attacker's cost at 6 | same defender's cost) 7 | 8 | + yescrypt supports optional ROM for protection from use of botnet 9 | nodes (and other relatively small memory devices) 10 | 11 | + yescrypt has a dependency not only on RAM and maybe ROM, but 12 | also on fast on-die local memory (such as a CPU's L1 or L2 cache), 13 | which provides bcrypt-like anti-GPU properties even at very low 14 | per-hash RAM sizes (where scrypt and Argon2 are more likely to lose 15 | to bcrypt in terms of GPU attack speed) and even without ROM 16 | 17 | + yescrypt and scrypt currently have little low-level 18 | parallelism within processing of a block (yescrypt allows for 19 | tuning this later, scrypt does not), whereas Argon2 has a fixed and 20 | currently commonly excessive amount of such parallelism, which may 21 | be extracted to speed up e.g. GPU attacks through use of more 22 | computing resources per the same total memory size due to each hash 23 | computation's memory needs being split between 32 threads (yescrypt 24 | currently has four 16-byte lanes that can be processed in parallel 25 | within a 64-byte sub-block before running into a data dependency 26 | for the next sub-block, whereas Argon2 allows for parallel 27 | processing of eight 128-byte chunks within a 1 KiB block with only 28 | two synchronization points for the entire block, as well as of four 29 | 32-byte parts of the 128-byte chunks with only two more 30 | synchronization points for the entire 1 KiB block) 31 | 32 | + yescrypt uses computation latency hardening based on integer 33 | multiplication and local memory access speed, which ties its 34 | per-hash RAMs up for a guaranteed minimum amount of time regardless 35 | of possibly much higher memory bandwidth on the attacker's 36 | hardware, whereas Argon2 uses only the multiplications and performs 37 | 6 times fewer of those sequentially (96 sequential multiplications 38 | per 1 KiB for yescrypt vs. 16 per 1 KiB for Argon2, providing 39 | correspondingly different minimum time guarantees) and scrypt does 40 | not use this technique at all (but is no worse than Argon2 in this 41 | respect anyway due to having less low-level parallelism) 42 | 43 | + yescrypt and Argon2 are time-memory trade-off (TMTO) resistant 44 | (thus, computing them in less memory takes disproportionately 45 | longer), whereas scrypt is deliberately TMTO-friendly (and 46 | moreover, computing it in less memory takes up to 4x less than 47 | proportionately longer) 48 | 49 | + Extra optional built-in features 50 | 51 | + Hash encryption so that the hashes are not crackable without 52 | the key (to be stored separately) 53 | 54 | + Hash upgrade to higher settings without knowledge of password 55 | (temporarily removed from 1.0, to be re-added later) 56 | 57 | + SCRAM-like client-side computation of challenge responses 58 | (already part of the algorithm, not yet exposed via the API) 59 | 60 | + yescrypt's and Argon2's running time is tunable on top of 61 | memory usage and parallelism, unlike in scrypt's 62 | 63 | + Cryptographic security provided by NIST-approved primitives 64 | 65 | + (ye)scrypt's cryptographic security is provided by SHA-256, 66 | HMAC, and PBKDF2, which are NIST-approved and time-tested (the rest 67 | of yescrypt's processing, while most crucial for its offline attack 68 | resistance properties, provably does not affect its basic 69 | cryptographic hash properties), whereas Argon2 relies on the newer 70 | BLAKE2 (either choice is just fine for security, but use of 71 | approved algorithms may sometimes be required for compliance) 72 | 73 | + SHA-256, HMAC, PBKDF2, and scrypt are usable from the same codebase 74 | 75 | yescrypt's drawbacks: 76 | 77 | - Complex (higher risk of human error occurring and remaining 78 | unnoticed for long) 79 | 80 | - Cache-timing unsafe (like bcrypt, scrypt, and Argon2d, but 81 | unlike Argon2i) 82 | 83 | - Not the PHC winner (Argon2 is), but is merely a "special recognition" 84 | 85 | - Supported in fewer third-party projects (as of this writing, there's 86 | yescrypt support in libxcrypt, Linux-PAM, shadow, and mkpasswd) 87 | 88 | Other observations: 89 | 90 | * yescrypt's complexity is related to its current primary target use 91 | case (mass user authentication) and is relatively small compared to 92 | the total complexity of the authentication service, so the risk may 93 | be justified 94 | 95 | * Cache-timing safety is unimportant on dedicated servers, is 96 | mitigated for some use cases and threat models by proper use of 97 | salts, and is fully achieved in Argon2 only in its 2i flavor and only 98 | through reduction of resistance to the usual offline attacks compared 99 | to the 2d flavor 100 | 101 | * yescrypt's single-threaded memory filling speed on an otherwise 102 | idle machine and at our currently recommended settings is lower than 103 | Argon2's, but that's a result of our deliberate tuning (there's a 104 | knob to change that, but we don't recommend doing so) preventing 105 | yescrypt from bumping into memory access speed prematurely, and is 106 | irrelevant for determining server request rate capacity and maximum 107 | response latency where multiple instances or threads would be run 108 | (under that scenario, the algorithms deliver similar speeds) 109 | 110 | * yescrypt has been designed and currently configured to fit the 111 | SSE2 and NEON instruction sets and 128-bit SIMD perfectly, not 112 | benefiting from AVX's 3-register instructions (unlike classic scrypt, 113 | which doesn't fit SSE2 as perfectly and thus benefits from AVX and 114 | XOP) nor from AVX2's and AVX-512's wider SIMD (although it can be 115 | reconfigured for wider SIMD later), whereas Argon2 significantly 116 | benefits from those at least when running fewer threads or concurrent 117 | instances than are supported by the hardware (yet yescrypt's SSE2 118 | code is competitive with Argon2's AVX2 code under full server load) 119 | 120 | * yescrypt vs. Argon2 benchmarks are further complicated by these 121 | two schemes having different minimum amount of processing over memory 122 | (yescrypt's is 4/3 of Argon2's), and thus different average memory 123 | usage (5/8 of peak for yescrypt t=0 vs. 1/2 of peak for Argon2 t=1), 124 | which needs to be taken into account 125 | 126 | * scrypt benchmarks are also different in amount of processing over 127 | memory (twice Argon2's minimum) and average memory usage (3/4 of 128 | peak), but that's even further complicated by scrypt's 129 | TMTO-friendliness providing up to a 4x advantage to some attackers 130 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2013-2018 Alexander Peslyak 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted. 6 | # 7 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 8 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 10 | # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 11 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 12 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 13 | # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 14 | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 15 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 16 | # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 17 | # SUCH DAMAGE. 18 | 19 | CC = gcc 20 | LD = $(CC) 21 | RM = rm -f 22 | OMPFLAGS = -fopenmp 23 | OMPFLAGS_MAYBE = $(OMPFLAGS) 24 | #CFLAGS = -Wall -O2 -fomit-frame-pointer $(OMPFLAGS_MAYBE) -DSKIP_MEMZERO 25 | CFLAGS = -Wall -O2 -march=native -fomit-frame-pointer $(OMPFLAGS_MAYBE) -DSKIP_MEMZERO 26 | #CFLAGS = -Wall -O2 -funroll-loops -fomit-frame-pointer $(OMPFLAGS_MAYBE) -DSKIP_MEMZERO 27 | #CFLAGS = -Wall -O2 -march=native -funroll-loops -fomit-frame-pointer $(OMPFLAGS_MAYBE) -DSKIP_MEMZERO 28 | # -lrt is for userom's use of clock_gettime() 29 | LDFLAGS = -s -lrt $(OMPFLAGS_MAYBE) 30 | 31 | PROJ = tests phc-test initrom userom 32 | OBJS_CORE = yescrypt-opt.o 33 | OBJS_COMMON = yescrypt-common.o sha256.o insecure_memzero.o 34 | OBJS_TESTS = $(OBJS_CORE) $(OBJS_COMMON) tests.o 35 | OBJS_PHC = $(OBJS_CORE) $(OBJS_COMMON) phc-test.o 36 | OBJS_INITROM = $(OBJS_CORE) $(OBJS_COMMON) initrom.o 37 | OBJS_USEROM = $(OBJS_CORE) $(OBJS_COMMON) userom.o 38 | OBJS_RM = yescrypt-*.o 39 | 40 | all: $(PROJ) 41 | 42 | check: tests phc-test 43 | @echo 'Running main tests' 44 | @time ./tests | tee TESTS-OUT 45 | @diff -U0 TESTS-OK TESTS-OUT && echo PASSED || echo FAILED 46 | @if [ -e PHC-TEST-OK-SHA256 ]; then \ 47 | echo 'Running PHC tests'; \ 48 | time ./phc-test > PHC-TEST-OUT; \ 49 | sha256sum -c PHC-TEST-OK-SHA256; \ 50 | fi 51 | 52 | ref: 53 | $(MAKE) $(PROJ) OBJS_CORE=yescrypt-ref.o 54 | 55 | check-ref: 56 | $(MAKE) check OBJS_CORE=yescrypt-ref.o 57 | 58 | tests: $(OBJS_TESTS) 59 | $(LD) $(LDFLAGS) $(OBJS_TESTS) -o $@ 60 | 61 | phc-test.o: phc.c 62 | $(CC) -c $(CFLAGS) -DTEST phc.c -o $@ 63 | 64 | phc-test: $(OBJS_PHC) 65 | $(LD) $(LDFLAGS) $(OBJS_PHC) -o $@ 66 | 67 | initrom: $(OBJS_INITROM) 68 | $(LD) $(LDFLAGS) $(OBJS_INITROM) -o $@ 69 | 70 | userom: $(OBJS_USEROM) 71 | $(LD) $(LDFLAGS) $(OMPFLAGS) $(OBJS_USEROM) -o $@ 72 | 73 | userom.o: userom.c 74 | $(CC) -c $(CFLAGS) $(OMPFLAGS) $*.c 75 | 76 | .c.o: 77 | $(CC) -c $(CFLAGS) $*.c 78 | 79 | yescrypt-opt.o: yescrypt-platform.c 80 | 81 | clean: 82 | $(RM) $(PROJ) 83 | $(RM) $(OBJS_TESTS) $(OBJS_PHC) $(OBJS_INITROM) $(OBJS_USEROM) 84 | $(RM) $(OBJS_RM) 85 | $(RM) TESTS-OUT PHC-TEST-OUT 86 | -------------------------------------------------------------------------------- /PARAMETERS: -------------------------------------------------------------------------------- 1 | Optimal yescrypt configuration. 2 | 3 | yescrypt is very flexible, but configuring it optimally is complicated. 4 | Here are some guidelines to simplify near-optimal configuration. We 5 | start by listing the parameters and their typical values, and then give 6 | currently recommended parameter sets by use case. 7 | 8 | 9 | Parameters and their typical values. 10 | 11 | Set flags (yescrypt flavor) to YESCRYPT_DEFAULTS to use the currently 12 | recommended flavor. (Other flags values exist for compatibility and for 13 | specialized cases where you think you know what you're doing.) 14 | 15 | Set N (block count) based on target memory usage and running time, as 16 | well as on the value of r (block size in 128 byte units). N must be a 17 | power of two. 18 | 19 | Set r (block size) to 8 (so that N is in KiB, which is convenient) or to 20 | another small value (if more optimal or for fine-tuning of the total 21 | size and/or running time). Reasonable values for r are from 8 to 96. 22 | 23 | Set p (parallelism) to 1 meaning no thread-level parallelism within one 24 | computation of yescrypt. (Use of thread-level parallelism within 25 | yescrypt makes sense for ROM initialization and for key derivation at 26 | high memory usage, but usually not for password hashing where 27 | parallelism is available through concurrent authentication attempts. 28 | Don't use p > 1 unnecessarily.) 29 | 30 | Set t (time) to 0 to use the optimal running time for a given memory 31 | usage. This will allow you to maximize the memory usage (the value of 32 | N*r) while staying within your running time constraints. (Non-zero t 33 | makes sense in specialized cases where you can't afford higher memory 34 | usage but can afford more time.) 35 | 36 | Set g (upgrades) to 0 because there have been no hash upgrades yet. 37 | 38 | Set NROM (block count of ROM) to 0 unless you use a ROM (see below). 39 | NROM must be a power of two. 40 | 41 | 42 | Password hashing for user authentication, no ROM. 43 | 44 | Small and fast (memory usage 2 MiB, performance like bcrypt cost 2^5 - 45 | latency 2-3 ms and throughput 10,000+ per second on a 16-core server): 46 | 47 | flags = YESCRYPT_DEFAULTS, N = 2048, r = 8, p = 1, t = 0, g = 0, NROM = 0 48 | 49 | Large and slow (memory usage 16 MiB, performance like bcrypt cost 2^8 - 50 | latency 10-30 ms and throughput 1000+ per second on a 16-core server): 51 | 52 | flags = YESCRYPT_DEFAULTS, N = 4096, r = 32, p = 1, t = 0, g = 0, NROM = 0 53 | 54 | Of course, even heavier and slower settings are possible, if affordable. 55 | Simply double the value of N as many times as needed. Since N must be a 56 | power of two, you may use r (in the range of 8 to 32) or/and t (in the 57 | range of 0 to 2) for fine-tuning the running time, but first bring N to 58 | the maximum you can afford. If this feels too complicated, just use one 59 | of the two parameter sets given above (preferably the second) as-is. 60 | 61 | 62 | Password hashing for user authentication, with ROM. 63 | 64 | It's similar to the above, except that you need to adjust r, set NROM, 65 | and initialize the ROM. 66 | 67 | First decide on a ROM size, such as making it a large portion of your 68 | dedicated authentication servers' RAM sizes. Since NROM (block count) 69 | must be a power of two, you might need to choose r (block size) based on 70 | how your desired ROM size corresponds to a power of two. Also tuning 71 | for performance on current hardware, you'll likely end up with r in the 72 | range from slightly below 16 to 32. For example, to use 15/16 of a 73 | server's 256 GiB RAM as ROM (thus, making it 240 GiB), you could use 74 | r=15 or r=30. To use 23/24 of a server's 384 GiB RAM as ROM (thus, 75 | making it 368 GiB), you'd use r=23. Then set NROM to your desired ROM 76 | size in KiB divided by 128*r. Note that these examples might (or might 77 | not) be too extreme, leaving little memory for the rest of the system. 78 | You could as well opt for 7/8 with r=14 or 11/12 with r=11 or r=22. 79 | 80 | Note that higher r may make placing of ROM in e.g. NVMe flash memory 81 | instead of in RAM more reasonable (or less unreasonable) than it would 82 | have been with a lower r. If this is a concern as it relates to 83 | possible attacks and you do not intend to ever do it defensively, you 84 | might want to keep r lower (e.g., prefer r=15 over r=30 in the example 85 | above, even if 30 performs slightly faster). 86 | 87 | Your adjustments to r, if you deviate from powers of two, will also 88 | result in weirder memory usage per hash. Like 1.75 MiB at r=14 instead 89 | of 2 MiB at r=8 that you would have used without a ROM. That's OK. 90 | 91 | For ROM initialization, which you do with yescrypt_init_shared(), use 92 | the same r and NROM that you'd later use for password hashing, choose p 93 | based on your servers' physical and/or logical CPU count (maybe 94 | considering eventual upgrades as you won't be able to change this later, 95 | but without going unnecessarily high - e.g., p=28, p=56, or p=112 make 96 | sense on servers that currently have 28 physical / 56 logical CPUs), and 97 | set the rest of the parameters to: 98 | 99 | flags = YESCRYPT_DEFAULTS, N = 0, t = 0, g = 0 100 | 101 | N is set to 0 because it isn't relevant during ROM initialization (you 102 | can use different values of N for hashing passwords with the same ROM). 103 | 104 | To keep the ROM in e.g. SysV shared memory and reuse it across your 105 | authentication service restarts, you'd need to allocate the memory and 106 | set the flags to "YESCRYPT_DEFAULTS | YESCRYPT_SHARED_PREALLOCATED". 107 | 108 | For actual password hashing, you'd use your chosen values for N, r, 109 | NROM, and set the rest of the parameters to: 110 | 111 | flags = YESCRYPT_DEFAULTS, p = 1, t = 0, g = 0 112 | 113 | Note that although you'd use a large p for ROM initialization, you 114 | should use p=1 for actual password hashing like you would without a ROM. 115 | 116 | Do not forget to pass the ROM into the actual password hashing (and keep 117 | r and NROM set accordingly). 118 | 119 | Since N must be a power of two and r is dependent on ROM size, you may 120 | use t (in the range of 0 to 2) for fine-tuning the running time, but 121 | first bring N to the maximum you can afford. 122 | 123 | If this feels too complicated, or even if it doesn't, please consider 124 | engaging Openwall for your yescrypt deployment. We'd be happy to help. 125 | 126 | 127 | Password-based key derivation. 128 | 129 | (Or rather passphrase-based.) 130 | 131 | Use settings similar to those for password hashing without a ROM, but 132 | adjusted for higher memory usage and running time, and optionally with 133 | thread-level parallelism. 134 | 135 | Small and fast (memory usage 128 MiB, running time under 100 ms on a 136 | fast desktop): 137 | 138 | flags = YESCRYPT_DEFAULTS, N = 32768, r = 32, p = 1, t = 0, g = 0, NROM = 0 139 | 140 | Large and fast (memory usage 1 GiB, running time under 200 ms on a fast 141 | quad-core desktop not including memory allocation overhead, under 250 ms 142 | with the overhead included), but requires build with OpenMP support (or 143 | otherwise will run as slow as yet be weaker than its p=1 alternative): 144 | 145 | flags = YESCRYPT_DEFAULTS, N = 262144, r = 32, p = 4, t = 0, g = 0, NROM = 0 146 | 147 | Large and slower (memory usage 1 GiB, running time under 300 ms on a 148 | fast quad-core desktop not including memory allocation overhead, under 149 | 350 ms with the overhead included), also requires build with OpenMP 150 | support (or otherwise will run slower than the p=1 alternative below): 151 | 152 | flags = YESCRYPT_DEFAULTS, N = 262144, r = 32, p = 4, t = 2, g = 0, NROM = 0 153 | 154 | Large and slow (memory usage 1 GiB, running time under 600 ms on a fast 155 | desktop not including memory allocation overhead, under 650 ms with the 156 | overhead included): 157 | 158 | flags = YESCRYPT_DEFAULTS, N = 262144, r = 32, p = 1, t = 0, g = 0, NROM = 0 159 | 160 | Just like with password hashing, even heavier and slower settings are 161 | possible, if affordable, and you achieve them by adjusting N, r, t in 162 | the same way and in the same preferred ranges (please see the section on 163 | password hashing without a ROM, above). Unlike with password hashing, 164 | it makes some sense to go above t=2 if you expect that your users might 165 | not be able to afford more memory but can afford more time. However, 166 | increasing the memory usage provides better protection, and we don't 167 | recommend forcing your users to wait for more than 1 second as they 168 | could as well type more characters in that time. If this feels too 169 | complicated, just use one of the above parameter sets as-is. 170 | 171 | 172 | Amortization of memory allocation overhead. 173 | 174 | It takes a significant fraction of yescrypt's total running time to 175 | allocate memory from the operating system, especially considering that 176 | the kernel zeroizes the memory before handing it over to your program. 177 | 178 | Unless you naturally need to compute yescrypt just once per process, you 179 | may achieve greater efficiency by fully using advanced yescrypt APIs 180 | that let you preserve and reuse the memory allocation across yescrypt 181 | invocations. This is done by reusing the structure pointed to by the 182 | "yescrypt_local_t *local" argument of yescrypt_r() or yescrypt_kdf() 183 | without calling yescrypt_free_local() inbetween the repeated invocations 184 | of yescrypt. 185 | 186 | 187 | YESCRYPT_DEFAULTS macro. 188 | 189 | Please note that the value of the YESCRYPT_DEFAULTS macro might change 190 | later, so if you use the macro like it's recommended here then for 191 | results reproducible across versions you might need to store its value 192 | somewhere along with the hashes or the encrypted data. 193 | 194 | If you use yescrypt's standard hash string encoding, then yescrypt 195 | already encodes and decodes this value for you, so you don't need to 196 | worry about this. 197 | -------------------------------------------------------------------------------- /PERFORMANCE: -------------------------------------------------------------------------------- 1 | Although yescrypt is usable for a variety of purposes (password hashing, 2 | KDF, PoW) and is extremely scalable (from 1 CPU core to many, from 3 | kilobytes to terabytes and beyond) while achieving good security 4 | properties across this whole range of use cases and settings, at this 5 | time we're primarily targeting the mass user authentication use case. 6 | Hence, this is what the setup and benchmarks shown in here focus on. 7 | 8 | The test system is a server (kindly provided by Packet.net) with dual 9 | Xeon Gold 5120 CPUs (2.2 GHz, turbo to up to 3.2 GHz) and 384 GiB RAM 10 | (12x DDR4-2400 ECC Reg). These CPUs have 14 cores and 6 memory channels 11 | each, for a total of 28 physical cores, 56 logical CPUs (HT is enabled), 12 | and 12 memory channels. The OS is Ubuntu 17.10 with kernel 13 | "4.13.0-25-generic #29-Ubuntu SMP Mon Jan 8 21:14:41 UTC 2018 x86_64" 14 | and compiler "gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0". 15 | 16 | First, we need to configure the Linux system, as root. Grant our user 17 | account's group the privilege to access "huge pages" (2 MiB or 1 GiB as 18 | opposed to x86's default 4 KiB pages): 19 | 20 | # sysctl -w vm.hugetlb_shm_group=1000 21 | 22 | (You may need to replace the "1000" with your user account's actual 23 | group id.) 24 | 25 | Disable swap, so that it doesn't get in the way: 26 | 27 | # swapoff -a 28 | 29 | Let processes allocate shared memory segments of up to 368 GiB each, and 30 | up to 369 GiB total for the system: 31 | 32 | # sysctl -w kernel.shmmax=395136991232 33 | # sysctl -w kernel.shmall=396210733056 34 | 35 | (The allowance for an extra gigabyte is in case any processes unrelated 36 | to ours make use of SysV shared memory as well.) 37 | 38 | Preallocate the 368 GiB and 2 GiB more (to be potentially used for 39 | threads' "RAM" lookup tables), thus 370 GiB total, into huge pages (this 40 | will only work when existing memory allocations aren't too fragmented 41 | yet, so is normally to be performed right upon system bootup): 42 | 43 | # sysctl -w vm.nr_hugepages=189440 44 | 45 | Check that the preallocation has succeeded by examining /proc/meminfo: 46 | 47 | # grep ^Huge /proc/meminfo 48 | HugePages_Total: 189440 49 | HugePages_Free: 189440 50 | 51 | (If the memory were too fragmented, this would show lower numbers, which 52 | would be problematic - worse than no use of huge pages at all.) 53 | 54 | This is quite extreme. Although it sort of leaves 14 GiB free (as the 55 | difference between 370 GiB and the physical RAM of 384 GiB), in practice 56 | on our test system only less than 5 GiB remains allocatable by user 57 | processes after this point. For actual use, you might consider using a 58 | slightly lower fraction (than 23/24 that we're targeting here) of total 59 | memory for yescrypt ROM, or/and not pre-allocating any huge pages for 60 | the RAMs (especially if they won't be used that way anyway, which 61 | depends on the HUGEPAGE_THRESHOLD setting in yescrypt-platform.c - 62 | currently at 32 MiB). 63 | 64 | Now initialization of the ROM is possible, and we can work as non-root 65 | from this point on: 66 | 67 | $ GOMP_CPU_AFFINITY=0-55 time ./initrom 368 1 68 | r=23 N=2^9 NROM=2^27 69 | Will use 385875968.00 KiB ROM 70 | 1472.00 KiB RAM 71 | Initializing ROM ... DONE (98764b03) 72 | '$y$j6K5O$LdJMENpBABJJ3hIHjB1Bi.$VtHhEYlX3mDbxmXUUYt9Xldf.2R5/G0E/tMioNUQ/F8' 73 | 1058.64user 163.70system 0:22.04elapsed 5544%CPU (0avgtext+0avgdata 4692maxresident)k 74 | 0inputs+0outputs (0major+193094minor)pagefaults 0swaps 75 | 76 | It took 22 seconds to initialize our 368 GiB ROM, and now we may hash 77 | passwords from another process (this may be the authentication service): 78 | 79 | $ GOMP_CPU_AFFINITY=0-55 ./userom 368 1 80 | r=23 N=2^9 NROM=2^27 81 | Will use 385875968.00 KiB ROM 82 | 1472.00 KiB RAM 83 | Plaintext: '$y$j6K5O$LdJMENpBABJJ3hIHjB1Bi.$VtHhEYlX3mDbxmXUUYt9Xldf.2R5/G0E/tMioNUQ/F8' 84 | Encrypted: '$y$j6K5O$LdJMENpBABJJ3hIHjB1Bi.$LZropFwwbIVeo/8DfHbxg6VhFLkUqdvdNy7L.T8tud.' 85 | Benchmarking 1 thread ... 86 | 809 c/s real, 812 c/s virtual (2047 hashes in 2.53 seconds) 87 | Benchmarking 56 threads ... 88 | 21307 c/s real, 384 c/s virtual (114632 hashes in 5.38 seconds) 89 | min 1.393 ms, avg 2.591 ms, max 3.628 ms 90 | 91 | $ GOMP_CPU_AFFINITY=0-55 ./userom 368 2 92 | r=23 N=2^10 NROM=2^27 93 | Will use 385875968.00 KiB ROM 94 | 2944.00 KiB RAM 95 | Plaintext: '$y$j7K5O$LdJMENpBABJJ3hIHjB1Bi.$ljg0jm5/lpMa98qlF1GeAI9YkqWXSA4KVTGxidC6Gy0' 96 | Encrypted: '$y$j7K5O$LdJMENpBABJJ3hIHjB1Bi.$7X1fd6TFYK5VQOH.7M2dRJMxvFTZbv5d1i7.GwQ/7YC' 97 | Benchmarking 1 thread ... 98 | 419 c/s real, 420 c/s virtual (1023 hashes in 2.44 seconds) 99 | Benchmarking 56 threads ... 100 | 10248 c/s real, 184 c/s virtual (57288 hashes in 5.59 seconds) 101 | min 2.571 ms, avg 5.413 ms, max 6.704 ms 102 | 103 | $ GOMP_CPU_AFFINITY=0-55 ./userom 368 23 104 | r=23 N=2^13 NROM=2^27 105 | Will use 385875968.00 KiB ROM 106 | 23552.00 KiB RAM 107 | Plaintext: '$y$jAK5O$LdJMENpBABJJ3hIHjB1Bi.$UL29LYGiz.rXa6c620meFuqT3IiZmBO0BlW6HenRmA4' 108 | Encrypted: '$y$jAK5O$LdJMENpBABJJ3hIHjB1Bi.$U15LiKcR4vHbUmCbt7SUllXp/jUyNXYOC1I.426Vk80' 109 | Benchmarking 1 thread ... 110 | 50 c/s real, 50 c/s virtual (127 hashes in 2.52 seconds) 111 | Benchmarking 56 threads ... 112 | 1201 c/s real, 21 c/s virtual (7112 hashes in 5.92 seconds) 113 | min 32.444 ms, avg 46.362 ms, max 48.067 ms 114 | 115 | While using the ROM, we're able to compute over 21k, over 10k, or around 116 | 1200 password hashes per second with per-thread RAM sizes of 1.4375 MiB, 117 | 2.875 MiB, or 23 MiB, respectively. 118 | 119 | We can also reasonably use yescrypt without a ROM: 120 | 121 | $ GOMP_CPU_AFFINITY=0-55 ./userom 0 2 122 | r=16 N=2^10 NROM=2^0 123 | Will use 0.00 KiB ROM 124 | 2048.00 KiB RAM 125 | Plaintext: '$y$j7D$LdJMENpBABJJ3hIHjB1Bi.$MpcIFGNF/2yn.6pugGKCS3k6Js5sbJ7j3qLBBqKLUk4' 126 | Encrypted: '$y$j7D$LdJMENpBABJJ3hIHjB1Bi.$7yuShztNep5CDrsQE9Ms9DkH1zqJzTy8wRiSHozJy.9' 127 | Benchmarking 1 thread ... 128 | 828 c/s real, 828 c/s virtual (2047 hashes in 2.47 seconds) 129 | Benchmarking 56 threads ... 130 | 21710 c/s real, 388 c/s virtual (114632 hashes in 5.28 seconds) 131 | min 1.679 ms, avg 2.571 ms, max 3.591 ms 132 | 133 | $ GOMP_CPU_AFFINITY=0-55 ./userom 0 4 134 | r=16 N=2^11 NROM=2^0 135 | Will use 0.00 KiB ROM 136 | 4096.00 KiB RAM 137 | Plaintext: '$y$j8D$LdJMENpBABJJ3hIHjB1Bi.$dT8UO1PVT6lpQcAuWsreFpgdw9TeYdEkqsCp5syNoL9' 138 | Encrypted: '$y$j8D$LdJMENpBABJJ3hIHjB1Bi.$evEI7SjEM6GKYxcIaNYmanAesDLMRezuOfT4V01aj33' 139 | Benchmarking 1 thread ... 140 | 417 c/s real, 417 c/s virtual (1023 hashes in 2.45 seconds) 141 | Benchmarking 56 threads ... 142 | 10434 c/s real, 186 c/s virtual (57288 hashes in 5.49 seconds) 143 | min 3.120 ms, avg 5.339 ms, max 6.878 ms 144 | 145 | $ GOMP_CPU_AFFINITY=0-55 ./userom 0 16 146 | r=16 N=2^13 NROM=2^0 147 | Will use 0.00 KiB ROM 148 | 16384.00 KiB RAM 149 | Plaintext: '$y$jAD$LdJMENpBABJJ3hIHjB1Bi.$Cap65IlIDN8g9Lh0aVhLLWORQhpwxvh0rhkIB6OOpqC' 150 | Encrypted: '$y$jAD$LdJMENpBABJJ3hIHjB1Bi.$d5Qoew0sKNt63xBRsAxNDhGV52p1jHAFN1/fglibMbA' 151 | Benchmarking 1 thread ... 152 | 100 c/s real, 100 c/s virtual (255 hashes in 2.54 seconds) 153 | Benchmarking 56 threads ... 154 | 2314 c/s real, 41 c/s virtual (14280 hashes in 6.17 seconds) 155 | min 13.440 ms, avg 24.049 ms, max 25.467 ms 156 | 157 | $ GOMP_CPU_AFFINITY=0-55 ./userom 0 32 158 | r=16 N=2^14 NROM=2^0 159 | Will use 0.00 KiB ROM 160 | 32768.00 KiB RAM 161 | Plaintext: '$y$jBD$LdJMENpBABJJ3hIHjB1Bi.$zdJjnnDFSqeRbC8ZUQFZShGpP2gvFCGjAZ01h10dWa9' 162 | Encrypted: '$y$jBD$LdJMENpBABJJ3hIHjB1Bi.$U45EV25V/KtqyetJ7AHsJaeeNTJwvQ3hBG7lokzkyR6' 163 | Benchmarking 1 thread ... 164 | 48 c/s real, 49 c/s virtual (127 hashes in 2.61 seconds) 165 | Benchmarking 56 threads ... 166 | 1136 c/s real, 20 c/s virtual (7112 hashes in 6.26 seconds) 167 | min 27.844 ms, avg 48.837 ms, max 50.792 ms 168 | 169 | Slightly higher speeds are possible for 4 MiB and higher with larger 170 | yescrypt block size (r=32 instead of r=16, thus 4 KiB blocks instead of 171 | 2 KiB blocks benchmarked above). Here they are for 4 MiB, 16 MiB, and 172 | 32 MiB, respectively: 173 | 174 | 10589 c/s real, 189 c/s virtual (57288 hashes in 5.41 seconds) 175 | min 3.465 ms, avg 5.260 ms, max 6.705 ms 176 | 177 | 2462 c/s real, 44 c/s virtual (14280 hashes in 5.80 seconds) 178 | min 13.923 ms, avg 22.638 ms, max 24.042 ms 179 | 180 | 1221 c/s real, 21 c/s virtual (7112 hashes in 5.82 seconds) 181 | min 28.909 ms, avg 45.658 ms, max 47.265 ms 182 | 183 | Thus, when not using a ROM we're able to compute over 21k, over 10k, 184 | around 2400, or around 1200 hashes per second with per-thread RAM sizes 185 | of 2 MiB, 4 MiB, 16 MiB, or 32 MiB, respectively. 186 | 187 | The same might not hold on another machine. 188 | 189 | By the way, here's what our SysV shared memory segment looks like: 190 | 191 | $ ipcs -m 192 | 193 | ------ Shared Memory Segments -------- 194 | key shmid owner perms bytes nattch status 195 | [...] 196 | 0x7965730a 327683 user 640 395136991232 0 197 | 198 | The 395+ GB size corresponds to 368 GiB. 199 | 200 | To cleanup, let's remove the SysV shared memory segment holding the ROM: 201 | 202 | $ ipcrm -M 0x7965730a 203 | 204 | and free up the preallocated huge pages, as root: 205 | 206 | # sysctl -w vm.nr_hugepages=0 207 | -------------------------------------------------------------------------------- /PHC-TEST-OK-SHA256: -------------------------------------------------------------------------------- 1 | 05ad49b9d9fb9eb65df78c919c3a778b7952e2e63f2e8ddb6b2b3f4b645e3cd0 PHC-TEST-OUT 2 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | What is yescrypt? 2 | 3 | yescrypt is a password-based key derivation function (KDF) and password 4 | hashing scheme. It builds upon Colin Percival's scrypt. This 5 | implementation is able to compute native yescrypt hashes as well as 6 | classic scrypt. 7 | 8 | As of this writing, yescrypt is the default password hashing scheme on 9 | recent ALT Linux, Arch Linux, Debian 11+, Fedora 35+, Kali Linux 2021.1+, 10 | and Ubuntu 22.04+. It is also supported in Fedora 29+, RHEL 9+, and 11 | Ubuntu 20.04+, and is recommended for new passwords in Fedora CoreOS. 12 | 13 | 14 | Why yescrypt? 15 | 16 | Like it or not, password authentication remains relevant (including as 17 | one of several authentication factors), password hash database leaks 18 | happen, the leaks are not always detected and fully dealt with right 19 | away, and even once they are many users' same or similar passwords 20 | reused elsewhere remain exposed. To mitigate these risks (as well as 21 | those present in other scenarios where password-based key derivation or 22 | password hashing is relevant), computationally expensive (bcrypt, 23 | PBKDF2, etc.) and more recently also memory-hard (scrypt, Argon2, etc.) 24 | password hashing schemes have been introduced. Unfortunately, at high 25 | target throughput and/or low target latency their memory usage is 26 | unreasonably low, up to the point where they're not obviously better 27 | than the much older bcrypt (considering attackers with pre-existing 28 | hardware). This is a primary drawback that yescrypt addresses. 29 | 30 | Most notable for large-scale deployments is yescrypt's optional 31 | initialization and reuse of a large lookup table, typically occupying 32 | at least tens of gigabytes of RAM and essentially forming a 33 | site-specific ROM. This limits attackers' use of pre-existing hardware 34 | such as botnet nodes. 35 | 36 | yescrypt's other changes from scrypt additionally slow down GPUs and to 37 | a lesser extent FPGAs and ASICs even when its memory usage is low and 38 | even when there's no ROM, and provide extra knobs and built-in features. 39 | 40 | Technically, yescrypt is the most scalable password hashing scheme so 41 | far, providing near-optimal security from offline password cracking 42 | across the whole range from kilobytes to terabytes and beyond. However, 43 | the price for this is complexity, and we recognize that complexity is a 44 | major drawback of any software. Thus, at this time we focus on 45 | large-scale deployments, where the added complexity is relatively small 46 | compared to the total complexity of the authentication service setup. 47 | For smaller deployments, bcrypt with its simplicity and existing library 48 | support is a reasonable short-term choice (although we're making 49 | progress towards more efficient FPGA attacks on bcrypt under a separate 50 | project). We might introduce a cut-down yescrypt-lite later or/and 51 | yescrypt might become part of standard or popular libraries, making it 52 | more suitable for smaller deployments as well. 53 | 54 | 55 | Parameter selection. 56 | 57 | Please refer to PARAMETERS for guidelines on parameter selection and the 58 | currently recommended parameter sets by use case (password hashing with 59 | or without a ROM, and KDF). 60 | 61 | 62 | Performance. 63 | 64 | Please refer to PERFORMANCE for example setup and benchmarks relevant to 65 | the mass user authentication use case. 66 | 67 | The test system is a server (kindly provided by Packet.net) with dual 68 | Xeon Gold 5120 CPUs (2.2 GHz, turbo to up to 3.2 GHz) and 384 GiB RAM 69 | (12x DDR4-2400 ECC Reg). These CPUs have 14 cores and 6 memory channels 70 | each, for a total of 28 physical cores, 56 logical CPUs (HT is enabled), 71 | and 12 memory channels. 72 | 73 | Some highlights: initialization of a 368 GiB ROM takes 22 seconds (to 74 | be done on server bootup), and while using the ROM we're able to compute 75 | over 21k, over 10k, or around 1200 hashes per second with per-hash RAM 76 | usage of 1.4375 MiB, 2.875 MiB, or 23 MiB, respectively. 77 | 78 | When not using a ROM, we're able to compute over 21k, over 10k, or 79 | around 1200 hashes per second with per-hash RAM usage of 2 MiB, 4 MiB, 80 | or 32 MiB, respectively. 81 | 82 | 83 | Comparison to scrypt and Argon2. 84 | 85 | yescrypt's advantages: 86 | 87 | + Greater resistance to offline attacks 88 | + Extra optional built-in features 89 | + Cryptographic security provided by NIST-approved primitives 90 | + SHA-256, HMAC, PBKDF2, and scrypt are usable from the same codebase 91 | 92 | yescrypt's drawbacks: 93 | 94 | - Complex 95 | - Cache-timing unsafe (like scrypt and Argon2d, but unlike Argon2i) 96 | - Not the PHC winner (Argon2 is), but is merely a "special recognition" 97 | - Supported in fewer third-party projects 98 | 99 | Please refer to COMPARISON for a lot more detail and other observations. 100 | 101 | 102 | A note on cryptocurrencies. 103 | 104 | For historical reasons, multiple CPU mining focused cryptocurrencies use 105 | yescrypt 0.5'ish as their proof-of-work (PoW) scheme. We currently have 106 | a separate project for the PoW use case: yespower. Thus, rather than 107 | misuse yescrypt 1.0+ for PoW, those and other projects are advised to 108 | use yespower 1.0+ instead. The yespower homepage is: 109 | 110 | https://www.openwall.com/yespower/ 111 | 112 | 113 | How to test yescrypt for proper operation. 114 | 115 | On a Unix-like system, invoke "make check". This will build and run a 116 | program called "tests", and check its output against the supplied file 117 | TESTS-OK. It will also build a program called "phc-test", and if a file 118 | called PHC-TEST-OK-SHA256 is present will run that program and check its 119 | output against that file's contents. If everything matches, each of 120 | these two sets of tests prints one word "PASSED", so there will be two 121 | such lines among "make check" output, one of them being the final line 122 | of output. 123 | 124 | We do most of our testing on Linux systems with gcc. The supplied 125 | Makefile assumes that you use gcc. 126 | 127 | 128 | ROM in SysV shared memory demo and benchmark. 129 | 130 | Also included with this version of yescrypt are "initrom" and "userom" 131 | demo programs. They're built by simply typing "make". Please refer to 132 | PERFORMANCE for their usage. 133 | 134 | 135 | Alternate code versions and make targets. 136 | 137 | Two implementations of yescrypt are included: reference and optimized. 138 | By default, the optimized implementation is built. Internally, the 139 | optimized implementation uses conditional compilation to choose between 140 | usage of various SIMD instruction sets where supported and scalar code. 141 | 142 | The reference implementation is unoptimized and is very slow, but it has 143 | simpler and shorter source code. Its purpose is to provide a simple 144 | human- and machine-readable specification that implementations intended 145 | for actual use should be tested against. It is deliberately mostly not 146 | optimized, and it is not meant to be used in production. 147 | 148 | Similarly to "make check", there's "make check-ref" to build and test 149 | the reference implementation. There's also "make ref" to build the 150 | reference implementation and have the "initrom" and "userom" programs 151 | use it. 152 | 153 | "make clean" may need to be run between making different builds. 154 | 155 | 156 | Development status. 157 | 158 | This yescrypt distribution is a work-in-progress. Its interfaces other 159 | than crypto_scrypt() are subject to change in future revisions, however 160 | no incompatible changes to the yescrypt algorithm are expected. 161 | 162 | 163 | Credits. 164 | 165 | scrypt has been designed by Colin Percival. yescrypt has been designed 166 | by Solar Designer building upon scrypt. 167 | 168 | The following other people and projects have also indirectly helped make 169 | yescrypt what it is: 170 | 171 | - Bill Cox 172 | - Rich Felker 173 | - Anthony Ferrara 174 | - Christian Forler 175 | - Taylor Hornby 176 | - Dmitry Khovratovich 177 | - Samuel Neves 178 | - Marcos Simplicio 179 | - Ken T Takusagawa 180 | - Jakob Wenzel 181 | - Christian Winnerlein 182 | 183 | - DARPA Cyber Fast Track 184 | - Password Hashing Competition 185 | 186 | 187 | Contact info. 188 | 189 | First, please check the yescrypt homepage for new versions, etc.: 190 | 191 | https://www.openwall.com/yescrypt/ 192 | 193 | If you have anything valuable to add or a non-trivial question to ask, 194 | you may join and post to the yescrypt mailing list (referenced on the 195 | yescrypt homepage above) or contact the maintainer of yescrypt at: 196 | 197 | Solar Designer 198 | -------------------------------------------------------------------------------- /TESTS-OK: -------------------------------------------------------------------------------- 1 | scrypt("", "", 16, 1, 1) = 77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06 2 | scrypt("password", "NaCl", 1024, 8, 16) = fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe 7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62 2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40 3 | scrypt("pleaseletmein", "SodiumChloride", 16384, 8, 1) = 70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2 d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9 e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87 4 | scrypt("pleaseletmein", "SodiumChloride", 1048576, 8, 1) = 21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81 ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47 8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3 37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4 5 | yescrypt("", "", 0, 16, 1, 1, 0, 0) = 77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97 f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42 fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17 e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06 6 | yescrypt("", "", 0, 16, 1, 1, 0, 0) = 77 d6 57 62 38 65 7b 20 7 | yescrypt("", "", 0, 4, 1, 1, 0, 0) = ef ad 0c 23 31 4c b5 72 bc 3c fb 15 43 da 42 f8 a8 b0 73 00 4c 86 6b 64 ab 50 55 a4 f0 9f a5 f5 71 14 2e bf e7 e0 5a 3b 92 c4 32 f3 1d ea 95 ad 5f 9c 85 4b 64 56 46 2f 4b d0 f7 32 b7 cd c5 49 8 | yescrypt("", "", 1, 4, 1, 1, 0, 0) = 85 dd a4 8c 9e c9 de 2f 7f 1a e8 b4 df ed a5 1f 8b 6d 56 f3 08 1b e1 a7 c0 83 3b a2 71 9a 36 ab 02 88 5d ae 36 55 7d 34 26 86 b1 7b a7 5f 2c 21 77 92 de 09 70 ab 1d 07 a9 c7 50 93 6d 31 42 6f 9 | yescrypt("", "", 1, 4, 1, 1, 0, 0) = 85 dd a4 8c 9e c9 de 2f 10 | yescrypt("", "", 1, 4, 1, 1, 1, 0) = 4b aa 8c d8 60 8b a9 1f 3e 34 39 d9 ec 4f ae 8f 9f c0 92 d9 ca 22 b7 37 7e 31 ae 5b 9a d7 87 7c 11 68 69 11 62 dd 0e 5e f0 49 e5 70 65 0c be d4 38 4a d6 05 34 fb 0c be d1 9f f3 f0 33 c9 4b 0c 11 | yescrypt("", "", 1, 4, 1, 1, 2, 0) = e6 e8 bb a0 9b 64 12 ff b0 b3 cc 35 e3 7d 0b 78 2a 47 fb aa dc 57 a0 76 d7 c6 cc 2e 70 91 9a 1b 8d 47 38 c4 f8 33 55 69 07 42 d9 be d7 1c 3b 8f b0 d7 eb 08 6a b1 34 c5 e5 57 07 c2 c1 3c 75 ef 12 | yescrypt("", "", 1, 4, 1, 1, 3, 0) = ac d9 a4 20 1c f4 a4 76 ec f7 ba a6 11 3d 86 fb 65 cd 07 10 2b 40 04 e4 f9 d9 9c d3 42 55 a1 08 99 7d 70 ae 0a 64 bf 0a 4d 96 c1 73 ab f8 82 79 c1 a9 4a d9 bd f1 68 ed fb bd 90 f6 6e d5 c8 0d 13 | yescrypt("", "", 1, 4, 1, 1, 3, 0) = ac d9 a4 20 1c f4 a4 76 ec f7 ba a6 11 3d 86 fb 65 cd 07 10 2b 40 04 e4 f9 d9 9c d3 42 55 a1 08 99 14 | yescrypt("", "", 1, 4, 1, 1, 3, 0) = ac d9 a4 20 1c f4 a4 76 ec f7 ba a6 11 3d 86 fb 65 cd 07 10 2b 40 04 e4 f9 d9 9c d3 42 55 a1 08 15 | yescrypt("", "", 1, 4, 1, 1, 3, 0) = ac d9 a4 20 1c f4 a4 76 ec f7 ba a6 11 3d 86 fb 65 cd 07 10 2b 40 04 e4 f9 d9 9c d3 42 55 a1 16 | yescrypt("", "", 1, 4, 1, 1, 3, 0) = ac 17 | yescrypt("", "", 182, 4, 1, 1, 0, 0) = 0c d5 af 76 eb 24 1d f8 11 9a 9a 12 2a e3 69 20 bc c7 f4 14 b9 c0 d5 8f 45 00 80 60 da de 46 b0 c8 09 22 bd cc 16 a3 ab 5d 20 1d 4c 61 40 c6 71 be 1f 75 27 2c a9 04 73 9d 5a d1 ff 67 2b 0c 21 18 | yescrypt("", "", 182, 4, 1, 1, 0, 0) = 0c d5 af 76 19 | yescrypt("", "", 182, 4, 1, 1, 1, 0) = 23 b6 ad f0 b6 0c 9a 99 7f 58 58 3d 80 cd a4 8c 63 8c dc 2f 28 9e df 93 a7 08 07 72 5a 0d 35 c4 68 ca 36 2c 55 57 cc 04 b6 81 1e 2e 73 08 41 f5 26 d8 f4 f7 ac fb fa 9e 06 fe 1f 38 3a 71 15 5e 20 | yescrypt("", "", 182, 4, 1, 1, 1, 0) = 23 b6 ad f0 b6 0c 9a 99 7f 58 58 3d 80 cd a4 8c 63 8c dc 2f 28 9e df 93 a7 08 07 72 5a 0d 35 c4 68 21 | yescrypt("", "", 182, 4, 1, 1, 1, 0) = 23 b6 ad f0 b6 0c 9a 99 7f 58 58 3d 80 cd a4 8c 63 8c dc 2f 28 9e df 93 a7 08 07 72 5a 0d 35 c4 22 | yescrypt("", "", 182, 4, 1, 1, 1, 0) = 23 b6 ad f0 b6 0c 9a 99 7f 58 58 3d 80 cd a4 8c 63 8c dc 2f 28 9e df 93 a7 08 07 72 5a 0d 35 23 | yescrypt("", "", 182, 4, 1, 1, 1, 0) = 23 24 | yescrypt("p", "s", 182, 16, 8, 1, 10, 0) = e1 f9 81 73 3a 94 05 2f cd 7a cb 14 05 df 0b bd e8 e4 99 b6 a1 33 1b 77 59 09 b4 8c 2f 51 6c 40 dc c8 30 16 35 b7 23 7b 25 | yescrypt("p", "s", 1, 16, 8, 1, 10, 0) = 9e 7a 40 97 64 42 84 cf 3b 73 b6 04 50 ff 23 0c dc b6 b1 b1 9b 15 09 ee b4 82 f6 96 c4 f1 c7 05 c0 0f 74 02 16 18 3a 12 26 | yescrypt("p", "s", 182, 16, 8, 1, 0, 0) = c8 c7 ff 11 22 b0 b2 91 c3 f2 60 89 48 78 2c d6 89 cc 45 57 90 17 aa a5 ff 8b aa 74 a6 32 ec 99 c3 d6 69 30 fb 20 23 bb 27 | yescrypt("p", "s", 1, 16, 8, 1, 0, 0) = 9d d6 36 c2 d0 bb 92 34 52 86 ef da f8 a6 8c fc 1b 4f fd c4 b1 ad ac cc 7d 86 4b 9a 67 87 b8 5d 6a e0 f5 28 0d a8 88 9f 28 | yescrypt("p", "s", 182, 16, 8, 1, 0, 0) = c8 c7 ff 11 22 b0 b2 91 c3 f2 60 89 48 78 2c d6 89 cc 45 57 90 17 aa a5 ff 8b aa 74 a6 32 ec 99 29 | yescrypt("p", "s", 182, 16, 8, 1, 0, 0) = c8 c7 ff 11 22 b0 b2 91 30 | '$y$jD5.7$LdJMENpBABJJ3hIHjB1Bi.' 31 | Plaintext: '$y$jD5.7$LdJMENpBABJJ3hIHjB1Bi.$HboGM6qPrsK.StKYGt6KErmUYtioHreJd98oIugoNB6' 32 | Encrypted: '$y$jD5.7$BkbiDbyWZnzlLWOAcru671$zLAHafRUyp9n9XZWnltUbj3ULWUtMN4fteTltjWkARC' 33 | Plaintext: '$y$jC4$LdJMENpBABJJ3hIHjB1B$jVg4HoqqpbmQv/NCpin.QCMagJ8o4QX7lXdzvVV0xFC' 34 | Encrypted: '$y$jC4$qiyh2SQgE5vrF3ORvFho$HurI7MuukXHz..TpxrwKuakji/j9VKDh2WVUK4DIsq5' 35 | Plaintext: '$y$/B3.6$LdJMENpBABJJ3hIHjB1$h8sE4hJo.BsdlfJr0.d8bNJNPZymH7Y3kLj4aY1Rfc8' 36 | Encrypted: '$y$/B3.6$YiN5s/dKpjNrdKm9ND0$lBNMoUaAsw.JR0zMq9IBKIi/VPxj7lD7Sg64nB5LFw2' 37 | Plaintext: '$y$/A2$LdJMENpBABJJ3hIHj/$5IEld1eWdmh5lylrqHLF5dvA3ISpimEM9J1Dd05n/.3' 38 | Encrypted: '$y$/A2$TqjvmGXoqnsNU/8Y40$ZB43..7UnMt6ySU7XbpPyvyahahHSkJJgztkLWp6/IC' 39 | Plaintext: '$y$j91.5$LdJMENpBABJJ3hIH$ebKnn23URD5vyLgF9cP2EvVosrUXf7UErGRV0KmC6e6' 40 | Encrypted: '$y$j91.5$bICydADAaInC9UR/$rpsDDkULkr1caCVYV9PNAsiZxijoQ2/gDcbonlowRi7' 41 | Plaintext: '$y$j80$LdJMENpBABJJ3h2$ysXVVJwuaVlI1BWoEKt/Bz3WNDDmdOWz/8KTQaHL1cC' 42 | Encrypted: '$y$j80$fmxyeGYOC34lh19$mm9FRBs0iHLTHfSNznm1kJVchXN4PaS8hoNI6TTAlB7' 43 | Plaintext: '$y$/7/.4$LdJMENpBABJJ3/$lXHleh7bIZMGNtJVxGVrsIWkEIXfBedlfPui/PITflC' 44 | Encrypted: '$y$/7/.4$EuTbL3Wtm3khW0$1jvKQzIcAqYnYxfb4TEs.FeAZ7rLDl5vNQEkPPcj2KC' 45 | Plaintext: '$y$/6.$LdJMENpBABJJ$zQITmYSih5.CTY47x0IuE4wl.b3HzYGKKCSggakaQ22' 46 | Encrypted: '$y$/6.$x0G/jIr053ui$4O.aVGTPptkjx6eXrW8fdvqcPEV28w7a1PSos6CXV31' 47 | Plaintext: '$y$j5..3$LdJMENpBAB3$xi27PTUNd8NsChHeLOz85JFnUOyibRHkWzprowRlR5/' 48 | Encrypted: '$y$j5..3$/nwg3UXJWp/$5jcvDgeotKpaG9IeSJx0fJNSz33JjTYYD4Kwao3Eki5' 49 | Plaintext: '$y$j4/$LdJMENpBA/$tHlkpTQ8V/eEnTVau1uW36T97LIXlfPrEzdeV5SE5K7' 50 | Encrypted: '$y$j4/$yoneNBwae0$uPBnH0yXBCOM5v5BU9qlvUUtUr3QD5btS0upc6sdvf4' 51 | Plaintext: '$y$/3..2$LdJMENpB$tNczXFuNUd3HMqypStCRsEaL4e4KF7ZYLBe8Hbeg0B7' 52 | Encrypted: '$y$/3..2$VD20uHT3$AV5WWaN6bEKRvZlCuurj.mnHMmZmJ9ExQ9HjiReCDwC' 53 | Plaintext: '$y$/2/$LdJMEN3$RRorHhfsw1/P/WR6Aurg4U72e9Q7qt9vFPURdyfiqK8' 54 | Encrypted: '$y$/2/$BYujKJA$fsMwVvFm8r1caFQP.mem3OUuMYBCDGj9CEoDfSwFDLB' 55 | Plaintext: '$y$j2..1$LdJME/$iLEt6kuTwHch6XdCxtTHfsQzYwWFmpUwgl6Ax8RH4d1' 56 | Encrypted: '$y$j2..1$.mZga/$X6GFMkoYPxFapo.3H4LllEjltFapONQcKUOdEd9oPa/' 57 | Plaintext: '$y$j0/$LdJM$k7BXzSDuoGHW56SY3HxROCiA0gWRscZe2aA0q5oHPM0' 58 | Encrypted: '$y$j0/$SkNZ$DQ06H0br45bpE7lGgCD9gOxTMP9SsO6Mt1T9lo5PHz1' 59 | Plaintext: '$y$//..0$Ld3$6BJXezMFxaMiO5wsuoEmztvtCs/79085dZO56ADlV5B' 60 | Encrypted: '$y$//..0$lM1$60gjeUIW/3QidfN6zU9NqB09Ni1NBMfj2VaSZMjDd18' 61 | Plaintext: '$y$///$L/$Rrrkp6OVljrIk0kcwkCDhAiHJiSthh3cKeIGHUW7Z0C' 62 | Encrypted: '$y$///$q.$/.tR4GqigxciLYGoB8fmzudWQR7IzSu9s3dR8wp3VsD' 63 | Plaintext: '$y$j1../$LdJMENpBABJJ3hIHjB1Bi.$L8OQFc8mxJPd7CpUFgkS7KqJM2I9jGXu3BdqX2D.647' 64 | Encrypted: '$y$j1../$BkbiDbyWZnzlLWOAcru671$iicGI2gNZyhimPVgz2VoKrJAB9fWykBN.3Mh0AwEy29' 65 | Plaintext: '$y$j//$LdJMENpBABJJ3hIHjB1B$U8a2MaK.yesqWySK8Owk6PWeWmp/XuagMbpP45q1/q1' 66 | Encrypted: '$y$j//$qiyh2SQgE5vrF3ORvFho$5dD9ick8ugystfp8wa3xbV7ASDux0dpoOh0QJxFuXH5' 67 | '$7$C6..../....SodiumChloride$kBGj9fHznVYFQMEn/qDCfrDevf9YDtcDdKvEqHJLV8D' 68 | '$7$06..../....SodiumChloride$ENlyo6fGw4PCcDBOFepfSZjFUnVatHzCcW55.ZGz3B0' 69 | r=8 N=2^11 NROM=2^18 70 | Will use 262144.00 KiB ROM 71 | 2048.00 KiB RAM 72 | Initializing ROM ... DONE (696ebab2) 73 | '$y$j8567F$LdJMENpBABJJ3hIHjB1Bi.' 74 | '$y$j8567F$LdJMENpBABJJ3hIHjB1Bi.$4XJGTsv75AjIN60Z31kPN3.86vkCYzIq7LMz2Pb2lC.' 75 | Initializing ROM in preallocated memory ... DONE (696ebab2) 76 | '$y$j8567F$LdJMENpBABJJ3hIHjB1Bi.$4XJGTsv75AjIN60Z31kPN3.86vkCYzIq7LMz2Pb2lC.' 77 | '$y$j8567F$LdJMENpBABJJ3hIHjB1Bi.$K3wFVK9/t3QsjCk/oK2s8dKzzZ4m7QTP8Ms5uywhWv8' 78 | '$y$j8567F$LdJMENpBABJJ3ZIHjB1Bi.$/OnmIkP0UK5OxyxD0Af/V1oL0zWvTLAUWg3Nr0bsFEB' 79 | '$y$j8567F$LdJMENpBABJJ3ZIHjB1Bi.$DskEGULspNduIZVFK5SOK8enlXnSs/vkuXFdi0wkQ1.' 80 | '$y$j/.5I$LdJMENpBABJJ3hIHjB1Bi.$NqCMKxN9Y9Uw821.72ScGDMpyk7U7V51qnHSRPapzW8' 81 | -------------------------------------------------------------------------------- /initrom.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2013-2018 Alexander Peslyak 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted. 7 | * 8 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 9 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 12 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 13 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 14 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 15 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 16 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 17 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 18 | * SUCH DAMAGE. 19 | */ 20 | 21 | #define YESCRYPT_FLAGS YESCRYPT_DEFAULTS 22 | 23 | #define ROM_SHM_KEY 0x7965730a 24 | #define ROM_LOCAL_PARAM "change this before use" 25 | 26 | /* Maximum parallelism factor during ROM initialization */ 27 | #define YESCRYPT_PROM_SHM 112 28 | #define YESCRYPT_PROM_FILE 4 29 | 30 | //#define USE_HUGEPAGE 31 | //#define DUMP_SHARED 32 | 33 | #include 34 | #include 35 | #include /* for atoi() */ 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include "yescrypt.h" 44 | 45 | int main(int argc, const char * const *argv) 46 | { 47 | #if 0 48 | uint64_t rom_bytes = 112 * (1024ULL*1024*1024); 49 | uint64_t ram_bytes = 1 * (1024ULL*1024); 50 | #else 51 | uint64_t rom_bytes = 3 * (1024ULL*1024*1024); 52 | uint64_t ram_bytes = 2 * (1024ULL*1024); 53 | #endif 54 | uint32_t r, min_r; 55 | uint64_t NROM_log2, N_log2; 56 | int shmid; 57 | yescrypt_shared_t shared; 58 | yescrypt_binary_t *digest; 59 | const char *rom_filename = NULL; 60 | int rom_fd; 61 | 62 | if (argc > 1) 63 | rom_bytes = atoi(argv[1]) * (1024ULL*1024*1024); 64 | if (argc > 2) 65 | ram_bytes = atoi(argv[2]) * (1024ULL*1024); 66 | if (argc > 3) 67 | rom_filename = argv[3]; 68 | 69 | if (!rom_bytes) { 70 | puts("Wrong ROM size requested"); 71 | return 1; 72 | } 73 | 74 | min_r = 9; 75 | if (rom_filename) 76 | min_r = 8 * 256; 77 | 78 | NROM_log2 = 0; 79 | while (((rom_bytes >> NROM_log2) & 0xff) == 0) 80 | NROM_log2++; 81 | r = rom_bytes >> (7 + NROM_log2); 82 | while (r < min_r && NROM_log2 > 0) { 83 | r <<= 1; 84 | NROM_log2--; 85 | } 86 | rom_bytes = (uint64_t)r << (7 + NROM_log2); 87 | 88 | N_log2 = 3; 89 | while (((uint64_t)r << (7 + N_log2)) < ram_bytes) 90 | N_log2++; 91 | ram_bytes = (uint64_t)r << (7 + N_log2); 92 | 93 | printf("r=%u N=2^%u NROM=2^%u\n", r, 94 | (unsigned int)N_log2, (unsigned int)NROM_log2); 95 | 96 | printf("Will use %.2f KiB ROM\n", rom_bytes / 1024.0); 97 | printf(" %.2f KiB RAM\n", ram_bytes / 1024.0); 98 | 99 | shared.aligned_size = rom_bytes; 100 | 101 | if (rom_filename) { 102 | rom_fd = open(rom_filename, O_CREAT|O_RDWR|O_EXCL, 103 | S_IRUSR|S_IRGRP|S_IWUSR); 104 | if (rom_fd < 0) { 105 | perror("open"); 106 | return 1; 107 | } 108 | if (ftruncate(rom_fd, rom_bytes)) { 109 | perror("ftruncate"); 110 | close(rom_fd); 111 | unlink(rom_filename); 112 | return 1; 113 | } 114 | 115 | int flags = 116 | #ifdef MAP_NOCORE 117 | MAP_NOCORE | 118 | #endif 119 | #if defined(MAP_HUGETLB) && defined(USE_HUGEPAGE) 120 | MAP_HUGETLB | 121 | #endif 122 | MAP_SHARED; 123 | void *p = mmap(NULL, rom_bytes, PROT_READ | PROT_WRITE, 124 | flags, rom_fd, 0); 125 | #if defined(MAP_HUGETLB) && defined(USE_HUGEPAGE) 126 | if (p == MAP_FAILED) 127 | p = mmap(NULL, rom_bytes, PROT_READ | PROT_WRITE, 128 | flags & ~MAP_HUGETLB, rom_fd, 0); 129 | #endif 130 | if (p == MAP_FAILED) { 131 | perror("mmap"); 132 | close(rom_fd); 133 | unlink(rom_filename); 134 | return 1; 135 | } 136 | close(rom_fd); 137 | shared.base = shared.aligned = p; 138 | } else { 139 | shmid = shmget(ROM_SHM_KEY, shared.aligned_size, 140 | #ifdef SHM_HUGETLB 141 | SHM_HUGETLB | 142 | #endif 143 | IPC_CREAT|IPC_EXCL | S_IRUSR|S_IRGRP|S_IWUSR); 144 | if (shmid == -1) { 145 | #ifdef SHM_HUGETLB 146 | perror("shmget"); 147 | puts("Retrying without SHM_HUGETLB"); 148 | shmid = shmget(ROM_SHM_KEY, shared.aligned_size, 149 | IPC_CREAT|IPC_EXCL | S_IRUSR|S_IRGRP|S_IWUSR); 150 | #endif 151 | if (shmid == -1) { 152 | perror("shmget"); 153 | return 1; 154 | } 155 | } 156 | 157 | shared.base = shared.aligned = shmat(shmid, NULL, 0); 158 | if (shared.base == (void *)-1) { 159 | int save_errno = errno; 160 | shmctl(shmid, IPC_RMID, NULL); 161 | errno = save_errno; 162 | perror("shmat"); 163 | return 1; 164 | } 165 | } 166 | 167 | printf("Initializing ROM ..."); 168 | fflush(stdout); 169 | yescrypt_params_t rom_params = { 170 | .flags = YESCRYPT_DEFAULTS | YESCRYPT_SHARED_PREALLOCATED, 171 | .NROM = (uint64_t)1 << NROM_log2, 172 | .r = r, 173 | .p = rom_filename ? YESCRYPT_PROM_FILE : YESCRYPT_PROM_SHM }; 174 | if (yescrypt_init_shared(&shared, 175 | (uint8_t *)ROM_LOCAL_PARAM, strlen(ROM_LOCAL_PARAM), 176 | &rom_params)) { 177 | puts(" FAILED"); 178 | if (rom_filename) 179 | unlink(rom_filename); 180 | return 1; 181 | } 182 | #ifdef DUMP_SHARED 183 | fwrite(shared.aligned, shared.aligned_size, 1, stderr); 184 | #endif 185 | digest = yescrypt_digest_shared(&shared); 186 | printf(" DONE (%02x%02x%02x%02x)\n", 187 | digest->uc[0], digest->uc[1], digest->uc[2], digest->uc[3]); 188 | 189 | { 190 | yescrypt_local_t local; 191 | const uint8_t *setting; 192 | uint8_t hash[128]; 193 | 194 | if (yescrypt_init_local(&local)) { 195 | puts("yescrypt_init_local() FAILED"); 196 | return 1; 197 | } 198 | 199 | yescrypt_params_t params = rom_params; 200 | params.flags = YESCRYPT_FLAGS; 201 | params.N = (uint64_t)1 << N_log2; 202 | params.p = 1; 203 | setting = yescrypt_encode_params(¶ms, 204 | (const uint8_t *)"WZaPV7LSUEKMo34.", 16); 205 | 206 | printf("'%s'\n", (char *)yescrypt_r(&shared, &local, 207 | (const uint8_t *)"pleaseletmein", 13, setting, NULL, 208 | hash, sizeof(hash))); 209 | } 210 | 211 | if (rom_filename && munmap(shared.base, rom_bytes)) { 212 | perror("munmap"); 213 | return 1; 214 | } 215 | 216 | return 0; 217 | } 218 | -------------------------------------------------------------------------------- /insecure_memzero.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 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 | #ifndef SKIP_MEMZERO 28 | 29 | #include 30 | #include 31 | 32 | #include "insecure_memzero.h" 33 | 34 | /* Function which does the zeroing. */ 35 | static void 36 | insecure_memzero_func(volatile void * buf, size_t len) 37 | { 38 | volatile uint8_t * _buf = buf; 39 | size_t i; 40 | 41 | for (i = 0; i < len; i++) 42 | _buf[i] = 0; 43 | } 44 | 45 | /* Pointer to memory-zeroing function. */ 46 | void (* volatile insecure_memzero_ptr)(volatile void *, size_t) = 47 | insecure_memzero_func; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /insecure_memzero.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014 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 | #ifndef _INSECURE_MEMZERO_H_ 28 | #define _INSECURE_MEMZERO_H_ 29 | 30 | #ifdef SKIP_MEMZERO 31 | #define insecure_memzero(buf, len) /* empty */ 32 | #else 33 | 34 | #include 35 | 36 | /* Pointer to memory-zeroing function. */ 37 | extern void (* volatile insecure_memzero_ptr)(volatile void *, size_t); 38 | 39 | /** 40 | * insecure_memzero(buf, len): 41 | * Attempt to zero ${len} bytes at ${buf} in spite of optimizing compilers' 42 | * best (standards-compliant) attempts to remove the buffer-zeroing. In 43 | * particular, to avoid performing the zeroing, a compiler would need to 44 | * use optimistic devirtualization; recognize that non-volatile objects do not 45 | * need to be treated as volatile, even if they are accessed via volatile 46 | * qualified pointers; and perform link-time optimization; in addition to the 47 | * dead-code elimination which often causes buffer-zeroing to be elided. 48 | * 49 | * Note however that zeroing a buffer does not guarantee that the data held 50 | * in the buffer is not stored elsewhere; in particular, there may be copies 51 | * held in CPU registers or in anonymous allocations on the stack, even if 52 | * every named variable is successfully sanitized. Solving the "wipe data 53 | * from the system" problem will require a C language extension which does not 54 | * yet exist. 55 | * 56 | * For more information, see: 57 | * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html 58 | * http://www.daemonology.net/blog/2014-09-06-zeroing-buffers-is-insufficient.html 59 | */ 60 | static inline void 61 | insecure_memzero(volatile void * buf, size_t len) 62 | { 63 | 64 | (insecure_memzero_ptr)(buf, len); 65 | } 66 | 67 | #endif 68 | 69 | #endif /* !_INSECURE_MEMZERO_H_ */ 70 | -------------------------------------------------------------------------------- /phc.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2014-2016,2018 Alexander Peslyak 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted. 7 | * 8 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 9 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 12 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 13 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 14 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 15 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 16 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 17 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 18 | * SUCH DAMAGE. 19 | */ 20 | 21 | #define YESCRYPT_FLAGS YESCRYPT_DEFAULTS 22 | #define YESCRYPT_BASE_N 8 23 | #define YESCRYPT_R 8 24 | #define YESCRYPT_P 1 25 | 26 | #include "yescrypt.h" 27 | 28 | #ifdef TEST 29 | static 30 | #endif 31 | int PHS(void *out, size_t outlen, const void *in, size_t inlen, 32 | const void *salt, size_t saltlen, unsigned int t_cost, unsigned int m_cost) 33 | { 34 | yescrypt_local_t local; 35 | yescrypt_params_t params = { 36 | .flags = YESCRYPT_FLAGS, 37 | .N = (uint64_t)YESCRYPT_BASE_N << m_cost, 38 | .r = YESCRYPT_R, 39 | .p = YESCRYPT_P, 40 | .t = t_cost, 41 | .g = 0 }; 42 | int retval; 43 | 44 | if (yescrypt_init_local(&local)) 45 | return -1; 46 | retval = yescrypt_kdf(NULL, &local, in, inlen, salt, saltlen, ¶ms, 47 | out, outlen); 48 | if (yescrypt_free_local(&local)) 49 | return -1; 50 | return retval; 51 | } 52 | 53 | #ifdef TEST 54 | #include 55 | #include /* for sysconf() */ 56 | #include 57 | 58 | static void print_hex(const uint8_t *buf, size_t buflen, const char *sep) 59 | { 60 | size_t i; 61 | 62 | putchar('"'); 63 | for (i = 0; i < buflen; i++) 64 | printf("\\x%02x", buf[i]); 65 | printf("\"%s", sep); 66 | } 67 | 68 | static void print_PHS(const void *in, size_t inlen, 69 | const void *salt, size_t saltlen, unsigned int t_cost, unsigned int m_cost) 70 | { 71 | uint8_t dk[32]; 72 | 73 | printf("PHS("); 74 | print_hex(in, inlen, ", "); 75 | print_hex(salt, saltlen, ", "); 76 | printf("%u, %u) = ", t_cost, m_cost); 77 | 78 | if (PHS(dk, sizeof(dk), in, inlen, salt, saltlen, t_cost, m_cost)) { 79 | puts("FAILED"); 80 | return; 81 | } 82 | 83 | print_hex(dk, sizeof(dk), "\n"); 84 | } 85 | 86 | static void print_all_PHS(unsigned int t_cost, unsigned int m_cost) 87 | { 88 | clock_t clk_tck = sysconf(_SC_CLK_TCK); 89 | struct tms start_tms, end_tms; 90 | clock_t start = times(&start_tms), end, start_v, end_v; 91 | const size_t count = 0x102; 92 | size_t inlen, i, j; 93 | 94 | inlen = 0; 95 | for (i = 0; i < count; i++) { 96 | uint8_t in[128], salt[16]; 97 | 98 | for (j = 0; j < inlen; j++) 99 | in[j] = (i + j) & 0xff; 100 | for (j = 0; j < sizeof(salt); j++) 101 | salt[j] = ~(i + j) & 0xff; 102 | 103 | print_PHS(in, inlen, salt, sizeof(salt), t_cost, m_cost); 104 | 105 | if (++inlen > sizeof(in)) 106 | inlen = 0; 107 | } 108 | 109 | end = times(&end_tms); 110 | 111 | start_v = start_tms.tms_utime + start_tms.tms_stime + 112 | start_tms.tms_cutime + start_tms.tms_cstime; 113 | end_v = end_tms.tms_utime + end_tms.tms_stime + 114 | end_tms.tms_cutime + end_tms.tms_cstime; 115 | 116 | if (end == start) 117 | end++; 118 | if (end_v == start_v) 119 | end_v++; 120 | 121 | fprintf(stderr, "m_cost=%u (%.0f KiB), t_cost=%u\n" 122 | "%llu c/s real, %llu c/s virtual (%llu hashes in %.2f seconds)\n", 123 | m_cost, (YESCRYPT_BASE_N << m_cost) * YESCRYPT_R / 8.0, t_cost, 124 | (unsigned long long)count * clk_tck / (end - start), 125 | (unsigned long long)count * clk_tck / (end_v - start_v), 126 | (unsigned long long)count, (double)(end - start) / clk_tck); 127 | } 128 | 129 | int main(void) 130 | { 131 | #if 0 132 | setvbuf(stdout, NULL, _IOLBF, 0); 133 | #endif 134 | 135 | print_all_PHS(0, 0); 136 | print_all_PHS(0, 7); 137 | print_all_PHS(0, 8); 138 | print_all_PHS(1, 8); 139 | print_all_PHS(2, 8); 140 | print_all_PHS(3, 8); 141 | print_all_PHS(0, 11); 142 | 143 | return 0; 144 | } 145 | #endif 146 | -------------------------------------------------------------------------------- /sha256.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2005-2016 Colin Percival 3 | * Copyright 2016-2018,2021 Alexander Peslyak 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "insecure_memzero.h" 33 | #include "sysendian.h" 34 | 35 | #include "sha256.h" 36 | 37 | #ifdef __ICC 38 | /* Miscompile with icc 14.0.0 (at least), so don't use restrict there */ 39 | #define restrict 40 | #elif __STDC_VERSION__ >= 199901L 41 | /* Have restrict */ 42 | #elif defined(__GNUC__) 43 | #define restrict __restrict 44 | #else 45 | #define restrict 46 | #endif 47 | 48 | /* 49 | * Encode a length len*2 vector of (uint32_t) into a length len*8 vector of 50 | * (uint8_t) in big-endian form. 51 | */ 52 | static void 53 | be32enc_vect(uint8_t * dst, const uint32_t * src, size_t len) 54 | { 55 | 56 | /* Encode vector, two words at a time. */ 57 | do { 58 | be32enc(&dst[0], src[0]); 59 | be32enc(&dst[4], src[1]); 60 | src += 2; 61 | dst += 8; 62 | } while (--len); 63 | } 64 | 65 | /* 66 | * Decode a big-endian length len*8 vector of (uint8_t) into a length 67 | * len*2 vector of (uint32_t). 68 | */ 69 | static void 70 | be32dec_vect(uint32_t * dst, const uint8_t * src, size_t len) 71 | { 72 | 73 | /* Decode vector, two words at a time. */ 74 | do { 75 | dst[0] = be32dec(&src[0]); 76 | dst[1] = be32dec(&src[4]); 77 | src += 8; 78 | dst += 2; 79 | } while (--len); 80 | } 81 | 82 | /* SHA256 round constants. */ 83 | static const uint32_t Krnd[64] = { 84 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 85 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 86 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 87 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 88 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 89 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 90 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 91 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 92 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 93 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 94 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 95 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 96 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 97 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 98 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 99 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 100 | }; 101 | 102 | /* Elementary functions used by SHA256 */ 103 | #define Ch(x, y, z) ((x & (y ^ z)) ^ z) 104 | #if 1 /* Explicit caching/reuse of common subexpression between rounds */ 105 | #define Maj(x, y, z) (y ^ ((x_xor_y = x ^ y) & y_xor_z)) 106 | #else /* Let the compiler cache/reuse or not */ 107 | #define Maj(x, y, z) (y ^ ((x ^ y) & (y ^ z))) 108 | #endif 109 | #define SHR(x, n) (x >> n) 110 | #define ROTR(x, n) ((x >> n) | (x << (32 - n))) 111 | #define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) 112 | #define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) 113 | #define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3)) 114 | #define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10)) 115 | 116 | /* SHA256 round function */ 117 | #define RND(a, b, c, d, e, f, g, h, k) \ 118 | h += S1(e) + Ch(e, f, g) + k; \ 119 | d += h; \ 120 | h += S0(a) + Maj(a, b, c); \ 121 | y_xor_z = x_xor_y; 122 | 123 | /* Adjusted round function for rotating state */ 124 | #define RNDr(S, W, i, ii) \ 125 | RND(S[(64 - i) % 8], S[(65 - i) % 8], \ 126 | S[(66 - i) % 8], S[(67 - i) % 8], \ 127 | S[(68 - i) % 8], S[(69 - i) % 8], \ 128 | S[(70 - i) % 8], S[(71 - i) % 8], \ 129 | W[i + ii] + Krnd[i + ii]) 130 | 131 | /* Message schedule computation */ 132 | #define MSCH(W, ii, i) \ 133 | W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii] 134 | 135 | /* 136 | * SHA256 block compression function. The 256-bit state is transformed via 137 | * the 512-bit input block to produce a new state. 138 | */ 139 | static void 140 | SHA256_Transform(uint32_t state[static restrict 8], 141 | const uint8_t block[static restrict 64], 142 | uint32_t W[static restrict 64], uint32_t S[static restrict 8]) 143 | { 144 | int i; 145 | 146 | /* 1. Prepare the first part of the message schedule W. */ 147 | be32dec_vect(W, block, 8); 148 | 149 | /* 2. Initialize working variables. */ 150 | memcpy(S, state, 32); 151 | 152 | /* 3. Mix. */ 153 | for (i = 0; i < 64; i += 16) { 154 | uint32_t x_xor_y, y_xor_z = S[(65 - i) % 8] ^ S[(66 - i) % 8]; 155 | RNDr(S, W, 0, i); 156 | RNDr(S, W, 1, i); 157 | RNDr(S, W, 2, i); 158 | RNDr(S, W, 3, i); 159 | RNDr(S, W, 4, i); 160 | RNDr(S, W, 5, i); 161 | RNDr(S, W, 6, i); 162 | RNDr(S, W, 7, i); 163 | RNDr(S, W, 8, i); 164 | RNDr(S, W, 9, i); 165 | RNDr(S, W, 10, i); 166 | RNDr(S, W, 11, i); 167 | RNDr(S, W, 12, i); 168 | RNDr(S, W, 13, i); 169 | RNDr(S, W, 14, i); 170 | RNDr(S, W, 15, i); 171 | 172 | if (i == 48) 173 | break; 174 | MSCH(W, 0, i); 175 | MSCH(W, 1, i); 176 | MSCH(W, 2, i); 177 | MSCH(W, 3, i); 178 | MSCH(W, 4, i); 179 | MSCH(W, 5, i); 180 | MSCH(W, 6, i); 181 | MSCH(W, 7, i); 182 | MSCH(W, 8, i); 183 | MSCH(W, 9, i); 184 | MSCH(W, 10, i); 185 | MSCH(W, 11, i); 186 | MSCH(W, 12, i); 187 | MSCH(W, 13, i); 188 | MSCH(W, 14, i); 189 | MSCH(W, 15, i); 190 | } 191 | 192 | /* 4. Mix local working variables into global state. */ 193 | state[0] += S[0]; 194 | state[1] += S[1]; 195 | state[2] += S[2]; 196 | state[3] += S[3]; 197 | state[4] += S[4]; 198 | state[5] += S[5]; 199 | state[6] += S[6]; 200 | state[7] += S[7]; 201 | } 202 | 203 | static const uint8_t PAD[64] = { 204 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 205 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 207 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 208 | }; 209 | 210 | /* Add padding and terminating bit-count. */ 211 | static void 212 | SHA256_Pad(SHA256_CTX * ctx, uint32_t tmp32[static restrict 72]) 213 | { 214 | size_t r; 215 | 216 | /* Figure out how many bytes we have buffered. */ 217 | r = (ctx->count >> 3) & 0x3f; 218 | 219 | /* Pad to 56 mod 64, transforming if we finish a block en route. */ 220 | if (r < 56) { 221 | /* Pad to 56 mod 64. */ 222 | memcpy(&ctx->buf[r], PAD, 56 - r); 223 | } else { 224 | /* Finish the current block and mix. */ 225 | memcpy(&ctx->buf[r], PAD, 64 - r); 226 | SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]); 227 | 228 | /* The start of the final block is all zeroes. */ 229 | memset(&ctx->buf[0], 0, 56); 230 | } 231 | 232 | /* Add the terminating bit-count. */ 233 | be64enc(&ctx->buf[56], ctx->count); 234 | 235 | /* Mix in the final block. */ 236 | SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]); 237 | } 238 | 239 | /* Magic initialization constants. */ 240 | static const uint32_t initial_state[8] = { 241 | 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 242 | 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 243 | }; 244 | 245 | /** 246 | * SHA256_Init(ctx): 247 | * Initialize the SHA256 context ${ctx}. 248 | */ 249 | void 250 | SHA256_Init(SHA256_CTX * ctx) 251 | { 252 | 253 | /* Zero bits processed so far. */ 254 | ctx->count = 0; 255 | 256 | /* Initialize state. */ 257 | memcpy(ctx->state, initial_state, sizeof(initial_state)); 258 | } 259 | 260 | /** 261 | * SHA256_Update(ctx, in, len): 262 | * Input ${len} bytes from ${in} into the SHA256 context ${ctx}. 263 | */ 264 | static void 265 | _SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len, 266 | uint32_t tmp32[static restrict 72]) 267 | { 268 | uint32_t r; 269 | const uint8_t * src = in; 270 | 271 | /* Return immediately if we have nothing to do. */ 272 | if (len == 0) 273 | return; 274 | 275 | /* Number of bytes left in the buffer from previous updates. */ 276 | r = (ctx->count >> 3) & 0x3f; 277 | 278 | /* Update number of bits. */ 279 | ctx->count += (uint64_t)(len) << 3; 280 | 281 | /* Handle the case where we don't need to perform any transforms. */ 282 | if (len < 64 - r) { 283 | memcpy(&ctx->buf[r], src, len); 284 | return; 285 | } 286 | 287 | /* Finish the current block. */ 288 | memcpy(&ctx->buf[r], src, 64 - r); 289 | SHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]); 290 | src += 64 - r; 291 | len -= 64 - r; 292 | 293 | /* Perform complete blocks. */ 294 | while (len >= 64) { 295 | SHA256_Transform(ctx->state, src, &tmp32[0], &tmp32[64]); 296 | src += 64; 297 | len -= 64; 298 | } 299 | 300 | /* Copy left over data into buffer. */ 301 | memcpy(ctx->buf, src, len); 302 | } 303 | 304 | /* Wrapper function for intermediate-values sanitization. */ 305 | void 306 | SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len) 307 | { 308 | uint32_t tmp32[72]; 309 | 310 | /* Call the real function. */ 311 | _SHA256_Update(ctx, in, len, tmp32); 312 | 313 | /* Clean the stack. */ 314 | insecure_memzero(tmp32, 288); 315 | } 316 | 317 | /** 318 | * SHA256_Final(digest, ctx): 319 | * Output the SHA256 hash of the data input to the context ${ctx} into the 320 | * buffer ${digest}. 321 | */ 322 | static void 323 | _SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx, 324 | uint32_t tmp32[static restrict 72]) 325 | { 326 | 327 | /* Add padding. */ 328 | SHA256_Pad(ctx, tmp32); 329 | 330 | /* Write the hash. */ 331 | be32enc_vect(digest, ctx->state, 4); 332 | } 333 | 334 | /* Wrapper function for intermediate-values sanitization. */ 335 | void 336 | SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx) 337 | { 338 | uint32_t tmp32[72]; 339 | 340 | /* Call the real function. */ 341 | _SHA256_Final(digest, ctx, tmp32); 342 | 343 | /* Clear the context state. */ 344 | insecure_memzero(ctx, sizeof(SHA256_CTX)); 345 | 346 | /* Clean the stack. */ 347 | insecure_memzero(tmp32, 288); 348 | } 349 | 350 | /** 351 | * SHA256_Buf(in, len, digest): 352 | * Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}. 353 | */ 354 | void 355 | SHA256_Buf(const void * in, size_t len, uint8_t digest[32]) 356 | { 357 | SHA256_CTX ctx; 358 | uint32_t tmp32[72]; 359 | 360 | SHA256_Init(&ctx); 361 | _SHA256_Update(&ctx, in, len, tmp32); 362 | _SHA256_Final(digest, &ctx, tmp32); 363 | 364 | /* Clean the stack. */ 365 | insecure_memzero(&ctx, sizeof(SHA256_CTX)); 366 | insecure_memzero(tmp32, 288); 367 | } 368 | 369 | /** 370 | * HMAC_SHA256_Init(ctx, K, Klen): 371 | * Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from 372 | * ${K}. 373 | */ 374 | static void 375 | _HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen, 376 | uint32_t tmp32[static restrict 72], uint8_t pad[static restrict 64], 377 | uint8_t khash[static restrict 32]) 378 | { 379 | const uint8_t * K = _K; 380 | size_t i; 381 | 382 | /* If Klen > 64, the key is really SHA256(K). */ 383 | if (Klen > 64) { 384 | SHA256_Init(&ctx->ictx); 385 | _SHA256_Update(&ctx->ictx, K, Klen, tmp32); 386 | _SHA256_Final(khash, &ctx->ictx, tmp32); 387 | K = khash; 388 | Klen = 32; 389 | } 390 | 391 | /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */ 392 | SHA256_Init(&ctx->ictx); 393 | memset(pad, 0x36, 64); 394 | for (i = 0; i < Klen; i++) 395 | pad[i] ^= K[i]; 396 | _SHA256_Update(&ctx->ictx, pad, 64, tmp32); 397 | 398 | /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */ 399 | SHA256_Init(&ctx->octx); 400 | memset(pad, 0x5c, 64); 401 | for (i = 0; i < Klen; i++) 402 | pad[i] ^= K[i]; 403 | _SHA256_Update(&ctx->octx, pad, 64, tmp32); 404 | } 405 | 406 | /* Wrapper function for intermediate-values sanitization. */ 407 | void 408 | HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen) 409 | { 410 | uint32_t tmp32[72]; 411 | uint8_t pad[64]; 412 | uint8_t khash[32]; 413 | 414 | /* Call the real function. */ 415 | _HMAC_SHA256_Init(ctx, _K, Klen, tmp32, pad, khash); 416 | 417 | /* Clean the stack. */ 418 | insecure_memzero(tmp32, 288); 419 | insecure_memzero(khash, 32); 420 | insecure_memzero(pad, 64); 421 | } 422 | 423 | /** 424 | * HMAC_SHA256_Update(ctx, in, len): 425 | * Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}. 426 | */ 427 | static void 428 | _HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len, 429 | uint32_t tmp32[static restrict 72]) 430 | { 431 | 432 | /* Feed data to the inner SHA256 operation. */ 433 | _SHA256_Update(&ctx->ictx, in, len, tmp32); 434 | } 435 | 436 | /* Wrapper function for intermediate-values sanitization. */ 437 | void 438 | HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len) 439 | { 440 | uint32_t tmp32[72]; 441 | 442 | /* Call the real function. */ 443 | _HMAC_SHA256_Update(ctx, in, len, tmp32); 444 | 445 | /* Clean the stack. */ 446 | insecure_memzero(tmp32, 288); 447 | } 448 | 449 | /** 450 | * HMAC_SHA256_Final(digest, ctx): 451 | * Output the HMAC-SHA256 of the data input to the context ${ctx} into the 452 | * buffer ${digest}. 453 | */ 454 | static void 455 | _HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx, 456 | uint32_t tmp32[static restrict 72], uint8_t ihash[static restrict 32]) 457 | { 458 | 459 | /* Finish the inner SHA256 operation. */ 460 | _SHA256_Final(ihash, &ctx->ictx, tmp32); 461 | 462 | /* Feed the inner hash to the outer SHA256 operation. */ 463 | _SHA256_Update(&ctx->octx, ihash, 32, tmp32); 464 | 465 | /* Finish the outer SHA256 operation. */ 466 | _SHA256_Final(digest, &ctx->octx, tmp32); 467 | } 468 | 469 | /* Wrapper function for intermediate-values sanitization. */ 470 | void 471 | HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx) 472 | { 473 | uint32_t tmp32[72]; 474 | uint8_t ihash[32]; 475 | 476 | /* Call the real function. */ 477 | _HMAC_SHA256_Final(digest, ctx, tmp32, ihash); 478 | 479 | /* Clean the stack. */ 480 | insecure_memzero(tmp32, 288); 481 | insecure_memzero(ihash, 32); 482 | } 483 | 484 | /** 485 | * HMAC_SHA256_Buf(K, Klen, in, len, digest): 486 | * Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of 487 | * length ${Klen}, and write the result to ${digest}. 488 | */ 489 | void 490 | HMAC_SHA256_Buf(const void * K, size_t Klen, const void * in, size_t len, 491 | uint8_t digest[32]) 492 | { 493 | HMAC_SHA256_CTX ctx; 494 | uint32_t tmp32[72]; 495 | uint8_t tmp8[96]; 496 | 497 | _HMAC_SHA256_Init(&ctx, K, Klen, tmp32, &tmp8[0], &tmp8[64]); 498 | _HMAC_SHA256_Update(&ctx, in, len, tmp32); 499 | _HMAC_SHA256_Final(digest, &ctx, tmp32, &tmp8[0]); 500 | 501 | /* Clean the stack. */ 502 | insecure_memzero(&ctx, sizeof(HMAC_SHA256_CTX)); 503 | insecure_memzero(tmp32, 288); 504 | insecure_memzero(tmp8, 96); 505 | } 506 | 507 | /* Add padding and terminating bit-count, but don't invoke Transform yet. */ 508 | static int 509 | SHA256_Pad_Almost(SHA256_CTX * ctx, uint8_t len[static restrict 8], 510 | uint32_t tmp32[static restrict 72]) 511 | { 512 | uint32_t r; 513 | 514 | r = (ctx->count >> 3) & 0x3f; 515 | if (r >= 56) 516 | return -1; 517 | 518 | /* 519 | * Convert length to a vector of bytes -- we do this now rather 520 | * than later because the length will change after we pad. 521 | */ 522 | be64enc(len, ctx->count); 523 | 524 | /* Add 1--56 bytes so that the resulting length is 56 mod 64. */ 525 | _SHA256_Update(ctx, PAD, 56 - r, tmp32); 526 | 527 | /* Add the terminating bit-count. */ 528 | ctx->buf[63] = len[7]; 529 | _SHA256_Update(ctx, len, 7, tmp32); 530 | 531 | return 0; 532 | } 533 | 534 | /** 535 | * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): 536 | * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and 537 | * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). 538 | */ 539 | void 540 | PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, 541 | size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) 542 | { 543 | HMAC_SHA256_CTX Phctx, PShctx, hctx; 544 | uint32_t tmp32[72]; 545 | union { 546 | uint8_t tmp8[96]; 547 | uint32_t state[8]; 548 | } u; 549 | size_t i; 550 | uint8_t ivec[4]; 551 | uint8_t U[32]; 552 | uint8_t T[32]; 553 | uint64_t j; 554 | int k; 555 | size_t clen; 556 | 557 | /* Sanity-check. */ 558 | assert(dkLen <= 32 * (size_t)(UINT32_MAX)); 559 | 560 | if (c == 1 && (dkLen & 31) == 0 && (saltlen & 63) <= 51) { 561 | uint32_t oldcount; 562 | uint8_t * ivecp; 563 | 564 | /* Compute HMAC state after processing P and S. */ 565 | _HMAC_SHA256_Init(&hctx, passwd, passwdlen, 566 | tmp32, &u.tmp8[0], &u.tmp8[64]); 567 | _HMAC_SHA256_Update(&hctx, salt, saltlen, tmp32); 568 | 569 | /* Prepare ictx padding. */ 570 | oldcount = hctx.ictx.count & (0x3f << 3); 571 | _HMAC_SHA256_Update(&hctx, "\0\0\0", 4, tmp32); 572 | if ((hctx.ictx.count & (0x3f << 3)) < oldcount || 573 | SHA256_Pad_Almost(&hctx.ictx, u.tmp8, tmp32)) 574 | goto generic; /* Can't happen due to saltlen check */ 575 | ivecp = hctx.ictx.buf + (oldcount >> 3); 576 | 577 | /* Prepare octx padding. */ 578 | hctx.octx.count += 32 << 3; 579 | SHA256_Pad_Almost(&hctx.octx, u.tmp8, tmp32); 580 | 581 | /* Iterate through the blocks. */ 582 | for (i = 0; i * 32 < dkLen; i++) { 583 | /* Generate INT(i + 1). */ 584 | be32enc(ivecp, (uint32_t)(i + 1)); 585 | 586 | /* Compute U_1 = PRF(P, S || INT(i)). */ 587 | memcpy(u.state, hctx.ictx.state, sizeof(u.state)); 588 | SHA256_Transform(u.state, hctx.ictx.buf, 589 | &tmp32[0], &tmp32[64]); 590 | be32enc_vect(hctx.octx.buf, u.state, 4); 591 | memcpy(u.state, hctx.octx.state, sizeof(u.state)); 592 | SHA256_Transform(u.state, hctx.octx.buf, 593 | &tmp32[0], &tmp32[64]); 594 | be32enc_vect(&buf[i * 32], u.state, 4); 595 | } 596 | 597 | goto cleanup; 598 | } 599 | 600 | generic: 601 | /* Compute HMAC state after processing P. */ 602 | _HMAC_SHA256_Init(&Phctx, passwd, passwdlen, 603 | tmp32, &u.tmp8[0], &u.tmp8[64]); 604 | 605 | /* Compute HMAC state after processing P and S. */ 606 | memcpy(&PShctx, &Phctx, sizeof(HMAC_SHA256_CTX)); 607 | _HMAC_SHA256_Update(&PShctx, salt, saltlen, tmp32); 608 | 609 | /* Iterate through the blocks. */ 610 | for (i = 0; i * 32 < dkLen; i++) { 611 | /* Generate INT(i + 1). */ 612 | be32enc(ivec, (uint32_t)(i + 1)); 613 | 614 | /* Compute U_1 = PRF(P, S || INT(i)). */ 615 | memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX)); 616 | _HMAC_SHA256_Update(&hctx, ivec, 4, tmp32); 617 | _HMAC_SHA256_Final(T, &hctx, tmp32, u.tmp8); 618 | 619 | if (c > 1) { 620 | /* T_i = U_1 ... */ 621 | memcpy(U, T, 32); 622 | 623 | for (j = 2; j <= c; j++) { 624 | /* Compute U_j. */ 625 | memcpy(&hctx, &Phctx, sizeof(HMAC_SHA256_CTX)); 626 | _HMAC_SHA256_Update(&hctx, U, 32, tmp32); 627 | _HMAC_SHA256_Final(U, &hctx, tmp32, u.tmp8); 628 | 629 | /* ... xor U_j ... */ 630 | for (k = 0; k < 32; k++) 631 | T[k] ^= U[k]; 632 | } 633 | } 634 | 635 | /* Copy as many bytes as necessary into buf. */ 636 | clen = dkLen - i * 32; 637 | if (clen > 32) 638 | clen = 32; 639 | memcpy(&buf[i * 32], T, clen); 640 | } 641 | 642 | /* Clean the stack. */ 643 | insecure_memzero(&Phctx, sizeof(HMAC_SHA256_CTX)); 644 | insecure_memzero(&PShctx, sizeof(HMAC_SHA256_CTX)); 645 | insecure_memzero(U, 32); 646 | insecure_memzero(T, 32); 647 | 648 | cleanup: 649 | insecure_memzero(&hctx, sizeof(HMAC_SHA256_CTX)); 650 | insecure_memzero(tmp32, 288); 651 | insecure_memzero(&u, sizeof(u)); 652 | } 653 | -------------------------------------------------------------------------------- /sha256.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2005-2016 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 | #ifndef _SHA256_H_ 28 | #define _SHA256_H_ 29 | 30 | #include 31 | #include 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | /* 38 | * Use #defines in order to avoid namespace collisions with anyone else's 39 | * SHA256 code (e.g., the code in OpenSSL). 40 | */ 41 | #define SHA256_Init libcperciva_SHA256_Init 42 | #define SHA256_Update libcperciva_SHA256_Update 43 | #define SHA256_Final libcperciva_SHA256_Final 44 | #define SHA256_Buf libcperciva_SHA256_Buf 45 | #define SHA256_CTX libcperciva_SHA256_CTX 46 | #define HMAC_SHA256_Init libcperciva_HMAC_SHA256_Init 47 | #define HMAC_SHA256_Update libcperciva_HMAC_SHA256_Update 48 | #define HMAC_SHA256_Final libcperciva_HMAC_SHA256_Final 49 | #define HMAC_SHA256_Buf libcperciva_HMAC_SHA256_Buf 50 | #define HMAC_SHA256_CTX libcperciva_HMAC_SHA256_CTX 51 | 52 | /* Context structure for SHA256 operations. */ 53 | typedef struct { 54 | uint32_t state[8]; 55 | uint64_t count; 56 | uint8_t buf[64]; 57 | } SHA256_CTX; 58 | 59 | /** 60 | * SHA256_Init(ctx): 61 | * Initialize the SHA256 context ${ctx}. 62 | */ 63 | void SHA256_Init(SHA256_CTX *); 64 | 65 | /** 66 | * SHA256_Update(ctx, in, len): 67 | * Input ${len} bytes from ${in} into the SHA256 context ${ctx}. 68 | */ 69 | void SHA256_Update(SHA256_CTX *, const void *, size_t); 70 | 71 | /** 72 | * SHA256_Final(digest, ctx): 73 | * Output the SHA256 hash of the data input to the context ${ctx} into the 74 | * buffer ${digest}. 75 | */ 76 | void SHA256_Final(uint8_t[32], SHA256_CTX *); 77 | 78 | /** 79 | * SHA256_Buf(in, len, digest): 80 | * Compute the SHA256 hash of ${len} bytes from ${in} and write it to ${digest}. 81 | */ 82 | void SHA256_Buf(const void *, size_t, uint8_t[32]); 83 | 84 | /* Context structure for HMAC-SHA256 operations. */ 85 | typedef struct { 86 | SHA256_CTX ictx; 87 | SHA256_CTX octx; 88 | } HMAC_SHA256_CTX; 89 | 90 | /** 91 | * HMAC_SHA256_Init(ctx, K, Klen): 92 | * Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from 93 | * ${K}. 94 | */ 95 | void HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t); 96 | 97 | /** 98 | * HMAC_SHA256_Update(ctx, in, len): 99 | * Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}. 100 | */ 101 | void HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t); 102 | 103 | /** 104 | * HMAC_SHA256_Final(digest, ctx): 105 | * Output the HMAC-SHA256 of the data input to the context ${ctx} into the 106 | * buffer ${digest}. 107 | */ 108 | void HMAC_SHA256_Final(uint8_t[32], HMAC_SHA256_CTX *); 109 | 110 | /** 111 | * HMAC_SHA256_Buf(K, Klen, in, len, digest): 112 | * Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of 113 | * length ${Klen}, and write the result to ${digest}. 114 | */ 115 | void HMAC_SHA256_Buf(const void *, size_t, const void *, size_t, uint8_t[32]); 116 | 117 | /** 118 | * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): 119 | * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and 120 | * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). 121 | */ 122 | void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, 123 | uint64_t, uint8_t *, size_t); 124 | 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | #endif /* !_SHA256_H_ */ 130 | -------------------------------------------------------------------------------- /sysendian.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2007-2014 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 | #ifndef _SYSENDIAN_H_ 28 | #define _SYSENDIAN_H_ 29 | 30 | #include 31 | 32 | /* Avoid namespace collisions with BSD . */ 33 | #define be32dec libcperciva_be32dec 34 | #define be32enc libcperciva_be32enc 35 | #define be64enc libcperciva_be64enc 36 | #define le32dec libcperciva_le32dec 37 | #define le32enc libcperciva_le32enc 38 | #define le64dec libcperciva_le64dec 39 | #define le64enc libcperciva_le64enc 40 | 41 | static inline uint32_t 42 | be32dec(const void * pp) 43 | { 44 | const uint8_t * p = (uint8_t const *)pp; 45 | 46 | return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + 47 | ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); 48 | } 49 | 50 | static inline void 51 | be32enc(void * pp, uint32_t x) 52 | { 53 | uint8_t * p = (uint8_t *)pp; 54 | 55 | p[3] = x & 0xff; 56 | p[2] = (x >> 8) & 0xff; 57 | p[1] = (x >> 16) & 0xff; 58 | p[0] = (x >> 24) & 0xff; 59 | } 60 | 61 | static inline void 62 | be64enc(void * pp, uint64_t x) 63 | { 64 | uint8_t * p = (uint8_t *)pp; 65 | 66 | p[7] = x & 0xff; 67 | p[6] = (x >> 8) & 0xff; 68 | p[5] = (x >> 16) & 0xff; 69 | p[4] = (x >> 24) & 0xff; 70 | p[3] = (x >> 32) & 0xff; 71 | p[2] = (x >> 40) & 0xff; 72 | p[1] = (x >> 48) & 0xff; 73 | p[0] = (x >> 56) & 0xff; 74 | } 75 | 76 | static inline uint32_t 77 | le32dec(const void * pp) 78 | { 79 | const uint8_t * p = (uint8_t const *)pp; 80 | 81 | return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + 82 | ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); 83 | } 84 | 85 | static inline void 86 | le32enc(void * pp, uint32_t x) 87 | { 88 | uint8_t * p = (uint8_t *)pp; 89 | 90 | p[0] = x & 0xff; 91 | p[1] = (x >> 8) & 0xff; 92 | p[2] = (x >> 16) & 0xff; 93 | p[3] = (x >> 24) & 0xff; 94 | } 95 | 96 | static inline uint64_t 97 | le64dec(const void * pp) 98 | { 99 | const uint8_t * p = (uint8_t const *)pp; 100 | 101 | return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) + 102 | ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) + 103 | ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) + 104 | ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56)); 105 | } 106 | 107 | static inline void 108 | le64enc(void * pp, uint64_t x) 109 | { 110 | uint8_t * p = (uint8_t *)pp; 111 | 112 | p[0] = x & 0xff; 113 | p[1] = (x >> 8) & 0xff; 114 | p[2] = (x >> 16) & 0xff; 115 | p[3] = (x >> 24) & 0xff; 116 | p[4] = (x >> 32) & 0xff; 117 | p[5] = (x >> 40) & 0xff; 118 | p[6] = (x >> 48) & 0xff; 119 | p[7] = (x >> 56) & 0xff; 120 | } 121 | 122 | #endif /* !_SYSENDIAN_H_ */ 123 | -------------------------------------------------------------------------------- /tests.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2013-2018 Alexander Peslyak 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted. 7 | * 8 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 9 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 12 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 13 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 14 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 15 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 16 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 17 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 18 | * SUCH DAMAGE. 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | #define YESCRYPT_FLAGS YESCRYPT_DEFAULTS 25 | #if 1 26 | #define YESCRYPT_P 11 27 | #define YESCRYPT_PROM 8 28 | #else 29 | #define YESCRYPT_P 1 30 | #define YESCRYPT_PROM 1 31 | #endif 32 | 33 | #undef TEST_PBKDF2_SHA256 34 | #define TEST_SCRYPT 35 | #define TEST_YESCRYPT_KDF 36 | #define TEST_YESCRYPT_ENCODING 37 | #define TEST_ROM 38 | #define TEST_ROM_PREALLOC 39 | 40 | #ifdef TEST_ROM_PREALLOC 41 | #include /* for malloc() */ 42 | #endif 43 | 44 | #ifdef TEST_PBKDF2_SHA256 45 | #include 46 | 47 | #include "sha256.h" 48 | 49 | static void print_PBKDF2_SHA256_raw(const char *passwd, size_t passwdlen, 50 | const char *salt, size_t saltlen, uint64_t c, size_t dkLen) 51 | { 52 | uint8_t dk[64]; 53 | size_t i; 54 | 55 | assert(dkLen <= sizeof(dk)); 56 | 57 | /* XXX This prints the strings truncated at first NUL */ 58 | printf("PBKDF2_SHA256(\"%s\", \"%s\", %llu, %llu) =", 59 | passwd, salt, (unsigned long long)c, (unsigned long long)dkLen); 60 | 61 | PBKDF2_SHA256((const uint8_t *) passwd, passwdlen, 62 | (const uint8_t *) salt, saltlen, c, dk, dkLen); 63 | 64 | for (i = 0; i < dkLen; i++) 65 | printf(" %02x", dk[i]); 66 | puts(""); 67 | } 68 | 69 | static void print_PBKDF2_SHA256(const char *passwd, 70 | const char *salt, uint64_t c, size_t dkLen) 71 | { 72 | print_PBKDF2_SHA256_raw(passwd, strlen(passwd), salt, strlen(salt), c, 73 | dkLen); 74 | } 75 | #endif 76 | 77 | #if defined(TEST_SCRYPT) || defined(TEST_YESCRYPT_ENCODING) 78 | #include "yescrypt.h" 79 | #endif 80 | 81 | #ifdef TEST_SCRYPT 82 | static void print_scrypt(const char *passwd, const char *salt, 83 | uint64_t N, uint32_t r, uint32_t p) 84 | { 85 | uint8_t dk[64]; 86 | size_t i; 87 | 88 | printf("scrypt(\"%s\", \"%s\", %llu, %u, %u) =", 89 | passwd, salt, (unsigned long long)N, r, p); 90 | 91 | if (crypto_scrypt((const uint8_t *) passwd, strlen(passwd), 92 | (const uint8_t *) salt, strlen(salt), N, r, p, dk, sizeof(dk))) { 93 | puts(" FAILED"); 94 | return; 95 | } 96 | 97 | for (i = 0; i < sizeof(dk); i++) 98 | printf(" %02x", dk[i]); 99 | puts(""); 100 | } 101 | #endif 102 | 103 | #ifdef TEST_YESCRYPT_KDF 104 | static void print_yescrypt(const char *passwd, const char *salt, 105 | yescrypt_flags_t flags, 106 | uint64_t N, uint32_t r, uint32_t p, uint32_t t, uint32_t g, 107 | uint32_t dklen) 108 | { 109 | yescrypt_local_t local; 110 | yescrypt_params_t params = {flags, N, r, p, t, g, 0}; 111 | uint8_t dk[64]; 112 | uint32_t i; 113 | 114 | #if 1 115 | /* Don't test hash upgrades */ 116 | if (g) 117 | return; 118 | #endif 119 | 120 | if (dklen > sizeof(dk) || yescrypt_init_local(&local)) { 121 | puts("FAILED"); 122 | return; 123 | } 124 | 125 | printf("yescrypt(\"%s\", \"%s\", %u, %llu, %u, %u, %u, %u) =", 126 | passwd, salt, flags, (unsigned long long)N, r, p, t, g); 127 | 128 | if (yescrypt_kdf(NULL, &local, 129 | (const uint8_t *) passwd, strlen(passwd), 130 | (const uint8_t *) salt, strlen(salt), ¶ms, dk, dklen)) { 131 | yescrypt_free_local(&local); 132 | puts(" FAILED"); 133 | return; 134 | } 135 | 136 | yescrypt_free_local(&local); 137 | 138 | for (i = 0; i < dklen; i++) 139 | printf(" %02x", dk[i]); 140 | puts(""); 141 | } 142 | #endif 143 | 144 | int main(void) 145 | { 146 | int i; 147 | 148 | setvbuf(stdout, NULL, _IOLBF, 0); 149 | 150 | #ifdef TEST_PBKDF2_SHA256 151 | print_PBKDF2_SHA256("password", "salt", 1, 20); 152 | print_PBKDF2_SHA256("password", "salt", 2, 20); 153 | print_PBKDF2_SHA256("password", "salt", 4096, 20); 154 | print_PBKDF2_SHA256("password", "salt", 16777216, 20); 155 | print_PBKDF2_SHA256("passwordPASSWORDpassword", 156 | "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25); 157 | print_PBKDF2_SHA256_raw("pass\0word", 9, "sa\0lt", 5, 4096, 16); 158 | #if 0 159 | print_PBKDF2_SHA256("password", "salt", 1, 32); 160 | print_PBKDF2_SHA256("password", "salt", 2, 32); 161 | print_PBKDF2_SHA256("password", "salt", 4096, 32); 162 | print_PBKDF2_SHA256("password", "salt", 16777216, 32); 163 | print_PBKDF2_SHA256("passwordPASSWORDpassword", 164 | "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 40); 165 | print_PBKDF2_SHA256("password", "salt", 4096, 16); 166 | print_PBKDF2_SHA256("password", "salt", 1, 20); 167 | print_PBKDF2_SHA256("password", "salt", 2, 20); 168 | print_PBKDF2_SHA256("password", "salt", 4096, 20); 169 | print_PBKDF2_SHA256("password", "salt", 16777216, 20); 170 | print_PBKDF2_SHA256("password", "salt", 4096, 25); 171 | print_PBKDF2_SHA256("password", "salt", 4096, 16); 172 | #endif 173 | #endif 174 | 175 | #ifdef TEST_SCRYPT 176 | print_scrypt("", "", 16, 1, 1); 177 | print_scrypt("password", "NaCl", 1024, 8, 16); 178 | print_scrypt("pleaseletmein", "SodiumChloride", 16384, 8, 1); 179 | print_scrypt("pleaseletmein", "SodiumChloride", 1048576, 8, 1); 180 | #endif 181 | 182 | #ifdef TEST_YESCRYPT_KDF 183 | print_yescrypt("", "", 0, 16, 1, 1, 0, 0, 64); 184 | print_yescrypt("", "", 0, 16, 1, 1, 0, 0, 8); 185 | print_yescrypt("", "", 0, 4, 1, 1, 0, 0, 64); 186 | print_yescrypt("", "", YESCRYPT_WORM, 4, 1, 1, 0, 0, 64); 187 | print_yescrypt("", "", YESCRYPT_WORM, 4, 1, 1, 0, 0, 8); 188 | print_yescrypt("", "", YESCRYPT_WORM, 4, 1, 1, 1, 0, 64); 189 | print_yescrypt("", "", YESCRYPT_WORM, 4, 1, 1, 2, 0, 64); 190 | print_yescrypt("", "", YESCRYPT_WORM, 4, 1, 1, 3, 0, 64); 191 | print_yescrypt("", "", YESCRYPT_WORM, 4, 1, 1, 3, 0, 33); 192 | print_yescrypt("", "", YESCRYPT_WORM, 4, 1, 1, 3, 0, 32); 193 | print_yescrypt("", "", YESCRYPT_WORM, 4, 1, 1, 3, 0, 31); 194 | print_yescrypt("", "", YESCRYPT_WORM, 4, 1, 1, 3, 0, 1); 195 | print_yescrypt("", "", YESCRYPT_DEFAULTS, 4, 1, 1, 0, 0, 64); 196 | print_yescrypt("", "", YESCRYPT_DEFAULTS, 4, 1, 1, 0, 0, 4); 197 | print_yescrypt("", "", YESCRYPT_DEFAULTS, 4, 1, 1, 1, 0, 64); 198 | print_yescrypt("", "", YESCRYPT_DEFAULTS, 4, 1, 1, 1, 0, 33); 199 | print_yescrypt("", "", YESCRYPT_DEFAULTS, 4, 1, 1, 1, 0, 32); 200 | print_yescrypt("", "", YESCRYPT_DEFAULTS, 4, 1, 1, 1, 0, 31); 201 | print_yescrypt("", "", YESCRYPT_DEFAULTS, 4, 1, 1, 1, 0, 1); 202 | for (i = 0; i <= 6; i++) 203 | print_yescrypt("p", "s", YESCRYPT_DEFAULTS, 16, 8, 1, i + 10, i, 40); 204 | for (i = 0; i <= 6; i++) 205 | print_yescrypt("p", "s", YESCRYPT_WORM, 16, 8, 1, i + 10, i, 40); 206 | for (i = 0; i <= 6; i++) 207 | print_yescrypt("p", "s", YESCRYPT_DEFAULTS, 16, 8, 1, 0, i, 40); 208 | for (i = 0; i <= 6; i++) 209 | print_yescrypt("p", "s", YESCRYPT_WORM, 16, 8, 1, 0, i, 40); 210 | for (i = 0; i <= 2; i++) 211 | print_yescrypt("p", "s", YESCRYPT_DEFAULTS, 16, 8, 1, 0, i, 32); 212 | for (i = 0; i <= 2; i++) 213 | print_yescrypt("p", "s", YESCRYPT_DEFAULTS, 16, 8, 1, 0, i, 8); 214 | #endif 215 | 216 | #ifdef TEST_YESCRYPT_ENCODING 217 | { 218 | uint8_t *setting; 219 | yescrypt_binary_t key = {.uc={ 220 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, 221 | 17,18,19,20,21,22,23,24,25,26,27,28,255,128,64,32}}; 222 | 223 | for (i = 0; i < 18; i++) { 224 | uint32_t N_log2 = (i < 14) ? (16 - i) : 2; 225 | uint32_t r = (i < 8) ? (8 - i) : (1 + (i & 1)); 226 | uint32_t p = (i & 1) ? 1 : YESCRYPT_P; 227 | yescrypt_flags_t flags = YESCRYPT_DEFAULTS; 228 | if ((int)p - (i / 2) > 1) 229 | p -= i / 2; 230 | if (i & 2) { 231 | flags = YESCRYPT_WORM; 232 | } else { 233 | while ((1ULL << N_log2) / p <= 3) 234 | N_log2++; 235 | } 236 | yescrypt_params_t params = 237 | {flags, (uint64_t)1 << N_log2, r, p, 0, 0, 0}; 238 | setting = yescrypt_encode_params(¶ms, 239 | (const uint8_t *)"WZaPV7LSUEKMo34.", 16 - (i & 15)); 240 | if (i == 0) 241 | printf("'%s'\n", (char *)setting); 242 | if (!setting) 243 | printf("%d yescrypt_encode_params() = NULL\n", i); 244 | if (setting) { 245 | uint8_t *hash = yescrypt( 246 | (const uint8_t *)"pleaseletmein", setting); 247 | printf("Plaintext: '%s'\n", (char *)hash); 248 | hash = (uint8_t *)strdup((char *)hash); 249 | if (!hash || strcmp( 250 | (char *)hash, (char *)yescrypt( 251 | (const uint8_t *)"pleaseletmein", hash))) 252 | puts("Validation FAILED"); 253 | uint8_t *orig = (uint8_t *)strdup((char *)hash); 254 | if (!yescrypt_reencrypt(hash, NULL, &key)) 255 | printf("%d yescrypt_reencrypt() = NULL\n", i); 256 | printf("Encrypted: '%s'\n", (char *)hash); 257 | yescrypt_local_t local; 258 | if (yescrypt_init_local(&local)) { 259 | puts("yescrypt_init_local() FAILED"); 260 | return 1; 261 | } 262 | uint8_t buf[128]; 263 | if (strcmp((char *)hash, (char *)yescrypt_r( 264 | NULL, &local, 265 | (const uint8_t *)"pleaseletmein", 13, 266 | hash, &key, buf, sizeof(buf)))) 267 | puts("Validation of encrypted FAILED"); 268 | if (!strcmp((char *)hash, (char *)yescrypt_r( 269 | NULL, &local, 270 | (const uint8_t *)"pleaseletmein", 13, 271 | hash, NULL, buf, sizeof(buf)))) 272 | puts("Validation of encrypted " 273 | "unexpectedly succeeded"); 274 | if (!strcmp((char *)orig, (char *)yescrypt_r( 275 | NULL, &local, 276 | (const uint8_t *)"pleaseletmein", 13, 277 | orig, &key, buf, sizeof(buf)))) 278 | puts("Validation of unencrypted " 279 | "unexpectedly succeeded"); 280 | yescrypt_free_local(&local); 281 | if (!yescrypt_reencrypt(hash, &key, NULL)) 282 | printf("%d yescrypt_reencrypt() = NULL\n", i); 283 | if (strcmp((char *)hash, (char *)orig)) 284 | puts("Decryption FAILED"); 285 | free(orig); 286 | free(hash); 287 | } 288 | } 289 | 290 | printf("'%s'\n", (char *)yescrypt( 291 | (const uint8_t *)"pleaseletmein", 292 | (const uint8_t *)"$7$C6..../....SodiumChloride")); 293 | 294 | printf("'%s'\n", (char *)yescrypt( 295 | (const uint8_t *)"pleaseletmein", 296 | (const uint8_t *)"$7$06..../....SodiumChloride")); 297 | 298 | #ifdef TEST_ROM 299 | uint64_t rom_bytes = 256 * (1024ULL*1024); 300 | uint64_t ram_bytes = 2 * (1024ULL*1024); 301 | uint32_t r; 302 | uint64_t NROM_log2, N_log2; 303 | yescrypt_shared_t shared; 304 | yescrypt_local_t local; 305 | 306 | NROM_log2 = 0; 307 | while (((rom_bytes >> NROM_log2) & 0xff) == 0) 308 | NROM_log2++; 309 | r = rom_bytes >> (7 + NROM_log2); 310 | while (r < 5 && NROM_log2 > 0) { 311 | r <<= 1; 312 | NROM_log2--; 313 | } 314 | rom_bytes = (uint64_t)r << (7 + NROM_log2); 315 | 316 | N_log2 = 0; 317 | while (((uint64_t)r << (7 + N_log2)) < ram_bytes) 318 | N_log2++; 319 | ram_bytes = (uint64_t)r << (7 + N_log2); 320 | 321 | printf("r=%u N=2^%u NROM=2^%u\n", r, 322 | (unsigned int)N_log2, (unsigned int)NROM_log2); 323 | 324 | printf("Will use %.2f KiB ROM\n", rom_bytes / 1024.0); 325 | printf(" %.2f KiB RAM\n", ram_bytes / 1024.0); 326 | 327 | printf("Initializing ROM ..."); 328 | fflush(stdout); 329 | yescrypt_params_t rom_params = { YESCRYPT_DEFAULTS, 330 | 0, r, YESCRYPT_PROM, 0, 0, (uint64_t)1 << NROM_log2 }; 331 | if (yescrypt_init_shared(&shared, 332 | (const uint8_t *)"local param", 12, &rom_params)) { 333 | puts(" FAILED"); 334 | return 1; 335 | } 336 | yescrypt_binary_t *digest = yescrypt_digest_shared(&shared); 337 | printf(" DONE (%02x%02x%02x%02x)\n", 338 | digest->uc[0], digest->uc[1], digest->uc[2], digest->uc[3]); 339 | 340 | if (yescrypt_init_local(&local)) { 341 | puts("FAILED"); 342 | return 1; 343 | } 344 | 345 | yescrypt_params_t params = rom_params; 346 | params.flags = YESCRYPT_FLAGS; 347 | params.N = (uint64_t)1 << N_log2; 348 | params.p = YESCRYPT_P; 349 | setting = yescrypt_encode_params(¶ms, 350 | (const uint8_t *)"WZaPV7LSUEKMo34.", 16); 351 | printf("'%s'\n", (char *)setting); 352 | 353 | uint8_t hash[128]; 354 | 355 | printf("'%s'\n", (char *)yescrypt_r(&shared, &local, 356 | (const uint8_t *)"pleaseletmein", 13, setting, NULL, 357 | hash, sizeof(hash))); 358 | 359 | #ifdef TEST_ROM_PREALLOC 360 | yescrypt_free_shared(&shared); 361 | 362 | shared.aligned_size = ((uint64_t)1 << NROM_log2) * 128 * r; 363 | shared.base_size = shared.aligned_size + 63; 364 | uint8_t *where = shared.base = malloc(shared.base_size); 365 | where += 63; 366 | where = shared.aligned = where - ((uintptr_t)where & 63); 367 | 368 | printf("Initializing ROM in preallocated memory ..."); 369 | fflush(stdout); 370 | rom_params.flags |= YESCRYPT_SHARED_PREALLOCATED; 371 | if (yescrypt_init_shared(&shared, 372 | (const uint8_t *)"local param", 12, &rom_params)) { 373 | puts(" FAILED"); 374 | return 1; 375 | } 376 | digest = yescrypt_digest_shared(&shared); 377 | printf(" DONE (%02x%02x%02x%02x)\n", 378 | digest->uc[0], digest->uc[1], digest->uc[2], digest->uc[3]); 379 | 380 | if ((void *)where != shared.aligned) 381 | puts("YESCRYPT_SHARED_PREALLOCATED failed"); 382 | #endif 383 | 384 | printf("'%s'\n", (char *)yescrypt_r(&shared, &local, 385 | (const uint8_t *)"pleaseletmein", 13, setting, NULL, 386 | hash, sizeof(hash))); 387 | 388 | printf("'%s'\n", (char *)yescrypt_r(&shared, &local, 389 | (const uint8_t *)"pleaseletmeIn", 13, setting, NULL, 390 | hash, sizeof(hash))); 391 | 392 | setting = yescrypt_encode_params(¶ms, 393 | (const uint8_t *)"WZaPV7LSUEIMo34.", 16); 394 | 395 | printf("'%s'\n", (char *)yescrypt_r(&shared, &local, 396 | (const uint8_t *)"pleaseletmein", 13, setting, NULL, 397 | hash, sizeof(hash))); 398 | 399 | printf("'%s'\n", (char *)yescrypt_r(&shared, &local, 400 | (const uint8_t *)"pleaseletmeIn", 13, setting, NULL, 401 | hash, sizeof(hash))); 402 | 403 | params.N = 4; 404 | params.NROM *= params.r; 405 | params.r = 1; 406 | params.p = 1; 407 | setting = yescrypt_encode_params(¶ms, 408 | (const uint8_t *)"WZaPV7LSUEKMo34.", 16); 409 | 410 | printf("'%s'\n", (char *)yescrypt_r(&shared, &local, 411 | (const uint8_t *)"pleaseletmein", 13, setting, NULL, 412 | hash, sizeof(hash))); 413 | #endif 414 | } 415 | #endif 416 | 417 | return 0; 418 | } 419 | -------------------------------------------------------------------------------- /userom.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2013-2018 Alexander Peslyak 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted. 7 | * 8 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 9 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 12 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 13 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 14 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 15 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 16 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 17 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 18 | * SUCH DAMAGE. 19 | */ 20 | 21 | #define YESCRYPT_FLAGS YESCRYPT_DEFAULTS 22 | //#define YESCRYPT_FLAGS YESCRYPT_WORM 23 | //#define YESCRYPT_FLAGS 0 24 | 25 | #define ROM_SHM_KEY 0x7965730a 26 | 27 | //#define DISABLE_ROM 28 | //#define DUMP_LOCAL 29 | 30 | #include 31 | #include /* for atoi() */ 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "yescrypt.h" 43 | 44 | #ifdef _OPENMP 45 | #include 46 | 47 | #define NSAVE 1000 48 | 49 | static uint64_t time_us(void) 50 | { 51 | struct timespec t; 52 | #ifdef CLOCK_MONOTONIC_RAW 53 | if (clock_gettime(CLOCK_MONOTONIC_RAW, &t)) 54 | return 0; 55 | #else 56 | if (clock_gettime(CLOCK_MONOTONIC, &t)) 57 | return 0; 58 | #endif 59 | return 1 + (uint64_t)t.tv_sec * 1000000 + t.tv_nsec / 1000; 60 | } 61 | #endif 62 | 63 | int main(int argc, const char * const *argv) 64 | { 65 | #if 0 66 | uint64_t rom_bytes = 112 * (1024ULL*1024*1024); 67 | uint64_t ram_bytes = 1 * (1024ULL*1024); 68 | #else 69 | uint64_t rom_bytes = 3 * (1024ULL*1024*1024); 70 | uint64_t ram_bytes = 2 * (1024ULL*1024); 71 | #endif 72 | uint32_t r, min_r; 73 | uint64_t NROM_log2, N_log2; 74 | yescrypt_shared_t shared_s; 75 | yescrypt_shared_t *shared = NULL; 76 | #ifndef DISABLE_ROM 77 | int shmid; 78 | #endif 79 | const char *rom_filename = NULL; 80 | int rom_fd; 81 | yescrypt_binary_t key = {.uc={ 82 | 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, 83 | 17,18,19,20,21,22,23,24,25,26,27,28,255,128,64,32}}; 84 | 85 | if (argc > 1) 86 | rom_bytes = atoi(argv[1]) * (1024ULL*1024*1024); 87 | if (argc > 2) 88 | ram_bytes = atoi(argv[2]) * (1024ULL*1024); 89 | if (argc > 3 && rom_bytes) 90 | rom_filename = argv[3]; 91 | 92 | r = 16; 93 | min_r = 9; 94 | if (rom_filename) 95 | min_r = 8 * 64; 96 | 97 | NROM_log2 = 0; 98 | if (rom_bytes) { 99 | while (((rom_bytes >> NROM_log2) & 0xff) == 0) 100 | NROM_log2++; 101 | r = rom_bytes >> (7 + NROM_log2); 102 | while (r < min_r && NROM_log2 > 0) { 103 | r <<= 1; 104 | NROM_log2--; 105 | } 106 | rom_bytes = (uint64_t)r << (7 + NROM_log2); 107 | } 108 | 109 | N_log2 = 0; 110 | while (((uint64_t)r << (7 + N_log2)) < ram_bytes) 111 | N_log2++; 112 | ram_bytes = (uint64_t)r << (7 + N_log2); 113 | 114 | printf("r=%u N=2^%u NROM=2^%u\n", r, 115 | (unsigned int)N_log2, (unsigned int)NROM_log2); 116 | 117 | #ifdef DISABLE_ROM 118 | rom_bytes = 0; 119 | #endif 120 | 121 | printf("Will use %.2f KiB ROM\n", rom_bytes / 1024.0); 122 | printf(" %.2f KiB RAM\n", ram_bytes / 1024.0); 123 | 124 | #ifndef DISABLE_ROM 125 | if (rom_filename) { 126 | rom_fd = open(rom_filename, O_RDONLY); 127 | if (rom_fd < 0) { 128 | perror("open"); 129 | return 1; 130 | } 131 | 132 | int flags = 133 | #ifdef MAP_NOCORE 134 | MAP_NOCORE | 135 | #endif 136 | #ifdef MAP_HUGETLB 137 | MAP_HUGETLB | 138 | #endif 139 | MAP_SHARED; 140 | void *p = mmap(NULL, rom_bytes, PROT_READ, flags, rom_fd, 0); 141 | #ifdef MAP_HUGETLB 142 | if (p == MAP_FAILED) 143 | p = mmap(NULL, rom_bytes, PROT_READ, 144 | flags & ~MAP_HUGETLB, rom_fd, 0); 145 | #endif 146 | if (p == MAP_FAILED) { 147 | perror("mmap"); 148 | close(rom_fd); 149 | return 1; 150 | } 151 | close(rom_fd); 152 | 153 | shared = &shared_s; 154 | shared->base = shared->aligned = p; 155 | shared->aligned_size = rom_bytes; 156 | } else if (rom_bytes) { 157 | shared = &shared_s; 158 | shared->aligned_size = rom_bytes; 159 | shmid = shmget(ROM_SHM_KEY, shared->aligned_size, 0); 160 | if (shmid == -1) { 161 | perror("shmget"); 162 | return 1; 163 | } 164 | 165 | shared->base = shared->aligned = shmat(shmid, NULL, SHM_RDONLY); 166 | if (shared->base == (void *)-1) { 167 | perror("shmat"); 168 | return 1; 169 | } 170 | } 171 | #endif 172 | 173 | { 174 | yescrypt_local_t local; 175 | const uint8_t *setting; 176 | 177 | if (yescrypt_init_local(&local)) { 178 | puts("yescrypt_init_local() FAILED"); 179 | return 1; 180 | } 181 | 182 | yescrypt_params_t params = { 183 | .flags = YESCRYPT_FLAGS, 184 | .N = (uint64_t)1 << N_log2, 185 | .NROM = NROM_log2 ? ((uint64_t)1 << NROM_log2) : 0, 186 | .r = r, 187 | .p = 1 }; 188 | setting = yescrypt_encode_params(¶ms, 189 | (const uint8_t *)"WZaPV7LSUEKMo34.", 16); 190 | 191 | { 192 | uint8_t hash[128]; 193 | if (!yescrypt_r(shared, &local, 194 | (const uint8_t *)"pleaseletmein", 13, setting, NULL, 195 | hash, sizeof(hash))) { 196 | puts("yescrypt_r() FAILED"); 197 | return 1; 198 | } 199 | printf("Plaintext: '%s'\n", (char *)hash); 200 | if (!yescrypt_r(shared, &local, 201 | (const uint8_t *)"pleaseletmein", 13, setting, &key, 202 | hash, sizeof(hash))) { 203 | puts("yescrypt_r() FAILED"); 204 | return 1; 205 | } 206 | printf("Encrypted: '%s'\n", (char *)hash); 207 | } 208 | 209 | #ifdef DUMP_LOCAL 210 | #if 0 211 | fwrite(local.aligned, local.aligned_size, 1, stderr); 212 | #else 213 | /* Skip B, dump only V */ 214 | if (local.aligned_size >= ram_bytes + 128 * r) 215 | fwrite((char *)local.aligned + 128 * r, ram_bytes, 216 | 1, stderr); 217 | #endif 218 | #endif 219 | 220 | puts("Benchmarking 1 thread ..."); 221 | 222 | clock_t clk_tck = sysconf(_SC_CLK_TCK); 223 | struct tms start_tms, end_tms; 224 | clock_t start = times(&start_tms), end; 225 | unsigned int i, n; 226 | unsigned long long count; 227 | #ifdef _OPENMP 228 | char save[NSAVE][128]; 229 | unsigned int nsave = 0; 230 | #endif 231 | unsigned int seed = start * 1812433253U; 232 | 233 | n = 1; 234 | count = 0; 235 | do { 236 | for (i = 0; i < n; i++) { 237 | unsigned int j = count + i; 238 | char p[32]; 239 | uint8_t hash[128]; 240 | snprintf(p, sizeof(p), "%u", seed + j); 241 | #ifdef _OPENMP 242 | const uint8_t *h = 243 | #endif 244 | yescrypt_r(shared, &local, 245 | (const uint8_t *)p, strlen(p), 246 | setting, &key, hash, sizeof(hash)); 247 | #ifdef _OPENMP 248 | if (j < NSAVE) { 249 | save[j][0] = 0; 250 | strncat(save[j], (char *)h, 251 | sizeof(save[j]) - 1); 252 | nsave = j; 253 | } 254 | #endif 255 | } 256 | count += n; 257 | 258 | end = times(&end_tms); 259 | n <<= 1; 260 | } while (end - start < clk_tck * 2); 261 | 262 | clock_t start_v = start_tms.tms_utime + start_tms.tms_stime + 263 | start_tms.tms_cutime + start_tms.tms_cstime; 264 | clock_t end_v = end_tms.tms_utime + end_tms.tms_stime + 265 | end_tms.tms_cutime + end_tms.tms_cstime; 266 | 267 | printf("%llu c/s real, %llu c/s virtual " 268 | "(%llu hashes in %.2f seconds)\n", 269 | count * clk_tck / (end - start), 270 | count * clk_tck / (end_v - start_v), 271 | count, (double)(end - start) / clk_tck); 272 | 273 | #ifdef _OPENMP 274 | unsigned int nt = omp_get_max_threads(); 275 | 276 | printf("Benchmarking %u thread%s ...\n", 277 | nt, nt == 1 ? "" : "s"); 278 | 279 | typedef struct { 280 | yescrypt_local_t local; 281 | uint64_t min, max, total; 282 | } thread_data_s; 283 | union { 284 | thread_data_s s; 285 | uint8_t cachelines[2][64]; /* avoid false sharing */ 286 | } thread_data[nt]; /* tricky to align this when on stack */ 287 | 288 | unsigned int t; 289 | for (t = 0; t < nt; t++) { 290 | thread_data_s *td = &thread_data[t].s; 291 | if (yescrypt_init_local(&td->local)) { 292 | puts("yescrypt_init_local() FAILED"); 293 | return 1; 294 | } 295 | td->min = ~(uint64_t)0; td->max = 0; td->total = 0; 296 | } 297 | 298 | unsigned long long count1 = count, count_restart = 0; 299 | 300 | if (!geteuid()) { 301 | puts("Running as root, so trying to set SCHED_RR"); 302 | #pragma omp parallel 303 | { 304 | struct sched_param param = { .sched_priority = 1 }; 305 | if (sched_setscheduler(getpid(), SCHED_RR, ¶m)) 306 | perror("sched_setscheduler"); 307 | } 308 | } 309 | 310 | start = times(&start_tms); 311 | 312 | n = count * omp_get_max_threads(); 313 | count = 0; 314 | do { 315 | #pragma omp parallel for default(none) private(i) shared(n, shared, thread_data, setting, seed, count, save, nsave, key) 316 | for (i = 0; i < n; i++) { 317 | unsigned int j = count + i; 318 | char p[32]; 319 | uint8_t hash[128]; 320 | snprintf(p, sizeof(p), "%u", seed + j); 321 | thread_data_s *td = &thread_data[omp_get_thread_num()].s; 322 | uint64_t start1 = time_us(); 323 | #if 1 324 | const char *h = (const char *)yescrypt_r( 325 | shared, &td->local, 326 | (const uint8_t *)p, strlen(p), 327 | setting, &key, hash, sizeof(hash)); 328 | #else 329 | yescrypt_local_t local; 330 | yescrypt_init_local(&local); 331 | const char *h = (const char *)yescrypt_r( 332 | shared, &local, 333 | (const uint8_t *)p, strlen(p), 334 | setting, &key, hash, sizeof(hash)); 335 | yescrypt_free_local(&local); 336 | #endif 337 | uint64_t end1 = time_us(); 338 | if (end1 < start1) 339 | end1 = start1; 340 | uint64_t diff1 = end1 - start1; 341 | td->total += diff1; 342 | if (diff1 < td->min) 343 | td->min = diff1; 344 | if (diff1 > td->max) 345 | td->max = diff1; 346 | if (j < nsave && strcmp(save[j], h)) { 347 | #pragma omp critical 348 | printf("Mismatch at %u, %s != %s\n", 349 | j, save[j], h); 350 | } 351 | } 352 | 353 | count += n; 354 | if ((count - n) < count1 && count >= count1) { 355 | /* Disregard our repeat of single thread's results (could be partially cached 356 | * by same core, but OTOH other cores not yet warmed up to full clock rate). */ 357 | start = times(&start_tms); 358 | count_restart = count; 359 | for (t = 0; t < nt; t++) { 360 | thread_data_s *td = &thread_data[t].s; 361 | td->min = ~(uint64_t)0; td->max = 0; td->total = 0; 362 | } 363 | } else { 364 | n <<= 1; 365 | } 366 | 367 | end = times(&end_tms); 368 | } while (end - start < clk_tck); 369 | 370 | if (!count_restart) 371 | puts("Didn't reach single-thread's hash count"); 372 | count -= count_restart; 373 | 374 | start_v = start_tms.tms_utime + start_tms.tms_stime + 375 | start_tms.tms_cutime + start_tms.tms_cstime; 376 | end_v = end_tms.tms_utime + end_tms.tms_stime + 377 | end_tms.tms_cutime + end_tms.tms_cstime; 378 | 379 | printf("%llu c/s real, %llu c/s virtual " 380 | "(%llu hashes in %.2f seconds)\n", 381 | count * clk_tck / (end - start), 382 | count * clk_tck / (end_v - start_v), 383 | count, (double)(end - start) / clk_tck); 384 | 385 | uint64_t min = ~(uint64_t)0, max = 0, total = 0; 386 | for (t = 0; t < nt; t++) { 387 | thread_data_s *td = &thread_data[t].s; 388 | total += td->total; 389 | if (td->min < min) 390 | min = td->min; 391 | if (td->max > max) 392 | max = td->max; 393 | } 394 | printf("min %.3f ms, avg %.3f ms, max %.3f ms\n", 395 | min / 1000.0, total / 1000.0 / count, max / 1000.0); 396 | #endif 397 | } 398 | 399 | if (rom_filename && munmap(shared->base, rom_bytes)) { 400 | perror("munmap"); 401 | return 1; 402 | } 403 | 404 | return 0; 405 | } 406 | -------------------------------------------------------------------------------- /yescrypt-common.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2013-2018 Alexander Peslyak 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted. 7 | * 8 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 9 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 12 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 13 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 14 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 15 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 16 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 17 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 18 | * SUCH DAMAGE. 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | #include "insecure_memzero.h" 25 | #include "sha256.h" 26 | 27 | #define YESCRYPT_INTERNAL 28 | #include "yescrypt.h" 29 | 30 | #define BYTES2CHARS(bytes) ((((bytes) * 8) + 5) / 6) 31 | 32 | #define HASH_SIZE sizeof(yescrypt_binary_t) /* bytes */ 33 | #define HASH_LEN BYTES2CHARS(HASH_SIZE) /* base-64 chars */ 34 | 35 | /* 36 | * "$y$", up to 8 params of up to 6 chars each, '$', salt 37 | * Alternatively, but that's smaller: 38 | * "$7$", 3 params encoded as 1+5+5 chars, salt 39 | */ 40 | #define PREFIX_LEN (3 + 8 * 6 + 1 + BYTES2CHARS(32)) 41 | 42 | static const char * const itoa64 = 43 | "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 44 | 45 | static const uint8_t atoi64_partial[77] = { 46 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 47 | 64, 64, 64, 64, 64, 64, 64, 48 | 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 49 | 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 50 | 64, 64, 64, 64, 64, 64, 51 | 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 52 | 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 53 | }; 54 | 55 | static uint8_t *encode64_uint32(uint8_t *dst, size_t dstlen, 56 | uint32_t src, uint32_t min) 57 | { 58 | uint32_t start = 0, end = 47, chars = 1, bits = 0; 59 | 60 | if (src < min) 61 | return NULL; 62 | src -= min; 63 | 64 | do { 65 | uint32_t count = (end + 1 - start) << bits; 66 | if (src < count) 67 | break; 68 | if (start >= 63) 69 | return NULL; 70 | start = end + 1; 71 | end = start + (62 - end) / 2; 72 | src -= count; 73 | chars++; 74 | bits += 6; 75 | } while (1); 76 | 77 | if (dstlen <= chars) /* require room for a NUL terminator */ 78 | return NULL; 79 | 80 | *dst++ = itoa64[start + (src >> bits)]; 81 | 82 | while (--chars) { 83 | bits -= 6; 84 | *dst++ = itoa64[(src >> bits) & 0x3f]; 85 | } 86 | 87 | *dst = 0; /* NUL terminate just in case */ 88 | 89 | return dst; 90 | } 91 | 92 | static inline uint32_t atoi64(uint8_t src) 93 | { 94 | if (src >= '.' && src <= 'z') 95 | return atoi64_partial[src - '.']; 96 | 97 | return 64; 98 | } 99 | 100 | static const uint8_t *decode64_uint32(uint32_t *dst, 101 | const uint8_t *src, uint32_t min) 102 | { 103 | uint32_t start = 0, end = 47, chars = 1, bits = 0; 104 | uint32_t c; 105 | 106 | c = atoi64(*src++); 107 | if (c > 63) 108 | goto fail; 109 | 110 | *dst = min; 111 | while (c > end) { 112 | *dst += (end + 1 - start) << bits; 113 | start = end + 1; 114 | end = start + (62 - end) / 2; 115 | chars++; 116 | bits += 6; 117 | } 118 | 119 | *dst += (c - start) << bits; 120 | 121 | while (--chars) { 122 | c = atoi64(*src++); 123 | if (c > 63) 124 | goto fail; 125 | bits -= 6; 126 | *dst += c << bits; 127 | } 128 | 129 | return src; 130 | 131 | fail: 132 | *dst = 0; 133 | return NULL; 134 | } 135 | 136 | static uint8_t *encode64_uint32_fixed(uint8_t *dst, size_t dstlen, 137 | uint32_t src, uint32_t srcbits) 138 | { 139 | uint32_t bits; 140 | 141 | for (bits = 0; bits < srcbits; bits += 6) { 142 | if (dstlen < 2) 143 | return NULL; 144 | *dst++ = itoa64[src & 0x3f]; 145 | dstlen--; 146 | src >>= 6; 147 | } 148 | 149 | if (src || dstlen < 1) 150 | return NULL; 151 | 152 | *dst = 0; /* NUL terminate just in case */ 153 | 154 | return dst; 155 | } 156 | 157 | static uint8_t *encode64(uint8_t *dst, size_t dstlen, 158 | const uint8_t *src, size_t srclen) 159 | { 160 | size_t i; 161 | 162 | for (i = 0; i < srclen; ) { 163 | uint8_t *dnext; 164 | uint32_t value = 0, bits = 0; 165 | do { 166 | value |= (uint32_t)src[i++] << bits; 167 | bits += 8; 168 | } while (bits < 24 && i < srclen); 169 | dnext = encode64_uint32_fixed(dst, dstlen, value, bits); 170 | if (!dnext) 171 | return NULL; 172 | dstlen -= dnext - dst; 173 | dst = dnext; 174 | } 175 | 176 | if (dstlen < 1) 177 | return NULL; 178 | 179 | *dst = 0; /* NUL terminate just in case */ 180 | 181 | return dst; 182 | } 183 | 184 | static const uint8_t *decode64_uint32_fixed(uint32_t *dst, uint32_t dstbits, 185 | const uint8_t *src) 186 | { 187 | uint32_t bits; 188 | 189 | *dst = 0; 190 | for (bits = 0; bits < dstbits; bits += 6) { 191 | uint32_t c = atoi64(*src++); 192 | if (c > 63) { 193 | *dst = 0; 194 | return NULL; 195 | } 196 | *dst |= c << bits; 197 | } 198 | 199 | return src; 200 | } 201 | 202 | static const uint8_t *decode64(uint8_t *dst, size_t *dstlen, 203 | const uint8_t *src, size_t srclen) 204 | { 205 | size_t dstpos = 0; 206 | 207 | while (dstpos <= *dstlen && srclen) { 208 | uint32_t value = 0, bits = 0; 209 | while (srclen--) { 210 | uint32_t c = atoi64(*src); 211 | if (c > 63) { 212 | srclen = 0; 213 | break; 214 | } 215 | src++; 216 | value |= c << bits; 217 | bits += 6; 218 | if (bits >= 24) 219 | break; 220 | } 221 | if (!bits) 222 | break; 223 | if (bits < 12) /* must have at least one full byte */ 224 | goto fail; 225 | while (dstpos++ < *dstlen) { 226 | *dst++ = value; 227 | value >>= 8; 228 | bits -= 8; 229 | if (bits < 8) { /* 2 or 4 */ 230 | if (value) /* must be 0 */ 231 | goto fail; 232 | bits = 0; 233 | break; 234 | } 235 | } 236 | if (bits) 237 | goto fail; 238 | } 239 | 240 | if (!srclen && dstpos <= *dstlen) { 241 | *dstlen = dstpos; 242 | return src; 243 | } 244 | 245 | fail: 246 | *dstlen = 0; 247 | return NULL; 248 | } 249 | 250 | typedef enum { ENC = 1, DEC = -1 } encrypt_dir_t; 251 | 252 | static void memxor(unsigned char *dst, unsigned char *src, size_t size) 253 | { 254 | while (size--) 255 | *dst++ ^= *src++; 256 | } 257 | 258 | static void encrypt(unsigned char *data, size_t datalen, 259 | const yescrypt_binary_t *key, encrypt_dir_t dir) 260 | { 261 | SHA256_CTX ctx; 262 | unsigned char f[32 + 4]; 263 | size_t halflen, which; 264 | unsigned char mask, round, target; 265 | 266 | if (!datalen) 267 | return; 268 | if (datalen > 64) 269 | datalen = 64; 270 | 271 | halflen = datalen >> 1; 272 | 273 | which = 0; /* offset to half we are working on (0 or halflen) */ 274 | mask = 0x0f; /* current half's extra nibble mask if datalen is odd */ 275 | 276 | round = 0; 277 | target = 5; /* 6 rounds due to Jacques Patarin's CRYPTO 2004 paper */ 278 | 279 | if (dir == DEC) { 280 | which = halflen; /* even round count, so swap the halves */ 281 | mask ^= 0xff; 282 | 283 | round = target; 284 | target = 0; 285 | } 286 | 287 | f[32] = 0; 288 | f[33] = sizeof(*key); 289 | f[34] = datalen; 290 | 291 | do { 292 | SHA256_Init(&ctx); 293 | f[35] = round; 294 | SHA256_Update(&ctx, &f[32], 4); 295 | SHA256_Update(&ctx, key, sizeof(*key)); 296 | SHA256_Update(&ctx, &data[which], halflen); 297 | if (datalen & 1) { 298 | f[0] = data[datalen - 1] & mask; 299 | SHA256_Update(&ctx, f, 1); 300 | } 301 | SHA256_Final(f, &ctx); 302 | which ^= halflen; 303 | memxor(&data[which], f, halflen); 304 | if (datalen & 1) { 305 | mask ^= 0xff; 306 | data[datalen - 1] ^= f[halflen] & mask; 307 | } 308 | if (round == target) 309 | break; 310 | round += dir; 311 | } while (1); 312 | 313 | /* ctx is presumably zeroized by SHA256_Final() */ 314 | insecure_memzero(f, sizeof(f)); 315 | } 316 | 317 | uint8_t *yescrypt_r(const yescrypt_shared_t *shared, yescrypt_local_t *local, 318 | const uint8_t *passwd, size_t passwdlen, 319 | const uint8_t *setting, 320 | const yescrypt_binary_t *key, 321 | uint8_t *buf, size_t buflen) 322 | { 323 | unsigned char saltbin[64], hashbin[32]; 324 | const uint8_t *src, *saltstr, *salt; 325 | uint8_t *dst; 326 | size_t need, prefixlen, saltstrlen, saltlen; 327 | yescrypt_params_t params = { .p = 1 }; 328 | 329 | if (setting[0] != '$' || 330 | (setting[1] != '7' && setting[1] != 'y') || 331 | setting[2] != '$') 332 | return NULL; 333 | src = setting + 3; 334 | 335 | if (setting[1] == '7') { 336 | uint32_t N_log2 = atoi64(*src++); 337 | if (N_log2 < 1 || N_log2 > 63) 338 | return NULL; 339 | params.N = (uint64_t)1 << N_log2; 340 | 341 | src = decode64_uint32_fixed(¶ms.r, 30, src); 342 | if (!src) 343 | return NULL; 344 | 345 | src = decode64_uint32_fixed(¶ms.p, 30, src); 346 | if (!src) 347 | return NULL; 348 | 349 | if (key) 350 | return NULL; 351 | } else { 352 | uint32_t flavor, N_log2; 353 | 354 | src = decode64_uint32(&flavor, src, 0); 355 | if (!src) 356 | return NULL; 357 | 358 | if (flavor < YESCRYPT_RW) { 359 | params.flags = flavor; 360 | } else if (flavor <= YESCRYPT_RW + (YESCRYPT_RW_FLAVOR_MASK >> 2)) { 361 | params.flags = YESCRYPT_RW + ((flavor - YESCRYPT_RW) << 2); 362 | } else { 363 | return NULL; 364 | } 365 | 366 | src = decode64_uint32(&N_log2, src, 1); 367 | if (!src || N_log2 > 63) 368 | return NULL; 369 | params.N = (uint64_t)1 << N_log2; 370 | 371 | src = decode64_uint32(¶ms.r, src, 1); 372 | if (!src) 373 | return NULL; 374 | 375 | if (*src != '$') { 376 | uint32_t have; 377 | 378 | src = decode64_uint32(&have, src, 1); 379 | if (!src) 380 | return NULL; 381 | 382 | if (have & 1) { 383 | src = decode64_uint32(¶ms.p, src, 2); 384 | if (!src) 385 | return NULL; 386 | } 387 | 388 | if (have & 2) { 389 | src = decode64_uint32(¶ms.t, src, 1); 390 | if (!src) 391 | return NULL; 392 | } 393 | 394 | if (have & 4) { 395 | src = decode64_uint32(¶ms.g, src, 1); 396 | if (!src) 397 | return NULL; 398 | } 399 | 400 | if (have & 8) { 401 | uint32_t NROM_log2; 402 | src = decode64_uint32(&NROM_log2, src, 1); 403 | if (!src || NROM_log2 > 63) 404 | return NULL; 405 | params.NROM = (uint64_t)1 << NROM_log2; 406 | } 407 | } 408 | 409 | if (*src++ != '$') 410 | return NULL; 411 | } 412 | 413 | prefixlen = src - setting; 414 | 415 | saltstr = src; 416 | src = (uint8_t *)strrchr((char *)saltstr, '$'); 417 | if (src) 418 | saltstrlen = src - saltstr; 419 | else 420 | saltstrlen = strlen((char *)saltstr); 421 | 422 | if (setting[1] == '7') { 423 | salt = saltstr; 424 | saltlen = saltstrlen; 425 | } else { 426 | const uint8_t *saltend; 427 | 428 | saltlen = sizeof(saltbin); 429 | saltend = decode64(saltbin, &saltlen, saltstr, saltstrlen); 430 | 431 | if (!saltend || (size_t)(saltend - saltstr) != saltstrlen) 432 | goto fail; 433 | 434 | salt = saltbin; 435 | 436 | if (key) 437 | encrypt(saltbin, saltlen, key, ENC); 438 | } 439 | 440 | need = prefixlen + saltstrlen + 1 + HASH_LEN + 1; 441 | if (need > buflen || need < saltstrlen) 442 | goto fail; 443 | 444 | if (yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen, 445 | ¶ms, hashbin, sizeof(hashbin))) 446 | goto fail; 447 | 448 | if (key) { 449 | insecure_memzero(saltbin, sizeof(saltbin)); 450 | encrypt(hashbin, sizeof(hashbin), key, ENC); 451 | } 452 | 453 | dst = buf; 454 | memcpy(dst, setting, prefixlen + saltstrlen); 455 | dst += prefixlen + saltstrlen; 456 | *dst++ = '$'; 457 | 458 | dst = encode64(dst, buflen - (dst - buf), hashbin, sizeof(hashbin)); 459 | insecure_memzero(hashbin, sizeof(hashbin)); 460 | if (!dst || dst >= buf + buflen) 461 | return NULL; 462 | 463 | *dst = 0; /* NUL termination */ 464 | 465 | return buf; 466 | 467 | fail: 468 | insecure_memzero(saltbin, sizeof(saltbin)); 469 | insecure_memzero(hashbin, sizeof(hashbin)); 470 | return NULL; 471 | } 472 | 473 | uint8_t *yescrypt(const uint8_t *passwd, const uint8_t *setting) 474 | { 475 | /* prefix, '$', hash, NUL */ 476 | static uint8_t buf[PREFIX_LEN + 1 + HASH_LEN + 1]; 477 | yescrypt_local_t local; 478 | uint8_t *retval; 479 | 480 | if (yescrypt_init_local(&local)) 481 | return NULL; 482 | retval = yescrypt_r(NULL, &local, 483 | passwd, strlen((char *)passwd), setting, NULL, buf, sizeof(buf)); 484 | if (yescrypt_free_local(&local)) 485 | return NULL; 486 | return retval; 487 | } 488 | 489 | uint8_t *yescrypt_reencrypt(uint8_t *hash, 490 | const yescrypt_binary_t *from_key, 491 | const yescrypt_binary_t *to_key) 492 | { 493 | uint8_t *retval = NULL, *saltstart, *hashstart; 494 | const uint8_t *hashend; 495 | unsigned char saltbin[64], hashbin[32]; 496 | size_t saltstrlen, saltlen = 0, hashlen; 497 | 498 | if (strncmp((char *)hash, "$y$", 3)) 499 | return NULL; 500 | 501 | saltstart = NULL; 502 | hashstart = (uint8_t *)strrchr((char *)hash, '$'); 503 | if (hashstart) { 504 | if (hashstart > (uint8_t *)hash) { 505 | saltstart = hashstart - 1; 506 | while (*saltstart != '$' && saltstart > hash) 507 | saltstart--; 508 | if (*saltstart == '$') 509 | saltstart++; 510 | } 511 | hashstart++; 512 | } else { 513 | hashstart = hash; 514 | } 515 | saltstrlen = saltstart ? (hashstart - 1 - saltstart) : 0; 516 | if (saltstrlen > BYTES2CHARS(64) || 517 | strlen((char *)hashstart) != HASH_LEN) 518 | return NULL; 519 | 520 | if (saltstrlen) { 521 | const uint8_t *saltend; 522 | saltlen = sizeof(saltbin); 523 | saltend = decode64(saltbin, &saltlen, saltstart, saltstrlen); 524 | if (!saltend || *saltend != '$' || saltlen < 1 || saltlen > 64) 525 | goto out; 526 | 527 | if (from_key) 528 | encrypt(saltbin, saltlen, from_key, ENC); 529 | if (to_key) 530 | encrypt(saltbin, saltlen, to_key, DEC); 531 | } 532 | 533 | hashlen = sizeof(hashbin); 534 | hashend = decode64(hashbin, &hashlen, hashstart, HASH_LEN); 535 | if (!hashend || *hashend || hashlen != sizeof(hashbin)) 536 | goto out; 537 | 538 | if (from_key) 539 | encrypt(hashbin, hashlen, from_key, DEC); 540 | if (to_key) 541 | encrypt(hashbin, hashlen, to_key, ENC); 542 | 543 | if (saltstrlen) { 544 | if (!encode64(saltstart, saltstrlen + 1, saltbin, saltlen)) 545 | goto out; /* can't happen */ 546 | *(saltstart + saltstrlen) = '$'; 547 | } 548 | 549 | if (!encode64(hashstart, HASH_LEN + 1, hashbin, hashlen)) 550 | goto out; /* can't happen */ 551 | 552 | retval = hash; 553 | 554 | out: 555 | insecure_memzero(saltbin, sizeof(saltbin)); 556 | insecure_memzero(hashbin, sizeof(hashbin)); 557 | 558 | return retval; 559 | } 560 | 561 | static uint32_t N2log2(uint64_t N) 562 | { 563 | uint32_t N_log2; 564 | 565 | if (N < 2) 566 | return 0; 567 | 568 | N_log2 = 2; 569 | while (N >> N_log2 != 0) 570 | N_log2++; 571 | N_log2--; 572 | 573 | if (N >> N_log2 != 1) 574 | return 0; 575 | 576 | return N_log2; 577 | } 578 | 579 | uint8_t *yescrypt_encode_params_r(const yescrypt_params_t *params, 580 | const uint8_t *src, size_t srclen, 581 | uint8_t *buf, size_t buflen) 582 | { 583 | uint32_t flavor, N_log2, NROM_log2, have; 584 | uint8_t *dst; 585 | 586 | if (srclen > SIZE_MAX / 16) 587 | return NULL; 588 | 589 | if (params->flags < YESCRYPT_RW) { 590 | flavor = params->flags; 591 | } else if ((params->flags & YESCRYPT_MODE_MASK) == YESCRYPT_RW && 592 | params->flags <= (YESCRYPT_RW | YESCRYPT_RW_FLAVOR_MASK)) { 593 | flavor = YESCRYPT_RW + (params->flags >> 2); 594 | } else { 595 | return NULL; 596 | } 597 | 598 | N_log2 = N2log2(params->N); 599 | if (!N_log2) 600 | return NULL; 601 | 602 | NROM_log2 = N2log2(params->NROM); 603 | if (params->NROM && !NROM_log2) 604 | return NULL; 605 | 606 | if ((uint64_t)params->r * (uint64_t)params->p >= (1U << 30)) 607 | return NULL; 608 | 609 | dst = buf; 610 | *dst++ = '$'; 611 | *dst++ = 'y'; 612 | *dst++ = '$'; 613 | 614 | dst = encode64_uint32(dst, buflen - (dst - buf), flavor, 0); 615 | if (!dst) 616 | return NULL; 617 | 618 | dst = encode64_uint32(dst, buflen - (dst - buf), N_log2, 1); 619 | if (!dst) 620 | return NULL; 621 | 622 | dst = encode64_uint32(dst, buflen - (dst - buf), params->r, 1); 623 | if (!dst) 624 | return NULL; 625 | 626 | have = 0; 627 | if (params->p != 1) 628 | have |= 1; 629 | if (params->t) 630 | have |= 2; 631 | if (params->g) 632 | have |= 4; 633 | if (NROM_log2) 634 | have |= 8; 635 | 636 | if (have) { 637 | dst = encode64_uint32(dst, buflen - (dst - buf), have, 1); 638 | if (!dst) 639 | return NULL; 640 | } 641 | 642 | if (params->p != 1) { 643 | dst = encode64_uint32(dst, buflen - (dst - buf), params->p, 2); 644 | if (!dst) 645 | return NULL; 646 | } 647 | 648 | if (params->t) { 649 | dst = encode64_uint32(dst, buflen - (dst - buf), params->t, 1); 650 | if (!dst) 651 | return NULL; 652 | } 653 | 654 | if (params->g) { 655 | dst = encode64_uint32(dst, buflen - (dst - buf), params->g, 1); 656 | if (!dst) 657 | return NULL; 658 | } 659 | 660 | if (NROM_log2) { 661 | dst = encode64_uint32(dst, buflen - (dst - buf), NROM_log2, 1); 662 | if (!dst) 663 | return NULL; 664 | } 665 | 666 | if (dst >= buf + buflen) 667 | return NULL; 668 | 669 | *dst++ = '$'; 670 | 671 | dst = encode64(dst, buflen - (dst - buf), src, srclen); 672 | if (!dst || dst >= buf + buflen) 673 | return NULL; 674 | 675 | *dst = 0; /* NUL termination */ 676 | 677 | return buf; 678 | } 679 | 680 | uint8_t *yescrypt_encode_params(const yescrypt_params_t *params, 681 | const uint8_t *src, size_t srclen) 682 | { 683 | /* prefix, NUL */ 684 | static uint8_t buf[PREFIX_LEN + 1]; 685 | return yescrypt_encode_params_r(params, src, srclen, buf, sizeof(buf)); 686 | } 687 | 688 | int crypto_scrypt(const uint8_t *passwd, size_t passwdlen, 689 | const uint8_t *salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p, 690 | uint8_t *buf, size_t buflen) 691 | { 692 | yescrypt_local_t local; 693 | yescrypt_params_t params = { .flags = 0, .N = N, .r = r, .p = p }; 694 | int retval; 695 | 696 | if (yescrypt_init_local(&local)) 697 | return -1; 698 | retval = yescrypt_kdf(NULL, &local, 699 | passwd, passwdlen, salt, saltlen, ¶ms, buf, buflen); 700 | if (yescrypt_free_local(&local)) 701 | return -1; 702 | return retval; 703 | } 704 | -------------------------------------------------------------------------------- /yescrypt-platform.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2013-2018,2022 Alexander Peslyak 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted. 7 | * 8 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 9 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 12 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 13 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 14 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 15 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 16 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 17 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 18 | * SUCH DAMAGE. 19 | */ 20 | 21 | #ifdef __unix__ 22 | #include 23 | #endif 24 | #ifdef __linux__ 25 | #include /* for MAP_HUGE_2MB */ 26 | #endif 27 | 28 | #define HUGEPAGE_THRESHOLD (32 * 1024 * 1024) 29 | 30 | #ifdef __x86_64__ 31 | #define HUGEPAGE_SIZE (2 * 1024 * 1024) 32 | #else 33 | #undef HUGEPAGE_SIZE 34 | #endif 35 | 36 | static void *alloc_region(yescrypt_region_t *region, size_t size) 37 | { 38 | size_t base_size = size; 39 | uint8_t *base, *aligned; 40 | #ifdef MAP_ANON 41 | int flags = 42 | #ifdef MAP_NOCORE 43 | MAP_NOCORE | 44 | #endif 45 | MAP_ANON | MAP_PRIVATE; 46 | #if defined(MAP_HUGETLB) && defined(MAP_HUGE_2MB) && defined(HUGEPAGE_SIZE) 47 | size_t new_size = size; 48 | const size_t hugepage_mask = (size_t)HUGEPAGE_SIZE - 1; 49 | if (size >= HUGEPAGE_THRESHOLD && size + hugepage_mask >= size) { 50 | flags |= MAP_HUGETLB | MAP_HUGE_2MB; 51 | /* 52 | * Linux's munmap() fails on MAP_HUGETLB mappings if size is not a multiple of 53 | * huge page size, so let's round up to huge page size here. 54 | */ 55 | new_size = size + hugepage_mask; 56 | new_size &= ~hugepage_mask; 57 | } 58 | base = mmap(NULL, new_size, PROT_READ | PROT_WRITE, flags, -1, 0); 59 | if (base != MAP_FAILED) { 60 | base_size = new_size; 61 | } else if (flags & MAP_HUGETLB) { 62 | flags &= ~(MAP_HUGETLB | MAP_HUGE_2MB); 63 | base = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0); 64 | } 65 | 66 | #else 67 | base = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, -1, 0); 68 | #endif 69 | if (base == MAP_FAILED) 70 | base = NULL; 71 | aligned = base; 72 | #elif defined(HAVE_POSIX_MEMALIGN) 73 | if ((errno = posix_memalign((void **)&base, 64, size)) != 0) 74 | base = NULL; 75 | aligned = base; 76 | #else 77 | base = aligned = NULL; 78 | if (size + 63 < size) { 79 | errno = ENOMEM; 80 | } else if ((base = malloc(size + 63)) != NULL) { 81 | aligned = base + 63; 82 | aligned -= (uintptr_t)aligned & 63; 83 | } 84 | #endif 85 | region->base = base; 86 | region->aligned = aligned; 87 | region->base_size = base ? base_size : 0; 88 | region->aligned_size = base ? size : 0; 89 | return aligned; 90 | } 91 | 92 | static inline void init_region(yescrypt_region_t *region) 93 | { 94 | region->base = region->aligned = NULL; 95 | region->base_size = region->aligned_size = 0; 96 | } 97 | 98 | static int free_region(yescrypt_region_t *region) 99 | { 100 | if (region->base) { 101 | #ifdef MAP_ANON 102 | if (munmap(region->base, region->base_size)) 103 | return -1; 104 | #else 105 | free(region->base); 106 | #endif 107 | } 108 | init_region(region); 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /yescrypt-ref.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * Copyright 2013-2018 Alexander Peslyak 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | * 27 | * This file was originally written by Colin Percival as part of the Tarsnap 28 | * online backup system. 29 | * 30 | * This is the reference implementation. Its purpose is to provide a simple 31 | * human- and machine-readable specification that implementations intended 32 | * for actual use should be tested against. It is deliberately mostly not 33 | * optimized, and it is not meant to be used in production. Instead, use 34 | * yescrypt-opt.c. 35 | */ 36 | 37 | #ifdef __GNUC__ 38 | #warning "This reference implementation is deliberately mostly not optimized, nor does it make any attempt not to leave sensitive data in memory. Use yescrypt-opt.c instead unless you're testing (against) the reference implementation on purpose." 39 | #endif 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include "sha256.h" 47 | #include "sysendian.h" 48 | 49 | #define YESCRYPT_INTERNAL 50 | #include "yescrypt.h" 51 | 52 | static void blkcpy(uint32_t *dst, const uint32_t *src, size_t count) 53 | { 54 | do { 55 | *dst++ = *src++; 56 | } while (--count); 57 | } 58 | 59 | static void blkxor(uint32_t *dst, const uint32_t *src, size_t count) 60 | { 61 | do { 62 | *dst++ ^= *src++; 63 | } while (--count); 64 | } 65 | 66 | /** 67 | * salsa20(B): 68 | * Apply the Salsa20 core to the provided block. 69 | */ 70 | static void salsa20(uint32_t B[16], uint32_t rounds) 71 | { 72 | uint32_t x[16]; 73 | size_t i; 74 | 75 | /* SIMD unshuffle */ 76 | for (i = 0; i < 16; i++) 77 | x[i * 5 % 16] = B[i]; 78 | 79 | for (i = 0; i < rounds; i += 2) { 80 | #define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) 81 | /* Operate on columns */ 82 | x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); 83 | x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); 84 | 85 | x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); 86 | x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); 87 | 88 | x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); 89 | x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); 90 | 91 | x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); 92 | x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); 93 | 94 | /* Operate on rows */ 95 | x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); 96 | x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); 97 | 98 | x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); 99 | x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); 100 | 101 | x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); 102 | x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); 103 | 104 | x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); 105 | x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); 106 | #undef R 107 | } 108 | 109 | /* SIMD shuffle */ 110 | for (i = 0; i < 16; i++) 111 | B[i] += x[i * 5 % 16]; 112 | } 113 | 114 | /** 115 | * blockmix_salsa8(B, Y, r): 116 | * Compute B = BlockMix_{salsa20/8, r}(B). The input B must be 128r bytes in 117 | * length; the temporary space Y must also be the same size. 118 | */ 119 | static void blockmix_salsa8(uint32_t *B, uint32_t *Y, size_t r) 120 | { 121 | uint32_t X[16]; 122 | size_t i; 123 | 124 | /* 1: X <-- B_{2r - 1} */ 125 | blkcpy(X, &B[(2 * r - 1) * 16], 16); 126 | 127 | /* 2: for i = 0 to 2r - 1 do */ 128 | for (i = 0; i < 2 * r; i++) { 129 | /* 3: X <-- H(X xor B_i) */ 130 | blkxor(X, &B[i * 16], 16); 131 | salsa20(X, 8); 132 | 133 | /* 4: Y_i <-- X */ 134 | blkcpy(&Y[i * 16], X, 16); 135 | } 136 | 137 | /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ 138 | for (i = 0; i < r; i++) 139 | blkcpy(&B[i * 16], &Y[(i * 2) * 16], 16); 140 | for (i = 0; i < r; i++) 141 | blkcpy(&B[(i + r) * 16], &Y[(i * 2 + 1) * 16], 16); 142 | } 143 | 144 | /* These are tunable, but they must meet certain constraints */ 145 | #define PWXsimple 2 146 | #define PWXgather 4 147 | #define PWXrounds 6 148 | #define Swidth 8 149 | 150 | /* Derived values. Not tunable on their own. */ 151 | #define PWXbytes (PWXgather * PWXsimple * 8) 152 | #define PWXwords (PWXbytes / sizeof(uint32_t)) 153 | #define Sbytes (3 * (1 << Swidth) * PWXsimple * 8) 154 | #define Swords (Sbytes / sizeof(uint32_t)) 155 | #define Smask (((1 << Swidth) - 1) * PWXsimple * 8) 156 | #define rmin ((PWXbytes + 127) / 128) 157 | 158 | typedef struct { 159 | uint32_t *S; 160 | uint32_t (*S0)[2], (*S1)[2], (*S2)[2]; 161 | size_t w; 162 | } pwxform_ctx_t; 163 | 164 | /** 165 | * pwxform(B): 166 | * Transform the provided block using the provided S-boxes. 167 | */ 168 | static void pwxform(uint32_t *B, pwxform_ctx_t *ctx) 169 | { 170 | uint32_t (*X)[PWXsimple][2] = (uint32_t (*)[PWXsimple][2])B; 171 | uint32_t (*S0)[2] = ctx->S0, (*S1)[2] = ctx->S1, (*S2)[2] = ctx->S2; 172 | size_t w = ctx->w; 173 | size_t i, j, k; 174 | 175 | /* 1: for i = 0 to PWXrounds - 1 do */ 176 | for (i = 0; i < PWXrounds; i++) { 177 | /* 2: for j = 0 to PWXgather - 1 do */ 178 | for (j = 0; j < PWXgather; j++) { 179 | uint32_t xl = X[j][0][0]; 180 | uint32_t xh = X[j][0][1]; 181 | uint32_t (*p0)[2], (*p1)[2]; 182 | 183 | /* 3: p0 <-- (lo(B_{j,0}) & Smask) / (PWXsimple * 8) */ 184 | p0 = S0 + (xl & Smask) / sizeof(*S0); 185 | /* 4: p1 <-- (hi(B_{j,0}) & Smask) / (PWXsimple * 8) */ 186 | p1 = S1 + (xh & Smask) / sizeof(*S1); 187 | 188 | /* 5: for k = 0 to PWXsimple - 1 do */ 189 | for (k = 0; k < PWXsimple; k++) { 190 | uint64_t x, s0, s1; 191 | 192 | /* 6: B_{j,k} <-- (hi(B_{j,k}) * lo(B_{j,k}) + S0_{p0,k}) xor S1_{p1,k} */ 193 | s0 = ((uint64_t)p0[k][1] << 32) + p0[k][0]; 194 | s1 = ((uint64_t)p1[k][1] << 32) + p1[k][0]; 195 | 196 | xl = X[j][k][0]; 197 | xh = X[j][k][1]; 198 | 199 | x = (uint64_t)xh * xl; 200 | x += s0; 201 | x ^= s1; 202 | 203 | X[j][k][0] = x; 204 | X[j][k][1] = x >> 32; 205 | 206 | /* 8: if (i != 0) and (i != PWXrounds - 1) */ 207 | if (i != 0 && i != PWXrounds - 1) { 208 | /* 9: S2_w <-- B_j */ 209 | S2[w][0] = x; 210 | S2[w][1] = x >> 32; 211 | /* 10: w <-- w + 1 */ 212 | w++; 213 | } 214 | } 215 | } 216 | } 217 | 218 | /* 14: (S0, S1, S2) <-- (S2, S0, S1) */ 219 | ctx->S0 = S2; 220 | ctx->S1 = S0; 221 | ctx->S2 = S1; 222 | /* 15: w <-- w mod 2^Swidth */ 223 | ctx->w = w & ((1 << Swidth) * PWXsimple - 1); 224 | } 225 | 226 | /** 227 | * blockmix_pwxform(B, ctx, r): 228 | * Compute B = BlockMix_pwxform{salsa20/2, ctx, r}(B). The input B must be 229 | * 128r bytes in length. 230 | */ 231 | static void blockmix_pwxform(uint32_t *B, pwxform_ctx_t *ctx, size_t r) 232 | { 233 | uint32_t X[PWXwords]; 234 | size_t r1, i; 235 | 236 | /* Convert 128-byte blocks to PWXbytes blocks */ 237 | /* 1: r_1 <-- 128r / PWXbytes */ 238 | r1 = 128 * r / PWXbytes; 239 | 240 | /* 2: X <-- B'_{r_1 - 1} */ 241 | blkcpy(X, &B[(r1 - 1) * PWXwords], PWXwords); 242 | 243 | /* 3: for i = 0 to r_1 - 1 do */ 244 | for (i = 0; i < r1; i++) { 245 | /* 4: if r_1 > 1 */ 246 | if (r1 > 1) { 247 | /* 5: X <-- X xor B'_i */ 248 | blkxor(X, &B[i * PWXwords], PWXwords); 249 | } 250 | 251 | /* 7: X <-- pwxform(X) */ 252 | pwxform(X, ctx); 253 | 254 | /* 8: B'_i <-- X */ 255 | blkcpy(&B[i * PWXwords], X, PWXwords); 256 | } 257 | 258 | /* 10: i <-- floor((r_1 - 1) * PWXbytes / 64) */ 259 | i = (r1 - 1) * PWXbytes / 64; 260 | 261 | /* 11: B_i <-- H(B_i) */ 262 | salsa20(&B[i * 16], 2); 263 | 264 | #if 1 /* No-op with our current pwxform settings, but do it to make sure */ 265 | /* 12: for i = i + 1 to 2r - 1 do */ 266 | for (i++; i < 2 * r; i++) { 267 | /* 13: B_i <-- H(B_i xor B_{i-1}) */ 268 | blkxor(&B[i * 16], &B[(i - 1) * 16], 16); 269 | salsa20(&B[i * 16], 2); 270 | } 271 | #endif 272 | } 273 | 274 | /** 275 | * integerify(B, r): 276 | * Return the result of parsing B_{2r-1} as a little-endian integer. 277 | */ 278 | static uint64_t integerify(const uint32_t *B, size_t r) 279 | { 280 | /* 281 | * Our 32-bit words are in host byte order, and word 13 is the second word of 282 | * B_{2r-1} due to SIMD shuffling. The 64-bit value we return is also in host 283 | * byte order, as it should be. 284 | */ 285 | const uint32_t *X = &B[(2 * r - 1) * 16]; 286 | return ((uint64_t)X[13] << 32) + X[0]; 287 | } 288 | 289 | /** 290 | * p2floor(x): 291 | * Largest power of 2 not greater than argument. 292 | */ 293 | static uint64_t p2floor(uint64_t x) 294 | { 295 | uint64_t y; 296 | while ((y = x & (x - 1))) 297 | x = y; 298 | return x; 299 | } 300 | 301 | /** 302 | * wrap(x, i): 303 | * Wrap x to the range 0 to i-1. 304 | */ 305 | static uint64_t wrap(uint64_t x, uint64_t i) 306 | { 307 | uint64_t n = p2floor(i); 308 | return (x & (n - 1)) + (i - n); 309 | } 310 | 311 | /** 312 | * smix1(B, r, N, flags, V, NROM, VROM, XY, ctx): 313 | * Compute first loop of B = SMix_r(B, N). The input B must be 128r bytes in 314 | * length; the temporary storage V must be 128rN bytes in length; the temporary 315 | * storage XY must be 256r bytes in length. 316 | */ 317 | static void smix1(uint32_t *B, size_t r, uint64_t N, yescrypt_flags_t flags, 318 | uint32_t *V, uint64_t NROM, const uint32_t *VROM, 319 | uint32_t *XY, pwxform_ctx_t *ctx) 320 | { 321 | size_t s = 32 * r; 322 | uint32_t *X = XY; 323 | uint32_t *Y = &XY[s]; 324 | uint64_t i, j; 325 | size_t k; 326 | 327 | /* 1: X <-- B */ 328 | for (k = 0; k < 2 * r; k++) 329 | for (i = 0; i < 16; i++) 330 | X[k * 16 + i] = le32dec(&B[k * 16 + (i * 5 % 16)]); 331 | 332 | /* 2: for i = 0 to N - 1 do */ 333 | for (i = 0; i < N; i++) { 334 | /* 3: V_i <-- X */ 335 | blkcpy(&V[i * s], X, s); 336 | 337 | if (VROM && i == 0) { 338 | /* X <-- X xor VROM_{NROM-1} */ 339 | blkxor(X, &VROM[(NROM - 1) * s], s); 340 | } else if (VROM && (i & 1)) { 341 | /* j <-- Integerify(X) mod NROM */ 342 | j = integerify(X, r) & (NROM - 1); 343 | 344 | /* X <-- X xor VROM_j */ 345 | blkxor(X, &VROM[j * s], s); 346 | } else if ((flags & YESCRYPT_RW) && i > 1) { 347 | /* j <-- Wrap(Integerify(X), i) */ 348 | j = wrap(integerify(X, r), i); 349 | 350 | /* X <-- X xor V_j */ 351 | blkxor(X, &V[j * s], s); 352 | } 353 | 354 | /* 4: X <-- H(X) */ 355 | if (ctx) 356 | blockmix_pwxform(X, ctx, r); 357 | else 358 | blockmix_salsa8(X, Y, r); 359 | } 360 | 361 | /* B' <-- X */ 362 | for (k = 0; k < 2 * r; k++) 363 | for (i = 0; i < 16; i++) 364 | le32enc(&B[k * 16 + (i * 5 % 16)], X[k * 16 + i]); 365 | } 366 | 367 | /** 368 | * smix2(B, r, N, Nloop, flags, V, NROM, VROM, XY, ctx): 369 | * Compute second loop of B = SMix_r(B, N). The input B must be 128r bytes in 370 | * length; the temporary storage V must be 128rN bytes in length; the temporary 371 | * storage XY must be 256r bytes in length. The value N must be a power of 2 372 | * greater than 1. 373 | */ 374 | static void smix2(uint32_t *B, size_t r, uint64_t N, uint64_t Nloop, 375 | yescrypt_flags_t flags, uint32_t *V, uint64_t NROM, 376 | const uint32_t *VROM, uint32_t *XY, pwxform_ctx_t *ctx) 377 | { 378 | size_t s = 32 * r; 379 | uint32_t *X = XY; 380 | uint32_t *Y = &XY[s]; 381 | uint64_t i, j; 382 | size_t k; 383 | 384 | /* X <-- B */ 385 | for (k = 0; k < 2 * r; k++) 386 | for (i = 0; i < 16; i++) 387 | X[k * 16 + i] = le32dec(&B[k * 16 + (i * 5 % 16)]); 388 | 389 | /* 6: for i = 0 to N - 1 do */ 390 | for (i = 0; i < Nloop; i++) { 391 | if (VROM && (i & 1)) { 392 | /* j <-- Integerify(X) mod NROM */ 393 | j = integerify(X, r) & (NROM - 1); 394 | 395 | /* X <-- H(X xor VROM_j) */ 396 | blkxor(X, &VROM[j * s], s); 397 | } else { 398 | /* 7: j <-- Integerify(X) mod N */ 399 | j = integerify(X, r) & (N - 1); 400 | 401 | /* 8.1: X <-- X xor V_j */ 402 | blkxor(X, &V[j * s], s); 403 | /* V_j <-- X */ 404 | if (flags & YESCRYPT_RW) 405 | blkcpy(&V[j * s], X, s); 406 | } 407 | 408 | /* 8.2: X <-- H(X) */ 409 | if (ctx) 410 | blockmix_pwxform(X, ctx, r); 411 | else 412 | blockmix_salsa8(X, Y, r); 413 | } 414 | 415 | /* 10: B' <-- X */ 416 | for (k = 0; k < 2 * r; k++) 417 | for (i = 0; i < 16; i++) 418 | le32enc(&B[k * 16 + (i * 5 % 16)], X[k * 16 + i]); 419 | } 420 | 421 | /** 422 | * smix(B, r, N, p, t, flags, V, NROM, VROM, XY, ctx, passwd): 423 | * Compute B = SMix_r(B, N). The input B must be 128rp bytes in length; the 424 | * temporary storage V must be 128rN bytes in length; the temporary storage 425 | * XY must be 256r bytes in length. The value N must be a power of 2 greater 426 | * than 1. 427 | */ 428 | static void smix(uint32_t *B, size_t r, uint64_t N, uint32_t p, uint32_t t, 429 | yescrypt_flags_t flags, 430 | uint32_t *V, uint64_t NROM, const uint32_t *VROM, 431 | uint32_t *XY, pwxform_ctx_t *ctx, uint8_t *passwd) 432 | { 433 | size_t s = 32 * r; 434 | uint64_t Nchunk, Nloop_all, Nloop_rw, Vchunk; 435 | uint32_t i; 436 | 437 | /* 1: n <-- N / p */ 438 | Nchunk = N / p; 439 | 440 | /* 2: Nloop_all <-- fNloop(n, t, flags) */ 441 | Nloop_all = Nchunk; 442 | if (flags & YESCRYPT_RW) { 443 | if (t <= 1) { 444 | if (t) 445 | Nloop_all *= 2; /* 2/3 */ 446 | Nloop_all = (Nloop_all + 2) / 3; /* 1/3, round up */ 447 | } else { 448 | Nloop_all *= t - 1; 449 | } 450 | } else if (t) { 451 | if (t == 1) 452 | Nloop_all += (Nloop_all + 1) / 2; /* 1.5, round up */ 453 | Nloop_all *= t; 454 | } 455 | 456 | /* 6: Nloop_rw <-- 0 */ 457 | Nloop_rw = 0; 458 | if (flags & YESCRYPT_INIT_SHARED) { 459 | Nloop_rw = Nloop_all; 460 | } else { 461 | /* 3: if YESCRYPT_RW flag is set */ 462 | if (flags & YESCRYPT_RW) { 463 | /* 4: Nloop_rw <-- Nloop_all / p */ 464 | Nloop_rw = Nloop_all / p; 465 | } 466 | } 467 | 468 | /* 8: n <-- n - (n mod 2) */ 469 | Nchunk &= ~(uint64_t)1; /* round down to even */ 470 | /* 9: Nloop_all <-- Nloop_all + (Nloop_all mod 2) */ 471 | Nloop_all++; Nloop_all &= ~(uint64_t)1; /* round up to even */ 472 | /* 10: Nloop_rw <-- Nloop_rw + (Nloop_rw mod 2) */ 473 | Nloop_rw++; Nloop_rw &= ~(uint64_t)1; /* round up to even */ 474 | 475 | /* 11: for i = 0 to p - 1 do */ 476 | /* 12: u <-- in */ 477 | for (i = 0, Vchunk = 0; i < p; i++, Vchunk += Nchunk) { 478 | /* 13: if i = p - 1 */ 479 | /* 14: n <-- N - u */ 480 | /* 15: end if */ 481 | /* 16: v <-- u + n - 1 */ 482 | uint64_t Np = (i < p - 1) ? Nchunk : (N - Vchunk); 483 | uint32_t *Bp = &B[i * s]; 484 | uint32_t *Vp = &V[Vchunk * s]; 485 | pwxform_ctx_t *ctx_i = NULL; 486 | /* 17: if YESCRYPT_RW flag is set */ 487 | if (flags & YESCRYPT_RW) { 488 | ctx_i = &ctx[i]; 489 | /* 18: SMix1_1(B_i, Sbytes / 128, S_i, no flags) */ 490 | smix1(Bp, 1, Sbytes / 128, 0 /* no flags */, 491 | ctx_i->S, 0, NULL, XY, NULL); 492 | /* 19: S2_i <-- S_{i,0...2^Swidth-1} */ 493 | ctx_i->S2 = (uint32_t (*)[2])ctx_i->S; 494 | /* 20: S1_i <-- S_{i,2^Swidth...2*2^Swidth-1} */ 495 | ctx_i->S1 = ctx_i->S2 + (1 << Swidth) * PWXsimple; 496 | /* 21: S0_i <-- S_{i,2*2^Swidth...3*2^Swidth-1} */ 497 | ctx_i->S0 = ctx_i->S1 + (1 << Swidth) * PWXsimple; 498 | /* 22: w_i <-- 0 */ 499 | ctx_i->w = 0; 500 | /* 23: if i = 0 */ 501 | if (i == 0) { 502 | /* 24: passwd <-- HMAC-SHA256(B_{0,2r-1}, passwd) */ 503 | HMAC_SHA256_Buf(Bp + (s - 16), 64, 504 | passwd, 32, passwd); 505 | } 506 | } 507 | /* 27: SMix1_r(B_i, n, V_{u..v}, flags) */ 508 | smix1(Bp, r, Np, flags, Vp, NROM, VROM, XY, ctx_i); 509 | /* 28: SMix2_r(B_i, p2floor(n), Nloop_rw, V_{u..v}, flags) */ 510 | smix2(Bp, r, p2floor(Np), Nloop_rw, flags, Vp, 511 | NROM, VROM, XY, ctx_i); 512 | } 513 | 514 | /* 30: for i = 0 to p - 1 do */ 515 | for (i = 0; i < p; i++) { 516 | uint32_t *Bp = &B[i * s]; 517 | /* 31: SMix2_r(B_i, N, Nloop_all - Nloop_rw, V, flags excluding YESCRYPT_RW) */ 518 | smix2(Bp, r, N, Nloop_all - Nloop_rw, flags & ~YESCRYPT_RW, 519 | V, NROM, VROM, XY, (flags & YESCRYPT_RW) ? &ctx[i] : NULL); 520 | } 521 | } 522 | 523 | /** 524 | * yescrypt_kdf_body(shared, local, passwd, passwdlen, salt, saltlen, 525 | * flags, N, r, p, t, NROM, buf, buflen): 526 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 527 | * p, buflen), or a revision of scrypt as requested by flags and shared, and 528 | * write the result into buf. 529 | * 530 | * shared and flags may request special modes as described in yescrypt.h. 531 | * 532 | * local is the thread-local data structure, allowing optimized implementations 533 | * to preserve and reuse a memory allocation across calls, thereby reducing its 534 | * overhead (this reference implementation does not make that optimization). 535 | * 536 | * t controls computation time while not affecting peak memory usage. 537 | * 538 | * Return 0 on success; or -1 on error. 539 | */ 540 | static int yescrypt_kdf_body(const yescrypt_shared_t *shared, 541 | yescrypt_local_t *local, 542 | const uint8_t *passwd, size_t passwdlen, 543 | const uint8_t *salt, size_t saltlen, 544 | yescrypt_flags_t flags, uint64_t N, uint32_t r, uint32_t p, uint32_t t, 545 | uint64_t NROM, 546 | uint8_t *buf, size_t buflen) 547 | { 548 | int retval = -1; 549 | const uint32_t *VROM; 550 | size_t B_size, V_size; 551 | uint32_t *B, *V, *XY, *S; 552 | pwxform_ctx_t *pwxform_ctx; 553 | uint32_t sha256[8]; 554 | uint8_t dk[sizeof(sha256)], *dkp = buf; 555 | uint32_t i; 556 | 557 | /* Sanity-check parameters */ 558 | switch (flags & YESCRYPT_MODE_MASK) { 559 | case 0: /* classic scrypt - can't have anything non-standard */ 560 | if (flags || t || NROM) 561 | goto out_EINVAL; 562 | break; 563 | case YESCRYPT_WORM: 564 | if (flags != YESCRYPT_WORM || NROM) 565 | goto out_EINVAL; 566 | break; 567 | case YESCRYPT_RW: 568 | if (flags != (flags & YESCRYPT_KNOWN_FLAGS)) 569 | goto out_EINVAL; 570 | #if PWXsimple == 2 && PWXgather == 4 && PWXrounds == 6 && Sbytes == 12288 571 | if ((flags & YESCRYPT_RW_FLAVOR_MASK) == 572 | (YESCRYPT_ROUNDS_6 | YESCRYPT_GATHER_4 | 573 | YESCRYPT_SIMPLE_2 | YESCRYPT_SBOX_12K)) 574 | break; 575 | #else 576 | #error "Unsupported pwxform settings" 577 | #endif 578 | /* FALLTHRU */ 579 | default: 580 | goto out_EINVAL; 581 | } 582 | #if SIZE_MAX > UINT32_MAX 583 | if (buflen > (((uint64_t)1 << 32) - 1) * 32) 584 | goto out_EINVAL; 585 | #endif 586 | if ((uint64_t)r * (uint64_t)p >= 1 << 30) 587 | goto out_EINVAL; 588 | if ((N & (N - 1)) != 0 || N <= 1 || r < 1 || p < 1) 589 | goto out_EINVAL; 590 | if (r > SIZE_MAX / 128 / p || 591 | #if SIZE_MAX / 256 <= UINT32_MAX 592 | r > SIZE_MAX / 256 || 593 | #endif 594 | N > SIZE_MAX / 128 / r) 595 | goto out_EINVAL; 596 | if (N > UINT64_MAX / ((uint64_t)t + 1)) 597 | goto out_EINVAL; 598 | if (flags & YESCRYPT_RW) { 599 | if (N / p <= 1 || r < rmin || 600 | p > SIZE_MAX / Sbytes || 601 | p > SIZE_MAX / sizeof(*pwxform_ctx)) 602 | goto out_EINVAL; 603 | } 604 | 605 | VROM = NULL; 606 | if (shared) { 607 | uint64_t expected_size = (size_t)128 * r * NROM; 608 | if ((NROM & (NROM - 1)) != 0 || NROM <= 1 || 609 | shared->aligned_size < expected_size) 610 | goto out_EINVAL; 611 | if (!(flags & YESCRYPT_INIT_SHARED)) { 612 | uint32_t *tag = (uint32_t *) 613 | ((uint8_t *)shared->aligned + expected_size - 48); 614 | uint64_t tag1 = ((uint64_t)tag[1] << 32) + tag[0]; 615 | uint64_t tag2 = ((uint64_t)tag[3] << 32) + tag[2]; 616 | if (tag1 != YESCRYPT_ROM_TAG1 || tag2 != YESCRYPT_ROM_TAG2) 617 | goto out_EINVAL; 618 | } 619 | VROM = shared->aligned; 620 | } else { 621 | if (NROM) 622 | goto out_EINVAL; 623 | } 624 | 625 | /* Allocate memory */ 626 | V_size = (size_t)128 * r * N; 627 | if (flags & YESCRYPT_INIT_SHARED) { 628 | V = (uint32_t *)local->aligned; 629 | if (local->aligned_size < V_size) { 630 | if (local->base || local->aligned || 631 | local->base_size || local->aligned_size) 632 | goto out_EINVAL; 633 | if ((V = malloc(V_size)) == NULL) 634 | return -1; 635 | local->base = local->aligned = V; 636 | local->base_size = local->aligned_size = V_size; 637 | } 638 | if (flags & YESCRYPT_ALLOC_ONLY) 639 | return -2; /* expected "failure" */ 640 | } else { 641 | if ((V = malloc(V_size)) == NULL) 642 | return -1; 643 | } 644 | B_size = (size_t)128 * r * p; 645 | if ((B = malloc(B_size)) == NULL) 646 | goto free_V; 647 | if ((XY = malloc((size_t)256 * r)) == NULL) 648 | goto free_B; 649 | S = NULL; 650 | pwxform_ctx = NULL; 651 | if (flags & YESCRYPT_RW) { 652 | if ((S = malloc((size_t)Sbytes * p)) == NULL) 653 | goto free_XY; 654 | if ((pwxform_ctx = malloc(sizeof(*pwxform_ctx) * p)) == NULL) 655 | goto free_S; 656 | } 657 | 658 | if (flags) { 659 | HMAC_SHA256_Buf("yescrypt-prehash", 660 | (flags & YESCRYPT_PREHASH) ? 16 : 8, 661 | passwd, passwdlen, (uint8_t *)sha256); 662 | passwd = (uint8_t *)sha256; 663 | passwdlen = sizeof(sha256); 664 | } 665 | 666 | /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ 667 | PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, 668 | (uint8_t *)B, B_size); 669 | 670 | if (flags) 671 | blkcpy(sha256, B, sizeof(sha256) / sizeof(sha256[0])); 672 | 673 | if (flags & YESCRYPT_RW) { 674 | for (i = 0; i < p; i++) 675 | pwxform_ctx[i].S = &S[i * Swords]; 676 | smix(B, r, N, p, t, flags, V, NROM, VROM, XY, pwxform_ctx, 677 | (uint8_t *)sha256); 678 | } else { 679 | /* 2: for i = 0 to p - 1 do */ 680 | for (i = 0; i < p; i++) { 681 | /* 3: B_i <-- MF(B_i, N) */ 682 | smix(&B[(size_t)32 * r * i], r, N, 1, t, flags, V, 683 | NROM, VROM, XY, NULL, NULL); 684 | } 685 | } 686 | 687 | dkp = buf; 688 | if (flags && buflen < sizeof(dk)) { 689 | PBKDF2_SHA256(passwd, passwdlen, (uint8_t *)B, B_size, 1, 690 | dk, sizeof(dk)); 691 | dkp = dk; 692 | } 693 | 694 | /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ 695 | PBKDF2_SHA256(passwd, passwdlen, (uint8_t *)B, B_size, 1, buf, buflen); 696 | 697 | /* 698 | * Except when computing classic scrypt, allow all computation so far 699 | * to be performed on the client. The final steps below match those of 700 | * SCRAM (RFC 5802), so that an extension of SCRAM (with the steps so 701 | * far in place of SCRAM's use of PBKDF2 and with SHA-256 in place of 702 | * SCRAM's use of SHA-1) would be usable with yescrypt hashes. 703 | */ 704 | if (flags && !(flags & YESCRYPT_PREHASH)) { 705 | /* Compute ClientKey */ 706 | HMAC_SHA256_Buf(dkp, sizeof(dk), "Client Key", 10, 707 | (uint8_t *)sha256); 708 | /* Compute StoredKey */ 709 | { 710 | size_t clen = buflen; 711 | if (clen > sizeof(dk)) 712 | clen = sizeof(dk); 713 | SHA256_Buf((uint8_t *)sha256, sizeof(sha256), dk); 714 | memcpy(buf, dk, clen); 715 | } 716 | } 717 | 718 | /* Success! */ 719 | retval = 0; 720 | 721 | /* Free memory */ 722 | free(pwxform_ctx); 723 | free_S: 724 | free(S); 725 | free_XY: 726 | free(XY); 727 | free_B: 728 | free(B); 729 | free_V: 730 | if (!(flags & YESCRYPT_INIT_SHARED)) 731 | free(V); 732 | 733 | return retval; 734 | 735 | out_EINVAL: 736 | errno = EINVAL; 737 | return -1; 738 | } 739 | 740 | /** 741 | * yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen, params, 742 | * buf, buflen): 743 | * Compute scrypt or its revision as requested by the parameters. The inputs 744 | * to this function are the same as those for yescrypt_kdf_body() above, with 745 | * the addition of g, which controls hash upgrades (0 for no upgrades so far). 746 | */ 747 | int yescrypt_kdf(const yescrypt_shared_t *shared, yescrypt_local_t *local, 748 | const uint8_t *passwd, size_t passwdlen, 749 | const uint8_t *salt, size_t saltlen, 750 | const yescrypt_params_t *params, 751 | uint8_t *buf, size_t buflen) 752 | { 753 | yescrypt_flags_t flags = params->flags; 754 | uint64_t N = params->N; 755 | uint32_t r = params->r; 756 | uint32_t p = params->p; 757 | uint32_t t = params->t; 758 | uint32_t g = params->g; 759 | uint64_t NROM = params->NROM; 760 | uint8_t dk[32]; 761 | 762 | /* Support for hash upgrades has been temporarily removed */ 763 | if (g) { 764 | errno = EINVAL; 765 | return -1; 766 | } 767 | 768 | if ((flags & YESCRYPT_RW) && 769 | p >= 1 && N / p >= 0x100 && N / p * r >= 0x20000) { 770 | /* 771 | * This reference implementation's yescrypt_kdf_body() 772 | * (de)allocates memory on each call, which defeats the purpose 773 | * of this pre-hashing. The optimized implementations, which 774 | * you should actually use, make the larger allocation first 775 | * and then reuse it. Thus, this implementation doing things 776 | * differently serves as a test that the computation result is 777 | * unaffected by such differences. 778 | */ 779 | int retval = yescrypt_kdf_body(shared, local, 780 | passwd, passwdlen, salt, saltlen, 781 | flags | YESCRYPT_PREHASH, N >> 6, r, p, 0, NROM, 782 | dk, sizeof(dk)); 783 | if (retval) 784 | return retval; 785 | passwd = dk; 786 | passwdlen = sizeof(dk); 787 | } 788 | 789 | return yescrypt_kdf_body(shared, local, 790 | passwd, passwdlen, salt, saltlen, 791 | flags, N, r, p, t, NROM, buf, buflen); 792 | } 793 | 794 | int yescrypt_init_shared(yescrypt_shared_t *shared, 795 | const uint8_t *seed, size_t seedlen, 796 | const yescrypt_params_t *params) 797 | { 798 | yescrypt_flags_t flags = params->flags; 799 | uint64_t N = params->NROM; 800 | uint32_t r = params->r; 801 | uint32_t p = params->p; 802 | uint32_t t = params->t; 803 | yescrypt_shared_t half1, half2; 804 | uint8_t salt[32]; 805 | uint32_t *tag; 806 | 807 | if (!(params->flags & YESCRYPT_RW) || params->N || params->g) 808 | return -1; 809 | 810 | if (flags & YESCRYPT_SHARED_PREALLOCATED) { 811 | if (!shared->aligned || !shared->aligned_size) 812 | return -1; 813 | 814 | /* Overwrite a possible old ROM tag before we overwrite the rest */ 815 | tag = (uint32_t *) 816 | ((uint8_t *)shared->aligned + shared->aligned_size - 48); 817 | memset(tag, 0, 48); 818 | } else { 819 | shared->base = shared->aligned = NULL; 820 | shared->base_size = shared->aligned_size = 0; 821 | 822 | if (yescrypt_kdf_body(NULL, shared, NULL, 0, NULL, 0, 823 | flags | YESCRYPT_INIT_SHARED | YESCRYPT_ALLOC_ONLY, 824 | N, r, p, t, 0, NULL, 0) != -2 || !shared->aligned) 825 | goto fail; 826 | } 827 | 828 | half1 = half2 = *shared; 829 | half1.aligned_size /= 2; 830 | half2.aligned = (uint8_t *)half2.aligned + half1.aligned_size; 831 | half2.aligned_size = half1.aligned_size; 832 | N /= 2; 833 | 834 | if (yescrypt_kdf_body(NULL, &half1, 835 | seed, seedlen, (const uint8_t *)"yescrypt-ROMhash", 16, 836 | flags | YESCRYPT_INIT_SHARED, N, r, p, t, 0, 837 | salt, sizeof(salt))) 838 | goto fail; 839 | 840 | if (yescrypt_kdf_body(&half1, &half2, 841 | seed, seedlen, salt, sizeof(salt), 842 | flags | YESCRYPT_INIT_SHARED, N, r, p, t, N, 843 | salt, sizeof(salt))) 844 | goto fail; 845 | 846 | if (yescrypt_kdf_body(&half2, &half1, 847 | seed, seedlen, salt, sizeof(salt), 848 | flags | YESCRYPT_INIT_SHARED, N, r, p, t, N, 849 | salt, sizeof(salt))) 850 | goto fail; 851 | 852 | tag = (uint32_t *) 853 | ((uint8_t *)shared->aligned + shared->aligned_size - 48); 854 | tag[0] = YESCRYPT_ROM_TAG1 & 0xffffffffU; 855 | tag[1] = YESCRYPT_ROM_TAG1 >> 32; 856 | tag[2] = YESCRYPT_ROM_TAG2 & 0xffffffffU; 857 | tag[3] = YESCRYPT_ROM_TAG2 >> 32; 858 | tag[4] = le32dec(salt); 859 | tag[5] = le32dec(salt + 4); 860 | tag[6] = le32dec(salt + 8); 861 | tag[7] = le32dec(salt + 12); 862 | tag[8] = le32dec(salt + 16); 863 | tag[9] = le32dec(salt + 20); 864 | tag[10] = le32dec(salt + 24); 865 | tag[11] = le32dec(salt + 28); 866 | 867 | return 0; 868 | 869 | fail: 870 | if (!(flags & YESCRYPT_SHARED_PREALLOCATED)) 871 | free(shared->base); 872 | return -1; 873 | } 874 | 875 | yescrypt_binary_t *yescrypt_digest_shared(yescrypt_shared_t *shared) 876 | { 877 | static yescrypt_binary_t digest; 878 | uint32_t *tag; 879 | uint64_t tag1, tag2; 880 | 881 | if (shared->aligned_size < 48) 882 | return NULL; 883 | 884 | tag = (uint32_t *) 885 | ((uint8_t *)shared->aligned + shared->aligned_size - 48); 886 | 887 | tag1 = ((uint64_t)tag[1] << 32) + tag[0]; 888 | tag2 = ((uint64_t)tag[3] << 32) + tag[2]; 889 | if (tag1 != YESCRYPT_ROM_TAG1 || tag2 != YESCRYPT_ROM_TAG2) 890 | return NULL; 891 | 892 | le32enc(digest.uc, tag[4]); 893 | le32enc(digest.uc + 4, tag[5]); 894 | le32enc(digest.uc + 8, tag[6]); 895 | le32enc(digest.uc + 12, tag[7]); 896 | le32enc(digest.uc + 16, tag[8]); 897 | le32enc(digest.uc + 20, tag[9]); 898 | le32enc(digest.uc + 24, tag[10]); 899 | le32enc(digest.uc + 28, tag[11]); 900 | 901 | return &digest; 902 | } 903 | 904 | int yescrypt_free_shared(yescrypt_shared_t *shared) 905 | { 906 | free(shared->base); 907 | shared->base = shared->aligned = NULL; 908 | shared->base_size = shared->aligned_size = 0; 909 | return 0; 910 | } 911 | 912 | int yescrypt_init_local(yescrypt_local_t *local) 913 | { 914 | /* The reference implementation doesn't use the local structure */ 915 | local->base = local->aligned = NULL; 916 | local->base_size = local->aligned_size = 0; 917 | return 0; 918 | } 919 | 920 | int yescrypt_free_local(yescrypt_local_t *local) 921 | { 922 | /* The reference implementation frees its memory in yescrypt_kdf() */ 923 | (void)local; /* unused */ 924 | return 0; 925 | } 926 | -------------------------------------------------------------------------------- /yescrypt.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright 2009 Colin Percival 3 | * Copyright 2013-2018 Alexander Peslyak 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | * 27 | * This file was originally written by Colin Percival as part of the Tarsnap 28 | * online backup system. 29 | */ 30 | #ifndef _YESCRYPT_H_ 31 | #define _YESCRYPT_H_ 32 | 33 | #include 34 | #include /* for size_t */ 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /** 41 | * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 42 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 43 | * p, buflen) and write the result into buf. The parameters r, p, and buflen 44 | * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 45 | * must be a power of 2 greater than 1. 46 | * 47 | * Return 0 on success; or -1 on error. 48 | * 49 | * MT-safe as long as buf is local to the thread. 50 | */ 51 | extern int crypto_scrypt(const uint8_t *passwd, size_t passwdlen, 52 | const uint8_t *salt, size_t saltlen, 53 | uint64_t N, uint32_t r, uint32_t p, uint8_t *buf, size_t buflen); 54 | 55 | /** 56 | * Internal type used by the memory allocator. Please do not use it directly. 57 | * Use yescrypt_shared_t and yescrypt_local_t as appropriate instead, since 58 | * they might differ from each other in a future version. 59 | */ 60 | typedef struct { 61 | void *base, *aligned; 62 | size_t base_size, aligned_size; 63 | } yescrypt_region_t; 64 | 65 | /** 66 | * Types for shared (ROM) and thread-local (RAM) data structures. 67 | */ 68 | typedef yescrypt_region_t yescrypt_shared_t; 69 | typedef yescrypt_region_t yescrypt_local_t; 70 | 71 | /** 72 | * Two 64-bit tags placed 48 bytes to the end of a ROM in host byte endianness 73 | * (and followed by 32 bytes of the ROM digest). 74 | */ 75 | #define YESCRYPT_ROM_TAG1 0x7470797263736579ULL /* "yescrypt" */ 76 | #define YESCRYPT_ROM_TAG2 0x687361684d4f522dULL /* "-ROMhash" */ 77 | 78 | /** 79 | * Type and possible values for the flags argument of yescrypt_kdf(), 80 | * yescrypt_encode_params_r(), yescrypt_encode_params(). Most of these may be 81 | * OR'ed together, except that YESCRYPT_WORM stands on its own. 82 | * Please refer to the description of yescrypt_kdf() below for the meaning of 83 | * these flags. 84 | */ 85 | typedef uint32_t yescrypt_flags_t; 86 | /* Public */ 87 | #define YESCRYPT_WORM 1 88 | #define YESCRYPT_RW 0x002 89 | #define YESCRYPT_ROUNDS_3 0x000 90 | #define YESCRYPT_ROUNDS_6 0x004 91 | #define YESCRYPT_GATHER_1 0x000 92 | #define YESCRYPT_GATHER_2 0x008 93 | #define YESCRYPT_GATHER_4 0x010 94 | #define YESCRYPT_GATHER_8 0x018 95 | #define YESCRYPT_SIMPLE_1 0x000 96 | #define YESCRYPT_SIMPLE_2 0x020 97 | #define YESCRYPT_SIMPLE_4 0x040 98 | #define YESCRYPT_SIMPLE_8 0x060 99 | #define YESCRYPT_SBOX_6K 0x000 100 | #define YESCRYPT_SBOX_12K 0x080 101 | #define YESCRYPT_SBOX_24K 0x100 102 | #define YESCRYPT_SBOX_48K 0x180 103 | #define YESCRYPT_SBOX_96K 0x200 104 | #define YESCRYPT_SBOX_192K 0x280 105 | #define YESCRYPT_SBOX_384K 0x300 106 | #define YESCRYPT_SBOX_768K 0x380 107 | /* Only valid for yescrypt_init_shared() */ 108 | #define YESCRYPT_SHARED_PREALLOCATED 0x10000 109 | #ifdef YESCRYPT_INTERNAL 110 | /* Private */ 111 | #define YESCRYPT_MODE_MASK 0x003 112 | #define YESCRYPT_RW_FLAVOR_MASK 0x3fc 113 | #define YESCRYPT_INIT_SHARED 0x01000000 114 | #define YESCRYPT_ALLOC_ONLY 0x08000000 115 | #define YESCRYPT_PREHASH 0x10000000 116 | #endif 117 | 118 | #define YESCRYPT_RW_DEFAULTS \ 119 | (YESCRYPT_RW | \ 120 | YESCRYPT_ROUNDS_6 | YESCRYPT_GATHER_4 | YESCRYPT_SIMPLE_2 | \ 121 | YESCRYPT_SBOX_12K) 122 | 123 | #define YESCRYPT_DEFAULTS YESCRYPT_RW_DEFAULTS 124 | 125 | #ifdef YESCRYPT_INTERNAL 126 | #define YESCRYPT_KNOWN_FLAGS \ 127 | (YESCRYPT_MODE_MASK | YESCRYPT_RW_FLAVOR_MASK | \ 128 | YESCRYPT_SHARED_PREALLOCATED | \ 129 | YESCRYPT_INIT_SHARED | YESCRYPT_ALLOC_ONLY | YESCRYPT_PREHASH) 130 | #endif 131 | 132 | /** 133 | * yescrypt parameters combined into one struct. N, r, p are the same as in 134 | * classic scrypt, except that the meaning of p changes when YESCRYPT_RW is 135 | * set. flags, t, g, NROM are special to yescrypt. 136 | */ 137 | typedef struct { 138 | yescrypt_flags_t flags; 139 | uint64_t N; 140 | uint32_t r, p, t, g; 141 | uint64_t NROM; 142 | } yescrypt_params_t; 143 | 144 | /** 145 | * A 256-bit yescrypt hash, or a hash encryption key (which may itself have 146 | * been derived as a yescrypt hash of a human-specified key string). 147 | */ 148 | typedef union { 149 | unsigned char uc[32]; 150 | uint64_t u64[4]; 151 | } yescrypt_binary_t; 152 | 153 | /** 154 | * yescrypt_init_shared(shared, seed, seedlen, params): 155 | * Optionally allocate memory for and initialize the shared (ROM) data 156 | * structure. The parameters flags, NROM, r, p, and t specify how the ROM is 157 | * to be initialized, and seed and seedlen specify the initial seed affecting 158 | * the data with which the ROM is filled. 159 | * 160 | * Return 0 on success; or -1 on error. 161 | * 162 | * If bit YESCRYPT_SHARED_PREALLOCATED in flags is set, then memory for the 163 | * ROM is assumed to have been preallocated by the caller, with shared->aligned 164 | * being the start address of the ROM and shared->aligned_size being its size 165 | * (which must be sufficient for NROM, r, p). This may be used e.g. when the 166 | * ROM is to be placed in a SysV shared memory segment allocated by the caller. 167 | * 168 | * MT-safe as long as shared is local to the thread. 169 | */ 170 | extern int yescrypt_init_shared(yescrypt_shared_t *shared, 171 | const uint8_t *seed, size_t seedlen, const yescrypt_params_t *params); 172 | 173 | /** 174 | * yescrypt_digest_shared(shared): 175 | * Extract the previously stored message digest of the provided yescrypt ROM. 176 | * 177 | * Return pointer to the message digest on success; or NULL on error. 178 | * 179 | * MT-unsafe. 180 | */ 181 | extern yescrypt_binary_t *yescrypt_digest_shared(yescrypt_shared_t *shared); 182 | 183 | /** 184 | * yescrypt_free_shared(shared): 185 | * Free memory that had been allocated with yescrypt_init_shared(). 186 | * 187 | * Return 0 on success; or -1 on error. 188 | * 189 | * MT-safe as long as shared is local to the thread. 190 | */ 191 | extern int yescrypt_free_shared(yescrypt_shared_t *shared); 192 | 193 | /** 194 | * yescrypt_init_local(local): 195 | * Initialize the thread-local (RAM) data structure. Actual memory allocation 196 | * is currently fully postponed until a call to yescrypt_kdf() or yescrypt_r(). 197 | * 198 | * Return 0 on success; or -1 on error. 199 | * 200 | * MT-safe as long as local is local to the thread. 201 | */ 202 | extern int yescrypt_init_local(yescrypt_local_t *local); 203 | 204 | /** 205 | * yescrypt_free_local(local): 206 | * Free memory that may have been allocated for an initialized thread-local 207 | * (RAM) data structure. 208 | * 209 | * Return 0 on success; or -1 on error. 210 | * 211 | * MT-safe as long as local is local to the thread. 212 | */ 213 | extern int yescrypt_free_local(yescrypt_local_t *local); 214 | 215 | /** 216 | * yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen, params, 217 | * buf, buflen): 218 | * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 219 | * p, buflen), or a revision of scrypt as requested by flags and shared, and 220 | * write the result into buf. The parameters N, r, p, and buflen must satisfy 221 | * the same conditions as with crypto_scrypt(). t controls computation time 222 | * while not affecting peak memory usage (t = 0 is optimal unless higher N*r 223 | * is not affordable while higher t is). g controls hash upgrades (g = 0 for 224 | * no upgrades so far). shared and flags may request special modes. local is 225 | * the thread-local data structure, allowing to preserve and reuse a memory 226 | * allocation across calls, thereby reducing processing overhead. 227 | * 228 | * Return 0 on success; or -1 on error. 229 | * 230 | * Classic scrypt is available by setting shared = NULL, flags = 0, and t = 0. 231 | * 232 | * Setting YESCRYPT_WORM enables only minimal deviations from classic scrypt: 233 | * support for the t parameter, and pre- and post-hashing. 234 | * 235 | * Setting YESCRYPT_RW fully enables yescrypt. As a side effect of differences 236 | * between the algorithms, it also prevents p > 1 from growing the threads' 237 | * combined processing time and memory allocation (like it did with classic 238 | * scrypt and YESCRYPT_WORM), treating p as a divider rather than a multiplier. 239 | * 240 | * Passing a shared structure, with ROM contents previously computed by 241 | * yescrypt_init_shared(), enables the use of ROM and requires YESCRYPT_RW. 242 | * 243 | * In order to allow for initialization of the ROM to be split into a separate 244 | * program (or separate invocation of the same program), the shared->aligned 245 | * and shared->aligned_size fields may optionally be set by the caller directly 246 | * (e.g., to a mapped SysV shm segment), without using yescrypt_init_shared(). 247 | * 248 | * local must be initialized with yescrypt_init_local(). 249 | * 250 | * MT-safe as long as local and buf are local to the thread. 251 | */ 252 | extern int yescrypt_kdf(const yescrypt_shared_t *shared, 253 | yescrypt_local_t *local, 254 | const uint8_t *passwd, size_t passwdlen, 255 | const uint8_t *salt, size_t saltlen, 256 | const yescrypt_params_t *params, 257 | uint8_t *buf, size_t buflen); 258 | 259 | /** 260 | * yescrypt_r(shared, local, passwd, passwdlen, setting, key, buf, buflen): 261 | * Compute and encode an scrypt or enhanced scrypt hash of passwd given the 262 | * parameters and salt value encoded in setting. If shared is not NULL, a ROM 263 | * is used and YESCRYPT_RW is required. Otherwise, whether to compute classic 264 | * scrypt, YESCRYPT_WORM (a slight deviation from classic scrypt), or 265 | * YESCRYPT_RW (time-memory tradeoff discouraging modification) is determined 266 | * by the setting string. shared (if not NULL) and local must be initialized 267 | * as described above for yescrypt_kdf(). buf must be large enough (as 268 | * indicated by buflen) to hold the encoded hash string. 269 | * 270 | * Return the encoded hash string on success; or NULL on error. 271 | * 272 | * MT-safe as long as local and buf are local to the thread. 273 | */ 274 | extern uint8_t *yescrypt_r(const yescrypt_shared_t *shared, 275 | yescrypt_local_t *local, 276 | const uint8_t *passwd, size_t passwdlen, 277 | const uint8_t *setting, 278 | const yescrypt_binary_t *key, 279 | uint8_t *buf, size_t buflen); 280 | 281 | /** 282 | * yescrypt(passwd, setting): 283 | * Compute and encode an scrypt or enhanced scrypt hash of passwd given the 284 | * parameters and salt value encoded in setting. Whether to compute classic 285 | * scrypt, YESCRYPT_WORM (a slight deviation from classic scrypt), or 286 | * YESCRYPT_RW (time-memory tradeoff discouraging modification) is determined 287 | * by the setting string. 288 | * 289 | * Return the encoded hash string on success; or NULL on error. 290 | * 291 | * This is a crypt(3)-like interface, which is simpler to use than 292 | * yescrypt_r(), but it is not MT-safe, it does not allow for the use of a ROM, 293 | * and it is slower than yescrypt_r() for repeated calls because it allocates 294 | * and frees memory on each call. 295 | * 296 | * MT-unsafe. 297 | */ 298 | extern uint8_t *yescrypt(const uint8_t *passwd, const uint8_t *setting); 299 | 300 | /** 301 | * yescrypt_reencrypt(hash, from_key, to_key): 302 | * Re-encrypt a yescrypt hash from one key to another. Either key may be NULL 303 | * to indicate unencrypted hash. The encoded hash string is modified in-place. 304 | * 305 | * Return the hash pointer on success; or NULL on error (in which case the hash 306 | * string is left unmodified). 307 | * 308 | * MT-safe as long as hash is local to the thread. 309 | */ 310 | extern uint8_t *yescrypt_reencrypt(uint8_t *hash, 311 | const yescrypt_binary_t *from_key, 312 | const yescrypt_binary_t *to_key); 313 | 314 | /** 315 | * yescrypt_encode_params_r(params, src, srclen, buf, buflen): 316 | * Generate a setting string for use with yescrypt_r() and yescrypt() by 317 | * encoding into it the parameters flags, N, r, p, t, g, and a salt given by 318 | * src (of srclen bytes). buf must be large enough (as indicated by buflen) 319 | * to hold the setting string. 320 | * 321 | * Return the setting string on success; or NULL on error. 322 | * 323 | * MT-safe as long as buf is local to the thread. 324 | */ 325 | extern uint8_t *yescrypt_encode_params_r(const yescrypt_params_t *params, 326 | const uint8_t *src, size_t srclen, 327 | uint8_t *buf, size_t buflen); 328 | 329 | /** 330 | * yescrypt_encode_params(params, src, srclen): 331 | * Generate a setting string for use with yescrypt_r() and yescrypt(). This 332 | * function is the same as yescrypt_encode_params_r() except that it uses a 333 | * static buffer and thus is not MT-safe. 334 | * 335 | * Return the setting string on success; or NULL on error. 336 | * 337 | * MT-unsafe. 338 | */ 339 | extern uint8_t *yescrypt_encode_params(const yescrypt_params_t *params, 340 | const uint8_t *src, size_t srclen); 341 | 342 | #ifdef __cplusplus 343 | } 344 | #endif 345 | 346 | #endif /* !_YESCRYPT_H_ */ 347 | --------------------------------------------------------------------------------