diff options
Diffstat (limited to 'crypto-mcf.c')
-rw-r--r-- | crypto-mcf.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/crypto-mcf.c b/crypto-mcf.c new file mode 100644 index 0000000..66e92f0 --- /dev/null +++ b/crypto-mcf.c @@ -0,0 +1,64 @@ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdint.h> +#include <float.h> + +#include <math.h> + +#include "libscrypt.h" + +/* Although log2 exists in GNU99 C, more portable code shouldn't use it +* Note that this function returns a float and hence is not compatible with the +* GNU prototype +*/ +static double scrypt_log2( uint32_t n ) +{ + // log(n)/log(2) is log2. + double temp; + /* Using the temp variable keeps splint happy */ + temp = log(2); + return (log((double)n) / temp); +} + +int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, char *salt, char *hash, char *mcf) +{ + + + uint32_t params; + int s; + double t, t2, fracpart; + + if(!mcf || !hash) + return 0; + /* Although larger values of r, p are valid in scrypt, this mcf format + * limits to 8 bits. If your number is larger, current computers will + * struggle + */ + if(r > (uint8_t)(-1) || p > (uint8_t)(-1)) + return 0; + + + t = scrypt_log2(N); + + /* The "whole numebr" check below is non-trivial due to precision + * issues, where you could printf("%d", (int)t) and find yourself + * looking at (expected value) -1 + */ + fracpart = modf(t, &t2); + if(fracpart > DBL_EPSILON) + return 0; + + params = (r << 8) + p; + params += (uint32_t)t << 16; + + /* Using snprintf - not checking for overflows. We've already + * determined that mcf should be defined as at least SCRYPT_MCF_LEN + * in length + */ + s = snprintf(mcf, SCRYPT_MCF_LEN, SCRYPT_MCF_ID "$%06x$%s$%s", (unsigned int)params, salt, hash); + if (s > SCRYPT_MCF_LEN) + return 0; + + return 1; +} |