/*
* Copyright (C) 2020-2022 Red Hat, Inc.
*
* Authors: Ondrej Moris, Zoltan Fridrich
*
* This file is part of GnuTLS.
*
* The GnuTLS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see
*
*/
#include "config.h"
#include
#include
#include
#include
#include
#include
#include "dirname.h"
#include "errors.h"
#define FORMAT_VERSION 1
#define HMAC_SIZE 32
#define HMAC_ALGO GNUTLS_MAC_SHA256
#define HMAC_STR_SIZE (2 * HMAC_SIZE + 1)
static int get_path(const char *lib, const char *symbol, char *path, size_t path_size)
{
int ret;
void *dl, *sym;
Dl_info info;
dl = dlopen(lib, RTLD_LAZY);
if (dl == NULL)
return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
sym = dlsym(dl, symbol);
if (sym == NULL) {
ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
goto cleanup;
}
ret = dladdr(sym, &info);
if (ret == 0) {
ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
goto cleanup;
}
ret = snprintf(path, path_size, "%s", info.dli_fname);
if ((size_t)ret >= path_size) {
ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
goto cleanup;
}
ret = 0;
cleanup:
dlclose(dl);
return ret;
}
static int get_hmac(const char *path, char *hmac, size_t hmac_size)
{
int ret;
size_t size;
uint8_t buffer[HMAC_SIZE];
gnutls_datum_t hex = { buffer, sizeof(buffer) };
gnutls_datum_t data = { NULL, 0 };
ret = gnutls_load_file(path, &data);
if (ret < 0)
return gnutls_assert_val(ret);
GNUTLS_FIPS140_SET_LAX_MODE();
ret = gnutls_hmac_fast(HMAC_ALGO, FIPS_KEY, sizeof(FIPS_KEY) - 1,
data.data, data.size, buffer);
GNUTLS_FIPS140_SET_STRICT_MODE();
gnutls_free(data.data);
if (ret < 0)
return gnutls_assert_val(ret);
size = hmac_size;
ret = gnutls_hex_encode(&hex, hmac, &size);
if (ret < 0)
return gnutls_assert_val(ret);
return 0;
}
static int print_lib_path(const char *path)
{
int ret;
char hmac[HMAC_STR_SIZE];
ret = get_hmac(path, hmac, sizeof(hmac));
if (ret < 0) {
fprintf(stderr, "Could not calculate HMAC for %s: %s\n",
last_component(path), gnutls_strerror(ret));
return ret;
}
printf("[%s]\n", last_component(path));
printf("path = %s\n", path);
printf("hmac = %s\n", hmac);
return 0;
}
static int print_lib_dl(const char *lib, const char *sym)
{
int ret;
char path[GNUTLS_PATH_MAX];
ret = get_path(lib, sym, path, sizeof(path));
if (ret < 0) {
fprintf(stderr, "Could not get lib path for %s: %s\n",
lib, gnutls_strerror(ret));
return ret;
}
return print_lib_path(path);
}
int main(int argc, char **argv)
{
int ret;
if (argc != 1 && argc != 2) {
fprintf(stderr, "Usage: %s [gnutls_so_path]\n", last_component(argv[0]));
return EXIT_FAILURE;
}
printf("[global]\n");
printf("format-version = %d\n", FORMAT_VERSION);
if (argc == 2)
ret = print_lib_path(argv[1]);
else
ret = print_lib_dl(GNUTLS_LIBRARY_SONAME, "gnutls_global_init");
if (ret < 0)
return EXIT_FAILURE;
ret = print_lib_dl(NETTLE_LIBRARY_SONAME, "nettle_aes_set_encrypt_key");
if (ret < 0)
return EXIT_FAILURE;
ret = print_lib_dl(HOGWEED_LIBRARY_SONAME, "nettle_mpz_sizeinbase_256_u");
if (ret < 0)
return EXIT_FAILURE;
ret = print_lib_dl(GMP_LIBRARY_SONAME, "__gmpz_init");
if (ret < 0)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}