/* * 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 #ifdef HAVE_DL_ITERATE_PHDR #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_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(const char *path, const char *soname) { int ret; char *real_path = NULL; char hmac[HMAC_STR_SIZE]; real_path = canonicalize_file_name(path); if (real_path == NULL) { fprintf(stderr, "Could not get realpath from %s\n", path); ret = GNUTLS_E_FILE_ERROR; goto cleanup; } ret = get_hmac(real_path, hmac, sizeof(hmac)); if (ret < 0) { fprintf(stderr, "Could not calculate HMAC for %s: %s\n", last_component(real_path), gnutls_strerror(ret)); goto cleanup; } printf("[%s]\n", soname); printf("path = %s\n", real_path); printf("hmac = %s\n", hmac); cleanup: free(real_path); return ret; } static int callback(struct dl_phdr_info *info, size_t size, void *data) { const char *path = info->dlpi_name; const char *soname = last_component(path); if (!strcmp(soname, GNUTLS_LIBRARY_SONAME)) return print_lib(data ? data : path, soname); if (!strcmp(soname, NETTLE_LIBRARY_SONAME)) return print_lib(path, soname); if (!strcmp(soname, HOGWEED_LIBRARY_SONAME)) return print_lib(path, soname); if (!strcmp(soname, GMP_LIBRARY_SONAME)) return print_lib(path, soname); return 0; } int main(int argc, char **argv) { 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); return dl_iterate_phdr(callback, argc == 2 ? argv[1] : NULL); } #else int main(void) { fprintf(stderr, "Function dl_iterate_phdr is missing\n"); return EXIT_FAILURE; } #endif /* HAVE_DL_ITERATE_PHDR */