Rewrote the server in cpp with the frontend in svelte
This commit is contained in:
279
lib/Botan-3.2.0/doc/api_ref/bigint.rst
Normal file
279
lib/Botan-3.2.0/doc/api_ref/bigint.rst
Normal file
@@ -0,0 +1,279 @@
|
||||
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``.
|
||||
318
lib/Botan-3.2.0/doc/api_ref/block_cipher.rst
Normal file
318
lib/Botan-3.2.0/doc/api_ref/block_cipher.rst
Normal file
@@ -0,0 +1,318 @@
|
||||
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.
|
||||
377
lib/Botan-3.2.0/doc/api_ref/cipher_modes.rst
Normal file
377
lib/Botan-3.2.0/doc/api_ref/cipher_modes.rst
Normal file
@@ -0,0 +1,377 @@
|
||||
.. _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.
|
||||
97
lib/Botan-3.2.0/doc/api_ref/compression.rst
Normal file
97
lib/Botan-3.2.0/doc/api_ref/compression.rst
Normal file
@@ -0,0 +1,97 @@
|
||||
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.
|
||||
41
lib/Botan-3.2.0/doc/api_ref/contents.rst
Normal file
41
lib/Botan-3.2.0/doc/api_ref/contents.rst
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
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
|
||||
197
lib/Botan-3.2.0/doc/api_ref/credentials_manager.rst
Normal file
197
lib/Botan-3.2.0/doc/api_ref/credentials_manager.rst
Normal file
@@ -0,0 +1,197 @@
|
||||
|
||||
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.
|
||||
34
lib/Botan-3.2.0/doc/api_ref/cryptobox.rst
Normal file
34
lib/Botan-3.2.0/doc/api_ref/cryptobox.rst
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
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.
|
||||
284
lib/Botan-3.2.0/doc/api_ref/ecc.rst
Normal file
284
lib/Botan-3.2.0/doc/api_ref/ecc.rst
Normal file
@@ -0,0 +1,284 @@
|
||||
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
|
||||
|
||||
|
||||
|
||||
35
lib/Botan-3.2.0/doc/api_ref/env_vars.rst
Normal file
35
lib/Botan-3.2.0/doc/api_ref/env_vars.rst
Normal file
@@ -0,0 +1,35 @@
|
||||
.. _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.
|
||||
1547
lib/Botan-3.2.0/doc/api_ref/ffi.rst
Normal file
1547
lib/Botan-3.2.0/doc/api_ref/ffi.rst
Normal file
File diff suppressed because it is too large
Load Diff
733
lib/Botan-3.2.0/doc/api_ref/filters.rst
Normal file
733
lib/Botan-3.2.0/doc/api_ref/filters.rst
Normal file
@@ -0,0 +1,733 @@
|
||||
|
||||
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.
|
||||
|
||||
60
lib/Botan-3.2.0/doc/api_ref/footguns.rst
Normal file
60
lib/Botan-3.2.0/doc/api_ref/footguns.rst
Normal file
@@ -0,0 +1,60 @@
|
||||
========================================
|
||||
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`.
|
||||
98
lib/Botan-3.2.0/doc/api_ref/fpe.rst
Normal file
98
lib/Botan-3.2.0/doc/api_ref/fpe.rst
Normal file
@@ -0,0 +1,98 @@
|
||||
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
|
||||
312
lib/Botan-3.2.0/doc/api_ref/hash.rst
Normal file
312
lib/Botan-3.2.0/doc/api_ref/hash.rst
Normal file
@@ -0,0 +1,312 @@
|
||||
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.
|
||||
153
lib/Botan-3.2.0/doc/api_ref/kdf.rst
Normal file
153
lib/Botan-3.2.0/doc/api_ref/kdf.rst
Normal file
@@ -0,0 +1,153 @@
|
||||
|
||||
.. _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.
|
||||
60
lib/Botan-3.2.0/doc/api_ref/keywrap.rst
Normal file
60
lib/Botan-3.2.0/doc/api_ref/keywrap.rst
Normal file
@@ -0,0 +1,60 @@
|
||||
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.
|
||||
|
||||
|
||||
195
lib/Botan-3.2.0/doc/api_ref/message_auth_codes.rst
Normal file
195
lib/Botan-3.2.0/doc/api_ref/message_auth_codes.rst
Normal file
@@ -0,0 +1,195 @@
|
||||
|
||||
.. _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.
|
||||
98
lib/Botan-3.2.0/doc/api_ref/otp.rst
Normal file
98
lib/Botan-3.2.0/doc/api_ref/otp.rst
Normal file
@@ -0,0 +1,98 @@
|
||||
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.
|
||||
215
lib/Botan-3.2.0/doc/api_ref/passhash.rst
Normal file
215
lib/Botan-3.2.0/doc/api_ref/passhash.rst
Normal file
@@ -0,0 +1,215 @@
|
||||
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``
|
||||
294
lib/Botan-3.2.0/doc/api_ref/pbkdf.rst
Normal file
294
lib/Botan-3.2.0/doc/api_ref/pbkdf.rst
Normal file
@@ -0,0 +1,294 @@
|
||||
|
||||
.. _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.
|
||||
944
lib/Botan-3.2.0/doc/api_ref/pkcs11.rst
Normal file
944
lib/Botan-3.2.0/doc/api_ref/pkcs11.rst
Normal file
@@ -0,0 +1,944 @@
|
||||
.. _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
|
||||
110
lib/Botan-3.2.0/doc/api_ref/psk_db.rst
Normal file
110
lib/Botan-3.2.0/doc/api_ref/psk_db.rst
Normal file
@@ -0,0 +1,110 @@
|
||||
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)``.
|
||||
1021
lib/Botan-3.2.0/doc/api_ref/pubkey.rst
Normal file
1021
lib/Botan-3.2.0/doc/api_ref/pubkey.rst
Normal file
File diff suppressed because it is too large
Load Diff
667
lib/Botan-3.2.0/doc/api_ref/python.rst
Normal file
667
lib/Botan-3.2.0/doc/api_ref/python.rst
Normal file
@@ -0,0 +1,667 @@
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
289
lib/Botan-3.2.0/doc/api_ref/rng.rst
Normal file
289
lib/Botan-3.2.0/doc/api_ref/rng.rst
Normal file
@@ -0,0 +1,289 @@
|
||||
.. _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.
|
||||
6
lib/Botan-3.2.0/doc/api_ref/roughtime.rst
Normal file
6
lib/Botan-3.2.0/doc/api_ref/roughtime.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
Roughtime
|
||||
===========
|
||||
|
||||
.. versionadded:: 2.13.0
|
||||
|
||||
Botan includes a Roughtime client, available in ``botan/roughtime.h``
|
||||
31
lib/Botan-3.2.0/doc/api_ref/secmem.rst
Normal file
31
lib/Botan-3.2.0/doc/api_ref/secmem.rst
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
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).
|
||||
77
lib/Botan-3.2.0/doc/api_ref/srp.rst
Normal file
77
lib/Botan-3.2.0/doc/api_ref/srp.rst
Normal file
@@ -0,0 +1,77 @@
|
||||
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).
|
||||
194
lib/Botan-3.2.0/doc/api_ref/stream_ciphers.rst
Normal file
194
lib/Botan-3.2.0/doc/api_ref/stream_ciphers.rst
Normal file
@@ -0,0 +1,194 @@
|
||||
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.
|
||||
1346
lib/Botan-3.2.0/doc/api_ref/tls.rst
Normal file
1346
lib/Botan-3.2.0/doc/api_ref/tls.rst
Normal file
File diff suppressed because it is too large
Load Diff
113
lib/Botan-3.2.0/doc/api_ref/tpm.rst
Normal file
113
lib/Botan-3.2.0/doc/api_ref/tpm.rst
Normal file
@@ -0,0 +1,113 @@
|
||||
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
|
||||
45
lib/Botan-3.2.0/doc/api_ref/tss.rst
Normal file
45
lib/Botan-3.2.0/doc/api_ref/tss.rst
Normal file
@@ -0,0 +1,45 @@
|
||||
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
|
||||
|
||||
102
lib/Botan-3.2.0/doc/api_ref/versions.rst
Normal file
102
lib/Botan-3.2.0/doc/api_ref/versions.rst
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
.. _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
|
||||
|
||||
954
lib/Botan-3.2.0/doc/api_ref/x509.rst
Normal file
954
lib/Botan-3.2.0/doc/api_ref/x509.rst
Normal file
@@ -0,0 +1,954 @@
|
||||
.. _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``.
|
||||
62
lib/Botan-3.2.0/doc/api_ref/zfec.rst
Normal file
62
lib/Botan-3.2.0/doc/api_ref/zfec.rst
Normal file
@@ -0,0 +1,62 @@
|
||||
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``.
|
||||
Reference in New Issue
Block a user