Changeset View
Changeset View
Standalone View
Standalone View
lib/libcrypt/crypt-sha256.c
Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
#define SALT_LEN_MAX 16 | #define SALT_LEN_MAX 16 | ||||
/* Default number of rounds if not explicitly specified. */ | /* Default number of rounds if not explicitly specified. */ | ||||
#define ROUNDS_DEFAULT 5000 | #define ROUNDS_DEFAULT 5000 | ||||
/* Minimum number of rounds. */ | /* Minimum number of rounds. */ | ||||
#define ROUNDS_MIN 1000 | #define ROUNDS_MIN 1000 | ||||
/* Maximum number of rounds. */ | /* Maximum number of rounds. */ | ||||
#define ROUNDS_MAX 999999999 | #define ROUNDS_MAX 999999999 | ||||
static char * | int | ||||
crypt_sha256_r(const char *key, const char *salt, char *buffer, int buflen) | crypt_sha256(const char *key, const char *salt, char *buffer) | ||||
{ | { | ||||
u_long srounds; | u_long srounds; | ||||
int n; | |||||
uint8_t alt_result[32], temp_result[32]; | uint8_t alt_result[32], temp_result[32]; | ||||
SHA256_CTX ctx, alt_ctx; | SHA256_CTX ctx, alt_ctx; | ||||
size_t salt_len, key_len, cnt, rounds; | size_t salt_len, key_len, cnt, rounds; | ||||
char *cp, *copied_key, *copied_salt, *p_bytes, *s_bytes, *endp; | char *cp, *copied_key, *copied_salt, *p_bytes, *s_bytes, *endp; | ||||
const char *num; | const char *num; | ||||
bool rounds_custom; | bool rounds_custom; | ||||
copied_key = NULL; | copied_key = NULL; | ||||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | else | ||||
SHA256_Update(&ctx, p_bytes, key_len); | SHA256_Update(&ctx, p_bytes, key_len); | ||||
/* Create intermediate result. */ | /* Create intermediate result. */ | ||||
SHA256_Final(alt_result, &ctx); | SHA256_Final(alt_result, &ctx); | ||||
} | } | ||||
/* Now we can construct the result string. It consists of three | /* Now we can construct the result string. It consists of three | ||||
* parts. */ | * parts. */ | ||||
cp = stpncpy(buffer, sha256_salt_prefix, MAX(0, buflen)); | cp = stpcpy(buffer, sha256_salt_prefix); | ||||
buflen -= sizeof(sha256_salt_prefix) - 1; | |||||
if (rounds_custom) { | if (rounds_custom) | ||||
n = snprintf(cp, MAX(0, buflen), "%s%zu$", | cp += sprintf(cp, "%s%zu$", sha256_rounds_prefix, rounds); | ||||
sha256_rounds_prefix, rounds); | |||||
cp += n; | cp = stpncpy(cp, salt, salt_len); | ||||
buflen -= n; | |||||
} | |||||
cp = stpncpy(cp, salt, MIN((size_t)MAX(0, buflen), salt_len)); | |||||
buflen -= MIN((size_t)MAX(0, buflen), salt_len); | |||||
if (buflen > 0) { | |||||
*cp++ = '$'; | *cp++ = '$'; | ||||
--buflen; | |||||
} | |||||
b64_from_24bit(alt_result[0], alt_result[10], alt_result[20], 4, &buflen, &cp); | b64_from_24bit(alt_result[0], alt_result[10], alt_result[20], 4, &cp); | ||||
b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4, &buflen, &cp); | b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4, &cp); | ||||
b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4, &buflen, &cp); | b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4, &cp); | ||||
b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4, &buflen, &cp); | b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4, &cp); | ||||
b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4, &buflen, &cp); | b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4, &cp); | ||||
b64_from_24bit(alt_result[15], alt_result[25], alt_result[5], 4, &buflen, &cp); | b64_from_24bit(alt_result[15], alt_result[25], alt_result[5], 4, &cp); | ||||
b64_from_24bit(alt_result[6], alt_result[16], alt_result[26], 4, &buflen, &cp); | b64_from_24bit(alt_result[6], alt_result[16], alt_result[26], 4, &cp); | ||||
b64_from_24bit(alt_result[27], alt_result[7], alt_result[17], 4, &buflen, &cp); | b64_from_24bit(alt_result[27], alt_result[7], alt_result[17], 4, &cp); | ||||
b64_from_24bit(alt_result[18], alt_result[28], alt_result[8], 4, &buflen, &cp); | b64_from_24bit(alt_result[18], alt_result[28], alt_result[8], 4, &cp); | ||||
b64_from_24bit(alt_result[9], alt_result[19], alt_result[29], 4, &buflen, &cp); | b64_from_24bit(alt_result[9], alt_result[19], alt_result[29], 4, &cp); | ||||
b64_from_24bit(0, alt_result[31], alt_result[30], 3, &buflen, &cp); | b64_from_24bit(0, alt_result[31], alt_result[30], 3, &cp); | ||||
if (buflen <= 0) { | |||||
errno = ERANGE; | |||||
buffer = NULL; | |||||
} | |||||
else | |||||
*cp = '\0'; /* Terminate the string. */ | *cp = '\0'; /* Terminate the string. */ | ||||
/* Clear the buffer for the intermediate result so that people | /* Clear the buffer for the intermediate result so that people | ||||
* attaching to processes or reading core dumps cannot get any | * attaching to processes or reading core dumps cannot get any | ||||
* information. We do it in this way to clear correct_words[] inside | * information. We do it in this way to clear correct_words[] inside | ||||
* the SHA256 implementation as well. */ | * the SHA256 implementation as well. */ | ||||
SHA256_Init(&ctx); | SHA256_Init(&ctx); | ||||
SHA256_Final(alt_result, &ctx); | SHA256_Final(alt_result, &ctx); | ||||
memset(temp_result, '\0', sizeof(temp_result)); | memset(temp_result, '\0', sizeof(temp_result)); | ||||
memset(p_bytes, '\0', key_len); | memset(p_bytes, '\0', key_len); | ||||
memset(s_bytes, '\0', salt_len); | memset(s_bytes, '\0', salt_len); | ||||
memset(&ctx, '\0', sizeof(ctx)); | memset(&ctx, '\0', sizeof(ctx)); | ||||
memset(&alt_ctx, '\0', sizeof(alt_ctx)); | memset(&alt_ctx, '\0', sizeof(alt_ctx)); | ||||
if (copied_key != NULL) | if (copied_key != NULL) | ||||
memset(copied_key, '\0', key_len); | memset(copied_key, '\0', key_len); | ||||
if (copied_salt != NULL) | if (copied_salt != NULL) | ||||
memset(copied_salt, '\0', salt_len); | memset(copied_salt, '\0', salt_len); | ||||
return buffer; | return (0); | ||||
} | |||||
/* This entry point is equivalent to crypt(3). */ | |||||
char * | |||||
crypt_sha256(const char *key, const char *salt) | |||||
{ | |||||
/* We don't want to have an arbitrary limit in the size of the | |||||
* password. We can compute an upper bound for the size of the | |||||
* result in advance and so we can prepare the buffer we pass to | |||||
* `crypt_sha256_r'. */ | |||||
static char *buffer; | |||||
static int buflen; | |||||
int needed; | |||||
char *new_buffer; | |||||
needed = (sizeof(sha256_salt_prefix) - 1 | |||||
+ sizeof(sha256_rounds_prefix) + 9 + 1 | |||||
+ strlen(salt) + 1 + 43 + 1); | |||||
if (buflen < needed) { | |||||
new_buffer = (char *)realloc(buffer, needed); | |||||
if (new_buffer == NULL) | |||||
return NULL; | |||||
buffer = new_buffer; | |||||
buflen = needed; | |||||
} | |||||
return crypt_sha256_r(key, salt, buffer, buflen); | |||||
} | } | ||||
#ifdef TEST | #ifdef TEST | ||||
static const struct { | static const struct { | ||||
const char *input; | const char *input; | ||||
const char result[32]; | const char result[32]; | ||||
} tests[] = | } tests[] = | ||||
▲ Show 20 Lines • Show All 173 Lines • Show Last 20 Lines |