10ac341f1SConrad Meyer /*-
20ac341f1SConrad Meyer * Copyright 2013 Alexander Peslyak
30ac341f1SConrad Meyer * All rights reserved.
40ac341f1SConrad Meyer *
50ac341f1SConrad Meyer * Redistribution and use in source and binary forms, with or without
60ac341f1SConrad Meyer * modification, are permitted.
70ac341f1SConrad Meyer *
80ac341f1SConrad Meyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
90ac341f1SConrad Meyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
100ac341f1SConrad Meyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
110ac341f1SConrad Meyer * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
120ac341f1SConrad Meyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
130ac341f1SConrad Meyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
140ac341f1SConrad Meyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
150ac341f1SConrad Meyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
160ac341f1SConrad Meyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
170ac341f1SConrad Meyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
180ac341f1SConrad Meyer * SUCH DAMAGE.
190ac341f1SConrad Meyer */
200ac341f1SConrad Meyer
210ac341f1SConrad Meyer #include <stdint.h>
220ac341f1SConrad Meyer #include <string.h>
230ac341f1SConrad Meyer
240ac341f1SConrad Meyer #include "crypto_pwhash_scryptsalsa208sha256.h"
250ac341f1SConrad Meyer #include "crypto_scrypt.h"
260ac341f1SConrad Meyer #include "private/common.h"
270ac341f1SConrad Meyer #include "runtime.h"
280ac341f1SConrad Meyer #include "utils.h"
290ac341f1SConrad Meyer
300ac341f1SConrad Meyer static const char *const itoa64 =
310ac341f1SConrad Meyer "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
320ac341f1SConrad Meyer
330ac341f1SConrad Meyer static uint8_t *
encode64_uint32(uint8_t * dst,size_t dstlen,uint32_t src,uint32_t srcbits)340ac341f1SConrad Meyer encode64_uint32(uint8_t *dst, size_t dstlen, uint32_t src, uint32_t srcbits)
350ac341f1SConrad Meyer {
360ac341f1SConrad Meyer uint32_t bit;
370ac341f1SConrad Meyer
380ac341f1SConrad Meyer for (bit = 0; bit < srcbits; bit += 6) {
390ac341f1SConrad Meyer if (dstlen < 1) {
400ac341f1SConrad Meyer return NULL; /* LCOV_EXCL_LINE */
410ac341f1SConrad Meyer }
420ac341f1SConrad Meyer *dst++ = itoa64[src & 0x3f];
430ac341f1SConrad Meyer dstlen--;
440ac341f1SConrad Meyer src >>= 6;
450ac341f1SConrad Meyer }
460ac341f1SConrad Meyer return dst;
470ac341f1SConrad Meyer }
480ac341f1SConrad Meyer
490ac341f1SConrad Meyer static uint8_t *
encode64(uint8_t * dst,size_t dstlen,const uint8_t * src,size_t srclen)500ac341f1SConrad Meyer encode64(uint8_t *dst, size_t dstlen, const uint8_t *src, size_t srclen)
510ac341f1SConrad Meyer {
520ac341f1SConrad Meyer size_t i;
530ac341f1SConrad Meyer
540ac341f1SConrad Meyer for (i = 0; i < srclen;) {
550ac341f1SConrad Meyer uint8_t *dnext;
560ac341f1SConrad Meyer uint32_t value = 0, bits = 0;
570ac341f1SConrad Meyer
580ac341f1SConrad Meyer do {
590ac341f1SConrad Meyer value |= (uint32_t) src[i++] << bits;
600ac341f1SConrad Meyer bits += 8;
610ac341f1SConrad Meyer } while (bits < 24 && i < srclen);
620ac341f1SConrad Meyer
630ac341f1SConrad Meyer dnext = encode64_uint32(dst, dstlen, value, bits);
640ac341f1SConrad Meyer if (!dnext) {
650ac341f1SConrad Meyer return NULL; /* LCOV_EXCL_LINE */
660ac341f1SConrad Meyer }
670ac341f1SConrad Meyer dstlen -= dnext - dst;
680ac341f1SConrad Meyer dst = dnext;
690ac341f1SConrad Meyer }
700ac341f1SConrad Meyer return dst;
710ac341f1SConrad Meyer }
720ac341f1SConrad Meyer
730ac341f1SConrad Meyer static int
decode64_one(uint32_t * dst,uint8_t src)740ac341f1SConrad Meyer decode64_one(uint32_t *dst, uint8_t src)
750ac341f1SConrad Meyer {
760ac341f1SConrad Meyer const char *ptr = strchr(itoa64, src);
770ac341f1SConrad Meyer
780ac341f1SConrad Meyer if (ptr) {
790ac341f1SConrad Meyer *dst = (uint32_t)(ptr - itoa64);
800ac341f1SConrad Meyer return 0;
810ac341f1SConrad Meyer }
820ac341f1SConrad Meyer *dst = 0;
830ac341f1SConrad Meyer
840ac341f1SConrad Meyer return -1;
850ac341f1SConrad Meyer }
860ac341f1SConrad Meyer
870ac341f1SConrad Meyer static const uint8_t *
decode64_uint32(uint32_t * dst,uint32_t dstbits,const uint8_t * src)880ac341f1SConrad Meyer decode64_uint32(uint32_t *dst, uint32_t dstbits, const uint8_t *src)
890ac341f1SConrad Meyer {
900ac341f1SConrad Meyer uint32_t bit;
910ac341f1SConrad Meyer uint32_t value;
920ac341f1SConrad Meyer
930ac341f1SConrad Meyer value = 0;
940ac341f1SConrad Meyer for (bit = 0; bit < dstbits; bit += 6) {
950ac341f1SConrad Meyer uint32_t one;
960ac341f1SConrad Meyer if (decode64_one(&one, *src)) {
970ac341f1SConrad Meyer *dst = 0;
980ac341f1SConrad Meyer return NULL;
990ac341f1SConrad Meyer }
1000ac341f1SConrad Meyer src++;
1010ac341f1SConrad Meyer value |= one << bit;
1020ac341f1SConrad Meyer }
1030ac341f1SConrad Meyer *dst = value;
1040ac341f1SConrad Meyer
1050ac341f1SConrad Meyer return src;
1060ac341f1SConrad Meyer }
1070ac341f1SConrad Meyer
1080ac341f1SConrad Meyer const uint8_t *
escrypt_parse_setting(const uint8_t * setting,uint32_t * N_log2_p,uint32_t * r_p,uint32_t * p_p)1090ac341f1SConrad Meyer escrypt_parse_setting(const uint8_t *setting,
1100ac341f1SConrad Meyer uint32_t *N_log2_p, uint32_t *r_p, uint32_t *p_p)
1110ac341f1SConrad Meyer {
1120ac341f1SConrad Meyer const uint8_t *src;
1130ac341f1SConrad Meyer
1140ac341f1SConrad Meyer if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$') {
1150ac341f1SConrad Meyer return NULL;
1160ac341f1SConrad Meyer }
1170ac341f1SConrad Meyer src = setting + 3;
1180ac341f1SConrad Meyer
1190ac341f1SConrad Meyer if (decode64_one(N_log2_p, *src)) {
1200ac341f1SConrad Meyer return NULL;
1210ac341f1SConrad Meyer }
1220ac341f1SConrad Meyer src++;
1230ac341f1SConrad Meyer
1240ac341f1SConrad Meyer src = decode64_uint32(r_p, 30, src);
1250ac341f1SConrad Meyer if (!src) {
1260ac341f1SConrad Meyer return NULL;
1270ac341f1SConrad Meyer }
1280ac341f1SConrad Meyer
1290ac341f1SConrad Meyer src = decode64_uint32(p_p, 30, src);
1300ac341f1SConrad Meyer if (!src) {
1310ac341f1SConrad Meyer return NULL;
1320ac341f1SConrad Meyer }
1330ac341f1SConrad Meyer return src;
1340ac341f1SConrad Meyer }
1350ac341f1SConrad Meyer
1360ac341f1SConrad Meyer uint8_t *
escrypt_r(escrypt_local_t * local,const uint8_t * passwd,size_t passwdlen,const uint8_t * setting,uint8_t * buf,size_t buflen)1370ac341f1SConrad Meyer escrypt_r(escrypt_local_t *local, const uint8_t *passwd, size_t passwdlen,
1380ac341f1SConrad Meyer const uint8_t *setting, uint8_t *buf, size_t buflen)
1390ac341f1SConrad Meyer {
1400ac341f1SConrad Meyer uint8_t hash[crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES];
1410ac341f1SConrad Meyer escrypt_kdf_t escrypt_kdf;
1420ac341f1SConrad Meyer const uint8_t *src;
1430ac341f1SConrad Meyer const uint8_t *salt;
1440ac341f1SConrad Meyer uint8_t *dst;
1450ac341f1SConrad Meyer size_t prefixlen;
1460ac341f1SConrad Meyer size_t saltlen;
1470ac341f1SConrad Meyer size_t need;
1480ac341f1SConrad Meyer uint64_t N;
1490ac341f1SConrad Meyer uint32_t N_log2;
1500ac341f1SConrad Meyer uint32_t r;
1510ac341f1SConrad Meyer uint32_t p;
1520ac341f1SConrad Meyer
1530ac341f1SConrad Meyer src = escrypt_parse_setting(setting, &N_log2, &r, &p);
1540ac341f1SConrad Meyer if (!src) {
1550ac341f1SConrad Meyer return NULL;
1560ac341f1SConrad Meyer }
1570ac341f1SConrad Meyer N = (uint64_t) 1 << N_log2;
1580ac341f1SConrad Meyer prefixlen = src - setting;
1590ac341f1SConrad Meyer
1600ac341f1SConrad Meyer salt = src;
1610ac341f1SConrad Meyer src = (uint8_t *) strrchr((char *) salt, '$');
1620ac341f1SConrad Meyer if (src) {
1630ac341f1SConrad Meyer saltlen = src - salt;
1640ac341f1SConrad Meyer } else {
1650ac341f1SConrad Meyer saltlen = strlen((char *) salt);
1660ac341f1SConrad Meyer }
1670ac341f1SConrad Meyer need = prefixlen + saltlen + 1 +
1680ac341f1SConrad Meyer crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1;
1690ac341f1SConrad Meyer if (need > buflen || need < saltlen) {
1700ac341f1SConrad Meyer return NULL;
1710ac341f1SConrad Meyer }
1720ac341f1SConrad Meyer #ifdef HAVE_EMMINTRIN_H
1730ac341f1SConrad Meyer escrypt_kdf =
1740ac341f1SConrad Meyer sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
1750ac341f1SConrad Meyer #else
1760ac341f1SConrad Meyer escrypt_kdf = escrypt_kdf_nosse;
1770ac341f1SConrad Meyer #endif
1780ac341f1SConrad Meyer if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen, N, r, p, hash,
1790ac341f1SConrad Meyer sizeof(hash))) {
1800ac341f1SConrad Meyer return NULL;
1810ac341f1SConrad Meyer }
1820ac341f1SConrad Meyer dst = buf;
1830ac341f1SConrad Meyer memcpy(dst, setting, prefixlen + saltlen);
1840ac341f1SConrad Meyer dst += prefixlen + saltlen;
1850ac341f1SConrad Meyer *dst++ = '$';
1860ac341f1SConrad Meyer
1870ac341f1SConrad Meyer dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash));
1880ac341f1SConrad Meyer sodium_memzero(hash, sizeof hash);
1890ac341f1SConrad Meyer if (!dst || dst >= buf + buflen) {
1900ac341f1SConrad Meyer return NULL; /* Can't happen LCOV_EXCL_LINE */
1910ac341f1SConrad Meyer }
1920ac341f1SConrad Meyer *dst = 0; /* NUL termination */
1930ac341f1SConrad Meyer
1940ac341f1SConrad Meyer return buf;
1950ac341f1SConrad Meyer }
1960ac341f1SConrad Meyer
1970ac341f1SConrad Meyer uint8_t *
escrypt_gensalt_r(uint32_t N_log2,uint32_t r,uint32_t p,const uint8_t * src,size_t srclen,uint8_t * buf,size_t buflen)1980ac341f1SConrad Meyer escrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p, const uint8_t *src,
1990ac341f1SConrad Meyer size_t srclen, uint8_t *buf, size_t buflen)
2000ac341f1SConrad Meyer {
2010ac341f1SConrad Meyer uint8_t *dst;
2020ac341f1SConrad Meyer size_t prefixlen =
2030ac341f1SConrad Meyer (sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */);
2040ac341f1SConrad Meyer size_t saltlen = BYTES2CHARS(srclen);
2050ac341f1SConrad Meyer size_t need;
2060ac341f1SConrad Meyer
2070ac341f1SConrad Meyer need = prefixlen + saltlen + 1;
2080ac341f1SConrad Meyer if (need > buflen || need < saltlen || saltlen < srclen) {
2090ac341f1SConrad Meyer return NULL; /* LCOV_EXCL_LINE */
2100ac341f1SConrad Meyer }
2110ac341f1SConrad Meyer if (N_log2 > 63 || ((uint64_t) r * (uint64_t) p >= (1U << 30))) {
2120ac341f1SConrad Meyer return NULL; /* LCOV_EXCL_LINE */
2130ac341f1SConrad Meyer }
2140ac341f1SConrad Meyer dst = buf;
2150ac341f1SConrad Meyer *dst++ = '$';
2160ac341f1SConrad Meyer *dst++ = '7';
2170ac341f1SConrad Meyer *dst++ = '$';
2180ac341f1SConrad Meyer
2190ac341f1SConrad Meyer *dst++ = itoa64[N_log2];
2200ac341f1SConrad Meyer
2210ac341f1SConrad Meyer dst = encode64_uint32(dst, buflen - (dst - buf), r, 30);
2220ac341f1SConrad Meyer if (!dst) {
2230ac341f1SConrad Meyer return NULL; /* Can't happen LCOV_EXCL_LINE */
2240ac341f1SConrad Meyer }
2250ac341f1SConrad Meyer dst = encode64_uint32(dst, buflen - (dst - buf), p, 30);
2260ac341f1SConrad Meyer if (!dst) {
2270ac341f1SConrad Meyer return NULL; /* Can't happen LCOV_EXCL_LINE */
2280ac341f1SConrad Meyer }
2290ac341f1SConrad Meyer dst = encode64(dst, buflen - (dst - buf), src, srclen);
2300ac341f1SConrad Meyer if (!dst || dst >= buf + buflen) {
2310ac341f1SConrad Meyer return NULL; /* Can't happen LCOV_EXCL_LINE */
2320ac341f1SConrad Meyer }
2330ac341f1SConrad Meyer *dst = 0; /* NUL termination */
2340ac341f1SConrad Meyer
2350ac341f1SConrad Meyer return buf;
2360ac341f1SConrad Meyer }
2370ac341f1SConrad Meyer
2380ac341f1SConrad Meyer int
crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd,size_t passwdlen,const uint8_t * salt,size_t saltlen,uint64_t N,uint32_t r,uint32_t p,uint8_t * buf,size_t buflen)2390ac341f1SConrad Meyer crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t *passwd, size_t passwdlen,
2400ac341f1SConrad Meyer const uint8_t *salt, size_t saltlen,
2410ac341f1SConrad Meyer uint64_t N, uint32_t r, uint32_t p,
2420ac341f1SConrad Meyer uint8_t *buf, size_t buflen)
2430ac341f1SConrad Meyer {
2440ac341f1SConrad Meyer escrypt_kdf_t escrypt_kdf;
2450ac341f1SConrad Meyer escrypt_local_t local;
2460ac341f1SConrad Meyer int retval;
2470ac341f1SConrad Meyer
2480ac341f1SConrad Meyer if (escrypt_init_local(&local)) {
2490ac341f1SConrad Meyer return -1; /* LCOV_EXCL_LINE */
2500ac341f1SConrad Meyer }
2510ac341f1SConrad Meyer #if defined(HAVE_EMMINTRIN_H)
2520ac341f1SConrad Meyer escrypt_kdf =
2530ac341f1SConrad Meyer sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse;
2540ac341f1SConrad Meyer #else
2550ac341f1SConrad Meyer escrypt_kdf = escrypt_kdf_nosse;
2560ac341f1SConrad Meyer #endif
2570ac341f1SConrad Meyer retval = escrypt_kdf(&local, passwd, passwdlen, salt, saltlen, N, r, p, buf,
2580ac341f1SConrad Meyer buflen);
2590ac341f1SConrad Meyer if (escrypt_free_local(&local)) {
2600ac341f1SConrad Meyer return -1; /* LCOV_EXCL_LINE */
2610ac341f1SConrad Meyer }
2620ac341f1SConrad Meyer return retval;
2630ac341f1SConrad Meyer }
264