static int checkparams(size_t maxmem, double maxmemfrac, double maxtime, int logN, uint32_t r, uint32_t p) { size_t memlimit; double opps; double opslimit; uint64_t N; int rc; /* Figure out the maximum amount of memory we can use. */ if (memtouse(maxmem, maxmemfrac, &memlimit)) return (1); /* Figure out how fast the CPU is. */ if ((rc = scryptenc_cpuperf(&opps)) != 0) return (rc); opslimit = opps * maxtime; /* Sanity-check values. */ if ((logN < 1) || (logN > 63)) return (7); if ((uint64_t)(r) * (uint64_t)(p) >= 0x40000000) return (7); /* Check limits. */ N = (uint64_t)(1) << logN; if ((memlimit / N) / r < 128) return (9); if ((opslimit / N) / (r * p) < 4) return (10); /* Success! */ return (0); }
/* * Given maxmem, maxmemfrac and maxtime, this functions calculates the N,r,p variables. * Values for N,r,p are machine dependent. This is copied directly from Colin Percival's srypt reference code */ int pickparams(int *logN, uint32_t *r, uint32_t *p, double maxtime, size_t maxmem, double maxmemfrac) { //Note: logN (as opposed to N) is calculated here. This is because it is compact (it can be represented by an int) // and it is easy (and quick) to convert to N by right shifting bits. Most importantly, using logN only requires // 32 bits to be stored. Seeing as it is embedded inside the hash, the smaller the better size_t memlimit; double opps; double opslimit; double maxN, maxrp; int rc; /* Figure out how much memory to use. */ if (memtouse(maxmem, maxmemfrac, &memlimit)) return (1); /* Figure out how fast the CPU is. */ if ((rc = scryptenc_cpuperf(&opps)) != 0) return (rc); opslimit = opps * maxtime; /* Allow a minimum of 2^15 salsa20/8 cores. */ if (opslimit < 32768) opslimit = 32768; /* Set r to 8 */ *r = 8; // r is the underlying block size, Colin Percival defaults to 8 in his reference implementation /* * The memory limit requires that 128Nr <= memlimit, while the CPU * limit requires that 4Nrp <= opslimit. If opslimit < memlimit/32, * opslimit imposes the stronger limit on N. */ if (opslimit < memlimit/32) { /* Set p = 1 and choose N based on the CPU limit. */ *p = 1; maxN = opslimit / (*r * 4); for (*logN = 1; *logN < 63; *logN += 1) { if ((uint64_t)(1) << *logN > maxN / 2) break; } } else { /* Set N based on the memory limit. */ maxN = (double)(memlimit / (*r * 128)); for (*logN = 1; *logN < 63; *logN += 1) { if ((uint64_t)(1) << *logN > maxN / 2) break; } /* Choose p based on the CPU limit. */ maxrp = (opslimit / 4) / ((uint64_t)(1) << *logN); if (maxrp > 0x3fffffff) maxrp = 0x3fffffff; *p = (uint32_t)(maxrp) / *r; } /* Success! */ return (0); }
static int pickparams(size_t maxmem, double maxmemfrac, double maxtime, int * logN, uint32_t * r, uint32_t * p) { size_t memlimit; double opps; double opslimit; double maxN, maxrp; int rc; /* Figure out how much memory to use. */ if (memtouse(maxmem, maxmemfrac, &memlimit)) return (1); /* Figure out how fast the CPU is. */ if ((rc = scryptenc_cpuperf(&opps)) != 0) return (rc); opslimit = opps * maxtime; /* Allow a minimum of 2^15 salsa20/8 cores. */ if (opslimit < 32768) opslimit = 32768; /* Fix r = 8 for now. */ *r = 8; /* * The memory limit requires that 128Nr <= memlimit, while the CPU * limit requires that 4Nrp <= opslimit. If opslimit < memlimit/32, * opslimit imposes the stronger limit on N. */ #ifdef DEBUG fprintf(stderr, "Requiring 128Nr <= %zu, 4Nrp <= %f\n", memlimit, opslimit); #endif if (opslimit < memlimit/32) { /* Set p = 1 and choose N based on the CPU limit. */ *p = 1; maxN = opslimit / (*r * 4); for (*logN = 1; *logN < 63; *logN += 1) { if ((uint64_t)(1) << *logN > maxN / 2) break; } } else { /* Set N based on the memory limit. */ maxN = memlimit / (*r * 128); for (*logN = 1; *logN < 63; *logN += 1) { if ((uint64_t)(1) << *logN > maxN / 2) break; } /* Choose p based on the CPU limit. */ maxrp = (opslimit / 4) / ((uint64_t)(1) << *logN); if (maxrp > 0x3fffffff) maxrp = 0x3fffffff; *p = (uint32_t)(maxrp) / *r; } #ifdef DEBUG fprintf(stderr, "N = %zu r = %d p = %d\n", (size_t)(1) << *logN, (int)(*r), (int)(*p)); #endif /* Success! */ return (0); }