uint8_t* yescrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p, yescrypt_flags_t flags, const uint8_t* src, size_t srclen, uint8_t* buf, size_t buflen) { uint8_t * dst; size_t prefixlen = 3 + 1 + 5 + 5; size_t saltlen = BYTES2CHARS(srclen); size_t need; if (p == 1) flags &= ~YESCRYPT_PARALLEL_SMIX; if (flags) { if (flags & ~0x3f) return NULL; prefixlen++; if (flags != YESCRYPT_RW) prefixlen++; } need = prefixlen + saltlen + 1; if (need > buflen || need < saltlen || saltlen < srclen) return NULL; if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30))) return NULL; dst = buf; *dst++ = '$'; *dst++ = '7'; if (flags) { *dst++ = 'X'; /* eXperimental, subject to change */ if (flags != YESCRYPT_RW) *dst++ = itoa64[flags]; } *dst++ = '$'; *dst++ = itoa64[N_log2]; dst = encode64_uint32(dst, buflen - (dst - buf), r, 30); if (!dst) /* Can't happen */ return NULL; dst = encode64_uint32(dst, buflen - (dst - buf), p, 30); if (!dst) /* Can't happen */ return NULL; dst = encode64(dst, buflen - (dst - buf), src, srclen); if (!dst || dst >= buf + buflen) /* Can't happen */ return NULL; *dst = 0; /* NUL termination */ return buf; }
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) { uint8_t *dst; size_t prefixlen = (sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */); size_t saltlen = BYTES2CHARS(srclen); size_t need; need = prefixlen + saltlen + 1; if (need > buflen || need < saltlen || saltlen < srclen) { return NULL; } if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30))) { return NULL; } dst = buf; *dst++ = '$'; *dst++ = '7'; *dst++ = '$'; *dst++ = itoa64[N_log2]; dst = encode64_uint32(dst, buflen - (dst - buf), r, 30); if (!dst) { /* Can't happen */ return NULL; } dst = encode64_uint32(dst, buflen - (dst - buf), p, 30); if (!dst) { /* Can't happen */ return NULL; } dst = encode64(dst, buflen - (dst - buf), src, srclen); if (!dst || dst >= buf + buflen) { /* Can't happen */ return NULL; } *dst = 0; /* NUL termination */ return buf; }
static uint8_t* encode64(uint8_t* dst, size_t dstlen, const uint8_t* src, size_t srclen) { size_t i; for (i = 0; i < srclen; ) { uint8_t * dnext; uint32_t value = 0, bits = 0; do { value |= (uint32_t)src[i++] << bits; bits += 8; } while (bits < 24 && i < srclen); dnext = encode64_uint32(dst, dstlen, value, bits); if (!dnext) return NULL; dstlen -= dnext - dst; dst = dnext; } return dst; }
static char *prepare(char *fields[10], struct fmt_main *self) { static char Buf[256]; char tmp[256], tmp2[256], tmp3[256], tmp4[256], tmp5[6], tmp6[6]; int N, r, p; if (strncmp(fields[1], FMT_CISCO9, 3) != 0 && strncmp(fields[1], FMT_SCRYPTKDF, 7)) return fields[1]; if (!strncmp(fields[1], FMT_CISCO9, 3)) { // cisco type 9 hashes. scrypt params: N=16384, r=1, p=1 hash in crypt format. Change it to CryptBS. // salt is 14 byte RAW, we can use it as is. //from: {"$9$nhEmQVczB7dqsO$X.HsgL6x1il0RxkOSSvyQYwucySCt7qFm4v7pqCxkKM", "cisco"}, //to: {"$7$C/..../....nhEmQVczB7dqsO$AG.yl8LDCkiErlh4ttizmxYCXSiXYrNY6vKmLDKj/P4", "cisco"}, if (strlen(fields[1]) != 4+14+43) return fields[1]; N=1<<14; r=1; p=1; encode64_uint32((uint8_t*)tmp5, sizeof(tmp5), r, 30); tmp5[5]=0; encode64_uint32((uint8_t*)tmp6, sizeof(tmp6), p, 30); tmp6[5]=0; sprintf (Buf, "$7$%c%s%s%14.14s$%s", N_to_c(N), tmp5, tmp6, &(fields[1][3]), base64_convert_cp(&(fields[1][3+14+1]), e_b64_crypt, 43, tmp, e_b64_cryptBS, sizeof(tmp), flg_Base64_NO_FLAGS)); } else { // ScryptKDF.pm (perl) format scrypt, generated by: scrypt_hash($_[1],$salt,$N,$r,$p,$bytes); Since N, r, p // AND bytes are variable, we have to handle computing all of them. NOTE, we may have to make changes to // the crypto_scrypt-common.c to handle the variable number of bytes. // to put into proper format, we mime->raw the salt and mime->cryptBS the hash hash, and fixup $N,$r,$p //from: {"SCRYPT:16384:8:1:VHRuaXZOZ05INWJs:JjrOzA8pdPhLvLh8sY64fLLaAjFUwYCXMmS16NXcn0A=","password"}, //to: {"$7$C6..../....TtnivNgNH5bl$acXnAzE8oVzGwW9Tlu6iw7fq021J/1sZmEKhcLBrT02","password"}, char *cp = strrchr(fields[1], ':'), *cp2; if (!cp || strlen(cp) > sizeof(tmp2)) return fields[1]; strcpy(tmp2, &cp[1]); // hash (mime format, we need cryptBS) cp2 = cp; --cp2; while (cp2 > fields[1] && *cp2 != ':') --cp2; if (*cp2 != ':' || cp-cp2 > sizeof(tmp3)) return fields[1]; strnzcpy(tmp3, &cp2[1], cp-cp2); // salt (mime format, we need raw) cp = &fields[1][7]; N = atoi(cp); cp = strchr(cp, ':'); if (!cp) return fields[1]; ++cp; r = atoi(cp); cp = strchr(cp, ':'); if (!cp) return fields[1]; ++cp; p = atoi(cp); cp = strchr(cp, ':'); if (cp != cp2) return fields[1]; encode64_uint32((uint8_t*)tmp5, sizeof(tmp5), r, 30); tmp5[5]=0; encode64_uint32((uint8_t*)tmp6, sizeof(tmp6), p, 30); tmp6[5]=0; memset(tmp4, 0, sizeof(tmp4)); sprintf (Buf, "$7$%c%s%s%s$%s", N_to_c(N), tmp5, tmp6, base64_convert_cp(tmp3, e_b64_mime, strlen(tmp3), tmp4, e_b64_raw, sizeof(tmp4), flg_Base64_NO_FLAGS), base64_convert_cp(tmp2, e_b64_mime, strlen(tmp2), tmp, e_b64_cryptBS, sizeof(tmp),flg_Base64_NO_FLAGS)); } return Buf; }