mirror of
https://github.com/falk-werner/webfuse
synced 2025-06-13 12:54:15 +00:00
added userdb to encapsulate authentication stuff
This commit is contained in:
parent
c0a905d65b
commit
44b0fad541
@ -157,6 +157,24 @@ install(FILES "${PROJECT_BINARY_DIR}/libwsfs-provider.pc" DESTINATION lib${LIB_S
|
|||||||
|
|
||||||
if(NOT WITHOUT_EXAMPLE)
|
if(NOT WITHOUT_EXAMPLE)
|
||||||
|
|
||||||
|
# libuserdb
|
||||||
|
|
||||||
|
add_library(userdb STATIC
|
||||||
|
example/lib/userdb/src/userdb.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(userdb PUBLIC
|
||||||
|
example/lib/userdb/include
|
||||||
|
${OPENSSL_INCLUDE_DIRS}
|
||||||
|
${JANSSON_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_options(userdb PUBLIC
|
||||||
|
${C_WARNINGS}
|
||||||
|
${OPENSSL_CFLAGS_OTHER}
|
||||||
|
${JANSSON_CFLAGS_OTHER}
|
||||||
|
)
|
||||||
|
|
||||||
# daemon
|
# daemon
|
||||||
|
|
||||||
add_executable(wsfsd
|
add_executable(wsfsd
|
||||||
@ -189,12 +207,14 @@ add_executable(wsfs-passwd
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(wsfs-passwd PUBLIC
|
target_link_libraries(wsfs-passwd PUBLIC
|
||||||
|
userdb
|
||||||
${OPENSSL_LIBRARIES}
|
${OPENSSL_LIBRARIES}
|
||||||
${JANSSON_LIBRARIES}
|
${JANSSON_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(wsfs-passwd PUBLIC
|
target_include_directories(wsfs-passwd PUBLIC
|
||||||
example/passwd
|
example/passwd
|
||||||
|
example/lib/userdb/include
|
||||||
${OPENSSL_INCLUDE_DIRS}
|
${OPENSSL_INCLUDE_DIRS}
|
||||||
${JANSSON_INCLUDE_DIRS}
|
${JANSSON_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
46
example/lib/userdb/include/userdb.h
Normal file
46
example/lib/userdb/include/userdb.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef USERDB_H
|
||||||
|
#define USERDB_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stdbool.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct userdb;
|
||||||
|
|
||||||
|
extern struct userdb * userdb_create(
|
||||||
|
char const * pepper);
|
||||||
|
|
||||||
|
extern void userdb_dispose(struct userdb * db);
|
||||||
|
|
||||||
|
extern bool userdb_save(
|
||||||
|
struct userdb * db,
|
||||||
|
char const * filename);
|
||||||
|
|
||||||
|
extern bool userdb_load(
|
||||||
|
struct userdb * db,
|
||||||
|
char const * filename);
|
||||||
|
|
||||||
|
extern void userdb_add(
|
||||||
|
struct userdb * db,
|
||||||
|
char const * username,
|
||||||
|
char const * password);
|
||||||
|
|
||||||
|
extern void userdb_remove(
|
||||||
|
struct userdb * db,
|
||||||
|
char const * user);
|
||||||
|
|
||||||
|
extern bool userdb_check(
|
||||||
|
struct userdb * db,
|
||||||
|
char const * username,
|
||||||
|
char const * password);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
278
example/lib/userdb/src/userdb.c
Normal file
278
example/lib/userdb/src/userdb.c
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
#include "userdb.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <jansson.h>
|
||||||
|
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
#define USERDB_HASH_ALGORITHM "sha512"
|
||||||
|
#define USERDB_MAJOR 1
|
||||||
|
#define USERDB_MINOR 0
|
||||||
|
|
||||||
|
#define USERDB_SALT_SIZE 32
|
||||||
|
|
||||||
|
struct userdb
|
||||||
|
{
|
||||||
|
json_t * users;
|
||||||
|
char * pepper;
|
||||||
|
char * hash_algorithm;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool is_compatible(json_t * meta)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
if (json_is_object(meta))
|
||||||
|
{
|
||||||
|
json_t * type = json_object_get(meta, "type");
|
||||||
|
json_t * major = json_object_get(meta, "major");
|
||||||
|
json_t * minor = json_object_get(meta, "minor");
|
||||||
|
json_t * hash_algorithm = json_object_get(meta, "hash_algorithm");
|
||||||
|
|
||||||
|
result = (
|
||||||
|
json_is_string(type) &&
|
||||||
|
(0 == strcmp(json_string_value(type), "wsfs-userdb")) &&
|
||||||
|
json_is_integer(major) &&
|
||||||
|
(USERDB_MAJOR == json_integer_value(major)) &&
|
||||||
|
json_is_integer(minor) &&
|
||||||
|
json_is_string(hash_algorithm)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
char const * algorithm = json_string_value(hash_algorithm);
|
||||||
|
result = (NULL != EVP_get_digestbyname(algorithm));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char hex_char(unsigned char value)
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case 0x00: return '0';
|
||||||
|
case 0x01: return '1';
|
||||||
|
case 0x02: return '2';
|
||||||
|
case 0x03: return '3';
|
||||||
|
case 0x04: return '4';
|
||||||
|
case 0x05: return '5';
|
||||||
|
case 0x06: return '6';
|
||||||
|
case 0x07: return '7';
|
||||||
|
case 0x08: return '8';
|
||||||
|
case 0x09: return '9';
|
||||||
|
case 0x0a: return 'a';
|
||||||
|
case 0x0b: return 'b';
|
||||||
|
case 0x0c: return 'c';
|
||||||
|
case 0x0d: return 'd';
|
||||||
|
case 0x0e: return 'e';
|
||||||
|
case 0x0f: return 'f';
|
||||||
|
default: return '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char * to_hex(unsigned char const * value, size_t length)
|
||||||
|
{
|
||||||
|
char * result = malloc((2 * length) + 1);
|
||||||
|
if (NULL != result)
|
||||||
|
{
|
||||||
|
for (size_t i = 0, j = 0; i < length; i++, j+=2)
|
||||||
|
{
|
||||||
|
unsigned char high = (value[i] >> 4) & 0x0f;
|
||||||
|
unsigned char low = value[i] & 0x0f;
|
||||||
|
|
||||||
|
result[j ] = hex_char(high);
|
||||||
|
result[j + 1] = hex_char(low);
|
||||||
|
}
|
||||||
|
|
||||||
|
result[2 * length] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char * generate_salt(void)
|
||||||
|
{
|
||||||
|
unsigned char buffer[USERDB_SALT_SIZE];
|
||||||
|
int rc = RAND_bytes(buffer, USERDB_SALT_SIZE);
|
||||||
|
if (1 != rc)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "fatal: failed to generate salt (OpenSSL RAND_bytes failed)\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return to_hex(buffer, USERDB_SALT_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char * compute_hash(
|
||||||
|
struct userdb * db,
|
||||||
|
char const * password,
|
||||||
|
char const * salt)
|
||||||
|
{
|
||||||
|
EVP_MD const * digest = EVP_get_digestbyname(db->hash_algorithm);
|
||||||
|
if (NULL == digest)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "error: hash algorithm %s not supported\n", db->hash_algorithm);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * result = NULL;
|
||||||
|
unsigned int hash_size = digest->md_size;
|
||||||
|
unsigned char * hash = malloc(hash_size);
|
||||||
|
|
||||||
|
if (NULL != hash)
|
||||||
|
{
|
||||||
|
EVP_MD_CTX context;
|
||||||
|
EVP_MD_CTX_init(&context);
|
||||||
|
EVP_DigestInit_ex(&context, digest, NULL);
|
||||||
|
EVP_DigestUpdate(&context, password, strlen(password));
|
||||||
|
EVP_DigestUpdate(&context, salt, strlen(salt));
|
||||||
|
EVP_DigestUpdate(&context, db->pepper, strlen(db->pepper));
|
||||||
|
EVP_DigestFinal_ex(&context, hash, &hash_size);
|
||||||
|
EVP_MD_CTX_cleanup(&context);
|
||||||
|
|
||||||
|
result = to_hex(hash, hash_size);
|
||||||
|
free(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct userdb * userdb_create(
|
||||||
|
char const * pepper)
|
||||||
|
{
|
||||||
|
struct userdb * db = malloc(sizeof(struct userdb));
|
||||||
|
if (NULL != db)
|
||||||
|
{
|
||||||
|
db->users = json_object();
|
||||||
|
db->pepper = strdup(pepper);
|
||||||
|
db->hash_algorithm = strdup(USERDB_HASH_ALGORITHM);
|
||||||
|
}
|
||||||
|
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
|
||||||
|
void userdb_dispose(
|
||||||
|
struct userdb * db)
|
||||||
|
{
|
||||||
|
json_decref(db->users);
|
||||||
|
free(db->pepper);
|
||||||
|
free(db->hash_algorithm);
|
||||||
|
free(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool userdb_save(
|
||||||
|
struct userdb * db,
|
||||||
|
char const * filename)
|
||||||
|
{
|
||||||
|
json_t * container = json_object();
|
||||||
|
|
||||||
|
json_t * meta = json_object();
|
||||||
|
json_object_set_new(meta, "type", json_string("wsfs-userdb"));
|
||||||
|
json_object_set_new(meta, "major", json_integer(USERDB_MAJOR));
|
||||||
|
json_object_set_new(meta, "minor", json_integer(USERDB_MINOR));
|
||||||
|
json_object_set_new(meta, "hash_algorithm", json_string(db->hash_algorithm));
|
||||||
|
json_object_set_new(container, "meta", meta);
|
||||||
|
|
||||||
|
json_object_set(container, "users", db->users);
|
||||||
|
|
||||||
|
int result = json_dump_file(container, filename, JSON_INDENT(2));
|
||||||
|
json_decref(container);
|
||||||
|
|
||||||
|
return (0 == result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool userdb_load(
|
||||||
|
struct userdb * db,
|
||||||
|
char const * filename)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
json_t * container = json_load_file(filename, 0, NULL);
|
||||||
|
if (NULL != container)
|
||||||
|
{
|
||||||
|
json_t * meta = json_object_get(container, "meta");
|
||||||
|
json_t * users = json_object_get(container, "users");
|
||||||
|
|
||||||
|
if ((is_compatible(meta)) && (json_is_object(users))) {
|
||||||
|
json_t * hash_algorithm = json_object_get(meta, "hash_algorithm");
|
||||||
|
free(db->hash_algorithm);
|
||||||
|
db->hash_algorithm = strdup(json_string_value(hash_algorithm));
|
||||||
|
|
||||||
|
json_decref(db->users);
|
||||||
|
json_incref(users);
|
||||||
|
db->users = users;
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_decref(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void userdb_add(
|
||||||
|
struct userdb * db,
|
||||||
|
char const * username,
|
||||||
|
char const * password)
|
||||||
|
{
|
||||||
|
char * salt = generate_salt();
|
||||||
|
char * hash = compute_hash(db, password, salt);
|
||||||
|
|
||||||
|
json_t * user = json_object();
|
||||||
|
json_object_set_new(user, "password_hash", json_string(hash));
|
||||||
|
json_object_set_new(user, "salt", json_string(salt));
|
||||||
|
|
||||||
|
json_object_set_new(db->users, username, user);
|
||||||
|
|
||||||
|
free(salt);
|
||||||
|
free(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
void userdb_remove(
|
||||||
|
struct userdb * db,
|
||||||
|
char const * user)
|
||||||
|
{
|
||||||
|
json_object_del(db->users, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char const * json_object_get_string(
|
||||||
|
json_t * object,
|
||||||
|
char const * key)
|
||||||
|
{
|
||||||
|
char const * result = NULL;
|
||||||
|
|
||||||
|
json_t * string_holder = json_object_get(object, key);
|
||||||
|
if (json_is_string(string_holder))
|
||||||
|
{
|
||||||
|
result = json_string_value(string_holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool userdb_check(
|
||||||
|
struct userdb * db,
|
||||||
|
char const * username,
|
||||||
|
char const * password)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
json_t * user = json_object_get(db->users, username);
|
||||||
|
if (json_is_object(user))
|
||||||
|
{
|
||||||
|
char const * salt = json_object_get_string(user, "salt");
|
||||||
|
char const * hash = json_object_get_string(user, "password_hash");
|
||||||
|
|
||||||
|
char * computed_hash = compute_hash(db, password, salt);
|
||||||
|
|
||||||
|
result = (0 == strcmp(computed_hash, hash));
|
||||||
|
free(computed_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
@ -11,10 +11,8 @@
|
|||||||
#include <openssl/engine.h>
|
#include <openssl/engine.h>
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
|
#include <userdb.h>
|
||||||
|
|
||||||
#define HASH_ALGORITHM "sha512"
|
|
||||||
#define PASSWD_FORMAT_MAJOR 1
|
|
||||||
#define PASSWD_FORMAT_MINOR 0
|
|
||||||
|
|
||||||
struct args
|
struct args
|
||||||
{
|
{
|
||||||
@ -151,22 +149,11 @@ static void args_init(struct args * args)
|
|||||||
|
|
||||||
static int create_passwd(struct args * args)
|
static int create_passwd(struct args * args)
|
||||||
{
|
{
|
||||||
json_t * db = json_object();
|
struct userdb * db = userdb_create(args->pepper);
|
||||||
|
bool result = userdb_save(db, args->file);
|
||||||
|
userdb_dispose(db);
|
||||||
|
|
||||||
json_t * meta = json_object();
|
return (result) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
json_object_set_new(meta, "type", json_string("wsfs-passwd"));
|
|
||||||
json_object_set_new(meta, "major", json_integer(PASSWD_FORMAT_MAJOR));
|
|
||||||
json_object_set_new(meta, "minor", json_integer(PASSWD_FORMAT_MINOR));
|
|
||||||
json_object_set_new(meta, "hash_alorithm", json_string(HASH_ALGORITHM));
|
|
||||||
json_object_set_new(db, "meta", meta);
|
|
||||||
|
|
||||||
json_t * users = json_object();
|
|
||||||
json_object_set_new(db, "users", users);
|
|
||||||
|
|
||||||
int result = json_dump_file(db, args->file, JSON_INDENT(2));
|
|
||||||
json_decref(db);
|
|
||||||
|
|
||||||
return (0 == result) ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_user(struct args * args)
|
static int add_user(struct args * args)
|
||||||
@ -185,24 +172,58 @@ static int add_user(struct args * args)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct userdb * db = userdb_create(args->pepper);
|
||||||
|
userdb_load(db, args->file);
|
||||||
|
userdb_add(db, args->username, args->password);
|
||||||
|
bool result = userdb_save(db, args->file);
|
||||||
|
userdb_dispose(db);
|
||||||
|
|
||||||
|
return (result) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
puts("add");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int remove_user(struct args * args)
|
static int remove_user(struct args * args)
|
||||||
{
|
{
|
||||||
puts("remove");
|
if (NULL == args->username)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "error: missing username");
|
||||||
|
args->show_help = true;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct userdb * db = userdb_create(args->pepper);
|
||||||
|
userdb_load(db, args->file);
|
||||||
|
userdb_remove(db, args->username);
|
||||||
|
bool result = userdb_save(db, args->file);
|
||||||
|
userdb_dispose(db);
|
||||||
|
|
||||||
|
return (result) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
static int check_password(struct args * args)
|
static int check_password(struct args * args)
|
||||||
{
|
{
|
||||||
puts("check");
|
if (NULL == args->username)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "error: missing username");
|
||||||
|
args->show_help = true;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NULL == args->password)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "error: missing password");
|
||||||
|
args->show_help = true;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct userdb * db = userdb_create(args->pepper);
|
||||||
|
userdb_load(db, args->file);
|
||||||
|
bool result = userdb_check(db, args->username, args->password);
|
||||||
|
userdb_dispose(db);
|
||||||
|
|
||||||
|
printf("%s\n", (result) ? "OK" : "FAILURE");
|
||||||
|
return (result) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
static int invoke_invalid_command(struct args * args)
|
static int invoke_invalid_command(struct args * args)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "error: unknown command\n");
|
fprintf(stderr, "error: unknown command\n");
|
||||||
@ -246,84 +267,6 @@ static void args_cleanup(struct args * args)
|
|||||||
free(args->pepper);
|
free(args->pepper);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char hex_char(unsigned char value)
|
|
||||||
{
|
|
||||||
switch (value)
|
|
||||||
{
|
|
||||||
case 0x00: return '0';
|
|
||||||
case 0x01: return '1';
|
|
||||||
case 0x02: return '2';
|
|
||||||
case 0x03: return '3';
|
|
||||||
case 0x04: return '4';
|
|
||||||
case 0x05: return '5';
|
|
||||||
case 0x06: return '6';
|
|
||||||
case 0x07: return '7';
|
|
||||||
case 0x08: return '8';
|
|
||||||
case 0x09: return '9';
|
|
||||||
case 0x0a: return 'a';
|
|
||||||
case 0x0b: return 'b';
|
|
||||||
case 0x0c: return 'c';
|
|
||||||
case 0x0d: return 'd';
|
|
||||||
case 0x0e: return 'e';
|
|
||||||
case 0x0f: return 'f';
|
|
||||||
default: return '?';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static char * to_hex(unsigned char const * value, size_t length)
|
|
||||||
{
|
|
||||||
char * result = malloc((2 * length) + 1);
|
|
||||||
if (NULL != result)
|
|
||||||
{
|
|
||||||
for (size_t i = 0, j = 0; i < length; i++, j+=2)
|
|
||||||
{
|
|
||||||
unsigned char high = (value[i] >> 4) & 0x0f;
|
|
||||||
unsigned char low = value[i] & 0x0f;
|
|
||||||
|
|
||||||
result[j ] = hex_char(high);
|
|
||||||
result[j + 1] = hex_char(low);
|
|
||||||
}
|
|
||||||
|
|
||||||
result[2 * length] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char * get_password_hash(
|
|
||||||
char const * password,
|
|
||||||
char const * salt,
|
|
||||||
char * pepper)
|
|
||||||
{
|
|
||||||
EVP_MD const * digest = EVP_get_digestbyname(HASH_ALGORITHM);
|
|
||||||
if (NULL == digest)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "error: hash algorithm %s not supported\n", HASH_ALGORITHM);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
char * result = NULL;
|
|
||||||
unsigned int hash_size = digest->md_size;
|
|
||||||
unsigned char * hash = malloc(hash_size);
|
|
||||||
|
|
||||||
if (NULL != hash)
|
|
||||||
{
|
|
||||||
EVP_MD_CTX context;
|
|
||||||
EVP_MD_CTX_init(&context);
|
|
||||||
EVP_DigestInit_ex(&context, digest, NULL);
|
|
||||||
EVP_DigestUpdate(&context, password, strlen(password));
|
|
||||||
EVP_DigestUpdate(&context, salt, strlen(salt));
|
|
||||||
EVP_DigestUpdate(&context, pepper, strlen(pepper));
|
|
||||||
EVP_DigestFinal_ex(&context, hash, &hash_size);
|
|
||||||
EVP_MD_CTX_cleanup(&context);
|
|
||||||
|
|
||||||
result = to_hex(hash, hash_size);
|
|
||||||
free(hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void openssl_cleanup(void)
|
static void openssl_cleanup(void)
|
||||||
{
|
{
|
||||||
FIPS_mode_set(0);
|
FIPS_mode_set(0);
|
||||||
|
Loading…
Reference in New Issue
Block a user