/* bcryptFfi.c -- low-level FFI to the bcrypt library * Copyright (C) 2013 Benjamin Barenblat . */ #include #include #include #include #include #include #include "bcrypt/ow-crypt.h" uw_Basis_string uw_BcryptFfi_randomSetting(uw_context ctx) { // Grab some random bits for the salt. We need 128 bits, or 16 bytes. const int random_fd = open("/dev/urandom", O_RDONLY); if (random_fd == -1) { uw_error(ctx, FATAL, "unable to open /dev/urandom"); } char salt[16]; if (read(random_fd, salt, 16) != 16) { uw_error(ctx, BOUNDED_RETRY, "/dev/urandom ran dry"); } close(random_fd); // Generate the setting. uw_Basis_string setting = uw_malloc(ctx, 30); if (! crypt_gensalt_rn("$2y$", 0, // default number of rounds salt, 16, setting, 30)) { uw_error(ctx, FATAL, "unable to generate bcrypt setting"); } return setting; } uw_Basis_string uw_BcryptFfi_crypt(uw_context ctx, uw_Basis_string setting, uw_Basis_string password) { char *const scratchpad = uw_malloc(ctx, 61); uw_Basis_string result = crypt_rn(password, setting, scratchpad, 61); if (result == NULL) { uw_error(ctx, FATAL, "unable to perform bcrypt operation"); } /* At this point, 'result' points somewhere inside 'scratchpad'. * 'scratchpad' is allocated on the Ur heap, so we don't have to do * anything extra to marshal from C back into Ur. */ return result; }