1
0
mirror of https://github.com/rg3/libbcrypt.git synced 2026-10-25 00:19:18 +03:00
Files
bcrypt/bcrypt.c
Ricardo Garcia d4bac5883f Make all nonstatic functions start with bcrypt_
This is irrelevant for the dynamic library thanks to
-fvisibility=hidden, but it can be important to avoid symbol name
collisions in the static library.
2017-12-07 12:42:07 +01:00

124 lines
3.1 KiB
C

/*
* bcrypt wrapper library
*
* Written in 2011, 2013, 2014, 2015, 2017 by Ricardo Garcia <r@rg3.name>
*
* To the extent possible under law, the author(s) have dedicated all copyright
* and related and neighboring rights to this software to the public domain
* worldwide. This software is distributed without any warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication along
* with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include "bcrypt.h"
#include "crypt_blowfish/ow-crypt.h"
#include "sha512.h"
#include "keccak.h"
#include "base64.h"
#define RANDBYTES (16)
#define BYTES_IN_512BITS (64)
#define BCRYPT_API __attribute__ ((visibility ("default")))
/*
* This is a best effort implementation. Nothing prevents a compiler from
* optimizing this function and making it vulnerable to timing attacks, but
* this method is commonly used in crypto libraries like NaCl.
*
* Return value is zero if both strings are equal and nonzero otherwise.
*/
static int timing_safe_strcmp(const char *str1, const char *str2)
{
const unsigned char *a;
const unsigned char *b;
int ret;
int i;
int len1 = strlen(str1);
int len2 = strlen(str2);
/* In our context both strings should always have the same length
* because they will be hashed passwords. */
if (len1 != len2)
return 1;
/* Force unsigned for bitwise operations. */
a = (const unsigned char *)str1;
b = (const unsigned char *)str2;
ret = 0;
for (i = 0; i < len1; ++i)
ret |= (a[i] ^ b[i]);
return ret;
}
BCRYPT_API int bcrypt_gensalt(int factor, char salt[BCRYPT_HASHSIZE])
{
int ret;
char input[RANDBYTES];
int workf;
char *aux;
/* Get random bytes. */
ret = getentropy(input, sizeof(input));
if (ret != 0)
return 1;
/* Generate salt. */
workf = (factor < 4 || factor > 31)?BCRYPT_DEFAULT_WORK_FACTOR:factor;
aux = crypt_gensalt_rn("$2a$", workf, input, RANDBYTES,
salt, BCRYPT_HASHSIZE);
return (aux == NULL)?2:0;
}
BCRYPT_API int bcrypt_hashpw(const char *passwd, const char salt[BCRYPT_HASHSIZE], char hash[BCRYPT_HASHSIZE])
{
char *aux;
aux = crypt_rn(passwd, salt, hash, BCRYPT_HASHSIZE);
return (aux == NULL)?1:0;
}
BCRYPT_API int bcrypt_checkpw(const char *passwd, const char hash[BCRYPT_HASHSIZE])
{
int ret;
char outhash[BCRYPT_HASHSIZE];
ret = bcrypt_hashpw(passwd, hash, outhash);
if (ret != 0)
return -1;
return timing_safe_strcmp(hash, outhash);
}
BCRYPT_API int bcrypt_sha512(const char *in, char digest[BCRYPT_512BITS_BASE64_SIZE])
{
unsigned char bindigest[BYTES_IN_512BITS];
size_t len = strlen(in);
if (len > ULONG_MAX)
return 1;
bcrypt_sha512_calc(in, (unsigned long)len, (char *)bindigest);
bcrypt_base64_calc(bindigest, sizeof(bindigest), digest);
return 0;
}
BCRYPT_API int bcrypt_sha3_512(const char *in, char digest[BCRYPT_512BITS_BASE64_SIZE])
{
unsigned char bindigest[BYTES_IN_512BITS];
size_t len = strlen(in);
if(len > ULLONG_MAX)
return 1;
bcrypt_sha3_512_calc((const u8 *)in, (u64)len, bindigest);
bcrypt_base64_calc(bindigest, sizeof(bindigest), digest);
return 0;
}