1 /*- 2 * Copyright 2009 Colin Percival 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * This file was originally written by Colin Percival as part of the Tarsnap 27 * online backup system. 28 */ 29 #include <sys/types.h> 30 #include <sys/mman.h> 31 32 #include <errno.h> 33 #include <stdint.h> 34 #include <stdlib.h> 35 #include <string.h> 36 37 #include "pbkdf2.h" 38 39 #include "crypto_scrypt_smix.h" 40 41 #include "crypto_scrypt.h" 42 43 static void (*smix_func)(uint8_t *, size_t, uint64_t, void *, void *) = NULL; 44 45 /** 46 * _crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen, smix): 47 * Perform the requested scrypt computation, using ${smix} as the smix routine. 48 */ 49 static int 50 _crypto_scrypt(const uint8_t * passwd, size_t passwdlen, 51 const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t _r, uint32_t _p, 52 uint8_t * buf, size_t buflen, 53 void (*smix)(uint8_t *, size_t, uint64_t, void *, void *)) 54 { 55 void * B0, * V0, * XY0; 56 uint8_t * B; 57 uint32_t * V; 58 uint32_t * XY; 59 size_t r = _r, p = _p; 60 uint32_t i; 61 62 /* Sanity-check parameters. */ 63 #if SIZE_MAX > UINT32_MAX 64 if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { 65 errno = EFBIG; 66 goto err0; 67 } 68 #endif 69 if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { 70 errno = EFBIG; 71 goto err0; 72 } 73 if (((N & (N - 1)) != 0) || (N < 2)) { 74 errno = EINVAL; 75 goto err0; 76 } 77 if ((r > SIZE_MAX / 128 / p) || 78 #if SIZE_MAX / 256 <= UINT32_MAX 79 (r > (SIZE_MAX - 64) / 256) || 80 #endif 81 (N > SIZE_MAX / 128 / r)) { 82 errno = ENOMEM; 83 goto err0; 84 } 85 86 /* Allocate memory. */ 87 #ifdef HAVE_POSIX_MEMALIGN 88 if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0) 89 goto err0; 90 B = (uint8_t *)(B0); 91 if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0) 92 goto err1; 93 XY = (uint32_t *)(XY0); 94 #if !defined(MAP_ANON) || !defined(HAVE_MMAP) 95 if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0) 96 goto err2; 97 V = (uint32_t *)(V0); 98 #endif 99 #else 100 if ((B0 = malloc(128 * r * p + 63)) == NULL) 101 goto err0; 102 B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63)); 103 if ((XY0 = malloc(256 * r + 64 + 63)) == NULL) 104 goto err1; 105 XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63)); 106 #if !defined(MAP_ANON) || !defined(HAVE_MMAP) 107 if ((V0 = malloc(128 * r * N + 63)) == NULL) 108 goto err2; 109 V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63)); 110 #endif 111 #endif 112 #if defined(MAP_ANON) && defined(HAVE_MMAP) 113 if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE, 114 #ifdef MAP_NOCORE 115 MAP_ANON | MAP_PRIVATE | MAP_NOCORE, 116 #else 117 MAP_ANON | MAP_PRIVATE, 118 #endif 119 -1, 0)) == MAP_FAILED) 120 goto err2; 121 V = (uint32_t *)(V0); 122 #endif 123 124 /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ 125 PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); 126 127 /* 2: for i = 0 to p - 1 do */ 128 for (i = 0; i < p; i++) { 129 /* 3: B_i <-- MF(B_i, N) */ 130 (smix)(&B[i * 128 * r], r, N, V, XY); 131 } 132 133 /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ 134 PBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); 135 136 /* Free memory. */ 137 #if defined(MAP_ANON) && defined(HAVE_MMAP) 138 if (munmap(V0, 128 * r * N)) 139 goto err2; 140 #else 141 free(V0); 142 #endif 143 free(XY0); 144 free(B0); 145 146 /* Success! */ 147 return (0); 148 149 err2: 150 free(XY0); 151 err1: 152 free(B0); 153 err0: 154 /* Failure! */ 155 return (-1); 156 } 157 158 #define TESTLEN 64 159 static struct scrypt_test { 160 const char * passwd; 161 const char * salt; 162 uint64_t N; 163 uint32_t r; 164 uint32_t p; 165 uint8_t result[TESTLEN]; 166 } testcase = { 167 "pleaseletmein", 168 "SodiumChloride", 169 16, 170 8, 171 1, 172 { 173 0x25, 0xa9, 0xfa, 0x20, 0x7f, 0x87, 0xca, 0x09, 174 0xa4, 0xef, 0x8b, 0x9f, 0x77, 0x7a, 0xca, 0x16, 175 0xbe, 0xb7, 0x84, 0xae, 0x18, 0x30, 0xbf, 0xbf, 176 0xd3, 0x83, 0x25, 0xaa, 0xbb, 0x93, 0x77, 0xdf, 177 0x1b, 0xa7, 0x84, 0xd7, 0x46, 0xea, 0x27, 0x3b, 178 0xf5, 0x16, 0xa4, 0x6f, 0xbf, 0xac, 0xf5, 0x11, 179 0xc5, 0xbe, 0xba, 0x4c, 0x4a, 0xb3, 0xac, 0xc7, 180 0xfa, 0x6f, 0x46, 0x0b, 0x6c, 0x0f, 0x47, 0x7b, 181 } 182 }; 183 184 static int 185 testsmix(void (*smix)(uint8_t *, size_t, uint64_t, void *, void *)) 186 { 187 uint8_t hbuf[TESTLEN]; 188 189 /* Perform the computation. */ 190 if (_crypto_scrypt( 191 (const uint8_t *)testcase.passwd, strlen(testcase.passwd), 192 (const uint8_t *)testcase.salt, strlen(testcase.salt), 193 testcase.N, testcase.r, testcase.p, hbuf, TESTLEN, smix)) 194 return (-1); 195 196 /* Does it match? */ 197 return (memcmp(testcase.result, hbuf, TESTLEN)); 198 } 199 200 static void 201 selectsmix(void) 202 { 203 /* If generic smix works, use it. */ 204 if (!testsmix(crypto_scrypt_smix)) { 205 smix_func = crypto_scrypt_smix; 206 return; 207 } 208 209 /* If we get here, something really bad happened. */ 210 abort(); 211 } 212 213 /** 214 * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): 215 * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, 216 * p, buflen) and write the result into buf. The parameters r, p, and buflen 217 * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N 218 * must be a power of 2 greater than 1. 219 * 220 * Return 0 on success; or -1 on error. 221 */ 222 int 223 crypto_scrypt(const uint8_t * passwd, size_t passwdlen, 224 const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t _r, uint32_t _p, 225 uint8_t * buf, size_t buflen) 226 { 227 228 if (smix_func == NULL) 229 selectsmix(); 230 231 return (_crypto_scrypt(passwd, passwdlen, salt, saltlen, N, _r, _p, 232 buf, buflen, smix_func)); 233 } 234