Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mbedtls support #69

Merged
merged 1 commit into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 42 additions & 7 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@ jobs:
- checkout
- run:
command: |
export DEBIAN_FRONTEND=noninteractive
apt update && apt -y install git gcc clang cmake libcriterion-dev libgcrypt20-dev
mkdir build && cd "$_"
cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTS=ON ..
make && make install
./tests/test_base32encode
./tests/test_base32decode
./tests/test_cotp
ubuntu2204_gcrypt:
ubuntu2404_gcrypt:
docker:
- image: ubuntu:22.04
- image: ubuntu:24.04
steps:
- checkout
- run:
command: |
export DEBIAN_FRONTEND=noninteractive
apt update && apt -y install git gcc clang cmake libcriterion-dev libgcrypt20-dev
mkdir build && cd "$_"
cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTS=ON ..
Expand All @@ -36,33 +38,66 @@ jobs:
- checkout
- run:
command: |
export DEBIAN_FRONTEND=noninteractive
apt update && apt -y install git gcc clang cmake libcriterion-dev libssl-dev
mkdir build && cd "$_"
cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTS=ON -DHMAC_WRAPPER=openssl ..
make && make install
./tests/test_base32encode
./tests/test_base32decode
./tests/test_cotp
ubuntu2204_openssl:
ubuntu2404_openssl:
docker:
- image: ubuntu:22.04
- image: ubuntu:24.04
steps:
- checkout
- run:
command: |
export DEBIAN_FRONTEND=noninteractive
apt update && apt -y install git gcc clang cmake libcriterion-dev libssl-dev
mkdir build && cd "$_"
cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTS=ON -DHMAC_WRAPPER=openssl ..
make && make install
./tests/test_base32encode
./tests/test_base32decode
./tests/test_cotp

debianStable_mbedtls:
docker:
- image: debian:stable
steps:
- checkout
- run:
command: |
export DEBIAN_FRONTEND=noninteractive
apt update && apt -y install git gcc clang cmake libcriterion-dev libmbedtls-dev
mkdir build && cd "$_"
cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTS=ON -DHMAC_WRAPPER=mbedtls ..
make && make install
./tests/test_base32encode
./tests/test_base32decode
./tests/test_cotp
ubuntu2404_mbedtls:
docker:
- image: ubuntu:24.04
steps:
- checkout
- run:
command: |
export DEBIAN_FRONTEND=noninteractive
apt update && apt -y install git gcc clang cmake libcriterion-dev libmbedtls-dev
mkdir build && cd "$_"
cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_TESTS=ON -DHMAC_WRAPPER=mbedtls ..
make && make install
./tests/test_base32encode
./tests/test_base32decode
./tests/test_cotp
workflows:
version: 2
build:
jobs:
- debianStable_gcrypt
- ubuntu2204_gcrypt
- ubuntu2404_gcrypt
- debianStable_openssl
- ubuntu2204_openssl
- ubuntu2404_openssl
- debianStable_mbedtls
- ubuntu2404_mbedtls
16 changes: 11 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ find_package(PkgConfig)

option(BUILD_SHARED_LIBS "Build libcotp as a shared library" ON)
option(BUILD_TESTS "Build base32 and cotp tests" OFF)
set(HMAC_WRAPPER "gcrypt" CACHE STRING "Choose between gcrypt (default), openssl or mbedtls for HMAC computation")
set_property(CACHE HMAC_WRAPPER PROPERTY STRINGS "gcrypt" "openssl" "mbedtls")

set(HMAC_WRAPPER "gcrypt" CACHE STRING "library to use during hmac computation")
if("${HMAC_WRAPPER}" STREQUAL "gcrypt")
set(HMAC_SOURCE_FILES
src/utils/whmac_gcrypt.c
)
find_package(Gcrypt 1.8.0 REQUIRED)
set(HMAC_INCLUDE_DIR ${GCRYPT_INCLUDE_DIR})
set(HMAC_LIBRARY_DIRS ${GCRYPT_LIBRARY_DIRS})
set(HMAC_LIBRARIES ${GCRYPT_LIBRARIES})
message("libcotp will use gcrypt for hmac")
elseif("${HMAC_WRAPPER}" STREQUAL "openssl")
Expand All @@ -28,15 +28,21 @@ elseif("${HMAC_WRAPPER}" STREQUAL "openssl")
src/utils/whmac_openssl.c
)
set(HMAC_INCLUDE_DIR ${OPENSSL_INCLUDE_DIR})
set(HMAC_LIBRARY_DIRS ${OPENSSL_LIBRARY_DIRS})
set(HMAC_LIBRARIES ${OPENSSL_LIBRARIES})
message("libcotp will use openssl for hmac")
elseif("${HMAC_WRAPPER}" STREQUAL "mbedtls")
find_package(MbedTLS REQUIRED)
set(HMAC_SOURCE_FILES
src/utils/whmac_mbedtls.c
)
set(HMAC_INCLUDE_DIR ${MBEDTLS_INCLUDE_DIRS})
set(HMAC_LIBRARIES ${MBEDTLS_LIBRARIES})
message("libcotp will use mbedtls for hmac")
else()
message("libcotp can't use ${HMAC_WRAPPER} for hmac")
endif()

