diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..0451da0
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,67 @@
+# Generated from CLion C/C++ Code Style settings
+BasedOnStyle: LLVM
+AccessModifierOffset: -8
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: Consecutive
+AlignOperands: Align
+AllowAllArgumentsOnNextLine: false
+AllowAllConstructorInitializersOnNextLine: false
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: Always
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: Always
+AllowShortLambdasOnASingleLine: All
+AllowShortLoopsOnASingleLine: true
+AlwaysBreakAfterReturnType: TopLevel
+AlwaysBreakTemplateDeclarations: Yes
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterCaseLabel: false
+ AfterClass: false
+ AfterControlStatement: Never
+ AfterEnum: false
+ AfterFunction: true
+ AfterNamespace: false
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+ SplitEmptyFunction: false
+ SplitEmptyRecord: true
+BreakBeforeBinaryOperators: None
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: BeforeColon
+BreakInheritanceList: BeforeColon
+ColumnLimit: 0
+CompactNamespaces: false
+ContinuationIndentWidth: 4
+IndentCaseLabels: false
+IndentPPDirectives: None
+IndentWidth: 8
+KeepEmptyLinesAtTheStartOfBlocks: true
+MaxEmptyLinesToKeep: 2
+NamespaceIndentation: None
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+QualifierAlignment: Left
+PointerAlignment: Right
+ReflowComments: false
+SpaceAfterCStyleCast: true
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: false
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 0
+SpacesInAngles: false
+SpacesInCStyleCastParentheses: false
+SpacesInContainerLiterals: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+TabWidth: 8
+UseTab: ForContinuationAndIndentation
diff --git a/.clang-tidy b/.clang-tidy
new file mode 100644
index 0000000..183b1d8
--- /dev/null
+++ b/.clang-tidy
@@ -0,0 +1,34 @@
+Checks: >-
+ bugprone-*,
+ cppcoreguidelines-*,
+ google-*,
+ misc-*,
+ modernize-*,
+ performance-*,
+ readability-*,
+ -bugprone-lambda-function-name,
+ -bugprone-reserved-identifier,
+ -cppcoreguidelines-avoid-goto,
+ -cppcoreguidelines-avoid-magic-numbers,
+ -cppcoreguidelines-avoid-non-const-global-variables,
+ -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+ -cppcoreguidelines-pro-type-vararg,
+ -google-readability-braces-around-statements,
+ -google-readability-function-size,
+ -misc-no-recursion,
+ -modernize-return-braced-init-list,
+ -modernize-use-nodiscard,
+ -modernize-use-trailing-return-type,
+ -performance-unnecessary-value-param,
+ -readability-identifier-length,
+ -readability-magic-numbers
+
+CheckOptions:
+ - key: readability-function-cognitive-complexity.Threshold
+ value: 100
+ - key: readability-function-cognitive-complexity.IgnoreMacros
+ value: true
+ # Set naming conventions for your style below (there are dozens of naming settings possible):
+ # See https://clang.llvm.org/extra/clang-tidy/checks/readability/identifier-naming.html
+ - key: readability-identifier-naming.ClassCase
+ value: CamelCase
diff --git a/.gitignore b/.gitignore
index 42334a5..979d0c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,59 +1,7 @@
-*.o
-*.lo
-*.a
-*.la
-*.dirstamp
-*.pc
-*.log
-*.trs
+build
+cmake-build-*
+
TAGS
tags
core*
-# autoconf output
-autom4te.cache
-*.in
-!/src/libemsha-1.pc.in
-config.*
-compile
-*.m4
-configure
-depcomp
-*.info
-mdate-sh
-stamp-*
-texinfo.tex
-version.texi
-install-sh
-missing
-Makefile
-.deps
-.libs
-libtool
-ltmain.sh
-
-RELEASE_NOTES
-debian/files
-debian/libemsha-1.postinst.debhelper
-debian/libemsha-1.postrm.debhelper
-debian/libemsha-1.substvars
-debian/libemsha-1/
-debian/libemsha-dev.substvars
-debian/libemsha-dev/
-debian/shlibs.local
-debian/source/
-debian/tmp/
-doc/source/header.dated.rst
-doc/source/header.rst
-src/cov-int/
-src/emsha_core_test
-src/emsha_hmac_test
-src/emsha_mem_test
-src/emsha_sha256_test
-src/emsha_static_hmac_test
-src/emsha_static_mem_test
-src/emsha_static_sha_test
-src/libemsha.tgz
-doc/source/conf.py
-/test-driver
-do-release
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..5ff5750
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..41aee02
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/emsha.iml b/.idea/emsha.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/.idea/emsha.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..536a3da
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..79b3c94
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..799808a
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/scopes/ProjectSources.xml b/.idea/scopes/ProjectSources.xml
new file mode 100644
index 0000000..15fa1f8
--- /dev/null
+++ b/.idea/scopes/ProjectSources.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.trunk/.gitignore b/.trunk/.gitignore
new file mode 100644
index 0000000..1e24652
--- /dev/null
+++ b/.trunk/.gitignore
@@ -0,0 +1,8 @@
+*out
+*logs
+*actions
+*notifications
+*tools
+plugins
+user_trunk.yaml
+user.yaml
diff --git a/.trunk/configs/.clang-tidy b/.trunk/configs/.clang-tidy
new file mode 100644
index 0000000..e4bd819
--- /dev/null
+++ b/.trunk/configs/.clang-tidy
@@ -0,0 +1,39 @@
+Checks: >-
+ bugprone-*,
+ cppcoreguidelines-*,
+ google-*,
+ misc-*,
+ modernize-*,
+ performance-*,
+ readability-*,
+ -bugprone-lambda-function-name,
+ -bugprone-reserved-identifier,
+ -cppcoreguidelines-avoid-goto,
+ -cppcoreguidelines-avoid-magic-numbers,
+ -cppcoreguidelines-avoid-non-const-global-variables,
+ -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+ -cppcoreguidelines-pro-type-vararg,
+ -google-readability-braces-around-statements,
+ -google-readability-function-size,
+ -misc-no-recursion,
+ -modernize-return-braced-init-list,
+ -modernize-use-nodiscard,
+ -modernize-use-trailing-return-type,
+ -performance-unnecessary-value-param,
+ -readability-magic-numbers,
+
+CheckOptions:
+ - key: readability-function-cognitive-complexity.Threshold
+ value: 100
+ - key: readability-function-cognitive-complexity.IgnoreMacros
+ value: true
+ # Set naming conventions for your style below (there are dozens of naming settings possible):
+ # See https://clang.llvm.org/extra/clang-tidy/checks/readability/identifier-naming.html
+ # - key: readability-identifier-naming.ClassCase
+ # value: CamelCase
+ # - key: readability-identifier-naming.NamespaceCase
+ # value: lower_case
+ # - key: readability-identifier-naming.PrivateMemberSuffix
+ # value: _
+ # - key: readability-identifier-naming.StructCase
+ # value: CamelCase
diff --git a/.trunk/configs/.isort.cfg b/.trunk/configs/.isort.cfg
new file mode 100644
index 0000000..b9fb3f3
--- /dev/null
+++ b/.trunk/configs/.isort.cfg
@@ -0,0 +1,2 @@
+[settings]
+profile=black
diff --git a/.trunk/configs/.markdownlint.yaml b/.trunk/configs/.markdownlint.yaml
new file mode 100644
index 0000000..fb94039
--- /dev/null
+++ b/.trunk/configs/.markdownlint.yaml
@@ -0,0 +1,10 @@
+# Autoformatter friendly markdownlint config (all formatting rules disabled)
+default: true
+blank_lines: false
+bullet: false
+html: false
+indentation: false
+line_length: false
+spaces: false
+url: false
+whitespace: false
diff --git a/.trunk/configs/.shellcheckrc b/.trunk/configs/.shellcheckrc
new file mode 100644
index 0000000..8c7b1ad
--- /dev/null
+++ b/.trunk/configs/.shellcheckrc
@@ -0,0 +1,7 @@
+enable=all
+source-path=SCRIPTDIR
+disable=SC2154
+
+# If you're having issues with shellcheck following source, disable the errors via:
+# disable=SC1090
+# disable=SC1091
diff --git a/.trunk/configs/.yamllint.yaml b/.trunk/configs/.yamllint.yaml
new file mode 100644
index 0000000..4d44466
--- /dev/null
+++ b/.trunk/configs/.yamllint.yaml
@@ -0,0 +1,10 @@
+rules:
+ quoted-strings:
+ required: only-when-needed
+ extra-allowed: ["{|}"]
+ empty-values:
+ forbid-in-block-mappings: true
+ forbid-in-flow-mappings: true
+ key-duplicates: {}
+ octal-values:
+ forbid-implicit-octal: true
diff --git a/.trunk/configs/ruff.toml b/.trunk/configs/ruff.toml
new file mode 100644
index 0000000..f5a235c
--- /dev/null
+++ b/.trunk/configs/ruff.toml
@@ -0,0 +1,5 @@
+# Generic, formatter-friendly config.
+select = ["B", "D3", "E", "F"]
+
+# Never enforce `E501` (line length violations). This should be handled by formatters.
+ignore = ["E501"]
diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml
new file mode 100644
index 0000000..0881aa2
--- /dev/null
+++ b/.trunk/trunk.yaml
@@ -0,0 +1,39 @@
+# This file controls the behavior of Trunk: https://docs.trunk.io/cli
+# To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml
+version: 0.1
+cli:
+ version: 1.17.0
+plugins:
+ sources:
+ - id: trunk
+ ref: v1.2.6
+ uri: https://github.com/trunk-io/plugins
+runtimes:
+ enabled:
+ - go@1.21.0
+ - node@18.12.1
+ - python@3.10.8
+lint:
+ enabled:
+ - clang-tidy@16.0.3
+ - bandit@1.7.5
+ - black@23.9.1
+ - checkov@2.5.9
+ - git-diff-check
+ - isort@5.12.0
+ - markdownlint@0.37.0
+ - osv-scanner@1.4.1
+ - prettier@3.0.3
+ - ruff@0.0.292
+ - shellcheck@0.9.0
+ - shfmt@3.6.0
+ - trivy@0.46.0
+ - trufflehog@3.60.0
+ - yamllint@1.32.0
+actions:
+ disabled:
+ - trunk-announce
+ - trunk-check-pre-push
+ - trunk-fmt-pre-commit
+ enabled:
+ - trunk-upgrade-available
diff --git a/CHANGELOG b/CHANGELOG
index 4572473..c2d342e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,11 @@
LIBEMSHA CHANGELOG
==================
+1.0.3 (2023-10-17):
+
+Changed:
+ + Switched from autotools to cmake.
+
1.0.2 (2015-01-28):
Added:
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..90f2778
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,71 @@
+cmake_minimum_required(VERSION 3.22)
+project(emsha
+ VERSION 1.0.3
+ LANGUAGES CXX
+ DESCRIPTION "A compact HMAC-SHA-256 C++11 library.")
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_VERBOSE_MAKEFILES ON)
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
+set(EMSHA_NO_HEXSTRING OFF CACHE BOOL
+ "Don't include support for hex strings.")
+set(EMSHA_NO_HEXLUT OFF CACHE BOOL
+ "Don't use a LUT for hex strings (saves ~256B of memory).")
+
+include(CTest)
+enable_testing()
+
+# compile options:
+# -Wall Default to all errors.
+# -Wextra And a few extra.
+# -Werror And require them to be fixed to build.
+# -Wno-unused-function This is a library. Not every function is used here.
+# -Wno-unused-parameter Some functions have parameters defined for compatibility,
+# and aren't used in the implementation.
+add_compile_options(
+ "-static"
+ "-Wall"
+ "-Wextra"
+ "-Werror"
+ "-Wno-unused-function"
+ "-Wno-unused-parameter"
+ "-g"
+ "$<$:-O2>"
+)
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ add_compile_options("-stdlib=libc++")
+else ()
+ # nothing special for gcc at the moment
+endif ()
+
+### Set up the build ###
+set(HEADERS
+ emsha/emsha.h
+ emsha/sha256.h
+ emsha/hmac.h
+ emsha/internal.h)
+set(SOURCES emsha.cc sha256.cc hmac.cc)
+
+include_directories(SYSTEM .)
+
+### Build products ###
+
+add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS})
+
+### TESTS ###
+
+set(TEST_SOURCES test_utils.cc)
+macro(generate_test name)
+ add_executable(${name} ${name}.cc ${TEST_SOURCES} ${ARGN})
+ target_link_libraries(${name} ${PROJECT_NAME})
+ add_test(${name} ${name})
+endmacro()
+
+generate_test(test_${PROJECT_NAME} test_${PROJECT_NAME}.cc)
+generate_test(test_hmac)
+generate_test(test_mem)
+generate_test(test_sha256)
+
+include(cmake/docs.cmake)
+include(cmake/install.cmake)
+include(cmake/packaging.cmake)
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index 92642e1..0000000
--- a/Makefile.am
+++ /dev/null
@@ -1,28 +0,0 @@
-ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = src
-
-TESTS = src/emsha_core_test \
- src/emsha_sha256_test \
- src/emsha_hmac_test
-
-dist_data_DATA = LICENSE \
- README.rst \
- doc/libemsha.rst
-dist_noinst_DATA = autobuild \
- doc/source \
- doc/Makefile
-
-.PHONY: valgrind-check
-valgrind-check:
- cd src && make $@
-
-.PHONY: cloc-report
-cloc-report:
- cd src && make $@
-
-.PHONY: coverity-scan
-coverity-scan:
- cd src && make $@
-
-epub:
- cd doc && make $@
diff --git a/autobuild b/autobuild
deleted file mode 100755
index cc7467b..0000000
--- a/autobuild
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-CXX=g++
-command -v clang 2>&1 > /dev/null && CXX=clang++
-[ -d m4 ] || mkdir m4
-autoreconf -i && ./configure --enable-silent-rules CXX=$CXX \
- && make && make check
diff --git a/cleanroom b/cleanroom
deleted file mode 100755
index 8d9e5db..0000000
--- a/cleanroom
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/sh
-
-echo ' ____ _ _ _ ____ _____ ____ '
-echo ' | _ \ / \ | \ | |/ ___| ____| _ \ '
-echo ' | | | |/ _ \ | \| | | _| _| | |_) |'
-echo ' | |_| / ___ \| |\ | |_| | |___| _ < '
-echo ' |____/_/ \_\_| \_|\____|_____|_| \_\'
-echo ''
-
-echo "[!] This script will destroy anything not tracked by git."
-echo "[!] Waiting 5 seconds before running. Press ^C to abort."
-
-echo -n "5"
-sleep 1
-echo -n " 4"
-sleep 1
-echo -n " 3"
-sleep 1
-echo -n " 2"
-sleep 1
-echo -n " 1"
-sleep 1
-echo " nuking from orbit!"
-sleep 1
-
-echo ""
-git clean -fxd
-
-echo ""
-echo "-------------------------------------------------------------"
-echo "If you wish to make an apple pie from scratch, you must first"
-echo "create the universe."
-echo " -- Carl Fucking Sagan"
-echo "-------------------------------------------------------------"
-echo ""
-./autobuild
-
diff --git a/cmake/docs.cmake b/cmake/docs.cmake
new file mode 100644
index 0000000..af153ff
--- /dev/null
+++ b/cmake/docs.cmake
@@ -0,0 +1,41 @@
+# Doxygen support for scsl.
+
+add_custom_target(manpages)
+
+macro(md2man source)
+ block()
+ set(SOURCE_MANPAGE)
+ set(SOURCE_SECTION)
+ string(REGEX REPLACE "^.+/([^/]+)\.md$" "\\1" SOURCE_MANPAGE ${source})
+ string(REGEX REPLACE "^.+/[^/]+\.([0-9])\.md$" "\\1" SOURCE_SECTION ${source})
+ file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man/man${SOURCE_SECTION})
+ configure_file(${source} ${SOURCE_MANPAGE}.scdoc)
+ add_custom_command(TARGET manpages
+ COMMAND scdoc < ${SOURCE_MANPAGE}.scdoc > man/man${SOURCE_SECTION}/${SOURCE_MANPAGE})
+ endblock()
+endmacro()
+
+md2man(docs/emsha.3.md)
+
+find_package(Doxygen)
+if (${DOXYGEN_FOUND})
+ # prefer scdocs for manpages.
+ set(DOXYGEN_GENERATE_MAN NO)
+ set(DOXYGEN_GENERATE_LATEX YES)
+ set(DOXYGEN_EXTRACT_ALL YES)
+ set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "${CMAKE_CURRENT_SOURCE_DIR}/docs/mainpage.md")
+ message(STATUS "Doxygen found, building docs.")
+
+ doxygen_add_docs(${PROJECT_NAME}_docs
+ ${HEADER_FILES}
+ ${SOURCE_FILES}
+ USE_STAMP_FILE)
+ add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}_docs)
+ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
+ ${CMAKE_CURRENT_BINARY_DIR}/latex
+ DESTINATION share/doc/${PROJECT_NAME}/doxygen)
+ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/man
+ DESTINATION share)
+ add_dependencies(${PROJECT_NAME}_docs manpages)
+endif ()
+
diff --git a/cmake/emshaConfig.cmake b/cmake/emshaConfig.cmake
new file mode 100644
index 0000000..bef07a5
--- /dev/null
+++ b/cmake/emshaConfig.cmake
@@ -0,0 +1,3 @@
+set(EMSHA_INCLUDE_DIRS include/@PROJECT_NAME@)
+set(EMSHA_LIBRARIES libemsha-@PROJECT_VERSION_MAJOR@.a)
+
diff --git a/cmake/install.cmake b/cmake/install.cmake
new file mode 100644
index 0000000..c6e7bc4
--- /dev/null
+++ b/cmake/install.cmake
@@ -0,0 +1,27 @@
+### Install ###
+
+include(CMakePackageConfigHelpers)
+
+### library packaging for CMake and pkgconfig to find built targets.
+write_basic_package_version_file(
+ ${PROJECT_NAME}Config.cmake
+ VERSION ${PACKAGE_VERSION}
+ COMPATIBILITY SameMajorVersion
+)
+write_basic_package_version_file(
+ ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
+ VERSION ${PROJECT_VERSION}
+ COMPATIBILITY SameMajorVersion)
+configure_file(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
+
+### set up installation targets.
+
+install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib)
+install(FILES ${HEADERS} DESTINATION include/${PROJECT_NAME})
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
+ DESTINATION lib/pkgconfig)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
+ DESTINATION share/${PROJECT_CMAKE_CONFIG_NAME}/cmake)
+
+
diff --git a/cmake/packaging.cmake b/cmake/packaging.cmake
new file mode 100644
index 0000000..ae2d21f
--- /dev/null
+++ b/cmake/packaging.cmake
@@ -0,0 +1,41 @@
+### Packaging ###
+
+include(InstallRequiredSystemLibraries)
+
+set(CPACK_PACKAGE_VENDOR "K. Isom")
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${PROJECT_DESCRIPTION})
+set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
+set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
+set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
+
+set(CPACK_PACKAGE_FILE_NAME
+ ${PROJECT_NAME}-${PROJECT_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_ARCH}${CMAKE_HOST_SYSTEM_PROCESSOR})
+
+# Debian settings
+set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${CPACK_PACKAGE_VENDOR})
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${CPACK_PACKAGE_DESCRIPTION})
+set(CPACK_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION})
+set(CPACK_PACKAGE_DEPENDS)
+set(CPACK_DEBIAN_PACKAGE_SECTION devel)
+set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON)
+set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
+
+if(LINUX)
+set(CPACK_GENERATOR "DEB;STGZ;TGZ")
+elseif(APPLE)
+set(CPACK_GENERATOR "productbuild")
+elseif(MSVC OR MSYS OR MINGW)
+set(CPACK_GENERATOR "NSIS;ZIP")
+else()
+set(CPACK_GENERATOR "ZIP")
+endif()
+
+set(CPACK_SOURCE_GENERATOR "TGZ;ZIP")
+
+set(CPACK_SOURCE_IGNORE_FILES
+ /.git
+ /dist
+ /.*build.*)
+
+include (CPack)
+add_custom_target(package_docs DEPENDS emsha_docs package package_source)
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index c637299..0000000
--- a/configure.ac
+++ /dev/null
@@ -1,62 +0,0 @@
-# autoconf version 2.68 and automake version 1.11 seem to be the latest
-# versions that can be used with Travis right now.
-AC_PREREQ([2.68])
-AC_INIT([libemsha],
- [1.0.2],
- [coder@kyleisom.net],
- [libemsha],
- [https://kyleisom.net/projects/libemsha/])
-AM_INIT_AUTOMAKE([1.11 foreign])
-
-AC_CONFIG_SRCDIR([src/emsha/sha256.hh])
-AC_CONFIG_FILES([Makefile src/Makefile doc/source/conf.py doc/source/header.rst src/libemsha-1.pc])
-AC_CONFIG_FILES([do-release], [chmod +x do-release])
-AC_CONFIG_MACRO_DIR([m4])
-
-PKG_PROG_PKG_CONFIG
-AC_CHECK_HEADERS
-
-LT_INIT
-AC_PROG_CXX
-AC_PROG_INSTALL
-AC_PROG_CC_C_O
-
-AC_CHECK_PROGS([SPHINX], [sphinx-build])
-if test -z "$SPHINX";
-then
- AC_MSG_WARN([Sphinx not found - continuing without Sphinx support])
-fi
-
-AC_ARG_ENABLE([hexstring],
- AS_HELP_STRING([--disable-hexstring], [Don't build with support for hex string output (default enabled)]),
- [:], [enable_hexstring=check])
-
-AC_ARG_ENABLE([hexlut],
- AS_HELP_STRING([--disable-hexlut], [Don't build with the larger LUT for building hex strings (saves ~1KB of memory). This has no effect if hex strings are disabled.]),
- [:], [enable_hexlut=check])
-
-AC_ARG_ENABLE([selftest],
- AS_HELP_STRING([--disable-selftest], [Don't build with support for internal self-tests (saves some memory that is used by the test vectors.)]),
- [:], [enable_selftest=check])
-
-# The default for the ARG_ENABLE options is to have them enabled.
-AS_IF([test "x$enable_hexstring" == "xno"], [
- AC_MSG_NOTICE([disabling hexstrings.])
- AC_DEFINE(EMSHA_NO_HEXSTRING)
-])
-
-AS_IF([test "x$enable_hexlut" == "xno"], [
- AC_MSG_NOTICE([disabling the large hexstring LUT.])
- AC_DEFINE(EMSHA_NO_HEXLUT)
-])
-
-AS_IF([test "x$enable_selftest" == "xno"], [
- AC_MSG_NOTICE([disabling the internal self tests.])
- AC_DEFINE(EMSHA_NO_SELFTEST)
-])
-
-
-AM_CONDITIONAL([HAVE_SPHINX],
- [test -n "$SPHINX"])
-
-AC_OUTPUT
diff --git a/do-release.in b/do-release.in
deleted file mode 100755
index 96a83ea..0000000
--- a/do-release.in
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/sh
-
-set -e
-
-VERSION="@PACKAGE_VERSION@"
-TARBALL="@PACKAGE_NAME@-$VERSION"
-
-make clean
-echo "[+] rebuilding single ReST doc"
-cd doc && make clean singlerst clean && cd ..
-echo "[+] building release tarballs"
-make dist-gzip
-if [ ! -e "$TARBALL.tar.gz" ]
-then
- >&2 echo "[!] Expected to find ${TARBALL}.tar.gz, but it wasn't found."
- >&2 echo " Cannot proceed, aborting."
- exit 1
-fi
-
-make dist-zip
-if [ ! -e "$TARBALL.zip" ]
-then
- >&2 echo "[!] Expected to find ${TARBALL}.zip, but it wasn't found."
- >&2 echo " Cannot proceed, aborting."
- exit 1
-fi
-
-mv "${TARBALL}.tar.gz" "@PACKAGE_NAME@-release.tar.gz"
-mv "${TARBALL}.zip" "@PACKAGE_NAME@-release.zip"
-
-echo "[+] building release notes"
-RELEASE_NOTES_AWK="/^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)? \([0-9]{4}-[0-9]{2}-[0-9]{2}\):/{
- nmatch++;
- if (nmatch>1) exit
-}
-
-{
- if (nmatch>0)
- print \$0;
-}"
-
-awk "$RELEASE_NOTES_AWK" CHANGELOG > RELEASE_NOTES
-echo "[+] release is ready"
diff --git a/doc/Makefile b/doc/Makefile
deleted file mode 100644
index a6f9e61..0000000
--- a/doc/Makefile
+++ /dev/null
@@ -1,204 +0,0 @@
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-PAPER =
-BUILDDIR = build
-
-# User-friendly check for sphinx-build
-ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
-$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
-endif
-
-# Internal variables.
-PAPEROPT_a4 = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
-# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
-
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext check
-
-help:
- @echo "Please use \`make ' where is one of"
- @echo " html to make standalone HTML files"
- @echo " dirhtml to make HTML files named index.html in directories"
- @echo " singlehtml to make a single large HTML file"
- @echo " pickle to make pickle files"
- @echo " json to make JSON files"
- @echo " htmlhelp to make HTML files and a HTML help project"
- @echo " qthelp to make HTML files and a qthelp project"
- @echo " devhelp to make HTML files and a Devhelp project"
- @echo " epub to make an epub"
- @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
- @echo " latexpdf to make LaTeX files and run them through pdflatex"
- @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
- @echo " text to make text files"
- @echo " man to make manual pages"
- @echo " texinfo to make Texinfo files"
- @echo " info to make Texinfo files and run them through makeinfo"
- @echo " gettext to make PO message catalogs"
- @echo " changes to make an overview of all changed/added/deprecated items"
- @echo " xml to make Docutils-native XML files"
- @echo " pseudoxml to make pseudoxml-XML files for display purposes"
- @echo " linkcheck to check all external links for integrity"
- @echo " doctest to run all doctests embedded in the documentation (if enabled)"
-
-# The autotools Makefiles don't seem to do anything for docs in all or check.
-all:
-check:
-
-distclean: clean
- rm -f source/header*.rst
- rm -f source/conf.py
-
-clean:
- rm -rf $(BUILDDIR)/*
-
-html:
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
- @echo
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
- @echo
- @echo "Build finished; now you can process the pickle files."
-
-json:
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
- @echo
- @echo "Build finished; now you can process the JSON files."
-
-htmlhelp:
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
- @echo
- @echo "Build finished; now you can run HTML Help Workshop with the" \
- ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
- @echo
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PACKAGE_NAME.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PACKAGE_NAME.qhc"
-
-devhelp:
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
- @echo
- @echo "Build finished."
- @echo "To view the help file:"
- @echo "# mkdir -p $$HOME/.local/share/devhelp/PACKAGE_NAME"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PACKAGE_NAME"
- @echo "# devhelp"
-
-epub:
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
- @echo
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
- @echo "Run \`make' in that directory to run these through (pdf)latex" \
- "(use \`make latexpdf' here to do that automatically)."
-
-pdf: latexpdf
-
-latexpdf:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through pdflatex..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-latexpdfja:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through platex and dvipdfmx..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
- @echo
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
- @echo
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-texinfo:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo
- @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
- @echo "Run \`make' in that directory to run these through makeinfo" \
- "(use \`make info' here to do that automatically)."
-
-info:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo "Running Texinfo files through makeinfo..."
- make -C $(BUILDDIR)/texinfo info
- @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
-
-gettext:
- $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
- @echo
- @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
-
-changes:
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
- @echo
- @echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
- @echo
- @echo "Link check complete; look for any errors in the above output " \
- "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
- @echo "Testing of doctests in the sources finished, look at the " \
- "results in $(BUILDDIR)/doctest/output.txt."
-
-xml:
- $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
- @echo
- @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
-
-pseudoxml:
- $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
- @echo
- @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
-
-singlerst:
- sed -e "s/@BUILD_DATE@/$$(date +'%Y-%m-%d')/" \
- source/header.rst > source/header.dated.rst
- cat source/header.dated.rst \
- source/intro.rst \
- source/building.rst \
- source/overview.rst \
- source/hash.rst \
- source/sha256.rst \
- source/hmac.rst \
- source/misc.rst \
- source/tests.rst \
- source/refs.rst \
- > libemsha.rst
-
-
diff --git a/doc/build/.gitkeep b/doc/build/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/doc/libemsha.rst b/doc/libemsha.rst
deleted file mode 100644
index 7134fad..0000000
--- a/doc/libemsha.rst
+++ /dev/null
@@ -1,601 +0,0 @@
-========
-libemsha
-========
-
-Version: 1.0.2
-
-Date: 2016-01-28
-
-
------------------
-Table of Contents
------------------
-
-+ Introduction
-+ Getting and Building the Source
-+ Library Overview
-+ The Hash interface
-+ The SHA256 class
-+ The HMAC class
-+ Miscellaneous functions
-+ Test Programs
-+ References
-
-
--------------
-Introduction
--------------
-
-This library is an MIT-licensed compact HMAC-SHA-256 C++11 library
-designed for embedded systems. It is built following the JPL `Power of
-Ten `_ rules.
-
-This library came about as a result of a need for a standalone
-SHA-256 library for an embedded system. The original goal was
-to implement a wrapper around the code extracted from `RFC 6234
-`_; instead a standalone
-implementation was decided on.
-
-Additional resources:
-
-+ `Github page `_
-+ `Travis CI status `_
-+ `Coverity Scan page `_
-
-
--------------------------------
-Getting and Building the Source
--------------------------------
-
-The source code is available via `Github
-`_; each version should be git tagged. ::
-
- git clone https://github.com/kisom/libemsha
- git clone git@github.com:kisom/libemsha
-
-The current release is `1.0.0 `_.
-
-The project is built using Autotools and ``make``.
-
-When building from a git checkout, the `autobuild` script will bootstrap
-the project from the autotools sources (e.g. via ``autoreconf -i``),
-run ``configurei`` (by default to use clang), and attempt to build the library
-and run the unit tests.
-
-Once the autotools infrastructure has been bootstrapped, the following
-should work: ::
-
- ./configure && make && make check && make install
-
-There are three flags to ``configure`` that might be useful:
-
-+ ``--disable-hexstring`` disables the provided ``hexstring`` function;
- while this might be useful in many cases, it also adds extra size to
- the code.
-
-+ ``--disable-hexlut`` disables the larger lookup table used by
- ``hexstring``, which can save around a kilobyte of program space. If
- the ``hexstring`` function is disabled, this option has no effect.
-
-+ ``--disable-selftest`` disables the internal self-tests, which can
- reclaim some additional program space.
-
-----------------
-Library Overview
-----------------
-
-.. cpp:namespace:: emsha
-
-The package provides a pair of classes, :cpp:class:`SHA256` and
-:cpp:class:`HMAC`, that both satisfy a common interface :cpp:class:`Hash`. All
-functionality provided by this library is found under the ``emsha`` namespace.
-
-
-``EMSHA_RESULT``
-^^^^^^^^^^^^^^^^^
-
-The ``EMSHA_RESULT`` enum is used to convey the result of an
-operation. The possible values are:
-
-.. cpp:enum:: _EMSHA_RESULT_ : uint8_t
-
-::
-
- // All operations have completed successfully so far.
- EMSHA_ROK = 0,
-
- // A self test or unit test failed.
- EMSHA_TEST_FAILURE = 1,
-
- // A null pointer was passed in as a buffer where it
- // shouldn't have been.
- EMSHA_NULLPTR = 2,
-
- // The Hash is in an invalid state.
- EMSHA_INVALID_STATE = 3,
-
- // The input to SHA256::update is too large.
- SHA256_INPUT_TOO_LONG = 4,
-
- // The self tests have been disabled, but a self test
- // function was called.
- EMSHA_SELFTEST_DISABLED = 5
-
-As a convenience, the following ``typedef`` is also provided.
-
- ``typedef enum _EMSHA_RESULT_`` :cpp:type:`EMSHA_RESULT`
-
-
-------------------
-The Hash interface
-------------------
-
-.. cpp:class:: emsha::Hash
-
- The ``Hash`` class contains a top-level interface for the objects in
- this library.
-
-In general, a `Hash` is used along the lines of: ::
-
- emsha::EMSHA_RESULT
- hash_single_pass(uint8_t *m, uint32_t ml, uint8_t *digest)
- {
- // Depending on the implementation, the constructor may need
- // arguments.
- emsha::Hash h;
- emsha::EMSHA_RESULT res;
-
- res = h.write(m, ml);
- if (emsha::EMSHA_ROK != res) {
- return res;
- }
-
- // digest will contain the output of the Hash, and the
- // caller MUST ensure that there is enough space in
- // the buffer.
- return h.result(d);
- }
-
-Methods
-^^^^^^^
-
-.. cpp:function:: emsha::EMSHA_RESULT reset(void)
-
- reset should bring the Hash back into its initial state. That is,
- the idea is that::
-
- hash->reset();
- hash->update(...); // possibly many of these...
- hash->result(...); // should always return the same hash.
-
- is idempotent, assuming the inputs to ``update`` and ``result``
- are constant. The implications of this for a given concrete class
- should be described in that class's documentation, but in general,
- it has the effect of preserving any initial state while removing any
- data written to the Hash via the update method.
-
-.. cpp:function:: emsha::EMSHA_RESULT update(const uint8_t *m, uint32_t ml)
-
- ``update`` is used to write message data into
- the Hash.
-
-.. cpp:function:: emsha::EMSHA_RESULT finalize(uint8_t *d)
-
- ``finalize`` should carry out any final operations on the `Hash`;
- after a call to finalize, no more data can be written. Additionally,
- it transfers out the resulting hash into its argument.
-
- Note that this library does not allocate memory, and therefore the
- caller *must* ensure that ``d`` is a valid buffer containing at least
- ``this->size()`` bytes.
-
-.. cpp:function:: emsha::EMSHA_RESULT result(uint8_t *d)
-
- ``result`` is used to transfer out the hash to the argument. This implies
- that the `Hash` must keep enough state for repeated calls to ``result``
- to work.
-
-.. cpp:function:: uint32_t size(void)
-
- ``size`` should return the output size of the `Hash`; this is, how large
- the buffers written to by ``result`` should be.
-
------------------
-The SHA256 class
------------------
-
-.. cpp:class:: emsha::SHA256
-
- SHA256 is an implementation of the :cpp:class:`emsha::Hash` interface
- implementing the SHA-256 cryptographic hash algorithm
-
-.. cpp:function:: SHA256::SHA256()
-
- A SHA256 context does not need any special construction. It can be
- declared and immediately start being used.
-
-
-.. cpp:function:: SHA256::~SHA256()
-
- The SHA256 destructor will clear out its internal message buffer;
- all of the members are local and not resource handles, so cleanup
- is minimal.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::reset(void)
-
- reset clears the internal state of the `SHA256` context and returns
- it to its initial state. It should always return ``EMSHA_ROK``.
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::update(const uint8_t *m, uint32_t ml)
-
- update writes data into the context. While there is an upper limit
- on the size of data that SHA-256 can operate on, this package is
- designed for small systems that will not approach that level of
- data (which is on the order of 2 exabytes), so it is not thought to
- be a concern.
-
- **Inputs**:
-
- + ``m``: a byte array containing the message to be written. It must
- not be NULL (unless the message length is zero).
-
- + ``ml``: the message length, in bytes.
-
- **Return values**:
-
- * ``EMSHA_NULLPTR`` is returned if ``m`` is NULL and ``ml`` is nonzero.
-
- * ``EMSHA_INVALID_STATE`` is returned if the `update` is called
- after a call to `finalize`.
-
- * ``SHA256_INPUT_TOO_LONG`` is returned if too much data has been
- written to the context.
-
- + ``EMSHA_ROK`` is returned if the data was successfully added to
- the SHA-256 context.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::finalize(uint8_t *d)
-
- ``finalize`` completes the digest. Once this method is called, the
- context cannot be updated unless the context is reset.
-
- **Inputs**:
-
- * d: a byte buffer that must be at least ``SHA256.size()`` in
- length.
-
- **Outputs**:
-
- * ``EMSHA_NULLPTR`` is returned if ``d`` is the null pointer.
-
- * ``EMSHA_INVALID_STATE`` is returned if the SHA-256 context is in
- an invalid state, such as if there were errors in previous
- updates.
-
- * ``EMSHA_ROK`` is returned if the context was successfully
- finalised and the digest copied to ``d``.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::result(uint8_t *d)
-
- ``result`` copies the result from the SHA-256 context into the
- buffer pointed to by ``d``, running finalize if needed. Once
- called, the context cannot be updated until the context is reset.
-
- **Inputs**:
-
- * ``d``: a byte buffer that must be at least ``SHA256.size()`` in
- length.
-
- **Outputs**:
-
- * ``EMSHA_NULLPTR`` is returned if ``d`` is the null pointer.
-
- * ``EMSHA_INVALID_STATE`` is returned if the SHA-256 context is in
- an invalid state, such as if there were errors in previous
- updates.
-
- * ``EMSHA_ROK`` is returned if the context was successfully
- finalised and the digest copied to ``d``.
-
-.. cpp:function:: uint32_t SHA256::size(void)
-
- ``size`` returns the output size of SHA256, e.g.
- the size that the buffers passed to ``finalize``
- and ``result`` should be.
-
- **Outputs**:
-
- * a ``uint32_t`` representing the expected size of buffers passed
- to ``result`` and ``finalize``.
-
-
---------------
-The HMAC class
---------------
-
-
-.. cpp:class:: emsha::HMAC
-
- HMAC is an implementation of the :cpp:class:`emsha::Hash` interface
- implementing the HMAC keyed-hash message authentication code as
- defined in FIPS 198-1, using SHA-256 internally.
-
-.. cpp:function:: HMAC::HMAC(const uint8_t *key, uint32_t keylen)
-
- An HMAC context must be initialised with a key.
-
-
-.. cpp:function:: HMAc::~HMAC()
-
- The HMAC destructor will attempt to wipe the key and reset the
- underlying SHA-256 context.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT HMAC::reset(void)
-
- reset clears the internal state of the `HMAC` context and returns
- it to its initial state. It should always return ``EMSHA_ROK``.
- This function will **not** wipe the key; an `HMAC` object that has
- `reset` called it can be used immediately after.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT HMAC::update(const uint8_t *m, uint32_t ml)
-
- update writes data into the context. While there is an upper limit on
- the size of data that the underlying SHA-256 context can operate on,
- this package is designed for small systems that will not approach
- that level of data (which is on the order of 2 exabytes), so it is
- not thought to be a concern.
-
- **Inputs**:
-
- + ``m``: a byte array containing the message to be written. It must
- not be NULL (unless the message length is zero).
-
- + ``ml``: the message length, in bytes.
-
- **Return values**:
-
- * ``EMSHA_NULLPTR`` is returned if ``m`` is NULL and ``ml`` is nonzero.
-
- * ``EMSHA_INVALID_STATE`` is returned if the `update` is called
- after a call to `finalize`.
-
- * ``SHA256_INPUT_TOO_LONG`` is returned if too much data has been
- written to the context.
-
- + ``EMSHA_ROK`` is returned if the data was successfully added to
- the HMAC context.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::finalize(uint8_t *d)
-
- ``finalize`` completes the digest. Once this method is called, the
- context cannot be updated unless the context is reset.
-
- **Inputs**:
-
- * d: a byte buffer that must be at least ``SHA256.size()`` in
- length.
-
- **Outputs**:
-
- * ``EMSHA_NULLPTR`` is returned if ``d`` is the null pointer.
-
- * ``EMSHA_INVALID_STATE`` is returned if the HMAC context is in
- an invalid state, such as if there were errors in previous
- updates.
-
- * ``EMSHA_ROK`` is returned if the context was successfully
- finalised and the digest copied to ``d``.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::result(uint8_t *d)
-
- ``result`` copies the result from the HMAC context into the
- buffer pointed to by ``d``, running finalize if needed. Once
- called, the context cannot be updated until the context is reset.
-
- **Inputs**:
-
- * ``d``: a byte buffer that must be at least ``HMAC.size()`` in
- length.
-
- **Outputs**:
-
- * ``EMSHA_NULLPTR`` is returned if ``d`` is the null pointer.
-
- * ``EMSHA_INVALID_STATE`` is returned if the HMAC context is in
- an invalid state, such as if there were errors in previous
- updates.
-
- * ``EMSHA_ROK`` is returned if the context was successfully
- finalised and the digest copied to ``d``.
-
-.. cpp:function:: uint32_t SHA256::size(void)
-
- ``size`` returns the output size of HMAC, e.g. the size that the
- buffers passed to ``finalize`` and ``result`` should be.
-
- **Outputs**:
-
- * a ``uint32_t`` representing the expected size of buffers passed
- to ``result`` and ``finalize``.
-
------------------------
-Miscellaneous functions
------------------------
-
-.. cpp:function:: emsha::EMSHA_RESULT sha256_self_test(void)
-
- If the library was `compiled with support for self tests
- <./building.html>`_ (the default), this function will run a few self
- tests on the SHA-256 functions to validate that they are working
- correctly.
-
- **Outputs**:
-
- * ``EMSHA_ROK`` if the self-test completed successfully.
-
- * ``EMSHA_TEST_FAILURE`` if the SHA-256 functions did not produce
- the expected value.
-
- * ``EMSHA_SELFTEST_DISABLED`` if the library was built without
- support for the self test.
-
- * If an error occurs in the SHA-256 code, the resulting error code
- will be returned.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT sha256_digest(const uint8_t *m, uint32_t ml, uint8_t *d)
-
- The ``sha256_digest`` function will compute the digest on the
- ``ml``-byte octet string stored in ``m``, returning the result
- in ``d``. This is a convenience function implemented as: ::
-
- EMSHA_RESULT
- sha256_digest(const uint8_t *m, uint32_t ml, uint8_t *d)
- {
- SHA256 h;
- EMSHA_RESULT ret;
-
- if (EMSHA_ROK != (ret = h.update(m, ml))) {
- return ret;
- }
-
- return h.finalize(d);
- }
-
-.. cpp:function:: emsha::EMSHA_RESULT compute_hmac(const uint8_t *k, uint32_t kl, const uint8_t *m, uint32_t ml, uint8_t *d)
-
- The ``compute_hmac`` function computes the MAC on the ``ml``-byte
- octet string stored in``m``, using the ``kl``-length key ``k``. The
- result is stored in ``d``. This is a convenience function implemented
- as: ::
-
- EMSHA_RESULT
- compute_hmac(const uint8_t *k, uint32_t kl, const uint8_t *m, uint32_t ml,
- uint8_t *d)
- {
- EMSHA_RESULT res;
- HMAC h(k, kl);
-
- res = h.update(m, ml);
- if (EMSHA_ROK != res) {
- return res;
- }
-
- res = h.result(d);
- if (EMSHA_ROK != res) {
- return res;
- }
-
- return res;
- }
-
-.. cpp:function:: bool hash_equal(const uint8_t *a, const uint8_t *b)
-
- ``hash_equal`` performs a constant-time comparison of the first
- ``emsha::SHA256_HASH_SIZE`` bytes in the two byte array arguments.
-
- **Inputs**:
-
- * ``a``, ``b``: byte arrays at least ``emsha::SHA256_HASH_SIZE``
- bytes in length.
-
- ** Outputs**:
-
- * true *iff* the first ``emsha::SHA256_HASH_SIZE`` bytes match in
- both arrays.
-
- * false otherwise.
-
-
-.. cpp:function:: void hexstring(uint8_t *dest, uint8_t *src, uint32_t srclen)
-
- **Note**: this function is only present if the library was
- `built with support <./building.html>`_ for the hexstring functionality.
-
- **Inputs**:
-
- * dest: a byte array that is 2 * ``srclen``.
-
- * src: a byte array containing the data to process.
-
- * srclen: the size of ``src``.
-
- **Outputs**:
-
- When the function returns, the hex-encoded string will be placed in
- ``dest``.
-
--------------
-Test Programs
--------------
-
-Running ``make check`` builds and runs the test programs. These are:
-
-* ``emsha_core_test`` runs the core tests.
-* ``emsha_sha256_test`` runs test vectors on the SHA-256 code.
-* ``emsha_hmac_test`` runs test vectors on the HMAC code.
-
-Additionally, the following test programs are built but not run. These
-programs do not link with the library as the above programs do; instead,
-they compile the object files in to avoid the libtool dance before the
-library is installed.
-
-* ``emsha_mem_test`` and ``emsha_static_mem_test`` are for memory
- profiling (e.g., with `Valgrind `_ during
- development.
-
-* ``emsha_static_sha256_test`` and ``emsha_static_hmac_test`` are used
- to facilitate testing and debugging the library. These programs run
- the same tests as the ``emsha_sha256_test`` and ``emsha_hmac_test``
- programs.
-
-
-Core Tests
-^^^^^^^^^^
-
-There are three tests run in the core tests: a hexstring test (if
-`support is built in <./building.html>`_) and the constant time
-check. The constant time test does not validate that the function
-is constant time, only that it correctly verifies that two byte
-arrays are equal.
-
-
-SHA-256 Tests
-^^^^^^^^^^^^^
-
-The SHA-256 checks take a number of test vectors from the Go standard
-library's SHA-256 library.
-
-
-HMAC Tests
-^^^^^^^^^^
-
-The HMAC checks apply the `RFC 4231 `_
-test vectors to the HMAC code.
-
-
-
-----------
-References
-----------
-
-* `FIPS 180-4, the Secure Hash Standard `_
-* `FIPS 198-1, The Keyed-Hash Message Authentication Code (HMAC) `_
-* `RFC 2014, HMAC: Keyed-Hashing for Message Authentication `_
-* `RFC 6234, US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF) `_\ [#f1]_
-* The behaviour of this package was cross-checked using the Go 1.5.1
- linux/amd64 standard library's `crypto/sha256 `_
- package.
-
-.. rubric:: Footnotes
-
-.. [#f1] This library came about after extracting the relevant C code
- from RFC 6234, and needing a C++ version. It draws heavy
- inspiration from that code base.
diff --git a/doc/source/_static/.gitkeep b/doc/source/_static/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/doc/source/_templates/.gitkeep b/doc/source/_templates/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/doc/source/building.rst b/doc/source/building.rst
deleted file mode 100644
index 41d538c..0000000
--- a/doc/source/building.rst
+++ /dev/null
@@ -1,37 +0,0 @@
--------------------------------
-Getting and Building the Source
--------------------------------
-
-The source code is available via `Github
-`_; each version should be git tagged. ::
-
- git clone https://github.com/kisom/libemsha
- git clone git@github.com:kisom/libemsha
-
-The current release is `1.0.0 `_.
-
-The project is built using Autotools and ``make``.
-
-When building from a git checkout, the `autobuild` script will bootstrap
-the project from the autotools sources (e.g. via ``autoreconf -i``),
-run ``configurei`` (by default to use clang), and attempt to build the library
-and run the unit tests.
-
-Once the autotools infrastructure has been bootstrapped, the following
-should work: ::
-
- ./configure && make && make check && make install
-
-There are three flags to ``configure`` that might be useful:
-
-+ ``--disable-hexstring`` disables the provided ``hexstring`` function;
- while this might be useful in many cases, it also adds extra size to
- the code.
-
-+ ``--disable-hexlut`` disables the larger lookup table used by
- ``hexstring``, which can save around a kilobyte of program space. If
- the ``hexstring`` function is disabled, this option has no effect.
-
-+ ``--disable-selftest`` disables the internal self-tests, which can
- reclaim some additional program space.
-
diff --git a/doc/source/conf.py.in b/doc/source/conf.py.in
deleted file mode 100644
index 581a6eb..0000000
--- a/doc/source/conf.py.in
+++ /dev/null
@@ -1,335 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# @PACKAGE_NAME@ documentation build configuration file, created by
-# sphinx-quickstart on Tue Dec 15 23:35:10 2015.
-#
-# This file is execfile()d with the current directory set to its
-# containing dir.
-#
-# Note that not all possible configuration values are present in this
-# autogenerated file.
-#
-# All configuration values have a default; values that are commented out
-# serve to show the default.
-
-import sys
-import os
-
-import sphinx_rtd_theme
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
-
-# -- General configuration ------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
-extensions = [
- 'sphinx.ext.todo',
-]
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
-
-# The suffix of source filenames.
-source_suffix = '.rst'
-
-# The encoding of source files.
-#source_encoding = 'utf-8-sig'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u'@PACKAGE_NAME@'
-copyright = u'2015, K. Isom '
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The short X.Y version.
-version = '@PACKAGE_VERSION@'
-# The full version, including alpha/beta/rc tags.
-release = '@PACKAGE_VERSION@'
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#language = None
-
-# There are two options for replacing |today|: either, you set today to some
-# non-false value, then it is used:
-#today = ''
-# Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-exclude_patterns = []
-
-# The reST default role (used for this markup: `text`) to use for all
-# documents.
-#default_role = None
-
-# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
-
-# If true, the current module name will be prepended to all description
-# unit titles (such as .. function::).
-#add_module_names = True
-
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-#show_authors = False
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
-
-# A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
-
-# If true, keep warnings as "system message" paragraphs in the built documents.
-#keep_warnings = False
-
-highlight_language = 'c++'
-
-
-# -- Options for HTML output ----------------------------------------------
-
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-html_theme = 'sphinx_rtd_theme'
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#html_theme_options = {}
-
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
-
-# The name for this set of Sphinx documents. If None, it defaults to
-# " v documentation".
-#html_title = None
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
-
-# Add any extra paths that contain custom files (such as robots.txt or
-# .htaccess) here, relative to this directory. These files are copied
-# directly to the root of the documentation.
-#html_extra_path = []
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
-# Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = '@PACKAGE_NAME@doc'
-
-
-# -- Options for LaTeX output ---------------------------------------------
-
-latex_elements = {
-# The paper size ('letterpaper' or 'a4paper').
-#'papersize': 'letterpaper',
-
-# The font size ('10pt', '11pt' or '12pt').
-#'pointsize': '10pt',
-
-# Additional stuff for the LaTeX preamble.
-#'preamble': '',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-# author, documentclass [howto, manual, or own class]).
-latex_documents = [
- ('index', '@PACKAGE_NAME@.tex', u'@PACKAGE_NAME@ Documentation',
- u'K. Isom ', 'manual'),
-]
-
-# The name of an image file (relative to this directory) to place at the top of
-# the title page.
-#latex_logo = None
-
-# For "manual" documents, if this is true, then toplevel headings are parts,
-# not chapters.
-#latex_use_parts = False
-
-# If true, show page references after internal links.
-latex_show_pagerefs = True
-
-# If true, show URL addresses after external links.
-# latex_show_urls = True
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_domain_indices = True
-
-
-# -- Options for manual page output ---------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
- ('index', 'package_name', u'@PACKAGE_NAME@ Documentation',
- [u'K. Isom '], 1)
-]
-
-# If true, show URL addresses after external links.
-man_show_urls = True
-
-
-# -- Options for Texinfo output -------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-# dir menu entry, description, category)
-texinfo_documents = [
- ('index', '@PACKAGE_NAME@', u'@PACKAGE_NAME@ Documentation',
- u'K. Isom ', '@PACKAGE_NAME@', 'HMAC-SHA-256 C++11 library designed for embedded systems.',
- 'Development'),
-]
-
-# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
-
-# If false, no module index is generated.
-#texinfo_domain_indices = True
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
-
-# If true, do not generate a @detailmenu in the "Top" node's menu.
-#texinfo_no_detailmenu = False
-
-
-# -- Options for Epub output ----------------------------------------------
-
-# Bibliographic Dublin Core info.
-epub_title = u'@PACKAGE_NAME@'
-epub_author = u'K. Isom '
-epub_publisher = u'K. Isom '
-epub_copyright = u'2015, K. Isom '
-
-# The basename for the epub file. It defaults to the project name.
-#epub_basename = u'@PACKAGE_NAME@'
-
-# The HTML theme for the epub output. Since the default themes are not optimized
-# for small screen space, using the same theme for HTML and epub output is
-# usually not wise. This defaults to 'epub', a theme designed to save visual
-# space.
-#epub_theme = 'epub'
-
-# The language of the text. It defaults to the language option
-# or en if the language is not set.
-#epub_language = ''
-
-# The scheme of the identifier. Typical schemes are ISBN or URL.
-#epub_scheme = ''
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#epub_identifier = ''
-
-# A unique identification for the text.
-#epub_uid = ''
-
-# A tuple containing the cover image and cover page html template filenames.
-#epub_cover = ()
-
-# A sequence of (type, uri, title) tuples for the guide element of content.opf.
-#epub_guide = ()
-
-# HTML files that should be inserted before the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_pre_files = []
-
-# HTML files shat should be inserted after the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_post_files = []
-
-# A list of files that should not be packed into the epub file.
-epub_exclude_files = ['search.html']
-
-# The depth of the table of contents in toc.ncx.
-#epub_tocdepth = 3
-
-# Allow duplicate toc entries.
-#epub_tocdup = True
-
-# Choose between 'default' and 'includehidden'.
-#epub_tocscope = 'default'
-
-# Fix unsupported image types using the PIL.
-#epub_fix_images = False
-
-# Scale large images.
-#epub_max_image_width = 0
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#epub_show_urls = 'inline'
-
-# If false, no index is generated.
-#epub_use_index = True
diff --git a/doc/source/hash.rst b/doc/source/hash.rst
deleted file mode 100644
index 0c77c72..0000000
--- a/doc/source/hash.rst
+++ /dev/null
@@ -1,74 +0,0 @@
-------------------
-The Hash interface
-------------------
-
-.. cpp:class:: emsha::Hash
-
- The ``Hash`` class contains a top-level interface for the objects in
- this library.
-
-In general, a `Hash` is used along the lines of: ::
-
- emsha::EMSHA_RESULT
- hash_single_pass(uint8_t *m, uint32_t ml, uint8_t *digest)
- {
- // Depending on the implementation, the constructor may need
- // arguments.
- emsha::Hash h;
- emsha::EMSHA_RESULT res;
-
- res = h.write(m, ml);
- if (emsha::EMSHA_ROK != res) {
- return res;
- }
-
- // digest will contain the output of the Hash, and the
- // caller MUST ensure that there is enough space in
- // the buffer.
- return h.result(d);
- }
-
-Methods
-^^^^^^^
-
-.. cpp:function:: emsha::EMSHA_RESULT reset(void)
-
- reset should bring the Hash back into its initial state. That is,
- the idea is that::
-
- hash->reset();
- hash->update(...); // possibly many of these...
- hash->result(...); // should always return the same hash.
-
- is idempotent, assuming the inputs to ``update`` and ``result``
- are constant. The implications of this for a given concrete class
- should be described in that class's documentation, but in general,
- it has the effect of preserving any initial state while removing any
- data written to the Hash via the update method.
-
-.. cpp:function:: emsha::EMSHA_RESULT update(const uint8_t *m, uint32_t ml)
-
- ``update`` is used to write message data into
- the Hash.
-
-.. cpp:function:: emsha::EMSHA_RESULT finalize(uint8_t *d)
-
- ``finalize`` should carry out any final operations on the `Hash`;
- after a call to finalize, no more data can be written. Additionally,
- it transfers out the resulting hash into its argument.
-
- Note that this library does not allocate memory, and therefore the
- caller *must* ensure that ``d`` is a valid buffer containing at least
- ``this->size()`` bytes.
-
-.. cpp:function:: emsha::EMSHA_RESULT result(uint8_t *d)
-
- ``result`` is used to transfer out the hash to the argument. This implies
- that the `Hash` must keep enough state for repeated calls to ``result``
- to work.
-
-.. cpp:function:: uint32_t size(void)
-
- ``size`` should return the output size of the `Hash`; this is, how large
- the buffers written to by ``result`` should be.
-
diff --git a/doc/source/header.rst.in b/doc/source/header.rst.in
deleted file mode 100644
index a3704ed..0000000
--- a/doc/source/header.rst.in
+++ /dev/null
@@ -1,24 +0,0 @@
-========
-libemsha
-========
-
-Version: @PACKAGE_VERSION@
-
-Date: @BUILD_DATE@
-
-
------------------
-Table of Contents
------------------
-
-+ Introduction
-+ Getting and Building the Source
-+ Library Overview
-+ The Hash interface
-+ The SHA256 class
-+ The HMAC class
-+ Miscellaneous functions
-+ Test Programs
-+ References
-
-
diff --git a/doc/source/hmac.rst b/doc/source/hmac.rst
deleted file mode 100644
index 615a2df..0000000
--- a/doc/source/hmac.rst
+++ /dev/null
@@ -1,113 +0,0 @@
---------------
-The HMAC class
---------------
-
-
-.. cpp:class:: emsha::HMAC
-
- HMAC is an implementation of the :cpp:class:`emsha::Hash` interface
- implementing the HMAC keyed-hash message authentication code as
- defined in FIPS 198-1, using SHA-256 internally.
-
-.. cpp:function:: HMAC::HMAC(const uint8_t *key, uint32_t keylen)
-
- An HMAC context must be initialised with a key.
-
-
-.. cpp:function:: HMAc::~HMAC()
-
- The HMAC destructor will attempt to wipe the key and reset the
- underlying SHA-256 context.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT HMAC::reset(void)
-
- reset clears the internal state of the `HMAC` context and returns
- it to its initial state. It should always return ``EMSHA_ROK``.
- This function will **not** wipe the key; an `HMAC` object that has
- `reset` called it can be used immediately after.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT HMAC::update(const uint8_t *m, uint32_t ml)
-
- update writes data into the context. While there is an upper limit on
- the size of data that the underlying SHA-256 context can operate on,
- this package is designed for small systems that will not approach
- that level of data (which is on the order of 2 exabytes), so it is
- not thought to be a concern.
-
- **Inputs**:
-
- + ``m``: a byte array containing the message to be written. It must
- not be NULL (unless the message length is zero).
-
- + ``ml``: the message length, in bytes.
-
- **Return values**:
-
- * ``EMSHA_NULLPTR`` is returned if ``m`` is NULL and ``ml`` is nonzero.
-
- * ``EMSHA_INVALID_STATE`` is returned if the `update` is called
- after a call to `finalize`.
-
- * ``SHA256_INPUT_TOO_LONG`` is returned if too much data has been
- written to the context.
-
- + ``EMSHA_ROK`` is returned if the data was successfully added to
- the HMAC context.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::finalize(uint8_t *d)
-
- ``finalize`` completes the digest. Once this method is called, the
- context cannot be updated unless the context is reset.
-
- **Inputs**:
-
- * d: a byte buffer that must be at least ``SHA256.size()`` in
- length.
-
- **Outputs**:
-
- * ``EMSHA_NULLPTR`` is returned if ``d`` is the null pointer.
-
- * ``EMSHA_INVALID_STATE`` is returned if the HMAC context is in
- an invalid state, such as if there were errors in previous
- updates.
-
- * ``EMSHA_ROK`` is returned if the context was successfully
- finalised and the digest copied to ``d``.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::result(uint8_t *d)
-
- ``result`` copies the result from the HMAC context into the
- buffer pointed to by ``d``, running finalize if needed. Once
- called, the context cannot be updated until the context is reset.
-
- **Inputs**:
-
- * ``d``: a byte buffer that must be at least ``HMAC.size()`` in
- length.
-
- **Outputs**:
-
- * ``EMSHA_NULLPTR`` is returned if ``d`` is the null pointer.
-
- * ``EMSHA_INVALID_STATE`` is returned if the HMAC context is in
- an invalid state, such as if there were errors in previous
- updates.
-
- * ``EMSHA_ROK`` is returned if the context was successfully
- finalised and the digest copied to ``d``.
-
-.. cpp:function:: uint32_t SHA256::size(void)
-
- ``size`` returns the output size of HMAC, e.g. the size that the
- buffers passed to ``finalize`` and ``result`` should be.
-
- **Outputs**:
-
- * a ``uint32_t`` representing the expected size of buffers passed
- to ``result`` and ``finalize``.
-
diff --git a/doc/source/index.rst b/doc/source/index.rst
deleted file mode 100644
index 3408366..0000000
--- a/doc/source/index.rst
+++ /dev/null
@@ -1,27 +0,0 @@
-.. libemsha documentation master file, created by
- sphinx-quickstart on Tue Dec 15 23:35:10 2015.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-
-libemsha
-========
-
-.. toctree::
- :maxdepth: 2
-
- intro
- building
- overview
- hash
- sha256
- hmac
- misc
- tests
- refs
-
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-
diff --git a/doc/source/intro.rst b/doc/source/intro.rst
deleted file mode 100644
index d269820..0000000
--- a/doc/source/intro.rst
+++ /dev/null
@@ -1,21 +0,0 @@
--------------
-Introduction
--------------
-
-This library is an MIT-licensed compact HMAC-SHA-256 C++11 library
-designed for embedded systems. It is built following the JPL `Power of
-Ten `_ rules.
-
-This library came about as a result of a need for a standalone
-SHA-256 library for an embedded system. The original goal was
-to implement a wrapper around the code extracted from `RFC 6234
-`_; instead a standalone
-implementation was decided on.
-
-Additional resources:
-
-+ `Github page `_
-+ `Travis CI status `_
-+ `Coverity Scan page `_
-
-
diff --git a/doc/source/misc.rst b/doc/source/misc.rst
deleted file mode 100644
index b526385..0000000
--- a/doc/source/misc.rst
+++ /dev/null
@@ -1,107 +0,0 @@
------------------------
-Miscellaneous functions
------------------------
-
-.. cpp:function:: emsha::EMSHA_RESULT sha256_self_test(void)
-
- If the library was `compiled with support for self tests
- <./building.html>`_ (the default), this function will run a few self
- tests on the SHA-256 functions to validate that they are working
- correctly.
-
- **Outputs**:
-
- * ``EMSHA_ROK`` if the self-test completed successfully.
-
- * ``EMSHA_TEST_FAILURE`` if the SHA-256 functions did not produce
- the expected value.
-
- * ``EMSHA_SELFTEST_DISABLED`` if the library was built without
- support for the self test.
-
- * If an error occurs in the SHA-256 code, the resulting error code
- will be returned.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT sha256_digest(const uint8_t *m, uint32_t ml, uint8_t *d)
-
- The ``sha256_digest`` function will compute the digest on the
- ``ml``-byte octet string stored in ``m``, returning the result
- in ``d``. This is a convenience function implemented as: ::
-
- EMSHA_RESULT
- sha256_digest(const uint8_t *m, uint32_t ml, uint8_t *d)
- {
- SHA256 h;
- EMSHA_RESULT ret;
-
- if (EMSHA_ROK != (ret = h.update(m, ml))) {
- return ret;
- }
-
- return h.finalize(d);
- }
-
-.. cpp:function:: emsha::EMSHA_RESULT compute_hmac(const uint8_t *k, uint32_t kl, const uint8_t *m, uint32_t ml, uint8_t *d)
-
- The ``compute_hmac`` function computes the MAC on the ``ml``-byte
- octet string stored in``m``, using the ``kl``-length key ``k``. The
- result is stored in ``d``. This is a convenience function implemented
- as: ::
-
- EMSHA_RESULT
- compute_hmac(const uint8_t *k, uint32_t kl, const uint8_t *m, uint32_t ml,
- uint8_t *d)
- {
- EMSHA_RESULT res;
- HMAC h(k, kl);
-
- res = h.update(m, ml);
- if (EMSHA_ROK != res) {
- return res;
- }
-
- res = h.result(d);
- if (EMSHA_ROK != res) {
- return res;
- }
-
- return res;
- }
-
-.. cpp:function:: bool hash_equal(const uint8_t *a, const uint8_t *b)
-
- ``hash_equal`` performs a constant-time comparison of the first
- ``emsha::SHA256_HASH_SIZE`` bytes in the two byte array arguments.
-
- **Inputs**:
-
- * ``a``, ``b``: byte arrays at least ``emsha::SHA256_HASH_SIZE``
- bytes in length.
-
- ** Outputs**:
-
- * true *iff* the first ``emsha::SHA256_HASH_SIZE`` bytes match in
- both arrays.
-
- * false otherwise.
-
-
-.. cpp:function:: void hexstring(uint8_t *dest, uint8_t *src, uint32_t srclen)
-
- **Note**: this function is only present if the library was
- `built with support <./building.html>`_ for the hexstring functionality.
-
- **Inputs**:
-
- * dest: a byte array that is 2 * ``srclen``.
-
- * src: a byte array containing the data to process.
-
- * srclen: the size of ``src``.
-
- **Outputs**:
-
- When the function returns, the hex-encoded string will be placed in
- ``dest``.
-
diff --git a/doc/source/overview.rst b/doc/source/overview.rst
deleted file mode 100644
index 35e17f0..0000000
--- a/doc/source/overview.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-----------------
-Library Overview
-----------------
-
-.. cpp:namespace:: emsha
-
-The package provides a pair of classes, :cpp:class:`SHA256` and
-:cpp:class:`HMAC`, that both satisfy a common interface :cpp:class:`Hash`. All
-functionality provided by this library is found under the ``emsha`` namespace.
-
-
-``EMSHA_RESULT``
-^^^^^^^^^^^^^^^^^
-
-The ``EMSHA_RESULT`` enum is used to convey the result of an
-operation. The possible values are:
-
-.. cpp:enum:: _EMSHA_RESULT_ : uint8_t
-
-::
-
- // All operations have completed successfully so far.
- EMSHA_ROK = 0,
-
- // A self test or unit test failed.
- EMSHA_TEST_FAILURE = 1,
-
- // A null pointer was passed in as a buffer where it
- // shouldn't have been.
- EMSHA_NULLPTR = 2,
-
- // The Hash is in an invalid state.
- EMSHA_INVALID_STATE = 3,
-
- // The input to SHA256::update is too large.
- SHA256_INPUT_TOO_LONG = 4,
-
- // The self tests have been disabled, but a self test
- // function was called.
- EMSHA_SELFTEST_DISABLED = 5
-
-As a convenience, the following ``typedef`` is also provided.
-
- ``typedef enum _EMSHA_RESULT_`` :cpp:type:`EMSHA_RESULT`
-
-
diff --git a/doc/source/refs.rst b/doc/source/refs.rst
deleted file mode 100644
index a696dde..0000000
--- a/doc/source/refs.rst
+++ /dev/null
@@ -1,17 +0,0 @@
-----------
-References
-----------
-
-* `FIPS 180-4, the Secure Hash Standard `_
-* `FIPS 198-1, The Keyed-Hash Message Authentication Code (HMAC) `_
-* `RFC 2014, HMAC: Keyed-Hashing for Message Authentication `_
-* `RFC 6234, US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF) `_\ [#f1]_
-* The behaviour of this package was cross-checked using the Go 1.5.1
- linux/amd64 standard library's `crypto/sha256 `_
- package.
-
-.. rubric:: Footnotes
-
-.. [#f1] This library came about after extracting the relevant C code
- from RFC 6234, and needing a C++ version. It draws heavy
- inspiration from that code base.
diff --git a/doc/source/sha256.rst b/doc/source/sha256.rst
deleted file mode 100644
index 5d65b4f..0000000
--- a/doc/source/sha256.rst
+++ /dev/null
@@ -1,112 +0,0 @@
------------------
-The SHA256 class
------------------
-
-.. cpp:class:: emsha::SHA256
-
- SHA256 is an implementation of the :cpp:class:`emsha::Hash` interface
- implementing the SHA-256 cryptographic hash algorithm
-
-.. cpp:function:: SHA256::SHA256()
-
- A SHA256 context does not need any special construction. It can be
- declared and immediately start being used.
-
-
-.. cpp:function:: SHA256::~SHA256()
-
- The SHA256 destructor will clear out its internal message buffer;
- all of the members are local and not resource handles, so cleanup
- is minimal.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::reset(void)
-
- reset clears the internal state of the `SHA256` context and returns
- it to its initial state. It should always return ``EMSHA_ROK``.
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::update(const uint8_t *m, uint32_t ml)
-
- update writes data into the context. While there is an upper limit
- on the size of data that SHA-256 can operate on, this package is
- designed for small systems that will not approach that level of
- data (which is on the order of 2 exabytes), so it is not thought to
- be a concern.
-
- **Inputs**:
-
- + ``m``: a byte array containing the message to be written. It must
- not be NULL (unless the message length is zero).
-
- + ``ml``: the message length, in bytes.
-
- **Return values**:
-
- * ``EMSHA_NULLPTR`` is returned if ``m`` is NULL and ``ml`` is nonzero.
-
- * ``EMSHA_INVALID_STATE`` is returned if the `update` is called
- after a call to `finalize`.
-
- * ``SHA256_INPUT_TOO_LONG`` is returned if too much data has been
- written to the context.
-
- + ``EMSHA_ROK`` is returned if the data was successfully added to
- the SHA-256 context.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::finalize(uint8_t *d)
-
- ``finalize`` completes the digest. Once this method is called, the
- context cannot be updated unless the context is reset.
-
- **Inputs**:
-
- * d: a byte buffer that must be at least ``SHA256.size()`` in
- length.
-
- **Outputs**:
-
- * ``EMSHA_NULLPTR`` is returned if ``d`` is the null pointer.
-
- * ``EMSHA_INVALID_STATE`` is returned if the SHA-256 context is in
- an invalid state, such as if there were errors in previous
- updates.
-
- * ``EMSHA_ROK`` is returned if the context was successfully
- finalised and the digest copied to ``d``.
-
-
-.. cpp:function:: emsha::EMSHA_RESULT SHA256::result(uint8_t *d)
-
- ``result`` copies the result from the SHA-256 context into the
- buffer pointed to by ``d``, running finalize if needed. Once
- called, the context cannot be updated until the context is reset.
-
- **Inputs**:
-
- * ``d``: a byte buffer that must be at least ``SHA256.size()`` in
- length.
-
- **Outputs**:
-
- * ``EMSHA_NULLPTR`` is returned if ``d`` is the null pointer.
-
- * ``EMSHA_INVALID_STATE`` is returned if the SHA-256 context is in
- an invalid state, such as if there were errors in previous
- updates.
-
- * ``EMSHA_ROK`` is returned if the context was successfully
- finalised and the digest copied to ``d``.
-
-.. cpp:function:: uint32_t SHA256::size(void)
-
- ``size`` returns the output size of SHA256, e.g.
- the size that the buffers passed to ``finalize``
- and ``result`` should be.
-
- **Outputs**:
-
- * a ``uint32_t`` representing the expected size of buffers passed
- to ``result`` and ``finalize``.
-
-
diff --git a/doc/source/tests.rst b/doc/source/tests.rst
deleted file mode 100644
index 9a152a1..0000000
--- a/doc/source/tests.rst
+++ /dev/null
@@ -1,50 +0,0 @@
--------------
-Test Programs
--------------
-
-Running ``make check`` builds and runs the test programs. These are:
-
-* ``emsha_core_test`` runs the core tests.
-* ``emsha_sha256_test`` runs test vectors on the SHA-256 code.
-* ``emsha_hmac_test`` runs test vectors on the HMAC code.
-
-Additionally, the following test programs are built but not run. These
-programs do not link with the library as the above programs do; instead,
-they compile the object files in to avoid the libtool dance before the
-library is installed.
-
-* ``emsha_mem_test`` and ``emsha_static_mem_test`` are for memory
- profiling (e.g., with `Valgrind `_ during
- development.
-
-* ``emsha_static_sha256_test`` and ``emsha_static_hmac_test`` are used
- to facilitate testing and debugging the library. These programs run
- the same tests as the ``emsha_sha256_test`` and ``emsha_hmac_test``
- programs.
-
-
-Core Tests
-^^^^^^^^^^
-
-There are three tests run in the core tests: a hexstring test (if
-`support is built in <./building.html>`_) and the constant time
-check. The constant time test does not validate that the function
-is constant time, only that it correctly verifies that two byte
-arrays are equal.
-
-
-SHA-256 Tests
-^^^^^^^^^^^^^
-
-The SHA-256 checks take a number of test vectors from the Go standard
-library's SHA-256 library.
-
-
-HMAC Tests
-^^^^^^^^^^
-
-The HMAC checks apply the `RFC 4231 `_
-test vectors to the HMAC code.
-
-
-
diff --git a/docs/emsha.3.md b/docs/emsha.3.md
new file mode 100644
index 0000000..200bbd8
--- /dev/null
+++ b/docs/emsha.3.md
@@ -0,0 +1,25 @@
+libemsha(3) "@PROJECT_VERSION@"
+
+# Introduction
+
+This library is an MIT-licensed compact HMAC-SHA-256 C++11 library
+designed for embedded systems. It is built following the JPL Power of
+Ten rules.
+
+This library came about as a result of a need for a standalone SHA-256
+library for an embedded system. The original goal was to implement a
+wrapper around the code extracted from RFC 6234; instead a standalone
+implementation was decided on.
+
+# References
+
+- FIPS 180-4, the Secure Hash Standard: (http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf)
+- FIPS 198-1, The Keyed-Hash Message Authentication Code (HMAC): (http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf)
+- RFC 2014, HMAC: Keyed-Hashing for Message Authentication: (https://tools.ietf.org/html/rfc2104)
+- RFC 6234, US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF): (https://tools.ietf.org/html/rfc6234)
+- The Power of Ten – Rules for Developing Safety Critical Code: (http://spinroot.com/gerard/pdf/P10.pdf)
+
+# Validation
+
+- The behaviour of this package was cross-checked using the Go 1.5.1 linux/amd64 standard library\'s
+ crypto/sha256 package.
diff --git a/docs/libemsha.7.md b/docs/libemsha.7.md
new file mode 100644
index 0000000..31a11bd
--- /dev/null
+++ b/docs/libemsha.7.md
@@ -0,0 +1,13 @@
+@PROJECT_NAME@(7) "@PROJECT_VERSION@"
+
+# NAME
+
+# DESCRIPTION
+
+# DATA STRUCTURES
+
+# HEADER FILES
+
+# NOTES
+
+# SEE ALSO
diff --git a/docs/mainpage.md b/docs/mainpage.md
new file mode 100644
index 0000000..12194cd
--- /dev/null
+++ b/docs/mainpage.md
@@ -0,0 +1,198 @@
+# libemsha
+
+Version: 1.0.2
+
+Date: 2016-01-28
+
+## Table of Contents
+
+- Introduction
+- Getting and Building the Source
+- Library Overview
+- The Hash interface
+- The SHA256 class
+- The HMAC class
+- Miscellaneous functions
+- Test Programs
+- References
+
+## Introduction
+
+This library is an MIT-licensed compact HMAC-SHA-256 C++11 library
+designed for embedded systems. It is built following the JPL [Power of
+Ten](http://spinroot.com/gerard/pdf/P10.pdf) rules.
+
+This library came about as a result of a need for a standalone SHA-256
+library for an embedded system. The original goal was to implement a
+wrapper around the code extracted from [RFC
+6234](https://tools.ietf.org/html/rfc6234); instead a standalone
+implementation was decided on.
+
+Additional resources:
+
+- [Github page](https://github.com/kisom/libemsha)
+- [Travis CI status](https://travis-ci.org/kisom/libemsha/)
+- [Coverity Scan page](https://scan.coverity.com/projects/libemsha-52f2a5fd-e759-43c2-9073-cf6c2ed9abdb)
+
+## Getting and Building the Source
+
+The source code is available via
+[Github](https://github.com/kisom/libemsha/); each version should be git
+tagged. :
+
+ git clone https://github.com/kisom/libemsha
+ git clone git@github.com:kisom/libemsha
+
+The current release is
+[1.0.0](https://github.com/kisom/libemsha/archive/1.0.0.zip).
+
+The project is built using Autotools and `make`.
+
+When building from a git checkout, the [autobuild]{.title-ref} script
+will bootstrap the project from the autotools sources (e.g. via
+`autoreconf -i`), run `configurei` (by default to use clang), and
+attempt to build the library and run the unit tests.
+
+Once the autotools infrastructure has been bootstrapped, the following
+should work: :
+
+ ./configure && make && make check && make install
+
+There are three flags to `configure` that might be useful:
+
+- `--disable-hexstring` disables the provided `hexstring` function;
+ while this might be useful in many cases, it also adds extra size to
+ the code.
+- `--disable-hexlut` disables the larger lookup table used by
+ `hexstring`, which can save around a kilobyte of program space. If
+ the `hexstring` function is disabled, this option has no effect.
+- `--disable-selftest` disables the internal self-tests, which can
+ reclaim some additional program space.
+
+## Library Overview
+
+The package provides a pair of classes, :cpp`SHA256`{.interpreted-text
+role="class"} and :cpp`HMAC`{.interpreted-text role="class"}, that both
+satisfy a common interface :cpp`Hash`{.interpreted-text role="class"}.
+All functionality provided by this library is found under the `emsha`
+namespace.
+
+### `EMSHA_RESULT`
+
+The `EMSHA_RESULT` enum is used to convey the result of an operation.
+The possible values are:
+
+ // All operations have completed successfully so far.
+ EMSHA_ROK = 0,
+
+ // A self test or unit test failed.
+ EMSHA_TEST_FAILURE = 1,
+
+ // A null pointer was passed in as a buffer where it
+ // shouldn't have been.
+ EMSHA_NULLPTR = 2,
+
+ // The Hash is in an invalid state.
+ EMSHA_INVALID_STATE = 3,
+
+ // The input to SHA256::update is too large.
+ SHA256_INPUT_TOO_LONG = 4,
+
+ // The self tests have been disabled, but a self test
+ // function was called.
+ EMSHA_SELFTEST_DISABLED = 5
+
+As a convenience, the following `typedef` is also provided.
+
+> `typedef enum _EMSHA_RESULT_` :cpp`EMSHA_RESULT`{.interpreted-text
+> role="type"}
+
+## The Hash interface
+
+In general, a [Hash]{.title-ref} is used along the lines of: :
+
+ emsha::EMSHA_RESULT
+ hash_single_pass(uint8_t *m, uint32_t ml, uint8_t *digest)
+ {
+ // Depending on the implementation, the constructor may need
+ // arguments.
+ emsha::Hash h;
+ emsha::EMSHA_RESULT res;
+
+ res = h.write(m, ml);
+ if (emsha::EMSHA_ROK != res) {
+ return res;
+ }
+
+ // digest will contain the output of the Hash, and the
+ // caller MUST ensure that there is enough space in
+ // the buffer.
+ return h.result(d);
+ }
+
+### Methods
+
+## The SHA256 class
+
+## The HMAC class
+
+## Miscellaneous functions
+
+## Test Programs
+
+Running `make check` builds and runs the test programs. These are:
+
+- `emsha_core_test` runs the core tests.
+- `emsha_sha256_test` runs test vectors on the SHA-256 code.
+- `emsha_hmac_test` runs test vectors on the HMAC code.
+
+Additionally, the following test programs are built but not run. These
+programs do not link with the library as the above programs do; instead,
+they compile the object files in to avoid the libtool dance before the
+library is installed.
+
+- `emsha_mem_test` and `emsha_static_mem_test` are for memory
+ profiling (e.g., with [Valgrind](http://valgrind.org/) during
+ development.
+- `emsha_static_sha256_test` and `emsha_static_hmac_test` are used to
+ facilitate testing and debugging the library. These programs run the
+ same tests as the `emsha_sha256_test` and `emsha_hmac_test`
+ programs.
+
+### Core Tests
+
+There are three tests run in the core tests: a hexstring test (if
+[support is built in](./building.html)) and the constant time check. The
+constant time test does not validate that the function is constant time,
+only that it correctly verifies that two byte arrays are equal.
+
+### SHA-256 Tests
+
+The SHA-256 checks take a number of test vectors from the Go standard
+library\'s SHA-256 library.
+
+### HMAC Tests
+
+The HMAC checks apply the [RFC 4231](http://tools.ietf.org/html/rfc4231)
+test vectors to the HMAC code.
+
+## References
+
+- [FIPS 180-4, the Secure Hash
+ Standard](http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf)
+- [FIPS 198-1, The Keyed-Hash Message Authentication Code
+ (HMAC)](http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf)
+- [RFC 2014, HMAC: Keyed-Hashing for Message
+ Authentication](https://tools.ietf.org/html/rfc2104)
+- [RFC 6234, US Secure Hash Algorithms (SHA and SHA-based HMAC and
+ HKDF)](https://tools.ietf.org/html/rfc6234)[^1]
+- The behaviour of this package was cross-checked using the Go 1.5.1
+ linux/amd64 standard library\'s
+ [crypto/sha256](https://golang.org/src/crypto/sha256/) package.
+
+**Footnotes**
+
+[^1]:
+ This library came about after extracting the relevant C code from
+ RFC 6234, and needing a C++ version. It draws heavy inspiration from
+ that code base.
diff --git a/src/emsha.cc b/emsha.cc
similarity index 89%
rename from src/emsha.cc
rename to emsha.cc
index dfccdcf..b590b07 100644
--- a/src/emsha.cc
+++ b/emsha.cc
@@ -28,31 +28,23 @@
#include
#include
-#include
+#include
using std::uint8_t;
using std::uint32_t;
-using std::cout;
-using std::endl;
namespace emsha {
-Hash::~Hash()
-{
- // Nothing to see here.
-}
-
-
bool
-hash_equal(const uint8_t *a, const uint8_t *b)
+HashEqual(const uint8_t *a, const uint8_t *b)
{
uint8_t res = 0;
- EMSHA_CHECK(a != NULL, false);
- EMSHA_CHECK(b != NULL, false);
+ EMSHA_CHECK(a != nullptr, false);
+ EMSHA_CHECK(b != nullptr, false);
for (uint32_t i = 0; i < SHA256_HASH_SIZE; i++) {
res += a[i] ^ b[i];
@@ -67,7 +59,7 @@ hash_equal(const uint8_t *a, const uint8_t *b)
// If using a lookup table is permitted, then the faster way to do this
// is to use one.
static void
-write_hex_char(uint8_t *dest, uint8_t src)
+writeHexChar(uint8_t *dest, uint8_t src)
{
static constexpr uint8_t lut[256][3] = {
"00", "01", "02", "03", "04", "05", "06", "07",
@@ -108,13 +100,14 @@ write_hex_char(uint8_t *dest, uint8_t src)
*(dest + 1) = lut[src][1];
}
+
#else // #ifndef EMSHA_NO_HEXLUT
// If the full lookup table can't be used, e.g. because MSP430-level
// memory constraints, we'll work around this using a small (16-byte)
// lookup table and some bit shifting. On platforms where even this is
-// too much, the hexstring functionality will just be disabled.
+// too much, the HexString functionality will just be disabled.
static void
-write_hex_char(uint8_t *dest, uint8_t src)
+writeHexChar(uint8_t *dest, uint8_t src)
{
static constexpr uint8_t lut[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
@@ -124,23 +117,21 @@ write_hex_char(uint8_t *dest, uint8_t src)
*dest = lut[((src & 0xF0) >> 4)];
*(dest + 1) = lut[(src & 0xF)];
}
-
#endif // #ifndef EMSHA_NO_HEXLUT
void
-hexstring(uint8_t *dest, uint8_t *src, uint32_t srclen)
+HexString(uint8_t *dest, uint8_t *src, uint32_t srclen)
{
- uint8_t *dp = dest;
+ size_t dp = 0;
for (uint32_t i = 0; i < srclen; i++) {
- write_hex_char(dp, src[i]);
+ writeHexChar(&dest[dp], src[i]);
dp += 2;
}
}
-
-
#endif // #ifndef EMSHA_NO_HEXSTRING
} // end of namespace emsha
+
diff --git a/emsha.pc.in b/emsha.pc.in
new file mode 100644
index 0000000..a231a47
--- /dev/null
+++ b/emsha.pc.in
@@ -0,0 +1,10 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=${prefix}/lib
+includedir=${prefix}/include
+
+Name: @PROJECT_NAME@
+Description: C++11 HMAC-SHA256 library
+URL: https://git.wntrmute.dev/kyle/emsha
+Version: @PROJECT_VERSION@
+Libs: -L${libdir} -lemsha
diff --git a/emsha/emsha.h b/emsha/emsha.h
new file mode 100644
index 0000000..5587ebb
--- /dev/null
+++ b/emsha/emsha.h
@@ -0,0 +1,170 @@
+///
+/// \file emsha/emsha.h
+/// \author K. Isom
+/// \date 2015-12-17
+/// \brief Declares an interface for an EMbedded Secure HAshing interface.
+///
+/// The MIT License (MIT)
+///
+/// Copyright (c) 2015 K. Isom
+///
+/// Permission is hereby granted, free of charge, to any person obtaining a copy
+/// copy of this software and associated documentation files (the "Software"),
+/// to deal in the Software without restriction, including without limitation
+/// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+/// and/or sell copies of the Software, and to permit persons to whom the
+/// Software is furnished to do so, subject to the following conditions:
+///
+/// The above copyright notice and this permission notice shall be included in
+/// all copies or substantial portions of the Software.
+///
+/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+/// IN THE SOFTWARE.
+///
+
+
+#ifndef EMSHA_EMSHA_H
+#define EMSHA_EMSHA_H
+
+
+#include
+
+
+// Emsha is an EMbedded Secure HAshing interface.
+namespace emsha {
+
+
+/// EMSHA_CHECK is used for sanity checks in certain parts of the code.
+#ifdef NDEBUG
+/// EMSHA_CHECK is used for sanity checks in certain parts of
+/// the code. If asserts are turned off, expand the check to an
+/// if statement that will return with retval if the condition
+/// isn't met.
+#define EMSHA_CHECK(condition, retval) if (!(condition)) { return (retval); }
+#else
+/// EMSHA_CHECK is used for sanity checks in certain parts of
+/// the code. If asserts are turned on, the check is expanded to
+/// an assertion that the condition holds. In this case, retval
+/// is not used.
+#define EMSHA_CHECK(condition, retval) (assert((condition)))
+#endif
+
+/// SHA256_HASH_SIZE is the output length of SHA-256 in bytes.
+const std::uint32_t SHA256_HASH_SIZE = 32;
+
+
+/// The EMSHA_RESULT type is used to indicate whether an
+/// operation succeeded, and if not, what the general fault type
+/// was.
+typedef enum _EMSHA_RESULT_ : std::uint8_t {
+ /// All operations have completed successfully so far.
+ EMSHA_ROK = 0,
+
+ /// A self test or unit test failed.
+ EMSHA_TEST_FAILURE = 1,
+
+ /// A null pointer was passed in as a buffer where it shouldn't
+ /// have been.
+ EMSHA_NULLPTR = 2,
+
+ /// The Hash is in an invalid state.
+ EMSHA_INVALID_STATE = 3,
+
+ /// The input to SHA256::update is too large.
+ SHA256_INPUT_TOO_LONG = 4,
+
+ /// The self tests have been disabled, but a self-test function
+ /// was called.
+ EMSHA_SELFTEST_DISABLED = 5
+} EMSHA_RESULT;
+
+
+// A Hash is generalised superclass supporting concrete classes
+// that produce digests of data.
+class Hash {
+public:
+ virtual ~Hash() = default;
+
+ /// Reset should bring the Hash back into its
+ /// initial state. That is, the idea is that
+ ///
+ /// hash->reset(); hash->update(...)... ;
+ /// hash->result(...) ;
+ ///
+ /// is idempotent, assuming the inputs to update
+ /// and result are constant. The implications of
+ /// this for a given concrete class should be
+ /// described in that class's documentation, but
+ /// in general, it has the effect of preserving
+ /// any initial state while removing any data
+ /// written to the Hash via the update method.
+ virtual EMSHA_RESULT Reset() = 0;
+
+ // Update is writes message data into the Hash.
+ virtual EMSHA_RESULT Update(const std::uint8_t *m,
+ std::uint32_t ml) = 0;
+
+ /// Finalise carries out any final operations
+ /// on the Hash; after a call to finalize, no
+ /// more data can be written. Additionally, it
+ /// transfers out the resulting hash into its
+ /// argument.
+ virtual EMSHA_RESULT Finalise(std::uint8_t *d) = 0;
+
+ /// Result transfers out the hash to the
+ /// argument. The Hash must keep enough state
+ /// for repeated calls to result to work.
+ virtual EMSHA_RESULT Result(std::uint8_t *d) = 0;
+
+ /// Size should return the output size of the
+ /// Hash; this is, how large the buffers written
+ /// to by result should be.
+ virtual std::uint32_t Size() = 0;
+};
+
+/// HashEqual provides a constant time function for comparing
+/// two hashes. The caller *must* ensure that both a and b are
+/// the same size. The recommended approach is to use fixed-size
+/// buffers of emsha::SHA256_HASH_SIZE length:
+///
+/// ```c++
+/// uint8_t expected[emsha::SHA256_HASH_SIZE];
+/// uint8_t actual[emsha::SHA256_HASH_SIZE];
+///
+/// // Fill in expected and actual using the Hash operations.
+///
+/// if (hash_equal(expected, actual)) {
+/// proceed();
+/// }
+/// ```
+///
+/// \param a A byte buffer of size Hash::Size().
+/// \param b A byte buffer of size Hash::Size().
+/// \return True if both byte arrays match.
+bool
+HashEqual(const std::uint8_t *a, const std::uint8_t *b);
+
+#ifndef EMSHA_NO_HEXSTRING
+/// HexString writes a hex-encoded version of the src byte
+/// array into dest. The caller *must* ensure that dest is
+/// srclen * 2 bytes or longer.
+///
+///
+/// \param dest The destination byte array at least (2*srclen)
+/// bytes in length.
+/// \param src A byte array containing the data to hexify..
+/// \param srclen The size in bytes of src.
+void
+HexString(std::uint8_t *dest, std::uint8_t *src, std::uint32_t srclen);
+#endif // EMSHA_NO_HEXSTRING
+
+
+} // end of namespace emsha
+
+
+#endif // EMSHA_EMSHA_H
diff --git a/emsha/hmac.h b/emsha/hmac.h
new file mode 100644
index 0000000..b8d540b
--- /dev/null
+++ b/emsha/hmac.h
@@ -0,0 +1,194 @@
+///
+/// \file emsha/hmac.h
+/// \author K. Isom
+/// \date 2015-12-17
+/// \brief Declares an interface for HMAC tagging.
+///
+/// The MIT License (MIT)
+///
+/// Copyright (c) 2015 K. Isom
+///
+/// Permission is hereby granted, free of charge, to any person obtaining a copy
+/// copy of this software and associated documentation files (the "Software"),
+/// to deal in the Software without restriction, including without limitation
+/// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+/// and/or sell copies of the Software, and to permit persons to whom the
+/// Software is furnished to do so, subject to the following conditions:
+///
+/// The above copyright notice and this permission notice shall be included in
+/// all copies or substantial portions of the Software.
+///
+/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+/// IN THE SOFTWARE.
+///
+
+#ifndef EMSHA_HMAC_H
+#define EMSHA_HMAC_H
+
+
+#include
+
+#include "emsha.h"
+#include "sha256.h"
+
+
+namespace emsha {
+
+const uint32_t HMAC_KEY_LENGTH = SHA256_MB_SIZE;
+
+/// HMAC is a keyed hash that can be used to produce an
+/// authenticated hash of some data. The HMAC is built on
+/// (and uses internally) the SHA-256 class; it's helpful to
+/// note that faults that occur in the SHA-256 code will be
+/// propagated up as the return value from many of the HMAC
+/// functions.
+class HMAC : Hash {
+public:
+ /// An HMAC is constructed with a key and the
+ /// length of the key. This key is stored in
+ /// the HMAC context, and is wiped by the HMAC
+ /// destructor.
+ ///
+ /// \param k The HMAC key.
+ /// \param kl THe length of the HMAC key.
+ HMAC(const uint8_t *k, uint32_t kl);
+
+ /// Reset clears any data written to the HMAC;
+ /// this is equivalent to constructing a new HMAC,
+ /// but it preserves the keys.
+ ///
+ /// \return EMSHA_ROK is returned if the reset
+ /// occurred without (detected) fault.
+ /// If a fault occurs with the under-
+ /// lying SHA-256 context, the error
+ /// code is returned.
+ EMSHA_RESULT Reset() override;
+
+ /// Update writes data into the context. While
+ /// there is an upper limit on the size of data
+ /// that the underlying hash can operate on,
+ /// this package is designed for small systems
+ /// that will not approach that level of data
+ /// (which is on the order of 2 exabytes), so it
+ /// is not thought to be a concern.
+ ///
+ /// \param m A byte array containing the message
+ /// to be written.
+ /// \param ml The message length, in bytes.
+ /// \return
+ /// - EMSHA_NULLPTR is returned if m is NULL and ml is
+ /// nonzero.
+ /// - EMSHA_INVALID_STATE is returned if the update
+ /// is called after a call to finalize.
+ /// - SHA256_INPUT_TOO_LONG is returned if too much
+ /// data has been written to the context.
+ /// - EMSHA_ROK is returned if the data was
+ /// successfully written into the HMAC context.
+ ///
+ EMSHA_RESULT Update(const uint8_t *, uint32_t) override;
+
+ // Finalise completes the HMAC computation. Once this
+ // method is called, the context cannot be updated
+ // unless the context is reset.
+ //
+ // Inputs:
+ // d: a byte buffer that must be at least
+ // HMAC.size() in length.
+ //
+ // Outputs:
+ // EMSHA_NULLPTR is returned if d is the null
+ // pointer.
+ //
+ // EMSHA_INVALID_STATE is returned if the HMAC
+ // context is in an invalid state, such as if there
+ // were errors in previous updates.
+ //
+ // EMSHA_ROK is returned if the context was
+ // successfully finalised and the digest copied to
+ // d.
+ //
+ EMSHA_RESULT Finalise(uint8_t *) override;
+
+ // Result copies the result from the HMAC context into
+ // the buffer pointed to by d, running finalize if
+ // needed. Once called, the context cannot be updated
+ // until the context is reset.
+ //
+ // Inputs:
+ // d: a byte buffer that must be at least
+ // HMAC.size() in length.
+ //
+ // Outputs:
+ // EMSHA_NULLPTR is returned if d is the null
+ // pointer.
+ //
+ // EMSHA_INVALID_STATE is returned if the HMAC
+ // context is in an invalid state, such as if there
+ // were errors in previous updates.
+ //
+ // EMSHA_ROK is returned if the context was
+ // successfully finalised and the digest copied to
+ // d.
+ //
+ EMSHA_RESULT Result(uint8_t *) override;
+
+
+ // size returns the output size of HMAC-SHA-256, e.g.
+ // the size that the buffers passed to finalize and
+ // result should be.
+ //
+ // Outputs:
+ // A uint32_t representing the expected size
+ // of buffers passed to result and finalize.
+ std::uint32_t Size() override;
+
+ // When an HMAC context is destroyed, it is reset and
+ // the key material is zeroised using the STL fill
+ // function.
+ ~HMAC(void);
+private:
+ uint8_t hstate;
+ SHA256 ctx;
+ uint8_t k[HMAC_KEY_LENGTH];
+ uint8_t buf[SHA256_HASH_SIZE];
+
+ EMSHA_RESULT reset();
+ inline EMSHA_RESULT
+ finalResult(uint8_t *d);
+};
+
+// compute_hmac performs a single-pass HMAC computation over
+// a message.
+//
+// Inputs:
+// k: a byte buffer containing the HMAC key.
+//
+// kl: the length of the HMAC key.
+//
+// m: the message data over which the HMAC is to be computed.
+//
+// ml: the length of the message.
+//
+// d: a byte buffer that will be used to store the resulting
+// HMAC. It should be SHA256_HASH_SIZE bytes in size.
+//
+// Outputs:
+// This function handles setting up the HMAC context with
+// the given key, calling update with the message data, and
+// then calling finalize to place the result in the output
+// buffer. Any of the faults that can occur in these functions
+// can be returned here, or EMSHA_ROK if the HMAC was
+// successfully computed.
+EMSHA_RESULT
+ComputeHMAC(const uint8_t *k, uint32_t kl,
+ const uint8_t *m, uint32_t ml,
+ uint8_t *d);
+} // end of namespace emsha
+
+
+#endif // EMSHA_HMAC_H
diff --git a/emsha/internal.h b/emsha/internal.h
new file mode 100644
index 0000000..5fd5bb3
--- /dev/null
+++ b/emsha/internal.h
@@ -0,0 +1,96 @@
+///
+/// \file emsha/internal.h
+/// \author K. Isom
+/// \date 2015-12-17
+/// \brief Declares internal interfaces for the emsha library.
+///
+/// The MIT License (MIT)
+///
+/// Copyright (c) 2015 K. Isom
+///
+/// Permission is hereby granted, free of charge, to any person obtaining a copy
+/// copy of this software and associated documentation files (the "Software"),
+/// to deal in the Software without restriction, including without limitation
+/// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+/// and/or sell copies of the Software, and to permit persons to whom the
+/// Software is furnished to do so, subject to the following conditions:
+///
+/// The above copyright notice and this permission notice shall be included in
+/// all copies or substantial portions of the Software.
+///
+/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+/// IN THE SOFTWARE.
+///
+
+#ifndef EMSHA_INTERNAL_H
+#define EMSHA_INTERNAL_H
+
+
+#include
+
+using std::uint8_t;
+using std::uint32_t;
+
+
+namespace emsha {
+
+
+static inline uint32_t
+rotr32(uint32_t x, uint8_t n)
+{
+ return ((x >> n) | (x << (32 - n)));
+}
+
+
+static inline uint32_t
+sha_ch(uint32_t x, uint32_t y, uint32_t z)
+{
+ return ((x & y) ^ ((~x) & z));
+}
+
+
+static inline uint32_t
+sha_maj(uint32_t x, uint32_t y, uint32_t z)
+{
+ return (x & y) ^ (x & z) ^ (y & z);
+}
+
+
+static inline uint32_t
+sha_Sigma0(uint32_t x)
+{
+ return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22);
+}
+
+
+static inline uint32_t
+sha_Sigma1(uint32_t x)
+{
+ return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25);
+}
+
+
+static inline uint32_t
+sha_sigma0(uint32_t x)
+{
+ return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >> 3);
+}
+
+
+static inline uint32_t
+sha_sigma1(uint32_t x)
+{
+ return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10);
+}
+
+
+
+} // end of namespace emsha
+
+
+#endif // EMSHA_INTERNAL_H
diff --git a/emsha/sha256.h b/emsha/sha256.h
new file mode 100644
index 0000000..e9e796d
--- /dev/null
+++ b/emsha/sha256.h
@@ -0,0 +1,218 @@
+///
+/// \file emsha/sha256.h
+/// \author K. Isom
+/// \date 2015-12-17
+/// \brief Declares an interface for producing SHA-256 hashes.
+///
+/// The MIT License (MIT)
+///
+/// Copyright (c) 2015 K. Isom
+///
+/// Permission is hereby granted, free of charge, to any person obtaining a copy
+/// copy of this software and associated documentation files (the "Software"),
+/// to deal in the Software without restriction, including without limitation
+/// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+/// and/or sell copies of the Software, and to permit persons to whom the
+/// Software is furnished to do so, subject to the following conditions:
+///
+/// The above copyright notice and this permission notice shall be included in
+/// all copies or substantial portions of the Software.
+///
+/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+/// IN THE SOFTWARE.
+///
+
+#ifndef EMSHA_SHA256_H
+#define EMSHA_SHA256_H
+
+
+#include
+
+#include
+
+
+namespace emsha {
+
+
+// SHA256_MB_SIZE is the size of a message block.
+const uint32_t SHA256_MB_SIZE = 64;
+
+class SHA256 : Hash {
+public:
+ // A SHA256 context does not need any special
+ // construction. It can be declared and
+ // immediately start being used.
+ SHA256();
+
+ // The SHA256 destructor will clear out its internal
+ // message buffer; all the members are local and
+ // not resource handles, so cleanup is minimal.
+ ~SHA256();
+
+ // reset clears the internal state of the SHA256
+ // context and returns it to its initial state.
+ // It should always return EMSHA_ROK.
+ EMSHA_RESULT Reset() override;
+
+ // update writes data into the context. While
+ // there is an upper limit on the size of data
+ // that SHA-256 can operate on, this package is
+ // designed for small systems that will not
+ // approach that level of data (which is on the
+ // order of 2 exabytes), so it is not thought
+ // to be a concern.
+ //
+ // Inputs:
+ // m: a byte array containing the message to
+ // be written. It must not be NULL (unless
+ // the message length is zero).
+ //
+ // ml: the message length, in bytes.
+ //
+ // Outputs:
+ // EMSHA_NULLPTR is returned if m is NULL
+ // and ml is nonzero.
+ //
+ // EMSHA_INVALID_STATE is returned if the
+ // update is called after a call to
+ // finalize.
+ //
+ // SHA256_INPUT_TOO_LONG is returned if too
+ // much data has been written to the
+ // context.
+ //
+ // EMSHA_ROK is returned if the data was
+ // successfully added to the SHA-256
+ // context.
+ //
+ EMSHA_RESULT Update(const uint8_t *m, uint32_t ml) override;
+
+ // Finalise completes the digest. Once this
+ // method is called, the context cannot be
+ // updated unless the context is reset.
+ //
+ // Inputs:
+ // d: a byte buffer that must be at least
+ // SHA256.size() in length.
+ //
+ // Outputs:
+ // EMSHA_NULLPTR is returned if d is the
+ // null pointer.
+ //
+ // EMSHA_INVALID_STATE is returned if the
+ // SHA-256 context is in an invalid state,
+ // such as if there were errors in previous
+ // updates.
+ //
+ // EMSHA_ROK is returned if the context was
+ // successfully finalised and the digest
+ // copied to d.
+ //
+ EMSHA_RESULT Finalise(uint8_t *d) override;
+
+ // result copies the result from the SHA-256
+ // context into the buffer pointed to by d,
+ // running Finalise if needed. Once called,
+ // the context cannot be updated until the
+ // context is reset.
+ //
+ // Inputs:
+ // d: a byte buffer that must be at least
+ // SHA256.size() in length.
+ //
+ // Outputs:
+ // EMSHA_NULLPTR is returned if d is the
+ // null pointer.
+ //
+ // EMSHA_INVALID_STATE is returned if the
+ // SHA-256 context is in an invalid state,
+ // such as if there were errors in previous
+ // updates.
+ //
+ // EMSHA_ROK is returned if the context was
+ // successfully finalised and the digest
+ // copied to d.
+ //
+ EMSHA_RESULT Result(uint8_t *d) override;
+
+ // size returns the output size of SHA256, e.g.
+ // the size that the buffers passed to finalize
+ // and result should be.
+ //
+ // Outputs:
+ // a uint32_t representing the expected size
+ // of buffers passed to result and finalize.
+ std::uint32_t Size() override;
+
+private:
+ // mlen stores the current message length.
+ uint64_t mlen;
+
+ // The intermediate hash is 8x 32-bit blocks.
+ uint32_t i_hash[8];
+
+ // hStatus is the hash status, and hComplete indicates
+ // whether the hash has been finalised.
+ EMSHA_RESULT hStatus;
+ uint8_t hComplete;
+
+ // mb is the message block, and mbi is the message
+ // block index.
+ uint8_t mbi;
+ uint8_t mb[SHA256_MB_SIZE];
+
+ inline EMSHA_RESULT addLength(const uint32_t);
+ inline void updateMessageBlock(void);
+ inline void padMessage(uint8_t pc);
+ EMSHA_RESULT reset();
+}; // end class SHA256
+
+// sha256Digest performs a single pass hashing of the message
+// passed in.
+//
+// Inputs:
+// m: byte buffer containing the message to hash.
+//
+// ml: the length of m.
+//
+// d: byte buffer that will be used to store the resulting
+// hash; it should have at least emsha::SHA256_HASH_SIZE
+// bytes available.
+//
+// Outputs:
+// This function handles setting up a SHA256 context, calling
+// update using the message data, and then calling finalize. Any
+// of the errors that can occur in those functions can be
+// returned here, or EMSHA_ROK if the digest was computed
+// successfully.
+//
+EMSHA_RESULT
+sha256Digest(const uint8_t *m, uint32_t ml, uint8_t *d);
+
+// sha256SelfTest runs through two test cases to ensure that the
+// SHA-256 functions are working correctly.
+//
+// Outputs:
+// EMSHA_ROK is returned if the self tests pass.
+//
+// EMSHA_SELFTEST_DISABLED is returned if the self tests
+// have been disabled (e.g., libemsha was compiled with the
+// EMSHA_NO_SELFTEST #define).
+//
+// If a fault occurred inside the SHA-256 code, the error
+// code from one of the update, finalize, result, or reset
+// methods is returned.
+//
+// If the fault is that the output does not match the test
+// vector, EMSHA_TEST_FAILURE is returned.
+EMSHA_RESULT
+sha256SelfTest(void);
+} // end of namespace emsha
+
+
+#endif // EMSHA_SHA256_H
diff --git a/src/hmac.cc b/hmac.cc
similarity index 77%
rename from src/hmac.cc
rename to hmac.cc
index 96d9477..7e8b347 100644
--- a/src/hmac.cc
+++ b/hmac.cc
@@ -28,31 +28,32 @@
#include
-#include
-#include
-#include
+#include
+#include
+#include
namespace emsha {
+
// These constants are used to keep track of the state of the HMAC.
-// HMAC is in a clean-slate state following a call to reset().
-constexpr uint8_t HMAC_INIT = 0;
+// HMAC is in a clean-slate state following a call to Reset().
+constexpr uint8_t HMAC_INIT = 0;
// The ipad constants have been XOR'd into the key and written to the
// SHA-256 context.
-constexpr uint8_t HMAC_IPAD = 1;
+constexpr uint8_t HMAC_IPAD = 1;
// The opad constants have been XOR'd into the key and written to the
// SHA-256 context.
-constexpr uint8_t HMAC_OPAD = 2;
+constexpr uint8_t HMAC_OPAD = 2;
// HMAC has been finalised
-constexpr uint8_t HMAC_FIN = 3;
+constexpr uint8_t HMAC_FIN = 3;
// HMAC is in an invalid state.
-constexpr uint8_t HMAC_INVALID = 4;
+constexpr uint8_t HMAC_INVALID = 4;
static constexpr uint8_t ipad = 0x36;
@@ -60,9 +61,9 @@ static constexpr uint8_t opad = 0x5c;
HMAC::HMAC(const uint8_t *ik, uint32_t ikl)
- :hstate(), ctx()
+ : hstate(HMAC_INIT), k{0}, buf{0}
{
- this->hstate = HMAC_INIT;
+
std::fill(this->k, this->k + emsha::HMAC_KEY_LENGTH, 0);
if (ikl < HMAC_KEY_LENGTH) {
@@ -71,9 +72,9 @@ HMAC::HMAC(const uint8_t *ik, uint32_t ikl)
this->k[ikl++] = 0;
}
} else if (ikl > HMAC_KEY_LENGTH) {
- this->ctx.update(ik, ikl);
- this->ctx.result(this->k);
- this->ctx.reset();
+ this->ctx.Update(ik, ikl);
+ this->ctx.Result(this->k);
+ this->ctx.Reset();
} else {
std::copy(ik, ik + ikl, this->k);
}
@@ -92,25 +93,32 @@ HMAC::~HMAC()
}
+EMSHA_RESULT
+HMAC::Reset()
+{
+ return this->reset();
+}
+
+
EMSHA_RESULT
HMAC::reset()
{
- EMSHA_RESULT res;
+ EMSHA_RESULT res;
// Following a reset, both SHA-256 contexts and result buffer should be
// zero'd out for a clean slate. The HMAC state should be reset
// accordingly.
- this->ctx.reset();
+ this->ctx.Reset();
std::fill(this->buf, this->buf + SHA256_HASH_SIZE, 0);
// Set up the k0 ⊕ ipad construction, and write it into the
// SHA-256 context.
- uint8_t key[HMAC_KEY_LENGTH];
+ uint8_t key[HMAC_KEY_LENGTH];
for (uint32_t i = 0; i < HMAC_KEY_LENGTH; i++) {
key[i] = this->k[i] ^ ipad;
}
- res = this->ctx.update(key, HMAC_KEY_LENGTH);
+ res = this->ctx.Update(key, HMAC_KEY_LENGTH);
if (EMSHA_ROK != res) {
this->hstate = HMAC_INVALID;
return res;
@@ -125,15 +133,16 @@ HMAC::reset()
EMSHA_RESULT
-HMAC::update(const uint8_t *m, uint32_t ml)
+HMAC::Update(const uint8_t *m, uint32_t ml)
{
- EMSHA_RESULT res;
- SHA256& hctx = this->ctx;
+ EMSHA_RESULT res;
+ SHA256 &hctx = this->ctx;
+ EMSHA_CHECK(m != nullptr, EMSHA_NULLPTR);
EMSHA_CHECK(HMAC_IPAD == this->hstate, EMSHA_INVALID_STATE);
// Write the message to the SHA-256 context.
- res = hctx.update(m, ml);
+ res = hctx.Update(m, ml);
if (EMSHA_ROK != res) {
this->hstate = HMAC_INVALID;
return res;
@@ -145,7 +154,7 @@ HMAC::update(const uint8_t *m, uint32_t ml)
inline EMSHA_RESULT
-HMAC::final_result(uint8_t *d)
+HMAC::finalResult(uint8_t *d)
{
if (nullptr == d) {
return EMSHA_NULLPTR;
@@ -160,11 +169,11 @@ HMAC::final_result(uint8_t *d)
EMSHA_CHECK(HMAC_IPAD == this->hstate, EMSHA_INVALID_STATE);
- EMSHA_RESULT res;
+ EMSHA_RESULT res;
// Use the result buffer as an intermediate buffer to store the result
// of the inner hash.
- res = this->ctx.result(this->buf);
+ res = this->ctx.Result(this->buf);
if (EMSHA_ROK != res) {
this->hstate = HMAC_INVALID;
return EMSHA_INVALID_STATE;
@@ -173,16 +182,16 @@ HMAC::final_result(uint8_t *d)
// The SHA-256 context needs to be reset so that it may be
// re-used for the outer digest.
- this->ctx.reset();
+ this->ctx.Reset();
// Set up the k0 ⊕ opad construction, and write it into the
// SHA-256 context.
- uint8_t key[HMAC_KEY_LENGTH];
+ uint8_t key[HMAC_KEY_LENGTH];
for (uint32_t i = 0; i < HMAC_KEY_LENGTH; i++) {
key[i] = this->k[i] ^ opad;
}
- res = this->ctx.update(key, HMAC_KEY_LENGTH);
+ res = this->ctx.Update(key, HMAC_KEY_LENGTH);
if (EMSHA_ROK != res) {
this->hstate = HMAC_INVALID;
return res;
@@ -193,14 +202,14 @@ HMAC::final_result(uint8_t *d)
std::fill(key, key + HMAC_KEY_LENGTH, 0);
// Write the inner hash result into the outer hash.
- res = this->ctx.update(this->buf, SHA256_HASH_SIZE);
+ res = this->ctx.Update(this->buf, SHA256_HASH_SIZE);
if (EMSHA_ROK != res) {
this->hstate = HMAC_INVALID;
return res;
}
// Write the outer hash result into the working buffer.
- res = this->ctx.finalize(this->buf);
+ res = this->ctx.Finalise(this->buf);
if (EMSHA_ROK != res) {
this->hstate = HMAC_INVALID;
return res;
@@ -214,32 +223,39 @@ HMAC::final_result(uint8_t *d)
EMSHA_RESULT
-HMAC::finalize(uint8_t *d)
+HMAC::Finalise(uint8_t *d)
{
- return this->final_result(d);
+ return this->finalResult(d);
}
EMSHA_RESULT
-HMAC::result(uint8_t *d)
+HMAC::Result(uint8_t *d)
{
- return this->final_result(d);
+ return this->finalResult(d);
+}
+
+
+std::uint32_t
+HMAC::Size()
+{
+ return SHA256_HASH_SIZE;
}
EMSHA_RESULT
-compute_hmac(const uint8_t *k, uint32_t kl, const uint8_t *m, uint32_t ml,
- uint8_t *d)
+ComputeHMAC(const uint8_t *k, uint32_t kl, const uint8_t *m, uint32_t ml,
+ uint8_t *d)
{
- EMSHA_RESULT res;
- HMAC h(k, kl);
+ EMSHA_RESULT res;
+ HMAC h(k, kl);
- res = h.update(m, ml);
+ res = h.Update(m, ml);
if (EMSHA_ROK != res) {
return res;
}
- res = h.result(d);
+ res = h.Result(d);
if (EMSHA_ROK != res) {
return res;
}
@@ -249,3 +265,4 @@ compute_hmac(const uint8_t *k, uint32_t kl, const uint8_t *m, uint32_t ml,
} // end of namespace emsha
+
diff --git a/scripts/check-code.sh b/scripts/check-code.sh
new file mode 100755
index 0000000..c0359d8
--- /dev/null
+++ b/scripts/check-code.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env sh
+
+######################################################################
+# @author : kyle (kyle@midgard)
+# @file : check-code
+# @created : Tuesday Oct 17, 2023 22:39:39 PDT
+#
+# @description :
+######################################################################
+
+
+run_clang_tidy () {
+ sources="${1:-*.cc}"
+ echo "[+] clang-tidy ${sources}"
+
+ if [ ! -e compile_commands.json ]
+ then
+ echo "[!] compile_commands.json not found" > /dev/stderr
+ candidate=$(find -name compile_commands.json | head)
+
+ if [ -z "${candidates}" ]
+ then
+ echo "[!] no suitable candidates found; can't proceed" > /dev/stderr
+ exit 1
+ fi
+
+ echo "[+] compile_commands.json candidate: $candidate"
+ ln -s ${candidate} .
+ echo "[+] if this isn't correct, you will need to manually link it"
+ fi
+
+ clang-tidy ${sources}
+}
+
+
+run_cppcheck () {
+ sources="${1:-*.cc}"
+ echo "[+] cppcheck ${sources}"
+
+ cppcheck --enable=all --suppress=unusedFunction --suppress=missingIncludeSystem -I. ${sources}
+}
+
+
+run_trunk () {
+ sources="${1:-}"
+ echo "[+] trunk check ${sources}"
+
+ trunk check --filter clang-tidy ${sources}
+}
+
+
+main () {
+ command="${1:-usage}"
+ shift
+
+ case ${command} in
+ clang-tidy) run_clang_tidy $@ ;;
+ cppcheck) run_cppcheck $@ ;;
+ trunk) run_trunk $@ ;;
+ *)
+ echo "[!] scanner ${command} isn't supported" > /dev/stderr
+ exit 1
+ ;;
+ esac
+}
+
+main $@
+
diff --git a/scripts/install-cmake-debian.sh b/scripts/install-cmake-debian.sh
new file mode 100755
index 0000000..1b4bd5c
--- /dev/null
+++ b/scripts/install-cmake-debian.sh
@@ -0,0 +1,42 @@
+#!/usr/bin/env bash
+
+set -eu
+
+
+source /etc/lsb-release
+
+preinstall () {
+ echo "[+] preparing to install"
+ sudo apt-get update
+ sudo apt-get install ca-certificates gpg wget
+}
+
+do_install () {
+ if [ ! -f /etc/apt/sources.list.d/kitware.list ]
+ then
+ echo "[+] fetching initial keyring"
+ wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
+
+ echo "[+] adding repo to sources.list.d"
+ echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ ${DISTRIB_CODENAME} main" | \
+ sudo tee /etc/apt/sources.list.d/kitware.list >/dev/null
+ sudo apt-get update
+
+ echo "[+] installing kitware keyring"
+ if [ -f "/usr/share/keyrings/kitware-archive-keyring.gpg" ]
+ then
+ sudo rm /usr/share/keyrings/kitware-archive-keyring.gpg
+ fi
+ sudo apt-get install kitware-archive-keyring
+ fi
+
+ if [ "${USE_CMAKE_RC}" = "YES" ]
+ then
+ echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ ${DISTRIB_RELEASE}-rc main' | \
+ sudo tee -a /etc/apt/sources.list.d/kitware.list >/dev/null
+ sudo apt-get update
+ fi
+}
+
+do_install
+sudo apt-get install cmake
diff --git a/scripts/install-depdendencies.sh b/scripts/install-depdendencies.sh
new file mode 100755
index 0000000..3aa7684
--- /dev/null
+++ b/scripts/install-depdendencies.sh
@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+
+#####################################################################
+# This script attempts to install the appopriate build dependencies #
+# for the host system. #
+# #
+# This is primarily developed on the latest Ubuntu LTS release and #
+# MacOS; other platforms are not supported. #
+#####################################################################
+
+set -eu
+
+AUTOMATED_MODE=${AUTOMATED_MODE:-}
+
+install_debianesque () {
+ APTARGS=""
+
+ if [ ! -z "${AUTOMATED_MODE}" ]
+ then
+ APTARGS="-y"
+ fi
+
+ echo "[+] distribution is ${DISTRIB_ID}, choosing Debianesque install."
+
+ if [ -z "$(command -v cmake)" ]
+ then
+ ./scripts/install-cmake-debian.sh
+
+ echo "[+] installing tools"
+ sudo apt-get $APTARGS install git cmake clang scdoc python3-pip
+
+ ( cd docs/ && python3 -m pip install -r requirements.txt )
+}
+
+install_unsupported () {
+ echo "[+] distribution is ${DISTRIB_ID}, choosing Redhat install."
+ echo "[!] This distribution is unsupported." > /dev/stderr
+ exit 1;
+}
+
+install_macos () {
+ # TODO: consider supporting macports?
+ echo "[+] host system is MacOS"
+
+ echo "[+] installing tools"
+ brew install git cmake scdoc
+
+ echo "[+] installing libraries and development headers"
+ # TODO: look up proper package names in homebrew
+}
+
+
+install_linux () {
+ echo "[+] host system is Linux"
+ [[ -f "/etc/lsb-release" ]] && source /etc/lsb-release
+ if [ -z "${DISTRIB_ID}" ]
+ then
+ if [ -d /etc/apt ]
+ then
+ DISTRIB_ID="apt-based"
+ else
+ DISTRIB_ID="unsupported/unknown"
+ fi
+ fi
+
+ case ${DISTRIB_ID} in
+ Ubuntu) install_debianesque ;;
+ Debian) install_debianesque ;;
+ apt-based) install_debianesque ;;
+ *)
+ echo "[!] distribution ${DISTRIB_ID} isn't supported in this script." > /dev/null
+ ;;
+ esac
+}
+
+
+case "$(uname -s)" in
+ Linux) install_linux ;;
+ Darwin) install_macos ;;
+ *)
+ echo "[!] platform $(uname -s) isn't supported in this script." > /dev/null
+ ;;
+esac
+
+
diff --git a/sha256.cc b/sha256.cc
new file mode 100644
index 0000000..5612dab
--- /dev/null
+++ b/sha256.cc
@@ -0,0 +1,493 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 K. Isom
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+
+namespace emsha {
+
+
+/*
+ * SHA-256 constants, from FIPS 180-4 page 11.
+ */
+static constexpr uint32_t sha256K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+
+/*
+ * SHA-256 initialisation vector, from FIPS 180-4 page 15.
+ */
+static constexpr uint32_t emsha256H0[] = {
+ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
+ 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
+};
+
+
+EMSHA_RESULT
+sha256Digest(const uint8_t *m, uint32_t ml, uint8_t *d)
+{
+ SHA256 h;
+ EMSHA_RESULT ret;
+
+ if (EMSHA_ROK != (ret = h.Update(m, ml))) {
+ return ret;
+ }
+
+ return h.Finalise(d);
+}
+
+
+SHA256::SHA256()
+ : mlen(), hStatus(), hComplete(), mbi()
+{
+ this->reset();
+}
+
+
+SHA256::~SHA256()
+{
+ memset(this->mb, 0, SHA256_MB_SIZE);
+}
+
+
+EMSHA_RESULT
+SHA256::addLength(const uint32_t l)
+{
+ uint32_t tmp = this->mlen + l;
+
+ if (tmp < this->mlen) {
+ return SHA256_INPUT_TOO_LONG;
+ }
+
+ this->mlen = tmp;
+ assert(this->mlen > 0);
+
+ return EMSHA_ROK;
+}
+
+
+EMSHA_RESULT
+SHA256::Reset()
+{
+ return this->reset();
+}
+
+EMSHA_RESULT
+SHA256::reset()
+{
+ // The message block is set to the initial hash vector.
+ this->i_hash[0] = emsha256H0[0];
+ this->i_hash[1] = emsha256H0[1];
+ this->i_hash[2] = emsha256H0[2];
+ this->i_hash[3] = emsha256H0[3];
+ this->i_hash[4] = emsha256H0[4];
+ this->i_hash[5] = emsha256H0[5];
+ this->i_hash[6] = emsha256H0[6];
+ this->i_hash[7] = emsha256H0[7];
+
+ this->mbi = 0;
+ this->hStatus = EMSHA_ROK;
+ this->hComplete = 0;
+ this->mlen = 0;
+ memset(this->mb, 0, SHA256_MB_SIZE);
+
+ return this->hStatus;
+}
+
+
+// Read 32 bits from the byte buffer chunk as an unsigned 32-bit integer.
+static uint32_t
+chunkToUint32(const uint8_t *chunk)
+{
+ return ((*chunk) << 24) |
+ ((*(chunk + 1)) << 16) |
+ ((*(chunk + 2)) << 8) |
+ (*(chunk + 3));
+}
+
+
+// Copy an unsigned 32-bit integer into the start of the byte buffer chunk.
+static void
+uint32ToChunk(uint32_t x, uint8_t *chunk)
+{
+ chunk[0] = (x & 0xff000000) >> 24;
+ chunk[1] = (x & 0x00ff0000) >> 16;
+ chunk[2] = (x & 0x0000ff00) >> 8;
+ chunk[3] = (x & 0x000000ff);
+}
+
+
+// FIPS 180-4, page 22.
+void
+SHA256::updateMessageBlock()
+{
+ uint32_t w[64];
+ uint32_t i = 0;
+ uint32_t chunk = 0;
+ uint32_t a = 0;
+ uint32_t b = 0;
+ uint32_t c = 0;
+ uint32_t d = 0;
+ uint32_t e = 0;
+ uint32_t f = 0;
+ uint32_t g = 0;
+ uint32_t h = 0;
+
+ while (i < 16) {
+ w[i++] = chunkToUint32(this->mb + chunk);
+ chunk += 4;
+ }
+ this->mbi = 0;
+
+ for (i = 16; i < 64; i++) {
+ w[i] = sha_sigma1(w[i - 2]) + w[i - 7] +
+ sha_sigma0(w[i - 15]) + w[i - 16];
+ }
+
+ a = this->i_hash[0];
+ b = this->i_hash[1];
+ c = this->i_hash[2];
+ d = this->i_hash[3];
+ e = this->i_hash[4];
+ f = this->i_hash[5];
+ g = this->i_hash[6];
+ h = this->i_hash[7];
+
+ for (i = 0; i < 64; i++) {
+ uint32_t t1 = 0;
+ uint32_t t2 = 0;
+ t1 = h + sha_Sigma1(e) + sha_ch(e, f, g) + sha256K[i] + w[i];
+ t2 = sha_Sigma0(a) + sha_maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + t1;
+ d = c;
+ c = b;
+ b = a;
+ a = t1 + t2;
+ }
+
+ this->i_hash[0] += a;
+ this->i_hash[1] += b;
+ this->i_hash[2] += c;
+ this->i_hash[3] += d;
+ this->i_hash[4] += e;
+ this->i_hash[5] += f;
+ this->i_hash[6] += g;
+ this->i_hash[7] += h;
+}
+
+
+EMSHA_RESULT
+SHA256::Update(const uint8_t *m, uint32_t ml)
+{
+ // Checking invariants:
+ // If the message length is zero, there's nothing to be done.
+ if (0 == ml) { return EMSHA_ROK; }
+
+ // The message passed in cannot be the null pointer if the
+ // message length is greater than 0.
+ if (nullptr == m) { return EMSHA_NULLPTR; }
+
+ // If the SHA256 object is in a bad state, don't proceed.
+ if (EMSHA_ROK != this->hStatus) { return this->hStatus; }
+
+ // If the hash has been finalised, don't proceed.
+ if (0 != this->hComplete) { return EMSHA_INVALID_STATE; }
+ // Invariants satisfied by here.
+
+ for (uint32_t i = 0; i < ml; i++) {
+ this->mb[this->mbi] = *(m + i);
+ mbi++;
+
+ if (EMSHA_ROK == this->addLength(8)) {
+ if (SHA256_MB_SIZE == this->mbi) {
+ this->updateMessageBlock();
+
+ // Assumption: following the message block
+ // write, the context should still be in a good
+ // state.
+ assert(EMSHA_ROK == this->hStatus);
+ }
+ }
+ }
+
+ return this->hStatus;
+}
+
+
+inline void
+SHA256::padMessage(uint8_t pc)
+{
+ // Assumption: the context is not in a corrupted state.
+ assert(EMSHA_ROK == this->hStatus);
+
+ if (this->mbi < (SHA256_MB_SIZE - 8)) {
+ this->mb[this->mbi++] = pc;
+ } else {
+ bool pc_add = false;
+
+ if (this->mbi < SHA256_MB_SIZE - 1) {
+ this->mb[this->mbi++] = pc;
+ pc_add = true;
+ }
+
+ while (this->mbi < SHA256_MB_SIZE) {
+ this->mb[this->mbi++] = 0;
+ }
+
+ this->updateMessageBlock();
+ if (!pc_add) {
+ this->mb[this->mbi++] = pc;
+ }
+
+ // Assumption: updating the message block has not left the
+ // context in a corrupted state.
+ assert(EMSHA_ROK == this->hStatus);
+ }
+
+ while (this->mbi < (SHA256_MB_SIZE - 8)) {
+ this->mb[this->mbi++] = 0;
+ }
+
+ // lstart marks the starting point for the length packing.
+ uint32_t const lstart = SHA256_MB_SIZE - 8;
+
+ this->mb[lstart] = static_cast(this->mlen >> 56);
+ this->mb[lstart + 1] =
+ static_cast((this->mlen & 0x00ff000000000000L) >> 48);
+ this->mb[lstart + 2] =
+ static_cast((this->mlen & 0x0000ff0000000000L) >> 40);
+ this->mb[lstart + 3] =
+ static_cast((this->mlen & 0x000000ff00000000L) >> 32);
+ this->mb[lstart + 4] =
+ static_cast((this->mlen & 0x00000000ff000000L) >> 24);
+ this->mb[lstart + 5] =
+ static_cast((this->mlen & 0x0000000000ff0000L) >> 16);
+ this->mb[lstart + 6] =
+ static_cast((this->mlen & 0x000000000000ff00L) >> 8);
+ this->mb[lstart + 7] =
+ static_cast(this->mlen & 0x00000000000000ffL);
+
+ this->updateMessageBlock();
+
+ // Assumption: updating the message block has not left the context in a
+ // corrupted state.
+ assert(EMSHA_ROK == this->hStatus);
+}
+
+
+EMSHA_RESULT
+SHA256::Finalise(uint8_t *d)
+{
+ // Check invariants.
+ // The digest cannot be a null pointer; this library allocates
+ // no memory of its own.
+ if (nullptr == d) { return EMSHA_NULLPTR; }
+
+ // If the SHA256 object is in a bad state, don't proceed.
+ if (EMSHA_ROK != this->hStatus) { return this->hStatus; }
+
+ // If the hash has been finalised, don't proceed.
+ if (0 != this->hComplete) { return EMSHA_INVALID_STATE; }
+ // Invariants satisfied by here.
+
+ this->padMessage(0x80);
+
+ // Assumption: padding the message block has not left the context in a
+ // corrupted state.
+ assert(EMSHA_ROK == this->hStatus);
+ std::fill(this->mb, this->mb + SHA256_MB_SIZE, 0);
+
+ this->hComplete = 1;
+ this->mlen = 0;
+
+ uint32ToChunk(this->i_hash[0], d);
+ uint32ToChunk(this->i_hash[1], d + 4);
+ uint32ToChunk(this->i_hash[2], d + 8);
+ uint32ToChunk(this->i_hash[3], d + 12);
+ uint32ToChunk(this->i_hash[4], d + 16);
+ uint32ToChunk(this->i_hash[5], d + 20);
+ uint32ToChunk(this->i_hash[6], d + 24);
+ uint32ToChunk(this->i_hash[7], d + 28);
+
+ return EMSHA_ROK;
+}
+
+
+EMSHA_RESULT
+SHA256::Result(uint8_t *d)
+{
+ // Check invariants.
+
+ // The digest cannot be a null pointer; this library allocates
+ // no memory of its own.
+ if (nullptr == d) { return EMSHA_NULLPTR; }
+
+ // If the SHA256 object is in a bad state, don't proceed.
+ if (EMSHA_ROK != this->hStatus) { return this->hStatus; }
+
+ // Invariants satisfied by here.
+
+ if (this->hComplete == 0U) {
+ return this->Finalise(d);
+ }
+
+ uint32ToChunk(this->i_hash[0], d);
+ uint32ToChunk(this->i_hash[1], d + 4);
+ uint32ToChunk(this->i_hash[2], d + 8);
+ uint32ToChunk(this->i_hash[3], d + 12);
+ uint32ToChunk(this->i_hash[4], d + 16);
+ uint32ToChunk(this->i_hash[5], d + 20);
+ uint32ToChunk(this->i_hash[6], d + 24);
+ uint32ToChunk(this->i_hash[7], d + 28);
+
+ return EMSHA_ROK;
+}
+
+
+std::uint32_t
+SHA256::Size()
+{
+ return SHA256_HASH_SIZE;
+}
+
+
+#ifndef EMSHA_NO_SELFTEST
+static const uint8_t emptyVector[] = {
+ 0xe3, 0xb0, 0xc4, 0x42,
+ 0x98, 0xfc, 0x1c, 0x14,
+ 0x9a, 0xfb, 0xf4, 0xc8,
+ 0x99, 0x6f, 0xb9, 0x24,
+ 0x27, 0xae, 0x41, 0xe4,
+ 0x64, 0x9b, 0x93, 0x4c,
+ 0xa4, 0x95, 0x99, 0x1b,
+ 0x78, 0x52, 0xb8, 0x55
+};
+
+
+static const uint8_t helloWorld[] = {
+ 0x09, 0xca, 0x7e, 0x4e,
+ 0xaa, 0x6e, 0x8a, 0xe9,
+ 0xc7, 0xd2, 0x61, 0x16,
+ 0x71, 0x29, 0x18, 0x48,
+ 0x83, 0x64, 0x4d, 0x07,
+ 0xdf, 0xba, 0x7c, 0xbf,
+ 0xbc, 0x4c, 0x8a, 0x2e,
+ 0x08, 0x36, 0x0d, 0x5b,
+};
+
+constexpr uint32_t EMSHA_SELF_TEST_ITERS = 4;
+
+static EMSHA_RESULT
+runTest(const uint8_t *input, uint32_t input_len, const uint8_t *expected)
+{
+ uint8_t hexString[65]{0};
+ uint8_t d[SHA256_HASH_SIZE]{0};
+ emsha::SHA256 ctx;
+ emsha::EMSHA_RESULT res;
+
+ res = ctx.Update(input, input_len);
+ if (EMSHA_ROK != res) {
+ return res;
+ }
+
+ for (uint32_t n = 0; n < EMSHA_SELF_TEST_ITERS; n++) {
+ res = ctx.Result(d);
+ if (EMSHA_ROK != res) {
+ return res;
+ }
+
+ for (uint32_t i = 0; i < SHA256_HASH_SIZE; i++) {
+ if (expected[i] != d[i]) {
+ HexString(hexString, const_cast(d), 32);
+ std::cerr << "[!] have: " << hexString << "\n";
+ HexString(hexString, const_cast(helloWorld), 32);
+ std::cerr << "[!] want: " << hexString << "\n";
+ return EMSHA_TEST_FAILURE;
+ }
+ }
+ }
+
+ return EMSHA_ROK;
+}
+
+
+EMSHA_RESULT
+sha256SelfTest()
+{
+ EMSHA_RESULT res;
+
+ res = runTest(reinterpret_cast(""), 0, emptyVector);
+ if (EMSHA_ROK == res) {
+ res = runTest(reinterpret_cast("hello, world"), 12, helloWorld);
+ if (res != EMSHA_ROK) {
+ std::cerr << "[!] failed on hello, world.\n";
+ }
+ } else {
+ std::cerr << "[!] failed on empty vector\n";
+ }
+
+ return res;
+}
+
+
+#else // #ifdef EMSHA_NO_SELFTEST
+EMSHA_RESULT
+sha256_self_test()
+{
+ return EMSHA_SELFTEST_DISABLED;
+}
+
+
+#endif // EMSHA_NO_SELFTEST
+
+
+} // end namespace emsha
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index 0e87322..0000000
--- a/src/Makefile.am
+++ /dev/null
@@ -1,85 +0,0 @@
-AM_CPPFLAGS = -Wall -Wextra -pedantic -Wshadow -Wpointer-arith -Wcast-align
-AM_CPPFLAGS += -Wwrite-strings -Wmissing-declarations -Wno-long-long -Werror
-AM_CPPFLAGS += -Wunused-variable -std=c++11 -D_XOPEN_SOURCE -Os -I.
-AM_CPPFLAGS += -fno-elide-constructors -Weffc++
-TEST_UTILS = test_utils.hh test_utils.cc
-CLOC_PSOURCES = emsha.cc sha256.cc hmac.cc internal.hh \
- emsha/emsha.hh emsha/hmac.hh emsha/sha256.hh
-CLOC_TSOURCES = test_emsha.cc test_hmac.cc test_mem.cc test_sha256.cc \
- test_utils.cc test_utils.hh
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libemsha-1.pc
-
-lib_LTLIBRARIES = libemsha.la
-nobase_include_HEADERS = emsha/sha256.hh emsha/hmac.hh emsha/emsha.hh
-libemsha_la_SOURCES = emsha.cc sha256.cc hmac.cc internal.hh
-libemsha_li_CPPFLAGS = $(AM_CPPFLAGS) -Winline
-
-check_PROGRAMS = emsha_sha256_test emsha_hmac_test \
- emsha_core_test emsha_mem_test \
- emsha_static_mem_test \
- emsha_static_sha_test \
- emsha_static_hmac_test
-check_CPPFLAGS = $(AM_CPPFLAGS) -Wnoinline
-
-# emsha_sha256_test runs through some SHA-256 test vectors, ensuring
-# that the library's behaviour is correct.
-emsha_sha256_test_SOURCES = test_sha256.cc $(TEST_UTILS)
-emsha_sha256_test_LDADD = libemsha.la
-
-# emsha_hmac_test runs through a set of HMAC-SHA-256 test vectors,
-# ensuring that the library's behaviour is correct.
-emsha_hmac_test_SOURCES = test_hmac.cc $(TEST_UTILS)
-emsha_hmac_test_LDADD = libemsha.la
-
-# emsha_core_test validates some of the additional functions provided
-# by the emsha library.
-emsha_core_test_SOURCES = test_emsha.cc $(TEST_UTILS)
-emsha_core_test_LDADD = libemsha.la
-
-# emsha_mem_test is used for testing with valgrind; it aims to introduce
-# no heap allocations via the test harness so that memory usage inside
-# the library may be more accurately checked.
-emsha_mem_test_SOURCES = test_mem.cc $(TEST_UTILS)
-emsha_mem_test_LDADD = libemsha.la
-
-emsha_static_mem_test_SOURCES = test_mem.cc emsha.cc sha256.cc hmac.cc $(TEST_UTILS)
-emsha_static_mem_test_CPPFLAGS = $(AM_CPPFLAGS) -static
-emsha_static_mem_test_LDFLAGS = $(AM_LDFLAGS) -static
-
-emsha_static_sha_test_SOURCES = test_sha256.cc emsha.cc sha256.cc hmac.cc $(TEST_UTILS)
-emsha_static_sha_test_CPPFLAGS = $(AM_CPPFLAGS) -static
-emsha_static_sha_test_LDFLAGS = $(AM_LDFLAGS) -static
-
-emsha_static_hmac_test_SOURCES = test_hmac.cc emsha.cc sha256.cc hmac.cc $(TEST_UTILS)
-emsha_static_hmac_test_CPPFLAGS = $(AM_CPPFLAGS) -static
-emsha_static_hmac_test_LDFLAGS = $(AM_LDFLAGS) -static
-
-
-.PHONY: valgrind-check
-valgrind-check: emsha_static_mem_test
- valgrind --tool=massif -v emsha_static_mem_test ms_print
-
-.PHONY: cloc-report
-cloc-report:
- @echo "=== Library Sources ==="
- @cloc $(CLOC_PSOURCES)
- @echo
- @echo "=== Test Sources ==="
- @cloc $(CLOC_TSOURCES)
-
-.PHONY: coverity-scan
-coverity-scan: clean
- cov-build --dir cov-int make all check
- tar czf $(PACKAGE_NAME)-$(PACKAGE_VERSION)_coverity.tar.gz cov-int
- rm -rf cov-int
-
-.PHONY: scanners clang-scanner cppcheck-scanner
-scanners: clang-scanner cppcheck-scanner
-clang-scanner:
- clang++ $(AM_CPPFLAGS) --analyze $(CLOC_PSOURCES)
-
-cppcheck-scanner:
- cppcheck --quiet --enable=all -I ./ $(CLOC_PSOURCES)
-
-
diff --git a/src/emsha/emsha.hh b/src/emsha/emsha.hh
deleted file mode 100644
index aaa57c3..0000000
--- a/src/emsha/emsha.hh
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 K. Isom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-
-#ifndef __EMSHA_EMSHA_HH
-#define __EMSHA_EMSHA_HH
-
-
-#include
-
-
-namespace emsha {
-
-
-// EMSHA_CHECK is used for sanity checks in certain parts of the code.
-#ifdef NDEBUG
- // If asserts are turned off, expand the check to an if
- // statement that will return with retval if the condition
- // isn't met.
- #define EMSHA_CHECK(condition, retval) if (!(condition)) { return (retval); }
-#else
- // If asserts are turned on, the check is expanded to an
- // assertion that the condition holds. In this case, retval is
- // not used.
- #define EMSHA_CHECK(condition, retval) (assert((condition)))
-#endif
-
-
- // SHA256_HASH_SIZE is the output length of SHA-256 in bytes.
- const std::uint32_t SHA256_HASH_SIZE = 32;
-
-
- // The EMSHA_RESULT type is used to indicate whether an
- // operation succeeded, and if not, what the general fault type
- // was.
- typedef enum _EMSHA_RESULT_: std::uint8_t {
- // All operations have completed successfully so far.
- EMSHA_ROK = 0,
-
- // A self test or unit test failed.
- EMSHA_TEST_FAILURE = 1,
-
- // A null pointer was passed in as a buffer where it shouldn't
- // have been.
- EMSHA_NULLPTR = 2,
-
- // The Hash is in an invalid state.
- EMSHA_INVALID_STATE = 3,
-
- // The input to SHA256::update is too large.
- SHA256_INPUT_TOO_LONG = 4,
-
- // The self tests have been disabled, but a self-test function
- // was called.
- EMSHA_SELFTEST_DISABLED = 5
- } EMSHA_RESULT;
-
-
- // A Hash is generalised superclass supporting concrete classes
- // that produce digests of data.
- class Hash {
- public:
- virtual ~Hash() =0;
-
- // reset should bring the Hash back into its initial
- // state. That is, the idea is that
- //
- // hash->reset(); hash->update(...)...;
- // hash->result(...);
- //
- // is idempotent, assuming the inputs to update and
- // result are constant. The implications of this for a
- // given concrete class should be described in that
- // class's documentation, but in general, it has the
- // effect of preserving any initial state while removing
- // any data written to the Hash via the update method.
- virtual EMSHA_RESULT reset(void) =0;
-
- // update is used to write message data into the Hash.
- virtual EMSHA_RESULT update(const std::uint8_t *m,
- std::uint32_t ml) =0;
-
- // finalize should carry out any final operations on the
- // Hash; after a call to finalize, no more data can be
- // written. Additionally, it transfers out the
- // resulting hash into its argument.
- virtual EMSHA_RESULT finalize(std::uint8_t *d) =0;
-
- // result is used to transfer out the hash to the
- // argument. This implies that the Hash must keep enough
- // state for repeated calls to result to work.
- virtual EMSHA_RESULT result(std::uint8_t *d) =0;
-
- // size should return the output size of the Hash; this
- // is, how large the buffers written to by result should
- // be.
- virtual std::uint32_t size(void) =0;
- };
-
- // hash_equal provides a constant time function for comparing two
- // hashes. The caller *must* ensure that both a and b are the same
- // size. The recommended approach is to use fixed-size buffers of
- // emsha::SHA256_HASH_SIZE length:
- //
- // uint8_t expected[emsha::SHA256_HASH_SIZE];
- // uint8_t actual[emsha::SHA256_HASH_SIZE];
- //
- // // Fill in expected and actual using the Hash operations.
- //
- // if (hash_equal(expected, actual)) {
- // proceed();
- // }
- //
- // Inputs:
- // a, b: byte arrays that MUST contain at least
- // emsha::SHA256_HASH_SIZE bytes. Only the first
- // emsha::SHA256_HASH_SIZE bytes will be compared.
- //
- // Outputs:
- // true iff both byte arrays match
- //
- // false if the arrays do not match
- //
- bool hash_equal(const std::uint8_t *a, const std::uint8_t *b);
-
-#ifndef EMSHA_NO_HEXSTRING
- // hexstring writes a hex-encoded version of the src byte
- // array into dest. The caller *must* ensure that dest is
- // srclen * 2 bytes or longer.
- //
- // Inputs:
- //
- // dest: a byte array that is 2 * srclen.
- //
- // src: a byte array containing the data to process.
- //
- // srclen: the size of src.
- //
- // Outputs:
- //
- // The hex-encoded string will be placed into dest.
- //
- void hexstring(std::uint8_t *dest, std::uint8_t *src, std::uint32_t srclen);
-#endif // EMSHA_NO_HEXSTRING
-} // end of namespace emsha
-
-
-#endif // __EMSHA_EMSHA_HH
diff --git a/src/emsha/hmac.hh b/src/emsha/hmac.hh
deleted file mode 100644
index 9e68236..0000000
--- a/src/emsha/hmac.hh
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 K. Isom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-
-#ifndef __EMSHA_HMAC_HH
-#define __EMSHA_HMAC_HH
-
-
-#include
-
-#include
-#include
-
-
-namespace emsha {
-
- const uint32_t HMAC_KEY_LENGTH = SHA256_MB_SIZE;
-
- // HMAC is a keyed hash that can be used to produce an
- // authenticated hash of some data. The HMAC is built on (and
- // uses internally) the SHA-256 class; it's helpful to note that
- // faults that occur in the SHA-256 code will be propagated up
- // as the return value from many of the HMAC functions.
- class HMAC : Hash {
- public:
- // An HMAC is constructed with a key and the
- // length of the key. This key is stored in
- // the HMAC context, and is wiped by the HMAC
- // destructor.
- //
- // Inputs:
- // k: the HMAC key.
- // kl: the length of the HMAC key.
- //
- HMAC(const uint8_t *k, uint32_t kl);
-
- // reset clears any data written to the HMAC;
- // this is equivalent to constructing a new HMAC,
- // but it preserves the keys.
- //
- // Outputs:
- // EMSHA_ROK is returned if the reset occurred
- // without (detected) fault.
- //
- // If a fault occurs with the underlying SHA-256
- // context, the error code is returned.
- //
- EMSHA_RESULT reset(void);
-
- // update writes data into the context. While there is
- // an upper limit on the size of data that the
- // underlying hash can operate on, this package is
- // designed for small systems that will not approach
- // that level of data (which is on the order of 2
- // exabytes), so it is not thought to be a concern.
- //
- // Inputs:
- // m: a byte array containing the message to be
- // written. It must not be NULL (unless the message
- // length is zero).
- //
- // ml: the message length, in bytes.
- //
- // Outputs:
- // EMSHA_NULLPTR is returned if m is NULL and ml is
- // nonzero.
- //
- // EMSHA_INVALID_STATE is returned if the update
- // is called after a call to finalize.
- //
- // SHA256_INPUT_TOO_LONG is returned if too much
- // data has been written to the context.
- //
- // EMSHA_ROK is returned if the data was
- // successfully written into the HMAC context.
- //
- EMSHA_RESULT update(const uint8_t *, uint32_t);
-
- // finalize completes the HMAC computation. Once this
- // method is called, the context cannot be updated
- // unless the context is reset.
- //
- // Inputs:
- // d: a byte buffer that must be at least
- // HMAC.size() in length.
- //
- // Outputs:
- // EMSHA_NULLPTR is returned if d is the null
- // pointer.
- //
- // EMSHA_INVALID_STATE is returned if the HMAC
- // context is in an invalid state, such as if there
- // were errors in previous updates.
- //
- // EMSHA_ROK is returned if the context was
- // successfully finalised and the digest copied to
- // d.
- //
- EMSHA_RESULT finalize(uint8_t *);
-
- // result copies the result from the HMAC context into
- // the buffer pointed to by d, running finalize if
- // needed. Once called, the context cannot be updated
- // until the context is reset.
- //
- // Inputs:
- // d: a byte buffer that must be at least
- // HMAC.size() in length.
- //
- // Outputs:
- // EMSHA_NULLPTR is returned if d is the null
- // pointer.
- //
- // EMSHA_INVALID_STATE is returned if the HMAC
- // context is in an invalid state, such as if there
- // were errors in previous updates.
- //
- // EMSHA_ROK is returned if the context was
- // successfully finalised and the digest copied to
- // d.
- //
- EMSHA_RESULT result(uint8_t *);
-
-
- // size returns the output size of HMAC-SHA-256, e.g.
- // the size that the buffers passed to finalize and
- // result should be.
- //
- // Outputs:
- // A uint32_t representing the expected size
- // of buffers passed to result and finalize.
- uint32_t size(void) { return SHA256_HASH_SIZE; }
-
- // When an HMAC context is destroyed, it is reset and
- // the key material is zeroised using the STL fill
- // function.
- ~HMAC(void);
- private:
- uint8_t hstate;
- SHA256 ctx;
- uint8_t k[HMAC_KEY_LENGTH];
- uint8_t buf[SHA256_HASH_SIZE];
-
- inline EMSHA_RESULT
- final_result(uint8_t *);
- };
-
- // compute_hmac performs a single-pass HMAC computation over
- // a message.
- //
- // Inputs:
- // k: a byte buffer containing the HMAC key.
- //
- // kl: the length of the HMAC key.
- //
- // m: the message data over which the HMAC is to be computed.
- //
- // ml: the length of the message.
- //
- // d: a byte buffer that will be used to store the resulting
- // HMAC. It should be SHA256_HASH_SIZE bytes in size.
- //
- // Outputs:
- // This function handles setting up the HMAC context with
- // the given key, calling update with the message data, and
- // then calling finalize to place the result in the output
- // buffer. Any of the faults that can occur in these functions
- // can be returned here, or EMSHA_ROK if the HMAC was
- // successfully computed.
- EMSHA_RESULT compute_hmac(const uint8_t *k, uint32_t kl,
- const uint8_t *m, uint32_t ml,
- uint8_t *d);
-} // end of namespace emsha
-
-
-#endif // __EMSHA_HMAC_HH
diff --git a/src/emsha/sha256.hh b/src/emsha/sha256.hh
deleted file mode 100644
index e5b668e..0000000
--- a/src/emsha/sha256.hh
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 K. Isom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-
-#ifndef __EMSHA_SHA256_HH
-#define __EMSHA_SHA256_HH
-
-
-#include
-
-#include
-
-
-namespace emsha {
-
-
- // SHA256_MB_SIZE is the size of a message block.
- const uint32_t SHA256_MB_SIZE = 64;
-
- class SHA256 : Hash {
- public:
- // A SHA256 context does not need any special
- // construction. It can be declared and
- // immediately start being used.
- SHA256();
-
- // The SHA256 destructor will clear out its internal
- // message buffer; all of the members are local
- // and not resource handles, so cleanup is minimal.
- ~SHA256();
-
- // reset clears the internal state of the SHA256
- // context and returns it to its initial state.
- // It should always return EMSHA_ROK.
- EMSHA_RESULT reset(void);
-
- // update writes data into the context. While
- // there is an upper limit on the size of data
- // that SHA-256 can operate on, this package is
- // designed for small systems that will not
- // approach that level of data (which is on the
- // order of 2 exabytes), so it is not thought
- // to be a concern.
- //
- // Inputs:
- // m: a byte array containing the message to
- // be written. It must not be NULL (unless
- // the message length is zero).
- //
- // ml: the message length, in bytes.
- //
- // Outputs:
- // EMSHA_NULLPTR is returned if m is NULL
- // and ml is nonzero.
- //
- // EMSHA_INVALID_STATE is returned if the
- // update is called after a call to
- // finalize.
- //
- // SHA256_INPUT_TOO_LONG is returned if too
- // much data has been written to the
- // context.
- //
- // EMSHA_ROK is returned if the data was
- // successfully added to the SHA-256
- // context.
- //
- EMSHA_RESULT update(const uint8_t *m, uint32_t ml);
-
- // finalize completes the digest. Once this
- // method is called, the context cannot be
- // updated unless the context is reset.
- //
- // Inputs:
- // d: a byte buffer that must be at least
- // SHA256.size() in length.
- //
- // Outputs:
- // EMSHA_NULLPTR is returned if d is the
- // null pointer.
- //
- // EMSHA_INVALID_STATE is returned if the
- // SHA-256 context is in an invalid state,
- // such as if there were errors in previous
- // updates.
- //
- // EMSHA_ROK is returned if the context was
- // successfully finalised and the digest
- // copied to d.
- //
- EMSHA_RESULT finalize(uint8_t *d);
-
- // result copies the result from the SHA-256
- // context into the buffer pointed to by d,
- // running finalize if needed. Once called,
- // the context cannot be updated until the
- // context is reset.
- //
- // Inputs:
- // d: a byte buffer that must be at least
- // SHA256.size() in length.
- //
- // Outputs:
- // EMSHA_NULLPTR is returned if d is the
- // null pointer.
- //
- // EMSHA_INVALID_STATE is returned if the
- // SHA-256 context is in an invalid state,
- // such as if there were errors in previous
- // updates.
- //
- // EMSHA_ROK is returned if the context was
- // successfully finalised and the digest
- // copied to d.
- //
- EMSHA_RESULT result(uint8_t *d);
-
- // size returns the output size of SHA256, e.g.
- // the size that the buffers passed to finalize
- // and result should be.
- //
- // Outputs:
- // a uint32_t representing the expected size
- // of buffers passed to result and finalize.
- uint32_t size(void) { return SHA256_HASH_SIZE; }
- private:
- // mlen stores the current message length.
- uint64_t mlen;
-
- // The intermediate hash is 8x 32-bit blocks.
- uint32_t i_hash[8];
-
- // hstatus is the hash status, and hcomplete indicates
- // whether the hash has been finalised.
- EMSHA_RESULT hstatus;
- uint8_t hcomplete;
-
- // mb is the message block, and mbi is the message
- // block index.
- uint8_t mbi;
- uint8_t mb[SHA256_MB_SIZE];
-
- inline EMSHA_RESULT add_length(uint32_t);
- inline void update_message_block(void);
- inline void pad_message(uint8_t);
- }; // end class SHA256
-
- // sha256_digest performs a single pass hashing of the message
- // passed in.
- //
- // Inputs:
- // m: byte buffer containing the message to hash.
- //
- // ml: the length of m.
- //
- // d: byte buffer that will be used to store the resulting
- // hash; it should have at least emsha::SHA256_HASH_SIZE
- // bytes available.
- //
- // Outputs:
- // This function handles setting up a SHA256 context, calling
- // update using the message data, and then calling finalize. Any
- // of the errors that can occur in those functions can be
- // returned here, or EMSHA_ROK if the digest was computed
- // successfully.
- //
- EMSHA_RESULT sha256_digest(const uint8_t *m, uint32_t ml, uint8_t *d);
-
- // sha256_self_test runs through two test cases to ensure that the
- // SHA-256 functions are working correctly.
- //
- // Outputs:
- // EMSHA_ROK is returned if the self tests pass.
- //
- // EMSHA_SELFTEST_DISABLED is returned if the self tests
- // have been disabled (e.g., libemsha was compiled with the
- // EMSHA_NO_SELFTEST #define).
- //
- // If a fault occurred inside the SHA-256 code, the error
- // code from one of the update, finalize, result, or reset
- // methods is returned.
- //
- // If the fault is that the output does not match the test
- // vector, EMSHA_TEST_FAILURE is returned.
- //
- EMSHA_RESULT sha256_self_test(void);
-} // end of namespace emsha
-
-
-#endif // __EMSHA_SHA256_HH
diff --git a/src/internal.hh b/src/internal.hh
deleted file mode 100644
index 9709695..0000000
--- a/src/internal.hh
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 K. Isom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-
-#ifndef __EMSHA_INTERNAL_HH
-#define __EMSHA_INTERNAL_HH
-
-
-#include
-
-using std::uint8_t;
-using std::uint32_t;
-
-
-namespace emsha {
-
-
-static inline uint32_t
-rotr32(uint32_t x, uint8_t n)
-{
- return ((x >> n) | (x << (32 - n)));
-}
-
-
-static inline uint32_t
-sha_ch(uint32_t x, uint32_t y, uint32_t z)
-{
- return ((x & y) ^ ((~x) & z));
-}
-
-
-static inline uint32_t
-sha_maj(uint32_t x, uint32_t y, uint32_t z)
-{
- return (x & y) ^ (x & z) ^ (y & z);
-}
-
-
-static inline uint32_t
-sha_Sigma0(uint32_t x)
-{
- return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22);
-}
-
-
-static inline uint32_t
-sha_Sigma1(uint32_t x)
-{
- return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25);
-}
-
-
-static inline uint32_t
-sha_sigma0(uint32_t x)
-{
- return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >> 3);
-}
-
-
-static inline uint32_t
-sha_sigma1(uint32_t x)
-{
- return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10);
-}
-
-
-
-} // end of namespace emsha
-
-
-#endif // __EMSHA_INTERNAL_HH
diff --git a/src/libemsha-1.pc.in b/src/libemsha-1.pc.in
deleted file mode 100644
index a713c3e..0000000
--- a/src/libemsha-1.pc.in
+++ /dev/null
@@ -1,10 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: @PACKAGE_NAME@
-Description: C++11 HMAC-SHA256 library
-URL: @PACKAGE_URL@
-Version: @PACKAGE_VERSION@
-Libs: -L${libdir} -Wl,-rpath,${libdir} -lemsha
diff --git a/src/sha256.cc b/src/sha256.cc
deleted file mode 100644
index 8674dc7..0000000
--- a/src/sha256.cc
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 K. Isom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-
-#include
-#include
-#include
-
-#include
-#include
-#include "internal.hh"
-
-
-namespace emsha {
-
-
-/*
- * SHA-256 constants, from FIPS 180-4 page 11.
- */
-static constexpr uint32_t SHA256_K[64] = {
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
- 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
- 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
- 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
- 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
-};
-
-
-/*
- * SHA-256 initialisation vector, from FIPS 180-4 page 15.
- */
-static constexpr uint32_t EMSHA_256_H0[] = {
- 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
- 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
-};
-
-
-EMSHA_RESULT
-sha256_digest(const uint8_t *m, uint32_t ml, uint8_t *d)
-{
- SHA256 h;
- EMSHA_RESULT ret;
-
- if (EMSHA_ROK != (ret = h.update(m, ml))) {
- return ret;
- }
-
- return h.finalize(d);
-}
-
-
-SHA256::SHA256()
- :mlen(), hstatus(), hcomplete(), mbi()
-{
- this->reset();
-}
-
-
-SHA256::~SHA256()
-{
- memset(this->mb, 0, SHA256_MB_SIZE);
-}
-
-
-inline EMSHA_RESULT
-SHA256::add_length(uint32_t l)
-{
- uint32_t tmp = this->mlen + l;
-
- if (tmp < this->mlen) {
- return SHA256_INPUT_TOO_LONG;
- }
- this->mlen = tmp;
- assert(this->mlen > 0);
-
- return EMSHA_ROK;
-}
-
-
-EMSHA_RESULT
-SHA256::reset()
-{
- // The message block is set to the initial hash vector.
- this->i_hash[0] = EMSHA_256_H0[0];
- this->i_hash[1] = EMSHA_256_H0[1];
- this->i_hash[2] = EMSHA_256_H0[2];
- this->i_hash[3] = EMSHA_256_H0[3];
- this->i_hash[4] = EMSHA_256_H0[4];
- this->i_hash[5] = EMSHA_256_H0[5];
- this->i_hash[6] = EMSHA_256_H0[6];
- this->i_hash[7] = EMSHA_256_H0[7];
-
- this->mbi = 0;
- this->hstatus = EMSHA_ROK;
- this->hcomplete = 0;
- this->mlen = 0;
- memset(this->mb, 0, SHA256_MB_SIZE);
-
- return this->hstatus;
-}
-
-
-// Read 32 bits from the byte buffer chunk as an unsigned 32-bit integer.
-static inline uint32_t
-chunk_to_uint32(uint8_t *chunk)
-{
- return ((*chunk) << 24) |
- ((*(chunk + 1)) << 16) |
- ((*(chunk + 2)) << 8) |
- (*(chunk + 3));
-}
-
-
-// Copy an unsigned 32-bit integer into the start of the byte buffer chunk.
-static inline void
-uint32_to_chunk(uint32_t x, uint8_t *chunk)
-{
- chunk[0] = (x & 0xff000000) >> 24;
- chunk[1] = (x & 0x00ff0000) >> 16;
- chunk[2] = (x & 0x0000ff00) >> 8;
- chunk[3] = (x & 0x000000ff);
-}
-
-
-// FIPS 180-4, page 22.
-void
-SHA256::update_message_block()
-{
- uint32_t w[64];
- uint32_t i = 0;
- uint32_t chunk = 0;
- uint32_t a, b, c, d, e, f, g, h;
-
- while (i < 16) {
- w[i++] = chunk_to_uint32(this->mb + chunk);
- chunk += 4;
- }
- this->mbi = 0;
-
- for (i = 16; i < 64; i++) {
- w[i] = sha_sigma1(w[i - 2]) + w[i - 7] +
- sha_sigma0(w[i - 15]) + w[i - 16];
- }
-
- a = this->i_hash[0];
- b = this->i_hash[1];
- c = this->i_hash[2];
- d = this->i_hash[3];
- e = this->i_hash[4];
- f = this->i_hash[5];
- g = this->i_hash[6];
- h = this->i_hash[7];
-
- for (i = 0; i < 64; i++) {
- uint32_t t1, t2;
- t1 = h + sha_Sigma1(e) + sha_ch(e, f, g) + SHA256_K[i] + w[i];
- t2 = sha_Sigma0(a) + sha_maj(a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + t1;
- d = c;
- c = b;
- b = a;
- a = t1 + t2;
- }
-
- this->i_hash[0] += a;
- this->i_hash[1] += b;
- this->i_hash[2] += c;
- this->i_hash[3] += d;
- this->i_hash[4] += e;
- this->i_hash[5] += f;
- this->i_hash[6] += g;
- this->i_hash[7] += h;
-}
-
-
-EMSHA_RESULT
-SHA256::update(const uint8_t *m, uint32_t ml)
-{
- // Checking invariants:
- // If the message length is zero, there's nothing to be done.
- if (0 == ml) return EMSHA_ROK;
-
- // The message passed in cannot be the null pointer if the
- // message length is greater than 0.
- if (nullptr == m) return EMSHA_NULLPTR;
-
- // If the SHA256 object is in a bad state, don't proceed.
- if (EMSHA_ROK != this->hstatus) return this->hstatus;
-
- // If the hash has been finalised, don't proceed.
- if (0 != this->hcomplete) return EMSHA_INVALID_STATE;
- // Invariants satisfied by here.
-
- for (uint32_t i = 0; i < ml; i++) {
- this->mb[this->mbi] = *(m + i);
- mbi++;
-
- if (EMSHA_ROK == this->add_length(8)) {
- if (SHA256_MB_SIZE == this->mbi) {
- this->update_message_block();
-
- // Assumption: following the message block
- // write, the context should still be in a good
- // state.
- assert(EMSHA_ROK == this->hstatus);
- }
- }
- }
-
- return this->hstatus;
-}
-
-
-inline void
-SHA256::pad_message(uint8_t pc)
-{
- // Assumption: the context is not in a corrupted state.
- assert(EMSHA_ROK == this->hstatus);
-
- if (this->mbi < (SHA256_MB_SIZE - 8)) {
- this->mb[this->mbi++] = pc;
- } else {
- bool pc_add = false;
-
- if (this->mbi < SHA256_MB_SIZE - 1) {
- this->mb[this->mbi++] = pc;
- pc_add = true;
- }
-
- while (this->mbi < SHA256_MB_SIZE) {
- this->mb[this->mbi++] = 0;
- }
-
- this->update_message_block();
- if (!pc_add) {
- this->mb[this->mbi++] = pc;
- }
-
- // Assumption: updating the message block has not left the
- // context in a corrupted state.
- assert(EMSHA_ROK == this->hstatus);
- }
-
- while (this->mbi < (SHA256_MB_SIZE - 8)) {
- this->mb[this->mbi++] = 0;
- }
-
- // lstart marks the starting point for the length packing.
- uint32_t lstart = SHA256_MB_SIZE - 8;
-
- this->mb[lstart] = (uint8_t)(this->mlen >> 56);
- this->mb[lstart+1] =
- (uint8_t)((this->mlen & 0x00ff000000000000L) >> 48);
- this->mb[lstart+2] =
- (uint8_t)((this->mlen & 0x0000ff0000000000L) >> 40);
- this->mb[lstart+3] =
- (uint8_t)((this->mlen & 0x000000ff00000000L) >> 32);
- this->mb[lstart+4] =
- (uint8_t)((this->mlen & 0x00000000ff000000L) >> 24);
- this->mb[lstart+5] =
- (uint8_t)((this->mlen & 0x0000000000ff0000L) >> 16);
- this->mb[lstart+6] =
- (uint8_t)((this->mlen & 0x000000000000ff00L) >> 8);
- this->mb[lstart+7] =
- (uint8_t)(this->mlen & 0x00000000000000ffL);
-
- this->update_message_block();
-
- // Assumption: updating the message block has not left the context in a
- // corrupted state.
- assert(EMSHA_ROK == this->hstatus);
-}
-
-
-EMSHA_RESULT
-SHA256::finalize(uint8_t *d)
-{
- // Check invariants.
- // The digest cannot be a null pointer; this library allocates
- // no memory of its own.
- if (nullptr == d) return EMSHA_NULLPTR;
-
- // If the SHA256 object is in a bad state, don't proceed.
- if (EMSHA_ROK != this->hstatus) return this->hstatus;
-
- // If the hash has been finalised, don't proceed.
- if (0 != this->hcomplete) return EMSHA_INVALID_STATE;
- // Invariants satisfied by here.
-
- this->pad_message(0x80);
-
- // Assumption: padding the message block has not left the context in a
- // corrupted state.
- assert(EMSHA_ROK == this->hstatus);
- for (uint8_t i = 0; i < SHA256_MB_SIZE; i++) {
- this->mb[i] = 0;
- }
-
- this->hcomplete = 1;
- this->mlen = 0;
-
- uint32_to_chunk(this->i_hash[0], d);
- uint32_to_chunk(this->i_hash[1], d+4);
- uint32_to_chunk(this->i_hash[2], d+8);
- uint32_to_chunk(this->i_hash[3], d+12);
- uint32_to_chunk(this->i_hash[4], d+16);
- uint32_to_chunk(this->i_hash[5], d+20);
- uint32_to_chunk(this->i_hash[6], d+24);
- uint32_to_chunk(this->i_hash[7], d+28);
-
- return EMSHA_ROK;
-}
-
-
-EMSHA_RESULT
-SHA256::result(uint8_t *d)
-{
- // Check invariants.
- // The digest cannot be a null pointer; this library allocates
- // no memory of its own.
- if (nullptr == d) return EMSHA_NULLPTR;
-
- // If the SHA256 object is in a bad state, don't proceed.
- if (EMSHA_ROK != this->hstatus) return this->hstatus;
- // Invariants satisfied by here.
-
- if (!this->hcomplete) {
- return this->finalize(d);
- }
-
- uint32_to_chunk(this->i_hash[0], d);
- uint32_to_chunk(this->i_hash[1], d+4);
- uint32_to_chunk(this->i_hash[2], d+8);
- uint32_to_chunk(this->i_hash[3], d+12);
- uint32_to_chunk(this->i_hash[4], d+16);
- uint32_to_chunk(this->i_hash[5], d+20);
- uint32_to_chunk(this->i_hash[6], d+24);
- uint32_to_chunk(this->i_hash[7], d+28);
-
- return EMSHA_ROK;
-}
-
-
-#ifndef EMSHA_NO_SELFTEST
-static const uint8_t empty_vector[] = {
- 0xe3, 0xb0, 0xc4, 0x42,
- 0x98, 0xfc, 0x1c, 0x14,
- 0x9a, 0xfb, 0xf4, 0xc8,
- 0x99, 0x6f, 0xb9, 0x24,
- 0x27, 0xae, 0x41, 0xe4,
- 0x64, 0x9b, 0x93, 0x4c,
- 0xa4, 0x95, 0x99, 0x1b,
- 0x78, 0x52, 0xb8, 0x55
-};
-
-
-static const uint8_t hello_world[] = {
- 0x09, 0xca, 0x7e, 0x4e,
- 0xaa, 0x6e, 0x8a, 0xe9,
- 0xc7, 0xd2, 0x61, 0x16,
- 0x71, 0x29, 0x18, 0x48,
- 0x83, 0x64, 0x4d, 0x07,
- 0xdf, 0xba, 0x7c, 0xbf,
- 0xbc, 0x4c, 0x8a, 0x2e,
- 0x08, 0x36, 0x0d, 0x5b,
-};
-
-constexpr uint32_t EMSHA_SELF_TEST_ITERS = 4;
-
-static EMSHA_RESULT
-run_test(const uint8_t *input, uint32_t input_len, const uint8_t *expected)
-{
- uint8_t d[SHA256_HASH_SIZE];
- emsha::SHA256 ctx;
- emsha::EMSHA_RESULT res;
-
- res = ctx.update(input, input_len);
- if (EMSHA_ROK != res) {
- return res;
- }
-
- for (uint32_t n = 0; n < EMSHA_SELF_TEST_ITERS; n++) {
- res = ctx.result(d);
- if (EMSHA_ROK != res) {
- return res;
- }
-
- for (uint32_t i = 0; i < SHA256_HASH_SIZE; i++) {
- if (expected[i] != d[i]) {
- return EMSHA_TEST_FAILURE;
- }
- }
- }
-
- return EMSHA_ROK;
-}
-
-
-EMSHA_RESULT
-sha256_self_test()
-{
- EMSHA_RESULT res;
-
- res = run_test((const uint8_t *)"", 0, empty_vector);
- if (EMSHA_ROK == res) {
- res = run_test((const uint8_t *)"hello, world", 12, hello_world);
- }
-
- return res;
-}
-
-
-#else // #ifdef EMSHA_NO_SELFTEST
-EMSHA_RESULT
-sha256_self_test()
-{
- return EMSHA_SELFTEST_DISABLED;
-}
-
-
-#endif // EMSHA_NO_SELFTEST
-
-
-} // end namespace emsha
diff --git a/src/test_mem.cc b/src/test_mem.cc
deleted file mode 100644
index c9de9e4..0000000
--- a/src/test_mem.cc
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 K. Isom
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-
-#ifdef NDEBUG
-#undef NDEBUG
-#endif
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-
-// Number of test iterations.
-static constexpr std::uint32_t ITERS = 3000000;
-
-// The key used for HMAC.
-static constexpr std::uint8_t k[] = {
- 0xc5, 0xb6, 0x80, 0xac, 0xdc, 0xf4, 0xff, 0xa1,
- 0x37, 0x05, 0xc0, 0x71, 0x11, 0x24, 0x31, 0x7c,
- 0xa5, 0xa2, 0xcf, 0x4d, 0x33, 0x00, 0x56, 0x4f,
- 0x69, 0x0f, 0x76, 0x70, 0x87, 0xd9, 0x35, 0xce,
- 0xa3, 0xad, 0xa3, 0x4f, 0x30, 0xe2, 0x7c, 0x58,
- 0x88, 0xd4, 0x89, 0x6a, 0xb5, 0xe0, 0x97, 0x1c,
- 0x7a, 0x69, 0x65, 0xc7, 0x61, 0x0d, 0x6d, 0xb6,
- 0x9b, 0x0e, 0x56, 0xd7, 0x0f, 0x5a, 0x01, 0x50,
-};
-static constexpr std::uint32_t kl = sizeof(k) / sizeof(k[0]);
-
-// The message provided to both SHA-256 and HMAC-SHA-256; it is
-// "The fugacity of a constituent in a mixture of gases at a given
-// temperature is proportional to its mole fraction. Lewis-Randall Rule",
-// chosen as one of the longer test vectors.
-static const std::uint8_t m[] = {
- 0x54, 0x68, 0x65, 0x20, 0x66, 0x75, 0x67, 0x61,
- 0x63, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20,
- 0x61, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x69,
- 0x74, 0x75, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e,
- 0x20, 0x61, 0x20, 0x6d, 0x69, 0x78, 0x74, 0x75,
- 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x61,
- 0x73, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x61,
- 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x74,
- 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75,
- 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72,
- 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e,
- 0x61, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74,
- 0x73, 0x20, 0x6d, 0x6f, 0x6c, 0x65, 0x20, 0x66,
- 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
- 0x20, 0x20, 0x4c, 0x65, 0x77, 0x69, 0x73, 0x2d,
- 0x52, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6c, 0x20,
- 0x52, 0x75, 0x6c, 0x65
-};
-
-// d is the expected result of SHA256(m).
-static constexpr std::uint8_t d[emsha::SHA256_HASH_SIZE] = {
- 0x39, 0x55, 0x85, 0xce, 0x30, 0x61, 0x7b, 0x62,
- 0xc8, 0x0b, 0x93, 0xe8, 0x20, 0x8c, 0xe8, 0x66,
- 0xd4, 0xed, 0xc8, 0x11, 0xa1, 0x77, 0xfd, 0xb4,
- 0xb8, 0x2d, 0x39, 0x11, 0xd8, 0x69, 0x64, 0x23
-};
-
-// t is the expected result of HMAC-SHA-256(k, m).
-static constexpr std::uint8_t t[emsha::SHA256_HASH_SIZE] = {
- 0xbb, 0xc4, 0x7c, 0x35, 0x33, 0x4b, 0x9d, 0x90,
- 0xee, 0x20, 0x88, 0x30, 0xe1, 0x1a, 0x0f, 0xf3,
- 0xf4, 0x7d, 0xcc, 0xb0, 0xc5, 0xfb, 0x83, 0xe5,
- 0xc2, 0xf5, 0xa7, 0x94, 0x50, 0xb6, 0xe0, 0xe0,
-};
-
-// dig is used to store the output of SHA-256 and HMAC-SHA-256.
-static std::uint8_t dig[emsha::SHA256_HASH_SIZE];
-
-
-static void
-init(void)
-{
- std::fill(dig, dig+emsha::SHA256_HASH_SIZE, 0);
-}
-
-
-static void
-iterate_sha(void)
-{
- emsha::SHA256 ctx;
- int cmp;
- emsha::EMSHA_RESULT res;
-
- res = ctx.update(m, sizeof(m));
- assert(emsha::EMSHA_ROK == res);
- res = ctx.result(dig);
- assert(emsha::EMSHA_ROK == res);
-
- cmp = std::memcmp(dig, d, emsha::SHA256_HASH_SIZE);
- assert(0 == cmp);
-}
-
-
-static void
-iterate_hmac(void)
-{
- emsha::HMAC ctx(k, kl);
- int cmp;
- emsha::EMSHA_RESULT res;
-
- res = ctx.update(m, sizeof(m));
- assert(emsha::EMSHA_ROK == res);
- res = ctx.result(dig);
- assert(emsha::EMSHA_ROK == res);
-
- cmp = std::memcmp(dig, t, emsha::SHA256_HASH_SIZE);
- assert(0 == cmp);
-}
-
-
-static void
-iterate_sha_sp(void)
-{
- int cmp;
-
- assert(emsha::EMSHA_ROK == emsha::sha256_digest(m, sizeof(m), dig));
- cmp = std::memcmp(dig, d, emsha::SHA256_HASH_SIZE);
- assert(0 == cmp);
-}
-
-
-static void
-iterate_hmac_sp(void)
-{
- int cmp;
- emsha::EMSHA_RESULT res;
-
- res = emsha::compute_hmac(k, kl, m, sizeof(m), dig);
- assert(emsha::EMSHA_ROK == res);
-
- cmp = std::memcmp(dig, t, emsha::SHA256_HASH_SIZE);
- assert(0 == cmp);
-}
-
-
-static void
-iterate(std::string label, void(iteration)(void))
-{
- std::cout << "=== " << label << " ===" << std::endl;
- auto start = std::chrono::steady_clock::now();
-
- for (std::uint32_t i = 0; i < ITERS; i++)
- iteration();
-
- auto end = std::chrono::steady_clock::now();
- auto delta = (end - start );
-
- std::cout << "Total time: "
- << std::chrono::duration (delta).count()
- << " ms" << std::endl;
- std::cout << "Average over " << ITERS << " tests: "
- << std::chrono::duration (delta).count() / ITERS
- << " ns" << std::endl;
-}
-
-
-static void
-cold_start(void)
-{
- std::cout << "=== SHA-256 cold start ===\n";
- auto start = std::chrono::steady_clock::now();
-
- iterate_sha();
-
- auto end = std::chrono::steady_clock::now();
- auto delta = (end - start );
-
- std::cout << "Total time: "
- << std::chrono::duration (delta).count()
- << " ns" << std::endl;
-}
-
-int
-main(void)
-{
- init();
-
- cold_start();
- iterate("SHA-256", iterate_sha);
- iterate("SHA-256 single-pass", iterate_sha_sp);
- iterate("HMAC-SHA-256", iterate_hmac);
- iterate("HMAC-SHA-256 single-pass", iterate_hmac_sp);
-}
diff --git a/src/test_emsha.cc b/test_emsha.cc
similarity index 65%
rename from src/test_emsha.cc
rename to test_emsha.cc
index d46a5e1..34b09eb 100644
--- a/src/test_emsha.cc
+++ b/test_emsha.cc
@@ -25,9 +25,9 @@
#include
-#include
+#include
-#include "test_utils.hh"
+#include "test_utils.h"
using namespace std;
@@ -35,27 +35,27 @@ using namespace std;
#ifndef EMSHA_NO_HEXSTRING
static void
-hexstring_test(void)
+hexStringTest()
{
- uint8_t buf[32];
- uint8_t out[65];
- string expected = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
+ uint8_t buf[32];
+ uint8_t out[65];
+ string const expected = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
out[64] = 0;
for (uint32_t i = 0; i < 32; i++) {
- buf[i] = (uint8_t)i;
+ buf[i] = static_cast(i);
}
- emsha::hexstring(out, buf, emsha::SHA256_HASH_SIZE);
- string outs(reinterpret_cast(out));
+ emsha::HexString(out, buf, emsha::SHA256_HASH_SIZE);
+ string const outs(reinterpret_cast(out));
if (outs != expected) {
- cerr << "FAILED: hexstring" << endl;
+ cerr << "FAILED: HexString" << endl;
cerr << "\twanted: " << expected << endl;
cerr << "\thave: " << out << endl;
exit(1);
}
- cout << "PASSED: hexstring ";
+ cout << "PASSED: HexString ";
#ifdef EMSHA_NO_HEXLUT
cout << "(small LUT)";
#else // #ifdef EMSHA_NO_HEXLUT
@@ -69,23 +69,23 @@ hexstring_test(void)
// TODO(kyle): build a test harness around this to verify times between
// runs.
static void
-hash_equal_test(void)
+hashEqualTest()
{
- uint8_t a[emsha::SHA256_HASH_SIZE];
- uint8_t b[emsha::SHA256_HASH_SIZE];
+ uint8_t a[emsha::SHA256_HASH_SIZE];
+ uint8_t b[emsha::SHA256_HASH_SIZE];
for (uint32_t i = 0; i < emsha::SHA256_HASH_SIZE; i++) {
a[i] = static_cast(i);
b[i] = static_cast(i);
}
- if (!(emsha::hash_equal(a, b))) {
- string s;
- cerr << "FAILED: hash_equal\n";
- cerr << "\thash_equal should have succeeded comparing a and b.\n";
- dump_hexstring(s, a, emsha::SHA256_HASH_SIZE);
+ if (!(emsha::HashEqual(a, b))) {
+ string s;
+ cerr << "FAILED: HashEqual\n";
+ cerr << "\tHashEqual should have succeeded comparing a and b.\n";
+ DumpHexString(s, a, emsha::SHA256_HASH_SIZE);
cerr << "\ta <- " << s << std::endl;
- dump_hexstring(s, b, emsha::SHA256_HASH_SIZE);
+ DumpHexString(s, b, emsha::SHA256_HASH_SIZE);
cerr << "\tb <- " << s << std::endl;
exit(1);
}
@@ -95,13 +95,13 @@ hash_equal_test(void)
b[i] = static_cast(emsha::SHA256_HASH_SIZE - i);
}
- if (emsha::hash_equal(a, b)) {
- string s;
- cerr << "FAILED: hash_equal\n";
- cerr << "\thash_equal should not have succeeded comparing a and b.\n";
- dump_hexstring(s, a, emsha::SHA256_HASH_SIZE);
+ if (emsha::HashEqual(a, b)) {
+ string s;
+ cerr << "FAILED: HashEqual\n";
+ cerr << "\tHashEqual should not have succeeded comparing a and b.\n";
+ DumpHexString(s, a, emsha::SHA256_HASH_SIZE);
cerr << "\ta <- " << s << std::endl;
- dump_hexstring(s, b, emsha::SHA256_HASH_SIZE);
+ DumpHexString(s, b, emsha::SHA256_HASH_SIZE);
cerr << "\tb <- " << s << std::endl;
exit(1);
}
@@ -112,32 +112,31 @@ hash_equal_test(void)
// res += a[i] ^ b[i];
for (uint32_t i = 0; i < emsha::SHA256_HASH_SIZE; i++) {
a[i] = static_cast(i);
- b[i] = static_cast(i+1);
+ b[i] = static_cast(i + 1);
}
b[emsha::SHA256_HASH_SIZE - 1]--;
- if (emsha::hash_equal(a, b)) {
- string s;
- cerr << "FAILED: hash_equal\n";
- cerr << "\tREGRESSION: hash_equal should not have succeeded comparing a and b.\n";
- dump_hexstring(s, a, emsha::SHA256_HASH_SIZE);
+ if (emsha::HashEqual(a, b)) {
+ string s;
+ cerr << "FAILED: HashEqual\n";
+ cerr << "\tREGRESSION: HashEqual should not have succeeded comparing a and b.\n";
+ DumpHexString(s, a, emsha::SHA256_HASH_SIZE);
cerr << "\ta <- " << s << std::endl;
- dump_hexstring(s, b, emsha::SHA256_HASH_SIZE);
+ DumpHexString(s, b, emsha::SHA256_HASH_SIZE);
cerr << "\tb <- " << s << std::endl;
exit(1);
}
-
- cout << "PASSED: hash_equal\n";
+ cout << "PASSED: HashEqual\n";
}
int
-main(void)
+main()
{
#ifndef EMSHA_NO_HEXSTRING
- hexstring_test();
+ hexStringTest();
#endif
- hash_equal_test();
+ hashEqualTest();
}
diff --git a/src/test_hmac.cc b/test_hmac.cc
similarity index 94%
rename from src/test_hmac.cc
rename to test_hmac.cc
index 77df8c3..a14500f 100644
--- a/src/test_hmac.cc
+++ b/test_hmac.cc
@@ -25,15 +25,15 @@
#include
-#include
-#include
+#include
+#include
-#include "test_utils.hh"
+#include "test_utils.h"
using namespace std;
-const struct hmac_test rfc4231[] = {
+const struct hmacTest rfc4231[] = {
{
{0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b,
@@ -122,13 +122,13 @@ const struct hmac_test rfc4231[] = {
int
-main(void)
+main()
{
- int res;
+ int res = 0;
- res = run_hmac_tests((struct hmac_test *)rfc4231,
- sizeof rfc4231 / sizeof rfc4231[0],
- "RFC 4231");
+ res = runHMACTests((struct hmacTest *) rfc4231,
+ sizeof rfc4231 / sizeof rfc4231[0],
+ "RFC 4231");
if (-1 == res) {
exit(1);
}
diff --git a/test_mem.cc b/test_mem.cc
new file mode 100644
index 0000000..70edd39
--- /dev/null
+++ b/test_mem.cc
@@ -0,0 +1,217 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 K. Isom
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+
+// Number of test iterations.
+static constexpr std::uint32_t ITERS = 8192;
+
+// The key used for HMAC.
+static constexpr std::uint8_t k[] = {
+ 0xc5, 0xb6, 0x80, 0xac, 0xdc, 0xf4, 0xff, 0xa1,
+ 0x37, 0x05, 0xc0, 0x71, 0x11, 0x24, 0x31, 0x7c,
+ 0xa5, 0xa2, 0xcf, 0x4d, 0x33, 0x00, 0x56, 0x4f,
+ 0x69, 0x0f, 0x76, 0x70, 0x87, 0xd9, 0x35, 0xce,
+ 0xa3, 0xad, 0xa3, 0x4f, 0x30, 0xe2, 0x7c, 0x58,
+ 0x88, 0xd4, 0x89, 0x6a, 0xb5, 0xe0, 0x97, 0x1c,
+ 0x7a, 0x69, 0x65, 0xc7, 0x61, 0x0d, 0x6d, 0xb6,
+ 0x9b, 0x0e, 0x56, 0xd7, 0x0f, 0x5a, 0x01, 0x50,
+};
+static constexpr std::uint32_t kl = sizeof(k) / sizeof(k[0]);
+
+// The message provided to both SHA-256 and HMAC-SHA-256; it is
+// "The fugacity of a constituent in a mixture of gases at a given
+// temperature is proportional to its mole fraction. Lewis-Randall Rule",
+// chosen as one of the longer test vectors.
+static const std::uint8_t m[] = {
+ 0x54, 0x68, 0x65, 0x20, 0x66, 0x75, 0x67, 0x61,
+ 0x63, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20,
+ 0x61, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x69,
+ 0x74, 0x75, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e,
+ 0x20, 0x61, 0x20, 0x6d, 0x69, 0x78, 0x74, 0x75,
+ 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x61,
+ 0x73, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x61,
+ 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x74,
+ 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75,
+ 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72,
+ 0x6f, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f, 0x6e,
+ 0x61, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74,
+ 0x73, 0x20, 0x6d, 0x6f, 0x6c, 0x65, 0x20, 0x66,
+ 0x72, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x20, 0x20, 0x4c, 0x65, 0x77, 0x69, 0x73, 0x2d,
+ 0x52, 0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6c, 0x20,
+ 0x52, 0x75, 0x6c, 0x65
+};
+
+// d is the expected result of SHA256(m).
+static constexpr std::uint8_t d[emsha::SHA256_HASH_SIZE] = {
+ 0x39, 0x55, 0x85, 0xce, 0x30, 0x61, 0x7b, 0x62,
+ 0xc8, 0x0b, 0x93, 0xe8, 0x20, 0x8c, 0xe8, 0x66,
+ 0xd4, 0xed, 0xc8, 0x11, 0xa1, 0x77, 0xfd, 0xb4,
+ 0xb8, 0x2d, 0x39, 0x11, 0xd8, 0x69, 0x64, 0x23
+};
+
+// t is the expected result of HMAC-SHA-256(k, m).
+static constexpr std::uint8_t t[emsha::SHA256_HASH_SIZE] = {
+ 0xbb, 0xc4, 0x7c, 0x35, 0x33, 0x4b, 0x9d, 0x90,
+ 0xee, 0x20, 0x88, 0x30, 0xe1, 0x1a, 0x0f, 0xf3,
+ 0xf4, 0x7d, 0xcc, 0xb0, 0xc5, 0xfb, 0x83, 0xe5,
+ 0xc2, 0xf5, 0xa7, 0x94, 0x50, 0xb6, 0xe0, 0xe0,
+};
+
+// dig is used to store the output of SHA-256 and HMAC-SHA-256.
+static std::uint8_t dig[emsha::SHA256_HASH_SIZE];
+
+
+static void
+init()
+{
+ std::fill(dig, dig + emsha::SHA256_HASH_SIZE, 0);
+}
+
+
+static void
+iterateSHA()
+{
+ emsha::SHA256 ctx;
+ int cmp = 0;
+ emsha::EMSHA_RESULT res;
+
+ res = ctx.Update(m, sizeof(m));
+ assert(emsha::EMSHA_ROK == res);
+ res = ctx.Result(dig);
+ assert(emsha::EMSHA_ROK == res);
+
+ cmp = std::memcmp(dig, d, emsha::SHA256_HASH_SIZE);
+ assert(0 == cmp);
+}
+
+
+static void
+iterateHMAC()
+{
+ emsha::HMAC ctx(k, kl);
+ int cmp = 0;
+ emsha::EMSHA_RESULT res;
+
+ res = ctx.Update(m, sizeof(m));
+ assert(emsha::EMSHA_ROK == res);
+ res = ctx.Result(dig);
+ assert(emsha::EMSHA_ROK == res);
+
+ cmp = std::memcmp(dig, t, emsha::SHA256_HASH_SIZE);
+ assert(0 == cmp);
+}
+
+
+static void
+iterateSHASP()
+{
+ int cmp = 0;
+
+ assert(emsha::EMSHA_ROK == emsha::sha256Digest(m, sizeof(m), dig));
+ cmp = std::memcmp(dig, d, emsha::SHA256_HASH_SIZE);
+ assert(0 == cmp);
+}
+
+
+static void
+iterateHMACSP()
+{
+ int cmp = 0;
+ emsha::EMSHA_RESULT res;
+
+ res = emsha::ComputeHMAC(k, kl, m, sizeof(m), dig);
+ assert(emsha::EMSHA_ROK == res);
+
+ cmp = std::memcmp(dig, t, emsha::SHA256_HASH_SIZE);
+ assert(0 == cmp);
+}
+
+
+static void
+iterate(const std::string &label, void(iteration)(void))
+{
+ std::cout << "=== " << label << " ===" << std::endl;
+ auto start = std::chrono::steady_clock::now();
+
+ for (std::uint32_t i = 0; i < ITERS; i++) {
+ iteration();
+ }
+
+ auto end = std::chrono::steady_clock::now();
+ auto delta = (end - start);
+
+ std::cout << "Total time: "
+ << std::chrono::duration(delta).count()
+ << " ms" << std::endl;
+ std::cout << "Average over " << ITERS << " tests: "
+ << std::chrono::duration(delta).count() / ITERS
+ << " ns" << std::endl;
+}
+
+
+static void
+coldStart()
+{
+ std::cout << "=== SHA-256 cold start ===\n";
+ auto start = std::chrono::steady_clock::now();
+
+ iterateSHA();
+
+ auto end = std::chrono::steady_clock::now();
+ auto delta = (end - start);
+
+ std::cout << "Total time: "
+ << std::chrono::duration(delta).count()
+ << " ns" << std::endl;
+}
+
+int
+main()
+{
+ init();
+
+ coldStart();
+ iterate("SHA-256", iterateSHA);
+ iterate("SHA-256 single-pass", iterateSHASP);
+ iterate("HMAC-SHA-256", iterateHMAC);
+ iterate("HMAC-SHA-256 single-pass", iterateHMACSP);
+}
diff --git a/src/test_sha256.cc b/test_sha256.cc
similarity index 88%
rename from src/test_sha256.cc
rename to test_sha256.cc
index 68fb0df..5436248 100644
--- a/src/test_sha256.cc
+++ b/test_sha256.cc
@@ -23,19 +23,17 @@
*/
-#include
-#include
#include
+#include
+#include
-#include
-
-#include "test_utils.hh"
+#include "test_utils.h"
using namespace std;
// Tests taken from the Go SHA-256 package.
-const struct hash_test golden_tests[] = {
+const struct hashTest goldenTests[] = {
{"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
{"ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", "a"},
{"fb8e20fc2e4c3f248c60c39bd652f3c1347298bb977b8b4d5903b85055620603", "ab"},
@@ -69,32 +67,33 @@ const struct hash_test golden_tests[] = {
{"4f9b189a13d030838269dce846b16a1ce9ce81fe63e65de2f636863336a98fe6", "How can you write a big system without C++? -Paul Glick"},
};
+static constexpr auto numGoldenTests = sizeof goldenTests / sizeof goldenTests[0];
+static const std::string labelGoldenTests = "golden tests";
int
-main(void)
+main()
{
- int res;
-
#ifdef EMSHA_NO_SELFTEST
cout << "[NOTICE] internal self-tests have been disabled.\n";
#else
- res = emsha::sha256_self_test();
- switch (res) {
+ auto selfTestStatus = emsha::sha256SelfTest();
+ switch (selfTestStatus) {
case emsha::EMSHA_ROK:
- cout << "PASSED: SHA-256 self test" << endl;
+ cout << "PASSED: SHA-256 self test\n";
break;
case emsha::EMSHA_TEST_FAILURE:
- cout << "FAILED: SHA-256 self test (test failure)" << endl;
+ cout << "FAILED: SHA-256 self test (test failure)\n";
break;
default:
- cout << "FAILED: SHA-256 self test (fault " << res << ")"
- << endl;
+ cout << "FAILED: SHA-256 self test (fault " << selfTestStatus << ")\n";
}
+ assert(selfTestStatus == emsha::EMSHA_ROK);
#endif
- res = run_hash_tests(const_cast(golden_tests),
- sizeof golden_tests / sizeof golden_tests[0],
- "golden tests");
- if (-1 == res) {
+
+
+ auto res = runHashTests(static_cast(goldenTests),
+ numGoldenTests, labelGoldenTests);
+ if (res == -1) {
exit(1);
}
diff --git a/src/test_utils.cc b/test_utils.cc
similarity index 80%
rename from src/test_utils.cc
rename to test_utils.cc
index 8c2b55b..39dd2e6 100644
--- a/src/test_utils.cc
+++ b/test_utils.cc
@@ -28,7 +28,7 @@
#include
#include
-#include "test_utils.hh"
+#include "test_utils.h"
using std::uint8_t;
using std::uint32_t;
@@ -39,14 +39,14 @@ using std::endl;
void
-dump_hexstring(string& hs, uint8_t *s, uint32_t sl)
+DumpHexString(std::string& hs, uint8_t *s, uint32_t sl)
{
- uint32_t bl = (2 * sl) + 1;
+ uint32_t const bl = (2 * sl) + 1;
char *buf = new char[bl];
string tmp;
memset(buf, 0, bl);
- emsha::hexstring((uint8_t *)buf, s, sl);
+ emsha::HexString(reinterpret_cast(buf), s, sl);
tmp = string(buf);
hs.swap(tmp);
delete[] buf;
@@ -54,25 +54,25 @@ dump_hexstring(string& hs, uint8_t *s, uint32_t sl)
emsha::EMSHA_RESULT
-run_hmac_test(struct hmac_test test, string label)
+runHMACTest(const struct hmacTest test, const string& label)
{
emsha::HMAC h(test.key, test.keylen);
emsha::EMSHA_RESULT res;
uint8_t dig[emsha::SHA256_HASH_SIZE];
- string hs = "";
+ string hs;
- res = h.update((uint8_t *)test.input.c_str(), test.input.size());
+ res = h.Update((uint8_t *)test.input.c_str(), test.input.size());
if (emsha::EMSHA_ROK != res) {
goto exit;
}
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
- res = h.result(dig);
+ res = h.Result(dig);
if (emsha::EMSHA_ROK != res) {
goto exit;
}
- dump_hexstring(hs, dig, emsha::SHA256_HASH_SIZE);
+ DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
if (hs != test.output) {
res = emsha::EMSHA_TEST_FAILURE;
goto exit;
@@ -81,20 +81,20 @@ run_hmac_test(struct hmac_test test, string label)
}
// Ensure that a reset and update gives the same results.
- h.reset();
+ h.Reset();
- res = h.update((uint8_t *)test.input.c_str(), test.input.size());
+ res = h.Update((uint8_t *)test.input.c_str(), test.input.size());
if (emsha::EMSHA_ROK != res) {
goto exit;
}
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
- res = h.result(dig);
+ res = h.Result(dig);
if (emsha::EMSHA_ROK != res) {
goto exit;
}
- dump_hexstring(hs, dig, emsha::SHA256_HASH_SIZE);
+ DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
if (hs != test.output) {
res = emsha::EMSHA_TEST_FAILURE;
goto exit;
@@ -103,7 +103,7 @@ run_hmac_test(struct hmac_test test, string label)
}
// Test that the single-pass function works.
- res = emsha::compute_hmac(test.key, test.keylen,
+ res = emsha::ComputeHMAC(test.key, test.keylen,
(uint8_t *)test.input.c_str(), test.input.size(),
dig);
if (emsha::EMSHA_ROK != res) {
@@ -111,7 +111,7 @@ run_hmac_test(struct hmac_test test, string label)
goto exit;
}
- dump_hexstring(hs, dig, emsha::SHA256_HASH_SIZE);
+ DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
if (hs != test.output) {
cerr << "(comparing single pass function output)\n";
res = emsha::EMSHA_TEST_FAILURE;
@@ -134,38 +134,38 @@ exit:
int
-run_hmac_tests(struct hmac_test *tests, uint32_t ntests, string label)
+runHMACTests(const struct hmacTest *tests, size_t nTests, const string& label)
{
- for (uint32_t i = 0; i < ntests; i++) {
- if (emsha::EMSHA_ROK != run_hmac_test(*(tests + i), label)) {
+ for (uint32_t i = 0; i < nTests; i++) {
+ if (emsha::EMSHA_ROK != runHMACTest(*(tests + i), label)) {
return -1;
}
}
- cout << "PASSED: " << label << " (" << ntests << ")" << endl;
+ cout << "PASSED: " << label << " (" << nTests << ")" << endl;
return 0;
}
emsha::EMSHA_RESULT
-run_hash_test(struct hash_test test, string label)
+runHashTest(const struct hashTest& test, const string& label)
{
emsha::SHA256 ctx;
emsha::EMSHA_RESULT res;
uint8_t dig[emsha::SHA256_HASH_SIZE];
string hs;
- res = ctx.update((uint8_t *)test.input.c_str(), test.input.size());
+ res = ctx.Update((uint8_t *)test.input.c_str(), test.input.size());
if (emsha::EMSHA_ROK != res) {
goto exit;
}
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
- res = ctx.result(dig);
+ res = ctx.Result(dig);
if (emsha::EMSHA_ROK != res) {
goto exit;
}
- dump_hexstring(hs, dig, emsha::SHA256_HASH_SIZE);
+ DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
if (hs != test.output) {
res = emsha::EMSHA_TEST_FAILURE;
goto exit;
@@ -174,20 +174,20 @@ run_hash_test(struct hash_test test, string label)
}
// Ensure that a reset and update gives the same results.
- ctx.reset();
+ ctx.Reset();
- res = ctx.update((uint8_t *)test.input.c_str(), test.input.size());
+ res = ctx.Update((uint8_t *)test.input.c_str(), test.input.size());
if (emsha::EMSHA_ROK != res) {
goto exit;
}
for (uint32_t n = 0; n < RESULT_ITERATIONS; n++) {
- res = ctx.result(dig);
+ res = ctx.Result(dig);
if (emsha::EMSHA_ROK != res) {
goto exit;
}
- dump_hexstring(hs, dig, emsha::SHA256_HASH_SIZE);
+ DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
if (hs != test.output) {
res = emsha::EMSHA_TEST_FAILURE;
goto exit;
@@ -196,14 +196,14 @@ run_hash_test(struct hash_test test, string label)
}
// Test that the single-pass function works.
- res = emsha::sha256_digest((uint8_t *)test.input.c_str(),
- test.input.size(), dig);
+ res = emsha::sha256Digest((uint8_t *) test.input.c_str(),
+ test.input.size(), dig);
if (emsha::EMSHA_ROK != res) {
cerr << "(running single pass function test)\n";
goto exit;
}
- dump_hexstring(hs, dig, emsha::SHA256_HASH_SIZE);
+ DumpHexString(hs, dig, emsha::SHA256_HASH_SIZE);
if (hs != test.output) {
cerr << "(comparing single pass function output)\n";
res = emsha::EMSHA_TEST_FAILURE;
@@ -224,10 +224,10 @@ exit:
int
-run_hash_tests(struct hash_test *tests, uint32_t ntests, string label)
+runHashTests(const struct hashTest *tests, const size_t ntests, const string& label)
{
for (uint32_t i = 0; i < ntests; i++) {
- if (emsha::EMSHA_ROK != run_hash_test(*(tests + i), label)) {
+ if (emsha::EMSHA_ROK != runHashTest(*(tests + i), label)) {
return -1;
}
}
@@ -284,7 +284,7 @@ write_hex_char(uint8_t *dest, uint8_t src)
void
-hexstring(uint8_t *dest, uint8_t *src, uint32_t srclen)
+HexString(uint8_t *dest, uint8_t *src, uint32_t srclen)
{
uint8_t *dp = dest;
diff --git a/src/test_utils.hh b/test_utils.h
similarity index 78%
rename from src/test_utils.hh
rename to test_utils.h
index 5719ea6..52a40dc 100644
--- a/src/test_utils.hh
+++ b/test_utils.h
@@ -30,9 +30,9 @@
#include
#include
-#include
-#include
-#include
+#include
+#include
+#include
// How many times should a test result be checked? The goal is to
@@ -44,13 +44,13 @@ constexpr uint32_t RESULT_ITERATIONS = 5;
// Test data structures.
-struct hash_test {
+struct hashTest {
std::string output;
std::string input;
};
-struct hmac_test {
+struct hmacTest {
std::uint8_t key[256];
std::uint32_t keylen;
std::string input;
@@ -59,20 +59,20 @@ struct hmac_test {
// General-purpose debuggery.
-void dump_hexstring(std::string&, std::uint8_t *, std::uint32_t);
+void DumpHexString(std::string&, std::uint8_t *, std::uint32_t);
void dump_pair(std::uint8_t *, std::uint8_t *);
// SHA-256 testing functions.
-emsha::EMSHA_RESULT run_hash_test(struct hash_test, std::string);
-int run_hash_tests(struct hash_test *, std::uint32_t,
- std::string);
+emsha::EMSHA_RESULT runHashTest(const struct hashTest& test, const std::string& label);
+int runHashTests(const struct hashTest *tests, const std::size_t nTests,
+ const std::string& label);
// HMAC-SHA-256 testery.
-emsha::EMSHA_RESULT run_hmac_test(struct hmac_test, std::string);
-int run_hmac_tests(struct hmac_test *, std::uint32_t,
- std::string);
+emsha::EMSHA_RESULT runHMACTest(struct hmacTest test, const std::string& label);
+int runHMACTests(const struct hmacTest *tests, std::size_t nTests,
+ const std::string& label);
#ifdef EMSHA_NO_HEXSTRING