Changeset View
Changeset View
Standalone View
Standalone View
secure/lib/libcrypt/crypt-blowfish.c
Show First 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | |||||
#define BCRYPT_MAXSALT 16 /* Precomputation is just so nice */ | #define BCRYPT_MAXSALT 16 /* Precomputation is just so nice */ | ||||
#define BCRYPT_BLOCKS 6 /* Ciphertext blocks */ | #define BCRYPT_BLOCKS 6 /* Ciphertext blocks */ | ||||
#define BCRYPT_MINLOGROUNDS 4 /* we have log2(rounds) in salt */ | #define BCRYPT_MINLOGROUNDS 4 /* we have log2(rounds) in salt */ | ||||
static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t); | static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t); | ||||
static void decode_base64(u_int8_t *, u_int16_t, const u_int8_t *); | static void decode_base64(u_int8_t *, u_int16_t, const u_int8_t *); | ||||
static char encrypted[_PASSWORD_LEN]; | |||||
const static u_int8_t Base64Code[] = | const static u_int8_t Base64Code[] = | ||||
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | ||||
const static u_int8_t index_64[128] = { | const static u_int8_t index_64[128] = { | ||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | while (bp < buffer + len) { | ||||
p += 4; | p += 4; | ||||
} | } | ||||
} | } | ||||
/* We handle $Vers$log2(NumRounds)$salt+passwd$ | /* We handle $Vers$log2(NumRounds)$salt+passwd$ | ||||
i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */ | i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */ | ||||
char * | int | ||||
crypt_blowfish(const char *key, const char *salt) | crypt_blowfish(const char *key, const char *salt, char *buffer) | ||||
{ | { | ||||
blf_ctx state; | blf_ctx state; | ||||
u_int32_t rounds, i, k; | u_int32_t rounds, i, k; | ||||
u_int16_t j; | u_int16_t j; | ||||
size_t key_len; | size_t key_len; | ||||
u_int8_t salt_len, logr, minr; | u_int8_t salt_len, logr, minr; | ||||
u_int8_t ciphertext[4 * BCRYPT_BLOCKS] = "OrpheanBeholderScryDoubt"; | u_int8_t ciphertext[4 * BCRYPT_BLOCKS] = "OrpheanBeholderScryDoubt"; | ||||
u_int8_t csalt[BCRYPT_MAXSALT]; | u_int8_t csalt[BCRYPT_MAXSALT]; | ||||
u_int32_t cdata[BCRYPT_BLOCKS]; | u_int32_t cdata[BCRYPT_BLOCKS]; | ||||
char arounds[3]; | char arounds[3]; | ||||
/* Defaults */ | /* Defaults */ | ||||
minr = 'b'; | minr = 'b'; | ||||
logr = BCRYPT_MINLOGROUNDS; | logr = BCRYPT_MINLOGROUNDS; | ||||
rounds = 1U << logr; | rounds = 1U << logr; | ||||
if (*salt == '$') { | if (*salt == '$') { | ||||
/* Discard "$" identifier */ | /* Discard "$" identifier */ | ||||
salt++; | salt++; | ||||
if (*salt > BCRYPT_VERSION) { | if (*salt > BCRYPT_VERSION) | ||||
/* How do I handle errors ? Return NULL */ | return (-1); | ||||
return NULL; | |||||
} | |||||
/* Check for minor versions */ | /* Check for minor versions */ | ||||
if (salt[1] != '$') { | if (salt[1] != '$') { | ||||
switch (salt[1]) { | switch (salt[1]) { | ||||
case 'a': /* 'ab' should not yield the same as 'abab' */ | case 'a': /* 'ab' should not yield the same as 'abab' */ | ||||
case 'b': /* cap input length at 72 bytes */ | case 'b': /* cap input length at 72 bytes */ | ||||
case 'y': /* same as 'b', for compatibility | case 'y': /* same as 'b', for compatibility | ||||
* with openwall crypt_blowfish | * with openwall crypt_blowfish | ||||
*/ | */ | ||||
minr = salt[1]; | minr = salt[1]; | ||||
salt++; | salt++; | ||||
break; | break; | ||||
default: | default: | ||||
return NULL; | return (-1); | ||||
} | } | ||||
} else | } else | ||||
minr = 0; | minr = 0; | ||||
/* Discard version + "$" identifier */ | /* Discard version + "$" identifier */ | ||||
salt += 2; | salt += 2; | ||||
if (salt[2] != '$') | if (salt[2] != '$') | ||||
/* Out of sync with passwd entry */ | /* Out of sync with passwd entry */ | ||||
return NULL; | return (-1); | ||||
memcpy(arounds, salt, sizeof(arounds)); | memcpy(arounds, salt, sizeof(arounds)); | ||||
if (arounds[sizeof(arounds) - 1] != '$') | if (arounds[sizeof(arounds) - 1] != '$') | ||||
return NULL; | return (-1); | ||||
arounds[sizeof(arounds) - 1] = 0; | arounds[sizeof(arounds) - 1] = 0; | ||||
logr = strtonum(arounds, BCRYPT_MINLOGROUNDS, 31, NULL); | logr = strtonum(arounds, BCRYPT_MINLOGROUNDS, 31, NULL); | ||||
if (logr == 0) | if (logr == 0) | ||||
return NULL; | return (-1); | ||||
/* Computer power doesn't increase linearly, 2^x should be fine */ | /* Computer power doesn't increase linearly, 2^x should be fine */ | ||||
rounds = 1U << logr; | rounds = 1U << logr; | ||||
/* Discard num rounds + "$" identifier */ | /* Discard num rounds + "$" identifier */ | ||||
salt += 3; | salt += 3; | ||||
} | } | ||||
if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT) | if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT) | ||||
return NULL; | return (-1); | ||||
/* We dont want the base64 salt but the raw data */ | /* We dont want the base64 salt but the raw data */ | ||||
decode_base64(csalt, BCRYPT_MAXSALT, (const u_int8_t *) salt); | decode_base64(csalt, BCRYPT_MAXSALT, (const u_int8_t *) salt); | ||||
salt_len = BCRYPT_MAXSALT; | salt_len = BCRYPT_MAXSALT; | ||||
if (minr <= 'a') | if (minr <= 'a') | ||||
key_len = (u_int8_t)(strlen(key) + (minr >= 'a' ? 1 : 0)); | key_len = (u_int8_t)(strlen(key) + (minr >= 'a' ? 1 : 0)); | ||||
else { | else { | ||||
/* strlen() returns a size_t, but the function calls | /* strlen() returns a size_t, but the function calls | ||||
Show All 30 Lines | for (i = 0; i < BCRYPT_BLOCKS; i++) { | ||||
ciphertext[4 * i + 2] = cdata[i] & 0xff; | ciphertext[4 * i + 2] = cdata[i] & 0xff; | ||||
cdata[i] = cdata[i] >> 8; | cdata[i] = cdata[i] >> 8; | ||||
ciphertext[4 * i + 1] = cdata[i] & 0xff; | ciphertext[4 * i + 1] = cdata[i] & 0xff; | ||||
cdata[i] = cdata[i] >> 8; | cdata[i] = cdata[i] >> 8; | ||||
ciphertext[4 * i + 0] = cdata[i] & 0xff; | ciphertext[4 * i + 0] = cdata[i] & 0xff; | ||||
} | } | ||||
i = 0; | *buffer++ = '$'; | ||||
encrypted[i++] = '$'; | *buffer++ = BCRYPT_VERSION; | ||||
encrypted[i++] = BCRYPT_VERSION; | |||||
if (minr) | if (minr) | ||||
encrypted[i++] = minr; | *buffer++ = minr; | ||||
encrypted[i++] = '$'; | *buffer++ = '$'; | ||||
snprintf(encrypted + i, 4, "%2.2u$", logr); | snprintf(buffer, 4, "%2.2u$", logr); | ||||
buffer += 3; | |||||
encode_base64((u_int8_t *) encrypted + i + 3, csalt, BCRYPT_MAXSALT); | encode_base64((u_int8_t *)buffer, csalt, BCRYPT_MAXSALT); | ||||
encode_base64((u_int8_t *) encrypted + strlen(encrypted), ciphertext, | buffer += strlen(buffer); | ||||
4 * BCRYPT_BLOCKS - 1); | encode_base64((u_int8_t *)buffer, ciphertext, 4 * BCRYPT_BLOCKS - 1); | ||||
memset(&state, 0, sizeof(state)); | memset(&state, 0, sizeof(state)); | ||||
memset(ciphertext, 0, sizeof(ciphertext)); | memset(ciphertext, 0, sizeof(ciphertext)); | ||||
memset(csalt, 0, sizeof(csalt)); | memset(csalt, 0, sizeof(csalt)); | ||||
memset(cdata, 0, sizeof(cdata)); | memset(cdata, 0, sizeof(cdata)); | ||||
return encrypted; | return (0); | ||||
} | } | ||||
static void | static void | ||||
encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len) | encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len) | ||||
{ | { | ||||
u_int8_t *bp = buffer; | u_int8_t *bp = buffer; | ||||
u_int8_t *p = data; | u_int8_t *p = data; | ||||
u_int8_t c1, c2; | u_int8_t c1, c2; | ||||
▲ Show 20 Lines • Show All 53 Lines • Show Last 20 Lines |