include_directories(${HMAC_INCLUDE_DIR})
link_directories(${HMAC_LIBRARY_DIRS})

if (BUILD_TESTS)
add_subdirectory(tests)
Expand Down Expand Up @@ -109,4 +115,4 @@ if (PkgConfig_FOUND)

configure_file("cotp.pc.in" "cotp.pc" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/cotp.pc" DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig/)
endif()
endif()
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ C library that generates TOTP and HOTP according to [RFC-6238](https://tools.iet

## Requirements
- GCC/Clang and CMake to build the library
- libgcrypt >= 1.8.0 or openssl >= 3.0.0
- libgcrypt >= 1.8.0 or openssl >= 3.0.0 or mbedtls (works with both 2.x and 3.x)

## Build and Install
```
Expand All @@ -17,13 +17,13 @@ $ cd libcotp
$ mkdir build && cd $_
$ cmake -DCMAKE_INSTALL_PREFIX=/usr ..
$ make
# make install
$ sudo make install
```

Available options you can pass to `cmake`:
* `-DBUILD_TESTS=ON`: if you want to compile also the tests (default **OFF**, requires criterion)
* `-DBUILD_SHARED_LIBS=ON`: if you want to build libcotp as a shared library (default **ON**)
* `-DHMAC_WRAPPER="<gcrypt|openssl>"`: you can choose between GCrypt and OpenSSL (default **Gcrypt**)
* `-DBUILD_SHARED_LIBS=OFF`: if you want to build libcotp as a static library (default **ON**)
* `-DHMAC_WRAPPER="<gcrypt|openssl|mbedtls>"`: you can choose between GCrypt, OpenSSL or MbedTLS (default **Gcrypt**)

## How To Use It
```
Expand Down
111 changes: 111 additions & 0 deletions cmake/FindMbedTLS.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# Find the mbedtls library
#
# Input variables:
#
# MBEDTLS_INCLUDE_DIR The mbedtls include directory
# MBEDTLS_INCLUDE_DIRS The mbedtls include directory (deprecated)
# MBEDTLS_LIBRARY Path to mbedtls library
# MBEDX509_LIBRARY Path to mbedx509 library
# MBEDCRYPTO_LIBRARY Path to mbedcrypto library
#
# Result variables:
#
# MBEDTLS_FOUND System has mbedtls
# MBEDTLS_INCLUDE_DIRS The mbedtls include directories
# MBEDTLS_LIBRARIES The mbedtls library names
# MBEDTLS_VERSION Version of mbedtls

if(DEFINED MBEDTLS_INCLUDE_DIRS AND NOT DEFINED MBEDTLS_INCLUDE_DIR)
message(WARNING "MBEDTLS_INCLUDE_DIRS is deprecated, use MBEDTLS_INCLUDE_DIR instead.")
set(MBEDTLS_INCLUDE_DIR "${MBEDTLS_INCLUDE_DIRS}")
unset(MBEDTLS_INCLUDE_DIRS)
endif()

if(CURL_USE_PKGCONFIG)
find_package(PkgConfig QUIET)
pkg_check_modules(PC_MBEDTLS "mbedtls")
endif()

find_path(MBEDTLS_INCLUDE_DIR NAMES "mbedtls/ssl.h"
HINTS
${PC_MBEDTLS_INCLUDEDIR}
${PC_MBEDTLS_INCLUDE_DIRS}
)

find_library(MBEDTLS_LIBRARY NAMES "mbedtls"
HINTS
${PC_MBEDTLS_LIBDIR}
${PC_MBEDTLS_LIBRARY_DIRS}
)
find_library(MBEDX509_LIBRARY NAMES "mbedx509"
HINTS
${PC_MBEDTLS_LIBDIR}
${PC_MBEDTLS_LIBRARY_DIRS}
)
find_library(MBEDCRYPTO_LIBRARY NAMES "mbedcrypto"
HINTS
${PC_MBEDTLS_LIBDIR}
${PC_MBEDTLS_LIBRARY_DIRS}
)

if(PC_MBEDTLS_VERSION)
set(MBEDTLS_VERSION ${PC_MBEDTLS_VERSION})
elseif(MBEDTLS_INCLUDE_DIR)
if(EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h") # 3.x
set(_version_header "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
elseif(EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h") # 2.x
set(_version_header "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
else()
unset(_version_header)
endif()
if(_version_header)
set(_version_regex "#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"([0-9.]+)\"")
file(STRINGS "${_version_header}" _version_str REGEX "${_version_regex}")
string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}")
set(MBEDTLS_VERSION "${_version_str}")
unset(_version_regex)
unset(_version_str)
unset(_version_header)
endif()
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MbedTLS
REQUIRED_VARS
MBEDTLS_INCLUDE_DIR
MBEDTLS_LIBRARY
MBEDX509_LIBRARY
MBEDCRYPTO_LIBRARY
VERSION_VAR
MBEDTLS_VERSION
)

if(MBEDTLS_FOUND)
set(MBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR})
set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY})
endif()

mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY)
94 changes: 94 additions & 0 deletions src/utils/whmac_mbedtls.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include <stdio.h>
#include <stdlib.h>
#include <mbedtls/md.h>
#include "../whmac.h"
#include "../cotp.h"

typedef struct whmac_handle_s whmac_handle_t;

struct whmac_handle_s
{
mbedtls_md_context_t sha_ctx;
const mbedtls_md_info_t *md_info;
int algo;
size_t dlen;
};

int
whmac_check (void)
{
return 0;
}

size_t
whmac_getlen (whmac_handle_t *hd)
{
return mbedtls_md_get_size(hd->md_info);
}

whmac_handle_t *
whmac_gethandle (int algo)
{
const mbedtls_md_type_t openssl_algo[] = {
MBEDTLS_MD_SHA1,
MBEDTLS_MD_SHA256,
MBEDTLS_MD_SHA512,
};

whmac_handle_t *whmac_handle = calloc (1, sizeof(*whmac_handle));
if (whmac_handle == NULL) {
return NULL;
}

if (algo > 2) {
free (whmac_handle);
return NULL;
}

mbedtls_md_init (&(whmac_handle->sha_ctx));
whmac_handle->md_info = mbedtls_md_info_from_type (openssl_algo[algo]);
int ret = mbedtls_md_setup (&(whmac_handle->sha_ctx), whmac_handle->md_info, 1);
if (ret != 0) {
printf ("mbedtls_md_setup() returned -0x%04x\n", -ret);
mbedtls_md_free (&(whmac_handle->sha_ctx));
free (whmac_handle);
return NULL;
}

return whmac_handle;
}

void
whmac_freehandle (whmac_handle_t *hd)
{
mbedtls_md_free (&(hd->sha_ctx));
free (hd);
}

int
whmac_setkey (whmac_handle_t *hd,
unsigned char *buffer,
size_t buflen)
{
mbedtls_md_hmac_starts (&(hd->sha_ctx), buffer, buflen);
return NO_ERROR;
}

void
whmac_update (whmac_handle_t *hd,
unsigned char *buffer,
size_t buflen)
{
mbedtls_md_hmac_update (&(hd->sha_ctx), buffer, buflen);
}

ssize_t
whmac_finalize (whmac_handle_t *hd,
unsigned char *buffer,
size_t buflen)
{
mbedtls_md_hmac_finish (&(hd->sha_ctx), buffer);

return buflen;
}

4 changes: 2 additions & 2 deletions src/utils/whmac_openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ whmac_gethandle (int algo)

size_t params_n = 0;

whmac_handle->mac_params[params_n++] = OSSL_PARAM_construct_utf8_string("digest", (char *)openssl_algo[algo], 0);
whmac_handle->mac_params[params_n] = OSSL_PARAM_construct_end();
whmac_handle->mac_params[params_n++] = OSSL_PARAM_construct_utf8_string ("digest", (char *)openssl_algo[algo], 0);
whmac_handle->mac_params[params_n] = OSSL_PARAM_construct_end ();
}
return whmac_handle;
}
Expand Down