v4.0.0
Highlights
This is a major release focused on security hardening, a modernised CMake build system, and a new ergonomic context API.
Breaking Changes
SHA1,SHA256,SHA512renamed toCOTP_SHA1,COTP_SHA256,COTP_SHA512(thanks to @CppPhil)MIN_DIGTStypo fixed toMIN_DIGITStypedef unsigned char ucharremoved;base32_encodenow takesconst uint8_t *,base32_decodereturnsuint8_t *b32_alphabetis no longer exported (nowstatic)- MSVC support dropped
get_hotp/get_totp/get_totp_atreturnNULLon all error paths; callers must check the return value and thecotp_error_toutput parameter- The library no longer prints to stderr on errors; all diagnostics are reported via
cotp_error_t
New Features
- Context API (
cotp_ctx): ergonomic wrapper for repeated TOTP calls with the same configuration (cotp_ctx_create,cotp_ctx_totp,cotp_ctx_totp_at,cotp_ctx_free) - Optional validation helper (
-DCOTP_ENABLE_VALIDATION=ON):validate_totp_in_window()for window-based TOTP verification with timing-safe comparison - CMake package config: consumers can now use
find_package(COTP CONFIG)and link viaCOTP::cotp
Improvements
otp_to_int()now validates input for NULL and non-digit characters before conversion- Base32
get_char_indexandvalid_b32_struse O(1) lookup tables instead of O(n) loops - Base32 decode buffer calculation uses exact integer arithmetic instead of floating-point approximation
islower()/toupper()calls cast tounsigned charto avoid undefined behaviour on signed char
Security Fixes
- Added runtime bounds checks in RFC 4226 truncation and Steam code paths (offset and length validated before array access)
- Fixed potential NULL dereference in OpenSSL backend (
whmac_setkeyerror path now frees context and setsctx = NULL) - Fixed OOB read in
strip_char(Base32): lookup table was 128 bytes but indexed with fulluint8_trange (0–255) - Fixed undefined behaviour in
base32_encode:strlen()on potentially non-NUL-terminated binary input replaced with bounds-safe check - Added NULL guards to
whmac_freehandle()across all three backends - Fixed MbedTLS
whmac_finalizereturningbufleninstead of actual digest length mbedtls_md_hmac_starts()return value is now checked- Timing-safe comparison (
cotp_timing_safe_memcmp) used in TOTP window validation cotp_secure_memzero()applied to decoded secrets and HMAC digests immediately after use
Build System
- Added CMake package config (
find_package(COTP CONFIG)) alongside existing pkg-config support - Compiler flags scoped to
cotptarget only (no longer pollute global scope viaadd_compile_options)
sha256: 6b17323779dac1699462d8914b81155d69914b0d28b5ed837f1570ed05f2bd90