0051ee0e1a476eb435aaef679ffa010550c5c796
[trex.git] /
1
2 #include <errno.h>
3 #include <limits.h>
4 #include <stddef.h>
5 #include <stdint.h>
6 #include <string.h>
7
8 #include "crypto_pwhash_scryptsalsa208sha256.h"
9 #include "crypto_scrypt.h"
10 #include "randombytes.h"
11 #include "utils.h"
12
13 #define SETTING_SIZE(saltbytes) \
14     (sizeof "$7$" - 1U) + \
15     (1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + BYTES2CHARS(saltbytes)
16
17 static int
18 pickparams(unsigned long long opslimit, const size_t memlimit,
19            uint32_t * const N_log2, uint32_t * const p, uint32_t * const r)
20 {
21     unsigned long long maxN;
22     unsigned long long maxrp;
23
24     if (opslimit < 32768) {
25         opslimit = 32768;
26     }
27     *r = 8;
28     if (opslimit < memlimit / 32) {
29         *p = 1;
30         maxN = opslimit / (*r * 4);
31         for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
32             if ((uint64_t)(1) << *N_log2 > maxN / 2) {
33                 break;
34             }
35         }
36     } else {
37         maxN = memlimit / ((size_t) *r * 128);
38         for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) {
39             if ((uint64_t) (1) << *N_log2 > maxN / 2) {
40                 break;
41             }
42         }
43         maxrp = (opslimit / 4) / ((uint64_t) (1) << *N_log2);
44         /* LCOV_EXCL_START */
45         if (maxrp > 0x3fffffff) {
46             maxrp = 0x3fffffff;
47         }
48         /* LCOV_EXCL_STOP */
49         *p = (uint32_t) (maxrp) / *r;
50     }
51     return 0;
52 }
53
54 size_t
55 crypto_pwhash_scryptsalsa208sha256_saltbytes(void)
56 {
57     return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
58 }
59
60 size_t
61 crypto_pwhash_scryptsalsa208sha256_strbytes(void)
62 {
63     return crypto_pwhash_scryptsalsa208sha256_STRBYTES;
64 }
65
66 const char *
67 crypto_pwhash_scryptsalsa208sha256_strprefix(void)
68 {
69     return crypto_pwhash_scryptsalsa208sha256_STRPREFIX;
70 }
71
72 size_t
73 crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void)
74 {
75     return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE;
76 }
77
78 size_t
79 crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void)
80 {
81     return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE;
82 }
83
84 size_t
85 crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void)
86 {
87     return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE;
88 }
89
90 size_t
91 crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void)
92 {
93     return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE;
94 }
95
96 int
97 crypto_pwhash_scryptsalsa208sha256(unsigned char * const out,
98                                     unsigned long long outlen,
99                                     const char * const passwd,
100                                     unsigned long long passwdlen,
101                                     const unsigned char * const salt,
102                                     unsigned long long opslimit,
103                                     size_t memlimit)
104 {
105     uint32_t N_log2;
106     uint32_t p;
107     uint32_t r;
108
109     memset(out, 0, outlen);
110     if (passwdlen > SIZE_MAX || outlen > SIZE_MAX) {
111         errno = EFBIG; /* LCOV_EXCL_LINE */
112         return -1; /* LCOV_EXCL_LINE */
113     }
114     if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
115         errno = EINVAL; /* LCOV_EXCL_LINE */
116         return -1; /* LCOV_EXCL_LINE */
117     }
118     return crypto_pwhash_scryptsalsa208sha256_ll((const uint8_t *) passwd,
119                                                  (size_t) passwdlen,
120                                                  (const uint8_t *) salt,
121                                                  crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
122                                                  (uint64_t) (1) << N_log2, r, p,
123                                                  out, (size_t) outlen);
124 }
125
126 int
127 crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
128                                         const char * const passwd,
129                                         unsigned long long passwdlen,
130                                         unsigned long long opslimit,
131                                         size_t memlimit)
132 {
133     uint8_t         salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES];
134     char            setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U];
135     escrypt_local_t escrypt_local;
136     uint32_t        N_log2;
137     uint32_t        p;
138     uint32_t        r;
139
140     memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES);
141     if (passwdlen > SIZE_MAX) {
142         errno = EFBIG; /* LCOV_EXCL_LINE */
143         return -1; /* LCOV_EXCL_LINE */
144     }
145     if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) {
146         errno = EINVAL; /* LCOV_EXCL_LINE */
147         return -1; /* LCOV_EXCL_LINE */
148     }
149     randombytes_buf(salt, sizeof salt);
150     if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt,
151                           (uint8_t *) setting, sizeof setting) == NULL) {
152         errno = EINVAL; /* LCOV_EXCL_LINE */
153         return -1; /* LCOV_EXCL_LINE */
154     }
155     if (escrypt_init_local(&escrypt_local) != 0) {
156         return -1; /* LCOV_EXCL_LINE */
157     }
158     if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
159                   (const uint8_t *) setting, (uint8_t *) out,
160                   crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) {
161         /* LCOV_EXCL_START */
162         escrypt_free_local(&escrypt_local);
163         errno = EINVAL;
164         return -1;
165         /* LCOV_EXCL_STOP */
166     }
167     escrypt_free_local(&escrypt_local);
168
169     (void) sizeof
170         (int[SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES)
171             == crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES ? 1 : -1]);
172     (void) sizeof
173         (int[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U +
174              crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U
175              == crypto_pwhash_scryptsalsa208sha256_STRBYTES ? 1 : -1]);
176
177     return 0;
178 }
179
180 int
181 crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES],
182                                                const char * const passwd,
183                                                unsigned long long passwdlen)
184 {
185     char            wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES];
186     escrypt_local_t escrypt_local;
187     int             ret = -1;
188
189     if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) !=
190         &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) {
191         return -1;
192     }
193     if (escrypt_init_local(&escrypt_local) != 0) {
194         return -1; /* LCOV_EXCL_LINE */
195     }
196     if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen,
197                   (const uint8_t *) str, (uint8_t *) wanted,
198                   sizeof wanted) == NULL) {
199         escrypt_free_local(&escrypt_local);
200         return -1;
201     }
202     escrypt_free_local(&escrypt_local);
203     ret = sodium_memcmp(wanted, str, sizeof wanted);
204     sodium_memzero(wanted, sizeof wanted);
205
206     return ret;
207 }