Moved dependencies into separate repo
All checks were successful
/ Build the server (push) Successful in 3m4s

This commit is contained in:
Mutzi 2023-10-24 11:38:52 +02:00
parent 023ef2ec49
commit 7334bd8e71
Signed by: root
GPG Key ID: 2437494E09F13876
4061 changed files with 11 additions and 773576 deletions

View File

@ -10,5 +10,8 @@
<file path="$PROJECT_DIR$/lib/restbed-4.8" />
<file path="$PROJECT_DIR$/phc-winner-argon2-20190702" />
</libraryRoots>
<excludeRoots>
<file path="$PROJECT_DIR$/cmake-build-debug" />
</excludeRoots>
</component>
</project>

View File

@ -1,55 +0,0 @@
Language: Cpp
Standard: c++20
BasedOnStyle: Chromium
ColumnLimit: 120
AccessModifierOffset: -3
IndentWidth: 3
ContinuationIndentWidth: 3
ConstructorInitializerIndentWidth: 6
PointerAlignment: Left
ReferenceAlignment: Left
QualifierAlignment: Left
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^<botan/internal/.*\.h>'
Priority: 3
CaseSensitive: false
- Regex: '^<botan/.*\.h>'
Priority: 2
CaseSensitive: false
- Regex: '^<.*'
Priority: 4
CaseSensitive: false
- Regex: '^<.*\.h>'
Priority: 3
CaseSensitive: false
- Regex: '.*'
Priority: 1
CaseSensitive: false
AttributeMacros: ['BOTAN_FUNC_ISA', 'BOTAN_FUNC_ISA_INLINE', 'BOTAN_FORCE_INLINE']
BinPackArguments: false
BreakStringLiterals: false
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
EmptyLineBeforeAccessModifier: Always
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterComma
AllowShortBlocksOnASingleLine: Empty
AllowShortFunctionsOnASingleLine: Inline
SpaceBeforeParens: Never
IndentPPDirectives: BeforeHash
FixNamespaceComments: true
SeparateDefinitionBlocks: Always
KeepEmptyLinesAtTheStartOfBlocks: false
IndentAccessModifiers: true
ReflowComments: false
RequiresClausePosition: OwnLine
IndentRequiresClause: true

View File

@ -1,54 +0,0 @@
# (C) 2022 Jack Lloyd
# (C) 2022 René Meusel, Rohde & Schwarz Cybersecurity
#
# Botan is released under the Simplified BSD License (see license.txt)
name: Setup Botan Build Agent
description: Set up a build agent for building and testing the Botan library
inputs:
target:
description: The ci_build.py target going to be built on this agent
required: true
cache-key:
description: The actions/cache key to be used for this runs, caching will be disabled when no key is provided
required: false
arch:
description: Target CPU architecture
required: false
default: x64
runs:
using: composite
steps:
- name: Setup Build Agent (Windows)
run: ${{ github.action_path }}/../../../src/scripts/ci/setup_gh_actions.ps1 "${{ inputs.target }}" "${{ inputs.arch }}"
shell: pwsh
if: runner.os == 'Windows'
- name: Setup Build Agent (Unix-like)
run: ${{ github.action_path }}/../../../src/scripts/ci/setup_gh_actions.sh "${{ inputs.target }}" "${{ inputs.arch }}"
shell: bash
if: runner.os != 'Windows'
- name: Check Availability of Compiler Cache
run: print("::warning ::No compiler cache available, build times might suffer")
shell: python
if: env.COMPILER_CACHE_LOCATION == '' && inputs.cache-key != ''
- uses: actions/cache@v3
if: env.COMPILER_CACHE_LOCATION != '' && inputs.cache-key != ''
with:
path: ${{ env.COMPILER_CACHE_LOCATION }}
key: ${{ inputs.cache-key }}-${{ github.run_id }}
restore-keys: ${{ inputs.cache-key }}
- name: Setup Visual Studio Environment
uses: egor-tensin/vs-shell@v2
with:
arch: ${{ env.VSENV_ARCH }} # set by setup_gh_actions.ps1
if: runner.os == 'Windows'
- name: Install Build Dependencies # after setting up Visual Studio Environment
run: ${{ github.action_path }}/../../../src/scripts/ci/setup_gh_actions_after_vcvars.ps1 ${{ inputs.target }}
shell: pwsh
if: runner.os == 'Windows'

View File

@ -1 +0,0 @@
../src/scripts/ci/codecov.yml

View File

@ -1,291 +0,0 @@
# (C) 2020,2022 Jack Lloyd
# (C) 2022 René Meusel, Rohde & Schwarz Cybersecurity
#
# Botan is released under the Simplified BSD License (see license.txt)
name: ci
permissions:
contents: read
# implicitly all other scopes not listed become none
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
# cancel running workflows when new commits are being pushed in pull requests
# but not on the master branch
concurrency:
group: ${{ github.workflow }} @ ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
windows:
name: "Windows"
strategy:
fail-fast: false
matrix:
include:
- target: shared
arch: x86_64
host_os: windows-2022
- target: static
arch: x86_64
host_os: windows-2022
- target: amalgamation
arch: x86_64
host_os: windows-2022
- target: shared
arch: x86
host_os: windows-2022
runs-on: ${{ matrix.host_os }}
steps:
- uses: actions/checkout@v3
- name: Setup Build Agent
uses: ./.github/actions/setup-build-agent
with:
target: ${{ matrix.target }}
cache-key: ${{ matrix.host_os }}-msvc-${{ matrix.arch }}-${{ matrix.target }}
arch: ${{ matrix.arch }}
- name: Build and Test Botan
run: python3 ./src/scripts/ci_build.py --cc='msvc' --make-tool='ninja' --cpu='${{ matrix.arch }}' --test-results-dir=junit_results ${{ matrix.target }}
linux:
name: "Linux"
strategy:
fail-fast: false
matrix:
include:
- compiler: gcc
target: shared
- compiler: gcc
target: amalgamation
- compiler: gcc
target: static
- compiler: clang
target: shared
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Setup Build Agent
uses: ./.github/actions/setup-build-agent
with:
target: ${{ matrix.target }}
cache-key: linux-${{ matrix.compiler }}-x86_64-${{ matrix.target }}
- name: Build and Test Botan
run: python3 ./src/scripts/ci_build.py --cc='${{ matrix.compiler }}' --test-results-dir=junit_results ${{ matrix.target }}
macos:
name: "macOS"
strategy:
fail-fast: false
matrix:
include:
- target: shared
compiler: clang
- target: amalgamation
compiler: clang
runs-on: macos-13
steps:
- uses: actions/checkout@v3
- name: Setup Build Agent
uses: ./.github/actions/setup-build-agent
with:
target: ${{ matrix.target }}
cache-key: macos-${{ matrix.compiler }}-x86_64-${{ matrix.target }}
- name: Build and Test Botan
run: python3 ./src/scripts/ci_build.py --cc='${{ matrix.compiler }}' --test-results-dir=junit_results ${{ matrix.target }}
clang-tidy:
name: "Clang Tidy"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Setup Build Agent
uses: ./.github/actions/setup-build-agent
with:
target: clang-tidy
cache-key: linux-x86_64-clang-tidy
- name: Configure Build
run: python3 ./configure.py --cc=clang
- name: Run Clang Tidy
run: |
./src/scripts/ci/gh_get_changes_in_pr.py $(git rev-parse HEAD) --api-token=${{ secrets.GITHUB_TOKEN }} | \
python3 ./src/scripts/dev_tools/run_clang_tidy.py --verbose --take-file-list-from-stdin --export-fixes-dir=clang_tidy_diagnostics
- name: Display Clang Tidy Results
if: failure()
run: ./src/scripts/ci/gh_clang_tidy_fixes_in_pr.py clang_tidy_diagnostics
analysis:
name: "Analysis"
strategy:
fail-fast: false
matrix:
include:
- target: coverage
compiler: gcc
host_os: ubuntu-22.04
- target: sanitizer
compiler: msvc
host_os: windows-2022
make_tool: ninja
- target: sanitizer
compiler: clang
host_os: ubuntu-22.04
- target: sanitizer
compiler: gcc
host_os: ubuntu-22.04
- target: valgrind
compiler: gcc
host_os: ubuntu-22.04
- target: fuzzers
compiler: gcc
host_os: ubuntu-22.04
- target: lint
compiler: gcc
host_os: ubuntu-22.04
- target: format
compiler: gcc
host_os: ubuntu-22.04
runs-on: ${{ matrix.host_os }}
env:
COVERALLS_REPO_TOKEN: pbLoTMBxC1DFvbws9WfrzVOvfEdEZTcCS
steps:
- uses: actions/checkout@v3
with:
path: ./source
- name: Fetch BoringSSL fork for BoGo tests
uses: actions/checkout@v3
with:
repository: randombit/boringssl
ref: rene/runner-20230705
path: ./boringssl
if: matrix.target == 'coverage' || matrix.target == 'sanitizer'
- name: Setup Build Agent
uses: ./source/.github/actions/setup-build-agent
with:
target: ${{ matrix.target }}
cache-key: ${{ matrix.host_os }}-${{ matrix.compiler }}-x86_64-${{ matrix.target }}
- name: Build and Test Botan
run: python3 ./source/src/scripts/ci_build.py --root-dir=${{ github.workspace }}/source --build-dir=${{ github.workspace }}/build --boringssl-dir=${{ github.workspace }}/boringssl --cc='${{ matrix.compiler }}' --make-tool='${{ matrix.make_tool }}' --test-results-dir=junit_results ${{ matrix.target }}
specials:
name: "Special"
strategy:
fail-fast: false
matrix:
include:
- target: examples
compiler: gcc
host_os: ubuntu-22.04
- target: minimized
compiler: gcc
host_os: ubuntu-22.04
- target: bsi
compiler: gcc
host_os: ubuntu-22.04
runs-on: ${{ matrix.host_os }}
steps:
- uses: actions/checkout@v3
with:
path: ./source
- name: Setup Build Agent
uses: ./source/.github/actions/setup-build-agent
with:
target: ${{ matrix.target }}
cache-key: ${{ matrix.host_os }}-${{ matrix.compiler }}-x86_64-${{ matrix.target }}
- name: Build and Test Botan
run: python3 ./source/src/scripts/ci_build.py --root-dir=${{ github.workspace }}/source --build-dir=${{ github.workspace }}/build --boringssl-dir=${{ github.workspace }}/boringssl --cc='${{ matrix.compiler }}' --make-tool='${{ matrix.make_tool }}' --test-results-dir=junit_results ${{ matrix.target }}
x-compile:
name: "Cross"
strategy:
fail-fast: false
matrix:
include:
- target: cross-i386
compiler: gcc
host_os: ubuntu-22.04
- target: cross-arm32
compiler: gcc
host_os: ubuntu-22.04
- target: cross-arm64
compiler: gcc
host_os: ubuntu-22.04
- target: cross-ppc64
compiler: gcc
host_os: ubuntu-22.04
- target: cross-riscv64
compiler: gcc
host_os: ubuntu-22.04
- target: cross-s390x
compiler: gcc
host_os: ubuntu-22.04
- target: cross-android-arm32
compiler: clang
host_os: ubuntu-22.04
- target: cross-android-arm64
compiler: clang
host_os: ubuntu-22.04
- target: static
compiler: gcc
host_os: windows-2022
make_tool: mingw32-make
- target: cross-ios-arm64
compiler: clang
host_os: macos-13
- target: emscripten
compiler: emcc
host_os: macos-13
runs-on: ${{ matrix.host_os }}
env:
ANDROID_NDK: android-ndk-r26
steps:
- uses: actions/checkout@v3
- name: Setup Build Agent
uses: ./.github/actions/setup-build-agent
with:
target: ${{ matrix.target }}
cache-key: ${{ matrix.host_os }}-${{ matrix.compiler }}-xcompile-${{ matrix.target }}
- name: Build and Test Botan
run: python3 ./src/scripts/ci_build.py --cc='${{ matrix.compiler }}' --test-results-dir=junit_results ${{ matrix.target }}

View File

@ -1,29 +0,0 @@
name: CIFuzz
permissions:
contents: read
# implicitly all other scopes not listed become none
on: [pull_request]
jobs:
Fuzzing:
runs-on: ubuntu-22.04
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'botan'
dry-run: false
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'botan'
fuzz-seconds: 180
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v1
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts

View File

@ -1,70 +0,0 @@
name: "CodeQL"
on:
push:
branches: ["master"]
pull_request:
# The branches below must be a subset of the branches above
branches: ["master"]
schedule:
# runs every day at 4:23 AM UTC
- cron: "23 4 * * *"
permissions:
contents: read
jobs:
codeql_cpp:
name: C++
runs-on: ubuntu-22.04
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Build Agent
uses: ./.github/actions/setup-build-agent
with:
target: codeql
cache-key: linux-gcc-x86_64-codeql
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: cpp
config-file: ./src/configs/codeql.yml
- name: Build Library
run: ./src/scripts/ci_build.py codeql
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: cpp
codeql_py:
name: Python
runs-on: ubuntu-22.04
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: python
config-file: ./src/configs/codeql.yml
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: python

View File

@ -1,89 +0,0 @@
# (C) 2023 Jack Lloyd
# (C) 2023 Fabian Albert, Rohde & Schwarz Cybersecurity
#
# Botan is released under the Simplified BSD License (see license.txt)
name: nightly
permissions:
contents: read
# implicitly all other scopes not listed become none
on:
schedule:
# runs every day at 3:23 AM UTC
- cron: '23 3 * * *'
jobs:
clang_tidy:
name: "clang-tidy"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Setup Build Agent
uses: ./.github/actions/setup-build-agent
with:
target: clang-tidy
cache-key: linux-x86_64-clang-tidy
- name: Install Boost
run: sudo apt-get -qq install libboost-dev
- name: Configure Build
run: python3 ./configure.py --cc=clang --build-targets=shared,cli,tests,examples,bogo_shim --build-fuzzers=test --with-boost --with-sqlite --with-zlib --with-lzma --with-bzip2
- name: Run Clang Tidy
run: python3 ./src/scripts/dev_tools/run_clang_tidy.py --verbose
valgrind:
name: "valgrind"
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Setup Build Agent
uses: ./.github/actions/setup-build-agent
with:
target: valgrind-full
cache-key: linux-x86_64-valgrind-full
- name: Valgrind Checks
run: python3 ./src/scripts/ci_build.py --cc=gcc --make-tool=make valgrind-full
tls_anvil_server_test:
name: "TLS-Anvil (server)"
runs-on: ubuntu-22.04
steps:
- name: Fetch Botan Repository
uses: actions/checkout@v3
- name: Setup Build Agent
uses: ./.github/actions/setup-build-agent
with:
target: tlsanvil
cache-key: linux-x86_64-tlsanvil
- name: Build and Test Botan Server with TLS-Anvil
run: >
python3 ./src/scripts/ci/ci_tlsanvil_test.py
--botan-dir .
--test-target server
--parallel $(nproc)
- uses: actions/upload-artifact@v3
with:
name: tls-anvil-server-test-results
path: |
./TestSuiteResults/
./logs/
- name: Check TLS-Anvil Test Results
run: python3 ./src/scripts/ci/ci_tlsanvil_check.py --verbose ./TestSuiteResults

View File

@ -1,98 +0,0 @@
/Makefile
CMakeLists.txt*
build.ninja
.ninja_log
libbotan*.so.*
*.a
*.so
*.dylib
*.exp
*.lib
*.pdb
*.ilk
*.dll
*.exe
*.manifest
build
build_deps
build.log
botan
botan-test
core.*
vgcore.*
# Text file backups (e.g. gedit, joe)
*~
\#*\#
.\#*
# Editor configuration files (top level)
/*.sublime-project
/*.sublime-workspace
/.editorconfig
# Archive files
*.tgz
*.tar
# Logs
*.log
# Patch files
*.patch
*.diff
*.orig
*.rej
# Cache and temporary files
*.pyc
.DS_Store
*.swp
/*.cache
# ctags/etags files
/TAGS
/tags
# Amalgamation code
botan_all.h
botan_all_internal.h
botan_all.cpp
botan_all_*.cpp
# Coverage output
coverage.info
coverage.info.raw
coverage/
lcov-out/
/fuzzer_corpus
# Profiler outputs
cachegrind.*
callgrind.*
# Ignore stuff in the top level dir that shouldn't be checked in
/*.c
/*.cpp
/*.h
/*.py
/*.key
/*.pem
/*.der
/*.ber
/*.gpg
/*.pub
/*.crt
/*.txt
/*.rst
# Add back files from the toplevel
!/news.rst
!/readme.rst
!/configure.py
!/license.txt
# cscope
cscope.out

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +0,0 @@
ABI Stability
====================
Botan uses semantic versioning for the API; if API features are added the minor
version increases, whereas if API compatibility breaks occur the major version
is increased.
However no guarantees about ABI are made between releases. Maintaining an ABI
compatible release in a complex C++ API is exceedingly expensive in development
time; just adding a single member variable or virtual function is enough to
cause ABI issues.
If ABI changes, the soname revision will increase to prevent applications from
linking against a potentially incompatible version at runtime.
If you are concerned about long-term ABI issues, considering using the C API
instead; this subset *is* ABI stable.
You can review a report on ABI changes to Botan at
https://abi-laboratory.pro/tracker/timeline/botan/

View File

@ -1,279 +0,0 @@
BigInt
========================================
``BigInt`` is Botan's implementation of a multiple-precision integer. Thanks to
C++'s operator overloading features, using ``BigInt`` is often quite similar to
using a native integer type. The number of functions related to ``BigInt`` is
quite large, and not all of them are documented here. You can find the complete
declarations in ``botan/bigint.h`` and ``botan/numthry.h``.
.. cpp:class:: BigInt
.. cpp:function:: BigInt()
Create a BigInt with value zero
.. cpp:function:: BigInt(uint64_t n)
Create a BigInt with value *n*
.. cpp:function:: BigInt(const std::string& str)
Create a BigInt from a string. By default decimal is expected. With an 0x
prefix instead it is treated as hexadecimal.
.. cpp:function:: BigInt(const uint8_t buf[], size_t length)
Create a BigInt from a binary array (big-endian encoding).
.. cpp:function:: BigInt(RandomNumberGenerator& rng, size_t bits, bool set_high_bit = true)
Create a random BigInt of the specified size.
.. cpp:function:: BigInt operator+(const BigInt& x, const BigInt& y)
Add ``x`` and ``y`` and return result.
.. cpp:function:: BigInt operator+(const BigInt& x, word y)
Add ``x`` and ``y`` and return result.
.. cpp:function:: BigInt operator+(word x, const BigInt& y)
Add ``x`` and ``y`` and return result.
.. cpp:function:: BigInt operator-(const BigInt& x, const BigInt& y)
Subtract ``y`` from ``x`` and return result.
.. cpp:function:: BigInt operator-(const BigInt& x, word y)
Subtract ``y`` from ``x`` and return result.
.. cpp:function:: BigInt operator*(const BigInt& x, const BigInt& y)
Multiply ``x`` and ``y`` and return result.
.. cpp:function:: BigInt operator/(const BigInt& x, const BigInt& y)
Divide ``x`` by ``y`` and return result.
.. cpp:function:: BigInt operator%(const BigInt& x, const BigInt& y)
Divide ``x`` by ``y`` and return remainder.
.. cpp:function:: word operator%(const BigInt& x, word y)
Divide ``x`` by ``y`` and return remainder.
.. cpp:function:: word operator<<(const BigInt& x, size_t n)
Left shift ``x`` by ``n`` and return result.
.. cpp:function:: word operator>>(const BigInt& x, size_t n)
Right shift ``x`` by ``n`` and return result.
.. cpp:function:: BigInt& operator+=(const BigInt& y)
Add y to ``*this``
.. cpp:function:: BigInt& operator+=(word y)
Add y to ``*this``
.. cpp:function:: BigInt& operator-=(const BigInt& y)
Subtract y from ``*this``
.. cpp:function:: BigInt& operator-=(word y)
Subtract y from ``*this``
.. cpp:function:: BigInt& operator*=(const BigInt& y)
Multiply ``*this`` with y
.. cpp:function:: BigInt& operator*=(word y)
Multiply ``*this`` with y
.. cpp:function:: BigInt& operator/=(const BigInt& y)
Divide ``*this`` by y
.. cpp:function:: BigInt& operator%=(const BigInt& y)
Divide ``*this`` by y and set ``*this`` to the remainder.
.. cpp:function:: word operator%=(word y)
Divide ``*this`` by y and set ``*this`` to the remainder.
.. cpp:function:: word operator<<=(size_t shift)
Left shift ``*this`` by *shift* bits
.. cpp:function:: word operator>>=(size_t shift)
Right shift ``*this`` by *shift* bits
.. cpp:function:: BigInt& operator++()
Increment ``*this`` by 1
.. cpp:function:: BigInt& operator--()
Decrement ``*this`` by 1
.. cpp:function:: BigInt operator++(int)
Postfix increment ``*this`` by 1
.. cpp:function:: BigInt operator--(int)
Postfix decrement ``*this`` by 1
.. cpp:function:: BigInt operator-() const
Negation operator
.. cpp:function:: bool operator !() const
Return true unless ``*this`` is zero
.. cpp:function:: void clear()
Set ``*this`` to zero
.. cpp:function:: size_t bytes() const
Return number of bytes need to represent value of ``*this``
.. cpp:function:: size_t bits() const
Return number of bits need to represent value of ``*this``
.. cpp:function:: bool is_even() const
Return true if ``*this`` is even
.. cpp:function:: bool is_odd() const
Return true if ``*this`` is odd
.. cpp:function:: bool is_nonzero() const
Return true if ``*this`` is not zero
.. cpp:function:: bool is_zero() const
Return true if ``*this`` is zero
.. cpp:function:: void set_bit(size_t n)
Set bit *n* of ``*this``
.. cpp:function:: void clear_bit(size_t n)
Clear bit *n* of ``*this``
.. cpp:function:: bool get_bit(size_t n) const
Get bit *n* of ``*this``
.. cpp:function:: uint32_t to_u32bit() const
Return value of ``*this`` as a 32-bit integer, if possible.
If the integer is negative or not in range, an exception is thrown.
.. cpp:function:: bool is_negative() const
Return true if ``*this`` is negative
.. cpp:function:: bool is_positive() const
Return true if ``*this`` is negative
.. cpp:function:: BigInt abs() const
Return absolute value of ``*this``
.. cpp:function:: void binary_encode(uint8_t buf[]) const
Encode this BigInt as a big-endian integer. The sign is ignored.
.. cpp:function:: void binary_encode(uint8_t buf[], size_t len) const
Encode this BigInt as a big-endian integer. The sign is ignored.
If ``len`` is less than ``bytes()`` then only the low ``len``
bytes are output. If ``len`` is greater than ``bytes()`` then
the output is padded with leading zeros.
.. cpp:function:: void binary_decode(uint8_t buf[])
Decode this BigInt as a big-endian integer.
.. cpp:function:: std::string to_dec_string() const
Encode the integer as a decimal string.
.. cpp:function:: std::string to_hex_string() const
Encode the integer as a hexadecimal string.
Number Theory
----------------------------------------
Number theoretic functions available include:
.. cpp:function:: BigInt gcd(BigInt x, BigInt y)
Returns the greatest common divisor of x and y
.. cpp:function:: BigInt lcm(BigInt x, BigInt y)
Returns an integer z which is the smallest integer such that z % x
== 0 and z % y == 0
.. cpp:function:: BigInt jacobi(BigInt a, BigInt n)
Return Jacobi symbol of (a|n).
.. cpp:function:: BigInt inverse_mod(BigInt x, BigInt m)
Returns the modular inverse of x modulo m, that is, an integer
y such that (x*y) % m == 1. If no such y exists, returns zero.
.. cpp:function:: BigInt power_mod(BigInt b, BigInt x, BigInt m)
Returns b to the xth power modulo m. If you are doing many
exponentiations with a single fixed modulus, it is faster to use a
``Power_Mod`` implementation.
.. cpp:function:: BigInt ressol(BigInt x, BigInt p)
Returns the square root modulo a prime, that is, returns a number y
such that (y*y) % p == x. Returns -1 if no such integer exists.
.. cpp:function:: bool is_prime(BigInt n, RandomNumberGenerator& rng, \
size_t prob = 56, double is_random = false)
Test *n* for primality using a probabilistic algorithm (Miller-Rabin). With
this algorithm, there is some non-zero probability that true will be returned
even if *n* is actually composite. Modifying *prob* allows you to decrease the
chance of such a false positive, at the cost of increased runtime. Sufficient
tests will be run such that the chance *n* is composite is no more than 1 in
2\ :sup:`prob`. Set *is_random* to true if (and only if) *n* was randomly
chosen (ie, there is no danger it was chosen maliciously) as far fewer tests
are needed in that case.
.. cpp:function:: BigInt random_prime(RandomNumberGenerator& rng, \
size_t bits, \
BigInt coprime = 1, \
size_t equiv = 1, \
size_t equiv_mod = 2)
Return a random prime number of ``bits`` bits long that is
relatively prime to ``coprime``, and equivalent to ``equiv`` modulo
``equiv_mod``.

View File

@ -1,318 +0,0 @@
Block Ciphers
=======================
Block ciphers are a n-bit permutation for some small n, typically 64 or 128
bits. They are a cryptographic primitive used to generate higher level
operations such as authenticated encryption.
.. warning::
In almost all cases, a bare block cipher is not what you should be using.
You probably want an authenticated cipher mode instead (see :ref:`cipher_modes`)
This interface is used to build higher level operations (such as cipher
modes or MACs), or in the very rare situation where ECB is required,
eg for compatibility with an existing system.
.. cpp:class:: BlockCipher
.. cpp:function:: static std::unique_ptr<BlockCipher> create(const std::string& algo_spec, \
const std::string& provider = "")
Create a new block cipher object, or else return null.
.. cpp:function:: static std::unique_ptr<BlockCipher> create_or_throw(const std::string& algo_spec, \
const std::string& provider = "")
Like ``create``, except instead of returning null an exception is thrown
if the cipher is not known.
.. cpp:function:: void set_key(const uint8_t* key, size_t length)
This sets the key to the value specified. Most algorithms only accept keys
of certain lengths. If you attempt to call ``set_key`` with a key length
that is not supported, the exception ``Invalid_Key_Length`` will be
thrown.
In all cases, ``set_key`` must be called on an object before any data
processing (encryption, decryption, etc) is done by that object. If this
is not done, an exception will be thrown.
thrown.
.. cpp:function:: bool valid_keylength(size_t length) const
This function returns true if and only if *length* is a valid keylength for
this algorithm.
.. cpp:function:: size_t minimum_keylength() const
Return the smallest key length (in bytes) that is acceptable for the
algorithm.
.. cpp:function:: size_t maximum_keylength() const
Return the largest key length (in bytes) that is acceptable for the
algorithm.
.. cpp:function:: std::string name() const
Return a human readable name for this algorithm. This is guaranteed to round-trip with
``create`` and ``create_or_throw`` calls, ie create("Foo")->name() == "Foo"
.. cpp:function:: void clear()
Zero out the key. The key must be reset before the cipher object can be used.
.. cpp:function:: std::unique_ptr<BlockCipher> new_object() const
Return a newly allocated BlockCipher object of the same type as this one.
The new object is unkeyed.
.. cpp:function:: size_t block_size() const
Return the size (in *bytes*) of the cipher.
.. cpp:function:: size_t parallelism() const
Return the parallelism underlying this implementation of the cipher. This
value can vary across versions and machines. A return value of N means that
encrypting or decrypting with N blocks can operate in parallel.
.. cpp:function:: size_t parallel_bytes() const
Returns ``parallelism`` multiplied by the block size as well as a small
fudge factor. That's because even ciphers that have no implicit parallelism
typically see a small speedup for being called with several blocks due to
caching effects.
.. cpp:function:: std::string provider() const
Return the provider type. Default value is "base" but can be any arbitrary string.
Other example values are "sse2", "avx2", "openssl".
.. cpp:function:: void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
Encrypt *blocks* blocks of data, taking the input from the array *in* and
placing the ciphertext into *out*. The two pointers may be identical, but
should not overlap ranges.
.. cpp:function:: void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const
Decrypt *blocks* blocks of data, taking the input from the array *in* and
placing the plaintext into *out*. The two pointers may be identical, but
should not overlap ranges.
.. cpp:function:: void encrypt(const uint8_t in[], uint8_t out[]) const
Encrypt a single block. Equivalent to :cpp:func:`encrypt_n`\ (in, out, 1).
.. cpp:function:: void encrypt(uint8_t block[]) const
Encrypt a single block. Equivalent to :cpp:func:`encrypt_n`\ (block, block, 1)
.. cpp:function:: void decrypt(const uint8_t in[], uint8_t out[]) const
Decrypt a single block. Equivalent to :cpp:func:`decrypt_n`\ (in, out, 1)
.. cpp:function:: void decrypt(uint8_t block[]) const
Decrypt a single block. Equivalent to :cpp:func:`decrypt_n`\ (block, block, 1)
.. cpp:function:: template<typename Alloc> void encrypt(std::vector<uint8_t, Alloc>& block) const
Assumes ``block`` is of a multiple of the block size.
.. cpp:function:: template<typename Alloc> void decrypt(std::vector<uint8_t, Alloc>& block) const
Assumes ``block`` is of a multiple of the block size.
Code Example
-----------------
For sheer demonstrative purposes, the following code encrypts a provided single
block of plaintext with AES-256 using two different keys.
.. literalinclude:: /../src/examples/aes.cpp
:language: cpp
Available Ciphers
---------------------
Botan includes a number of block ciphers that are specific to particular countries, as
well as a few that are included mostly due to their use in specific protocols such as PGP
but not widely used elsewhere. If you are developing new code and have no particular
opinion, use AES-256. If you desire an alternative to AES, consider Serpent, SHACAL2 or
Threefish.
.. warning:: Avoid any 64-bit block cipher in new designs. There are
combinatoric issues that affect any 64-bit cipher that render it
insecure when large amounts of data are processed.
AES
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comes in three variants, AES-128, AES-192, and AES-256.
The standard 128-bit block cipher. Many modern platforms offer hardware
acceleration. However, on platforms without hardware support, AES
implementations typically are vulnerable to side channel attacks. For x86
systems with SSSE3 but without AES-NI, Botan has an implementation which avoids
known side channels.
Available if ``BOTAN_HAS_AES`` is defined.
ARIA
~~~~~~
South Korean cipher used in industry there. No reason to use it otherwise.
Available if ``BOTAN_HAS_ARIA`` is defined.
Blowfish
~~~~~~~~~
A 64-bit cipher popular in the pre-AES era. Very slow key setup. Also used (with
bcrypt) for password hashing.
Available if ``BOTAN_HAS_BLOWFISH`` is defined.
CAST-128
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A 64-bit cipher, commonly used in OpenPGP.
Available if ``BOTAN_HAS_CAST128`` is defined.
Camellia
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Comes in three variants, Camellia-128, Camellia-192, and Camellia-256.
A Japanese design standardized by ISO, NESSIE and CRYPTREC.
Rarely used outside of Japan.
Available if ``BOTAN_HAS_CAMELLIA`` is defined.
Cascade
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Creates a block cipher cascade, where each block is encrypted by two ciphers
with independent keys. Useful if you're very paranoid. In practice any single
good cipher (such as Serpent, SHACAL2, or AES-256) is more than sufficient.
Available if ``BOTAN_HAS_CASCADE`` is defined.
DES and 3DES
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Originally designed by IBM and NSA in the 1970s. Today, DES's 56-bit key renders
it insecure to any well-resourced attacker. 3DES extends the key length,
and is still thought to be secure, modulo the limitation of a 64-bit block.
All are somewhat common in some industries such as finance. Avoid in new code.
Available if ``BOTAN_HAS_DES`` is defined.
GOST-28147-89
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Aka "Magma". An old 64-bit Russian cipher. Possible security issues, avoid
unless compatibility is needed.
Available if ``BOTAN_HAS_GOST_28147_89`` is defined.
.. warning::
Support for this cipher is deprecated and will be removed in a future major release.
IDEA
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An older but still unbroken 64-bit cipher with a 128-bit key. Somewhat common
due to its use in PGP. Avoid in new designs.
Available if ``BOTAN_HAS_IDEA`` is defined.
Kuznyechik
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 3.2
Newer Russian national cipher, also known as GOST R 34.12-2015 or "Grasshopper".
.. warning::
The sbox of this cipher is supposedly random, but was found to have a
mathematical structure which is exceedingly unlikely to have occured by
chance. This may indicate the existence of a backdoor or other issue. Avoid
using this cipher unless strictly required.
Available if ``BOTAN_HAS_KUZNYECHIK`` is defined.
Lion
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A "block cipher construction" which can encrypt blocks of nearly arbitrary
length. Built from a stream cipher and a hash function. Useful in certain
protocols where being able to encrypt large or arbitrary length blocks is
necessary.
Available if ``BOTAN_HAS_LION`` is defined.
Noekeon
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A fast 128-bit cipher by the designers of AES. Easily secured against side
channels. Quite obscure however.
Available if ``BOTAN_HAS_NOEKEON`` is defined.
.. warning::
Noekeon support is deprecated and will be removed in a future major release.
SEED
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A older South Korean cipher, widely used in industry there. No reason to choose it otherwise.
Available if ``BOTAN_HAS_SEED`` is defined.
SHACAL2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The 256-bit block cipher used inside SHA-256. Accepts up to a 512-bit key.
Fast, especially when SIMD or SHA-2 acceleration instructions are available.
Standardized by NESSIE but otherwise obscure.
Available if ``BOTAN_HAS_SHACAL2`` is defined.
SM4
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A 128-bit Chinese national cipher, required for use in certain commercial
applications in China. Quite slow. Probably no reason to use it outside of legal
requirements.
Available if ``BOTAN_HAS_SM4`` is defined.
Serpent
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An AES contender. Widely considered the most conservative design. Fairly slow
unless SIMD instructions are available.
Available if ``BOTAN_HAS_SERPENT`` is defined.
Threefish-512
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A 512-bit tweakable block cipher that was used in the Skein hash function.
Very fast on 64-bit processors.
Available if ``BOTAN_HAS_THREEFISH_512`` is defined.
Twofish
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A 128-bit block cipher that was one of the AES finalists. Has a somewhat complicated key
setup and a "kitchen sink" design.
Available if ``BOTAN_HAS_TWOFISH`` is defined.

View File

@ -1,377 +0,0 @@
.. _cipher_modes:
Cipher Modes
=====================
A block cipher by itself, is only able to securely encrypt a single data block.
To be able to securely encrypt data of arbitrary length, a mode of operation
applies the block cipher's single block operation repeatedly to encrypt
an entire message.
All cipher mode implementations are are derived from the base class
:cpp:class:`Cipher_Mode`, which is declared in ``botan/cipher_mode.h``.
.. warning::
Using an unauthenticted cipher mode without combining it with a
:ref:`mac` is insecure. Prefer using an :ref:`aead`.
.. cpp:class:: Cipher_Mode
.. cpp:function:: void set_key(const uint8_t* key, size_t length)
Set the symmetric key to be used.
.. cpp:function:: bool valid_keylength(size_t length) const
This function returns true if and only if *length* is a valid
keylength for the algorithm.
.. cpp:function:: size_t minimum_keylength() const
Return the smallest key length (in bytes) that is acceptable for the
algorithm.
.. cpp:function:: size_t maximum_keylength() const
Return the largest key length (in bytes) that is acceptable for the
algorithm.
.. cpp:function:: size_t default_nonce_length() const
Return the default (preferable) nonce size for this cipher mode.
.. cpp:function:: bool valid_nonce_length(size_t nonce_len) const
Return true if *nonce_len* is a valid length for a nonce with this
algorithm.
.. cpp:function:: bool authenticated() const
Return true if this cipher mode is authenticated
.. cpp:function:: size_t tag_size() const
Return the length in bytes of the authentication tag this algorithm
generates. If the mode is not authenticated, this will return 0. If the mode
is authenticated, it will return some positive value (typically somewhere
between 8 and 16).
.. cpp:function:: void clear()
Clear all internal state. The object will act exactly like one which was
just allocated.
.. cpp:function:: void reset()
Reset all message state. For example if you called :cpp:func:`start_msg`,
then :cpp:func:`process` to process some ciphertext, but then encounter an
IO error and must abandon the current message, you can call `reset`. The
object will retain the key (unlike calling :cpp:func:`clear` which also
resets the key) but the nonce and current message state will be erased.
.. cpp:function:: void start_msg(const uint8_t* nonce, size_t nonce_len)
Set up for processing a new message. This function must be called with a new
random value for each message. For almost all modes (excepting SIV), if the
same nonce is ever used twice with the same key, the encryption scheme loses
its confidentiality and/or authenticity properties.
.. cpp:function:: void start(const std::vector<uint8_t> nonce)
Acts like :cpp:func:`start_msg`\ (nonce.data(), nonce.size()).
.. cpp:function:: void start(const uint8_t* nonce, size_t nonce_len)
Acts like :cpp:func:`start_msg`\ (nonce, nonce_len).
.. cpp:function:: virtual size_t update_granularity() const
The :cpp:class:`Cipher_Mode` interface requires message processing in multiples of the block size.
Returns size of required blocks to update. Will return 1 if the mode implementation
does not require buffering.
.. cpp:function:: virtual size_t ideal_granularity() const
Returns a multiple of update_granularity sized for ideal performance.
In fact this is not truly the "ideal" buffer size but just reflects the
smallest possible buffer that can reasonably take advantage of available
parallelism (due to SIMD execution, etc). If you are concerned about
performance, it may be advisable to take this return value and scale it to
approximately 4 KB, and use buffers of that size.
.. cpp:function:: virtual size_t process(uint8_t* msg, size_t msg_len)
Process msg in place and returns the number of bytes written. *msg* must
be a multiple of :cpp:func:`update_granularity`.
.. cpp:function:: void update(secure_vector<uint8_t>& buffer, size_t offset = 0)
Continue processing a message in the buffer in place. The passed buffer's
size must be a multiple of :cpp:func:`update_granularity`. The first
*offset* bytes of the buffer will be ignored.
.. cpp:function:: size_t minimum_final_size() const
Returns the minimum size needed for :cpp:func:`finish`. This is used for
example when processing an AEAD message, to ensure the tag is available. In
that case, the encryption side will return 0 (since the tag is generated,
rather than being provided) while the decryption mode will return the size
of the tag.
.. cpp:function:: void finish(secure_vector<uint8_t>& final_block, size_t offset = 0)
Finalize the message processing with a final block of at least :cpp:func:`minimum_final_size` size.
The first *offset* bytes of the passed final block will be ignored.
Code Example
---------------------
The following code encrypts the specified plaintext using AES-128/CBC
with PKCS#7 padding.
.. warning::
This example ignores the requirement to authenticate the ciphertext
.. note::
Simply replacing the string "AES-128/CBC/PKCS7" string in the example below
with "AES-128/GCM" suffices to use authenticated encryption.
.. literalinclude:: /../src/examples/aes_cbc.cpp
:language: cpp
Available Unauthenticated Cipher Modes
-----------------------------------------
.. note::
CTR and OFB modes are also implemented, but these are treated as
:cpp:class:`Stream_Cipher`\s instead.
CBC
~~~~~~~~~~~~
Available if ``BOTAN_HAS_MODE_CBC`` is defined.
CBC requires the plaintext be padded using a reversible rule. The following
padding schemes are implemented
PKCS#7 (RFC5652)
The last byte in the padded block defines the padding length p, the remaining padding bytes are set to p as well.
ANSI X9.23
The last byte in the padded block defines the padding length, the remaining padding is filled with 0x00.
OneAndZeros (ISO/IEC 7816-4)
The first padding byte is set to 0x80, the remaining padding bytes are set to 0x00.
Ciphertext stealing (CTS) is also implemented. This scheme allows the
ciphertext to have the same length as the plaintext, however using CTS
requires the input be at least one full block plus one byte. It is
also less commonly implemented.
.. warning::
Using CBC with padding without an authentication mode exposes your
application to CBC padding oracle attacks, which allow recovering
the plaintext of arbitrary messages. Always pair CBC with a MAC such
as HMAC (or, preferably, use an AEAD such as GCM).
CFB
~~~~~~~~~~~~
Available if ``BOTAN_HAS_MODE_CFB`` is defined.
CFB uses a block cipher to create a self-synchronizing stream cipher. It is used
for example in the OpenPGP protocol. There is no reason to prefer it, as it has
worse performance characteristics than modes such as CTR or CBC.
XTS
~~~~~~~~~
Available if ``BOTAN_HAS_MODE_XTS`` is defined.
XTS is a mode specialized for encrypting disk or database storage
where ciphertext expansion is not possible. XTS requires all inputs be
at least one full block (16 bytes for AES), however for any acceptable
input length, there is no ciphertext expansion.
.. _aead:
AEAD Mode
---------------------------
AEAD (Authenticated Encryption with Associated Data) modes provide message
encryption, message authentication, and the ability to authenticate additional
data that is not included in the ciphertext (such as a sequence number or
header). It is a subclass of :cpp:class:`Cipher_Mode`.
.. cpp:class:: AEAD_Mode
.. cpp:function:: void set_key(const SymmetricKey& key)
Set the key
.. cpp:function:: Key_Length_Specification key_spec() const
Return the key length specification
.. cpp:function:: void set_associated_data(const uint8_t ad[], size_t ad_len)
Set any associated data for this message. For maximum portability between
different modes, this must be called after :cpp:func:`set_key` and before
:cpp:func:`start`.
If the associated data does not change, it is not necessary to call this
function more than once, even across multiple calls to :cpp:func:`start`
and :cpp:func:`finish`.
.. cpp:function:: void start(const uint8_t nonce[], size_t nonce_len)
Start processing a message, using *nonce* as the unique per-message
value. It does not need to be random, simply unique (per key).
.. warning::
With almost all AEADs, if the same nonce is ever used to encrypt two
different messages under the same key, all security is lost. If
reliably generating unique nonces is difficult in your environment,
use SIV mode which retains security even if nonces are repeated.
.. cpp:function:: void update(secure_vector<uint8_t>& buffer, size_t offset = 0)
Continue processing a message. The *buffer* is an in/out parameter and
may be resized. In particular, some modes require that all input be
consumed before any output is produced; with these modes, *buffer* will
be returned empty.
On input, the buffer must be sized in blocks of size
:cpp:func:`update_granularity`. For instance if the update granularity
was 64, then *buffer* could be 64, 128, 192, ... bytes.
The first *offset* bytes of *buffer* will be ignored (this allows in
place processing of a buffer that contains an initial plaintext header)
.. cpp:function:: void finish(secure_vector<uint8_t>& buffer, size_t offset = 0)
Complete processing a message with a final input of *buffer*, which is
treated the same as with :cpp:func:`update`. It must contain at least
:cpp:func:`final_minimum_size` bytes.
Note that if you have the entire message in hand, calling finish without
ever calling update is both efficient and convenient.
.. note::
During decryption, if the supplied authentication tag does not
validate, finish will throw an instance of Invalid_Authentication_Tag
(aka Integrity_Failure, which was the name for this exception in
versions before 2.10, a typedef is included for compatability).
If this occurs, all plaintext previously output via calls to update
must be destroyed and not used in any way that an attacker could
observe the effects of. This could be anything from echoing the
plaintext back (perhaps in an error message), or by making an external
RPC whose destination or contents depend on the plaintext. The only
thing you can do is buffer it, and in the event of an invalid tag,
erase the previously decrypted content from memory.
One simply way to assure this could never happen is to never
call update, and instead always marshal the entire message
into a single buffer and call finish on it when decrypting.
.. cpp:function:: size_t update_granularity() const
The AEAD interface requires :cpp:func:`update` be called with blocks of
this size. This will be 1, if the mode can process any length inputs.
.. cpp:function:: size_t final_minimum_size() const
The AEAD interface requires :cpp:func:`finish` be called with at least
this many bytes (which may be zero, or greater than
:cpp:func:`update_granularity`)
.. cpp:function:: bool valid_nonce_length(size_t nonce_len) const
Returns true if *nonce_len* is a valid nonce length for this scheme. For
EAX and GCM, any length nonces are allowed. OCB allows any value between
8 and 15 bytes.
.. cpp:function:: size_t default_nonce_length() const
Returns a reasonable length for the nonce, typically either 96
bits, or the only supported length for modes which don't
support 96 bit nonces.
Available AEAD Modes
-------------------------
If in doubt about what to use, pick ChaCha20Poly1305, AES-256/GCM, or AES-256/SIV.
Both ChaCha20Poly1305 and AES with GCM are widely implemented. SIV is somewhat
more obscure (and is slower than either GCM or ChaCha20Poly1305), but has
excellent security properties.
ChaCha20Poly1305
~~~~~~~~~~~~~~~~~~
Available if ``BOTAN_HAS_AEAD_CHACHA20_POLY1305`` is defined.
Unlike the other AEADs which are based on block ciphers, this mode is based on
the ChaCha stream cipher and the Poly1305 authentication code. It is very fast
on all modern platforms.
ChaCha20Poly1305 supports 64-bit, 96-bit, and (since 2.8) 192-bit nonces. 64-bit nonces
are the "classic" ChaCha20Poly1305 design. 96-bit nonces are used by the IETF standard
version of ChaCha20Poly1305. And 192-bit nonces is the XChaCha20Poly1305 construction,
which is somewhat less common.
For best interop use the IETF version with 96-bit nonces. However 96 bits is small enough
that it can be dangerous to generate nonces randomly if more than ~ 2^32 messages are
encrypted under a single key, since if a nonce is ever reused ChaCha20Poly1305 becomes
insecure. It is better to use a counter for the nonce in this case.
If you are encrypting many messages under a single key and cannot maintain a counter for
the nonce, prefer XChaCha20Poly1305 since a 192 bit nonce is large enough that randomly
chosen nonces are extremely unlikely to repeat.
GCM
~~~~~
Available if ``BOTAN_HAS_AEAD_GCM`` is defined.
NIST standard, commonly used. Requires a 128-bit block cipher. Fairly slow,
unless hardware support for carryless multiplies is available.
OCB
~~~~~
Available if ``BOTAN_HAS_AEAD_OCB`` is defined.
A block cipher based AEAD. Supports 128-bit, 256-bit and 512-bit block ciphers.
This mode is very fast and easily secured against side channels. Adoption has
been poor because until 2021 it was patented in the United States. The patent
was allowed to lapse in early 2021.
EAX
~~~~~
Available if ``BOTAN_HAS_AEAD_EAX`` is defined.
A secure composition of CTR mode and CMAC. Supports 128-bit, 256-bit and 512-bit
block ciphers.
SIV
~~~~~~
Available if ``BOTAN_HAS_AEAD_SIV`` is defined.
Requires a 128-bit block cipher. Unlike other AEADs, SIV is "misuse resistant";
if a nonce is repeated, SIV retains security, with the exception that if the
same nonce is used to encrypt the same message multiple times, an attacker can
detect the fact that the message was duplicated (this is simply because if both
the nonce and the message are reused, SIV will output identical ciphertexts).
CCM
~~~~~
Available if ``BOTAN_HAS_AEAD_CCM`` is defined.
A composition of CTR mode and CBC-MAC. Requires a 128-bit block cipher. This is
a NIST standard mode, but that is about all to recommend it. Prefer EAX.

View File

@ -1,97 +0,0 @@
Lossless Data Compression
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Some lossless data compression algorithms are available in botan, currently all
via third party libraries - these include zlib (including deflate and gzip
formats), bzip2, and lzma. Support for these must be enabled at build time;
you can check for them using the macros ``BOTAN_HAS_ZLIB``, ``BOTAN_HAS_BZIP2``,
and ``BOTAN_HAS_LZMA``.
.. note::
You should always compress *before* you encrypt, because encryption seeks to
hide the redundancy that compression is supposed to try to find and remove.
Compression is done through the ``Compression_Algorithm`` and
``Decompression_Algorithm`` classes, both defined in `compression.h`
Compression and decompression both work in three stages: starting a
message (``start``), continuing to process it (``update``), and then
finally completing processing the stream (``finish``).
.. cpp:class:: Compression_Algorithm
.. cpp:function:: void start(size_t level)
Initialize the compression engine. This must be done before calling
``update`` or ``finish``. The meaning of the `level` parameter varies by
the algorithm but generally takes a value between 1 and 9, with higher
values implying typically better compression from and more memory and/or
CPU time consumed by the compression process. The decompressor can always
handle input from any compressor.
.. cpp:function:: void update(secure_vector<uint8_t>& buf, \
size_t offset = 0, bool flush = false)
Compress the material in the in/out parameter ``buf``. The leading
``offset`` bytes of ``buf`` are ignored and remain untouched; this can be
useful for ignoring packet headers. If ``flush`` is true, the
compression state is flushed, allowing the decompressor to recover the
entire message up to this point without having the see the rest of the
compressed stream.
.. cpp::function:: void finish(secure_vector<uint8_t>& buf, size_t offset = 0)
Finish compressing a message. The ``buf`` and ``offset`` parameters are
treated as in ``update``. It is acceptable to call ``start`` followed by
``finish`` with the entire message, without any intervening call to
``update``.
.. cpp:class:: Decompression_Algorithm
.. cpp:function:: void start()
Initialize the decompression engine. This must be done before calling
``update`` or ``finish``. No level is provided here; the decompressor
can accept input generated by any compression parameters.
.. cpp:function:: void update(secure_vector<uint8_t>& buf, \
size_t offset = 0)
Decompress the material in the in/out parameter ``buf``. The leading
``offset`` bytes of ``buf`` are ignored and remain untouched; this can be
useful for ignoring packet headers.
This function may throw if the data seems to be invalid.
.. cpp::function:: void finish(secure_vector<uint8_t>& buf, size_t offset = 0)
Finish decompressing a message. The ``buf`` and ``offset`` parameters are
treated as in ``update``. It is acceptable to call ``start`` followed by
``finish`` with the entire message, without any intervening call to
``update``.
This function may throw if the data seems to be invalid.
The easiest way to get a compressor is via the functions
``Compression_Algorithm::create`` and
``Decompression_Algorithm::create`` which both accept a string
argument which can take values include `zlib` (raw zlib with no
checksum), `deflate` (zlib's deflate format), `gzip`, `bz2`, and
`lzma`. A null pointer will be returned if the algorithm is
unavailable.
Two older functions for this are
.. cpp:function:: Compression_Algorithm* make_compressor(std::string type)
.. cpp:function:: Decompression_Algorithm* make_decompressor(std::string type)
which call the relevant ``create`` function and then ``release`` the
returned ``unique_ptr``. Avoid these in new code.
To use a compression algorithm in a `Pipe` use the adapter types
`Compression_Filter` and `Decompression_Filter` from `comp_filter.h`. The
constructors of both filters take a `std::string` argument (passed to
`make_compressor` or `make_decompressor`), the compression filter also takes a
`level` parameter. Finally both constructors have a parameter `buf_sz` which
specifies the size of the internal buffer that will be used - inputs will be
broken into blocks of this size. The default is 4096.

View File

@ -1,41 +0,0 @@
API Reference
===================
.. toctree::
:maxdepth: 1
footguns
versions
secmem
rng
hash
block_cipher
stream_ciphers
message_auth_codes
cipher_modes
pubkey
x509
tls
credentials_manager
bigint
kdf
pbkdf
keywrap
passhash
cryptobox
srp
psk_db
filters
fpe
tss
ecc
compression
pkcs11
tpm
otp
roughtime
zfec
ffi
env_vars
python

View File

@ -1,197 +0,0 @@
Credentials Manager
==================================================
A ``Credentials_Manager`` is a way to abstract how the application
stores credentials. The main user is the :doc:`tls` implementation.
.. cpp:class:: Credentials_Manager
.. cpp:function:: std::vector<Certificate_Store*> \
trusted_certificate_authorities( \
const std::string& type, \
const std::string& context)
Return the list of certificate stores, each of which is assumed
to contain (only) trusted certificate authorities. The
``Credentials_Manager`` retains ownership of the
Certificate_Store pointers.
.. note::
It would have been a better API to return a vector of
``shared_ptr`` here. This may change in a future major release.
When *type* is "tls-client", *context* will be the hostname of
the server, or empty if the hostname is not known. This allows
using a different set of certificate stores in different contexts,
for example using the system certificate store unless contacting
one particular server which uses a cert issued by an internal CA.
When *type* is "tls-server", the *context* will again be the
hostname of the server, or empty if the client did not send a
server name indicator. For TLS servers, these CAs are the ones
trusted for signing of client certificates. If you do not want
the TLS server to ask for a client cert,
``trusted_certificate_authorities`` should return an empty list
for *type* "tls-server".
The default implementation returns an empty list.
.. cpp:function:: std::vector<X509_Certificate> find_cert_chain( \
const std::vector<std::string>& cert_key_types, \
const std::vector<X509_DN>& acceptable_CAs, \
const std::string& type, \
const std::string& context)
Return the certificate chain to use to identify ourselves. The
``acceptable_CAs`` parameter gives a list of CAs the peer trusts.
This may be empty.
.. warning::
If this function returns a certificate that is not one of the
types given in ``cert_key_types`` confusing handshake
failures will result.
.. cpp:function:: std::vector<X509_Certificate> cert_chain( \
const std::vector<std::string>& cert_key_types, \
const std::string& type, \
const std::string& context)
Return the certificate chain to use to identify ourselves. Starting in
2.5, prefer ``find_cert_chain`` which additionally provides the CA list.
.. cpp:function:: std::vector<X509_Certificate> cert_chain_single_type( \
const std::string& cert_key_type, \
const std::string& type, \
const std::string& context)
Return the certificate chain to use to identifier ourselves, if
we have one of type *cert_key_type* and we would like to use a
certificate in this *type*/*context*.
For servers *type* will be "tls-server" and the *context* will
be the server name that the client requested via SNI (or empty,
if the client did not send SNI).
.. warning::
To avoid cross-protocol attacks it is recommended that if a server
receives an SNI request for a name it does not expect, it should close
the connection with an alert. This can be done by throwing an exception
from the implementation of this function.
.. cpp:function:: std::shared_ptr<Private_Key> private_key_for(const X509_Certificate& cert, \
const std::string& type, \
const std::string& context)
Return a shared pointer to the private key for this certificate. The
*cert* will be the leaf cert of a chain returned previously by
``cert_chain`` or ``cert_chain_single_type``.
In versions before 1.11.34, there was an additional function on `Credentials_Manager`
.. cpp::function:: void verify_certificate_chain( \
const std::string& type, \
const std::string& hostname, \
const std::vector<X509_Certificate>& cert_chain)
This function has been replaced by `TLS::Callbacks::tls_verify_cert_chain`.
SRP Authentication
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``Credentials_Manager`` contains the hooks used by TLS clients and
servers for SRP authentication.
.. note::
Support for TLS-SRP is deprecated, and will be removed in a future
major release. When that occurs these APIs will be removed. Prefer
instead performing a standard TLS handshake, then perform a PAKE
authentication inside of (and cryptographically bound to) the TLS
channel.
.. cpp:function:: bool attempt_srp(const std::string& type, \
const std::string& context)
Returns if we should consider using SRP for authentication
.. cpp:function:: std::string srp_identifier(const std::string& type, \
const std::string& context)
Returns the SRP identifier we'd like to use (used by client)
.. cpp:function:: std::string srp_password(const std::string& type, \
const std::string& context, \
const std::string& identifier)
Returns the password for *identifier* (used by client)
.. cpp:function:: bool srp_verifier(const std::string& type, \
const std::string& context, \
const std::string& identifier, \
std::string& group_name, \
BigInt& verifier, \
std::vector<uint8_t>& salt, \
bool generate_fake_on_unknown)
Returns the SRP verifier information for *identifier* (used by server)
Preshared Keys
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TLS supports the use of pre shared keys for authentication.
.. cpp:function:: SymmetricKey psk(const std::string& type, \
const std::string& context, \
const std::string& identity)
Return a symmetric key for use with *identity*
One important special case for ``psk`` is where *type* is
"tls-server", *context* is "session-ticket" and *identity* is an
empty string. If a key is returned for this case, a TLS server
will offer session tickets to clients who can use them, and the
returned key will be used to encrypt the ticket. The server is
allowed to change the key at any time (though changing the key
means old session tickets can no longer be used for resumption,
forcing a full re-handshake when the client next connects). One
simple approach to add support for session tickets in your server
is to generate a random key the first time ``psk`` is called to
retrieve the session ticket key, cache it for later use in the
``Credentials_Manager``, and simply let it be thrown away when the
process terminates. See :rfc:`4507` for more information about TLS
session tickets.
A similar special case exists for DTLS cookie verification. In
this case *type* will be "tls-server" and *context* is
"dtls-cookie-secret". If no key is returned, then DTLS cookies are
not used. Similar to the session ticket key, the DTLS cookie
secret can be chosen during server startup and rotated at any time
with no ill effect.
.. warning::
If DTLS cookies are not used then the server is prone to be
abused as a DoS amplifier, where the attacker sends a
relatively small client hello in a UDP packet with a forged
return address, and then the server replies to the victim with
several messages that are larger. This not only hides the
attackers address from the victim, but increases their
effective bandwidth. This is not an issue when using DTLS over
SCTP or TCP.
.. cpp:function:: std::string psk_identity_hint(const std::string& type, \
const std::string& context)
Returns an identity hint which may be provided to the client. This
can help a client understand what PSK to use.
.. cpp:function:: std::string psk_identity(const std::string& type, \
const std::string& context, \
const std::string& identity_hint)
Returns the identity we would like to use given this *type* and
*context* and the optional *identity_hint*. Not all servers or
protocols will provide a hint.

View File

@ -1,34 +0,0 @@
Cryptobox
========================================
Encryption using a passphrase
----------------------------------------
.. versionadded:: 1.8.6
.. deprecated:: 3.0
This is a set of simple routines that encrypt some data using a
passphrase. There are defined in the header `cryptobox.h`, inside
namespace `Botan::CryptoBox`.
It generates cipher and MAC keys using 8192 iterations of PBKDF2 with
HMAC(SHA-512), then encrypts using Serpent in CTR mode and authenticates using a
HMAC(SHA-512) mac of the ciphertext, truncated to 160 bits.
.. cpp:function:: std::string encrypt(const uint8_t input[], size_t input_len, \
const std::string& passphrase, \
RandomNumberGenerator& rng)
Encrypt the contents using *passphrase*.
.. cpp:function:: std::string decrypt(const uint8_t input[], size_t input_len, \
const std::string& passphrase)
Decrypts something encrypted with encrypt.
.. cpp:function:: std::string decrypt(const std::string& input, \
const std::string& passphrase)
Decrypts something encrypted with encrypt.

View File

@ -1,284 +0,0 @@
Elliptic Curve Operations
============================
In addition to high level operations for signatures, key agreement,
and message encryption using elliptic curve cryptography, the library
contains lower level interfaces for performing operations such as
elliptic curve point multiplication.
Only curves over prime fields are supported.
Many of these functions take a workspace, either a vector of words or
a vector of BigInts. These are used to minimize memory allocations
during common operations.
.. warning::
You should only use these interfaces if you know what you are doing.
.. cpp:class:: EC_Group
.. cpp:function:: EC_Group(const OID& oid)
Initialize an ``EC_Group`` using an OID referencing the curve
parameters.
.. cpp:function:: EC_Group(const std::string& name)
Initialize an ``EC_Group`` using a name or OID (for example
"secp256r1", or "1.2.840.10045.3.1.7")
.. cpp:function:: EC_Group(const BigInt& p, \
const BigInt& a, \
const BigInt& b, \
const BigInt& base_x, \
const BigInt& base_y, \
const BigInt& order, \
const BigInt& cofactor, \
const OID& oid = OID())
Initialize an elliptic curve group from the relevant parameters. This
is used for example to create custom (application-specific) curves.
.. cpp:function:: EC_Group(const std::vector<uint8_t>& ber_encoding)
Initialize an ``EC_Group`` by decoding a DER encoded parameter block.
.. cpp:function:: std::vector<uint8_t> DER_encode(EC_Group_Encoding form) const
Return the DER encoding of this group.
.. cpp:function:: std::string PEM_encode() const
Return the PEM encoding of this group (base64 of DER encoding plus
header/trailer).
.. cpp:function:: bool a_is_minus_3() const
Return true if the ``a`` parameter is congruent to -3 mod p.
.. cpp:function:: bool a_is_zero() const
Return true if the ``a`` parameter is congruent to 0 mod p.
.. cpp:function:: size_t get_p_bits() const
Return size of the prime in bits.
.. cpp:function:: size_t get_p_bytes() const
Return size of the prime in bytes.
.. cpp:function:: size_t get_order_bits() const
Return size of the group order in bits.
.. cpp:function:: size_t get_order_bytes() const
Return size of the group order in bytes.
.. cpp:function:: const BigInt& get_p() const
Return the prime modulus.
.. cpp:function:: const BigInt& get_a() const
Return the ``a`` parameter of the elliptic curve equation.
.. cpp:function:: const BigInt& get_b() const
Return the ``b`` parameter of the elliptic curve equation.
.. cpp:function:: const EC_Point& get_base_point() const
Return the groups base point element.
.. cpp:function:: const BigInt& get_g_x() const
Return the x coordinate of the base point element.
.. cpp:function:: const BigInt& get_g_y() const
Return the y coordinate of the base point element.
.. cpp:function:: const BigInt& get_order() const
Return the order of the group generated by the base point.
.. cpp:function:: const BigInt& get_cofactor() const
Return the cofactor of the curve. In most cases this will be 1.
.. cpp:function:: BigInt mod_order(const BigInt& x) const
Reduce argument ``x`` modulo the curve order.
.. cpp:function:: BigInt inverse_mod_order(const BigInt& x) const
Return inverse of argument ``x`` modulo the curve order.
.. cpp:function:: BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const
Multiply ``x`` and ``y`` and reduce the result modulo the curve order.
.. cpp:function:: bool verify_public_element(const EC_Point& y) const
Return true if ``y`` seems to be a valid group element.
.. cpp:function:: const OID& get_curve_oid() const
Return the OID used to identify the curve. May be empty.
.. cpp:function:: EC_Point point(const BigInt& x, const BigInt& y) const
Create and return a point with affine elements ``x`` and ``y``. Note
this function *does not* verify that ``x`` and ``y`` satisfy the curve
equation.
.. cpp:function:: EC_Point point_multiply(const BigInt& x, const EC_Point& pt, const BigInt& y) const
Multi-exponentiation. Returns base_point*x + pt*y. Not constant time.
(Ordinarily used for signature verification.)
.. cpp:function:: EC_Point blinded_base_point_multiply(const BigInt& k, \
RandomNumberGenerator& rng, \
std::vector<BigInt>& ws) const
Return ``base_point*k`` in a way that attempts to resist side channels.
.. cpp:function:: BigInt blinded_base_point_multiply_x(const BigInt& k, \
RandomNumberGenerator& rng, \
std::vector<BigInt>& ws) const
Like `blinded_base_point_multiply` but returns only the x coordinate.
.. cpp:function:: EC_Point blinded_var_point_multiply(const EC_Point& point, \
const BigInt& k, \
RandomNumberGenerator& rng, \
std::vector<BigInt>& ws) const
Return ``point*k`` in a way that attempts to resist side channels.
.. cpp:function:: BigInt random_scalar(RandomNumberGenerator& rng) const
Return a random scalar (ie an integer between 1 and the group order).
.. cpp:function:: EC_Point zero_point() const
Return the zero point (aka the point at infinity).
.. cpp:function:: EC_Point OS2ECP(const uint8_t bits[], size_t len) const
Decode a point from the binary encoding. This function verifies that
the decoded point is a valid element on the curve.
.. cpp:function:: bool verify_group(RandomNumberGenerator& rng, bool strong = false) const
Attempt to verify the group seems valid.
.. cpp:function:: static const std::set<std::string>& known_named_groups()
Return a list of known groups, ie groups for which ``EC_Group(name)``
will succeed.
.. cpp:class:: EC_Point
Stores elliptic curve points in Jacobian representation.
.. cpp:function:: std::vector<uint8_t> encode(EC_Point::Compression_Type format) const
Encode a point in a way that can later be decoded with `EC_Group::OS2ECP`.
.. cpp:function:: EC_Point& operator+=(const EC_Point& rhs)
Point addition.
.. cpp:function:: EC_Point& operator-=(const EC_Point& rhs)
Point subtraction.
.. cpp:function:: EC_Point& operator*=(const BigInt& scalar)
Point multiplication using Montgomery ladder.
.. warning::
Prefer the blinded functions in ``EC_Group``
.. cpp:function:: EC_Point& negate()
Negate this point.
.. cpp:function:: BigInt get_affine_x() const
Return the affine ``x`` coordinate of the point.
.. cpp:function:: BigInt get_affine_y() const
Return the affine ``y`` coordinate of the point.
.. cpp:function:: void force_affine()
Convert the point to its equivalent affine coordinates. Throws
if this is the point at infinity.
.. cpp:function:: static void force_all_affine(std::vector<EC_Point>& points, \
secure_vector<word>& ws)
Force several points to be affine at once. Uses Montgomery's
trick to reduce number of inversions required, so this is much
faster than calling ``force_affine`` on each point in sequence.
.. cpp:function:: bool is_affine() const
Return true if this point is in affine coordinates.
.. cpp:function:: bool is_zero() const
Return true if this point is zero (aka point at infinity).
.. cpp:function:: bool on_the_curve() const
Return true if this point is on the curve.
.. cpp:function:: void randomize_repr(RandomNumberGenerator& rng)
Randomize the point representation.
.. cpp:function:: bool operator==(const EC_Point& other) const
Point equality. This compares the affine representations.
.. cpp:function:: void add(const EC_Point& other, std::vector<BigInt>& workspace)
Point addition, taking a workspace.
.. cpp:function:: void add_affine(const EC_Point& other, std::vector<BigInt>& workspace)
Mixed (Jacobian+affine) addition, taking a workspace.
.. warning::
This function assumes that ``other`` is affine, if this is
not correct the result will be invalid.
.. cpp:function:: void mult2(std::vector<BigInt>& workspace)
Point doubling.
.. cpp:function:: void mult2i(size_t i, std::vector<BigInt>& workspace)
Repeated point doubling.
.. cpp:function:: EC_Point plus(const EC_Point& other, std::vector<BigInt>& workspace) const
Point addition, returning the result.
.. cpp:function:: EC_Point double_of(std::vector<BigInt>& workspace) const
Point doubling, returning the result.
.. cpp:function:: EC_Point zero() const
Return the point at infinity

View File

@ -1,35 +0,0 @@
.. _env_vars:
Environment Variables
======================
Certain environment variables can affect or tune the behavior of the
library. The variables and their behavior are described here.
* ``BOTAN_THREAD_POOL_SIZE`` controls the number of threads which will be
created for a thread pool used for some purposes within the library. If not
set, or set to 0, then it defaults to the number of CPUs available on the
system. If it is set to the string "none" then the thread pool is disabled;
instead all work passed to the thread pool will be executed immediately
by the calling thread.
As of version 3.2.0, on MinGW the thread pool is by default disabled, due to a
bug which causes deadlock on application shutdown. Enabling the pool can be
explicitly requested by setting ``BOTAN_THREAD_POOL_SIZE`` to an integer
value.
* ``BOTAN_MLOCK_POOL_SIZE`` controls the total amount of memory, in bytes, which
will be locked in memory using ``mlock`` or ``VirtualLock`` and managed in a
memory pool. This should be a multiple of the system page size. If set to
``0``, then the memory pool is disabled.
* ``BOTAN_FFI_PRINT_EXCEPTIONS`` if this variable is set (to any value), then
if an exception is caught by the FFI layer, before returning an error code, it
will print the text message of the exception to stderr. This is primarily
intended for debugging.
* ``BOTAN_CLEAR_CPUID``: this variable can be set to a comma-separated list of
CPUID fields to ignore. For example setting ``BOTAN_CLEAR_CPUID=avx2,avx512``
will cause AVX2 and AVX-512 codepaths to be avoided. Note that disabling basic
features (notably NEON or SSE2/SSSE3) can cause other higher level features
like AES-NI to also become disabled.

File diff suppressed because it is too large Load Diff

View File

@ -1,733 +0,0 @@
Pipe/Filter Message Processing
========================================
.. note::
The system described below provides a message processing system with a
straightforward API. However it makes many extra memory copies and
allocations than would otherwise be required, and also tends to make
applications using it somewhat opaque because it is not obvious what this or
that Pipe& object actually does (type of operation, number of messages
output (if any!), and so on), whereas using say a HashFunction or AEAD_Mode
provides a much better idea in the code of what operation is occurring.
This filter interface is no longer used within the library itself
(outside a few dusty corners) and will likely not see any further major
development. However it will remain included because the API is often
convenient and many applications use it.
Many common uses of cryptography involve processing one or more
streams of data. Botan provides services that make setting up data
flows through various operations, such as compression, encryption, and
base64 encoding. Each of these operations is implemented in what are
called *filters* in Botan. A set of filters are created and placed into
a *pipe*, and information "flows" through the pipe until it reaches
the end, where the output is collected for retrieval. If you're
familiar with the Unix shell environment, this design will sound quite
familiar.
Here is an example that uses a pipe to base64 encode some strings::
Pipe pipe(new Base64_Encoder); // pipe owns the pointer
pipe.start_msg();
pipe.write("message 1");
pipe.end_msg(); // flushes buffers, increments message number
// process_msg(x) is start_msg() && write(x) && end_msg()
pipe.process_msg("message2");
std::string m1 = pipe.read_all_as_string(0); // "message1"
std::string m2 = pipe.read_all_as_string(1); // "message2"
Byte streams in the pipe are grouped into messages; blocks of data that
are processed in an identical fashion (ie, with the same sequence of
filter operations). Messages are delimited by calls to ``start_msg``
and ``end_msg``. Each message in a pipe has its own identifier, which
currently is an integer that increments up from zero.
The ``Base64_Encoder`` was allocated using ``new``; but where was it
deallocated? When a filter object is passed to a ``Pipe``, the pipe
takes ownership of the object, and will deallocate it when it is no
longer needed.
There are two different ways to make use of messages. One is to send
several messages through a ``Pipe`` without changing the ``Pipe``
configuration, so you end up with a sequence of messages; one use of
this would be to send a sequence of identically encrypted UDP packets,
for example (note that the *data* need not be identical; it is just
that each is encrypted, encoded, signed, etc in an identical
fashion). Another is to change the filters that are used in the
``Pipe`` between each message, by adding or removing filters;
functions that let you do this are documented in the Pipe API section.
Botan has about 40 filters that perform different operations on data.
Here's code that uses one of them to encrypt a string with AES::
AutoSeeded_RNG rng,
SymmetricKey key(rng, 16); // a random 128-bit key
InitializationVector iv(rng, 16); // a random 128-bit IV
// The algorithm we want is specified by a string
Pipe pipe(get_cipher("AES-128/CBC", key, iv, Cipher_Dir::Encryption));
pipe.process_msg("secrets");
pipe.process_msg("more secrets");
secure_vector<uint8_t> c1 = pipe.read_all(0);
uint8_t c2[4096] = { 0 };
size_t got_out = pipe.read(c2, sizeof(c2), 1);
// use c2[0...got_out]
Note the use of ``AutoSeeded_RNG``, which is a random number
generator. If you want to, you can explicitly set up the random number
generators and entropy sources you want to, however for 99% of cases
``AutoSeeded_RNG`` is preferable.
``Pipe`` also has convenience methods for dealing with ``std::iostream``.
Here is an example of this, using the bzip2 compression filter::
std::ifstream in("data.bin", std::ios::binary)
std::ofstream out("data.bin.bz2", std::ios::binary)
Pipe pipe(new Compression_Filter("bzip2", 9));
pipe.start_msg();
in >> pipe;
pipe.end_msg();
out << pipe;
However there is a hitch to the code above; the complete contents of
the compressed data will be held in memory until the entire message
has been compressed, at which time the statement ``out << pipe`` is
executed, and the data is freed as it is read from the pipe and
written to the file. But if the file is very large, we might not have
enough physical memory (or even enough virtual memory!) for that to be
practical. So instead of storing the compressed data in the pipe for
reading it out later, we divert it directly to the file::
std::ifstream in("data.bin", std::ios::binary)
std::ofstream out("data.bin.bz2", std::ios::binary)
Pipe pipe(new Compression_Filter("bzip2", 9), new DataSink_Stream(out));
pipe.start_msg();
in >> pipe;
pipe.end_msg();
This is the first code we've seen so far that uses more than one
filter in a pipe. The output of the compressor is sent to the
``DataSink_Stream``. Anything written to a ``DataSink_Stream`` is
written to a file; the filter produces no output. As soon as the
compression algorithm finishes up a block of data, it will send it
along to the sink filter, which will immediately write it to the
stream; if you were to call ``pipe.read_all()`` after
``pipe.end_msg()``, you'd get an empty vector out. This is
particularly useful for cases where you are processing a large amount
of data, as it means you don't have to store everything in memory at
once.
Here's an example using two computational filters::
AutoSeeded_RNG rng,
SymmetricKey key(rng, 32);
InitializationVector iv(rng, 16);
Pipe encryptor(get_cipher("AES/CBC/PKCS7", key, iv, Cipher_Dir::Encryption),
new Base64_Encoder);
encryptor.start_msg();
file >> encryptor;
encryptor.end_msg(); // flush buffers, complete computations
std::cout << encryptor;
You can read from a pipe while you are still writing to it, which
allows you to bound the amount of memory that is in use at any one
time. A common idiom for this is::
pipe.start_msg();
std::vector<uint8_t> buffer(4096); // arbitrary size
while(infile.good())
{
infile.read((char*)&buffer[0], buffer.size());
const size_t got_from_infile = infile.gcount();
pipe.write(buffer, got_from_infile);
if(infile.eof())
pipe.end_msg();
while(pipe.remaining() > 0)
{
const size_t buffered = pipe.read(buffer, buffer.size());
outfile.write((const char*)&buffer[0], buffered);
}
}
if(infile.bad() || (infile.fail() && !infile.eof()))
throw Some_Exception();
Fork
---------------------------------
It is common that you might receive some data and want to perform more
than one operation on it (ie, encrypt it with Serpent and calculate
the SHA-256 hash of the plaintext at the same time). That's where
``Fork`` comes in. ``Fork`` is a filter that takes input and passes it
on to *one or more* filters that are attached to it. ``Fork`` changes
the nature of the pipe system completely: instead of being a linked
list, it becomes a tree or acyclic graph.
Each filter in the fork is given its own output buffer, and thus its
own message. For example, if you had previously written two messages
into a pipe, then you start a new one with a fork that has three
paths of filter's inside it, you add three new messages to the
pipe. The data you put into the pipe is duplicated and sent
into each set of filter and the eventual output is placed into a
dedicated message slot in the pipe.
Messages in the pipe are allocated in a depth-first manner. This is only
interesting if you are using more than one fork in a single pipe.
As an example, consider the following::
Pipe pipe(new Fork(
new Fork(
new Base64_Encoder,
new Fork(
NULL,
new Base64_Encoder
)
),
new Hex_Encoder
)
);
In this case, message 0 will be the output of the first
``Base64_Encoder``, message 1 will be a copy of the input (see below
for how fork interprets NULL pointers), message 2 will be the output
of the second ``Base64_Encoder``, and message 3 will be the output of
the ``Hex_Encoder``. This results in message numbers being allocated
in a top to bottom fashion, when looked at on the screen. However,
note that there could be potential for bugs if this is not
anticipated. For example, if your code is passed a filter, and you
assume it is a "normal" one that only uses one message, your message
offsets would be wrong, leading to some confusion during output.
If Fork's first argument is a null pointer, but a later argument is
not, then Fork will feed a copy of its input directly through. Here's
a case where that is useful::
// have std::string ciphertext, auth_code, key, iv, mac_key;
Pipe pipe(new Base64_Decoder,
get_cipher("AES-128", key, iv, Cipher_Dir::Decryption),
new Fork(
0, // this message gets plaintext
new MAC_Filter("HMAC(SHA-1)", mac_key)
)
);
pipe.process_msg(ciphertext);
std::string plaintext = pipe.read_all_as_string(0);
secure_vector<uint8_t> mac = pipe.read_all(1);
if(mac != auth_code)
error();
Here we wanted to not only decrypt the message, but send the decrypted
text through an additional computation, in order to compute the
authentication code.
Any filters that are attached to the pipe after the fork are
implicitly attached onto the first branch created by the fork. For
example, let's say you created this pipe::
Pipe pipe(new Fork(new Hash_Filter("SHA-256"),
new Hash_Filter("SHA-512")),
new Hex_Encoder);
And then called ``start_msg``, inserted some data, then
``end_msg``. Then ``pipe`` would contain two messages. The first one
(message number 0) would contain the SHA-256 sum of the input in hex
encoded form, and the other would contain the SHA-512 sum of the input
in raw binary. In many situations you'll want to perform a sequence of
operations on multiple branches of the fork; in which case, use
the filter described in :ref:`chain`.
There is also a ``Threaded_Fork`` which acts the same as ``Fork``,
except it runs each of the filters in its own thread.
.. _chain:
Chain
---------------------------------
A ``Chain`` filter creates a chain of filters and encapsulates them
inside a single filter (itself). This allows a sequence of filters to
become a single filter, to be passed into or out of a function, or to
a ``Fork`` constructor.
You can call ``Chain``'s constructor with up to four ``Filter``
pointers (they will be added in order), or with an array of filter
pointers and a ``size_t`` that tells ``Chain`` how many filters are in
the array (again, they will be attached in order). Here's the example
from the last section, using chain instead of relying on the implicit
pass through the other version used::
Pipe pipe(new Fork(
new Chain(new Hash_Filter("SHA-256"), new Hex_Encoder),
new Hash_Filter("SHA-512")
)
);
Sources and Sinks
----------------------------------------
Data Sources
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A ``DataSource`` is a simple abstraction for a thing that stores
bytes. This type is used heavily in the areas of the API related to
ASN.1 encoding/decoding. The following types are ``DataSource``:
``Pipe``, ``SecureQueue``, and a couple of special purpose ones:
``DataSource_Memory`` and ``DataSource_Stream``.
You can create a ``DataSource_Memory`` with an array of bytes and a
length field. The object will make a copy of the data, so you don't
have to worry about keeping that memory allocated. This is mostly for
internal use, but if it comes in handy, feel free to use it.
A ``DataSource_Stream`` is probably more useful than the memory based
one. Its constructors take either a ``std::istream`` or a
``std::string``. If it's a stream, the data source will use the
``istream`` to satisfy read requests (this is particularly useful to
use with ``std::cin``). If the string version is used, it will attempt
to open up a file with that name and read from it.
Data Sinks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A ``DataSink`` (in ``data_snk.h``) is a ``Filter`` that takes
arbitrary amounts of input, and produces no output. This means it's
doing something with the data outside the realm of what
``Filter``/``Pipe`` can handle, for example, writing it to a file
(which is what the ``DataSink_Stream`` does). There is no need for
``DataSink``s that write to a ``std::string`` or memory buffer,
because ``Pipe`` can handle that by itself.
Here's a quick example of using a ``DataSink``, which encrypts
``in.txt`` and sends the output to ``out.txt``. There is
no explicit output operation; the writing of ``out.txt`` is
implicit::
DataSource_Stream in("in.txt");
Pipe pipe(get_cipher("AES-128/CTR-BE", key, iv),
new DataSink_Stream("out.txt"));
pipe.process_msg(in);
A real advantage of this is that even if "in.txt" is large, only as
much memory is needed for internal I/O buffers will be used.
The Pipe API
---------------------------------
Initializing Pipe
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default, ``Pipe`` will do nothing at all; any input placed into the
``Pipe`` will be read back unchanged. Obviously, this has limited
utility, and presumably you want to use one or more filters to somehow
process the data. First, you can choose a set of filters to initialize
the ``Pipe`` via the constructor. You can pass it either a set of up
to four filter pointers, or a pre-defined array and a length::
Pipe pipe1(new Filter1(/*args*/), new Filter2(/*args*/),
new Filter3(/*args*/), new Filter4(/*args*/));
Pipe pipe2(new Filter1(/*args*/), new Filter2(/*args*/));
Filter* filters[5] = {
new Filter1(/*args*/), new Filter2(/*args*/), new Filter3(/*args*/),
new Filter4(/*args*/), new Filter5(/*args*/) /* more if desired... */
};
Pipe pipe3(filters, 5);
This is by far the most common way to initialize a ``Pipe``. However,
occasionally a more flexible initialization strategy is necessary;
this is supported by 4 member functions. These functions may only be
used while the pipe in question is not in use; that is, either before
calling ``start_msg``, or after ``end_msg`` has been called (and no
new calls to ``start_msg`` have been made yet).
.. cpp:function:: void Pipe::prepend(Filter* filter)
Calling ``prepend`` will put the passed filter first in the list of
transformations. For example, if you prepend a filter implementing
encryption, and the pipe already had a filter that hex encoded the
input, then the next message processed would be first encrypted,
and *then* hex encoded.
.. cpp:function:: void Pipe::append(Filter* filter)
Like ``prepend``, but places the filter at the end of the message
flow. This doesn't always do what you expect if there is a fork.
.. cpp:function:: void Pipe::pop()
Removes the first filter in the flow.
.. cpp:function:: void Pipe::reset()
Removes all the filters that the pipe currently holds - it is reset
to an empty/no-op state. Any data that is being retained by the
pipe is retained after a ``reset``, and ``reset`` does not affect
message numbers (discussed later).
Giving Data to a Pipe
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Input to a ``Pipe`` is delimited into messages, which can be read from
independently (ie, you can read 5 bytes from one message, and then all of
another message, without either read affecting any other messages).
.. cpp:function:: void Pipe::start_msg()
Starts a new message; if a message was already running, an exception is
thrown. After this function returns, you can call ``write``.
.. cpp:function:: void Pipe::write(const uint8_t* input, size_t length)
.. cpp:function:: void Pipe::write(const std::vector<uint8_t>& input)
.. cpp:function:: void Pipe::write(const std::string& input)
.. cpp:function:: void Pipe::write(DataSource& input)
.. cpp:function:: void Pipe::write(uint8_t input)
All versions of ``write`` write the input into the filter sequence.
If a message is not currently active, an exception is thrown.
.. cpp:function:: void Pipe::end_msg()
End the currently active message
Sometimes, you may want to do only a single write per message. In this
case, you can use the ``process_msg`` series of functions, which start
a message, write their argument into the pipe, and then end the
message. In this case you would not make any explicit calls to
``start_msg``/``end_msg``.
Pipes can also be used with the ``>>`` operator, and will accept a
``std::istream``, or on Unix systems with the ``fd_unix`` module, a
Unix file descriptor. In either case, the entire contents of the file
will be read into the pipe.
Getting Output from a Pipe
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Retrieving the processed data from a pipe is a bit more complicated,
for various reasons. The pipe will separate each message into a
separate buffer, and you have to retrieve data from each message
independently. Each of the reader functions has a final parameter that
specifies what message to read from. If this parameter is set to
``Pipe::DEFAULT_MESSAGE``, it will read the current default message
(``DEFAULT_MESSAGE`` is also the default value of this parameter).
Functions in ``Pipe`` related to reading include:
.. cpp:function:: size_t Pipe::read(uint8_t* out, size_t len)
Reads up to ``len`` bytes into ``out``, and returns the number of
bytes actually read.
.. cpp:function:: size_t Pipe::peek(uint8_t* out, size_t len)
Acts exactly like `read`, except the data is not actually read; the
next read will return the same data.
.. cpp:function:: secure_vector<uint8_t> Pipe::read_all()
Reads the entire message into a buffer and returns it
.. cpp:function:: std::string Pipe::read_all_as_string()
Like ``read_all``, but it returns the data as a ``std::string``.
No encoding is done; if the message contains raw binary, so will
the string.
.. cpp:function:: size_t Pipe::remaining()
Returns how many bytes are left in the message
.. cpp:function:: Pipe::message_id Pipe::default_msg()
Returns the current default message number
.. cpp:function:: Pipe::message_id Pipe::message_count()
Returns the total number of messages currently in the pipe
.. cpp:function:: Pipe::set_default_msg(Pipe::message_id msgno)
Sets the default message number (which must be a valid message
number for that pipe). The ability to set the default message number
is particularly important in the case of using the file output
operations (``<<`` with a ``std::ostream`` or Unix file descriptor),
because there is no way to specify the message explicitly when using
the output operator.
Pipe I/O for Unix File Descriptors
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is a minor feature, but it comes in handy sometimes. In all
installations of the library, Botan's ``Pipe`` object overloads the
``<<`` and ``>>`` operators for C++ iostream objects,
which is usually more than sufficient for doing I/O.
However, there are cases where the iostream hierarchy does not map well to
local 'file types', so there is also the ability to do I/O directly with Unix
file descriptors. This is most useful when you want to read from or write to
something like a TCP or Unix-domain socket, or a pipe, since for simple file
access it's usually easier to just use C++'s file streams.
If ``BOTAN_EXT_PIPE_UNIXFD_IO`` is defined, then you can use the
overloaded I/O operators with Unix file descriptors. For an example of this,
check out the ``hash_fd`` example, included in the Botan distribution.
Filter Catalog
---------------------------------
This section documents most of the useful filters included in the
library.
Keyed Filters
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
A few sections ago, it was mentioned that ``Pipe`` can process
multiple messages, treating each of them the same. Well, that was a
bit of a lie. There are some algorithms (in particular, block ciphers
not in ECB mode, and all stream ciphers) that change their state as
data is put through them.
Naturally, you might well want to reset the keys or (in the case of
block cipher modes) IVs used by such filters, so multiple messages can
be processed using completely different keys, or new IVs, or new keys
and IVs, or whatever. And in fact, even for a MAC or an ECB block
cipher, you might well want to change the key used from message to
message.
Enter ``Keyed_Filter``, which acts as an abstract interface for any
filter that is uses keys: block cipher modes, stream ciphers, MACs,
and so on. It has two functions, ``set_key`` and ``set_iv``. Calling
``set_key`` will set (or reset) the key used by the algorithm. Setting
the IV only makes sense in certain algorithms -- a call to ``set_iv``
on an object that doesn't support IVs will cause an exception. You
must call ``set_key`` *before* calling ``set_iv``.
Here's a example::
Keyed_Filter *aes, *hmac;
Pipe pipe(new Base64_Decoder,
// Note the assignments to the cast and hmac variables
aes = get_cipher("AES-128/CBC", aes_key, iv),
new Fork(
0, // Read the section 'Fork' to understand this
new Chain(
hmac = new MAC_Filter("HMAC(SHA-1)", mac_key, 12),
new Base64_Encoder
)
)
);
pipe.start_msg();
// use pipe for a while, decrypt some stuff, derive new keys and IVs
pipe.end_msg();
aes->set_key(aes_key2);
aes->set_iv(iv2);
hmac->set_key(mac_key2);
pipe.start_msg();
// use pipe for some other things
pipe.end_msg();
There are some requirements to using ``Keyed_Filter`` that you must
follow. If you call ``set_key`` or ``set_iv`` on a filter that is
owned by a ``Pipe``, you must do so while the ``Pipe`` is
"unlocked". This refers to the times when no messages are being
processed by ``Pipe`` -- either before ``Pipe``'s ``start_msg`` is
called, or after ``end_msg`` is called (and no new call to
``start_msg`` has happened yet). Doing otherwise will result in
undefined behavior, probably silently getting invalid output.
And remember: if you're resetting both values, reset the key *first*.
Cipher Filters
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Getting a hold of a ``Filter`` implementing a cipher is very
easy. Make sure you're including the header ``lookup.h``, and
then call ``get_cipher``. You will pass the return value
directly into a ``Pipe``. There are a couple different functions
which do varying levels of initialization:
.. cpp:function:: Keyed_Filter* get_cipher(std::string cipher_spec, \
SymmetricKey key, InitializationVector iv, Cipher_Dir dir)
.. cpp:function:: Keyed_Filter* get_cipher(std::string cipher_spec, \
SymmetricKey key, Cipher_Dir dir)
The version that doesn't take an IV is useful for things that don't
use them, like block ciphers in ECB mode, or most stream ciphers. If
you specify a cipher spec that does want a IV, and you use the version
that doesn't take one, an exception will be thrown. The ``dir``
argument can be either ``Cipher_Dir::Encryption`` or ``Cipher_Dir::Decryption``.
The cipher_spec is a string that specifies what cipher is to be
used. The general syntax for "cipher_spec" is "STREAM_CIPHER",
"BLOCK_CIPHER/MODE", or "BLOCK_CIPHER/MODE/PADDING". In the case of
stream ciphers, no mode is necessary, so just the name is
sufficient. A block cipher requires a mode of some sort, which can be
"ECB", "CBC", "CFB(n)", "OFB", "CTR-BE", or "EAX(n)". The argument to
CFB mode is how many bits of feedback should be used. If you just use
"CFB" with no argument, it will default to using a feedback equal to
the block size of the cipher. EAX mode also takes an optional bit
argument, which tells EAX how large a tag size to use~--~generally
this is the size of the block size of the cipher, which is the default
if you don't specify any argument.
In the case of the ECB and CBC modes, a padding method can also be
specified. If it is not supplied, ECB defaults to not padding, and CBC
defaults to using PKCS #5/#7 compatible padding. The padding methods
currently available are "NoPadding", "PKCS7", "OneAndZeros", and
"CTS". CTS padding is currently only available for CBC mode, but the
others can also be used in ECB mode.
Some example "cipher_spec arguments are: "AES-128/CBC",
"Blowfish/CTR-BE", "Serpent/XTS", and "AES-256/EAX".
"CTR-BE" refers to counter mode where the counter is incremented as if
it were a big-endian encoded integer. This is compatible with most
other implementations, but it is possible some will use the
incompatible little endian convention. This version would be denoted
as "CTR-LE" if it were supported.
"EAX" is a new cipher mode designed by Wagner, Rogaway, and
Bellare. It is an authenticated cipher mode (that is, no separate
authentication is needed), has provable security, and is free from
patent entanglements. It runs about half as fast as most of the other
cipher modes (like CBC, OFB, or CTR), which is not bad considering you
don't need to use an authentication code.
Hashes and MACs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Hash functions and MACs don't need anything special when it comes to
filters. Both just take their input and produce no output until
``end_msg`` is called, at which time they complete the hash or MAC and
send that as output.
These filters take a string naming the type to be used. If for some
reason you name something that doesn't exist, an exception will be thrown.
.. cpp:function:: Hash_Filter::Hash_Filter(std::string hash, size_t outlen = 0)
This constructor creates a filter that hashes its input with
``hash``. When ``end_msg`` is called on the owning pipe, the hash is
completed and the digest is sent on to the next filter in the
pipeline. The parameter ``outlen`` specifies how many bytes of the
hash output will be passed along to the next filter when ``end_msg``
is called. By default, it will pass the entire hash.
Examples of names for ``Hash_Filter`` are "SHA-1" and "Whirlpool".
.. cpp:function:: MAC_Filter::MAC_Filter(std::string mac, SymmetricKey key, size_t outlen = 0)
This constructor takes a name for a mac, such as "HMAC(SHA-1)" or
"CMAC(AES-128)", along with a key to use. The optional ``outlen``
works the same as in ``Hash_Filter``.
Encoders
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Often you want your data to be in some form of text (for sending over
channels that aren't 8-bit clean, printing it, etc). The filters
``Hex_Encoder`` and ``Base64_Encoder`` will convert arbitrary binary
data into hex or base64 formats. Not surprisingly, you can use
``Hex_Decoder`` and ``Base64_Decoder`` to convert it back into its
original form.
Both of the encoders can take a few options about how the data should
be formatted (all of which have defaults). The first is a ``bool``
which says if the encoder should insert line breaks. This defaults to
false. Line breaks don't matter either way to the decoder, but it
makes the output a bit more appealing to the human eye, and a few
transport mechanisms (notably some email systems) limit the maximum
line length.
The second encoder option is an integer specifying how long such lines
will be (obviously this will be ignored if line-breaking isn't being
used). The default tends to be in the range of 60-80 characters, but
is not specified. If you want a specific value, set it. Otherwise the
default should be fine.
Lastly, ``Hex_Encoder`` takes an argument of type ``Case``, which can
be ``Uppercase`` or ``Lowercase`` (default is ``Uppercase``). This
specifies what case the characters A-F should be output as. The base64
encoder has no such option, because it uses both upper and lower case
letters for its output.
You can find the declarations for these types in ``hex_filt.h`` and
``b64_filt.h``.
Writing New Filters
---------------------------------
The system of filters and pipes was designed in an attempt to make it
as simple as possible to write new filter types. There are four
functions that need to be implemented by a class deriving from
``Filter``:
.. cpp:function:: std::string Filter::name() const
This should just return a useful decription of the filter object.
.. cpp:function:: void Filter::write(const uint8_t* input, size_t length)
This function is what is called when a filter receives input for it
to process. The filter is not required to process the data right
away; many filters buffer their input before producing any output. A
filter will usually have ``write`` called many times during its
lifetime.
.. cpp:function:: void Filter::send(uint8_t* output, size_t length)
Eventually, a filter will want to produce some output to send along
to the next filter in the pipeline. It does so by calling ``send``
with whatever it wants to send along to the next filter. There is
also a version of ``send`` taking a single byte argument, as a
convenience.
.. note::
Normally a filter does not need to override ``send``, though it
can for special handling. It does however need to call this
function whenever it wants to produce output.
.. cpp:function:: void Filter::start_msg()
Implementing this function is optional. Implement it if your filter
would like to do some processing or setup at the start of each
message, such as allocating a data structure.
.. cpp:function:: void Filter::end_msg()
Implementing this function is optional. It is called when it has
been requested that filters finish up their computations. The filter
should finish up with whatever computation it is working on (for
example, a compressing filter would flush the compressor and
``send`` the final block), and empty any buffers in preparation for
processing a fresh new set of input.
Additionally, if necessary, filters can define a constructor that
takes any needed arguments, and a destructor to deal with deallocating
memory, closing files, etc.

View File

@ -1,60 +0,0 @@
========================================
Footguns
========================================
This section notes areas where certain usages can cause confusing bugs or problems.
Static Objects
------------------
If you maintain ``static`` variables which hold Botan objects, you will perhaps
find that in some circumstances your application crashes in strange ways on
shutdown. That is because, at least on some operating systems, Botan uses a
locked memory pool as backing storage for the ``secure_vector`` type. This pool
allocates out of pages which have been locked into memory using ``mlock`` or
``VirtualLock`` system calls.
If your variable happens to be destroyed before the pool, all is well. If the
pool happens to be destroyed before the variable, then when the object goes to
free its memory, a crash will occur.
This is basically the famous C++ "Static Initialization Order Fiasco", except
in reverse.
The best course of action is to avoid ``static`` variables. If that is
impossible or inconvenient, one option is to disable the pool, either at build
time (disable the ``locking_allocator`` module) or at runtime. Unfortunately the
runtime setting requires setting an environment variable (see :ref:`env_vars`),
and doing so consistently *prior to static intialization* is not trivial, due to
the previously mentioned fiasco. One option might be to use GCC's
``constructor`` function attribute.
Another approach is to use the utility class ``Allocator_Initializer`` (declared
in ``mem_ops.h``) as an associated ``static`` variable in your code. As long as
the ``Allocator_Initializer`` is created *before* your static variables, that
means the allocator is created before your object, and thus will be destroyed
after your object is destroyed.
Ideally a more satisfactory solution to this issue could be found, especially
given the difficulty of disabling the pool at runtime.
Multithreaded Access
----------------------
It is perfectly safe to use the library from multiple threads.
It is *not* safe to use the same object from multiple threads, without some form
of external serialization or locking.
There are a few exceptions to this rule, where the type itself maintains an
internal mutexes. This will be noted in the respective documentation for that type.
Use of `fork`
----------------------
If you use the `fork` syscall in your code, and attempt to use the library in
both processes, likely bad things will happen due to internal locks. You can
avoid this problem by either at build time disabling the features associated
with these locks (namely ``locking_allocator`` and ``thread_utils``) or
disabling them at runtime using :ref:`env_vars`, ideally at the very start of
`main`.

View File

@ -1,98 +0,0 @@
Format Preserving Encryption
========================================
Format preserving encryption (FPE) refers to a set of techniques for
encrypting data such that the ciphertext has the same format as the
plaintext. For instance, you can use FPE to encrypt credit card
numbers with valid checksums such that the ciphertext is also an
credit card number with a valid checksum, or similarly for bank
account numbers, US Social Security numbers, or even more general
mappings like English words onto other English words.
The scheme currently implemented in botan is called FE1, and described
in the paper `Format Preserving Encryption
<https://eprint.iacr.org/2009/251>`_ by Mihir Bellare, Thomas
Ristenpart, Phillip Rogaway, and Till Stegers. FPE is an area of
ongoing standardization and it is likely that other schemes will be
included in the future.
To encrypt an arbitrary value using FE1, you need to use a ranking
method. Basically, the idea is to assign an integer to every value you
might encrypt. For instance, a 16 digit credit card number consists of
a 15 digit code plus a 1 digit checksum. So to encrypt a credit card
number, you first remove the checksum, encrypt the 15 digit value
modulo 10\ :sup:`15`, and then calculate what the checksum is for the
new (ciphertext) number. Or, if you were encrypting words in a
dictionary, you could rank the words by their lexicographical order,
and choose the modulus to be the number of words in the dictionary.
The interfaces for FE1 are defined in the header ``fpe_fe1.h``:
.. versionadded:: 2.5.0
.. cpp:class:: FPE_FE1
.. cpp:function:: FPE_FE1(const BigInt& n, size_t rounds = 5, \
bool compat_mode = false, \
std::string mac_algo = "HMAC(SHA-256)")
Initialize an FPE operation to encrypt/decrypt integers less
than *n*. It is expected that *n* is trivially factorable into
small integers. Common usage would be n to be a power of 10.
Note that the default parameters to this constructor are
**incompatible** with the ``fe1_encrypt`` and ``fe1_decrypt``
function originally added in 1.9.17. For compatibility, use
3 rounds and set ``compat_mode`` to true.
.. cpp:function:: BigInt encrypt(const BigInt& x, const uint8_t tweak[], size_t tweak_len) const
Encrypts the value *x* modulo the value *n* using the *key* and *tweak*
specified. Returns an integer less than *n*. The *tweak* is a value that
does not need to be secret that parameterizes the encryption function. For
instance, if you were encrypting a database column with a single key, you
could use a per-row-unique integer index value as the tweak. The same
tweak value must be used during decryption.
.. cpp:function:: BigInt decrypt(const BigInt& x, const uint8_t tweak[], size_t tweak_len) const
Decrypts an FE1 ciphertext. The *tweak* must be the same as that provided
to the encryption function. Returns the plaintext integer.
Note that there is not any implicit authentication or checking of data in
FE1, so if you provide an incorrect key or tweak the result is simply a
random integer.
.. cpp:function:: BigInt encrypt(const BigInt& x, uint64_t tweak)
Convenience version of encrypt taking an integer tweak.
.. cpp:function:: BigInt decrypt(const BigInt& x, uint64_t tweak)
Convenience version of decrypt taking an integer tweak.
There are two functions that handle the entire FE1 encrypt/decrypt operation.
These are the original interface to FE1, first added in 1.9.17. However because
they do the entire setup cost for each operation, they are significantly slower
than the class-based API presented above.
.. warning:: These functions are hardcoded to use 3 rounds, which may be
insufficient depending on the chosen modulus.
.. cpp:function:: BigInt FPE::fe1_encrypt(const BigInt& n, const BigInt& X, \
const SymmetricKey& key, const std::vector<uint8_t>& tweak)
This creates an FPE_FE1 object, sets the key, and encrypts *X* using
the provided tweak.
.. cpp:function:: BigInt FPE::fe1_decrypt(const BigInt& n, const BigInt& X, \
const SymmetricKey& key, const std::vector<uint8_t>& tweak)
This creates an FPE_FE1 object, sets the key, and decrypts *X* using
the provided tweak.
This example encrypts a credit card number with a valid `Luhn checksum
<https://en.wikipedia.org/wiki/Luhn_algorithm>`_ to another number with the same
format, including a correct checksum.
.. literalinclude:: ../../src/cli/cc_enc.cpp

View File

@ -1,312 +0,0 @@
Hash Functions and Checksums
=============================
Hash functions are one-way functions, which map data of arbitrary size to a
fixed output length. Most of the hash functions in Botan are designed to be
cryptographically secure, which means that it is computationally infeasible to
create a collision (finding two inputs with the same hash) or preimages (given a
hash output, generating an arbitrary input with the same hash). But note that
not all such hash functions meet their goals, in particular MD4 and MD5 are
trivially broken. However they are still included due to their wide adoption in
various protocols.
The class :cpp:class:`HashFunction` is defined in `botan/hash.h`.
Using a hash function is typically split into three stages: initialization,
update, and finalization (often referred to as a IUF interface). The
initialization stage is implicit: after creating a hash function object, it is
ready to process data. Then update is called one or more times. Calling update
several times is equivalent to calling it once with all of the arguments
concatenated. After completing a hash computation (eg using ``final``), the
internal state is reset to begin hashing a new message.
.. cpp:class:: HashFunction
.. cpp:function:: static std::unique_ptr<HashFunction> create(const std::string& name)
Return a newly allocated hash function object, or nullptr if the
name is not recognized.
.. cpp:function:: static std::unique_ptr<HashFunction> create_or_throw(const std::string& name)
Like ``create`` except that it will throw an exception instead of
returning nullptr.
.. cpp:function:: size_t output_length()
Return the size (in *bytes*) of the output of this function.
.. cpp:function:: void update(const uint8_t* input, size_t length)
Updates the computation with *input*.
.. cpp:function:: void update(uint8_t input)
Updates the computation with *input*.
.. cpp:function:: void update(const std::vector<uint8_t>& input)
Updates the computation with *input*.
.. cpp:function:: void update(const std::string& input)
Updates the computation with *input*.
.. cpp:function:: void final(uint8_t* out)
Finalize the calculation and place the result into ``out``.
For the argument taking an array, exactly ``output_length`` bytes will
be written. After you call ``final``, the algorithm is reset to
its initial state, so it may be reused immediately.
.. cpp:function:: secure_vector<uint8_t> final()
Similar to the other function of the same name, except it returns
the result in a newly allocated vector.
.. cpp:function:: secure_vector<uint8_t> process(const uint8_t in[], size_t length)
Equivalent to calling ``update`` followed by ``final``.
.. cpp:function:: secure_vector<uint8_t> process(const std::string& in)
Equivalent to calling ``update`` followed by ``final``.
.. cpp:function:: std::unique_ptr<HashFunction> new_object()
Return a newly allocated HashFunction object of the same type as this one.
.. cpp:function:: std::unique_ptr<HashFunction> copy_state()
Return a newly allocated HashFunction object of the same type as this one,
whose internal state matches the current state of this.
Code Example
------------
Assume we want to calculate the SHA-256, SHA-384, and SHA-3 hash digests of the STDIN stream using the Botan library.
.. literalinclude:: /../src/examples/hash.cpp
:language: cpp
Available Hash Functions
------------------------------
The following cryptographic hash functions are implemented. If in doubt,
any of SHA-384, SHA-3, or BLAKE2b are fine choices.
BLAKE2b
^^^^^^^^^
Available if ``BOTAN_HAS_BLAKE2B`` is defined.
A recently designed hash function. Very fast on 64-bit processors. Can output a
hash of any length between 1 and 64 bytes, this is specified by passing a value
to the constructor with the desired length.
Named like "Blake2b" which selects default 512-bit output, or as
"Blake2b(256)" to select 256 bits of output.
GOST-34.11
^^^^^^^^^^^^^^^
.. deprecated:: 2.11
Available if ``BOTAN_HAS_GOST_34_11`` is defined.
Russian national standard hash. It is old, slow, and has some weaknesses. Avoid
it unless you must.
.. warning::
As this hash function is no longer approved by the latest Russian standards,
support for GOST 34.11 hash is deprecated and will be removed in a future
major release.
Keccak-1600
^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_KECCAK`` is defined.
An older (and incompatible) variant of SHA-3, but sometimes used. Prefer SHA-3 in
new code.
MD4
^^^^^^^^^
An old and now broken hash function. Available if ``BOTAN_HAS_MD4`` is defined.
.. warning::
MD4 collisions can be easily created. There is no safe cryptographic use
for this function.
.. warning::
Support for MD4 is deprecated and will be removed in a future major release.
MD5
^^^^^^^^^
An old and now broken hash function. Available if ``BOTAN_HAS_MD5`` is defined.
.. warning::
MD5 collisions can be easily created. MD5 should never be used for signatures.
RIPEMD-160
^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_RIPEMD160`` is defined.
A 160 bit hash function, quite old but still thought to be secure (up to the
limit of 2**80 computation required for a collision which is possible with any
160 bit hash function). Somewhat deprecated these days. Prefer SHA-2 or SHA-3
in new code.
SHA-1
^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_SHA1`` is defined.
Widely adopted NSA designed hash function. Use SHA-2 or SHA-3 in new code.
.. warning::
SHA-1 collisions can now be created by moderately resourced attackers. It
must never be used for signatures.
SHA-256
^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_SHA2_32`` is defined.
Relatively fast 256 bit hash function, thought to be secure.
Also includes the variant SHA-224. There is no real reason to use SHA-224.
SHA-512
^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_SHA2_64`` is defined.
SHA-512 is faster than SHA-256 on 64-bit processors. Also includes the
truncated variants SHA-384 and SHA-512/256, which have the advantage
of avoiding message extension attacks.
SHA-3
^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_SHA3`` is defined.
The new NIST standard hash. Fairly slow.
Supports 224, 256, 384 or 512 bit outputs. SHA-3 is faster with
smaller outputs. Use as "SHA-3(256)" or "SHA-3(512)". Plain "SHA-3"
selects default 512 bit output.
SHAKE (SHAKE-128, SHAKE-256)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_SHAKE`` is defined.
These are actually XOFs (extensible output functions) based on SHA-3, which can
output a value of any byte length. For example "SHAKE-128(1024)" will produce
1024 bits of output. The specified length must be a multiple of 8.
SM3
^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_SM3`` is defined.
Chinese national hash function, 256 bit output. Widely used in industry there.
Fast and seemingly secure, but no reason to prefer it over SHA-2 or SHA-3 unless
required.
Skein-512
^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_SKEIN_512`` is defined.
A contender for the NIST SHA-3 competition. Very fast on 64-bit systems. Can
output a hash of any length between 1 and 64 bytes. It also accepts an optional
"personalization string" which can create variants of the hash. This is useful
for domain separation.
To set a personalization string set the second param to any value,
typically ASCII strings are used. Examples "Skein-512(256)" or
"Skein-512(384,personalization_string)".
Streebog (Streebog-256, Streebog-512)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_STREEBOG`` is defined.
Newly designed Russian national hash function. Due to use of input-dependent
table lookups, it is vulnerable to side channels. There is no reason to use it
unless compatibility is needed.
.. warning::
The Streebog Sbox has recently been revealed to have a hidden structure which
interacts with its linear layer in a way which may provide a backdoor when
used in certain ways. Avoid Streebog if at all possible.
Whirlpool
^^^^^^^^^^^^^^^
Available if ``BOTAN_HAS_WHIRLPOOL`` is defined.
A 512-bit hash function standardized by ISO and NESSIE. Relatively slow, and due
to the table based implementation it is potentially vulnerable to cache based
side channels.
Hash Function Combiners
---------------------------
These are functions which combine multiple hash functions to create a new hash
function. They are typically only used in specialized applications.
Parallel
^^^^^^^^^^^^^
Available if ``BOTAN_HAS_PARALLEL_HASH`` is defined.
Parallel simply concatenates multiple hash functions. For example
"Parallel(SHA-256,SHA-512)" outputs a 256+512 bit hash created by hashing the
input with both SHA-256 and SHA-512 and concatenating the outputs.
Note that due to the "multicollision attack" it turns out that generating a
collision for multiple parallel hash functions is no harder than generating a
collision for the strongest hash function.
Comp4P
^^^^^^^^^^^^^
Available if ``BOTAN_HAS_COMB4P`` is defined.
This combines two cryptographic hashes in such a way that preimage and collision
attacks are provably at least as hard as a preimage or collision attack on the
strongest hash.
Checksums
----------------
.. note:: Checksums are not suitable for cryptographic use, but can be used for
error checking purposes.
Adler32
^^^^^^^^^^^
Available if ``BOTAN_HAS_ADLER32`` is defined.
The Adler32 checksum is used in the zlib format. 32 bit output.
CRC24
^^^^^^^^^^^
Available if ``BOTAN_HAS_CRC24`` is defined.
This is the CRC function used in OpenPGP. 24 bit output.
CRC32
^^^^^^^^^^^
Available if ``BOTAN_HAS_CRC32`` is defined.
This is the 32-bit CRC used in protocols such as Ethernet, gzip, PNG, etc.

View File

@ -1,153 +0,0 @@
.. _key_derivation_function:
Key Derivation Functions (KDF)
========================================
Key derivation functions are used to turn some amount of shared secret material
into uniform random keys suitable for use with symmetric algorithms. An example
of an input which is useful for a KDF is a shared secret created using
Diffie-Hellman key agreement.
Typically a KDF is also used with a *salt* and a *label*. The *salt* should be
some random information which is available to all of the parties that would need
to use the KDF; this could be performed by setting the salt to some kind of
session identifier, or by having one of the parties generate a random salt and
including it in a message.
The *label* is used to bind the KDF output to some specific context. For
instance if you were using the KDF to derive a specific key referred to as the
"message key" in the protocol description, you might use a label of "FooProtocol
v2 MessageKey". This labeling ensures that if you accidentally use the same
input key and salt in some other context, you still use different keys in the
two contexts.
.. cpp:class:: KDF
.. cpp:function:: std::unique_ptr<KDF> KDF::create(const std::string& algo)
Create a new KDF object. Returns nullptr if the named key derivation
function was not available
.. cpp:function:: std::unique_ptr<KDF> KDF::create_or_throw(const std::string& algo)
Create a new KDF object. Throws an exception if the named key derivation
function was not available
.. cpp:function:: template<concepts::resizable_byte_buffer T = secure_vector<uint8_t>> \
T derive_key(size_t key_len, \
std::span<const uint8_t> secret, \
std::span<const uint8_t> salt, \
std::span<const uint8_t> label) const
This version is parameterized to the output buffer type, so it can be used
to return a ``std::vector``, a ``secure_vector``, or anything else
satisfying the ``resizable_byte_buffer`` concept.
.. cpp:function:: secure_vector<uint8_t> derive_key( \
const uint8_t secret[], \
size_t secret_len, \
const uint8_t salt[], \
size_t salt_len, \
const uint8_t label[], \
size_t label_len) const
.. cpp:function:: secure_vector<uint8_t> derive_key( \
size_t key_len, const std::vector<uint8_t>& secret, \
const std::vector<uint8_t>& salt, \
const std::vector<uint8_t>& label) const
.. cpp:function:: secure_vector<uint8_t> derive_key( \
size_t key_len, const std::vector<uint8_t>& secret, \
const uint8_t* salt, size_t salt_len) const
.. cpp:function:: secure_vector<uint8_t> derive_key( \
size_t key_len, const uint8_t* secret, size_t secret_len, \
const std::string& salt) const
All variations on the same theme. Deterministically creates a
uniform random value from *secret*, *salt*, and *label*, whose
meaning is described above.
Code Example
------------
An example demonstrating using the API to hash a secret using HKDF
.. literalinclude:: /../src/examples/kdf.cpp
:language: cpp
Available KDFs
-------------------
Botan includes many different KDFs simply because different protocols and.
standards have created subtly different approaches to this problem. For new
code, use HKDF which is conservative, well studied, widely implemented and NIST
approved. There is no technical reason (besides compatability) to choose any
other KDF.
HKDF
~~~~~
Defined in RFC 5869, HKDF uses HMAC to process inputs. Also available
are variants HKDF-Extract and HKDF-Expand. HKDF is the combined
Extract+Expand operation. Use the combined HKDF unless you need
compatibility with some other system.
Available if ``BOTAN_HAS_HKDF`` is defined.
KDF2
~~~~~
KDF2 comes from IEEE 1363. It uses a hash function.
Available if ``BOTAN_HAS_KDF2`` is defined.
KDF1-18033
~~~~~~~~~~~~
KDF1 from ISO 18033-2. Very similar to (but incompatible with) KDF2.
Available if ``BOTAN_HAS_KDF1_18033`` is defined.
KDF1
~~~~~~
KDF1 from IEEE 1363. It can only produce an output at most the length
of the hash function used.
Available if ``BOTAN_HAS_KDF1`` is defined.
X9.42 PRF
~~~~~~~~~~
A KDF from ANSI X9.42. Sometimes used for Diffie-Hellman. However it is
overly complicated and is fixed to use only SHA-1.
Available if ``BOTAN_HAS_X942_PRF`` is defined.
.. warning::
X9.42 PRF is deprecated and will be removed in a future major release.
SP800-108
~~~~~~~~~~
KDFs from NIST SP 800-108. Variants include "SP800-108-Counter",
"SP800-108-Feedback" and "SP800-108-Pipeline".
Available if ``BOTAN_HAS_SP800_108`` is defined.
SP800-56A
~~~~~~~~~~
KDF from NIST SP 800-56A.
Available if ``BOTAN_HAS_SP800_56A`` is defined.
SP800-56C
~~~~~~~~~~
KDF from NIST SP 800-56C.
Available if ``BOTAN_HAS_SP800_56C`` is defined.

View File

@ -1,60 +0,0 @@
AES Key Wrapping
=================================
NIST specifies two mechanisms for wrapping (encrypting) symmetric keys using
another key. The first (and older, more widely supported) method requires the
input be a multiple of 8 bytes long. The other allows any length input, though
only up to 2**32 bytes.
These algorithms are described in NIST SP 800-38F, and RFCs 3394 and 5649.
This API, defined in ``nist_keywrap.h``, first became available in version 2.4.0
These functions take an arbitrary 128-bit block cipher object, which must
already have been keyed with the key encryption key. NIST only allows these
functions with AES, but any 128-bit cipher will do and some other implementations
(such as in OpenSSL) do also allow other ciphers. Use AES for best interop.
.. cpp:function:: std::vector<uint8_t> nist_key_wrap(const uint8_t input[], \
size_t input_len, const BlockCipher& bc)
This performs KW (key wrap) mode. The input must be a multiple of 8 bytes long.
.. cpp:function:: secure_vector<uint8_t> nist_key_unwrap(const uint8_t input[], \
size_t input_len, const BlockCipher& bc)
This unwraps the result of nist_key_wrap, or throw Invalid_Authentication_Tag on error.
.. cpp:function:: std::vector<uint8_t> nist_key_wrap_padded(const uint8_t input[], \
size_t input_len, const BlockCipher& bc)
This performs KWP (key wrap with padding) mode. The input can be any length.
.. cpp:function:: secure_vector<uint8_t> nist_key_unwrap_padded(const uint8_t input[], \
size_t input_len, const BlockCipher& bc)
This unwraps the result of nist_key_wrap_padded, or throws Invalid_Authentication_Tag
on error.
RFC 3394 Interface
-----------------------------
This is an older interface that was first available (with slight changes) in
1.10, and available in its current form since 2.0 release. It uses a 128-bit,
192-bit, or 256-bit key to encrypt an input key. AES is always used. The input
must be a multiple of 8 bytes; if not an exception is thrown.
This interface is defined in ``rfc3394.h``.
.. cpp:function:: secure_vector<uint8_t> rfc3394_keywrap(const secure_vector<uint8_t>& key, \
const SymmetricKey& kek)
Wrap the input key using kek (the key encryption key), and return the result. It will
be 8 bytes longer than the input key.
.. cpp:function:: secure_vector<uint8_t> rfc3394_keyunwrap(const secure_vector<uint8_t>& key, \
const SymmetricKey& kek)
Unwrap a key wrapped with rfc3394_keywrap.

View File

@ -1,195 +0,0 @@
.. _mac:
Message Authentication Codes (MAC)
===================================
A Message Authentication Code algorithm computes a tag over a message utilizing
a shared secret key. Thus a valid tag confirms the authenticity and integrity of
the message. Only entities in possession of the shared secret key are able to
verify the tag.
.. note::
When combining a MAC with unauthenticated encryption mode, prefer to first
encrypt the message and then MAC the ciphertext. The alternative is to MAC
the plaintext, which depending on exact usage can suffer serious security
issues. For a detailed discussion of this issue see the paper "The Order of
Encryption and Authentication for Protecting Communications" by Hugo
Krawczyk
The Botan MAC computation is split into five stages.
#. Instantiate the MAC algorithm.
#. Set the secret key.
#. Process IV.
#. Process data.
#. Finalize the MAC computation.
.. cpp:class:: MessageAuthenticationCode
.. cpp:function:: std::string name() const
Returns a human-readable string of the name of this algorithm.
.. cpp:function:: void clear()
Clear the key.
.. cpp:function:: std::unique_ptr<MessageAuthenticationCode> new_object() const
Return a newly allocated object of the same type as this one.
The new object is unkeyed.
.. cpp:function:: void set_key(const uint8_t* key, size_t length)
Set the shared MAC key for the calculation. This function has to be called before the data is processed.
.. cpp:function:: bool valid_keylength(size_t length) const
This function returns true if and only if *length* is a valid
keylength for the algorithm.
.. cpp:function:: size_t minimum_keylength() const
Return the smallest key length (in bytes) that is acceptable for the
algorithm.
.. cpp:function:: size_t maximum_keylength() const
Return the largest key length (in bytes) that is acceptable for the
algorithm.
.. cpp:function:: void start(const uint8_t* nonce, size_t nonce_len)
Set the IV for the MAC calculation. Note that not all MAC algorithms require an IV.
If an IV is required, the function has to be called before the data is processed.
For algorithms that don't require it, the call can be omitted, or else called
with ``nonce_len`` of zero.
.. cpp:function:: void update(const uint8_t* input, size_t length)
Process the passed data.
.. cpp:function:: void update(const secure_vector<uint8_t>& in)
Process the passed data.
.. cpp:function:: void update(uint8_t in)
Process a single byte.
.. cpp:function:: void final(uint8_t* out)
Complete the MAC computation and write the calculated tag to the passed byte array.
.. cpp:function:: secure_vector<uint8_t> final()
Complete the MAC computation and return the calculated tag.
.. cpp:function:: bool verify_mac(const uint8_t* mac, size_t length)
Finalize the current MAC computation and compare the result to the passed
``mac``. Returns ``true``, if the verification is successful and false
otherwise.
Code Examples
------------------------
The following example computes an HMAC with a random key then verifies the tag.
.. literalinclude:: /../src/examples/hmac.cpp
:language: cpp
The following example code computes a AES-256 GMAC and subsequently verifies the
tag. Unlike most other MACs, GMAC requires a nonce *which must not repeat or
all security is lost*.
.. literalinclude:: /../src/examples/gmac.cpp
:language: cpp
The following example code computes a valid AES-128 CMAC tag and modifies the
data to demonstrate a MAC verification failure.
.. literalinclude:: /../src/examples/cmac.cpp
:language: cpp
Available MACs
------------------------------------------
Currently the following MAC algorithms are available in Botan. In new code,
default to HMAC with a strong hash like SHA-256 or SHA-384.
CMAC
~~~~~~~~~~~~
A modern CBC-MAC variant that avoids the security problems of plain CBC-MAC.
Approved by NIST. Also sometimes called OMAC.
Available if ``BOTAN_HAS_CMAC`` is defined.
GMAC
~~~~~~~~~~~~
GMAC is related to the GCM authenticated cipher mode. It is quite slow unless
hardware support for carryless multiplications is available. A new nonce
must be used with **each** message authenticated, or otherwise all security is
lost.
Available if ``BOTAN_HAS_GMAC`` is defined.
.. warning::
Due to the nonce requirement, GMAC is exceptionally fragile. Avoid it unless
absolutely required.
HMAC
~~~~~~~~~~~~
A message authentication code based on a hash function. Very commonly used.
Available if ``BOTAN_HAS_HMAC`` is defined.
KMAC
~~~~~~~~~~~~
.. versionadded:: 3.2
A SHA-3 derived message authentication code defined by NIST in SP 800-185.
There are two variants, ``KMAC-128`` and ``KMAC-256``. Both take a parameter
which specifies the output length in bits, for example ``KMAC-128(256)``.
Available if ``BOTAN_HAS_KMAC`` is defined.
Poly1305
~~~~~~~~~~~~
A polynomial mac (similar to GMAC). Very fast, but tricky to use safely. Forms
part of the ChaCha20Poly1305 AEAD mode. A new key must be used for **each**
message, or all security is lost.
Available if ``BOTAN_HAS_POLY1305`` is defined.
.. warning::
Due to the nonce requirement, Poly1305 is exceptionally fragile. Avoid it unless
absolutely required.
SipHash
~~~~~~~~~~~~
A modern and very fast PRF. Produces only a 64-bit output. Defaults to
"SipHash(2,4)" which is the recommended configuration, using 2 rounds for each
input block and 4 rounds for finalization.
Available if ``BOTAN_HAS_SIPHASH`` is defined.
X9.19-MAC
~~~~~~~~~~~~
A CBC-MAC variant sometimes used in finance. Always uses DES.
Sometimes called the "DES retail MAC", also standardized in ISO 9797-1.
It is slow and has known attacks. Avoid unless required.
Available if ``BOTAN_HAS_X919_MAC`` is defined.

View File

@ -1,98 +0,0 @@
One Time Passwords
========================
.. versionadded:: 2.2.0
One time password schemes are a user authentication method that relies on a
fixed secret key which is used to derive a sequence of short passwords, each of
which is accepted only once. Commonly this is used to implement two-factor
authentication (2FA), where the user authenticates using both a conventional
password (or a public key signature) and an OTP generated by a small device such
as a mobile phone.
Botan implements the HOTP and TOTP schemes from RFC 4226 and 6238.
Since the range of possible OTPs is quite small, applications must rate limit
OTP authentication attempts to some small number per second. Otherwise an attacker
could quickly try all 1000000 6-digit OTPs in a brief amount of time.
HOTP
^^^^^^
HOTP generates OTPs that are a short numeric sequence, between 6 and 8 digits
(most applications use 6 digits), created using the HMAC of a 64-bit counter
value. If the counter ever repeats the OTP will also repeat, thus both parties
must assure the counter only increments and is never repeated or
decremented. Thus both client and server must keep track of the next counter
expected.
Anyone with access to the client-specific secret key can authenticate as that
client, so it should be treated with the same security consideration as would be
given to any other symmetric key or plaintext password.
.. cpp:class:: HOTP
Implement counter-based OTP
.. cpp:function:: HOTP(const SymmetricKey& key, const std::string& hash_algo = "SHA-1", size_t digits = 6)
Initialize an HOTP instance with a secret key (specific to each client),
a hash algorithm (must be SHA-1, SHA-256, or SHA-512), and the number of
digits with each OTP (must be 6, 7, or 8).
In RFC 4226, HOTP is only defined with SHA-1, but many HOTP
implementations support SHA-256 as an extension. The collision attacks
on SHA-1 do not have any known effect on HOTP's security.
.. cpp:function:: uint32_t generate_hotp(uint64_t counter)
Return the OTP associated with a specific counter value.
.. cpp:function:: std::pair<bool,uint64_t> verify_hotp(uint32_t otp, \
uint64_t starting_counter, size_t resync_range = 0)
Check if a provided OTP matches the one that should be generated for
the specified counter.
The *starting_counter* should be the counter of the last successful
authentication plus 1. If *resync_resync* is greater than 0, some number
of counter values above *starting_counter* will also be checked if
necessary. This is useful for instance when a client mistypes an OTP on
entry; the authentication will fail so the server will not update its
counter, but the client device will subsequently show the OTP for the
next counter. Depending on the environment a *resync_range* of 3 to 10
might be appropriate.
Returns a pair of (is_valid,next_counter_to_use). If the OTP is invalid
then always returns (false,starting_counter), since the last successful
authentication counter has not changed.
TOTP
^^^^^^^^^^
TOTP is based on the same algorithm as HOTP, but instead of a counter a
timestamp is used.
.. cpp:class:: TOTP
.. cpp:function:: TOTP(const SymmetricKey& key, const std::string& hash_algo = "SHA-1", \
size_t digits = 6, size_t time_step = 30)
Setup to perform TOTP authentication using secret key *key*.
.. cpp:function:: uint32_t generate_totp(std::chrono::system_clock::time_point time_point)
.. cpp:function:: uint32_t generate_totp(uint64_t unix_time)
Generate and return a TOTP code based on a timestamp.
.. cpp:function:: bool verify_totp(uint32_t otp, std::chrono::system_clock::time_point time, \
size_t clock_drift_accepted = 0)
.. cpp:function:: bool verify_totp(uint32_t otp, uint64_t unix_time, \
size_t clock_drift_accepted = 0)
Return true if the provided OTP code is correct for the provided
timestamp. If required, use *clock_drift_accepted* to deal with
the client and server having slightly different clocks.

View File

@ -1,215 +0,0 @@
Password Hashing
========================================
Storing passwords for user authentication purposes in plaintext is the
simplest but least secure method; when an attacker compromises the
database in which the passwords are stored, they immediately gain
access to all of them. Often passwords are reused among multiple
services or machines, meaning once a password to a single service is
known an attacker has a substantial head start on attacking other
machines.
The general approach is to store, instead of the password, the output
of a one way function of the password. Upon receiving an
authentication request, the authenticating party can recompute the one way
function and compare the value just computed with the one that was
stored. If they match, then the authentication request succeeds. But
when an attacker gains access to the database, they only have the
output of the one way function, not the original password.
Common hash functions such as SHA-256 are one way, but used alone they
have problems for this purpose. What an attacker can do, upon gaining
access to such a stored password database, is hash common dictionary
words and other possible passwords, storing them in a list. Then he
can search through his list; if a stored hash and an entry in his list
match, then he has found the password. Even worse, this can happen
*offline*: an attacker can begin hashing common passwords days,
months, or years before ever gaining access to the database. In
addition, if two users choose the same password, the one way function
output will be the same for both of them, which will be visible upon
inspection of the database.
There are two solutions to these problems: salting and
iteration. Salting refers to including, along with the password, a
randomly chosen value which perturbs the one way function. Salting can
reduce the effectiveness of offline dictionary generation, because for
each potential password, an attacker would have to compute the one way
function output for all possible salts. It also prevents the same
password from producing the same output, as long as the salts do not
collide. Choosing n-bit salts randomly, salt collisions become likely
only after about 2\ :sup:\ `(n/2)` salts have been generated. Choosing a
large salt (say 80 to 128 bits) ensures this is very unlikely. Note
that in password hashing salt collisions are unfortunate, but not
fatal - it simply allows the attacker to attack those two passwords in
parallel easier than they would otherwise be able to.
The other approach, iteration, refers to the general technique of
forcing multiple one way function evaluations when computing the
output, to slow down the operation. For instance if hashing a single
password requires running SHA-256 100,000 times instead of just once,
that will slow down user authentication by a factor of 100,000, but
user authentication happens quite rarely, and usually there are more
expensive operations that need to occur anyway (network and database
I/O, etc). On the other hand, an attacker who is attempting to break a
database full of stolen password hashes will be seriously
inconvenienced by a factor of 100,000 slowdown; they will be able to
only test at a rate of .0001% of what they would without iterations
(or, equivalently, will require 100,000 times as many zombie botnet
hosts).
Memory usage while checking a password is also a consideration; if the
computation requires using a certain minimum amount of memory, then an
attacker can become memory-bound, which may in particular make
customized cracking hardware more expensive. Some password hashing
designs, such as scrypt, explicitly attempt to provide this. The
bcrypt approach requires over 4 KiB of RAM (for the Blowfish key
schedule) and may also make some hardware attacks more expensive.
Botan provides three techniques for password hashing: Argon2, bcrypt, and
passhash9 (based on PBKDF2).
Argon2
----------------------------------------
.. versionadded:: 2.11.0
Argon2 is the winner of the PHC (Password Hashing Competition) and provides
a tunable memory hard password hash. It has a standard string encoding, which looks like::
"$argon2i$v=19$m=8192,t=10,p=3$YWFhYWFhYWE$itkWB9ODqTd85wUsoib7pfpVTNGMOu0ZJan1odl25V8"
Argon2 has three tunable parameters: ``M``, ``p``, and ``t``. ``M`` gives the
total memory consumption of the algorithm in kilobytes. Increasing ``p``
increases the available parallelism of the computation. The ``t`` parameter
gives the number of passes which are made over the data.
There are three variants of Argon2, namely Argon2d, Argon2i and Argon2id.
Argon2d uses data dependent table lookups with may leak information about the
password via side channel attacks, and is **not recommended** for password
hashing. Argon2i uses data independent table lookups and is immune to these
attacks, but at the cost of requiring higher ``t`` for security. Argon2id uses a
hybrid approach which is thought to be highly secure. The algorithm designers
recommend using Argon2id with ``t`` and ``p`` both equal to 1 and ``M`` set to
the largest amount of memory usable in your environment.
.. cpp:function:: std::string argon2_generate_pwhash(const char* password, size_t password_len, \
RandomNumberGenerator& rng, \
size_t p, size_t M, size_t t, \
size_t y = 2, size_t salt_len = 16, size_t output_len = 32)
Generate an Argon2 hash of the specified password. The ``y`` parameter specifies
the variant: 0 for Argon2d, 1 for Argon2i, and 2 for Argon2id.
.. cpp:function:: bool argon2_check_pwhash(const char* password, size_t password_len, \
const std::string& hash)
Verify an Argon2 password hash against the provided password. Returns false if
the input hash seems malformed or if the computed hash does not match.
Bcrypt
----------------------------------------
`Bcrypt <https://www.usenix.org/legacy/event/usenix99/provos/provos.pdf>`_ is a
password hashing scheme originally designed for use in OpenBSD, but numerous
other implementations exist. It is made available by including ``bcrypt.h``.
It has the advantage that it requires a small amount (4K) of fast RAM
to compute, which can make hardware password cracking somewhat more
expensive.
Bcrypt provides outputs that look like this::
"$2a$12$7KIYdyv8Bp32WAvc.7YvI.wvRlyVn0HP/EhPmmOyMQA4YKxINO0p2"
.. note::
Due to the design of bcrypt, the password is effectively truncated at 72
characters; further characters are ignored and do not change the hash. To
support longer passwords, one common approach is to pre-hash the password
with SHA-256, then run bcrypt using the hex or base64 encoding of the hash as
the password. (Many bcrypt implementations truncate the password at the first
NULL character, so hashing the raw binary SHA-256 may cause problems. Botan's
bcrypt implementation will hash whatever values are given in the
``std::string`` including any embedded NULLs so this is not an issue, but
might cause interop problems if another library needs to validate the
password hashes.)
.. cpp:function:: std::string generate_bcrypt(const std::string& password, \
RandomNumberGenerator& rng, \
uint16_t work_factor = 12, \
char bcrypt_version = "a")
Takes the password to hash, a rng, and a work factor.
The resulting password hash is returned as a string.
Higher work factors increase the amount of time the algorithm runs,
increasing the cost of cracking attempts. The increase is exponential, so a
work factor of 12 takes roughly twice as long as work factor 11. The default
work factor was set to 10 up until the 2.8.0 release.
It is recommended to set the work factor as high as your system can tolerate
(from a performance and latency perspective) since higher work factors greatly
improve the security against GPU-based attacks. For example, for protecting
high value administrator passwords, consider using work factor 15 or 16; at
these work factors each bcrypt computation takes several seconds. Since admin
logins will be relatively uncommon, it might be acceptable for each login
attempt to take some time. As of 2018, a good password cracking rig (with 8
NVIDIA 1080 cards) can attempt about 1 billion bcrypt computations per month
for work factor 13. For work factor 12, it can do twice as many. For work
factor 15, it can do only one quarter as many attempts.
Due to bugs affecting various implementations of bcrypt, several different
variants of the algorithm are defined. As of 2.7.0 Botan supports generating
(or checking) the 2a, 2b, and 2y variants. Since Botan has never been
affected by any of the bugs which necessitated these version upgrades, all
three versions are identical beyond the version identifier. Which variant to
use is controlled by the ``bcrypt_version`` argument.
The bcrypt work factor must be at least 4 (though at this work factor bcrypt
is not very secure). The bcrypt format allows up to 31, but Botan currently
rejects all work factors greater than 18 since even that work factor requires
roughly 15 seconds of computation on a fast machine.
.. cpp:function:: bool check_bcrypt(const std::string& password, \
const std::string& hash)
Takes a password and a bcrypt output and returns true if the
password is the same as the one that was used to generate the
bcrypt hash.
.. _passhash9:
Passhash9
----------------------------------------
Botan also provides a password hashing technique called passhash9, in
``passhash9.h``, which is based on PBKDF2.
Passhash9 hashes look like::
"$9$AAAKxwMGNPSdPkOKJS07Xutm3+1Cr3ytmbnkjO6LjHzCMcMQXvcT"
This function should be secure with the proper parameters, and will remain in
the library for the foreseeable future, but it is specific to Botan rather than
being a widely used password hash. Prefer bcrypt or Argon2.
.. warning::
This password format string ("$9$") conflicts with the format used
for scrypt password hashes on Cisco systems.
.. cpp:function:: std::string generate_passhash9(const std::string& password, \
RandomNumberGenerator& rng, uint16_t work_factor = 15, uint8_t alg_id = 4)
Functions much like ``generate_bcrypt``. The last parameter,
``alg_id``, specifies which PRF to use. Currently defined values are
0: HMAC(SHA-1), 1: HMAC(SHA-256), 2: CMAC(Blowfish), 3: HMAC(SHA-384), 4: HMAC(SHA-512)
The work factor must be greater than zero and less than 512. This performs
10000 * ``work_factor`` PBKDF2 iterations, using 96 bits of salt taken from
``rng``. Using work factor of 10 or more is recommended.
.. cpp:function:: bool check_passhash9(const std::string& password, \
const std::string& hash)
Functions much like ``check_bcrypt``

View File

@ -1,294 +0,0 @@
.. _pbkdf:
Password Based Key Derivation
========================================
Often one needs to convert a human readable password into a cryptographic
key. It is useful to slow down the computation of these computations in order to
reduce the speed of brute force search, thus they are parameterized in some
way which allows their required computation to be tuned.
PasswordHash
--------------
.. versionadded:: 2.8.0
This API, declared in ``pwdhash.h``, has two classes, ``PasswordHashFamily``
representing the general algorithm, such as "PBKDF2(SHA-256)", or "Scrypt", and
``PasswordHash`` representing a specific instance of the problem which is fully
specified with all parameters (say "Scrypt" with ``N`` = 8192, ``r`` = 64, and
``p`` = 8) and which can be used to derive keys.
.. cpp:class:: PasswordHash
.. cpp:function:: void hash(std::span<uint8_t> out, \
std::string_view password, \
std::span<uint8> salt)
Derive a key from the specified *password* and *salt*, placing it into *out*.
.. cpp:function:: void hash(std::span<uint8_t> out, \
std::string_view password, \
std::span<const uint8> salt, \
std::span<const uint8> ad, \
std::span<const uint8> key)
Derive a key from the specified *password*, *salt*, associated data (*ad*), and
secret *key*, placing it into *out*. The *ad* and *key* are both allowed
to be empty. Currently non-empty AD/key is only supported with Argon2.
.. cpp:function:: void derive_key(uint8_t out[], size_t out_len, \
const char* password, const size_t password_len, \
const uint8_t salt[], size_t salt_len) const
Same functionality as the 3 argument variant of :cpp:func:`PasswordHash::hash`.
.. cpp:function:: void derive_key(uint8_t out[], size_t out_len, \
const char* password, const size_t password_len, \
const uint8_t salt[], size_t salt_len, \
const uint8_t ad[], size_t ad_len, \
const uint8_t key[], size_t key_len) const
Same functionality as the 5 argument variant of :cpp:func:`PasswordHash::hash`.
.. cpp:function:: std::string to_string() const
Return a descriptive string including the parameters (iteration count, etc)
.. cpp:function:: size_t iterations() const
Return the iteration parameter
.. cpp:function:: size_t memory_param() const
Return the memory usage parameter, or 0 if the algorithm does not offer
a memory usage option.
.. cpp:function:: size_t parallelism() const
Returns the parallelism parameter, or 0 if the algorithm does not offer a
parallelism option.
.. cpp:function:: size_t total_memory_usage() const
Return a guesstimate of the total number of bytes of memory consumed when
running this algorithm. If the function is not intended to be memory-hard
and uses an effictively fixed amount of memory when running, this function
returns 0.
.. cpp:function:: bool supports_keyed_operation() const
Returns true if this password hash supports supplying a secret key
to :cpp:func:`PasswordHash::hash`.
.. cpp:function:: bool supports_associated_data() const
Returns true if this password hash supports supplying associated data
to :cpp:func:`PasswordHash::hash`.
The ``PasswordHashFamily`` creates specific instances of ``PasswordHash``:
.. cpp:class:: PasswordHashFamily
.. cpp:function:: static std::unique_ptr<PasswordHashFamily> create(const std::string& what)
For example "PBKDF2(SHA-256)", "Scrypt", "Argon2id". Returns null if the
algorithm is not available.
.. cpp:function:: std::unique_ptr<PasswordHash> default_params() const
Create a default instance of the password hashing algorithm. Be warned the
value returned here may change from release to release.
.. cpp:function:: std::unique_ptr<PasswordHash> tune( \
size_t output_len, \
std::chrono::milliseconds msec, \
size_t max_memory_usage_mb = 0, \
std::chrono::milliseconds tuning_msec = std::chrono::milliseconds(10)) const
Return a password hash instance tuned to run for approximately ``msec``
milliseconds when producing an output of length ``output_len``. (Accuracy
may vary, use the command line utility ``botan pbkdf_tune`` to check.)
The parameters will be selected to use at most *max_memory_usage_mb* megabytes
of memory, or if left as zero any size is allowed.
This function works by runing a short tuning loop to estimate the
performance of the algorithm, then scaling the parameters appropriately to
hit the target size. The length of time the tuning loop runs can be
controlled using the *tuning_msec* parameter.
.. cpp:function:: std::unique_ptr<PasswordHash> from_params( \
size_t i1, size_t i2 = 0, size_t i3 = 0) const
Create a password hash using some scheme specific format. Parameters are as follows:
* For PBKDF2, PGP-S2K, and Bcrypt-PBKDF, ``i1`` is iterations
* Scrypt uses ``i1`` == ``N``, ``i2`` == ``r``, and ``i3`` == ``p``
* Argon2 family uses ``i1`` == ``M``, ``i2`` == ``t``, and ``i3`` == ``p``
All unneeded parameters should be set to 0 or left blank.
Code Example
------------
An example demonstrating using the API to hash a password using Argon2i:
.. literalinclude:: /../src/examples/pwdhash.cpp
:language: cpp
Available Schemes
----------------------
General Recommendations
^^^^^^^^^^^^^^^^^^^^^^^^^
If you need wide interoperability use PBKDF2 with HMAC-SHA256 and at least 50K
iterations. If you don't, use Argon2id with p=1, t=3 and M as large as you
can reasonably set (say 1 gigabyte).
You can test how long a particular PBKDF takes to execute using the cli tool
``pbkdf_tune``::
$ ./botan pbkdf_tune --algo=Argon2id 500 --max-mem=192 --check
For 500 ms selected Argon2id(196608,3,1) using 192 MiB took 413.159 msec to compute
This returns the parameters chosen by the fast auto-tuning algorithm, and
because ``--check`` was supplied the hash is also executed with the full set of
parameters and timed.
PBKDF2
^^^^^^^^^^^^
PBKDF2 is the "standard" password derivation scheme, widely implemented in many
different libraries. It uses HMAC internally and requires choosing a hash
function to use. (If in doubt use SHA-256 or SHA-512). It also requires choosing
an iteration count, which makes brute force attacks more expensive. Use *at
least* 50000 and preferably much more. Using 250,000 would not be unreasonable.
Scrypt
^^^^^^^^^^
.. versionadded:: 2.7.0
Scrypt is a relatively newer design which is "memory hard" - in
addition to requiring large amounts of CPU power it uses a large block
of memory to compute the hash. This makes brute force attacks using
ASICs substantially more expensive.
Scrypt has three parameters, usually termed ``N``, ``r``, and ``p``. ``N`` is
the primary control of the workfactor, and must be a power of 2. For interactive
logins use 32768, for protection of secret keys or backups use 1048576.
The ``r`` parameter controls how 'wide' the internal hashing operation is. It
also increases the amount of memory that is used. Values from 1 to 8 are
reasonable.
Setting ``p`` parameter to greater than 1 splits up the work in a way that up
to p processors can work in parallel.
As a general recommendation, use ``N`` = 32768, ``r`` = 8, ``p`` = 1
Argon2
^^^^^^^^^^
.. versionadded:: 2.11.0
Argon2 is the winner of the PHC (Password Hashing Competition) and
provides a tunable memory hard PBKDF. There are three minor variants
of Argon2 - Argon2d, Argon2i, and Argon2id. All three are implemented.
Bcrypt
^^^^^^^^^^^^
.. versionadded:: 2.11.0
Bcrypt-PBKDF is a variant of the well known ``bcrypt`` password hashing
function. Like ``bcrypt`` it is based around using Blowfish for the key
expansion, which requires 4 KiB of fast random access memory, making hardware
based attacks more expensive. Unlike Argon2 or Scrypt, the memory usage is not
tunable.
This function is relatively obscure but is used for example in OpenSSH.
Prefer Argon2 or Scrypt in new systems.
OpenPGP S2K
^^^^^^^^^^^^
.. warning::
The OpenPGP algorithm is weak and strange, and should be avoided unless
implementing OpenPGP.
There are some oddities about OpenPGP's S2K algorithms that are documented
here. For one thing, it uses the iteration count in a strange manner; instead of
specifying how many times to iterate the hash, it tells how many *bytes* should
be hashed in total (including the salt). So the exact iteration count will
depend on the size of the salt (which is fixed at 8 bytes by the OpenPGP
standard, though the implementation will allow any salt size) and the size of
the passphrase.
To get what OpenPGP calls "Simple S2K", set iterations to 0, and do not specify
a salt. To get "Salted S2K", again leave the iteration count at 0, but give an
8-byte salt. "Salted and Iterated S2K" requires an 8-byte salt and some
iteration count (this should be significantly larger than the size of the
longest passphrase that might reasonably be used; somewhere from 1024 to 65536
would probably be about right). Using both a reasonably sized salt and a large
iteration count is highly recommended to prevent password guessing attempts.
PBKDF
---------
:cpp:class:`PBKDF` is the older API for this functionality, presented in header
``pbkdf.h``. It only supports PBKDF2 and the PGP S2K algorithm, not
Scrypt, Argon2, or bcrypt. This interface is deprecated and will be removed
in a future major release.
In addition, this API requires the passphrase be entered as a
``std::string``, which means the secret will be stored in memory that
will not be zeroed.
.. cpp:class:: PBKDF
.. cpp:function:: static std::unique_ptr<PBKDF> create(const std::string& algo_spec, \
const std::string& provider = "")
Return a newly created PBKDF object. The name should be in the
format "PBKDF2(HASHNAME)", "PBKDF2(HMAC(HASHNAME))", or
"OpenPGP-S2K". Returns null if the algorithm is not available.
.. cpp:function:: void pbkdf_iterations(uint8_t out[], size_t out_len, \
const std::string& passphrase, \
const uint8_t salt[], size_t salt_len, \
size_t iterations) const
Run the PBKDF algorithm for the specified number of iterations,
with the given salt, and write output to the buffer.
.. cpp:function:: void pbkdf_timed(uint8_t out[], size_t out_len, \
const std::string& passphrase, \
const uint8_t salt[], size_t salt_len, \
std::chrono::milliseconds msec, \
size_t& iterations) const
Choose (via short run-time benchmark) how many iterations to perform
in order to run for roughly msec milliseconds. Writes the number
of iterations used to reference argument.
.. cpp:function:: OctetString derive_key( \
size_t output_len, const std::string& passphrase, \
const uint8_t* salt, size_t salt_len, \
size_t iterations) const
Computes a key from *passphrase* and the *salt* (of length
*salt_len* bytes) using an algorithm-specific interpretation of
*iterations*, producing a key of length *output_len*.
Use an iteration count of at least 10000. The salt should be
randomly chosen by a good random number generator (see
:ref:`random_number_generators` for how), or at the very least
unique to this usage of the passphrase.
If you call this function again with the same parameters, you will
get the same key.

View File

@ -1,944 +0,0 @@
.. _pkcs11:
PKCS#11
========================================
.. versionadded:: 1.11.31
|
PKCS#11 is a platform-independent interface for accessing smart cards and
hardware security modules (HSM). Vendors of PKCS#11 compatible devices usually
provide a so called middleware or "PKCS#11 module" which implements the PKCS#11
standard. This middleware translates calls from the platform-independent PKCS#11
API to device specific calls. So application developers don't have to write smart card
or HSM specific code for each device they want to support.
.. note::
The Botan PKCS#11 interface is implemented against version v2.40 of the standard.
Botan wraps the C PKCS#11 API to provide a C++ PKCS#11 interface. This is done
in two levels of abstraction: a low level API (see :ref:`pkcs11_low_level`) and
a high level API (see :ref:`pkcs11_high_level`). The low level API provides
access to all functions that are specified by the standard. The high level API
represents an object oriented approach to use PKCS#11 compatible devices but
only provides a subset of the functions described in the standard.
To use the PKCS#11 implementation the ``pkcs11`` module has to be enabled.
.. note::
Both PKCS#11 APIs live in the namespace ``Botan::PKCS11``
.. _pkcs11_low_level:
Low Level API
----------------------------------------
The PKCS#11 standards committee provides header files (``pkcs11.h``, ``pkcs11f.h`` and
``pkcs11t.h``) which define the PKCS#11 API in the C programming language. These
header files could be used directly to access PKCS#11 compatible smart cards or
HSMs. The external header files are shipped with Botan in version v2.4 of the standard. The PKCS#11 low
level API wraps the original PKCS#11 API, but still allows to access all functions described in the
standard and has the advantage that it is a C++ interface with features like RAII, exceptions
and automatic memory management.
The low level API is implemented by the :cpp:class:`LowLevel` class and can be accessed by
including the header ``botan/p11.h``.
Preface
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
All constants that belong together in the PKCS#11 standard are grouped into C++
enum classes. For example the different user types are grouped in the
:cpp:enum:`UserType` enumeration:
.. cpp:enum-class:: UserType : CK_USER_TYPE
.. cpp:enumerator:: UserType::SO = CKU_SO
.. cpp:enumerator:: UserType::User = CKU_USER
.. cpp:enumerator:: UserType::ContextSpecific = CKU_CONTEXT_SPECIFIC
Additionally, all types that are used by the low or high level API are mapped by
type aliases to more C++ like names. For instance:
.. cpp:type:: FunctionListPtr = CK_FUNCTION_LIST_PTR
.. rubric:: C-API Wrapping
There is at least one method in the :cpp:class:`LowLevel` class that corresponds to a PKCS#11
function. For example the :cpp:func:`C_GetSlotList` method in the :cpp:class:`LowLevel` class is defined as follows:
.. cpp:class:: LowLevel
.. cpp:function:: bool C_GetSlotList(Bbool token_present, SlotId* slot_list_ptr, Ulong* count_ptr, ReturnValue* return_value = ThrowException) const
The :cpp:class:`LowLevel` class calls the PKCS#11 function from the function list of the PKCS#11 module:
.. code-block:: c
CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)( CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
CK_ULONG_PTR pulCount )
Where it makes sense there is also an overload of the :cpp:class:`LowLevel` method to make usage easier and safer:
.. cpp:function:: bool C_GetSlotList( bool token_present, std::vector<SlotId>& slot_ids, ReturnValue* return_value = ThrowException ) const
With this overload the user of this API just has to pass a vector of :cpp:type:`SlotId` instead of pointers
to preallocated memory for the slot list and the number of elements. Additionally, there is no need
to call the method twice in order to determine the number of elements first.
Another example is the :cpp:func:`C_InitPIN` overload:
.. cpp:function:: template<typename Talloc> bool C_InitPIN( SessionHandle session, const std::vector<uint8_t, TAlloc>& pin, ReturnValue* return_value = ThrowException ) const
The templated ``pin`` parameter allows to pass the PIN as a ``std::vector<uint8_t>`` or a ``secure_vector<uint8_t>``.
If used with a ``secure_vector`` it is assured that the memory is securely erased when the ``pin`` object is no longer needed.
Error Handling
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All possible PKCS#11 return values are represented by the enum class:
.. cpp:enum-class:: ReturnValue : CK_RV
All methods of the :cpp:class:`LowLevel` class have a default parameter ``ReturnValue* return_value = ThrowException``.
This parameter controls the error handling of all :cpp:class:`LowLevel` methods. The default
behavior ``return_value = ThrowException`` is to throw an exception if the method does
not complete successfully. If a non-``NULL`` pointer is passed, ``return_value`` receives the
return value of the PKCS#11 function and no exception is thrown. In case ``nullptr`` is
passed as ``return_value``, the exact return value is ignored and the method just returns
``true`` if the function succeeds and ``false`` otherwise.
Getting started
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
An object of this class can be accessed by the ``Module::operator->()`` method.
----------
Code Example:
.. literalinclude:: /../src/examples/pkcs11_low_level.cpp
:language: cpp
.. _pkcs11_high_level:
High Level API
----------------------------------------
The high level API provides access to the most commonly used PKCS#11 functionality in an
object oriented manner. Functionality of the high level API includes:
* Loading/unloading of PKCS#11 modules
* Initialization of tokens
* Change of PIN/SO-PIN
* Session management
* Random number generation
* Enumeration of objects on the token (certificates, public keys, private keys)
* Import/export/deletion of certificates
* Generation/import/export/deletion of RSA and EC public and private keys
* Encryption/decryption using RSA with support for OAEP and PKCS1-v1_5 (and raw)
* Signature generation/verification using RSA with support for PSS and PKCS1-v1_5 (and raw)
* Signature generation/verification using ECDSA
* Key derivation using ECDH
Module
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The :cpp:class:`Module` class represents a PKCS#11 shared library (module) and is defined in
``botan/p11_module.h``.
It is constructed from a a file path to a PKCS#11 module and optional :cpp:type:`C_InitializeArgs`:
.. cpp:class:: Module
.. code-block:: cpp
Module(const std::string& file_path, C_InitializeArgs init_args =
{ nullptr, nullptr, nullptr, nullptr, static_cast<CK_FLAGS>(Flag::OsLockingOk), nullptr })
It loads the shared library and calls :cpp:func:`C_Initialize` with the provided :cpp:type:`C_InitializeArgs`.
On destruction of the object :cpp:func:`C_Finalize` is called.
There are two more methods in this class. One is for reloading the shared library
and reinitializing the PKCS#11 module:
.. code-block:: cpp
void reload(C_InitializeArgs init_args =
{ nullptr, nullptr, nullptr, nullptr, static_cast< CK_FLAGS >(Flag::OsLockingOk), nullptr });
The other one is for getting general information about the PKCS#11 module:
.. cpp:function:: Info get_info() const
This function calls :cpp:func:`C_GetInfo` internally.
----------
Code example:
.. literalinclude:: /../src/examples/pkcs11_module.cpp
:language: cpp
Slot
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The :cpp:class:`Slot` class represents a PKCS#11 slot and is defined in
``botan/p11_slot.h``.
A PKCS#11 slot is usually a smart card reader that potentially contains a token.
.. cpp:class:: Slot
.. cpp:function:: Slot(Module& module, SlotId slot_id)
To instantiate this class a reference to a :cpp:class:`Module` object and a ``slot_id`` have to be passed
to the constructor.
.. cpp:function:: static std::vector<SlotId> get_available_slots(Module& module, bool token_present)
Retrieve available slot ids by calling this static method.
The parameter ``token_present`` controls whether all slots or only slots with a
token attached are returned by this method. This method calls :cpp:func:`C_GetSlotList()`.
.. cpp:function:: SlotInfo get_slot_info() const
Returns information about the slot. Calls :cpp:func:`C_GetSlotInfo`.
.. cpp:function:: TokenInfo get_token_info() const
Obtains information about a particular token in the system. Calls :cpp:func:`C_GetTokenInfo`.
.. cpp:function:: std::vector<MechanismType> get_mechanism_list() const
Obtains a list of mechanism types supported by the slot. Calls :cpp:func:`C_GetMechanismList`.
.. cpp:function:: MechanismInfo get_mechanism_info(MechanismType mechanism_type) const
Obtains information about a particular mechanism possibly supported by a slot.
Calls :cpp:func:`C_GetMechanismInfo`.
.. cpp:function:: void initialize(const std::string& label, const secure_string& so_pin) const
Calls :cpp:func:`C_InitToken` to initialize the token. The ``label`` must not exceed 32 bytes.
The current PIN of the security officer must be passed in ``so_pin`` if the token
is reinitialized or if it's a factory new token, the ``so_pin`` that is passed will initially be set.
----------
Code example:
.. literalinclude:: /../src/examples/pkcs11_slot.cpp
:language: cpp
Session
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The :cpp:class:`Session` class represents a PKCS#11 session and is defined in ``botan/p11_session.h``.
A session is a logical connection between an application and a token.
The session is passed to most other PKCS#11 operations, and must remain alive
as long as any other PKCS#11 object which the session was passed to is still
alive, otherwise errors or even an application crash are possible.
In the future,
the API may change to using ``shared_ptr`` to remove this problem.
.. cpp:class:: Session
There are two constructors to create a new session and one constructor to
take ownership of an existing session. The destructor calls
:cpp:func:`C_Logout` if a user is logged in to this session and always
:cpp:func:`C_CloseSession`.
.. cpp:function:: Session(Slot& slot, bool read_only)
To initialize a session object a :cpp:class:`Slot` has to be specified on which the session
should operate. ``read_only`` specifies whether the session should be read only or read write.
Calls :cpp:func:`C_OpenSession`.
.. cpp:function:: Session(Slot& slot, Flags flags, VoidPtr callback_data, Notify notify_callback)
Creates a new session by passing a :cpp:class:`Slot`, session ``flags``, ``callback_data`` and a
``notify_callback``. Calls :cpp:func:`C_OpenSession`.
.. cpp:function:: Session(Slot& slot, SessionHandle handle)
Takes ownership of an existing session by passing :cpp:class:`Slot` and a session ``handle``.
.. cpp:function:: SessionHandle release()
Returns the released :cpp:type:`SessionHandle`
.. cpp:function:: void login(UserType userType, const secure_string& pin)
Login to this session by passing :cpp:enum:`UserType` and ``pin``. Calls :cpp:func:`C_Login`.
.. cpp:function:: void logoff()
Logout from this session. Not mandatory because on destruction of the :cpp:class:`Session` object
this is done automatically.
.. cpp:function:: SessionInfo get_info() const
Returns information about this session. Calls :cpp:func:`C_GetSessionInfo`.
.. cpp:function:: void set_pin(const secure_string& old_pin, const secure_string& new_pin) const
Calls :cpp:func:`C_SetPIN` to change the PIN of the logged in user using the ``old_pin``.
.. cpp:function:: void init_pin(const secure_string& new_pin)
Calls :cpp:func:`C_InitPIN` to change or initialize the PIN using the SO_PIN (requires a logged in session).
----------
Code example:
.. literalinclude:: /../src/examples/pkcs11_session.cpp
:language: cpp
Objects
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PKCS#11 objects consist of various attributes (:c:type:`CK_ATTRIBUTE`). For example :c:macro:`CKA_TOKEN`
describes if a PKCS#11 object is a session object or a token object. The helper class :cpp:class:`AttributeContainer`
helps with storing these attributes. The class is defined in ``botan/p11_object.h``.
.. cpp:class:: AttributeContainer
Attributes can be set in an :cpp:class:`AttributeContainer` by various ``add_`` methods:
.. cpp:function:: void add_class(ObjectClass object_class)
Add a class attribute (:c:macro:`CKA_CLASS` / :cpp:enumerator:`AttributeType::Class`)
.. cpp:function:: void add_string(AttributeType attribute, const std::string& value)
Add a string attribute (e.g. :c:macro:`CKA_LABEL` / :cpp:enumerator:`AttributeType::Label`).
.. cpp:function:: void AttributeContainer::add_binary(AttributeType attribute, const uint8_t* value, size_t length)
Add a binary attribute (e.g. :c:macro:`CKA_ID` / :cpp:enumerator:`AttributeType::Id`).
.. cpp:function:: template<typename TAlloc> void AttributeContainer::add_binary(AttributeType attribute, const std::vector<uint8_t, TAlloc>& binary)
Add a binary attribute by passing a ``vector``/``secure_vector`` (e.g. :c:macro:`CKA_ID` / :cpp:enumerator:`AttributeType::Id`).
.. cpp:function:: void AttributeContainer::add_bool(AttributeType attribute, bool value)
Add a bool attribute (e.g. :c:macro:`CKA_SENSITIVE` / :cpp:enumerator:`AttributeType::Sensitive`).
.. cpp:function:: template<typename T> void AttributeContainer::add_numeric(AttributeType attribute, T value)
Add a numeric attribute (e.g. :c:macro:`CKA_MODULUS_BITS` / :cpp:enumerator:`AttributeType::ModulusBits`).
.. rubric:: Object Properties
The PKCS#11 standard defines the mandatory and optional attributes for each object class.
The mandatory and optional attribute requirements are mapped in so called property classes.
Mandatory attributes are set in the constructor, optional attributes can be set via ``set_`` methods.
In the top hierarchy is the :cpp:class:`ObjectProperties` class which inherits from the :cpp:class:`AttributeContainer`.
This class represents the common attributes of all PKCS#11 objects.
.. cpp:class:: ObjectProperties : public AttributeContainer
The constructor is defined as follows:
.. cpp:function:: ObjectProperties::ObjectProperties(ObjectClass object_class)
Every PKCS#11 object needs an object class attribute.
The next level defines the :cpp:class:`StorageObjectProperties` class which inherits from
:cpp:class:`ObjectProperties`.
.. cpp:class:: StorageObjectProperties : public ObjectProperties
The only mandatory attribute is the object class, so the constructor is
defined as follows:
.. cpp:function:: StorageObjectProperties::StorageObjectProperties(ObjectClass object_class)
But in contrast to the :cpp:class:`ObjectProperties` class there are various setter methods. For example to
set the :cpp:enumerator:`AttributeType::Label`:
.. cpp:function:: void set_label(const std::string& label)
Sets the label description of the object (RFC2279 string).
The remaining hierarchy is defined as follows:
* :cpp:class:`DataObjectProperties` inherits from :cpp:class:`StorageObjectProperties`
* :cpp:class:`CertificateProperties` inherits from :cpp:class:`StorageObjectProperties`
* :cpp:class:`DomainParameterProperties` inherits from :cpp:class:`StorageObjectProperties`
* :cpp:class:`KeyProperties` inherits from :cpp:class:`StorageObjectProperties`
* :cpp:class:`PublicKeyProperties` inherits from :cpp:class:`KeyProperties`
* :cpp:class:`PrivateKeyProperties` inherits from :cpp:class:`KeyProperties`
* :cpp:class:`SecretKeyProperties` inherits from :cpp:class:`KeyProperties`
PKCS#11 objects themselves are represented by the :cpp:class:`Object` class.
.. cpp:class:: Object
Following constructors are defined:
.. cpp:function:: Object::Object(Session& session, ObjectHandle handle)
Takes ownership over an existing object.
.. cpp:function:: Object::Object(Session& session, const ObjectProperties& obj_props)
Creates a new object with the :cpp:class:`ObjectProperties` provided in ``obj_props``.
The other methods are:
.. cpp:function:: secure_vector<uint8_t> get_attribute_value(AttributeType attribute) const
Returns the value of the given attribute (using :cpp:func:`C_GetAttributeValue`)
.. cpp:function:: void set_attribute_value(AttributeType attribute, const secure_vector<uint8_t>& value) const
Sets the given value for the attribute (using :cpp:func:`C_SetAttributeValue`)
.. cpp:function:: void destroy() const
Destroys the object.
.. cpp:function:: ObjectHandle copy(const AttributeContainer& modified_attributes) const
Allows to copy the object with modified attributes.
And static methods to search for objects:
.. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::vector<Attribute>& search_template)
Searches for all objects of the given type that match ``search_template``.
.. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::string& label)
Searches for all objects of the given type using the label (:c:macro:`CKA_LABEL`).
.. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::vector<uint8_t>& id)
Searches for all objects of the given type using the id (:c:macro:`CKA_ID`).
.. cpp:function:: template<typename T> static std::vector<T> search(Session& session, const std::string& label, const std::vector<uint8_t>& id)
Searches for all objects of the given type using the label (:c:macro:`CKA_LABEL`) and id (:c:macro:`CKA_ID`).
.. cpp:function:: template<typename T> static std::vector<T> search(Session& session)
Searches for all objects of the given type.
.. rubric:: The ObjectFinder
Another way for searching objects is to use the :cpp:class:`ObjectFinder` class. This class
manages calls to the ``C_FindObjects*`` functions: :cpp:func:`C_FindObjectsInit`, :cpp:func:`C_FindObjects`
and :cpp:func:`C_FindObjectsFinal`.
.. cpp:class:: ObjectFinder
The constructor has the following signature:
.. cpp:function:: ObjectFinder::ObjectFinder(Session& session, const std::vector<Attribute>& search_template)
A search can be prepared with an :cpp:class:`ObjectSearcher` by passing a :cpp:class:`Session` and a ``search_template``.
The actual search operation is started by calling the :cpp:func:`find` method:
.. cpp:function:: std::vector<ObjectHandle> find(std::uint32_t max_count = 100) const
Starts or continues a search for token and session objects that match a template. ``max_count``
specifies the maximum number of search results (object handles) that are returned.
.. cpp:function:: void finish()
Finishes the search operation manually to allow a new :cpp:class:`ObjectFinder` to exist.
Otherwise the search is finished by the destructor.
----------
Code example:
.. literalinclude:: /../src/examples/pkcs11_objects.cpp
:language: cpp
RSA
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PKCS#11 RSA support is implemented in ``<botan/p11_rsa.h>``.
.. rubric:: RSA Public Keys
PKCS#11 RSA public keys are provided by the class :cpp:class:`PKCS11_RSA_PublicKey`. This class
inherits from :cpp:class:`RSA_PublicKey` and :cpp:class:`Object`. Furthermore there are two property classes defined
to generate and import RSA public keys analogous to the other property classes described
before: :cpp:class:`RSA_PublicKeyGenerationProperties` and :cpp:class:`RSA_PublicKeyImportProperties`.
.. cpp:class:: PKCS11_RSA_PublicKey : public RSA_PublicKey, public Object
.. cpp:function:: PKCS11_RSA_PublicKey(Session& session, ObjectHandle handle)
Existing PKCS#11 RSA public keys can be used by providing an :cpp:type:`ObjectHandle` to the
constructor.
.. cpp:function:: PKCS11_RSA_PublicKey(Session& session, const RSA_PublicKeyImportProperties& pubkey_props)
This constructor can be used to import an existing RSA public key with the :cpp:class:`RSA_PublicKeyImportProperties`
passed in ``pubkey_props`` to the token.
.. rubric:: RSA Private Keys
The support for PKCS#11 RSA private keys is implemented in a similar way. There are two property
classes: :cpp:class:`RSA_PrivateKeyGenerationProperties` and :cpp:class:`RSA_PrivateKeyImportProperties`. The :cpp:class:`PKCS11_RSA_PrivateKey`
class implements the actual support for PKCS#11 RSA private keys. This class inherits from :cpp:class:`Private_Key`,
:cpp:class:`RSA_PublicKey` and :cpp:class:`Object`. In contrast to the public key class there is a third constructor
to generate private keys directly on the token or in the session and one method to export private keys.
.. cpp:class:: PKCS11_RSA_PrivateKey : public Private_Key, public RSA_PublicKey, public Object
.. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, ObjectHandle handle)
Existing PKCS#11 RSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
constructor.
.. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, const RSA_PrivateKeyImportProperties& priv_key_props)
This constructor can be used to import an existing RSA private key with the :cpp:class:`RSA_PrivateKeyImportProperties`
passed in ``priv_key_props`` to the token.
.. cpp:function:: PKCS11_RSA_PrivateKey(Session& session, uint32_t bits, const RSA_PrivateKeyGenerationProperties& priv_key_props)
Generates a new PKCS#11 RSA private key with bit length provided in ``bits`` and the :cpp:class:`RSA_PrivateKeyGenerationProperties`
passed in ``priv_key_props``.
.. cpp:function:: RSA_PrivateKey export_key() const
Returns the exported :cpp:class:`RSA_PrivateKey`.
PKCS#11 RSA key pairs can be generated with the following free function:
.. cpp:function:: PKCS11_RSA_KeyPair PKCS11::generate_rsa_keypair(Session& session, const RSA_PublicKeyGenerationProperties& pub_props, const RSA_PrivateKeyGenerationProperties& priv_props)
----------
Code example:
.. literalinclude:: /../src/examples/pkcs11_rsa.cpp
:language: cpp
ECDSA
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PKCS#11 ECDSA support is implemented in ``<botan/p11_ecdsa.h>``.
.. rubric:: ECDSA Public Keys
PKCS#11 ECDSA public keys are provided by the class :cpp:class:`PKCS11_ECDSA_PublicKey`. This class
inherits from :cpp:class:`PKCS11_EC_PublicKey` and :cpp:class:`ECDSA_PublicKey`. The necessary property classes
are defined in ``<botan/p11_ecc_key.h>``. For public keys there are :cpp:class:`EC_PublicKeyGenerationProperties`
and :cpp:class:`EC_PublicKeyImportProperties`.
.. cpp:class:: PKCS11_ECDSA_PublicKey : public PKCS11_EC_PublicKey, public virtual ECDSA_PublicKey
.. cpp:function:: PKCS11_ECDSA_PublicKey(Session& session, ObjectHandle handle)
Existing PKCS#11 ECDSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
constructor.
.. cpp:function:: PKCS11_ECDSA_PublicKey(Session& session, const EC_PublicKeyImportProperties& props)
This constructor can be used to import an existing ECDSA public key with the :cpp:class:`EC_PublicKeyImportProperties`
passed in ``props`` to the token.
.. cpp:function:: ECDSA_PublicKey PKCS11_ECDSA_PublicKey::export_key() const
Returns the exported :cpp:class:`ECDSA_PublicKey`.
.. rubric:: ECDSA Private Keys
The class :cpp:class:`PKCS11_ECDSA_PrivateKey` inherits from :cpp:class:`PKCS11_EC_PrivateKey` and implements support
for PKCS#11 ECDSA private keys. There are two property classes for key generation
and import: :cpp:class:`EC_PrivateKeyGenerationProperties` and :cpp:class:`EC_PrivateKeyImportProperties`.
.. cpp:class:: PKCS11_ECDSA_PrivateKey : public PKCS11_EC_PrivateKey
.. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, ObjectHandle handle)
Existing PKCS#11 ECDSA private keys can be used by providing an :cpp:type:`ObjectHandle` to the
constructor.
.. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props)
This constructor can be used to import an existing ECDSA private key with the :cpp:class:`EC_PrivateKeyImportProperties`
passed in ``props`` to the token.
.. cpp:function:: PKCS11_ECDSA_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params, const EC_PrivateKeyGenerationProperties& props)
This constructor can be used to generate a new ECDSA private key with the :cpp:class:`EC_PrivateKeyGenerationProperties`
passed in ``props`` on the token. The ``ec_params`` parameter is the DER-encoding of an
ANSI X9.62 Parameters value.
.. cpp:function:: ECDSA_PrivateKey export_key() const
Returns the exported :cpp:class:`ECDSA_PrivateKey`.
PKCS#11 ECDSA key pairs can be generated with the following free function:
.. cpp:function:: PKCS11_ECDSA_KeyPair PKCS11::generate_ecdsa_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props, const EC_PrivateKeyGenerationProperties& priv_props)
----------
Code example:
.. literalinclude:: /../src/examples/pkcs11_ecdsa.cpp
:language: cpp
ECDH
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PKCS#11 ECDH support is implemented in ``<botan/p11_ecdh.h>``.
.. rubric:: ECDH Public Keys
PKCS#11 ECDH public keys are provided by the class :cpp:class:`PKCS11_ECDH_PublicKey`. This class
inherits from :cpp:class:`PKCS11_EC_PublicKey`. The necessary property classes
are defined in ``<botan/p11_ecc_key.h>``. For public keys there are :cpp:class:`EC_PublicKeyGenerationProperties`
and :cpp:class:`EC_PublicKeyImportProperties`.
.. cpp:class:: PKCS11_ECDH_PublicKey : public PKCS11_EC_PublicKey
.. cpp:function:: PKCS11_ECDH_PublicKey(Session& session, ObjectHandle handle)
Existing PKCS#11 ECDH private keys can be used by providing an :cpp:type:`ObjectHandle` to the
constructor.
.. cpp:function:: PKCS11_ECDH_PublicKey(Session& session, const EC_PublicKeyImportProperties& props)
This constructor can be used to import an existing ECDH public key with the :cpp:class:`EC_PublicKeyImportProperties`
passed in ``props`` to the token.
.. cpp:function:: ECDH_PublicKey export_key() const
Returns the exported :cpp:class:`ECDH_PublicKey`.
.. rubric:: ECDH Private Keys
The class :cpp:class:`PKCS11_ECDH_PrivateKey` inherits from :cpp:class:`PKCS11_EC_PrivateKey` and :cpp:class:`PK_Key_Agreement_Key`
and implements support for PKCS#11 ECDH private keys. There are two
property classes. One for key generation and one for import: :cpp:class:`EC_PrivateKeyGenerationProperties` and
:cpp:class:`EC_PrivateKeyImportProperties`.
.. cpp:class:: PKCS11_ECDH_PrivateKey : public virtual PKCS11_EC_PrivateKey, public virtual PK_Key_Agreement_Key
.. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, ObjectHandle handle)
Existing PKCS#11 ECDH private keys can be used by providing an :cpp:type:`ObjectHandle` to the
constructor.
.. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props)
This constructor can be used to import an existing ECDH private key with the :cpp:class:`EC_PrivateKeyImportProperties`
passed in ``props`` to the token.
.. cpp:function:: PKCS11_ECDH_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params, const EC_PrivateKeyGenerationProperties& props)
This constructor can be used to generate a new ECDH private key with the :cpp:class:`EC_PrivateKeyGenerationProperties`
passed in ``props`` on the token. The ``ec_params`` parameter is the DER-encoding of an
ANSI X9.62 Parameters value.
.. cpp:function:: ECDH_PrivateKey export_key() const
Returns the exported :cpp:class:`ECDH_PrivateKey`.
PKCS#11 ECDH key pairs can be generated with the following free function:
.. cpp:function:: PKCS11_ECDH_KeyPair PKCS11::generate_ecdh_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props, const EC_PrivateKeyGenerationProperties& priv_props)
----------
Code example:
.. literalinclude:: /../src/examples/pkcs11_ecdh.cpp
:language: cpp
RNG
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The PKCS#11 RNG is defined in ``<botan/p11_randomgenerator.h>``. The class :cpp:class:`PKCS11_RNG`
implements the :cpp:class:`Hardware_RNG` interface.
.. cpp:class:: PKCS11_RNG : public Hardware_RNG
.. cpp:function:: PKCS11_RNG(Session& session)
A PKCS#11 :cpp:class:`Session` must be passed to instantiate a ``PKCS11_RNG``.
.. cpp:function:: void randomize(uint8_t output[], std::size_t length) override
Calls :cpp:func:`C_GenerateRandom` to generate random data.
.. cpp:function:: void add_entropy(const uint8_t in[], std::size_t length) override
Calls :cpp:func:`C_SeedRandom` to add entropy to the random generation function of the token/middleware.
----------
Code example:
.. literalinclude:: /../src/examples/pkcs11_rng.cpp
:language: cpp
Token Management Functions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The header file ``<botan/p11.h>`` also defines some free functions for token management:
.. cpp:function:: void initialize_token(Slot& slot, const std::string& label, const secure_string& so_pin, const secure_string& pin)
Initializes a token by passing a :cpp:class:`Slot`, a ``label`` and the ``so_pin`` of the security officer.
.. cpp:function:: void change_pin(Slot& slot, const secure_string& old_pin, const secure_string& new_pin)
Change PIN with ``old_pin`` to ``new_pin``.
.. cpp:function:: void change_so_pin(Slot& slot, const secure_string& old_so_pin, const secure_string& new_so_pin)
Change SO_PIN with ``old_so_pin`` to new ``new_so_pin``.
.. cpp:function:: void set_pin(Slot& slot, const secure_string& so_pin, const secure_string& pin)
Sets user ``pin`` with ``so_pin``.
----------
Code example:
.. literalinclude:: /../src/examples/pkcs11_token_management.cpp
:language: cpp
X.509
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The header file ``<botan/p11_x509.h>`` defines the property class :cpp:class:`X509_CertificateProperties`
and the class :cpp:class:`PKCS11_X509_Certificate`.
.. cpp:class:: PKCS11_X509_Certificate : public Object, public X509_Certificate
.. cpp:function:: PKCS11_X509_Certificate(Session& session, ObjectHandle handle)
Allows to use existing certificates on the token by passing a valid :cpp:type:`ObjectHandle`.
.. cpp:function:: PKCS11_X509_Certificate(Session& session, const X509_CertificateProperties& props)
Allows to import an existing X.509 certificate to the token with the :cpp:class:`X509_CertificateProperties`
passed in ``props``.
----------
Code example:
.. literalinclude:: /../src/examples/pkcs11_x509.cpp
:language: cpp
Tests
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The PKCS#11 tests are not executed automatically because the depend on an external
PKCS#11 module/middleware. The test tool has to be executed with ``--pkcs11-lib=``
followed with the path of the PKCS#11 module and a second argument which controls the
PKCS#11 tests that are executed. Passing ``pkcs11`` will execute all PKCS#11 tests but it's
also possible to execute only a subset with the following arguments:
- pkcs11-ecdh
- pkcs11-ecdsa
- pkcs11-lowlevel
- pkcs11-manage
- pkcs11-module
- pkcs11-object
- pkcs11-rng
- pkcs11-rsa
- pkcs11-session
- pkcs11-slot
- pkcs11-x509
The following PIN and SO-PIN/PUK values are used in tests:
- PIN 123456
- SO-PIN/PUK 12345678
.. warning::
Unlike the CardOS (4.4, 5.0, 5.3), the aforementioned SO-PIN/PUK is
inappropriate for Gemalto (IDPrime MD 3840) cards, as it must be a byte array
of length 24. For this reason some of the tests for Gemalto card involving
SO-PIN will fail. You run into a risk of exceding login attempts and as a
result locking your card! Currently, specifying pin via command-line option
is not implemented, and therefore the desired PIN must be modified in the
header src/tests/test_pkcs11.h:
.. code-block:: cpp
// SO PIN is expected to be set to "12345678" prior to running the tests
const std::string SO_PIN = "12345678";
const auto SO_PIN_SECVEC = Botan::PKCS11::secure_string(SO_PIN.begin(), SO_PIN.end());
Tested/Supported Smartcards
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You are very welcome to contribute your own test results for other testing environments or other cards.
Test results
+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
| Smartcard | Status | OS | Midleware | Botan | Errors |
+=====================================+===========================================+===================================================+===================================================+===================================================+===================================================+
| CardOS 4.4 | mostly works | Windows 10, 64-bit, version 1709 | API Version 5.4.9.77 (Cryptoki v2.11) | 2.4.0, Cryptoki v2.40 | [50]_ |
+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
| CardOS 5.0 | mostly works | Windows 10, 64-bit, version 1709 | API Version 5.4.9.77 (Cryptoki v2.11) | 2.4.0, Cryptoki v2.40 | [51]_ |
+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
| CardOS 5.3 | mostly works | Windows 10, 64-bit, version 1709 | API Version 5.4.9.77 (Cryptoki v2.11) | 2.4.0, Cryptoki v2.40 | [52]_ |
+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
| CardOS 5.3 | mostly works | Windows 10, 64-bit, version 1903 | API Version 5.5.1 (Cryptoki v2.11) | 2.12.0 unreleased, Cryptoki v2.40 | [53]_ |
+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
| Gemalto IDPrime MD 3840 | mostly works | Windows 10, 64-bit, version 1709 | IDGo 800, v1.2.4 (Cryptoki v2.20) | 2.4.0, Cryptoki v2.40 | [54]_ |
+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
| SoftHSM 2.3.0 (OpenSSL 1.0.2g) | works | Windows 10, 64-bit, version 1709 | Cryptoki v2.40 | 2.4.0, Cryptoki v2.40 | |
+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
| SoftHSM 2.5.0 (OpenSSL 1.1.1) | works | Windows 10, 64-bit, version 1803 | Cryptoki v2.40 | 2.11.0, Cryptoki v2.40 | |
+-------------------------------------+-------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+---------------------------------------------------+
.. [50] Failing operations for CardOS 4.4:
- object_copy [20]_
- rsa_privkey_export [21]_
- rsa_generate_private_key [22]_
- rsa_sign_verify [23]_
- ecdh_privkey_import [3]_
- ecdh_privkey_export [2]_
- ecdh_pubkey_import [4]_
- ecdh_pubkey_export [4]_
- ecdh_generate_private_key [3]_
- ecdh_generate_keypair [3]_
- ecdh_derive [3]_
- ecdsa_privkey_import [3]_
- ecdsa_privkey_export [2]_
- ecdsa_pubkey_import [4]_
- ecdsa_pubkey_export [4]_
- ecdsa_generate_private_key [3]_
- ecdsa_generate_keypair [3]_
- ecdsa_sign_verify [3]_
- rng_add_entropy [5]_
.. [51] Failing operations for CardOS 5.0
- object_copy [20]_
- rsa_privkey_export [21]_
- rsa_generate_private_key [22]_
- rsa_sign_verify [23]_
- ecdh_privkey_export [2]_
- ecdh_pubkey_import [4]_
- ecdh_generate_private_key [32]_
- ecdh_generate_keypair [3]_
- ecdh_derive [33]_
- ecdsa_privkey_export [2]_
- ecdsa_generate_private_key [30]_
- ecdsa_generate_keypair [30]_
- ecdsa_sign_verify [30]_
- rng_add_entropy [5]_
.. [52] Failing operations for CardOS 5.3
- object_copy [20]_
- rsa_privkey_export [21]_
- rsa_generate_private_key [22]_
- rsa_sign_verify [23]_
- ecdh_privkey_export [2]_
- ecdh_pubkey_import [6]_
- ecdh_pubkey_export [6]_
- ecdh_generate_private_key [30]_
- ecdh_generate_keypair [31]_
- ecdh_derive [30]_
- ecdsa_privkey_export [2]_
- ecdsa_pubkey_import [6]_
- ecdsa_pubkey_export [6]_
- ecdsa_generate_private_key [31]_
- ecdsa_generate_keypair [31]_
- ecdsa_sign_verify [34]_
- rng_add_entropy [5]_
.. [53] Failing operations for CardOS 5.3 (middelware 5.5.1)
- ecdh_privkey_export [2]_
- ecdh_generate_private_key [35]_
- ecdsa_privkey_export [2]_
- ecdsa_generate_private_key [36]_
- c_copy_object [4]_
- object_copy [4]_
- rng_add_entropy [5]_
- rsa_sign_verify [3]_
- rsa_privkey_export [2]_
- rsa_generate_private_key [9]_
.. [54] Failing operations for Gemalto IDPrime MD 3840
- session_login_logout [2]_
- session_info [2]_
- set_pin [2]_
- initialize [2]_
- change_so_pin [2]_
- object_copy [20]_
- rsa_generate_private_key [7]_
- rsa_encrypt_decrypt [8]_
- rsa_sign_verify [2]_
- rng_add_entropy [5]_
Error descriptions
.. [2] CKR_ARGUMENTS_BAD (0x7=7)
.. [3] CKR_MECHANISM_INVALID (0x70=112)
.. [4] CKR_FUNCTION_NOT_SUPPORTED (0x54=84)
.. [5] CKR_RANDOM_SEED_NOT_SUPPORTED (0x120=288)
.. [6] CKM_X9_42_DH_KEY_PAIR_GEN | CKR_DEVICE_ERROR (0x30=48)
.. [7] CKR_TEMPLATE_INCONSISTENT (0xD1=209)
.. [8] CKR_ENCRYPTED_DATA_INVALID | CKM_SHA256_RSA_PKCS (0x40=64)
.. [9] CKR_TEMPLATE_INCOMPLETE (0xD0=208)
.. [20] Test fails due to unsupported copy function (CKR_FUNCTION_NOT_SUPPORTED)
.. [21] Generating private key for extraction with property extractable fails (CKR_ARGUMENTS_BAD)
.. [22] Generate rsa private key operation fails (CKR_TEMPLATE_INCOMPLETE)
.. [23] Raw RSA sign-verify fails (CKR_MECHANISM_INVALID)
.. [30] Invalid argument Decoding error: BER: Value truncated
.. [31] Invalid argument Decoding error: BER: Length field is to large
.. [32] Invalid argument OS2ECP: Unknown format type 155
.. [33] Invalid argument OS2ECP: Unknown format type 92
.. [34] Invalid argument OS2ECP: Unknown format type 57
.. [35] Invalid argument OS2ECP: Unknown format type 82
.. [36] Invalid argument OS2ECP: Unknown format type 102

View File

@ -1,110 +0,0 @@
PSK Database
======================
.. versionadded:: 2.4.0
Many applications need to store pre-shared keys (hereafter PSKs) for
authentication purposes.
An abstract interface to PSK stores, along with some implementations
of same, are provided in ``psk_db.h``
.. cpp:class:: PSK_Database
.. cpp:function:: bool is_encrypted() const
Returns true if (at least) the PSKs themselves are encrypted. Returns
false if PSKs are stored in plaintext.
.. cpp:function:: std::set<std::string> list_names() const
Return the set of valid names stored in the database, ie values for which
``get`` will return a value.
.. cpp:function:: void set(const std::string& name, const uint8_t psk[], size_t psk_len)
Save a PSK. If ``name`` already exists, the current value will be
overwritten.
.. cpp:function:: secure_vector<uint8_t> get(const std::string& name) const
Return a value saved with ``set``. Throws an exception if ``name`` doesn't
exist.
.. cpp:function:: void remove(const std::string& name)
Remove ``name`` from the database. If ``name`` doesn't exist, ignores the request.
.. cpp::function:: std::string get_str(const std::string& name) const
Like ``get`` but casts the return value to a string.
.. cpp:function:: void set_str(const std::string& name, const std::string& psk)
Like ``set`` but accepts the psk as a string (eg for a password).
.. cpp:function:: template<typename Alloc> void set_vec(const std::string& name, \
const std::vector<uint8_t, Alloc>& psk)
Like ``set`` but accepting a vector.
The same header also provides a specific instantiation of ``PSK_Database`` which
encrypts both names and PSKs. It must be subclassed to provide the storage.
.. cpp:class:: Encrypted_PSK_Database : public PSK_Database
.. cpp:function:: Encrypted_PSK_Database(const secure_vector<uint8_t>& master_key)
Initializes or opens a PSK database. The master key is used the secure the
contents. It may be of any length. If encrypting PSKs under a passphrase,
use a suitable key derivation scheme (such as PBKDF2) to derive the secret
key. If the master key is lost, all PSKs stored are unrecoverable.
Both names and values are encrypted using NIST key wrapping (see NIST
SP800-38F) with AES-256. First the master key is used with HMAC(SHA-256)
to derive two 256-bit keys, one for encrypting all names and the other to
key an instance of HMAC(SHA-256). Values are each encrypted under an
individual key created by hashing the encrypted name with HMAC. This
associates the encrypted key with the name, and prevents an attacker with
write access to the data store from taking an encrypted key associated
with one entity and copying it to another entity.
Names and PSKs are both padded to the next multiple of 8 bytes, providing
some obfuscation of the length.
One artifact of the names being encrypted is that is is possible to use
multiple different master keys with the same underlying storage. Each
master key will be responsible for a subset of the keys. An attacker who
knows one of the keys will be able to tell there are other values
encrypted under another key, but will not be able to tell how many other
master keys are in use.
.. cpp:function:: virtual void kv_set(const std::string& index, const std::string& value) = 0
Save an encrypted value. Both ``index`` and ``value`` will be non-empty
base64 encoded strings.
.. cpp:function:: virtual std::string kv_get(const std::string& index) const = 0
Return a value saved with ``kv_set``, or return the empty string.
.. cpp:function:: virtual void kv_del(const std::string& index) = 0
Remove a value saved with ``kv_set``.
.. cpp:function:: virtual std::set<std::string> kv_get_all() const = 0
Return all active names (ie values for which ``kv_get`` will return a
non-empty string).
A subclass of ``Encrypted_PSK_Database`` which stores data in a SQL database
is also available.
.. cpp:class:: Encrypted_PSK_Database_SQL : public Encrypted_PSK_Database
.. cpp:function:: Encrypted_PSK_Database_SQL(const secure_vector<uint8_t>& master_key, \
std::shared_ptr<SQL_Database> db, \
const std::string& table_name)
Creates or uses the named table in ``db``. The SQL schema of the table is
``(psk_name TEXT PRIMARY KEY, psk_value TEXT)``.

File diff suppressed because it is too large Load Diff

View File

@ -1,667 +0,0 @@
Python Binding
========================================
.. versionadded:: 1.11.14
.. highlight:: python
.. py:module:: botan3
The Python binding is based on the `ffi` module of botan and the
`ctypes` module of the Python standard library.
The versioning of the Python module follows the major versioning of
the C++ library. So for Botan 2, the module is named ``botan2`` while
for Botan 3 it is ``botan3``.
Versioning
----------------------------------------
.. py:function:: version_major()
Returns the major number of the library version.
.. py:function:: version_minor()
Returns the minor number of the library version.
.. py:function:: version_patch()
Returns the patch number of the library version.
.. py:function:: version_string()
Returns a free form version string for the library
Random Number Generators
----------------------------------------
.. py:class:: RandomNumberGenerator(rng_type = 'system')
Previously ``rng``
Type 'user' also allowed (userspace HMAC_DRBG seeded from system
rng). The system RNG is very cheap to create, as just a single file
handle or CSP handle is kept open, from first use until shutdown,
no matter how many 'system' rng instances are created. Thus it is
easy to use the RNG in a one-off way, with `botan.RandomNumberGenerator().get(32)`.
.. py:method:: get(length)
Return some bytes
.. py:method:: reseed(bits = 256)
Meaningless on system RNG, on userspace RNG causes a reseed/rekey
.. py:method:: reseed_from_rng(source_rng, bits = 256)
Take bits from the source RNG and use it to seed ``self``
.. py:method:: add_entropy(seed)
Add some unpredictable seed data to the RNG
Hash Functions
----------------------------------------
.. py:class:: HashFunction(algo)
Previously ``hash_function``
The ``algo`` param is a string (eg 'SHA-1', 'SHA-384', 'BLAKE2b')
.. py:method:: algo_name()
Returns the name of this algorithm
.. py:method:: clear()
Clear state
.. py:method:: output_length()
Return output length in bytes
.. py:method:: update(x)
Add some input
.. py:method:: final()
Returns the hash of all input provided, resets
for another message.
Message Authentication Codes
----------------------------------------
.. py:class:: MsgAuthCode(algo)
Previously ``message_authentication_code``
Algo is a string (eg 'HMAC(SHA-256)', 'Poly1305', 'CMAC(AES-256)')
.. py:method:: algo_name()
Returns the name of this algorithm
.. py:method:: clear()
Clear internal state including the key
.. py:method:: output_length()
Return the output length in bytes
.. py:method:: set_key(key)
Set the key
.. py:method:: update(x)
Add some input
.. py:method:: final()
Returns the MAC of all input provided, resets
for another message with the same key.
Ciphers
----------------------------------------
.. py:class:: SymmetricCipher(object, algo, encrypt = True)
Previously ``cipher``
The algorithm is spcified as a string (eg 'AES-128/GCM',
'Serpent/OCB(12)', 'Threefish-512/EAX').
Set the second param to False for decryption
.. py:method:: algo_name()
Returns the name of this algorithm
.. py:method:: tag_length()
Returns the tag length (0 for unauthenticated modes)
.. py:method:: default_nonce_length()
Returns default nonce length
.. py:method:: update_granularity()
Returns update block size. Call to update() must provide input
of exactly this many bytes
.. py:method:: is_authenticated()
Returns True if this is an AEAD mode
.. py:method:: valid_nonce_length(nonce_len)
Returns True if nonce_len is a valid nonce len for this mode
.. py:method:: clear()
Resets all state
.. py:method:: set_key(key)
Set the key
.. py:method:: set_assoc_data(ad)
Sets the associated data. Fails if this is not an AEAD mode
.. py:method:: start(nonce)
Start processing a message using nonce
.. py:method:: update(txt)
Consumes input text and returns output. Input text must be of
update_granularity() length. Alternately, always call finish
with the entire message, avoiding calls to update entirely
.. py:method:: finish(txt = None)
Finish processing (with an optional final input). May throw if
message authentication checks fail, in which case all plaintext
previously processed must be discarded. You may call finish()
with the entire message
Bcrypt
----------------------------------------
.. py:function:: bcrypt(passwd, rng, work_factor = 10)
Provided the password and an RNG object, returns a bcrypt string
.. py:function:: check_bcrypt(passwd, bcrypt)
Check a bcrypt hash against the provided password, returning True
iff the password matches.
PBKDF
----------------------------------------
.. py:function:: pbkdf(algo, password, out_len, iterations = 100000, salt = None)
Runs a PBKDF2 algo specified as a string (eg 'PBKDF2(SHA-256)',
'PBKDF2(CMAC(Blowfish))'). Runs with specified iterations, with
meaning depending on the algorithm. The salt can be provided or
otherwise is randomly chosen. In any case it is returned from the
call.
Returns out_len bytes of output (or potentially less depending on
the algorithm and the size of the request).
Returns tuple of salt, iterations, and psk
.. py:function:: pbkdf_timed(algo, password, out_len, ms_to_run = 300, salt = rng().get(12))
Runs for as many iterations as needed to consumed ms_to_run
milliseconds on whatever we're running on. Returns tuple of salt,
iterations, and psk
Scrypt
---------------
.. versionadded:: 2.8.0
.. py:function:: scrypt(out_len, password, salt, N=1024, r=8, p=8)
Runs Scrypt key derivation function over the specified password
and salt using Scrypt parameters N, r, p.
KDF
----------------------------------------
.. py:function:: kdf(algo, secret, out_len, salt)
Performs a key derviation function (such as "HKDF(SHA-384)") over
the provided secret and salt values. Returns a value of the
specified length.
Public Key
----------------------------------------
.. py:class:: PublicKey(object)
Previously ``public_key``
.. py:classmethod:: load(val)
Load a public key. The value should be a PEM or DER blob.
.. py:classmethod:: load_rsa(n, e)
Load an RSA public key giving the modulus and public exponent
as integers.
.. py:classmethod:: load_dsa(p, q, g, y)
Load an DSA public key giving the parameters and public value
as integers.
.. py:classmethod:: load_dh(p, g, y)
Load an Diffie-Hellman public key giving the parameters and
public value as integers.
.. py:classmethod:: load_elgamal(p, q, g, y)
Load an ElGamal public key giving the parameters and
public value as integers.
.. py:classmethod:: load_ecdsa(curve, pub_x, pub_y)
Load an ECDSA public key giving the curve as a string
(like "secp256r1") and the public point as a pair of
integers giving the affine coordinates.
.. py:classmethod:: load_ecdh(curve, pub_x, pub_y)
Load an ECDH public key giving the curve as a string
(like "secp256r1") and the public point as a pair of
integers giving the affine coordinates.
.. py:classmethod:: load_sm2(curve, pub_x, pub_y)
Load a SM2 public key giving the curve as a string (like
"sm2p256v1") and the public point as a pair of integers giving
the affine coordinates.
.. py:method:: check_key(rng_obj, strong=True):
Test the key for consistency. If ``strong`` is ``True`` then
more expensive tests are performed.
.. py:method:: export(pem=False)
Exports the public key using the usual X.509 SPKI representation.
If ``pem`` is True, the result is a PEM encoded string. Otherwise
it is a binary DER value.
.. py:method:: to_der()
Like ``self.export(False)``
.. py:method:: to_pem()
Like ``self.export(True)``
.. py:method:: get_field(field_name)
Return an integer field related to the public key. The valid field names
vary depending on the algorithm. For example RSA public modulus can be
extracted with ``rsa_key.get_field("n")``.
.. py:method:: fingerprint(hash = 'SHA-256')
Returns a hash of the public key
.. py:method:: algo_name()
Returns the algorithm name
.. py:method:: estimated_strength()
Returns the estimated strength of this key against known attacks
(NFS, Pollard's rho, etc)
Private Key
----------------------------------------
.. py:class:: PrivateKey
Previously ``private_key``
.. py:classmethod:: create(algo, param, rng)
Creates a new private key. The parameter type/value depends on
the algorithm. For "rsa" is is the size of the key in bits.
For "ecdsa" and "ecdh" it is a group name (for instance
"secp256r1"). For "ecdh" there is also a special case for group
"curve25519" (which is actually a completely distinct key type
with a non-standard encoding).
.. py:classmethod:: load(val, passphrase="")
Return a private key (DER or PEM formats accepted)
.. py:classmethod:: load_rsa(p, q, e)
Return a private RSA key
.. py:classmethod:: load_dsa(p, q, g, x)
Return a private DSA key
.. py:classmethod:: load_dh(p, g, x)
Return a private DH key
.. py:classmethod:: load_elgamal(p, q, g, x)
Return a private ElGamal key
.. py:classmethod:: load_ecdsa(curve, x)
Return a private ECDSA key
.. py:classmethod:: load_ecdh(curve, x)
Return a private ECDH key
.. py:classmethod:: load_sm2(curve, x)
Return a private SM2 key
.. py:method:: get_public_key()
Return a public_key object
.. py:method:: to_pem()
Return the PEM encoded private key (unencrypted). Like ``self.export(True)``
.. py:method:: to_der()
Return the PEM encoded private key (unencrypted). Like ``self.export(False)``
.. py:method:: check_key(rng_obj, strong=True):
Test the key for consistency. If ``strong`` is ``True`` then
more expensive tests are performed.
.. py:method:: algo_name()
Returns the algorithm name
.. py:method:: export(pem=False)
Exports the private key in PKCS8 format. If ``pem`` is True, the
result is a PEM encoded string. Otherwise it is a binary DER
value. The key will not be encrypted.
.. py:method:: export_encrypted(passphrase, rng, pem=False, msec=300, cipher=None, pbkdf=None)
Exports the private key in PKCS8 format, encrypted using the
provided passphrase. If ``pem`` is True, the result is a PEM
encoded string. Otherwise it is a binary DER value.
.. py:method:: get_field(field_name)
Return an integer field related to the public key. The valid field names
vary depending on the algorithm. For example first RSA secret prime can be
extracted with ``rsa_key.get_field("p")``. This function can also be
used to extract the public parameters.
Public Key Operations
----------------------------------------
.. py:class:: PKEncrypt(pubkey, padding)
Previously ``pk_op_encrypt``
.. py:method:: encrypt(msg, rng)
.. py:class:: PKDecrypt(privkey, padding)
Previously ``pk_op_decrypt``
.. py:method:: decrypt(msg)
.. py:class:: PKSign(privkey, hash_w_padding)
Previously ``pk_op_sign``
.. py:method:: update(msg)
.. py:method:: finish(rng)
.. py:class:: PKVerify(pubkey, hash_w_padding)
Previously ``pk_op_verify``
.. py:method:: update(msg)
.. py:method:: check_signature(signature)
.. py:class:: PKKeyAgreement(privkey, kdf)
Previously ``pk_op_key_agreement``
.. py:method:: public_value()
Returns the public value to be passed to the other party
.. py:method:: agree(other, key_len, salt)
Returns a key derived by the KDF.
Multiple Precision Integers (MPI)
-------------------------------------
.. versionadded:: 2.8.0
.. py:class:: MPI(initial_value=None, radix=None)
Initialize an MPI object with specified value, left as zero otherwise. The
``initial_value`` should be an ``int``, ``str``, or ``MPI``.
The ``radix`` value should be set to 16 when initializing from a base 16 `str` value.
Most of the usual arithmetic operators (``__add__``, ``__mul__``, etc) are
defined.
.. py:method:: inverse_mod(modulus)
Return the inverse of ``self`` modulo ``modulus``, or zero if no inverse exists
.. py:method:: is_prime(rng, prob=128)
Test if ``self`` is prime
.. py:method:: pow_mod(exponent, modulus):
Return ``self`` to the ``exponent`` power modulo ``modulus``
.. py:method:: mod_mul(other, modulus):
Return the multiplication product of ``self`` and ``other`` modulo ``modulus``
.. py:method:: gcd(other):
Return the greatest common divisor of ``self`` and ``other``
Format Preserving Encryption (FE1 scheme)
-----------------------------------------
.. versionadded:: 2.8.0
.. py:class:: FormatPreservingEncryptionFE1(modulus, key, rounds=5, compat_mode=False)
Initialize an instance for format preserving encryption
.. py:method:: encrypt(msg, tweak)
The msg should be a botan3.MPI or an object which can be converted to one
.. py:method:: decrypt(msg, tweak)
The msg should be a botan3.MPI or an object which can be converted to one
HOTP
-----------------------------------------
.. versionadded:: 2.8.0
.. py:class:: HOTP(key, hash="SHA-1", digits=6)
.. py:method:: generate(counter)
Generate an HOTP code for the provided counter
.. py:method:: check(code, counter, resync_range=0)
Check if provided ``code`` is the correct code for ``counter``.
If ``resync_range`` is greater than zero, HOTP also checks
up to ``resync_range`` following counter values.
Returns a tuple of (bool,int) where the boolean indicates if the
code was valid, and the int indicates the next counter value
that should be used. If the code did not verify, the next
counter value is always identical to the counter that was passed
in. If the code did verify and resync_range was zero, then the
next counter will always be counter+1.
X509Cert
-----------------------------------------
.. py:class:: X509Cert(filename=None, buf=None)
.. py:method:: time_starts()
Return the time the certificate becomes valid, as a string in form
"YYYYMMDDHHMMSSZ" where Z is a literal character reflecting that this time is
relative to UTC.
.. py:method:: time_expires()
Return the time the certificate expires, as a string in form
"YYYYMMDDHHMMSSZ" where Z is a literal character reflecting that this time is
relative to UTC.
.. py:method:: to_string()
Format the certificate as a free-form string.
.. py:method:: fingerprint(hash_algo='SHA-256')
Return a fingerprint for the certificate, which is basically just a hash
of the binary contents. Normally SHA-1 or SHA-256 is used, but any hash
function is allowed.
.. py:method:: serial_number()
Return the serial number of the certificate.
.. py:method:: authority_key_id()
Return the authority key ID set in the certificate, which may be empty.
.. py:method:: subject_key_id()
Return the subject key ID set in the certificate, which may be empty.
.. py:method:: subject_public_key_bits()
Get the serialized representation of the public key included in this certificate.
.. py:method:: subject_public_key()
Get the public key included in this certificate as an object of class ``PublicKey``.
.. py:method:: subject_dn(key, index)
Get a value from the subject DN field.
``key`` specifies a value to get, for instance ``"Name"`` or `"Country"`.
.. py:method:: issuer_dn(key, index)
Get a value from the issuer DN field.
``key`` specifies a value to get, for instance ``"Name"`` or `"Country"`.
.. py:method:: hostname_match(hostname)
Return True if the Common Name (CN) field of the certificate matches a given ``hostname``.
.. py:method:: not_before()
Return the time the certificate becomes valid, as seconds since epoch.
.. py:method:: not_after()
Return the time the certificate expires, as seconds since epoch.
.. py:method:: allowed_usage(usage_list)
Return True if the certificates Key Usage extension contains all constraints given in ``usage_list``.
Also return True if the certificate doesn't have this extension.
Example usage constraints are: ``"DIGITAL_SIGNATURE"``, ``"KEY_CERT_SIGN"``, ``"CRL_SIGN"``.
.. py:method:: verify(intermediates=None, \
trusted=None, \
trusted_path=None, \
required_strength=0, \
hostname=None, \
reference_time=0 \
crls=None)
Verify a certificate. Returns 0 if validation was successful, returns a positive error code
if the validation was unsuccesful.
``intermediates`` is a list of untrusted subauthorities.
``trusted`` is a list of trusted root CAs.
The `trusted_path` refers to a directory where one or more trusted CA
certificates are stored.
Set ``required_strength`` to indicate the minimum key and hash strength
that is allowed. For instance setting to 80 allows 1024-bit RSA and SHA-1.
Setting to 110 requires 2048-bit RSA and SHA-256 or higher. Set to zero
to accept a default.
If ``hostname`` is given, it will be checked against the certificates CN field.
Set ``reference_time`` to be the time which the certificate chain is
validated against. Use zero (default) to use the current system clock.
``crls`` is a list of CRLs issued by either trusted or untrusted authorities.
.. py:classmethod:: validation_status(error_code)
Return an informative string associated with the verification return code.
.. py:method:: is_revoked(self, crl)
Check if the certificate (``self``) is revoked on the given ``crl``.
X509CRL
-----------------------------------------
.. py:class:: X509CRL(filename=None, buf=None)
Class representing an X.509 Certificate Revocation List.
A CRL in PEM or DER format can be loaded from a file, with the ``filename`` argument,
or from a bytestring, with the ``buf`` argument.

View File

@ -1,289 +0,0 @@
.. _random_number_generators:
Random Number Generators
========================================
.. cpp:class:: RandomNumberGenerator
The base class for all RNG objects, is declared in ``rng.h``.
.. cpp:function:: void randomize(uint8_t* output_array, size_t length)
Places *length* random bytes into the provided buffer.
.. cpp:function:: void randomize_with_input(uint8_t* data, size_t length, \
const uint8_t* extra_input, size_t extra_input_len)
Like randomize, but first incorporates the additional input field into the
state of the RNG. The additional input could be anything which
parameterizes this request. Not all RNG types accept additional inputs,
the value will be silently ignored when not supported.
.. cpp:function:: void randomize_with_ts_input(uint8_t* data, size_t length)
Creates a buffer with some timestamp values and calls ``randomize_with_input``
.. note::
When RDRAND is enabled and available at runtime, instead of timestamps
the output of RDRAND is used as the additional data.
.. cpp:function:: uint8_t next_byte()
Generates a single random byte and returns it. Note that calling this
function several times is much slower than calling ``randomize`` once to
produce multiple bytes at a time.
.. cpp:function:: void add_entropy(const uint8_t* data, size_t length)
Incorporates provided data into the state of the PRNG, if at all possible.
This works for most RNG types, including the system and TPM RNGs. But if
the RNG doesn't support this operation, the data is dropped, no error is
indicated.
.. cpp:function:: bool accepts_input() const
This function returns ``false`` if it is known that this RNG object cannot
accept external inputs. In this case, any calls to
:cpp:func:`RandomNumberGenerator::add_entropy` will be ignored.
.. cpp:function:: void reseed_from_rng(RandomNumberGenerator& rng, \
size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS)
Reseed by calling ``rng`` to acquire ``poll_bits`` data.
RNG Types
----------------------------------------
Several different RNG types are implemented. Some access hardware RNGs, which
are only available on certain platforms. Others are mostly useful in specific
situations.
Generally prefer using ``System_RNG``, or if not available use ``AutoSeeded_RNG``
which is intended to provide best possible behavior in a userspace PRNG.
System_RNG
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
On systems which support it, in ``system_rng.h`` you can access a shared
reference to a process global instance of the system PRNG (using interfaces such
as ``/dev/urandom``, ``getrandom``, ``arc4random``, ``BCryptGenRandom``,
or ``RtlGenRandom``):
.. cpp:function:: RandomNumberGenerator& system_rng()
Returns a reference to the system RNG
There is also a wrapper class ``System_RNG`` which simply invokes on
the return value of ``system_rng()``. This is useful in situations where
you may sometimes want to use the system RNG and a userspace RNG in others,
for example::
std::unique_ptr<Botan::RandomNumberGenerator> rng;
#if defined(BOTAN_HAS_SYSTEM_RNG)
rng.reset(new System_RNG);
#else
rng.reset(new AutoSeeded_RNG);
#endif
Unlike nearly any other object in Botan it is acceptable to share a single
instance of ``System_RNG`` between threads without locking, because the underlying
RNG is itself thread safe due to being serialized by a mutex in the kernel itself.
AutoSeeded_RNG
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AutoSeeded_RNG is type naming a 'best available' userspace PRNG. The
exact definition of this has changed over time and may change again in the
future. Fortunately there is no compatibility concerns when changing
any RNG since the only expectation is it produces bits
indistinguishable from random.
.. note:: Starting in 2.16.0, AutoSeeded_RNG uses an internal lock and so is
safe to share among threads. However if possible it is still better to
use a RNG per thread as otherwise the RNG object needlessly creates a
point of contention. In previous versions, the RNG does not have an
internal lock and all access to it must be serialized.
The current version uses HMAC_DRBG with either SHA-384 or SHA-256. The
initial seed is generated either by the system PRNG (if available) or
a default set of entropy sources. These are also used for periodic
reseeding of the RNG state.
HMAC_DRBG
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
HMAC-DRBG is a random number generator designed by NIST and specified
in SP 800-90A. It seems to be the most conservative generator of the
NIST approved options.
It can be instantiated with any HMAC but is typically used with
SHA-256, SHA-384, or SHA-512, as these are the hash functions approved
for this use by NIST.
.. note::
There is no reason to use this class directly unless your application
requires HMAC-DRBG with specific parameters or options. Usually this
would be for some standards conformance reason. If you just want a
userspace RNG, use ``AutoSeeded_RNG``.
``HMAC_DRBG``'s constructors are:
.. cpp:class:: HMAC_DRBG
.. cpp:function:: HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf, \
RandomNumberGenerator& underlying_rng, \
size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL, \
size_t max_number_of_bytes_per_request = 64 * 1024)
Creates a DRBG which will automatically reseed as required by making
calls to ``underlying_rng`` either after being invoked
``reseed_interval`` times, or if use of ``fork`` system call is
detected.
You can disable automatic reseeding by setting ``reseed_interval`` to
zero, in which case ``underlying_rng`` will only be invoked in the case
of ``fork``.
The specification of HMAC DRBG requires that each invocation produce no
more than 64 kibibytes of data. However, the RNG interface allows
producing arbitrary amounts of data in a single request. To accommodate
this, ``HMAC_DRBG`` treats requests for more data as if they were
multiple requests each of (at most) the maximum size. You can specify a
smaller maximum size with ``max_number_of_bytes_per_request``. There is
normally no reason to do this.
.. cpp:function:: HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf, \
Entropy_Sources& entropy_sources, \
size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL, \
size_t max_number_of_bytes_per_request = 64 * 1024)
Like above function, but instead of an RNG taking a set of entropy
sources to seed from as required.
.. cpp:function:: HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf, \
RandomNumberGenerator& underlying_rng, \
Entropy_Sources& entropy_sources, \
size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL, \
size_t max_number_of_bytes_per_request = 64 * 1024)
Like above function, but taking both an RNG and a set of entropy
sources to seed from as required.
.. cpp:function:: HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf)
Creates an unseeded DRBG. You must explicitly provide seed data later
on in order to use this RNG. This is primarily useful for deterministic
key generation.
Since no source of data is available to automatically reseed, automatic
reseeding is disabled when this constructor is used. If the RNG object
detects that ``fork`` system call was used without it being
subsequently reseeded, it will throw an exception.
.. cpp:function:: HMAC_DRBG(const std::string& hmac_hash)
Like the constructor just taking a PRF, except instead of a PRF object,
a string specifying what hash to use with HMAC is provided.
ChaCha_RNG
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is a very fast userspace PRNG based on ChaCha20 and HMAC(SHA-256). The key
for ChaCha is derived by hashing entropy inputs with HMAC. Then the ChaCha
keystream generator is run, first to generate the new HMAC key (used for any
future entropy additions), then the desired RNG outputs.
This RNG composes two primitives thought to be secure (ChaCha and HMAC) in a
simple and well studied way (the extract-then-expand paradigm), but is still an
ad-hoc and non-standard construction. It is included because it is roughly 20x
faster then HMAC_DRBG (basically running as fast as ChaCha can generate
keystream bits), and certain applications need access to a very fast RNG.
One thing applications using ``ChaCha_RNG`` need to be aware of is that for
performance reasons, no backtracking resistance is implemented in the RNG
design. An attacker who recovers the ``ChaCha_RNG`` state can recover the output
backwards in time to the last rekey and forwards to the next rekey.
An explicit reseeding (:cpp:func:`RandomNumberGenerator::add_entropy`) or
providing any input to the RNG
(:cpp:func:`RandomNumberGenerator::randomize_with_ts_input`,
:cpp:func:`RandomNumberGenerator::randomize_with_input`) is sufficient to cause
a reseeding. Or, if a RNG or entropy source was provided to the ``ChaCha_RNG``
constructor, then reseeding will be performed automatically after a certain
interval of requests.
Processor_RNG
^^^^^^^^^^^^^^^^^
This RNG type directly invokes a CPU instruction capable of generating
a cryptographically secure random number. On x86 it uses ``rdrand``,
on POWER ``darn``. If the relevant instruction is not available, the
constructor of the class will throw at runtime. You can test
beforehand by checking the result of ``Processor_RNG::available()``.
TPM_RNG
^^^^^^^^^^^^^^^^^
This RNG type allows using the RNG exported from a TPM chip.
PKCS11_RNG
^^^^^^^^^^^^^^^^^
This RNG type allows using the RNG exported from a hardware token accessed via PKCS11.
Entropy Sources
---------------------------------
An ``EntropySource`` is an abstract representation of some method of
gather "real" entropy. This tends to be very system dependent. The
*only* way you should use an ``EntropySource`` is to pass it to a PRNG
that will extract entropy from it -- never use the output directly for
any kind of key or nonce generation!
``EntropySource`` has a pair of functions for getting entropy from
some external source, called ``fast_poll`` and ``slow_poll``. These
pass a buffer of bytes to be written; the functions then return how
many bytes of entropy were gathered.
Note for writers of ``EntropySource`` subclasses: it isn't necessary
to use any kind of cryptographic hash on your output. The data
produced by an EntropySource is only used by an application after it
has been hashed by the ``RandomNumberGenerator`` that asked for the
entropy, thus any hashing you do will be wasteful of both CPU cycles
and entropy.
The following entropy sources are currently used:
* The system RNG (``/dev/urandom``, ``getrandom``, ``arc4random``,
``BCryptGenRandom``, or ``RtlGenRandom``).
* Processor provided RNG outputs (RDRAND, RDSEED, DARN) are used if available,
but not counted as contributing entropy
* The ``getentropy`` call is used on OpenBSD, FreeBSD, and macOS
* ``/proc`` walk: read files in ``/proc``. Last ditch protection against
flawed system RNG.
* Win32 stats: takes snapshot of current system processes. Last ditch
protection against flawed system RNG.
Fork Safety
---------------------------------
On Unix platforms, the ``fork()`` and ``clone()`` system calls can
be used to spawn a new child process. Fork safety ensures that the
child process doesn't see the same output of random bytes as the
parent process. Botan tries to ensure fork safety by feeding the
process ID into the internal state of the random generator and by
automatically reseeding the random generator if the process ID
changed between two requests of random bytes. However, this does
not protect against PID wrap around. The process ID is usually
implemented as a 16 bit integer. In this scenario, a process will
spawn a new child process, which exits the parent process and
spawns a new child process himself. If the PID wrapped around, the
second child process may get assigned the process ID of it's
grandparent and the fork safety can not be ensured.
Therefore, it is strongly recommended to explicitly reseed any
userspace random generators after forking a new process. If this is
not possible in your application, prefer using the system PRNG
instead.

View File

@ -1,6 +0,0 @@
Roughtime
===========
.. versionadded:: 2.13.0
Botan includes a Roughtime client, available in ``botan/roughtime.h``

View File

@ -1,31 +0,0 @@
Memory container
========================================
A major concern with mixing modern multi-user OSes and cryptographic
code is that at any time the code (including secret keys) could be
swapped to disk, where it can later be read by an attacker, or left
floating around in memory for later retrieval.
For this reason the library uses a ``std::vector`` with a custom
allocator that will zero memory before deallocation, named via typedef
as ``secure_vector``. Because it is simply a STL vector with a custom
allocator, it has an identical API to the ``std::vector`` you know and
love.
Some operating systems offer the ability to lock memory into RAM,
preventing swapping from occurring. Typically this operation is
restricted to privileged users (root or admin), however some OSes
including Linux and FreeBSD allow normal users to lock a small amount
of memory. On these systems, allocations first attempt to allocate out
of this small locked pool, and then if that fails will fall back to
normal heap allocations.
The ``secure_vector`` template is only meant for primitive data types
(bytes or ints): if you want a container of higher level Botan
objects, you can just use a ``std::vector``, since these objects know
how to clear themselves when they are destroyed. You cannot, however,
have a ``std::vector`` (or any other container) of ``Pipe`` objects or
filters, because these types have pointers to other filters, and
implementing copy constructors for these types would be both hard and
quite expensive (vectors of pointers to such objects is fine, though).

View File

@ -1,77 +0,0 @@
Secure Remote Password
========================================
The library contains an implementation of the
`SRP6-a <http://srp.stanford.edu/design.html>`_ password authenticated
key exchange protocol in ``srp6.h``.
A SRP client provides what is called a SRP *verifier* to the server.
This verifier is based on a password, but the password cannot be
easily derived from the verifier (however brute force attacks are
possible). Later, the client and server can perform an SRP exchange,
which results in a shared secret key. This key can be used for mutual
authentication and/or encryption.
SRP works in a discrete logarithm group. Special parameter sets for
SRP6 are defined, denoted in the library as "modp/srp/<size>", for
example "modp/srp/2048".
.. warning::
While knowledge of the verifier does not easily allow an attacker
to get the raw password, they could still use the verifier to
impersonate the server to the client, so verifiers should be
protected as carefully as a plaintext password would be.
.. cpp:function:: BigInt generate_srp6_verifier( \
const std::string& username, \
const std::string& password, \
const std::vector<uint8_t>& salt, \
const std::string& group_id, \
const std::string& hash_id)
Generates a new verifier using the specified password and salt.
This is stored by the server. The salt must also be stored. Later,
the given username and password are used to by the client during
the key agreement step.
.. cpp:function:: std::string srp6_group_identifier( \
const BigInt& N, const BigInt& g)
.. cpp:class:: SRP6_Server_Session
.. cpp:function:: BigInt step1(const BigInt& v, \
const std::string& group_id, \
const std::string& hash_id, \
RandomNumberGenerator& rng)
Takes a verifier (generated by generate_srp6_verifier) along
with the group_id, and output a value `B` which is provided to
the client.
.. cpp:function:: SymmetricKey step2(const BigInt& A)
Takes the parameter A generated by srp6_client_agree,
and return the shared secret key.
In the event of an impersonation attack (or wrong username/password, etc)
no error occurs, but the key returned will be different on the two sides.
The two sides must verify each other, for example by using the shared
secret to key an HMAC and then exchanging authenticated messages.
.. cpp:function:: std::pair<BigInt,SymmetricKey> srp6_client_agree( \
const std::string& username, \
const std::string& password, \
const std::string& group_id, \
const std::string& hash_id, \
const std::vector<uint8_t>& salt, \
const BigInt& B, \
RandomNumberGenerator& rng)
The client receives these parameters from the server, except for
the username and password which are provided by the user. The
parameter B is the output of `step1`.
The client agreement step outputs a shared symmetric key along
with the parameter A which is returned to the server (and allows
it the compute the shared key).

View File

@ -1,194 +0,0 @@
Stream Ciphers
========================
In contrast to block ciphers, stream ciphers operate on a plaintext stream
instead of blocks. Thus encrypting data results in changing the internal state
of the cipher and encryption of plaintext with arbitrary length is possible in
one go (in byte amounts). All implemented stream ciphers derive from the base
class :cpp:class:`StreamCipher` (`botan/stream_cipher.h`).
.. warning::
Using a stream cipher without an authentication code is extremely insecure,
because an attacker can trivially modify messages. Prefer using an
authenticated cipher mode such as GCM or SIV.
.. warning::
Encrypting more than one message with the same key requires careful management
of initialization vectors. Otherwise the keystream will be reused, which causes
the security of the cipher to completely fail.
.. cpp:class:: StreamCipher
.. cpp:function:: std::string name() const
Returns a human-readable string of the name of this algorithm.
.. cpp:function:: void clear()
Clear the key.
.. cpp:function:: std::unique_ptr<StreamCipher> new_object() const
Return a newly allocated object of the same type as this one.
The new object is unkeyed.
.. cpp:function:: void set_key(const uint8_t* key, size_t length)
Set the stream cipher key. If the length is not accepted, an
``Invalid_Key_Length`` exception is thrown.
.. cpp:function:: bool valid_keylength(size_t length) const
This function returns true if and only if *length* is a valid
keylength for the algorithm.
.. cpp:function:: size_t minimum_keylength() const
Return the smallest key length (in bytes) that is acceptable for the
algorithm.
.. cpp:function:: size_t maximum_keylength() const
Return the largest key length (in bytes) that is acceptable for the
algorithm.
.. cpp:function:: bool valid_iv_length(size_t iv_len) const
This function returns true if and only if *length* is a valid IV length for
the stream cipher. Some ciphers do not support IVs at all, and will return
false for any value except zero.
.. cpp:function:: size_t default_iv_length() const
Returns some default IV size, normally the largest IV supported by the cipher.
If this function returns zero, then IVs are not supported and any call to
``set_iv`` with a non-empty value will fail.
.. cpp:function:: void set_iv(const uint8_t*, size_t len)
Load IV into the stream cipher state. This should happen after the key is
set and before any operation (encrypt/decrypt/seek) is called.
If the cipher does not support IVs, then a call with ``len`` equal to zero
will be accepted and any other length will cause a ``Invalid_IV_Length``
exception.
.. cpp:function:: void seek(uint64_t offset)
Sets the state of the stream cipher and keystream according to the passed
*offset*, exactly as if *offset* bytes had first been encrypted. The key
and (if required) the IV have to be set before this can be called. Not all
ciphers support seeking; such objects will throw ``Not_Implemented`` in
this case.
.. cpp:function:: void cipher(const uint8_t* in, uint8_t* out, size_t n)
Processes *n* bytes plain/ciphertext from *in* and writes the result to *out*.
.. cpp:function:: void cipher1(uint8_t* inout, size_t n)
Processes *n* bytes plain/ciphertext in place. Acts like :cpp:func:`cipher`\ (inout, inout, n).
.. cpp:function:: void encipher(std::vector<uint8_t> inout)
.. cpp:function:: void encrypt(std::vector<uint8_t> inout)
.. cpp:function:: void decrypt(std::vector<uint8_t> inout)
Processes plain/ciphertext *inout* in place. Acts like :cpp:func:`cipher`\ (inout.data(), inout.data(), inout.size()).
Code Example
-----------------
The following code encrypts a provided plaintext using ChaCha20.
.. literalinclude:: /../src/examples/chacha.cpp
:language: cpp
Available Stream Ciphers
----------------------------
Botan provides the following stream ciphers. If in doubt, pick ChaCha20 or CTR(AES-256).
CTR-BE
~~~~~~~
Counter mode converts a block cipher into a stream cipher. It offers
parallel execution and can seek within the output stream, both useful
properties.
CTR mode requires a nonce, which can be any length up to the block size of the
underlying cipher. If it is shorter than the block size, sufficient zero bytes
are appended.
It is possible to choose the width of the counter portion, which can improve
performance somewhat, but limits the maximum number of bytes that can safely be
encrypted. Different protocols have different conventions for the width of the
counter portion. This is done by specifying the width (which must be at least 4
bytes, allowing to encrypt 2\ :sup:`32` blocks of data) for example using
"CTR(AES-256,8)" will select a 64-bit (8 byte) counter.
(The ``-BE`` suffix refers to big-endian convention for the counter.
Little-endian counter mode is rarely used and not currently implemented.)
OFB
~~~~~
Another stream cipher based on a block cipher. Unlike CTR mode, it does not
allow parallel execution or seeking within the output stream. Prefer CTR.
Available if ``BOTAN_HAS_OFB`` is defined.
ChaCha
~~~~~~~~
A very fast cipher, now widely deployed in TLS as part of the ChaCha20Poly1305
AEAD. Can be used with 8 (fast but dangerous), 12 (balance), or 20 rounds
(conservative). Even with 20 rounds, ChaCha is very fast. Use 20 rounds.
ChaCha supports an optional IV (which defaults to all zeros). It can be of
length 64, 96 or (since 2.8) 192 bits. Using ChaCha with a 192 bit nonce is also
known as XChaCha.
Available if ``BOTAN_HAS_CHACHA`` is defined.
Salsa20
~~~~~~~~~
An earlier iteration of the ChaCha design, this cipher is popular due to its use
in the libsodium library. Prefer ChaCha.
Salsa supports an optional IV (which defaults to all zeros). It can be of length
64 or 192 bits. Using Salsa with a 192 bit nonce is also known as XSalsa.
Available if ``BOTAN_HAS_SALSA20`` is defined.
SHAKE-128
~~~~~~~~~~~~
This is the SHAKE-128 XOF exposed as a stream cipher. It is slower
than ChaCha and somewhat obscure, and was primarily implemented to
support a particular post-quantum scheme which is no longer supported.
SHAKE does not support IVs, nor seeking within the cipher stream.
Available if ``BOTAN_HAS_SHAKE_CIPHER`` is defined.
.. warning::
SHAKE support (as a stream cipher) is deprecated and will be removed
in a future major release.
RC4
~~~~
An old and very widely deployed stream cipher notable for its simplicity. It
does not support IVs or seeking within the cipher stream. Compared to modern
algorithms like ChaCha20, it is also quite slow.
.. warning::
RC4 is prone to numerous attacks. **Avoid in new code** and use only if
required for compatibility with existing systems.
Available if ``BOTAN_HAS_RC4`` is defined.

File diff suppressed because it is too large Load Diff

View File

@ -1,113 +0,0 @@
Trusted Platform Module (TPM)
==========================================
.. versionadded:: 1.11.26
Some computers come with a TPM, which is a small side processor which can
perform certain operations which include RSA key generation and signing, a
random number generator, accessing a small amount of NVRAM, and a set of PCRs
which can be used to measure software state (this is TPMs most famous use, for
authenticating a boot sequence).
The TPM NVRAM and PCR APIs are not supported by Botan at this time, patches welcome.
Currently only v1.2 TPMs are supported, and the only TPM library supported is
TrouSerS (http://trousers.sourceforge.net/). Hopefully both of these limitations
will be removed in a future release, in order to support newer TPM v2.0 systems.
The current code has been tested with an ST TPM running in a Lenovo laptop.
Test for TPM support with the macro ``BOTAN_HAS_TPM``, include ``<botan/tpm.h>``.
First, create a connection to the TPM with a ``TPM_Context``. The context is
passed to all other TPM operations, and should remain alive as long as any other
TPM object which the context was passed to is still alive, otherwise errors or
even an application crash are possible. In the future, the API may change to
using ``shared_ptr`` to remove this problem.
.. cpp:class:: TPM_Context
.. cpp:function:: TPM_Context(pin_cb cb, const char* srk_password)
The (somewhat improperly named) pin_cb callback type takes a std::string as
an argument, which is an informative message for the user. It should return
a string containing the password entered by the user.
Normally the SRK password is null. Use nullptr to signal this.
The TPM contains a RNG of unknown design or quality. If that doesn't scare you
off, you can use it with ``TPM_RNG`` which implements the standard
``RandomNumberGenerator`` interface.
.. cpp:class:: TPM_RNG
.. cpp:function:: TPM_RNG(TPM_Context& ctx)
Initialize a TPM RNG object. After initialization, reading from
this RNG reads from the hardware? RNG on the TPM.
The v1.2 TPM uses only RSA, but because this key is implemented completely in
hardware it uses a different private key type, with a somewhat different API to
match the TPM's behavior.
.. cpp:class:: TPM_PrivateKey
.. cpp:function:: TPM_PrivateKey(TPM_Context& ctx, size_t bits, const char* key_password)
Create a new RSA key stored on the TPM. The bits should be either 1024
or 2048; the TPM interface hypothetically allows larger keys but in
practice no v1.2 TPM hardware supports them.
The TPM processor is not fast, be prepared for this to take a while.
The key_password is the password to the TPM key ?
.. cpp:function:: std::string register_key(TPM_Storage_Type storage_type)
Registers a key with the TPM. The storage_type can be either
`TPM_Storage_Type::User` or `TPM_Storage_Type::System`. If System, the
key is stored on the TPM itself. If User, it is stored on the local hard
drive in a database maintained by an intermediate piece of system
software (which actual interacts with the physical TPM on behalf of any
number of applications calling the TPM API).
The TPM has only some limited space to store private keys and may reject
requests to store the key.
In either case the key is encrypted with an RSA key which was generated
on the TPM and which it will not allow to be exported. Thus (so goes the
theory) without physically attacking the TPM
Returns a UUID which can be passed back to constructor below.
.. cpp:function:: TPM_PrivateKey(TPM_Context& ctx, const std::string& uuid, \
TPM_Storage_Type storage_type)
Load a registered key. The UUID was returned by the ``register_key`` function.
.. cpp:function:: std::vector<uint8_t> export_blob() const
Export the key as an encrypted blob. This blob can later be presented
back to the same TPM to load the key.
.. cpp:function:: TPM_PrivateKey(TPM_Context& ctx, const std::vector<uint8_t>& blob)
Load a TPM key previously exported as a blob with ``export_blob``.
.. cpp:function:: std::unique_ptr<Public_Key> public_key() const
Return the public key associated with this TPM private key.
TPM does not store public keys, nor does it support signature verification.
.. cpp:function:: TSS_HKEY handle() const
Returns the bare TSS key handle. Use if you need to call the raw TSS API.
A ``TPM_PrivateKey`` can be passed to a ``PK_Signer`` constructor and used to
sign messages just like any other key. Only PKCS #1 v1.5 signatures are supported
by the v1.2 TPM.
.. cpp:function:: std::vector<std::string> TPM_PrivateKey::registered_keys(TPM_Context& ctx)
This static function returns the list of all keys (in URL format)
registered with the system

View File

@ -1,45 +0,0 @@
Threshold Secret Sharing
========================================
.. versionadded:: 1.9.1
Threshold secret sharing allows splitting a secret into ``N`` shares such that
``M`` (for specified ``M`` <= ``N``) is sufficient to recover the secret, but an
attacker with ``M - 1`` shares cannot derive any information about the secret.
The implementation in Botan follows an expired Internet draft
"draft-mcgrew-tss-03". Several other implementations of this TSS format exist.
.. cpp:class:: RTSS_Share
.. cpp:function:: static std::vector<RTSS_Share> split(uint8_t M, uint8_t N, \
const uint8_t secret[], uint16_t secret_len, \
const std::vector<uint8_t>& identifier, \
const std::string& hash_fn, \
RandomNumberGenerator& rng)
Split a secret. The identifier is an optional key identifier which may be
up to 16 bytes long. Shorter identifiers are padded with zeros.
The hash function must be either "SHA-1", "SHA-256", or "None" to disable
the checksum.
This will return a vector of length ``N``, any ``M`` of these shares is
sufficient to reconstruct the data.
.. cpp:function:: static secure_vector<uint8_t> reconstruct(const std::vector<RTSS_Share>& shares)
Given a sufficient number of shares, reconstruct a secret.
.. cpp:function:: RTSS_Share(const uint8_t data[], size_t len)
Read a TSS share as a sequence of bytes.
.. cpp:function:: const secure_vector<uint8>& data() const
Return the data of this share.
.. cpp:function:: uint8_t share_id() const
Return the share ID which will be in the range 1...255

View File

@ -1,102 +0,0 @@
.. _versioning:
Versioning
========================================
All versions are of the tuple (major,minor,patch).
As of Botan 2.0.0, Botan uses semantic versioning. The minor number increases if
any feature addition is made. The patch version is used to indicate a release
where only bug fixes were applied. If an incompatible API change is required,
the major version will be increased.
The library has functions for checking compile-time and runtime versions.
The build-time version information is defined in `botan/build.h`
.. c:macro:: BOTAN_VERSION_MAJOR
The major version of the release.
.. c:macro:: BOTAN_VERSION_MINOR
The minor version of the release.
.. c:macro:: BOTAN_VERSION_PATCH
The patch version of the release.
.. c:macro:: BOTAN_VERSION_DATESTAMP
Expands to an integer of the form YYYYMMDD if this is an official
release, or 0 otherwise. For instance, 1.10.1, which was released
on July 11, 2011, has a `BOTAN_VERSION_DATESTAMP` of 20110711.
.. c:macro:: BOTAN_DISTRIBUTION_INFO
.. versionadded:: 1.9.3
A macro expanding to a string that is set at build time using the
``--distribution-info`` option. It allows a packager of the library
to specify any distribution-specific patches. If no value is given
at build time, the value is the string "unspecified".
.. c:macro:: BOTAN_VERSION_VC_REVISION
.. versionadded:: 1.10.1
A macro expanding to a string that is set to a revision identifier
corresponding to the source, or "unknown" if this could not be
determined. It is set for all official releases, and for builds that
originated from within a git checkout.
The runtime version information, and some helpers for compile time
version checks, are included in `botan/version.h`
.. cpp:function:: std::string version_string()
Returns a single-line string containing relevant information about
this build and version of the library in an unspecified format.
.. cpp:function:: uint32_t version_major()
Returns the major part of the version.
.. cpp:function:: uint32_t version_minor()
Returns the minor part of the version.
.. cpp:function:: uint32_t version_patch()
Returns the patch part of the version.
.. cpp:function:: uint32_t version_datestamp()
Return the datestamp of the release (or 0 if the current version is
not an official release).
.. cpp:function:: std::string runtime_version_check(uint32_t major, uint32_t minor, uint32_t patch)
Call this function with the compile-time version being built against, eg::
Botan::runtime_version_check(BOTAN_VERSION_MAJOR, BOTAN_VERSION_MINOR, BOTAN_VERSION_PATCH)
It will return an empty string if the versions match, or otherwise
an error message indicating the discrepancy. This only is useful in
dynamic libraries, where it is possible to compile and run against
different versions.
.. c:macro:: BOTAN_VERSION_CODE_FOR(maj,min,patch)
Return a value that can be used to compare versions. The current
(compile-time) version is available as the macro
`BOTAN_VERSION_CODE`. For instance, to choose one code path for
version 2.1.0 and later, and another code path for older releases::
#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,1,0)
// 2.1+ code path
#else
// code path for older versions
#endif

View File

@ -1,954 +0,0 @@
.. _x509_certificates:
X.509 Certificates and CRLs
=================================
A certificate is a binding between some identifying information
(called a *subject*) and a public key. This binding is asserted by a
signature on the certificate, which is placed there by some authority
(the *issuer*) that at least claims that it knows the subject named in
the certificate really "owns" the private key corresponding to the
public key in the certificate.
The major certificate format in use today is X.509v3, used for instance in the
:doc:`tls` protocol. A X.509 certificate is represented by the class
``X509_Certificate``. The data of an X.509 certificate is stored as a
``shared_ptr`` to a structure containing the decoded information. So copying
``X509_Certificate`` objects is quite cheap.
.. cpp:class:: X509_Certificate
.. cpp:function:: X509_Certificate(const std::string& filename)
Load a certificate from a file. PEM or DER is accepted.
.. cpp:function:: X509_Certificate(const std::vector<uint8_t>& in)
Load a certificate from a byte string.
.. cpp:function:: X509_Certificate(DataSource& source)
Load a certificate from an abstract ``DataSource``.
.. cpp:function:: X509_DN subject_dn() const
Returns the distinguished name (DN) of the certificate's subject. This is
the primary place where information about the subject of the certificate is
stored. However "modern" information that doesn't fit in the X.500
framework, such as DNS name, email, IP address, or XMPP address, appears
instead in the subject alternative name.
.. cpp:function:: X509_DN issuer_dn() const
Returns the distinguished name (DN) of the certificate's issuer, ie the CA
that issued this certificate.
.. cpp:function:: const AlternativeName& subject_alt_name() const
Return the subjects alternative name. This is used to store
values like associated URIs, DNS addresses, and email addresses.
.. cpp:function:: const AlternativeName& issuer_alt_name() const
Return alternative names for the issuer.
.. cpp:function:: std::unique_ptr<Public_Key> load_subject_public_key() const
Deserialize the stored public key and return a new object. This
might throw, if it happens that the public key object stored in
the certificate is malformed in some way, or in the case that the
public key algorithm used is not supported by the library.
See :ref:`serializing_public_keys` for more information about what to do
with the returned object. It may be any type of key, in principle, though
RSA and ECDSA are most common.
.. cpp:function:: std::vector<uint8_t> subject_public_key_bits() const
Return the binary encoding of the subject public key. This value (or a hash of
it) is used in various protocols, eg for public key pinning.
.. cpp:function:: AlgorithmIdentifier subject_public_key_algo() const
Return an algorithm identifier that identifies the algorithm used in the
subject's public key.
.. cpp:function:: std::vector<uint8_t> serial_number() const
Return the certificates serial number. The tuple of issuer DN and
serial number should be unique.
.. cpp:function:: std::vector<uint8> raw_subject_dn() const
Return the binary encoding of the subject DN.
.. cpp:function:: std::vector<uint8> raw_issuer_dn() const
Return the binary encoding of the issuer DN.
.. cpp:function:: X509_Time not_before() const
Returns the point in time the certificate becomes valid
.. cpp:function:: X509_Time not_after() const
Returns the point in time the certificate expires
.. cpp:function:: const Extensions& v3_extensions() const
Returns all extensions of this certificate. You can use this
to examine any extension data associated with the certificate,
including custom extensions the library doesn't know about.
.. cpp:function:: std::vector<uint8_t> authority_key_id() const
Return the authority key id, if set. This is an arbitrary string; in the
issuing certificate this will be the subject key id.
.. cpp:function:: std::vector<uint8_t> subject_key_id() const
Return the subject key id, if set.
.. cpp:function:: bool allowed_extended_usage(const OID& usage) const
Return true if and only if the usage OID appears in the extended key usage
extension. Also will return true if the extended key usage extension is
not used in the current certificate.
.. cpp:function:: std::vector<OID> extended_key_usage() const
Return the list of extended key usages. May be empty.
.. cpp:function:: std::string fingerprint(const std::string& hash_fn = "SHA-1") const
Return a fingerprint for the certificate, which is basically just a hash
of the binary contents. Normally SHA-1 or SHA-256 is used, but any hash
function is allowed.
.. cpp:function:: Key_Constraints constraints() const
Returns a basic list of constraints which govern usage of the
key embedded in this certificate.
The Key_Constraints is a class that behaves somewhat like an
``enum``. The easiest way to use it is with its ``includes``
method. For example::
constraints().includes(Key_Constraints::DigitalSignature)
checks if the certificate key is valid for generating digital
signatures.
.. cpp:function:: bool matches_dns_name(const std::string& name) const
Check if the certificate's subject alternative name DNS fields
match ``name``. This function also handles wildcard certificates.
.. cpp:function:: std::string to_string() const
Returns a free-form human readable string describing the certificate.
.. cpp:function:: std::string PEM_encode() const
Returns the PEM encoding of the certificate
.. cpp:function:: std::vector<uint8_t> BER_encode() const
Returns the DER/BER encoding of the certificate
X.509 Distinguished Names
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. cpp:class:: X509_DN
.. cpp:function:: bool has_field(const std::string& attr) const
Returns true if ``get_attribute`` or ``get_first_attribute`` will return a value.
.. cpp:function:: std::vector<std::string> get_attribute(const std::string& attr) const
Return all attributes associated with a certain attribute type.
.. cpp:function:: std::string get_first_attribute(const std::string& attr) const
Like ``get_attribute`` but returns just the first attribute, or
empty if the DN has no attribute of the specified type.
.. cpp:function:: std::multimap<OID, std::string> get_attributes() const
Get all attributes of the DN. The OID maps to a DN component such as
2.5.4.10 ("Organization"), and the strings are UTF-8 encoded.
.. cpp:function:: std::multimap<std::string, std::string> contents() const
Similar to ``get_attributes``, but the OIDs are decoded to strings.
.. cpp:function:: void add_attribute(const std::string& key, const std::string& val)
Add an attribute to a DN.
.. cpp:function:: void add_attribute(const OID& oid, const std::string& val)
Add an attribute to a DN using an OID instead of string-valued attribute type.
The ``X509_DN`` type also supports iostream extraction and insertion operators,
for formatted input and output.
X.509v3 Extensions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
X.509v3 specifies a large number of possible extensions. Botan supports some,
but by no means all of them. The following listing lists which X.509v3
extensions are supported and notes areas where there may be problems with the
handling.
- Key Usage and Extended Key Usage: No problems known.
- Basic Constraints: No problems known. A self-signed v1 certificate
is assumed to be a CA, while a v3 certificate is marked as a CA if
and only if the basic constraints extension is present and set for
a CA cert.
- Subject Alternative Names: Only the "rfc822Name", "dNSName", and
"uniformResourceIdentifier" and raw IPv4 fields will be stored; all
others are ignored.
- Issuer Alternative Names: Same restrictions as the Subject
Alternative Names extension. New certificates generated by Botan
never include the issuer alternative name.
- Authority Key Identifier: Only the version using KeyIdentifier is
supported. If the GeneralNames version is used and the extension is
critical, an exception is thrown. If both the KeyIdentifier and GeneralNames
versions are present, then the KeyIdentifier will be used, and the
GeneralNames ignored.
- Subject Key Identifier: No problems known.
- Name Constraints: No problems known (though encoding is not supported).
Any unknown critical extension in a certificate will lead to an
exception during path validation.
Extensions are handled by a special class taking care of encoding
and decoding. It also supports encoding and decoding of custom extensions.
To do this, it internally keeps two lists of extensions. Different lookup
functions are provided to search them.
.. note::
Validation of custom extensions during path validation is currently not supported.
.. cpp:class:: Extensions
.. cpp:function:: void add(Certificate_Extension* extn, bool critical = false)
Adds a new extension to the extensions object. If an extension of the same
type already exists, ``extn`` will replace it. If ``critical`` is true the
extension will be marked as critical in the encoding.
.. cpp:function:: bool add_new(Certificate_Extension* extn, bool critical = false)
Like ``add`` but an existing extension will not be replaced. Returns true if the
extension was used, false if an extension of the same type was already in place.
.. cpp:function:: void replace(Certificate_Extension* extn, bool critical = false)
Adds an extension to the list or replaces it, if the same
extension was already added
.. cpp:function:: std::unique_ptr<Certificate_Extension> get(const OID& oid) const
Searches for an extension by OID and returns the result
.. cpp:function:: template<typename T> \
std::unique_ptr<T> get_raw(const OID& oid)
Searches for an extension by OID and returns the result.
Only the unknown extensions, that is, extensions types that are not
listed above, are searched for by this function.
.. cpp:function:: std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> extensions() const
Returns the list of extensions together with the corresponding
criticality flag. Only contains the supported extension types
listed above.
.. cpp:function:: std::map<OID, std::pair<std::vector<uint8_t>, bool>> extensions_raw() const
Returns the list of extensions as raw, encoded bytes
together with the corresponding criticality flag.
Contains all extensions, known as well as unknown extensions.
Certificate Revocation Lists
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It will occasionally happen that a certificate must be revoked before
its expiration date. Examples of this happening include the private
key being compromised, or the user to which it has been assigned
leaving an organization. Certificate revocation lists are an answer to
this problem (though online certificate validation techniques are
starting to become somewhat more popular). Every once in a while the
CA will release a new CRL, listing all certificates that have been
revoked. Also included is various pieces of information like what time
a particular certificate was revoked, and for what reason. In most
systems, it is wise to support some form of certificate revocation,
and CRLs handle this easily.
For most users, processing a CRL is quite easy. All you have to do is
call the constructor, which will take a filename (or a
``DataSource&``). The CRLs can either be in raw BER/DER, or in PEM
format; the constructor will figure out which format without any extra
information. For example::
X509_CRL crl1("crl1.der");
DataSource_Stream in("crl2.pem");
X509_CRL crl2(in);
After that, pass the ``X509_CRL`` object to a ``Certificate_Store`` object
with
.. cpp:function:: void Certificate_Store::add_crl(const X509_CRL& crl)
and all future verifications will take into account the provided CRL.
Certificate Stores
----------------------------------------
An object of type ``Certificate_Store`` is a generalized interface to
an external source for certificates (and CRLs). Examples of such a
store would be one that looked up the certificates in a SQL database,
or by contacting a CGI script running on a HTTP server. There are
currently three mechanisms for looking up a certificate, and one for
retrieving CRLs. By default, most of these mechanisms will return an
empty ``std::optional`` of ``X509_Certificate``. This storage mechanism
is *only* queried when doing certificate validation: it allows you to
distribute only the root key with an application, and let some online
method handle getting all the other certificates that are needed to
validate an end entity certificate. In particular, the search routines
will not attempt to access the external database.
The certificate lookup methods are ``find_cert`` (by Subject
Distinguished Name and optional Subject Key Identifier) and
``find_cert_by_pubkey_sha1`` (by SHA-1 hash of the certificate's
public key). The Subject Distinguished Name is given as a ``X509_DN``,
while the SKID parameter takes a ``std::vector<uint8_t>`` containing
the subject key identifier in raw binary. Both lookup methods are
mandatory to implement.
Finally, there is a method for finding a CRL, called ``find_crl_for``,
that takes an ``X509_Certificate`` object, and returns a
``std::optional`` of ``X509_CRL``. The ``std::optional`` return
type makes it easy to return no CRLs by returning ``nullopt``
(eg, if the certificate store doesn't support retrieving CRLs).
Implementing the function is optional, and by default will return
``nullopt``.
Certificate stores are used in the :doc:`tls` module to store a
list of trusted certificate authorities.
.. note::
In the 2.x library, the certificate store interface relied on
``shared_ptr<X509_Certificate>`` to avoid copies. However since
2.4.0, the ``X509_Certificate`` was internally shared, and thus the
outer ``shared_ptr`` was just a cause of needless runtime overhead
and API complexity. Starting in version 3.0, the certificate store
interface is defined in terms of plain ``X509_Certificate``.
In Memory Certificate Store
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The in memory certificate store keeps all objects in memory only.
Certificates can be loaded from disk initially, but also added
later.
.. cpp:class:: Certificate_Store_In_Memory
.. cpp:function:: Certificate_Store_In_Memory(const std::string& dir)
Attempt to parse all files in ``dir`` (including subdirectories)
as certificates. Ignores errors.
.. cpp:function:: Certificate_Store_In_Memory(const X509_Certificate& cert)
Adds given certificate to the store
.. cpp:function:: Certificate_Store_In_Memory()
Create an empty store
.. cpp:function:: void add_certificate(const X509_Certificate& cert)
Add a certificate to the store
.. cpp:function:: void add_crl(const X509_CRL& crl)
Add a certificate revocation list (CRL) to the store.
System Certificate Stores
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
An interface to use the system provided certificate stores is available for
Unix, macOS and Windows systems, ``System_Certificate_Store``
Flatfile Certificate Stores
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``Flatfile_Certificate_Store`` is an implementation of certificate store that
reads certificates as files from a directory. This is also used as the
implementation of the Unix/Linux system certificate store.
The constructor takes a path to the directory to read, along with an optional
boolean indicating if non-CA certificates should be ignored.
SQL-backed Certificate Stores
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The SQL-backed certificate stores store all objects in an SQL database. They
also additionally provide private key storage and revocation of individual
certificates.
.. cpp:class:: Certificate_Store_In_SQL
.. cpp:function:: Certificate_Store_In_SQL(const std::shared_ptr<SQL_Database> db, \
const std::string& passwd, RandomNumberGenerator& rng, const std::string& table_prefix = "")
Create or open an existing certificate store from an SQL database.
The password in ``passwd`` will be used to encrypt private keys.
.. cpp:function:: bool insert_cert(const X509_Certificate& cert)
Inserts ``cert`` into the store. Returns `false` if the certificate is
already known and `true` if insertion was successful.
.. cpp:function:: remove_cert(const X509_Certificate& cert)
Removes ``cert`` from the store. Returns `false` if the certificate could not
be found and `true` if removal was successful.
.. cpp:function:: std::shared_ptr<const Private_Key> find_key(const X509_Certificate&) const
Returns the private key for "cert" or an empty shared_ptr if none was found
.. cpp:function:: std::vector<X509_Certificate> find_certs_for_key(const Private_Key& key) const
Returns all certificates for private key ``key``
.. cpp:function:: bool insert_key(const X509_Certificate& cert, const Private_Key& key)
Inserts ``key`` for ``cert`` into the store, returns `false` if the key is
already known and `true` if insertion was successful.
.. cpp:function:: void remove_key(const Private_Key& key)
Removes ``key`` from the store
.. cpp:function:: void revoke_cert(const X509_Certificate&, CRL_Code, \
const X509_Time& time = X509_Time())
Marks ``cert`` as revoked starting from ``time``
.. cpp:function:: void affirm_cert(const X509_Certificate&)
Reverses the revocation for ``cert``
.. cpp:function:: std::vector<X509_CRL> generate_crls() const
Generates CRLs for all certificates marked as revoked.
A CRL is returned for each unique issuer DN.
The ``Certificate_Store_In_SQL`` class operates on an abstract ``SQL_Database``
object. If support for sqlite3 was enabled at build time, Botan includes an
implementation of this interface for sqlite3, and a subclass of
``Certificate_Store_In_SQL`` which creates or opens a sqlite3 database.
.. cpp:class:: Certificate_Store_In_SQLite
.. cpp:function:: Certificate_Store_In_SQLite(const std::string& db_path, \
const std::string& passwd, RandomNumberGenerator& rng, const std::string& table_prefix = "")
Create or open an existing certificate store from an sqlite database file.
The password in ``passwd`` will be used to encrypt private keys.
Path Validation
----------------------------------------
The process of validating a certificate chain up to a trusted root is
called `path validation`, and in botan that operation is handled by a
set of functions in ``x509path.h`` named ``x509_path_validate``:
.. cpp:function:: Path_Validation_Result \
x509_path_validate(const X509_Certificate& end_cert, \
const Path_Validation_Restrictions& restrictions, \
const Certificate_Store& store, const std::string& hostname = "", \
Usage_Type usage = Usage_Type::UNSPECIFIED, \
std::chrono::system_clock::time_point validation_time = std::chrono::system_clock::now(), \
std::chrono::milliseconds ocsp_timeout = std::chrono::milliseconds(0), \
const std::vector<std::optional<OCSP::Response>>& ocsp_resp = std::vector<std::optional<OCSP::Response>>())
The last five parameters are optional. ``hostname`` specifies a hostname which is
matched against the subject DN in ``end_cert`` according to RFC 6125.
An empty hostname disables hostname validation.
``usage`` specifies key usage restrictions that are compared
to the key usage fields in `end_cert` according to RFC 5280, if not set to
``UNSPECIFIED``. ``validation_time`` allows setting the time point at which all certificates
are validated. This is really only useful for testing. The default is the
current system clock's current time. ``ocsp_timeout`` sets the timeout for
OCSP requests. The default of 0 disables OCSP checks completely.
``ocsp_resp`` allows adding additional OCSP responses retrieved from outside
of the path validation. Note that OCSP online checks are done only
as long as the http_util module was compiled in. Availability of online
OCSP checks can be checked using the macro BOTAN_HAS_ONLINE_REVOCATION_CHECKS.
For the different flavors of ``x509_path_validate``, check ``x509path.h``.
The result of the validation is returned as a class:
.. cpp:class:: Path_Validation_Result
Specifies the result of the validation
.. cpp:function:: bool successful_validation() const
Returns true if a certificate path from *end_cert* to a trusted
root was found and all path validation checks passed.
.. cpp:function:: std::string result_string() const
Returns a descriptive string of the validation status (for
instance "Verified", "Certificate is not yet valid", or
"Signature error"). This is the string value of
the `result` function below.
.. cpp:function:: const X509_Certificate& trust_root() const
If the validation was successful, returns the certificate which
is acting as the trust root for *end_cert*.
.. cpp:function:: const std::vector<X509_Certificate>& cert_path() const
Returns the full certificate path starting with the end entity
certificate and ending in the trust root.
.. cpp:function:: Certificate_Status_Code result() const
Returns the 'worst' error that occurred during validation. For
instance, we do not want an expired certificate with an invalid
signature to be reported to the user as being simply expired (a
relatively innocuous and common error) when the signature isn't
even valid.
.. cpp:function:: const std::vector<std::set<Certificate_Status_Code>>& all_statuses() const
For each certificate in the chain, returns a set of status which
indicate all errors which occurred during validation. This is
primarily useful for diagnostic purposes.
.. cpp:function:: std::set<std::string> trusted_hashes() const
Returns the set of all cryptographic hash functions which are
implicitly trusted for this validation to be correct.
A ``Path_Validation_Restrictions`` is passed to the path
validator and specifies restrictions and options for the validation
step. The two constructors are:
.. cpp:function:: Path_Validation_Restrictions(bool require_rev, \
size_t minimum_key_strength, \
bool ocsp_all_intermediates, \
const std::set<std::string>& trusted_hashes)
If `require_rev` is true, then any path without revocation
information (CRL or OCSP check) is rejected with the code
`NO_REVOCATION_DATA`. The `minimum_key_strength` parameter
specifies the minimum strength of public key signature we will
accept is. The set of hash names `trusted_hashes` indicates which
hash functions we'll accept for cryptographic signatures. Any
untrusted hash will cause the error case `UNTRUSTED_HASH`.
.. cpp:function:: Path_Validation_Restrictions(bool require_rev = false, \
size_t minimum_key_strength = 80, \
bool ocsp_all_intermediates = false)
A variant of the above with some convenient defaults. The current
default `minimum_key_strength` of 80 roughly corresponds to 1024
bit RSA. The set of trusted hashes is set to all SHA-2 variants,
and, if `minimum_key_strength` is less than or equal to 80, then
SHA-1 signatures will also be accepted.
Creating New Certificates
---------------------------------
A CA is represented by the type ``X509_CA``, which can be found in
``x509_ca.h``. A CA always needs its own certificate, which can either
be a self-signed certificate (see below on how to create one) or one
issued by another CA (see the section on PKCS #10 requests). Creating
a CA object is done by the following constructor:
.. cpp:function:: X509_CA::X509_CA(const X509_Certificate& cert, \
const Private_Key& key, \
const std::string& hash_fn, \
RandomNumberGenerator& rng)
The private ``key`` is the private key corresponding to the public key in the
CA's certificate. ``hash_fn`` is the name of the hash function to use
for signing, e.g., `SHA-256`. ``rng`` is queried for random during signing.
There is an alternative constructor that lets you set additional options, namely
the padding scheme that will be used by the X509_CA object to sign certificates
and certificate revocation lists. If the padding is not set explicitly, the CA
will use some default. The only time you need this alternate interface is
for creating RSA-PSS certificates.
.. cpp:function:: X509_CA::X509_CA(const X509_Certificate& cert, \
const Private_Key& key, \
const std::string& hash_fn, \
const std::string& padding_fn, \
RandomNumberGenerator& rng)
Requests for new certificates are supplied to a CA in the form of PKCS
#10 certificate requests (called a ``PKCS10_Request`` object in
Botan). These are decoded in a similar manner to
certificates/CRLs/etc. A request is vetted by humans (who somehow
verify that the name in the request corresponds to the name of the
entity who requested it), and then signed by a CA key, generating a
new certificate:
.. cpp:function:: X509_Certificate \
X509_CA::sign_request(const PKCS10_Request& req, \
RandomNumberGenerator& rng, \
const X509_Time& not_before, \
const X509_Time& not_after)
If you need more control over the signing process, you can use the methods
.. cpp:function:: static X509_Certificate X509_CA::make_cert(PK_Signer& signer, \
RandomNumberGenerator& rng, \
const BigInt& serial_number, \
const AlgorithmIdentifier& sig_algo, \
const std::vector<uint8_t>& pub_key, \
const X509_Time& not_before, \
const X509_Time& not_after, \
const X509_DN& issuer_dn, \
const X509_DN& subject_dn, \
const Extensions& extensions)
.. cpp:function:: static Extensions X509_CA::choose_extensions(const PKCS10_Request& req, \
const X509_Certificate& ca_certificate, \
const std::string& hash_fn)
Returns the extensions that would be created by sign_request if it was used.
You can call this and then modify the extensions list before invoking
:cpp:func:`X509_CA::make_cert`
Generating CRLs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As mentioned previously, the ability to process CRLs is highly
important in many PKI systems. In fact, according to strict X.509
rules, you must not validate any certificate if the appropriate CRLs
are not available (though hardly any systems are that strict). In any
case, a CA should have a valid CRL available at all times.
Of course, you might be wondering what to do if no certificates have
been revoked. Never fear; empty CRLs, which revoke nothing at all, can
be issued. To generate a new, empty CRL, just call
.. cpp:function:: X509_CRL X509_CA::new_crl(RandomNumberGenerator& rng, \
uint32_t next_update = 0)
This function will return a new, empty CRL. The ``next_update`` parameter is
the number of seconds before the CRL expires. If it is set to the (default)
value of zero, then a reasonable default (currently 7 days) will be used.
On the other hand, you may have issued a CRL before. In that case, you will
want to issue a new CRL that contains all previously revoked
certificates, along with any new ones. This is done by calling
.. cpp:function:: X509_CRL X509_CA::update_crl(const X509_CRL& last_crl, \
std::vector<CRL_Entry> new_entries, RandomNumberGenerator& rng, \
size_t next_update = 0)
Where ``last_crl`` is the last CRL this CA issued, and
``new_entries`` is a list of any newly revoked certificates. The
function returns a new ``X509_CRL`` to make available for
clients.
The ``CRL_Entry`` type is a structure that contains, at a minimum, the serial
number of the revoked certificate. As serial numbers are never repeated, the
pairing of an issuer and a serial number (should) distinctly identify any
certificate. In this case, we represent the serial number as a
``secure_vector<uint8_t>`` called ``serial``. There are two additional (optional)
values, an enumeration called ``CRL_Code`` that specifies the reason for
revocation (``reason``), and an object that represents the time that the
certificate became invalid (if this information is known).
If you wish to remove an old entry from the CRL, insert a new entry for the
same cert, with a ``reason`` code of ``REMOVE_FROM_CRL``. For example, if a
revoked certificate has expired 'normally', there is no reason to continue to
explicitly revoke it, since clients will reject the cert as expired in any
case.
Self-Signed Certificates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Generating a new self-signed certificate can often be useful, for
example when setting up a new root CA, or for use in specialized
protocols. The library provides a utility function for this:
.. cpp:function:: X509_Certificate create_self_signed_cert( \
const X509_Cert_Options& opts, const Private_Key& key, \
const std::string& hash_fn, RandomNumberGenerator& rng)
Where ``key`` is the private key you wish to use (the public key,
used in the certificate itself is extracted from the private key),
and ``opts`` is an structure that has various bits of information
that will be used in creating the certificate (this structure, and
its use, is discussed below).
Creating PKCS #10 Requests
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Also in ``x509self.h``, there is a function for generating new PKCS #10
certificate requests:
.. cpp:function:: PKCS10_Request create_cert_req( \
const X509_Cert_Options& opts, const Private_Key& key, \
const std::string& hash_fn, RandomNumberGenerator& rng)
This function acts quite similarly to
:cpp:func:`create_self_signed_cert`, except it instead returns a PKCS
#10 certificate request. After creating it, one would typically
transmit it to a CA, who signs it and returns a freshly minted X.509
certificate.
.. cpp:function:: PKCS10_Request PKCS10_Request::create(const Private_Key& key, \
const X509_DN& subject_dn, \
const Extensions& extensions, \
const std::string& hash_fn, \
RandomNumberGenerator& rng, \
const std::string& padding_scheme = "", \
const std::string& challenge = "")
This function (added in 2.5) is similar to ``create_cert_req`` but allows
specifying all the parameters directly. In fact ``create_cert_req`` just
creates the DN and extensions from the options, then uses this call to
actually create the ``PKCS10_Request`` object.
Certificate Options
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
What is this ``X509_Cert_Options`` thing we've been passing around?
It's a class representing a bunch of information that will end up
being stored into the certificate. This information comes in 3 major
flavors: information about the subject (CA or end-user), the validity
period of the certificate, and restrictions on the usage of the
certificate. For special cases, you can also add custom X.509v3
extensions.
First and foremost is a number of ``std::string`` members, which
contains various bits of information about the user: ``common_name``,
``serial_number``, ``country``, ``organization``, ``org_unit``,
``locality``, ``state``, ``email``, ``dns_name``, and ``uri``. As many
of these as possible should be filled it (especially an email
address), though the only required ones are ``common_name`` and
``country``.
Additionally there are a small selection of ``std::vector<std::string>``
members, which allow space for repeating elements:
``more_org_units`` and ``more_dns``.
There is another value that is only useful when creating a PKCS #10
request, which is called ``challenge``. This is a challenge password,
which you can later use to request certificate revocation (*if* the CA
supports doing revocations in this manner).
Then there is the validity period; these are set with ``not_before``
and ``not_after``. Both of these functions also take a
``std::string``, which specifies when the certificate should start
being valid, and when it should stop being valid. If you don't set the
starting validity period, it will automatically choose the current
time. If you don't set the ending time, it will choose the starting
time plus a default time period. The arguments to these functions
specify the time in the following format: "2002/11/27 1:50:14". The
time is in 24-hour format, and the date is encoded as
year/month/day. The date must be specified, but you can omit the time
or trailing parts of it, for example "2002/11/27 1:50" or
"2002/11/27".
Third, you can set constraints on a key. The one you're mostly likely
to want to use is to create (or request) a CA certificate, which can
be done by calling the member function ``CA_key``. This should only be
used when needed.
Moreover, you can specify the padding scheme to be used when digital signatures
are computed by calling function ``set_padding_scheme`` with a string
representing the padding scheme. This way, you can control the padding scheme
for self-signed certificates and PKCS #10 requests. The padding scheme used by
a CA when building a certificate or a certificate revocation list can be set in
the ``X509_CA`` constructor. The supported padding schemes can be found in
src/lib/pubkey/padding.cpp. Some alternative names for the padding schemes are
understood, as well.
Other constraints can be set by calling the member functions
``add_constraints`` and ``add_ex_constraints``. The first takes a
``Key_Constraints`` value, and replaces any previously set value. If
no value is set, then the certificate key is marked as being valid for
any usage. You can set it to any of the following (for more than one
usage, OR them together): ``DigitalSignature``, ``NonRepudiation``,
``KeyEncipherment``, ``DataEncipherment``, ``KeyAgreement``,
``KeyCertSign``, ``CrlSign``, ``EncipherOnly``, or ``DecipherOnly``.
Many of these have quite special semantics, so you should either
consult the appropriate standards document (such as RFC 5280), or just
not call ``add_constraints``, in which case the appropriate values
will be chosen for you based on the key type.
The second function, ``add_ex_constraints``, allows you to specify an
OID that has some meaning with regards to restricting the key to
particular usages. You can, if you wish, specify any OID you like, but
there is a set of standard ones that other applications will be able
to understand. These are the ones specified by the PKIX standard, and
are named "PKIX.ServerAuth" (for TLS server authentication),
"PKIX.ClientAuth" (for TLS client authentication), "PKIX.CodeSigning",
"PKIX.EmailProtection" (most likely for use with S/MIME),
"PKIX.IPsecUser", "PKIX.IPsecTunnel", "PKIX.IPsecEndSystem", and
"PKIX.TimeStamping". You can call "add_ex_constraints" any number of
times - each new OID will be added to the list to include in the
certificate.
Lastly, you can add any X.509v3 extensions in the `extensions` member, which is
useful if you want to encode a custom extension, or encode an extension in a way
differently from how Botan defaults.
OCSP Requests
----------------------------------------
A client makes an OCSP request to what is termed an 'OCSP responder'. This
responder returns a signed response attesting that the certificate in question
has not been revoked. The most recent OCSP specification is as of this
writing :rfc:`6960`.
Normally OCSP validation happens automatically as part of X.509 certificate
validation, as long as OCSP is enabled (by setting a non-zero ``ocsp_timeout``
in the call to ``x509_path_validate``, or for TLS by implementing the related
``tls_verify_cert_chain_ocsp_timeout`` callback and returning a non-zero value
from that). So most applications should not need to directly manipulate OCSP
request and response objects.
For those that do, the primary ocsp interface is in ``ocsp.h``. First a request
must be formed, using information contained in the subject certificate and in
the subject's issuing certificate.
.. cpp:class:: OCSP::Request
.. cpp:function:: OCSP::Request(const X509_Certificate& issuer_cert, \
const BigInt& subject_serial)
Create a new OCSP request
.. cpp:function:: OCSP::Request(const X509_Certificate& issuer_cert, \
const X509_Certificate& subject_cert)
Variant of the above, using serial number from ``subject_cert``.
.. cpp:function:: std::vector<uint8_t> BER_encode() const
Encode the current OCSP request as a binary string.
.. cpp:function:: std::string base64_encode() const
Encode the current OCSP request as a base64 string.
Then the response is parsed and validated, and if valid, can be consulted
for certificate status information.
.. cpp:class:: OCSP::Response
.. cpp:function:: OCSP::Response(const uint8_t response_bits[], size_t response_bits_len)
Attempts to parse ``response_bits`` as an OCSP response. Throws an
exception if parsing fails. Note that this does not verify that the OCSP
response is valid (ie that the signature is correct), merely that the
ASN.1 structure matches an OCSP response.
.. cpp:function:: Certificate_Status_Code check_signature( \
const std::vector<Certificate_Store*>& trust_roots, \
const std::vector<X509_Certificate>& cert_path = const std::vector<X509_Certificate>()) const
Find the issuing certificate of the OCSP response, and check the signature.
If possible, pass the full certificate path being validated in
the optional ``cert_path`` argument: this additional information
helps locate the OCSP signer's certificate in some cases. If this
does not return ``Certificate_Status_Code::OCSP_SIGNATURE_OK``,
then the request must not be be used further.
.. cpp:function:: Certificate_Status_Code verify_signature(const X509_Certificate& issuing_cert) const
If the certificate that issued the OCSP response is already known (eg,
because in some specific application all the OCSP responses will always
be signed by a single trusted issuer whose cert is baked into the code)
this provides an alternate version of `check_signature`.
.. cpp:function:: Certificate_Status_Code status_for(const X509_Certificate& issuer, \
const X509_Certificate& subject, \
std::chrono::system_clock::time_point ref_time = std::chrono::system_clock::now()) const
Assuming the signature is valid, returns the status for the subject certificate.
Make sure to get the ordering of the issuer and subject certificates correct.
The ``ref_time`` is normally just the system clock, but can be used if
validation against some other reference time is desired (such as for
testing, to verify an old previously valid OCSP response, or to use an
alternate time source such as the Roughtime protocol instead of the local
client system clock).
.. cpp:function:: const X509_Time& produced_at() const
Return the time this OCSP response was (claimed to be) produced at.
.. cpp:function:: const X509_DN& signer_name() const
Return the distinguished name of the signer. This is used to help
find the issuing certificate.
This field is optional in OCSP responses, and may not be set.
.. cpp:function:: const std::vector<uint8_t>& signer_key_hash() const
Return the SHA-1 hash of the public key of the signer. This is used to
help find the issuing certificate. The ``Certificate_Store`` API
``find_cert_by_pubkey_sha1`` can search on this value.
This field is optional in OCSP responses, and may not be set.
.. cpp:function:: const std::vector<uint8_t>& raw_bits() const
Return the entire raw ASN.1 blob (for debugging or specialized decoding needs)
One common way of making OCSP requests is via HTTP, see :rfc:`2560`
Appendix A for details. A basic implementation of this is the function
``online_check``, which is available as long as the ``http_util`` module
was compiled in; check by testing for the macro ``BOTAN_HAS_HTTP_UTIL``.
.. cpp:function:: OCSP::Response online_check(const X509_Certificate& issuer, \
const BigInt& subject_serial, \
const std::string& ocsp_responder, \
const Certificate_Store* trusted_roots)
Assemble a OCSP request for serial number ``subject_serial`` and attempt to request
it to responder at URI ``ocsp_responder`` over a new HTTP socket, parses and returns
the response. If trusted_roots is not null, then the response is additionally
validated using OCSP response API ``check_signature``. Otherwise, this call must be
performed later by the application.
.. cpp:function:: OCSP::Response online_check(const X509_Certificate& issuer, \
const X509_Certificate& subject, \
const Certificate_Store* trusted_roots)
Variant of the above but uses serial number and OCSP responder URI from ``subject``.

View File

@ -1,62 +0,0 @@
ZFEC Forward Error Correction
===============================
.. versionadded:: 3.0.0
The ``ZFEC`` class provides forward error correction compatible
with the `zfec <https://github.com/tahoe-lafs/zfec>`_ library.
Forward error correction takes an input and creates multiple "shares",
such that any ``K`` of ``N`` shares is sufficient to recover the
entire original input.
.. note::
Specific to the ZFEC format, the first ``K`` generated shares are
identical to the original input data, followed by ``N-K`` shares of
error correcting code. This is very different from threshold secret
sharing, where having fewer than ``K`` shares gives no information
about the original input.
.. warning::
If a corrupted share is provided to the decoding algorithm, the
resulting decoding will be invalid. It is recommended to protect
shares using a technique such as a MAC or public key signature, if
corruption is likely in your application.
``ZFEC`` requires that the input length be exactly divisible by ``K``;
if needed define a padding scheme to pad your input to the necessary
size.
An example application that adds padding and a hash checksum is available
in ``src/cli/zfec.cpp`` and invokable using ``botan fec_encode`` and
``botan fec_decode``.
.. cpp:class:: ZFEC
.. cpp:function:: ZFEC(size_t k, size_t n)
Set up for encoding or decoding using parameters ``k`` and ``n``.
Both must be less than 256, and ``k`` must be less than ``n``.
.. cpp:function:: void encode_shares(const std::vector<const uint8_t*>& shares, \
size_t share_size, \
std::function<void (size_t, const uint8_t[], size_t)> output_cb) const
Encode ``K`` shares in ``shares`` each of length ``share_size`` into ``N``
shares, also each of length ``share_size``. The ``output_cb`` function will
be called once for each output share (in some unspecified and possibly
non-deterministic order).
The parameters to ``output_cb`` are: the share being output, the share
contents, and the length of the encoded share (which will always be
equal to ``share_size``).
.. cpp:function:: void decode_shares(const std::map<size_t, const uint8_t*>& shares, \
size_t share_size, \
std::function<void (size_t, const uint8_t[], size_t)> output_cb) const
Decode some set of shares into the original input. Each share is
of ``share_size`` bytes. The shares are identified by a small
integer (between 0 and 255).
The parameters to ``output_cb`` are similar to that of ``encode_shares``.

View File

@ -1,106 +0,0 @@
Alastair Houghton
Alexander Bluhm (genua GmbH)
Alex Gaynor
Alf-André Walla
Allan L. Bazinet
Alon Bar-Lev
Andrew Moon
Antonio Coratelli
Atanas Filyanov
Baruch Burstein
Bhaskar Biswas
Bi11
Bogdan Gusiev
Chris Desjardins
Christian Mainka (Hackmanit GmbH)
Christopher Bläsius
Christoph Ludwig
cryptosource GmbH
cynecx
Dan Brown
Daniel Neus (Rohde & Schwarz Cybersecurity)
Daniel Seither (Kullo GmbH)
Daniel Wyatt
Elektrobit Automotive GmbH
Eric Cornelius
Erwan Chaussy
etcimon
Evgeny Pokhilko
Fabian Weissberg
Falko Strenzke (cryptosource GmbH)
Felix Yan
FlexSecure GmbH
Florent Le Coz
Francis Dupont
Frank Schoenmann
Google Inc
Gustavo Serra Scalet
guywithcrookedface
Hannes Rantzsch
Harry Reimann
Hegedüs Márton Csaba
Hubert Bugaj
ilovezfs
J08nY
Jack Lloyd
Jeffrey Walton
Joel Low
joerg
Jose Luis Pereira (Fyde Inc.)
Juraj Somorovsky (Hackmanit GmbH)
Justin Karneges
Kai Michaelis (Rohde & Schwarz Cybersecurity)
Kirill A. Korinsky
Konstantinos Kolelis
Krzysztof Kwiatkowski
Lauri Nurmi
Luca Piccarreta
Manuel Glaser (Rohde & Schwarz Cybersecurity)
Manuel Hartl
Marcus Brinkmann
Markus Wanner
Martin Doering
Matej Kenda (TopIT d.o.o.)
Mathieu Souchaud
Matthew Gregan
Matthias Gierlings (Hackmanit GmbH)
Matt Johnston
Michael Boric (Rohde & Schwarz Cybersecurity)
Nathan Hourt
neXenio GmbH
Nicolas Sendrier
Nuno Goncalves
Ori Peleg
Patrick Sona
Patrick Wildt
Patrik Fiedler
Peter J Jones
Philippe Lieser (Rohde & Schwarz Cybersecurity)
Philipp Weber (Rohde & Schwarz Cybersecurity)
Projet SECRET, INRIA, Rocquencourt
René Korthaus (Rohde & Schwarz Cybersecurity)
René Meusel
Ribose Inc
Robert Dailey
Ryuhei Mori
schregger
Sergii Cherkavskyi
seu
Shlomi Fish
Simon Cogliani
Simon Warta (Kullo GmbH)
slaviber
souch
t0b3
tcely
Technische Universitat Darmstadt
Tim Oesterreich
Tobias @neverhub
Tomasz Frydrych
Uri Blumenthal
Vaclav Ovsik
Volker Aßmann
Yuri
Yves Jerschow
Zoltan Gyarmati
0xdefaced

File diff suppressed because it is too large Load Diff

View File

@ -1,441 +0,0 @@
Command Line Interface
========================================
.. highlight:: sh
Outline
------------
The ``botan`` program is a command line tool for using a broad variety
of functions of the Botan library in the shell.
All commands follow the syntax ``botan <command> <command-options>``.
If ``botan`` is run with an unknown command, or without any command, or with the
``--help`` option, all available commands will be printed. If a particular
command is run with the ``--help`` option (like ``botan <command> --help``)
some information about the usage of the command is printed.
Starting in version 2.9, commands that take a passphrase (such as
``gen_bcrypt`` or ``pkcs8``) will also accept the literal ``-`` to mean
ask for the passphrase on the terminal. If supported by the operating
system, echo will be disabled while reading the passphrase.
Most arguments that take a path to a file will also accept the literal ``-``
to mean the file content should be read from STDIN instead.
All options for the command line are displayed in the summary line,
and in the help output. All options are, as the name suggests,
optional, and the default values are shown. For example ``hash file``
prints the SHA-256 of the file encoded as hex, while
``hash --format=base64 --algo=SHA-384 file`` prints the base64 encoded
SHA-384 hash of the same file.
Hash Function
----------------
``hash --algo=SHA-256 --buf-size=4096 --no-fsname --format=hex *files``
Compute the *algo* digest over the data in any number of *files*. If
no files are listed on the command line, the input source defaults
to standard input. Unless the ``--no-fsname`` option is given, the
filename is printed alongside the hash, in the style of tools such
as ``sha256sum``.
Password Hash
----------------
``gen_argon2 --mem=65536 --p=1 --t=1 password``
Calculate the Argon2 password digest of *password*. *mem* is the amount of
memory to use in Kb, *p* the parallelization parameter and *t* the number of
iterations to use.
``check_argon2 password hash``
Checks if the Argon2 hash of the passed *password* equals the passed *hash* value.
``gen_bcrypt --work-factor=12 password``
Calculate the bcrypt password digest of *password*. *work-factor* is an
integer between 4 and 18. A higher *work-factor* value results in a
more expensive hash calculation.
``check_bcrypt password hash``
Checks if the bcrypt hash of the passed *password* equals the passed *hash* value.
``pbkdf_tune --algo=Scrypt --max-mem=256 --output-len=32 --check *times``
Tunes the PBKDF algorithm specified with ``--algo=`` for the given *times*.
HMAC
----------------
``hmac --hash=SHA-256 --buf-size=4096 --no-fsname key files``
Compute the HMAC tag with the cryptographic hash function *hash*
using the key in file *key* over the data in *files*. *files*
defaults to STDIN. Unless the ``--no-fsname`` option is given, the
filename is printed alongside the HMAC value.
Encryption
----------------
``cipher --buf-size=4096 --decrypt --cipher= --key= --nonce= --ad=``
Encrypt a given file with the specified *cipher*, eg "AES-256/GCM".
If ``--decrypt`` is provided the file is decrypted instead.
Public Key Cryptography
-------------------------------------
``keygen --algo=RSA --params= --passphrase= --cipher= --pbkdf= --pbkdf-ms=300 --provider= --der-out``
Generate a PKCS #8 *algo* private key. If *der-out* is passed, the pair is BER
encoded. Otherwise, PEM encoding is used. To protect the PKCS #8 formatted
key, it is recommended to encrypt it with a provided *passphrase*.
If a passphrase is used, *cipher* specifies the name of the desired encryption
algorithm (such as "AES-256/CBC", or leave empty to use a default), and
*pbkdf* can be used to specify the password hashing mechanism (either a hash
such as "SHA-256" to select PBKDF2, or "Scrypt").
The cipher mode must have an object identifier defined, this allows use of
ciphers such as AES, Twofish, Serpent, and SM4. Ciphers in CBC, GCM, and SIV
modes are supported. However most other implementations support only AES or
3DES in CBC mode.
If encryption is used, the parameter *pbkdf-ms* controls how long the password
hashing function will run to derive the encryption key from the passed
*passphrase*.
Algorithm specific parameters, as the desired bit length of an RSA key, can be
passed with *params*.
- For RSA *params* specifies the bit length of the RSA modulus. It defaults to 3072.
- For DH *params* specifies the DH parameters. It defaults to modp/ietf/2048.
- For DSA *params* specifies the DSA parameters. It defaults to dsa/botan/2048.
- For EC algorithms *params* specifies the elliptic curve. It defaults to secp256r1.
``pkcs8 --pass-in= --pub-out --der-out --pass-out= --cipher= --pbkdf= --pbkdf-ms=300 key``
Open a PKCS #8 formatted key at *key*. If *key* is encrypted, the passphrase
must be passed as *pass-in*. It is possible to (re)encrypt the read key with
the passphrase passed as *pass-out*. The parameters *cipher*, *pbkdf*, and
*pbkdf-ms* work similarly to ``keygen``.
``sign --der-format --passphrase= --hash=SHA-256 --padding= --provider= key file``
Sign the data in *file* using the PKCS #8 private key *key* and cryptographic
hash *hash*. If *key* is encrypted, the used passphrase must be passed as
*pass-in*.
The *padding* option can be used to control padding for algorithms that have
divergent methods; this mostly applies to RSA. For RSA, if the option is not
specified PSS signatures are used. You can select generating a PKCS #1 v1.5
formatted signature instead by providing ``--padding=PKCS1v15``.
For ECDSA and DSA, the option ``--der-format`` outputs the signature as an
ASN.1 encoded blob. Some other tools (including ``openssl``) default to this
format. This option does not make sense for other algorithms such as RSA.
The signature is formatted for your screen using base64.
``verify --der-format --hash=SHA-256 --padding= pubkey file signature``
Verify the authenticity of the data in *file* with the provided signature
*signature* and the public key *pubkey*. Similarly to the signing process,
*padding* specifies the padding scheme and *hash* the cryptographic hash
function to use.
``gen_dl_group --pbits=1024 --qbits=0 --seed= --type=subgroup``
Generate ANSI X9.42 encoded Diffie-Hellman group parameters.
- If *type=subgroup* is passed, the size of the prime subgroup q is sampled
as a prime of *qbits* length and p is *pbits* long. If *qbits* is not
passed, its length is estimated from *pbits* as described in RFC 3766.
- If *type=strong* is passed, p is sampled as a safe prime with length
*pbits* and the prime subgroup has size q with *pbits*-1 length.
- If *type=dsa* is used, p and q are generated by the algorithm specified in
FIPS 186-4. If the ``--seed`` parameter is used, it allows to select the
seed value, instead of one being randomly generated. If the seed does not
in fact generate a valid DSA group, the command will fail.
``dl_group_info --pem name``
Print raw Diffie-Hellman parameters (p,g) of the standardized DH group
*name*. If *pem* is set, the X9.42 encoded group is printed.
``ec_group_info --pem name``
Print raw elliptic curve domain parameters of the standardized curve *name*. If
*pem* is set, the encoded domain is printed.
``pk_encrypt --aead=AES-256/GCM rsa_pubkey datafile``
Encrypts ``datafile`` using the specified AEAD algorithm, under a key protected
by the specified RSA public key.
``pk_decrypt rsa_privkey datafile``
Decrypts a file encrypted with ``pk_encrypt``. If the key is encrypted using a
password, it will be prompted for on the terminal.
``fingerprint --no-fsname --algo=SHA-256 *keys``
Calculate the public key fingerprint of the *keys*.
``pk_workfactor --type=rsa bits``
Provide an estimate of the strength of a public key based on it's size.
``--type=`` can be "rsa", "dl" or "dl_exp".
X.509
----------------------------------------------
``gen_pkcs10 key CN --country= --organization= --ca --path-limit=1 --email= --dns= --ext-ku= --key-pass= --hash=SHA-256 --emsa=``
Generate a PKCS #10 certificate signing request (CSR) using the passed PKCS #8
private key *key*. If the private key is encrypted, the decryption passphrase
*key-pass* has to be passed.*emsa* specifies the padding scheme to be used
when calculating the signature.
- For RSA keys EMSA4 (RSA-PSS) is the default scheme.
- For ECDSA, DSA, ECGDSA, ECKCDSA and GOST-34.10 keys *emsa* defaults to EMSA1.
``gen_self_signed key CN --country= --dns= --organization= --email= --path-limit=1 --days=365 --key-pass= --ca --hash=SHA-256 --emsa= --der``
Generate a self signed X.509 certificate using the PKCS #8 private key
*key*. If the private key is encrypted, the decryption passphrase *key-pass*
has to be passed. If *ca* is passed, the certificate is marked for certificate
authority (CA) usage. *emsa* specifies the padding scheme to be used when
calculating the signature.
- For RSA keys EMSA4 (RSA-PSS) is the default scheme.
- For ECDSA, DSA, ECGDSA, ECKCDSA and GOST-34.10 keys *emsa* defaults to EMSA1.
``sign_cert --ca-key-pass= --hash=SHA-256 --duration=365 --emsa= ca_cert ca_key pkcs10_req``
Create a CA signed X.509 certificate from the information contained in the
PKCS #10 CSR *pkcs10_req*. The CA certificate is passed as *ca_cert* and the
respective PKCS #8 private key as *ca_key*. If the private key is encrypted,
the decryption passphrase *ca-key-pass* has to be passed. The created
certificate has a validity period of *duration* days. *emsa* specifies the
padding scheme to be used when calculating the signature. *emsa* defaults to
the padding scheme used in the CA certificate.
``ocsp_check --timeout=3000 subject issuer``
Verify an X.509 certificate against the issuers OCSP responder. Pass the
certificate to validate as *subject* and the CA certificate as *issuer*.
``cert_info --fingerprint file``
Parse X.509 PEM certificate and display data fields. If ``--fingerprint`` is
used, the certificate's fingerprint is also printed.
``cert_verify subject *ca_certs``
Verify if the provided X.509 certificate *subject* can be successfully
validated. The list of trusted CA certificates is passed with *ca_certs*,
which is a list of one or more certificates.
``trust_roots --dn --dn-only --display``
List the certificates in the system trust store.
TLS Server/Client
-----------------------
The ``--policy=`` argument of the TLS commands specifies the TLS policy to use.
The policy can be any of the strings "default", "suiteb_128", "suiteb_192",
"bsi", "strict", or "all" to denote built-in policies, or it can name a file
from which a policy description will be read.
``tls_ciphers --policy=default --version=tls1.2``
Prints the list of ciphersuites that will be offered under a particular
policy/version.
``tls_client host --port=443 --print-certs --policy=default --tls1.0 --tls1.1 --tls1.2 --skip-system-cert-store --trusted-cas= --session-db= --session-db-pass= --next-protocols= --type=tcp --client-cert= --client-cert-key=``
Implements a testing TLS client, which connects to *host* via TCP or UDP on
port *port*. The TLS version can be set with the flags *tls1.0*, *tls1.1* and
*tls1.2* of which the lowest specified version is automatically chosen. If
none of the TLS version flags is set, the latest supported version is
chosen. The client honors the TLS policy specified with *policy* and
prints all certificates in the chain, if *print-certs* is passed.
*next-protocols* is a comma separated list and specifies the protocols to
advertise with Application-Layer Protocol Negotiation (ALPN).
Pass a path to a client certificate PEM and unencrypted PKCS8 encoded private
key if client authentication is required.
``tls_server cert key --port=443 --type=tcp --policy=default --dump-traces= --max-clients=0 --socket-id=0``
Implements a testing TLS server, which allows TLS clients to connect and which
echos any data that is sent to it. Binds to either TCP or UDP on port
*port*. The server uses the certificate *cert* and the respective PKCS #8
private key *key*. The server honors the TLS policy specified with *policy*.
*socket-id* is only available on FreeBSD and sets the *so_user_cookie* value
of the used socket.
``tls_http_server cert key --port=443 --policy=default --threads=0 --max-clients=0 --session-db --session-db-pass=``
Only available if Boost.Asio support was enabled. Provides a simple HTTP server
which replies to all requests with an informational text output. The server
honors the TLS policy specified with *policy*.
``tls_proxy listen_port target_host target_port server_cert server_key--policy=default --threads=0 --max-clients=0 --session-db= --session-db-pass=``
Only available if Boost.Asio support was enabled. Listens on a port and
forwards all connects to a target server specified at
``target_host`` and ``target_port``.
``tls_client_hello --hex input``
Parse and print a TLS client hello message.
Number Theory
-----------------------
``is_prime --prob=56 n``
Test if the integer *n* is composite or prime with a Miller-Rabin primality test with *(prob+2)/2* iterations.
``factor n``
Factor the integer *n* using a combination of trial division by small primes, and Pollard's Rho algorithm.
It can in reasonable time factor integers up to 110 bits or so.
``gen_prime --count=1 bits``
Samples *count* primes with a length of *bits* bits.
``mod_inverse n mod``
Calculates a modular inverse.
PSK Database
--------------------
The PSK database commands are only available if sqlite3 support was compiled in.
``psk_set db db_key name psk``
Using the PSK database named db and encrypting under the (hex) key ``db_key``,
save the provided psk (also hex) under ``name``::
$ botan psk_set psk.db deadba55 bunny f00fee
``psk_get db db_key name``
Get back a value saved with ``psk_set``::
$ botan psk_get psk.db deadba55 bunny
f00fee
``psk_list db db_key``
List all values saved to the database under the given key::
$ botan psk_list psk.db deadba55
bunny
Secret Sharing
------------------
Split a file into several shares.
``tss_split M N data_file --id= --share-prefix=share --share-suffix=tss --hash=SHA-256``
Split a file into ``N`` pieces any ``M`` of which suffices to
recover the original input. The ID allows specifying a unique key ID
which may be up to 16 bytes long, this ensures that shares can be
uniquely matched. If not specified a random 16 byte value is
used. A checksum can be appended to the data to help verify correct
recovery, this can be disabled using ``--hash=None``.
``tss_recover *shares``
Recover some data split by ``tss_split``. If insufficient number of
shares are provided an error is printed.
Data Encoding/Decoding
------------------------
``base32_dec file``
Decode *file* to Base32.
``base32_enc file``
Encode Base32 encoded *file*.
``base58_enc --check file``
Encode *file* to Base58. If ``--check`` is provided Base58Check is used.
``base58_dec --check file``
Decode Base58 encoded *file*. If ``--check`` is provided Base58Check is used.
``base64_dec file``
Decode *file* to Base64.
``base64_enc file``
Encode Base64 encoded *file*.
``hex_dec file``
Decode *file* to Hex.
``hex_enc file``
Encode Hex encoded *file*.
Forward Error Correction
------------------------
``fec_encode --suffix=fec --prefix= --output-dir= k n input``
Split a given ``input`` file into ``n`` shares where ``k`` shares are required
to recreate the original file. The output shares a written to files with the
file extension specified in ``--suffix`` and either the original file name or
the one specified in ``--prefix``. The output directory is either equal to the
input file's directory or the one specified in ``--output-dir``.
``fec_decode *shares``
If given enough shares, this will output the original input file's content to
stdout. Otherwise an error is printed on stderr.
``fec_info share``
Given a single share this will print information about the share.
For instance: ``FEC share 4/4 with 3 needed for recovery``
Miscellaneous Commands
-------------------------------------
``version --full``
Print the version number. If option ``--full`` is provided,
additional details are printed.
``has_command cmd``
Test if the command *cmd* is available.
``config info_type``
Prints build information, useful for applications which want to
build against the library. The ``info_type`` argument can be any of
``prefix``, ``cflags``, ``ldflags``, or ``libs``. This is
similar to information provided by the ``pkg-config`` tool.
``cpuid``
List available processor flags (AES-NI, SIMD extensions, ...).
``cpu_clock --test-duration=500``
Estimate the speed of the CPU cycle counter.
``asn1print --skip-context-specific --print-limit=4096 --bin-limit=2048 --max-depth=64 --pem file```
Decode and print *file* with ASN.1 Basic Encoding Rules (BER). If flag ``--pem`` is
used, or the filename ends in ``.pem``, then PEM encoding is assumed. Otherwise
the input is assumed to be binary DER/BER.
``http_get --redirects=1 --timeout=3000 url``
Retrieve resource from the passed http *url*.
``speed --msec=500 --format=default --ecc-groups= --provider= --buf-size=1024 --clear-cpuid= --cpu-clock-speed=0 --cpu-clock-ratio=1.0 *algos``
Measures the speed of the passed *algos*. If no *algos* are passed all
available speed tests are executed. *msec* (in milliseconds) sets the period
of measurement for each algorithm. The *buf-size* option allows testing the
same algorithm on one or more input sizes, for example
``speed --buf-size=136,1500 AES-128/GCM`` tests the performance of GCM for
small and large packet sizes.
*format* can be "default", "table" or "json".
``timing_test test_type --test-data-file= --test-data-dir=src/tests/data/timing --warmup-runs=1000 --measurement-runs=10000``
Run various timing side channel tests.
``rng --format=hex --system --rdrand --auto --entropy --drbg --drbg-seed= *bytes``
Sample *bytes* random bytes from the specified random number generator. If
*system* is set, the system RNG is used. If *rdrand* is set, the hardware
RDRAND instruction is used. If *auto* is set, AutoSeeded_RNG is used, seeded
with the system RNG if available or the global entropy source otherwise. If
*entropy* is set, AutoSeeded_RNG is used, seeded with the global entropy
source. If *drbg* is set, HMAC_DRBG is used seeded with *drbg-seed*.
``entropy --truncate-at=128 source``
Sample a raw entropy source.
``cc_encrypt CC passphrase --tweak=``
Encrypt the passed valid credit card number *CC* using FPE encryption and the
passphrase *passphrase*. The key is derived from the passphrase using PBKDF2
with SHA256. Due to the nature of FPE, the ciphertext is also a credit card
number with a valid checksum. *tweak* is public and parameterizes the
encryption function.
``cc_decrypt CC passphrase --tweak=``
Decrypt the passed valid ciphertext *CC* using FPE decryption with
the passphrase *passphrase* and the tweak *tweak*.
``roughtime_check --raw-time chain-file``
Parse and validate a Roughtime chain file.
``roughtime --raw-time --chain-file=roughtime-chain --max-chain-size=128 --check-local-clock=60 --host= --pubkey= --servers-file=``
Retrieve time from a Roughtime server and store it in a chain file.
``uuid``
Generate and print a random UUID.
``compress --type=gzip --level=6 --buf-size=8192 file``
Compress a given file.
``decompress --buf-size=8192 file``
Decompress a given compressed archive.

View File

@ -1,27 +0,0 @@
Contents
========================================
.. toctree::
index
goals
support
building
sem_ver
migration_guide
api_ref/contents
cli
deprecated
roadmap
credits
abi
packaging
security
side_channels
dev_ref/contents
.. toctree::
:hidden:
old_news

View File

@ -1,179 +0,0 @@
Credits
========================================
This is at least a partial credits-file of people that have contributed
to botan. It is sorted by name and formatted to allow easy grepping
and beautification by scripts. The fields are name (N), email (E),
web-address (W), PGP key ID and fingerprint (P), description (D),
snail-mail address (S), and Bitcoin address (B).
.. highlight:: none
::
N: Alexander Bluhm
W: https://www.genua.de/
P: 1E3B BEA4 6C20 EA00 2FFC DE4D C5F4 83AD DEE8 6380
D: improve support for OpenBSD
S: Kirchheim, Germany
N: Charles Brockman
W: http://www.securitygenetics.com/
D: documentation editing
S: Oregon, USA
N: Simon Cogliani
E: simon.cogliani@tanker.io
W: https://www.tanker.io/
P: EA73 D0AF 5A81 A61A 8931 C2CA C9AB F2E4 3820 4F25
D: Getting keystream of ChaCha
S: Paris, France
N: Martin Doering
E: doering@cdc.informatik.tu-darmstadt.de
D: GF(p) arithmetic
N: Olivier de Gaalon
D: SQLite encryption codec (src/contrib/sqlite)
N: Matthias Gierlings
E: matthias.gierlings@hackmanit.de
W: https://www.hackmanit.de/
P: 39E0 D270 19A4 B356 05D0 29AE 1BD3 49CF 744A 02FF
D: GMAC, Extended Hash-Based Signatures (XMSS)
S: Bochum, Germany
N: Matthew Gregan
D: Binary file I/O support, allocator fixes
N: Hany Greiss
D: Windows porting
N: Manuel Hartl
E: hartl@flexsecure.de
W: http://www.flexsecure.de/
D: ECDSA, ECDH
N: Yves Jerschow
E: yves.jerschow@uni-duesseldorf.de
D: Optimizations for memory load/store and HMAC
D: Support for IPv4 addresses in X.509 alternative names
S: Germany
N: Matt Johnston
D: Allocator fixes and optimizations, decompressor fixes
N: Peter J. Jones
E: pjones@pmade.org
D: Bzip2 compression module
S: Colorado, USA
N: Justin Karneges
D: Qt support modules (mutexes and types), X.509 API design
N: Vojtech Kral
E: vojtech@kral.hk
D: LZMA compression module
S: Czech Republic
N: Matej Kenda
E: matej.kenda@topit.si
D: Locking in Algo_Registry for Windows OS
S: Slovenia
N: René Fischer (formerly Korthaus)
E: rene.fischer@rohde-schwarz.com
W: https://www.rohde-schwarz.com/cybersecurity
P: C196 FF9D 3DDC A5E7 F98C E745 9AD0 F9FA 587E 74D6
D: CI, ECGDSA, ECKCDSA
S: Bochum, Germany
N: Adam Langley
E: agl@imperialviolet.org
D: Curve25519
N: Jack Lloyd
E: jack@randombit.net
W: https://www.randombit.net/
P: 3F69 2E64 6D92 3BBE E7AE 9258 5C0F 96E8 4EC1 6D6B
B: 1DwxWb2J4vuX4vjsbzaCXW696rZfeamahz
D: Original designer/author, maintainer 2001-current
S: Vermont, USA
N: Joel Low
D: DLL symbol visibility and Windows DLL support in general
D: Threaded_Fork
N: Christoph Ludwig
E: ludwig@fh-worms.de
D: GP(p) arithmetic
N: Vaclav Ovsik
E: vaclav.ovsik@i.cz
D: Perl XS module (src/contrib/perl-xs)
N: Luca Piccarreta
E: luca.piccarreta@gmail.com
D: x86/amd64 assembler, BigInt optimizations, Win32 mutex module
S: Italy
N: Daniel Seither
E: post@tiwoc.de
D: iOS support, improved Android support, improved MSVC support
N: Falko Strenzke
E: fstrenzke@cryptosource.de
W: http://www.cryptosource.de
D: McEliece, GF(p) arithmetic, CVC, Shanks-Tonelli algorithm
S: Darmstadt, Germany
N: Simon Warta
E: simon@kullo.net
W: https://www.kullo.net
D: Build system
S: Germany
N: Philipp Weber
E: philipp.weber@rohde-schwarz.com
W: https://www.rohde-schwarz.com/cybersecurity
D: KDF1-18033, ECIES
S: Saarland, Germany
N: Daniel Neus
E: daniel.neus@rohde-schwarz.com
W: https://www.rohde-schwarz.com/cybersecurity
D: CI, PKCS#11, RdSeed, BSI module policy
S: Bochum, Germany
N: Erwan Chaussy
D: Base32, Base64 matching Base32 implementation
S: France
N: Daniel Wyatt (on behalf of Ribose Inc)
E: daniel.wyatt@ribose.com
W: https://www.ribose.com/
D: SM3, Streebog, various minor contributions
N: Rostyslav Khudolii
E: rhudoliy@gmail.com
D: SRP6 FFI
S: Ukraine/Denmark
N: René Meusel
E: rene.meusel@rohde-schwarz.com
W: https://www.rohde-schwarz.com/cybersecurity
D: CI, TLS 1.3, Kyber, Dilithium, SPHINCS+
S: Berlin, Germany
N: Philippe Lieser
E: philippe.lieser@rohde-schwarz.com
W: https://www.rohde-schwarz.com/cybersecurity
D: CI, BSI module policy, various minor contributions
S: Saarland, Germany
N: Fabian Albert
E: fabian.albert@rohde-schwarz.com
W: https://www.rohde-schwarz.com/cybersecurity
D: SPHINCS+
S: Bochum, Germany

View File

@ -1,134 +0,0 @@
Deprecated Features
========================
Certain functionality is deprecated and is likely to be removed in
a future major release.
To help warn users, macros are used to annotate deprecated functions
and headers. These warnings are enabled by default, but can be
disabled by defining the macro ``BOTAN_NO_DEPRECATED_WARNINGS`` prior
to including any Botan headers.
.. warning::
Not all of the functionality which is currently deprecated has an
associated warning.
If you are using something which is currently deprecated and there
doesn't seem to be an obvious alternative, contact the developers to
explain your use case if you want to make sure your code continues to
work.
Platform Support Deprecations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* Support for building for Windows systems prior to Windows 10 is deprecated.
TLS Protocol Deprecations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following TLS protocol features are deprecated and will be removed
in a future major release:
- Support for point compression in TLS. This is supported in v1.2 but
removed in v1.3. For simplicity it will be removed in v1.2 also.
- All CBC mode ciphersuites. This includes all available 3DES ciphersuites.
This implies also removing Encrypt-then-MAC extension.
- All DHE ciphersuites
- Support for renegotiation in TLS v1.2
- All ciphersuites using static RSA key exchange
- ``Credentials_Manager::psk()`` to provide various TLS-specific keys and
secrets, most notably "session-ticket", "dtls-cookie-secret" and the actual
TLS PSKs for given identities and hosts. Instead, use the dedicated methods in
``Credentials_Manager`` and do not override the ``psk()`` method any longer.
Deprecated Functionality
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This section lists cryptographic functionality which will be removed
in a future major release.
- Kyber 90s mode is deprecated and will be removed.
- Currently it is possible to create an EC_Group with cofactor > 1.
None of the builtin groups have composite order, and in the future
it will be impossible to create composite order EC_Groups.
- Prior to 2.8.0, SM2 algorithms were implemented as two distinct key
types, one used for encryption and the other for signatures. In 2.8,
the two types were merged. However it is still possible to refer to
SM2 using the split names of "SM2_Enc" or "SM2_Sig". In a future major
release this will be removed, and only "SM2" will be recognized.
- DSA, ECDSA, ECGDSA, ECKCDSA, and GOST-34.10 previously (before Botan 3)
required that the hash be named as "EMSA1(HASH_NAME)". This is no longer
required. In a future major release, only "HASH_NAME" will be accepted.
- Block cipher GOST 28147, Noekeon, Lion
- Hash function GOST 34.11-94, Streebog, MD4
- GOST 34.10 signature scheme
- Stream cipher SHAKE (this does not affect SHAKE used as a HashFunction or XOF)
- The utility functions in cryptobox.h
- X9.42 KDF
- The current McEliece implementation (in ``pubkey/mce``) will be
replaced by a more modern code-based KEM from the NIST
competition. (Probably the "Classic McEliece" submission.)
- DLIES
- GCM support for 64-bit tags
- Weak or rarely used ECC builtin groups including "secp160k1", "secp160r1",
"secp160r2", "secp192k1", "secp224k1",
"brainpool160r1", "brainpool192r1", "brainpool224r1", "brainpool320r1",
"x962_p192v2", "x962_p192v3", "x962_p239v1", "x962_p239v2", "x962_p239v3".
- All built in MODP groups < 2048 bits
- Support for explicit ECC curve parameters and ImplicitCA encoded parameters in
EC_Group and all users (including X.509 certificates and PKCS#8 private keys).
- All pre-created DSA groups
- All support for loading, generating or using RSA keys with a public
exponent larger than 2**64-1
Deprecated Headers
^^^^^^^^^^^^^^^^^^^^^^
PBKDF headers: ``bcrypt_pbkdf.h``, ``pbkdf2.h``, ``pgp_s2k.h``, ``scrypt.h``,
and ``argon2.h``: Use the ``PasswordHash`` interface instead.
Internal implementation headers - seemingly no reason for applications to use:
``curve_gfp.h``,
``reducer.h``,
``tls_algos.h``,
``tls_magic.h``
Utility headers, nominally useful in applications but not a core part of
the library API and most are just sufficient for what the library needs
to implement other functionality.
``compiler.h``,
``uuid.h``,
Other API deprecations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The ``PBKDF`` class is deprecated in favor of ``PasswordHash`` and
``PasswordHashFamily``.
- The ``Buffered_Computation`` base class. In a future release the
class will be removed, and all of member functions instead declared
directly on ``MessageAuthenticationCode`` and ``HashFunction``. So
this only affects you if you are directly referencing
``Botan::Buffered_Computation`` in some way.

View File

@ -1,440 +0,0 @@
.. _configure_script:
Understanding configure.py
============================
.. highlight:: none
Botan's build is handled with a custom Python script, ``configure.py``.
This document tries to explain how configure works.
.. note::
You only need to read this if you are modifying the library,
or debugging some problem with your build. For how to use it,
see :ref:`building`.
Build Structure
--------------------
Modules are a group of related source and header files, which can be
individually enabled or disabled at build time. Modules can depend on
other modules; if a dependency is not available then the module itself
is also removed from the list. Examples of modules in the existing
codebase are ``asn1`` and ``x509``, Since ``x509`` depends on (among
other things) ``asn1``, disabling ``asn1`` will also disable ``x509``.
Most modules define one or more macros, which application code can use
to detect the modules presence or absence. The value of each macro is
a datestamp, in the form YYYYMMDD which indicates the last time this
module changed in a way that would be visible to an application. For
example if a class gains a new function, the datestamp should be
incremented. That allows applications to detect if the new feature is
available.
What ``configure.py`` does
-----------------------------
First, all command line options are parsed.
Then all of the files giving information about target CPUs, compilers,
etc are parsed and sanity checked.
In ``calculate_cc_min_version`` the compiler version is detected using
the preprocessor.
Then in ``check_compiler_arch`` the target architecture are detected, again
using the preprocessor.
Now that the target is identified and options have been parsed, the modules to
include into the artifact are picked, in ``ModulesChooser``.
In ``create_template_vars``, a dictionary of variables is created which describe
different aspects of the build. These are serialized to
``build/build_config.json``.
Up until this point no changes have been made on disk. This occurs in
``do_io_for_build``. Build output directories are created, and header files are
linked into ``build/include/botan``. Templates are processed to create the
Makefile, ``build.h`` and other artifacts.
When Modifying ``configure.py``
--------------------------------
Run ``./src/scripts/ci_build.py lint`` to run Pylint checks after any change.
Template Language
--------------------
Various output files are generated by processing input files using a simple
template language. All input files are stored in ``src/build-data`` and use the
suffix ``.in``. Anything not recognized as a template command is passed through
to the output unmodified. The template elements are:
* Variable substitution, ``%{variable_name}``. The configure script creates
many variables for various purposes, this allows getting their value within
the output. If a variable is not defined, an error occurs.
If a variable reference ends with ``|upper``, the value is uppercased before
being inserted into the template output.
* Iteration, ``%{for variable} block %{endfor}``. This iterates over a list and
repeats the block as many times as it is included. Variables within the block
are expanded. The two template elements ``%{for ...}`` and ``%{endfor}`` must
appear on lines with no text before or after.
* Conditional inclusion, ``%{if variable} block %{endif}``. If the variable
named is defined and true (in the Python sense of the word; if the variable
is empty or zero it is considered false), then the block will be included and
any variables expanded. As with the for loop syntax, both the start and end
of the conditional must be on their own lines with no additional text.
Build.h
-------
The ``build.h`` header file is generated and overwritten each time the
``configure.py`` script is executed. This header can be included in any header
or source file and provides plenty of compile-time information in the form of
preprocessor ``#define``\ s.
It is helpful to check which modules are included in the current build of the
library via macro defines of the form "BOTAN_HAS" followed by the module name.
Also, it contains :ref:`version information macros <versioning>` and compile-time
library configurations.
Adding a new module
--------------------
Create a directory in the appropriate place and create a ``info.txt`` file.
Syntax of ``info.txt``
------------------------
.. warning::
The syntax described here is documented to make it easier to use
and understand, but it is not considered part of the public API
contract. That is, the developers are allowed to change the syntax
at any time on the assumption that all users are contained within
the library itself. If that happens this document will be updated.
Modules and files describing information about the system use the same
parser and have common syntactical elements.
Comments begin with '#' and continue to end of line.
There are three main types: maps, lists, and variables.
A map has a syntax like::
<MAP_NAME>
NAME1 -> VALUE1
NAME2 -> VALUE2
...
</MAP_NAME>
The interpretation of the names and values will depend on the map's name
and what type of file is being parsed.
A list has similar syntax, it just doesn't have values::
<LIST_NAME>
ELEM1
ELEM2
...
</LIST_NAME>
Lastly there are single value variables like::
VAR1 SomeValue
VAR2 "Quotes Can Be Used (And will be stripped out)"
VAR3 42
Variables can have string, integer or boolean values. Boolean values
are specified with 'yes' or 'no'.
Module Syntax
---------------------
The ``info.txt`` files have the following elements. Not all are required; a minimal
file for a module with no dependencies might just contain a macro define and module_info.
Lists:
* ``comment`` and ``warning`` provides block-comments which
are displayed to the user at build time.
* ``requires`` is a list of module dependencies. An ``os_features`` can be
specified as a condition for needing the dependency by writing it before
the module name and separated by a ``?``, e.g. ``rtlgenrandom?dyn_load``.
* ``header:internal`` is the list of headers (from the current module)
which are internal-only.
* ``header:public`` is a the list of headers (from the
current module) which should be exported for public use. If neither
``header:internal`` nor ``header:public`` are used then all headers
in the current directory are assumed internal.
.. note:: If you omit a header from both internal and public lists, it will
be ignored.
* ``header:external`` is used when naming headers which are included
in the source tree but might be replaced by an external version. This is used
for the PKCS11 headers.
* ``arch`` is a list of architectures this module may be used on.
* ``isa`` lists ISA features which must be enabled to use this module.
Can be proceeded by an ``arch`` name followed by a ``:`` if it is only needed
on a specific architecture, e.g. ``x86_64:ssse3``.
* ``cc`` is a list of compilers which can be used with this module. If the
compiler name is suffixed with a version (like "gcc:5.0") then only compilers
with that minimum version can use the module. If you need to exclude just
one specific compiler (for example because that compiler miscompiles the code
in the module), you can prefix a compiler name with ``!`` - like ``!msvc``.
* ``os_features`` is a list of OS features which are required in order to use this
module. Each line can specify one or more features combined with ','. Alternatives
can be specified on additional lines.
Maps:
* ``defines`` is a map from macros to datestamps. These macros will be defined in
the generated ``build.h``.
* ``module_info`` contains documentation-friendly information about the module.
Available mappings:
* ``name`` must contain a human-understandable name for the module
* ``brief`` may provide a short description about the module's contents
* ``type`` specifies the type of the module (defaults to ``Public``)
* ``Public`` Library users can directly interact with this module. E.g.
they may enable or disable the module at will during build.
* ``Internal`` Library users must not directly interact with this module.
It is enabled and used as required by other modules.
* ``Virtual`` This module does not contain any implementation but acts as
a container for other sub-modules. It cannot be interacted with by the
library user and cannot be depended upon directly.
* ``libs`` specifies additional libraries which should be linked if this module is
included. It maps from the OS name to a list of libraries (comma seperated).
* ``frameworks`` is a macOS/iOS specific feature which maps from an OS name to
a framework.
Variables:
* ``load_on`` Can take on values ``never``, ``always``, ``auto``, ``dep`` or ``vendor``.
TODO describe the behavior of these
* ``endian`` Required endian for the module (``any`` (default), ``little``, ``big``)
An example::
# Disable this by default
load_on never
<isa>
sse2
</isa>
<defines>
DEFINE1 -> 20180104
DEFINE2 -> 20190301
</defines>
<module_info>
name -> "This Is Just To Say"
brief -> "Contains a poem by William Carlos Williams"
</module_info>
<comment>
I have eaten
the plums
that were in
the icebox
</comment>
<warning>
There are no more plums
</warning>
<header:public>
header1.h
</header:public>
<header:internal>
header_helper.h
whatever.h
</header:internal>
<arch>
x86_64
</arch>
<cc>
gcc:4.9 # gcc 4.8 doesn't work for <reasons>
clang
</cc>
# Can work with POSIX+getentropy or Win32
<os_features>
posix1,getentropy
win32
</os_features>
<frameworks>
macos -> FramyMcFramerson
</frameworks>
<libs>
qnx -> foo,bar,baz
solaris -> socket
</libs>
Supporting a new CPU type
---------------------------
CPU information is stored in ``src/build-data/arch``.
There is also a file ``src/build-data/detect_arch.cpp`` which is used
for build-time architecture detection using the compiler preprocessor.
Supporting this is optional but recommended.
Lists:
* ``aliases`` is a list of alternative names for the CPU architecture.
* ``isa_extensions`` is a list of possible ISA extensions that can be used on
this architecture. For example x86-64 has extensions "sse2", "ssse3",
"avx2", "aesni", ...
Variables:
* ``endian`` if defined should be "little" or "big". This can also be
controlled or overridden at build time.
* ``family`` can specify a family group for several related architecture.
For example both x86_32 and x86_64 use ``family`` of "x86".
* ``wordsize`` is the default wordsize, which controls the size of limbs
in the multi precision integers. If not set, defaults to 32.
Supporting a new compiler
---------------------------
Compiler information is stored in ``src/build-data/cc``. Looking over
those files will probably help understanding, especially the ones for
GCC and Clang which are most complete.
In addition to the info file, for compilers there is a file
``src/build-data/detect_version.cpp``. The ``configure.py`` script runs the
preprocessor over this file to attempt to detect the compiler
version. Supporting this is not strictly necessary.
Maps:
* ``binary_link_commands`` gives the command to use to run the linker,
it maps from operating system name to the command to use. It uses
the entry "default" for any OS not otherwise listed.
* ``cpu_flags_no_debug`` unused, will be removed
* ``cpu_flags`` used to emit CPU specific flags, for example LLVM
bitcode target uses ``-emit-llvm`` flag. Rarely needed.
* ``isa_flags`` maps from CPU extensions (like NEON or AES-NI) to
compiler flags which enable that extension. These have the same name
as the ISA flags listed in the architecture files.
* ``lib_flags`` has a single possible entry "debug" which if set maps
to additional flags to pass when building a debug library.
Rarely needed.
* ``mach_abi_linking`` specifies flags to enable when building and
linking on a particular CPU. This is usually flags that modify
ABI. There is a special syntax supported here
"all!os1,arch1,os2,arch2" which allows setting ABI flags which are
used for all but the named operating systems and/or architectures.
* ``sanitizers`` is a map of sanitizers the compiler supports. It must
include "default" which is a list of sanitizers to include by default
when sanitizers are requested. The other keys should map to compiler
flags.
* ``so_link_commands`` maps from operating system to the command to
use to build a shared object.
Variables:
* ``binary_name`` the default name of the compiler binary.
* ``linker_name`` the name of the linker to use with this compiler.
* ``macro_name`` a macro of the for ``BOTAN_BUILD_COMPILER_IS_XXX``
will be defined.
* ``output_to_object`` (default "-o") gives the compiler option used to
name the output object.
* ``output_to_exe`` (default "-o") gives the compiler option used to
name the output object.
* ``add_include_dir_option`` (default "-I") gives the compiler option used
to specify an additional include dir.
* ``add_lib_dir_option`` (default "-L") gives the compiler option used
to specify an additional library dir.
* ``add_sysroot_option`` gives the compiler option used to specify the sysroot.
* ``add_lib_option`` (default "-l%s") gives the compiler option to
link in a library. ``%s`` will be replaced with the library name.
* ``add_framework_option`` (default "-framework") gives the compiler option
to add a macOS framework.
* ``preproc_flags`` (default "-E") gives the compiler option used to run
the preprocessor.
* ``compile_flags`` (default "-c") gives the compiler option used to compile a file.
* ``debug_info_flags`` (default "-g") gives the compiler option used to enable debug info.
* ``optimization_flags`` gives the compiler optimization flags to use.
* ``size_optimization_flags`` gives compiler optimization flags to use when
compiling for size. If not set then ``--optimize-for-size`` will use
the default optimization flags.
* ``sanitizer_optimization_flags`` gives compiler optimization flags to use
when building with sanitizers.
* ``coverage_flags`` gives the compiler flags to use when generating coverage
information.
* ``stack_protector_flags`` gives compiler flags to enable stack overflow checking.
* ``shared_flags`` gives compiler flags to use when generation shared libraries.
* ``lang_flags`` gives compiler flags used to enable the required version of C++.
* ``lang_binary_linker_flags`` gives flags to be passed to the linker when creating a binary
* ``warning_flags`` gives warning flags to enable.
* ``maintainer_warning_flags`` gives extra warning flags to enable during maintainer
mode builds.
* ``visibility_build_flags`` gives compiler flags to control symbol visibility
when generation shared libraries.
* ``visibility_attribute`` gives the attribute to use in the ``BOTAN_DLL`` macro
to specify visibility when generation shared libraries.
* ``ar_command`` gives the command to build static libraries
* ``ar_options`` gives the options to pass to ``ar_command``, if not set here
takes this from the OS specific information.
* ``ar_output_to`` gives the flag to pass to ``ar_command`` to specify where to
output the static library.
* ``werror_flags`` gives the complier flags to treat warnings as errors.
Supporting a new OS
---------------------------
Operating system information is stored in ``src/build-data/os``.
Lists:
* ``aliases`` is a list of alternative names which will be accepted
* ``target_features`` is a list of target specific OS features. Some of these
are supported by many OSes (for example "posix1") others are specific to
just one or two OSes (such as "getauxval"). Adding a value here causes a new
macro ``BOTAN_TARGET_OS_HAS_XXX`` to be defined at build time. Use
``configure.py --list-os-features`` to list the currently defined OS
features.
* ``feature_macros`` is a list of macros to define.
Variables:
* ``ar_command`` gives the command to build static libraries
* ``ar_options`` gives the options to pass to ``ar_command``
* ``ar_output_to`` gives the flag to pass to ``ar_command`` to specify where to
output the static library.
* ``bin_dir`` (default "bin") specifies where binaries should be installed,
relative to install_root.
* ``cli_exe_name`` (default "botan") specifies the name of the command line utility.
* ``default_compiler`` specifies the default compiler to use for this OS.
* ``doc_dir`` (default "doc") specifies where documentation should be installed,
relative to install_root
* ``header_dir`` (default "include") specifies where include files
should be installed, relative to install_root
* ``install_root`` (default "/usr/local") specifies where to install
by default.
* ``lib_dir`` (default "lib") specifies where library should be installed,
relative to install_root.
* ``lib_prefix`` (default "lib") prefix to add to the library name
* ``library_name``
* ``man_dir`` specifies where man files should be installed, relative to install_root
* ``obj_suffix`` (default "o") specifies the suffix used for object files
* ``program_suffix`` (default "") specifies the suffix used for executables
* ``shared_lib_symlinks`` (default "yes) specifies if symbolic names should be
created from the base and patch soname to the library name.
* ``soname_pattern_abi``
* ``soname_pattern_base``
* ``soname_pattern_patch``
* ``soname_suffix`` file extension to use for shared library if ``soname_pattern_base``
is not specified.
* ``static_suffix`` (default "a") file extension to use for static library.
* ``use_stack_protector`` (default "true") specify if by default stack smashing
protections should be enabled.
* ``uses_pkg_config`` (default "yes") specify if by default a pkg-config file
should be created.

View File

@ -1,20 +0,0 @@
Developer Reference
=====================
This section contains information useful to people making
contributions to the library
.. toctree::
:maxdepth: 1
contributing
configure
test_framework
continuous_integration
fuzzing
release_process
todo
os
oids
reading_list
mistakes

View File

@ -1,52 +0,0 @@
Continuous Integration and Automated Testing
===============================================
CI Build Script
----------------
The Github Actions builds are orchestrated using a script
``src/scripts/ci_build.py``. This allows one to easily reproduce the CI process
on a local machine.
Github Actions
---------------
https://github.com/randombit/botan/actions/workflows/ci.yml
Github Actions is the primary CI, and tests the Linux, Windows, macOS, and iOS
builds. Among other things it runs tests using valgrind, cross-compilation
for various architectures (currently including ARM and PPC64), MinGW build,
and a build that produces the coverage report.
The Github Actions configuration is in ``.github/workflows/ci.yml`` which
executes platform dependent setup scripts ``src/scripts/ci/setup_gh_actions.sh``
or ``src/scripts/ci/setup_gh_actions.ps1`` and ``.../setup_gh_actions_after_vcvars.ps1``
to install needed packages and detect certain platform specifics like compiler
cache locations.
Then ``src/scripts/ci_build.py`` is invoked to steer the actual build and test
runs.
Github Actions (nightly)
-------------------------
https://github.com/randombit/botan/actions/workflows/nightly.yml
Some checks are just too slow to include in the main CI builds. These
are instead delegated to a scheduled job that runs every night against
master.
Currently these checks include a full run of ``valgrind`` (the valgrind build in
CI only runs a subset of the tests), and a run of ``clang-tidy`` with all
warnings (that we are currently clean for) enabled. Each of these jobs takes
about an hour to run. In the main CI, we aim to have no job take more than
half an hour.
OSS-Fuzz
----------
https://github.com/google/oss-fuzz/
OSS-Fuzz is a distributed fuzzer run by Google. Every night, the fuzzer harnesses
in ``src/fuzzer`` are built and run on many machines, with any findings reported
to the developers via email.

View File

@ -1,299 +0,0 @@
Notes for New Contributors
===================================
Source Code Layout
-------------------------------------------------
Under ``src`` there are directories
* ``lib`` is the library itself, more on that below
* ``cli`` is the command line application ``botan``
* ``tests`` contain what you would expect. Input files go under ``tests/data``.
* ``python/botan3.py`` is the Python ctypes wrapper
* ``bogo_shim`` contains the shim binary and configuration for
`BoringSSL's TLS test suite <https://github.com/google/boringssl/tree/master/ssl/test>`_
* ``fuzzer`` contains fuzz targets for various modules of the library
* ``build-data`` contains files read by the configure script. For
example ``build-data/cc/gcc.txt`` describes various gcc options.
* ``examples`` contains usage examples used in the documentation.
* ``scripts`` contains misc scripts: install, distribution, various
codegen things. Scripts controlling CI go under ``scripts/ci``.
* ``configs`` contains configuration files tools like pylint
* ``editors`` contains configuration files for editors like vscode and emacs
Under ``doc`` one finds the sources of this documentation
Library Layout
----------------------------------------
Under ``src/lib`` are several directories
* ``asn1`` is the DER encoder/decoder
* ``base`` defines some high level types
* ``block`` contains the block cipher implementations
* ``codec`` has hex, base64, base32, base58
* ``compat`` a (partial) compatibility layer for the libsodium API
* ``compression`` has the compression wrappers (zlib, bzip2, lzma)
* ``entropy`` has various entropy sources used by some of the RNGs
* ``ffi`` is the C99 API
* ``filters`` is a filter/pipe API for data transforms
* ``hash`` contains the hash function implementations
* ``kdf`` contains the key derivation functions
* ``mac`` contains the message authentication codes
* ``math`` is the big integer math library. It is divided into three parts:
``mp`` which are the low level algorithms; ``bigint`` which is a C++ wrapper
around ``mp``, and ``numbertheory`` which contains higher level algorithms like
primality testing and exponentiation
* ``misc`` contains odds and ends: format preserving encryption, SRP, threshold
secret sharing, all or nothing transform, and others
* ``modes`` contains block cipher modes (CBC, GCM, etc)
* ``passhash`` contains password hashing algorithms for authentication
* ``pbkdf`` contains password hashing algorithms for key derivation
* ``pk_pad`` contains padding schemes for public key algorithms
* ``prov`` contains bindings to external libraries such as PKCS #11
* ``psk_db`` contains a generic interface for a Pre-Shared-Key database
* ``pubkey`` contains the public key algorithms
* ``rng`` contains the random number generators
* ``stream`` contains the stream ciphers
* ``tls`` contains the TLS implementation
* ``utils`` contains various utility functions and types
* ``x509`` is X.509 certificates, PKCS #10 requests, OCSP
Each of these folders can contain subfolders which are treated as modules if they
contain an ``info.txt`` file. These submodules have an implicit dependency on their
parent module. The chapter :ref:`configure_script` contains more information on
Botan's module architecture.
Sending patches
----------------------------------------
All contributions should be submitted as pull requests via GitHub
(https://github.com/randombit/botan). If you are planning a large
change, open a discussion ticket on github before starting out to make
sure you are on the right path. And once you have something written,
even if it is not complete/ready to go, feel free to open a draft PR
for early review and comment.
If possible please sign your git commits using a PGP key.
See https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work for
instructions on how to set this up.
Depending on what your change is, your PR should probably also include an update
to ``news.rst`` with a note explaining the change. If your change is a
simple bug fix, a one sentence description is perhaps sufficient. If there is an
existing ticket on GitHub with discussion or other information, reference it in
your change note as 'GH #000'.
Update ``doc/credits.txt`` with your information so people know what you did!
If you are interested in contributing but don't know where to start check out
``doc/dev_ref/todo.rst`` for some ideas - these are changes we would almost
certainly accept once they've passed code review.
Also, try building and testing it on whatever hardware you have handy,
especially unusual platforms, or using C++ compilers other than the regularly
tested GCC, Clang, and Visual Studio.
FFI Additions
----------------
If adding a new function declaration to ``ffi.h``, the same PR must also add the
same declaration in the Python binding ``botan3.py``, in addition the new API
functionality must be exposed to Python and a test written in Python.
Git Usage
----------------------------------------
Do *NOT* merge ``master`` into your topic branch, this creates needless commits
and noise in history. Instead, as needed, rebase your branch against master
(``git rebase -i master``) and force push the branch to update the PR. If the
GitHub PR page does not report any merge conflicts and nobody asks you to
rebase, you don't need to rebase.
Try to keep your history clean and use rebase to squash your commits as
needed. If your diff is less than roughly 100 lines, it should probably be a
single commit. Only split commits as needed to help with review/understanding of
the change.
Python
----------------------------------------
Scripts should be in Python 3 whenever possible.
For configure.py (and helper scripts install.py, cleanup.py and build_docs.py)
the target is stock (no modules outside the standard library) CPython 3.x.
Support for PyPy, etc is great when viable (in the sense of not causing problems
for 3.x, and not requiring huge blocks of version dependent code). As running
this program successfully is required for a working build, making it as portable
as possible is considered key.
The python wrapper botan3.py targets CPython 3.x, and latest PyPy. Note that
a single file is used to avoid dealing with any of Python's various crazy module
distribution issues.
For random scripts not typically run by an end-user (codegen, visualization, and
so on) there isn't any need to worry about platform independence. Here it's fine
to depend on any useful modules such as graphviz or matplotlib, regardless if it
is available from a stock CPython install.
Build Tools and Hints
----------------------------------------
If you don't already use it for all your C/C++ development, install ``ccache``
(or on Windows, ``sccache``) right now, and configure a large cache on a fast
disk. It allows for very quick rebuilds by caching the compiler output.
Use ``--enable-sanitizers=`` flag to enable various sanitizer checks. Supported
values including "address" and "undefined" for GCC and Clang. GCC also supports
"iterator" (checked iterators), and Clang supports "memory" (MSan) and
"coverage" (for fuzzing).
On Linux if you have the ``lcov`` and ``gcov`` tools installed, then running
``./src/scripts/ci_build.py coverage`` will produce a coverage enabled build,
run the tests, test the fuzzers against a corpus, and produce an HTML report
of total coverage. This coverage build requires the development headers for
zlib, bzip2, liblzma, TrouSerS (libtspi), and Sqlite3.
Copyright Notice
----------------------------------------
At the top of any new file add a comment with a copyright and a reference to the
license, for example::
/*
* (C) 202x <You>
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
If you are making a substantial or non-trivial change to an existing file, add
or update your own copyright statement at the top of each file.
Style Conventions
----------------------------------------
When writing your code remember the need for it to be easily understood by
reviewers and auditors, both at the time of the patch submission and in the
future.
Avoid complicated template metaprogramming where possible. It has its places but
should be used judiciously.
When designing a new API (for use either by library users or just internally)
try writing out the calling code first. That is, write out some code calling
your idealized API, then just implement that API. This can often help avoid
cut-and-paste by creating the correct abstractions needed to solve the problem
at hand.
The C++11 ``auto`` keyword is very convenient but only use it when the type
truly is obvious (considering also the potential for unexpected integer
conversions and the like, such as an apparent uint8_t being promoted to an int).
Unless there is a specific reason otherwise (eg due to calling some C API which
requires exactly a ``long*`` be provided) integer types should be either
``(u)intXX_t`` or ``size_t``. If the variable is used for integer values of "no
particular size", as in the loop ``for(some_type i = 0; i != 100; ++i)`` then
the type should be ``size_t``. Use one of the specific size integer types only
when there is a algorithmic/protocol reason to use an integer of that size. For
example if a parsing a protocol that uses 16-bit integer fields to encode a
length, naturally one would use ``uint16_t`` there.
If a variable is defined and not modified, declare it ``const``. Some exception
for very short-lived variables, but generally speaking being able to read the
declaration and know it will not be modified is useful.
Use ``override`` annotations whenever overriding a virtual function. If
introducing a new type that is not intended for further derivation, mark it ``final``.
Avoid explicit ``new`` or (especially) explicit ``delete``: use RAII,
``make_unique``, etc.
Use ``m_`` prefix on all member variables.
``clang-format`` is used for all C++ formatting. The configuration is
in ``.clang-format`` in the root directory. You can rerun the
formatter using ``make fmt`` or by invoking the script
``src/scripts/dev_tools/run_clang_format.py``. If the output would be
truly horrible, it is allowed to disable formatting for a specific
area using ``// clang-format off`` annotations.
.. note::
Since the output of clang-format varies from version to version, we
currently require using exactly ``clang-format 15``.
Use braces on both sides of if/else blocks, even if only using a single
statement.
Avoid ``using namespace`` declarations, even inside of single functions. One
allowed exception is ``using namespace std::placeholders`` in functions which
use ``std::bind``. (But, don't use ``std::bind`` - use a lambda instead).
Use ``::`` to explicitly refer to the global namespace (eg, when calling an OS
or external library function like ``::select`` or ``::sqlite3_open``).
Use of External Dependencies
----------------------------------------
Compiler Dependencies
~~~~~~~~~~~~~~~~~~~~~~~
The library should always be as functional as possible when compiled with just
Standard C++20. However, feel free to use the full language.
Use of compiler extensions is fine whenever appropriate; this is typically
restricted to a single file or an internal header. Compiler extensions used
currently include native uint128_t, SIMD intrinsics, inline asm syntax and so
on, so there are some existing examples of appropriate use.
Generally intrinsics or inline asm is preferred over bare assembly to avoid
calling convention issues among different platforms; the improvement in
maintainability is seen as worth any potential performance tradeoff. One risk
with intrinsics is that the compiler might rewrite your clever const-time SIMD
into something with a conditional jump, but code intended to be const-time
should in any case be annotated (using ``CT::poison``) so it can be checked at
runtime with tools.
Operating System Dependencies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you're adding a small OS dependency in some larger piece of code, try to
contain the actual non-portable operations to utils/os_utils.* and then call
them from there.
As a policy, operating systems which are not supported by their original vendor
are not supported by Botan either. Patches that complicate the code in order to
support obsolete operating systems will likely be rejected. In writing OS
specific code, feel free to assume roughly POSIX 2008, or for Windows, Windows 8
/Server 2012 (which are as of this writing the oldest versions still supported
by Microsoft).
Some operating systems, such as OpenBSD, only support the latest release. For
such cases, it's acceptable to add code that requires APIs added in the most
recent release of that OS as soon as the release is available.
Library Dependencies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Any external library dependency - even optional ones - is met with as one PR
submitter put it "great skepticism".
At every API boundary there is potential for confusion that does not exist when
the call stack is all contained within the boundary. So the additional API
really needs to pull its weight. For example a simple text parser or such which
can be trivially implemented is not really for consideration. As a rough idea of
the bar, equate the viewed cost of an external dependency as at least 1000
additional lines of code in the library. That is, if the library really does
need this functionality, and it can be done in the library for less than that,
then it makes sense to just write the code. Yup.
Currently the (optional) external dependencies of the library are several
compression libraries (zlib, bzip2, lzma), sqlite3 database, Trousers (TPM
integration), plus various operating system utilities like basic filesystem
operations. These provide major pieces of functionality which seem worth the
trouble of maintaining an integration with.
At this point the most plausible examples of an appropriate new external
dependency are all deeper integrations with system level cryptographic
interfaces (CommonCrypto, CryptoAPI, /dev/crypto, iOS keychain, TPM 2.0, etc)

View File

@ -1,91 +0,0 @@
Fuzzing The Library
============================
Botan comes with a set of fuzzing endpoints which can be used to test
the library.
.. highlight:: shell
Fuzzing with libFuzzer
------------------------
To fuzz with libFuzzer (https://llvm.org/docs/LibFuzzer.html), you'll first
need to compile libFuzzer::
$ svn co https://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer libFuzzer
$ cd libFuzzer && clang -c -g -O2 -std=c++11 *.cpp
$ ar cr libFuzzer.a libFuzzer/*.o
Then build the fuzzers::
$ ./configure.py --cc=clang --build-fuzzer=libfuzzer --unsafe-fuzzer-mode \
--with-debug-info --enable-sanitizers=coverage,address,undefined
$ make fuzzers
Enabling 'coverage' sanitizer flags is required for libFuzzer to work.
Address sanitizer and undefined sanitizer are optional.
The fuzzer binaries will be in `build/fuzzer`. Simply pick one and run it, optionally
also passing a directory containing corpus inputs.
Using `libfuzzer` build mode implicitly assumes the fuzzers need to
link with `libFuzzer`; if another library is needed (for example in
OSS-Fuzz, which uses `libFuzzingEngine`), use the flag
`--with-fuzzer-lib` to specify the desired name.
Fuzzing with AFL
--------------------
To fuzz with AFL (http://lcamtuf.coredump.cx/afl/)::
$ ./configure.py --with-sanitizers --build-fuzzer=afl --unsafe-fuzzer-mode --cc-bin=afl-g++
$ make fuzzers
For AFL sanitizers are optional. You can also use `afl-clang-fast++`
or `afl-clang++`, be sure to set `--cc=clang` also.
The fuzzer binaries will be in `build/fuzzer`. To run them you need to
run under `afl-fuzz`::
$ afl-fuzz -i corpus_path -o output_path ./build/fuzzer/binary
Fuzzing with TLS-Attacker
--------------------------
TLS-Attacker (https://github.com/RUB-NDS/TLS-Attacker) includes a mode for fuzzing
TLS servers. A prebuilt copy of TLS-Attacker is available in a git repository::
$ git clone --depth 1 https://github.com/randombit/botan-ci-tools.git
To run it against Botan's server::
$ ./configure.py --with-sanitizers
$ make botan
$ ./src/scripts/run_tls_attacker.py ./botan ./botan-ci-tools
Output and logs from the fuzzer are placed into `/tmp`. See the
TLS-Attacker documentation for more information about how to use this
tool.
Input Corpus
-----------------------
AFL requires an input corpus, and libFuzzer can certainly make good
use of it.
Some crypto corpus repositories include
* https://github.com/randombit/crypto-corpus
* https://github.com/mozilla/nss-fuzzing-corpus
* https://github.com/google/boringssl/tree/master/fuzz
* https://github.com/openssl/openssl/tree/master/fuzz/corpora
Adding new fuzzers
---------------------
New fuzzers are created by adding a source file to `src/fuzzers` which
have the signature:
``void fuzz(const uint8_t in[], size_t len)``
After adding your fuzzer, rerun ``./configure.py`` and build.

View File

@ -1,79 +0,0 @@
Mistakes Were Made
===================
These are mistakes made early on in the project's history which are difficult to
fix now, but mentioned in the hope they may serve as an example for others.
C++ API
---------
As an implementation language, I still think C++ is the best choice (or at least
the best choice available in early '00s) at offering good performance,
reasonable abstractions, and low overhead. But the user API should have been
pure C with opaque structs (rather like the FFI layer, which was added much
later). Then an expressive C++ API could be built on top of the C API. This
would have given us a stable ABI, allowed C applications to use the library, and
(these days) make it easier to progressively rewrite the library in Rust.
Public Algorithm Specific Classes
------------------------------------
Classes like AES_128 and SHA_256 should never have been exposed to applications.
Intead such operations should have been accessible only via the higher level
interfaces (here BlockCipher and HashFunction). This would substantially reduce
the overall API and ABI surface.
[These interfaces were made internal in 3.0]
Header Directories
-------------------
It would have been better to install all headers as ``X/header.h``
where ``X`` is the base dir in the source, eg ``block/aes128.h``,
``hash/md5.h``, ...
Exceptions
-----------
Constant ABI headaches from this, and it impacts performance and makes APIs
harder to understand. Should have been handled with a result<> type instead.
Alternatively, and possibly more practically, there should have not been any
exception hierarchy (or at least not one visible to users) - instead only the
high level Exception type with contains an error type enum.
Virtual inheritance
---------------------
This was used in the public key interfaces and the hierarchy is a tangle.
Public and private keys should be distinct classes, with a function on private
keys that creates a new object corresponding to the public key.
Cipher Interface
------------------
The cipher interface taking a secure_vector that it reads from and writes to was
an artifact of an earlier design which supported both compression and encryption
in a single API. But it leads to inefficient copies.
(I am hoping this issue can be somewhat fixed by introducing a new cipher API
and implementing the old API in terms of the new one.)
Pipe Interface
----------------
On the surface this API seems very convenient and easy to use. And it is. But
the downside is it makes the application code totally opaque; some bytes go into
a Pipe object and then come out the end transformed in some way. What happens in
between? Unless the Pipe was built in the same function and you can see the
parameters to the constructor, there is no way to find out.
The problems with the Pipe API are documented, and it is no longer used within
the library itself. But since many people seem to like it and many applications
use it, we are stuck at least with maintaining it as it currently exists.
License
---------
MIT is more widely used and doesn't have the ambiguity surrounding the
various flavors of BSD.

View File

@ -1,92 +0,0 @@
Private OID Assignments
==========================
The library uses some OIDs under a private arc assigned by IANA,
1.3.6.1.4.1.25258
Values currently assigned are::
randombit OBJECT IDENTIFIER ::= { 1 3 6 1 4 1 25258 }
publicKey OBJECT IDENTIFIER ::= { randombit 1 }
mceliece OBJECT IDENTIFIER ::= { publicKey 3 }
-- { publicKey 4 } previously used as private X25519
-- { publicKey 5 } previously used for XMSS draft 6
gost-3410-with-sha256 OBJECT IDENTIFIER ::= { publicKey 6 1 }
kyber OBJECT IDENTIFIER ::= { publicKey 7 }
kyber-90s OBJECT IDENTIFIER ::= { publicKey 11 }
kyber-512 OBJECT IDENTIFIER ::= { kyber 1 }
kyber-768 OBJECT IDENTIFIER ::= { kyber 2 }
kyber-1024 OBJECT IDENTIFIER ::= { kyber 3 }
kyber-512-90s OBJECT IDENTIFIER ::= { kyber-90s 1 }
kyber-768-90s OBJECT IDENTIFIER ::= { kyber-90s 2 }
kyber-1024-90s OBJECT IDENTIFIER ::= { kyber-90s 3 }
xmss OBJECT IDENTIFIER ::= { publicKey 8 }
-- The current dilithium implementation is compatible with the reference
-- implementation commit 3e9b9f1412f6c7435dbeb4e10692ea58f181ee51
dilithium OBJECT IDENTIFIER ::= { publicKey 9 }
dilithium-aes OBJECT IDENTIFIER ::= { publicKey 10 }
dilithium-4x4 OBJECT IDENTIFIER ::= { dilithium 1 }
dilithium-6x5 OBJECT IDENTIFIER ::= { dilithium 2 }
dilithium-8x7 OBJECT IDENTIFIER ::= { dilithium 3 }
dilithium-aes-4x4 OBJECT IDENTIFIER ::= { dilithium-aes 1 }
dilithium-aes-6x5 OBJECT IDENTIFIER ::= { dilithium-aes 2 }
dilithium-aes-8x7 OBJECT IDENTIFIER ::= { dilithium-aes 3 }
SphincsPlus OBJECT IDENTIFIER ::= { publicKey 12 }
SphincsPlus-shake OBJECT IDENTIFIER ::= { SphincsPlus 1 }
SphincsPlus-sha2 OBJECT IDENTIFIER ::= { SphincsPlus 2 }
SphincsPlus-haraka OBJECT IDENTIFIER ::= { SphincsPlus 3 }
SphincsPlus-shake-128s-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-shake256 1 }
SphincsPlus-shake-128f-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-shake256 2 }
SphincsPlus-shake-192s-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-shake256 3 }
SphincsPlus-shake-192f-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-shake256 4 }
SphincsPlus-shake-256s-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-shake256 5 }
SphincsPlus-shake-256f-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-shake256 6 }
SphincsPlus-sha2-128s-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-sha256 1 }
SphincsPlus-sha2-128f-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-sha256 2 }
SphincsPlus-sha2-192s-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-sha256 3 }
SphincsPlus-sha2-192f-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-sha256 4 }
SphincsPlus-sha2-256s-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-sha256 5 }
SphincsPlus-sha2-256f-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-sha256 6 }
SphincsPlus-haraka-128s-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-haraka 1 }
SphincsPlus-haraka-128f-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-haraka 2 }
SphincsPlus-haraka-192s-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-haraka 3 }
SphincsPlus-haraka-192f-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-haraka 4 }
SphincsPlus-haraka-256s-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-haraka 5 }
SphincsPlus-haraka-256f-r3.1 OBJECT IDENTIFIER ::= { SphincsPlus-haraka 6 }
symmetricKey OBJECT IDENTIFIER ::= { randombit 3 }
ocbModes OBJECT IDENTIFIER ::= { symmetricKey 2 }
aes-128-ocb OBJECT IDENTIFIER ::= { ocbModes 1 }
aes-192-ocb OBJECT IDENTIFIER ::= { ocbModes 2 }
aes-256-ocb OBJECT IDENTIFIER ::= { ocbModes 3 }
serpent-256-ocb OBJECT IDENTIFIER ::= { ocbModes 4 }
twofish-256-ocb OBJECT IDENTIFIER ::= { ocbModes 5 }
camellia-128-ocb OBJECT IDENTIFIER ::= { ocbModes 6 }
camellia-192-ocb OBJECT IDENTIFIER ::= { ocbModes 7 }
camellia-256-ocb OBJECT IDENTIFIER ::= { ocbModes 8 }
sivModes OBJECT IDENTIFIER ::= { symmetricKey 4 }
aes-128-siv OBJECT IDENTIFIER ::= { sivModes 1 }
aes-192-siv OBJECT IDENTIFIER ::= { sivModes 2 }
aes-256-siv OBJECT IDENTIFIER ::= { sivModes 3 }
serpent-256-siv OBJECT IDENTIFIER ::= { sivModes 4 }
twofish-256-siv OBJECT IDENTIFIER ::= { sivModes 5 }
camellia-128-siv OBJECT IDENTIFIER ::= { sivModes 6 }
camellia-192-siv OBJECT IDENTIFIER ::= { sivModes 7 }
camellia-256-siv OBJECT IDENTIFIER ::= { sivModes 8 }
sm4-128-siv OBJECT IDENTIFIER ::= { sivModes 9 }

View File

@ -1,70 +0,0 @@
OS Features
========================================
A summary of OS features as defined in ``src/build-data/os``.
::
a: aix
a: android
c: cygwin
d: dragonfly
e: emscripten
f: freebsd
g: generic
h: haiku
h: hpux
h: hurd
i: ios
l: linux
l: llvm
m: macos
m: mingw
n: netbsd
n: none
o: openbsd
q: qnx
s: solaris
u: uwp
w: windows
.. csv-table::
:header: "Feature", "a", "a", "c", "d", "e", "f", "g", "h", "h", "h", "i", "l", "l", "m", "m", "n", "n", "o", "q", "s", "u", "w"
"alloc_conceal", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " "
"apple_keychain", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", " "
"arc4random", " ", "X", " ", "X", " ", "X", " ", " ", " ", " ", "X", " ", " ", "X", " ", "X", " ", "X", " ", " ", " ", " "
"atomics", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", " ", "X", "X", "X", "X", "X"
"auxinfo", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " "
"cap_enter", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "
"ccrandom", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", " "
"certificate_store", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", "X"
"clock_gettime", "X", "X", " ", "X", " ", "X", " ", "X", "X", "X", " ", "X", " ", "X", " ", "X", " ", "X", "X", "X", " ", " "
"commoncrypto", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", " "
"crypto_ng", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " "
"dev_random", "X", "X", "X", "X", "X", "X", " ", "X", "X", "X", " ", "X", " ", "X", " ", "X", " ", "X", "X", "X", " ", " "
"elf_aux_info", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "
"explicit_bzero", " ", " ", " ", "X", " ", "X", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", "X", " ", " ", " ", " "
"explicit_memset", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " "
"filesystem", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", " ", "X", "X", "X", "X", "X"
"getauxval", " ", "X", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "
"getentropy", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", "X", " ", "X", " ", " ", " ", "X", " ", "X", " ", " "
"getrandom", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "
"pledge", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " "
"posix1", "X", "X", "X", "X", "X", "X", " ", "X", "X", "X", "X", "X", " ", "X", " ", "X", " ", "X", "X", "X", " ", " "
"posix_mlock", "X", "X", " ", "X", " ", "X", " ", " ", "X", "X", "X", "X", " ", "X", " ", "X", " ", "X", "X", "X", " ", " "
"prctl", " ", "X", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "
"proc_fs", "X", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", "X", " ", " "
"rtlgenrandom", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", "X"
"rtlsecurezeromemory", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", "X"
"sandbox_proc", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", " ", " "
"setppriv", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " "
"sockets", "X", "X", "X", "X", " ", "X", " ", "X", "X", "X", "X", "X", " ", "X", " ", "X", " ", "X", "X", "X", " ", " "
"thread_local", "X", "X", "X", "X", " ", "X", "X", "X", "X", "X", "X", "X", " ", "X", "X", "X", " ", "X", "X", "X", "X", "X"
"threads", "X", "X", "X", "X", " ", "X", "X", "X", "X", "X", "X", "X", " ", "X", "X", "X", " ", "X", "X", "X", "X", "X"
"virtual_lock", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", " ", "X"
"win32", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", " ", " ", " ", " ", " ", "X", "X"
"winsock2", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", "X", "X"
.. note::
This file is auto generated by ``src/scripts/gen_os_features.py``. Dont modify it manually.

View File

@ -1,93 +0,0 @@
Reading List
================
These are papers, articles and books that are interesting or useful from the
perspective of crypto implementation.
Papers
--------
Implementation Techniques
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* "Randomizing the Montgomery Powering Ladder"
Le, Tan, Tunstall https://eprint.iacr.org/2015/657
A variant of Algorithm 7 is used for GF(p) point multplications when
BOTAN_POINTGFP_BLINDED_MULTIPLY_USE_MONTGOMERY_LADDER is set
* "Accelerating AES with vector permute instructions"
Mike Hamburg https://shiftleft.org/papers/vector_aes/
His public doman assembly code was rewritten into SSS3 intrinsics
for aes_ssse3.
* "Elliptic curves and their implementation" Langley
http://www.imperialviolet.org/2010/12/04/ecc.html
Describes sparse representations for ECC math
Random Number Generation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* "On Extract-then-Expand Key Derivation Functions and an HMAC-based KDF"
Hugo Krawczyk http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.131.8254
RNG design underlying HMAC_RNG
AES Side Channels
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* "Software mitigations to hedge AES against cache-based software side
channel vulnerabilities" https://eprint.iacr.org/2006/052.pdf
* "Cache Games - Bringing Access-Based Cache Attacks on AES to Practice"
http://www.ieee-security.org/TC/SP2011/PAPERS/2011/paper031.pdf
* "Cache-Collision Timing Attacks Against AES" Bonneau, Mironov
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.88.4753
Public Key Side Channels
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* "Fast Elliptic Curve Multiplications Resistant against Side Channel Attacks"
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.98.1028&rep=rep1&type=pdf
* "Resistance against Differential Power Analysis for Elliptic Curve Cryptosystems"
Coron http://www.jscoron.fr/publications/dpaecc.pdf
* "Further Results and Considerations on Side Channel Attacks on RSA"
Klima, Rosa https://eprint.iacr.org/2002/071
Side channel attacks on RSA-KEM and MGF1-SHA1
* "Side-Channel Attacks on the McEliece and Niederreiter Public-Key Cryptosystems"
Avanzi, Hoerder, Page, and Tunstall https://eprint.iacr.org/2010/479
* "Minimum Requirements for Evaluating Side-Channel Attack Resistance
of Elliptic Curve Implementations" BSI
https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Zertifizierung/Interpretationen/AIS_46_ECCGuide_e_pdf.pdf
Books
------
* "Handbook of Elliptic and Hyperelliptic Curve Cryptography"
Cohen and Frey https://www.hyperelliptic.org/HEHCC/
An excellent reference for ECC math, algorithms, and side channels
* "Post-Quantum Cryptography" Bernstein, Buchmann, Dahmen
Covers code, lattice, and hash based cryptography
Standards
-----------
* IEEE 1363 http://grouper.ieee.org/groups/1363/
Very influential early in the library lifetime, so a lot of terminology used
in the public key (such as "EME" for message encoding) code comes from here.
* ISO/IEC 18033-2 http://www.shoup.net/iso/std4.pdf
RSA-KEM, PSEC-KEM
* NIST SP 800-108
http://csrc.nist.gov/publications/nistpubs/800-108/sp800-108.pdf
KDF schemes
* NIST SP 800-90A
http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
HMAC_DRBG, Hash_DRBG, CTR_DRBG, maybe one other thing?

View File

@ -1,103 +0,0 @@
Release Process and Checklist
========================================
Releases are done quarterly, normally on the second non-holiday Monday
of January, April, July and October. A feature freeze goes into effect
starting 9 days before the release.
.. highlight:: shell
.. note::
This information is only useful if you are a developer of botan who
is creating a new release of the library.
Pre Release Testing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Do maintainer-mode builds with Clang and GCC to catch any warnings
that should be corrected.
Other checks which are not in CI:
- Native compile on FreeBSD x86-64
- Native compile on at least one unusual platform (AIX, NetBSD, ...)
- Build the website content to detect any Doxygen problems
- Test many build configurations (using `src/scripts/test_all_configs.py`)
- Build/test SoftHSM
Confirm that the release notes in ``news.rst`` are accurate and
complete and that the version number in ``version.txt`` is correct.
Tag the Release
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Update the release date in the release notes and change the entry for
the appropriate branch in ``readme.rst`` to point to the new release.
Now check in, and backport changes to the release branch::
$ git commit readme.rst news.rst -m "Update for 3.8.2 release"
$ git checkout release-3
$ git merge master
$ git tag 3.8.2
Build The Release Tarballs
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The release script is ``src/scripts/dist.py`` and must be run from a
git workspace.
$ src/scripts/dist.py 3.8.2
One useful option is ``--output-dir``, which specifies where the
output will be placed.
Now do a final build/test of the released tarball.
The ``--pgp-key-id`` option is used to specify a PGP keyid. If set,
the script assumes that it can execute GnuPG and will attempt to
create signatures for the tarballs. The default value is ``EFBADFBC``,
which is the official signing key. You can use ``--pgp-key-id=none``
to avoid creating any signature, though official distributed releases
*should not* be released without signatures.
The releases served on the official site are taken from the contents
in a git repository::
$ git checkout git@botan.randombit.net:/srv/git/botan-releases.git
$ src/scripts/dist.py 3.8.2 --output-dir=botan-releases
$ cd botan-releases
$ sha256sum Botan-3.8.2.tgz >> sha256sums.txt
$ git add .
$ git commit -m "Release version 3.8.2"
$ git push origin master
A cron job updates the live site every 10 minutes.
Push to GitHub
^^^^^^^^^^^^^^^^^^
Don't forget to also push tags::
$ git push origin --tags release-3 master
Update The Website
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The website content is created by ``src/scripts/website.py``.
The website is mirrored automatically from a git repository which must be updated::
$ git checkout git@botan.randombit.net:/srv/git/botan-website.git
$ ./src/scripts/website.py --output botan-website
$ cd botan-website
$ git add .
$ git commit -m "Update for 3.8.2"
$ git push origin master
Announce The Release
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Send an email to the botan-announce and botan-devel mailing lists
noting that a new release is available.

View File

@ -1,314 +0,0 @@
Test Framework
================
Botan uses a custom-built test framework. Some portions of it are
quite similar to assertion-based test frameworks such as Catch or
Gtest, but it also includes many features which are well suited for
testing cryptographic algorithms.
The intent is that the test framework and the test suite evolve
symbiotically; as a general rule of thumb if a new function would make
the implementation of just two distinct tests simpler, it is worth
adding to the framework on the assumption it will prove useful again.
Feel free to propose changes to the test system.
When writing a new test, there are three key classes that are used,
namely ``Test``, ``Test::Result``, and ``Text_Based_Test``. A ``Test``
(or ``Test_Based_Test``) runs and returns one or more ``Test::Result``.
Namespaces in Test
-------------------
The test code lives in a distinct namespace (``Botan_Tests``) and all
code in the tests which calls into the library should use the
namespace prefix ``Botan::`` rather than a ``using namespace``
declaration. This makes it easier to see where the test is actually
invoking the library, and makes it easier to reuse test code for
applications.
Test Data
-----------
The test framework is heavily data driven. As of this writing, there
is about 1 Mib of test code and 17 MiB of test data. For most (though
certainly not all) tests, it is better to add a data file representing
the input and outputs, and run the tests over it. Data driven tests
make adding or editing tests easier, for example by writing scripts
which produce new test data and output it in the expected format.
Test
--------
.. cpp:class:: Test
.. cpp:function:: virtual std::vector<Test::Result> run() = 0
This is the key function of a ``Test``: it executes and returns a
list of results. Almost all other functions on ``Test`` are
static functions which just serve as helper functions for ``run``.
.. cpp:function:: static std::string read_data_file(const std::string& path)
Return the contents of a data file and return it as a string.
.. cpp:function:: static std::vector<uint8_t> read_binary_data_file(const std::string& path)
Return the contents of a data file and return it as a vector of
bytes.
.. cpp:function:: static std::string data_file(const std::string& what)
An alternative to ``read_data_file`` and ``read_binary_file``,
use only as a last result, typically for library APIs which
themselves accept a filename rather than a data blob.
.. cpp:function:: static bool run_long_tests() const
Returns true if the user gave option ``--run-long-tests``. Use
this to gate particularly time-intensive tests.
.. cpp:function:: static Botan::RandomNumberGenerator& rng()
Returns a reference to a fast, not cryptographically secure
random number generator. It is deterministicly seeded with the
seed logged by the test runner, so it is possible to reproduce
results in "random" tests.
Tests are registered using the macro ``BOTAN_REGISTER_TEST`` which
takes 2 arguments: the name of the test and the name of the test class.
For example given a ``Test`` instance named ``MyTest``, use::
BOTAN_REGISTER_TEST("mytest", MyTest);
All test names should contain only lowercase letters, numbers, and
underscore.
Test::Result
-------------
.. cpp:class:: Test::Result
A ``Test::Result`` records one or more tests on a particular topic
(say "AES-128/CBC" or "ASN.1 date parsing"). Most of the test functions
return true or false if the test was successful or not; this allows
performing conditional blocks as a result of earlier tests::
if(result.test_eq("first value", produced, expected))
{
// further tests that rely on the initial test being correct
}
Only the most commonly used functions on ``Test::Result`` are documented here,
see the header ``tests.h`` for more.
.. cpp:function:: Test::Result(const std::string& who)
Create a test report on a particular topic. This will be displayed in the
test results.
.. cpp:function:: bool test_success()
Report a test that was successful.
.. cpp:function:: bool test_success(const std::string& note)
Report a test that was successful, including some comment.
.. cpp:function:: bool test_failure(const std::string& err)
Report a test failure of some kind. The error string will be logged.
.. cpp:function:: bool test_failure(const std::string& what, const std::string& error)
Report a test failure of some kind, with a description of what failed and
what the error was.
.. cpp:function:: void test_failure(const std::string& what, const uint8_t buf[], size_t buf_len)
Report a test failure due to some particular input, which is provided as
arguments. Normally this is only used if the test was using some
randomized input which unexpectedly failed, since if the input is
hardcoded or from a file it is easier to just reference the test number.
.. cpp:function:: bool test_eq(const std::string& what, const std::string& produced, const std::string& expected)
Compare to strings for equality.
.. cpp:function:: bool test_ne(const std::string& what, const std::string& produced, const std::string& expected)
Compare to strings for non-equality.
.. cpp:function:: bool test_eq(const char* producer, const std::string& what, \
const uint8_t produced[], size_t produced_len, \
const uint8_t expected[], size_t expected_len)
Compare two arrays for equality.
.. cpp:function:: bool test_ne(const char* producer, const std::string& what, \
const uint8_t produced[], size_t produced_len, \
const uint8_t expected[], size_t expected_len)
Compare two arrays for non-equality.
.. cpp:function:: bool test_eq(const std::string& producer, const std::string& what, \
const std::vector<uint8_t>& produced, \
const std::vector<uint8_t>& expected)
Compare two vectors for equality.
.. cpp:function:: bool test_ne(const std::string& producer, const std::string& what, \
const std::vector<uint8_t>& produced, \
const std::vector<uint8_t>& expected)
Compare two vectors for non-equality.
.. cpp:function:: bool confirm(const std::string& what, bool expr)
Test that some expression evaluates to ``true``.
.. cpp:function:: template<typename T> bool test_not_null(const std::string& what, T* ptr)
Verify that the pointer is not null.
.. cpp:function:: bool test_lt(const std::string& what, size_t produced, size_t expected)
Test that ``produced`` < ``expected``.
.. cpp:function:: bool test_lte(const std::string& what, size_t produced, size_t expected)
Test that ``produced`` <= ``expected``.
.. cpp:function:: bool test_gt(const std::string& what, size_t produced, size_t expected)
Test that ``produced`` > ``expected``.
.. cpp:function:: bool test_gte(const std::string& what, size_t produced, size_t expected)
Test that ``produced`` >= ``expected``.
.. cpp:function:: bool test_throws(const std::string& what, std::function<void ()> fn)
Call a function and verify it throws an exception of some kind.
.. cpp:function:: bool test_throws(const std::string& what, const std::string& expected, std::function<void ()> fn)
Call a function and verify it throws an exception of some kind
and that the exception message exactly equals ``expected``.
Text_Based_Test
-----------------
A ``Text_Based_Text`` runs tests that are produced from a text file
with a particular format which looks somewhat like an INI-file::
# Comments begin with # and continue to end of line
[Header]
# Test 1
Key1 = Value1
Key2 = Value2
# Test 2
Key1 = Value1
Key2 = Value2
.. cpp:class:: VarMap
An object of this type is passed to each invocation of the text-based test.
It is used to access the test variables. All access takes a key, which is
one of the strings which was passed to the constructor of ``Text_Based_Text``.
Accesses are either required (``get_req_foo``), in which case an exception is
throwing if the key is not set, or optional (``get_opt_foo``) in which case
the test provides a default value which is returned if the key was not set
for this particular instance of the test.
.. cpp:function:: std::vector<uint8_t> get_req_bin(const std::string& key) const
Return a required binary string. The input is assumed to be hex encoded.
.. cpp:function:: std::vector<uint8_t> get_opt_bin(const std::string& key) const
Return an optional binary string. The input is assumed to be hex encoded.
.. cpp:function:: std::vector<std::vector<uint8_t>> get_req_bin_list(const std::string& key) const
.. cpp:function:: Botan::BigInt get_req_bn(const std::string& key) const
Return a required BigInt. The input can be decimal or (with "0x" prefix) hex encoded.
.. cpp:function:: Botan::BigInt get_opt_bn(const std::string& key, const Botan::BigInt& def_value) const
Return an optional BigInt. The input can be decimal or (with "0x" prefix) hex encoded.
.. cpp:function:: std::string get_req_str(const std::string& key) const
Return a required text string.
.. cpp:function:: std::string get_opt_str(const std::string& key, const std::string& def_value) const
Return an optional text string.
.. cpp:function:: size_t get_req_sz(const std::string& key) const
Return a required integer. The input should be decimal.
.. cpp:function:: size_t get_opt_sz(const std::string& key, const size_t def_value) const
Return an optional integer. The input should be decimal.
.. cpp:class:: Text_Based_Test : public Test
.. cpp:function:: Text_Based_Test(const std::string& input_file, \
const std::string& required_keys, \
const std::string& optional_keys = "")
This constructor is
.. note::
The final element of required_keys is the "output key", that is
the key which signifies the boundary between one test and the next.
When this key is seen, ``run_one_test`` will be invoked. In the
test input file, this key must always appear least for any particular
test. All the other keys may appear in any order.
.. cpp:function:: Test::Result run_one_test(const std::string& header, \
const VarMap& vars)
Runs a single test and returns the result of it. The ``header``
parameter gives the value (if any) set in a ``[Header]`` block.
This can be useful to distinguish several types of tests within a
single file, for example "[Valid]" and "[Invalid]".
.. cpp:function:: bool clear_between_callbacks() const
By default this function returns ``false``. If it returns
``true``, then when processing the data in the file, variables
are not cleared between tests. This can be useful when several
tests all use some common parameters.
Test Runner
-------------
If you are simply writing a new test there should be no need to modify
the runner, however it can be useful to be aware of its abilities.
The runner can run tests concurrently across many cores. By default single
threaded execution is used, but you can use ``--test-threads`` option to
specify the number of threads to use. If you use ``--test-threads=0`` then
the runner will probe the number of active CPUs and use that (but limited
to at most 16). If you want to run across many cores on a large machine,
explicitly specify a thread count. The speedup is close to linear.
The RNG used in the tests is deterministic, and the seed is logged for each
execution. You can cause the random sequence to repeat using ``--drbg-seed``
option.
.. note::
Currently the RNG is seeded just once at the start of execution. So you
must run the exact same sequence of tests as the original test run in
order to get reproducible results.
If you are trying to track down a bug that happens only occasionally, two very
useful options are ``--test-runs`` and ``--abort-on-first-fail``. The first
takes an integer and runs the specified test cases that many times. The second
causes abort to be called on the very first failed test. This is sometimes
useful when tracing a memory corruption bug.

View File

@ -1,160 +0,0 @@
Todo List
========================================
Feel free to take one of these on if it interests you. Before starting
out on something, send an email to the dev list or open a discussion
ticket on GitHub to make sure you're on the right track.
Request a new feature by opening a pull request to update this file.
New Ciphers/Hashes/MACs
----------------------------------------
* GCM-SIV (RFC 8452)
* EME* tweakable block cipher (https://eprint.iacr.org/2004/125)
* PMAC
* SIV-PMAC
* Threefish-1024
* Skein-MAC
* FFX format preserving encryption (NIST 800-38G)
* Adiantum (https://eprint.iacr.org/2018/720)
* HPKE (draft-irtf-cfrg-hpke)
* Blake3
Improved Ciphers Implementations
----------------------------------------
* Stiched AES/GCM mode for CPUs supporting both AES and CLMUL
* Combine AES-NI, ARMv8 and POWER AES implementations (as already done for CLMUL)
* Support for VAES (Zen4/Ice Lake)
* NEON/VMX support for the SIMD based GHASH
* Vector permute AES only supports little-endian systems; fix for big-endian
* SM4 using AES-NI (https://github.com/mjosaarinen/sm4ni) or vector permute
* Poly1305 using AVX2
* SHA-512 using BMI2+AVX2
* Constant time bitsliced DES
* SIMD evaluation of SHA-2 and SHA-3 compression functions
* Improved Salsa implementations (SIMD_4x32 and/or AVX2)
* Add CLMUL/PMULL implementations for CRC24/CRC32
Public Key Crypto, Math
----------------------------------------
* Short vector optimization for BigInt
* Abstract representation of ECC point elements to allow specific
implementations of the field arithmetic depending upon the curve.
* Curves for pairings (BLS12-381)
* Identity based encryption
* Paillier homomorphic cryptosystem
* New PAKEs (pending CFRG bakeoff results)
* New post quantum schemes (pending NIST contest results)
* SPHINX password store (https://eprint.iacr.org/2018/695)
* X448 and Ed448
Utility Functions
------------------
* Make Memory_Pool more concurrent (currently uses a global lock)
* Guarded integer type to prevent overflow bugs
External Providers, Hardware Support
----------------------------------------
* Add support ARMv8.4-A SHA-512, SHA-3, SM3 and RNG
* Aarch64 inline asm for BigInt
* /dev/crypto provider (ciphers, hashes)
* Windows CryptoNG provider (ciphers, hashes)
* Extend Apple CommonCrypto provider (HMAC, CMAC, RSA, ECDSA, ECDH)
* Add support for iOS keychain access
* POWER8 SHA-2 extensions (GH #1486 + #1487)
* Add support VPSUM on big-endian PPC64 (GH #2252)
* Better TPM support: NVRAM, PCR measurements, sealing
* Add support for TPM 2.0 hardware
TLS
----------------------------------------
* Make DTLS support optional at build time
* Improve/optimize DTLS defragmentation and retransmission
* Make RSA optional at build time
* Make finite field DH optional at build time
* Certificate Transparency extensions
* TLS supplemental authorization data (RFC 4680, RFC 5878)
* DTLS-SCTP (RFC 6083)
PKIX
----------------------------------------
* Further tests of validation API (see GH #785)
* Test suite for validation of 'real world' cert chains (GH #611)
* X.509 policy constraints
* OCSP responder logic
New Protocols / Formats
----------------------------------------
* Noise protocol
* ACME protocol
* Cryptographic Message Syntax (RFC 5652)
* Fernet symmetric encryption (https://cryptography.io/en/latest/fernet/)
* RNCryptor format (https://github.com/RNCryptor/RNCryptor)
* Age format (https://age-encryption.org/v1)
* Useful OpenPGP subset 1: symmetrically encrypted files.
Not aiming to process arbitrary OpenPGP, but rather produce
something that happens to be readable by `gpg` and is relatively
simple to process for decryption. Require AEAD mode (EAX/OCB).
* Useful OpenPGP subset 2: Process OpenPGP public keys
* Useful OpenPGP subset 3: Verification of OpenPGP signatures
Cleanups
-----------
* Unicode path support on Windows (GH #1615)
* The X.509 path validation tests have much duplicated logic
New C APIs
----------------------------------------
* PKCS10 requests
* Certificate signing
* CRLs
* Expose TLS
* Expose NIST key wrap with padding
* Expose secret sharing
* Expose deterministic PRNG
* base32
* base58
* DL_Group
* EC_Group
Build/Test
----------------------------------------
* Support hardcoding all test vectors into the botan-test binary
so it can run as a standalone item (copied to a device, etc)
* Run iOS binary under simulator in CI
* Run Android binary under simulator in CI
* Run the TPM tests against an emulator
(https://github.com/PeterHuewe/tpm-emulator)
* Add support for vxWorks
CLI
----------------------------------------
* Add a ``--completion`` option to dump autocomplete info, write
support for autocompletion in bash/zsh.
* Refactor ``speed``
* Change `tls_server` to be a tty<->socket app, like `tls_client` is,
instead of a bogus echo server.
* `encrypt` / `decrypt` tools providing password based file encryption
* Add ECM factoring
* Clone of `minisign` signature utility
* Implementation of `tlsdate`
* Password store utility
* TOTP calculator
* Clone of magic wormhole
* ACVP client (https://github.com/usnistgov/ACVP)
Documentation
----------------------------------------
* Always needs help

View File

@ -1,131 +0,0 @@
Project Goals
================================
Botan seeks to be a broadly applicable library that can be used to implement a
range of secure distributed systems.
The library has the following project goals guiding changes. It does not succeed
in all of these areas in every way just yet, but it describes the system that is
the desired end result. Over time further progress is made in each.
* Secure and reliable. The implementations must of course be correct and well
tested, and attacks such as side channels and fault attacks should be
accounted for where necessary. The library should never crash, or invoke
undefined behavior, regardless of circumstances.
* Implement schemes important in practice. It should be practical to implement
any real-world crypto protocol using just what the library provides. It is
worth some (limited) additional complexity in the library, in order to expand
the set of applications which can easily adopt Botan.
* Ease of use. It should be straightforward for an application programmer to do
whatever it is they need to do. There should be one obvious way to perform any
operation. The API should be predicable, and follow the "principle of least
astonishment" in its design. This is not just a nicety; confusing APIs often
result in errors that end up compromising security.
* Simplicity of design, clarity of code, ease of review. The code should be easy
to read and understand by other library developers, users seeking to better
understand the behavior of the code, and by professional reviewers looking for
bugs. This is important because bugs in convoluted code can easily escape
multiple expert reviews, and end up living on for years.
* Well tested. The code should be correct against the spec, with as close to
100% test coverage as possible. All available static and dynamic analysis
tools at our disposal should be used, including fuzzers, symbolic execution,
and protocol specific tools. Within reason, all warnings from compilers and
static analyzers should be addressed, even if they seem like false positives,
because that maximizes the signal value of new warnings from the tool.
* Safe defaults. Policies should aim to be highly restrictive by default, and if
they must be made less restrictive by certain applications, it should be
obvious to the developer that they are doing something unsafe.
* Post quantum security. Possibly a practical quantum computer that can break
RSA and ECC will never be built, but the future is notoriously hard to predict.
It seems prudent to begin designing and deploying systems now which have at
least the option of using a post-quantum scheme. Botan provides a conservative
selection of algorithms thought to be post-quantum secure.
* Performance. Botan does not in every case strive to be faster than every other
software implementation, but performance should be competitive and over time
new optimizations are identified and applied.
* Support whatever I/O mechanism the application wants. Allow the application to
control all aspects of how the network is contacted, and ensure the API makes
asynchronous operations easy to handle. This both insulates Botan from
system-specific details and allows the application to use whatever networking
style they please.
* Portability to modern systems. Botan does not run everywhere, and we actually
do not want it to (see non-goals below). But we do want it to run on anything
that someone is deploying new applications on. That includes both major
platforms like Windows, Linux, Android and iOS, and also promising new systems
such as Fuchsia.
* Well documented. Ideally every public API would have some place in the manual
describing its usage.
* Useful command line utility. The botan command line tool should be flexible
and featured enough to replace similar tools such as ``openssl`` for everyday
users.
Non-Goals
-------------------------
There are goals some crypto libraries have, but which Botan actively does not
seek to address.
* Deep embedded support. Botan requires a heap, C++ exceptions, and RTTI, and at
least in terms of performance optimizations effectively assumes a 32 or 64 bit
processor. It is not suitable for deploying on, say FreeRTOS running on a
MSP430, or smartcard with an 8 bit CPU and 256 bytes RAM. A larger SoC, such
as a Cortex-A7 running Linux, is entirely within scope.
* Implementing every crypto scheme in existence. The focus is on algorithms
which are in practical use in systems deployed now, as well as promising
algorithms for future deployment. Many algorithms which were of interest
in the past but never saw widespread deployment and have no compelling
benefit over other designs have been removed to simplify the codebase.
* Portable to obsolete systems. There is no reason for crypto software to
support ancient OS platforms like SunOS or Windows 2000, since these unpatched
systems are completely unsafe anyway. The additional complexity supporting
such platforms just creates more room for bugs.
* Portable to every C++ compiler ever made. Over time Botan moves forward to
both take advantage of new language/compiler features, and to shed workarounds
for dealing with bugs in ancient compilers, allowing further simplifications
in the codebase. The set of supported compilers is fixed for each new release
branch, for example Botan 2.x will always support GCC 4.8. But a future 3.x
release version will likely increase the required versions for all compilers.
* FIPS 140 validation. The primary developer was (long ago) a consultant with a
NIST approved testing lab. He does not have a positive view of the process or
results, particularly when it comes to Level 1 software validations. The only
benefit of a Level 1 validation is to allow for government sales, and the cost
of validation includes enormous amounts of time and money, adding 'checks'
that are useless or actively harmful, then freezing the software so security
updates cannot be applied in the future. It does force a certain minimum
standard (ie, FIPS Level 1 does assure AES and RSA are probably implemented
correctly) but this is an issue of interop not security since Level 1 does not
seriously consider attacks of any kind. Any security budget would be far
better spent on a review from a specialized crypto consultancy, who would look
for actual flaws.
That said it would be easy to add a "FIPS 140" build mode to Botan, which just
disabled all the builtin crypto and wrapped whatever the most recent OpenSSL
FIPS module exports.
* Educational purposes. The library code is intended to be easy to read and
review, and so might be useful in an educational context. However it does not
contain any toy ciphers (unless you count DES and RC4) nor any tools for
simple cryptanalysis. Generally the manual and source comments assume previous
knowledge on the basic concepts involved.
* User proof. Some libraries provide a very high level API in an attempt to save
the user from themselves. Occasionally they succeed. It would be appropriate
and useful to build such an API on top of Botan, but Botan itself wants to
cover a broad set of uses cases and some of these involve having pointy things
within reach.

View File

@ -1,55 +0,0 @@
Getting Started
========================================
If you need to build the library first, start with :doc:`building`.
Some Linux distributions include packages for Botan, so building from
source may not be required on your system.
.. only:: html
The :ref:`genindex` and :ref:`search` may be useful to get started.
.. only:: html and website
You can also download this manual as a `PDF <https://botan.randombit.net/handbook/botan.pdf>`_.
Examples
----------
Some examples of usage are included in this documentation. However a better
source for example code is in the implementation of the
`command line interface <https://github.com/randombit/botan/tree/master/src/cli>`_,
which was intentionally written to act as practical examples of usage.
Books and other references
----------------------------
You should have some knowledge of cryptography *before* trying to use
the library. This is an area where it is very easy to make mistakes,
and where things are often subtle and/or counterintuitive. Obviously
the library tries to provide things at a high level precisely to
minimize the number of ways things can go wrong, but naive use will
almost certainly not result in a secure system.
Especially recommended are:
- *Cryptography Engineering*
by Niels Ferguson, Bruce Schneier, and Tadayoshi Kohno
- `Security Engineering -- A Guide to Building Dependable Distributed Systems
<https://www.cl.cam.ac.uk/~rja14/book.html>`_ by Ross Anderson
- `Handbook of Applied Cryptography <http://www.cacr.math.uwaterloo.ca/hac/>`_
by Alfred J. Menezes, Paul C. Van Oorschot, and Scott A. Vanstone
If you're doing something non-trivial or unique, you might want to at
the very least ask for review/input at a place such as the
`cryptography stack exchange <https://crypto.stackexchange.com/>`_.
And (if possible) pay a professional cryptographer or security company
to review your design and code.
.. toctree::
:maxdepth: 1
:numbered:

View File

@ -1,449 +0,0 @@
Botan 2.x to 3.x Migration
==============================
This is a guide on migrating applications from Botan 2.x to 3.0.
This guide attempts to be, but is not, complete. If you run into a problem while
converting code that does not seem to be described here, please open an issue on
Github.
Headers
--------
Many headers have been removed from the public API.
In some cases, such as ``datastor.h`` or ``tls_blocking.h``, the functionality
presented was entirely deprecated, in which case it has been removed.
In other cases (such as ``loadstor.h`` or ``rotate.h``) the header was really an
implementation header of the library and not intended to be consumed as a public
API. In these cases the header is still used internally, but not installed for
application use.
However in most cases there is a better way of performing the same operations,
which usually works in both 2.x and 3.x. For example, in 3.0 all of the
algorithm headers (such as ``aes.h``) have been removed. Instead you should
create objects via the factory methods (in the case of AES,
``BlockCipher::create``) which works in both 2.x and 3.0
Build Artifacts
---------------
For consistency with other platforms the DLL is now suffixed with the library's
major version on Windows as well.
TLS
---
Starting with Botan 3.0 TLS 1.3 is supported.
This development required a number of backward-incompatible changes to
accomodate the protocol differences to TLS 1.2, which is still supported.
Build modules
^^^^^^^^^^^^^
The build module ``tls`` is now internal and contains common TLS helpers. Users
have to explicitly enable ``tls12`` and/or ``tls13``. Note that for Botan 3.0 it
is not (yet) possible to exclusively enable TLS 1.3 at build time.
Removed Functionality
^^^^^^^^^^^^^^^^^^^^^
Functionality removed from the TLS implementation includes
* TLS 1.0, 1.1 and DTLS 1.0
* DSA ciphersuites
* anonymous ciphersuites
* SRP ciphersuites
* SEED ciphersuites
* Camellia CBC ciphersuites
* AES-128 OCB ciphersuites
* DHE_PSK ciphersuites
* CECPQ1 ciphersuites
enum classes
^^^^^^^^^^^^
The publicly available C++ enums in the TLS namespace are now `enum class` and
their member naming scheme was converted from `SHOUTING_SNAKE_CASE` to
`CamelCase`.
Callbacks
^^^^^^^^^
A number of new callbacks were added with TLS 1.3. None of those new callbacks
is mandatory to implement by applications, though. Additionally there are a few
backward incompatible changes in callbacks that might require attention by some
applications:
tls_record_received() / tls_emit_data()
"""""""""""""""""""""""""""""""""""""""
Those callbacks now take `std::span<const uint8_t>` instead of `const uint8_t*`
with a `size_t` buffer length.
tls_session_established()
"""""""""""""""""""""""""
This callback provides a summary of the just-negotiated connection. It used to
have a bool return value letting an application decide to store or discard the
connection's resumption information. This use case is now provided via:
`tls_should_persist_resumption_information()` which might be called more than
once for a single TLS 1.3 connection.
`tls_session_established` is not a mandatory callback anymore but still allows
applications to abort a connection given a summary of the negotiated
characteristics. Note that this summary is not a persistable `Session` anymore.
tls_verify_cert_chain()
"""""""""""""""""""""""
The parameter `ocsp_responses`, which was previously
`std::shared_ptr<OCSP::Response>`, is now `std::optional<OCSP::Response>`.
tls_modify_extensions() / tls_examine_extensions()
""""""""""""""""""""""""""""""""""""""""""""""""""
These callbacks now have an additional parameter of type `Handshake_Type` that
identify the TLS handshake message the extensions in question are residing in.
TLS 1.3 makes much heavier use of such extensions in a wider range of messages
to implement core protocol functionality.
tls_dh_agree() / tls_ecdh_agree() / tls_decode_group_param()
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
These callbacks were used as customization points for the TLS 1.2 key exchange
in the TLS client. To allow similar (and more) customizations with the
introduction of TLS 1.3, these callbacks were replaced with a more generic
approach.
Key agreement is split into two callbacks, namely `tls_generate_ephemeral_key()`
and `tls_ephemeral_key_agreement()`. Those are used in both clients and servers
and in all protocol versions. `tls_decode_group_param()` is removed as it became
obsolete by the replacement of the other two callbacks.
Policy
^^^^^^
choose_key_exchange_group()
"""""""""""""""""""""""""""
The new parameter `offered_by_peer` identifies the key exchange groups a peer
has sent public exchange offerings for (in TLS 1.3 handshakes only).
Choosing a key exchange group that is not listed is legal but will result in an
additional network round trip (cf. "Hello Retry Request").
In TLS 1.2, this vector is always empty and can be ignored.
session_ticket_lifetime()
"""""""""""""""""""""""""
Now returns `std::chrono::seconds` rather than a bare `uint32_t`.
Credentials Manager
^^^^^^^^^^^^^^^^^^^
find_cert_chain(), cert_chain() and cert_chain_single_type()
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
These methods now have a `cert_signature_schemes` parameter that identifies
a list of signature schemes the peer is willing to accept for signatures
in certificates.
Notably, this *does not necessarily* mean that the leaf certificate must feature
a public key type able to generate one of those schemes.
private_key_for()
"""""""""""""""""
Applications must now provide a `std::shared_ptr<>` to the requested private key
object instead of a raw pointer to better communicate the implementation's
life-time expectations of this private key object.
.. _tls_session_manager_migration:
Session and Ticket Handling
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Old (pre-Botan 3.0) sessions won't load in Botan 3.0 anymore and should be
discarded.
For applications using `Session_Manager_SQL` or `Session_Manager_SQLite`
discarding happens automatically on first access after the update.
With Botan 3.0 the session manager now is responsible for stateful session
handling (backed by a database) and creation and management of stateless session
tickets.
The latter was previously handled transparently by the TLS implementation itself.
Therefore, TLS server applications that relied on Botan's default session
management implementations (most notably `Session_Manager_SQLite` or
`Session_Manager_In_Memory`) are advised to re-evaluate their choice.
Have a look at `Session_Manager_Hybrid` to retain support for both stateful and
stateless TLS sessions.
TLS client applications may safely keep relying on the above-mentioned default
implementations.
Applications implementing their own `Session_Manager` will need to adapt to the
new base class API.
New API of Session Manager
""""""""""""""""""""""""""
TLS 1.3 removed the legacy resumption procedures based on session IDs or session
tickets and combined them under the protocol's Pre-Shared Key mechanism.
This new approach allows TLS servers to handle sessions both stateless (as
self-contained encrypted and authenticated tickets) and stateful (identified
with unique database handles).
To accomodates this flexibility the `Session_Manager` base class API has changed
drastically and is now responsible for creation, storage and management of both
stateful sessions and stateless session tickets.
Sub-classes therefore gain full control over the session ticket's structure and
content.
API details are documented in the class' doxygen comments.
The Session Object and its Handle
"""""""""""""""""""""""""""""""""
Objects of class `Session` are not aware of their "session ID" or their "session
ticket" anymore.
Instead, the new class `Session_Handle` encapsulates the session's identifier or
ticket and accompanies the `Session` object where necessary.
Algorithms Removed
-------------------
The algorithms CAST-256, MISTY1, Kasumi, DESX, XTEA, PBKDF1, MCEIES, CBC-MAC,
Tiger, CECPQ1, and NewHope have been removed.
Certificate API shared_ptr
----------------------------
Previously the certificate store used ``shared_ptr<X509_Certificate>`` in
various APIs. However starting in 2.4.0, ``X509_Certificate`` itself is a pimpl
to a ``shared_ptr``, making the outer shared pointer pointless. In 3.0 the
certificate interfaces have changed to just consume and return ``X509_Certificate``.
All Or Nothing Package Transform
----------------------------------
This code was deprecated and has been removed.
Exception Changes
-------------------
Several exceptions, mostly ones not used by the library, were removed.
A few others that were very specific (such as Illegal_Point) were replaced
by throws of their immediate base class exception type.
The base class of Encoding_Error and Decoding_Error changed from
Invalid_Argument to Exception. If you are explicitly catching Invalid_Argument,
verify that you do not need to now also explicitly catch Encoding_Error and/or
Decoding_Error.
X.509 Certificate Info Access
-------------------------------
Previously ``X509_Certificate::subject_info`` and ``issuer_info`` could be used
to query information about extensions. This is not longer the case; instead you
should either call a specific function on ``X509_Certificate`` which returns the
same information, or lacking that, iterate over the result of
``X509_Certificate::v3_extensions``.
OCSP Response Validation
------------------------
After mitigating CVE-2022-43705 the OCSP response signature validation was refactored.
This led to the removal of the `OCSP::Response::check_signature()` method. If you
must validate OCSP responses directly in your application please use the new method
`OCSP::Response::find_signing_certificate()` and `OCSP::Response::verify_signature()`.
Use of ``enum class``
--------------------------------
Several enumerations where modified to become ``enum class``, including
``DL_Group::Format``, ``CRL_Code``, ``EC_Group_Encoding``, ``Signature_Format``,
``Cipher_Dir``, ``TLS::Extension_Code``, ``TLS::Connection_Side``,
``TLS::Record_Type``, and ``TLS::Handshake_Type``
In many cases the enumeration values were renamed from ``SHOUTING_CASE`` to
``CamelCase``. In some cases where the enumeration was commonly used by
applications (for example ``Signature_Format`` and ``Cipher_Dir``) the old
enumeration names are retained as deprecated variants.
ASN.1 enums
---------------
The enum ``ASN1_Tag`` has been split into ``ASN1_Type`` and ``ASN1_Class``.
Unlike ``ASN1_Tag``, these new enums are ``enum class``. The members of the
enums have changed from ``SHOUTING_CASE`` to ``CamelCase``, eg ``CONSTRUCTED``
is now ``Constructed``.
Also an important change related to ``ASN1_Tag::PRIVATE``. This enum value was
incorrect, and actually was used for explicitly tagged context specific values.
Now, ``ASN1_Class::Private`` refers to the correct class, but would lead to a
different encoding vs 2.x's ``ASN1_Tag::PRIVATE``. The correct value to use in
3.0 to match ``ASN1_Tag::PRIVATE`` is ``ASN1_Class::ExplicitContextSpecific``.
Cipher Mode Granularity
-------------------------
Previously Cipher_Mode::update_granularity specified the minimum buffer size
that must be provided during processing. However the value returned was often
much larger than what was strictly required. In particular some modes can easily
accept inputs as small as 1 byte, but their update_granularity was much larger
to encourage best performance.
Now update_granularity returns the true minimum value, and the new
Cipher_Mode::ideal_granularity returns a value which is a multiple of
update_granularity sized for good performance.
If you are sizing buffers on the basis of update_granularity consider
using ideal_granularity instead. Otherwise you may encounter performance
regressions due to creating and processing very small buffers.
"SHA-160" and "SHA1"
---------------------
Previously the library accepted "SHA-160" and "SHA1" alternative names
for "SHA-1". This is no longer the case, you must use "SHA-1". Botan
2.x also recognizes "SHA-1".
PointGFp
------------
This type is now named ``EC_Point``
X509::load_key
-------------------
Previously these functions returned a raw pointer. They now return
a std::unique_ptr
PKCS11_Request::subject_public_key and X509_Certificate::subject_public_key
-----------------------------------------------------------------------------
These functions now return a unique_ptr
choose_sig_format removed
---------------------------
The freestanding functions choose_sig_format have been removed.
Use X509_Object::choose_sig_format
DLIES Constructors
--------------------
Previously the constructors to the DLIES classes took raw pointers,
and retained ownership of them. They now consume std::unique_ptrs
Credentials_Manager::private_key_for
-------------------------------------
Previously this function returned a raw pointer, which the Credentials_Manager
implementation had to keep alive "forever", since there was no way for it to
know when or if the TLS layer had completed using the returned key.
Now this function returns std::shared_ptr<Private_Key>
OID operator+
------------------------
OID operator+ allowed concatenating new fields onto an object identifier. This
was not used at all within the library or the tests, and seems of marginal
value, so it was removed.
If necessary in your application, this can be done by retrieving the
vector of components from your source OID, push the new element onto the vector
and create an OID from the result.
RSA with "EMSA1" padding
-------------------------
EMSA1 indicates that effectively the plain hash is signed, with no other
padding. It is typically used for algorithms like ECSDA, but was allowed for
RSA. This is now no longer implemented.
If you must generate such signatures for some horrible reason, you can pre-hash
the message using a hash function as usual, and then sign using a "Raw" padding,
which will allow you to sign any arbitrary bits with no preprocessing.
ECDSA/DSA with "EMSA1" padding
---------------------------------
Previous versions of Botan required using a hash specifier like "EMSA1(SHA-256)"
when generating or verifying ECDSA/DSA signatures, with the specified hash. The
"EMSA1" was a reference to a now obsolete IEEE standard.
In Botan 3 the "EMSA1" notation is still accepted, but now also it is possible
to simply use the name of the hash, eg "EMSA1(SHA-256)" becomes "SHA-256".
Signature Algorithm OIDs
-----------------------------
In line with the previous entries, previously Botan used a string like
"ECDSA/EMSA1(SHA-256)" to identify the OID 1.2.840.10045.4.3.2. Now it
uses the string "ECDSA/SHA-256" instead, and does not recognize the
EMSA1 variant at all (for example in ``OID::from_string``).
Public Key Signature Padding
-----------------------------
In previous versions Botan was somewhat lenient about allowing the application
to specify using a hash which was in fact incompatible with the algorithm. For
example, Ed25519 signatures are *always* generated using SHA-512; there is no
choice in the matter. In the past, requesting using some other hash, say
SHA-256, would be silently ignored. Now an exception is thrown, indicating the
desired hash is not compatible with the algorithm.
In previous versions, various APIs required that the application specify the
hash function to be used. In most cases this can now be omitted (passing an
empty string) and a suitable default will be chosen.
Discrete Logarithm Key Changes
--------------------------------
Keys based on the discrete logarithm problem no longer derive from the
DL_Scheme_PrivateKey and DL_Scheme_PublicKey classes; these classes
have been removed.
Functions to access DL algorithm internal fields (such as the integer value of
the private key using ``get_x``) have been removed. If you need access to this
information you can use the new ``get_int_field`` function.
The constructors of the DL scheme private keys have changed. Previously, loading
and creating a key used the same constructor, namely one taking arguments
``(DL_Group, RandomNumberGenerator&, BigInt x = 0)`` and then the behavior of
the constructor depend on if ``x`` was zero (in which case a new key was
created) or otherwise if ``x`` was non-zero then it was taken as the private
key. Now there are two constructors, one taking a random number generator and a
group, which generates a new key, and a second taking a group and an integer,
which loads an existing key.
XMSS Signature Changes
------------------------
The logic to derive WOTS+ private keys from the seed contained in the XMSS
private key has been updated according to the recommendations in
NIST SP 800-208. While signatures created with old private keys are still valid using
the old public key, new valid signatures cannot be created. To still support legacy
private XMSS keys, they can be used by passing ``WOTS_Derivation_Method::Botan2x`` to
the constructor of the ``XMSS_PrivateKey``.
Private XMSS keys created this way use the old derivation logic and can therefore
generate new valid signatures. It is recommended to use
``WOTS_Derivation_Method::NIST_SP800_208`` (default) when creating new XMSS keys.
Random Number Generator
-----------------------
Fetching a large number of bytes via `randomize_with_input()` from a stateful
RNG will now incorporate the provided "input" data in the first request to the
underlying DRBG only. This applies to such DRBGs that pose a limit on the number
of bytes per request (most notable ``HMAC_DRBG`` with a 64kB default). Botan 2.x
(erroneously) applied the input to *all* underlying DRBG requests in such cases.
Applications that rely on a static seed for deterministic RNG output might
observe a different byte stream in such cases. As a workaround, users are
advised to "mimick" the legacy behaviour by manually pulling from the RNG in
"byte limit"-sized chunks and provide the "input" with each invocation.

File diff suppressed because it is too large Load Diff

View File

@ -1,54 +0,0 @@
Notes for Distributors
========================
This document has information for anyone who is packaging copies of Botan for
use by downstream developers, such as through a Linux distribution or other
package management system.
Recommended Options
------------------------
In most environments, zlib, bzip2, and sqlite are already installed, so there is
no reason to not include support for them in Botan as well. Build with options
``--with-zlib --with-bzip2 --with-sqlite3`` to enable these features.
Set Path to the System CA bundle
---------------------------------
Most Unix/Linux systems maintain a list of trusted CA certificates at some well
known path like ``/etc/ssl/certs/ca-certificates.crt`` or
``/etc/ssl/cert.pem``. Unfortunately the exact path varies between systems. Use
``--system-cert-bundle=PATH`` to set this path. If the option is not used,
``configure.py`` tries a list of known locations.
Set Distribution Info
------------------------
If your distribution of Botan involves creating library binaries, use the
configure.py flag ``--distribution-info=`` to set the version of your
packaging. For example Foonix OS might distribute its 4th revision of the
package for Botan 2.1.3 using ``--distribution-info='Foonix 2.1.3-4'``. The
string is completely free-form, since it depends on how the distribution numbers
releases and packages.
Any value set with ``--distribution-info`` flag will be included in the version
string, and can read through the ``BOTAN_DISTRIBUTION_INFO`` macro.
Minimize Distribution Patches
------------------------------
We (Botan upstream) *strongly* prefer that downstream distributions maintain no
long-term patches against Botan. Even if it is a build problem which probably
only affects your environment, please open an issue on github and include the
patch you are using. Perhaps the issue does affect other users, and even if not
it would be better for everyone if the library were improved so it were not
necessary for the patch to be created in the first place. For example, having to
modify or remove a build data file, or edit the makefile after generation,
suggests an area where the build system is insufficiently flexible.
Obviously nothing in the BSD-2 license prevents you from distributing patches or
modified versions of Botan however you please. But long term patches by
downstream distributors have a tendency to bitrot and sometimes even result in
security problems (such as in the Debian OpenSSL RNG fiasco) because the patches
are never reviewed by the library developers. So we try to discourage them, and
work to ensure they are never necessary.

View File

@ -1,169 +0,0 @@
The following PGP key is used to sign all releases:
pub 2048R/EFBADFBC 2004-10-30
Key fingerprint = 621D AF64 11E1 851C 4CF9 A2E1 6211 EBF1 EFBA DFBC
uid Botan Distribution Key
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.17 (GNU/Linux)
mQELBEGD1j0BCADHxPJkPcjJE+4Dlisx2hVc0Dj6JI1MSLrkM8R+2bOhVUSferxP
T1EMPhfrAdOHTAloyvRThJztnZsNKqfLL49GGcBLdEGAVNks1pG37Teze5Lx1XIu
zJFrozL2sqBy5C6nHpFgd1tcD68Rah2wp0u2cR9owXf1IqKdEfuo661+MTv7wTB1
4hKV75nB7ZO6676SEZRILYM+7RJwKAKEmEPJc6hEf94VXn9ecNzaTlHgYkjhz9db
LOd3od9XvuUw+LMR1dwBqMxbvR90MiXjbedDEkbArcZB9YOAIvEX/lC3qaW4XJt4
iwHWl/YVZEfALcvQywe2CDrH5hO794wd9MpBAAYptBZCb3RhbiBEaXN0cmlidXRp
b24gS2V5iQEqBBMBAgAUAhsDAh4BAheABQJKfFpnBBUKCQgACgkQYhHr8e+637xk
PQf/aOi78XenwwvFrwXOVIVTdZIf8rK1zJksf26h09UD8uVV6z5iiTcpn86+eN9p
6Ar8IH3tD+JuFnPSwZ/r9MNC2XZwenYo4Gb14jqM6/9hBe328vmeM4Y1G7bD4HrL
kgV5WEyokqm3zbp3FBLr3Vh68TAC5JB9aHevra+cCA2u3vBNI3YUM5z4TdO150P3
J00whkqImQEUni8bgxvllBLFM+uhucsX3HZWkoDEpotbg8yd0bqMkiPEyMr1OnJq
eDVDMrB5wnyLgLFfRAAw3mopM0C1PNOAHr/BIYiaDHX2OwnOfep8rMDoRVf2Ge0D
DBgsJJ6LduQHLeg403SHWL2F6YkCHAQTAQIABgUCQYPWUgAKCRBcD5boTsFta+r9
EACWVis7YcaGkKKgRB/5ox8rM36XVhMXdh/hnnGHt5rapbbRRkRHRcWU8WIcFO1A
59+TfwNNd8gN1MEt/5aX5KHWVKHBDexJgIxm6Dm1pisYHf/dnYQPM18hmqqwNlKY
97hFkPpHd7enrtc/SvGbQhhLXYlpwBrdMl76e9xJLnnrRQksxegGPo8cr+C9HTs1
Lwa8zzBxyBwYBYX+0moDkDShEhuXx6mEOXrGvQanJuIvpoIwGH+62E65MbJGlwWp
w/MAtm2jFhBIhGV0bqJCFp9zIgdNgfskBaPr0oilbuJQZqP0Iqe/6CCt4XkS51yW
ZqxjLAFpEpvDec4PGw3witKf/koGon9X8C035+nEjLBrWy18Q91vw2USyLI+mm9d
iMAS8pY2gomfxBO2VwYHJryZykjCYQkccRA1tHteRj4gqTObo0Ak47y5MnplTWwi
40oP7K2cfhCRBmMioxmYES4xsHEupfRBo3xr1Jq9q0t688WTT1NXHPMPoueF9mKZ
Cf2pa9aHsqBmWTm3sCaNQKGubCDBEUmJUyndmSatJyYM7NVYoUp6EfqMACFuTNdB
sjKMh7aWVikQpbJDfA1BIU3lZeqgjgrghVAWkEOBfhG0IVZj+RVCJpsqoTJ8asY2
VreArSCyr/VnLEnfuH/QpgvCiCbepo3E34DJt4SaAOO2ZohGBBARAgAGBQJMGVc1
AAoJEKY/LL36AvvMgsoAn2G7kXd09BF7ffk1Sfh174SVrvM9AKC7+R7x0+yV3SCd
JkkUOo3xR5cOxw==
=1QuR
-----END PGP PUBLIC KEY BLOCK-----
This key can be used to contact the primary maintainer:
pub rsa3072/57123B60 2015-03-23
Key fingerprint = 4E60 C735 51AF 2188 DF0A 5A62 78E9 8043 5712 3B60
uid Jack Lloyd <jack@randombit.net>
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQGNBFUQXRMBDACZJvcSkr+GNDtIdP9fQWRXByriiIKvuKbqU8KGdhTcPeKwl3y3
l1W9XsWA2DJ8QDKo4ZcV0lycszIvwBLZllJJWSVNFKxJK2IW33xcIo9dhNqj+hcz
LxKtBlBU3QKXdQ9+VKSY4EpO6gt/ar21PV+EQcFA9UtT1mRKVqY0pGGxqfQjrOss
rJKoJyA+1trH4ir7+0/524HNzsBj3B1GmrYfstspqetXyVQ1DoFiThUnj/zJGes5
uW9laI9VBgrtMTBbYrylBytXiF0Flzx+bd21krgL37NH2uU0EHPjSx571q/XGG2U
4iOEPvPu7vtV8Rpqd0xQyaHcpoHNklcfND1c/6uZG1Sx9atDScRYHinUZvtTRtN+
OY5vW+H7LJqT6CeMjh6Ev53V+0JCDZFQLaBdP/NanSQBUhPkyfyQSiqWOSuaMD6n
Eu+BigmzwDlsauuReTJ65gdIGI9Egt7Ax/ooKpBvPkWeT+GORKTs+qGy6sbKXrTe
crFFN/HZPWAJ+c8AEQEAAbQfSmFjayBMbG95ZCA8amFja0ByYW5kb21iaXQubmV0
PokB0QQTAQoAOwIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgBYhBE5gxzVRryGI
3wpaYnjpgENXEjtgBQJlIUveAhkBAAoJEHjpgENXEjtg9d0L/iMxl7bVhwrRNUDo
fdxZoCVPqPBnA29uiwN4Ff8VIr5yiA39DYAD14PoQN8+mVc9+0P5ersLanszSg7b
ZMLd1s39Ryydy2YfXqk9jHlDOFpsimknAd+NEYYPrRTQ+dybk9qoL/qeNxZl7Oig
/GyMS96I9PDHLx43gBe4OsIe+QB2ulgVTMIDwnMyeuaIDRmL+w4+caTxKBj4fwtV
3SN1VSugEV1Uli0Ofk1yp+NsEIVyOJCi7mV/KLmffdAMqSoBnHZvNqz65i4Tt2mV
PvEb5Xvh5E4HBGLCFNj5XEFZmWvjOhkx7XyaJBqHS2I3j/JWGhpLDXwITlpQLBMi
ssstlL4ju+STOCfGWDQjOxFGelgbjD54Pu2N/TlidT5FORLguR0Eqtb0A6gYybNh
UY/dJqbSPegd9xFWszrnO5o7sV3O1x5oWIOkEi/IYhy9SschPPi3m5RI7qJt6PRI
TfF5IBx9GQQtDnrQnbCHB3+BkVuixbEOORmYxm1sR79NE8UTerQgSmFjayBMbG95
ZCA8bGxveWRAcmFuZG9tYml0Lm5ldD6JARwEEAEIAAYFAlYaUEwACgkQYhHr8e+6
37zLeQf+OdP/xE2YyFUJL1+xEKHpvAeN+98Vn1C2sTmotNIaPwVBY9FLeA484IWd
FwnJfXx1gQyybxlytz4BZuC7Jzu60OEmk5IFRIqQoVywEXWCOUg/UEBWZm+ZcRzI
Fciqj9PcOfpt6s/aSZd5+Rcm5HUGALYCqek2s9nGO8a1Wnk4m9d1u/RAGlxFM2th
e1v5p597ItGhcOP3tjWVPPOuTe0E+/FI3ZxpotKGdfS6F/GB2bP7kma2iVO621Cs
9wsYmrZEamKpax7X7p9myaAG0YRdCTslFd/EOTLOllPhy58DTr7qyswBPEI0x8WE
DTE0G0IdQYNmLq4kuzeOaIlcUMULzYkBuQQTAQIAIwUCVRBdEwIbAwcLCQgHAwIB
BhUIAgkKCwQWAgMBAh4BAheAAAoJEHjpgENXEjtgjxoL/0ZjgM16mq2imrViVjVe
u3IuDe0bMq8lUdfDTuQZmK68U5hclwPO4qEVoa4grEn7s++t45fJwP/39YVfILC+
FzMyBtF/eUWqSNB2a+fCYgZR9kvemqiskN1KMqJpeTz80kEQEeVM3X31sUQJPMGv
jyR4YevNQ9RiHZTfCjwI1blmwcceaJuN6g6l90uAr52dQ3A6Tf+cRm1ZR31xPAKd
3m/LG3sjWnWe1vcksAR3jPnB3Zp8kduNBne6JNAFcNR3U8Ufojp8jsv5R5T60Y09
7d97ob7M2HGYk8oE8TDNMD+vqK4utDA0Edg9ibon98oENTXXsefC7Phb1FJVWu2L
MJYhtroSm0V6dyKCu4Ido7gJZsWXvUK7yfqJsQg0d0qkT2pDNIPmQd/CwnoVWeX1
CTzImqH1Ts0X8LyEctukX0nmfhZ83epnIWlQxuwRWnpGG/85ufHBqo1hYKoLKIJr
Cw2T/+Szhev4eZ48ndcD2XO+BUKgwStr6fVFscIQYialSYkB0AQTAQoAOgIbAwcL
CQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAFiEETmDHNVGvIYjfClpieOmAQ1cSO2AF
AmUhSvkACgkQeOmAQ1cSO2A22QwAk8/mcCQOeBn8mHgeoYiaSTW1JoIC0fIagMPh
hp2eAbPofk/I3L443t31Ye4YSMjqF7YiyNo063qBBQoyok4kT3hftnIrml8CwIO0
33pREPKg3dgU/t+4cOIFlBYiCYn5T3SLjGAL5vlxzTmSKX1Xu79uo+EKa7G2u5hM
Gpz5rDXkPgSyZ19/uDu+01CG+JlwHgwOh8bZQSu0/Jg8Qu0ecc87ENpR+eFXqlSL
hzdYJ6XPTC6RN/LQFLxTcR8TQ15ThRK6LEocZadg1kJDeadcdM8aRYPI2S7aLCha
MnqUzckYdDSW40Bsg0PdxNKTDSBoa7vPbDMR/XkAd03bRGzdezxbr7m7SHOzjnmY
SXhAlnkVH6ouSM0GFarWqIeMe6isDiKX8LKdWNySEiMuSuTz2KX15ZedOcYPksdb
DfC0tuQUL6O3plsIGJWy9fVOrLnW6D+P77AlHQsRe7OxlFo3Jhsf4FdsD4cLXVN4
r/fngFYkokBOv3rGp+aXcEF5uYKAtCFKYWNrIExsb3lkIDxqYWNrLmxsb3lkQGdt
YWlsLmNvbT6JAc4EEwEKADgCGwMFCwkIBwIGFQgJCgsCBBYCAwECHgECF4AWIQRO
YMc1Ua8hiN8KWmJ46YBDVxI7YAUCZSFK4QAKCRB46YBDVxI7YGvdC/4jdtd4Qfo2
i4VUmOrjJ1sFiSehutOCsTAweDDyqUjxmXaMLOlPAeVp9Nq/kUtO4qtLac5sRBxX
KigxjrBYJpBq0cK9nYnMEHdX86uXhfvclFQIxzvwkC3pYQgZcD9XfduUTiJeNGrh
mQbyopcfbKzv3Q5j4v1H4s61L3LySIDxvZYvzgQEcCrG89+gxlsG2eWMuPySBICE
skEAe/2rLuGKcSSFTJXpVAkB9r8o9cOHSw63BydvL5o1T1KeDs4cZD1KUlJ2VaBf
W1IoaXynUIHcti1h8iHWNifirgtSRSezz5/G3JeQ8cUSyC4bkMXmQulrHUUCuhZ6
GxqtxAEQ8rUrNV8G9xZrU0VP1un3c0RGS4kz2IKa1uk1FEnxDa6YQaExwrHbWzR0
8YX1zl7/lekdE1tjRrqIdpzu84MiLHraEvX5agrbdv3F59cJB5lYTXsYaX/8rgus
AFdFAQA87MfUKVo38fBZF4BKFu8goGUP7UeGIuZGExavIAjzQkDrUwO5AY0EVRBd
EwEMAN6NE/fR/Ours4jc6SaVocKSZ+/pGXVrxQ/ZFoba7kJq09DLQZ21vHYkq7wM
rAta9D6gH5bLZ90xI6ScyR9fYTWYDXdDHx8Sg7Mj3ZKhxjr1tQicRPT6BP4WLqBI
CdlUWV//OCRFk13G8feDO+ZT8YP/dVUrj3n9/mwfOHm7Npb7PHX/LFuDyo/1EXZZ
yqw3/LlI+z+1uBKFYD2WqzLw8Sm/U+ajzP6y04wUkf45VjLkFI2bPk6CVYNt2TvO
EzIO3zBAN6DSLSFOTYn9UwR2vrpvoJsDjjSRjcjbZ/8uFCWfLhgTwMeQcH0jxHr4
7Qs2coApHBAIB57eS6Z/y4Vja3Y0ANpb51Fu7MDPXQXW4g89GMTIEKu2/KUN/onG
IYh6Js9RYNf8SJ+waQ0NULXAMk1AAfknl2Apl9gKRDH6EvevQXPVI6ElOTZw4gqG
z9xGqC+gbmh2UmS5n8B/nK2d0AMN+1elZAapTFFdOMhMdDeBk+1GRQ/t/zsLTUPS
SRVLFwARAQABiQGfBBgBAgAJBQJVEF0TAhsMAAoJEHjpgENXEjtg3rgMAIDJgnuE
Y7neuJMIzHyO59a8X+9ip9XfeDNwjaqJk0rIoqSdkIqjG8I6C4lbeL0pnGzliudv
EmQij4hnSNfOUk58oGyRdyUeK9eC2KeZ+Hs3sqMuAhlYIh+RR6ifo5kqxR/geo6i
XKS8VqDQRiqoSSrLqhIU7kQiFcQWc3wYaSOUXNpZzvlTlMYM4qP9Yrzu8dG1tKST
3fmWi8l9/TmHIPtskgB0dzTdkKe2kZpJFFquYtorWtCQwF+wmtA02NMHwrQzwh/R
qNz9wUEwhQVBa/A8p0wdEskLFQZXt3PnY8GHQVz59tArolw3kes0/VrtgCUFS7tv
mn9xI6lJxveQiN6Ec2z5gbwKBShkSvopi0g83YLeSNPrCIBmLSCOm1AjsXF3sQaz
EYqAGhB6qibCsuebxnprq8Qa/j0wsq7n8ZO7a6cdcnhu4fF3YdWcaWlCUKzzWb8W
XXoeCaOKxmD5IgsGiAxnPKvsBge1rMhlCoJJhJEmUlwxoP67Nt2mHbYh/Q==
=4XG/
-----END PGP PUBLIC KEY BLOCK-----
This key is used for signing git commits:
pub rsa2048 2016-03-03 [SC] [expires: 2028-03-01]
117510149DF418ABD19CB06D9FFD596FAB50F90D
uid Jack Lloyd (Git Signing Key) <jack@randombit.net>
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBFbYWi4BCACjgz3gYgWMybPLiovNLnLonG0ex2y9kJgsR+Pm08L2fwCVCaHx
wjlK5Oq04x3bvujZk7P0TThqS1WonYtEiVxz3Hcvt7rlU5fSCj/1uYmZV+mbPBdY
f/yXMx3UD1UkZrdzbM21L78dfOoLZ2ybyuk4QOEad/AkouDCUA2pY3DJdNyX8Aee
dBdQ+sQqF6DyDz4SDY+KAq3nFmmT04bdkiL9sZb2HUokxIdeA6HIR+CxxFaZzrYW
Ky4iNPS1Zxv5D1KmpZzUOfN9RTgkbdRltgWxjpB+DFNUkpu3hYm/Y9lTPqGBt2C8
JfIS5OaHxUVz0A+DtIGy+lk8/O5ek4suQBZ3ABEBAAG0MUphY2sgTGxveWQgKEdp
dCBTaWduaW5nIEtleSkgPGphY2tAcmFuZG9tYml0Lm5ldD6JAVcEEwEIAEECGwMF
CwkIBwIGFQgJCgsCBBYCAwECHgECF4ACGQEWIQQRdRAUnfQYq9GcsG2f/Vlvq1D5
DQUCZAH4lgUJFo+f6AAKCRCf/Vlvq1D5DfCYB/0TXJ9WuuL5cgXJLK6IyvrlJJvp
mncY2PDzfscgO8jWLGfnhOO/Fiy6JvSXmllgNiSufNbaaq3c9wx+qXY7qqUbwiM8
w0bokFyVCbIc+Y7d7q359mdFFx0U8NWuQStkeGQ7GcckMLZ2rftY4fyBgeL0MiuH
YpzWpFgvmllB+vVniHAh79VMQqnR42Y7r6W5XWYmz6AmpBlI7IOLY272k6nyu7Qr
SGlKVU3XctvKS8RAEqvD6CSbls9tXcEZ9XEcOxvUPAgb+NRN7aXbHed3eE8s4NBY
Z2vPDgPBCQ423PRnB+McFVHA+N7fdMGOcxkkDi0F1DcgSAcyMuiJFns88BKgiQE9
BBMBCAAnBQJYD2ybAhsDBQkHhM4ABQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJ
EJ/9WW+rUPkNXfIIAIOgepYeZN2HL2T3A8pk+5JR2cfBoRufYgnG6mVHPejgZDW+
9PH1tPDgidnePw3/jfD1oskt1VwOCkqaSBAcG2QeOBEklcsrQuvOfW7B7XFydYGw
T9Fm8/sxekiGjDQQWQEEH4j3Vt1GlI2sJrpqMe/WMXISsEnLfw0kDspUSlFOn8oy
rBU9Pd8KaSi38lp05a9Mcun5enJ3JpQHQ5RlNXDNh/Sn9NZ+MKWggytZqIy82jnv
6zo0raZDup4hLKopjen/SINR5XcwRK2lUtYVwwQH8FHG9IkeVJNWJkVCdZLB08sq
4WHRbtVjy6mpvEHTmolAtHjLSiV5W50LDKLwX260MkphY2sgTGxveWQgKEdpdCBT
aWduaW5nIEtleSkgPGxsb3lkQHJhbmRvbWJpdC5uZXQ+iQFUBBMBCAA+AhsDBQsJ
CAcCBhUICQoLAgQWAgMBAh4BAheAFiEEEXUQFJ30GKvRnLBtn/1Zb6tQ+Q0FAmQB
+J0FCRaPn+gACgkQn/1Zb6tQ+Q1DIAgAlR0igunTJjz38Zs9M8rWr5OzeG9Hbkse
mClFcH2TPGxLIjI5eMLLjVbxyQkeP2rjaZb/bnuzrohQ5X6Le0LZQA77khFkWpRZ
HQ0wDHGSLlLeSD9BiPmhf4drDf8/M+QXA5kTxEHMyKxPsLaOhXYgHPyYQcS3R+H4
6jIVmCB5PyYynsSKhFoUiFcBbURApAagaUTf/TGzcaXDGzKkdA6X5g1xlLt+3GTK
3aKwOLN7RhMYLz1V6FwblLUYSgpwuAmDfGayNVcBkhK/Qg4yPT0M25H5tLrELh2L
fvkeuV29sD3005sI3t+4T4yTCNOCcahaRCaFfUKpyZk7OyUYXRAPaokBnAQQAQgA
BgUCVthcNwAKCRB46YBDVxI7YLwrC/95sk2uEyiScbl1I9UmknEvS1r+bgpgGNf3
hWwHo5/P3pSac2UJ70TFuLTZ5wvKBB8H1RS/ueys5EY5KggQhX9FJiA3Z5hQzbUM
d12WBUbcNNGsb/+JXqvMB2CRl1GTEGGfN4UlG/hMyadFBczbH6COiCcNYumOB2+R
EVy/mXp9MfbgiV1x3Kae+aoGawu+qgoWPXcK2wOOeCnmAaCn+J4hbqw+aBBfWkkJ
YcUN7/SpyO+7LR8oyrQ7J3T/x1cKc1rA9v/3GVBj6UKkcgt+8WxW3Ll2OoeoM0oQ
G5jHI+McgI8ZG6RIr7MJLQQTyfP+jGivg4ivmy9rB8g7lnDr1RKjTWML4rU5JElC
2EV+3kapPCR8eeJglJWHsrWs8j8ffm1/5dksHCVp9azu9Bvxdl8A/OGrD1uVzlFL
jvyurM1DQXU8chONtpIKQwKBo1rZp5qgjD25COnq4HZPjEYB6qx3ok+uvmDVVkU+
q2Fd2IO7omY3hpWSwb9ILHYLC/aqK5I=
=fsUW
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -1,43 +0,0 @@
Development Roadmap
========================================
Near Term Plans
----------------------------------------
Here is an outline for the development plans over the next 12-24 months,
as of February 2023.
Botan 2
---------------
Botan 2 is still supported, but no further feature work is planned.
Only security issues and serious bugs will be addressed.
Botan 3
---------------
The following future work is currently planned for Botan 3:
* BSI Project 481 [https://github.com/randombit/botan/issues/3108]
will add several new post-quantum algorithms including SPHINCS+
signatures, LMS signatures, FrodoKEM, and Classic McEliece.
* New ECC based password authenticated key exchanges, to replace SRP.
The most likely candidate algorithms are CPace, OPAQUE, or SPAKE2+.
* Adding an implementation of BLS12-381 elliptic curve pairing.
* Low level integer math and elliptic curve arithmetic optimizations.
Botan 4
---------------
At this time there is no immediate plan for a new major version. When it occurs,
it will remove functionality currently marked as deprecated, and adopt a new C++
version. This is unlikely to occur before 2026, at the earliest.
One major change already planned for Botan 4 is that in this release, Public_Key
will no longer derive from Private_Key. And similarly, specific private keys
(for example RSA_PrivateKey) will no longer derive from their cooresponding
public key type.

View File

@ -1,390 +0,0 @@
.. highlight:: none
Security Advisories
========================================
If you think you have found a security bug in Botan please contact
Jack Lloyd (jack@randombit.net). If you would like to encrypt your
mail please use::
pub rsa3072/57123B60 2015-03-23
Key fingerprint = 4E60 C735 51AF 2188 DF0A 5A62 78E9 8043 5712 3B60
uid Jack Lloyd <jack@randombit.net>
This key can be found in the file ``doc/pgpkey.txt`` or online at
https://keybase.io/jacklloyd and on most PGP keyservers.
2022
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* 2022-11-16: Failure to correctly check OCSP responder embedded certificate
OCSP responses for some end entity are either signed by the issuing CA certificate of
the PKI, or an OCSP responder certificate that the PKI authorized to sign responses in
their name. In the latter case, the responder certificate (and its validation path
certificate) may be embedded into the OCSP response and clients must verify that such
certificates are indeed authorized by the CA when validating OCSP responses.
The OCSP implementation failed to verify that an authorized responder certificate
embedded in an OCSP response is authorized by the issuing CA. As a result, any valid
signature by an embedded certificate passed the check and was allowed to make claims
about the revocation status of certificates of any CA.
Attackers that are in a position to spoof OCSP responses for a client could therefore
render legitimate certificates of a 3rd party CA as revoked or even use a compromised
(and actually revoked) certificate by spoofing an OCSP-"OK" response. E.g. an attacker
could exploit this to impersonate a legitimate TLS server using a compromised
certificate of that host and get around the revocation check using OCSP stapling.
Introduced in 1.11.34, fixed in 2.19.3
2020
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* 2020-12-21 (CVE-2021-24115): Codec encoding/decoding was not constant time
The base64, base32, base58 and hex encoding/decoding routines used lookup
tables which could leak information via a cache-based side channel attack.
The encoding tables were small and unlikely to be exploitable, but the
decoding tables were large enough to cause non-negligible information
leakage. In particular parsing an unencrypted PEM-encoded private key within
an SGX enclave could be easily attacked to leak key material.
Identified and reported by Jan Wichelmann, Thomas Eisenbarth,
Sebastian Berndt, and Florian Sieck.
Fixed in 2.17.3
* 2020-07-05: Failure to enforce name constraints on alternative names
The path validation algorithm enforced name constraints on the primary DN
included in the certificate but failed to do so against alternative DNs which
may be included in the subject alternative name. This would allow a corrupted
sub-CA which was constrained by a name constraints extension in its own
certificate to issue a certificate containing a prohibited DN. Until 2.15.0,
there was no API to access these alternative name DNs so it is unlikely that
any application would make incorrect access control decisions on the basis of
the incorrect DN. Reported by Mario Korth of Ruhr-Universität Bochum.
Introduced in 1.11.29, fixed in 2.15.0
* 2020-03-24: Side channel during CBC padding
The CBC padding operations were not constant time and as a result would leak
the length of the plaintext values which were being padded to an attacker
running a side channel attack via shared resources such as cache or branch
predictor. No information about the contents was leaked, but the length alone
might be used to make inferences about the contents. This issue affects TLS
CBC ciphersuites as well as CBC encryption using PKCS7 or other similar padding
mechanisms. In all cases, the unpadding operations were already constant time
and are not affected. Reported by Maximilian Blochberger of Universität
Hamburg.
Fixed in 2.14.0, all prior versions affected.
2018
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* 2018-12-17 (CVE-2018-20187): Side channel during ECC key generation
A timing side channel during ECC key generation could leak information about
the high bits of the secret scalar. Such information allows an attacker to
perform a brute force attack on the key somewhat more efficiently than they
would otherwise. Found by Ján Jančár using ECTester.
Introduced in 1.11.20, fixed in 2.8.0.
* 2018-06-13 (CVE-2018-12435): ECDSA side channel
A side channel in the ECDSA signature operation could allow a local attacker
to recover the secret key. Found by Keegan Ryan of NCC Group.
Bug introduced in 2.5.0, fixed in 2.7.0. The 1.10 branch is not affected.
* 2018-04-10 (CVE-2018-9860): Memory overread in TLS CBC decryption
An off by one error in TLS CBC decryption meant that for a particular
malformed ciphertext, the receiver would miscompute a length field and HMAC
exactly 64K bytes of data following the record buffer as if it was part of the
message. This cannot be used to leak information since the MAC comparison will
subsequently fail and the connection will be closed. However it might be used
for denial of service. Found by OSS-Fuzz.
Bug introduced in 1.11.32, fixed in 2.6.0
* 2018-03-29 (CVE-2018-9127): Invalid wildcard match
RFC 6125 wildcard matching was incorrectly implemented, so that a wildcard
certificate such as ``b*.domain.com`` would match any hosts ``*b*.domain.com``
instead of just server names beginning with ``b``. The host and certificate
would still have to be in the same domain name. Reported by Fabian Weißberg of
Rohde and Schwarz Cybersecurity.
Bug introduced in 2.2.0, fixed in 2.5.0
2017
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* 2017-10-02 (CVE-2017-14737): Potential side channel using cache information
In the Montgomery exponentiation code, a table of precomputed values
is used. An attacker able to analyze which cache lines were accessed
(perhaps via an active attack such as Prime+Probe) could recover
information about the exponent. Identified in "CacheD: Identifying
Cache-Based Timing Channels in Production Software" by Wang, Wang,
Liu, Zhang, and Wu (Usenix Security 2017).
Fixed in 1.10.17 and 2.3.0, all prior versions affected.
* 2017-07-16: Failure to fully zeroize memory before free
The secure_allocator type attempts to zeroize memory before freeing it. Due to
a error sometimes only a portion of the memory would be zeroed, because of a
confusion between the number of elements vs the number of bytes that those
elements use. So byte vectors would always be fully zeroed (since the two
notions result in the same value), but for example with an array of 32-bit
integers, only the first 1/4 of the elements would be zeroed before being
deallocated. This may result in information leakage, if an attacker can access
memory on the heap. Reported by Roman Pozlevich.
Bug introduced in 1.11.10, fixed in 2.2.0
* 2017-04-04 (CVE-2017-2801): Incorrect comparison in X.509 DN strings
Botan's implementation of X.509 name comparisons had a flaw which
could result in an out of bound memory read while processing a
specially formed DN. This could potentially be exploited for
information disclosure or denial of service, or result in incorrect
validation results. Found independently by Aleksandar Nikolic of
Cisco Talos, and OSS-Fuzz automated fuzzing infrastructure.
Bug introduced in 1.6.0 or earlier, fixed in 2.1.0 and 1.10.16
* 2017-03-23 (CVE-2017-7252): Incorrect bcrypt computation
Botan's implementation of bcrypt password hashing scheme truncated long
passwords at 56 characters, instead of at bcrypt's standard 72 characters
limit. Passwords with lengths between these two bounds could be cracked more
easily than should be the case due to the final password bytes being ignored.
Found and reported by Solar Designer.
Bug introduced in 1.11.0, fixed in 2.1.0.
2016
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* 2016-11-27 (CVE-2016-9132) Integer overflow in BER decoder
While decoding BER length fields, an integer overflow could occur. This could
occur while parsing untrusted inputs such as X.509 certificates. The overflow
does not seem to lead to any obviously exploitable condition, but exploitation
cannot be positively ruled out. Only 32-bit platforms are likely affected; to
cause an overflow on 64-bit the parsed data would have to be many gigabytes.
Bug found by Falko Strenzke, cryptosource GmbH.
Fixed in 1.10.14 and 1.11.34, all prior versions affected.
* 2016-10-26 (CVE-2016-8871) OAEP side channel
A side channel in OAEP decoding could be used to distinguish RSA ciphertexts
that did or did not have a leading 0 byte. For an attacker capable of
precisely measuring the time taken for OAEP decoding, this could be used as an
oracle allowing decryption of arbitrary RSA ciphertexts. Remote exploitation
seems difficult as OAEP decoding is always paired with RSA decryption, which
takes substantially more (and variable) time, and so will tend to mask the
timing channel. This attack does seems well within reach of a local attacker
capable of a cache or branch predictor based side channel attack. Finding,
analysis, and patch by Juraj Somorovsky.
Introduced in 1.11.29, fixed in 1.11.33
* 2016-08-30 (CVE-2016-6878) Undefined behavior in Curve25519
On systems without a native 128-bit integer type, the Curve25519 code invoked
undefined behavior. This was known to produce incorrect results on 32-bit ARM
when compiled by Clang.
Introduced in 1.11.12, fixed in 1.11.31
* 2016-08-30 (CVE-2016-6879) Bad result from X509_Certificate::allowed_usage
If allowed_usage was called with more than one Key_Usage set in the enum
value, the function would return true if *any* of the allowed usages were set,
instead of if *all* of the allowed usages are set. This could be used to
bypass an application key usage check. Credit to Daniel Neus of Rohde &
Schwarz Cybersecurity for finding this issue.
Introduced in 1.11.0, fixed in 1.11.31
* 2016-03-17 (CVE-2016-2849): ECDSA side channel
ECDSA (and DSA) signature algorithms perform a modular inverse on the
signature nonce `k`. The modular inverse algorithm used had input dependent
loops, and it is possible a side channel attack could recover sufficient
information about the nonce to eventually recover the ECDSA secret key. Found
by Sean Devlin.
Introduced in 1.7.15, fixed in 1.10.13 and 1.11.29
* 2016-03-17 (CVE-2016-2850): Failure to enforce TLS policy
TLS v1.2 allows negotiating which signature algorithms and hash functions each
side is willing to accept. However received signatures were not actually
checked against the specified policy. This had the effect of allowing a
server to use an MD5 or SHA-1 signature, even though the default policy
prohibits it. The same issue affected client cert authentication.
The TLS client also failed to verify that the ECC curve the server chose to
use was one which was acceptable by the client policy.
Introduced in 1.11.0, fixed in 1.11.29
* 2016-02-01 (CVE-2016-2196): Overwrite in P-521 reduction
The P-521 reduction function would overwrite zero to one word
following the allocated block. This could potentially result
in remote code execution or a crash. Found with AFL
Introduced in 1.11.10, fixed in 1.11.27
* 2016-02-01 (CVE-2016-2195): Heap overflow on invalid ECC point
The PointGFp constructor did not check that the affine coordinate
arguments were less than the prime, but then in curve multiplication
assumed that both arguments if multiplied would fit into an integer
twice the size of the prime.
The bigint_mul and bigint_sqr functions received the size of the
output buffer, but only used it to dispatch to a faster algorithm in
cases where there was sufficient output space to call an unrolled
multiplication function.
The result is a heap overflow accessible via ECC point decoding,
which accepted untrusted inputs. This is likely exploitable for
remote code execution.
On systems which use the mlock pool allocator, it would allow an
attacker to overwrite memory held in secure_vector objects. After
this point the write will hit the guard page at the end of the
mmap'ed region so it probably could not be used for code execution
directly, but would allow overwriting adjacent key material.
Found by Alex Gaynor fuzzing with AFL
Introduced in 1.9.18, fixed in 1.11.27 and 1.10.11
* 2016-02-01 (CVE-2016-2194): Infinite loop in modular square root algorithm
The ressol function implements the Tonelli-Shanks algorithm for
finding square roots could be sent into a nearly infinite loop due
to a misplaced conditional check. This could occur if a composite
modulus is provided, as this algorithm is only defined for primes.
This function is exposed to attacker controlled input via the OS2ECP
function during ECC point decompression. Found by AFL
Introduced in 1.7.15, fixed in 1.11.27 and 1.10.11
2015
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* 2015-11-04: TLS certificate authentication bypass
When the bugs affecting X.509 path validation were fixed in 1.11.22, a check
in Credentials_Manager::verify_certificate_chain was accidentally removed
which caused path validation failures not to be signaled to the TLS layer. So
for affected versions, certificate authentication in TLS is bypassed. As a
workaround, applications can override the call and implement the correct
check. Reported by Florent Le Coz in GH #324
Introduced in 1.11.22, fixed in 1.11.24
* 2015-10-26 (CVE-2015-7824): Padding oracle attack on TLS
A padding oracle attack was possible against TLS CBC ciphersuites because if a
certain length check on the packet fields failed, a different alert type than
one used for message authentication failure would be returned to the sender.
This check triggering would leak information about the value of the padding
bytes and could be used to perform iterative decryption.
As with most such oracle attacks, the danger depends on the underlying
protocol - HTTP servers are particularly vulnerable. The current analysis
suggests that to exploit it an attacker would first have to guess several
bytes of plaintext, but again this is quite possible in many situations
including HTTP.
Found in a review by Sirrix AG and 3curity GmbH.
Introduced in 1.11.0, fixed in 1.11.22
* 2015-10-26 (CVE-2015-7825): Infinite loop during certificate path validation
When evaluating a certificate path, if a loop in the certificate chain
was encountered (for instance where C1 certifies C2, which certifies C1)
an infinite loop would occur eventually resulting in memory exhaustion.
Found in a review by Sirrix AG and 3curity GmbH.
Introduced in 1.11.6, fixed in 1.11.22
* 2015-10-26 (CVE-2015-7826): Acceptance of invalid certificate names
RFC 6125 specifies how to match a X.509v3 certificate against a DNS name
for application usage.
Otherwise valid certificates using wildcards would be accepted as matching
certain hostnames that should they should not according to RFC 6125. For
example a certificate issued for ``*.example.com`` should match
``foo.example.com`` but not ``example.com`` or ``bar.foo.example.com``. Previously
Botan would accept such a certificate as also valid for ``bar.foo.example.com``.
RFC 6125 also requires that when matching a X.509 certificate against a DNS
name, the CN entry is only compared if no subjectAlternativeName entry is
available. Previously X509_Certificate::matches_dns_name would always check
both names.
Found in a review by Sirrix AG and 3curity GmbH.
Introduced in 1.11.0, fixed in 1.11.22
* 2015-10-26 (CVE-2015-7827): PKCS #1 v1.5 decoding was not constant time
During RSA decryption, how long decoding of PKCS #1 v1.5 padding took was
input dependent. If these differences could be measured by an attacker, it
could be used to mount a Bleichenbacher million-message attack. PKCS #1 v1.5
decoding has been rewritten to use a sequence of operations which do not
contain any input-dependent indexes or jumps. Notations for checking constant
time blocks with ctgrind (https://github.com/agl/ctgrind) were added to PKCS
#1 decoding among other areas. Found in a review by Sirrix AG and 3curity GmbH.
Fixed in 1.11.22 and 1.10.13. Affected all previous versions.
* 2015-08-03 (CVE-2015-5726): Crash in BER decoder
The BER decoder would crash due to reading from offset 0 of an empty vector if
it encountered a BIT STRING which did not contain any data at all. This can be
used to easily crash applications reading untrusted ASN.1 data, but does not
seem exploitable for code execution. Found with afl.
Fixed in 1.11.19 and 1.10.10, affected all previous versions of 1.10 and 1.11
* 2015-08-03 (CVE-2015-5727): Excess memory allocation in BER decoder
The BER decoder would allocate a fairly arbitrary amount of memory in a length
field, even if there was no chance the read request would succeed. This might
cause the process to run out of memory or invoke the OOM killer. Found with afl.
Fixed in 1.11.19 and 1.10.10, affected all previous versions of 1.10 and 1.11
2014
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* 2014-04-10 (CVE-2014-9742): Insufficient randomness in Miller-Rabin primality check
A bug in the Miller-Rabin primality test resulted in only a single random base
being used instead of a sequence of such bases. This increased the probability
that a non-prime would be accepted by is_prime or that a randomly generated
prime might actually be composite. The probability of a random 1024 bit
number being incorrectly classed as prime with a single base is around 2^-40.
Reported by Jeff Marrison.
Introduced in 1.8.3, fixed in 1.10.8 and 1.11.9

View File

@ -1,32 +0,0 @@
Semantic Versioning
=====================
Starting with 2.0.0, Botan adopted semantic versioning. This means we endevour
to make no change which will either break compilation of existing code, or cause
different behavior in a way that will cause compatability issues. Such changes
are reserved for new major versions.
If on upgrading to a new minor version, you encounter a problem where your
existing code either fails to compile, or the code behaves differently in some
way that causes trouble, it is probably a bug; please report it on Github.
Exception
-----------------------
There is an important exception to the SemVer guarantees that you should be
aware of. If you in your application derive a new class from a class in the
library, we do not guarantee a future minor release will not break your
code. For example, we may in a minor release introduce a new pure virtual
function to a base class like ``BlockCipher``, and implement it for all
subclasses within the library. In this case your code would fail to compile
until you implemented the new virtual function. Or we might rename or remove a
protected function, or a protected member variable.
There is also an exception to this exception! The following classes are intended
for derivation by applications, and are fully covered by SemVer:
* ``Credentials_Manager``
* ``Entropy_Source``
* ``TLS::Callbacks``
* ``TLS::Policy`` (and subclasses thereof)
* ``TLS::Stream<T>``

View File

@ -1,469 +0,0 @@
Side Channels
=========================
Many cryptographic systems can be easily broken by side channels. This document
notes side channel protections which are currently implemented, as well as areas
of the code which are known to be vulnerable to side channels. The latter are
obviously all open for future improvement.
The following text assumes the reader is already familiar with cryptographic
implementations, side channel attacks, and common countermeasures.
Modular Exponentiation
------------------------
Modular exponentiation uses a fixed window algorithm with Montgomery
representation. A side channel silent table lookup is used to access the
precomputed powers. The caller provides the maximum possible bit length of the
exponent, and the exponent is zero-padded as required. For example, in a DSA
signature with 256-bit q, the caller will specify a maximum length of exponent
of 256 bits, even if the k that was generated was 250 bits. This avoids leaking
the length of the exponent through the number of loop iterations.
See monty_exp.cpp and monty.cpp
Karatsuba multiplication algorithm avoids any conditional branches; in
cases where different operations must be performed it instead uses masked
operations. See mp_karat.cpp for details.
The Montgomery reduction is written to run in constant time.
The final reduction is handled with a masked subtraction. See mp_monty.cpp.
Barrett Reduction
--------------------
The Barrett reduction code is written to avoid input dependent branches. The
Barrett algorithm only works for inputs up to a certain size, and larger values
fall back on a different (slower) division algorithm. This secondary algorithm
is also const time, but the branch allows detecting when a value larger than
2^{2k} was reduced, where k is the word length of the modulus. This leaks only
the size of the two values, and not anything else about their value.
RSA
----------------------
Blinding is always used to protect private key operations (there is no way to
turn it off). Both base blinding and exponent blinding are used.
For base blinding, as an optimization, instead of choosing a new random mask and
inverse with each decryption, both the mask and its inverse are simply squared
to choose the next blinding factor. This is much faster than computing a fresh
value each time, and the additional relation is thought to provide only minimal
useful information for an attacker. Every BOTAN_BLINDING_REINIT_INTERVAL
(default 64) operations, a new starting point is chosen.
Exponent blinding uses new values for each signature, with 64 bit masks.
RSA signing uses the CRT optimization, which is much faster but vulnerable to
trivial fault attacks [RsaFault] which can result in the key being entirely
compromised. To protect against this (or any other computational error which
would have the same effect as a fault attack in this case), after every private
key operation the result is checked for consistency with the public key. This
introduces only slight additional overhead and blocks most fault attacks; it is
possible to use a second fault attack to bypass this verification, but such a
double fault attack requires significantly more control on the part of an
attacker than a BellCore style attack, which is possible if any error at all
occurs during either modular exponentiation involved in the RSA signature
operation.
RSA key generation is also prone to side channel vulnerabilities due to the need
to calculate the CRT parameters. The GCD computation, LCM computations, modulo,
and inversion of ``q`` modulo ``p`` are all done via constant time algorithms.
An additional inversion, of ``e`` modulo ``phi(n)``, is also required. This one
is somewhat more complicated because ``phi(n)`` is even and the primary constant
time algorithm for inversions only works for odd moduli. This is worked around
by a technique based on the CRT - ``phi(n)`` is factored to ``2**e * z`` for
some ``e`` > 1 and some odd ``z``. Then ``e`` is inverted modulo ``2**e`` and
also modulo ``z``. The inversion modulo ``2**e`` is done via a specialized
constant-time algoirthm which only works for powers of 2. Then the two
inversions are combined using the CRT. This process does leak the value of
``e``; to avoid problems ``p`` and ``q`` are chosen so that ``e`` is always 1.
See blinding.cpp and rsa.cpp.
Decryption of PKCS #1 v1.5 Ciphertexts
----------------------------------------
This padding scheme is used with RSA, and is very vulnerable to errors. In a
scenario where an attacker can repeatedly present RSA ciphertexts, and a
legitimate key holder will attempt to decrypt each ciphertext and simply
indicates to the attacker if the PKCS padding was valid or not (without
revealing any additional information), the attacker can use this behavior as an
oracle to perform iterative decryption of arbitrary RSA ciphertexts encrypted
under that key. This is the famous million message attack [MillionMsg]. A side
channel such as a difference in time taken to handle valid and invalid RSA
ciphertexts is enough to mount the attack [MillionMsgTiming].
As a first step, the PKCS v1.5 decoding operation runs without any
conditional jumps or indexes, with the only variance in runtime being
based on the length of the public modulus, which is public information.
Preventing the attack in full requires some application level changes. In
protocols which know the expected length of the encrypted key, PK_Decryptor
provides the function `decrypt_or_random` which first generates a random fake
key, then decrypts the presented ciphertext, then in constant time either copies
out the random key or the decrypted plaintext depending on if the ciphertext was
valid or not (valid padding and expected plaintext length). Then in the case of
an attack, the protocol will carry on with a randomly chosen key, which will
presumably cause total failure in a way that does not allow an attacker to
distinguish (via any timing or other side channel, nor any error messages
specific to the one situation vs the other) if the RSA padding was valid or
invalid.
One very important user of PKCS #1 v1.5 encryption is the TLS protocol. In TLS,
some extra versioning information is embedded in the plaintext message, along
with the key. It turns out that this version information must be treated in an
identical (constant-time) way with the PKCS padding, or again the system is
broken. [VersionOracle]. This is supported by a special version of
PK_Decryptor::decrypt_or_random that additionally allows verifying one or more
content bytes, in addition to the PKCS padding.
See eme_pkcs.cpp and pubkey.cpp.
Verification of PKCS #1 v1.5 Signatures
----------------------------------------
One way of verifying PKCS #1 v1.5 signature padding is to decode it with an
ASN.1 BER parser. However such a design commonly leads to accepting signatures
besides the (single) valid RSA PKCS #1 v1.5 signature for any given message,
because often the BER parser accepts variations of the encoding which are
actually invalid. It also needlessly exposes the BER parser to untrusted inputs.
It is safer and simpler to instead re-encode the hash value we are expecting
using the PKCS #1 v1.5 encoding rules, and const time compare our expected
encoding with the output of the RSA operation. So that is what Botan does.
See emsa_pkcs.cpp.
OAEP
----------------------
RSA OAEP is (PKCS#1 v2) is the recommended version of RSA encoding standard,
because it is not directly vulnerable to Bleichenbacher attack. However, if
implemented incorrectly, a side channel can be presented to an attacker and
create an oracle for decrypting RSA ciphertexts [OaepTiming].
This attack is avoided in Botan by making the OAEP decoding operation run
without any conditional jumps or indexes, with the only variance in runtime
coming from the length of the RSA key (which is public information).
See eme_oaep.cpp.
ECC point decoding
----------------------
The API function OS2ECP, which is used to convert byte strings to ECC points,
verifies that all points satisfy the ECC curve equation. Points that do not
satisfy the equation are invalid, and can sometimes be used to break
protocols ([InvalidCurve] [InvalidCurveTLS]). See ec_point.cpp.
ECC scalar multiply
----------------------
There are several different implementations of ECC scalar multiplications which
depend on the API invoked. This include ``EC_Point::operator*``,
``EC_Group::blinded_base_point_multiply`` and
``EC_Group::blinded_var_point_multiply``.
The ``EC_Point::operator*`` implementation uses the Montgomery ladder, which is
fairly resistant to side channels. However it leaks the size of the scalar,
because the loop iterations are bounded by the scalar size. It should not be
used in cases when the scalar is a secret.
Both ``blinded_base_point_multiply`` and ``blinded_var_point_multiply`` apply
side channel countermeasures. The scalar is masked by a multiple of the group
order (this is commonly called Coron's first countermeasure [CoronDpa]),
currently the mask is scaled to be half the bit length of the order of the group.
Botan stores all ECC points in Jacobian representation. This form allows faster
computation by representing points (x,y) as (X,Y,Z) where x=X/Z^2 and
y=Y/Z^3. As the representation is redundant, for any randomly chosen non-zero r,
(X*r^2,Y*r^3,Z*r) is an equivalent point. Changing the point values prevents an
attacker from mounting attacks based on the input point remaining unchanged over
multiple executions. This is commonly called Coron's third countermeasure, see
again [CoronDpa].
The base point multiplication algorithm is a comb-like technique which
precomputes ``P^i,(2*P)^i,(3*P)^i`` for all ``i`` in the range of valid scalars.
This means the scalar multiplication involves only point additions and no
doublings, which may help against attacks which rely on distinguishing between
point doublings and point additions. The elements of the table are accessed by
masked lookups, so as not to leak information about bits of the scalar via a
cache side channel. However, whenever 3 sequential bits of the (masked) scalar
are all 0, no operation is performed in that iteration of the loop. This exposes
the scalar multiply to a cache-based side channel attack; scalar blinding is
necessary to prevent this attack from leaking information about the scalar.
The variable point multiplication algorithm uses a fixed-window algorithm. Since
this is normally invoked using untrusted points (eg during ECDH key exchange) it
randomizes all inputs to prevent attacks which are based on chosen input
points. The table of precomputed multiples is accessed using a masked lookup
which should not leak information about the secret scalar to an attacker who can
mount a cache-based side channel attack.
See ec_point.cpp and point_mul.cpp in src/lib/pubkey/ec_group
ECDH
----------------------
ECDH verifies (through its use of OS2ECP) that all input points received from
the other party satisfy the curve equation. This prevents twist attacks. The
same check is performed on the output point, which helps prevent fault attacks.
ECDSA
----------------------
Inversion of the ECDSA nonce k must be done in constant time, as any leak of
even a single bit of the nonce can be sufficient to allow recovering the private
key. In Botan all inverses modulo an odd number are performed using a constant
time algorithm due to Niels Möller.
x25519
----------------------
The x25519 code is independent of the main Weierstrass form ECC code, instead
based on curve25519-donna-c64.c by Adam Langley. The code seems immune to cache
based side channels. It does make use of integer multiplications; on some old
CPUs these multiplications take variable time and might allow a side channel
attack. This is not considered a problem on modern processors.
TLS CBC ciphersuites
----------------------
The original TLS v1.0 CBC Mac-then-Encrypt mode is vulnerable to an oracle
attack. If an attacker can distinguish padding errors through different error
messages [TlsCbcOracle] or via a side channel attack like [Lucky13], they can
abuse the server as a decryption oracle.
The side channel protection for Lucky13 follows the approach proposed in the
Lucky13 paper. It is not perfectly constant time, but does hide the padding
oracle in practice. Tools to test TLS CBC decoding are included in the timing
tests. See https://github.com/randombit/botan/pull/675 for more information.
The Encrypt-then-MAC extension, which completely avoids the side channel, is
implemented and used by default for CBC ciphersuites.
CBC mode padding
----------------------
In theory, any good protocol protects CBC ciphertexts with a MAC. But in
practice, some protocols are not good and cannot be fixed immediately. To avoid
making a bad problem worse, the code to handle decoding CBC ciphertext padding
bytes runs in constant time, depending only on the block size of the cipher.
base64 decoding
----------------------
Base64 (and related encodings base32, base58 and hex) are sometimes used to
encode or decode secret data. To avoid possible side channels which might leak
key material during the encoding or decoding process, these functions avoid any
input-dependent table lookups.
AES
----------------------
Some x86, ARMv8 and POWER processors support AES instructions which
are fast and are thought to be side channel silent. These instructions
are used when available.
On CPUs which do not have hardware AES instructions but do support SIMD vectors
with a byte shuffle (including x86's SSSE3, ARM's NEON and PowerPC AltiVec), a
version of AES is implemented which is side channel silent. This implementation
is based on code by Mike Hamburg [VectorAes], see aes_vperm.cpp.
On all other processors, a constant time bitsliced implementation is used. This
is typically slower than the vector permute implementation, and additionally for
best performance multiple blocks must be processed in parellel. So modes such
as CTR, GCM or XTS are relatively fast, but others such as CBC encryption
suffer.
GCM
---------------------
On platforms that support a carryless multiply instruction (ARMv8 and recent x86),
GCM is fast and constant time.
On all other platforms, GCM uses an algorithm based on precomputing all powers
of H from 1 to 128. Then for every bit of the input a mask is formed which
allows conditionally adding that power without leaking information via a cache
side channel. There is also an SSSE3 variant of this algorithm which is somewhat
faster on processors which have SSSE3 but no AES-NI instructions.
OCB
-----------------------
It is straightforward to implement OCB mode in a efficient way that does not
depend on any secret branches or lookups. See ocb.cpp for the implementation.
Poly1305
----------------------
The Poly1305 implementation does not have any secret lookups or conditionals.
The code is based on the public domain version by Andrew Moon.
DES/3DES
----------------------
The DES implementation relies on table lookups but they are limited to
tables which are exactly 64 bytes in size. On systems with 64 byte (or
larger) cache lines, these should not leak information. It may still
be vulnerable to side channels on processors which leak cache line
access offsets via cache bank conflicts; vulnerable hardware includes
Sandy Bridge processors, but not later Intel or AMD CPUs.
Twofish
------------------------
This algorithm uses table lookups with secret sboxes. No cache-based side
channel attack on Twofish has ever been published, but it is possible nobody
sufficiently skilled has ever tried.
ChaCha20, Serpent, Threefish, ...
-----------------------------------
Some algorithms including ChaCha, Salsa, Serpent and Threefish are 'naturally'
silent to cache and timing side channels on all recent processors.
IDEA
---------------
IDEA encryption, decryption, and key schedule are implemented to take constant
time regardless of their inputs.
Hash Functions
-------------------------
Most hash functions included in Botan such as MD5, SHA-1, SHA-2, SHA-3, Skein,
and BLAKE2 do not require any input-dependent memory lookups, and so seem to not be
affected by common CPU side channels. However the implementations of Whirlpool
and Streebog use table lookups and probably can be attacked by side channels.
Memory comparisons
----------------------
The function same_mem in header mem_ops.h provides a constant-time comparison
function. It is used when comparing MACs or other secret values. It is also
exposed for application use.
Memory zeroizing
----------------------
There is no way in portable C/C++ to zero out an array before freeing it, in
such a way that it is guaranteed that the compiler will not elide the
'additional' (seemingly unnecessary) writes to zero out the memory.
The function secure_scrub_memory (in mem_ops.cpp) uses some system specific
trick to zero out an array. If possible an OS provided routine (such as
``RtlSecureZeroMemory`` or ``explicit_bzero``) is used.
On other platforms, by default the trick of referencing memset through a
volatile function pointer is used. This approach is not guaranteed to work on
all platforms, and currently there is no systematic check of the resulting
binary function that it is compiled as expected. But, it is the best approach
currently known and has been verified to work as expected on common platforms.
If BOTAN_USE_VOLATILE_MEMSET_FOR_ZERO is set to 0 in build.h (not the default) a
byte at a time loop through a volatile pointer is used to overwrite the array.
Memory allocation
----------------------
Botan's secure_vector type is a std::vector with a custom allocator. The
allocator calls secure_scrub_memory before freeing memory.
Some operating systems support an API call to lock a range of pages
into memory, such that they will never be swapped out (``mlock`` on POSIX,
``VirtualLock`` on Windows). On many POSIX systems ``mlock`` is only usable by
root, but on Linux, FreeBSD and possibly other systems a small amount
of memory can be locked by processes without extra credentials.
If available, Botan uses such a region for storing key material. A page-aligned
block of memory is allocated and locked, then the memory is scrubbed before
freeing. This memory pool is used by secure_vector when available. It can be
disabled at runtime setting the environment variable BOTAN_MLOCK_POOL_SIZE to 0.
Automated Analysis
---------------------
Currently the main tool used by the Botan developers for testing for side
channels at runtime is valgrind; valgrind's runtime API is used to taint memory
values, and any jumps or indexes using data derived from these values will cause
a valgrind warning. This technique was first used by Adam Langley in ctgrind.
See header ct_utils.h.
To check, install valgrind, configure the build with --with-valgrind, and run
the tests.
.. highlight:: shell
There is also a test utility built into the command line util, `timing_test`,
which runs an operation on several different inputs many times in order to
detect simple timing differences. The output can be processed using the
Mona timing report library (https://github.com/seecurity/mona-timing-report).
To run a timing report (here for example pow_mod)::
$ ./botan timing_test pow_mod > pow_mod.raw
This must be run from a checkout of the source, or otherwise ``--test-data-dir=``
must be used to point to the expected input files.
Build and run the Mona report as::
$ git clone https://github.com/seecurity/mona-timing-report.git
$ cd mona-timing-report
$ ant
$ java -jar ReportingTool.jar --lowerBound=0.4 --upperBound=0.5 --inputFile=pow_mod.raw --name=PowMod
This will produce plots and an HTML file in subdirectory starting with
``reports_`` followed by a representation of the current date and time.
References
---------------
[Aes256Sc] Neve, Tiri "On the complexity of side-channel attacks on AES-256"
(https://eprint.iacr.org/2007/318.pdf)
[AesCacheColl] Bonneau, Mironov "Cache-Collision Timing Attacks Against AES"
(http://www.jbonneau.com/doc/BM06-CHES-aes_cache_timing.pdf)
[CoronDpa] Coron,
"Resistance against Differential Power Analysis for Elliptic Curve Cryptosystems"
(https://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.1.5695)
[InvalidCurve] Biehl, Meyer, Müller: Differential fault attacks on
elliptic curve cryptosystems
(https://www.iacr.org/archive/crypto2000/18800131/18800131.pdf)
[InvalidCurveTLS] Jager, Schwenk, Somorovsky: Practical Invalid Curve
Attacks on TLS-ECDH
(https://www.nds.rub.de/research/publications/ESORICS15/)
[SafeCurves] Bernstein, Lange: SafeCurves: choosing safe curves for
elliptic-curve cryptography. (https://safecurves.cr.yp.to)
[Lucky13] AlFardan, Paterson "Lucky Thirteen: Breaking the TLS and DTLS Record Protocols"
(http://www.isg.rhul.ac.uk/tls/TLStiming.pdf)
[MillionMsg] Bleichenbacher "Chosen Ciphertext Attacks Against Protocols Based
on the RSA Encryption Standard PKCS1"
(https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.19.8543)
[MillionMsgTiming] Meyer, Somorovsky, Weiss, Schwenk, Schinzel, Tews: Revisiting
SSL/TLS Implementations: New Bleichenbacher Side Channels and Attacks
(https://www.nds.rub.de/research/publications/mswsst2014-bleichenbacher-usenix14/)
[OaepTiming] Manger, "A Chosen Ciphertext Attack on RSA Optimal Asymmetric
Encryption Padding (OAEP) as Standardized in PKCS #1 v2.0"
(http://archiv.infsec.ethz.ch/education/fs08/secsem/Manger01.pdf)
[RsaFault] Boneh, Demillo, Lipton
"On the importance of checking cryptographic protocols for faults"
(https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.9764)
[RandomMonty] Le, Tan, Tunstall "Randomizing the Montgomery Powering Ladder"
(https://eprint.iacr.org/2015/657)
[VectorAes] Hamburg, "Accelerating AES with Vector Permute Instructions"
https://shiftleft.org/papers/vector_aes/vector_aes.pdf
[VersionOracle] Klíma, Pokorný, Rosa "Attacking RSA-based Sessions in SSL/TLS"
(https://eprint.iacr.org/2003/052)

View File

@ -1,89 +0,0 @@
Support Information
=======================
Supported Platforms
------------------------
For Botan 3, the tier-1 supported platforms are
* Linux x86-64, GCC 11.2 or later
* Linux x86-64, Clang 14 or later
* Linux aarch64, GCC 11.2 or later
* Linux ppc64le, GCC 11.2 or later
* Windows x86-64, Visual C++ 2022 or later
These platforms are all tested by continuous integration, and the developers
have access to hardware in order to test patches. Problems affecting these
platforms are considered release blockers.
For Botan 3, the tier-2 supported platforms are
* macOS x86-64, latest XCode Clang
* iOS aarch64, latest XCode Clang
* Windows x86-64, latest MinGW GCC
* Android aarch64, latest NDK Clang
* Linux arm32, GCC 11.2 or later
* Linux x86-32, GCC 11.2 or later
* FreeBSD x86-64, Clang 14 or later
.. note::
Notice that the minimum version requirements for XCode and NDK is different
from other compilers. With GCC or Clang, we fix the minimum required compiler
version and aim to maintain that support for the entire lifecycle of
Botan 3. In contrast, for XCode and NDK the minimum version is floating;
namely, we will only support the very latest version. It's possible earlier
versions will work, but this is not guaranteed.
.. note::
As of June 2023, it is known that at least XCode 13.3 is required, since
earlier versions did not support certain C++20 language features that the
library uses. XCode 15.0 or higher is recommended.
.. note::
For Android, NDK 26 is required
Some (but not all) of the tier-2 platforms are tested by CI. Everything should
work, and if problems are encountered, the developers will probably be able to
help. But they are not as carefully tested as tier-1.
Of course most other modern OSes such as QNX, AIX, OpenBSD, NetBSD, and Solaris
also work just fine. Some are tested occasionally, usually just before a new
release. But very little code specific to these platforms is written by the
primary developers. For example, any functionality in the library which
utilizes OpenBSD specific APIs was likely contributed by someone interested in
that platform.
In theory any working C++20 compiler is fine but in practice, we only regularly
test with GCC, Clang, and Visual C++. Several other compilers (such as IBM XLC,
Intel C++, and Sun Studio) are supported by the build system but are not tested
by the developers and may have build or codegen problems. Patches to improve
support for these compilers is welcome.
Branch Support Status
-------------------------
Following table provides the support status for Botan branches, as of
July 2023.
"Active development" refers to adding new features and optimizations. At the
conclusion of the active development phase, only bugfixes are applied.
End of life dates may be extended as circumstances warrant.
============== ============== ========================== ============
Branch First Release End of Active Development End of Life
============== ============== ========================== ============
Botan 1.8 2008-12-08 2010-08-31 2016-02-13
Botan 1.10 2011-06-20 2012-07-10 2018-12-31
Botan 2 2017-01-06 2020-11-05 2024-12-31 or later
Botan 3 2023-04-11 ? 2026-12-31 or later
============== ============== ========================== ============
Getting Help
------------------
To get help with Botan, open an issue on
`GitHub <https://github.com/randombit/botan/issues>`_

View File

@ -1,24 +0,0 @@
Copyright (C) 1999-2023 The Botan Authors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load Diff

View File

@ -1,136 +0,0 @@
Botan: Crypto and TLS for Modern C++
========================================
Botan (Japanese for peony flower) is a C++ cryptography library released under the
permissive `Simplified BSD <https://botan.randombit.net/license.txt>`_ license.
Botan's goal is to be the best option for cryptography in C++ by offering the
tools necessary to implement a range of practical systems, such as TLS protocol,
X.509 certificates, modern AEAD ciphers, PKCS#11 and TPM hardware support,
password hashing, and post quantum crypto schemes. A Python binding is included,
and several other `language bindings
<https://github.com/randombit/botan/wiki/Language-Bindings>`_ are available.
The library is accompanied by a featureful
`command line interface <https://botan.randombit.net/handbook/cli.html>`_.
See the `documentation <https://botan.randombit.net/handbook>`_ for more
information about included features.
Development is coordinated on `GitHub <https://github.com/randombit/botan>`_
and contributions are welcome. If you need help, please open an issue on
`GitHub <https://github.com/randombit/botan/issues>`_.
If you think you have found a security issue, see the `security page
<https://botan.randombit.net/security.html>`_ for contact information.
.. image:: https://github.com/randombit/botan/actions/workflows/ci.yml/badge.svg?branch=master
:target: https://github.com/randombit/botan/actions/workflows/ci.yml
:alt: CI status
.. image:: https://github.com/randombit/botan/actions/workflows/nightly.yml/badge.svg?branch=master
:target: https://github.com/randombit/botan/actions/workflows/nightly.yml
:alt: nightly CI status
.. image:: https://img.shields.io/coverallsCoverage/github/randombit/botan?branch=master
:target: https://coveralls.io/github/randombit/botan
:alt: Coverage report
.. image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/botan.svg
:target: https://oss-fuzz.com/coverage-report/job/libfuzzer_asan_botan/latest
:alt: OSS-Fuzz status
.. image:: https://repology.org/badge/tiny-repos/botan.svg
:target: https://repology.org/project/botan/versions
:alt: Packaging status
.. image:: https://api.securityscorecards.dev/projects/github.com/randombit/botan/badge
:target: https://securityscorecards.dev/viewer/?uri=github.com/randombit/botan
:alt: CII Best Practices statement
.. image:: https://bestpractices.coreinfrastructure.org/projects/531/badge
:target: https://bestpractices.coreinfrastructure.org/projects/531
:alt: CII Best Practices statement
Releases
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The latest release from the Botan2 release series is
`2.19.3 <https://botan.randombit.net/releases/Botan-2.19.3.tar.xz>`_
`(sig) <https://botan.randombit.net/releases/Botan-2.19.3.tar.xz.asc>`_,
released on 2022-11-16.
The latest release from the Botan3 release series is
`3.2.0 <https://botan.randombit.net/releases/Botan-3.2.0.tar.xz>`_
`(sig) <https://botan.randombit.net/releases/Botan-3.2.0.tar.xz.asc>`_,
released on 2023-10-09.
All releases are signed with a `PGP key <https://botan.randombit.net/pgpkey.txt>`_.
See the `release notes <https://botan.randombit.net/news.html>`_ for
what is new. Botan is also available through most
`distributions <https://github.com/randombit/botan/wiki/Distros>`_
such as Fedora, Debian, Arch and Homebrew.
Find Enclosed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Transport Layer Security (TLS) Protocol
----------------------------------------
* TLS v1.2/v1.3, and DTLS v1.2
* Supported extensions include session tickets, SNI, ALPN, OCSP stapling,
encrypt-then-mac CBC, and extended master secret.
* Supports authentication using certificates or preshared keys (PSK)
* Supports record encryption with ChaCha20Poly1305, AES/OCB, AES/GCM, AES/CCM,
Camellia/GCM as well as legacy CBC ciphersuites.
* Key exchange using ECDH, FFDHE, or RSA
Public Key Infrastructure
----------------------------------------
* X.509v3 certificates and CRL creation and handling
* PKIX certificate path validation, including name constraints.
* OCSP request creation and response handling
* PKCS #10 certificate request generation and processing
* Access to Windows, macOS and Unix system certificate stores
* SQL database backed certificate store
Public Key Cryptography
----------------------------------------
* RSA signatures and encryption
* DH and ECDH key agreement
* Signature schemes ECDSA, DSA, Ed25519, ECGDSA, ECKCDSA, SM2, GOST 34.10
* Post-quantum signature schemes Dilithium, SPHINCS+, and XMSS
* Post-quantum key agreement schemes McEliece and Kyber
* ElGamal encryption
* Padding schemes OAEP, PSS, PKCS #1 v1.5, X9.31
Ciphers, hashes, MACs, and checksums
----------------------------------------
* Authenticated cipher modes EAX, OCB, GCM, SIV, CCM, (X)ChaCha20Poly1305
* Cipher modes CTR, CBC, XTS, CFB, OFB
* Block ciphers AES, ARIA, Blowfish, Camellia, CAST-128, DES/3DES, IDEA,
Lion, SEED, Serpent, SHACAL2, SM4, Threefish-512, Twofish
* Stream ciphers (X)ChaCha20, (X)Salsa20, SHAKE-128, RC4
* Hash functions SHA-1, SHA-2, SHA-3, MD5, RIPEMD-160, BLAKE2b,
Skein-512, SM3, Streebog, Whirlpool
* Password hashing schemes PBKDF2, Argon2, Scrypt, bcrypt
* Authentication codes HMAC, CMAC, Poly1305, SipHash, GMAC, X9.19 DES-MAC
* Non-cryptographic checksums Adler32, CRC24, CRC32
Other Useful Things
----------------------------------------
* Full C++ PKCS #11 API wrapper
* Interfaces for TPM v1.2 device access
* Simple compression API wrapping zlib, bzip2, and lzma libraries
* RNG wrappers for system RNG and hardware RNGs
* HMAC_DRBG and entropy collection system for userspace RNGs
* SRP-6a password authenticated key exchange
* Key derivation functions including HKDF, KDF2, SP 800-108, SP 800-56A, SP 800-56C
* HOTP and TOTP algorithms
* Format preserving encryption scheme FE1
* Threshold secret sharing
* NIST key wrapping
* Boost.Asio compatible TLS client stream

View File

@ -1,82 +0,0 @@
---
# This file was automatically generated by src/scripts/dev_tools/run_clang_tidy.py --regenerate-inline-config-file
#
# All manual edits to this file will be lost. Edit the script
# then regenerate this configuration file.
Checks: >
bugprone-*,
cert-*,
clang-analyzer-*,
cppcoreguidelines-*,
hicpp-*,
misc-*,
modernize-*,
performance-*,
portability-*,
readability-*,
-*-named-parameter,
-*-member-init,
-bugprone-lambda-function-name,
-bugprone-unchecked-optional-access,
-cert-err58-cpp,
-cppcoreguidelines-avoid-const-or-ref-data-members,
-cppcoreguidelines-init-variables,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-prefer-member-initializer,
-cppcoreguidelines-slicing,
-hicpp-explicit-conversions,
-misc-const-correctness,
-misc-redundant-expression,
-misc-misplaced-const,
-misc-confusable-identifiers,
-modernize-avoid-bind,
-modernize-pass-by-value,
-readability-convert-member-functions-to-static,
-readability-implicit-bool-conversion,
-readability-inconsistent-declaration-parameter-name,
-readability-qualified-auto,
-readability-simplify-boolean-expr,
-readability-static-accessed-through-instance,
-*-array-to-pointer-decay,
-*-avoid-c-arrays,
-*-else-after-return,
-*-function-size,
-*-magic-numbers,
-*-narrowing-conversions,
-*-no-array-decay,
-*-use-auto,
-*-use-emplace,
-*-deprecated-headers,
-bugprone-argument-comment,
-bugprone-branch-clone,
-bugprone-easily-swappable-parameters,
-bugprone-implicit-widening-of-multiplication-result,
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-non-private-member-variables-in-classes,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-bounds-constant-array-index,
-cppcoreguidelines-pro-type-const-cast,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-vararg,
-hicpp-no-assembler,
-hicpp-vararg,
-hicpp-signed-bitwise,
-misc-no-recursion,
-modernize-loop-convert,
-modernize-raw-string-literal,
-modernize-use-trailing-return-type,
-modernize-return-braced-init-list,
-modernize-use-default-member-init,
-modernize-use-nodiscard,
-modernize-use-using,
-portability-simd-intrinsics,
-readability-container-data-pointer,
-readability-function-cognitive-complexity,
-readability-identifier-length,
-readability-isolate-declaration,
-readability-non-const-parameter,
-readability-redundant-access-specifiers,
-readability-suspicious-call-argument,
-readability-use-anyofallof,
---

File diff suppressed because it is too large Load Diff

View File

@ -1,221 +0,0 @@
{
"LooseErrorTests": {
"AppDataBeforeHandshake": "BoGo expects different error before vs after CCS",
"AppDataBeforeHandshake-Empty": "Invalid record message",
"ServerHelloBogusCipher": "Unexpected error",
"Garbage": "Decoding error",
"Resume-Client-CipherMismatch": "Unexpected error",
"InvalidECDHPoint-Server": "Unexpected error",
"NoSharedCipher": "Unexpected error",
"NoSharedCipher-TLS13": "Unexpected error",
"PartialFinishedWithServerHelloDone": "Unexpected record vs excess handshake data",
"HelloRetryRequest-DuplicateCurve-TLS13": "expects 'illegal parameter' but we want to stick with 'decode error'",
"HelloRetryRequest-DuplicateCookie-TLS13": "expects 'illegal parameter' but we want to stick with 'decode error'",
"EncryptedExtensionsWithKeyShare-TLS13": "expects 'unsupported extension' but RFC requires 'illegal parameter'",
"ClientSkipCertificateVerify-TLS13": "would require ambiguous error mapping",
"Resume-Client-Mismatch-TLS13-TLS12-TLS": "server requests a downgrade to TLS 1.2, echoing the random session ID during a TLS 1.3 resumption. => error mapping conflict",
"ServerAuth-NoFallback-TLS13": "would require ambiguous error mapping"
},
"DisabledTests": {
"*TLS1": "No TLS 1.0",
"*-TLS1-*": "No TLS 1.0",
"*-TLS10-*": "No TLS 1.0",
"TLS1-*": "No TLS 1.0",
"VersionNegotiation*-TLS": "No TLS 1.0",
"VersionNegotiation*-DTLS": "No DTLS 1.0",
"*TLS11": "No TLS 1.1",
"*-TLS11-*": "No TLS 1.1",
"TLS11-*": "No TLS 1.1",
"*RSA_PKCS1_MD5_SHA1": "We do not implement MD5/SHA1 concatenation anyway",
"Compliance-fips202205-*": "We do not have explicit support for a FIPS TLS policy",
"Compliance-fips-202205-*": "We do not have explicit support for a FIPS TLS policy",
"Compliance-wpa-202304-*": "We do not have explicit support for the WPA Enterprise mode",
"CBCRecordSplitting*": "No need to split CBC records in TLS 1.2",
"DelegatedCredentials*": "No support of -delegated-cerdential",
"*SCSV*": "SCSV is meaningless without TLS 1.0/1.1 support",
"AllExtensions-*": "Not all extensions are implemented",
"VersionTolerance-TLS13": "We are not tolerating 0x0400 as Client Hello legacy_version",
"Server-JDK11-*": "We don't implement JDK-specific workarounds",
"Client-RejectJDK11DowngradeRandom": "We don't implement this workaround",
"ExportTrafficSecrets-*": "Exporting traffic secrets is not implemented",
"TooManyChangeCipherSpec-Client-TLS13": "Limits on the number of CCS are not implemented",
"TooManyChangeCipherSpec-Server-TLS13": "Limits on the number of CCS are not implemented",
"TooManyKeyUpdates": "Limits on the number of KeyUpdates are not implemented",
"TLS12SessionID-TLS13": "We don't offer TLS 1.3 when a TLS 1.2 session was found",
"Ticket-Forbidden-TLS13": "We don't offer TLS 1.3 when a TLS 1.2 session was found",
"Resume-Client-NoResume-TLS12-TLS13-TLS": "We don't offer TLS 1.3 when a TLS 1.2 session was found",
"Resume-Client-Mismatch-TLS12-TLS13-TLS": "We don't offer TLS 1.3 when a TLS 1.2 session was found",
"Resume-Server-UnofferedCipher-TLS13": "BoringSSL will not allow switching ciphers during TLS 1.3 resumption, we do, though.",
"HttpGET": "TLS 1.3 server does not detect HTTP",
"HttpPOST": "TLS 1.3 server does not detect HTTP",
"HttpPUT": "TLS 1.3 server does not detect HTTP",
"HttpHEAD": "TLS 1.3 server does not detect HTTP",
"HttpCONNECT": "TLS 1.3 server does not detect HTTP",
"*EarlyData*": "No TLS 1.3 Early Data, yet",
"TLS13-TicketAgeSkew-*": "No TLS 1.3 Early Data, yet",
"ExportKeyingMaterial-Server-HalfRTT-TLS13": "No TLS 1.3 Early Data, yet",
"EarlyDataEnabled*": "No TLS 1.3 Early Data, yet",
"EarlyData-Reject0RTT*": "No TLS 1.3 Early Data, yet",
"PartialEndOfEarlyDataWithClientHello": "No TLS 1.3 Early Data, yet",
"SendNoClientCertificateExtensions-TLS13": "-signed-cert-timestamps currently not supported in the shim",
"KeyUpdate-RequestACK-UnfinishedWrite": "-read-with-unfinished-write currently not supported in the shim",
"TLS-ECH*": "No ECH support",
"ECH*": "No ECH support",
"DuplicateCertCompressionExt*": "No support for 1.3 cert compression extension",
"CertCompression*-TLS13": "No support for 1.3 cert compression extension",
"SupportedVersionSelection-TLS12": "We just ignore the version extension in this case",
"Downgrade-*-Client-Ignore": "Not possible to ignore downgrade indicator",
"Agree-Digest-SHA1": "No SHA-1 in TLS 1.2",
"ServerAuth-SHA1-Fallback-*": "No SHA-1 in TLS 1.2",
"*-InvalidSignature-*_SHA1-TLS12": "No SHA-1 in TLS 1.2",
"*-Sign-*_SHA1-TLS12": "No SHA-1 in TLS 1.2",
"*-Sign-Negotiate-*_SHA1-TLS12": "No SHA-1 in TLS 1.2",
"*-VerifyDefault-*_SHA1-TLS12": "No SHA-1 in TLS 1.2",
"*-Verify-*_SHA1-TLS12": "No SHA-1 in TLS 1.2",
"*QUIC*": "No QUIC",
"ALPS*": "No ALPS",
"ExtraClientEncryptedExtension-TLS-TLS13": "No ALPS",
"*NPN*": "No support for NPN",
"ALPNServer-Preferred-*": "No support for NPN",
"*-NextProtocol*": "No support for NPN",
"*SignedCertificateTimestamp*": "No support for SCT",
"*SCT*": "No support for SCT",
"Renegotiation-ChangeAuthProperties": "No support for SCT",
"UnsolicitedCertificateExtensions-*": "No support for SCT",
"IgnoreExtensionsOnIntermediates-TLS13": "No support for SCT",
"SendNoExtensionsOnIntermediate-TLS13": "No support for SCT",
"CertificateVerificationSoftFail*": "Fail, but don't fail... wtf?",
"*NULL-SHA*": "No support for NULL ciphers",
"*WITH_NULL*": "No support for NULL ciphers",
"*GREASE*": "No support for GREASE",
"*ChannelID*": "No support for ChannelID",
"*TokenBinding*": "No support for Token Binding",
"ClientHelloPadding": "No support for client hello padding extension",
"TLSUnique*": "Not supported",
"*CECPQ2*": "Not implemented",
"PQExperimentSignal*": "Not implemented",
"*P-224*": "P-224 not supported in TLS",
"*V2ClientHello*": "No support for SSLv2 client hellos",
"*Ed25519*": "Ed25519 not implemented in TLS",
"*FalseStart*": "Botan doesn't do false start",
"MaxSendFragment*": "Maximum fragment extension not supported",
"ExportKeyingMaterial-EmptyContext*": "No support for empty context",
"Peek-*": "No peek API",
"*OldCallback*": "BoringSSL specific API test",
"*Renegotiate-Client-Explicit*": "BoringSSL specific API test",
"CBCRecordSplittingPartialWrite*": "BoringSSL specific API test",
"TicketCallback*": "BoringSSL specific API test",
"Server-DDoS*": "BoringSSL specific API test",
"RetainOnlySHA256-*": "BoringSSL specific API test",
"Renegotiate-Client-UnfinishedWrite": "BoringSSL specific API test",
"FailEarlyCallback": "BoringSSL specific API test",
"NotJustKyberKeyShare": "BoringSSL specific policy test (we may offer solo PQ/T groups)",
"KyberKeyShareIncludedSecond": "BoringSSL specific policy test (we may offer solo PQ/T groups)",
"KyberKeyShareIncludedThird": "BoringSSL specific policy test (we may offer solo PQ/T groups)",
"ShimTicketRewritable": "Botan has a different ticket format",
"Resume-Server-DeclineCrossVersion*": "Botan has a different ticket format",
"Resume-Server-DeclineBadCipher*": "Botan has a different ticket format",
"Resume-Server-CipherNotPreferred*": "Botan has a different ticket format",
"TLS*-NoTicket-NoAccept": "BoGo expects that if ticket is issued stateful resumption is impossible",
"CheckLeafCurve": "Botan doesn't care what curve an ECDSA cert uses",
"CertificateVerificationDoesNotFailOnResume*": "Botan doesn't support reverify on resume",
"CertificateVerificationFailsOnResume*": "Botan doesn't support reverify on resume",
"CertificateVerificationPassesOnResume*": "Botan doesn't support reverify on resume",
"CipherNegotiation-2": "No support for cipher equivalence classes",
"CipherNegotiation-3": "No support for cipher equivalence classes",
"CipherNegotiation-4": "No support for cipher equivalence classes",
"CipherNegotiation-5": "No support for cipher equivalence classes",
"CipherNegotiation-8": "No support for cipher equivalence classes",
"ALPNServer-SelectEmpty-*": "Botan treats empty ALPN from callback as a decline",
"AppDataAfterChangeCipherSpec-DTLS*": "BoringSSL DTLS drops out of order AppData, we reject",
"Resume-Client-NoResume-TLS1-TLS11-TLS": "BoGo expects resumption attempt sends latest version",
"Resume-Client-NoResume-TLS1-TLS12-TLS": "BoGo expects resumption attempt sends latest version",
"Resume-Client-NoResume-TLS11-TLS12-TLS": "BoGo expects resumption attempt sends latest version",
"Resume-Client-NoResume-TLS1-TLS12-DTLS": "BoGo expects resumption attempt sends latest version",
"Resume-Client-Mismatch-TLS1-TLS11-TLS": "BoGo expects resumption attempt sends latest version",
"Resume-Client-Mismatch-TLS1-TLS12-TLS": "BoGo expects resumption attempt sends latest version",
"Resume-Client-Mismatch-TLS11-TLS12-TLS": "BoGo expects resumption attempt sends latest version",
"Resume-Client-Mismatch-TLS1-TLS12-DTLS": "BoGo expects resumption attempt sends latest version",
"LooseInitialRecordVersion-TLS12": "Botan is somewhat strict about the record version number",
"CurveTest-*-Compressed*": "Point compression is supported, which BoGo doesn't expect",
"PointFormat-*-MissingUncompressed": "Point compression is supported, which BoGo doesn't expect",
"RSAPSSSupport-ConfigPSS-NoCerts-TLS12-*": "Needs investigation",
"RSAPSSSupport-Default-NoCerts-TLS12-*": "Needs investigation",
"DTLS-Retransmit*": "Shim needs timeout support",
"DTLS-StrayRetransmitFinished-ClientFull": "Needs investigation",
"DTLS-StrayRetransmitFinished-ServerResume": "Needs investigation",
"SRTP-Server-IgnoreMKI-*": "Non-empty MKI is rejected (bug)",
"Renegotiate-Client-Packed": "Packing HelloRequest with Finished loses the HelloRequest (bug)",
"SendHalfHelloRequest*PackHandshake": "Packing HelloRequest with Finished loses the HelloRequest (bug)",
"PartialClientFinishedWithClientHello": "Need to check for buffered messages when CCS (bug)",
"SendUnencryptedFinished-DTLS": "Need to check for buffered messages when CCS (bug)",
"RSAKeyUsage-*-TLS12": "We always enforce key usage",
"RSAKeyUsage-Client-WantSignature-GotEncipherment-AlwaysEnforced-TLS13": "We always enforce key usage",
"AllExtensions-Client-Permute-TLS-TLS12" : "Requires new shim flags that are NYI (as of March 2022)",
"AllExtensions-Client-Permute-DTLS-TLS12" : "Requires new shim flags that are NYI (as of March 2022)",
"EarlyData-WriteAfterEncryptedExtensions" : "Requires new shim flags that are NYI (as of March 2022)",
"EarlyData-WriteAfterServerHello" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-CipherMismatch1" : "Requires new shim flags that are NYI (as of March 2023)",
"TLS-HintMismatch-CipherMismatch2" : "Requires new shim flags that are NYI (as of March 2023)",
"TLS-HintMismatch-ECDHE-Group" : "Requires new shim flags that are NYI (as of March 2023)",
"TLS-HintMismatch-SignatureInput" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-KeyShare" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-HandshakerHelloRetryRequest" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-ShimHelloRetryRequest" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-SignatureAlgorithm-TLS*" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-NoTickets1-TLS*" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-NoTickets2-TLS*" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-Version2" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-CertificateRequest" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-CertificateCompression-HandshakerOnly" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-CertificateCompression-ShimOnly" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-CertificateCompression-AlgorithmMismatch" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-CertificateCompression-InputMismatch" : "Requires new shim flags that are NYI (as of March 2022)",
"TLS-HintMismatch-Version1" : "Requires new shim flags that are NYI (as of March 2022)"
}
}

View File

@ -1,7 +0,0 @@
endian little
wordsize 64
<aliases>
axp
alphaaxp
</aliases>

View File

@ -1,21 +0,0 @@
endian little
family arm
<aliases>
arm
armeb
armel # For Debian
armhf # For Debian
evbarm # For NetBSD
armv7
armv7l
armv7a
armv7-a
armv8l # For AlpineLinux
</aliases>
<isa_extensions>
neon
</isa_extensions>

View File

@ -1,20 +0,0 @@
endian little
wordsize 64
family arm
<aliases>
aarch64
aarch64_be
armv8
armv8-a
</aliases>
<isa_extensions>
neon
armv8crypto
armv8sm3
armv8sm4
armv8sha3
armv8sha512
</isa_extensions>

View File

@ -1,4 +0,0 @@
# This target can be used when building an amalgamation which must
# be built on multiple architectures, or when targetting a CPU
# which the build system doesn't know about.

View File

@ -1,8 +0,0 @@
<aliases>
hp-pa
parisc
parisc64
pa-risc
hp-parisc
hp-pa-risc
</aliases>

View File

@ -1,6 +0,0 @@
wordsize 64
<aliases>
itanium
itanic
</aliases>

View File

@ -1 +0,0 @@
wordsize 64

View File

@ -1,3 +0,0 @@
family loongarch
endian little
wordsize 64

View File

@ -1,6 +0,0 @@
endian big
<aliases>
680x0
68k
</aliases>

View File

@ -1,6 +0,0 @@
<aliases>
mips
mipsbe # RedHat
mipsle # RedHat
mipsel # Debian
</aliases>

View File

@ -1,5 +0,0 @@
wordsize 64
<aliases>
mips64el
</aliases>

View File

@ -1,3 +0,0 @@
endian big
family ppc

View File

@ -1,12 +0,0 @@
endian big
family ppc
<aliases>
powerpc
ppc
</aliases>
<isa_extensions>
altivec
</isa_extensions>

View File

@ -1,18 +0,0 @@
endian big
family ppc
wordsize 64
<aliases>
powerpc64
powerpc64le
ppc64le
ppc64el
</aliases>
<isa_extensions>
altivec
vsx
powercrypto
power9
</isa_extensions>

View File

@ -1,2 +0,0 @@
family riscv
endian little

View File

@ -1,3 +0,0 @@
family riscv
endian little
wordsize 64

View File

@ -1 +0,0 @@
endian big

View File

@ -1,2 +0,0 @@
endian big
wordsize 64

View File

@ -1,7 +0,0 @@
endian big
family sparc
<aliases>
sparc
</aliases>

Some files were not shown because too many files have changed in this diff Show More