summaryrefslogtreecommitdiff
path: root/crypto-mcf.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto-mcf.c')
-rw-r--r--crypto-mcf.c61
1 files changed, 35 insertions, 26 deletions
diff --git a/crypto-mcf.c b/crypto-mcf.c
index 66e92f0..8ad3eb8 100644
--- a/crypto-mcf.c
+++ b/crypto-mcf.c
@@ -3,31 +3,47 @@
#include <stdio.h>
#include <stdint.h>
#include <float.h>
-
+#include <stdint.h>
#include <math.h>
+#ifndef S_SPLINT_S /* Including this here triggers a known bug in splint */
+#include <unistd.h>
+#endif
+
#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);
+/* ilog2 for powers of two */
+static uint32_t scrypt_ilog2(uint32_t n)
+{
+#ifndef S_SPLINT_S
+
+ /* Check for a valid power of two */
+ if (n < 2 || (n & (n - 1)))
+ return -1;
+#endif
+ uint32_t t = 1;
+ while (((uint32_t)1 << t) < n)
+ {
+ if(t > SCRYPT_SAFE_N)
+ return (uint32_t) -1; /* Check for insanity */
+ t++;
+ }
+
+ return t;
}
-int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, char *salt, char *hash, char *mcf)
-{
+#ifdef _MSC_VER
+ #define SNPRINTF _snprintf
+#else
+ #define SNPRINTF snprintf
+#endif
+int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, const char *salt,
+ const char *hash, char *mcf)
+{
- uint32_t params;
+ uint32_t t, params;
int s;
- double t, t2, fracpart;
if(!mcf || !hash)
return 0;
@@ -38,15 +54,8 @@ int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, char *salt, char *hash, ch
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)
+ t = scrypt_ilog2(N);
+ if (t < 1)
return 0;
params = (r << 8) + p;
@@ -56,7 +65,7 @@ int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, char *salt, char *hash, ch
* 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);
+ s = SNPRINTF(mcf, SCRYPT_MCF_LEN, SCRYPT_MCF_ID "$%06x$%s$%s", (unsigned int)params, salt, hash);
if (s > SCRYPT_MCF_LEN)
return 0;