42080 lines
1.3 MiB
42080 lines
1.3 MiB
/*
|
|
* Botan 2.18.1 Amalgamation
|
|
* (C) 1999-2020 The Botan Authors
|
|
*
|
|
* Botan is released under the Simplified BSD License (see license.txt)
|
|
*/
|
|
|
|
#ifndef BOTAN_AMALGAMATION_H_
|
|
#define BOTAN_AMALGAMATION_H_
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <chrono>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <deque>
|
|
#include <exception>
|
|
#include <functional>
|
|
#include <initializer_list>
|
|
#include <iosfwd>
|
|
#include <istream>
|
|
#include <list>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <set>
|
|
#include <stddef.h>
|
|
#include <string>
|
|
#include <type_traits>
|
|
#include <unordered_map>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
/*
|
|
* Build configuration for Botan 2.18.1
|
|
*
|
|
* Automatically generated from
|
|
* 'configure.py --amalgamation --os=macos --cc=clang --disable-shared'
|
|
*
|
|
* Target
|
|
* - Compiler: clang++ -fstack-protector -m64 -pthread -stdlib=libc++ -std=c++11 -D_REENTRANT -O3
|
|
* - Arch: x86_64
|
|
* - OS: macos
|
|
*/
|
|
|
|
#define BOTAN_VERSION_MAJOR 2
|
|
#define BOTAN_VERSION_MINOR 18
|
|
#define BOTAN_VERSION_PATCH 1
|
|
#define BOTAN_VERSION_DATESTAMP 0
|
|
|
|
|
|
#define BOTAN_VERSION_RELEASE_TYPE "unreleased"
|
|
|
|
#define BOTAN_VERSION_VC_REVISION "unknown"
|
|
|
|
#define BOTAN_DISTRIBUTION_INFO "unspecified"
|
|
|
|
/* How many bits per limb in a BigInt */
|
|
#define BOTAN_MP_WORD_BITS 64
|
|
|
|
|
|
#define BOTAN_INSTALL_PREFIX R"(/usr/local)"
|
|
#define BOTAN_INSTALL_HEADER_DIR R"(include/botan-2)"
|
|
#define BOTAN_INSTALL_LIB_DIR R"(/usr/local/lib)"
|
|
#define BOTAN_LIB_LINK "-ldl -framework CoreFoundation -framework Security"
|
|
#define BOTAN_LINK_FLAGS "-fstack-protector -m64 -pthread -stdlib=libc++"
|
|
|
|
#define BOTAN_SYSTEM_CERT_BUNDLE "/etc/ssl/certs/ca-certificates.crt"
|
|
|
|
#ifndef BOTAN_DLL
|
|
#define BOTAN_DLL
|
|
#endif
|
|
|
|
/* Target identification and feature test macros */
|
|
|
|
#define BOTAN_TARGET_OS_IS_MACOS
|
|
|
|
#define BOTAN_TARGET_OS_HAS_APPLE_KEYCHAIN
|
|
#define BOTAN_TARGET_OS_HAS_ARC4RANDOM
|
|
#define BOTAN_TARGET_OS_HAS_ATOMICS
|
|
#define BOTAN_TARGET_OS_HAS_CLOCK_GETTIME
|
|
#define BOTAN_TARGET_OS_HAS_COMMONCRYPTO
|
|
#define BOTAN_TARGET_OS_HAS_DEV_RANDOM
|
|
#define BOTAN_TARGET_OS_HAS_FILESYSTEM
|
|
#define BOTAN_TARGET_OS_HAS_GETENTROPY
|
|
#define BOTAN_TARGET_OS_HAS_POSIX1
|
|
#define BOTAN_TARGET_OS_HAS_POSIX_MLOCK
|
|
#define BOTAN_TARGET_OS_HAS_SOCKETS
|
|
#define BOTAN_TARGET_OS_HAS_THREAD_LOCAL
|
|
#define BOTAN_TARGET_OS_HAS_THREADS
|
|
|
|
|
|
#define BOTAN_BUILD_COMPILER_IS_CLANG
|
|
|
|
|
|
|
|
|
|
#define BOTAN_TARGET_ARCH_IS_X86_64
|
|
#define BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN
|
|
#define BOTAN_TARGET_CPU_IS_X86_FAMILY
|
|
#define BOTAN_TARGET_CPU_HAS_NATIVE_64BIT
|
|
|
|
#define BOTAN_TARGET_SUPPORTS_AESNI
|
|
#define BOTAN_TARGET_SUPPORTS_AVX2
|
|
#define BOTAN_TARGET_SUPPORTS_BMI2
|
|
#define BOTAN_TARGET_SUPPORTS_RDRAND
|
|
#define BOTAN_TARGET_SUPPORTS_RDSEED
|
|
#define BOTAN_TARGET_SUPPORTS_SHA
|
|
#define BOTAN_TARGET_SUPPORTS_SSE2
|
|
#define BOTAN_TARGET_SUPPORTS_SSE41
|
|
#define BOTAN_TARGET_SUPPORTS_SSE42
|
|
#define BOTAN_TARGET_SUPPORTS_SSSE3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Module availability definitions
|
|
*/
|
|
#define BOTAN_HAS_ADLER32 20131128
|
|
#define BOTAN_HAS_AEAD_CCM 20131128
|
|
#define BOTAN_HAS_AEAD_CHACHA20_POLY1305 20180807
|
|
#define BOTAN_HAS_AEAD_EAX 20131128
|
|
#define BOTAN_HAS_AEAD_GCM 20131128
|
|
#define BOTAN_HAS_AEAD_MODES 20131128
|
|
#define BOTAN_HAS_AEAD_OCB 20131128
|
|
#define BOTAN_HAS_AEAD_SIV 20131202
|
|
#define BOTAN_HAS_AES 20131128
|
|
#define BOTAN_HAS_AES_NI 20131128
|
|
#define BOTAN_HAS_AES_VPERM 20190901
|
|
#define BOTAN_HAS_ANSI_X919_MAC 20131128
|
|
#define BOTAN_HAS_ARGON2 20190824
|
|
#define BOTAN_HAS_ARIA 20170415
|
|
#define BOTAN_HAS_ASN1 20171109
|
|
#define BOTAN_HAS_AUTO_RNG 20161126
|
|
#define BOTAN_HAS_AUTO_SEEDING_RNG 20160821
|
|
#define BOTAN_HAS_BASE32_CODEC 20180418
|
|
#define BOTAN_HAS_BASE58_CODEC 20181209
|
|
#define BOTAN_HAS_BASE64_CODEC 20131128
|
|
#define BOTAN_HAS_BCRYPT 20131128
|
|
#define BOTAN_HAS_BIGINT 20131128
|
|
#define BOTAN_HAS_BIGINT_MP 20151225
|
|
#define BOTAN_HAS_BLAKE2B 20130131
|
|
#define BOTAN_HAS_BLOCK_CIPHER 20131128
|
|
#define BOTAN_HAS_BLOWFISH 20180718
|
|
#define BOTAN_HAS_CAMELLIA 20150922
|
|
#define BOTAN_HAS_CASCADE 20131128
|
|
#define BOTAN_HAS_CAST 20131128
|
|
#define BOTAN_HAS_CAST_128 20171203
|
|
#define BOTAN_HAS_CAST_256 20171203
|
|
#define BOTAN_HAS_CBC_MAC 20131128
|
|
#define BOTAN_HAS_CECPQ1 20161116
|
|
#define BOTAN_HAS_CERTSTOR_FLATFILE 20190410
|
|
#define BOTAN_HAS_CERTSTOR_MACOS 20190207
|
|
#define BOTAN_HAS_CERTSTOR_SQL 20160818
|
|
#define BOTAN_HAS_CERTSTOR_SYSTEM 20190411
|
|
#define BOTAN_HAS_CHACHA 20180807
|
|
#define BOTAN_HAS_CHACHA_AVX2 20180418
|
|
#define BOTAN_HAS_CHACHA_RNG 20170728
|
|
#define BOTAN_HAS_CHACHA_SIMD32 20181104
|
|
#define BOTAN_HAS_CIPHER_MODES 20180124
|
|
#define BOTAN_HAS_CIPHER_MODE_PADDING 20131128
|
|
#define BOTAN_HAS_CMAC 20131128
|
|
#define BOTAN_HAS_CODEC_FILTERS 20131128
|
|
#define BOTAN_HAS_COMB4P 20131128
|
|
#define BOTAN_HAS_CPUID 20170917
|
|
#define BOTAN_HAS_CRC24 20131128
|
|
#define BOTAN_HAS_CRC32 20131128
|
|
#define BOTAN_HAS_CRYPTO_BOX 20131128
|
|
#define BOTAN_HAS_CTR_BE 20131128
|
|
#define BOTAN_HAS_CURVE_25519 20170621
|
|
#define BOTAN_HAS_DES 20131128
|
|
#define BOTAN_HAS_DIFFIE_HELLMAN 20131128
|
|
#define BOTAN_HAS_DLIES 20160713
|
|
#define BOTAN_HAS_DL_GROUP 20131128
|
|
#define BOTAN_HAS_DL_PUBLIC_KEY_FAMILY 20131128
|
|
#define BOTAN_HAS_DSA 20131128
|
|
#define BOTAN_HAS_DYNAMIC_LOADER 20160310
|
|
#define BOTAN_HAS_ECC_GROUP 20170225
|
|
#define BOTAN_HAS_ECC_KEY 20190801
|
|
#define BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO 20131128
|
|
#define BOTAN_HAS_ECDH 20131128
|
|
#define BOTAN_HAS_ECDSA 20131128
|
|
#define BOTAN_HAS_ECGDSA 20160301
|
|
#define BOTAN_HAS_ECIES 20160128
|
|
#define BOTAN_HAS_ECKCDSA 20160413
|
|
#define BOTAN_HAS_EC_CURVE_GFP 20131128
|
|
#define BOTAN_HAS_ED25519 20170607
|
|
#define BOTAN_HAS_ELGAMAL 20131128
|
|
#define BOTAN_HAS_EME_OAEP 20180305
|
|
#define BOTAN_HAS_EME_PKCS1 20190426
|
|
#define BOTAN_HAS_EME_PKCS1v15 20131128
|
|
#define BOTAN_HAS_EME_RAW 20150313
|
|
#define BOTAN_HAS_EMSA1 20131128
|
|
#define BOTAN_HAS_EMSA_PKCS1 20140118
|
|
#define BOTAN_HAS_EMSA_PSSR 20131128
|
|
#define BOTAN_HAS_EMSA_RAW 20131128
|
|
#define BOTAN_HAS_EMSA_X931 20140118
|
|
#define BOTAN_HAS_ENTROPY_SOURCE 20151120
|
|
#define BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM 20131128
|
|
#define BOTAN_HAS_ENTROPY_SRC_GETENTROPY 20170327
|
|
#define BOTAN_HAS_ENTROPY_SRC_RDSEED 20151218
|
|
#define BOTAN_HAS_FFI 20210220
|
|
#define BOTAN_HAS_FILTERS 20160415
|
|
#define BOTAN_HAS_FPE_FE1 20131128
|
|
#define BOTAN_HAS_GHASH 20201002
|
|
#define BOTAN_HAS_GHASH_CLMUL_VPERM 20201002
|
|
#define BOTAN_HAS_GMAC 20160207
|
|
#define BOTAN_HAS_GOST_28147_89 20131128
|
|
#define BOTAN_HAS_GOST_34_10_2001 20131128
|
|
#define BOTAN_HAS_GOST_34_10_2012 20190801
|
|
#define BOTAN_HAS_GOST_34_11 20131128
|
|
#define BOTAN_HAS_HASH 20180112
|
|
#define BOTAN_HAS_HASH_ID 20131128
|
|
#define BOTAN_HAS_HEX_CODEC 20131128
|
|
#define BOTAN_HAS_HKDF 20170927
|
|
#define BOTAN_HAS_HMAC 20131128
|
|
#define BOTAN_HAS_HMAC_DRBG 20140319
|
|
#define BOTAN_HAS_HOTP 20180816
|
|
#define BOTAN_HAS_HTTP_UTIL 20171003
|
|
#define BOTAN_HAS_IDEA 20131128
|
|
#define BOTAN_HAS_IDEA_SSE2 20131128
|
|
#define BOTAN_HAS_ISO_9796 20161121
|
|
#define BOTAN_HAS_KASUMI 20131128
|
|
#define BOTAN_HAS_KDF1 20131128
|
|
#define BOTAN_HAS_KDF1_18033 20160128
|
|
#define BOTAN_HAS_KDF2 20131128
|
|
#define BOTAN_HAS_KDF_BASE 20131128
|
|
#define BOTAN_HAS_KECCAK 20131128
|
|
#define BOTAN_HAS_KEYPAIR_TESTING 20131128
|
|
#define BOTAN_HAS_LION 20131128
|
|
#define BOTAN_HAS_LOCKING_ALLOCATOR 20131128
|
|
#define BOTAN_HAS_MAC 20150626
|
|
#define BOTAN_HAS_MCEIES 20150706
|
|
#define BOTAN_HAS_MCELIECE 20150922
|
|
#define BOTAN_HAS_MD4 20131128
|
|
#define BOTAN_HAS_MD5 20131128
|
|
#define BOTAN_HAS_MDX_HASH_FUNCTION 20131128
|
|
#define BOTAN_HAS_MEM_POOL 20180309
|
|
#define BOTAN_HAS_MGF1 20140118
|
|
#define BOTAN_HAS_MISTY1 20131128
|
|
#define BOTAN_HAS_MODES 20150626
|
|
#define BOTAN_HAS_MODE_CBC 20131128
|
|
#define BOTAN_HAS_MODE_CFB 20131128
|
|
#define BOTAN_HAS_MODE_XTS 20131128
|
|
#define BOTAN_HAS_NEWHOPE 20161018
|
|
#define BOTAN_HAS_NIST_KEYWRAP 20171119
|
|
#define BOTAN_HAS_NOEKEON 20131128
|
|
#define BOTAN_HAS_NOEKEON_SIMD 20160903
|
|
#define BOTAN_HAS_NUMBERTHEORY 20131128
|
|
#define BOTAN_HAS_OCSP 20161118
|
|
#define BOTAN_HAS_OFB 20131128
|
|
#define BOTAN_HAS_PACKAGE_TRANSFORM 20131128
|
|
#define BOTAN_HAS_PARALLEL_HASH 20131128
|
|
#define BOTAN_HAS_PASSHASH9 20131128
|
|
#define BOTAN_HAS_PBKDF 20180902
|
|
#define BOTAN_HAS_PBKDF1 20131128
|
|
#define BOTAN_HAS_PBKDF2 20180902
|
|
#define BOTAN_HAS_PBKDF_BCRYPT 20190531
|
|
#define BOTAN_HAS_PEM_CODEC 20131128
|
|
#define BOTAN_HAS_PGP_S2K 20170527
|
|
#define BOTAN_HAS_PIPE_UNIXFD_IO 20131128
|
|
#define BOTAN_HAS_PKCS11 20160219
|
|
#define BOTAN_HAS_PKCS5_PBES2 20141119
|
|
#define BOTAN_HAS_PK_PADDING 20131128
|
|
#define BOTAN_HAS_POLY1305 20141227
|
|
#define BOTAN_HAS_POLY_DBL 20170927
|
|
#define BOTAN_HAS_PROCESSOR_RNG 20200508
|
|
#define BOTAN_HAS_PSK_DB 20171119
|
|
#define BOTAN_HAS_PUBLIC_KEY_CRYPTO 20131128
|
|
#define BOTAN_HAS_RC4 20131128
|
|
#define BOTAN_HAS_RDRAND_RNG 20160619
|
|
#define BOTAN_HAS_RFC3394_KEYWRAP 20131128
|
|
#define BOTAN_HAS_RFC6979_GENERATOR 20140321
|
|
#define BOTAN_HAS_RIPEMD_160 20131128
|
|
#define BOTAN_HAS_ROUGHTIME 20190220
|
|
#define BOTAN_HAS_RSA 20160730
|
|
#define BOTAN_HAS_SALSA20 20171114
|
|
#define BOTAN_HAS_SCRYPT 20180902
|
|
#define BOTAN_HAS_SEED 20131128
|
|
#define BOTAN_HAS_SERPENT 20131128
|
|
#define BOTAN_HAS_SERPENT_AVX2 20180824
|
|
#define BOTAN_HAS_SERPENT_SIMD 20160903
|
|
#define BOTAN_HAS_SHA1 20131128
|
|
#define BOTAN_HAS_SHA1_SSE2 20160803
|
|
#define BOTAN_HAS_SHA2_32 20131128
|
|
#define BOTAN_HAS_SHA2_32_X86_BMI2 20180526
|
|
#define BOTAN_HAS_SHA2_64 20131128
|
|
#define BOTAN_HAS_SHA2_64_BMI2 20190117
|
|
#define BOTAN_HAS_SHA3 20161018
|
|
#define BOTAN_HAS_SHA3_BMI2 20190117
|
|
#define BOTAN_HAS_SHACAL2 20170813
|
|
#define BOTAN_HAS_SHACAL2_AVX2 20180826
|
|
#define BOTAN_HAS_SHACAL2_SIMD 20170813
|
|
#define BOTAN_HAS_SHAKE 20161009
|
|
#define BOTAN_HAS_SHAKE_CIPHER 20161018
|
|
#define BOTAN_HAS_SIMD_32 20131128
|
|
#define BOTAN_HAS_SIMD_AVX2 20180824
|
|
#define BOTAN_HAS_SIPHASH 20150110
|
|
#define BOTAN_HAS_SKEIN_512 20131128
|
|
#define BOTAN_HAS_SM2 20180801
|
|
#define BOTAN_HAS_SM3 20170402
|
|
#define BOTAN_HAS_SM4 20170716
|
|
#define BOTAN_HAS_SOCKETS 20171216
|
|
#define BOTAN_HAS_SODIUM_API 20190615
|
|
#define BOTAN_HAS_SP800_108 20160128
|
|
#define BOTAN_HAS_SP800_56A 20170501
|
|
#define BOTAN_HAS_SP800_56C 20160211
|
|
#define BOTAN_HAS_SRP6 20161017
|
|
#define BOTAN_HAS_STATEFUL_RNG 20160819
|
|
#define BOTAN_HAS_STREAM_CIPHER 20131128
|
|
#define BOTAN_HAS_STREEBOG 20170623
|
|
#define BOTAN_HAS_SYSTEM_RNG 20141202
|
|
#define BOTAN_HAS_THREAD_UTILS 20190922
|
|
#define BOTAN_HAS_THREEFISH_512 20131224
|
|
#define BOTAN_HAS_THREEFISH_512_AVX2 20160903
|
|
#define BOTAN_HAS_THRESHOLD_SECRET_SHARING 20131128
|
|
#define BOTAN_HAS_TIGER 20131128
|
|
#define BOTAN_HAS_TLS 20191210
|
|
#define BOTAN_HAS_TLS_CBC 20161008
|
|
#define BOTAN_HAS_TLS_SESSION_MANAGER_SQL_DB 20141219
|
|
#define BOTAN_HAS_TLS_V10 20191109
|
|
#define BOTAN_HAS_TLS_V10_PRF 20131128
|
|
#define BOTAN_HAS_TLS_V12_PRF 20131128
|
|
#define BOTAN_HAS_TOTP 20180816
|
|
#define BOTAN_HAS_TWOFISH 20131128
|
|
#define BOTAN_HAS_UTIL_FUNCTIONS 20180903
|
|
#define BOTAN_HAS_UUID 20180930
|
|
#define BOTAN_HAS_WHIRLPOOL 20131128
|
|
#define BOTAN_HAS_X25519 20180910
|
|
#define BOTAN_HAS_X509 20180911
|
|
#define BOTAN_HAS_X509_CERTIFICATES 20151023
|
|
#define BOTAN_HAS_X942_PRF 20131128
|
|
#define BOTAN_HAS_XMSS_RFC8391 20201101
|
|
#define BOTAN_HAS_XTEA 20131128
|
|
|
|
|
|
/*
|
|
* Local/misc configuration options (if any) follow
|
|
*/
|
|
|
|
|
|
/*
|
|
* Things you can edit (but probably shouldn't)
|
|
*/
|
|
|
|
#if !defined(BOTAN_DEPRECATED_PUBLIC_MEMBER_VARIABLES)
|
|
|
|
#if defined(BOTAN_NO_DEPRECATED)
|
|
#define BOTAN_DEPRECATED_PUBLIC_MEMBER_VARIABLES private
|
|
#else
|
|
#define BOTAN_DEPRECATED_PUBLIC_MEMBER_VARIABLES public
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/* How much to allocate for a buffer of no particular size */
|
|
#define BOTAN_DEFAULT_BUFFER_SIZE 1024
|
|
|
|
/*
|
|
* Total maximum amount of RAM (in KiB) we will lock into memory, even
|
|
* if the OS would let us lock more
|
|
*/
|
|
#define BOTAN_MLOCK_ALLOCATOR_MAX_LOCKED_KB 512
|
|
|
|
/*
|
|
* If BOTAN_MEM_POOL_USE_MMU_PROTECTIONS is defined, the Memory_Pool
|
|
* class used for mlock'ed memory will use OS calls to set page
|
|
* permissions so as to prohibit access to pages on the free list, then
|
|
* enable read/write access when the page is set to be used. This will
|
|
* turn (some) use after free bugs into a crash.
|
|
*
|
|
* The additional syscalls have a substantial performance impact, which
|
|
* is why this option is not enabled by default.
|
|
*/
|
|
#if defined(BOTAN_HAS_VALGRIND) || defined(BOTAN_ENABLE_DEBUG_ASSERTS)
|
|
#define BOTAN_MEM_POOL_USE_MMU_PROTECTIONS
|
|
#endif
|
|
|
|
/*
|
|
* If enabled uses memset via volatile function pointer to zero memory,
|
|
* otherwise does a byte at a time write via a volatile pointer.
|
|
*/
|
|
#define BOTAN_USE_VOLATILE_MEMSET_FOR_ZERO 1
|
|
|
|
/*
|
|
* Normally blinding is performed by choosing a random starting point (plus
|
|
* its inverse, of a form appropriate to the algorithm being blinded), and
|
|
* then choosing new blinding operands by successive squaring of both
|
|
* values. This is much faster than computing a new starting point but
|
|
* introduces some possible corelation
|
|
*
|
|
* To avoid possible leakage problems in long-running processes, the blinder
|
|
* periodically reinitializes the sequence. This value specifies how often
|
|
* a new sequence should be started.
|
|
*/
|
|
#define BOTAN_BLINDING_REINIT_INTERVAL 64
|
|
|
|
/*
|
|
* Userspace RNGs like HMAC_DRBG will reseed after a specified number
|
|
* of outputs are generated. Set to zero to disable automatic reseeding.
|
|
*/
|
|
#define BOTAN_RNG_DEFAULT_RESEED_INTERVAL 1024
|
|
#define BOTAN_RNG_RESEED_POLL_BITS 256
|
|
|
|
#define BOTAN_RNG_AUTO_RESEED_TIMEOUT std::chrono::milliseconds(10)
|
|
#define BOTAN_RNG_RESEED_DEFAULT_TIMEOUT std::chrono::milliseconds(50)
|
|
|
|
/*
|
|
* Specifies (in order) the list of entropy sources that will be used
|
|
* to seed an in-memory RNG.
|
|
*/
|
|
#define BOTAN_ENTROPY_DEFAULT_SOURCES \
|
|
{ "rdseed", "hwrng", "p9_darn", "getentropy", "dev_random", \
|
|
"system_rng", "proc_walk", "system_stats" }
|
|
|
|
/* Multiplier on a block cipher's native parallelism */
|
|
#define BOTAN_BLOCK_CIPHER_PAR_MULT 4
|
|
|
|
/*
|
|
* These control the RNG used by the system RNG interface
|
|
*/
|
|
#define BOTAN_SYSTEM_RNG_DEVICE "/dev/urandom"
|
|
#define BOTAN_SYSTEM_RNG_POLL_DEVICES { "/dev/urandom", "/dev/random" }
|
|
|
|
/*
|
|
* This directory will be monitored by ProcWalking_EntropySource and
|
|
* the contents provided as entropy inputs to the RNG. May also be
|
|
* usefully set to something like "/sys", depending on the system being
|
|
* deployed to. Set to an empty string to disable.
|
|
*/
|
|
#define BOTAN_ENTROPY_PROC_FS_PATH "/proc"
|
|
|
|
/*
|
|
* These paramaters control how many bytes to read from the system
|
|
* PRNG, and how long to block if applicable. The timeout only applies
|
|
* to reading /dev/urandom and company.
|
|
*/
|
|
#define BOTAN_SYSTEM_RNG_POLL_REQUEST 64
|
|
#define BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS 20
|
|
|
|
/*
|
|
* When a PBKDF is self-tuning parameters, it will attempt to take about this
|
|
* amount of time to self-benchmark.
|
|
*/
|
|
#define BOTAN_PBKDF_TUNING_TIME std::chrono::milliseconds(10)
|
|
|
|
/*
|
|
* If no way of dynamically determining the cache line size for the
|
|
* system exists, this value is used as the default. Used by the side
|
|
* channel countermeasures rather than for alignment purposes, so it is
|
|
* better to be on the smaller side if the exact value cannot be
|
|
* determined. Typically 32 or 64 bytes on modern CPUs.
|
|
*/
|
|
#if !defined(BOTAN_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE)
|
|
#define BOTAN_TARGET_CPU_DEFAULT_CACHE_LINE_SIZE 32
|
|
#endif
|
|
|
|
/**
|
|
* Controls how AutoSeeded_RNG is instantiated
|
|
*/
|
|
#if !defined(BOTAN_AUTO_RNG_HMAC)
|
|
|
|
#if defined(BOTAN_HAS_SHA2_64)
|
|
#define BOTAN_AUTO_RNG_HMAC "HMAC(SHA-384)"
|
|
#elif defined(BOTAN_HAS_SHA2_32)
|
|
#define BOTAN_AUTO_RNG_HMAC "HMAC(SHA-256)"
|
|
#elif defined(BOTAN_HAS_SHA3)
|
|
#define BOTAN_AUTO_RNG_HMAC "HMAC(SHA-3(256))"
|
|
#elif defined(BOTAN_HAS_SHA1)
|
|
#define BOTAN_AUTO_RNG_HMAC "HMAC(SHA-1)"
|
|
#endif
|
|
/* Otherwise, no hash found: leave BOTAN_AUTO_RNG_HMAC undefined */
|
|
|
|
#endif
|
|
|
|
/* Check for a common build problem */
|
|
|
|
#if defined(BOTAN_TARGET_ARCH_IS_X86_64) && ((defined(_MSC_VER) && !defined(_WIN64)) || \
|
|
(defined(__clang__) && !defined(__x86_64__)) || \
|
|
(defined(__GNUG__) && !defined(__x86_64__)))
|
|
#error "Trying to compile Botan configured as x86_64 with non-x86_64 compiler."
|
|
#endif
|
|
|
|
#if defined(BOTAN_TARGET_ARCH_IS_X86_32) && ((defined(_MSC_VER) && defined(_WIN64)) || \
|
|
(defined(__clang__) && !defined(__i386__)) || \
|
|
(defined(__GNUG__) && !defined(__i386__)))
|
|
|
|
#error "Trying to compile Botan configured as x86_32 with non-x86_32 compiler."
|
|
#endif
|
|
|
|
/* Should we use GCC-style inline assembler? */
|
|
#if defined(BOTAN_BUILD_COMPILER_IS_GCC) || \
|
|
defined(BOTAN_BUILD_COMPILER_IS_CLANG) || \
|
|
defined(BOTAN_BUILD_COMPILER_IS_XLC) || \
|
|
defined(BOTAN_BUILD_COMPILER_IS_SUN_STUDIO)
|
|
|
|
#define BOTAN_USE_GCC_INLINE_ASM
|
|
#endif
|
|
|
|
/**
|
|
* Used to annotate API exports which are public and supported.
|
|
* These APIs will not be broken/removed unless strictly required for
|
|
* functionality or security, and only in new major versions.
|
|
* @param maj The major version this public API was released in
|
|
* @param min The minor version this public API was released in
|
|
*/
|
|
#define BOTAN_PUBLIC_API(maj,min) BOTAN_DLL
|
|
|
|
/**
|
|
* Used to annotate API exports which are public, but are now deprecated
|
|
* and which will be removed in a future major release.
|
|
*/
|
|
#define BOTAN_DEPRECATED_API(msg) BOTAN_DLL BOTAN_DEPRECATED(msg)
|
|
|
|
/**
|
|
* Used to annotate API exports which are public and can be used by
|
|
* applications if needed, but which are intentionally not documented,
|
|
* and which may change incompatibly in a future major version.
|
|
*/
|
|
#define BOTAN_UNSTABLE_API BOTAN_DLL
|
|
|
|
/**
|
|
* Used to annotate API exports which are exported but only for the
|
|
* purposes of testing. They should not be used by applications and
|
|
* may be removed or changed without notice.
|
|
*/
|
|
#define BOTAN_TEST_API BOTAN_DLL
|
|
|
|
/*
|
|
* Define BOTAN_GCC_VERSION
|
|
*/
|
|
#if defined(__GNUC__) && !defined(__clang__)
|
|
#define BOTAN_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__)
|
|
#else
|
|
#define BOTAN_GCC_VERSION 0
|
|
#endif
|
|
|
|
/*
|
|
* Define BOTAN_CLANG_VERSION
|
|
*/
|
|
#if defined(__clang__)
|
|
#define BOTAN_CLANG_VERSION (__clang_major__ * 10 + __clang_minor__)
|
|
#else
|
|
#define BOTAN_CLANG_VERSION 0
|
|
#endif
|
|
|
|
/*
|
|
* Define BOTAN_FUNC_ISA
|
|
*/
|
|
#if (defined(__GNUC__) && !defined(__clang__)) || (BOTAN_CLANG_VERSION > 38)
|
|
#define BOTAN_FUNC_ISA(isa) __attribute__ ((target(isa)))
|
|
#else
|
|
#define BOTAN_FUNC_ISA(isa)
|
|
#endif
|
|
|
|
/*
|
|
* Define BOTAN_WARN_UNUSED_RESULT
|
|
*/
|
|
#if defined(__GNUC__) || defined(__clang__)
|
|
#define BOTAN_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
|
|
#else
|
|
#define BOTAN_WARN_UNUSED_RESULT
|
|
#endif
|
|
|
|
/*
|
|
* Define BOTAN_MALLOC_FN
|
|
*/
|
|
#if defined(__ibmxl__)
|
|
/* XLC pretends to be both Clang and GCC, but is neither */
|
|
#define BOTAN_MALLOC_FN __attribute__ ((malloc))
|
|
#elif defined(__GNUC__)
|
|
#define BOTAN_MALLOC_FN __attribute__ ((malloc, alloc_size(1,2)))
|
|
#elif defined(_MSC_VER)
|
|
#define BOTAN_MALLOC_FN __declspec(restrict)
|
|
#else
|
|
#define BOTAN_MALLOC_FN
|
|
#endif
|
|
|
|
/*
|
|
* Define BOTAN_DEPRECATED
|
|
*/
|
|
#if !defined(BOTAN_NO_DEPRECATED_WARNINGS) && !defined(BOTAN_IS_BEING_BUILT) && !defined(BOTAN_AMALGAMATION_H_)
|
|
|
|
#if defined(__clang__)
|
|
#define BOTAN_DEPRECATED(msg) __attribute__ ((deprecated(msg)))
|
|
#define BOTAN_DEPRECATED_HEADER(hdr) _Pragma("message \"this header is deprecated\"")
|
|
#define BOTAN_FUTURE_INTERNAL_HEADER(hdr) _Pragma("message \"this header will be made internal in the future\"")
|
|
|
|
#elif defined(_MSC_VER)
|
|
#define BOTAN_DEPRECATED(msg) __declspec(deprecated(msg))
|
|
#define BOTAN_DEPRECATED_HEADER(hdr) __pragma(message("this header is deprecated"))
|
|
#define BOTAN_FUTURE_INTERNAL_HEADER(hdr) __pragma(message("this header will be made internal in the future"))
|
|
|
|
#elif defined(__GNUC__)
|
|
/* msg supported since GCC 4.5, earliest we support is 4.8 */
|
|
#define BOTAN_DEPRECATED(msg) __attribute__ ((deprecated(msg)))
|
|
#define BOTAN_DEPRECATED_HEADER(hdr) _Pragma("GCC warning \"this header is deprecated\"")
|
|
#define BOTAN_FUTURE_INTERNAL_HEADER(hdr) _Pragma("GCC warning \"this header will be made internal in the future\"")
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#if !defined(BOTAN_DEPRECATED)
|
|
#define BOTAN_DEPRECATED(msg)
|
|
#endif
|
|
|
|
#if !defined(BOTAN_DEPRECATED_HEADER)
|
|
#define BOTAN_DEPRECATED_HEADER(hdr)
|
|
#endif
|
|
|
|
#if !defined(BOTAN_FUTURE_INTERNAL_HEADER)
|
|
#define BOTAN_FUTURE_INTERNAL_HEADER(hdr)
|
|
#endif
|
|
|
|
/*
|
|
* Define BOTAN_NORETURN
|
|
*/
|
|
#if !defined(BOTAN_NORETURN)
|
|
|
|
#if defined (__clang__) || defined (__GNUC__)
|
|
#define BOTAN_NORETURN __attribute__ ((__noreturn__))
|
|
|
|
#elif defined (_MSC_VER)
|
|
#define BOTAN_NORETURN __declspec(noreturn)
|
|
|
|
#else
|
|
#define BOTAN_NORETURN
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Define BOTAN_THREAD_LOCAL
|
|
*/
|
|
#if !defined(BOTAN_THREAD_LOCAL)
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_THREADS) && defined(BOTAN_TARGET_OS_HAS_THREAD_LOCAL)
|
|
#define BOTAN_THREAD_LOCAL thread_local
|
|
#else
|
|
#define BOTAN_THREAD_LOCAL /**/
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Define BOTAN_IF_CONSTEXPR
|
|
*/
|
|
#if !defined(BOTAN_IF_CONSTEXPR)
|
|
#if __cplusplus >= 201703
|
|
#define BOTAN_IF_CONSTEXPR if constexpr
|
|
#else
|
|
#define BOTAN_IF_CONSTEXPR if
|
|
#endif
|
|
#endif
|
|
|
|
/*
|
|
* Define BOTAN_PARALLEL_FOR
|
|
*/
|
|
#if !defined(BOTAN_PARALLEL_FOR)
|
|
|
|
#if defined(BOTAN_TARGET_HAS_OPENMP)
|
|
#define BOTAN_PARALLEL_FOR _Pragma("omp parallel for") for
|
|
#else
|
|
#define BOTAN_PARALLEL_FOR for
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Define BOTAN_FORCE_INLINE
|
|
*/
|
|
#if !defined(BOTAN_FORCE_INLINE)
|
|
|
|
#if defined (__clang__) || defined (__GNUC__)
|
|
#define BOTAN_FORCE_INLINE __attribute__ ((__always_inline__)) inline
|
|
|
|
#elif defined (_MSC_VER)
|
|
#define BOTAN_FORCE_INLINE __forceinline
|
|
|
|
#else
|
|
#define BOTAN_FORCE_INLINE inline
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Define BOTAN_PARALLEL_SIMD_FOR
|
|
*/
|
|
#if !defined(BOTAN_PARALLEL_SIMD_FOR)
|
|
|
|
#if defined(BOTAN_TARGET_HAS_OPENMP)
|
|
#define BOTAN_PARALLEL_SIMD_FOR _Pragma("omp simd") for
|
|
#elif defined(BOTAN_BUILD_COMPILER_IS_GCC) && (BOTAN_GCC_VERSION >= 490)
|
|
#define BOTAN_PARALLEL_SIMD_FOR _Pragma("GCC ivdep") for
|
|
#else
|
|
#define BOTAN_PARALLEL_SIMD_FOR for
|
|
#endif
|
|
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Called when an assertion fails
|
|
* Throws an Exception object
|
|
*/
|
|
BOTAN_NORETURN void BOTAN_PUBLIC_API(2,0)
|
|
assertion_failure(const char* expr_str,
|
|
const char* assertion_made,
|
|
const char* func,
|
|
const char* file,
|
|
int line);
|
|
|
|
/**
|
|
* Called when an invalid argument is used
|
|
* Throws Invalid_Argument
|
|
*/
|
|
BOTAN_NORETURN void BOTAN_UNSTABLE_API throw_invalid_argument(const char* message,
|
|
const char* func,
|
|
const char* file);
|
|
|
|
|
|
#define BOTAN_ARG_CHECK(expr, msg) \
|
|
do { if(!(expr)) Botan::throw_invalid_argument(msg, __func__, __FILE__); } while(0)
|
|
|
|
/**
|
|
* Called when an invalid state is encountered
|
|
* Throws Invalid_State
|
|
*/
|
|
BOTAN_NORETURN void BOTAN_UNSTABLE_API throw_invalid_state(const char* message,
|
|
const char* func,
|
|
const char* file);
|
|
|
|
|
|
#define BOTAN_STATE_CHECK(expr) \
|
|
do { if(!(expr)) Botan::throw_invalid_state(#expr, __func__, __FILE__); } while(0)
|
|
|
|
/**
|
|
* Make an assertion
|
|
*/
|
|
#define BOTAN_ASSERT(expr, assertion_made) \
|
|
do { \
|
|
if(!(expr)) \
|
|
Botan::assertion_failure(#expr, \
|
|
assertion_made, \
|
|
__func__, \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} while(0)
|
|
|
|
/**
|
|
* Make an assertion
|
|
*/
|
|
#define BOTAN_ASSERT_NOMSG(expr) \
|
|
do { \
|
|
if(!(expr)) \
|
|
Botan::assertion_failure(#expr, \
|
|
"", \
|
|
__func__, \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} while(0)
|
|
|
|
/**
|
|
* Assert that value1 == value2
|
|
*/
|
|
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made) \
|
|
do { \
|
|
if((expr1) != (expr2)) \
|
|
Botan::assertion_failure(#expr1 " == " #expr2, \
|
|
assertion_made, \
|
|
__func__, \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} while(0)
|
|
|
|
/**
|
|
* Assert that expr1 (if true) implies expr2 is also true
|
|
*/
|
|
#define BOTAN_ASSERT_IMPLICATION(expr1, expr2, msg) \
|
|
do { \
|
|
if((expr1) && !(expr2)) \
|
|
Botan::assertion_failure(#expr1 " implies " #expr2, \
|
|
msg, \
|
|
__func__, \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} while(0)
|
|
|
|
/**
|
|
* Assert that a pointer is not null
|
|
*/
|
|
#define BOTAN_ASSERT_NONNULL(ptr) \
|
|
do { \
|
|
if((ptr) == nullptr) \
|
|
Botan::assertion_failure(#ptr " is not null", \
|
|
"", \
|
|
__func__, \
|
|
__FILE__, \
|
|
__LINE__); \
|
|
} while(0)
|
|
|
|
#if defined(BOTAN_ENABLE_DEBUG_ASSERTS)
|
|
|
|
#define BOTAN_DEBUG_ASSERT(expr) BOTAN_ASSERT_NOMSG(expr)
|
|
|
|
#else
|
|
|
|
#define BOTAN_DEBUG_ASSERT(expr) do {} while(0)
|
|
|
|
#endif
|
|
|
|
/**
|
|
* Mark variable as unused. Takes between 1 and 9 arguments and marks all as unused,
|
|
* e.g. BOTAN_UNUSED(a); or BOTAN_UNUSED(x, y, z);
|
|
*/
|
|
#define _BOTAN_UNUSED_IMPL1(a) static_cast<void>(a)
|
|
#define _BOTAN_UNUSED_IMPL2(a, b) static_cast<void>(a); _BOTAN_UNUSED_IMPL1(b)
|
|
#define _BOTAN_UNUSED_IMPL3(a, b, c) static_cast<void>(a); _BOTAN_UNUSED_IMPL2(b, c)
|
|
#define _BOTAN_UNUSED_IMPL4(a, b, c, d) static_cast<void>(a); _BOTAN_UNUSED_IMPL3(b, c, d)
|
|
#define _BOTAN_UNUSED_IMPL5(a, b, c, d, e) static_cast<void>(a); _BOTAN_UNUSED_IMPL4(b, c, d, e)
|
|
#define _BOTAN_UNUSED_IMPL6(a, b, c, d, e, f) static_cast<void>(a); _BOTAN_UNUSED_IMPL5(b, c, d, e, f)
|
|
#define _BOTAN_UNUSED_IMPL7(a, b, c, d, e, f, g) static_cast<void>(a); _BOTAN_UNUSED_IMPL6(b, c, d, e, f, g)
|
|
#define _BOTAN_UNUSED_IMPL8(a, b, c, d, e, f, g, h) static_cast<void>(a); _BOTAN_UNUSED_IMPL7(b, c, d, e, f, g, h)
|
|
#define _BOTAN_UNUSED_IMPL9(a, b, c, d, e, f, g, h, i) static_cast<void>(a); _BOTAN_UNUSED_IMPL8(b, c, d, e, f, g, h, i)
|
|
#define _BOTAN_UNUSED_GET_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, IMPL_NAME, ...) IMPL_NAME
|
|
|
|
#define BOTAN_UNUSED(...) _BOTAN_UNUSED_GET_IMPL(__VA_ARGS__, \
|
|
_BOTAN_UNUSED_IMPL9, \
|
|
_BOTAN_UNUSED_IMPL8, \
|
|
_BOTAN_UNUSED_IMPL7, \
|
|
_BOTAN_UNUSED_IMPL6, \
|
|
_BOTAN_UNUSED_IMPL5, \
|
|
_BOTAN_UNUSED_IMPL4, \
|
|
_BOTAN_UNUSED_IMPL3, \
|
|
_BOTAN_UNUSED_IMPL2, \
|
|
_BOTAN_UNUSED_IMPL1, \
|
|
unused dummy rest value \
|
|
) /* we got an one of _BOTAN_UNUSED_IMPL*, now call it */ (__VA_ARGS__)
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* @mainpage Botan Crypto Library API Reference
|
|
*
|
|
* <dl>
|
|
* <dt>Abstract Base Classes<dd>
|
|
* BlockCipher, HashFunction, KDF, MessageAuthenticationCode, RandomNumberGenerator,
|
|
* StreamCipher, SymmetricAlgorithm, AEAD_Mode, Cipher_Mode
|
|
* <dt>Public Key Interface Classes<dd>
|
|
* PK_Key_Agreement, PK_Signer, PK_Verifier, PK_Encryptor, PK_Decryptor
|
|
* <dt>Authenticated Encryption Modes<dd>
|
|
* @ref CCM_Mode "CCM", @ref ChaCha20Poly1305_Mode "ChaCha20Poly1305", @ref EAX_Mode "EAX",
|
|
* @ref GCM_Mode "GCM", @ref OCB_Mode "OCB", @ref SIV_Mode "SIV"
|
|
* <dt>Block Ciphers<dd>
|
|
* @ref aria.h "ARIA", @ref aes.h "AES", @ref Blowfish, @ref camellia.h "Camellia", @ref Cascade_Cipher "Cascade",
|
|
* @ref CAST_128 "CAST-128", @ref CAST_128 "CAST-256", DES, @ref DESX "DES-X", @ref TripleDES "3DES",
|
|
* @ref GOST_28147_89 "GOST 28147-89", IDEA, KASUMI, Lion, MISTY1, Noekeon, SEED, Serpent, SHACAL2, SM4,
|
|
* @ref Threefish_512 "Threefish", Twofish, XTEA
|
|
* <dt>Stream Ciphers<dd>
|
|
* ChaCha, @ref CTR_BE "CTR", OFB, RC4, Salsa20
|
|
* <dt>Hash Functions<dd>
|
|
* BLAKE2b, @ref GOST_34_11 "GOST 34.11", @ref Keccak_1600 "Keccak", MD4, MD5, @ref RIPEMD_160 "RIPEMD-160",
|
|
* @ref SHA_160 "SHA-1", @ref SHA_224 "SHA-224", @ref SHA_256 "SHA-256", @ref SHA_384 "SHA-384",
|
|
* @ref SHA_512 "SHA-512", @ref Skein_512 "Skein-512", SM3, Streebog, Tiger, Whirlpool
|
|
* <dt>Non-Cryptographic Checksums<dd>
|
|
* Adler32, CRC24, CRC32
|
|
* <dt>Message Authentication Codes<dd>
|
|
* @ref CBC_MAC "CBC-MAC", CMAC, HMAC, Poly1305, SipHash, ANSI_X919_MAC
|
|
* <dt>Random Number Generators<dd>
|
|
* AutoSeeded_RNG, HMAC_DRBG, Processor_RNG, System_RNG
|
|
* <dt>Key Derivation<dd>
|
|
* HKDF, @ref KDF1 "KDF1 (IEEE 1363)", @ref KDF1_18033 "KDF1 (ISO 18033-2)", @ref KDF2 "KDF2 (IEEE 1363)",
|
|
* @ref sp800_108.h "SP800-108", @ref SP800_56C "SP800-56C", @ref PKCS5_PBKDF1 "PBKDF1 (PKCS#5),
|
|
* @ref PKCS5_PBKDF2 "PBKDF2 (PKCS#5)"
|
|
* <dt>Password Hashing<dd>
|
|
* @ref argon2.h "Argon2", @ref scrypt.h "scrypt", @ref bcrypt.h "bcrypt", @ref passhash9.h "passhash9"
|
|
* <dt>Public Key Cryptosystems<dd>
|
|
* @ref dlies.h "DLIES", @ref ecies.h "ECIES", @ref elgamal.h "ElGamal"
|
|
* @ref rsa.h "RSA", @ref newhope.h "NewHope", @ref mceliece.h "McEliece" and @ref mceies.h "MCEIES",
|
|
* @ref sm2.h "SM2"
|
|
* <dt>Public Key Signature Schemes<dd>
|
|
* @ref dsa.h "DSA", @ref ecdsa.h "ECDSA", @ref ecgdsa.h "ECGDSA", @ref eckcdsa.h "ECKCDSA",
|
|
* @ref gost_3410.h "GOST 34.10-2001", @ref sm2.h "SM2", @ref xmss.h "XMSS"
|
|
* <dt>Key Agreement<dd>
|
|
* @ref dh.h "DH", @ref ecdh.h "ECDH"
|
|
* <dt>Compression<dd>
|
|
* @ref bzip2.h "bzip2", @ref lzma.h "lzma", @ref zlib.h "zlib"
|
|
* <dt>TLS<dd>
|
|
* TLS::Client, TLS::Server, TLS::Policy, TLS::Protocol_Version, TLS::Callbacks, TLS::Ciphersuite,
|
|
* TLS::Session, TLS::Session_Manager, Credentials_Manager
|
|
* <dt>X.509<dd>
|
|
* X509_Certificate, X509_CRL, X509_CA, Certificate_Extension, PKCS10_Request, X509_Cert_Options,
|
|
* Certificate_Store, Certificate_Store_In_SQL, Certificate_Store_In_SQLite
|
|
* </dl>
|
|
*/
|
|
|
|
using std::uint8_t;
|
|
using std::uint16_t;
|
|
using std::uint32_t;
|
|
using std::uint64_t;
|
|
using std::int32_t;
|
|
using std::int64_t;
|
|
using std::size_t;
|
|
|
|
/*
|
|
* These typedefs are no longer used within the library headers
|
|
* or code. They are kept only for compatability with software
|
|
* written against older versions.
|
|
*/
|
|
using byte = std::uint8_t;
|
|
using u16bit = std::uint16_t;
|
|
using u32bit = std::uint32_t;
|
|
using u64bit = std::uint64_t;
|
|
using s32bit = std::int32_t;
|
|
|
|
#if (BOTAN_MP_WORD_BITS == 32)
|
|
typedef uint32_t word;
|
|
#elif (BOTAN_MP_WORD_BITS == 64)
|
|
typedef uint64_t word;
|
|
#else
|
|
#error BOTAN_MP_WORD_BITS must be 32 or 64
|
|
#endif
|
|
|
|
/*
|
|
* Should this assert fail on your system please contact the developers
|
|
* for assistance in porting.
|
|
*/
|
|
static_assert(sizeof(std::size_t) == 8 || sizeof(std::size_t) == 4,
|
|
"This platform has an unexpected size for size_t");
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Allocate a memory buffer by some method. This should only be used for
|
|
* primitive types (uint8_t, uint32_t, etc).
|
|
*
|
|
* @param elems the number of elements
|
|
* @param elem_size the size of each element
|
|
* @return pointer to allocated and zeroed memory, or throw std::bad_alloc on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3) BOTAN_MALLOC_FN void* allocate_memory(size_t elems, size_t elem_size);
|
|
|
|
/**
|
|
* Free a pointer returned by allocate_memory
|
|
* @param p the pointer returned by allocate_memory
|
|
* @param elems the number of elements, as passed to allocate_memory
|
|
* @param elem_size the size of each element, as passed to allocate_memory
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3) void deallocate_memory(void* p, size_t elems, size_t elem_size);
|
|
|
|
/**
|
|
* Ensure the allocator is initialized
|
|
*/
|
|
void BOTAN_UNSTABLE_API initialize_allocator();
|
|
|
|
class Allocator_Initializer
|
|
{
|
|
public:
|
|
Allocator_Initializer() { initialize_allocator(); }
|
|
};
|
|
|
|
/**
|
|
* Scrub memory contents in a way that a compiler should not elide,
|
|
* using some system specific technique. Note that this function might
|
|
* not zero the memory (for example, in some hypothetical
|
|
* implementation it might combine the memory contents with the output
|
|
* of a system PRNG), but if you can detect any difference in behavior
|
|
* at runtime then the clearing is side-effecting and you can just
|
|
* use `clear_mem`.
|
|
*
|
|
* Use this function to scrub memory just before deallocating it, or on
|
|
* a stack buffer before returning from the function.
|
|
*
|
|
* @param ptr a pointer to memory to scrub
|
|
* @param n the number of bytes pointed to by ptr
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) void secure_scrub_memory(void* ptr, size_t n);
|
|
|
|
/**
|
|
* Memory comparison, input insensitive
|
|
* @param x a pointer to an array
|
|
* @param y a pointer to another array
|
|
* @param len the number of Ts in x and y
|
|
* @return 0xFF iff x[i] == y[i] forall i in [0...n) or 0x00 otherwise
|
|
*/
|
|
BOTAN_PUBLIC_API(2,9) uint8_t ct_compare_u8(const uint8_t x[],
|
|
const uint8_t y[],
|
|
size_t len);
|
|
|
|
/**
|
|
* Memory comparison, input insensitive
|
|
* @param x a pointer to an array
|
|
* @param y a pointer to another array
|
|
* @param len the number of Ts in x and y
|
|
* @return true iff x[i] == y[i] forall i in [0...n)
|
|
*/
|
|
inline bool constant_time_compare(const uint8_t x[],
|
|
const uint8_t y[],
|
|
size_t len)
|
|
{
|
|
return ct_compare_u8(x, y, len) == 0xFF;
|
|
}
|
|
|
|
/**
|
|
* Zero out some bytes. Warning: use secure_scrub_memory instead if the
|
|
* memory is about to be freed or otherwise the compiler thinks it can
|
|
* elide the writes.
|
|
*
|
|
* @param ptr a pointer to memory to zero
|
|
* @param bytes the number of bytes to zero in ptr
|
|
*/
|
|
inline void clear_bytes(void* ptr, size_t bytes)
|
|
{
|
|
if(bytes > 0)
|
|
{
|
|
std::memset(ptr, 0, bytes);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Zero memory before use. This simply calls memset and should not be
|
|
* used in cases where the compiler cannot see the call as a
|
|
* side-effecting operation (for example, if calling clear_mem before
|
|
* deallocating memory, the compiler would be allowed to omit the call
|
|
* to memset entirely under the as-if rule.)
|
|
*
|
|
* @param ptr a pointer to an array of Ts to zero
|
|
* @param n the number of Ts pointed to by ptr
|
|
*/
|
|
template<typename T> inline void clear_mem(T* ptr, size_t n)
|
|
{
|
|
clear_bytes(ptr, sizeof(T)*n);
|
|
}
|
|
|
|
// is_trivially_copyable is missing in g++ < 5.0
|
|
#if (BOTAN_GCC_VERSION > 0 && BOTAN_GCC_VERSION < 500)
|
|
#define BOTAN_IS_TRIVIALLY_COPYABLE(T) true
|
|
#else
|
|
#define BOTAN_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
|
|
#endif
|
|
|
|
/**
|
|
* Copy memory
|
|
* @param out the destination array
|
|
* @param in the source array
|
|
* @param n the number of elements of in/out
|
|
*/
|
|
template<typename T> inline void copy_mem(T* out, const T* in, size_t n)
|
|
{
|
|
static_assert(std::is_trivial<typename std::decay<T>::type>::value, "");
|
|
BOTAN_ASSERT_IMPLICATION(n > 0, in != nullptr && out != nullptr,
|
|
"If n > 0 then args are not null");
|
|
|
|
if(in != nullptr && out != nullptr && n > 0)
|
|
{
|
|
std::memmove(out, in, sizeof(T)*n);
|
|
}
|
|
}
|
|
|
|
template<typename T> inline void typecast_copy(uint8_t out[], T in[], size_t N)
|
|
{
|
|
static_assert(BOTAN_IS_TRIVIALLY_COPYABLE(T), "");
|
|
std::memcpy(out, in, sizeof(T)*N);
|
|
}
|
|
|
|
template<typename T> inline void typecast_copy(T out[], const uint8_t in[], size_t N)
|
|
{
|
|
static_assert(std::is_trivial<T>::value, "");
|
|
std::memcpy(out, in, sizeof(T)*N);
|
|
}
|
|
|
|
template<typename T> inline void typecast_copy(uint8_t out[], T in)
|
|
{
|
|
typecast_copy(out, &in, 1);
|
|
}
|
|
|
|
template<typename T> inline void typecast_copy(T& out, const uint8_t in[])
|
|
{
|
|
static_assert(std::is_trivial<typename std::decay<T>::type>::value, "");
|
|
typecast_copy(&out, in, 1);
|
|
}
|
|
|
|
template <class To, class From> inline To typecast_copy(const From *src) noexcept
|
|
{
|
|
static_assert(BOTAN_IS_TRIVIALLY_COPYABLE(From) && std::is_trivial<To>::value, "");
|
|
To dst;
|
|
std::memcpy(&dst, src, sizeof(To));
|
|
return dst;
|
|
}
|
|
|
|
/**
|
|
* Set memory to a fixed value
|
|
* @param ptr a pointer to an array of bytes
|
|
* @param n the number of Ts pointed to by ptr
|
|
* @param val the value to set each byte to
|
|
*/
|
|
inline void set_mem(uint8_t* ptr, size_t n, uint8_t val)
|
|
{
|
|
if(n > 0)
|
|
{
|
|
std::memset(ptr, val, n);
|
|
}
|
|
}
|
|
|
|
inline const uint8_t* cast_char_ptr_to_uint8(const char* s)
|
|
{
|
|
return reinterpret_cast<const uint8_t*>(s);
|
|
}
|
|
|
|
inline const char* cast_uint8_ptr_to_char(const uint8_t* b)
|
|
{
|
|
return reinterpret_cast<const char*>(b);
|
|
}
|
|
|
|
inline uint8_t* cast_char_ptr_to_uint8(char* s)
|
|
{
|
|
return reinterpret_cast<uint8_t*>(s);
|
|
}
|
|
|
|
inline char* cast_uint8_ptr_to_char(uint8_t* b)
|
|
{
|
|
return reinterpret_cast<char*>(b);
|
|
}
|
|
|
|
/**
|
|
* Memory comparison, input insensitive
|
|
* @param p1 a pointer to an array
|
|
* @param p2 a pointer to another array
|
|
* @param n the number of Ts in p1 and p2
|
|
* @return true iff p1[i] == p2[i] forall i in [0...n)
|
|
*/
|
|
template<typename T> inline bool same_mem(const T* p1, const T* p2, size_t n)
|
|
{
|
|
volatile T difference = 0;
|
|
|
|
for(size_t i = 0; i != n; ++i)
|
|
difference |= (p1[i] ^ p2[i]);
|
|
|
|
return difference == 0;
|
|
}
|
|
|
|
template<typename T, typename Alloc>
|
|
size_t buffer_insert(std::vector<T, Alloc>& buf,
|
|
size_t buf_offset,
|
|
const T input[],
|
|
size_t input_length)
|
|
{
|
|
BOTAN_ASSERT_NOMSG(buf_offset <= buf.size());
|
|
const size_t to_copy = std::min(input_length, buf.size() - buf_offset);
|
|
if(to_copy > 0)
|
|
{
|
|
copy_mem(&buf[buf_offset], input, to_copy);
|
|
}
|
|
return to_copy;
|
|
}
|
|
|
|
template<typename T, typename Alloc, typename Alloc2>
|
|
size_t buffer_insert(std::vector<T, Alloc>& buf,
|
|
size_t buf_offset,
|
|
const std::vector<T, Alloc2>& input)
|
|
{
|
|
BOTAN_ASSERT_NOMSG(buf_offset <= buf.size());
|
|
const size_t to_copy = std::min(input.size(), buf.size() - buf_offset);
|
|
if(to_copy > 0)
|
|
{
|
|
copy_mem(&buf[buf_offset], input.data(), to_copy);
|
|
}
|
|
return to_copy;
|
|
}
|
|
|
|
/**
|
|
* XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
|
|
* @param out the input/output buffer
|
|
* @param in the read-only input buffer
|
|
* @param length the length of the buffers
|
|
*/
|
|
inline void xor_buf(uint8_t out[],
|
|
const uint8_t in[],
|
|
size_t length)
|
|
{
|
|
const size_t blocks = length - (length % 32);
|
|
|
|
for(size_t i = 0; i != blocks; i += 32)
|
|
{
|
|
uint64_t x[4];
|
|
uint64_t y[4];
|
|
|
|
typecast_copy(x, out + i, 4);
|
|
typecast_copy(y, in + i, 4);
|
|
|
|
x[0] ^= y[0];
|
|
x[1] ^= y[1];
|
|
x[2] ^= y[2];
|
|
x[3] ^= y[3];
|
|
|
|
typecast_copy(out + i, x, 4);
|
|
}
|
|
|
|
for(size_t i = blocks; i != length; ++i)
|
|
{
|
|
out[i] ^= in[i];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* XOR arrays. Postcondition out[i] = in[i] ^ in2[i] forall i = 0...length
|
|
* @param out the output buffer
|
|
* @param in the first input buffer
|
|
* @param in2 the second output buffer
|
|
* @param length the length of the three buffers
|
|
*/
|
|
inline void xor_buf(uint8_t out[],
|
|
const uint8_t in[],
|
|
const uint8_t in2[],
|
|
size_t length)
|
|
{
|
|
const size_t blocks = length - (length % 32);
|
|
|
|
for(size_t i = 0; i != blocks; i += 32)
|
|
{
|
|
uint64_t x[4];
|
|
uint64_t y[4];
|
|
|
|
typecast_copy(x, in + i, 4);
|
|
typecast_copy(y, in2 + i, 4);
|
|
|
|
x[0] ^= y[0];
|
|
x[1] ^= y[1];
|
|
x[2] ^= y[2];
|
|
x[3] ^= y[3];
|
|
|
|
typecast_copy(out + i, x, 4);
|
|
}
|
|
|
|
for(size_t i = blocks; i != length; ++i)
|
|
{
|
|
out[i] = in[i] ^ in2[i];
|
|
}
|
|
}
|
|
|
|
template<typename Alloc, typename Alloc2>
|
|
void xor_buf(std::vector<uint8_t, Alloc>& out,
|
|
const std::vector<uint8_t, Alloc2>& in,
|
|
size_t n)
|
|
{
|
|
xor_buf(out.data(), in.data(), n);
|
|
}
|
|
|
|
template<typename Alloc>
|
|
void xor_buf(std::vector<uint8_t, Alloc>& out,
|
|
const uint8_t* in,
|
|
size_t n)
|
|
{
|
|
xor_buf(out.data(), in, n);
|
|
}
|
|
|
|
template<typename Alloc, typename Alloc2>
|
|
void xor_buf(std::vector<uint8_t, Alloc>& out,
|
|
const uint8_t* in,
|
|
const std::vector<uint8_t, Alloc2>& in2,
|
|
size_t n)
|
|
{
|
|
xor_buf(out.data(), in, in2.data(), n);
|
|
}
|
|
|
|
template<typename Alloc, typename Alloc2>
|
|
std::vector<uint8_t, Alloc>&
|
|
operator^=(std::vector<uint8_t, Alloc>& out,
|
|
const std::vector<uint8_t, Alloc2>& in)
|
|
{
|
|
if(out.size() < in.size())
|
|
out.resize(in.size());
|
|
|
|
xor_buf(out.data(), in.data(), in.size());
|
|
return out;
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
template<typename T>
|
|
class secure_allocator
|
|
{
|
|
public:
|
|
/*
|
|
* Assert exists to prevent someone from doing something that will
|
|
* probably crash anyway (like secure_vector<non_POD_t> where ~non_POD_t
|
|
* deletes a member pointer which was zeroed before it ran).
|
|
* MSVC in debug mode uses non-integral proxy types in container types
|
|
* like std::vector, thus we disable the check there.
|
|
*/
|
|
#if !defined(_ITERATOR_DEBUG_LEVEL) || _ITERATOR_DEBUG_LEVEL == 0
|
|
static_assert(std::is_integral<T>::value, "secure_allocator supports only integer types");
|
|
#endif
|
|
|
|
typedef T value_type;
|
|
typedef std::size_t size_type;
|
|
|
|
secure_allocator() noexcept = default;
|
|
secure_allocator(const secure_allocator&) noexcept = default;
|
|
secure_allocator& operator=(const secure_allocator&) noexcept = default;
|
|
~secure_allocator() noexcept = default;
|
|
|
|
template<typename U>
|
|
secure_allocator(const secure_allocator<U>&) noexcept {}
|
|
|
|
T* allocate(std::size_t n)
|
|
{
|
|
return static_cast<T*>(allocate_memory(n, sizeof(T)));
|
|
}
|
|
|
|
void deallocate(T* p, std::size_t n)
|
|
{
|
|
deallocate_memory(p, n, sizeof(T));
|
|
}
|
|
};
|
|
|
|
template<typename T, typename U> inline bool
|
|
operator==(const secure_allocator<T>&, const secure_allocator<U>&)
|
|
{ return true; }
|
|
|
|
template<typename T, typename U> inline bool
|
|
operator!=(const secure_allocator<T>&, const secure_allocator<U>&)
|
|
{ return false; }
|
|
|
|
template<typename T> using secure_vector = std::vector<T, secure_allocator<T>>;
|
|
template<typename T> using secure_deque = std::deque<T, secure_allocator<T>>;
|
|
|
|
// For better compatibility with 1.10 API
|
|
template<typename T> using SecureVector = secure_vector<T>;
|
|
|
|
template<typename T>
|
|
std::vector<T> unlock(const secure_vector<T>& in)
|
|
{
|
|
return std::vector<T>(in.begin(), in.end());
|
|
}
|
|
|
|
template<typename T, typename Alloc, typename Alloc2>
|
|
std::vector<T, Alloc>&
|
|
operator+=(std::vector<T, Alloc>& out,
|
|
const std::vector<T, Alloc2>& in)
|
|
{
|
|
out.reserve(out.size() + in.size());
|
|
out.insert(out.end(), in.begin(), in.end());
|
|
return out;
|
|
}
|
|
|
|
template<typename T, typename Alloc>
|
|
std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out, T in)
|
|
{
|
|
out.push_back(in);
|
|
return out;
|
|
}
|
|
|
|
template<typename T, typename Alloc, typename L>
|
|
std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out,
|
|
const std::pair<const T*, L>& in)
|
|
{
|
|
out.reserve(out.size() + in.second);
|
|
out.insert(out.end(), in.first, in.first + in.second);
|
|
return out;
|
|
}
|
|
|
|
template<typename T, typename Alloc, typename L>
|
|
std::vector<T, Alloc>& operator+=(std::vector<T, Alloc>& out,
|
|
const std::pair<T*, L>& in)
|
|
{
|
|
out.reserve(out.size() + in.second);
|
|
out.insert(out.end(), in.first, in.first + in.second);
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* Zeroise the values; length remains unchanged
|
|
* @param vec the vector to zeroise
|
|
*/
|
|
template<typename T, typename Alloc>
|
|
void zeroise(std::vector<T, Alloc>& vec)
|
|
{
|
|
clear_mem(vec.data(), vec.size());
|
|
}
|
|
|
|
/**
|
|
* Zeroise the values then free the memory
|
|
* @param vec the vector to zeroise and free
|
|
*/
|
|
template<typename T, typename Alloc>
|
|
void zap(std::vector<T, Alloc>& vec)
|
|
{
|
|
zeroise(vec);
|
|
vec.clear();
|
|
vec.shrink_to_fit();
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents any kind of computation which uses an internal
|
|
* state, such as hash functions or MACs
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Buffered_Computation
|
|
{
|
|
public:
|
|
/**
|
|
* @return length of the output of this function in bytes
|
|
*/
|
|
virtual size_t output_length() const = 0;
|
|
|
|
/**
|
|
* Add new input to process.
|
|
* @param in the input to process as a byte array
|
|
* @param length of param in in bytes
|
|
*/
|
|
void update(const uint8_t in[], size_t length) { add_data(in, length); }
|
|
|
|
/**
|
|
* Add new input to process.
|
|
* @param in the input to process as a secure_vector
|
|
*/
|
|
void update(const secure_vector<uint8_t>& in)
|
|
{
|
|
add_data(in.data(), in.size());
|
|
}
|
|
|
|
/**
|
|
* Add new input to process.
|
|
* @param in the input to process as a std::vector
|
|
*/
|
|
void update(const std::vector<uint8_t>& in)
|
|
{
|
|
add_data(in.data(), in.size());
|
|
}
|
|
|
|
void update_be(uint16_t val);
|
|
void update_be(uint32_t val);
|
|
void update_be(uint64_t val);
|
|
|
|
void update_le(uint16_t val);
|
|
void update_le(uint32_t val);
|
|
void update_le(uint64_t val);
|
|
|
|
/**
|
|
* Add new input to process.
|
|
* @param str the input to process as a std::string. Will be interpreted
|
|
* as a byte array based on the strings encoding.
|
|
*/
|
|
void update(const std::string& str)
|
|
{
|
|
add_data(cast_char_ptr_to_uint8(str.data()), str.size());
|
|
}
|
|
|
|
/**
|
|
* Process a single byte.
|
|
* @param in the byte to process
|
|
*/
|
|
void update(uint8_t in) { add_data(&in, 1); }
|
|
|
|
/**
|
|
* Complete the computation and retrieve the
|
|
* final result.
|
|
* @param out The byte array to be filled with the result.
|
|
* Must be of length output_length()
|
|
*/
|
|
void final(uint8_t out[]) { final_result(out); }
|
|
|
|
/**
|
|
* Complete the computation and retrieve the
|
|
* final result.
|
|
* @return secure_vector holding the result
|
|
*/
|
|
secure_vector<uint8_t> final()
|
|
{
|
|
secure_vector<uint8_t> output(output_length());
|
|
final_result(output.data());
|
|
return output;
|
|
}
|
|
|
|
std::vector<uint8_t> final_stdvec()
|
|
{
|
|
std::vector<uint8_t> output(output_length());
|
|
final_result(output.data());
|
|
return output;
|
|
}
|
|
|
|
template<typename Alloc>
|
|
void final(std::vector<uint8_t, Alloc>& out)
|
|
{
|
|
out.resize(output_length());
|
|
final_result(out.data());
|
|
}
|
|
|
|
/**
|
|
* Update and finalize computation. Does the same as calling update()
|
|
* and final() consecutively.
|
|
* @param in the input to process as a byte array
|
|
* @param length the length of the byte array
|
|
* @result the result of the call to final()
|
|
*/
|
|
secure_vector<uint8_t> process(const uint8_t in[], size_t length)
|
|
{
|
|
add_data(in, length);
|
|
return final();
|
|
}
|
|
|
|
/**
|
|
* Update and finalize computation. Does the same as calling update()
|
|
* and final() consecutively.
|
|
* @param in the input to process
|
|
* @result the result of the call to final()
|
|
*/
|
|
secure_vector<uint8_t> process(const secure_vector<uint8_t>& in)
|
|
{
|
|
add_data(in.data(), in.size());
|
|
return final();
|
|
}
|
|
|
|
/**
|
|
* Update and finalize computation. Does the same as calling update()
|
|
* and final() consecutively.
|
|
* @param in the input to process
|
|
* @result the result of the call to final()
|
|
*/
|
|
secure_vector<uint8_t> process(const std::vector<uint8_t>& in)
|
|
{
|
|
add_data(in.data(), in.size());
|
|
return final();
|
|
}
|
|
|
|
/**
|
|
* Update and finalize computation. Does the same as calling update()
|
|
* and final() consecutively.
|
|
* @param in the input to process as a string
|
|
* @result the result of the call to final()
|
|
*/
|
|
secure_vector<uint8_t> process(const std::string& in)
|
|
{
|
|
update(in);
|
|
return final();
|
|
}
|
|
|
|
virtual ~Buffered_Computation() = default;
|
|
private:
|
|
/**
|
|
* Add more data to the computation
|
|
* @param input is an input buffer
|
|
* @param length is the length of input in bytes
|
|
*/
|
|
virtual void add_data(const uint8_t input[], size_t length) = 0;
|
|
|
|
/**
|
|
* Write the final output to out
|
|
* @param out is an output buffer of output_length()
|
|
*/
|
|
virtual void final_result(uint8_t out[]) = 0;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents hash function (message digest) objects
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) HashFunction : public Buffered_Computation
|
|
{
|
|
public:
|
|
/**
|
|
* Create an instance based on a name, or return null if the
|
|
* algo/provider combination cannot be found. If provider is
|
|
* empty then best available is chosen.
|
|
*/
|
|
static std::unique_ptr<HashFunction>
|
|
create(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* Create an instance based on a name
|
|
* If provider is empty then best available is chosen.
|
|
* @param algo_spec algorithm name
|
|
* @param provider provider implementation to use
|
|
* Throws Lookup_Error if not found.
|
|
*/
|
|
static std::unique_ptr<HashFunction>
|
|
create_or_throw(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* @return list of available providers for this algorithm, empty if not available
|
|
* @param algo_spec algorithm name
|
|
*/
|
|
static std::vector<std::string> providers(const std::string& algo_spec);
|
|
|
|
/**
|
|
* @return new object representing the same algorithm as *this
|
|
*/
|
|
virtual HashFunction* clone() const = 0;
|
|
|
|
/**
|
|
* @return provider information about this implementation. Default is "base",
|
|
* might also return "sse2", "avx2", "openssl", or some other arbitrary string.
|
|
*/
|
|
virtual std::string provider() const { return "base"; }
|
|
|
|
virtual ~HashFunction() = default;
|
|
|
|
/**
|
|
* Reset the state.
|
|
*/
|
|
virtual void clear() = 0;
|
|
|
|
/**
|
|
* @return the hash function name
|
|
*/
|
|
virtual std::string name() const = 0;
|
|
|
|
/**
|
|
* @return hash block size as defined for this algorithm
|
|
*/
|
|
virtual size_t hash_block_size() const { return 0; }
|
|
|
|
/**
|
|
* Return a new hash object with the same state as *this. This
|
|
* allows computing the hash of several messages with a common
|
|
* prefix more efficiently than would otherwise be possible.
|
|
*
|
|
* This function should be called `clone` but that was already
|
|
* used for the case of returning an uninitialized object.
|
|
* @return new hash object
|
|
*/
|
|
virtual std::unique_ptr<HashFunction> copy_state() const = 0;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(adler32.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* The Adler32 checksum, used in zlib
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Adler32 final : public HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "Adler32"; }
|
|
size_t output_length() const override { return 4; }
|
|
HashFunction* clone() const override { return new Adler32; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override { m_S1 = 1; m_S2 = 0; }
|
|
|
|
Adler32() { clear(); }
|
|
~Adler32() { clear(); }
|
|
private:
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
uint16_t m_S1, m_S2;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Octet String
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) OctetString final
|
|
{
|
|
public:
|
|
/**
|
|
* @return size of this octet string in bytes
|
|
*/
|
|
size_t length() const { return m_data.size(); }
|
|
size_t size() const { return m_data.size(); }
|
|
|
|
/**
|
|
* @return this object as a secure_vector<uint8_t>
|
|
*/
|
|
secure_vector<uint8_t> bits_of() const { return m_data; }
|
|
|
|
/**
|
|
* @return start of this string
|
|
*/
|
|
const uint8_t* begin() const { return m_data.data(); }
|
|
|
|
/**
|
|
* @return end of this string
|
|
*/
|
|
const uint8_t* end() const { return begin() + m_data.size(); }
|
|
|
|
/**
|
|
* @return this encoded as hex
|
|
*/
|
|
std::string to_string() const;
|
|
|
|
std::string BOTAN_DEPRECATED("Use OctetString::to_string") as_string() const
|
|
{
|
|
return this->to_string();
|
|
}
|
|
|
|
/**
|
|
* XOR the contents of another octet string into this one
|
|
* @param other octet string
|
|
* @return reference to this
|
|
*/
|
|
OctetString& operator^=(const OctetString& other);
|
|
|
|
/**
|
|
* Force to have odd parity
|
|
*/
|
|
void set_odd_parity();
|
|
|
|
/**
|
|
* Create a new OctetString
|
|
* @param str is a hex encoded string
|
|
*/
|
|
explicit OctetString(const std::string& str = "");
|
|
|
|
/**
|
|
* Create a new random OctetString
|
|
* @param rng is a random number generator
|
|
* @param len is the desired length in bytes
|
|
*/
|
|
OctetString(class RandomNumberGenerator& rng, size_t len);
|
|
|
|
/**
|
|
* Create a new OctetString
|
|
* @param in is an array
|
|
* @param len is the length of in in bytes
|
|
*/
|
|
OctetString(const uint8_t in[], size_t len);
|
|
|
|
/**
|
|
* Create a new OctetString
|
|
* @param in a bytestring
|
|
*/
|
|
OctetString(const secure_vector<uint8_t>& in) : m_data(in) {}
|
|
|
|
/**
|
|
* Create a new OctetString
|
|
* @param in a bytestring
|
|
*/
|
|
OctetString(const std::vector<uint8_t>& in) : m_data(in.begin(), in.end()) {}
|
|
|
|
private:
|
|
secure_vector<uint8_t> m_data;
|
|
};
|
|
|
|
/**
|
|
* Compare two strings
|
|
* @param x an octet string
|
|
* @param y an octet string
|
|
* @return if x is equal to y
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) bool operator==(const OctetString& x,
|
|
const OctetString& y);
|
|
|
|
/**
|
|
* Compare two strings
|
|
* @param x an octet string
|
|
* @param y an octet string
|
|
* @return if x is not equal to y
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) bool operator!=(const OctetString& x,
|
|
const OctetString& y);
|
|
|
|
/**
|
|
* Concatenate two strings
|
|
* @param x an octet string
|
|
* @param y an octet string
|
|
* @return x concatenated with y
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) OctetString operator+(const OctetString& x,
|
|
const OctetString& y);
|
|
|
|
/**
|
|
* XOR two strings
|
|
* @param x an octet string
|
|
* @param y an octet string
|
|
* @return x XORed with y
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) OctetString operator^(const OctetString& x,
|
|
const OctetString& y);
|
|
|
|
|
|
/**
|
|
* Alternate name for octet string showing intent to use as a key
|
|
*/
|
|
using SymmetricKey = OctetString;
|
|
|
|
/**
|
|
* Alternate name for octet string showing intent to use as an IV
|
|
*/
|
|
using InitializationVector = OctetString;
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Represents the length requirements on an algorithm key
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Key_Length_Specification final
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor for fixed length keys
|
|
* @param keylen the supported key length
|
|
*/
|
|
explicit Key_Length_Specification(size_t keylen) :
|
|
m_min_keylen(keylen),
|
|
m_max_keylen(keylen),
|
|
m_keylen_mod(1)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Constructor for variable length keys
|
|
* @param min_k the smallest supported key length
|
|
* @param max_k the largest supported key length
|
|
* @param k_mod the number of bytes the key must be a multiple of
|
|
*/
|
|
Key_Length_Specification(size_t min_k,
|
|
size_t max_k,
|
|
size_t k_mod = 1) :
|
|
m_min_keylen(min_k),
|
|
m_max_keylen(max_k ? max_k : min_k),
|
|
m_keylen_mod(k_mod)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @param length is a key length in bytes
|
|
* @return true iff this length is a valid length for this algo
|
|
*/
|
|
bool valid_keylength(size_t length) const
|
|
{
|
|
return ((length >= m_min_keylen) &&
|
|
(length <= m_max_keylen) &&
|
|
(length % m_keylen_mod == 0));
|
|
}
|
|
|
|
/**
|
|
* @return minimum key length in bytes
|
|
*/
|
|
size_t minimum_keylength() const
|
|
{
|
|
return m_min_keylen;
|
|
}
|
|
|
|
/**
|
|
* @return maximum key length in bytes
|
|
*/
|
|
size_t maximum_keylength() const
|
|
{
|
|
return m_max_keylen;
|
|
}
|
|
|
|
/**
|
|
* @return key length multiple in bytes
|
|
*/
|
|
size_t keylength_multiple() const
|
|
{
|
|
return m_keylen_mod;
|
|
}
|
|
|
|
/*
|
|
* Multiplies all length requirements with the given factor
|
|
* @param n the multiplication factor
|
|
* @return a key length specification multiplied by the factor
|
|
*/
|
|
Key_Length_Specification multiple(size_t n) const
|
|
{
|
|
return Key_Length_Specification(n * m_min_keylen,
|
|
n * m_max_keylen,
|
|
n * m_keylen_mod);
|
|
}
|
|
|
|
private:
|
|
size_t m_min_keylen, m_max_keylen, m_keylen_mod;
|
|
};
|
|
|
|
/**
|
|
* This class represents a symmetric algorithm object.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SymmetricAlgorithm
|
|
{
|
|
public:
|
|
virtual ~SymmetricAlgorithm() = default;
|
|
|
|
/**
|
|
* Reset the state.
|
|
*/
|
|
virtual void clear() = 0;
|
|
|
|
/**
|
|
* @return object describing limits on key size
|
|
*/
|
|
virtual Key_Length_Specification key_spec() const = 0;
|
|
|
|
/**
|
|
* @return maximum allowed key length
|
|
*/
|
|
size_t maximum_keylength() const
|
|
{
|
|
return key_spec().maximum_keylength();
|
|
}
|
|
|
|
/**
|
|
* @return minimum allowed key length
|
|
*/
|
|
size_t minimum_keylength() const
|
|
{
|
|
return key_spec().minimum_keylength();
|
|
}
|
|
|
|
/**
|
|
* Check whether a given key length is valid for this algorithm.
|
|
* @param length the key length to be checked.
|
|
* @return true if the key length is valid.
|
|
*/
|
|
bool valid_keylength(size_t length) const
|
|
{
|
|
return key_spec().valid_keylength(length);
|
|
}
|
|
|
|
/**
|
|
* Set the symmetric key of this object.
|
|
* @param key the SymmetricKey to be set.
|
|
*/
|
|
void set_key(const SymmetricKey& key)
|
|
{
|
|
set_key(key.begin(), key.length());
|
|
}
|
|
|
|
template<typename Alloc>
|
|
void set_key(const std::vector<uint8_t, Alloc>& key)
|
|
{
|
|
set_key(key.data(), key.size());
|
|
}
|
|
|
|
/**
|
|
* Set the symmetric key of this object.
|
|
* @param key the to be set as a byte array.
|
|
* @param length in bytes of key param
|
|
*/
|
|
void set_key(const uint8_t key[], size_t length);
|
|
|
|
/**
|
|
* @return the algorithm name
|
|
*/
|
|
virtual std::string name() const = 0;
|
|
|
|
protected:
|
|
void verify_key_set(bool cond) const
|
|
{
|
|
if(cond == false)
|
|
throw_key_not_set_error();
|
|
}
|
|
|
|
private:
|
|
void throw_key_not_set_error() const;
|
|
|
|
/**
|
|
* Run the key schedule
|
|
* @param key the key
|
|
* @param length of key
|
|
*/
|
|
virtual void key_schedule(const uint8_t key[], size_t length) = 0;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Different types of errors that might occur
|
|
*/
|
|
enum class ErrorType {
|
|
/** Some unknown error */
|
|
Unknown = 1,
|
|
/** An error while calling a system interface */
|
|
SystemError,
|
|
/** An operation seems valid, but not supported by the current version */
|
|
NotImplemented,
|
|
/** Memory allocation failure */
|
|
OutOfMemory,
|
|
/** An internal error occurred */
|
|
InternalError,
|
|
/** An I/O error occurred */
|
|
IoError,
|
|
|
|
/** Invalid object state */
|
|
InvalidObjectState = 100,
|
|
/** A key was not set on an object when this is required */
|
|
KeyNotSet,
|
|
/** The application provided an argument which is invalid */
|
|
InvalidArgument,
|
|
/** A key with invalid length was provided */
|
|
InvalidKeyLength,
|
|
/** A nonce with invalid length was provided */
|
|
InvalidNonceLength,
|
|
/** An object type was requested but cannot be found */
|
|
LookupError,
|
|
/** Encoding a message or datum failed */
|
|
EncodingFailure,
|
|
/** Decoding a message or datum failed */
|
|
DecodingFailure,
|
|
/** A TLS error (error_code will be the alert type) */
|
|
TLSError,
|
|
/** An error during an HTTP operation */
|
|
HttpError,
|
|
/** A message with an invalid authentication tag was detected */
|
|
InvalidTag,
|
|
/** An error during Roughtime validation */
|
|
RoughtimeError,
|
|
|
|
/** An error when calling OpenSSL */
|
|
OpenSSLError = 200,
|
|
/** An error when interacting with CommonCrypto API */
|
|
CommonCryptoError,
|
|
/** An error when interacting with a PKCS11 device */
|
|
Pkcs11Error,
|
|
/** An error when interacting with a TPM device */
|
|
TPMError,
|
|
/** An error when interacting with a database */
|
|
DatabaseError,
|
|
|
|
/** An error when interacting with zlib */
|
|
ZlibError = 300,
|
|
/** An error when interacting with bzip2 */
|
|
Bzip2Error,
|
|
/** An error when interacting with lzma */
|
|
LzmaError,
|
|
|
|
};
|
|
|
|
//! \brief Convert an ErrorType to string
|
|
std::string BOTAN_PUBLIC_API(2,11) to_string(ErrorType type);
|
|
|
|
/**
|
|
* Base class for all exceptions thrown by the library
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Exception : public std::exception
|
|
{
|
|
public:
|
|
/**
|
|
* Return a descriptive string which is hopefully comprehensible to
|
|
* a developer. It will likely not be useful for an end user.
|
|
*
|
|
* The string has no particular format, and the content of exception
|
|
* messages may change from release to release. Thus the main use of this
|
|
* function is for logging or debugging.
|
|
*/
|
|
const char* what() const noexcept override { return m_msg.c_str(); }
|
|
|
|
/**
|
|
* Return the "type" of error which occurred.
|
|
*/
|
|
virtual ErrorType error_type() const noexcept { return Botan::ErrorType::Unknown; }
|
|
|
|
/**
|
|
* Return an error code associated with this exception, or otherwise 0.
|
|
*
|
|
* The domain of this error varies depending on the source, for example on
|
|
* POSIX systems it might be errno, while on a Windows system it might be
|
|
* the result of GetLastError or WSAGetLastError. For error_type() is
|
|
* OpenSSLError, it will (if nonzero) be an OpenSSL error code from
|
|
* ERR_get_error.
|
|
*/
|
|
virtual int error_code() const noexcept { return 0; }
|
|
|
|
/**
|
|
* Avoid throwing base Exception, use a subclass
|
|
*/
|
|
explicit Exception(const std::string& msg);
|
|
|
|
/**
|
|
* Avoid throwing base Exception, use a subclass
|
|
*/
|
|
Exception(const char* prefix, const std::string& msg);
|
|
|
|
/**
|
|
* Avoid throwing base Exception, use a subclass
|
|
*/
|
|
Exception(const std::string& msg, const std::exception& e);
|
|
|
|
private:
|
|
std::string m_msg;
|
|
};
|
|
|
|
/**
|
|
* An invalid argument was provided to an API call.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Invalid_Argument : public Exception
|
|
{
|
|
public:
|
|
explicit Invalid_Argument(const std::string& msg);
|
|
|
|
explicit Invalid_Argument(const std::string& msg, const std::string& where);
|
|
|
|
Invalid_Argument(const std::string& msg, const std::exception& e);
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::InvalidArgument; }
|
|
};
|
|
|
|
/**
|
|
* An invalid key length was used
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Invalid_Key_Length final : public Invalid_Argument
|
|
{
|
|
public:
|
|
Invalid_Key_Length(const std::string& name, size_t length);
|
|
ErrorType error_type() const noexcept override { return ErrorType::InvalidKeyLength; }
|
|
};
|
|
|
|
/**
|
|
* An invalid nonce length was used
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Invalid_IV_Length final : public Invalid_Argument
|
|
{
|
|
public:
|
|
Invalid_IV_Length(const std::string& mode, size_t bad_len);
|
|
ErrorType error_type() const noexcept override { return ErrorType::InvalidNonceLength; }
|
|
};
|
|
|
|
/**
|
|
* Invalid_Algorithm_Name Exception
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Invalid_Algorithm_Name final : public Invalid_Argument
|
|
{
|
|
public:
|
|
explicit Invalid_Algorithm_Name(const std::string& name);
|
|
};
|
|
|
|
/**
|
|
* Encoding_Error Exception
|
|
*
|
|
* This exception derives from Invalid_Argument for historical reasons, and it
|
|
* does not make any real sense for it to do so. In a future major release this
|
|
* exception type will derive directly from Exception instead.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Encoding_Error final : public Invalid_Argument
|
|
{
|
|
public:
|
|
explicit Encoding_Error(const std::string& name);
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::EncodingFailure; }
|
|
};
|
|
|
|
/**
|
|
* A decoding error occurred.
|
|
*
|
|
* This exception derives from Invalid_Argument for historical reasons, and it
|
|
* does not make any real sense for it to do so. In a future major release this
|
|
* exception type will derive directly from Exception instead.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Decoding_Error : public Invalid_Argument
|
|
{
|
|
public:
|
|
explicit Decoding_Error(const std::string& name);
|
|
|
|
Decoding_Error(const std::string& name, const char* exception_message);
|
|
|
|
Decoding_Error(const std::string& msg, const std::exception& e);
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::DecodingFailure; }
|
|
};
|
|
|
|
/**
|
|
* Invalid state was encountered. A request was made on an object while the
|
|
* object was in a state where the operation cannot be performed.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Invalid_State : public Exception
|
|
{
|
|
public:
|
|
explicit Invalid_State(const std::string& err) : Exception(err) {}
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::InvalidObjectState; }
|
|
};
|
|
|
|
/**
|
|
* A PRNG was called on to produce output while still unseeded
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PRNG_Unseeded final : public Invalid_State
|
|
{
|
|
public:
|
|
explicit PRNG_Unseeded(const std::string& algo);
|
|
};
|
|
|
|
/**
|
|
* The key was not set on an object. This occurs with symmetric objects where
|
|
* an operation which requires the key is called prior to set_key being called.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,4) Key_Not_Set : public Invalid_State
|
|
{
|
|
public:
|
|
explicit Key_Not_Set(const std::string& algo);
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::KeyNotSet; }
|
|
};
|
|
|
|
/**
|
|
* A request was made for some kind of object which could not be located
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Lookup_Error : public Exception
|
|
{
|
|
public:
|
|
explicit Lookup_Error(const std::string& err) : Exception(err) {}
|
|
|
|
Lookup_Error(const std::string& type,
|
|
const std::string& algo,
|
|
const std::string& provider);
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::LookupError; }
|
|
};
|
|
|
|
/**
|
|
* Algorithm_Not_Found Exception
|
|
*
|
|
* @warning This exception type will be removed in the future. Instead
|
|
* just catch Lookup_Error.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Algorithm_Not_Found final : public Lookup_Error
|
|
{
|
|
public:
|
|
explicit Algorithm_Not_Found(const std::string& name);
|
|
};
|
|
|
|
/**
|
|
* Provider_Not_Found is thrown when a specific provider was requested
|
|
* but that provider is not available.
|
|
*
|
|
* @warning This exception type will be removed in the future. Instead
|
|
* just catch Lookup_Error.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Provider_Not_Found final : public Lookup_Error
|
|
{
|
|
public:
|
|
Provider_Not_Found(const std::string& algo, const std::string& provider);
|
|
};
|
|
|
|
/**
|
|
* An AEAD or MAC check detected a message modification
|
|
*
|
|
* In versions before 2.10, Invalid_Authentication_Tag was named
|
|
* Integrity_Failure, it was renamed to make its usage more clear.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Invalid_Authentication_Tag final : public Exception
|
|
{
|
|
public:
|
|
explicit Invalid_Authentication_Tag(const std::string& msg);
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::InvalidTag; }
|
|
};
|
|
|
|
/**
|
|
* For compatability with older versions
|
|
*/
|
|
typedef Invalid_Authentication_Tag Integrity_Failure;
|
|
|
|
/**
|
|
* An error occurred while operating on an IO stream
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Stream_IO_Error final : public Exception
|
|
{
|
|
public:
|
|
explicit Stream_IO_Error(const std::string& err);
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::IoError; }
|
|
};
|
|
|
|
/**
|
|
* System_Error
|
|
*
|
|
* This exception is thrown in the event of an error related to interacting
|
|
* with the operating system.
|
|
*
|
|
* This exception type also (optionally) captures an integer error code eg
|
|
* POSIX errno or Windows GetLastError.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,9) System_Error : public Exception
|
|
{
|
|
public:
|
|
System_Error(const std::string& msg) : Exception(msg), m_error_code(0) {}
|
|
|
|
System_Error(const std::string& msg, int err_code);
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::SystemError; }
|
|
|
|
int error_code() const noexcept override { return m_error_code; }
|
|
|
|
private:
|
|
int m_error_code;
|
|
};
|
|
|
|
/**
|
|
* An internal error occurred. If observed, please file a bug.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Internal_Error : public Exception
|
|
{
|
|
public:
|
|
explicit Internal_Error(const std::string& err);
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::InternalError; }
|
|
};
|
|
|
|
/**
|
|
* Not Implemented Exception
|
|
*
|
|
* This is thrown in the situation where a requested operation is
|
|
* logically valid but is not implemented by this version of the library.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Not_Implemented final : public Exception
|
|
{
|
|
public:
|
|
explicit Not_Implemented(const std::string& err);
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::NotImplemented; }
|
|
};
|
|
|
|
/*
|
|
The following exception types are still in use for compatability reasons,
|
|
but are deprecated and will be removed in a future major release.
|
|
Instead catch the base class.
|
|
*/
|
|
|
|
/**
|
|
* An invalid OID string was used.
|
|
*
|
|
* This exception will be removed in a future major release.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Invalid_OID final : public Decoding_Error
|
|
{
|
|
public:
|
|
explicit Invalid_OID(const std::string& oid);
|
|
};
|
|
|
|
/*
|
|
The following exception types are deprecated, no longer used,
|
|
and will be removed in a future major release
|
|
*/
|
|
|
|
/**
|
|
* Self Test Failure Exception
|
|
*
|
|
* This exception is no longer used. It will be removed in a future major release.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Self_Test_Failure final : public Internal_Error
|
|
{
|
|
public:
|
|
BOTAN_DEPRECATED("no longer used") explicit Self_Test_Failure(const std::string& err);
|
|
};
|
|
|
|
/**
|
|
* No_Provider_Found Exception
|
|
*
|
|
* This exception is no longer used. It will be removed in a future major release.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) No_Provider_Found final : public Exception
|
|
{
|
|
public:
|
|
BOTAN_DEPRECATED("no longer used") explicit No_Provider_Found(const std::string& name);
|
|
};
|
|
|
|
/**
|
|
* Policy_Violation Exception
|
|
*
|
|
* This exception is no longer used. It will be removed in a future major release.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Policy_Violation final : public Invalid_State
|
|
{
|
|
public:
|
|
BOTAN_DEPRECATED("no longer used") explicit Policy_Violation(const std::string& err);
|
|
};
|
|
|
|
/**
|
|
* Unsupported_Argument Exception
|
|
*
|
|
* An argument that is invalid because it is not supported by Botan.
|
|
* It might or might not be valid in another context like a standard.
|
|
*
|
|
* This exception is no longer used, instead Not_Implemented is thrown.
|
|
* It will be removed in a future major release.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Unsupported_Argument final : public Invalid_Argument
|
|
{
|
|
public:
|
|
BOTAN_DEPRECATED("no longer used") explicit Unsupported_Argument(const std::string& msg) : Invalid_Argument(msg) {}
|
|
};
|
|
|
|
template<typename E, typename... Args>
|
|
inline void do_throw_error(const char* file, int line, const char* func, Args... args)
|
|
{
|
|
throw E(file, line, func, args...);
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* The two possible directions for cipher filters, determining whether they
|
|
* actually perform encryption or decryption.
|
|
*/
|
|
enum Cipher_Dir : int { ENCRYPTION, DECRYPTION };
|
|
|
|
/**
|
|
* Interface for cipher modes
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Cipher_Mode : public SymmetricAlgorithm
|
|
{
|
|
public:
|
|
/**
|
|
* @return list of available providers for this algorithm, empty if not available
|
|
* @param algo_spec algorithm name
|
|
*/
|
|
static std::vector<std::string> providers(const std::string& algo_spec);
|
|
|
|
/**
|
|
* Create an AEAD mode
|
|
* @param algo the algorithm to create
|
|
* @param direction specify if this should be an encryption or decryption AEAD
|
|
* @param provider optional specification for provider to use
|
|
* @return an AEAD mode or a null pointer if not available
|
|
*/
|
|
static std::unique_ptr<Cipher_Mode> create(const std::string& algo,
|
|
Cipher_Dir direction,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* Create an AEAD mode, or throw
|
|
* @param algo the algorithm to create
|
|
* @param direction specify if this should be an encryption or decryption AEAD
|
|
* @param provider optional specification for provider to use
|
|
* @return an AEAD mode, or throw an exception
|
|
*/
|
|
static std::unique_ptr<Cipher_Mode> create_or_throw(const std::string& algo,
|
|
Cipher_Dir direction,
|
|
const std::string& provider = "");
|
|
|
|
/*
|
|
* Prepare for processing a message under the specified nonce
|
|
*/
|
|
virtual void start_msg(const uint8_t nonce[], size_t nonce_len) = 0;
|
|
|
|
/**
|
|
* Begin processing a message.
|
|
* @param nonce the per message nonce
|
|
*/
|
|
template<typename Alloc>
|
|
void start(const std::vector<uint8_t, Alloc>& nonce)
|
|
{
|
|
start_msg(nonce.data(), nonce.size());
|
|
}
|
|
|
|
/**
|
|
* Begin processing a message.
|
|
* @param nonce the per message nonce
|
|
* @param nonce_len length of nonce
|
|
*/
|
|
void start(const uint8_t nonce[], size_t nonce_len)
|
|
{
|
|
start_msg(nonce, nonce_len);
|
|
}
|
|
|
|
/**
|
|
* Begin processing a message.
|
|
*/
|
|
void start()
|
|
{
|
|
return start_msg(nullptr, 0);
|
|
}
|
|
|
|
/**
|
|
* Process message blocks
|
|
*
|
|
* Input must be a multiple of update_granularity
|
|
*
|
|
* Processes msg in place and returns bytes written. Normally
|
|
* this will be either msg_len (indicating the entire message was
|
|
* processed) or for certain AEAD modes zero (indicating that the
|
|
* mode requires the entire message be processed in one pass).
|
|
*
|
|
* @param msg the message to be processed
|
|
* @param msg_len length of the message in bytes
|
|
*/
|
|
virtual size_t process(uint8_t msg[], size_t msg_len) = 0;
|
|
|
|
/**
|
|
* Process some data. Input must be in size update_granularity() uint8_t blocks.
|
|
* @param buffer in/out parameter which will possibly be resized
|
|
* @param offset an offset into blocks to begin processing
|
|
*/
|
|
void update(secure_vector<uint8_t>& buffer, size_t offset = 0)
|
|
{
|
|
BOTAN_ASSERT(buffer.size() >= offset, "Offset ok");
|
|
uint8_t* buf = buffer.data() + offset;
|
|
const size_t buf_size = buffer.size() - offset;
|
|
|
|
const size_t written = process(buf, buf_size);
|
|
buffer.resize(offset + written);
|
|
}
|
|
|
|
/**
|
|
* Complete processing of a message.
|
|
*
|
|
* @param final_block in/out parameter which must be at least
|
|
* minimum_final_size() bytes, and will be set to any final output
|
|
* @param offset an offset into final_block to begin processing
|
|
*/
|
|
virtual void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) = 0;
|
|
|
|
/**
|
|
* Returns the size of the output if this transform is used to process a
|
|
* message with input_length bytes. In most cases the answer is precise.
|
|
* If it is not possible to precise (namely for CBC decryption) instead a
|
|
* lower bound is returned.
|
|
*/
|
|
virtual size_t output_length(size_t input_length) const = 0;
|
|
|
|
/**
|
|
* @return size of required blocks to update
|
|
*/
|
|
virtual size_t update_granularity() const = 0;
|
|
|
|
/**
|
|
* @return required minimium size to finalize() - may be any
|
|
* length larger than this.
|
|
*/
|
|
virtual size_t minimum_final_size() const = 0;
|
|
|
|
/**
|
|
* @return the default size for a nonce
|
|
*/
|
|
virtual size_t default_nonce_length() const = 0;
|
|
|
|
/**
|
|
* @return true iff nonce_len is a valid length for the nonce
|
|
*/
|
|
virtual bool valid_nonce_length(size_t nonce_len) const = 0;
|
|
|
|
/**
|
|
* Resets just the message specific state and allows encrypting again under the existing key
|
|
*/
|
|
virtual void reset() = 0;
|
|
|
|
/**
|
|
* @return true iff this mode provides authentication as well as
|
|
* confidentiality.
|
|
*/
|
|
virtual bool authenticated() const { return false; }
|
|
|
|
/**
|
|
* @return the size of the authentication tag used (in bytes)
|
|
*/
|
|
virtual size_t tag_size() const { return 0; }
|
|
|
|
/**
|
|
* @return provider information about this implementation. Default is "base",
|
|
* might also return "sse2", "avx2", "openssl", or some other arbitrary string.
|
|
*/
|
|
virtual std::string provider() const { return "base"; }
|
|
};
|
|
|
|
/**
|
|
* Get a cipher mode by name (eg "AES-128/CBC" or "Serpent/XTS")
|
|
* @param algo_spec cipher name
|
|
* @param direction ENCRYPTION or DECRYPTION
|
|
* @param provider provider implementation to choose
|
|
*/
|
|
inline Cipher_Mode* get_cipher_mode(const std::string& algo_spec,
|
|
Cipher_Dir direction,
|
|
const std::string& provider = "")
|
|
{
|
|
return Cipher_Mode::create(algo_spec, direction, provider).release();
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Interface for AEAD (Authenticated Encryption with Associated Data)
|
|
* modes. These modes provide both encryption and message
|
|
* authentication, and can authenticate additional per-message data
|
|
* which is not included in the ciphertext (for instance a sequence
|
|
* number).
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) AEAD_Mode : public Cipher_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* Create an AEAD mode
|
|
* @param algo the algorithm to create
|
|
* @param direction specify if this should be an encryption or decryption AEAD
|
|
* @param provider optional specification for provider to use
|
|
* @return an AEAD mode or a null pointer if not available
|
|
*/
|
|
static std::unique_ptr<AEAD_Mode> create(const std::string& algo,
|
|
Cipher_Dir direction,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* Create an AEAD mode, or throw
|
|
* @param algo the algorithm to create
|
|
* @param direction specify if this should be an encryption or decryption AEAD
|
|
* @param provider optional specification for provider to use
|
|
* @return an AEAD mode, or throw an exception
|
|
*/
|
|
static std::unique_ptr<AEAD_Mode> create_or_throw(const std::string& algo,
|
|
Cipher_Dir direction,
|
|
const std::string& provider = "");
|
|
|
|
bool authenticated() const override { return true; }
|
|
|
|
/**
|
|
* Set associated data that is not included in the ciphertext but
|
|
* that should be authenticated. Must be called after set_key and
|
|
* before start.
|
|
*
|
|
* Unless reset by another call, the associated data is kept
|
|
* between messages. Thus, if the AD does not change, calling
|
|
* once (after set_key) is the optimum.
|
|
*
|
|
* @param ad the associated data
|
|
* @param ad_len length of add in bytes
|
|
*/
|
|
virtual void set_associated_data(const uint8_t ad[], size_t ad_len) = 0;
|
|
|
|
/**
|
|
* Set associated data that is not included in the ciphertext but
|
|
* that should be authenticated. Must be called after set_key and
|
|
* before start.
|
|
*
|
|
* Unless reset by another call, the associated data is kept
|
|
* between messages. Thus, if the AD does not change, calling
|
|
* once (after set_key) is the optimum.
|
|
*
|
|
* Some AEADs (namely SIV) support multiple AD inputs. For
|
|
* all other modes only nominal AD input 0 is supported; all
|
|
* other values of i will cause an exception.
|
|
*
|
|
* @param ad the associated data
|
|
* @param ad_len length of add in bytes
|
|
*/
|
|
virtual void set_associated_data_n(size_t i, const uint8_t ad[], size_t ad_len);
|
|
|
|
/**
|
|
* Returns the maximum supported number of associated data inputs which
|
|
* can be provided to set_associated_data_n
|
|
*
|
|
* If returns 0, then no associated data is supported.
|
|
*/
|
|
virtual size_t maximum_associated_data_inputs() const { return 1; }
|
|
|
|
/**
|
|
* Most AEADs require the key to be set prior to setting the AD
|
|
* A few allow the AD to be set even before the cipher is keyed.
|
|
* Such ciphers would return false from this function.
|
|
*/
|
|
virtual bool associated_data_requires_key() const { return true; }
|
|
|
|
/**
|
|
* Set associated data that is not included in the ciphertext but
|
|
* that should be authenticated. Must be called after set_key and
|
|
* before start.
|
|
*
|
|
* See @ref set_associated_data().
|
|
*
|
|
* @param ad the associated data
|
|
*/
|
|
template<typename Alloc>
|
|
void set_associated_data_vec(const std::vector<uint8_t, Alloc>& ad)
|
|
{
|
|
set_associated_data(ad.data(), ad.size());
|
|
}
|
|
|
|
/**
|
|
* Set associated data that is not included in the ciphertext but
|
|
* that should be authenticated. Must be called after set_key and
|
|
* before start.
|
|
*
|
|
* See @ref set_associated_data().
|
|
*
|
|
* @param ad the associated data
|
|
*/
|
|
template<typename Alloc>
|
|
void set_ad(const std::vector<uint8_t, Alloc>& ad)
|
|
{
|
|
set_associated_data(ad.data(), ad.size());
|
|
}
|
|
|
|
/**
|
|
* @return default AEAD nonce size (a commonly supported value among AEAD
|
|
* modes, and large enough that random collisions are unlikely)
|
|
*/
|
|
size_t default_nonce_length() const override { return 12; }
|
|
|
|
virtual ~AEAD_Mode() = default;
|
|
};
|
|
|
|
/**
|
|
* Get an AEAD mode by name (eg "AES-128/GCM" or "Serpent/EAX")
|
|
* @param name AEAD name
|
|
* @param direction ENCRYPTION or DECRYPTION
|
|
*/
|
|
inline AEAD_Mode* get_aead(const std::string& name, Cipher_Dir direction)
|
|
{
|
|
return AEAD_Mode::create(name, direction, "").release();
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents a block cipher object.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) BlockCipher : public SymmetricAlgorithm
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Create an instance based on a name
|
|
* If provider is empty then best available is chosen.
|
|
* @param algo_spec algorithm name
|
|
* @param provider provider implementation to choose
|
|
* @return a null pointer if the algo/provider combination cannot be found
|
|
*/
|
|
static std::unique_ptr<BlockCipher>
|
|
create(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* Create an instance based on a name, or throw if the
|
|
* algo/provider combination cannot be found. If provider is
|
|
* empty then best available is chosen.
|
|
*/
|
|
static std::unique_ptr<BlockCipher>
|
|
create_or_throw(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* @return list of available providers for this algorithm, empty if not available
|
|
* @param algo_spec algorithm name
|
|
*/
|
|
static std::vector<std::string> providers(const std::string& algo_spec);
|
|
|
|
/**
|
|
* @return block size of this algorithm
|
|
*/
|
|
virtual size_t block_size() const = 0;
|
|
|
|
/**
|
|
* @return native parallelism of this cipher in blocks
|
|
*/
|
|
virtual size_t parallelism() const { return 1; }
|
|
|
|
/**
|
|
* @return prefererred parallelism of this cipher in bytes
|
|
*/
|
|
size_t parallel_bytes() const
|
|
{
|
|
return parallelism() * block_size() * BOTAN_BLOCK_CIPHER_PAR_MULT;
|
|
}
|
|
|
|
/**
|
|
* @return provider information about this implementation. Default is "base",
|
|
* might also return "sse2", "avx2", "openssl", or some other arbitrary string.
|
|
*/
|
|
virtual std::string provider() const { return "base"; }
|
|
|
|
/**
|
|
* Encrypt a block.
|
|
* @param in The plaintext block to be encrypted as a byte array.
|
|
* Must be of length block_size().
|
|
* @param out The byte array designated to hold the encrypted block.
|
|
* Must be of length block_size().
|
|
*/
|
|
void encrypt(const uint8_t in[], uint8_t out[]) const
|
|
{ encrypt_n(in, out, 1); }
|
|
|
|
/**
|
|
* Decrypt a block.
|
|
* @param in The ciphertext block to be decypted as a byte array.
|
|
* Must be of length block_size().
|
|
* @param out The byte array designated to hold the decrypted block.
|
|
* Must be of length block_size().
|
|
*/
|
|
void decrypt(const uint8_t in[], uint8_t out[]) const
|
|
{ decrypt_n(in, out, 1); }
|
|
|
|
/**
|
|
* Encrypt a block.
|
|
* @param block the plaintext block to be encrypted
|
|
* Must be of length block_size(). Will hold the result when the function
|
|
* has finished.
|
|
*/
|
|
void encrypt(uint8_t block[]) const { encrypt_n(block, block, 1); }
|
|
|
|
/**
|
|
* Decrypt a block.
|
|
* @param block the ciphertext block to be decrypted
|
|
* Must be of length block_size(). Will hold the result when the function
|
|
* has finished.
|
|
*/
|
|
void decrypt(uint8_t block[]) const { decrypt_n(block, block, 1); }
|
|
|
|
/**
|
|
* Encrypt one or more blocks
|
|
* @param block the input/output buffer (multiple of block_size())
|
|
*/
|
|
template<typename Alloc>
|
|
void encrypt(std::vector<uint8_t, Alloc>& block) const
|
|
{
|
|
return encrypt_n(block.data(), block.data(), block.size() / block_size());
|
|
}
|
|
|
|
/**
|
|
* Decrypt one or more blocks
|
|
* @param block the input/output buffer (multiple of block_size())
|
|
*/
|
|
template<typename Alloc>
|
|
void decrypt(std::vector<uint8_t, Alloc>& block) const
|
|
{
|
|
return decrypt_n(block.data(), block.data(), block.size() / block_size());
|
|
}
|
|
|
|
/**
|
|
* Encrypt one or more blocks
|
|
* @param in the input buffer (multiple of block_size())
|
|
* @param out the output buffer (same size as in)
|
|
*/
|
|
template<typename Alloc, typename Alloc2>
|
|
void encrypt(const std::vector<uint8_t, Alloc>& in,
|
|
std::vector<uint8_t, Alloc2>& out) const
|
|
{
|
|
return encrypt_n(in.data(), out.data(), in.size() / block_size());
|
|
}
|
|
|
|
/**
|
|
* Decrypt one or more blocks
|
|
* @param in the input buffer (multiple of block_size())
|
|
* @param out the output buffer (same size as in)
|
|
*/
|
|
template<typename Alloc, typename Alloc2>
|
|
void decrypt(const std::vector<uint8_t, Alloc>& in,
|
|
std::vector<uint8_t, Alloc2>& out) const
|
|
{
|
|
return decrypt_n(in.data(), out.data(), in.size() / block_size());
|
|
}
|
|
|
|
/**
|
|
* Encrypt one or more blocks
|
|
* @param in the input buffer (multiple of block_size())
|
|
* @param out the output buffer (same size as in)
|
|
* @param blocks the number of blocks to process
|
|
*/
|
|
virtual void encrypt_n(const uint8_t in[], uint8_t out[],
|
|
size_t blocks) const = 0;
|
|
|
|
/**
|
|
* Decrypt one or more blocks
|
|
* @param in the input buffer (multiple of block_size())
|
|
* @param out the output buffer (same size as in)
|
|
* @param blocks the number of blocks to process
|
|
*/
|
|
virtual void decrypt_n(const uint8_t in[], uint8_t out[],
|
|
size_t blocks) const = 0;
|
|
|
|
virtual void encrypt_n_xex(uint8_t data[],
|
|
const uint8_t mask[],
|
|
size_t blocks) const
|
|
{
|
|
const size_t BS = block_size();
|
|
xor_buf(data, mask, blocks * BS);
|
|
encrypt_n(data, data, blocks);
|
|
xor_buf(data, mask, blocks * BS);
|
|
}
|
|
|
|
virtual void decrypt_n_xex(uint8_t data[],
|
|
const uint8_t mask[],
|
|
size_t blocks) const
|
|
{
|
|
const size_t BS = block_size();
|
|
xor_buf(data, mask, blocks * BS);
|
|
decrypt_n(data, data, blocks);
|
|
xor_buf(data, mask, blocks * BS);
|
|
}
|
|
|
|
/**
|
|
* @return new object representing the same algorithm as *this
|
|
*/
|
|
virtual BlockCipher* clone() const = 0;
|
|
|
|
virtual ~BlockCipher() = default;
|
|
};
|
|
|
|
/**
|
|
* Tweakable block ciphers allow setting a tweak which is a non-keyed
|
|
* value which affects the encryption/decryption operation.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,8) Tweakable_Block_Cipher : public BlockCipher
|
|
{
|
|
public:
|
|
/**
|
|
* Set the tweak value. This must be called after setting a key. The value
|
|
* persists until either set_tweak, set_key, or clear is called.
|
|
* Different algorithms support different tweak length(s). If called with
|
|
* an unsupported length, Invalid_Argument will be thrown.
|
|
*/
|
|
virtual void set_tweak(const uint8_t tweak[], size_t len) = 0;
|
|
};
|
|
|
|
/**
|
|
* Represents a block cipher with a single fixed block size
|
|
*/
|
|
template<size_t BS, size_t KMIN, size_t KMAX = 0, size_t KMOD = 1, typename BaseClass = BlockCipher>
|
|
class Block_Cipher_Fixed_Params : public BaseClass
|
|
{
|
|
public:
|
|
enum { BLOCK_SIZE = BS };
|
|
size_t block_size() const final override { return BS; }
|
|
|
|
// override to take advantage of compile time constant block size
|
|
void encrypt_n_xex(uint8_t data[],
|
|
const uint8_t mask[],
|
|
size_t blocks) const final override
|
|
{
|
|
xor_buf(data, mask, blocks * BS);
|
|
this->encrypt_n(data, data, blocks);
|
|
xor_buf(data, mask, blocks * BS);
|
|
}
|
|
|
|
void decrypt_n_xex(uint8_t data[],
|
|
const uint8_t mask[],
|
|
size_t blocks) const final override
|
|
{
|
|
xor_buf(data, mask, blocks * BS);
|
|
this->decrypt_n(data, data, blocks);
|
|
xor_buf(data, mask, blocks * BS);
|
|
}
|
|
|
|
Key_Length_Specification key_spec() const final override
|
|
{
|
|
return Key_Length_Specification(KMIN, KMAX, KMOD);
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(aes.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* AES-128
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) AES_128 final : public Block_Cipher_Fixed_Params<16, 16>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
|
|
std::string provider() const override;
|
|
std::string name() const override { return "AES-128"; }
|
|
BlockCipher* clone() const override { return new AES_128; }
|
|
size_t parallelism() const override;
|
|
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
#if defined(BOTAN_HAS_AES_VPERM)
|
|
void vperm_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
void vperm_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
void vperm_key_schedule(const uint8_t key[], size_t length);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_AES_NI)
|
|
void aesni_key_schedule(const uint8_t key[], size_t length);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_AES_POWER8) || defined(BOTAN_HAS_AES_ARMV8) || defined(BOTAN_HAS_AES_NI)
|
|
void hw_aes_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
void hw_aes_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
#endif
|
|
|
|
secure_vector<uint32_t> m_EK, m_DK;
|
|
};
|
|
|
|
/**
|
|
* AES-192
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) AES_192 final : public Block_Cipher_Fixed_Params<16, 24>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
|
|
std::string provider() const override;
|
|
std::string name() const override { return "AES-192"; }
|
|
BlockCipher* clone() const override { return new AES_192; }
|
|
size_t parallelism() const override;
|
|
|
|
private:
|
|
#if defined(BOTAN_HAS_AES_VPERM)
|
|
void vperm_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
void vperm_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
void vperm_key_schedule(const uint8_t key[], size_t length);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_AES_NI)
|
|
void aesni_key_schedule(const uint8_t key[], size_t length);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_AES_POWER8) || defined(BOTAN_HAS_AES_ARMV8) || defined(BOTAN_HAS_AES_NI)
|
|
void hw_aes_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
void hw_aes_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
#endif
|
|
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
secure_vector<uint32_t> m_EK, m_DK;
|
|
};
|
|
|
|
/**
|
|
* AES-256
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) AES_256 final : public Block_Cipher_Fixed_Params<16, 32>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
|
|
std::string provider() const override;
|
|
|
|
std::string name() const override { return "AES-256"; }
|
|
BlockCipher* clone() const override { return new AES_256; }
|
|
size_t parallelism() const override;
|
|
|
|
private:
|
|
#if defined(BOTAN_HAS_AES_VPERM)
|
|
void vperm_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
void vperm_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
void vperm_key_schedule(const uint8_t key[], size_t length);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_AES_NI)
|
|
void aesni_key_schedule(const uint8_t key[], size_t length);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_AES_POWER8) || defined(BOTAN_HAS_AES_ARMV8) || defined(BOTAN_HAS_AES_NI)
|
|
void hw_aes_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
void hw_aes_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
#endif
|
|
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
secure_vector<uint32_t> m_EK, m_DK;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Base class for password based key derivation functions.
|
|
*
|
|
* Converts a password into a key using a salt and iterated hashing to
|
|
* make brute force attacks harder.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,8) PasswordHash
|
|
{
|
|
public:
|
|
virtual ~PasswordHash() = default;
|
|
|
|
virtual std::string to_string() const = 0;
|
|
|
|
/**
|
|
* Most password hashes have some notion of iterations.
|
|
*/
|
|
virtual size_t iterations() const = 0;
|
|
|
|
/**
|
|
* Some password hashing algorithms have a parameter which controls how
|
|
* much memory is used. If not supported by some algorithm, returns 0.
|
|
*/
|
|
virtual size_t memory_param() const { return 0; }
|
|
|
|
/**
|
|
* Some password hashing algorithms have a parallelism parameter.
|
|
* If the algorithm does not support this notion, then the
|
|
* function returns zero. This allows distinguishing between a
|
|
* password hash which just does not support parallel operation,
|
|
* vs one that does support parallel operation but which has been
|
|
* configured to use a single lane.
|
|
*/
|
|
virtual size_t parallelism() const { return 0; }
|
|
|
|
/**
|
|
* Returns an estimate of the total memory usage required to perform this
|
|
* key derivation.
|
|
*
|
|
* If this algorithm uses a small and constant amount of memory, with no
|
|
* effort made towards being memory hard, this function returns 0.
|
|
*/
|
|
virtual size_t total_memory_usage() const { return 0; }
|
|
|
|
/**
|
|
* Derive a key from a password
|
|
*
|
|
* @param out buffer to store the derived key, must be of out_len bytes
|
|
* @param out_len the desired length of the key to produce
|
|
* @param password the password to derive the key from
|
|
* @param password_len the length of password in bytes
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
*
|
|
* This function is const, but is not thread safe. Different threads should
|
|
* either use unique objects, or serialize all access.
|
|
*/
|
|
virtual void derive_key(uint8_t out[], size_t out_len,
|
|
const char* password, size_t password_len,
|
|
const uint8_t salt[], size_t salt_len) const = 0;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,8) PasswordHashFamily
|
|
{
|
|
public:
|
|
/**
|
|
* Create an instance based on a name
|
|
* If provider is empty then best available is chosen.
|
|
* @param algo_spec algorithm name
|
|
* @param provider provider implementation to choose
|
|
* @return a null pointer if the algo/provider combination cannot be found
|
|
*/
|
|
static std::unique_ptr<PasswordHashFamily> create(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* Create an instance based on a name, or throw if the
|
|
* algo/provider combination cannot be found. If provider is
|
|
* empty then best available is chosen.
|
|
*/
|
|
static std::unique_ptr<PasswordHashFamily>
|
|
create_or_throw(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* @return list of available providers for this algorithm, empty if not available
|
|
*/
|
|
static std::vector<std::string> providers(const std::string& algo_spec);
|
|
|
|
virtual ~PasswordHashFamily() = default;
|
|
|
|
/**
|
|
* @return name of this PasswordHash
|
|
*/
|
|
virtual std::string name() const = 0;
|
|
|
|
/**
|
|
* Return a new parameter set tuned for this machine
|
|
* @param output_length how long the output length will be
|
|
* @param msec the desired execution time in milliseconds
|
|
*
|
|
* @param max_memory_usage_mb some password hash functions can use a tunable
|
|
* amount of memory, in this case max_memory_usage limits the amount of RAM
|
|
* the returned parameters will require, in mebibytes (2**20 bytes). It may
|
|
* require some small amount above the request. Set to zero to place no
|
|
* limit at all.
|
|
*/
|
|
virtual std::unique_ptr<PasswordHash> tune(size_t output_length,
|
|
std::chrono::milliseconds msec,
|
|
size_t max_memory_usage_mb = 0) const = 0;
|
|
|
|
/**
|
|
* Return some default parameter set for this PBKDF that should be good
|
|
* enough for most users. The value returned may change over time as
|
|
* processing power and attacks improve.
|
|
*/
|
|
virtual std::unique_ptr<PasswordHash> default_params() const = 0;
|
|
|
|
/**
|
|
* Return a parameter chosen based on a rough approximation with the
|
|
* specified iteration count. The exact value this returns for a particular
|
|
* algorithm may change from over time. Think of it as an alternative to
|
|
* tune, where time is expressed in terms of PBKDF2 iterations rather than
|
|
* milliseconds.
|
|
*/
|
|
virtual std::unique_ptr<PasswordHash> from_iterations(size_t iterations) const = 0;
|
|
|
|
/**
|
|
* Create a password hash using some scheme specific format.
|
|
* Eg PBKDF2 and PGP-S2K set iterations in i1
|
|
* Scrypt uses N,r,p in i{1-3}
|
|
* Bcrypt-PBKDF just has iterations
|
|
* Argon2{i,d,id} would use iterations, memory, parallelism for i{1-3},
|
|
* and Argon2 type is part of the family.
|
|
*
|
|
* Values not needed should be set to 0
|
|
*/
|
|
virtual std::unique_ptr<PasswordHash> from_params(
|
|
size_t i1,
|
|
size_t i2 = 0,
|
|
size_t i3 = 0) const = 0;
|
|
};
|
|
|
|
}
|
|
|
|
//BOTAN_FUTURE_INTERNAL_HEADER(argon2.h)
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Argon2 key derivation function
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,11) Argon2 final : public PasswordHash
|
|
{
|
|
public:
|
|
Argon2(uint8_t family, size_t M, size_t t, size_t p);
|
|
|
|
Argon2(const Argon2& other) = default;
|
|
Argon2& operator=(const Argon2&) = default;
|
|
|
|
/**
|
|
* Derive a new key under the current Argon2 parameter set
|
|
*/
|
|
void derive_key(uint8_t out[], size_t out_len,
|
|
const char* password, size_t password_len,
|
|
const uint8_t salt[], size_t salt_len) const override;
|
|
|
|
std::string to_string() const override;
|
|
|
|
size_t M() const { return m_M; }
|
|
size_t t() const { return m_t; }
|
|
size_t p() const { return m_p; }
|
|
|
|
size_t iterations() const override { return t(); }
|
|
|
|
size_t parallelism() const override { return p(); }
|
|
|
|
size_t memory_param() const override { return M(); }
|
|
|
|
size_t total_memory_usage() const override { return M() * 1024; }
|
|
|
|
private:
|
|
uint8_t m_family;
|
|
size_t m_M, m_t, m_p;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,11) Argon2_Family final : public PasswordHashFamily
|
|
{
|
|
public:
|
|
Argon2_Family(uint8_t family);
|
|
|
|
std::string name() const override;
|
|
|
|
std::unique_ptr<PasswordHash> tune(size_t output_length,
|
|
std::chrono::milliseconds msec,
|
|
size_t max_memory) const override;
|
|
|
|
std::unique_ptr<PasswordHash> default_params() const override;
|
|
|
|
std::unique_ptr<PasswordHash> from_iterations(size_t iter) const override;
|
|
|
|
std::unique_ptr<PasswordHash> from_params(
|
|
size_t M, size_t t, size_t p) const override;
|
|
private:
|
|
const uint8_t m_family;
|
|
};
|
|
|
|
/**
|
|
* Argon2 key derivation function
|
|
*
|
|
* @param output the output will be placed here
|
|
* @param output_len length of output
|
|
* @param password the user password
|
|
* @param password_len the length of password
|
|
* @param salt the salt
|
|
* @param salt_len length of salt
|
|
* @param key an optional secret key
|
|
* @param key_len the length of key
|
|
* @param ad an optional additional input
|
|
* @param ad_len the length of ad
|
|
* @param y the Argon2 variant (0 = Argon2d, 1 = Argon2i, 2 = Argon2id)
|
|
* @param p the parallelization parameter
|
|
* @param M the amount of memory to use in Kb
|
|
* @param t the number of iterations to use
|
|
*/
|
|
void BOTAN_PUBLIC_API(2,11) argon2(uint8_t output[], size_t output_len,
|
|
const char* password, size_t password_len,
|
|
const uint8_t salt[], size_t salt_len,
|
|
const uint8_t key[], size_t key_len,
|
|
const uint8_t ad[], size_t ad_len,
|
|
uint8_t y, size_t p, size_t M, size_t t);
|
|
|
|
std::string BOTAN_PUBLIC_API(2,11)
|
|
argon2_generate_pwhash(const char* password, size_t password_len,
|
|
RandomNumberGenerator& rng,
|
|
size_t p, size_t M, size_t t,
|
|
uint8_t y = 2, size_t salt_len = 16, size_t output_len = 32);
|
|
|
|
/**
|
|
* Check a previously created password hash
|
|
* @param password the password to check against
|
|
* @param password_len the length of password
|
|
* @param hash the stored hash to check against
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,11) argon2_check_pwhash(const char* password, size_t password_len,
|
|
const std::string& hash);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(aria.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* ARIA-128
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,3) ARIA_128 final : public Block_Cipher_Fixed_Params<16, 16>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "ARIA-128"; }
|
|
BlockCipher* clone() const override { return new ARIA_128; }
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
// Encryption and Decryption round keys.
|
|
secure_vector<uint32_t> m_ERK, m_DRK;
|
|
};
|
|
|
|
/**
|
|
* ARIA-192
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,3) ARIA_192 final : public Block_Cipher_Fixed_Params<16, 24>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "ARIA-192"; }
|
|
BlockCipher* clone() const override { return new ARIA_192; }
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
// Encryption and Decryption round keys.
|
|
secure_vector<uint32_t> m_ERK, m_DRK;
|
|
};
|
|
|
|
/**
|
|
* ARIA-256
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,3) ARIA_256 final : public Block_Cipher_Fixed_Params<16, 32>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "ARIA-256"; }
|
|
BlockCipher* clone() const override { return new ARIA_256; }
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
// Encryption and Decryption round keys.
|
|
secure_vector<uint32_t> m_ERK, m_DRK;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class BER_Decoder;
|
|
class DER_Encoder;
|
|
|
|
/**
|
|
* ASN.1 Type and Class Tags
|
|
* This will become an enum class in a future major release
|
|
*/
|
|
enum ASN1_Tag : uint32_t {
|
|
UNIVERSAL = 0x00,
|
|
APPLICATION = 0x40,
|
|
CONTEXT_SPECIFIC = 0x80,
|
|
|
|
CONSTRUCTED = 0x20,
|
|
|
|
PRIVATE = CONSTRUCTED | CONTEXT_SPECIFIC,
|
|
|
|
EOC = 0x00,
|
|
BOOLEAN = 0x01,
|
|
INTEGER = 0x02,
|
|
BIT_STRING = 0x03,
|
|
OCTET_STRING = 0x04,
|
|
NULL_TAG = 0x05,
|
|
OBJECT_ID = 0x06,
|
|
ENUMERATED = 0x0A,
|
|
SEQUENCE = 0x10,
|
|
SET = 0x11,
|
|
|
|
UTF8_STRING = 0x0C,
|
|
NUMERIC_STRING = 0x12,
|
|
PRINTABLE_STRING = 0x13,
|
|
T61_STRING = 0x14,
|
|
IA5_STRING = 0x16,
|
|
VISIBLE_STRING = 0x1A,
|
|
UNIVERSAL_STRING = 0x1C,
|
|
BMP_STRING = 0x1E,
|
|
|
|
UTC_TIME = 0x17,
|
|
GENERALIZED_TIME = 0x18,
|
|
UTC_OR_GENERALIZED_TIME = 0x19,
|
|
|
|
NO_OBJECT = 0xFF00,
|
|
DIRECTORY_STRING = 0xFF01
|
|
};
|
|
|
|
std::string BOTAN_UNSTABLE_API asn1_tag_to_string(ASN1_Tag type);
|
|
std::string BOTAN_UNSTABLE_API asn1_class_to_string(ASN1_Tag type);
|
|
|
|
/**
|
|
* Basic ASN.1 Object Interface
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ASN1_Object
|
|
{
|
|
public:
|
|
/**
|
|
* Encode whatever this object is into to
|
|
* @param to the DER_Encoder that will be written to
|
|
*/
|
|
virtual void encode_into(DER_Encoder& to) const = 0;
|
|
|
|
/**
|
|
* Decode whatever this object is from from
|
|
* @param from the BER_Decoder that will be read from
|
|
*/
|
|
virtual void decode_from(BER_Decoder& from) = 0;
|
|
|
|
/**
|
|
* Return the encoding of this object. This is a convenience
|
|
* method when just one object needs to be serialized. Use
|
|
* DER_Encoder for complicated encodings.
|
|
*/
|
|
std::vector<uint8_t> BER_encode() const;
|
|
|
|
ASN1_Object() = default;
|
|
ASN1_Object(const ASN1_Object&) = default;
|
|
ASN1_Object & operator=(const ASN1_Object&) = default;
|
|
virtual ~ASN1_Object() = default;
|
|
};
|
|
|
|
/**
|
|
* BER Encoded Object
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) BER_Object final
|
|
{
|
|
public:
|
|
BER_Object() : type_tag(NO_OBJECT), class_tag(UNIVERSAL) {}
|
|
|
|
BER_Object(const BER_Object& other) = default;
|
|
|
|
BER_Object& operator=(const BER_Object& other) = default;
|
|
|
|
BER_Object(BER_Object&& other) = default;
|
|
|
|
BER_Object& operator=(BER_Object&& other) = default;
|
|
|
|
bool is_set() const { return type_tag != NO_OBJECT; }
|
|
|
|
ASN1_Tag tagging() const { return ASN1_Tag(type() | get_class()); }
|
|
|
|
ASN1_Tag type() const { return type_tag; }
|
|
ASN1_Tag get_class() const { return class_tag; }
|
|
|
|
const uint8_t* bits() const { return value.data(); }
|
|
|
|
size_t length() const { return value.size(); }
|
|
|
|
void assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag,
|
|
const std::string& descr = "object") const;
|
|
|
|
bool is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) const;
|
|
|
|
bool is_a(int type_tag, ASN1_Tag class_tag) const;
|
|
|
|
BOTAN_DEPRECATED_PUBLIC_MEMBER_VARIABLES:
|
|
/*
|
|
* The following member variables are public for historical reasons, but
|
|
* will be made private in a future major release. Use the accessor
|
|
* functions above.
|
|
*/
|
|
ASN1_Tag type_tag, class_tag;
|
|
secure_vector<uint8_t> value;
|
|
|
|
private:
|
|
|
|
friend class BER_Decoder;
|
|
|
|
void set_tagging(ASN1_Tag type_tag, ASN1_Tag class_tag);
|
|
|
|
uint8_t* mutable_bits(size_t length)
|
|
{
|
|
value.resize(length);
|
|
return value.data();
|
|
}
|
|
};
|
|
|
|
/*
|
|
* ASN.1 Utility Functions
|
|
*/
|
|
class DataSource;
|
|
|
|
namespace ASN1 {
|
|
|
|
std::vector<uint8_t> put_in_sequence(const std::vector<uint8_t>& val);
|
|
std::vector<uint8_t> put_in_sequence(const uint8_t bits[], size_t len);
|
|
std::string to_string(const BER_Object& obj);
|
|
|
|
/**
|
|
* Heuristics tests; is this object possibly BER?
|
|
* @param src a data source that will be peeked at but not modified
|
|
*/
|
|
bool maybe_BER(DataSource& src);
|
|
|
|
}
|
|
|
|
/**
|
|
* General BER Decoding Error Exception
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) BER_Decoding_Error : public Decoding_Error
|
|
{
|
|
public:
|
|
explicit BER_Decoding_Error(const std::string&);
|
|
};
|
|
|
|
/**
|
|
* Exception For Incorrect BER Taggings
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) BER_Bad_Tag final : public BER_Decoding_Error
|
|
{
|
|
public:
|
|
BER_Bad_Tag(const std::string& msg, ASN1_Tag tag);
|
|
BER_Bad_Tag(const std::string& msg, ASN1_Tag tag1, ASN1_Tag tag2);
|
|
};
|
|
|
|
/**
|
|
* This class represents ASN.1 object identifiers.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) OID final : public ASN1_Object
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Create an uninitialied OID object
|
|
*/
|
|
explicit OID() {}
|
|
|
|
/**
|
|
* Construct an OID from a string.
|
|
* @param str a string in the form "a.b.c" etc., where a,b,c are numbers
|
|
*/
|
|
explicit OID(const std::string& str);
|
|
|
|
/**
|
|
* Initialize an OID from a sequence of integer values
|
|
*/
|
|
explicit OID(std::initializer_list<uint32_t> init) : m_id(init) {}
|
|
|
|
/**
|
|
* Initialize an OID from a vector of integer values
|
|
*/
|
|
explicit OID(std::vector<uint32_t>&& init) : m_id(init) {}
|
|
|
|
/**
|
|
* Construct an OID from a string.
|
|
* @param str a string in the form "a.b.c" etc., where a,b,c are numbers
|
|
* or any known OID name (for example "RSA" or "X509v3.SubjectKeyIdentifier")
|
|
*/
|
|
static OID from_string(const std::string& str);
|
|
|
|
void encode_into(class DER_Encoder&) const override;
|
|
void decode_from(class BER_Decoder&) override;
|
|
|
|
/**
|
|
* Find out whether this OID is empty
|
|
* @return true is no OID value is set
|
|
*/
|
|
bool empty() const { return m_id.empty(); }
|
|
|
|
/**
|
|
* Find out whether this OID has a value
|
|
* @return true is this OID has a value
|
|
*/
|
|
bool has_value() const { return (m_id.empty() == false); }
|
|
|
|
/**
|
|
* Get this OID as list (vector) of its components.
|
|
* @return vector representing this OID
|
|
*/
|
|
const std::vector<uint32_t>& get_components() const { return m_id; }
|
|
|
|
const std::vector<uint32_t>& get_id() const { return get_components(); }
|
|
|
|
/**
|
|
* Get this OID as a string
|
|
* @return string representing this OID
|
|
*/
|
|
std::string BOTAN_DEPRECATED("Use OID::to_string") as_string() const
|
|
{
|
|
return this->to_string();
|
|
}
|
|
|
|
/**
|
|
* Get this OID as a dotted-decimal string
|
|
* @return string representing this OID
|
|
*/
|
|
std::string to_string() const;
|
|
|
|
/**
|
|
* If there is a known name associated with this OID, return that.
|
|
* Otherwise return the result of to_string
|
|
*/
|
|
std::string to_formatted_string() const;
|
|
|
|
/**
|
|
* Compare two OIDs.
|
|
* @return true if they are equal, false otherwise
|
|
*/
|
|
bool operator==(const OID& other) const
|
|
{
|
|
return m_id == other.m_id;
|
|
}
|
|
|
|
/**
|
|
* Reset this instance to an empty OID.
|
|
*/
|
|
void BOTAN_DEPRECATED("Avoid mutation of OIDs") clear() { m_id.clear(); }
|
|
|
|
/**
|
|
* Add a component to this OID.
|
|
* @param new_comp the new component to add to the end of this OID
|
|
* @return reference to *this
|
|
*/
|
|
BOTAN_DEPRECATED("Avoid mutation of OIDs") OID& operator+=(uint32_t new_comp)
|
|
{
|
|
m_id.push_back(new_comp);
|
|
return (*this);
|
|
}
|
|
|
|
private:
|
|
std::vector<uint32_t> m_id;
|
|
};
|
|
|
|
/**
|
|
* Append another component onto the OID.
|
|
* @param oid the OID to add the new component to
|
|
* @param new_comp the new component to add
|
|
*/
|
|
OID BOTAN_PUBLIC_API(2,0) operator+(const OID& oid, uint32_t new_comp);
|
|
|
|
/**
|
|
* Compare two OIDs.
|
|
* @param a the first OID
|
|
* @param b the second OID
|
|
* @return true if a is not equal to b
|
|
*/
|
|
inline bool operator!=(const OID& a, const OID& b)
|
|
{
|
|
return !(a == b);
|
|
}
|
|
|
|
/**
|
|
* Compare two OIDs.
|
|
* @param a the first OID
|
|
* @param b the second OID
|
|
* @return true if a is lexicographically smaller than b
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,0) operator<(const OID& a, const OID& b);
|
|
|
|
/**
|
|
* Time (GeneralizedTime/UniversalTime)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ASN1_Time final : public ASN1_Object
|
|
{
|
|
public:
|
|
/// DER encode a ASN1_Time
|
|
void encode_into(DER_Encoder&) const override;
|
|
|
|
// Decode a BER encoded ASN1_Time
|
|
void decode_from(BER_Decoder&) override;
|
|
|
|
/// Return an internal string representation of the time
|
|
std::string to_string() const;
|
|
|
|
/// Returns a human friendly string replesentation of no particular formatting
|
|
std::string readable_string() const;
|
|
|
|
/// Return if the time has been set somehow
|
|
bool time_is_set() const;
|
|
|
|
/// Compare this time against another
|
|
int32_t cmp(const ASN1_Time& other) const;
|
|
|
|
/// Create an invalid ASN1_Time
|
|
ASN1_Time() = default;
|
|
|
|
/// Create a ASN1_Time from a time point
|
|
explicit ASN1_Time(const std::chrono::system_clock::time_point& time);
|
|
|
|
/// Create an ASN1_Time from string
|
|
ASN1_Time(const std::string& t_spec, ASN1_Tag tag);
|
|
|
|
/// Returns a STL timepoint object
|
|
std::chrono::system_clock::time_point to_std_timepoint() const;
|
|
|
|
/// Return time since epoch
|
|
uint64_t time_since_epoch() const;
|
|
|
|
private:
|
|
void set_to(const std::string& t_spec, ASN1_Tag);
|
|
bool passes_sanity_check() const;
|
|
|
|
uint32_t m_year = 0;
|
|
uint32_t m_month = 0;
|
|
uint32_t m_day = 0;
|
|
uint32_t m_hour = 0;
|
|
uint32_t m_minute = 0;
|
|
uint32_t m_second = 0;
|
|
ASN1_Tag m_tag = NO_OBJECT;
|
|
};
|
|
|
|
/*
|
|
* Comparison Operations
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,0) operator==(const ASN1_Time&, const ASN1_Time&);
|
|
bool BOTAN_PUBLIC_API(2,0) operator!=(const ASN1_Time&, const ASN1_Time&);
|
|
bool BOTAN_PUBLIC_API(2,0) operator<=(const ASN1_Time&, const ASN1_Time&);
|
|
bool BOTAN_PUBLIC_API(2,0) operator>=(const ASN1_Time&, const ASN1_Time&);
|
|
bool BOTAN_PUBLIC_API(2,0) operator<(const ASN1_Time&, const ASN1_Time&);
|
|
bool BOTAN_PUBLIC_API(2,0) operator>(const ASN1_Time&, const ASN1_Time&);
|
|
|
|
typedef ASN1_Time X509_Time;
|
|
|
|
/**
|
|
* ASN.1 string type
|
|
* This class normalizes all inputs to a UTF-8 std::string
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ASN1_String final : public ASN1_Object
|
|
{
|
|
public:
|
|
void encode_into(class DER_Encoder&) const override;
|
|
void decode_from(class BER_Decoder&) override;
|
|
|
|
ASN1_Tag tagging() const { return m_tag; }
|
|
|
|
const std::string& value() const { return m_utf8_str; }
|
|
|
|
size_t size() const { return value().size(); }
|
|
|
|
bool empty() const { return m_utf8_str.empty(); }
|
|
|
|
std::string BOTAN_DEPRECATED("Use value() to get UTF-8 string instead")
|
|
iso_8859() const;
|
|
|
|
/**
|
|
* Return true iff this is a tag for a known string type we can handle.
|
|
* This ignores string types that are not supported, eg teletexString
|
|
*/
|
|
static bool is_string_type(ASN1_Tag tag);
|
|
|
|
bool operator==(const ASN1_String& other) const
|
|
{ return value() == other.value(); }
|
|
|
|
explicit ASN1_String(const std::string& utf8 = "");
|
|
ASN1_String(const std::string& utf8, ASN1_Tag tag);
|
|
private:
|
|
std::vector<uint8_t> m_data;
|
|
std::string m_utf8_str;
|
|
ASN1_Tag m_tag;
|
|
};
|
|
|
|
/**
|
|
* Algorithm Identifier
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) AlgorithmIdentifier final : public ASN1_Object
|
|
{
|
|
public:
|
|
enum Encoding_Option { USE_NULL_PARAM, USE_EMPTY_PARAM };
|
|
|
|
void encode_into(class DER_Encoder&) const override;
|
|
void decode_from(class BER_Decoder&) override;
|
|
|
|
AlgorithmIdentifier() = default;
|
|
|
|
AlgorithmIdentifier(const OID& oid, Encoding_Option enc);
|
|
AlgorithmIdentifier(const std::string& oid_name, Encoding_Option enc);
|
|
|
|
AlgorithmIdentifier(const OID& oid, const std::vector<uint8_t>& params);
|
|
AlgorithmIdentifier(const std::string& oid_name, const std::vector<uint8_t>& params);
|
|
|
|
const OID& get_oid() const { return oid; }
|
|
const std::vector<uint8_t>& get_parameters() const { return parameters; }
|
|
|
|
bool parameters_are_null() const;
|
|
bool parameters_are_empty() const { return parameters.empty(); }
|
|
|
|
bool parameters_are_null_or_empty() const
|
|
{
|
|
return parameters_are_empty() || parameters_are_null();
|
|
}
|
|
|
|
BOTAN_DEPRECATED_PUBLIC_MEMBER_VARIABLES:
|
|
/*
|
|
* These values are public for historical reasons, but in a future release
|
|
* they will be made private. Do not access them.
|
|
*/
|
|
OID oid;
|
|
std::vector<uint8_t> parameters;
|
|
};
|
|
|
|
/*
|
|
* Comparison Operations
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,0) operator==(const AlgorithmIdentifier&,
|
|
const AlgorithmIdentifier&);
|
|
bool BOTAN_PUBLIC_API(2,0) operator!=(const AlgorithmIdentifier&,
|
|
const AlgorithmIdentifier&);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class BER_Decoder;
|
|
|
|
/**
|
|
* Format ASN.1 data and call a virtual to format
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,4) ASN1_Formatter
|
|
{
|
|
public:
|
|
virtual ~ASN1_Formatter() = default;
|
|
|
|
/**
|
|
* @param print_context_specific if true, try to parse nested context specific data.
|
|
* @param max_depth do not recurse more than this many times. If zero, recursion
|
|
* is unbounded.
|
|
*/
|
|
ASN1_Formatter(bool print_context_specific, size_t max_depth) :
|
|
m_print_context_specific(print_context_specific),
|
|
m_max_depth(max_depth)
|
|
{}
|
|
|
|
void print_to_stream(std::ostream& out,
|
|
const uint8_t in[],
|
|
size_t len) const;
|
|
|
|
std::string print(const uint8_t in[], size_t len) const;
|
|
|
|
template<typename Alloc>
|
|
std::string print(const std::vector<uint8_t, Alloc>& vec) const
|
|
{
|
|
return print(vec.data(), vec.size());
|
|
}
|
|
|
|
protected:
|
|
/**
|
|
* This is called for each element
|
|
*/
|
|
virtual std::string format(ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag,
|
|
size_t level,
|
|
size_t length,
|
|
const std::string& value) const = 0;
|
|
|
|
/**
|
|
* This is called to format binary elements that we don't know how to
|
|
* convert to a string The result will be passed as value to format; the
|
|
* tags are included as a hint to aid decoding.
|
|
*/
|
|
virtual std::string format_bin(ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag,
|
|
const std::vector<uint8_t>& vec) const = 0;
|
|
|
|
private:
|
|
void decode(std::ostream& output,
|
|
BER_Decoder& decoder,
|
|
size_t level) const;
|
|
|
|
const bool m_print_context_specific;
|
|
const size_t m_max_depth;
|
|
};
|
|
|
|
/**
|
|
* Format ASN.1 data into human readable output. The exact form of the output for
|
|
* any particular input is not guaranteed and may change from release to release.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,4) ASN1_Pretty_Printer final : public ASN1_Formatter
|
|
{
|
|
public:
|
|
/**
|
|
* @param print_limit strings larger than this are not printed
|
|
* @param print_binary_limit binary strings larger than this are not printed
|
|
* @param print_context_specific if true, try to parse nested context specific data.
|
|
* @param initial_level the initial depth (0 or 1 are the only reasonable values)
|
|
* @param value_column ASN.1 values are lined up at this column in output
|
|
* @param max_depth do not recurse more than this many times. If zero, recursion
|
|
* is unbounded.
|
|
*/
|
|
ASN1_Pretty_Printer(size_t print_limit = 4096,
|
|
size_t print_binary_limit = 2048,
|
|
bool print_context_specific = true,
|
|
size_t initial_level = 0,
|
|
size_t value_column = 60,
|
|
size_t max_depth = 64) :
|
|
ASN1_Formatter(print_context_specific, max_depth),
|
|
m_print_limit(print_limit),
|
|
m_print_binary_limit(print_binary_limit),
|
|
m_initial_level(initial_level),
|
|
m_value_column(value_column)
|
|
{}
|
|
|
|
private:
|
|
std::string format(ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag,
|
|
size_t level,
|
|
size_t length,
|
|
const std::string& value) const override;
|
|
|
|
std::string format_bin(ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag,
|
|
const std::vector<uint8_t>& vec) const override;
|
|
|
|
const size_t m_print_limit;
|
|
const size_t m_print_binary_limit;
|
|
const size_t m_initial_level;
|
|
const size_t m_value_column;
|
|
};
|
|
|
|
}
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_THREADS)
|
|
|
|
|
|
namespace Botan {
|
|
|
|
template<typename T> using lock_guard_type = std::lock_guard<T>;
|
|
typedef std::mutex mutex_type;
|
|
typedef std::recursive_mutex recursive_mutex_type;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
// No threads
|
|
|
|
namespace Botan {
|
|
|
|
template<typename Mutex>
|
|
class lock_guard final
|
|
{
|
|
public:
|
|
explicit lock_guard(Mutex& m) : m_mutex(m)
|
|
{ m_mutex.lock(); }
|
|
|
|
~lock_guard() { m_mutex.unlock(); }
|
|
|
|
lock_guard(const lock_guard& other) = delete;
|
|
lock_guard& operator=(const lock_guard& other) = delete;
|
|
private:
|
|
Mutex& m_mutex;
|
|
};
|
|
|
|
class noop_mutex final
|
|
{
|
|
public:
|
|
void lock() {}
|
|
void unlock() {}
|
|
};
|
|
|
|
typedef noop_mutex mutex_type;
|
|
typedef noop_mutex recursive_mutex_type;
|
|
template<typename T> using lock_guard_type = lock_guard<T>;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
class Entropy_Sources;
|
|
|
|
/**
|
|
* An interface to a cryptographic random number generator
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) RandomNumberGenerator
|
|
{
|
|
public:
|
|
virtual ~RandomNumberGenerator() = default;
|
|
|
|
RandomNumberGenerator() = default;
|
|
|
|
/*
|
|
* Never copy a RNG, create a new one
|
|
*/
|
|
RandomNumberGenerator(const RandomNumberGenerator& rng) = delete;
|
|
RandomNumberGenerator& operator=(const RandomNumberGenerator& rng) = delete;
|
|
|
|
/**
|
|
* Randomize a byte array.
|
|
* @param output the byte array to hold the random output.
|
|
* @param length the length of the byte array output in bytes.
|
|
*/
|
|
virtual void randomize(uint8_t output[], size_t length) = 0;
|
|
|
|
/**
|
|
* Returns false if it is known that this RNG object is not able to accept
|
|
* externally provided inputs (via add_entropy, randomize_with_input, etc).
|
|
* In this case, any such provided inputs are ignored.
|
|
*
|
|
* If this function returns true, then inputs may or may not be accepted.
|
|
*/
|
|
virtual bool accepts_input() const = 0;
|
|
|
|
/**
|
|
* Incorporate some additional data into the RNG state. For
|
|
* example adding nonces or timestamps from a peer's protocol
|
|
* message can help hedge against VM state rollback attacks.
|
|
* A few RNG types do not accept any externally provided input,
|
|
* in which case this function is a no-op.
|
|
*
|
|
* @param input a byte array containg the entropy to be added
|
|
* @param length the length of the byte array in
|
|
*/
|
|
virtual void add_entropy(const uint8_t input[], size_t length) = 0;
|
|
|
|
/**
|
|
* Incorporate some additional data into the RNG state.
|
|
*/
|
|
template<typename T> void add_entropy_T(const T& t)
|
|
{
|
|
static_assert(std::is_standard_layout<T>::value && std::is_trivial<T>::value, "add_entropy_T data must be POD");
|
|
this->add_entropy(reinterpret_cast<const uint8_t*>(&t), sizeof(T));
|
|
}
|
|
|
|
/**
|
|
* Incorporate entropy into the RNG state then produce output.
|
|
* Some RNG types implement this using a single operation, default
|
|
* calls add_entropy + randomize in sequence.
|
|
*
|
|
* Use this to further bind the outputs to your current
|
|
* process/protocol state. For instance if generating a new key
|
|
* for use in a session, include a session ID or other such
|
|
* value. See NIST SP 800-90 A, B, C series for more ideas.
|
|
*
|
|
* @param output buffer to hold the random output
|
|
* @param output_len size of the output buffer in bytes
|
|
* @param input entropy buffer to incorporate
|
|
* @param input_len size of the input buffer in bytes
|
|
*/
|
|
virtual void randomize_with_input(uint8_t output[], size_t output_len,
|
|
const uint8_t input[], size_t input_len);
|
|
|
|
/**
|
|
* This calls `randomize_with_input` using some timestamps as extra input.
|
|
*
|
|
* For a stateful RNG using non-random but potentially unique data the
|
|
* extra input can help protect against problems with fork, VM state
|
|
* rollback, or other cases where somehow an RNG state is duplicated. If
|
|
* both of the duplicated RNG states later incorporate a timestamp (and the
|
|
* timestamps don't themselves repeat), their outputs will diverge.
|
|
*/
|
|
virtual void randomize_with_ts_input(uint8_t output[], size_t output_len);
|
|
|
|
/**
|
|
* @return the name of this RNG type
|
|
*/
|
|
virtual std::string name() const = 0;
|
|
|
|
/**
|
|
* Clear all internally held values of this RNG
|
|
* @post is_seeded() == false
|
|
*/
|
|
virtual void clear() = 0;
|
|
|
|
/**
|
|
* Check whether this RNG is seeded.
|
|
* @return true if this RNG was already seeded, false otherwise.
|
|
*/
|
|
virtual bool is_seeded() const = 0;
|
|
|
|
/**
|
|
* Poll provided sources for up to poll_bits bits of entropy
|
|
* or until the timeout expires. Returns estimate of the number
|
|
* of bits collected.
|
|
*/
|
|
virtual size_t reseed(Entropy_Sources& srcs,
|
|
size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
|
|
std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT);
|
|
|
|
/**
|
|
* Reseed by reading specified bits from the RNG
|
|
*/
|
|
virtual void reseed_from_rng(RandomNumberGenerator& rng,
|
|
size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS);
|
|
|
|
// Some utility functions built on the interface above:
|
|
|
|
/**
|
|
* Return a random vector
|
|
* @param bytes number of bytes in the result
|
|
* @return randomized vector of length bytes
|
|
*/
|
|
secure_vector<uint8_t> random_vec(size_t bytes)
|
|
{
|
|
secure_vector<uint8_t> output;
|
|
random_vec(output, bytes);
|
|
return output;
|
|
}
|
|
|
|
template<typename Alloc>
|
|
void random_vec(std::vector<uint8_t, Alloc>& v, size_t bytes)
|
|
{
|
|
v.resize(bytes);
|
|
this->randomize(v.data(), v.size());
|
|
}
|
|
|
|
/**
|
|
* Return a random byte
|
|
* @return random byte
|
|
*/
|
|
uint8_t next_byte()
|
|
{
|
|
uint8_t b;
|
|
this->randomize(&b, 1);
|
|
return b;
|
|
}
|
|
|
|
/**
|
|
* @return a random byte that is greater than zero
|
|
*/
|
|
uint8_t next_nonzero_byte()
|
|
{
|
|
uint8_t b = this->next_byte();
|
|
while(b == 0)
|
|
b = this->next_byte();
|
|
return b;
|
|
}
|
|
|
|
/**
|
|
* Create a seeded and active RNG object for general application use
|
|
* Added in 1.8.0
|
|
* Use AutoSeeded_RNG instead
|
|
*/
|
|
BOTAN_DEPRECATED("Use AutoSeeded_RNG")
|
|
static RandomNumberGenerator* make_rng();
|
|
};
|
|
|
|
/**
|
|
* Convenience typedef
|
|
*/
|
|
typedef RandomNumberGenerator RNG;
|
|
|
|
/**
|
|
* Hardware_RNG exists to tag hardware RNG types (PKCS11_RNG, TPM_RNG, Processor_RNG)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Hardware_RNG : public RandomNumberGenerator
|
|
{
|
|
public:
|
|
virtual void clear() final override { /* no way to clear state of hardware RNG */ }
|
|
};
|
|
|
|
/**
|
|
* Null/stub RNG - fails if you try to use it for anything
|
|
* This is not generally useful except for in certain tests
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Null_RNG final : public RandomNumberGenerator
|
|
{
|
|
public:
|
|
bool is_seeded() const override { return false; }
|
|
|
|
bool accepts_input() const override { return false; }
|
|
|
|
void clear() override {}
|
|
|
|
void randomize(uint8_t[], size_t) override
|
|
{
|
|
throw PRNG_Unseeded("Null_RNG called");
|
|
}
|
|
|
|
void add_entropy(const uint8_t[], size_t) override {}
|
|
|
|
std::string name() const override { return "Null_RNG"; }
|
|
};
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_THREADS)
|
|
/**
|
|
* Wraps access to a RNG in a mutex
|
|
* Note that most of the time it's much better to use a RNG per thread
|
|
* otherwise the RNG will act as an unnecessary contention point
|
|
*
|
|
* Since 2.16.0 all Stateful_RNG instances have an internal lock, so
|
|
* this class is no longer needed. It will be removed in a future major
|
|
* release.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Serialized_RNG final : public RandomNumberGenerator
|
|
{
|
|
public:
|
|
void randomize(uint8_t out[], size_t len) override
|
|
{
|
|
lock_guard_type<mutex_type> lock(m_mutex);
|
|
m_rng->randomize(out, len);
|
|
}
|
|
|
|
bool accepts_input() const override
|
|
{
|
|
lock_guard_type<mutex_type> lock(m_mutex);
|
|
return m_rng->accepts_input();
|
|
}
|
|
|
|
bool is_seeded() const override
|
|
{
|
|
lock_guard_type<mutex_type> lock(m_mutex);
|
|
return m_rng->is_seeded();
|
|
}
|
|
|
|
void clear() override
|
|
{
|
|
lock_guard_type<mutex_type> lock(m_mutex);
|
|
m_rng->clear();
|
|
}
|
|
|
|
std::string name() const override
|
|
{
|
|
lock_guard_type<mutex_type> lock(m_mutex);
|
|
return m_rng->name();
|
|
}
|
|
|
|
size_t reseed(Entropy_Sources& src,
|
|
size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
|
|
std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override
|
|
{
|
|
lock_guard_type<mutex_type> lock(m_mutex);
|
|
return m_rng->reseed(src, poll_bits, poll_timeout);
|
|
}
|
|
|
|
void add_entropy(const uint8_t in[], size_t len) override
|
|
{
|
|
lock_guard_type<mutex_type> lock(m_mutex);
|
|
m_rng->add_entropy(in, len);
|
|
}
|
|
|
|
BOTAN_DEPRECATED("Use Serialized_RNG(new AutoSeeded_RNG) instead") Serialized_RNG();
|
|
|
|
/*
|
|
* Since 2.16.0 this is no longer needed for any RNG type. This
|
|
* class will be removed in a future major release.
|
|
*/
|
|
explicit Serialized_RNG(RandomNumberGenerator* rng) : m_rng(rng) {}
|
|
private:
|
|
mutable mutex_type m_mutex;
|
|
std::unique_ptr<RandomNumberGenerator> m_rng;
|
|
};
|
|
#endif
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Stateful_RNG;
|
|
|
|
/**
|
|
* A userspace PRNG
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) AutoSeeded_RNG final : public RandomNumberGenerator
|
|
{
|
|
public:
|
|
void randomize(uint8_t out[], size_t len) override;
|
|
|
|
void randomize_with_input(uint8_t output[], size_t output_len,
|
|
const uint8_t input[], size_t input_len) override;
|
|
|
|
bool is_seeded() const override;
|
|
|
|
bool accepts_input() const override { return true; }
|
|
|
|
/**
|
|
* Mark state as requiring a reseed on next use
|
|
*/
|
|
void force_reseed();
|
|
|
|
size_t reseed(Entropy_Sources& srcs,
|
|
size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
|
|
std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override;
|
|
|
|
void add_entropy(const uint8_t in[], size_t len) override;
|
|
|
|
std::string name() const override;
|
|
|
|
void clear() override;
|
|
|
|
/**
|
|
* Uses the system RNG (if available) or else a default group of
|
|
* entropy sources (all other systems) to gather seed material.
|
|
*
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed
|
|
*/
|
|
AutoSeeded_RNG(size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL);
|
|
|
|
/**
|
|
* Create an AutoSeeded_RNG which will get seed material from some other
|
|
* RNG instance. For example you could provide a reference to the system
|
|
* RNG or a hardware RNG.
|
|
*
|
|
* @param underlying_rng is a reference to some RNG which will be used
|
|
* to perform the periodic reseeding
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed
|
|
*/
|
|
AutoSeeded_RNG(RandomNumberGenerator& underlying_rng,
|
|
size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL);
|
|
|
|
/**
|
|
* Create an AutoSeeded_RNG which will get seed material from a set of
|
|
* entropy sources.
|
|
*
|
|
* @param entropy_sources will be polled to perform reseeding periodically
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed
|
|
*/
|
|
AutoSeeded_RNG(Entropy_Sources& entropy_sources,
|
|
size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL);
|
|
|
|
/**
|
|
* Create an AutoSeeded_RNG which will get seed material from both an
|
|
* underlying RNG and a set of entropy sources.
|
|
*
|
|
* @param underlying_rng is a reference to some RNG which will be used
|
|
* to perform the periodic reseeding
|
|
* @param entropy_sources will be polled to perform reseeding periodically
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed
|
|
*/
|
|
AutoSeeded_RNG(RandomNumberGenerator& underlying_rng,
|
|
Entropy_Sources& entropy_sources,
|
|
size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL);
|
|
|
|
~AutoSeeded_RNG();
|
|
|
|
private:
|
|
std::unique_ptr<Stateful_RNG> m_rng;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Perform base32 encoding
|
|
* @param output an array of at least base32_encode_max_output bytes
|
|
* @param input is some binary data
|
|
* @param input_length length of input in bytes
|
|
* @param input_consumed is an output parameter which says how many
|
|
* bytes of input were actually consumed. If less than
|
|
* input_length, then the range input[consumed:length]
|
|
* should be passed in later along with more input.
|
|
* @param final_inputs true iff this is the last input, in which case
|
|
padding chars will be applied if needed
|
|
* @return number of bytes written to output
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2, 7) base32_encode(char output[],
|
|
const uint8_t input[],
|
|
size_t input_length,
|
|
size_t& input_consumed,
|
|
bool final_inputs);
|
|
|
|
/**
|
|
* Perform base32 encoding
|
|
* @param input some input
|
|
* @param input_length length of input in bytes
|
|
* @return base32 representation of input
|
|
*/
|
|
std::string BOTAN_PUBLIC_API(2, 7) base32_encode(const uint8_t input[],
|
|
size_t input_length);
|
|
|
|
/**
|
|
* Perform base32 encoding
|
|
* @param input some input
|
|
* @return base32 representation of input
|
|
*/
|
|
template <typename Alloc>
|
|
std::string base32_encode(const std::vector<uint8_t, Alloc>& input)
|
|
{
|
|
return base32_encode(input.data(), input.size());
|
|
}
|
|
|
|
/**
|
|
* Perform base32 decoding
|
|
* @param output an array of at least base32_decode_max_output bytes
|
|
* @param input some base32 input
|
|
* @param input_length length of input in bytes
|
|
* @param input_consumed is an output parameter which says how many
|
|
* bytes of input were actually consumed. If less than
|
|
* input_length, then the range input[consumed:length]
|
|
* should be passed in later along with more input.
|
|
* @param final_inputs true iff this is the last input, in which case
|
|
padding is allowed
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return number of bytes written to output
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2, 7) base32_decode(uint8_t output[],
|
|
const char input[],
|
|
size_t input_length,
|
|
size_t& input_consumed,
|
|
bool final_inputs,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform base32 decoding
|
|
* @param output an array of at least base32_decode_max_output bytes
|
|
* @param input some base32 input
|
|
* @param input_length length of input in bytes
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return number of bytes written to output
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2, 7) base32_decode(uint8_t output[],
|
|
const char input[],
|
|
size_t input_length,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform base32 decoding
|
|
* @param output an array of at least base32_decode_max_output bytes
|
|
* @param input some base32 input
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return number of bytes written to output
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2, 7) base32_decode(uint8_t output[],
|
|
const std::string& input,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform base32 decoding
|
|
* @param input some base32 input
|
|
* @param input_length the length of input in bytes
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return decoded base32 output
|
|
*/
|
|
secure_vector<uint8_t> BOTAN_PUBLIC_API(2, 7) base32_decode(const char input[],
|
|
size_t input_length,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform base32 decoding
|
|
* @param input some base32 input
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return decoded base32 output
|
|
*/
|
|
secure_vector<uint8_t> BOTAN_PUBLIC_API(2, 7) base32_decode(const std::string& input,
|
|
bool ignore_ws = true);
|
|
|
|
} // namespace Botan
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Perform base58 encoding
|
|
*
|
|
* This is raw base58 encoding, without the checksum
|
|
*/
|
|
std::string
|
|
BOTAN_PUBLIC_API(2,9) base58_encode(const uint8_t input[],
|
|
size_t input_length);
|
|
|
|
/**
|
|
* Perform base58 encoding with checksum
|
|
*/
|
|
std::string
|
|
BOTAN_PUBLIC_API(2,9) base58_check_encode(const uint8_t input[],
|
|
size_t input_length);
|
|
|
|
|
|
/**
|
|
* Perform base58 decoding
|
|
*
|
|
* This is raw base58 encoding, without the checksum
|
|
*/
|
|
std::vector<uint8_t>
|
|
BOTAN_PUBLIC_API(2,9) base58_decode(const char input[],
|
|
size_t input_length);
|
|
|
|
/**
|
|
* Perform base58 decoding with checksum
|
|
*/
|
|
std::vector<uint8_t>
|
|
BOTAN_PUBLIC_API(2,9) base58_check_decode(const char input[],
|
|
size_t input_length);
|
|
|
|
|
|
// Some convenience wrappers:
|
|
|
|
template<typename Alloc>
|
|
inline std::string base58_encode(const std::vector<uint8_t, Alloc>& vec)
|
|
{
|
|
return base58_encode(vec.data(), vec.size());
|
|
}
|
|
|
|
template<typename Alloc>
|
|
inline std::string base58_check_encode(const std::vector<uint8_t, Alloc>& vec)
|
|
{
|
|
return base58_check_encode(vec.data(), vec.size());
|
|
}
|
|
|
|
inline std::vector<uint8_t> base58_decode(const std::string& s)
|
|
{
|
|
return base58_decode(s.data(), s.size());
|
|
}
|
|
|
|
inline std::vector<uint8_t> base58_check_decode(const std::string& s)
|
|
{
|
|
return base58_check_decode(s.data(), s.size());
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Perform base64 encoding
|
|
* @param output an array of at least base64_encode_max_output bytes
|
|
* @param input is some binary data
|
|
* @param input_length length of input in bytes
|
|
* @param input_consumed is an output parameter which says how many
|
|
* bytes of input were actually consumed. If less than
|
|
* input_length, then the range input[consumed:length]
|
|
* should be passed in later along with more input.
|
|
* @param final_inputs true iff this is the last input, in which case
|
|
padding chars will be applied if needed
|
|
* @return number of bytes written to output
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,0) base64_encode(char output[],
|
|
const uint8_t input[],
|
|
size_t input_length,
|
|
size_t& input_consumed,
|
|
bool final_inputs);
|
|
|
|
/**
|
|
* Perform base64 encoding
|
|
* @param input some input
|
|
* @param input_length length of input in bytes
|
|
* @return base64adecimal representation of input
|
|
*/
|
|
std::string BOTAN_PUBLIC_API(2,0) base64_encode(const uint8_t input[],
|
|
size_t input_length);
|
|
|
|
/**
|
|
* Perform base64 encoding
|
|
* @param input some input
|
|
* @return base64adecimal representation of input
|
|
*/
|
|
template<typename Alloc>
|
|
std::string base64_encode(const std::vector<uint8_t, Alloc>& input)
|
|
{
|
|
return base64_encode(input.data(), input.size());
|
|
}
|
|
|
|
/**
|
|
* Perform base64 decoding
|
|
* @param output an array of at least base64_decode_max_output bytes
|
|
* @param input some base64 input
|
|
* @param input_length length of input in bytes
|
|
* @param input_consumed is an output parameter which says how many
|
|
* bytes of input were actually consumed. If less than
|
|
* input_length, then the range input[consumed:length]
|
|
* should be passed in later along with more input.
|
|
* @param final_inputs true iff this is the last input, in which case
|
|
padding is allowed
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return number of bytes written to output
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,0) base64_decode(uint8_t output[],
|
|
const char input[],
|
|
size_t input_length,
|
|
size_t& input_consumed,
|
|
bool final_inputs,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform base64 decoding
|
|
* @param output an array of at least base64_decode_max_output bytes
|
|
* @param input some base64 input
|
|
* @param input_length length of input in bytes
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return number of bytes written to output
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,0) base64_decode(uint8_t output[],
|
|
const char input[],
|
|
size_t input_length,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform base64 decoding
|
|
* @param output an array of at least base64_decode_max_output bytes
|
|
* @param input some base64 input
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return number of bytes written to output
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,0) base64_decode(uint8_t output[],
|
|
const std::string& input,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform base64 decoding
|
|
* @param input some base64 input
|
|
* @param input_length the length of input in bytes
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return decoded base64 output
|
|
*/
|
|
secure_vector<uint8_t> BOTAN_PUBLIC_API(2,0) base64_decode(const char input[],
|
|
size_t input_length,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform base64 decoding
|
|
* @param input some base64 input
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return decoded base64 output
|
|
*/
|
|
secure_vector<uint8_t> BOTAN_PUBLIC_API(2,0) base64_decode(const std::string& input,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Calculate the size of output buffer for base64_encode
|
|
* @param input_length the length of input in bytes
|
|
* @return the size of output buffer in bytes
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,1) base64_encode_max_output(size_t input_length);
|
|
|
|
/**
|
|
* Calculate the size of output buffer for base64_decode
|
|
* @param input_length the length of input in bytes
|
|
* @return the size of output buffer in bytes
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,1) base64_decode_max_output(size_t input_length);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Create a password hash using Bcrypt
|
|
*
|
|
* @warning The password is truncated at at most 72 characters; characters after
|
|
* that do not have any effect on the resulting hash. To support longer
|
|
* passwords, consider pre-hashing the password, for example by using
|
|
* the hex encoding of SHA-256 of the password as the input to bcrypt.
|
|
*
|
|
* @param password the password.
|
|
* @param rng a random number generator
|
|
* @param work_factor how much work to do to slow down guessing attacks
|
|
* @param version which version to emit (may be 'a', 'b', or 'y' all of which
|
|
* have identical behavior in this implementation).
|
|
*
|
|
* @see https://www.usenix.org/events/usenix99/provos/provos_html/
|
|
*/
|
|
std::string BOTAN_PUBLIC_API(2,0) generate_bcrypt(const std::string& password,
|
|
RandomNumberGenerator& rng,
|
|
uint16_t work_factor = 12,
|
|
char version = 'a');
|
|
|
|
/**
|
|
* Check a previously created password hash
|
|
* @param password the password to check against
|
|
* @param hash the stored hash to check against
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,0) check_bcrypt(const std::string& password,
|
|
const std::string& hash);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(bcrypt_pbkdf.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Bcrypt-PBKDF key derivation function
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,11) Bcrypt_PBKDF final : public PasswordHash
|
|
{
|
|
public:
|
|
Bcrypt_PBKDF(size_t iterations) : m_iterations(iterations) {}
|
|
|
|
Bcrypt_PBKDF(const Bcrypt_PBKDF& other) = default;
|
|
Bcrypt_PBKDF& operator=(const Bcrypt_PBKDF&) = default;
|
|
|
|
/**
|
|
* Derive a new key under the current Bcrypt-PBKDF parameter set
|
|
*/
|
|
void derive_key(uint8_t out[], size_t out_len,
|
|
const char* password, size_t password_len,
|
|
const uint8_t salt[], size_t salt_len) const override;
|
|
|
|
std::string to_string() const override;
|
|
|
|
size_t iterations() const override { return m_iterations; }
|
|
|
|
size_t parallelism() const override { return 0; }
|
|
|
|
size_t memory_param() const override { return 0; }
|
|
|
|
size_t total_memory_usage() const override { return 4096; }
|
|
|
|
private:
|
|
size_t m_iterations;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,11) Bcrypt_PBKDF_Family final : public PasswordHashFamily
|
|
{
|
|
public:
|
|
Bcrypt_PBKDF_Family() {}
|
|
|
|
std::string name() const override;
|
|
|
|
std::unique_ptr<PasswordHash> tune(size_t output_length,
|
|
std::chrono::milliseconds msec,
|
|
size_t max_memory) const override;
|
|
|
|
std::unique_ptr<PasswordHash> default_params() const override;
|
|
|
|
std::unique_ptr<PasswordHash> from_iterations(size_t iter) const override;
|
|
|
|
std::unique_ptr<PasswordHash> from_params(
|
|
size_t i, size_t, size_t) const override;
|
|
};
|
|
|
|
/**
|
|
* Bcrypt PBKDF compatible with OpenBSD bcrypt_pbkdf
|
|
*/
|
|
void BOTAN_UNSTABLE_API bcrypt_pbkdf(uint8_t output[], size_t output_len,
|
|
const char* pass, size_t pass_len,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t rounds);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents an abstract data source object.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DataSource
|
|
{
|
|
public:
|
|
/**
|
|
* Read from the source. Moves the internal offset so that every
|
|
* call to read will return a new portion of the source.
|
|
*
|
|
* @param out the byte array to write the result to
|
|
* @param length the length of the byte array out
|
|
* @return length in bytes that was actually read and put
|
|
* into out
|
|
*/
|
|
virtual size_t read(uint8_t out[], size_t length) BOTAN_WARN_UNUSED_RESULT = 0;
|
|
|
|
virtual bool check_available(size_t n) = 0;
|
|
|
|
/**
|
|
* Read from the source but do not modify the internal
|
|
* offset. Consecutive calls to peek() will return portions of
|
|
* the source starting at the same position.
|
|
*
|
|
* @param out the byte array to write the output to
|
|
* @param length the length of the byte array out
|
|
* @param peek_offset the offset into the stream to read at
|
|
* @return length in bytes that was actually read and put
|
|
* into out
|
|
*/
|
|
virtual size_t peek(uint8_t out[], size_t length, size_t peek_offset) const BOTAN_WARN_UNUSED_RESULT = 0;
|
|
|
|
/**
|
|
* Test whether the source still has data that can be read.
|
|
* @return true if there is no more data to read, false otherwise
|
|
*/
|
|
virtual bool end_of_data() const = 0;
|
|
/**
|
|
* return the id of this data source
|
|
* @return std::string representing the id of this data source
|
|
*/
|
|
virtual std::string id() const { return ""; }
|
|
|
|
/**
|
|
* Read one byte.
|
|
* @param out the byte to read to
|
|
* @return length in bytes that was actually read and put
|
|
* into out
|
|
*/
|
|
size_t read_byte(uint8_t& out);
|
|
|
|
/**
|
|
* Peek at one byte.
|
|
* @param out an output byte
|
|
* @return length in bytes that was actually read and put
|
|
* into out
|
|
*/
|
|
size_t peek_byte(uint8_t& out) const;
|
|
|
|
/**
|
|
* Discard the next N bytes of the data
|
|
* @param N the number of bytes to discard
|
|
* @return number of bytes actually discarded
|
|
*/
|
|
size_t discard_next(size_t N);
|
|
|
|
/**
|
|
* @return number of bytes read so far.
|
|
*/
|
|
virtual size_t get_bytes_read() const = 0;
|
|
|
|
DataSource() = default;
|
|
virtual ~DataSource() = default;
|
|
DataSource& operator=(const DataSource&) = delete;
|
|
DataSource(const DataSource&) = delete;
|
|
};
|
|
|
|
/**
|
|
* This class represents a Memory-Based DataSource
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DataSource_Memory final : public DataSource
|
|
{
|
|
public:
|
|
size_t read(uint8_t[], size_t) override;
|
|
size_t peek(uint8_t[], size_t, size_t) const override;
|
|
bool check_available(size_t n) override;
|
|
bool end_of_data() const override;
|
|
|
|
/**
|
|
* Construct a memory source that reads from a string
|
|
* @param in the string to read from
|
|
*/
|
|
explicit DataSource_Memory(const std::string& in);
|
|
|
|
/**
|
|
* Construct a memory source that reads from a byte array
|
|
* @param in the byte array to read from
|
|
* @param length the length of the byte array
|
|
*/
|
|
DataSource_Memory(const uint8_t in[], size_t length) :
|
|
m_source(in, in + length), m_offset(0) {}
|
|
|
|
/**
|
|
* Construct a memory source that reads from a secure_vector
|
|
* @param in the MemoryRegion to read from
|
|
*/
|
|
explicit DataSource_Memory(const secure_vector<uint8_t>& in) :
|
|
m_source(in), m_offset(0) {}
|
|
|
|
/**
|
|
* Construct a memory source that reads from a std::vector
|
|
* @param in the MemoryRegion to read from
|
|
*/
|
|
explicit DataSource_Memory(const std::vector<uint8_t>& in) :
|
|
m_source(in.begin(), in.end()), m_offset(0) {}
|
|
|
|
size_t get_bytes_read() const override { return m_offset; }
|
|
private:
|
|
secure_vector<uint8_t> m_source;
|
|
size_t m_offset;
|
|
};
|
|
|
|
/**
|
|
* This class represents a Stream-Based DataSource.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DataSource_Stream final : public DataSource
|
|
{
|
|
public:
|
|
size_t read(uint8_t[], size_t) override;
|
|
size_t peek(uint8_t[], size_t, size_t) const override;
|
|
bool check_available(size_t n) override;
|
|
bool end_of_data() const override;
|
|
std::string id() const override;
|
|
|
|
DataSource_Stream(std::istream&,
|
|
const std::string& id = "<std::istream>");
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
|
|
/**
|
|
* Construct a Stream-Based DataSource from filesystem path
|
|
* @param file the path to the file
|
|
* @param use_binary whether to treat the file as binary or not
|
|
*/
|
|
DataSource_Stream(const std::string& file, bool use_binary = false);
|
|
#endif
|
|
|
|
DataSource_Stream(const DataSource_Stream&) = delete;
|
|
|
|
DataSource_Stream& operator=(const DataSource_Stream&) = delete;
|
|
|
|
~DataSource_Stream();
|
|
|
|
size_t get_bytes_read() const override { return m_total_read; }
|
|
private:
|
|
const std::string m_identifier;
|
|
|
|
std::unique_ptr<std::istream> m_source_memory;
|
|
std::istream& m_source;
|
|
size_t m_total_read;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class BigInt;
|
|
|
|
/**
|
|
* BER Decoding Object
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) BER_Decoder final
|
|
{
|
|
public:
|
|
/**
|
|
* Set up to BER decode the data in buf of length len
|
|
*/
|
|
BER_Decoder(const uint8_t buf[], size_t len);
|
|
|
|
/**
|
|
* Set up to BER decode the data in vec
|
|
*/
|
|
explicit BER_Decoder(const secure_vector<uint8_t>& vec);
|
|
|
|
/**
|
|
* Set up to BER decode the data in vec
|
|
*/
|
|
explicit BER_Decoder(const std::vector<uint8_t>& vec);
|
|
|
|
/**
|
|
* Set up to BER decode the data in src
|
|
*/
|
|
explicit BER_Decoder(DataSource& src);
|
|
|
|
/**
|
|
* Set up to BER decode the data in obj
|
|
*/
|
|
BER_Decoder(const BER_Object& obj) :
|
|
BER_Decoder(obj.bits(), obj.length()) {}
|
|
|
|
/**
|
|
* Set up to BER decode the data in obj
|
|
*/
|
|
BER_Decoder(BER_Object&& obj) :
|
|
BER_Decoder(std::move(obj), nullptr) {}
|
|
|
|
BER_Decoder(const BER_Decoder& other);
|
|
|
|
BER_Decoder& operator=(const BER_Decoder&) = delete;
|
|
|
|
/**
|
|
* Get the next object in the data stream.
|
|
* If EOF, returns an object with type NO_OBJECT.
|
|
*/
|
|
BER_Object get_next_object();
|
|
|
|
BER_Decoder& get_next(BER_Object& ber)
|
|
{
|
|
ber = get_next_object();
|
|
return (*this);
|
|
}
|
|
|
|
/**
|
|
* Push an object back onto the stream. Throws if another
|
|
* object was previously pushed and has not been subsequently
|
|
* read out.
|
|
*/
|
|
void push_back(const BER_Object& obj);
|
|
|
|
/**
|
|
* Push an object back onto the stream. Throws if another
|
|
* object was previously pushed and has not been subsequently
|
|
* read out.
|
|
*/
|
|
void push_back(BER_Object&& obj);
|
|
|
|
/**
|
|
* Return true if there is at least one more item remaining
|
|
*/
|
|
bool more_items() const;
|
|
|
|
/**
|
|
* Verify the stream is concluded, throws otherwise.
|
|
* Returns (*this)
|
|
*/
|
|
BER_Decoder& verify_end();
|
|
|
|
/**
|
|
* Verify the stream is concluded, throws otherwise.
|
|
* Returns (*this)
|
|
*/
|
|
BER_Decoder& verify_end(const std::string& err_msg);
|
|
|
|
/**
|
|
* Discard any data that remains unread
|
|
* Returns (*this)
|
|
*/
|
|
BER_Decoder& discard_remaining();
|
|
|
|
/**
|
|
* Start decoding a constructed data (sequence or set)
|
|
*/
|
|
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag = UNIVERSAL);
|
|
|
|
/**
|
|
* Finish decoding a constructed data, throws if any data remains.
|
|
* Returns the parent of *this (ie the object on which start_cons was called).
|
|
*/
|
|
BER_Decoder& end_cons();
|
|
|
|
/**
|
|
* Get next object and copy value to POD type
|
|
* Asserts value length is equal to POD type sizeof.
|
|
* Asserts Type tag and optional Class tag according to parameters.
|
|
* Copy value to POD type (struct, union, C-style array, std::array, etc.).
|
|
* @param out POD type reference where to copy object value
|
|
* @param type_tag ASN1_Tag enum to assert type on object read
|
|
* @param class_tag ASN1_Tag enum to assert class on object read (default: CONTEXT_SPECIFIC)
|
|
* @return this reference
|
|
*/
|
|
template <typename T>
|
|
BER_Decoder& get_next_value(T &out,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC)
|
|
{
|
|
static_assert(std::is_standard_layout<T>::value && std::is_trivial<T>::value, "Type must be POD");
|
|
|
|
BER_Object obj = get_next_object();
|
|
obj.assert_is_a(type_tag, class_tag);
|
|
|
|
if (obj.length() != sizeof(T))
|
|
throw BER_Decoding_Error(
|
|
"Size mismatch. Object value size is " +
|
|
std::to_string(obj.length()) +
|
|
"; Output type size is " +
|
|
std::to_string(sizeof(T)));
|
|
|
|
copy_mem(reinterpret_cast<uint8_t*>(&out), obj.bits(), obj.length());
|
|
|
|
return (*this);
|
|
}
|
|
|
|
/*
|
|
* Save all the bytes remaining in the source
|
|
*/
|
|
template<typename Alloc>
|
|
BER_Decoder& raw_bytes(std::vector<uint8_t, Alloc>& out)
|
|
{
|
|
out.clear();
|
|
uint8_t buf;
|
|
while(m_source->read_byte(buf))
|
|
out.push_back(buf);
|
|
return (*this);
|
|
}
|
|
|
|
BER_Decoder& decode_null();
|
|
|
|
/**
|
|
* Decode a BER encoded BOOLEAN
|
|
*/
|
|
BER_Decoder& decode(bool& out)
|
|
{
|
|
return decode(out, BOOLEAN, UNIVERSAL);
|
|
}
|
|
|
|
/*
|
|
* Decode a small BER encoded INTEGER
|
|
*/
|
|
BER_Decoder& decode(size_t& out)
|
|
{
|
|
return decode(out, INTEGER, UNIVERSAL);
|
|
}
|
|
|
|
/*
|
|
* Decode a BER encoded INTEGER
|
|
*/
|
|
BER_Decoder& decode(BigInt& out)
|
|
{
|
|
return decode(out, INTEGER, UNIVERSAL);
|
|
}
|
|
|
|
std::vector<uint8_t> get_next_octet_string()
|
|
{
|
|
std::vector<uint8_t> out_vec;
|
|
decode(out_vec, OCTET_STRING);
|
|
return out_vec;
|
|
}
|
|
|
|
/*
|
|
* BER decode a BIT STRING or OCTET STRING
|
|
*/
|
|
template<typename Alloc>
|
|
BER_Decoder& decode(std::vector<uint8_t, Alloc>& out, ASN1_Tag real_type)
|
|
{
|
|
return decode(out, real_type, real_type, UNIVERSAL);
|
|
}
|
|
|
|
BER_Decoder& decode(bool& v,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
|
|
|
|
BER_Decoder& decode(size_t& v,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
|
|
|
|
BER_Decoder& decode(BigInt& v,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
|
|
|
|
BER_Decoder& decode(std::vector<uint8_t>& v,
|
|
ASN1_Tag real_type,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
|
|
|
|
BER_Decoder& decode(secure_vector<uint8_t>& v,
|
|
ASN1_Tag real_type,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
|
|
|
|
BER_Decoder& decode(class ASN1_Object& obj,
|
|
ASN1_Tag type_tag = NO_OBJECT,
|
|
ASN1_Tag class_tag = NO_OBJECT);
|
|
|
|
/**
|
|
* Decode an integer value which is typed as an octet string
|
|
*/
|
|
BER_Decoder& decode_octet_string_bigint(BigInt& b);
|
|
|
|
uint64_t decode_constrained_integer(ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag,
|
|
size_t T_bytes);
|
|
|
|
template<typename T> BER_Decoder& decode_integer_type(T& out)
|
|
{
|
|
return decode_integer_type<T>(out, INTEGER, UNIVERSAL);
|
|
}
|
|
|
|
template<typename T>
|
|
BER_Decoder& decode_integer_type(T& out,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC)
|
|
{
|
|
out = static_cast<T>(decode_constrained_integer(type_tag, class_tag, sizeof(out)));
|
|
return (*this);
|
|
}
|
|
|
|
template<typename T>
|
|
BER_Decoder& decode_optional(T& out,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag,
|
|
const T& default_value = T());
|
|
|
|
template<typename T>
|
|
BER_Decoder& decode_optional_implicit(
|
|
T& out,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag,
|
|
ASN1_Tag real_type,
|
|
ASN1_Tag real_class,
|
|
const T& default_value = T());
|
|
|
|
template<typename T>
|
|
BER_Decoder& decode_list(std::vector<T>& out,
|
|
ASN1_Tag type_tag = SEQUENCE,
|
|
ASN1_Tag class_tag = UNIVERSAL);
|
|
|
|
template<typename T>
|
|
BER_Decoder& decode_and_check(const T& expected,
|
|
const std::string& error_msg)
|
|
{
|
|
T actual;
|
|
decode(actual);
|
|
|
|
if(actual != expected)
|
|
throw Decoding_Error(error_msg);
|
|
|
|
return (*this);
|
|
}
|
|
|
|
/*
|
|
* Decode an OPTIONAL string type
|
|
*/
|
|
template<typename Alloc>
|
|
BER_Decoder& decode_optional_string(std::vector<uint8_t, Alloc>& out,
|
|
ASN1_Tag real_type,
|
|
uint16_t type_no,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC)
|
|
{
|
|
BER_Object obj = get_next_object();
|
|
|
|
ASN1_Tag type_tag = static_cast<ASN1_Tag>(type_no);
|
|
|
|
if(obj.is_a(type_tag, class_tag))
|
|
{
|
|
if((class_tag & CONSTRUCTED) && (class_tag & CONTEXT_SPECIFIC))
|
|
{
|
|
BER_Decoder(std::move(obj)).decode(out, real_type).verify_end();
|
|
}
|
|
else
|
|
{
|
|
push_back(std::move(obj));
|
|
decode(out, real_type, type_tag, class_tag);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
out.clear();
|
|
push_back(std::move(obj));
|
|
}
|
|
|
|
return (*this);
|
|
}
|
|
|
|
private:
|
|
BER_Decoder(BER_Object&& obj, BER_Decoder* parent);
|
|
|
|
BER_Decoder* m_parent = nullptr;
|
|
BER_Object m_pushed;
|
|
// either m_data_src.get() or an unowned pointer
|
|
DataSource* m_source;
|
|
mutable std::unique_ptr<DataSource> m_data_src;
|
|
};
|
|
|
|
/*
|
|
* Decode an OPTIONAL or DEFAULT element
|
|
*/
|
|
template<typename T>
|
|
BER_Decoder& BER_Decoder::decode_optional(T& out,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag,
|
|
const T& default_value)
|
|
{
|
|
BER_Object obj = get_next_object();
|
|
|
|
if(obj.is_a(type_tag, class_tag))
|
|
{
|
|
if((class_tag & CONSTRUCTED) && (class_tag & CONTEXT_SPECIFIC))
|
|
{
|
|
BER_Decoder(std::move(obj)).decode(out).verify_end();
|
|
}
|
|
else
|
|
{
|
|
push_back(std::move(obj));
|
|
decode(out, type_tag, class_tag);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
out = default_value;
|
|
push_back(std::move(obj));
|
|
}
|
|
|
|
return (*this);
|
|
}
|
|
|
|
/*
|
|
* Decode an OPTIONAL or DEFAULT element
|
|
*/
|
|
template<typename T>
|
|
BER_Decoder& BER_Decoder::decode_optional_implicit(
|
|
T& out,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag,
|
|
ASN1_Tag real_type,
|
|
ASN1_Tag real_class,
|
|
const T& default_value)
|
|
{
|
|
BER_Object obj = get_next_object();
|
|
|
|
if(obj.is_a(type_tag, class_tag))
|
|
{
|
|
obj.set_tagging(real_type, real_class);
|
|
push_back(std::move(obj));
|
|
decode(out, real_type, real_class);
|
|
}
|
|
else
|
|
{
|
|
// Not what we wanted, push it back on the stream
|
|
out = default_value;
|
|
push_back(std::move(obj));
|
|
}
|
|
|
|
return (*this);
|
|
}
|
|
/*
|
|
* Decode a list of homogenously typed values
|
|
*/
|
|
template<typename T>
|
|
BER_Decoder& BER_Decoder::decode_list(std::vector<T>& vec,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag)
|
|
{
|
|
BER_Decoder list = start_cons(type_tag, class_tag);
|
|
|
|
while(list.more_items())
|
|
{
|
|
T value;
|
|
list.decode(value);
|
|
vec.push_back(std::move(value));
|
|
}
|
|
|
|
list.end_cons();
|
|
|
|
return (*this);
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Arbitrary precision integer
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) BigInt final
|
|
{
|
|
public:
|
|
/**
|
|
* Base enumerator for encoding and decoding
|
|
*/
|
|
enum Base { Decimal = 10, Hexadecimal = 16, Binary = 256 };
|
|
|
|
/**
|
|
* Sign symbol definitions for positive and negative numbers
|
|
*/
|
|
enum Sign { Negative = 0, Positive = 1 };
|
|
|
|
/**
|
|
* DivideByZero Exception
|
|
*
|
|
* In a future release this exception will be removed and its usage
|
|
* replaced by Invalid_Argument
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DivideByZero final : public Invalid_Argument
|
|
{
|
|
public:
|
|
DivideByZero() : Invalid_Argument("BigInt divide by zero") {}
|
|
};
|
|
|
|
/**
|
|
* Create empty BigInt
|
|
*/
|
|
BigInt() = default;
|
|
|
|
/**
|
|
* Create BigInt from 64 bit integer
|
|
* @param n initial value of this BigInt
|
|
*/
|
|
BigInt(uint64_t n);
|
|
|
|
/**
|
|
* Copy Constructor
|
|
* @param other the BigInt to copy
|
|
*/
|
|
BigInt(const BigInt& other) = default;
|
|
|
|
/**
|
|
* Create BigInt from a string. If the string starts with 0x the
|
|
* rest of the string will be interpreted as hexadecimal digits.
|
|
* Otherwise, it will be interpreted as a decimal number.
|
|
*
|
|
* @param str the string to parse for an integer value
|
|
*/
|
|
explicit BigInt(const std::string& str);
|
|
|
|
/**
|
|
* Create a BigInt from an integer in a byte array
|
|
* @param buf the byte array holding the value
|
|
* @param length size of buf
|
|
*/
|
|
BigInt(const uint8_t buf[], size_t length);
|
|
|
|
/**
|
|
* Create a BigInt from an integer in a byte array
|
|
* @param vec the byte vector holding the value
|
|
*/
|
|
template<typename Alloc>
|
|
explicit BigInt(const std::vector<uint8_t, Alloc>& vec) : BigInt(vec.data(), vec.size()) {}
|
|
|
|
/**
|
|
* Create a BigInt from an integer in a byte array
|
|
* @param buf the byte array holding the value
|
|
* @param length size of buf
|
|
* @param base is the number base of the integer in buf
|
|
*/
|
|
BigInt(const uint8_t buf[], size_t length, Base base);
|
|
|
|
/**
|
|
* Create a BigInt from an integer in a byte array
|
|
* @param buf the byte array holding the value
|
|
* @param length size of buf
|
|
* @param max_bits if the resulting integer is more than max_bits,
|
|
* it will be shifted so it is at most max_bits in length.
|
|
*/
|
|
BigInt(const uint8_t buf[], size_t length, size_t max_bits);
|
|
|
|
/**
|
|
* Create a BigInt from an array of words
|
|
* @param words the words
|
|
* @param length number of words
|
|
*/
|
|
BigInt(const word words[], size_t length);
|
|
|
|
/**
|
|
* \brief Create a random BigInt of the specified size
|
|
*
|
|
* @param rng random number generator
|
|
* @param bits size in bits
|
|
* @param set_high_bit if true, the highest bit is always set
|
|
*
|
|
* @see randomize
|
|
*/
|
|
BigInt(RandomNumberGenerator& rng, size_t bits, bool set_high_bit = true);
|
|
|
|
/**
|
|
* Create BigInt of specified size, all zeros
|
|
* @param sign the sign
|
|
* @param n size of the internal register in words
|
|
*/
|
|
BigInt(Sign sign, size_t n);
|
|
|
|
/**
|
|
* Move constructor
|
|
*/
|
|
BigInt(BigInt&& other)
|
|
{
|
|
this->swap(other);
|
|
}
|
|
|
|
~BigInt() { const_time_unpoison(); }
|
|
|
|
/**
|
|
* Move assignment
|
|
*/
|
|
BigInt& operator=(BigInt&& other)
|
|
{
|
|
if(this != &other)
|
|
this->swap(other);
|
|
|
|
return (*this);
|
|
}
|
|
|
|
/**
|
|
* Copy assignment
|
|
*/
|
|
BigInt& operator=(const BigInt&) = default;
|
|
|
|
/**
|
|
* Swap this value with another
|
|
* @param other BigInt to swap values with
|
|
*/
|
|
void swap(BigInt& other)
|
|
{
|
|
m_data.swap(other.m_data);
|
|
std::swap(m_signedness, other.m_signedness);
|
|
}
|
|
|
|
void swap_reg(secure_vector<word>& reg)
|
|
{
|
|
m_data.swap(reg);
|
|
// sign left unchanged
|
|
}
|
|
|
|
/**
|
|
* += operator
|
|
* @param y the BigInt to add to this
|
|
*/
|
|
BigInt& operator+=(const BigInt& y)
|
|
{
|
|
return add(y.data(), y.sig_words(), y.sign());
|
|
}
|
|
|
|
/**
|
|
* += operator
|
|
* @param y the word to add to this
|
|
*/
|
|
BigInt& operator+=(word y)
|
|
{
|
|
return add(&y, 1, Positive);
|
|
}
|
|
|
|
/**
|
|
* -= operator
|
|
* @param y the BigInt to subtract from this
|
|
*/
|
|
BigInt& operator-=(const BigInt& y)
|
|
{
|
|
return sub(y.data(), y.sig_words(), y.sign());
|
|
}
|
|
|
|
/**
|
|
* -= operator
|
|
* @param y the word to subtract from this
|
|
*/
|
|
BigInt& operator-=(word y)
|
|
{
|
|
return sub(&y, 1, Positive);
|
|
}
|
|
|
|
/**
|
|
* *= operator
|
|
* @param y the BigInt to multiply with this
|
|
*/
|
|
BigInt& operator*=(const BigInt& y);
|
|
|
|
/**
|
|
* *= operator
|
|
* @param y the word to multiply with this
|
|
*/
|
|
BigInt& operator*=(word y);
|
|
|
|
/**
|
|
* /= operator
|
|
* @param y the BigInt to divide this by
|
|
*/
|
|
BigInt& operator/=(const BigInt& y);
|
|
|
|
/**
|
|
* Modulo operator
|
|
* @param y the modulus to reduce this by
|
|
*/
|
|
BigInt& operator%=(const BigInt& y);
|
|
|
|
/**
|
|
* Modulo operator
|
|
* @param y the modulus (word) to reduce this by
|
|
*/
|
|
word operator%=(word y);
|
|
|
|
/**
|
|
* Left shift operator
|
|
* @param shift the number of bits to shift this left by
|
|
*/
|
|
BigInt& operator<<=(size_t shift);
|
|
|
|
/**
|
|
* Right shift operator
|
|
* @param shift the number of bits to shift this right by
|
|
*/
|
|
BigInt& operator>>=(size_t shift);
|
|
|
|
/**
|
|
* Increment operator
|
|
*/
|
|
BigInt& operator++() { return (*this += 1); }
|
|
|
|
/**
|
|
* Decrement operator
|
|
*/
|
|
BigInt& operator--() { return (*this -= 1); }
|
|
|
|
/**
|
|
* Postfix increment operator
|
|
*/
|
|
BigInt operator++(int) { BigInt x = (*this); ++(*this); return x; }
|
|
|
|
/**
|
|
* Postfix decrement operator
|
|
*/
|
|
BigInt operator--(int) { BigInt x = (*this); --(*this); return x; }
|
|
|
|
/**
|
|
* Unary negation operator
|
|
* @return negative this
|
|
*/
|
|
BigInt operator-() const;
|
|
|
|
/**
|
|
* ! operator
|
|
* @return true iff this is zero, otherwise false
|
|
*/
|
|
bool operator !() const { return (!is_nonzero()); }
|
|
|
|
static BigInt add2(const BigInt& x, const word y[], size_t y_words, Sign y_sign);
|
|
|
|
BigInt& add(const word y[], size_t y_words, Sign sign);
|
|
|
|
BigInt& sub(const word y[], size_t y_words, Sign sign)
|
|
{
|
|
return add(y, y_words, sign == Positive ? Negative : Positive);
|
|
}
|
|
|
|
/**
|
|
* Multiply this with y
|
|
* @param y the BigInt to multiply with this
|
|
* @param ws a temp workspace
|
|
*/
|
|
BigInt& mul(const BigInt& y, secure_vector<word>& ws);
|
|
|
|
/**
|
|
* Square value of *this
|
|
* @param ws a temp workspace
|
|
*/
|
|
BigInt& square(secure_vector<word>& ws);
|
|
|
|
/**
|
|
* Set *this to y - *this
|
|
* @param y the BigInt to subtract from as a sequence of words
|
|
* @param y_words length of y in words
|
|
* @param ws a temp workspace
|
|
*/
|
|
BigInt& rev_sub(const word y[], size_t y_words, secure_vector<word>& ws);
|
|
|
|
/**
|
|
* Set *this to (*this + y) % mod
|
|
* This function assumes *this is >= 0 && < mod
|
|
* @param y the BigInt to add - assumed y >= 0 and y < mod
|
|
* @param mod the positive modulus
|
|
* @param ws a temp workspace
|
|
*/
|
|
BigInt& mod_add(const BigInt& y, const BigInt& mod, secure_vector<word>& ws);
|
|
|
|
/**
|
|
* Set *this to (*this - y) % mod
|
|
* This function assumes *this is >= 0 && < mod
|
|
* @param y the BigInt to subtract - assumed y >= 0 and y < mod
|
|
* @param mod the positive modulus
|
|
* @param ws a temp workspace
|
|
*/
|
|
BigInt& mod_sub(const BigInt& y, const BigInt& mod, secure_vector<word>& ws);
|
|
|
|
/**
|
|
* Set *this to (*this * y) % mod
|
|
* This function assumes *this is >= 0 && < mod
|
|
* y should be small, less than 16
|
|
* @param y the small integer to multiply by
|
|
* @param mod the positive modulus
|
|
* @param ws a temp workspace
|
|
*/
|
|
BigInt& mod_mul(uint8_t y, const BigInt& mod, secure_vector<word>& ws);
|
|
|
|
/**
|
|
* Return *this % mod
|
|
*
|
|
* Assumes that *this is (if anything) only slightly larger than
|
|
* mod and performs repeated subtractions. It should not be used if
|
|
* *this is much larger than mod, instead use modulo operator.
|
|
*/
|
|
size_t reduce_below(const BigInt& mod, secure_vector<word> &ws);
|
|
|
|
/**
|
|
* Return *this % mod
|
|
*
|
|
* Assumes that *this is (if anything) only slightly larger than mod and
|
|
* performs repeated subtractions. It should not be used if *this is much
|
|
* larger than mod, instead use modulo operator.
|
|
*
|
|
* Performs exactly bound subtractions, so if *this is >= bound*mod then the
|
|
* result will not be fully reduced. If bound is zero, nothing happens.
|
|
*/
|
|
void ct_reduce_below(const BigInt& mod, secure_vector<word> &ws, size_t bound);
|
|
|
|
/**
|
|
* Zeroize the BigInt. The size of the underlying register is not
|
|
* modified.
|
|
*/
|
|
void clear() { m_data.set_to_zero(); m_signedness = Positive; }
|
|
|
|
/**
|
|
* Compare this to another BigInt
|
|
* @param n the BigInt value to compare with
|
|
* @param check_signs include sign in comparison?
|
|
* @result if (this<n) return -1, if (this>n) return 1, if both
|
|
* values are identical return 0 [like Perl's <=> operator]
|
|
*/
|
|
int32_t cmp(const BigInt& n, bool check_signs = true) const;
|
|
|
|
/**
|
|
* Compare this to another BigInt
|
|
* @param n the BigInt value to compare with
|
|
* @result true if this == n or false otherwise
|
|
*/
|
|
bool is_equal(const BigInt& n) const;
|
|
|
|
/**
|
|
* Compare this to another BigInt
|
|
* @param n the BigInt value to compare with
|
|
* @result true if this < n or false otherwise
|
|
*/
|
|
bool is_less_than(const BigInt& n) const;
|
|
|
|
/**
|
|
* Compare this to an integer
|
|
* @param n the value to compare with
|
|
* @result if (this<n) return -1, if (this>n) return 1, if both
|
|
* values are identical return 0 [like Perl's <=> operator]
|
|
*/
|
|
int32_t cmp_word(word n) const;
|
|
|
|
/**
|
|
* Test if the integer has an even value
|
|
* @result true if the integer is even, false otherwise
|
|
*/
|
|
bool is_even() const { return (get_bit(0) == 0); }
|
|
|
|
/**
|
|
* Test if the integer has an odd value
|
|
* @result true if the integer is odd, false otherwise
|
|
*/
|
|
bool is_odd() const { return (get_bit(0) == 1); }
|
|
|
|
/**
|
|
* Test if the integer is not zero
|
|
* @result true if the integer is non-zero, false otherwise
|
|
*/
|
|
bool is_nonzero() const { return (!is_zero()); }
|
|
|
|
/**
|
|
* Test if the integer is zero
|
|
* @result true if the integer is zero, false otherwise
|
|
*/
|
|
bool is_zero() const
|
|
{
|
|
return (sig_words() == 0);
|
|
}
|
|
|
|
/**
|
|
* Set bit at specified position
|
|
* @param n bit position to set
|
|
*/
|
|
void set_bit(size_t n)
|
|
{
|
|
conditionally_set_bit(n, true);
|
|
}
|
|
|
|
/**
|
|
* Conditionally set bit at specified position. Note if set_it is
|
|
* false, nothing happens, and if the bit is already set, it
|
|
* remains set.
|
|
*
|
|
* @param n bit position to set
|
|
* @param set_it if the bit should be set
|
|
*/
|
|
void conditionally_set_bit(size_t n, bool set_it);
|
|
|
|
/**
|
|
* Clear bit at specified position
|
|
* @param n bit position to clear
|
|
*/
|
|
void clear_bit(size_t n);
|
|
|
|
/**
|
|
* Clear all but the lowest n bits
|
|
* @param n amount of bits to keep
|
|
*/
|
|
void mask_bits(size_t n)
|
|
{
|
|
m_data.mask_bits(n);
|
|
}
|
|
|
|
/**
|
|
* Return bit value at specified position
|
|
* @param n the bit offset to test
|
|
* @result true, if the bit at position n is set, false otherwise
|
|
*/
|
|
bool get_bit(size_t n) const
|
|
{
|
|
return ((word_at(n / BOTAN_MP_WORD_BITS) >> (n % BOTAN_MP_WORD_BITS)) & 1);
|
|
}
|
|
|
|
/**
|
|
* Return (a maximum of) 32 bits of the complete value
|
|
* @param offset the offset to start extracting
|
|
* @param length amount of bits to extract (starting at offset)
|
|
* @result the integer extracted from the register starting at
|
|
* offset with specified length
|
|
*/
|
|
uint32_t get_substring(size_t offset, size_t length) const;
|
|
|
|
/**
|
|
* Convert this value into a uint32_t, if it is in the range
|
|
* [0 ... 2**32-1], or otherwise throw an exception.
|
|
* @result the value as a uint32_t if conversion is possible
|
|
*/
|
|
uint32_t to_u32bit() const;
|
|
|
|
/**
|
|
* Convert this value to a decimal string.
|
|
* Warning: decimal conversions are relatively slow
|
|
*/
|
|
std::string to_dec_string() const;
|
|
|
|
/**
|
|
* Convert this value to a hexadecimal string.
|
|
*/
|
|
std::string to_hex_string() const;
|
|
|
|
/**
|
|
* @param n the offset to get a byte from
|
|
* @result byte at offset n
|
|
*/
|
|
uint8_t byte_at(size_t n) const;
|
|
|
|
/**
|
|
* Return the word at a specified position of the internal register
|
|
* @param n position in the register
|
|
* @return value at position n
|
|
*/
|
|
word word_at(size_t n) const
|
|
{
|
|
return m_data.get_word_at(n);
|
|
}
|
|
|
|
void set_word_at(size_t i, word w)
|
|
{
|
|
m_data.set_word_at(i, w);
|
|
}
|
|
|
|
void set_words(const word w[], size_t len)
|
|
{
|
|
m_data.set_words(w, len);
|
|
}
|
|
|
|
/**
|
|
* Tests if the sign of the integer is negative
|
|
* @result true, iff the integer has a negative sign
|
|
*/
|
|
bool is_negative() const { return (sign() == Negative); }
|
|
|
|
/**
|
|
* Tests if the sign of the integer is positive
|
|
* @result true, iff the integer has a positive sign
|
|
*/
|
|
bool is_positive() const { return (sign() == Positive); }
|
|
|
|
/**
|
|
* Return the sign of the integer
|
|
* @result the sign of the integer
|
|
*/
|
|
Sign sign() const { return (m_signedness); }
|
|
|
|
/**
|
|
* @result the opposite sign of the represented integer value
|
|
*/
|
|
Sign reverse_sign() const
|
|
{
|
|
if(sign() == Positive)
|
|
return Negative;
|
|
return Positive;
|
|
}
|
|
|
|
/**
|
|
* Flip the sign of this BigInt
|
|
*/
|
|
void flip_sign()
|
|
{
|
|
set_sign(reverse_sign());
|
|
}
|
|
|
|
/**
|
|
* Set sign of the integer
|
|
* @param sign new Sign to set
|
|
*/
|
|
void set_sign(Sign sign)
|
|
{
|
|
if(sign == Negative && is_zero())
|
|
sign = Positive;
|
|
|
|
m_signedness = sign;
|
|
}
|
|
|
|
/**
|
|
* @result absolute (positive) value of this
|
|
*/
|
|
BigInt abs() const;
|
|
|
|
/**
|
|
* Give size of internal register
|
|
* @result size of internal register in words
|
|
*/
|
|
size_t size() const { return m_data.size(); }
|
|
|
|
/**
|
|
* Return how many words we need to hold this value
|
|
* @result significant words of the represented integer value
|
|
*/
|
|
size_t sig_words() const
|
|
{
|
|
return m_data.sig_words();
|
|
}
|
|
|
|
/**
|
|
* Give byte length of the integer
|
|
* @result byte length of the represented integer value
|
|
*/
|
|
size_t bytes() const;
|
|
|
|
/**
|
|
* Get the bit length of the integer
|
|
* @result bit length of the represented integer value
|
|
*/
|
|
size_t bits() const;
|
|
|
|
/**
|
|
* Get the number of high bits unset in the top (allocated) word
|
|
* of this integer. Returns BOTAN_MP_WORD_BITS only iff *this is
|
|
* zero. Ignores sign.
|
|
*/
|
|
size_t top_bits_free() const;
|
|
|
|
/**
|
|
* Return a mutable pointer to the register
|
|
* @result a pointer to the start of the internal register
|
|
*/
|
|
word* mutable_data() { return m_data.mutable_data(); }
|
|
|
|
/**
|
|
* Return a const pointer to the register
|
|
* @result a pointer to the start of the internal register
|
|
*/
|
|
const word* data() const { return m_data.const_data(); }
|
|
|
|
/**
|
|
* Don't use this function in application code
|
|
*/
|
|
secure_vector<word>& get_word_vector() { return m_data.mutable_vector(); }
|
|
|
|
/**
|
|
* Don't use this function in application code
|
|
*/
|
|
const secure_vector<word>& get_word_vector() const { return m_data.const_vector(); }
|
|
|
|
/**
|
|
* Increase internal register buffer to at least n words
|
|
* @param n new size of register
|
|
*/
|
|
void grow_to(size_t n) const { m_data.grow_to(n); }
|
|
|
|
/**
|
|
* Resize the vector to the minimum word size to hold the integer, or
|
|
* min_size words, whichever is larger
|
|
*/
|
|
void BOTAN_DEPRECATED("Use resize if required") shrink_to_fit(size_t min_size = 0)
|
|
{
|
|
m_data.shrink_to_fit(min_size);
|
|
}
|
|
|
|
void resize(size_t s) { m_data.resize(s); }
|
|
|
|
/**
|
|
* Fill BigInt with a random number with size of bitsize
|
|
*
|
|
* If \p set_high_bit is true, the highest bit will be set, which causes
|
|
* the entropy to be \a bits-1. Otherwise the highest bit is randomly chosen
|
|
* by the rng, causing the entropy to be \a bits.
|
|
*
|
|
* @param rng the random number generator to use
|
|
* @param bitsize number of bits the created random value should have
|
|
* @param set_high_bit if true, the highest bit is always set
|
|
*/
|
|
void randomize(RandomNumberGenerator& rng, size_t bitsize, bool set_high_bit = true);
|
|
|
|
/**
|
|
* Store BigInt-value in a given byte array
|
|
* @param buf destination byte array for the integer value
|
|
*/
|
|
void binary_encode(uint8_t buf[]) const;
|
|
|
|
/**
|
|
* Store BigInt-value in a given byte array. If len is less than
|
|
* the size of the value, then it will be truncated. If len is
|
|
* greater than the size of the value, it will be zero-padded.
|
|
* If len exactly equals this->bytes(), this function behaves identically
|
|
* to binary_encode.
|
|
*
|
|
* @param buf destination byte array for the integer value
|
|
* @param len how many bytes to write
|
|
*/
|
|
void binary_encode(uint8_t buf[], size_t len) const;
|
|
|
|
/**
|
|
* Read integer value from a byte array with given size
|
|
* @param buf byte array buffer containing the integer
|
|
* @param length size of buf
|
|
*/
|
|
void binary_decode(const uint8_t buf[], size_t length);
|
|
|
|
/**
|
|
* Read integer value from a byte vector
|
|
* @param buf the vector to load from
|
|
*/
|
|
template<typename Alloc>
|
|
void binary_decode(const std::vector<uint8_t, Alloc>& buf)
|
|
{
|
|
binary_decode(buf.data(), buf.size());
|
|
}
|
|
|
|
/**
|
|
* @param base the base to measure the size for
|
|
* @return size of this integer in base base
|
|
*
|
|
* Deprecated. This is only needed when using the `encode` and
|
|
* `encode_locked` functions, which are also deprecated.
|
|
*/
|
|
BOTAN_DEPRECATED("See comments on declaration")
|
|
size_t encoded_size(Base base = Binary) const;
|
|
|
|
/**
|
|
* Place the value into out, zero-padding up to size words
|
|
* Throw if *this cannot be represented in size words
|
|
*/
|
|
void encode_words(word out[], size_t size) const;
|
|
|
|
/**
|
|
* If predicate is true assign other to *this
|
|
* Uses a masked operation to avoid side channels
|
|
*/
|
|
void ct_cond_assign(bool predicate, const BigInt& other);
|
|
|
|
/**
|
|
* If predicate is true swap *this and other
|
|
* Uses a masked operation to avoid side channels
|
|
*/
|
|
void ct_cond_swap(bool predicate, BigInt& other);
|
|
|
|
/**
|
|
* If predicate is true add value to *this
|
|
*/
|
|
void ct_cond_add(bool predicate, const BigInt& value);
|
|
|
|
/**
|
|
* If predicate is true flip the sign of *this
|
|
*/
|
|
void cond_flip_sign(bool predicate);
|
|
|
|
#if defined(BOTAN_HAS_VALGRIND)
|
|
void const_time_poison() const;
|
|
void const_time_unpoison() const;
|
|
#else
|
|
void const_time_poison() const {}
|
|
void const_time_unpoison() const {}
|
|
#endif
|
|
|
|
/**
|
|
* @param rng a random number generator
|
|
* @param min the minimum value (must be non-negative)
|
|
* @param max the maximum value (must be non-negative and > min)
|
|
* @return random integer in [min,max)
|
|
*/
|
|
static BigInt random_integer(RandomNumberGenerator& rng,
|
|
const BigInt& min,
|
|
const BigInt& max);
|
|
|
|
/**
|
|
* Create a power of two
|
|
* @param n the power of two to create
|
|
* @return bigint representing 2^n
|
|
*/
|
|
static BigInt power_of_2(size_t n)
|
|
{
|
|
BigInt b;
|
|
b.set_bit(n);
|
|
return b;
|
|
}
|
|
|
|
/**
|
|
* Encode the integer value from a BigInt to a std::vector of bytes
|
|
* @param n the BigInt to use as integer source
|
|
* @result secure_vector of bytes containing the bytes of the integer
|
|
*/
|
|
static std::vector<uint8_t> encode(const BigInt& n)
|
|
{
|
|
std::vector<uint8_t> output(n.bytes());
|
|
n.binary_encode(output.data());
|
|
return output;
|
|
}
|
|
|
|
/**
|
|
* Encode the integer value from a BigInt to a secure_vector of bytes
|
|
* @param n the BigInt to use as integer source
|
|
* @result secure_vector of bytes containing the bytes of the integer
|
|
*/
|
|
static secure_vector<uint8_t> encode_locked(const BigInt& n)
|
|
{
|
|
secure_vector<uint8_t> output(n.bytes());
|
|
n.binary_encode(output.data());
|
|
return output;
|
|
}
|
|
|
|
/**
|
|
* Encode the integer value from a BigInt to a byte array
|
|
* @param buf destination byte array for the encoded integer
|
|
* @param n the BigInt to use as integer source
|
|
*/
|
|
static BOTAN_DEPRECATED("Use n.binary_encode") void encode(uint8_t buf[], const BigInt& n)
|
|
{
|
|
n.binary_encode(buf);
|
|
}
|
|
|
|
/**
|
|
* Create a BigInt from an integer in a byte array
|
|
* @param buf the binary value to load
|
|
* @param length size of buf
|
|
* @result BigInt representing the integer in the byte array
|
|
*/
|
|
static BigInt decode(const uint8_t buf[], size_t length)
|
|
{
|
|
return BigInt(buf, length);
|
|
}
|
|
|
|
/**
|
|
* Create a BigInt from an integer in a byte array
|
|
* @param buf the binary value to load
|
|
* @result BigInt representing the integer in the byte array
|
|
*/
|
|
template<typename Alloc>
|
|
static BigInt decode(const std::vector<uint8_t, Alloc>& buf)
|
|
{
|
|
return BigInt(buf);
|
|
}
|
|
|
|
/**
|
|
* Encode the integer value from a BigInt to a std::vector of bytes
|
|
* @param n the BigInt to use as integer source
|
|
* @param base number-base of resulting byte array representation
|
|
* @result secure_vector of bytes containing the integer with given base
|
|
*
|
|
* Deprecated. If you need Binary, call the version of encode that doesn't
|
|
* take a Base. If you need Hex or Decimal output, use to_hex_string or
|
|
* to_dec_string resp.
|
|
*/
|
|
BOTAN_DEPRECATED("See comments on declaration")
|
|
static std::vector<uint8_t> encode(const BigInt& n, Base base);
|
|
|
|
/**
|
|
* Encode the integer value from a BigInt to a secure_vector of bytes
|
|
* @param n the BigInt to use as integer source
|
|
* @param base number-base of resulting byte array representation
|
|
* @result secure_vector of bytes containing the integer with given base
|
|
*
|
|
* Deprecated. If you need Binary, call the version of encode_locked that
|
|
* doesn't take a Base. If you need Hex or Decimal output, use to_hex_string
|
|
* or to_dec_string resp.
|
|
*/
|
|
BOTAN_DEPRECATED("See comments on declaration")
|
|
static secure_vector<uint8_t> encode_locked(const BigInt& n,
|
|
Base base);
|
|
|
|
/**
|
|
* Encode the integer value from a BigInt to a byte array
|
|
* @param buf destination byte array for the encoded integer
|
|
* value with given base
|
|
* @param n the BigInt to use as integer source
|
|
* @param base number-base of resulting byte array representation
|
|
*
|
|
* Deprecated. If you need Binary, call binary_encode. If you need
|
|
* Hex or Decimal output, use to_hex_string or to_dec_string resp.
|
|
*/
|
|
BOTAN_DEPRECATED("See comments on declaration")
|
|
static void encode(uint8_t buf[], const BigInt& n, Base base);
|
|
|
|
/**
|
|
* Create a BigInt from an integer in a byte array
|
|
* @param buf the binary value to load
|
|
* @param length size of buf
|
|
* @param base number-base of the integer in buf
|
|
* @result BigInt representing the integer in the byte array
|
|
*/
|
|
static BigInt decode(const uint8_t buf[], size_t length,
|
|
Base base);
|
|
|
|
/**
|
|
* Create a BigInt from an integer in a byte array
|
|
* @param buf the binary value to load
|
|
* @param base number-base of the integer in buf
|
|
* @result BigInt representing the integer in the byte array
|
|
*/
|
|
template<typename Alloc>
|
|
static BigInt decode(const std::vector<uint8_t, Alloc>& buf, Base base)
|
|
{
|
|
if(base == Binary)
|
|
return BigInt(buf);
|
|
return BigInt::decode(buf.data(), buf.size(), base);
|
|
}
|
|
|
|
/**
|
|
* Encode a BigInt to a byte array according to IEEE 1363
|
|
* @param n the BigInt to encode
|
|
* @param bytes the length of the resulting secure_vector<uint8_t>
|
|
* @result a secure_vector<uint8_t> containing the encoded BigInt
|
|
*/
|
|
static secure_vector<uint8_t> encode_1363(const BigInt& n, size_t bytes);
|
|
|
|
static void encode_1363(uint8_t out[], size_t bytes, const BigInt& n);
|
|
|
|
/**
|
|
* Encode two BigInt to a byte array according to IEEE 1363
|
|
* @param n1 the first BigInt to encode
|
|
* @param n2 the second BigInt to encode
|
|
* @param bytes the length of the encoding of each single BigInt
|
|
* @result a secure_vector<uint8_t> containing the concatenation of the two encoded BigInt
|
|
*/
|
|
static secure_vector<uint8_t> encode_fixed_length_int_pair(const BigInt& n1, const BigInt& n2, size_t bytes);
|
|
|
|
/**
|
|
* Set output = vec[idx].m_reg in constant time
|
|
*
|
|
* All elements of vec must have the same size, and output must be
|
|
* pre-allocated with the same size.
|
|
*/
|
|
static void BOTAN_DEPRECATED("No longer in use") const_time_lookup(
|
|
secure_vector<word>& output,
|
|
const std::vector<BigInt>& vec,
|
|
size_t idx);
|
|
|
|
private:
|
|
|
|
class Data
|
|
{
|
|
public:
|
|
word* mutable_data()
|
|
{
|
|
invalidate_sig_words();
|
|
return m_reg.data();
|
|
}
|
|
|
|
const word* const_data() const
|
|
{
|
|
return m_reg.data();
|
|
}
|
|
|
|
secure_vector<word>& mutable_vector()
|
|
{
|
|
invalidate_sig_words();
|
|
return m_reg;
|
|
}
|
|
|
|
const secure_vector<word>& const_vector() const
|
|
{
|
|
return m_reg;
|
|
}
|
|
|
|
word get_word_at(size_t n) const
|
|
{
|
|
if(n < m_reg.size())
|
|
return m_reg[n];
|
|
return 0;
|
|
}
|
|
|
|
void set_word_at(size_t i, word w)
|
|
{
|
|
invalidate_sig_words();
|
|
if(i >= m_reg.size())
|
|
{
|
|
if(w == 0)
|
|
return;
|
|
grow_to(i + 1);
|
|
}
|
|
m_reg[i] = w;
|
|
}
|
|
|
|
void set_words(const word w[], size_t len)
|
|
{
|
|
invalidate_sig_words();
|
|
m_reg.assign(w, w + len);
|
|
}
|
|
|
|
void set_to_zero()
|
|
{
|
|
m_reg.resize(m_reg.capacity());
|
|
clear_mem(m_reg.data(), m_reg.size());
|
|
m_sig_words = 0;
|
|
}
|
|
|
|
void set_size(size_t s)
|
|
{
|
|
invalidate_sig_words();
|
|
clear_mem(m_reg.data(), m_reg.size());
|
|
m_reg.resize(s + (8 - (s % 8)));
|
|
}
|
|
|
|
void mask_bits(size_t n)
|
|
{
|
|
if(n == 0) { return set_to_zero(); }
|
|
|
|
const size_t top_word = n / BOTAN_MP_WORD_BITS;
|
|
|
|
// if(top_word < sig_words()) ?
|
|
if(top_word < size())
|
|
{
|
|
const word mask = (static_cast<word>(1) << (n % BOTAN_MP_WORD_BITS)) - 1;
|
|
const size_t len = size() - (top_word + 1);
|
|
if(len > 0)
|
|
{
|
|
clear_mem(&m_reg[top_word+1], len);
|
|
}
|
|
m_reg[top_word] &= mask;
|
|
invalidate_sig_words();
|
|
}
|
|
}
|
|
|
|
void grow_to(size_t n) const
|
|
{
|
|
if(n > size())
|
|
{
|
|
if(n <= m_reg.capacity())
|
|
m_reg.resize(n);
|
|
else
|
|
m_reg.resize(n + (8 - (n % 8)));
|
|
}
|
|
}
|
|
|
|
size_t size() const { return m_reg.size(); }
|
|
|
|
void shrink_to_fit(size_t min_size = 0)
|
|
{
|
|
const size_t words = std::max(min_size, sig_words());
|
|
m_reg.resize(words);
|
|
}
|
|
|
|
void resize(size_t s)
|
|
{
|
|
m_reg.resize(s);
|
|
}
|
|
|
|
void swap(Data& other)
|
|
{
|
|
m_reg.swap(other.m_reg);
|
|
std::swap(m_sig_words, other.m_sig_words);
|
|
}
|
|
|
|
void swap(secure_vector<word>& reg)
|
|
{
|
|
m_reg.swap(reg);
|
|
invalidate_sig_words();
|
|
}
|
|
|
|
void invalidate_sig_words() const
|
|
{
|
|
m_sig_words = sig_words_npos;
|
|
}
|
|
|
|
size_t sig_words() const
|
|
{
|
|
if(m_sig_words == sig_words_npos)
|
|
{
|
|
m_sig_words = calc_sig_words();
|
|
}
|
|
else
|
|
{
|
|
BOTAN_DEBUG_ASSERT(m_sig_words == calc_sig_words());
|
|
}
|
|
return m_sig_words;
|
|
}
|
|
private:
|
|
static const size_t sig_words_npos = static_cast<size_t>(-1);
|
|
|
|
size_t calc_sig_words() const;
|
|
|
|
mutable secure_vector<word> m_reg;
|
|
mutable size_t m_sig_words = sig_words_npos;
|
|
};
|
|
|
|
Data m_data;
|
|
Sign m_signedness = Positive;
|
|
};
|
|
|
|
/*
|
|
* Arithmetic Operators
|
|
*/
|
|
inline BigInt operator+(const BigInt& x, const BigInt& y)
|
|
{
|
|
return BigInt::add2(x, y.data(), y.sig_words(), y.sign());
|
|
}
|
|
|
|
inline BigInt operator+(const BigInt& x, word y)
|
|
{
|
|
return BigInt::add2(x, &y, 1, BigInt::Positive);
|
|
}
|
|
|
|
inline BigInt operator+(word x, const BigInt& y)
|
|
{
|
|
return y + x;
|
|
}
|
|
|
|
inline BigInt operator-(const BigInt& x, const BigInt& y)
|
|
{
|
|
return BigInt::add2(x, y.data(), y.sig_words(), y.reverse_sign());
|
|
}
|
|
|
|
inline BigInt operator-(const BigInt& x, word y)
|
|
{
|
|
return BigInt::add2(x, &y, 1, BigInt::Negative);
|
|
}
|
|
|
|
BigInt BOTAN_PUBLIC_API(2,0) operator*(const BigInt& x, const BigInt& y);
|
|
BigInt BOTAN_PUBLIC_API(2,8) operator*(const BigInt& x, word y);
|
|
inline BigInt operator*(word x, const BigInt& y) { return y*x; }
|
|
|
|
BigInt BOTAN_PUBLIC_API(2,0) operator/(const BigInt& x, const BigInt& d);
|
|
BigInt BOTAN_PUBLIC_API(2,0) operator/(const BigInt& x, word m);
|
|
BigInt BOTAN_PUBLIC_API(2,0) operator%(const BigInt& x, const BigInt& m);
|
|
word BOTAN_PUBLIC_API(2,0) operator%(const BigInt& x, word m);
|
|
BigInt BOTAN_PUBLIC_API(2,0) operator<<(const BigInt& x, size_t n);
|
|
BigInt BOTAN_PUBLIC_API(2,0) operator>>(const BigInt& x, size_t n);
|
|
|
|
/*
|
|
* Comparison Operators
|
|
*/
|
|
inline bool operator==(const BigInt& a, const BigInt& b)
|
|
{ return a.is_equal(b); }
|
|
inline bool operator!=(const BigInt& a, const BigInt& b)
|
|
{ return !a.is_equal(b); }
|
|
inline bool operator<=(const BigInt& a, const BigInt& b)
|
|
{ return (a.cmp(b) <= 0); }
|
|
inline bool operator>=(const BigInt& a, const BigInt& b)
|
|
{ return (a.cmp(b) >= 0); }
|
|
inline bool operator<(const BigInt& a, const BigInt& b)
|
|
{ return a.is_less_than(b); }
|
|
inline bool operator>(const BigInt& a, const BigInt& b)
|
|
{ return b.is_less_than(a); }
|
|
|
|
inline bool operator==(const BigInt& a, word b)
|
|
{ return (a.cmp_word(b) == 0); }
|
|
inline bool operator!=(const BigInt& a, word b)
|
|
{ return (a.cmp_word(b) != 0); }
|
|
inline bool operator<=(const BigInt& a, word b)
|
|
{ return (a.cmp_word(b) <= 0); }
|
|
inline bool operator>=(const BigInt& a, word b)
|
|
{ return (a.cmp_word(b) >= 0); }
|
|
inline bool operator<(const BigInt& a, word b)
|
|
{ return (a.cmp_word(b) < 0); }
|
|
inline bool operator>(const BigInt& a, word b)
|
|
{ return (a.cmp_word(b) > 0); }
|
|
|
|
/*
|
|
* I/O Operators
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::ostream& operator<<(std::ostream&, const BigInt&);
|
|
BOTAN_PUBLIC_API(2,0) std::istream& operator>>(std::istream&, BigInt&);
|
|
|
|
}
|
|
|
|
namespace std {
|
|
|
|
template<>
|
|
inline void swap<Botan::BigInt>(Botan::BigInt& x, Botan::BigInt& y)
|
|
{
|
|
x.swap(y);
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(blake2b.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* BLAKE2B
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) BLAKE2b final : public HashFunction
|
|
{
|
|
public:
|
|
/**
|
|
* @param output_bits the output size of BLAKE2b in bits
|
|
*/
|
|
explicit BLAKE2b(size_t output_bits = 512);
|
|
|
|
size_t hash_block_size() const override { return 128; }
|
|
size_t output_length() const override { return m_output_bits / 8; }
|
|
|
|
HashFunction* clone() const override;
|
|
std::string name() const override;
|
|
void clear() override;
|
|
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
private:
|
|
void add_data(const uint8_t input[], size_t length) override;
|
|
void final_result(uint8_t out[]) override;
|
|
|
|
void state_init();
|
|
void compress(const uint8_t* data, size_t blocks, uint64_t increment);
|
|
|
|
const size_t m_output_bits;
|
|
|
|
secure_vector<uint8_t> m_buffer;
|
|
size_t m_bufpos;
|
|
|
|
secure_vector<uint64_t> m_H;
|
|
uint64_t m_T[2];
|
|
uint64_t m_F[2];
|
|
};
|
|
|
|
typedef BLAKE2b Blake2b;
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Fused multiply-add
|
|
* @param a an integer
|
|
* @param b an integer
|
|
* @param c an integer
|
|
* @return (a*b)+c
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Just use (a*b)+c")
|
|
mul_add(const BigInt& a,
|
|
const BigInt& b,
|
|
const BigInt& c);
|
|
|
|
/**
|
|
* Fused subtract-multiply
|
|
* @param a an integer
|
|
* @param b an integer
|
|
* @param c an integer
|
|
* @return (a-b)*c
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Just use (a-b)*c")
|
|
sub_mul(const BigInt& a,
|
|
const BigInt& b,
|
|
const BigInt& c);
|
|
|
|
/**
|
|
* Fused multiply-subtract
|
|
* @param a an integer
|
|
* @param b an integer
|
|
* @param c an integer
|
|
* @return (a*b)-c
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Just use (a*b)-c")
|
|
mul_sub(const BigInt& a,
|
|
const BigInt& b,
|
|
const BigInt& c);
|
|
|
|
/**
|
|
* Return the absolute value
|
|
* @param n an integer
|
|
* @return absolute value of n
|
|
*/
|
|
inline BigInt abs(const BigInt& n) { return n.abs(); }
|
|
|
|
/**
|
|
* Compute the greatest common divisor
|
|
* @param x a positive integer
|
|
* @param y a positive integer
|
|
* @return gcd(x,y)
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) gcd(const BigInt& x, const BigInt& y);
|
|
|
|
/**
|
|
* Least common multiple
|
|
* @param x a positive integer
|
|
* @param y a positive integer
|
|
* @return z, smallest integer such that z % x == 0 and z % y == 0
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) lcm(const BigInt& x, const BigInt& y);
|
|
|
|
/**
|
|
* @param x an integer
|
|
* @return (x*x)
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) square(const BigInt& x);
|
|
|
|
/**
|
|
* Modular inversion. This algorithm is const time with respect to x,
|
|
* as long as x is less than modulus. It also avoids leaking
|
|
* information about the modulus, except that it does leak which of 3
|
|
* categories the modulus is in: an odd integer, a power of 2, or some
|
|
* other even number, and if the modulus is even, leaks the power of 2
|
|
* which divides the modulus.
|
|
*
|
|
* @param x a positive integer
|
|
* @param modulus a positive integer
|
|
* @return y st (x*y) % modulus == 1 or 0 if no such value
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) inverse_mod(const BigInt& x,
|
|
const BigInt& modulus);
|
|
|
|
/**
|
|
* Deprecated modular inversion function. Use inverse_mod instead.
|
|
* @param x a positive integer
|
|
* @param modulus a positive integer
|
|
* @return y st (x*y) % modulus == 1 or 0 if no such value
|
|
*/
|
|
BigInt BOTAN_DEPRECATED_API("Use inverse_mod") inverse_euclid(const BigInt& x, const BigInt& modulus);
|
|
|
|
/**
|
|
* Deprecated modular inversion function. Use inverse_mod instead.
|
|
*/
|
|
BigInt BOTAN_DEPRECATED_API("Use inverse_mod") ct_inverse_mod_odd_modulus(const BigInt& x, const BigInt& modulus);
|
|
|
|
/**
|
|
* Return a^-1 * 2^k mod b
|
|
* Returns k, between n and 2n
|
|
* Not const time
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use inverse_mod")
|
|
almost_montgomery_inverse(BigInt& result,
|
|
const BigInt& a,
|
|
const BigInt& b);
|
|
|
|
/**
|
|
* Call almost_montgomery_inverse and correct the result to a^-1 mod b
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use inverse_mod")
|
|
normalized_montgomery_inverse(const BigInt& a, const BigInt& b);
|
|
|
|
|
|
/**
|
|
* Compute the Jacobi symbol. If n is prime, this is equivalent
|
|
* to the Legendre symbol.
|
|
* @see http://mathworld.wolfram.com/JacobiSymbol.html
|
|
*
|
|
* @param a is a non-negative integer
|
|
* @param n is an odd integer > 1
|
|
* @return (n / m)
|
|
*/
|
|
int32_t BOTAN_PUBLIC_API(2,0) jacobi(const BigInt& a, const BigInt& n);
|
|
|
|
/**
|
|
* Modular exponentation
|
|
* @param b an integer base
|
|
* @param x a positive exponent
|
|
* @param m a positive modulus
|
|
* @return (b^x) % m
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) power_mod(const BigInt& b,
|
|
const BigInt& x,
|
|
const BigInt& m);
|
|
|
|
/**
|
|
* Compute the square root of x modulo a prime using the
|
|
* Tonelli-Shanks algorithm
|
|
*
|
|
* @param x the input
|
|
* @param p the prime
|
|
* @return y such that (y*y)%p == x, or -1 if no such integer
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) ressol(const BigInt& x, const BigInt& p);
|
|
|
|
/*
|
|
* Compute -input^-1 mod 2^MP_WORD_BITS. Throws an exception if input
|
|
* is even. If input is odd, then input and 2^n are relatively prime
|
|
* and an inverse exists.
|
|
*/
|
|
word BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use inverse_mod")
|
|
monty_inverse(word input);
|
|
|
|
/**
|
|
* @param x an integer
|
|
* @return count of the low zero bits in x, or, equivalently, the
|
|
* largest value of n such that 2^n divides x evenly. Returns
|
|
* zero if x is equal to zero.
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,0) low_zero_bits(const BigInt& x);
|
|
|
|
/**
|
|
* Check for primality
|
|
* @param n a positive integer to test for primality
|
|
* @param rng a random number generator
|
|
* @param prob chance of false positive is bounded by 1/2**prob
|
|
* @param is_random true if n was randomly chosen by us
|
|
* @return true if all primality tests passed, otherwise false
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,0) is_prime(const BigInt& n,
|
|
RandomNumberGenerator& rng,
|
|
size_t prob = 64,
|
|
bool is_random = false);
|
|
|
|
/**
|
|
* Test if the positive integer x is a perfect square ie if there
|
|
* exists some positive integer y st y*y == x
|
|
* See FIPS 186-4 sec C.4
|
|
* @return 0 if the integer is not a perfect square, otherwise
|
|
* returns the positive y st y*y == x
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,8) is_perfect_square(const BigInt& x);
|
|
|
|
inline bool BOTAN_DEPRECATED("Use is_prime")
|
|
quick_check_prime(const BigInt& n, RandomNumberGenerator& rng)
|
|
{ return is_prime(n, rng, 32); }
|
|
|
|
inline bool BOTAN_DEPRECATED("Use is_prime")
|
|
check_prime(const BigInt& n, RandomNumberGenerator& rng)
|
|
{ return is_prime(n, rng, 56); }
|
|
|
|
inline bool BOTAN_DEPRECATED("Use is_prime")
|
|
verify_prime(const BigInt& n, RandomNumberGenerator& rng)
|
|
{ return is_prime(n, rng, 80); }
|
|
|
|
/**
|
|
* Randomly generate a prime suitable for discrete logarithm parameters
|
|
* @param rng a random number generator
|
|
* @param bits how large the resulting prime should be in bits
|
|
* @param coprime a positive integer that (prime - 1) should be coprime to
|
|
* @param equiv a non-negative number that the result should be
|
|
equivalent to modulo equiv_mod
|
|
* @param equiv_mod the modulus equiv should be checked against
|
|
* @param prob use test so false positive is bounded by 1/2**prob
|
|
* @return random prime with the specified criteria
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) random_prime(RandomNumberGenerator& rng,
|
|
size_t bits,
|
|
const BigInt& coprime = 0,
|
|
size_t equiv = 1,
|
|
size_t equiv_mod = 2,
|
|
size_t prob = 128);
|
|
|
|
/**
|
|
* Generate a prime suitable for RSA p/q
|
|
* @param keygen_rng a random number generator
|
|
* @param prime_test_rng a random number generator
|
|
* @param bits how large the resulting prime should be in bits (must be >= 512)
|
|
* @param coprime a positive integer that (prime - 1) should be coprime to
|
|
* @param prob use test so false positive is bounded by 1/2**prob
|
|
* @return random prime with the specified criteria
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,7) generate_rsa_prime(RandomNumberGenerator& keygen_rng,
|
|
RandomNumberGenerator& prime_test_rng,
|
|
size_t bits,
|
|
const BigInt& coprime,
|
|
size_t prob = 128);
|
|
|
|
/**
|
|
* Return a 'safe' prime, of the form p=2*q+1 with q prime
|
|
* @param rng a random number generator
|
|
* @param bits is how long the resulting prime should be
|
|
* @return prime randomly chosen from safe primes of length bits
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) random_safe_prime(RandomNumberGenerator& rng,
|
|
size_t bits);
|
|
|
|
/**
|
|
* Generate DSA parameters using the FIPS 186 kosherizer
|
|
* @param rng a random number generator
|
|
* @param p_out where the prime p will be stored
|
|
* @param q_out where the prime q will be stored
|
|
* @param pbits how long p will be in bits
|
|
* @param qbits how long q will be in bits
|
|
* @return random seed used to generate this parameter set
|
|
*/
|
|
std::vector<uint8_t> BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use DL_Group")
|
|
generate_dsa_primes(RandomNumberGenerator& rng,
|
|
BigInt& p_out, BigInt& q_out,
|
|
size_t pbits, size_t qbits);
|
|
|
|
/**
|
|
* Generate DSA parameters using the FIPS 186 kosherizer
|
|
* @param rng a random number generator
|
|
* @param p_out where the prime p will be stored
|
|
* @param q_out where the prime q will be stored
|
|
* @param pbits how long p will be in bits
|
|
* @param qbits how long q will be in bits
|
|
* @param seed the seed used to generate the parameters
|
|
* @param offset optional offset from seed to start searching at
|
|
* @return true if seed generated a valid DSA parameter set, otherwise
|
|
false. p_out and q_out are only valid if true was returned.
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use DL_Group")
|
|
generate_dsa_primes(RandomNumberGenerator& rng,
|
|
BigInt& p_out, BigInt& q_out,
|
|
size_t pbits, size_t qbits,
|
|
const std::vector<uint8_t>& seed,
|
|
size_t offset = 0);
|
|
|
|
/**
|
|
* The size of the PRIMES[] array
|
|
*/
|
|
const size_t PRIME_TABLE_SIZE = 6541;
|
|
|
|
/**
|
|
* A const array of all odd primes less than 65535
|
|
*/
|
|
extern const uint16_t BOTAN_PUBLIC_API(2,0) PRIMES[];
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Modular Reducer (using Barrett's technique)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Modular_Reducer
|
|
{
|
|
public:
|
|
const BigInt& get_modulus() const { return m_modulus; }
|
|
|
|
BigInt reduce(const BigInt& x) const;
|
|
|
|
/**
|
|
* Multiply mod p
|
|
* @param x the first operand
|
|
* @param y the second operand
|
|
* @return (x * y) % p
|
|
*/
|
|
BigInt multiply(const BigInt& x, const BigInt& y) const
|
|
{ return reduce(x * y); }
|
|
|
|
/**
|
|
* Square mod p
|
|
* @param x the value to square
|
|
* @return (x * x) % p
|
|
*/
|
|
BigInt square(const BigInt& x) const
|
|
{ return reduce(Botan::square(x)); }
|
|
|
|
/**
|
|
* Cube mod p
|
|
* @param x the value to cube
|
|
* @return (x * x * x) % p
|
|
*/
|
|
BigInt cube(const BigInt& x) const
|
|
{ return multiply(x, this->square(x)); }
|
|
|
|
/**
|
|
* Low level reduction function. Mostly for internal use.
|
|
* Sometimes useful for performance by reducing temporaries
|
|
* Reduce x mod p and place the output in out. ** X and out must not reference each other **
|
|
* ws is a temporary workspace.
|
|
*/
|
|
void reduce(BigInt& out, const BigInt& x, secure_vector<word>& ws) const;
|
|
|
|
bool initialized() const { return (m_mod_words != 0); }
|
|
|
|
Modular_Reducer() { m_mod_words = 0; }
|
|
explicit Modular_Reducer(const BigInt& mod);
|
|
private:
|
|
BigInt m_modulus, m_mu;
|
|
size_t m_mod_words;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(blinding.h)
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Blinding Function Object.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Blinder final
|
|
{
|
|
public:
|
|
/**
|
|
* Blind a value.
|
|
* The blinding nonce k is freshly generated after
|
|
* BOTAN_BLINDING_REINIT_INTERVAL calls to blind().
|
|
* BOTAN_BLINDING_REINIT_INTERVAL = 0 means a fresh
|
|
* nonce is only generated once. On every other call,
|
|
* an updated nonce is used for blinding: k' = k*k mod n.
|
|
* @param x value to blind
|
|
* @return blinded value
|
|
*/
|
|
BigInt blind(const BigInt& x) const;
|
|
|
|
/**
|
|
* Unblind a value.
|
|
* @param x value to unblind
|
|
* @return unblinded value
|
|
*/
|
|
BigInt unblind(const BigInt& x) const;
|
|
|
|
/**
|
|
* @param modulus the modulus
|
|
* @param rng the RNG to use for generating the nonce
|
|
* @param fwd_func a function that calculates the modular
|
|
* exponentiation of the public exponent and the given value (the nonce)
|
|
* @param inv_func a function that calculates the modular inverse
|
|
* of the given value (the nonce)
|
|
*/
|
|
Blinder(const BigInt& modulus,
|
|
RandomNumberGenerator& rng,
|
|
std::function<BigInt (const BigInt&)> fwd_func,
|
|
std::function<BigInt (const BigInt&)> inv_func);
|
|
|
|
Blinder(const Blinder&) = delete;
|
|
|
|
Blinder& operator=(const Blinder&) = delete;
|
|
|
|
RandomNumberGenerator& rng() const { return m_rng; }
|
|
|
|
private:
|
|
BigInt blinding_nonce() const;
|
|
|
|
Modular_Reducer m_reducer;
|
|
RandomNumberGenerator& m_rng;
|
|
std::function<BigInt (const BigInt&)> m_fwd_fn;
|
|
std::function<BigInt (const BigInt&)> m_inv_fn;
|
|
size_t m_modulus_bits = 0;
|
|
|
|
mutable BigInt m_e, m_d;
|
|
mutable size_t m_counter = 0;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(blowfish.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Blowfish
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Blowfish final : public Block_Cipher_Fixed_Params<8, 1, 56>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
/**
|
|
* Modified EKSBlowfish key schedule, used for bcrypt password hashing
|
|
*/
|
|
void salted_set_key(const uint8_t key[], size_t key_length,
|
|
const uint8_t salt[], size_t salt_length,
|
|
const size_t workfactor, bool salt_first = false);
|
|
|
|
BOTAN_DEPRECATED("Use Blowfish::salted_set_key taking salt length")
|
|
void eks_key_schedule(const uint8_t key[], size_t key_length,
|
|
const uint8_t salt[16], size_t workfactor)
|
|
{
|
|
salted_set_key(key, key_length, salt, 16, workfactor);
|
|
}
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "Blowfish"; }
|
|
BlockCipher* clone() const override { return new Blowfish; }
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
void key_expansion(const uint8_t key[],
|
|
size_t key_length,
|
|
const uint8_t salt[],
|
|
size_t salt_length);
|
|
|
|
void generate_sbox(secure_vector<uint32_t>& box,
|
|
uint32_t& L, uint32_t& R,
|
|
const uint8_t salt[],
|
|
size_t salt_length,
|
|
size_t salt_off) const;
|
|
|
|
secure_vector<uint32_t> m_S, m_P;
|
|
};
|
|
|
|
}
|
|
|
|
#if defined(BOTAN_BUILD_COMPILER_IS_MSVC)
|
|
#include <stdlib.h>
|
|
#endif
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(bswap.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Swap a 16 bit integer
|
|
*/
|
|
inline uint16_t reverse_bytes(uint16_t val)
|
|
{
|
|
#if defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG) || defined(BOTAN_BUILD_COMPILER_IS_XLC)
|
|
return __builtin_bswap16(val);
|
|
#else
|
|
return static_cast<uint16_t>((val << 8) | (val >> 8));
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Swap a 32 bit integer
|
|
*/
|
|
inline uint32_t reverse_bytes(uint32_t val)
|
|
{
|
|
#if defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG) || defined(BOTAN_BUILD_COMPILER_IS_XLC)
|
|
return __builtin_bswap32(val);
|
|
|
|
#elif defined(BOTAN_BUILD_COMPILER_IS_MSVC)
|
|
return _byteswap_ulong(val);
|
|
|
|
#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
|
|
|
|
// GCC-style inline assembly for x86 or x86-64
|
|
asm("bswapl %0" : "=r" (val) : "0" (val));
|
|
return val;
|
|
|
|
#else
|
|
// Generic implementation
|
|
uint16_t hi = static_cast<uint16_t>(val >> 16);
|
|
uint16_t lo = static_cast<uint16_t>(val);
|
|
|
|
hi = reverse_bytes(hi);
|
|
lo = reverse_bytes(lo);
|
|
|
|
return (static_cast<uint32_t>(lo) << 16) | hi;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Swap a 64 bit integer
|
|
*/
|
|
inline uint64_t reverse_bytes(uint64_t val)
|
|
{
|
|
#if defined(BOTAN_BUILD_COMPILER_IS_GCC) || defined(BOTAN_BUILD_COMPILER_IS_CLANG) || defined(BOTAN_BUILD_COMPILER_IS_XLC)
|
|
return __builtin_bswap64(val);
|
|
|
|
#elif defined(BOTAN_BUILD_COMPILER_IS_MSVC)
|
|
return _byteswap_uint64(val);
|
|
|
|
#elif defined(BOTAN_USE_GCC_INLINE_ASM) && defined(BOTAN_TARGET_ARCH_IS_X86_64)
|
|
// GCC-style inline assembly for x86-64
|
|
asm("bswapq %0" : "=r" (val) : "0" (val));
|
|
return val;
|
|
|
|
#else
|
|
/* Generic implementation. Defined in terms of 32-bit bswap so any
|
|
* optimizations in that version can help.
|
|
*/
|
|
|
|
uint32_t hi = static_cast<uint32_t>(val >> 32);
|
|
uint32_t lo = static_cast<uint32_t>(val);
|
|
|
|
hi = reverse_bytes(hi);
|
|
lo = reverse_bytes(lo);
|
|
|
|
return (static_cast<uint64_t>(lo) << 32) | hi;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Swap 4 Ts in an array
|
|
*/
|
|
template<typename T>
|
|
inline void bswap_4(T x[4])
|
|
{
|
|
x[0] = reverse_bytes(x[0]);
|
|
x[1] = reverse_bytes(x[1]);
|
|
x[2] = reverse_bytes(x[2]);
|
|
x[3] = reverse_bytes(x[3]);
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Struct representing a particular date and time
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) calendar_point
|
|
{
|
|
public:
|
|
|
|
/** The year */
|
|
uint32_t get_year() const { return year; }
|
|
|
|
/** The month, 1 through 12 for Jan to Dec */
|
|
uint32_t get_month() const { return month; }
|
|
|
|
/** The day of the month, 1 through 31 (or 28 or 30 based on month */
|
|
uint32_t get_day() const { return day; }
|
|
|
|
/** Hour in 24-hour form, 0 to 23 */
|
|
uint32_t get_hour() const { return hour; }
|
|
|
|
/** Minutes in the hour, 0 to 60 */
|
|
uint32_t get_minutes() const { return minutes; }
|
|
|
|
/** Seconds in the minute, 0 to 60, but might be slightly
|
|
larger to deal with leap seconds on some systems
|
|
*/
|
|
uint32_t get_seconds() const { return seconds; }
|
|
|
|
/**
|
|
* Initialize a calendar_point
|
|
* @param y the year
|
|
* @param mon the month
|
|
* @param d the day
|
|
* @param h the hour
|
|
* @param min the minute
|
|
* @param sec the second
|
|
*/
|
|
calendar_point(uint32_t y, uint32_t mon, uint32_t d, uint32_t h, uint32_t min, uint32_t sec) :
|
|
year(y), month(mon), day(d), hour(h), minutes(min), seconds(sec) {}
|
|
|
|
/**
|
|
* Returns an STL timepoint object
|
|
*/
|
|
std::chrono::system_clock::time_point to_std_timepoint() const;
|
|
|
|
/**
|
|
* Returns a human readable string of the struct's components.
|
|
* Formatting might change over time. Currently it is RFC339 'iso-date-time'.
|
|
*/
|
|
std::string to_string() const;
|
|
|
|
BOTAN_DEPRECATED_PUBLIC_MEMBER_VARIABLES:
|
|
/*
|
|
The member variables are public for historical reasons. Use the get_xxx() functions
|
|
defined above. These members will be made private in a future major release.
|
|
*/
|
|
uint32_t year;
|
|
uint32_t month;
|
|
uint32_t day;
|
|
uint32_t hour;
|
|
uint32_t minutes;
|
|
uint32_t seconds;
|
|
};
|
|
|
|
/**
|
|
* Convert a time_point to a calendar_point
|
|
* @param time_point a time point from the system clock
|
|
* @return calendar_point object representing this time point
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) calendar_point calendar_value(
|
|
const std::chrono::system_clock::time_point& time_point);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(camellia.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Camellia-128
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Camellia_128 final : public Block_Cipher_Fixed_Params<16, 16>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "Camellia-128"; }
|
|
BlockCipher* clone() const override { return new Camellia_128; }
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
secure_vector<uint64_t> m_SK;
|
|
};
|
|
|
|
/**
|
|
* Camellia-192
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Camellia_192 final : public Block_Cipher_Fixed_Params<16, 24>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "Camellia-192"; }
|
|
BlockCipher* clone() const override { return new Camellia_192; }
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
secure_vector<uint64_t> m_SK;
|
|
};
|
|
|
|
/**
|
|
* Camellia-256
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Camellia_256 final : public Block_Cipher_Fixed_Params<16, 32>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "Camellia-256"; }
|
|
BlockCipher* clone() const override { return new Camellia_256; }
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
secure_vector<uint64_t> m_SK;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(cascade.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Block Cipher Cascade
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Cascade_Cipher final : public BlockCipher
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
size_t block_size() const override { return m_block; }
|
|
|
|
Key_Length_Specification key_spec() const override
|
|
{
|
|
return Key_Length_Specification(m_cipher1->maximum_keylength() +
|
|
m_cipher2->maximum_keylength());
|
|
}
|
|
|
|
void clear() override;
|
|
std::string name() const override;
|
|
BlockCipher* clone() const override;
|
|
|
|
/**
|
|
* Create a cascade of two block ciphers
|
|
* @param cipher1 the first cipher
|
|
* @param cipher2 the second cipher
|
|
*/
|
|
Cascade_Cipher(BlockCipher* cipher1, BlockCipher* cipher2);
|
|
|
|
Cascade_Cipher(const Cascade_Cipher&) = delete;
|
|
Cascade_Cipher& operator=(const Cascade_Cipher&) = delete;
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
size_t m_block;
|
|
std::unique_ptr<BlockCipher> m_cipher1, m_cipher2;
|
|
};
|
|
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(cast128.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* CAST-128
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CAST_128 final : public Block_Cipher_Fixed_Params<8, 11, 16>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "CAST-128"; }
|
|
BlockCipher* clone() const override { return new CAST_128; }
|
|
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
static void cast_ks(secure_vector<uint32_t>& ks,
|
|
secure_vector<uint32_t>& user_key);
|
|
|
|
secure_vector<uint32_t> m_MK;
|
|
secure_vector<uint8_t> m_RK;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(cast256.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* CAST-256
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CAST_256 final : public Block_Cipher_Fixed_Params<16, 4, 32, 4>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "CAST-256"; }
|
|
BlockCipher* clone() const override { return new CAST_256; }
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
secure_vector<uint32_t> m_MK;
|
|
secure_vector<uint8_t> m_RK;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(mode_pad.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Block Cipher Mode Padding Method
|
|
* This class is pretty limited, it cannot deal well with
|
|
* randomized padding methods, or any padding method that
|
|
* wants to add more than one block. For instance, it should
|
|
* be possible to define cipher text stealing mode as simply
|
|
* a padding mode for CBC, which happens to consume the last
|
|
* two block (and requires use of the block cipher).
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) BlockCipherModePaddingMethod
|
|
{
|
|
public:
|
|
/**
|
|
* Add padding bytes to buffer.
|
|
* @param buffer data to pad
|
|
* @param final_block_bytes size of the final block in bytes
|
|
* @param block_size size of each block in bytes
|
|
*/
|
|
virtual void add_padding(secure_vector<uint8_t>& buffer,
|
|
size_t final_block_bytes,
|
|
size_t block_size) const = 0;
|
|
|
|
/**
|
|
* Remove padding bytes from block
|
|
* @param block the last block
|
|
* @param len the size of the block in bytes
|
|
* @return number of data bytes, or if the padding is invalid returns len
|
|
*/
|
|
virtual size_t unpad(const uint8_t block[], size_t len) const = 0;
|
|
|
|
/**
|
|
* @param block_size of the cipher
|
|
* @return valid block size for this padding mode
|
|
*/
|
|
virtual bool valid_blocksize(size_t block_size) const = 0;
|
|
|
|
/**
|
|
* @return name of the mode
|
|
*/
|
|
virtual std::string name() const = 0;
|
|
|
|
/**
|
|
* virtual destructor
|
|
*/
|
|
virtual ~BlockCipherModePaddingMethod() = default;
|
|
};
|
|
|
|
/**
|
|
* PKCS#7 Padding
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PKCS7_Padding final : public BlockCipherModePaddingMethod
|
|
{
|
|
public:
|
|
void add_padding(secure_vector<uint8_t>& buffer,
|
|
size_t final_block_bytes,
|
|
size_t block_size) const override;
|
|
|
|
size_t unpad(const uint8_t[], size_t) const override;
|
|
|
|
bool valid_blocksize(size_t bs) const override { return (bs > 2 && bs < 256); }
|
|
|
|
std::string name() const override { return "PKCS7"; }
|
|
};
|
|
|
|
/**
|
|
* ANSI X9.23 Padding
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ANSI_X923_Padding final : public BlockCipherModePaddingMethod
|
|
{
|
|
public:
|
|
void add_padding(secure_vector<uint8_t>& buffer,
|
|
size_t final_block_bytes,
|
|
size_t block_size) const override;
|
|
|
|
size_t unpad(const uint8_t[], size_t) const override;
|
|
|
|
bool valid_blocksize(size_t bs) const override { return (bs > 2 && bs < 256); }
|
|
|
|
std::string name() const override { return "X9.23"; }
|
|
};
|
|
|
|
/**
|
|
* One And Zeros Padding (ISO/IEC 9797-1, padding method 2)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) OneAndZeros_Padding final : public BlockCipherModePaddingMethod
|
|
{
|
|
public:
|
|
void add_padding(secure_vector<uint8_t>& buffer,
|
|
size_t final_block_bytes,
|
|
size_t block_size) const override;
|
|
|
|
size_t unpad(const uint8_t[], size_t) const override;
|
|
|
|
bool valid_blocksize(size_t bs) const override { return (bs > 2); }
|
|
|
|
std::string name() const override { return "OneAndZeros"; }
|
|
};
|
|
|
|
/**
|
|
* ESP Padding (RFC 4304)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ESP_Padding final : public BlockCipherModePaddingMethod
|
|
{
|
|
public:
|
|
void add_padding(secure_vector<uint8_t>& buffer,
|
|
size_t final_block_bytes,
|
|
size_t block_size) const override;
|
|
|
|
size_t unpad(const uint8_t[], size_t) const override;
|
|
|
|
bool valid_blocksize(size_t bs) const override { return (bs > 2 && bs < 256); }
|
|
|
|
std::string name() const override { return "ESP"; }
|
|
};
|
|
|
|
/**
|
|
* Null Padding
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Null_Padding final : public BlockCipherModePaddingMethod
|
|
{
|
|
public:
|
|
void add_padding(secure_vector<uint8_t>&, size_t, size_t) const override
|
|
{
|
|
/* no padding */
|
|
}
|
|
|
|
size_t unpad(const uint8_t[], size_t size) const override { return size; }
|
|
|
|
bool valid_blocksize(size_t) const override { return true; }
|
|
|
|
std::string name() const override { return "NoPadding"; }
|
|
};
|
|
|
|
/**
|
|
* Get a block cipher padding mode by name (eg "NoPadding" or "PKCS7")
|
|
* @param algo_spec block cipher padding mode name
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) BlockCipherModePaddingMethod* get_bc_pad(const std::string& algo_spec);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(cbc.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* CBC Mode
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CBC_Mode : public Cipher_Mode
|
|
{
|
|
public:
|
|
std::string name() const override;
|
|
|
|
size_t update_granularity() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
size_t default_nonce_length() const override;
|
|
|
|
bool valid_nonce_length(size_t n) const override;
|
|
|
|
void clear() override;
|
|
|
|
void reset() override;
|
|
|
|
protected:
|
|
CBC_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding);
|
|
|
|
const BlockCipher& cipher() const { return *m_cipher; }
|
|
|
|
const BlockCipherModePaddingMethod& padding() const
|
|
{
|
|
BOTAN_ASSERT_NONNULL(m_padding);
|
|
return *m_padding;
|
|
}
|
|
|
|
size_t block_size() const { return m_block_size; }
|
|
|
|
secure_vector<uint8_t>& state() { return m_state; }
|
|
|
|
uint8_t* state_ptr() { return m_state.data(); }
|
|
|
|
private:
|
|
void start_msg(const uint8_t nonce[], size_t nonce_len) override;
|
|
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
std::unique_ptr<BlockCipherModePaddingMethod> m_padding;
|
|
secure_vector<uint8_t> m_state;
|
|
size_t m_block_size;
|
|
};
|
|
|
|
/**
|
|
* CBC Encryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CBC_Encryption : public CBC_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher block cipher to use
|
|
* @param padding padding method to use
|
|
*/
|
|
CBC_Encryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) :
|
|
CBC_Mode(cipher, padding) {}
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
|
|
size_t output_length(size_t input_length) const override;
|
|
|
|
size_t minimum_final_size() const override;
|
|
};
|
|
|
|
/**
|
|
* CBC Encryption with ciphertext stealing (CBC-CS3 variant)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CTS_Encryption final : public CBC_Encryption
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher block cipher to use
|
|
*/
|
|
explicit CTS_Encryption(BlockCipher* cipher) : CBC_Encryption(cipher, nullptr) {}
|
|
|
|
size_t output_length(size_t input_length) const override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
|
|
size_t minimum_final_size() const override;
|
|
|
|
bool valid_nonce_length(size_t n) const override;
|
|
};
|
|
|
|
/**
|
|
* CBC Decryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CBC_Decryption : public CBC_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher block cipher to use
|
|
* @param padding padding method to use
|
|
*/
|
|
CBC_Decryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) :
|
|
CBC_Mode(cipher, padding), m_tempbuf(update_granularity()) {}
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
|
|
size_t output_length(size_t input_length) const override;
|
|
|
|
size_t minimum_final_size() const override;
|
|
|
|
void reset() override;
|
|
|
|
private:
|
|
secure_vector<uint8_t> m_tempbuf;
|
|
};
|
|
|
|
/**
|
|
* CBC Decryption with ciphertext stealing (CBC-CS3 variant)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CTS_Decryption final : public CBC_Decryption
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher block cipher to use
|
|
*/
|
|
explicit CTS_Decryption(BlockCipher* cipher) : CBC_Decryption(cipher, nullptr) {}
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
|
|
size_t minimum_final_size() const override;
|
|
|
|
bool valid_nonce_length(size_t n) const override;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents Message Authentication Code (MAC) objects.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) MessageAuthenticationCode : public Buffered_Computation,
|
|
public SymmetricAlgorithm
|
|
{
|
|
public:
|
|
/**
|
|
* Create an instance based on a name
|
|
* If provider is empty then best available is chosen.
|
|
* @param algo_spec algorithm name
|
|
* @param provider provider implementation to use
|
|
* @return a null pointer if the algo/provider combination cannot be found
|
|
*/
|
|
static std::unique_ptr<MessageAuthenticationCode>
|
|
create(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/*
|
|
* Create an instance based on a name
|
|
* If provider is empty then best available is chosen.
|
|
* @param algo_spec algorithm name
|
|
* @param provider provider implementation to use
|
|
* Throws a Lookup_Error if algo/provider combination cannot be found
|
|
*/
|
|
static std::unique_ptr<MessageAuthenticationCode>
|
|
create_or_throw(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* @return list of available providers for this algorithm, empty if not available
|
|
*/
|
|
static std::vector<std::string> providers(const std::string& algo_spec);
|
|
|
|
virtual ~MessageAuthenticationCode() = default;
|
|
|
|
/**
|
|
* Prepare for processing a message under the specified nonce
|
|
*
|
|
* Most MACs neither require nor support a nonce; for these algorithms
|
|
* calling `start_msg` is optional and calling it with anything other than
|
|
* an empty string is an error. One MAC which *requires* a per-message
|
|
* nonce be specified is GMAC.
|
|
*
|
|
* @param nonce the message nonce bytes
|
|
* @param nonce_len the size of len in bytes
|
|
* Default implementation simply rejects all non-empty nonces
|
|
* since most hash/MAC algorithms do not support randomization
|
|
*/
|
|
virtual void start_msg(const uint8_t nonce[], size_t nonce_len);
|
|
|
|
/**
|
|
* Begin processing a message with a nonce
|
|
*
|
|
* @param nonce the per message nonce
|
|
*/
|
|
template<typename Alloc>
|
|
void start(const std::vector<uint8_t, Alloc>& nonce)
|
|
{
|
|
start_msg(nonce.data(), nonce.size());
|
|
}
|
|
|
|
/**
|
|
* Begin processing a message.
|
|
* @param nonce the per message nonce
|
|
* @param nonce_len length of nonce
|
|
*/
|
|
void start(const uint8_t nonce[], size_t nonce_len)
|
|
{
|
|
start_msg(nonce, nonce_len);
|
|
}
|
|
|
|
/**
|
|
* Begin processing a message.
|
|
*/
|
|
void start()
|
|
{
|
|
return start_msg(nullptr, 0);
|
|
}
|
|
|
|
/**
|
|
* Verify a MAC.
|
|
* @param in the MAC to verify as a byte array
|
|
* @param length the length of param in
|
|
* @return true if the MAC is valid, false otherwise
|
|
*/
|
|
virtual bool verify_mac(const uint8_t in[], size_t length);
|
|
|
|
/**
|
|
* Verify a MAC.
|
|
* @param in the MAC to verify as a byte array
|
|
* @return true if the MAC is valid, false otherwise
|
|
*/
|
|
virtual bool verify_mac(const std::vector<uint8_t>& in)
|
|
{
|
|
return verify_mac(in.data(), in.size());
|
|
}
|
|
|
|
/**
|
|
* Verify a MAC.
|
|
* @param in the MAC to verify as a byte array
|
|
* @return true if the MAC is valid, false otherwise
|
|
*/
|
|
virtual bool verify_mac(const secure_vector<uint8_t>& in)
|
|
{
|
|
return verify_mac(in.data(), in.size());
|
|
}
|
|
|
|
/**
|
|
* Get a new object representing the same algorithm as *this
|
|
*/
|
|
virtual MessageAuthenticationCode* clone() const = 0;
|
|
|
|
/**
|
|
* @return provider information about this implementation. Default is "base",
|
|
* might also return "sse2", "avx2", "openssl", or some other arbitrary string.
|
|
*/
|
|
virtual std::string provider() const { return "base"; }
|
|
|
|
};
|
|
|
|
typedef MessageAuthenticationCode MAC;
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(cbc_mac.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* CBC-MAC
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CBC_MAC final : public MessageAuthenticationCode
|
|
{
|
|
public:
|
|
std::string name() const override;
|
|
MessageAuthenticationCode* clone() const override;
|
|
size_t output_length() const override { return m_cipher->block_size(); }
|
|
void clear() override;
|
|
|
|
Key_Length_Specification key_spec() const override
|
|
{
|
|
return m_cipher->key_spec();
|
|
}
|
|
|
|
/**
|
|
* @param cipher the block cipher to use
|
|
*/
|
|
explicit CBC_MAC(BlockCipher* cipher);
|
|
private:
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
secure_vector<uint8_t> m_state;
|
|
size_t m_position = 0;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(ccm.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Base class for CCM encryption and decryption
|
|
* @see RFC 3610
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CCM_Mode : public AEAD_Mode
|
|
{
|
|
public:
|
|
size_t process(uint8_t buf[], size_t sz) override;
|
|
|
|
void set_associated_data(const uint8_t ad[], size_t ad_len) override;
|
|
|
|
bool associated_data_requires_key() const override { return false; }
|
|
|
|
std::string name() const override;
|
|
|
|
size_t update_granularity() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
bool valid_nonce_length(size_t) const override;
|
|
|
|
size_t default_nonce_length() const override;
|
|
|
|
void clear() override;
|
|
|
|
void reset() override;
|
|
|
|
size_t tag_size() const override { return m_tag_size; }
|
|
|
|
protected:
|
|
CCM_Mode(BlockCipher* cipher, size_t tag_size, size_t L);
|
|
|
|
size_t L() const { return m_L; }
|
|
|
|
const BlockCipher& cipher() const { return *m_cipher; }
|
|
|
|
void encode_length(uint64_t len, uint8_t out[]);
|
|
|
|
void inc(secure_vector<uint8_t>& C);
|
|
|
|
const secure_vector<uint8_t>& ad_buf() const { return m_ad_buf; }
|
|
|
|
secure_vector<uint8_t>& msg_buf() { return m_msg_buf; }
|
|
|
|
secure_vector<uint8_t> format_b0(size_t msg_size);
|
|
secure_vector<uint8_t> format_c0();
|
|
private:
|
|
void start_msg(const uint8_t nonce[], size_t nonce_len) override;
|
|
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
const size_t m_tag_size;
|
|
const size_t m_L;
|
|
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
secure_vector<uint8_t> m_nonce, m_msg_buf, m_ad_buf;
|
|
};
|
|
|
|
/**
|
|
* CCM Encryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CCM_Encryption final : public CCM_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher a 128-bit block cipher
|
|
* @param tag_size is how big the auth tag will be (even values
|
|
* between 4 and 16 are accepted)
|
|
* @param L length of L parameter. The total message length
|
|
* must be less than 2**L bytes, and the nonce is 15-L bytes.
|
|
*/
|
|
CCM_Encryption(BlockCipher* cipher, size_t tag_size = 16, size_t L = 3) :
|
|
CCM_Mode(cipher, tag_size, L) {}
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
|
|
size_t output_length(size_t input_length) const override
|
|
{ return input_length + tag_size(); }
|
|
|
|
size_t minimum_final_size() const override { return 0; }
|
|
};
|
|
|
|
/**
|
|
* CCM Decryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CCM_Decryption final : public CCM_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher a 128-bit block cipher
|
|
* @param tag_size is how big the auth tag will be (even values
|
|
* between 4 and 16 are accepted)
|
|
* @param L length of L parameter. The total message length
|
|
* must be less than 2**L bytes, and the nonce is 15-L bytes.
|
|
*/
|
|
CCM_Decryption(BlockCipher* cipher, size_t tag_size = 16, size_t L = 3) :
|
|
CCM_Mode(cipher, tag_size, L) {}
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
|
|
size_t output_length(size_t input_length) const override
|
|
{
|
|
BOTAN_ASSERT(input_length >= tag_size(), "Sufficient input");
|
|
return input_length - tag_size();
|
|
}
|
|
|
|
size_t minimum_final_size() const override { return tag_size(); }
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/*
|
|
* WARNING: This API is preliminary and will change
|
|
* Currently pubkey.h does not support a 2-phase KEM scheme of
|
|
* the sort NEWHOPE exports.
|
|
*/
|
|
|
|
// TODO: change to just a secure_vector
|
|
class BOTAN_UNSTABLE_API newhope_poly final
|
|
{
|
|
public:
|
|
uint16_t coeffs[1024];
|
|
~newhope_poly();
|
|
};
|
|
|
|
enum Newhope_Params
|
|
{
|
|
NEWHOPE_SENDABYTES = 1824,
|
|
NEWHOPE_SENDBBYTES = 2048,
|
|
|
|
NEWHOPE_OFFER_BYTES = 1824,
|
|
NEWHOPE_ACCEPT_BYTES = 2048,
|
|
NEWHOPE_SHARED_KEY_BYTES = 32,
|
|
|
|
NEWHOPE_SEED_BYTES = 32,
|
|
NEWHOPE_POLY_BYTES = 1792,
|
|
|
|
CECPQ1_OFFER_BYTES = NEWHOPE_OFFER_BYTES + 32,
|
|
CECPQ1_ACCEPT_BYTES = NEWHOPE_ACCEPT_BYTES + 32,
|
|
CECPQ1_SHARED_KEY_BYTES = NEWHOPE_SHARED_KEY_BYTES + 32
|
|
};
|
|
|
|
/**
|
|
* This chooses the XOF + hash for NewHope
|
|
* The official NewHope specification and reference implementation use
|
|
* SHA-3 and SHAKE-128. BoringSSL instead uses SHA-256 and AES-128 in
|
|
* CTR mode. CECPQ1 (x25519+NewHope) always uses BoringSSL's mode
|
|
*/
|
|
enum class Newhope_Mode
|
|
{
|
|
SHA3,
|
|
BoringSSL
|
|
};
|
|
|
|
// offer
|
|
void BOTAN_PUBLIC_API(2,0) newhope_keygen(uint8_t send[NEWHOPE_SENDABYTES],
|
|
newhope_poly* sk,
|
|
RandomNumberGenerator& rng,
|
|
Newhope_Mode = Newhope_Mode::SHA3);
|
|
|
|
// accept
|
|
void BOTAN_PUBLIC_API(2,0) newhope_sharedb(uint8_t sharedkey[NEWHOPE_SHARED_KEY_BYTES],
|
|
uint8_t send[],
|
|
const uint8_t* received,
|
|
RandomNumberGenerator& rng,
|
|
Newhope_Mode mode = Newhope_Mode::SHA3);
|
|
|
|
// finish
|
|
void BOTAN_PUBLIC_API(2,0) newhope_shareda(uint8_t sharedkey[NEWHOPE_SHARED_KEY_BYTES],
|
|
const newhope_poly* ska,
|
|
const uint8_t* received,
|
|
Newhope_Mode mode = Newhope_Mode::SHA3);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class CECPQ1_key final
|
|
{
|
|
public:
|
|
secure_vector<uint8_t> m_x25519;
|
|
newhope_poly m_newhope;
|
|
};
|
|
|
|
void BOTAN_PUBLIC_API(2,0) CECPQ1_offer(uint8_t* offer_message,
|
|
CECPQ1_key* offer_key_output,
|
|
RandomNumberGenerator& rng);
|
|
|
|
void BOTAN_PUBLIC_API(2,0) CECPQ1_accept(uint8_t* shared_key,
|
|
uint8_t* accept_message,
|
|
const uint8_t* offer_message,
|
|
RandomNumberGenerator& rng);
|
|
|
|
void BOTAN_PUBLIC_API(2,0) CECPQ1_finish(uint8_t* shared_key,
|
|
const CECPQ1_key& offer_key,
|
|
const uint8_t* accept_message);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Certificate validation status code
|
|
*/
|
|
enum class Certificate_Status_Code {
|
|
OK = 0,
|
|
VERIFIED = 0,
|
|
|
|
// Revocation status
|
|
OCSP_RESPONSE_GOOD = 1,
|
|
OCSP_SIGNATURE_OK = 2,
|
|
VALID_CRL_CHECKED = 3,
|
|
OCSP_NO_HTTP = 4,
|
|
|
|
// Warnings
|
|
FIRST_WARNING_STATUS = 500,
|
|
CERT_SERIAL_NEGATIVE = 500,
|
|
DN_TOO_LONG = 501,
|
|
OCSP_NO_REVOCATION_URL = 502,
|
|
OCSP_SERVER_NOT_AVAILABLE = 503,
|
|
|
|
// Typo versions of above - will be removed in future major release
|
|
OSCP_NO_REVOCATION_URL = 502,
|
|
OSCP_SERVER_NOT_AVAILABLE = 503,
|
|
|
|
// Errors
|
|
FIRST_ERROR_STATUS = 1000,
|
|
|
|
SIGNATURE_METHOD_TOO_WEAK = 1000,
|
|
UNTRUSTED_HASH = 1001,
|
|
NO_REVOCATION_DATA = 1002,
|
|
NO_MATCHING_CRLDP = 1003,
|
|
|
|
// Time problems
|
|
CERT_NOT_YET_VALID = 2000,
|
|
CERT_HAS_EXPIRED = 2001,
|
|
OCSP_NOT_YET_VALID = 2002,
|
|
OCSP_HAS_EXPIRED = 2003,
|
|
CRL_NOT_YET_VALID = 2004,
|
|
CRL_HAS_EXPIRED = 2005,
|
|
OCSP_IS_TOO_OLD = 2006,
|
|
|
|
// Chain generation problems
|
|
CERT_ISSUER_NOT_FOUND = 3000,
|
|
CANNOT_ESTABLISH_TRUST = 3001,
|
|
CERT_CHAIN_LOOP = 3002,
|
|
CHAIN_LACKS_TRUST_ROOT = 3003,
|
|
CHAIN_NAME_MISMATCH = 3004,
|
|
|
|
// Validation errors
|
|
POLICY_ERROR = 4000,
|
|
INVALID_USAGE = 4001,
|
|
CERT_CHAIN_TOO_LONG = 4002,
|
|
CA_CERT_NOT_FOR_CERT_ISSUER = 4003,
|
|
NAME_CONSTRAINT_ERROR = 4004,
|
|
|
|
// Revocation errors
|
|
CA_CERT_NOT_FOR_CRL_ISSUER = 4005,
|
|
OCSP_CERT_NOT_LISTED = 4006,
|
|
OCSP_BAD_STATUS = 4007,
|
|
|
|
// Other problems
|
|
CERT_NAME_NOMATCH = 4008,
|
|
UNKNOWN_CRITICAL_EXTENSION = 4009,
|
|
DUPLICATE_CERT_EXTENSION = 4010,
|
|
OCSP_SIGNATURE_ERROR = 4501,
|
|
OCSP_ISSUER_NOT_FOUND = 4502,
|
|
OCSP_RESPONSE_MISSING_KEYUSAGE = 4503,
|
|
OCSP_RESPONSE_INVALID = 4504,
|
|
EXT_IN_V1_V2_CERT = 4505,
|
|
DUPLICATE_CERT_POLICY = 4506,
|
|
V2_IDENTIFIERS_IN_V1_CERT = 4507,
|
|
|
|
// Hard failures
|
|
CERT_IS_REVOKED = 5000,
|
|
CRL_BAD_SIGNATURE = 5001,
|
|
SIGNATURE_ERROR = 5002,
|
|
CERT_PUBKEY_INVALID = 5003,
|
|
SIGNATURE_ALGO_UNKNOWN = 5004,
|
|
SIGNATURE_ALGO_BAD_PARAMS = 5005
|
|
};
|
|
|
|
/**
|
|
* Convert a status code to a human readable diagnostic message
|
|
* @param code the certifcate status
|
|
* @return string literal constant, or nullptr if code unknown
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) const char* to_string(Certificate_Status_Code code);
|
|
|
|
/**
|
|
* X.509v3 Key Constraints.
|
|
* If updating update copy in ffi.h
|
|
*/
|
|
enum Key_Constraints {
|
|
NO_CONSTRAINTS = 0,
|
|
DIGITAL_SIGNATURE = 1 << 15,
|
|
NON_REPUDIATION = 1 << 14,
|
|
KEY_ENCIPHERMENT = 1 << 13,
|
|
DATA_ENCIPHERMENT = 1 << 12,
|
|
KEY_AGREEMENT = 1 << 11,
|
|
KEY_CERT_SIGN = 1 << 10,
|
|
CRL_SIGN = 1 << 9,
|
|
ENCIPHER_ONLY = 1 << 8,
|
|
DECIPHER_ONLY = 1 << 7
|
|
};
|
|
|
|
/**
|
|
* X.509v2 CRL Reason Code.
|
|
* This will become an enum class in a future major release
|
|
*/
|
|
enum CRL_Code : uint32_t {
|
|
UNSPECIFIED = 0,
|
|
KEY_COMPROMISE = 1,
|
|
CA_COMPROMISE = 2,
|
|
AFFILIATION_CHANGED = 3,
|
|
SUPERSEDED = 4,
|
|
CESSATION_OF_OPERATION = 5,
|
|
CERTIFICATE_HOLD = 6,
|
|
REMOVE_FROM_CRL = 8,
|
|
PRIVLEDGE_WITHDRAWN = 9,
|
|
PRIVILEGE_WITHDRAWN = 9,
|
|
AA_COMPROMISE = 10,
|
|
|
|
DELETE_CRL_ENTRY = 0xFF00,
|
|
OCSP_GOOD = 0xFF01,
|
|
OCSP_UNKNOWN = 0xFF02
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Public_Key;
|
|
class Private_Key;
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* This class represents abstract X.509 signed objects as in the X.500
|
|
* SIGNED macro
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) X509_Object : public ASN1_Object
|
|
{
|
|
public:
|
|
/**
|
|
* The underlying data that is to be or was signed
|
|
* @return data that is or was signed
|
|
*/
|
|
std::vector<uint8_t> tbs_data() const;
|
|
|
|
/**
|
|
* @return signature on tbs_data()
|
|
*/
|
|
const std::vector<uint8_t>& signature() const { return m_sig; }
|
|
|
|
/**
|
|
* @return signed body
|
|
*/
|
|
const std::vector<uint8_t>& signed_body() const { return m_tbs_bits; }
|
|
|
|
/**
|
|
* @return signature algorithm that was used to generate signature
|
|
*/
|
|
const AlgorithmIdentifier& signature_algorithm() const { return m_sig_algo; }
|
|
|
|
/**
|
|
* @return hash algorithm that was used to generate signature
|
|
*/
|
|
std::string hash_used_for_signature() const;
|
|
|
|
/**
|
|
* Create a signed X509 object.
|
|
* @param signer the signer used to sign the object
|
|
* @param rng the random number generator to use
|
|
* @param alg_id the algorithm identifier of the signature scheme
|
|
* @param tbs the tbs bits to be signed
|
|
* @return signed X509 object
|
|
*/
|
|
static std::vector<uint8_t> make_signed(class PK_Signer* signer,
|
|
RandomNumberGenerator& rng,
|
|
const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& tbs);
|
|
|
|
/**
|
|
* Check the signature on this data
|
|
* @param key the public key purportedly used to sign this data
|
|
* @return status of the signature - OK if verified or otherwise an indicator of
|
|
* the problem preventing verification.
|
|
*/
|
|
Certificate_Status_Code verify_signature(const Public_Key& key) const;
|
|
|
|
/**
|
|
* Check the signature on this data
|
|
* @param key the public key purportedly used to sign this data
|
|
* @return true if the signature is valid, otherwise false
|
|
*/
|
|
bool check_signature(const Public_Key& key) const;
|
|
|
|
/**
|
|
* Check the signature on this data
|
|
* @param key the public key purportedly used to sign this data
|
|
* the object will be deleted after use (this should have
|
|
* been a std::unique_ptr<Public_Key>)
|
|
* @return true if the signature is valid, otherwise false
|
|
*/
|
|
bool check_signature(const Public_Key* key) const;
|
|
|
|
/**
|
|
* DER encode an X509_Object
|
|
* See @ref ASN1_Object::encode_into()
|
|
*/
|
|
void encode_into(class DER_Encoder& to) const override;
|
|
|
|
/**
|
|
* Decode a BER encoded X509_Object
|
|
* See @ref ASN1_Object::decode_from()
|
|
*/
|
|
void decode_from(class BER_Decoder& from) override;
|
|
|
|
/**
|
|
* @return PEM encoding of this
|
|
*/
|
|
std::string PEM_encode() const;
|
|
|
|
X509_Object(const X509_Object&) = default;
|
|
X509_Object& operator=(const X509_Object&) = default;
|
|
|
|
virtual std::string PEM_label() const = 0;
|
|
|
|
virtual std::vector<std::string> alternate_PEM_labels() const
|
|
{ return std::vector<std::string>(); }
|
|
|
|
virtual ~X509_Object() = default;
|
|
|
|
static std::unique_ptr<PK_Signer>
|
|
choose_sig_format(AlgorithmIdentifier& sig_algo,
|
|
const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& hash_fn,
|
|
const std::string& padding_algo);
|
|
|
|
protected:
|
|
|
|
X509_Object() = default;
|
|
|
|
/**
|
|
* Decodes from src as either DER or PEM data, then calls force_decode()
|
|
*/
|
|
void load_data(DataSource& src);
|
|
|
|
private:
|
|
virtual void force_decode() = 0;
|
|
|
|
AlgorithmIdentifier m_sig_algo;
|
|
std::vector<uint8_t> m_tbs_bits;
|
|
std::vector<uint8_t> m_sig;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Public_Key;
|
|
class X509_DN;
|
|
class Extensions;
|
|
class AlternativeName;
|
|
class NameConstraints;
|
|
|
|
enum class Usage_Type
|
|
{
|
|
UNSPECIFIED, // no restrictions
|
|
TLS_SERVER_AUTH,
|
|
TLS_CLIENT_AUTH,
|
|
CERTIFICATE_AUTHORITY,
|
|
OCSP_RESPONDER,
|
|
ENCRYPTION
|
|
};
|
|
|
|
struct X509_Certificate_Data;
|
|
|
|
/**
|
|
* This class represents an X.509 Certificate
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) X509_Certificate : public X509_Object
|
|
{
|
|
public:
|
|
/**
|
|
* Return a newly allocated copy of the public key associated
|
|
* with the subject of this certificate. This object is owned
|
|
* by the caller.
|
|
*
|
|
* Prefer load_subject_public_key in new code
|
|
*
|
|
* @return public key
|
|
*/
|
|
Public_Key* subject_public_key() const;
|
|
|
|
/**
|
|
* Create a public key object associated with the public key bits in this
|
|
* certificate. If the public key bits was valid for X.509 encoding
|
|
* purposes but invalid algorithmically (for example, RSA with an even
|
|
* modulus) that will be detected at this point, and an exception will be
|
|
* thrown.
|
|
*
|
|
* @return subject public key of this certificate
|
|
*/
|
|
std::unique_ptr<Public_Key> load_subject_public_key() const;
|
|
|
|
/**
|
|
* Get the public key associated with this certificate. This includes the
|
|
* outer AlgorithmIdentifier
|
|
* @return subject public key of this certificate
|
|
*/
|
|
const std::vector<uint8_t>& subject_public_key_bits() const;
|
|
|
|
/**
|
|
* Get the SubjectPublicKeyInfo associated with this certificate.
|
|
* @return subject public key info of this certificate
|
|
*/
|
|
const std::vector<uint8_t>& subject_public_key_info() const;
|
|
|
|
/**
|
|
* Return the algorithm identifier of the public key
|
|
*/
|
|
const AlgorithmIdentifier& subject_public_key_algo() const;
|
|
|
|
/**
|
|
* Get the bit string of the public key associated with this certificate
|
|
* @return public key bits
|
|
*/
|
|
const std::vector<uint8_t>& subject_public_key_bitstring() const;
|
|
|
|
/**
|
|
* Get the SHA-1 bit string of the public key associated with this certificate.
|
|
* This is used for OCSP among other protocols.
|
|
* This function will throw if SHA-1 is not available.
|
|
* @return hash of subject public key of this certificate
|
|
*/
|
|
const std::vector<uint8_t>& subject_public_key_bitstring_sha1() const;
|
|
|
|
/**
|
|
* Get the certificate's issuer distinguished name (DN).
|
|
* @return issuer DN of this certificate
|
|
*/
|
|
const X509_DN& issuer_dn() const;
|
|
|
|
/**
|
|
* Get the certificate's subject distinguished name (DN).
|
|
* @return subject DN of this certificate
|
|
*/
|
|
const X509_DN& subject_dn() const;
|
|
|
|
/**
|
|
* Get a value for a specific subject_info parameter name.
|
|
* @param name the name of the parameter to look up. Possible names include
|
|
* "X509.Certificate.version", "X509.Certificate.serial",
|
|
* "X509.Certificate.start", "X509.Certificate.end",
|
|
* "X509.Certificate.v2.key_id", "X509.Certificate.public_key",
|
|
* "X509v3.BasicConstraints.path_constraint",
|
|
* "X509v3.BasicConstraints.is_ca", "X509v3.NameConstraints",
|
|
* "X509v3.ExtendedKeyUsage", "X509v3.CertificatePolicies",
|
|
* "X509v3.SubjectKeyIdentifier", "X509.Certificate.serial",
|
|
* "X520.CommonName", "X520.Organization", "X520.Country",
|
|
* "RFC822" (Email in SAN) or "PKCS9.EmailAddress" (Email in DN).
|
|
* @return value(s) of the specified parameter
|
|
*/
|
|
std::vector<std::string> subject_info(const std::string& name) const;
|
|
|
|
/**
|
|
* Get a value for a specific subject_info parameter name.
|
|
* @param name the name of the parameter to look up. Possible names are
|
|
* "X509.Certificate.v2.key_id" or "X509v3.AuthorityKeyIdentifier".
|
|
* @return value(s) of the specified parameter
|
|
*/
|
|
std::vector<std::string> issuer_info(const std::string& name) const;
|
|
|
|
/**
|
|
* Raw issuer DN bits
|
|
*/
|
|
const std::vector<uint8_t>& raw_issuer_dn() const;
|
|
|
|
/**
|
|
* SHA-256 of Raw issuer DN
|
|
*/
|
|
std::vector<uint8_t> raw_issuer_dn_sha256() const;
|
|
|
|
/**
|
|
* Raw subject DN
|
|
*/
|
|
const std::vector<uint8_t>& raw_subject_dn() const;
|
|
|
|
/**
|
|
* SHA-256 of Raw subject DN
|
|
*/
|
|
std::vector<uint8_t> raw_subject_dn_sha256() const;
|
|
|
|
/**
|
|
* Get the notBefore of the certificate as a string
|
|
* @return notBefore of the certificate
|
|
*/
|
|
std::string BOTAN_DEPRECATED("Use not_before().to_string()") start_time() const
|
|
{
|
|
return not_before().to_string();
|
|
}
|
|
|
|
/**
|
|
* Get the notAfter of the certificate as a string
|
|
* @return notAfter of the certificate
|
|
*/
|
|
std::string BOTAN_DEPRECATED("Use not_after().to_string()") end_time() const
|
|
{
|
|
return not_after().to_string();
|
|
}
|
|
|
|
/**
|
|
* Get the notBefore of the certificate as X509_Time
|
|
* @return notBefore of the certificate
|
|
*/
|
|
const X509_Time& not_before() const;
|
|
|
|
/**
|
|
* Get the notAfter of the certificate as X509_Time
|
|
* @return notAfter of the certificate
|
|
*/
|
|
const X509_Time& not_after() const;
|
|
|
|
/**
|
|
* Get the X509 version of this certificate object.
|
|
* @return X509 version
|
|
*/
|
|
uint32_t x509_version() const;
|
|
|
|
/**
|
|
* Get the serial number of this certificate.
|
|
* @return certificates serial number
|
|
*/
|
|
const std::vector<uint8_t>& serial_number() const;
|
|
|
|
/**
|
|
* Get the serial number's sign
|
|
* @return 1 iff the serial is negative.
|
|
*/
|
|
bool is_serial_negative() const;
|
|
|
|
/**
|
|
* Get the DER encoded AuthorityKeyIdentifier of this certificate.
|
|
* @return DER encoded AuthorityKeyIdentifier
|
|
*/
|
|
const std::vector<uint8_t>& authority_key_id() const;
|
|
|
|
/**
|
|
* Get the DER encoded SubjectKeyIdentifier of this certificate.
|
|
* @return DER encoded SubjectKeyIdentifier
|
|
*/
|
|
const std::vector<uint8_t>& subject_key_id() const;
|
|
|
|
/**
|
|
* Check whether this certificate is self signed.
|
|
* If the DN issuer and subject agree,
|
|
* @return true if this certificate is self signed
|
|
*/
|
|
bool is_self_signed() const;
|
|
|
|
/**
|
|
* Check whether this certificate is a CA certificate.
|
|
* @return true if this certificate is a CA certificate
|
|
*/
|
|
bool is_CA_cert() const;
|
|
|
|
/**
|
|
* Returns true if the specified @param usage is set in the key usage extension
|
|
* or if no key usage constraints are set at all.
|
|
* To check if a certain key constraint is set in the certificate
|
|
* use @see X509_Certificate#has_constraints.
|
|
*/
|
|
bool allowed_usage(Key_Constraints usage) const;
|
|
|
|
/**
|
|
* Returns true if the specified @param usage is set in the extended key usage extension
|
|
* or if no extended key usage constraints are set at all.
|
|
* To check if a certain extended key constraint is set in the certificate
|
|
* use @see X509_Certificate#has_ex_constraint.
|
|
*/
|
|
bool allowed_extended_usage(const std::string& usage) const;
|
|
|
|
/**
|
|
* Returns true if the specified usage is set in the extended key usage extension,
|
|
* or if no extended key usage constraints are set at all.
|
|
* To check if a certain extended key constraint is set in the certificate
|
|
* use @see X509_Certificate#has_ex_constraint.
|
|
*/
|
|
bool allowed_extended_usage(const OID& usage) const;
|
|
|
|
/**
|
|
* Returns true if the required key and extended key constraints are set in the certificate
|
|
* for the specified @param usage or if no key constraints are set in both the key usage
|
|
* and extended key usage extension.
|
|
*/
|
|
bool allowed_usage(Usage_Type usage) const;
|
|
|
|
/**
|
|
* Returns true if the specified @param constraints are included in the key
|
|
* usage extension.
|
|
*/
|
|
bool has_constraints(Key_Constraints constraints) const;
|
|
|
|
/**
|
|
* Returns true if and only if @param ex_constraint (referring to an
|
|
* extended key constraint, eg "PKIX.ServerAuth") is included in the
|
|
* extended key extension.
|
|
*/
|
|
bool BOTAN_DEPRECATED("Use version taking an OID")
|
|
has_ex_constraint(const std::string& ex_constraint) const;
|
|
|
|
/**
|
|
* Returns true if and only if OID @param ex_constraint is
|
|
* included in the extended key extension.
|
|
*/
|
|
bool has_ex_constraint(const OID& ex_constraint) const;
|
|
|
|
/**
|
|
* Get the path limit as defined in the BasicConstraints extension of
|
|
* this certificate.
|
|
* @return path limit
|
|
*/
|
|
uint32_t path_limit() const;
|
|
|
|
/**
|
|
* Check whenever a given X509 Extension is marked critical in this
|
|
* certificate.
|
|
*/
|
|
bool is_critical(const std::string& ex_name) const;
|
|
|
|
/**
|
|
* Get the key constraints as defined in the KeyUsage extension of this
|
|
* certificate.
|
|
* @return key constraints
|
|
*/
|
|
Key_Constraints constraints() const;
|
|
|
|
/**
|
|
* Get the key constraints as defined in the ExtendedKeyUsage
|
|
* extension of this certificate.
|
|
* @return key constraints
|
|
*/
|
|
std::vector<std::string>
|
|
BOTAN_DEPRECATED("Use extended_key_usage") ex_constraints() const;
|
|
|
|
/**
|
|
* Get the key usage as defined in the ExtendedKeyUsage extension
|
|
* of this certificate, or else an empty vector.
|
|
* @return key usage
|
|
*/
|
|
const std::vector<OID>& extended_key_usage() const;
|
|
|
|
/**
|
|
* Get the name constraints as defined in the NameConstraints
|
|
* extension of this certificate.
|
|
* @return name constraints
|
|
*/
|
|
const NameConstraints& name_constraints() const;
|
|
|
|
/**
|
|
* Get the policies as defined in the CertificatePolicies extension
|
|
* of this certificate.
|
|
* @return certificate policies
|
|
*/
|
|
std::vector<std::string> BOTAN_DEPRECATED("Use certificate_policy_oids") policies() const;
|
|
|
|
const std::vector<OID>& certificate_policy_oids() const;
|
|
|
|
/**
|
|
* Get all extensions of this certificate.
|
|
* @return certificate extensions
|
|
*/
|
|
const Extensions& v3_extensions() const;
|
|
|
|
/**
|
|
* Return the v2 issuer key ID. v2 key IDs are almost never used,
|
|
* instead see v3_subject_key_id.
|
|
*/
|
|
const std::vector<uint8_t>& v2_issuer_key_id() const;
|
|
|
|
/**
|
|
* Return the v2 subject key ID. v2 key IDs are almost never used,
|
|
* instead see v3_subject_key_id.
|
|
*/
|
|
const std::vector<uint8_t>& v2_subject_key_id() const;
|
|
|
|
/**
|
|
* Return the subject alternative names (DNS, IP, ...)
|
|
*/
|
|
const AlternativeName& subject_alt_name() const;
|
|
|
|
/**
|
|
* Return the issuer alternative names (DNS, IP, ...)
|
|
*/
|
|
const AlternativeName& issuer_alt_name() const;
|
|
|
|
/**
|
|
* Return the listed address of an OCSP responder, or empty if not set
|
|
*/
|
|
std::string ocsp_responder() const;
|
|
|
|
/**
|
|
* Return the listed addresses of ca issuers, or empty if not set
|
|
*/
|
|
std::vector<std::string> ca_issuers() const;
|
|
|
|
/**
|
|
* Return the CRL distribution point, or empty if not set
|
|
*/
|
|
std::string crl_distribution_point() const;
|
|
|
|
/**
|
|
* @return a free-form string describing the certificate
|
|
*/
|
|
std::string to_string() const;
|
|
|
|
/**
|
|
* @return a fingerprint of the certificate
|
|
* @param hash_name hash function used to calculate the fingerprint
|
|
*/
|
|
std::string fingerprint(const std::string& hash_name = "SHA-1") const;
|
|
|
|
/**
|
|
* Check if a certain DNS name matches up with the information in
|
|
* the cert
|
|
* @param name DNS name to match
|
|
*/
|
|
bool matches_dns_name(const std::string& name) const;
|
|
|
|
/**
|
|
* Check to certificates for equality.
|
|
* @return true both certificates are (binary) equal
|
|
*/
|
|
bool operator==(const X509_Certificate& other) const;
|
|
|
|
/**
|
|
* Impose an arbitrary (but consistent) ordering, eg to allow sorting
|
|
* a container of certificate objects.
|
|
* @return true if this is less than other by some unspecified criteria
|
|
*/
|
|
bool operator<(const X509_Certificate& other) const;
|
|
|
|
/**
|
|
* Create a certificate from a data source providing the DER or
|
|
* PEM encoded certificate.
|
|
* @param source the data source
|
|
*/
|
|
explicit X509_Certificate(DataSource& source);
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
|
|
/**
|
|
* Create a certificate from a file containing the DER or PEM
|
|
* encoded certificate.
|
|
* @param filename the name of the certificate file
|
|
*/
|
|
explicit X509_Certificate(const std::string& filename);
|
|
#endif
|
|
|
|
/**
|
|
* Create a certificate from a buffer
|
|
* @param in the buffer containing the DER-encoded certificate
|
|
*/
|
|
explicit X509_Certificate(const std::vector<uint8_t>& in);
|
|
|
|
/**
|
|
* Create a certificate from a buffer
|
|
* @param data the buffer containing the DER-encoded certificate
|
|
* @param length length of data in bytes
|
|
*/
|
|
X509_Certificate(const uint8_t data[], size_t length);
|
|
|
|
/**
|
|
* Create an uninitialized certificate object. Any attempts to
|
|
* access this object will throw an exception.
|
|
*/
|
|
X509_Certificate() = default;
|
|
|
|
X509_Certificate(const X509_Certificate& other) = default;
|
|
|
|
X509_Certificate& operator=(const X509_Certificate& other) = default;
|
|
|
|
private:
|
|
std::string PEM_label() const override;
|
|
|
|
std::vector<std::string> alternate_PEM_labels() const override;
|
|
|
|
void force_decode() override;
|
|
|
|
const X509_Certificate_Data& data() const;
|
|
|
|
std::shared_ptr<X509_Certificate_Data> m_data;
|
|
};
|
|
|
|
/**
|
|
* Check two certificates for inequality
|
|
* @param cert1 The first certificate
|
|
* @param cert2 The second certificate
|
|
* @return true if the arguments represent different certificates,
|
|
* false if they are binary identical
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Extensions;
|
|
class X509_Certificate;
|
|
class X509_DN;
|
|
|
|
struct CRL_Entry_Data;
|
|
struct CRL_Data;
|
|
|
|
/**
|
|
* This class represents CRL entries
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CRL_Entry final : public ASN1_Object
|
|
{
|
|
public:
|
|
void encode_into(class DER_Encoder&) const override;
|
|
void decode_from(class BER_Decoder&) override;
|
|
|
|
/**
|
|
* Get the serial number of the certificate associated with this entry.
|
|
* @return certificate's serial number
|
|
*/
|
|
const std::vector<uint8_t>& serial_number() const;
|
|
|
|
/**
|
|
* Get the revocation date of the certificate associated with this entry
|
|
* @return certificate's revocation date
|
|
*/
|
|
const X509_Time& expire_time() const;
|
|
|
|
/**
|
|
* Get the entries reason code
|
|
* @return reason code
|
|
*/
|
|
CRL_Code reason_code() const;
|
|
|
|
/**
|
|
* Get the extensions on this CRL entry
|
|
*/
|
|
const Extensions& extensions() const;
|
|
|
|
/**
|
|
* Create uninitialized CRL_Entry object
|
|
*/
|
|
CRL_Entry() = default;
|
|
|
|
/**
|
|
* Construct an CRL entry.
|
|
* @param cert the certificate to revoke
|
|
* @param reason the reason code to set in the entry
|
|
*/
|
|
CRL_Entry(const X509_Certificate& cert,
|
|
CRL_Code reason = UNSPECIFIED);
|
|
|
|
private:
|
|
friend class X509_CRL;
|
|
|
|
const CRL_Entry_Data& data() const;
|
|
|
|
std::shared_ptr<CRL_Entry_Data> m_data;
|
|
};
|
|
|
|
/**
|
|
* Test two CRL entries for equality in all fields.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) bool operator==(const CRL_Entry&, const CRL_Entry&);
|
|
|
|
/**
|
|
* Test two CRL entries for inequality in at least one field.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) bool operator!=(const CRL_Entry&, const CRL_Entry&);
|
|
|
|
/**
|
|
* This class represents X.509 Certificate Revocation Lists (CRLs).
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) X509_CRL final : public X509_Object
|
|
{
|
|
public:
|
|
/**
|
|
* This class represents CRL related errors.
|
|
*
|
|
* In a future major release this exception type will be removed and
|
|
* replaced with Decoding_Error
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) X509_CRL_Error final : public Decoding_Error
|
|
{
|
|
public:
|
|
explicit X509_CRL_Error(const std::string& error) :
|
|
Decoding_Error("X509_CRL: " + error) {}
|
|
};
|
|
|
|
/**
|
|
* Check if this particular certificate is listed in the CRL
|
|
*/
|
|
bool is_revoked(const X509_Certificate& cert) const;
|
|
|
|
/**
|
|
* Get the entries of this CRL in the form of a vector.
|
|
* @return vector containing the entries of this CRL.
|
|
*/
|
|
const std::vector<CRL_Entry>& get_revoked() const;
|
|
|
|
/**
|
|
* Get the issuer DN of this CRL.
|
|
* @return CRLs issuer DN
|
|
*/
|
|
const X509_DN& issuer_dn() const;
|
|
|
|
/**
|
|
* @return extension data for this CRL
|
|
*/
|
|
const Extensions& extensions() const;
|
|
|
|
/**
|
|
* Get the AuthorityKeyIdentifier of this CRL.
|
|
* @return this CRLs AuthorityKeyIdentifier
|
|
*/
|
|
const std::vector<uint8_t>& authority_key_id() const;
|
|
|
|
/**
|
|
* Get the serial number of this CRL.
|
|
* @return CRLs serial number
|
|
*/
|
|
uint32_t crl_number() const;
|
|
|
|
/**
|
|
* Get the CRL's thisUpdate value.
|
|
* @return CRLs thisUpdate
|
|
*/
|
|
const X509_Time& this_update() const;
|
|
|
|
/**
|
|
* Get the CRL's nextUpdate value.
|
|
* @return CRLs nextdUpdate
|
|
*/
|
|
const X509_Time& next_update() const;
|
|
|
|
/**
|
|
* Get the CRL's distribution point
|
|
* @return CRL.IssuingDistributionPoint from the CRL's Data_Store
|
|
*/
|
|
std::string crl_issuing_distribution_point() const;
|
|
|
|
/**
|
|
* Create an uninitialized CRL object. Any attempts to access
|
|
* this object will throw an exception.
|
|
*/
|
|
X509_CRL() = default;
|
|
|
|
/**
|
|
* Construct a CRL from a data source.
|
|
* @param source the data source providing the DER or PEM encoded CRL.
|
|
*/
|
|
X509_CRL(DataSource& source);
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
|
|
/**
|
|
* Construct a CRL from a file containing the DER or PEM encoded CRL.
|
|
* @param filename the name of the CRL file
|
|
*/
|
|
X509_CRL(const std::string& filename);
|
|
#endif
|
|
|
|
/**
|
|
* Construct a CRL from a binary vector
|
|
* @param vec the binary (DER) representation of the CRL
|
|
*/
|
|
X509_CRL(const std::vector<uint8_t>& vec);
|
|
|
|
/**
|
|
* Construct a CRL
|
|
* @param issuer issuer of this CRL
|
|
* @param thisUpdate valid from
|
|
* @param nextUpdate valid until
|
|
* @param revoked entries to be included in the CRL
|
|
*/
|
|
X509_CRL(const X509_DN& issuer, const X509_Time& thisUpdate,
|
|
const X509_Time& nextUpdate, const std::vector<CRL_Entry>& revoked);
|
|
|
|
private:
|
|
std::string PEM_label() const override;
|
|
|
|
std::vector<std::string> alternate_PEM_labels() const override;
|
|
|
|
void force_decode() override;
|
|
|
|
const CRL_Data& data() const;
|
|
|
|
std::shared_ptr<CRL_Data> m_data;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Certificate Store Interface
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Certificate_Store
|
|
{
|
|
public:
|
|
virtual ~Certificate_Store();
|
|
|
|
/**
|
|
* Find a certificate by Subject DN and (optionally) key identifier
|
|
* @param subject_dn the subject's distinguished name
|
|
* @param key_id an optional key id
|
|
* @return a matching certificate or nullptr otherwise
|
|
* If more than one certificate in the certificate store matches, then
|
|
* a single value is selected arbitrarily.
|
|
*/
|
|
virtual std::shared_ptr<const X509_Certificate>
|
|
find_cert(const X509_DN& subject_dn, const std::vector<uint8_t>& key_id) const;
|
|
|
|
/**
|
|
* Find all certificates with a given Subject DN.
|
|
* Subject DN and even the key identifier might not be unique.
|
|
*/
|
|
virtual std::vector<std::shared_ptr<const X509_Certificate>> find_all_certs(
|
|
const X509_DN& subject_dn, const std::vector<uint8_t>& key_id) const = 0;
|
|
|
|
|
|
/**
|
|
* Find a certificate by searching for one with a matching SHA-1 hash of
|
|
* public key. Used for OCSP.
|
|
* @param key_hash SHA-1 hash of the subject's public key
|
|
* @return a matching certificate or nullptr otherwise
|
|
*/
|
|
virtual std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_pubkey_sha1(const std::vector<uint8_t>& key_hash) const = 0;
|
|
|
|
/**
|
|
* Find a certificate by searching for one with a matching SHA-256 hash of
|
|
* raw subject name. Used for OCSP.
|
|
* @param subject_hash SHA-256 hash of the subject's raw name
|
|
* @return a matching certificate or nullptr otherwise
|
|
*/
|
|
virtual std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_raw_subject_dn_sha256(const std::vector<uint8_t>& subject_hash) const = 0;
|
|
|
|
/**
|
|
* Finds a CRL for the given certificate
|
|
* @param subject the subject certificate
|
|
* @return the CRL for subject or nullptr otherwise
|
|
*/
|
|
virtual std::shared_ptr<const X509_CRL> find_crl_for(const X509_Certificate& subject) const;
|
|
|
|
/**
|
|
* @return whether the certificate is known
|
|
* @param cert certififcate to be searched
|
|
*/
|
|
bool certificate_known(const X509_Certificate& cert) const
|
|
{
|
|
return find_cert(cert.subject_dn(), cert.subject_key_id()) != nullptr;
|
|
}
|
|
|
|
// remove this (used by TLS::Server)
|
|
virtual std::vector<X509_DN> all_subjects() const = 0;
|
|
};
|
|
|
|
/**
|
|
* In Memory Certificate Store
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Certificate_Store_In_Memory final : public Certificate_Store
|
|
{
|
|
public:
|
|
/**
|
|
* Attempt to parse all files in dir (including subdirectories)
|
|
* as certificates. Ignores errors.
|
|
*/
|
|
explicit Certificate_Store_In_Memory(const std::string& dir);
|
|
|
|
/**
|
|
* Adds given certificate to the store.
|
|
*/
|
|
explicit Certificate_Store_In_Memory(const X509_Certificate& cert);
|
|
|
|
/**
|
|
* Create an empty store.
|
|
*/
|
|
Certificate_Store_In_Memory() = default;
|
|
|
|
/**
|
|
* Add a certificate to the store.
|
|
* @param cert certificate to be added
|
|
*/
|
|
void add_certificate(const X509_Certificate& cert);
|
|
|
|
/**
|
|
* Add a certificate already in a shared_ptr to the store.
|
|
* @param cert certificate to be added
|
|
*/
|
|
void add_certificate(std::shared_ptr<const X509_Certificate> cert);
|
|
|
|
/**
|
|
* Add a certificate revocation list (CRL) to the store.
|
|
* @param crl CRL to be added
|
|
*/
|
|
void add_crl(const X509_CRL& crl);
|
|
|
|
/**
|
|
* Add a certificate revocation list (CRL) to the store as a shared_ptr
|
|
* @param crl CRL to be added
|
|
*/
|
|
void add_crl(std::shared_ptr<const X509_CRL> crl);
|
|
|
|
/**
|
|
* @return DNs for all certificates managed by the store
|
|
*/
|
|
std::vector<X509_DN> all_subjects() const override;
|
|
|
|
/*
|
|
* Find a certificate by Subject DN and (optionally) key identifier
|
|
* @return the first certificate that matches
|
|
*/
|
|
std::shared_ptr<const X509_Certificate> find_cert(
|
|
const X509_DN& subject_dn,
|
|
const std::vector<uint8_t>& key_id) const override;
|
|
|
|
/*
|
|
* Find all certificates with a given Subject DN.
|
|
* Subject DN and even the key identifier might not be unique.
|
|
*/
|
|
std::vector<std::shared_ptr<const X509_Certificate>> find_all_certs(
|
|
const X509_DN& subject_dn, const std::vector<uint8_t>& key_id) const override;
|
|
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_pubkey_sha1(const std::vector<uint8_t>& key_hash) const override;
|
|
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_raw_subject_dn_sha256(const std::vector<uint8_t>& subject_hash) const override;
|
|
|
|
/**
|
|
* Finds a CRL for the given certificate
|
|
*/
|
|
std::shared_ptr<const X509_CRL> find_crl_for(const X509_Certificate& subject) const override;
|
|
private:
|
|
// TODO: Add indexing on the DN and key id to avoid linear search
|
|
std::vector<std::shared_ptr<const X509_Certificate>> m_certs;
|
|
std::vector<std::shared_ptr<const X509_CRL>> m_crls;
|
|
};
|
|
|
|
}
|
|
|
|
|
|
namespace Botan {
|
|
/**
|
|
* Certificate Store that is backed by a file of PEMs of trusted CAs.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2, 11) Flatfile_Certificate_Store final : public Certificate_Store
|
|
{
|
|
public:
|
|
/**
|
|
* Construct a new Certificate_Store given a file path to a file including
|
|
* PEMs of trusted self-signed CAs.
|
|
*
|
|
* @param file the name of the file to read certificates from
|
|
* @param ignore_non_ca if true, certs that are not self-signed CA certs will
|
|
* be ignored. Otherwise (if false), an exception will be thrown instead.
|
|
*/
|
|
Flatfile_Certificate_Store(const std::string& file, bool ignore_non_ca = false);
|
|
|
|
Flatfile_Certificate_Store(const Flatfile_Certificate_Store&) = default;
|
|
Flatfile_Certificate_Store(Flatfile_Certificate_Store&&) = default;
|
|
Flatfile_Certificate_Store& operator=(const Flatfile_Certificate_Store&) = default;
|
|
Flatfile_Certificate_Store& operator=(Flatfile_Certificate_Store&&) = default;
|
|
|
|
/**
|
|
* @return DNs for all certificates managed by the store
|
|
*/
|
|
std::vector<X509_DN> all_subjects() const override;
|
|
|
|
/**
|
|
* Find all certificates with a given Subject DN.
|
|
* Subject DN and even the key identifier might not be unique.
|
|
*/
|
|
std::vector<std::shared_ptr<const X509_Certificate>> find_all_certs(
|
|
const X509_DN& subject_dn, const std::vector<uint8_t>& key_id) const override;
|
|
|
|
/**
|
|
* Find a certificate by searching for one with a matching SHA-1 hash of
|
|
* public key.
|
|
* @return a matching certificate or nullptr otherwise
|
|
*/
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_pubkey_sha1(const std::vector<uint8_t>& key_hash) const override;
|
|
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_raw_subject_dn_sha256(const std::vector<uint8_t>& subject_hash) const override;
|
|
|
|
/**
|
|
* Fetching CRLs is not supported by this certificate store. This will
|
|
* always return an empty list.
|
|
*/
|
|
std::shared_ptr<const X509_CRL> find_crl_for(const X509_Certificate& subject) const override;
|
|
|
|
private:
|
|
std::vector<X509_DN> m_all_subjects;
|
|
std::map<X509_DN, std::vector<std::shared_ptr<const X509_Certificate>>> m_dn_to_cert;
|
|
std::map<std::vector<uint8_t>, std::shared_ptr<const X509_Certificate>> m_pubkey_sha1_to_cert;
|
|
std::map<std::vector<uint8_t>, std::shared_ptr<const X509_Certificate>> m_subject_dn_sha256_to_cert;
|
|
};
|
|
}
|
|
|
|
|
|
namespace Botan {
|
|
|
|
class Certificate_Store_MacOS_Impl;
|
|
|
|
/**
|
|
* Certificate Store that is backed by the system trust store on macOS. This
|
|
* opens a handle to the macOS keychain and serves certificate queries directly
|
|
* from there.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2, 10) Certificate_Store_MacOS final : public Certificate_Store
|
|
{
|
|
public:
|
|
Certificate_Store_MacOS();
|
|
|
|
Certificate_Store_MacOS(const Certificate_Store_MacOS&) = default;
|
|
Certificate_Store_MacOS(Certificate_Store_MacOS&&) = default;
|
|
Certificate_Store_MacOS& operator=(const Certificate_Store_MacOS&) = default;
|
|
Certificate_Store_MacOS& operator=(Certificate_Store_MacOS&&) = default;
|
|
|
|
/**
|
|
* @return DNs for all certificates managed by the store
|
|
*/
|
|
std::vector<X509_DN> all_subjects() const override;
|
|
|
|
/**
|
|
* Find a certificate by Subject DN and (optionally) key identifier
|
|
* @return the first certificate that matches
|
|
*/
|
|
std::shared_ptr<const X509_Certificate> find_cert(
|
|
const X509_DN& subject_dn,
|
|
const std::vector<uint8_t>& key_id) const override;
|
|
|
|
/**
|
|
* Find all certificates with a given Subject DN.
|
|
* Subject DN and even the key identifier might not be unique.
|
|
*/
|
|
std::vector<std::shared_ptr<const X509_Certificate>> find_all_certs(
|
|
const X509_DN& subject_dn, const std::vector<uint8_t>& key_id) const override;
|
|
|
|
/**
|
|
* Find a certificate by searching for one with a matching SHA-1 hash of
|
|
* public key.
|
|
* @return a matching certificate or nullptr otherwise
|
|
*/
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_pubkey_sha1(const std::vector<uint8_t>& key_hash) const override;
|
|
|
|
/**
|
|
* @throws Botan::Not_Implemented
|
|
*/
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_raw_subject_dn_sha256(const std::vector<uint8_t>& subject_hash) const override;
|
|
|
|
/**
|
|
* Fetching CRLs is not supported by the keychain on macOS. This will
|
|
* always return an empty list.
|
|
*/
|
|
std::shared_ptr<const X509_CRL> find_crl_for(const X509_Certificate& subject) const override;
|
|
|
|
private:
|
|
std::shared_ptr<Certificate_Store_MacOS_Impl> m_impl;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class BOTAN_PUBLIC_API(2,0) SQL_Database
|
|
{
|
|
public:
|
|
|
|
class BOTAN_PUBLIC_API(2,0) SQL_DB_Error final : public Exception
|
|
{
|
|
public:
|
|
explicit SQL_DB_Error(const std::string& what) :
|
|
Exception("SQL database", what),
|
|
m_rc(0)
|
|
{}
|
|
|
|
SQL_DB_Error(const std::string& what, int rc) :
|
|
Exception("SQL database", what),
|
|
m_rc(rc)
|
|
{}
|
|
|
|
ErrorType error_type() const noexcept override { return Botan::ErrorType::DatabaseError; }
|
|
|
|
int error_code() const noexcept override { return m_rc; }
|
|
private:
|
|
int m_rc;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,0) Statement
|
|
{
|
|
public:
|
|
/* Bind statement parameters */
|
|
virtual void bind(int column, const std::string& str) = 0;
|
|
|
|
virtual void bind(int column, size_t i) = 0;
|
|
|
|
virtual void bind(int column, std::chrono::system_clock::time_point time) = 0;
|
|
|
|
virtual void bind(int column, const std::vector<uint8_t>& blob) = 0;
|
|
|
|
virtual void bind(int column, const uint8_t* data, size_t len) = 0;
|
|
|
|
/* Get output */
|
|
virtual std::pair<const uint8_t*, size_t> get_blob(int column) = 0;
|
|
|
|
virtual std::string get_str(int column) = 0;
|
|
|
|
virtual size_t get_size_t(int column) = 0;
|
|
|
|
/* Run to completion */
|
|
virtual size_t spin() = 0;
|
|
|
|
/* Maybe update */
|
|
virtual bool step() = 0;
|
|
|
|
virtual ~Statement() = default;
|
|
};
|
|
|
|
/*
|
|
* Create a new statement for execution.
|
|
* Use ?1, ?2, ?3, etc for parameters to set later with bind
|
|
*/
|
|
virtual std::shared_ptr<Statement> new_statement(const std::string& base_sql) const = 0;
|
|
|
|
virtual size_t row_count(const std::string& table_name) = 0;
|
|
|
|
virtual void create_table(const std::string& table_schema) = 0;
|
|
|
|
virtual ~SQL_Database() = default;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Private_Key;
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Certificate and private key store backed by an SQL database.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Certificate_Store_In_SQL : public Certificate_Store
|
|
{
|
|
public:
|
|
/**
|
|
* Create/open a certificate store.
|
|
* @param db underlying database storage
|
|
* @param passwd password to encrypt private keys in the database
|
|
* @param rng used for encrypting keys
|
|
* @param table_prefix optional prefix for db table names
|
|
*/
|
|
explicit Certificate_Store_In_SQL(const std::shared_ptr<SQL_Database> db,
|
|
const std::string& passwd,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& table_prefix = "");
|
|
|
|
/**
|
|
* Returns the first certificate with matching subject DN and optional key ID.
|
|
*/
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert(const X509_DN& subject_dn, const std::vector<uint8_t>& key_id) const override;
|
|
|
|
/*
|
|
* Find all certificates with a given Subject DN.
|
|
* Subject DN and even the key identifier might not be unique.
|
|
*/
|
|
std::vector<std::shared_ptr<const X509_Certificate>> find_all_certs(
|
|
const X509_DN& subject_dn, const std::vector<uint8_t>& key_id) const override;
|
|
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_pubkey_sha1(const std::vector<uint8_t>& key_hash) const override;
|
|
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_raw_subject_dn_sha256(const std::vector<uint8_t>& subject_hash) const override;
|
|
|
|
/**
|
|
* Returns all subject DNs known to the store instance.
|
|
*/
|
|
std::vector<X509_DN> all_subjects() const override;
|
|
|
|
/**
|
|
* Inserts "cert" into the store, returns false if the certificate is
|
|
* already known and true if insertion was successful.
|
|
*/
|
|
bool insert_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.
|
|
*/
|
|
bool remove_cert(const X509_Certificate& cert);
|
|
|
|
/// Returns the private key for "cert" or an empty shared_ptr if none was found.
|
|
std::shared_ptr<const Private_Key> find_key(const X509_Certificate&) const;
|
|
|
|
/// Returns all certificates for private key "key".
|
|
std::vector<std::shared_ptr<const X509_Certificate>>
|
|
find_certs_for_key(const Private_Key& key) const;
|
|
|
|
/**
|
|
* Inserts "key" for "cert" into the store, returns false if the key is
|
|
* already known and true if insertion was successful.
|
|
*/
|
|
bool insert_key(const X509_Certificate& cert, const Private_Key& key);
|
|
|
|
/// Removes "key" from the store.
|
|
void remove_key(const Private_Key& key);
|
|
|
|
/// Marks "cert" as revoked starting from "time".
|
|
void revoke_cert(const X509_Certificate&, CRL_Code, const X509_Time& time = X509_Time());
|
|
|
|
/// Reverses the revokation for "cert".
|
|
void affirm_cert(const X509_Certificate&);
|
|
|
|
/**
|
|
* Generates Certificate Revocation Lists for all certificates marked as revoked.
|
|
* A CRL is returned for each unique issuer DN.
|
|
*/
|
|
std::vector<X509_CRL> generate_crls() const;
|
|
|
|
/**
|
|
* Generates a CRL for all certificates issued by the given issuer.
|
|
*/
|
|
std::shared_ptr<const X509_CRL>
|
|
find_crl_for(const X509_Certificate& issuer) const override;
|
|
|
|
private:
|
|
RandomNumberGenerator& m_rng;
|
|
std::shared_ptr<SQL_Database> m_database;
|
|
std::string m_prefix;
|
|
std::string m_password;
|
|
mutex_type m_mutex;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class BOTAN_PUBLIC_API(2,11) System_Certificate_Store final : public Certificate_Store
|
|
{
|
|
public:
|
|
|
|
System_Certificate_Store();
|
|
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert(const X509_DN& subject_dn, const std::vector<uint8_t>& key_id) const override;
|
|
|
|
std::vector<std::shared_ptr<const X509_Certificate>>
|
|
find_all_certs(const X509_DN& subject_dn, const std::vector<uint8_t>& key_id) const override;
|
|
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_pubkey_sha1(const std::vector<uint8_t>& key_hash) const override;
|
|
|
|
std::shared_ptr<const X509_Certificate>
|
|
find_cert_by_raw_subject_dn_sha256(const std::vector<uint8_t>& subject_hash) const override;
|
|
|
|
std::shared_ptr<const X509_CRL> find_crl_for(const X509_Certificate& subject) const override;
|
|
|
|
std::vector<X509_DN> all_subjects() const override;
|
|
|
|
private:
|
|
std::shared_ptr<Certificate_Store> m_system_store;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(cfb.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* CFB Mode
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CFB_Mode : public Cipher_Mode
|
|
{
|
|
public:
|
|
std::string name() const override final;
|
|
|
|
size_t update_granularity() const override final;
|
|
|
|
size_t minimum_final_size() const override final;
|
|
|
|
Key_Length_Specification key_spec() const override final;
|
|
|
|
size_t output_length(size_t input_length) const override final;
|
|
|
|
size_t default_nonce_length() const override final;
|
|
|
|
bool valid_nonce_length(size_t n) const override final;
|
|
|
|
void clear() override final;
|
|
|
|
void reset() override final;
|
|
protected:
|
|
CFB_Mode(BlockCipher* cipher, size_t feedback_bits);
|
|
|
|
void shift_register();
|
|
|
|
size_t feedback() const { return m_feedback_bytes; }
|
|
const BlockCipher& cipher() const { return *m_cipher; }
|
|
size_t block_size() const { return m_block_size; }
|
|
|
|
secure_vector<uint8_t> m_state;
|
|
secure_vector<uint8_t> m_keystream;
|
|
size_t m_keystream_pos = 0;
|
|
|
|
private:
|
|
void start_msg(const uint8_t nonce[], size_t nonce_len) override;
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
const size_t m_block_size;
|
|
const size_t m_feedback_bytes;
|
|
};
|
|
|
|
/**
|
|
* CFB Encryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CFB_Encryption final : public CFB_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* If feedback_bits is zero, cipher->block_size() bytes will be used.
|
|
* @param cipher block cipher to use
|
|
* @param feedback_bits number of bits fed back into the shift register,
|
|
* must be a multiple of 8
|
|
*/
|
|
CFB_Encryption(BlockCipher* cipher, size_t feedback_bits) :
|
|
CFB_Mode(cipher, feedback_bits) {}
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
};
|
|
|
|
/**
|
|
* CFB Decryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CFB_Decryption final : public CFB_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* If feedback_bits is zero, cipher->block_size() bytes will be used.
|
|
* @param cipher block cipher to use
|
|
* @param feedback_bits number of bits fed back into the shift register,
|
|
* must be a multiple of 8
|
|
*/
|
|
CFB_Decryption(BlockCipher* cipher, size_t feedback_bits) :
|
|
CFB_Mode(cipher, feedback_bits) {}
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Base class for all stream ciphers
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) StreamCipher : public SymmetricAlgorithm
|
|
{
|
|
public:
|
|
virtual ~StreamCipher() = default;
|
|
|
|
/**
|
|
* Create an instance based on a name
|
|
* If provider is empty then best available is chosen.
|
|
* @param algo_spec algorithm name
|
|
* @param provider provider implementation to use
|
|
* @return a null pointer if the algo/provider combination cannot be found
|
|
*/
|
|
static std::unique_ptr<StreamCipher>
|
|
create(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* Create an instance based on a name
|
|
* If provider is empty then best available is chosen.
|
|
* @param algo_spec algorithm name
|
|
* @param provider provider implementation to use
|
|
* Throws a Lookup_Error if the algo/provider combination cannot be found
|
|
*/
|
|
static std::unique_ptr<StreamCipher>
|
|
create_or_throw(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* @return list of available providers for this algorithm, empty if not available
|
|
*/
|
|
static std::vector<std::string> providers(const std::string& algo_spec);
|
|
|
|
/**
|
|
* Encrypt or decrypt a message
|
|
* @param in the plaintext
|
|
* @param out the byte array to hold the output, i.e. the ciphertext
|
|
* @param len the length of both in and out in bytes
|
|
*/
|
|
virtual void cipher(const uint8_t in[], uint8_t out[], size_t len) = 0;
|
|
|
|
/**
|
|
* Write keystream bytes to a buffer
|
|
* @param out the byte array to hold the keystream
|
|
* @param len the length of out in bytes
|
|
*/
|
|
virtual void write_keystream(uint8_t out[], size_t len)
|
|
{
|
|
clear_mem(out, len);
|
|
cipher1(out, len);
|
|
}
|
|
|
|
/**
|
|
* Encrypt or decrypt a message
|
|
* The message is encrypted/decrypted in place.
|
|
* @param buf the plaintext / ciphertext
|
|
* @param len the length of buf in bytes
|
|
*/
|
|
void cipher1(uint8_t buf[], size_t len)
|
|
{ cipher(buf, buf, len); }
|
|
|
|
/**
|
|
* Encrypt a message
|
|
* The message is encrypted/decrypted in place.
|
|
* @param inout the plaintext / ciphertext
|
|
*/
|
|
template<typename Alloc>
|
|
void encipher(std::vector<uint8_t, Alloc>& inout)
|
|
{ cipher(inout.data(), inout.data(), inout.size()); }
|
|
|
|
/**
|
|
* Encrypt a message
|
|
* The message is encrypted in place.
|
|
* @param inout the plaintext / ciphertext
|
|
*/
|
|
template<typename Alloc>
|
|
void encrypt(std::vector<uint8_t, Alloc>& inout)
|
|
{ cipher(inout.data(), inout.data(), inout.size()); }
|
|
|
|
/**
|
|
* Decrypt a message in place
|
|
* The message is decrypted in place.
|
|
* @param inout the plaintext / ciphertext
|
|
*/
|
|
template<typename Alloc>
|
|
void decrypt(std::vector<uint8_t, Alloc>& inout)
|
|
{ cipher(inout.data(), inout.data(), inout.size()); }
|
|
|
|
/**
|
|
* Resync the cipher using the IV
|
|
* @param iv the initialization vector
|
|
* @param iv_len the length of the IV in bytes
|
|
*/
|
|
virtual void set_iv(const uint8_t iv[], size_t iv_len) = 0;
|
|
|
|
/**
|
|
* Return the default (preferred) nonce length
|
|
* If this function returns 0, then this cipher does not support nonces
|
|
*/
|
|
virtual size_t default_iv_length() const { return 0; }
|
|
|
|
/**
|
|
* @param iv_len the length of the IV in bytes
|
|
* @return if the length is valid for this algorithm
|
|
*/
|
|
virtual bool valid_iv_length(size_t iv_len) const { return (iv_len == 0); }
|
|
|
|
/**
|
|
* @return a new object representing the same algorithm as *this
|
|
*/
|
|
virtual StreamCipher* clone() const = 0;
|
|
|
|
/**
|
|
* Set the offset and the state used later to generate the keystream
|
|
* @param offset the offset where we begin to generate the keystream
|
|
*/
|
|
virtual void seek(uint64_t offset) = 0;
|
|
|
|
/**
|
|
* @return provider information about this implementation. Default is "base",
|
|
* might also return "sse2", "avx2", "openssl", or some other arbitrary string.
|
|
*/
|
|
virtual std::string provider() const { return "base"; }
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(chacha.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* DJB's ChaCha (https://cr.yp.to/chacha.html)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ChaCha final : public StreamCipher
|
|
{
|
|
public:
|
|
/**
|
|
* @param rounds number of rounds
|
|
* @note Currently only 8, 12 or 20 rounds are supported, all others
|
|
* will throw an exception
|
|
*/
|
|
explicit ChaCha(size_t rounds = 20);
|
|
|
|
std::string provider() const override;
|
|
|
|
void cipher(const uint8_t in[], uint8_t out[], size_t length) override;
|
|
|
|
void write_keystream(uint8_t out[], size_t len) override;
|
|
|
|
void set_iv(const uint8_t iv[], size_t iv_len) override;
|
|
|
|
/*
|
|
* ChaCha accepts 0, 8, 12 or 24 byte IVs.
|
|
* The default IV is a 8 zero bytes.
|
|
* An IV of length 0 is treated the same as the default zero IV.
|
|
* An IV of length 24 selects XChaCha mode
|
|
*/
|
|
bool valid_iv_length(size_t iv_len) const override;
|
|
|
|
size_t default_iv_length() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
void clear() override;
|
|
|
|
StreamCipher* clone() const override;
|
|
|
|
std::string name() const override;
|
|
|
|
void seek(uint64_t offset) override;
|
|
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t key_len) override;
|
|
|
|
void initialize_state();
|
|
|
|
void chacha_x8(uint8_t output[64*8], uint32_t state[16], size_t rounds);
|
|
|
|
#if defined(BOTAN_HAS_CHACHA_SIMD32)
|
|
void chacha_simd32_x4(uint8_t output[64*4], uint32_t state[16], size_t rounds);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_CHACHA_AVX2)
|
|
void chacha_avx2_x8(uint8_t output[64*8], uint32_t state[16], size_t rounds);
|
|
#endif
|
|
|
|
size_t m_rounds;
|
|
secure_vector<uint32_t> m_key;
|
|
secure_vector<uint32_t> m_state;
|
|
secure_vector<uint8_t> m_buffer;
|
|
size_t m_position = 0;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(chacha20poly1305.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Base class
|
|
* See draft-irtf-cfrg-chacha20-poly1305-03 for specification
|
|
* If a nonce of 64 bits is used the older version described in
|
|
* draft-agl-tls-chacha20poly1305-04 is used instead.
|
|
* If a nonce of 192 bits is used, XChaCha20Poly1305 is selected.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ChaCha20Poly1305_Mode : public AEAD_Mode
|
|
{
|
|
public:
|
|
void set_associated_data(const uint8_t ad[], size_t ad_len) override;
|
|
|
|
bool associated_data_requires_key() const override { return false; }
|
|
|
|
std::string name() const override { return "ChaCha20Poly1305"; }
|
|
|
|
size_t update_granularity() const override { return 64; }
|
|
|
|
Key_Length_Specification key_spec() const override
|
|
{ return Key_Length_Specification(32); }
|
|
|
|
bool valid_nonce_length(size_t n) const override;
|
|
|
|
size_t tag_size() const override { return 16; }
|
|
|
|
void clear() override;
|
|
|
|
void reset() override;
|
|
|
|
protected:
|
|
std::unique_ptr<StreamCipher> m_chacha;
|
|
std::unique_ptr<MessageAuthenticationCode> m_poly1305;
|
|
|
|
ChaCha20Poly1305_Mode();
|
|
|
|
secure_vector<uint8_t> m_ad;
|
|
size_t m_nonce_len = 0;
|
|
size_t m_ctext_len = 0;
|
|
|
|
bool cfrg_version() const { return m_nonce_len == 12 || m_nonce_len == 24; }
|
|
void update_len(size_t len);
|
|
private:
|
|
void start_msg(const uint8_t nonce[], size_t nonce_len) override;
|
|
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
};
|
|
|
|
/**
|
|
* ChaCha20Poly1305 Encryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ChaCha20Poly1305_Encryption final : public ChaCha20Poly1305_Mode
|
|
{
|
|
public:
|
|
size_t output_length(size_t input_length) const override
|
|
{ return input_length + tag_size(); }
|
|
|
|
size_t minimum_final_size() const override { return 0; }
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
};
|
|
|
|
/**
|
|
* ChaCha20Poly1305 Decryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ChaCha20Poly1305_Decryption final : public ChaCha20Poly1305_Mode
|
|
{
|
|
public:
|
|
size_t output_length(size_t input_length) const override
|
|
{
|
|
BOTAN_ASSERT(input_length >= tag_size(), "Sufficient input");
|
|
return input_length - tag_size();
|
|
}
|
|
|
|
size_t minimum_final_size() const override { return tag_size(); }
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Inherited by RNGs which maintain in-process state, like HMAC_DRBG.
|
|
* On Unix these RNGs are vulnerable to problems with fork, where the
|
|
* RNG state is duplicated, and the parent and child process RNGs will
|
|
* produce identical output until one of them reseeds. Stateful_RNG
|
|
* reseeds itself whenever a fork is detected, or after a set number of
|
|
* bytes have been output.
|
|
*
|
|
* Not implemented by RNGs which access an external RNG, such as the
|
|
* system PRNG or a hardware RNG.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Stateful_RNG : public RandomNumberGenerator
|
|
{
|
|
public:
|
|
/**
|
|
* @param rng is a reference to some RNG which will be used
|
|
* to perform the periodic reseeding
|
|
* @param entropy_sources will be polled to perform reseeding periodically
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed
|
|
*/
|
|
Stateful_RNG(RandomNumberGenerator& rng,
|
|
Entropy_Sources& entropy_sources,
|
|
size_t reseed_interval) :
|
|
m_underlying_rng(&rng),
|
|
m_entropy_sources(&entropy_sources),
|
|
m_reseed_interval(reseed_interval)
|
|
{}
|
|
|
|
/**
|
|
* @param rng is a reference to some RNG which will be used
|
|
* to perform the periodic reseeding
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed
|
|
*/
|
|
Stateful_RNG(RandomNumberGenerator& rng, size_t reseed_interval) :
|
|
m_underlying_rng(&rng),
|
|
m_reseed_interval(reseed_interval)
|
|
{}
|
|
|
|
/**
|
|
* @param entropy_sources will be polled to perform reseeding periodically
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed
|
|
*/
|
|
Stateful_RNG(Entropy_Sources& entropy_sources, size_t reseed_interval) :
|
|
m_entropy_sources(&entropy_sources),
|
|
m_reseed_interval(reseed_interval)
|
|
{}
|
|
|
|
/**
|
|
* In this case, automatic reseeding is impossible
|
|
*/
|
|
Stateful_RNG() : m_reseed_interval(0) {}
|
|
|
|
/**
|
|
* Consume this input and mark the RNG as initialized regardless
|
|
* of the length of the input or the current seeded state of
|
|
* the RNG.
|
|
*/
|
|
void initialize_with(const uint8_t input[], size_t length);
|
|
|
|
bool is_seeded() const override final;
|
|
|
|
bool accepts_input() const override final { return true; }
|
|
|
|
/**
|
|
* Mark state as requiring a reseed on next use
|
|
*/
|
|
void force_reseed();
|
|
|
|
void reseed_from_rng(RandomNumberGenerator& rng,
|
|
size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS) override final;
|
|
|
|
void add_entropy(const uint8_t input[], size_t input_len) override final;
|
|
|
|
void randomize(uint8_t output[], size_t output_len) override final;
|
|
|
|
void randomize_with_input(uint8_t output[], size_t output_len,
|
|
const uint8_t input[], size_t input_len) override final;
|
|
|
|
/**
|
|
* Overrides default implementation and also includes the current
|
|
* process ID and the reseed counter.
|
|
*/
|
|
void randomize_with_ts_input(uint8_t output[], size_t output_len) override final;
|
|
|
|
/**
|
|
* Poll provided sources for up to poll_bits bits of entropy
|
|
* or until the timeout expires. Returns estimate of the number
|
|
* of bits collected.
|
|
*/
|
|
size_t reseed(Entropy_Sources& srcs,
|
|
size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS,
|
|
std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override;
|
|
|
|
/**
|
|
* @return intended security level of this DRBG
|
|
*/
|
|
virtual size_t security_level() const = 0;
|
|
|
|
/**
|
|
* Some DRBGs have a notion of the maximum number of bytes per
|
|
* request. Longer requests (to randomize) will be treated as
|
|
* multiple requests, and may initiate reseeding multiple times,
|
|
* depending on the values of max_number_of_bytes_per_request and
|
|
* reseed_interval(). This function returns zero if the RNG in
|
|
* question does not have such a notion.
|
|
*
|
|
* @return max number of bytes per request (or zero)
|
|
*/
|
|
virtual size_t max_number_of_bytes_per_request() const = 0;
|
|
|
|
size_t reseed_interval() const { return m_reseed_interval; }
|
|
|
|
void clear() override final;
|
|
|
|
protected:
|
|
void reseed_check();
|
|
|
|
virtual void generate_output(uint8_t output[], size_t output_len,
|
|
const uint8_t input[], size_t input_len) = 0;
|
|
|
|
virtual void update(const uint8_t input[], size_t input_len) = 0;
|
|
|
|
virtual void clear_state() = 0;
|
|
|
|
private:
|
|
void reset_reseed_counter();
|
|
|
|
mutable recursive_mutex_type m_mutex;
|
|
|
|
// A non-owned and possibly null pointer to shared RNG
|
|
RandomNumberGenerator* m_underlying_rng = nullptr;
|
|
|
|
// A non-owned and possibly null pointer to a shared Entropy_Source
|
|
Entropy_Sources* m_entropy_sources = nullptr;
|
|
|
|
const size_t m_reseed_interval;
|
|
uint32_t m_last_pid = 0;
|
|
|
|
/*
|
|
* Set to 1 after a successful seeding, then incremented. Reset
|
|
* to 0 by clear() or a fork. This logic is used even if
|
|
* automatic reseeding is disabled (via m_reseed_interval = 0)
|
|
*/
|
|
size_t m_reseed_counter = 0;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Entropy_Sources;
|
|
|
|
/**
|
|
* ChaCha_RNG is a very fast but completely ad-hoc RNG created by
|
|
* creating a 256-bit random value and using it as a key for ChaCha20.
|
|
*
|
|
* The RNG maintains two 256-bit keys, one for HMAC_SHA256 (HK) and the
|
|
* other for ChaCha20 (CK). To compute a new key in response to
|
|
* reseeding request or add_entropy calls, ChaCha_RNG computes
|
|
* CK' = HMAC_SHA256(HK, input_material)
|
|
* Then a new HK' is computed by running ChaCha20 with the new key to
|
|
* output 32 bytes:
|
|
* HK' = ChaCha20(CK')
|
|
*
|
|
* Now output can be produced by continuing to produce output with ChaCha20
|
|
* under CK'
|
|
*
|
|
* The first HK (before seeding occurs) is taken as the all zero value.
|
|
*
|
|
* @warning This RNG construction is probably fine but is non-standard.
|
|
* The primary reason to use it is in cases where the other RNGs are
|
|
* not fast enough.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,3) ChaCha_RNG final : public Stateful_RNG
|
|
{
|
|
public:
|
|
/**
|
|
* Automatic reseeding is disabled completely, as it has no access to
|
|
* any source for seed material.
|
|
*
|
|
* If a fork is detected, the RNG will be unable to reseed itself
|
|
* in response. In this case, an exception will be thrown rather
|
|
* than generating duplicated output.
|
|
*/
|
|
ChaCha_RNG();
|
|
|
|
/**
|
|
* Provide an initial seed to the RNG, without providing an
|
|
* underlying RNG or entropy source. Automatic reseeding is
|
|
* disabled completely, as it has no access to any source for
|
|
* seed material.
|
|
*
|
|
* If a fork is detected, the RNG will be unable to reseed itself
|
|
* in response. In this case, an exception will be thrown rather
|
|
* than generating duplicated output.
|
|
*
|
|
* @param seed the seed material, should be at least 256 bits
|
|
*/
|
|
ChaCha_RNG(const secure_vector<uint8_t>& seed);
|
|
|
|
/**
|
|
* Automatic reseeding from @p underlying_rng will take place after
|
|
* @p reseed_interval many requests or after a fork was detected.
|
|
*
|
|
* @param underlying_rng is a reference to some RNG which will be used
|
|
* to perform the periodic reseeding
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed
|
|
*/
|
|
ChaCha_RNG(RandomNumberGenerator& underlying_rng,
|
|
size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL);
|
|
|
|
/**
|
|
* Automatic reseeding from @p entropy_sources will take place after
|
|
* @p reseed_interval many requests or after a fork was detected.
|
|
*
|
|
* @param entropy_sources will be polled to perform reseeding periodically
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed.
|
|
*/
|
|
ChaCha_RNG(Entropy_Sources& entropy_sources,
|
|
size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL);
|
|
|
|
/**
|
|
* Automatic reseeding from @p underlying_rng and @p entropy_sources
|
|
* will take place after @p reseed_interval many requests or after
|
|
* a fork was detected.
|
|
*
|
|
* @param underlying_rng is a reference to some RNG which will be used
|
|
* to perform the periodic reseeding
|
|
* @param entropy_sources will be polled to perform reseeding periodically
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed.
|
|
*/
|
|
ChaCha_RNG(RandomNumberGenerator& underlying_rng,
|
|
Entropy_Sources& entropy_sources,
|
|
size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL);
|
|
|
|
std::string name() const override { return "ChaCha_RNG"; }
|
|
|
|
size_t security_level() const override;
|
|
|
|
size_t max_number_of_bytes_per_request() const override { return 0; }
|
|
|
|
private:
|
|
void update(const uint8_t input[], size_t input_len) override;
|
|
|
|
void generate_output(uint8_t output[], size_t output_len,
|
|
const uint8_t input[], size_t input_len) override;
|
|
|
|
void clear_state() override;
|
|
|
|
std::unique_ptr<MessageAuthenticationCode> m_hmac;
|
|
std::unique_ptr<StreamCipher> m_chacha;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(charset.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Convert a sequence of UCS-2 (big endian) characters to a UTF-8 string
|
|
* This is used for ASN.1 BMPString type
|
|
* @param ucs2 the sequence of UCS-2 characters
|
|
* @param len length of ucs2 in bytes, must be a multiple of 2
|
|
*/
|
|
std::string BOTAN_UNSTABLE_API ucs2_to_utf8(const uint8_t ucs2[], size_t len);
|
|
|
|
/**
|
|
* Convert a sequence of UCS-4 (big endian) characters to a UTF-8 string
|
|
* This is used for ASN.1 UniversalString type
|
|
* @param ucs4 the sequence of UCS-4 characters
|
|
* @param len length of ucs4 in bytes, must be a multiple of 4
|
|
*/
|
|
std::string BOTAN_UNSTABLE_API ucs4_to_utf8(const uint8_t ucs4[], size_t len);
|
|
|
|
/**
|
|
* Convert a UTF-8 string to Latin-1
|
|
* If a character outside the Latin-1 range is encountered, an exception is thrown.
|
|
*/
|
|
std::string BOTAN_UNSTABLE_API utf8_to_latin1(const std::string& utf8);
|
|
|
|
/**
|
|
* The different charsets (nominally) supported by Botan.
|
|
*/
|
|
enum Character_Set {
|
|
LOCAL_CHARSET,
|
|
UCS2_CHARSET,
|
|
UTF8_CHARSET,
|
|
LATIN1_CHARSET
|
|
};
|
|
|
|
namespace Charset {
|
|
|
|
/*
|
|
* Character set conversion - avoid this.
|
|
* For specific conversions, use the functions above like
|
|
* ucs2_to_utf8 and utf8_to_latin1
|
|
*
|
|
* If you need something more complex than that, use a real library
|
|
* such as iconv, Boost.Locale, or ICU
|
|
*/
|
|
std::string BOTAN_PUBLIC_API(2,0)
|
|
BOTAN_DEPRECATED("Avoid. See comment in header.")
|
|
transcode(const std::string& str,
|
|
Character_Set to,
|
|
Character_Set from);
|
|
|
|
/*
|
|
* Simple character classifier functions
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,0) is_digit(char c);
|
|
bool BOTAN_PUBLIC_API(2,0) is_space(char c);
|
|
bool BOTAN_PUBLIC_API(2,0) caseless_cmp(char x, char y);
|
|
|
|
uint8_t BOTAN_PUBLIC_API(2,0) char2digit(char c);
|
|
char BOTAN_PUBLIC_API(2,0) digit2char(uint8_t b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(cmac.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* CMAC, also known as OMAC1
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CMAC final : public MessageAuthenticationCode
|
|
{
|
|
public:
|
|
std::string name() const override;
|
|
size_t output_length() const override { return m_block_size; }
|
|
MessageAuthenticationCode* clone() const override;
|
|
|
|
void clear() override;
|
|
|
|
Key_Length_Specification key_spec() const override
|
|
{
|
|
return m_cipher->key_spec();
|
|
}
|
|
|
|
/**
|
|
* CMAC's polynomial doubling operation
|
|
*
|
|
* This function was only exposed for use elsewhere in the library, but it is not
|
|
* longer used. This function will be removed in a future release.
|
|
*
|
|
* @param in the input
|
|
*/
|
|
static secure_vector<uint8_t>
|
|
BOTAN_DEPRECATED("This was only for internal use and is no longer used")
|
|
poly_double(const secure_vector<uint8_t>& in);
|
|
|
|
/**
|
|
* @param cipher the block cipher to use
|
|
*/
|
|
explicit CMAC(BlockCipher* cipher);
|
|
|
|
CMAC(const CMAC&) = delete;
|
|
CMAC& operator=(const CMAC&) = delete;
|
|
private:
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
secure_vector<uint8_t> m_buffer, m_state, m_B, m_P;
|
|
const size_t m_block_size;
|
|
size_t m_position;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(comb4p.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Combines two hash functions using a Feistel scheme. Described in
|
|
* "On the Security of Hash Function Combiners", Anja Lehmann
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Comb4P final : public HashFunction
|
|
{
|
|
public:
|
|
/**
|
|
* @param h1 the first hash
|
|
* @param h2 the second hash
|
|
*/
|
|
Comb4P(HashFunction* h1, HashFunction* h2);
|
|
|
|
size_t hash_block_size() const override;
|
|
|
|
size_t output_length() const override
|
|
{
|
|
return m_hash1->output_length() + m_hash2->output_length();
|
|
}
|
|
|
|
HashFunction* clone() const override
|
|
{
|
|
return new Comb4P(m_hash1->clone(), m_hash2->clone());
|
|
}
|
|
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
std::string name() const override
|
|
{
|
|
return "Comb4P(" + m_hash1->name() + "," + m_hash2->name() + ")";
|
|
}
|
|
|
|
void clear() override;
|
|
private:
|
|
Comb4P() = default;
|
|
|
|
void add_data(const uint8_t input[], size_t length) override;
|
|
void final_result(uint8_t out[]) override;
|
|
|
|
std::unique_ptr<HashFunction> m_hash1, m_hash2;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(cpuid.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* A class handling runtime CPU feature detection. It is limited to
|
|
* just the features necessary to implement CPU specific code in Botan,
|
|
* rather than being a general purpose utility.
|
|
*
|
|
* This class supports:
|
|
*
|
|
* - x86 features using CPUID. x86 is also the only processor with
|
|
* accurate cache line detection currently.
|
|
*
|
|
* - PowerPC AltiVec detection on Linux, NetBSD, OpenBSD, and macOS
|
|
*
|
|
* - ARM NEON and crypto extensions detection. On Linux and Android
|
|
* systems which support getauxval, that is used to access CPU
|
|
* feature information. Otherwise a relatively portable but
|
|
* thread-unsafe mechanism involving executing probe functions which
|
|
* catching SIGILL signal is used.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,1) CPUID final
|
|
{
|
|
public:
|
|
/**
|
|
* Probe the CPU and see what extensions are supported
|
|
*/
|
|
static void initialize();
|
|
|
|
static bool has_simd_32();
|
|
|
|
/**
|
|
* Deprecated equivalent to
|
|
* o << "CPUID flags: " << CPUID::to_string() << "\n";
|
|
*/
|
|
BOTAN_DEPRECATED("Use CPUID::to_string")
|
|
static void print(std::ostream& o);
|
|
|
|
/**
|
|
* Return a possibly empty string containing list of known CPU
|
|
* extensions. Each name will be seperated by a space, and the ordering
|
|
* will be arbitrary. This list only contains values that are useful to
|
|
* Botan (for example FMA instructions are not checked).
|
|
*
|
|
* Example outputs "sse2 ssse3 rdtsc", "neon arm_aes", "altivec"
|
|
*/
|
|
static std::string to_string();
|
|
|
|
/**
|
|
* Return a best guess of the cache line size
|
|
*/
|
|
static size_t cache_line_size()
|
|
{
|
|
return state().cache_line_size();
|
|
}
|
|
|
|
static bool is_little_endian()
|
|
{
|
|
#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
|
|
return true;
|
|
#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
|
|
return false;
|
|
#else
|
|
return state().endian_status() == Endian_Status::Little;
|
|
#endif
|
|
}
|
|
|
|
static bool is_big_endian()
|
|
{
|
|
#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
|
|
return true;
|
|
#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
|
|
return false;
|
|
#else
|
|
return state().endian_status() == Endian_Status::Big;
|
|
#endif
|
|
}
|
|
|
|
enum CPUID_bits : uint64_t {
|
|
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
|
|
// These values have no relation to cpuid bitfields
|
|
|
|
// SIMD instruction sets
|
|
CPUID_SSE2_BIT = (1ULL << 0),
|
|
CPUID_SSSE3_BIT = (1ULL << 1),
|
|
CPUID_SSE41_BIT = (1ULL << 2),
|
|
CPUID_SSE42_BIT = (1ULL << 3),
|
|
CPUID_AVX2_BIT = (1ULL << 4),
|
|
CPUID_AVX512F_BIT = (1ULL << 5),
|
|
|
|
CPUID_AVX512DQ_BIT = (1ULL << 6),
|
|
CPUID_AVX512BW_BIT = (1ULL << 7),
|
|
|
|
// Ice Lake profile: AVX-512 F, DQ, BW, IFMA, VBMI, VBMI2, BITALG
|
|
CPUID_AVX512_ICL_BIT = (1ULL << 11),
|
|
|
|
// Crypto-specific ISAs
|
|
CPUID_AESNI_BIT = (1ULL << 16),
|
|
CPUID_CLMUL_BIT = (1ULL << 17),
|
|
CPUID_RDRAND_BIT = (1ULL << 18),
|
|
CPUID_RDSEED_BIT = (1ULL << 19),
|
|
CPUID_SHA_BIT = (1ULL << 20),
|
|
CPUID_AVX512_AES_BIT = (1ULL << 21),
|
|
CPUID_AVX512_CLMUL_BIT = (1ULL << 22),
|
|
|
|
// Misc useful instructions
|
|
CPUID_RDTSC_BIT = (1ULL << 48),
|
|
CPUID_ADX_BIT = (1ULL << 49),
|
|
CPUID_BMI1_BIT = (1ULL << 50),
|
|
CPUID_BMI2_BIT = (1ULL << 51),
|
|
#endif
|
|
|
|
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
|
|
CPUID_ALTIVEC_BIT = (1ULL << 0),
|
|
CPUID_POWER_CRYPTO_BIT = (1ULL << 1),
|
|
CPUID_DARN_BIT = (1ULL << 2),
|
|
#endif
|
|
|
|
#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
|
|
CPUID_ARM_NEON_BIT = (1ULL << 0),
|
|
CPUID_ARM_SVE_BIT = (1ULL << 1),
|
|
CPUID_ARM_AES_BIT = (1ULL << 16),
|
|
CPUID_ARM_PMULL_BIT = (1ULL << 17),
|
|
CPUID_ARM_SHA1_BIT = (1ULL << 18),
|
|
CPUID_ARM_SHA2_BIT = (1ULL << 19),
|
|
CPUID_ARM_SHA3_BIT = (1ULL << 20),
|
|
CPUID_ARM_SHA2_512_BIT = (1ULL << 21),
|
|
CPUID_ARM_SM3_BIT = (1ULL << 22),
|
|
CPUID_ARM_SM4_BIT = (1ULL << 23),
|
|
#endif
|
|
|
|
CPUID_INITIALIZED_BIT = (1ULL << 63)
|
|
};
|
|
|
|
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
|
|
/**
|
|
* Check if the processor supports AltiVec/VMX
|
|
*/
|
|
static bool has_altivec()
|
|
{ return has_cpuid_bit(CPUID_ALTIVEC_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports POWER8 crypto extensions
|
|
*/
|
|
static bool has_power_crypto()
|
|
{ return has_cpuid_bit(CPUID_POWER_CRYPTO_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports POWER9 DARN RNG
|
|
*/
|
|
static bool has_darn_rng()
|
|
{ return has_cpuid_bit(CPUID_DARN_BIT); }
|
|
|
|
#endif
|
|
|
|
#if defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
|
|
/**
|
|
* Check if the processor supports NEON SIMD
|
|
*/
|
|
static bool has_neon()
|
|
{ return has_cpuid_bit(CPUID_ARM_NEON_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports ARMv8 SVE
|
|
*/
|
|
static bool has_arm_sve()
|
|
{ return has_cpuid_bit(CPUID_ARM_SVE_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports ARMv8 SHA1
|
|
*/
|
|
static bool has_arm_sha1()
|
|
{ return has_cpuid_bit(CPUID_ARM_SHA1_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports ARMv8 SHA2
|
|
*/
|
|
static bool has_arm_sha2()
|
|
{ return has_cpuid_bit(CPUID_ARM_SHA2_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports ARMv8 AES
|
|
*/
|
|
static bool has_arm_aes()
|
|
{ return has_cpuid_bit(CPUID_ARM_AES_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports ARMv8 PMULL
|
|
*/
|
|
static bool has_arm_pmull()
|
|
{ return has_cpuid_bit(CPUID_ARM_PMULL_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports ARMv8 SHA-512
|
|
*/
|
|
static bool has_arm_sha2_512()
|
|
{ return has_cpuid_bit(CPUID_ARM_SHA2_512_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports ARMv8 SHA-3
|
|
*/
|
|
static bool has_arm_sha3()
|
|
{ return has_cpuid_bit(CPUID_ARM_SHA3_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports ARMv8 SM3
|
|
*/
|
|
static bool has_arm_sm3()
|
|
{ return has_cpuid_bit(CPUID_ARM_SM3_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports ARMv8 SM4
|
|
*/
|
|
static bool has_arm_sm4()
|
|
{ return has_cpuid_bit(CPUID_ARM_SM4_BIT); }
|
|
|
|
#endif
|
|
|
|
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
|
|
|
|
/**
|
|
* Check if the processor supports RDTSC
|
|
*/
|
|
static bool has_rdtsc()
|
|
{ return has_cpuid_bit(CPUID_RDTSC_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports SSE2
|
|
*/
|
|
static bool has_sse2()
|
|
{ return has_cpuid_bit(CPUID_SSE2_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports SSSE3
|
|
*/
|
|
static bool has_ssse3()
|
|
{ return has_cpuid_bit(CPUID_SSSE3_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports SSE4.1
|
|
*/
|
|
static bool has_sse41()
|
|
{ return has_cpuid_bit(CPUID_SSE41_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports SSE4.2
|
|
*/
|
|
static bool has_sse42()
|
|
{ return has_cpuid_bit(CPUID_SSE42_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports AVX2
|
|
*/
|
|
static bool has_avx2()
|
|
{ return has_cpuid_bit(CPUID_AVX2_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports AVX-512F
|
|
*/
|
|
static bool has_avx512f()
|
|
{ return has_cpuid_bit(CPUID_AVX512F_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports AVX-512DQ
|
|
*/
|
|
static bool has_avx512dq()
|
|
{ return has_cpuid_bit(CPUID_AVX512DQ_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports AVX-512BW
|
|
*/
|
|
static bool has_avx512bw()
|
|
{ return has_cpuid_bit(CPUID_AVX512BW_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports AVX-512 Ice Lake profile
|
|
*/
|
|
static bool has_avx512_icelake()
|
|
{ return has_cpuid_bit(CPUID_AVX512_ICL_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports AVX-512 AES (VAES)
|
|
*/
|
|
static bool has_avx512_aes()
|
|
{ return has_cpuid_bit(CPUID_AVX512_AES_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports AVX-512 VPCLMULQDQ
|
|
*/
|
|
static bool has_avx512_clmul()
|
|
{ return has_cpuid_bit(CPUID_AVX512_CLMUL_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports BMI1
|
|
*/
|
|
static bool has_bmi1()
|
|
{ return has_cpuid_bit(CPUID_BMI1_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports BMI2
|
|
*/
|
|
static bool has_bmi2()
|
|
{ return has_cpuid_bit(CPUID_BMI2_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports AES-NI
|
|
*/
|
|
static bool has_aes_ni()
|
|
{ return has_cpuid_bit(CPUID_AESNI_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports CLMUL
|
|
*/
|
|
static bool has_clmul()
|
|
{ return has_cpuid_bit(CPUID_CLMUL_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports Intel SHA extension
|
|
*/
|
|
static bool has_intel_sha()
|
|
{ return has_cpuid_bit(CPUID_SHA_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports ADX extension
|
|
*/
|
|
static bool has_adx()
|
|
{ return has_cpuid_bit(CPUID_ADX_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports RDRAND
|
|
*/
|
|
static bool has_rdrand()
|
|
{ return has_cpuid_bit(CPUID_RDRAND_BIT); }
|
|
|
|
/**
|
|
* Check if the processor supports RDSEED
|
|
*/
|
|
static bool has_rdseed()
|
|
{ return has_cpuid_bit(CPUID_RDSEED_BIT); }
|
|
#endif
|
|
|
|
/**
|
|
* Check if the processor supports byte-level vector permutes
|
|
* (SSSE3, NEON, Altivec)
|
|
*/
|
|
static bool has_vperm()
|
|
{
|
|
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
|
|
return has_ssse3();
|
|
#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
|
|
return has_neon();
|
|
#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
|
|
return has_altivec();
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Check if the processor supports hardware AES instructions
|
|
*/
|
|
static bool has_hw_aes()
|
|
{
|
|
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
|
|
return has_aes_ni();
|
|
#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
|
|
return has_arm_aes();
|
|
#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY)
|
|
return has_power_crypto();
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Check if the processor supports carryless multiply
|
|
* (CLMUL, PMULL)
|
|
*/
|
|
static bool has_carryless_multiply()
|
|
{
|
|
#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
|
|
return has_clmul();
|
|
#elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY)
|
|
return has_arm_pmull();
|
|
#elif defined(BOTAN_TARGET_ARCH_IS_PPC64)
|
|
return has_power_crypto();
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Clear a CPUID bit
|
|
* Call CPUID::initialize to reset
|
|
*
|
|
* This is only exposed for testing, don't use unless you know
|
|
* what you are doing.
|
|
*/
|
|
static void clear_cpuid_bit(CPUID_bits bit)
|
|
{
|
|
state().clear_cpuid_bit(static_cast<uint64_t>(bit));
|
|
}
|
|
|
|
/*
|
|
* Don't call this function, use CPUID::has_xxx above
|
|
* It is only exposed for the tests.
|
|
*/
|
|
static bool has_cpuid_bit(CPUID_bits elem)
|
|
{
|
|
const uint64_t elem64 = static_cast<uint64_t>(elem);
|
|
return state().has_bit(elem64);
|
|
}
|
|
|
|
static std::vector<CPUID::CPUID_bits> bit_from_string(const std::string& tok);
|
|
private:
|
|
enum class Endian_Status : uint32_t {
|
|
Unknown = 0x00000000,
|
|
Big = 0x01234567,
|
|
Little = 0x67452301,
|
|
};
|
|
|
|
struct CPUID_Data
|
|
{
|
|
public:
|
|
CPUID_Data();
|
|
|
|
CPUID_Data(const CPUID_Data& other) = default;
|
|
CPUID_Data& operator=(const CPUID_Data& other) = default;
|
|
|
|
void clear_cpuid_bit(uint64_t bit)
|
|
{
|
|
m_processor_features &= ~bit;
|
|
}
|
|
|
|
bool has_bit(uint64_t bit) const
|
|
{
|
|
return (m_processor_features & bit) == bit;
|
|
}
|
|
|
|
uint64_t processor_features() const { return m_processor_features; }
|
|
Endian_Status endian_status() const { return m_endian_status; }
|
|
size_t cache_line_size() const { return m_cache_line_size; }
|
|
|
|
private:
|
|
static Endian_Status runtime_check_endian();
|
|
|
|
#if defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) || \
|
|
defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY) || \
|
|
defined(BOTAN_TARGET_CPU_IS_X86_FAMILY)
|
|
|
|
static uint64_t detect_cpu_features(size_t* cache_line_size);
|
|
|
|
#endif
|
|
uint64_t m_processor_features;
|
|
size_t m_cache_line_size;
|
|
Endian_Status m_endian_status;
|
|
};
|
|
|
|
static CPUID_Data& state()
|
|
{
|
|
static CPUID::CPUID_Data g_cpuid;
|
|
return g_cpuid;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(crc24.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* 24-bit cyclic redundancy check
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CRC24 final : public HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "CRC24"; }
|
|
size_t output_length() const override { return 3; }
|
|
HashFunction* clone() const override { return new CRC24; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override { m_crc = 0XCE04B7L; }
|
|
|
|
CRC24() { clear(); }
|
|
~CRC24() { clear(); }
|
|
private:
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
uint32_t m_crc;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(crc32.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* 32-bit cyclic redundancy check
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CRC32 final : public HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "CRC32"; }
|
|
size_t output_length() const override { return 4; }
|
|
HashFunction* clone() const override { return new CRC32; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override { m_crc = 0xFFFFFFFF; }
|
|
|
|
CRC32() { clear(); }
|
|
~CRC32() { clear(); }
|
|
private:
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
uint32_t m_crc;
|
|
};
|
|
|
|
}
|
|
namespace Botan {
|
|
|
|
namespace PK_Ops {
|
|
|
|
class Encryption;
|
|
class Decryption;
|
|
class Verification;
|
|
class Signature;
|
|
class Key_Agreement;
|
|
class KEM_Encryption;
|
|
class KEM_Decryption;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* The two types of signature format supported by Botan.
|
|
*/
|
|
enum Signature_Format { IEEE_1363, DER_SEQUENCE };
|
|
|
|
/**
|
|
* Public Key Base Class.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Public_Key
|
|
{
|
|
public:
|
|
Public_Key() =default;
|
|
Public_Key(const Public_Key& other) = default;
|
|
Public_Key& operator=(const Public_Key& other) = default;
|
|
virtual ~Public_Key() = default;
|
|
|
|
/**
|
|
* Get the name of the underlying public key scheme.
|
|
* @return name of the public key scheme
|
|
*/
|
|
virtual std::string algo_name() const = 0;
|
|
|
|
/**
|
|
* Return the estimated strength of the underlying key against
|
|
* the best currently known attack. Note that this ignores anything
|
|
* but pure attacks against the key itself and do not take into
|
|
* account padding schemes, usage mistakes, etc which might reduce
|
|
* the strength. However it does suffice to provide an upper bound.
|
|
*
|
|
* @return estimated strength in bits
|
|
*/
|
|
virtual size_t estimated_strength() const = 0;
|
|
|
|
/**
|
|
* Return an integer value best approximating the length of the
|
|
* primary security parameter. For example for RSA this will be
|
|
* the size of the modulus, for ECDSA the size of the ECC group,
|
|
* and for McEliece the size of the code will be returned.
|
|
*/
|
|
virtual size_t key_length() const = 0;
|
|
|
|
/**
|
|
* Get the OID of the underlying public key scheme.
|
|
* @return OID of the public key scheme
|
|
*/
|
|
virtual OID get_oid() const;
|
|
|
|
/**
|
|
* Test the key values for consistency.
|
|
* @param rng rng to use
|
|
* @param strong whether to perform strong and lengthy version
|
|
* of the test
|
|
* @return true if the test is passed
|
|
*/
|
|
virtual bool check_key(RandomNumberGenerator& rng,
|
|
bool strong) const = 0;
|
|
|
|
|
|
/**
|
|
* @return X.509 AlgorithmIdentifier for this key
|
|
*/
|
|
virtual AlgorithmIdentifier algorithm_identifier() const = 0;
|
|
|
|
/**
|
|
* @return BER encoded public key bits
|
|
*/
|
|
virtual std::vector<uint8_t> public_key_bits() const = 0;
|
|
|
|
/**
|
|
* @return X.509 subject key encoding for this key object
|
|
*/
|
|
std::vector<uint8_t> subject_public_key() const;
|
|
|
|
/**
|
|
* @return Hash of the subject public key
|
|
*/
|
|
std::string fingerprint_public(const std::string& alg = "SHA-256") const;
|
|
|
|
// Internal or non-public declarations follow
|
|
|
|
/**
|
|
* Returns more than 1 if the output of this algorithm
|
|
* (ciphertext, signature) should be treated as more than one
|
|
* value. This is used for algorithms like DSA and ECDSA, where
|
|
* the (r,s) output pair can be encoded as either a plain binary
|
|
* list or a TLV tagged DER encoding depending on the protocol.
|
|
*
|
|
* This function is public but applications should have few
|
|
* reasons to ever call this.
|
|
*
|
|
* @return number of message parts
|
|
*/
|
|
virtual size_t message_parts() const { return 1; }
|
|
|
|
/**
|
|
* Returns how large each of the message parts refered to
|
|
* by message_parts() is
|
|
*
|
|
* This function is public but applications should have few
|
|
* reasons to ever call this.
|
|
*
|
|
* @return size of the message parts in bits
|
|
*/
|
|
virtual size_t message_part_size() const { return 0; }
|
|
|
|
virtual Signature_Format default_x509_signature_format() const
|
|
{
|
|
return (this->message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
|
|
}
|
|
|
|
/**
|
|
* This is an internal library function exposed on key types.
|
|
* In almost all cases applications should use wrappers in pubkey.h
|
|
*
|
|
* Return an encryption operation for this key/params or throw
|
|
*
|
|
* @param rng a random number generator. The PK_Op may maintain a
|
|
* reference to the RNG and use it many times. The rng must outlive
|
|
* any operations which reference it.
|
|
* @param params additional parameters
|
|
* @param provider the provider to use
|
|
*/
|
|
virtual std::unique_ptr<PK_Ops::Encryption>
|
|
create_encryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const;
|
|
|
|
/**
|
|
* This is an internal library function exposed on key types.
|
|
* In almost all cases applications should use wrappers in pubkey.h
|
|
*
|
|
* Return a KEM encryption operation for this key/params or throw
|
|
*
|
|
* @param rng a random number generator. The PK_Op may maintain a
|
|
* reference to the RNG and use it many times. The rng must outlive
|
|
* any operations which reference it.
|
|
* @param params additional parameters
|
|
* @param provider the provider to use
|
|
*/
|
|
virtual std::unique_ptr<PK_Ops::KEM_Encryption>
|
|
create_kem_encryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const;
|
|
|
|
/**
|
|
* This is an internal library function exposed on key types.
|
|
* In almost all cases applications should use wrappers in pubkey.h
|
|
*
|
|
* Return a verification operation for this key/params or throw
|
|
* @param params additional parameters
|
|
* @param provider the provider to use
|
|
*/
|
|
virtual std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string& params,
|
|
const std::string& provider) const;
|
|
};
|
|
|
|
/**
|
|
* Private Key Base Class
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Private_Key : public virtual Public_Key
|
|
{
|
|
public:
|
|
Private_Key() = default;
|
|
Private_Key(const Private_Key& other) = default;
|
|
Private_Key& operator=(const Private_Key& other) = default;
|
|
virtual ~Private_Key() = default;
|
|
|
|
virtual bool stateful_operation() const { return false; }
|
|
|
|
/**
|
|
* @return BER encoded private key bits
|
|
*/
|
|
virtual secure_vector<uint8_t> private_key_bits() const = 0;
|
|
|
|
/**
|
|
* @return PKCS #8 private key encoding for this key object
|
|
*/
|
|
secure_vector<uint8_t> private_key_info() const;
|
|
|
|
/**
|
|
* @return PKCS #8 AlgorithmIdentifier for this key
|
|
* Might be different from the X.509 identifier, but normally is not
|
|
*/
|
|
virtual AlgorithmIdentifier pkcs8_algorithm_identifier() const
|
|
{ return algorithm_identifier(); }
|
|
|
|
// Internal or non-public declarations follow
|
|
|
|
/**
|
|
* @return Hash of the PKCS #8 encoding for this key object
|
|
*/
|
|
std::string fingerprint_private(const std::string& alg) const;
|
|
|
|
BOTAN_DEPRECATED("Use fingerprint_private or fingerprint_public")
|
|
inline std::string fingerprint(const std::string& alg) const
|
|
{
|
|
return fingerprint_private(alg); // match behavior in previous versions
|
|
}
|
|
|
|
/**
|
|
* This is an internal library function exposed on key types.
|
|
* In almost all cases applications should use wrappers in pubkey.h
|
|
*
|
|
* Return an decryption operation for this key/params or throw
|
|
*
|
|
* @param rng a random number generator. The PK_Op may maintain a
|
|
* reference to the RNG and use it many times. The rng must outlive
|
|
* any operations which reference it.
|
|
* @param params additional parameters
|
|
* @param provider the provider to use
|
|
*
|
|
*/
|
|
virtual std::unique_ptr<PK_Ops::Decryption>
|
|
create_decryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const;
|
|
|
|
/**
|
|
* This is an internal library function exposed on key types.
|
|
* In almost all cases applications should use wrappers in pubkey.h
|
|
*
|
|
* Return a KEM decryption operation for this key/params or throw
|
|
*
|
|
* @param rng a random number generator. The PK_Op may maintain a
|
|
* reference to the RNG and use it many times. The rng must outlive
|
|
* any operations which reference it.
|
|
* @param params additional parameters
|
|
* @param provider the provider to use
|
|
*/
|
|
virtual std::unique_ptr<PK_Ops::KEM_Decryption>
|
|
create_kem_decryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const;
|
|
|
|
/**
|
|
* This is an internal library function exposed on key types.
|
|
* In almost all cases applications should use wrappers in pubkey.h
|
|
*
|
|
* Return a signature operation for this key/params or throw
|
|
*
|
|
* @param rng a random number generator. The PK_Op may maintain a
|
|
* reference to the RNG and use it many times. The rng must outlive
|
|
* any operations which reference it.
|
|
* @param params additional parameters
|
|
* @param provider the provider to use
|
|
*/
|
|
virtual std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const;
|
|
|
|
/**
|
|
* This is an internal library function exposed on key types.
|
|
* In almost all cases applications should use wrappers in pubkey.h
|
|
*
|
|
* Return a key agreement operation for this key/params or throw
|
|
*
|
|
* @param rng a random number generator. The PK_Op may maintain a
|
|
* reference to the RNG and use it many times. The rng must outlive
|
|
* any operations which reference it.
|
|
* @param params additional parameters
|
|
* @param provider the provider to use
|
|
*/
|
|
virtual std::unique_ptr<PK_Ops::Key_Agreement>
|
|
create_key_agreement_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const;
|
|
};
|
|
|
|
/**
|
|
* PK Secret Value Derivation Key
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PK_Key_Agreement_Key : public virtual Private_Key
|
|
{
|
|
public:
|
|
/*
|
|
* @return public component of this key
|
|
*/
|
|
virtual std::vector<uint8_t> public_value() const = 0;
|
|
|
|
PK_Key_Agreement_Key() = default;
|
|
PK_Key_Agreement_Key(const PK_Key_Agreement_Key&) = default;
|
|
PK_Key_Agreement_Key& operator=(const PK_Key_Agreement_Key&) = default;
|
|
virtual ~PK_Key_Agreement_Key() = default;
|
|
};
|
|
|
|
/*
|
|
* Old compat typedefs
|
|
* TODO: remove these?
|
|
*/
|
|
typedef PK_Key_Agreement_Key PK_KA_Key;
|
|
typedef Public_Key X509_PublicKey;
|
|
typedef Private_Key PKCS8_PrivateKey;
|
|
|
|
std::string BOTAN_PUBLIC_API(2,4)
|
|
create_hex_fingerprint(const uint8_t bits[], size_t len,
|
|
const std::string& hash_name);
|
|
|
|
template<typename Alloc>
|
|
std::string create_hex_fingerprint(const std::vector<uint8_t, Alloc>& vec,
|
|
const std::string& hash_name)
|
|
{
|
|
return create_hex_fingerprint(vec.data(), vec.size(), hash_name);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class X509_DN;
|
|
class BigInt;
|
|
|
|
/**
|
|
* Interface for a credentials manager.
|
|
*
|
|
* A type is a fairly static value that represents the general nature
|
|
* of the transaction occurring. Currently used values are "tls-client"
|
|
* and "tls-server". Context represents a hostname, email address,
|
|
* username, or other identifier.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Credentials_Manager
|
|
{
|
|
public:
|
|
virtual ~Credentials_Manager() = default;
|
|
|
|
/**
|
|
* Return a list of the certificates of CAs that we trust in this
|
|
* type/context.
|
|
*
|
|
* @param type specifies the type of operation occurring
|
|
*
|
|
* @param context specifies a context relative to type. For instance
|
|
* for type "tls-client", context specifies the servers name.
|
|
*/
|
|
virtual std::vector<Certificate_Store*> trusted_certificate_authorities(
|
|
const std::string& type,
|
|
const std::string& context);
|
|
|
|
/**
|
|
* Return a cert chain we can use, ordered from leaf to root,
|
|
* or else an empty vector.
|
|
*
|
|
* It is assumed that the caller can get the private key of the
|
|
* leaf with private_key_for
|
|
*
|
|
* @param cert_key_types specifies the key types desired ("RSA",
|
|
* "DSA", "ECDSA", etc), or empty if there
|
|
* is no preference by the caller.
|
|
*
|
|
* @param acceptable_CAs the CAs the requestor will accept (possibly empty)
|
|
* @param type specifies the type of operation occurring
|
|
* @param context specifies a context relative to type.
|
|
*/
|
|
virtual 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 a cert chain we can use, ordered from leaf to root,
|
|
* or else an empty vector.
|
|
*
|
|
* This virtual function is deprecated, and will be removed in a
|
|
* future release. Use (and override) find_cert_chain instead.
|
|
*
|
|
* It is assumed that the caller can get the private key of the
|
|
* leaf with private_key_for
|
|
*
|
|
* @param cert_key_types specifies the key types desired ("RSA",
|
|
* "DSA", "ECDSA", etc), or empty if there
|
|
* is no preference by the caller.
|
|
*
|
|
* @param type specifies the type of operation occurring
|
|
*
|
|
* @param context specifies a context relative to type.
|
|
*/
|
|
virtual std::vector<X509_Certificate> cert_chain(
|
|
const std::vector<std::string>& cert_key_types,
|
|
const std::string& type,
|
|
const std::string& context);
|
|
|
|
/**
|
|
* Return a cert chain we can use, ordered from leaf to root,
|
|
* or else an empty vector.
|
|
*
|
|
* It is assumed that the caller can get the private key of the
|
|
* leaf with private_key_for
|
|
*
|
|
* @param cert_key_type specifies the type of key requested
|
|
* ("RSA", "DSA", "ECDSA", etc)
|
|
*
|
|
* @param type specifies the type of operation occurring
|
|
*
|
|
* @param context specifies a context relative to type.
|
|
*/
|
|
std::vector<X509_Certificate> cert_chain_single_type(
|
|
const std::string& cert_key_type,
|
|
const std::string& type,
|
|
const std::string& context);
|
|
|
|
/**
|
|
* @return private key associated with this certificate if we should
|
|
* use it with this context. cert was returned by cert_chain
|
|
* @note this object should retain ownership of the returned key;
|
|
* it should not be deleted by the caller.
|
|
*/
|
|
virtual Private_Key* private_key_for(const X509_Certificate& cert,
|
|
const std::string& type,
|
|
const std::string& context);
|
|
|
|
/**
|
|
* @param type specifies the type of operation occurring
|
|
* @param context specifies a context relative to type.
|
|
* @return true if we should attempt SRP authentication
|
|
*/
|
|
virtual bool attempt_srp(const std::string& type,
|
|
const std::string& context);
|
|
|
|
/**
|
|
* @param type specifies the type of operation occurring
|
|
* @param context specifies a context relative to type.
|
|
* @return identifier for client-side SRP auth, if available
|
|
for this type/context. Should return empty string
|
|
if password auth not desired/available.
|
|
*/
|
|
virtual std::string srp_identifier(const std::string& type,
|
|
const std::string& context);
|
|
|
|
/**
|
|
* @param type specifies the type of operation occurring
|
|
* @param context specifies a context relative to type.
|
|
* @param identifier specifies what identifier we want the
|
|
* password for. This will be a value previously returned
|
|
* by srp_identifier.
|
|
* @return password for client-side SRP auth, if available
|
|
for this identifier/type/context.
|
|
*/
|
|
virtual std::string srp_password(const std::string& type,
|
|
const std::string& context,
|
|
const std::string& identifier);
|
|
|
|
/**
|
|
* Retrieve SRP verifier parameters
|
|
*/
|
|
virtual 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);
|
|
|
|
/**
|
|
* @param type specifies the type of operation occurring
|
|
* @param context specifies a context relative to type.
|
|
* @return the PSK identity hint for this type/context
|
|
*/
|
|
virtual std::string psk_identity_hint(const std::string& type,
|
|
const std::string& context);
|
|
|
|
/**
|
|
* @param type specifies the type of operation occurring
|
|
* @param context specifies a context relative to type.
|
|
* @param identity_hint was passed by the server (but may be empty)
|
|
* @return the PSK identity we want to use
|
|
*/
|
|
virtual std::string psk_identity(const std::string& type,
|
|
const std::string& context,
|
|
const std::string& identity_hint);
|
|
|
|
/**
|
|
* @param type specifies the type of operation occurring
|
|
* @param context specifies a context relative to type.
|
|
* @param identity is a PSK identity previously returned by
|
|
psk_identity for the same type and context.
|
|
* @return the PSK used for identity, or throw an exception if no
|
|
* key exists
|
|
*/
|
|
virtual SymmetricKey psk(const std::string& type,
|
|
const std::string& context,
|
|
const std::string& identity);
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* This namespace holds various high-level crypto functions
|
|
*/
|
|
namespace CryptoBox {
|
|
|
|
/**
|
|
* Encrypt a message using a passphrase
|
|
* @param input the input data
|
|
* @param input_len the length of input in bytes
|
|
* @param passphrase the passphrase used to encrypt the message
|
|
* @param rng a ref to a random number generator, such as AutoSeeded_RNG
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::string encrypt(const uint8_t input[], size_t input_len,
|
|
const std::string& passphrase,
|
|
RandomNumberGenerator& rng);
|
|
|
|
|
|
/**
|
|
* Decrypt a message encrypted with CryptoBox::encrypt
|
|
* @param input the input data
|
|
* @param input_len the length of input in bytes
|
|
* @param passphrase the passphrase used to encrypt the message
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3)
|
|
secure_vector<uint8_t>
|
|
decrypt_bin(const uint8_t input[], size_t input_len,
|
|
const std::string& passphrase);
|
|
|
|
/**
|
|
* Decrypt a message encrypted with CryptoBox::encrypt
|
|
* @param input the input data
|
|
* @param passphrase the passphrase used to encrypt the message
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3)
|
|
secure_vector<uint8_t>
|
|
decrypt_bin(const std::string& input,
|
|
const std::string& passphrase);
|
|
|
|
/**
|
|
* Decrypt a message encrypted with CryptoBox::encrypt
|
|
* @param input the input data
|
|
* @param input_len the length of input in bytes
|
|
* @param passphrase the passphrase used to encrypt the message
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0)
|
|
std::string decrypt(const uint8_t input[], size_t input_len,
|
|
const std::string& passphrase);
|
|
|
|
/**
|
|
* Decrypt a message encrypted with CryptoBox::encrypt
|
|
* @param input the input data
|
|
* @param passphrase the passphrase used to encrypt the message
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0)
|
|
std::string decrypt(const std::string& input,
|
|
const std::string& passphrase);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(ctr.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* CTR-BE (Counter mode, big-endian)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CTR_BE final : public StreamCipher
|
|
{
|
|
public:
|
|
void cipher(const uint8_t in[], uint8_t out[], size_t length) override;
|
|
|
|
void set_iv(const uint8_t iv[], size_t iv_len) override;
|
|
|
|
size_t default_iv_length() const override;
|
|
|
|
bool valid_iv_length(size_t iv_len) const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
std::string name() const override;
|
|
|
|
CTR_BE* clone() const override;
|
|
|
|
void clear() override;
|
|
|
|
/**
|
|
* @param cipher the block cipher to use
|
|
*/
|
|
explicit CTR_BE(BlockCipher* cipher);
|
|
|
|
CTR_BE(BlockCipher* cipher, size_t ctr_size);
|
|
|
|
void seek(uint64_t offset) override;
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t key_len) override;
|
|
void add_counter(const uint64_t counter);
|
|
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
|
|
const size_t m_block_size;
|
|
const size_t m_ctr_size;
|
|
const size_t m_ctr_blocks;
|
|
|
|
secure_vector<uint8_t> m_counter, m_pad;
|
|
std::vector<uint8_t> m_iv;
|
|
size_t m_pad_pos;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class BOTAN_PUBLIC_API(2,0) Curve25519_PublicKey : public virtual Public_Key
|
|
{
|
|
public:
|
|
std::string algo_name() const override { return "Curve25519"; }
|
|
|
|
size_t estimated_strength() const override { return 128; }
|
|
|
|
size_t key_length() const override { return 255; }
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool strong) const override;
|
|
|
|
AlgorithmIdentifier algorithm_identifier() const override;
|
|
|
|
std::vector<uint8_t> public_key_bits() const override;
|
|
|
|
std::vector<uint8_t> public_value() const { return m_public; }
|
|
|
|
/**
|
|
* Create a Curve25519 Public Key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
Curve25519_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Create a Curve25519 Public Key.
|
|
* @param pub 32-byte raw public key
|
|
*/
|
|
explicit Curve25519_PublicKey(const std::vector<uint8_t>& pub) : m_public(pub) {}
|
|
|
|
/**
|
|
* Create a Curve25519 Public Key.
|
|
* @param pub 32-byte raw public key
|
|
*/
|
|
explicit Curve25519_PublicKey(const secure_vector<uint8_t>& pub) :
|
|
m_public(pub.begin(), pub.end()) {}
|
|
|
|
protected:
|
|
Curve25519_PublicKey() = default;
|
|
std::vector<uint8_t> m_public;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,0) Curve25519_PrivateKey final : public Curve25519_PublicKey,
|
|
public virtual Private_Key,
|
|
public virtual PK_Key_Agreement_Key
|
|
{
|
|
public:
|
|
/**
|
|
* Construct a private key from the specified parameters.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits PKCS #8 structure
|
|
*/
|
|
Curve25519_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Generate a private key.
|
|
* @param rng the RNG to use
|
|
*/
|
|
explicit Curve25519_PrivateKey(RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Construct a private key from the specified parameters.
|
|
* @param secret_key the private key
|
|
*/
|
|
explicit Curve25519_PrivateKey(const secure_vector<uint8_t>& secret_key);
|
|
|
|
std::vector<uint8_t> public_value() const override { return Curve25519_PublicKey::public_value(); }
|
|
|
|
secure_vector<uint8_t> agree(const uint8_t w[], size_t w_len) const;
|
|
|
|
const secure_vector<uint8_t>& get_x() const { return m_private; }
|
|
|
|
secure_vector<uint8_t> private_key_bits() const override;
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool strong) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Key_Agreement>
|
|
create_key_agreement_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
private:
|
|
secure_vector<uint8_t> m_private;
|
|
};
|
|
|
|
typedef Curve25519_PublicKey X25519_PublicKey;
|
|
typedef Curve25519_PrivateKey X25519_PrivateKey;
|
|
|
|
/*
|
|
* The types above are just wrappers for curve25519_donna, plus defining
|
|
* encodings for public and private keys.
|
|
*/
|
|
void BOTAN_PUBLIC_API(2,0) curve25519_donna(uint8_t mypublic[32],
|
|
const uint8_t secret[32],
|
|
const uint8_t basepoint[32]);
|
|
|
|
/**
|
|
* Exponentiate by the x25519 base point
|
|
* @param mypublic output value
|
|
* @param secret random scalar
|
|
*/
|
|
void BOTAN_PUBLIC_API(2,0) curve25519_basepoint(uint8_t mypublic[32],
|
|
const uint8_t secret[32]);
|
|
|
|
}
|
|
|
|
// Currently exposed in PointGFp
|
|
//BOTAN_FUTURE_INTERNAL_HEADER(curve_gfp.h)
|
|
|
|
namespace Botan {
|
|
|
|
class BOTAN_UNSTABLE_API CurveGFp_Repr
|
|
{
|
|
public:
|
|
virtual ~CurveGFp_Repr() = default;
|
|
|
|
virtual const BigInt& get_p() const = 0;
|
|
virtual const BigInt& get_a() const = 0;
|
|
virtual const BigInt& get_b() const = 0;
|
|
|
|
virtual size_t get_p_words() const = 0;
|
|
|
|
virtual size_t get_ws_size() const = 0;
|
|
|
|
virtual bool is_one(const BigInt& x) const = 0;
|
|
|
|
virtual bool a_is_zero() const = 0;
|
|
|
|
virtual bool a_is_minus_3() const = 0;
|
|
|
|
/*
|
|
* Returns to_curve_rep(get_a())
|
|
*/
|
|
virtual const BigInt& get_a_rep() const = 0;
|
|
|
|
/*
|
|
* Returns to_curve_rep(get_b())
|
|
*/
|
|
virtual const BigInt& get_b_rep() const = 0;
|
|
|
|
/*
|
|
* Returns to_curve_rep(1)
|
|
*/
|
|
virtual const BigInt& get_1_rep() const = 0;
|
|
|
|
virtual BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const = 0;
|
|
|
|
virtual void to_curve_rep(BigInt& x, secure_vector<word>& ws) const = 0;
|
|
|
|
virtual void from_curve_rep(BigInt& x, secure_vector<word>& ws) const = 0;
|
|
|
|
void curve_mul(BigInt& z, const BigInt& x, const BigInt& y,
|
|
secure_vector<word>& ws) const
|
|
{
|
|
BOTAN_DEBUG_ASSERT(x.sig_words() <= get_p_words());
|
|
curve_mul_words(z, x.data(), x.size(), y, ws);
|
|
}
|
|
|
|
virtual void curve_mul_words(BigInt& z,
|
|
const word x_words[],
|
|
const size_t x_size,
|
|
const BigInt& y,
|
|
secure_vector<word>& ws) const = 0;
|
|
|
|
void curve_sqr(BigInt& z, const BigInt& x,
|
|
secure_vector<word>& ws) const
|
|
{
|
|
BOTAN_DEBUG_ASSERT(x.sig_words() <= get_p_words());
|
|
curve_sqr_words(z, x.data(), x.size(), ws);
|
|
}
|
|
|
|
virtual void curve_sqr_words(BigInt& z,
|
|
const word x_words[],
|
|
size_t x_size,
|
|
secure_vector<word>& ws) const = 0;
|
|
};
|
|
|
|
/**
|
|
* This class represents an elliptic curve over GF(p)
|
|
*
|
|
* There should not be any reason for applications to use this type.
|
|
* If you need EC primitives use the interfaces EC_Group and PointGFp
|
|
*
|
|
* It is likely this class will be removed entirely in a future major
|
|
* release.
|
|
*/
|
|
class BOTAN_UNSTABLE_API CurveGFp final
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Create an uninitialized CurveGFp
|
|
*/
|
|
CurveGFp() = default;
|
|
|
|
/**
|
|
* Construct the elliptic curve E: y^2 = x^3 + ax + b over GF(p)
|
|
* @param p prime number of the field
|
|
* @param a first coefficient
|
|
* @param b second coefficient
|
|
*/
|
|
CurveGFp(const BigInt& p, const BigInt& a, const BigInt& b) :
|
|
m_repr(choose_repr(p, a, b))
|
|
{
|
|
}
|
|
|
|
CurveGFp(const CurveGFp&) = default;
|
|
|
|
CurveGFp& operator=(const CurveGFp&) = default;
|
|
|
|
/**
|
|
* @return curve coefficient a
|
|
*/
|
|
const BigInt& get_a() const { return m_repr->get_a(); }
|
|
|
|
/**
|
|
* @return curve coefficient b
|
|
*/
|
|
const BigInt& get_b() const { return m_repr->get_b(); }
|
|
|
|
/**
|
|
* Get prime modulus of the field of the curve
|
|
* @return prime modulus of the field of the curve
|
|
*/
|
|
const BigInt& get_p() const { return m_repr->get_p(); }
|
|
|
|
size_t get_p_words() const { return m_repr->get_p_words(); }
|
|
|
|
size_t get_ws_size() const { return m_repr->get_ws_size(); }
|
|
|
|
const BigInt& get_a_rep() const { return m_repr->get_a_rep(); }
|
|
|
|
const BigInt& get_b_rep() const { return m_repr->get_b_rep(); }
|
|
|
|
const BigInt& get_1_rep() const { return m_repr->get_1_rep(); }
|
|
|
|
bool a_is_minus_3() const { return m_repr->a_is_minus_3(); }
|
|
bool a_is_zero() const { return m_repr->a_is_zero(); }
|
|
|
|
bool is_one(const BigInt& x) const { return m_repr->is_one(x); }
|
|
|
|
BigInt invert_element(const BigInt& x, secure_vector<word>& ws) const
|
|
{
|
|
return m_repr->invert_element(x, ws);
|
|
}
|
|
|
|
void to_rep(BigInt& x, secure_vector<word>& ws) const
|
|
{
|
|
m_repr->to_curve_rep(x, ws);
|
|
}
|
|
|
|
void from_rep(BigInt& x, secure_vector<word>& ws) const
|
|
{
|
|
m_repr->from_curve_rep(x, ws);
|
|
}
|
|
|
|
BigInt from_rep_to_tmp(const BigInt& x, secure_vector<word>& ws) const
|
|
{
|
|
BigInt xt(x);
|
|
m_repr->from_curve_rep(xt, ws);
|
|
return xt;
|
|
}
|
|
|
|
// TODO: from_rep taking && ref
|
|
|
|
void mul(BigInt& z, const BigInt& x, const BigInt& y, secure_vector<word>& ws) const
|
|
{
|
|
m_repr->curve_mul(z, x, y, ws);
|
|
}
|
|
|
|
void mul(BigInt& z, const word x_w[], size_t x_size,
|
|
const BigInt& y, secure_vector<word>& ws) const
|
|
{
|
|
m_repr->curve_mul_words(z, x_w, x_size, y, ws);
|
|
}
|
|
|
|
void sqr(BigInt& z, const BigInt& x, secure_vector<word>& ws) const
|
|
{
|
|
m_repr->curve_sqr(z, x, ws);
|
|
}
|
|
|
|
void sqr(BigInt& z, const word x_w[], size_t x_size, secure_vector<word>& ws) const
|
|
{
|
|
m_repr->curve_sqr_words(z, x_w, x_size, ws);
|
|
}
|
|
|
|
BigInt mul(const BigInt& x, const BigInt& y, secure_vector<word>& ws) const
|
|
{
|
|
return mul_to_tmp(x, y, ws);
|
|
}
|
|
|
|
BigInt sqr(const BigInt& x, secure_vector<word>& ws) const
|
|
{
|
|
return sqr_to_tmp(x, ws);
|
|
}
|
|
|
|
BigInt mul_to_tmp(const BigInt& x, const BigInt& y, secure_vector<word>& ws) const
|
|
{
|
|
BigInt z;
|
|
m_repr->curve_mul(z, x, y, ws);
|
|
return z;
|
|
}
|
|
|
|
BigInt sqr_to_tmp(const BigInt& x, secure_vector<word>& ws) const
|
|
{
|
|
BigInt z;
|
|
m_repr->curve_sqr(z, x, ws);
|
|
return z;
|
|
}
|
|
|
|
void swap(CurveGFp& other)
|
|
{
|
|
std::swap(m_repr, other.m_repr);
|
|
}
|
|
|
|
/**
|
|
* Equality operator
|
|
* @param other a curve
|
|
* @return true iff *this is the same as other
|
|
*/
|
|
inline bool operator==(const CurveGFp& other) const
|
|
{
|
|
if(m_repr.get() == other.m_repr.get())
|
|
return true;
|
|
|
|
return (get_p() == other.get_p()) &&
|
|
(get_a() == other.get_a()) &&
|
|
(get_b() == other.get_b());
|
|
}
|
|
|
|
private:
|
|
static std::shared_ptr<CurveGFp_Repr>
|
|
choose_repr(const BigInt& p, const BigInt& a, const BigInt& b);
|
|
|
|
std::shared_ptr<CurveGFp_Repr> m_repr;
|
|
};
|
|
|
|
inline bool operator!=(const CurveGFp& lhs, const CurveGFp& rhs)
|
|
{
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
}
|
|
|
|
namespace std {
|
|
|
|
template<> inline
|
|
void swap<Botan::CurveGFp>(Botan::CurveGFp& curve1,
|
|
Botan::CurveGFp& curve2) noexcept
|
|
{
|
|
curve1.swap(curve2);
|
|
}
|
|
|
|
} // namespace std
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(curve_nistp.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* NIST Prime reduction functions.
|
|
*
|
|
* Reduces the value in place
|
|
*
|
|
* ws is a workspace function which is used as a temporary,
|
|
* and will be resized as needed.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) const BigInt& prime_p521();
|
|
BOTAN_PUBLIC_API(2,0) void redc_p521(BigInt& x, secure_vector<word>& ws);
|
|
|
|
/*
|
|
Previously this macro indicated if the P-{192,224,256,384} reducers
|
|
were available. Now they are always enabled and this macro has no meaning.
|
|
The define will be removed in a future major release.
|
|
*/
|
|
#define BOTAN_HAS_NIST_PRIME_REDUCERS_W32
|
|
|
|
BOTAN_PUBLIC_API(2,0) const BigInt& prime_p384();
|
|
BOTAN_PUBLIC_API(2,0) void redc_p384(BigInt& x, secure_vector<word>& ws);
|
|
|
|
BOTAN_PUBLIC_API(2,0) const BigInt& prime_p256();
|
|
BOTAN_PUBLIC_API(2,0) void redc_p256(BigInt& x, secure_vector<word>& ws);
|
|
|
|
BOTAN_PUBLIC_API(2,0) const BigInt& prime_p224();
|
|
BOTAN_PUBLIC_API(2,0) void redc_p224(BigInt& x, secure_vector<word>& ws);
|
|
|
|
BOTAN_PUBLIC_API(2,0) const BigInt& prime_p192();
|
|
BOTAN_PUBLIC_API(2,0) void redc_p192(BigInt& x, secure_vector<word>& ws);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents general abstract filter objects.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Filter
|
|
{
|
|
public:
|
|
/**
|
|
* @return descriptive name for this filter
|
|
*/
|
|
virtual std::string name() const = 0;
|
|
|
|
/**
|
|
* Write a portion of a message to this filter.
|
|
* @param input the input as a byte array
|
|
* @param length the length of the byte array input
|
|
*/
|
|
virtual void write(const uint8_t input[], size_t length) = 0;
|
|
|
|
/**
|
|
* Start a new message. Must be closed by end_msg() before another
|
|
* message can be started.
|
|
*/
|
|
virtual void start_msg() { /* default empty */ }
|
|
|
|
/**
|
|
* Notify that the current message is finished; flush buffers and
|
|
* do end-of-message processing (if any).
|
|
*/
|
|
virtual void end_msg() { /* default empty */ }
|
|
|
|
/**
|
|
* Check whether this filter is an attachable filter.
|
|
* @return true if this filter is attachable, false otherwise
|
|
*/
|
|
virtual bool attachable() { return true; }
|
|
|
|
virtual ~Filter() = default;
|
|
protected:
|
|
/**
|
|
* @param in some input for the filter
|
|
* @param length the length of in
|
|
*/
|
|
virtual void send(const uint8_t in[], size_t length);
|
|
|
|
/**
|
|
* @param in some input for the filter
|
|
*/
|
|
void send(uint8_t in) { send(&in, 1); }
|
|
|
|
/**
|
|
* @param in some input for the filter
|
|
*/
|
|
template<typename Alloc>
|
|
void send(const std::vector<uint8_t, Alloc>& in)
|
|
{
|
|
send(in.data(), in.size());
|
|
}
|
|
|
|
/**
|
|
* @param in some input for the filter
|
|
* @param length the number of bytes of in to send
|
|
*/
|
|
template<typename Alloc>
|
|
void send(const std::vector<uint8_t, Alloc>& in, size_t length)
|
|
{
|
|
BOTAN_ASSERT_NOMSG(length <= in.size());
|
|
send(in.data(), length);
|
|
}
|
|
|
|
Filter();
|
|
|
|
Filter(const Filter&) = delete;
|
|
|
|
Filter& operator=(const Filter&) = delete;
|
|
|
|
private:
|
|
/**
|
|
* Start a new message in *this and all following filters. Only for
|
|
* internal use, not intended for use in client applications.
|
|
*/
|
|
void new_msg();
|
|
|
|
/**
|
|
* End a new message in *this and all following filters. Only for
|
|
* internal use, not intended for use in client applications.
|
|
*/
|
|
void finish_msg();
|
|
|
|
friend class Pipe;
|
|
friend class Fanout_Filter;
|
|
|
|
size_t total_ports() const;
|
|
size_t current_port() const { return m_port_num; }
|
|
|
|
/**
|
|
* Set the active port
|
|
* @param new_port the new value
|
|
*/
|
|
void set_port(size_t new_port);
|
|
|
|
size_t owns() const { return m_filter_owns; }
|
|
|
|
/**
|
|
* Attach another filter to this one
|
|
* @param f filter to attach
|
|
*/
|
|
void attach(Filter* f);
|
|
|
|
/**
|
|
* @param filters the filters to set
|
|
* @param count number of items in filters
|
|
*/
|
|
void set_next(Filter* filters[], size_t count);
|
|
Filter* get_next() const;
|
|
|
|
secure_vector<uint8_t> m_write_queue;
|
|
std::vector<Filter*> m_next; // not owned
|
|
size_t m_port_num, m_filter_owns;
|
|
|
|
// true if filter belongs to a pipe --> prohibit filter sharing!
|
|
bool m_owned;
|
|
};
|
|
|
|
/**
|
|
* This is the abstract Fanout_Filter base class.
|
|
**/
|
|
class BOTAN_PUBLIC_API(2,0) Fanout_Filter : public Filter
|
|
{
|
|
protected:
|
|
/**
|
|
* Increment the number of filters past us that we own
|
|
*/
|
|
void incr_owns() { ++m_filter_owns; }
|
|
|
|
void set_port(size_t n) { Filter::set_port(n); }
|
|
|
|
void set_next(Filter* f[], size_t n) { Filter::set_next(f, n); }
|
|
|
|
void attach(Filter* f) { Filter::attach(f); }
|
|
|
|
private:
|
|
friend class Threaded_Fork;
|
|
using Filter::m_write_queue;
|
|
using Filter::total_ports;
|
|
using Filter::m_next;
|
|
};
|
|
|
|
/**
|
|
* The type of checking to be performed by decoders:
|
|
* NONE - no checks, IGNORE_WS - perform checks, but ignore
|
|
* whitespaces, FULL_CHECK - perform checks, also complain
|
|
* about white spaces.
|
|
*/
|
|
enum Decoder_Checking { NONE, IGNORE_WS, FULL_CHECK };
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents abstract data sink objects.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DataSink : public Filter
|
|
{
|
|
public:
|
|
bool attachable() override { return false; }
|
|
DataSink() = default;
|
|
virtual ~DataSink() = default;
|
|
|
|
DataSink& operator=(const DataSink&) = delete;
|
|
DataSink(const DataSink&) = delete;
|
|
};
|
|
|
|
/**
|
|
* This class represents a data sink which writes its output to a stream.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DataSink_Stream final : public DataSink
|
|
{
|
|
public:
|
|
/**
|
|
* Construct a DataSink_Stream from a stream.
|
|
* @param stream the stream to write to
|
|
* @param name identifier
|
|
*/
|
|
DataSink_Stream(std::ostream& stream,
|
|
const std::string& name = "<std::ostream>");
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
|
|
|
|
/**
|
|
* Construct a DataSink_Stream from a filesystem path name.
|
|
* @param pathname the name of the file to open a stream to
|
|
* @param use_binary indicates whether to treat the file
|
|
* as a binary file or not
|
|
*/
|
|
DataSink_Stream(const std::string& pathname,
|
|
bool use_binary = false);
|
|
#endif
|
|
|
|
std::string name() const override { return m_identifier; }
|
|
|
|
void write(const uint8_t[], size_t) override;
|
|
|
|
void end_msg() override;
|
|
|
|
~DataSink_Stream();
|
|
|
|
private:
|
|
const std::string m_identifier;
|
|
|
|
// May be null, if m_sink was an external reference
|
|
std::unique_ptr<std::ostream> m_sink_memory;
|
|
std::ostream& m_sink;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class X509_Certificate;
|
|
class Data_Store;
|
|
class Public_Key;
|
|
|
|
/**
|
|
* Check that key constraints are permitted for a specific public key.
|
|
* @param pub_key the public key on which the constraints shall be enforced on
|
|
* @param constraints the constraints that shall be enforced on the key
|
|
* @throw Invalid_Argument if the given constraints are not permitted for this key
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) void verify_cert_constraints_valid_for_key_type(const Public_Key& pub_key,
|
|
Key_Constraints constraints);
|
|
|
|
std::string BOTAN_PUBLIC_API(2,0) key_constraints_to_string(Key_Constraints);
|
|
|
|
/**
|
|
* Distinguished Name
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) X509_DN final : public ASN1_Object
|
|
{
|
|
public:
|
|
X509_DN() = default;
|
|
|
|
explicit X509_DN(const std::multimap<OID, std::string>& args)
|
|
{
|
|
for(auto i : args)
|
|
add_attribute(i.first, i.second);
|
|
}
|
|
|
|
explicit X509_DN(const std::multimap<std::string, std::string>& args)
|
|
{
|
|
for(auto i : args)
|
|
add_attribute(i.first, i.second);
|
|
}
|
|
|
|
void encode_into(DER_Encoder&) const override;
|
|
void decode_from(BER_Decoder&) override;
|
|
|
|
bool has_field(const OID& oid) const;
|
|
ASN1_String get_first_attribute(const OID& oid) const;
|
|
|
|
/*
|
|
* Return the BER encoded data, if any
|
|
*/
|
|
const std::vector<uint8_t>& get_bits() const { return m_dn_bits; }
|
|
|
|
bool empty() const { return m_rdn.empty(); }
|
|
|
|
std::string to_string() const;
|
|
|
|
const std::vector<std::pair<OID,ASN1_String>>& dn_info() const { return m_rdn; }
|
|
|
|
std::multimap<OID, std::string> get_attributes() const;
|
|
std::multimap<std::string, std::string> contents() const;
|
|
|
|
bool has_field(const std::string& attr) const;
|
|
std::vector<std::string> get_attribute(const std::string& attr) const;
|
|
std::string get_first_attribute(const std::string& attr) const;
|
|
|
|
void add_attribute(const std::string& key, const std::string& val);
|
|
|
|
void add_attribute(const OID& oid, const std::string& val)
|
|
{
|
|
add_attribute(oid, ASN1_String(val));
|
|
}
|
|
|
|
void add_attribute(const OID& oid, const ASN1_String& val);
|
|
|
|
static std::string deref_info_field(const std::string& key);
|
|
|
|
/**
|
|
* Lookup upper bounds in characters for the length of distinguished name fields
|
|
* as given in RFC 5280, Appendix A.
|
|
*
|
|
* @param oid the oid of the DN to lookup
|
|
* @return the upper bound, or zero if no ub is known to Botan
|
|
*/
|
|
static size_t lookup_ub(const OID& oid);
|
|
|
|
private:
|
|
std::vector<std::pair<OID,ASN1_String>> m_rdn;
|
|
std::vector<uint8_t> m_dn_bits;
|
|
};
|
|
|
|
bool BOTAN_PUBLIC_API(2,0) operator==(const X509_DN& dn1, const X509_DN& dn2);
|
|
bool BOTAN_PUBLIC_API(2,0) operator!=(const X509_DN& dn1, const X509_DN& dn2);
|
|
|
|
/*
|
|
The ordering here is arbitrary and may change from release to release.
|
|
It is intended for allowing DNs as keys in std::map and similiar containers
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,0) operator<(const X509_DN& dn1, const X509_DN& dn2);
|
|
|
|
BOTAN_PUBLIC_API(2,0) std::ostream& operator<<(std::ostream& out, const X509_DN& dn);
|
|
BOTAN_PUBLIC_API(2,0) std::istream& operator>>(std::istream& in, X509_DN& dn);
|
|
|
|
/**
|
|
* Alternative Name
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) AlternativeName final : public ASN1_Object
|
|
{
|
|
public:
|
|
void encode_into(DER_Encoder&) const override;
|
|
void decode_from(BER_Decoder&) override;
|
|
|
|
std::multimap<std::string, std::string> contents() const;
|
|
|
|
bool has_field(const std::string& attr) const;
|
|
std::vector<std::string> get_attribute(const std::string& attr) const;
|
|
|
|
std::string get_first_attribute(const std::string& attr) const;
|
|
|
|
void add_attribute(const std::string& type, const std::string& value);
|
|
void add_othername(const OID& oid, const std::string& value, ASN1_Tag type);
|
|
|
|
const std::multimap<std::string, std::string>& get_attributes() const
|
|
{
|
|
return m_alt_info;
|
|
}
|
|
|
|
const std::multimap<OID, ASN1_String>& get_othernames() const
|
|
{
|
|
return m_othernames;
|
|
}
|
|
|
|
X509_DN dn() const;
|
|
|
|
bool has_items() const;
|
|
|
|
AlternativeName(const std::string& email_addr = "",
|
|
const std::string& uri = "",
|
|
const std::string& dns = "",
|
|
const std::string& ip_address = "");
|
|
private:
|
|
std::multimap<std::string, std::string> m_alt_info;
|
|
std::multimap<OID, ASN1_String> m_othernames;
|
|
};
|
|
|
|
/**
|
|
* Attribute
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Attribute final : public ASN1_Object
|
|
{
|
|
public:
|
|
void encode_into(DER_Encoder& to) const override;
|
|
void decode_from(BER_Decoder& from) override;
|
|
|
|
Attribute() = default;
|
|
Attribute(const OID&, const std::vector<uint8_t>&);
|
|
Attribute(const std::string&, const std::vector<uint8_t>&);
|
|
|
|
const OID& get_oid() const { return oid; }
|
|
|
|
const std::vector<uint8_t>& get_parameters() const { return parameters; }
|
|
|
|
BOTAN_DEPRECATED_PUBLIC_MEMBER_VARIABLES:
|
|
/*
|
|
* These values are public for historical reasons, but in a future release
|
|
* they will be made private. Do not access them.
|
|
*/
|
|
OID oid;
|
|
std::vector<uint8_t> parameters;
|
|
};
|
|
|
|
/**
|
|
* @brief X.509 GeneralName Type
|
|
*
|
|
* Handles parsing GeneralName types in their BER and canonical string
|
|
* encoding. Allows matching GeneralNames against each other using
|
|
* the rules laid out in the RFC 5280, sec. 4.2.1.10 (Name Contraints).
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GeneralName final : public ASN1_Object
|
|
{
|
|
public:
|
|
enum MatchResult : int
|
|
{
|
|
All,
|
|
Some,
|
|
None,
|
|
NotFound,
|
|
UnknownType,
|
|
};
|
|
|
|
/**
|
|
* Creates an empty GeneralName.
|
|
*/
|
|
GeneralName() = default;
|
|
|
|
/**
|
|
* Creates a new GeneralName for its string format.
|
|
* @param str type and name, colon-separated, e.g., "DNS:google.com"
|
|
*/
|
|
GeneralName(const std::string& str);
|
|
|
|
void encode_into(DER_Encoder&) const override;
|
|
|
|
void decode_from(BER_Decoder&) override;
|
|
|
|
/**
|
|
* @return Type of the name. Can be DN, DNS, IP, RFC822 or URI.
|
|
*/
|
|
const std::string& type() const { return m_type; }
|
|
|
|
/**
|
|
* @return The name as string. Format depends on type.
|
|
*/
|
|
const std::string& name() const { return m_name; }
|
|
|
|
/**
|
|
* Checks whether a given certificate (partially) matches this name.
|
|
* @param cert certificate to be matched
|
|
* @return the match result
|
|
*/
|
|
MatchResult matches(const X509_Certificate& cert) const;
|
|
|
|
private:
|
|
std::string m_type;
|
|
std::string m_name;
|
|
|
|
bool matches_dns(const std::string&) const;
|
|
bool matches_dn(const std::string&) const;
|
|
bool matches_ip(const std::string&) const;
|
|
};
|
|
|
|
std::ostream& operator<<(std::ostream& os, const GeneralName& gn);
|
|
|
|
/**
|
|
* @brief A single Name Constraint
|
|
*
|
|
* The Name Constraint extension adds a minimum and maximum path
|
|
* length to a GeneralName to form a constraint. The length limits
|
|
* are currently unused.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GeneralSubtree final : public ASN1_Object
|
|
{
|
|
public:
|
|
/**
|
|
* Creates an empty name constraint.
|
|
*/
|
|
GeneralSubtree() : m_base(), m_minimum(0), m_maximum(std::numeric_limits<std::size_t>::max())
|
|
{}
|
|
|
|
/***
|
|
* Creates a new name constraint.
|
|
* @param base name
|
|
* @param min minimum path length
|
|
* @param max maximum path length
|
|
*/
|
|
GeneralSubtree(const GeneralName& base, size_t min, size_t max)
|
|
: m_base(base), m_minimum(min), m_maximum(max)
|
|
{}
|
|
|
|
/**
|
|
* Creates a new name constraint for its string format.
|
|
* @param str name constraint
|
|
*/
|
|
GeneralSubtree(const std::string& str);
|
|
|
|
void encode_into(DER_Encoder&) const override;
|
|
|
|
void decode_from(BER_Decoder&) override;
|
|
|
|
/**
|
|
* @return name
|
|
*/
|
|
const GeneralName& base() const { return m_base; }
|
|
|
|
/**
|
|
* @return minimum path length
|
|
*/
|
|
size_t minimum() const { return m_minimum; }
|
|
|
|
/**
|
|
* @return maximum path length
|
|
*/
|
|
size_t maximum() const { return m_maximum; }
|
|
|
|
private:
|
|
GeneralName m_base;
|
|
size_t m_minimum;
|
|
size_t m_maximum;
|
|
};
|
|
|
|
std::ostream& operator<<(std::ostream& os, const GeneralSubtree& gs);
|
|
|
|
/**
|
|
* @brief Name Constraints
|
|
*
|
|
* Wraps the Name Constraints associated with a certificate.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) NameConstraints final
|
|
{
|
|
public:
|
|
/**
|
|
* Creates an empty name NameConstraints.
|
|
*/
|
|
NameConstraints() : m_permitted_subtrees(), m_excluded_subtrees() {}
|
|
|
|
/**
|
|
* Creates NameConstraints from a list of permitted and excluded subtrees.
|
|
* @param permitted_subtrees names for which the certificate is permitted
|
|
* @param excluded_subtrees names for which the certificate is not permitted
|
|
*/
|
|
NameConstraints(std::vector<GeneralSubtree>&& permitted_subtrees,
|
|
std::vector<GeneralSubtree>&& excluded_subtrees)
|
|
: m_permitted_subtrees(permitted_subtrees), m_excluded_subtrees(excluded_subtrees)
|
|
{}
|
|
|
|
/**
|
|
* @return permitted names
|
|
*/
|
|
const std::vector<GeneralSubtree>& permitted() const { return m_permitted_subtrees; }
|
|
|
|
/**
|
|
* @return excluded names
|
|
*/
|
|
const std::vector<GeneralSubtree>& excluded() const { return m_excluded_subtrees; }
|
|
|
|
private:
|
|
std::vector<GeneralSubtree> m_permitted_subtrees;
|
|
std::vector<GeneralSubtree> m_excluded_subtrees;
|
|
};
|
|
|
|
/**
|
|
* X.509 Certificate Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Certificate_Extension
|
|
{
|
|
public:
|
|
/**
|
|
* @return OID representing this extension
|
|
*/
|
|
virtual OID oid_of() const = 0;
|
|
|
|
/*
|
|
* @return specific OID name
|
|
* If possible OIDS table should match oid_name to OIDS, ie
|
|
* OID::from_string(ext->oid_name()) == ext->oid_of()
|
|
* Should return empty string if OID is not known
|
|
*/
|
|
virtual std::string oid_name() const = 0;
|
|
|
|
/**
|
|
* Make a copy of this extension
|
|
* @return copy of this
|
|
*/
|
|
virtual Certificate_Extension* copy() const = 0;
|
|
|
|
/*
|
|
* Add the contents of this extension into the information
|
|
* for the subject and/or issuer, as necessary.
|
|
* @param subject the subject info
|
|
* @param issuer the issuer info
|
|
*/
|
|
virtual void contents_to(Data_Store& subject,
|
|
Data_Store& issuer) const = 0;
|
|
|
|
/*
|
|
* Callback visited during path validation.
|
|
*
|
|
* An extension can implement this callback to inspect
|
|
* the path during path validation.
|
|
*
|
|
* If an error occurs during validation of this extension,
|
|
* an appropriate status code shall be added to cert_status.
|
|
*
|
|
* @param subject Subject certificate that contains this extension
|
|
* @param issuer Issuer certificate
|
|
* @param status Certificate validation status codes for subject certificate
|
|
* @param cert_path Certificate path which is currently validated
|
|
* @param pos Position of subject certificate in cert_path
|
|
*/
|
|
virtual void validate(const X509_Certificate& subject, const X509_Certificate& issuer,
|
|
const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
|
|
std::vector<std::set<Certificate_Status_Code>>& cert_status,
|
|
size_t pos);
|
|
|
|
virtual ~Certificate_Extension() = default;
|
|
protected:
|
|
friend class Extensions;
|
|
virtual bool should_encode() const { return true; }
|
|
virtual std::vector<uint8_t> encode_inner() const = 0;
|
|
virtual void decode_inner(const std::vector<uint8_t>&) = 0;
|
|
};
|
|
|
|
/**
|
|
* X.509 Certificate Extension List
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Extensions final : public ASN1_Object
|
|
{
|
|
public:
|
|
/**
|
|
* Look up an object in the extensions, based on OID Returns
|
|
* nullptr if not set, if the extension was either absent or not
|
|
* handled. The pointer returned is owned by the Extensions
|
|
* object.
|
|
* This would be better with an optional<T> return value
|
|
*/
|
|
const Certificate_Extension* get_extension_object(const OID& oid) const;
|
|
|
|
template<typename T>
|
|
const T* get_extension_object_as(const OID& oid = T::static_oid()) const
|
|
{
|
|
if(const Certificate_Extension* extn = get_extension_object(oid))
|
|
{
|
|
// Unknown_Extension oid_name is empty
|
|
if(extn->oid_name().empty())
|
|
{
|
|
return nullptr;
|
|
}
|
|
else if(const T* extn_as_T = dynamic_cast<const T*>(extn))
|
|
{
|
|
return extn_as_T;
|
|
}
|
|
else
|
|
{
|
|
throw Decoding_Error("Exception::get_extension_object_as dynamic_cast failed");
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
/**
|
|
* Return the set of extensions in the order they appeared in the certificate
|
|
* (or as they were added, if constructed)
|
|
*/
|
|
const std::vector<OID>& get_extension_oids() const
|
|
{
|
|
return m_extension_oids;
|
|
}
|
|
|
|
/**
|
|
* Return true if an extension was set
|
|
*/
|
|
bool extension_set(const OID& oid) const;
|
|
|
|
/**
|
|
* Return true if an extesion was set and marked critical
|
|
*/
|
|
bool critical_extension_set(const OID& oid) const;
|
|
|
|
/**
|
|
* Return the raw bytes of the extension
|
|
* Will throw if OID was not set as an extension.
|
|
*/
|
|
std::vector<uint8_t> get_extension_bits(const OID& oid) const;
|
|
|
|
void encode_into(class DER_Encoder&) const override;
|
|
void decode_from(class BER_Decoder&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const;
|
|
|
|
/**
|
|
* Adds a new extension to the list.
|
|
* @param extn pointer to the certificate extension (Extensions takes ownership)
|
|
* @param critical whether this extension should be marked as critical
|
|
* @throw Invalid_Argument if the extension is already present in the list
|
|
*/
|
|
void add(Certificate_Extension* extn, bool critical = false);
|
|
|
|
/**
|
|
* Adds a new extension to the list unless it already exists. If the extension
|
|
* already exists within the Extensions object, the extn pointer will be deleted.
|
|
*
|
|
* @param extn pointer to the certificate extension (Extensions takes ownership)
|
|
* @param critical whether this extension should be marked as critical
|
|
* @return true if the object was added false if the extension was already used
|
|
*/
|
|
bool add_new(Certificate_Extension* extn, bool critical = false);
|
|
|
|
/**
|
|
* Adds an extension to the list or replaces it.
|
|
* @param extn the certificate extension
|
|
* @param critical whether this extension should be marked as critical
|
|
*/
|
|
void replace(Certificate_Extension* extn, bool critical = false);
|
|
|
|
/**
|
|
* Remove an extension from the list. Returns true if the
|
|
* extension had been set, false otherwise.
|
|
*/
|
|
bool remove(const OID& oid);
|
|
|
|
/**
|
|
* Searches for an extension by OID and returns the result.
|
|
* Only the known extensions types declared in this header
|
|
* are searched for by this function.
|
|
* @return Copy of extension with oid, nullptr if not found.
|
|
* Can avoid creating a copy by using get_extension_object function
|
|
*/
|
|
std::unique_ptr<Certificate_Extension> get(const OID& oid) const;
|
|
|
|
/**
|
|
* Searches for an extension by OID and returns the result decoding
|
|
* it to some arbitrary extension type chosen by the application.
|
|
*
|
|
* Only the unknown extensions, that is, extensions types that
|
|
* are not declared in this header, are searched for by this
|
|
* function.
|
|
*
|
|
* @return Pointer to new extension with oid, nullptr if not found.
|
|
*/
|
|
template<typename T>
|
|
std::unique_ptr<T> get_raw(const OID& oid) const
|
|
{
|
|
auto extn_info = m_extension_info.find(oid);
|
|
|
|
if(extn_info != m_extension_info.end())
|
|
{
|
|
// Unknown_Extension oid_name is empty
|
|
if(extn_info->second.obj().oid_name() == "")
|
|
{
|
|
std::unique_ptr<T> ext(new T);
|
|
ext->decode_inner(extn_info->second.bits());
|
|
return ext;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
/**
|
|
* Returns a copy of the list of extensions together with the corresponding
|
|
* criticality flag. All extensions are encoded as some object, falling back
|
|
* to Unknown_Extension class which simply allows reading the bytes as well
|
|
* as the criticality flag.
|
|
*/
|
|
std::vector<std::pair<std::unique_ptr<Certificate_Extension>, bool>> extensions() const;
|
|
|
|
/**
|
|
* Returns the list of extensions as raw, encoded bytes
|
|
* together with the corresponding criticality flag.
|
|
* Contains all extensions, including any extensions encoded as Unknown_Extension
|
|
*/
|
|
std::map<OID, std::pair<std::vector<uint8_t>, bool>> extensions_raw() const;
|
|
|
|
Extensions() {}
|
|
|
|
Extensions(const Extensions&) = default;
|
|
Extensions& operator=(const Extensions&) = default;
|
|
|
|
Extensions(Extensions&&) = default;
|
|
Extensions& operator=(Extensions&&) = default;
|
|
|
|
private:
|
|
static std::unique_ptr<Certificate_Extension>
|
|
create_extn_obj(const OID& oid,
|
|
bool critical,
|
|
const std::vector<uint8_t>& body);
|
|
|
|
class Extensions_Info
|
|
{
|
|
public:
|
|
Extensions_Info(bool critical,
|
|
Certificate_Extension* ext) :
|
|
m_obj(ext),
|
|
m_bits(m_obj->encode_inner()),
|
|
m_critical(critical)
|
|
{
|
|
}
|
|
|
|
Extensions_Info(bool critical,
|
|
const std::vector<uint8_t>& encoding,
|
|
Certificate_Extension* ext) :
|
|
m_obj(ext),
|
|
m_bits(encoding),
|
|
m_critical(critical)
|
|
{
|
|
}
|
|
|
|
bool is_critical() const { return m_critical; }
|
|
const std::vector<uint8_t>& bits() const { return m_bits; }
|
|
const Certificate_Extension& obj() const
|
|
{
|
|
BOTAN_ASSERT_NONNULL(m_obj.get());
|
|
return *m_obj.get();
|
|
}
|
|
|
|
private:
|
|
std::shared_ptr<Certificate_Extension> m_obj;
|
|
std::vector<uint8_t> m_bits;
|
|
bool m_critical = false;
|
|
};
|
|
|
|
std::vector<OID> m_extension_oids;
|
|
std::map<OID, Extensions_Info> m_extension_info;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(datastor.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Data Store
|
|
*
|
|
* This class is used internally by the library, and exposed for ABI
|
|
* reasons. There is no reason for applications to use this type directly.
|
|
* It will be removed in a future major release.
|
|
*/
|
|
class BOTAN_UNSTABLE_API Data_Store final
|
|
{
|
|
public:
|
|
/**
|
|
* A search function
|
|
*/
|
|
bool operator==(const Data_Store&) const;
|
|
|
|
std::multimap<std::string, std::string> search_for(
|
|
std::function<bool (std::string, std::string)> predicate) const;
|
|
|
|
std::vector<std::string> get(const std::string&) const;
|
|
|
|
std::string get1(const std::string& key) const;
|
|
|
|
std::string get1(const std::string& key,
|
|
const std::string& default_value) const;
|
|
|
|
std::vector<uint8_t> get1_memvec(const std::string&) const;
|
|
uint32_t get1_uint32(const std::string&, uint32_t = 0) const;
|
|
|
|
bool has_value(const std::string&) const;
|
|
|
|
void add(const std::multimap<std::string, std::string>&);
|
|
void add(const std::string&, const std::string&);
|
|
void add(const std::string&, uint32_t);
|
|
void add(const std::string&, const secure_vector<uint8_t>&);
|
|
void add(const std::string&, const std::vector<uint8_t>&);
|
|
private:
|
|
std::multimap<std::string, std::string> m_contents;
|
|
};
|
|
|
|
/*
|
|
* Data Store Extraction Operations
|
|
*/
|
|
|
|
/*
|
|
* Create and populate a X509_DN
|
|
* @param info data store containing DN information
|
|
* @return DN containing attributes from data store
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) X509_DN
|
|
BOTAN_DEPRECATED("Avoid roundtripping names through Data_Store")
|
|
create_dn(const Data_Store& info);
|
|
|
|
/*
|
|
* Create and populate an AlternativeName
|
|
* @param info data store containing AlternativeName information
|
|
* @return AlternativeName containing attributes from data store
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) AlternativeName
|
|
BOTAN_DEPRECATED("Avoid roundtripping names through Data_Store")
|
|
create_alt_name(const Data_Store& info);
|
|
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class BigInt;
|
|
|
|
/**
|
|
* General DER Encoding Object
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DER_Encoder final
|
|
{
|
|
public:
|
|
typedef std::function<void (const uint8_t[], size_t)> append_fn;
|
|
|
|
/**
|
|
* DER encode, writing to an internal buffer
|
|
* Use get_contents or get_contents_unlocked to read the results
|
|
* after all encoding is completed.
|
|
*/
|
|
DER_Encoder() = default;
|
|
|
|
/**
|
|
* DER encode, writing to @param vec
|
|
* If this constructor is used, get_contents* may not be called.
|
|
*/
|
|
DER_Encoder(secure_vector<uint8_t>& vec);
|
|
|
|
/**
|
|
* DER encode, writing to @param vec
|
|
* If this constructor is used, get_contents* may not be called.
|
|
*/
|
|
DER_Encoder(std::vector<uint8_t>& vec);
|
|
|
|
/**
|
|
* DER encode, calling append to write output
|
|
* If this constructor is used, get_contents* may not be called.
|
|
*/
|
|
DER_Encoder(append_fn append) : m_append_output(append) {}
|
|
|
|
secure_vector<uint8_t> get_contents();
|
|
|
|
/**
|
|
* Return the encoded contents as a std::vector
|
|
*
|
|
* If using this function, instead pass a std::vector to the
|
|
* contructor of DER_Encoder where the output will be placed. This
|
|
* avoids several unecessary copies.
|
|
*/
|
|
std::vector<uint8_t> BOTAN_DEPRECATED("Use DER_Encoder(vector) instead") get_contents_unlocked();
|
|
|
|
DER_Encoder& start_cons(ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = UNIVERSAL);
|
|
DER_Encoder& end_cons();
|
|
|
|
DER_Encoder& start_explicit(uint16_t type_tag);
|
|
DER_Encoder& end_explicit();
|
|
|
|
/**
|
|
* Insert raw bytes directly into the output stream
|
|
*/
|
|
DER_Encoder& raw_bytes(const uint8_t val[], size_t len);
|
|
|
|
template<typename Alloc>
|
|
DER_Encoder& raw_bytes(const std::vector<uint8_t, Alloc>& val)
|
|
{
|
|
return raw_bytes(val.data(), val.size());
|
|
}
|
|
|
|
DER_Encoder& encode_null();
|
|
DER_Encoder& encode(bool b);
|
|
DER_Encoder& encode(size_t s);
|
|
DER_Encoder& encode(const BigInt& n);
|
|
DER_Encoder& encode(const uint8_t val[], size_t len, ASN1_Tag real_type);
|
|
|
|
template<typename Alloc>
|
|
DER_Encoder& encode(const std::vector<uint8_t, Alloc>& vec, ASN1_Tag real_type)
|
|
{
|
|
return encode(vec.data(), vec.size(), real_type);
|
|
}
|
|
|
|
DER_Encoder& encode(bool b,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
|
|
|
|
DER_Encoder& encode(size_t s,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
|
|
|
|
DER_Encoder& encode(const BigInt& n,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
|
|
|
|
DER_Encoder& encode(const uint8_t v[], size_t len,
|
|
ASN1_Tag real_type,
|
|
ASN1_Tag type_tag,
|
|
ASN1_Tag class_tag = CONTEXT_SPECIFIC);
|
|
|
|
template<typename Alloc>
|
|
DER_Encoder& encode(const std::vector<uint8_t, Alloc>& bytes,
|
|
ASN1_Tag real_type,
|
|
ASN1_Tag type_tag, ASN1_Tag class_tag)
|
|
{
|
|
return encode(bytes.data(), bytes.size(),
|
|
real_type, type_tag, class_tag);
|
|
}
|
|
|
|
template<typename T>
|
|
DER_Encoder& encode_optional(const T& value, const T& default_value)
|
|
{
|
|
if(value != default_value)
|
|
encode(value);
|
|
return (*this);
|
|
}
|
|
|
|
template<typename T>
|
|
DER_Encoder& encode_list(const std::vector<T>& values)
|
|
{
|
|
for(size_t i = 0; i != values.size(); ++i)
|
|
encode(values[i]);
|
|
return (*this);
|
|
}
|
|
|
|
/*
|
|
* Request for an object to encode itself to this stream
|
|
*/
|
|
DER_Encoder& encode(const ASN1_Object& obj);
|
|
|
|
/*
|
|
* Conditionally write some values to the stream
|
|
*/
|
|
DER_Encoder& encode_if(bool pred, DER_Encoder& enc)
|
|
{
|
|
if(pred)
|
|
return raw_bytes(enc.get_contents());
|
|
return (*this);
|
|
}
|
|
|
|
DER_Encoder& encode_if(bool pred, const ASN1_Object& obj)
|
|
{
|
|
if(pred)
|
|
encode(obj);
|
|
return (*this);
|
|
}
|
|
|
|
DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
|
|
const uint8_t rep[], size_t length);
|
|
|
|
DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
|
|
const std::vector<uint8_t>& rep)
|
|
{
|
|
return add_object(type_tag, class_tag, rep.data(), rep.size());
|
|
}
|
|
|
|
DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
|
|
const secure_vector<uint8_t>& rep)
|
|
{
|
|
return add_object(type_tag, class_tag, rep.data(), rep.size());
|
|
}
|
|
|
|
DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
|
|
const std::string& str);
|
|
|
|
DER_Encoder& add_object(ASN1_Tag type_tag, ASN1_Tag class_tag,
|
|
uint8_t val);
|
|
|
|
private:
|
|
class DER_Sequence final
|
|
{
|
|
public:
|
|
ASN1_Tag tag_of() const;
|
|
|
|
void push_contents(DER_Encoder& der);
|
|
|
|
void add_bytes(const uint8_t val[], size_t len);
|
|
|
|
void add_bytes(const uint8_t hdr[], size_t hdr_len,
|
|
const uint8_t val[], size_t val_len);
|
|
|
|
DER_Sequence(ASN1_Tag, ASN1_Tag);
|
|
|
|
DER_Sequence(DER_Sequence&& seq)
|
|
{
|
|
std::swap(m_type_tag, seq.m_type_tag);
|
|
std::swap(m_class_tag, seq.m_class_tag);
|
|
std::swap(m_contents, seq.m_contents);
|
|
std::swap(m_set_contents, seq.m_set_contents);
|
|
}
|
|
|
|
DER_Sequence& operator=(DER_Sequence&& seq)
|
|
{
|
|
std::swap(m_type_tag, seq.m_type_tag);
|
|
std::swap(m_class_tag, seq.m_class_tag);
|
|
std::swap(m_contents, seq.m_contents);
|
|
std::swap(m_set_contents, seq.m_set_contents);
|
|
return (*this);
|
|
}
|
|
|
|
DER_Sequence(const DER_Sequence& seq) = default;
|
|
|
|
DER_Sequence& operator=(const DER_Sequence& seq) = default;
|
|
|
|
private:
|
|
ASN1_Tag m_type_tag, m_class_tag;
|
|
secure_vector<uint8_t> m_contents;
|
|
std::vector< secure_vector<uint8_t> > m_set_contents;
|
|
};
|
|
|
|
append_fn m_append_output;
|
|
secure_vector<uint8_t> m_default_outbuf;
|
|
std::vector<DER_Sequence> m_subsequences;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(des.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* DES
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DES final : public Block_Cipher_Fixed_Params<8, 8>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "DES"; }
|
|
BlockCipher* clone() const override { return new DES; }
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
secure_vector<uint32_t> m_round_key;
|
|
};
|
|
|
|
/**
|
|
* Triple DES
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) TripleDES final : public Block_Cipher_Fixed_Params<8, 16, 24, 8>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "TripleDES"; }
|
|
BlockCipher* clone() const override { return new TripleDES; }
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
secure_vector<uint32_t> m_round_key;
|
|
};
|
|
|
|
/*
|
|
* DES Tables
|
|
*/
|
|
extern const uint32_t DES_SPBOX1[256];
|
|
extern const uint32_t DES_SPBOX2[256];
|
|
extern const uint32_t DES_SPBOX3[256];
|
|
extern const uint32_t DES_SPBOX4[256];
|
|
extern const uint32_t DES_SPBOX5[256];
|
|
extern const uint32_t DES_SPBOX6[256];
|
|
extern const uint32_t DES_SPBOX7[256];
|
|
extern const uint32_t DES_SPBOX8[256];
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(desx.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* DESX
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DESX final : public Block_Cipher_Fixed_Params<8, 24>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "DESX"; }
|
|
BlockCipher* clone() const override { return new DESX; }
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
secure_vector<uint8_t> m_K1, m_K2;
|
|
DES m_des;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Montgomery_Params;
|
|
class DL_Group_Data;
|
|
|
|
enum class DL_Group_Source {
|
|
Builtin,
|
|
RandomlyGenerated,
|
|
ExternalSource,
|
|
};
|
|
|
|
/**
|
|
* This class represents discrete logarithm groups. It holds a prime
|
|
* modulus p, a generator g, and (optionally) a prime q which is a
|
|
* factor of (p-1). In most cases g generates the order-q subgroup.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DL_Group final
|
|
{
|
|
public:
|
|
/**
|
|
* Determine the prime creation for DL groups.
|
|
*/
|
|
enum PrimeType { Strong, Prime_Subgroup, DSA_Kosherizer };
|
|
|
|
/**
|
|
* The DL group encoding format variants.
|
|
*/
|
|
enum Format {
|
|
ANSI_X9_42,
|
|
ANSI_X9_57,
|
|
PKCS_3,
|
|
|
|
DSA_PARAMETERS = ANSI_X9_57,
|
|
DH_PARAMETERS = ANSI_X9_42,
|
|
ANSI_X9_42_DH_PARAMETERS = ANSI_X9_42,
|
|
PKCS3_DH_PARAMETERS = PKCS_3
|
|
};
|
|
|
|
/**
|
|
* Construct a DL group with uninitialized internal value.
|
|
* Use this constructor is you wish to set the groups values
|
|
* from a DER or PEM encoded group.
|
|
*/
|
|
DL_Group() = default;
|
|
|
|
/**
|
|
* Construct a DL group that is registered in the configuration.
|
|
* @param name the name of the group, for example "modp/ietf/3072"
|
|
*
|
|
* @warning This constructor also accepts PEM inputs. This behavior is
|
|
* deprecated and will be removed in a future major release. Instead
|
|
* use DL_Group_from_PEM function
|
|
*/
|
|
explicit DL_Group(const std::string& name);
|
|
|
|
/*
|
|
* Read a PEM representation
|
|
*/
|
|
static DL_Group DL_Group_from_PEM(const std::string& pem);
|
|
|
|
/**
|
|
* Create a new group randomly.
|
|
* @param rng the random number generator to use
|
|
* @param type specifies how the creation of primes p and q shall
|
|
* be performed. If type=Strong, then p will be determined as a
|
|
* safe prime, and q will be chosen as (p-1)/2. If
|
|
* type=Prime_Subgroup and qbits = 0, then the size of q will be
|
|
* determined according to the estimated difficulty of the DL
|
|
* problem. If type=DSA_Kosherizer, DSA primes will be created.
|
|
* @param pbits the number of bits of p
|
|
* @param qbits the number of bits of q. Leave it as 0 to have
|
|
* the value determined according to pbits.
|
|
*/
|
|
DL_Group(RandomNumberGenerator& rng, PrimeType type,
|
|
size_t pbits, size_t qbits = 0);
|
|
|
|
/**
|
|
* Create a DSA group with a given seed.
|
|
* @param rng the random number generator to use
|
|
* @param seed the seed to use to create the random primes
|
|
* @param pbits the desired bit size of the prime p
|
|
* @param qbits the desired bit size of the prime q.
|
|
*/
|
|
DL_Group(RandomNumberGenerator& rng,
|
|
const std::vector<uint8_t>& seed,
|
|
size_t pbits = 1024, size_t qbits = 0);
|
|
|
|
/**
|
|
* Create a DL group.
|
|
* @param p the prime p
|
|
* @param g the base g
|
|
*/
|
|
DL_Group(const BigInt& p, const BigInt& g);
|
|
|
|
/**
|
|
* Create a DL group.
|
|
* @param p the prime p
|
|
* @param q the prime q
|
|
* @param g the base g
|
|
*/
|
|
DL_Group(const BigInt& p, const BigInt& q, const BigInt& g);
|
|
|
|
/**
|
|
* Decode a BER-encoded DL group param
|
|
*/
|
|
DL_Group(const uint8_t ber[], size_t ber_len, Format format);
|
|
|
|
/**
|
|
* Decode a BER-encoded DL group param
|
|
*/
|
|
template<typename Alloc>
|
|
DL_Group(const std::vector<uint8_t, Alloc>& ber, Format format) :
|
|
DL_Group(ber.data(), ber.size(), format) {}
|
|
|
|
/**
|
|
* Get the prime p.
|
|
* @return prime p
|
|
*/
|
|
const BigInt& get_p() const;
|
|
|
|
/**
|
|
* Get the prime q, returns zero if q is not used
|
|
* @return prime q
|
|
*/
|
|
const BigInt& get_q() const;
|
|
|
|
/**
|
|
* Get the base g.
|
|
* @return base g
|
|
*/
|
|
const BigInt& get_g() const;
|
|
|
|
/**
|
|
* Perform validity checks on the group.
|
|
* @param rng the rng to use
|
|
* @param strong whether to perform stronger by lengthier tests
|
|
* @return true if the object is consistent, false otherwise
|
|
*/
|
|
bool verify_group(RandomNumberGenerator& rng, bool strong = true) const;
|
|
|
|
/**
|
|
* Verify a public element, ie check if y = g^x for some x.
|
|
*
|
|
* This is not a perfect test. It verifies that 1 < y < p and (if q is set)
|
|
* that y is in the subgroup of size q.
|
|
*/
|
|
bool verify_public_element(const BigInt& y) const;
|
|
|
|
/**
|
|
* Verify a pair of elements y = g^x
|
|
*
|
|
* This verifies that 1 < x,y < p and that y=g^x mod p
|
|
*/
|
|
bool verify_element_pair(const BigInt& y, const BigInt& x) const;
|
|
|
|
/**
|
|
* Encode this group into a string using PEM encoding.
|
|
* @param format the encoding format
|
|
* @return string holding the PEM encoded group
|
|
*/
|
|
std::string PEM_encode(Format format) const;
|
|
|
|
/**
|
|
* Encode this group into a string using DER encoding.
|
|
* @param format the encoding format
|
|
* @return string holding the DER encoded group
|
|
*/
|
|
std::vector<uint8_t> DER_encode(Format format) const;
|
|
|
|
/**
|
|
* Reduce an integer modulo p
|
|
* @return x % p
|
|
*/
|
|
BigInt mod_p(const BigInt& x) const;
|
|
|
|
/**
|
|
* Multiply and reduce an integer modulo p
|
|
* @return (x*y) % p
|
|
*/
|
|
BigInt multiply_mod_p(const BigInt& x, const BigInt& y) const;
|
|
|
|
/**
|
|
* Return the inverse of x mod p
|
|
*/
|
|
BigInt inverse_mod_p(const BigInt& x) const;
|
|
|
|
/**
|
|
* Reduce an integer modulo q
|
|
* Throws if q is unset on this DL_Group
|
|
* @return x % q
|
|
*/
|
|
BigInt mod_q(const BigInt& x) const;
|
|
|
|
/**
|
|
* Multiply and reduce an integer modulo q
|
|
* Throws if q is unset on this DL_Group
|
|
* @return (x*y) % q
|
|
*/
|
|
BigInt multiply_mod_q(const BigInt& x, const BigInt& y) const;
|
|
|
|
/**
|
|
* Multiply and reduce an integer modulo q
|
|
* Throws if q is unset on this DL_Group
|
|
* @return (x*y*z) % q
|
|
*/
|
|
BigInt multiply_mod_q(const BigInt& x, const BigInt& y, const BigInt& z) const;
|
|
|
|
/**
|
|
* Square and reduce an integer modulo q
|
|
* Throws if q is unset on this DL_Group
|
|
* @return (x*x) % q
|
|
*/
|
|
BigInt square_mod_q(const BigInt& x) const;
|
|
|
|
/**
|
|
* Return the inverse of x mod q
|
|
* Throws if q is unset on this DL_Group
|
|
*/
|
|
BigInt inverse_mod_q(const BigInt& x) const;
|
|
|
|
/**
|
|
* Modular exponentiation
|
|
*
|
|
* @warning this function leaks the size of x via the number of
|
|
* loop iterations. Use the version taking the maximum size to
|
|
* avoid this.
|
|
*
|
|
* @return (g^x) % p
|
|
*/
|
|
BigInt power_g_p(const BigInt& x) const;
|
|
|
|
/**
|
|
* Modular exponentiation
|
|
* @param x the exponent
|
|
* @param max_x_bits x is assumed to be at most this many bits long.
|
|
*
|
|
* @return (g^x) % p
|
|
*/
|
|
BigInt power_g_p(const BigInt& x, size_t max_x_bits) const;
|
|
|
|
/**
|
|
* Multi-exponentiate
|
|
* Return (g^x * y^z) % p
|
|
*/
|
|
BigInt multi_exponentiate(const BigInt& x, const BigInt& y, const BigInt& z) const;
|
|
|
|
/**
|
|
* Return parameters for Montgomery reduction/exponentiation mod p
|
|
*/
|
|
std::shared_ptr<const Montgomery_Params> monty_params_p() const;
|
|
|
|
/**
|
|
* Return the size of p in bits
|
|
* Same as get_p().bits()
|
|
*/
|
|
size_t p_bits() const;
|
|
|
|
/**
|
|
* Return the size of p in bytes
|
|
* Same as get_p().bytes()
|
|
*/
|
|
size_t p_bytes() const;
|
|
|
|
/**
|
|
* Return the size of q in bits
|
|
* Same as get_q().bits()
|
|
* Throws if q is unset
|
|
*/
|
|
size_t q_bits() const;
|
|
|
|
/**
|
|
* Return the size of q in bytes
|
|
* Same as get_q().bytes()
|
|
* Throws if q is unset
|
|
*/
|
|
size_t q_bytes() const;
|
|
|
|
/**
|
|
* Return size in bits of a secret exponent
|
|
*
|
|
* This attempts to balance between the attack costs of NFS
|
|
* (which depends on the size of the modulus) and Pollard's rho
|
|
* (which depends on the size of the exponent).
|
|
*
|
|
* It may vary over time for a particular group, if the attack
|
|
* costs change.
|
|
*/
|
|
size_t exponent_bits() const;
|
|
|
|
/**
|
|
* Return an estimate of the strength of this group against
|
|
* discrete logarithm attacks (eg NFS). Warning: since this only
|
|
* takes into account known attacks it is by necessity an
|
|
* overestimate of the actual strength.
|
|
*/
|
|
size_t estimated_strength() const;
|
|
|
|
/**
|
|
* Decode a DER/BER encoded group into this instance.
|
|
* @param ber a vector containing the DER/BER encoded group
|
|
* @param format the format of the encoded group
|
|
*
|
|
* @warning avoid this. Instead use the DL_Group constructor
|
|
*/
|
|
void BER_decode(const std::vector<uint8_t>& ber, Format format);
|
|
|
|
/**
|
|
* Decode a PEM encoded group into this instance.
|
|
* @param pem the PEM encoding of the group
|
|
*/
|
|
void BOTAN_DEPRECATED("Use DL_Group_from_PEM") PEM_decode(const std::string& pem);
|
|
|
|
DL_Group_Source source() const;
|
|
|
|
/**
|
|
* Return PEM representation of named DL group
|
|
*/
|
|
static std::string BOTAN_DEPRECATED("Use DL_Group(name).PEM_encode()")
|
|
PEM_for_named_group(const std::string& name);
|
|
|
|
/*
|
|
* For internal use only
|
|
*/
|
|
static std::shared_ptr<DL_Group_Data> DL_group_info(const std::string& name);
|
|
|
|
private:
|
|
static std::shared_ptr<DL_Group_Data> load_DL_group_info(const char* p_str,
|
|
const char* q_str,
|
|
const char* g_str);
|
|
|
|
static std::shared_ptr<DL_Group_Data> load_DL_group_info(const char* p_str,
|
|
const char* g_str);
|
|
|
|
static std::shared_ptr<DL_Group_Data>
|
|
BER_decode_DL_group(const uint8_t data[], size_t data_len,
|
|
DL_Group::Format format,
|
|
DL_Group_Source source);
|
|
|
|
const DL_Group_Data& data() const;
|
|
std::shared_ptr<DL_Group_Data> m_data;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents discrete logarithm (DL) public keys.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DL_Scheme_PublicKey : public virtual Public_Key
|
|
{
|
|
public:
|
|
bool check_key(RandomNumberGenerator& rng, bool) const override;
|
|
|
|
AlgorithmIdentifier algorithm_identifier() const override;
|
|
|
|
std::vector<uint8_t> public_key_bits() const override;
|
|
|
|
/**
|
|
* Get the DL domain parameters of this key.
|
|
* @return DL domain parameters of this key
|
|
*/
|
|
const DL_Group& get_domain() const { return m_group; }
|
|
|
|
/**
|
|
* Get the DL domain parameters of this key.
|
|
* @return DL domain parameters of this key
|
|
*/
|
|
const DL_Group& get_group() const { return m_group; }
|
|
|
|
/**
|
|
* Get the public value y with y = g^x mod p where x is the secret key.
|
|
*/
|
|
const BigInt& get_y() const { return m_y; }
|
|
|
|
/**
|
|
* Get the prime p of the underlying DL group.
|
|
* @return prime p
|
|
*/
|
|
const BigInt& group_p() const { return m_group.get_p(); }
|
|
|
|
/**
|
|
* Get the prime q of the underlying DL group.
|
|
* @return prime q
|
|
*/
|
|
const BigInt& group_q() const { return m_group.get_q(); }
|
|
|
|
/**
|
|
* Get the generator g of the underlying DL group.
|
|
* @return generator g
|
|
*/
|
|
const BigInt& group_g() const { return m_group.get_g(); }
|
|
|
|
/**
|
|
* Get the underlying groups encoding format.
|
|
* @return encoding format
|
|
*/
|
|
virtual DL_Group::Format group_format() const = 0;
|
|
|
|
size_t key_length() const override;
|
|
size_t estimated_strength() const override;
|
|
|
|
DL_Scheme_PublicKey& operator=(const DL_Scheme_PublicKey& other) = default;
|
|
|
|
protected:
|
|
DL_Scheme_PublicKey() = default;
|
|
|
|
/**
|
|
* Create a public key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
* @param group_format the underlying groups encoding format
|
|
*/
|
|
DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits,
|
|
DL_Group::Format group_format);
|
|
|
|
DL_Scheme_PublicKey(const DL_Group& group, const BigInt& y);
|
|
|
|
/**
|
|
* The DL public key
|
|
*/
|
|
BigInt m_y;
|
|
|
|
/**
|
|
* The DL group
|
|
*/
|
|
DL_Group m_group;
|
|
};
|
|
|
|
/**
|
|
* This class represents discrete logarithm (DL) private keys.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DL_Scheme_PrivateKey : public virtual DL_Scheme_PublicKey,
|
|
public virtual Private_Key
|
|
{
|
|
public:
|
|
bool check_key(RandomNumberGenerator& rng, bool) const override;
|
|
|
|
/**
|
|
* Get the secret key x.
|
|
* @return secret key
|
|
*/
|
|
const BigInt& get_x() const { return m_x; }
|
|
|
|
secure_vector<uint8_t> private_key_bits() const override;
|
|
|
|
DL_Scheme_PrivateKey& operator=(const DL_Scheme_PrivateKey& other) = default;
|
|
|
|
protected:
|
|
/**
|
|
* Create a private key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded private key bits
|
|
* @param group_format the underlying groups encoding format
|
|
*/
|
|
DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits,
|
|
DL_Group::Format group_format);
|
|
|
|
DL_Scheme_PrivateKey() = default;
|
|
|
|
/**
|
|
* The DL private key
|
|
*/
|
|
BigInt m_x;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents Diffie-Hellman public keys.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DH_PublicKey : public virtual DL_Scheme_PublicKey
|
|
{
|
|
public:
|
|
std::string algo_name() const override { return "DH"; }
|
|
|
|
std::vector<uint8_t> public_value() const;
|
|
|
|
DL_Group::Format group_format() const override { return DL_Group::ANSI_X9_42; }
|
|
|
|
/**
|
|
* Create a public key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
DH_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits) :
|
|
DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42) {}
|
|
|
|
/**
|
|
* Construct a public key with the specified parameters.
|
|
* @param grp the DL group to use in the key
|
|
* @param y the public value y
|
|
*/
|
|
DH_PublicKey(const DL_Group& grp, const BigInt& y);
|
|
protected:
|
|
DH_PublicKey() = default;
|
|
};
|
|
|
|
/**
|
|
* This class represents Diffie-Hellman private keys.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DH_PrivateKey final : public DH_PublicKey,
|
|
public PK_Key_Agreement_Key,
|
|
public virtual DL_Scheme_PrivateKey
|
|
{
|
|
public:
|
|
std::vector<uint8_t> public_value() const override;
|
|
|
|
/**
|
|
* Load a private key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits PKCS #8 structure
|
|
*/
|
|
DH_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Create a private key.
|
|
* @param rng random number generator to use
|
|
* @param grp the group to be used in the key
|
|
* @param x the key's secret value (or if zero, generate a new key)
|
|
*/
|
|
DH_PrivateKey(RandomNumberGenerator& rng, const DL_Group& grp,
|
|
const BigInt& x = 0);
|
|
|
|
std::unique_ptr<PK_Ops::Key_Agreement>
|
|
create_key_agreement_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(divide.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* BigInt Division
|
|
* @param x an integer
|
|
* @param y a non-zero integer
|
|
* @param q will be set to x / y
|
|
* @param r will be set to x % y
|
|
*/
|
|
void BOTAN_UNSTABLE_API vartime_divide(const BigInt& x,
|
|
const BigInt& y,
|
|
BigInt& q,
|
|
BigInt& r);
|
|
|
|
/**
|
|
* BigInt division, const time variant
|
|
*
|
|
* This runs with control flow independent of the values of x/y.
|
|
* Warning: the loop bounds still leak the sizes of x and y.
|
|
*
|
|
* @param x an integer
|
|
* @param y a non-zero integer
|
|
* @param q will be set to x / y
|
|
* @param r will be set to x % y
|
|
*/
|
|
void BOTAN_PUBLIC_API(2,9) ct_divide(const BigInt& x,
|
|
const BigInt& y,
|
|
BigInt& q,
|
|
BigInt& r);
|
|
|
|
inline void divide(const BigInt& x,
|
|
const BigInt& y,
|
|
BigInt& q,
|
|
BigInt& r)
|
|
{
|
|
ct_divide(x, y, q, r);
|
|
}
|
|
|
|
/**
|
|
* BigInt division, const time variant
|
|
*
|
|
* This runs with control flow independent of the values of x/y.
|
|
* Warning: the loop bounds still leak the sizes of x and y.
|
|
*
|
|
* @param x an integer
|
|
* @param y a non-zero integer
|
|
* @return x/y with remainder discarded
|
|
*/
|
|
inline BigInt ct_divide(const BigInt& x, const BigInt& y)
|
|
{
|
|
BigInt q, r;
|
|
ct_divide(x, y, q, r);
|
|
return q;
|
|
}
|
|
|
|
/**
|
|
* BigInt division, const time variant
|
|
*
|
|
* This runs with control flow independent of the values of x/y.
|
|
* Warning: the loop bounds still leak the sizes of x and y.
|
|
*
|
|
* @param x an integer
|
|
* @param y a non-zero integer
|
|
* @param q will be set to x / y
|
|
* @param r will be set to x % y
|
|
*/
|
|
void BOTAN_PUBLIC_API(2,9) ct_divide_u8(const BigInt& x,
|
|
uint8_t y,
|
|
BigInt& q,
|
|
uint8_t& r);
|
|
|
|
/**
|
|
* BigInt modulo, const time variant
|
|
*
|
|
* Using this function is (slightly) cheaper than calling ct_divide and
|
|
* using only the remainder.
|
|
*
|
|
* @param x a non-negative integer
|
|
* @param modulo a positive integer
|
|
* @return result x % modulo
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,9) ct_modulo(const BigInt& x,
|
|
const BigInt& modulo);
|
|
|
|
}
|
|
|
|
#if defined(BOTAN_HAS_SYSTEM_RNG)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Return a shared reference to a global PRNG instance provided by the
|
|
* operating system. For instance might be instantiated by /dev/urandom
|
|
* or CryptGenRandom.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) RandomNumberGenerator& system_rng();
|
|
|
|
/*
|
|
* Instantiable reference to the system RNG.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) System_RNG final : public RandomNumberGenerator
|
|
{
|
|
public:
|
|
std::string name() const override { return system_rng().name(); }
|
|
|
|
void randomize(uint8_t out[], size_t len) override { system_rng().randomize(out, len); }
|
|
|
|
void add_entropy(const uint8_t in[], size_t length) override { system_rng().add_entropy(in, length); }
|
|
|
|
bool is_seeded() const override { return system_rng().is_seeded(); }
|
|
|
|
bool accepts_input() const override { return system_rng().accepts_input(); }
|
|
|
|
void clear() override { system_rng().clear(); }
|
|
};
|
|
|
|
}
|
|
#define BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Public Key Encryptor
|
|
* This is the primary interface for public key encryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PK_Encryptor
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Encrypt a message.
|
|
* @param in the message as a byte array
|
|
* @param length the length of the above byte array
|
|
* @param rng the random number source to use
|
|
* @return encrypted message
|
|
*/
|
|
std::vector<uint8_t> encrypt(const uint8_t in[], size_t length,
|
|
RandomNumberGenerator& rng) const
|
|
{
|
|
return enc(in, length, rng);
|
|
}
|
|
|
|
/**
|
|
* Encrypt a message.
|
|
* @param in the message
|
|
* @param rng the random number source to use
|
|
* @return encrypted message
|
|
*/
|
|
template<typename Alloc>
|
|
std::vector<uint8_t> encrypt(const std::vector<uint8_t, Alloc>& in,
|
|
RandomNumberGenerator& rng) const
|
|
{
|
|
return enc(in.data(), in.size(), rng);
|
|
}
|
|
|
|
/**
|
|
* Return the maximum allowed message size in bytes.
|
|
* @return maximum message size in bytes
|
|
*/
|
|
virtual size_t maximum_input_size() const = 0;
|
|
|
|
/**
|
|
* Return an upper bound on the ciphertext length
|
|
*/
|
|
virtual size_t ciphertext_length(size_t ctext_len) const = 0;
|
|
|
|
PK_Encryptor() = default;
|
|
virtual ~PK_Encryptor() = default;
|
|
|
|
PK_Encryptor(const PK_Encryptor&) = delete;
|
|
PK_Encryptor& operator=(const PK_Encryptor&) = delete;
|
|
|
|
private:
|
|
virtual std::vector<uint8_t> enc(const uint8_t[], size_t,
|
|
RandomNumberGenerator&) const = 0;
|
|
};
|
|
|
|
/**
|
|
* Public Key Decryptor
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PK_Decryptor
|
|
{
|
|
public:
|
|
/**
|
|
* Decrypt a ciphertext, throwing an exception if the input
|
|
* seems to be invalid (eg due to an accidental or malicious
|
|
* error in the ciphertext).
|
|
*
|
|
* @param in the ciphertext as a byte array
|
|
* @param length the length of the above byte array
|
|
* @return decrypted message
|
|
*/
|
|
secure_vector<uint8_t> decrypt(const uint8_t in[], size_t length) const;
|
|
|
|
/**
|
|
* Same as above, but taking a vector
|
|
* @param in the ciphertext
|
|
* @return decrypted message
|
|
*/
|
|
template<typename Alloc>
|
|
secure_vector<uint8_t> decrypt(const std::vector<uint8_t, Alloc>& in) const
|
|
{
|
|
return decrypt(in.data(), in.size());
|
|
}
|
|
|
|
/**
|
|
* Decrypt a ciphertext. If the ciphertext is invalid (eg due to
|
|
* invalid padding) or is not the expected length, instead
|
|
* returns a random string of the expected length. Use to avoid
|
|
* oracle attacks, especially against PKCS #1 v1.5 decryption.
|
|
*/
|
|
secure_vector<uint8_t>
|
|
decrypt_or_random(const uint8_t in[],
|
|
size_t length,
|
|
size_t expected_pt_len,
|
|
RandomNumberGenerator& rng) const;
|
|
|
|
/**
|
|
* Decrypt a ciphertext. If the ciphertext is invalid (eg due to
|
|
* invalid padding) or is not the expected length, instead
|
|
* returns a random string of the expected length. Use to avoid
|
|
* oracle attacks, especially against PKCS #1 v1.5 decryption.
|
|
*
|
|
* Additionally checks (also in const time) that:
|
|
* contents[required_content_offsets[i]] == required_content_bytes[i]
|
|
* for 0 <= i < required_contents
|
|
*
|
|
* Used for example in TLS, which encodes the client version in
|
|
* the content bytes: if there is any timing variation the version
|
|
* check can be used as an oracle to recover the key.
|
|
*/
|
|
secure_vector<uint8_t>
|
|
decrypt_or_random(const uint8_t in[],
|
|
size_t length,
|
|
size_t expected_pt_len,
|
|
RandomNumberGenerator& rng,
|
|
const uint8_t required_content_bytes[],
|
|
const uint8_t required_content_offsets[],
|
|
size_t required_contents) const;
|
|
|
|
/**
|
|
* Return an upper bound on the plaintext length for a particular
|
|
* ciphertext input length
|
|
*/
|
|
virtual size_t plaintext_length(size_t ctext_len) const = 0;
|
|
|
|
PK_Decryptor() = default;
|
|
virtual ~PK_Decryptor() = default;
|
|
|
|
PK_Decryptor(const PK_Decryptor&) = delete;
|
|
PK_Decryptor& operator=(const PK_Decryptor&) = delete;
|
|
|
|
private:
|
|
virtual secure_vector<uint8_t> do_decrypt(uint8_t& valid_mask,
|
|
const uint8_t in[], size_t in_len) const = 0;
|
|
};
|
|
|
|
/**
|
|
* Public Key Signer. Use the sign_message() functions for small
|
|
* messages. Use multiple calls update() to process large messages and
|
|
* generate the signature by finally calling signature().
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PK_Signer final
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Construct a PK Signer.
|
|
* @param key the key to use inside this signer
|
|
* @param rng the random generator to use
|
|
* @param emsa the EMSA to use
|
|
* An example would be "EMSA1(SHA-224)".
|
|
* @param format the signature format to use
|
|
* @param provider the provider to use
|
|
*/
|
|
PK_Signer(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& emsa,
|
|
Signature_Format format = IEEE_1363,
|
|
const std::string& provider = "");
|
|
|
|
#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS)
|
|
/**
|
|
* Construct a PK Signer.
|
|
* @param key the key to use inside this signer
|
|
* @param emsa the EMSA to use
|
|
* An example would be "EMSA1(SHA-224)".
|
|
* @param format the signature format to use
|
|
*/
|
|
BOTAN_DEPRECATED("Use constructor taking a RNG object")
|
|
PK_Signer(const Private_Key& key,
|
|
const std::string& emsa,
|
|
Signature_Format format = IEEE_1363,
|
|
const std::string& provider = "") :
|
|
PK_Signer(key, system_rng(), emsa, format, provider)
|
|
{}
|
|
#endif
|
|
|
|
~PK_Signer();
|
|
|
|
PK_Signer(const PK_Signer&) = delete;
|
|
PK_Signer& operator=(const PK_Signer&) = delete;
|
|
|
|
/**
|
|
* Sign a message all in one go
|
|
* @param in the message to sign as a byte array
|
|
* @param length the length of the above byte array
|
|
* @param rng the rng to use
|
|
* @return signature
|
|
*/
|
|
std::vector<uint8_t> sign_message(const uint8_t in[], size_t length,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
this->update(in, length);
|
|
return this->signature(rng);
|
|
}
|
|
|
|
/**
|
|
* Sign a message.
|
|
* @param in the message to sign
|
|
* @param rng the rng to use
|
|
* @return signature
|
|
*/
|
|
template<typename Alloc>
|
|
std::vector<uint8_t> sign_message(const std::vector<uint8_t, Alloc>& in,
|
|
RandomNumberGenerator& rng)
|
|
{
|
|
return sign_message(in.data(), in.size(), rng);
|
|
}
|
|
|
|
/**
|
|
* Add a message part (single byte).
|
|
* @param in the byte to add
|
|
*/
|
|
void update(uint8_t in) { update(&in, 1); }
|
|
|
|
/**
|
|
* Add a message part.
|
|
* @param in the message part to add as a byte array
|
|
* @param length the length of the above byte array
|
|
*/
|
|
void update(const uint8_t in[], size_t length);
|
|
|
|
/**
|
|
* Add a message part.
|
|
* @param in the message part to add
|
|
*/
|
|
template<typename Alloc>
|
|
void update(const std::vector<uint8_t, Alloc>& in)
|
|
{
|
|
update(in.data(), in.size());
|
|
}
|
|
|
|
/**
|
|
* Add a message part.
|
|
* @param in the message part to add
|
|
*/
|
|
void update(const std::string& in)
|
|
{
|
|
update(cast_char_ptr_to_uint8(in.data()), in.size());
|
|
}
|
|
|
|
/**
|
|
* Get the signature of the so far processed message (provided by the
|
|
* calls to update()).
|
|
* @param rng the rng to use
|
|
* @return signature of the total message
|
|
*/
|
|
std::vector<uint8_t> signature(RandomNumberGenerator& rng);
|
|
|
|
|
|
/**
|
|
* Set the output format of the signature.
|
|
* @param format the signature format to use
|
|
*/
|
|
void set_output_format(Signature_Format format) { m_sig_format = format; }
|
|
|
|
/**
|
|
* Return an upper bound on the length of the signatures this
|
|
* PK_Signer will produce
|
|
*/
|
|
size_t signature_length() const;
|
|
|
|
private:
|
|
std::unique_ptr<PK_Ops::Signature> m_op;
|
|
Signature_Format m_sig_format;
|
|
size_t m_parts, m_part_size;
|
|
};
|
|
|
|
/**
|
|
* Public Key Verifier. Use the verify_message() functions for small
|
|
* messages. Use multiple calls update() to process large messages and
|
|
* verify the signature by finally calling check_signature().
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PK_Verifier final
|
|
{
|
|
public:
|
|
/**
|
|
* Construct a PK Verifier.
|
|
* @param pub_key the public key to verify against
|
|
* @param emsa the EMSA to use (eg "EMSA3(SHA-1)")
|
|
* @param format the signature format to use
|
|
* @param provider the provider to use
|
|
*/
|
|
PK_Verifier(const Public_Key& pub_key,
|
|
const std::string& emsa,
|
|
Signature_Format format = IEEE_1363,
|
|
const std::string& provider = "");
|
|
|
|
~PK_Verifier();
|
|
|
|
PK_Verifier& operator=(const PK_Verifier&) = delete;
|
|
PK_Verifier(const PK_Verifier&) = delete;
|
|
|
|
/**
|
|
* Verify a signature.
|
|
* @param msg the message that the signature belongs to, as a byte array
|
|
* @param msg_length the length of the above byte array msg
|
|
* @param sig the signature as a byte array
|
|
* @param sig_length the length of the above byte array sig
|
|
* @return true if the signature is valid
|
|
*/
|
|
bool verify_message(const uint8_t msg[], size_t msg_length,
|
|
const uint8_t sig[], size_t sig_length);
|
|
/**
|
|
* Verify a signature.
|
|
* @param msg the message that the signature belongs to
|
|
* @param sig the signature
|
|
* @return true if the signature is valid
|
|
*/
|
|
template<typename Alloc, typename Alloc2>
|
|
bool verify_message(const std::vector<uint8_t, Alloc>& msg,
|
|
const std::vector<uint8_t, Alloc2>& sig)
|
|
{
|
|
return verify_message(msg.data(), msg.size(),
|
|
sig.data(), sig.size());
|
|
}
|
|
|
|
/**
|
|
* Add a message part (single byte) of the message corresponding to the
|
|
* signature to be verified.
|
|
* @param in the byte to add
|
|
*/
|
|
void update(uint8_t in) { update(&in, 1); }
|
|
|
|
/**
|
|
* Add a message part of the message corresponding to the
|
|
* signature to be verified.
|
|
* @param msg_part the new message part as a byte array
|
|
* @param length the length of the above byte array
|
|
*/
|
|
void update(const uint8_t msg_part[], size_t length);
|
|
|
|
/**
|
|
* Add a message part of the message corresponding to the
|
|
* signature to be verified.
|
|
* @param in the new message part
|
|
*/
|
|
template<typename Alloc>
|
|
void update(const std::vector<uint8_t, Alloc>& in)
|
|
{
|
|
update(in.data(), in.size());
|
|
}
|
|
|
|
/**
|
|
* Add a message part of the message corresponding to the
|
|
* signature to be verified.
|
|
*/
|
|
void update(const std::string& in)
|
|
{
|
|
update(cast_char_ptr_to_uint8(in.data()), in.size());
|
|
}
|
|
|
|
/**
|
|
* Check the signature of the buffered message, i.e. the one build
|
|
* by successive calls to update.
|
|
* @param sig the signature to be verified as a byte array
|
|
* @param length the length of the above byte array
|
|
* @return true if the signature is valid, false otherwise
|
|
*/
|
|
bool check_signature(const uint8_t sig[], size_t length);
|
|
|
|
/**
|
|
* Check the signature of the buffered message, i.e. the one build
|
|
* by successive calls to update.
|
|
* @param sig the signature to be verified
|
|
* @return true if the signature is valid, false otherwise
|
|
*/
|
|
template<typename Alloc>
|
|
bool check_signature(const std::vector<uint8_t, Alloc>& sig)
|
|
{
|
|
return check_signature(sig.data(), sig.size());
|
|
}
|
|
|
|
/**
|
|
* Set the format of the signatures fed to this verifier.
|
|
* @param format the signature format to use
|
|
*/
|
|
void set_input_format(Signature_Format format);
|
|
|
|
private:
|
|
std::unique_ptr<PK_Ops::Verification> m_op;
|
|
Signature_Format m_sig_format;
|
|
size_t m_parts, m_part_size;
|
|
};
|
|
|
|
/**
|
|
* Object used for key agreement
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PK_Key_Agreement final
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Construct a PK Key Agreement.
|
|
* @param key the key to use
|
|
* @param rng the random generator to use
|
|
* @param kdf name of the KDF to use (or 'Raw' for no KDF)
|
|
* @param provider the algo provider to use (or empty for default)
|
|
*/
|
|
PK_Key_Agreement(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& kdf,
|
|
const std::string& provider = "");
|
|
|
|
#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS)
|
|
/**
|
|
* Construct a PK Key Agreement.
|
|
* @param key the key to use
|
|
* @param kdf name of the KDF to use (or 'Raw' for no KDF)
|
|
* @param provider the algo provider to use (or empty for default)
|
|
*/
|
|
BOTAN_DEPRECATED("Use constructor taking a RNG object")
|
|
PK_Key_Agreement(const Private_Key& key,
|
|
const std::string& kdf,
|
|
const std::string& provider = "") :
|
|
PK_Key_Agreement(key, system_rng(), kdf, provider)
|
|
{}
|
|
#endif
|
|
|
|
~PK_Key_Agreement();
|
|
|
|
// For ECIES
|
|
PK_Key_Agreement& operator=(PK_Key_Agreement&&);
|
|
PK_Key_Agreement(PK_Key_Agreement&&);
|
|
|
|
PK_Key_Agreement& operator=(const PK_Key_Agreement&) = delete;
|
|
PK_Key_Agreement(const PK_Key_Agreement&) = delete;
|
|
|
|
/**
|
|
* Perform Key Agreement Operation
|
|
* @param key_len the desired key output size
|
|
* @param in the other parties key
|
|
* @param in_len the length of in in bytes
|
|
* @param params extra derivation params
|
|
* @param params_len the length of params in bytes
|
|
*/
|
|
SymmetricKey derive_key(size_t key_len,
|
|
const uint8_t in[],
|
|
size_t in_len,
|
|
const uint8_t params[],
|
|
size_t params_len) const;
|
|
|
|
/**
|
|
* Perform Key Agreement Operation
|
|
* @param key_len the desired key output size
|
|
* @param in the other parties key
|
|
* @param params extra derivation params
|
|
* @param params_len the length of params in bytes
|
|
*/
|
|
SymmetricKey derive_key(size_t key_len,
|
|
const std::vector<uint8_t>& in,
|
|
const uint8_t params[],
|
|
size_t params_len) const
|
|
{
|
|
return derive_key(key_len, in.data(), in.size(),
|
|
params, params_len);
|
|
}
|
|
|
|
/**
|
|
* Perform Key Agreement Operation
|
|
* @param key_len the desired key output size
|
|
* @param in the other parties key
|
|
* @param in_len the length of in in bytes
|
|
* @param params extra derivation params
|
|
*/
|
|
SymmetricKey derive_key(size_t key_len,
|
|
const uint8_t in[], size_t in_len,
|
|
const std::string& params = "") const
|
|
{
|
|
return derive_key(key_len, in, in_len,
|
|
cast_char_ptr_to_uint8(params.data()),
|
|
params.length());
|
|
}
|
|
|
|
/**
|
|
* Perform Key Agreement Operation
|
|
* @param key_len the desired key output size
|
|
* @param in the other parties key
|
|
* @param params extra derivation params
|
|
*/
|
|
SymmetricKey derive_key(size_t key_len,
|
|
const std::vector<uint8_t>& in,
|
|
const std::string& params = "") const
|
|
{
|
|
return derive_key(key_len, in.data(), in.size(),
|
|
cast_char_ptr_to_uint8(params.data()),
|
|
params.length());
|
|
}
|
|
|
|
/**
|
|
* Return the underlying size of the value that is agreed.
|
|
* If derive_key is called with a length of 0 with a "Raw"
|
|
* KDF, it will return a value of this size.
|
|
*/
|
|
size_t agreed_value_size() const;
|
|
|
|
private:
|
|
std::unique_ptr<PK_Ops::Key_Agreement> m_op;
|
|
};
|
|
|
|
/**
|
|
* Encryption using a standard message recovery algorithm like RSA or
|
|
* ElGamal, paired with an encoding scheme like OAEP.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PK_Encryptor_EME final : public PK_Encryptor
|
|
{
|
|
public:
|
|
size_t maximum_input_size() const override;
|
|
|
|
/**
|
|
* Construct an instance.
|
|
* @param key the key to use inside the encryptor
|
|
* @param rng the RNG to use
|
|
* @param padding the message encoding scheme to use (eg "OAEP(SHA-256)")
|
|
* @param provider the provider to use
|
|
*/
|
|
PK_Encryptor_EME(const Public_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& padding,
|
|
const std::string& provider = "");
|
|
|
|
#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS)
|
|
/**
|
|
* Construct an instance.
|
|
* @param key the key to use inside the encryptor
|
|
* @param padding the message encoding scheme to use (eg "OAEP(SHA-256)")
|
|
*/
|
|
BOTAN_DEPRECATED("Use constructor taking a RNG object")
|
|
PK_Encryptor_EME(const Public_Key& key,
|
|
const std::string& padding,
|
|
const std::string& provider = "") :
|
|
PK_Encryptor_EME(key, system_rng(), padding, provider) {}
|
|
#endif
|
|
|
|
~PK_Encryptor_EME();
|
|
|
|
PK_Encryptor_EME& operator=(const PK_Encryptor_EME&) = delete;
|
|
PK_Encryptor_EME(const PK_Encryptor_EME&) = delete;
|
|
|
|
/**
|
|
* Return an upper bound on the ciphertext length for a particular
|
|
* plaintext input length
|
|
*/
|
|
size_t ciphertext_length(size_t ptext_len) const override;
|
|
private:
|
|
std::vector<uint8_t> enc(const uint8_t[], size_t,
|
|
RandomNumberGenerator& rng) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Encryption> m_op;
|
|
};
|
|
|
|
/**
|
|
* Decryption with an MR algorithm and an EME.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PK_Decryptor_EME final : public PK_Decryptor
|
|
{
|
|
public:
|
|
/**
|
|
* Construct an instance.
|
|
* @param key the key to use inside the decryptor
|
|
* @param rng the random generator to use
|
|
* @param eme the EME to use
|
|
* @param provider the provider to use
|
|
*/
|
|
PK_Decryptor_EME(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& eme,
|
|
const std::string& provider = "");
|
|
|
|
|
|
#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS)
|
|
/**
|
|
* Construct an instance.
|
|
* @param key the key to use inside the decryptor
|
|
* @param eme the message encoding scheme to use (eg "OAEP(SHA-256)")
|
|
*/
|
|
BOTAN_DEPRECATED("Use constructor taking a RNG object")
|
|
PK_Decryptor_EME(const Private_Key& key,
|
|
const std::string& eme,
|
|
const std::string& provider = "") :
|
|
PK_Decryptor_EME(key, system_rng(), eme, provider) {}
|
|
#endif
|
|
|
|
size_t plaintext_length(size_t ptext_len) const override;
|
|
|
|
~PK_Decryptor_EME();
|
|
PK_Decryptor_EME& operator=(const PK_Decryptor_EME&) = delete;
|
|
PK_Decryptor_EME(const PK_Decryptor_EME&) = delete;
|
|
private:
|
|
secure_vector<uint8_t> do_decrypt(uint8_t& valid_mask,
|
|
const uint8_t in[],
|
|
size_t in_len) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Decryption> m_op;
|
|
};
|
|
|
|
/**
|
|
* Public Key Key Encapsulation Mechanism Encryption.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PK_KEM_Encryptor final
|
|
{
|
|
public:
|
|
/**
|
|
* Construct an instance.
|
|
* @param key the key to use inside the encryptor
|
|
* @param rng the RNG to use
|
|
* @param kem_param additional KEM parameters
|
|
* @param provider the provider to use
|
|
*/
|
|
PK_KEM_Encryptor(const Public_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& kem_param = "",
|
|
const std::string& provider = "");
|
|
|
|
#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS)
|
|
BOTAN_DEPRECATED("Use constructor taking a RNG object")
|
|
PK_KEM_Encryptor(const Public_Key& key,
|
|
const std::string& kem_param = "",
|
|
const std::string& provider = "") :
|
|
PK_KEM_Encryptor(key, system_rng(), kem_param, provider) {}
|
|
#endif
|
|
|
|
~PK_KEM_Encryptor();
|
|
|
|
PK_KEM_Encryptor& operator=(const PK_KEM_Encryptor&) = delete;
|
|
PK_KEM_Encryptor(const PK_KEM_Encryptor&) = delete;
|
|
|
|
/**
|
|
* Generate a shared key for data encryption.
|
|
* @param out_encapsulated_key the generated encapsulated key
|
|
* @param out_shared_key the generated shared key
|
|
* @param desired_shared_key_len desired size of the shared key in bytes
|
|
* @param rng the RNG to use
|
|
* @param salt a salt value used in the KDF
|
|
* @param salt_len size of the salt value in bytes
|
|
*/
|
|
void encrypt(secure_vector<uint8_t>& out_encapsulated_key,
|
|
secure_vector<uint8_t>& out_shared_key,
|
|
size_t desired_shared_key_len,
|
|
Botan::RandomNumberGenerator& rng,
|
|
const uint8_t salt[],
|
|
size_t salt_len);
|
|
|
|
/**
|
|
* Generate a shared key for data encryption.
|
|
* @param out_encapsulated_key the generated encapsulated key
|
|
* @param out_shared_key the generated shared key
|
|
* @param desired_shared_key_len desired size of the shared key in bytes
|
|
* @param rng the RNG to use
|
|
* @param salt a salt value used in the KDF
|
|
*/
|
|
template<typename Alloc>
|
|
void encrypt(secure_vector<uint8_t>& out_encapsulated_key,
|
|
secure_vector<uint8_t>& out_shared_key,
|
|
size_t desired_shared_key_len,
|
|
Botan::RandomNumberGenerator& rng,
|
|
const std::vector<uint8_t, Alloc>& salt)
|
|
{
|
|
this->encrypt(out_encapsulated_key,
|
|
out_shared_key,
|
|
desired_shared_key_len,
|
|
rng,
|
|
salt.data(), salt.size());
|
|
}
|
|
|
|
|
|
/**
|
|
* Generate a shared key for data encryption.
|
|
* @param out_encapsulated_key the generated encapsulated key
|
|
* @param out_shared_key the generated shared key
|
|
* @param desired_shared_key_len desired size of the shared key in bytes
|
|
* @param rng the RNG to use
|
|
*/
|
|
void encrypt(secure_vector<uint8_t>& out_encapsulated_key,
|
|
secure_vector<uint8_t>& out_shared_key,
|
|
size_t desired_shared_key_len,
|
|
Botan::RandomNumberGenerator& rng)
|
|
{
|
|
this->encrypt(out_encapsulated_key,
|
|
out_shared_key,
|
|
desired_shared_key_len,
|
|
rng,
|
|
nullptr,
|
|
0);
|
|
}
|
|
|
|
private:
|
|
std::unique_ptr<PK_Ops::KEM_Encryption> m_op;
|
|
};
|
|
|
|
/**
|
|
* Public Key Key Encapsulation Mechanism Decryption.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PK_KEM_Decryptor final
|
|
{
|
|
public:
|
|
/**
|
|
* Construct an instance.
|
|
* @param key the key to use inside the decryptor
|
|
* @param rng the RNG to use
|
|
* @param kem_param additional KEM parameters
|
|
* @param provider the provider to use
|
|
*/
|
|
PK_KEM_Decryptor(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& kem_param = "",
|
|
const std::string& provider = "");
|
|
|
|
#if defined(BOTAN_PUBKEY_INCLUDE_DEPRECATED_CONSTRUCTORS)
|
|
BOTAN_DEPRECATED("Use constructor taking a RNG object")
|
|
PK_KEM_Decryptor(const Private_Key& key,
|
|
const std::string& kem_param = "",
|
|
const std::string& provider = "") :
|
|
PK_KEM_Decryptor(key, system_rng(), kem_param, provider)
|
|
{}
|
|
#endif
|
|
|
|
~PK_KEM_Decryptor();
|
|
PK_KEM_Decryptor& operator=(const PK_KEM_Decryptor&) = delete;
|
|
PK_KEM_Decryptor(const PK_KEM_Decryptor&) = delete;
|
|
|
|
/**
|
|
* Decrypts the shared key for data encryption.
|
|
* @param encap_key the encapsulated key
|
|
* @param encap_key_len size of the encapsulated key in bytes
|
|
* @param desired_shared_key_len desired size of the shared key in bytes
|
|
* @param salt a salt value used in the KDF
|
|
* @param salt_len size of the salt value in bytes
|
|
* @return the shared data encryption key
|
|
*/
|
|
secure_vector<uint8_t> decrypt(const uint8_t encap_key[],
|
|
size_t encap_key_len,
|
|
size_t desired_shared_key_len,
|
|
const uint8_t salt[],
|
|
size_t salt_len);
|
|
|
|
/**
|
|
* Decrypts the shared key for data encryption.
|
|
* @param encap_key the encapsulated key
|
|
* @param encap_key_len size of the encapsulated key in bytes
|
|
* @param desired_shared_key_len desired size of the shared key in bytes
|
|
* @return the shared data encryption key
|
|
*/
|
|
secure_vector<uint8_t> decrypt(const uint8_t encap_key[],
|
|
size_t encap_key_len,
|
|
size_t desired_shared_key_len)
|
|
{
|
|
return this->decrypt(encap_key, encap_key_len,
|
|
desired_shared_key_len,
|
|
nullptr, 0);
|
|
}
|
|
|
|
/**
|
|
* Decrypts the shared key for data encryption.
|
|
* @param encap_key the encapsulated key
|
|
* @param desired_shared_key_len desired size of the shared key in bytes
|
|
* @param salt a salt value used in the KDF
|
|
* @return the shared data encryption key
|
|
*/
|
|
template<typename Alloc1, typename Alloc2>
|
|
secure_vector<uint8_t> decrypt(const std::vector<uint8_t, Alloc1>& encap_key,
|
|
size_t desired_shared_key_len,
|
|
const std::vector<uint8_t, Alloc2>& salt)
|
|
{
|
|
return this->decrypt(encap_key.data(), encap_key.size(),
|
|
desired_shared_key_len,
|
|
salt.data(), salt.size());
|
|
}
|
|
|
|
private:
|
|
std::unique_ptr<PK_Ops::KEM_Decryption> m_op;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Key Derivation Function
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) KDF
|
|
{
|
|
public:
|
|
virtual ~KDF() = default;
|
|
|
|
/**
|
|
* Create an instance based on a name
|
|
* If provider is empty then best available is chosen.
|
|
* @param algo_spec algorithm name
|
|
* @param provider provider implementation to choose
|
|
* @return a null pointer if the algo/provider combination cannot be found
|
|
*/
|
|
static std::unique_ptr<KDF>
|
|
create(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* Create an instance based on a name, or throw if the
|
|
* algo/provider combination cannot be found. If provider is
|
|
* empty then best available is chosen.
|
|
*/
|
|
static std::unique_ptr<KDF>
|
|
create_or_throw(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* @return list of available providers for this algorithm, empty if not available
|
|
*/
|
|
static std::vector<std::string> providers(const std::string& algo_spec);
|
|
|
|
/**
|
|
* @return KDF name
|
|
*/
|
|
virtual std::string name() const = 0;
|
|
|
|
/**
|
|
* Derive a key
|
|
* @param key buffer holding the derived key, must be of length key_len
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret the secret input
|
|
* @param secret_len size of secret in bytes
|
|
* @param salt a diversifier
|
|
* @param salt_len size of salt in bytes
|
|
* @param label purpose for the derived keying material
|
|
* @param label_len size of label in bytes
|
|
* @return the derived key
|
|
*/
|
|
virtual size_t kdf(uint8_t key[], size_t key_len,
|
|
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 = 0;
|
|
|
|
/**
|
|
* Derive a key
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret the secret input
|
|
* @param secret_len size of secret in bytes
|
|
* @param salt a diversifier
|
|
* @param salt_len size of salt in bytes
|
|
* @param label purpose for the derived keying material
|
|
* @param label_len size of label in bytes
|
|
* @return the derived key
|
|
*/
|
|
secure_vector<uint8_t> derive_key(size_t key_len,
|
|
const uint8_t secret[],
|
|
size_t secret_len,
|
|
const uint8_t salt[],
|
|
size_t salt_len,
|
|
const uint8_t label[] = nullptr,
|
|
size_t label_len = 0) const
|
|
{
|
|
secure_vector<uint8_t> key(key_len);
|
|
key.resize(kdf(key.data(), key.size(), secret, secret_len, salt, salt_len, label, label_len));
|
|
return key;
|
|
}
|
|
|
|
/**
|
|
* Derive a key
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret the secret input
|
|
* @param salt a diversifier
|
|
* @param label purpose for the derived keying material
|
|
* @return the derived key
|
|
*/
|
|
secure_vector<uint8_t> derive_key(size_t key_len,
|
|
const secure_vector<uint8_t>& secret,
|
|
const std::string& salt = "",
|
|
const std::string& label = "") const
|
|
{
|
|
return derive_key(key_len, secret.data(), secret.size(),
|
|
cast_char_ptr_to_uint8(salt.data()),
|
|
salt.length(),
|
|
cast_char_ptr_to_uint8(label.data()),
|
|
label.length());
|
|
|
|
}
|
|
|
|
/**
|
|
* Derive a key
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret the secret input
|
|
* @param salt a diversifier
|
|
* @param label purpose for the derived keying material
|
|
* @return the derived key
|
|
*/
|
|
template<typename Alloc, typename Alloc2, typename Alloc3>
|
|
secure_vector<uint8_t> derive_key(size_t key_len,
|
|
const std::vector<uint8_t, Alloc>& secret,
|
|
const std::vector<uint8_t, Alloc2>& salt,
|
|
const std::vector<uint8_t, Alloc3>& label) const
|
|
{
|
|
return derive_key(key_len,
|
|
secret.data(), secret.size(),
|
|
salt.data(), salt.size(),
|
|
label.data(), label.size());
|
|
}
|
|
|
|
/**
|
|
* Derive a key
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret the secret input
|
|
* @param salt a diversifier
|
|
* @param salt_len size of salt in bytes
|
|
* @param label purpose for the derived keying material
|
|
* @return the derived key
|
|
*/
|
|
secure_vector<uint8_t> derive_key(size_t key_len,
|
|
const secure_vector<uint8_t>& secret,
|
|
const uint8_t salt[],
|
|
size_t salt_len,
|
|
const std::string& label = "") const
|
|
{
|
|
return derive_key(key_len,
|
|
secret.data(), secret.size(),
|
|
salt, salt_len,
|
|
cast_char_ptr_to_uint8(label.data()),
|
|
label.size());
|
|
}
|
|
|
|
/**
|
|
* Derive a key
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret the secret input
|
|
* @param secret_len size of secret in bytes
|
|
* @param salt a diversifier
|
|
* @param label purpose for the derived keying material
|
|
* @return the derived key
|
|
*/
|
|
secure_vector<uint8_t> derive_key(size_t key_len,
|
|
const uint8_t secret[],
|
|
size_t secret_len,
|
|
const std::string& salt = "",
|
|
const std::string& label = "") const
|
|
{
|
|
return derive_key(key_len, secret, secret_len,
|
|
cast_char_ptr_to_uint8(salt.data()),
|
|
salt.length(),
|
|
cast_char_ptr_to_uint8(label.data()),
|
|
label.length());
|
|
}
|
|
|
|
/**
|
|
* @return new object representing the same algorithm as *this
|
|
*/
|
|
virtual KDF* clone() const = 0;
|
|
};
|
|
|
|
/**
|
|
* Factory method for KDF (key derivation function)
|
|
* @param algo_spec the name of the KDF to create
|
|
* @return pointer to newly allocated object of that type
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) KDF* get_kdf(const std::string& algo_spec);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* DLIES Encryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DLIES_Encryptor final : public PK_Encryptor
|
|
{
|
|
public:
|
|
/**
|
|
* Stream mode: use KDF to provide a stream of bytes to xor with the message
|
|
*
|
|
* @param own_priv_key own (ephemeral) DH private key
|
|
* @param rng the RNG to use
|
|
* @param kdf the KDF that should be used
|
|
* @param mac the MAC function that should be used
|
|
* @param mac_key_len key length of the MAC function. Default = 20 bytes
|
|
*
|
|
* output = (ephemeral) public key + ciphertext + tag
|
|
*/
|
|
DLIES_Encryptor(const DH_PrivateKey& own_priv_key,
|
|
RandomNumberGenerator& rng,
|
|
KDF* kdf,
|
|
MessageAuthenticationCode* mac,
|
|
size_t mac_key_len = 20);
|
|
|
|
/**
|
|
* Block cipher mode
|
|
*
|
|
* @param own_priv_key own (ephemeral) DH private key
|
|
* @param rng the RNG to use
|
|
* @param kdf the KDF that should be used
|
|
* @param cipher the block cipher that should be used
|
|
* @param cipher_key_len the key length of the block cipher
|
|
* @param mac the MAC function that should be used
|
|
* @param mac_key_len key length of the MAC function. Default = 20 bytes
|
|
*
|
|
* output = (ephemeral) public key + ciphertext + tag
|
|
*/
|
|
DLIES_Encryptor(const DH_PrivateKey& own_priv_key,
|
|
RandomNumberGenerator& rng,
|
|
KDF* kdf,
|
|
Cipher_Mode* cipher,
|
|
size_t cipher_key_len,
|
|
MessageAuthenticationCode* mac,
|
|
size_t mac_key_len = 20);
|
|
|
|
// Set the other parties public key
|
|
inline void set_other_key(const std::vector<uint8_t>& other_pub_key)
|
|
{
|
|
m_other_pub_key = other_pub_key;
|
|
}
|
|
|
|
/// Set the initialization vector for the data encryption method
|
|
inline void set_initialization_vector(const InitializationVector& iv)
|
|
{
|
|
m_iv = iv;
|
|
}
|
|
|
|
private:
|
|
std::vector<uint8_t> enc(const uint8_t[], size_t,
|
|
RandomNumberGenerator&) const override;
|
|
|
|
size_t maximum_input_size() const override;
|
|
|
|
size_t ciphertext_length(size_t ptext_len) const override;
|
|
|
|
std::vector<uint8_t> m_other_pub_key;
|
|
std::vector<uint8_t> m_own_pub_key;
|
|
PK_Key_Agreement m_ka;
|
|
std::unique_ptr<KDF> m_kdf;
|
|
std::unique_ptr<Cipher_Mode> m_cipher;
|
|
const size_t m_cipher_key_len;
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
const size_t m_mac_keylen;
|
|
InitializationVector m_iv;
|
|
};
|
|
|
|
/**
|
|
* DLIES Decryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DLIES_Decryptor final : public PK_Decryptor
|
|
{
|
|
public:
|
|
/**
|
|
* Stream mode: use KDF to provide a stream of bytes to xor with the message
|
|
*
|
|
* @param own_priv_key own (ephemeral) DH private key
|
|
* @param rng the RNG to use
|
|
* @param kdf the KDF that should be used
|
|
* @param mac the MAC function that should be used
|
|
* @param mac_key_len key length of the MAC function. Default = 20 bytes
|
|
*
|
|
* input = (ephemeral) public key + ciphertext + tag
|
|
*/
|
|
DLIES_Decryptor(const DH_PrivateKey& own_priv_key,
|
|
RandomNumberGenerator& rng,
|
|
KDF* kdf,
|
|
MessageAuthenticationCode* mac,
|
|
size_t mac_key_len = 20);
|
|
|
|
/**
|
|
* Block cipher mode
|
|
*
|
|
* @param own_priv_key own (ephemeral) DH private key
|
|
* @param rng the RNG to use
|
|
* @param kdf the KDF that should be used
|
|
* @param cipher the block cipher that should be used
|
|
* @param cipher_key_len the key length of the block cipher
|
|
* @param mac the MAC function that should be used
|
|
* @param mac_key_len key length of the MAC function. Default = 20 bytes
|
|
*
|
|
* input = (ephemeral) public key + ciphertext + tag
|
|
*/
|
|
DLIES_Decryptor(const DH_PrivateKey& own_priv_key,
|
|
RandomNumberGenerator& rng,
|
|
KDF* kdf,
|
|
Cipher_Mode* cipher,
|
|
size_t cipher_key_len,
|
|
MessageAuthenticationCode* mac,
|
|
size_t mac_key_len = 20);
|
|
|
|
/// Set the initialization vector for the data decryption method
|
|
inline void set_initialization_vector(const InitializationVector& iv)
|
|
{
|
|
m_iv = iv;
|
|
}
|
|
|
|
private:
|
|
secure_vector<uint8_t> do_decrypt(uint8_t& valid_mask,
|
|
const uint8_t in[], size_t in_len) const override;
|
|
|
|
size_t plaintext_length(size_t ctext_len) const override;
|
|
|
|
const size_t m_pub_key_size;
|
|
PK_Key_Agreement m_ka;
|
|
std::unique_ptr<KDF> m_kdf;
|
|
std::unique_ptr<Cipher_Mode> m_cipher;
|
|
const size_t m_cipher_key_len;
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
const size_t m_mac_keylen;
|
|
InitializationVector m_iv;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* DSA Public Key
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DSA_PublicKey : public virtual DL_Scheme_PublicKey
|
|
{
|
|
public:
|
|
std::string algo_name() const override { return "DSA"; }
|
|
|
|
DL_Group::Format group_format() const override { return DL_Group::ANSI_X9_57; }
|
|
size_t message_parts() const override { return 2; }
|
|
size_t message_part_size() const override { return group_q().bytes(); }
|
|
|
|
/**
|
|
* Load a public key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
DSA_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits) :
|
|
DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_57)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Create a public key.
|
|
* @param group the underlying DL group
|
|
* @param y the public value y = g^x mod p
|
|
*/
|
|
DSA_PublicKey(const DL_Group& group, const BigInt& y);
|
|
|
|
std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string& params,
|
|
const std::string& provider) const override;
|
|
protected:
|
|
DSA_PublicKey() = default;
|
|
};
|
|
|
|
/**
|
|
* DSA Private Key
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) DSA_PrivateKey final : public DSA_PublicKey,
|
|
public virtual DL_Scheme_PrivateKey
|
|
{
|
|
public:
|
|
/**
|
|
* Load a private key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded key bits in ANSI X9.57 format
|
|
*/
|
|
DSA_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Create a private key.
|
|
* @param rng the RNG to use
|
|
* @param group the underlying DL group
|
|
* @param private_key the private key (if zero, a new random key is generated)
|
|
*/
|
|
DSA_PrivateKey(RandomNumberGenerator& rng,
|
|
const DL_Group& group,
|
|
const BigInt& private_key = 0);
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool strong) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Represents a DLL or shared object
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Dynamically_Loaded_Library final
|
|
{
|
|
public:
|
|
/**
|
|
* Load a DLL (or fail with an exception)
|
|
* @param lib_name name or path to a library
|
|
*
|
|
* If you don't use a full path, the search order will be defined
|
|
* by whatever the system linker does by default. Always using fully
|
|
* qualified pathnames can help prevent code injection attacks (eg
|
|
* via manipulation of LD_LIBRARY_PATH on Linux)
|
|
*/
|
|
Dynamically_Loaded_Library(const std::string& lib_name);
|
|
|
|
/**
|
|
* Unload the DLL
|
|
* @warning Any pointers returned by resolve()/resolve_symbol()
|
|
* should not be used after this destructor runs.
|
|
*/
|
|
~Dynamically_Loaded_Library();
|
|
|
|
/**
|
|
* Load a symbol (or fail with an exception)
|
|
* @param symbol names the symbol to load
|
|
* @return address of the loaded symbol
|
|
*/
|
|
void* resolve_symbol(const std::string& symbol);
|
|
|
|
/**
|
|
* Convenience function for casting symbol to the right type
|
|
* @param symbol names the symbol to load
|
|
* @return address of the loaded symbol
|
|
*/
|
|
template<typename T>
|
|
T resolve(const std::string& symbol)
|
|
{
|
|
return reinterpret_cast<T>(resolve_symbol(symbol));
|
|
}
|
|
|
|
private:
|
|
Dynamically_Loaded_Library(const Dynamically_Loaded_Library&);
|
|
Dynamically_Loaded_Library& operator=(const Dynamically_Loaded_Library&);
|
|
|
|
std::string m_lib_name;
|
|
void* m_lib;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(eax.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* EAX base class
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EAX_Mode : public AEAD_Mode
|
|
{
|
|
public:
|
|
void set_associated_data(const uint8_t ad[], size_t ad_len) override;
|
|
|
|
std::string name() const override;
|
|
|
|
size_t update_granularity() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
// EAX supports arbitrary nonce lengths
|
|
bool valid_nonce_length(size_t) const override { return true; }
|
|
|
|
size_t tag_size() const override { return m_tag_size; }
|
|
|
|
void clear() override;
|
|
|
|
void reset() override;
|
|
|
|
protected:
|
|
/**
|
|
* @param cipher the cipher to use
|
|
* @param tag_size is how big the auth tag will be
|
|
*/
|
|
EAX_Mode(BlockCipher* cipher, size_t tag_size);
|
|
|
|
size_t block_size() const { return m_cipher->block_size(); }
|
|
|
|
size_t m_tag_size;
|
|
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
std::unique_ptr<StreamCipher> m_ctr;
|
|
std::unique_ptr<MessageAuthenticationCode> m_cmac;
|
|
|
|
secure_vector<uint8_t> m_ad_mac;
|
|
|
|
secure_vector<uint8_t> m_nonce_mac;
|
|
private:
|
|
void start_msg(const uint8_t nonce[], size_t nonce_len) override;
|
|
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
};
|
|
|
|
/**
|
|
* EAX Encryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EAX_Encryption final : public EAX_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher a 128-bit block cipher
|
|
* @param tag_size is how big the auth tag will be
|
|
*/
|
|
EAX_Encryption(BlockCipher* cipher, size_t tag_size = 0) :
|
|
EAX_Mode(cipher, tag_size) {}
|
|
|
|
size_t output_length(size_t input_length) const override
|
|
{ return input_length + tag_size(); }
|
|
|
|
size_t minimum_final_size() const override { return 0; }
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
};
|
|
|
|
/**
|
|
* EAX Decryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EAX_Decryption final : public EAX_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher a 128-bit block cipher
|
|
* @param tag_size is how big the auth tag will be
|
|
*/
|
|
EAX_Decryption(BlockCipher* cipher, size_t tag_size = 0) :
|
|
EAX_Mode(cipher, tag_size) {}
|
|
|
|
size_t output_length(size_t input_length) const override
|
|
{
|
|
BOTAN_ASSERT(input_length >= tag_size(), "Sufficient input");
|
|
return input_length - tag_size();
|
|
}
|
|
|
|
size_t minimum_final_size() const override { return tag_size(); }
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Exception thrown if you try to convert a zero point to an affine
|
|
* coordinate
|
|
*
|
|
* In a future major release this exception type will be removed and its
|
|
* usage replaced by Invalid_State
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Illegal_Transformation final : public Invalid_State
|
|
{
|
|
public:
|
|
explicit Illegal_Transformation(const std::string& err) : Invalid_State(err) {}
|
|
};
|
|
|
|
/**
|
|
* Exception thrown if some form of illegal point is decoded
|
|
*
|
|
* In a future major release this exception type will be removed and its
|
|
* usage replaced by Decoding_Error
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Illegal_Point final : public Decoding_Error
|
|
{
|
|
public:
|
|
explicit Illegal_Point(const std::string& err) : Decoding_Error(err) {}
|
|
};
|
|
|
|
/**
|
|
* This class represents one point on a curve of GF(p)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PointGFp final
|
|
{
|
|
public:
|
|
enum Compression_Type {
|
|
UNCOMPRESSED = 0,
|
|
COMPRESSED = 1,
|
|
HYBRID = 2
|
|
};
|
|
|
|
enum { WORKSPACE_SIZE = 8 };
|
|
|
|
/**
|
|
* Construct an uninitialized PointGFp
|
|
*/
|
|
PointGFp() = default;
|
|
|
|
/**
|
|
* Construct the zero point
|
|
* @param curve The base curve
|
|
*/
|
|
explicit PointGFp(const CurveGFp& curve);
|
|
|
|
/**
|
|
* Copy constructor
|
|
*/
|
|
PointGFp(const PointGFp&) = default;
|
|
|
|
/**
|
|
* Move Constructor
|
|
*/
|
|
PointGFp(PointGFp&& other)
|
|
{
|
|
this->swap(other);
|
|
}
|
|
|
|
/**
|
|
* Standard Assignment
|
|
*/
|
|
PointGFp& operator=(const PointGFp&) = default;
|
|
|
|
/**
|
|
* Move Assignment
|
|
*/
|
|
PointGFp& operator=(PointGFp&& other)
|
|
{
|
|
if(this != &other)
|
|
this->swap(other);
|
|
return (*this);
|
|
}
|
|
|
|
/**
|
|
* Construct a point from its affine coordinates
|
|
* Prefer EC_Group::point(x,y) for this operation.
|
|
* @param curve the base curve
|
|
* @param x affine x coordinate
|
|
* @param y affine y coordinate
|
|
*/
|
|
PointGFp(const CurveGFp& curve, const BigInt& x, const BigInt& y);
|
|
|
|
/**
|
|
* EC2OSP - elliptic curve to octet string primitive
|
|
* @param format which format to encode using
|
|
*/
|
|
std::vector<uint8_t> encode(PointGFp::Compression_Type format) const;
|
|
|
|
/**
|
|
* += Operator
|
|
* @param rhs the PointGFp to add to the local value
|
|
* @result resulting PointGFp
|
|
*/
|
|
PointGFp& operator+=(const PointGFp& rhs);
|
|
|
|
/**
|
|
* -= Operator
|
|
* @param rhs the PointGFp to subtract from the local value
|
|
* @result resulting PointGFp
|
|
*/
|
|
PointGFp& operator-=(const PointGFp& rhs);
|
|
|
|
/**
|
|
* *= Operator
|
|
* @param scalar the PointGFp to multiply with *this
|
|
* @result resulting PointGFp
|
|
*/
|
|
PointGFp& operator*=(const BigInt& scalar);
|
|
|
|
/**
|
|
* Negate this point
|
|
* @return *this
|
|
*/
|
|
PointGFp& negate()
|
|
{
|
|
if(!is_zero())
|
|
m_coord_y = m_curve.get_p() - m_coord_y;
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* get affine x coordinate
|
|
* @result affine x coordinate
|
|
*/
|
|
BigInt get_affine_x() const;
|
|
|
|
/**
|
|
* get affine y coordinate
|
|
* @result affine y coordinate
|
|
*/
|
|
BigInt get_affine_y() const;
|
|
|
|
const BigInt& get_x() const { return m_coord_x; }
|
|
const BigInt& get_y() const { return m_coord_y; }
|
|
const BigInt& get_z() const { return m_coord_z; }
|
|
|
|
void swap_coords(BigInt& new_x, BigInt& new_y, BigInt& new_z)
|
|
{
|
|
m_coord_x.swap(new_x);
|
|
m_coord_y.swap(new_y);
|
|
m_coord_z.swap(new_z);
|
|
}
|
|
|
|
/**
|
|
* Force this point to affine coordinates
|
|
*/
|
|
void force_affine();
|
|
|
|
/**
|
|
* Force all points on the list to affine coordinates
|
|
*/
|
|
static void force_all_affine(std::vector<PointGFp>& points,
|
|
secure_vector<word>& ws);
|
|
|
|
bool is_affine() const;
|
|
|
|
/**
|
|
* Is this the point at infinity?
|
|
* @result true, if this point is at infinity, false otherwise.
|
|
*/
|
|
bool is_zero() const { return m_coord_z.is_zero(); }
|
|
|
|
/**
|
|
* Checks whether the point is to be found on the underlying
|
|
* curve; used to prevent fault attacks.
|
|
* @return if the point is on the curve
|
|
*/
|
|
bool on_the_curve() const;
|
|
|
|
/**
|
|
* swaps the states of *this and other, does not throw!
|
|
* @param other the object to swap values with
|
|
*/
|
|
void swap(PointGFp& other);
|
|
|
|
/**
|
|
* Randomize the point representation
|
|
* The actual value (get_affine_x, get_affine_y) does not change
|
|
*/
|
|
void randomize_repr(RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Randomize the point representation
|
|
* The actual value (get_affine_x, get_affine_y) does not change
|
|
*/
|
|
void randomize_repr(RandomNumberGenerator& rng, secure_vector<word>& ws);
|
|
|
|
/**
|
|
* Equality operator
|
|
*/
|
|
bool operator==(const PointGFp& other) const;
|
|
|
|
/**
|
|
* Point addition
|
|
* @param other the point to add to *this
|
|
* @param workspace temp space, at least WORKSPACE_SIZE elements
|
|
*/
|
|
void add(const PointGFp& other, std::vector<BigInt>& workspace)
|
|
{
|
|
BOTAN_ASSERT_NOMSG(m_curve == other.m_curve);
|
|
|
|
const size_t p_words = m_curve.get_p_words();
|
|
|
|
add(other.m_coord_x.data(), std::min(p_words, other.m_coord_x.size()),
|
|
other.m_coord_y.data(), std::min(p_words, other.m_coord_y.size()),
|
|
other.m_coord_z.data(), std::min(p_words, other.m_coord_z.size()),
|
|
workspace);
|
|
}
|
|
|
|
/**
|
|
* Point addition. Array version.
|
|
*
|
|
* @param x_words the words of the x coordinate of the other point
|
|
* @param x_size size of x_words
|
|
* @param y_words the words of the y coordinate of the other point
|
|
* @param y_size size of y_words
|
|
* @param z_words the words of the z coordinate of the other point
|
|
* @param z_size size of z_words
|
|
* @param workspace temp space, at least WORKSPACE_SIZE elements
|
|
*/
|
|
void add(const word x_words[], size_t x_size,
|
|
const word y_words[], size_t y_size,
|
|
const word z_words[], size_t z_size,
|
|
std::vector<BigInt>& workspace);
|
|
|
|
/**
|
|
* Point addition - mixed J+A
|
|
* @param other affine point to add - assumed to be affine!
|
|
* @param workspace temp space, at least WORKSPACE_SIZE elements
|
|
*/
|
|
void add_affine(const PointGFp& other, std::vector<BigInt>& workspace)
|
|
{
|
|
BOTAN_ASSERT_NOMSG(m_curve == other.m_curve);
|
|
BOTAN_DEBUG_ASSERT(other.is_affine());
|
|
|
|
const size_t p_words = m_curve.get_p_words();
|
|
add_affine(other.m_coord_x.data(), std::min(p_words, other.m_coord_x.size()),
|
|
other.m_coord_y.data(), std::min(p_words, other.m_coord_y.size()),
|
|
workspace);
|
|
}
|
|
|
|
/**
|
|
* Point addition - mixed J+A. Array version.
|
|
*
|
|
* @param x_words the words of the x coordinate of the other point
|
|
* @param x_size size of x_words
|
|
* @param y_words the words of the y coordinate of the other point
|
|
* @param y_size size of y_words
|
|
* @param workspace temp space, at least WORKSPACE_SIZE elements
|
|
*/
|
|
void add_affine(const word x_words[], size_t x_size,
|
|
const word y_words[], size_t y_size,
|
|
std::vector<BigInt>& workspace);
|
|
|
|
/**
|
|
* Point doubling
|
|
* @param workspace temp space, at least WORKSPACE_SIZE elements
|
|
*/
|
|
void mult2(std::vector<BigInt>& workspace);
|
|
|
|
/**
|
|
* Repeated point doubling
|
|
* @param i number of doublings to perform
|
|
* @param workspace temp space, at least WORKSPACE_SIZE elements
|
|
*/
|
|
void mult2i(size_t i, std::vector<BigInt>& workspace);
|
|
|
|
/**
|
|
* Point addition
|
|
* @param other the point to add to *this
|
|
* @param workspace temp space, at least WORKSPACE_SIZE elements
|
|
* @return other plus *this
|
|
*/
|
|
PointGFp plus(const PointGFp& other, std::vector<BigInt>& workspace) const
|
|
{
|
|
PointGFp x = (*this);
|
|
x.add(other, workspace);
|
|
return x;
|
|
}
|
|
|
|
/**
|
|
* Point doubling
|
|
* @param workspace temp space, at least WORKSPACE_SIZE elements
|
|
* @return *this doubled
|
|
*/
|
|
PointGFp double_of(std::vector<BigInt>& workspace) const
|
|
{
|
|
PointGFp x = (*this);
|
|
x.mult2(workspace);
|
|
return x;
|
|
}
|
|
|
|
/**
|
|
* Return the zero (aka infinite) point associated with this curve
|
|
*/
|
|
PointGFp zero() const { return PointGFp(m_curve); }
|
|
|
|
/**
|
|
* Return base curve of this point
|
|
* @result the curve over GF(p) of this point
|
|
*
|
|
* You should not need to use this
|
|
*/
|
|
const CurveGFp& get_curve() const { return m_curve; }
|
|
|
|
private:
|
|
CurveGFp m_curve;
|
|
BigInt m_coord_x, m_coord_y, m_coord_z;
|
|
};
|
|
|
|
/**
|
|
* Point multiplication operator
|
|
* @param scalar the scalar value
|
|
* @param point the point value
|
|
* @return scalar*point on the curve
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) PointGFp operator*(const BigInt& scalar, const PointGFp& point);
|
|
|
|
/**
|
|
* ECC point multiexponentiation - not constant time!
|
|
* @param p1 a point
|
|
* @param z1 a scalar
|
|
* @param p2 a point
|
|
* @param z2 a scalar
|
|
* @result (p1 * z1 + p2 * z2)
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) PointGFp multi_exponentiate(
|
|
const PointGFp& p1, const BigInt& z1,
|
|
const PointGFp& p2, const BigInt& z2);
|
|
|
|
// relational operators
|
|
inline bool operator!=(const PointGFp& lhs, const PointGFp& rhs)
|
|
{
|
|
return !(rhs == lhs);
|
|
}
|
|
|
|
// arithmetic operators
|
|
inline PointGFp operator-(const PointGFp& lhs)
|
|
{
|
|
return PointGFp(lhs).negate();
|
|
}
|
|
|
|
inline PointGFp operator+(const PointGFp& lhs, const PointGFp& rhs)
|
|
{
|
|
PointGFp tmp(lhs);
|
|
return tmp += rhs;
|
|
}
|
|
|
|
inline PointGFp operator-(const PointGFp& lhs, const PointGFp& rhs)
|
|
{
|
|
PointGFp tmp(lhs);
|
|
return tmp -= rhs;
|
|
}
|
|
|
|
inline PointGFp operator*(const PointGFp& point, const BigInt& scalar)
|
|
{
|
|
return scalar * point;
|
|
}
|
|
|
|
// encoding and decoding
|
|
inline secure_vector<uint8_t> BOTAN_DEPRECATED("Use PointGFp::encode")
|
|
EC2OSP(const PointGFp& point, uint8_t format)
|
|
{
|
|
std::vector<uint8_t> enc = point.encode(static_cast<PointGFp::Compression_Type>(format));
|
|
return secure_vector<uint8_t>(enc.begin(), enc.end());
|
|
}
|
|
|
|
/**
|
|
* Perform point decoding
|
|
* Use EC_Group::OS2ECP instead
|
|
*/
|
|
PointGFp BOTAN_PUBLIC_API(2,0) OS2ECP(const uint8_t data[], size_t data_len,
|
|
const CurveGFp& curve);
|
|
|
|
/**
|
|
* Perform point decoding
|
|
* Use EC_Group::OS2ECP instead
|
|
*
|
|
* @param data the encoded point
|
|
* @param data_len length of data in bytes
|
|
* @param curve_p the curve equation prime
|
|
* @param curve_a the curve equation a parameter
|
|
* @param curve_b the curve equation b parameter
|
|
*/
|
|
std::pair<BigInt, BigInt> BOTAN_UNSTABLE_API OS2ECP(const uint8_t data[], size_t data_len,
|
|
const BigInt& curve_p,
|
|
const BigInt& curve_a,
|
|
const BigInt& curve_b);
|
|
|
|
template<typename Alloc>
|
|
PointGFp OS2ECP(const std::vector<uint8_t, Alloc>& data, const CurveGFp& curve)
|
|
{ return OS2ECP(data.data(), data.size(), curve); }
|
|
|
|
class PointGFp_Var_Point_Precompute;
|
|
|
|
/**
|
|
* Deprecated API for point multiplication
|
|
* Use EC_Group::blinded_base_point_multiply or EC_Group::blinded_var_point_multiply
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Blinded_Point_Multiply final
|
|
{
|
|
public:
|
|
Blinded_Point_Multiply(const PointGFp& base, const BigInt& order, size_t h = 0);
|
|
|
|
~Blinded_Point_Multiply();
|
|
|
|
PointGFp BOTAN_DEPRECATED("Use alternative APIs") blinded_multiply(const BigInt& scalar, RandomNumberGenerator& rng);
|
|
private:
|
|
std::vector<BigInt> m_ws;
|
|
const BigInt& m_order;
|
|
std::unique_ptr<PointGFp_Var_Point_Precompute> m_point_mul;
|
|
};
|
|
|
|
}
|
|
|
|
namespace std {
|
|
|
|
template<>
|
|
inline void swap<Botan::PointGFp>(Botan::PointGFp& x, Botan::PointGFp& y)
|
|
{ x.swap(y); }
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents elliptic curce domain parameters
|
|
*/
|
|
enum EC_Group_Encoding {
|
|
EC_DOMPAR_ENC_EXPLICIT = 0,
|
|
EC_DOMPAR_ENC_IMPLICITCA = 1,
|
|
EC_DOMPAR_ENC_OID = 2
|
|
};
|
|
|
|
enum class EC_Group_Source {
|
|
Builtin,
|
|
ExternalSource,
|
|
};
|
|
|
|
class CurveGFp;
|
|
|
|
class EC_Group_Data;
|
|
class EC_Group_Data_Map;
|
|
|
|
/**
|
|
* Class representing an elliptic curve
|
|
*
|
|
* The internal representation is stored in a shared_ptr, so copying an
|
|
* EC_Group is inexpensive.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EC_Group final
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Construct Domain paramers from specified parameters
|
|
* @param curve elliptic curve
|
|
* @param base_point a base point
|
|
* @param order the order of the base point
|
|
* @param cofactor the cofactor
|
|
*/
|
|
BOTAN_DEPRECATED("Use version taking all BigInts")
|
|
EC_Group(const CurveGFp& curve,
|
|
const PointGFp& base_point,
|
|
const BigInt& order,
|
|
const BigInt& cofactor) :
|
|
EC_Group(curve.get_p(),
|
|
curve.get_a(),
|
|
curve.get_b(),
|
|
base_point.get_affine_x(),
|
|
base_point.get_affine_y(),
|
|
order,
|
|
cofactor) {}
|
|
|
|
/**
|
|
* Construct Domain paramers from specified parameters
|
|
* @param p the elliptic curve p
|
|
* @param a the elliptic curve a param
|
|
* @param b the elliptic curve b param
|
|
* @param base_x the x coordinate of the base point
|
|
* @param base_y the y coordinate of the base point
|
|
* @param order the order of the base point
|
|
* @param cofactor the cofactor
|
|
* @param oid an optional OID used to identify this curve
|
|
*/
|
|
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());
|
|
|
|
/**
|
|
* Decode a BER encoded ECC domain parameter set
|
|
* @param ber the bytes of the BER encoding
|
|
* @param ber_len the length of ber
|
|
*/
|
|
explicit EC_Group(const uint8_t ber[], size_t ber_len);
|
|
|
|
template<typename Alloc>
|
|
EC_Group(const std::vector<uint8_t, Alloc>& ber) :
|
|
EC_Group(ber.data(), ber.size()) {}
|
|
|
|
/**
|
|
* Create an EC domain by OID (or throw if unknown)
|
|
* @param oid the OID of the EC domain to create
|
|
*/
|
|
explicit EC_Group(const OID& oid);
|
|
|
|
/**
|
|
* Create an EC domain from PEM encoding (as from PEM_encode), or
|
|
* from an OID name (eg "secp256r1", or "1.2.840.10045.3.1.7")
|
|
* @param pem_or_oid PEM-encoded data, or an OID
|
|
|
|
* @warning Support for PEM in this function is deprecated. Use
|
|
* EC_Group_from_PEM
|
|
*/
|
|
explicit EC_Group(const std::string& pem_or_oid);
|
|
|
|
static EC_Group EC_Group_from_PEM(const std::string& pem);
|
|
|
|
/**
|
|
* Create an uninitialized EC_Group
|
|
*/
|
|
EC_Group();
|
|
|
|
~EC_Group();
|
|
|
|
EC_Group(const EC_Group&) = default;
|
|
EC_Group(EC_Group&&) = default;
|
|
|
|
EC_Group& operator=(const EC_Group&) = default;
|
|
EC_Group& operator=(EC_Group&&) = default;
|
|
|
|
/**
|
|
* Create the DER encoding of this domain
|
|
* @param form of encoding to use
|
|
* @returns bytes encododed as DER
|
|
*/
|
|
std::vector<uint8_t> DER_encode(EC_Group_Encoding form) const;
|
|
|
|
/**
|
|
* Return the PEM encoding (always in explicit form)
|
|
* @return string containing PEM data
|
|
*/
|
|
std::string PEM_encode() const;
|
|
|
|
/**
|
|
* Return domain parameter curve
|
|
* @result domain parameter curve
|
|
*/
|
|
BOTAN_DEPRECATED("Avoid CurveGFp") const CurveGFp& get_curve() const;
|
|
|
|
/**
|
|
* Return if a == -3 mod p
|
|
*/
|
|
bool a_is_minus_3() const;
|
|
|
|
/**
|
|
* Return if a == 0 mod p
|
|
*/
|
|
bool a_is_zero() const;
|
|
|
|
/**
|
|
* Return the size of p in bits (same as get_p().bits())
|
|
*/
|
|
size_t get_p_bits() const;
|
|
|
|
/**
|
|
* Return the size of p in bits (same as get_p().bytes())
|
|
*/
|
|
size_t get_p_bytes() const;
|
|
|
|
/**
|
|
* Return the size of group order in bits (same as get_order().bits())
|
|
*/
|
|
size_t get_order_bits() const;
|
|
|
|
/**
|
|
* Return the size of p in bytes (same as get_order().bytes())
|
|
*/
|
|
size_t get_order_bytes() const;
|
|
|
|
/**
|
|
* Return the prime modulus of the field
|
|
*/
|
|
const BigInt& get_p() const;
|
|
|
|
/**
|
|
* Return the a parameter of the elliptic curve equation
|
|
*/
|
|
const BigInt& get_a() const;
|
|
|
|
/**
|
|
* Return the b parameter of the elliptic curve equation
|
|
*/
|
|
const BigInt& get_b() const;
|
|
|
|
/**
|
|
* Return group base point
|
|
* @result base point
|
|
*/
|
|
const PointGFp& get_base_point() const;
|
|
|
|
/**
|
|
* Return the x coordinate of the base point
|
|
*/
|
|
const BigInt& get_g_x() const;
|
|
|
|
/**
|
|
* Return the y coordinate of the base point
|
|
*/
|
|
const BigInt& get_g_y() const;
|
|
|
|
/**
|
|
* Return the order of the base point
|
|
* @result order of the base point
|
|
*/
|
|
const BigInt& get_order() const;
|
|
|
|
/*
|
|
* Reduce x modulo the order
|
|
*/
|
|
BigInt mod_order(const BigInt& x) const;
|
|
|
|
/*
|
|
* Return inverse of x modulo the order
|
|
*/
|
|
BigInt inverse_mod_order(const BigInt& x) const;
|
|
|
|
/*
|
|
* Reduce (x*x) modulo the order
|
|
*/
|
|
BigInt square_mod_order(const BigInt& x) const;
|
|
|
|
/*
|
|
* Reduce (x*y) modulo the order
|
|
*/
|
|
BigInt multiply_mod_order(const BigInt& x, const BigInt& y) const;
|
|
|
|
/*
|
|
* Reduce (x*y*z) modulo the order
|
|
*/
|
|
BigInt multiply_mod_order(const BigInt& x, const BigInt& y, const BigInt& z) const;
|
|
|
|
/**
|
|
* Return the cofactor
|
|
* @result the cofactor
|
|
*/
|
|
const BigInt& get_cofactor() const;
|
|
|
|
/**
|
|
* Check if y is a plausible point on the curve
|
|
*
|
|
* In particular, checks that it is a point on the curve, not infinity,
|
|
* and that it has order matching the group.
|
|
*/
|
|
bool verify_public_element(const PointGFp& y) const;
|
|
|
|
/**
|
|
* Return the OID of these domain parameters
|
|
* @result the OID as a string
|
|
*/
|
|
std::string BOTAN_DEPRECATED("Use get_curve_oid") get_oid() const { return get_curve_oid().to_string(); }
|
|
|
|
/**
|
|
* Return the OID of these domain parameters
|
|
* @result the OID
|
|
*/
|
|
const OID& get_curve_oid() const;
|
|
|
|
/**
|
|
* Return a point on this curve with the affine values x, y
|
|
*/
|
|
PointGFp point(const BigInt& x, const BigInt& y) const;
|
|
|
|
/**
|
|
* Multi exponentiate. Not constant time.
|
|
* @return base_point*x + pt*y
|
|
*/
|
|
PointGFp point_multiply(const BigInt& x, const PointGFp& pt, const BigInt& y) const;
|
|
|
|
/**
|
|
* Blinded point multiplication, attempts resistance to side channels
|
|
* @param k the scalar
|
|
* @param rng a random number generator
|
|
* @param ws a temp workspace
|
|
* @return base_point*k
|
|
*/
|
|
PointGFp blinded_base_point_multiply(const BigInt& k,
|
|
RandomNumberGenerator& rng,
|
|
std::vector<BigInt>& ws) const;
|
|
|
|
/**
|
|
* Blinded point multiplication, attempts resistance to side channels
|
|
* Returns just the x coordinate of the point
|
|
*
|
|
* @param k the scalar
|
|
* @param rng a random number generator
|
|
* @param ws a temp workspace
|
|
* @return x coordinate of base_point*k
|
|
*/
|
|
BigInt blinded_base_point_multiply_x(const BigInt& k,
|
|
RandomNumberGenerator& rng,
|
|
std::vector<BigInt>& ws) const;
|
|
|
|
/**
|
|
* Blinded point multiplication, attempts resistance to side channels
|
|
* @param point input point
|
|
* @param k the scalar
|
|
* @param rng a random number generator
|
|
* @param ws a temp workspace
|
|
* @return point*k
|
|
*/
|
|
PointGFp blinded_var_point_multiply(const PointGFp& point,
|
|
const BigInt& k,
|
|
RandomNumberGenerator& rng,
|
|
std::vector<BigInt>& ws) const;
|
|
|
|
/**
|
|
* Return a random scalar ie an integer in [1,order)
|
|
*/
|
|
BigInt random_scalar(RandomNumberGenerator& rng) const;
|
|
|
|
/**
|
|
* Return the zero (or infinite) point on this curve
|
|
*/
|
|
PointGFp zero_point() const;
|
|
|
|
size_t point_size(PointGFp::Compression_Type format) const;
|
|
|
|
PointGFp OS2ECP(const uint8_t bits[], size_t len) const;
|
|
|
|
template<typename Alloc>
|
|
PointGFp OS2ECP(const std::vector<uint8_t, Alloc>& vec) const
|
|
{
|
|
return this->OS2ECP(vec.data(), vec.size());
|
|
}
|
|
|
|
bool initialized() const { return (m_data != nullptr); }
|
|
|
|
/**
|
|
* Verify EC_Group domain
|
|
* @returns true if group is valid. false otherwise
|
|
*/
|
|
bool verify_group(RandomNumberGenerator& rng,
|
|
bool strong = false) const;
|
|
|
|
bool operator==(const EC_Group& other) const;
|
|
|
|
EC_Group_Source source() const;
|
|
|
|
/**
|
|
* Return PEM representation of named EC group
|
|
* Deprecated: Use EC_Group(name).PEM_encode() if this is needed
|
|
*/
|
|
static std::string BOTAN_DEPRECATED("See header comment") PEM_for_named_group(const std::string& name);
|
|
|
|
/**
|
|
* Return a set of known named EC groups
|
|
*/
|
|
static const std::set<std::string>& known_named_groups();
|
|
|
|
/*
|
|
* For internal use only
|
|
*/
|
|
static std::shared_ptr<EC_Group_Data> EC_group_info(const OID& oid);
|
|
|
|
static size_t clear_registered_curve_data();
|
|
|
|
private:
|
|
static EC_Group_Data_Map& ec_group_data();
|
|
|
|
static std::shared_ptr<EC_Group_Data> BER_decode_EC_group(const uint8_t bits[], size_t len,
|
|
EC_Group_Source source);
|
|
|
|
static std::shared_ptr<EC_Group_Data>
|
|
load_EC_group_info(const char* p,
|
|
const char* a,
|
|
const char* b,
|
|
const char* g_x,
|
|
const char* g_y,
|
|
const char* order,
|
|
const OID& oid);
|
|
|
|
// Member data
|
|
const EC_Group_Data& data() const;
|
|
std::shared_ptr<EC_Group_Data> m_data;
|
|
};
|
|
|
|
inline bool operator!=(const EC_Group& lhs,
|
|
const EC_Group& rhs)
|
|
{
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
// For compatibility with 1.8
|
|
typedef EC_Group EC_Domain_Params;
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents abstract ECC public keys. When encoding a key
|
|
* via an encoder that can be accessed via the corresponding member
|
|
* functions, the key will decide upon its internally stored encoding
|
|
* information whether to encode itself with or without domain
|
|
* parameters, or using the domain parameter oid. Furthermore, a public
|
|
* key without domain parameters can be decoded. In that case, it
|
|
* cannot be used for verification until its domain parameters are set
|
|
* by calling the corresponding member function.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EC_PublicKey : public virtual Public_Key
|
|
{
|
|
public:
|
|
/**
|
|
* Create a public key.
|
|
* @param dom_par EC domain parameters
|
|
* @param pub_point public point on the curve
|
|
*/
|
|
EC_PublicKey(const EC_Group& dom_par,
|
|
const PointGFp& pub_point);
|
|
|
|
/**
|
|
* Load a public key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
EC_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits);
|
|
|
|
EC_PublicKey(const EC_PublicKey& other) = default;
|
|
EC_PublicKey& operator=(const EC_PublicKey& other) = default;
|
|
virtual ~EC_PublicKey() = default;
|
|
|
|
/**
|
|
* Get the public point of this key.
|
|
* @throw Invalid_State is thrown if the
|
|
* domain parameters of this point are not set
|
|
* @result the public point of this key
|
|
*/
|
|
const PointGFp& public_point() const { return m_public_key; }
|
|
|
|
AlgorithmIdentifier algorithm_identifier() const override;
|
|
|
|
std::vector<uint8_t> public_key_bits() const override;
|
|
|
|
bool check_key(RandomNumberGenerator& rng,
|
|
bool strong) const override;
|
|
|
|
/**
|
|
* Get the domain parameters of this key.
|
|
* @throw Invalid_State is thrown if the
|
|
* domain parameters of this point are not set
|
|
* @result the domain parameters of this key
|
|
*/
|
|
const EC_Group& domain() const { return m_domain_params; }
|
|
|
|
/**
|
|
* Set the domain parameter encoding to be used when encoding this key.
|
|
* @param enc the encoding to use
|
|
*/
|
|
void set_parameter_encoding(EC_Group_Encoding enc);
|
|
|
|
/**
|
|
* Set the point encoding method to be used when encoding this key.
|
|
* @param enc the encoding to use
|
|
*/
|
|
void set_point_encoding(PointGFp::Compression_Type enc);
|
|
|
|
/**
|
|
* Return the DER encoding of this keys domain in whatever format
|
|
* is preset for this particular key
|
|
*/
|
|
std::vector<uint8_t> DER_domain() const
|
|
{ return domain().DER_encode(domain_format()); }
|
|
|
|
/**
|
|
* Get the domain parameter encoding to be used when encoding this key.
|
|
* @result the encoding to use
|
|
*/
|
|
EC_Group_Encoding domain_format() const
|
|
{ return m_domain_encoding; }
|
|
|
|
/**
|
|
* Get the point encoding method to be used when encoding this key.
|
|
* @result the encoding to use
|
|
*/
|
|
PointGFp::Compression_Type point_encoding() const
|
|
{ return m_point_encoding; }
|
|
|
|
size_t key_length() const override;
|
|
size_t estimated_strength() const override;
|
|
|
|
protected:
|
|
EC_PublicKey() : m_domain_params{}, m_public_key{}, m_domain_encoding(EC_DOMPAR_ENC_EXPLICIT)
|
|
{}
|
|
|
|
EC_Group m_domain_params;
|
|
PointGFp m_public_key;
|
|
EC_Group_Encoding m_domain_encoding;
|
|
PointGFp::Compression_Type m_point_encoding = PointGFp::UNCOMPRESSED;
|
|
};
|
|
|
|
/**
|
|
* This abstract class represents ECC private keys
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EC_PrivateKey : public virtual EC_PublicKey,
|
|
public virtual Private_Key
|
|
{
|
|
public:
|
|
/*
|
|
* If x=0, creates a new private key in the domain
|
|
* using the given rng. If with_modular_inverse is set,
|
|
* the public key will be calculated by multiplying
|
|
* the base point with the modular inverse of
|
|
* x (as in ECGDSA and ECKCDSA), otherwise by
|
|
* multiplying directly with x (as in ECDSA).
|
|
*/
|
|
EC_PrivateKey(RandomNumberGenerator& rng,
|
|
const EC_Group& domain,
|
|
const BigInt& x,
|
|
bool with_modular_inverse=false);
|
|
|
|
/*
|
|
* Creates a new private key object from the
|
|
* ECPrivateKey structure given in key_bits.
|
|
* If with_modular_inverse is set,
|
|
* the public key will be calculated by multiplying
|
|
* the base point with the modular inverse of
|
|
* x (as in ECGDSA and ECKCDSA), otherwise by
|
|
* multiplying directly with x (as in ECDSA).
|
|
*/
|
|
EC_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits,
|
|
bool with_modular_inverse=false);
|
|
|
|
secure_vector<uint8_t> private_key_bits() const override;
|
|
|
|
/**
|
|
* Get the private key value of this key object.
|
|
* @result the private key value of this key object
|
|
*/
|
|
const BigInt& private_value() const;
|
|
|
|
EC_PrivateKey(const EC_PrivateKey& other) = default;
|
|
EC_PrivateKey& operator=(const EC_PrivateKey& other) = default;
|
|
~EC_PrivateKey() = default;
|
|
protected:
|
|
EC_PrivateKey() = default;
|
|
|
|
BigInt m_private_key;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents ECDH Public Keys.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECDH_PublicKey : public virtual EC_PublicKey
|
|
{
|
|
public:
|
|
/**
|
|
* Create an ECDH public key.
|
|
* @param alg_id algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
ECDH_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits) :
|
|
EC_PublicKey(alg_id, key_bits) {}
|
|
|
|
/**
|
|
* Construct a public key from a given public point.
|
|
* @param dom_par the domain parameters associated with this key
|
|
* @param public_point the public point defining this key
|
|
*/
|
|
ECDH_PublicKey(const EC_Group& dom_par,
|
|
const PointGFp& public_point) :
|
|
EC_PublicKey(dom_par, public_point) {}
|
|
|
|
/**
|
|
* Get this keys algorithm name.
|
|
* @return this keys algorithm name
|
|
*/
|
|
std::string algo_name() const override { return "ECDH"; }
|
|
|
|
/**
|
|
* @return public point value
|
|
*/
|
|
std::vector<uint8_t> public_value() const
|
|
{ return public_point().encode(PointGFp::UNCOMPRESSED); }
|
|
|
|
/**
|
|
* @return public point value
|
|
*/
|
|
std::vector<uint8_t> public_value(PointGFp::Compression_Type format) const
|
|
{ return public_point().encode(format); }
|
|
|
|
protected:
|
|
ECDH_PublicKey() = default;
|
|
};
|
|
|
|
/**
|
|
* This class represents ECDH Private Keys.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECDH_PrivateKey final : public ECDH_PublicKey,
|
|
public EC_PrivateKey,
|
|
public PK_Key_Agreement_Key
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Load a private key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits ECPrivateKey bits
|
|
*/
|
|
ECDH_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits) :
|
|
EC_PrivateKey(alg_id, key_bits) {}
|
|
|
|
/**
|
|
* Generate a new private key
|
|
* @param rng a random number generator
|
|
* @param domain parameters to used for this key
|
|
* @param x the private key; if zero, a new random key is generated
|
|
*/
|
|
ECDH_PrivateKey(RandomNumberGenerator& rng,
|
|
const EC_Group& domain,
|
|
const BigInt& x = 0) :
|
|
EC_PrivateKey(rng, domain, x) {}
|
|
|
|
std::vector<uint8_t> public_value() const override
|
|
{ return ECDH_PublicKey::public_value(PointGFp::UNCOMPRESSED); }
|
|
|
|
std::vector<uint8_t> public_value(PointGFp::Compression_Type type) const
|
|
{ return ECDH_PublicKey::public_value(type); }
|
|
|
|
std::unique_ptr<PK_Ops::Key_Agreement>
|
|
create_key_agreement_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents ECDSA Public Keys.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECDSA_PublicKey : public virtual EC_PublicKey
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Create a public key from a given public point.
|
|
* @param dom_par the domain parameters associated with this key
|
|
* @param public_point the public point defining this key
|
|
*/
|
|
ECDSA_PublicKey(const EC_Group& dom_par,
|
|
const PointGFp& public_point) :
|
|
EC_PublicKey(dom_par, public_point) {}
|
|
|
|
/**
|
|
* Load a public key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
ECDSA_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits) :
|
|
EC_PublicKey(alg_id, key_bits) {}
|
|
|
|
/**
|
|
* Recover a public key from a signature/msg pair
|
|
* See SEC section 4.6.1
|
|
* @param group the elliptic curve group
|
|
* @param msg the message
|
|
* @param r the r paramter of the signature
|
|
* @param s the s paramter of the signature
|
|
* @param v the recovery ID
|
|
*/
|
|
ECDSA_PublicKey(const EC_Group& group,
|
|
const std::vector<uint8_t>& msg,
|
|
const BigInt& r,
|
|
const BigInt& s,
|
|
uint8_t v);
|
|
|
|
/**
|
|
* Get this keys algorithm name.
|
|
* @result this keys algorithm name ("ECDSA")
|
|
*/
|
|
std::string algo_name() const override { return "ECDSA"; }
|
|
|
|
size_t message_parts() const override { return 2; }
|
|
|
|
size_t message_part_size() const override
|
|
{ return domain().get_order().bytes(); }
|
|
|
|
uint8_t recovery_param(const std::vector<uint8_t>& msg,
|
|
const BigInt& r,
|
|
const BigInt& s) const;
|
|
|
|
std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string& params,
|
|
const std::string& provider) const override;
|
|
protected:
|
|
ECDSA_PublicKey() = default;
|
|
};
|
|
|
|
/**
|
|
* This class represents ECDSA Private Keys
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECDSA_PrivateKey final : public ECDSA_PublicKey,
|
|
public EC_PrivateKey
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Load a private key
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits ECPrivateKey bits
|
|
*/
|
|
ECDSA_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits) :
|
|
EC_PrivateKey(alg_id, key_bits) {}
|
|
|
|
/**
|
|
* Create a private key.
|
|
* @param rng a random number generator
|
|
* @param domain parameters to used for this key
|
|
* @param x the private key (if zero, generate a new random key)
|
|
*/
|
|
ECDSA_PrivateKey(RandomNumberGenerator& rng,
|
|
const EC_Group& domain,
|
|
const BigInt& x = 0) :
|
|
EC_PrivateKey(rng, domain, x) {}
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents ECGDSA public keys.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECGDSA_PublicKey : public virtual EC_PublicKey
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Construct a public key from a given public point.
|
|
* @param dom_par the domain parameters associated with this key
|
|
* @param public_point the public point defining this key
|
|
*/
|
|
ECGDSA_PublicKey(const EC_Group& dom_par,
|
|
const PointGFp& public_point) :
|
|
EC_PublicKey(dom_par, public_point) {}
|
|
|
|
/**
|
|
* Load a public key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
ECGDSA_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits) :
|
|
EC_PublicKey(alg_id, key_bits) {}
|
|
|
|
/**
|
|
* Get this keys algorithm name.
|
|
* @result this keys algorithm name ("ECGDSA")
|
|
*/
|
|
std::string algo_name() const override { return "ECGDSA"; }
|
|
|
|
size_t message_parts() const override { return 2; }
|
|
|
|
size_t message_part_size() const override
|
|
{ return domain().get_order().bytes(); }
|
|
|
|
std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string& params,
|
|
const std::string& provider) const override;
|
|
protected:
|
|
ECGDSA_PublicKey() = default;
|
|
};
|
|
|
|
/**
|
|
* This class represents ECGDSA private keys.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECGDSA_PrivateKey final : public ECGDSA_PublicKey,
|
|
public EC_PrivateKey
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Load a private key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits ECPrivateKey bits
|
|
*/
|
|
ECGDSA_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits) :
|
|
EC_PrivateKey(alg_id, key_bits, true) {}
|
|
|
|
/**
|
|
* Generate a new private key.
|
|
* @param rng a random number generator
|
|
* @param domain parameters to used for this key
|
|
* @param x the private key (if zero, generate a new random key)
|
|
*/
|
|
ECGDSA_PrivateKey(RandomNumberGenerator& rng,
|
|
const EC_Group& domain,
|
|
const BigInt& x = 0) :
|
|
EC_PrivateKey(rng, domain, x, true) {}
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
enum class ECIES_Flags : uint32_t
|
|
{
|
|
NONE = 0,
|
|
|
|
/// if set: prefix the input of the (ecdh) key agreement with the encoded (ephemeral) public key
|
|
SINGLE_HASH_MODE = 1,
|
|
|
|
/// (decryption only) if set: use cofactor multiplication during (ecdh) key agreement
|
|
COFACTOR_MODE = 2,
|
|
|
|
/// if set: use ecdhc instead of ecdh
|
|
OLD_COFACTOR_MODE = 4,
|
|
|
|
/// (decryption only) if set: test if the (ephemeral) public key is on the curve
|
|
CHECK_MODE = 8
|
|
};
|
|
|
|
inline ECIES_Flags operator |(ECIES_Flags a, ECIES_Flags b)
|
|
{
|
|
return static_cast<ECIES_Flags>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
|
|
}
|
|
|
|
inline ECIES_Flags operator &(ECIES_Flags a, ECIES_Flags b)
|
|
{
|
|
return static_cast<ECIES_Flags>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
|
|
}
|
|
|
|
/**
|
|
* Parameters for ECIES secret derivation
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECIES_KA_Params
|
|
{
|
|
public:
|
|
/**
|
|
* @param domain ec domain parameters of the involved ec keys
|
|
* @param kdf_spec name of the key derivation function
|
|
* @param length length of the secret to be derived
|
|
* @param compression_type format of encoded keys (affects the secret derivation if single_hash_mode is used)
|
|
* @param flags options, see documentation of ECIES_Flags
|
|
*/
|
|
ECIES_KA_Params(const EC_Group& domain, const std::string& kdf_spec, size_t length,
|
|
PointGFp::Compression_Type compression_type, ECIES_Flags flags);
|
|
|
|
ECIES_KA_Params(const ECIES_KA_Params&) = default;
|
|
ECIES_KA_Params& operator=(const ECIES_KA_Params&) = delete;
|
|
|
|
virtual ~ECIES_KA_Params() = default;
|
|
|
|
inline const EC_Group& domain() const
|
|
{
|
|
return m_domain;
|
|
}
|
|
|
|
inline size_t secret_length() const
|
|
{
|
|
return m_length;
|
|
}
|
|
|
|
inline bool single_hash_mode() const
|
|
{
|
|
return (m_flags & ECIES_Flags::SINGLE_HASH_MODE) == ECIES_Flags::SINGLE_HASH_MODE;
|
|
}
|
|
|
|
inline bool cofactor_mode() const
|
|
{
|
|
return (m_flags & ECIES_Flags::COFACTOR_MODE) == ECIES_Flags::COFACTOR_MODE;
|
|
}
|
|
|
|
inline bool old_cofactor_mode() const
|
|
{
|
|
return (m_flags & ECIES_Flags::OLD_COFACTOR_MODE) == ECIES_Flags::OLD_COFACTOR_MODE;
|
|
}
|
|
|
|
inline bool check_mode() const
|
|
{
|
|
return (m_flags & ECIES_Flags::CHECK_MODE) == ECIES_Flags::CHECK_MODE;
|
|
}
|
|
|
|
inline PointGFp::Compression_Type compression_type() const
|
|
{
|
|
return m_compression_mode;
|
|
}
|
|
|
|
const std::string& kdf_spec() const
|
|
{
|
|
return m_kdf_spec;
|
|
}
|
|
|
|
private:
|
|
const EC_Group m_domain;
|
|
const std::string m_kdf_spec;
|
|
const size_t m_length;
|
|
const PointGFp::Compression_Type m_compression_mode;
|
|
const ECIES_Flags m_flags;
|
|
};
|
|
|
|
|
|
class BOTAN_PUBLIC_API(2,0) ECIES_System_Params final : public ECIES_KA_Params
|
|
{
|
|
public:
|
|
/**
|
|
* @param domain ec domain parameters of the involved ec keys
|
|
* @param kdf_spec name of the key derivation function
|
|
* @param dem_algo_spec name of the data encryption method
|
|
* @param dem_key_len length of the key used for the data encryption method
|
|
* @param mac_spec name of the message authentication code
|
|
* @param mac_key_len length of the key used for the message authentication code
|
|
*/
|
|
ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, const std::string& dem_algo_spec,
|
|
size_t dem_key_len, const std::string& mac_spec, size_t mac_key_len);
|
|
|
|
/**
|
|
* @param domain ec domain parameters of the involved ec keys
|
|
* @param kdf_spec name of the key derivation function
|
|
* @param dem_algo_spec name of the data encryption method
|
|
* @param dem_key_len length of the key used for the data encryption method
|
|
* @param mac_spec name of the message authentication code
|
|
* @param mac_key_len length of the key used for the message authentication code
|
|
* @param compression_type format of encoded keys (affects the secret derivation if single_hash_mode is used)
|
|
* @param flags options, see documentation of ECIES_Flags
|
|
*/
|
|
ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, const std::string& dem_algo_spec,
|
|
size_t dem_key_len, const std::string& mac_spec, size_t mac_key_len,
|
|
PointGFp::Compression_Type compression_type, ECIES_Flags flags);
|
|
|
|
ECIES_System_Params(const ECIES_System_Params&) = default;
|
|
ECIES_System_Params& operator=(const ECIES_System_Params&) = delete;
|
|
virtual ~ECIES_System_Params() = default;
|
|
|
|
/// creates an instance of the message authentication code
|
|
std::unique_ptr<MessageAuthenticationCode> create_mac() const;
|
|
|
|
/// creates an instance of the data encryption method
|
|
std::unique_ptr<Cipher_Mode> create_cipher(Botan::Cipher_Dir direction) const;
|
|
|
|
/// returns the length of the key used by the data encryption method
|
|
inline size_t dem_keylen() const
|
|
{
|
|
return m_dem_keylen;
|
|
}
|
|
|
|
/// returns the length of the key used by the message authentication code
|
|
inline size_t mac_keylen() const
|
|
{
|
|
return m_mac_keylen;
|
|
}
|
|
|
|
private:
|
|
const std::string m_dem_spec;
|
|
const size_t m_dem_keylen;
|
|
const std::string m_mac_spec;
|
|
const size_t m_mac_keylen;
|
|
};
|
|
|
|
|
|
/**
|
|
* ECIES secret derivation according to ISO 18033-2
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECIES_KA_Operation
|
|
{
|
|
public:
|
|
/**
|
|
* @param private_key the (ephemeral) private key which is used to derive the secret
|
|
* @param ecies_params settings for ecies
|
|
* @param for_encryption disable cofactor mode if the secret will be used for encryption
|
|
* (according to ISO 18033 cofactor mode is only used during decryption)
|
|
* @param rng the RNG to use
|
|
*/
|
|
ECIES_KA_Operation(const PK_Key_Agreement_Key& private_key,
|
|
const ECIES_KA_Params& ecies_params,
|
|
bool for_encryption,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Performs a key agreement with the provided keys and derives the secret from the result
|
|
* @param eph_public_key_bin the encoded (ephemeral) public key which belongs to the used (ephemeral) private key
|
|
* @param other_public_key_point public key point of the other party
|
|
*/
|
|
SymmetricKey derive_secret(const std::vector<uint8_t>& eph_public_key_bin,
|
|
const PointGFp& other_public_key_point) const;
|
|
|
|
private:
|
|
const PK_Key_Agreement m_ka;
|
|
const ECIES_KA_Params m_params;
|
|
};
|
|
|
|
|
|
/**
|
|
* ECIES Encryption according to ISO 18033-2
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECIES_Encryptor final : public PK_Encryptor
|
|
{
|
|
public:
|
|
/**
|
|
* @param private_key the (ephemeral) private key which is used for the key agreement
|
|
* @param ecies_params settings for ecies
|
|
* @param rng random generator to use
|
|
*/
|
|
ECIES_Encryptor(const PK_Key_Agreement_Key& private_key,
|
|
const ECIES_System_Params& ecies_params,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Creates an ephemeral private key which is used for the key agreement
|
|
* @param rng random generator used during private key generation
|
|
* @param ecies_params settings for ecies
|
|
*/
|
|
ECIES_Encryptor(RandomNumberGenerator& rng, const ECIES_System_Params& ecies_params);
|
|
|
|
/// Set the public key of the other party
|
|
inline void set_other_key(const Botan::PointGFp& public_point)
|
|
{
|
|
m_other_point = public_point;
|
|
}
|
|
|
|
/// Set the initialization vector for the data encryption method
|
|
inline void set_initialization_vector(const InitializationVector& iv)
|
|
{
|
|
m_iv = iv;
|
|
}
|
|
|
|
/// Set the label which is appended to the input for the message authentication code
|
|
inline void set_label(const std::string& label)
|
|
{
|
|
m_label = std::vector<uint8_t>(label.begin(), label.end());
|
|
}
|
|
|
|
private:
|
|
std::vector<uint8_t> enc(const uint8_t data[], size_t length, RandomNumberGenerator&) const override;
|
|
|
|
size_t maximum_input_size() const override;
|
|
|
|
size_t ciphertext_length(size_t ptext_len) const override;
|
|
|
|
const ECIES_KA_Operation m_ka;
|
|
const ECIES_System_Params m_params;
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
std::unique_ptr<Cipher_Mode> m_cipher;
|
|
std::vector<uint8_t> m_eph_public_key_bin;
|
|
InitializationVector m_iv;
|
|
PointGFp m_other_point;
|
|
std::vector<uint8_t> m_label;
|
|
};
|
|
|
|
|
|
/**
|
|
* ECIES Decryption according to ISO 18033-2
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECIES_Decryptor final : public PK_Decryptor
|
|
{
|
|
public:
|
|
/**
|
|
* @param private_key the private key which is used for the key agreement
|
|
* @param ecies_params settings for ecies
|
|
* @param rng the random generator to use
|
|
*/
|
|
ECIES_Decryptor(const PK_Key_Agreement_Key& private_key,
|
|
const ECIES_System_Params& ecies_params,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/// Set the initialization vector for the data encryption method
|
|
inline void set_initialization_vector(const InitializationVector& iv)
|
|
{
|
|
m_iv = iv;
|
|
}
|
|
|
|
/// Set the label which is appended to the input for the message authentication code
|
|
inline void set_label(const std::string& label)
|
|
{
|
|
m_label = std::vector<uint8_t>(label.begin(), label.end());
|
|
}
|
|
|
|
private:
|
|
secure_vector<uint8_t> do_decrypt(uint8_t& valid_mask, const uint8_t in[], size_t in_len) const override;
|
|
|
|
size_t plaintext_length(size_t ctext_len) const override;
|
|
|
|
const ECIES_KA_Operation m_ka;
|
|
const ECIES_System_Params m_params;
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
std::unique_ptr<Cipher_Mode> m_cipher;
|
|
InitializationVector m_iv;
|
|
std::vector<uint8_t> m_label;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents ECKCDSA public keys.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECKCDSA_PublicKey : public virtual EC_PublicKey
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Construct a public key from a given public point.
|
|
* @param dom_par the domain parameters associated with this key
|
|
* @param public_point the public point defining this key
|
|
*/
|
|
ECKCDSA_PublicKey(const EC_Group& dom_par,
|
|
const PointGFp& public_point) :
|
|
EC_PublicKey(dom_par, public_point) {}
|
|
|
|
/**
|
|
* Load a public key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
ECKCDSA_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits) :
|
|
EC_PublicKey(alg_id, key_bits) {}
|
|
|
|
/**
|
|
* Get this keys algorithm name.
|
|
* @result this keys algorithm name ("ECGDSA")
|
|
*/
|
|
std::string algo_name() const override { return "ECKCDSA"; }
|
|
|
|
size_t message_parts() const override { return 2; }
|
|
|
|
size_t message_part_size() const override
|
|
{ return domain().get_order().bytes(); }
|
|
|
|
std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string& params,
|
|
const std::string& provider) const override;
|
|
protected:
|
|
ECKCDSA_PublicKey() = default;
|
|
};
|
|
|
|
/**
|
|
* This class represents ECKCDSA private keys.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ECKCDSA_PrivateKey final : public ECKCDSA_PublicKey,
|
|
public EC_PrivateKey
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Load a private key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits ECPrivateKey bits
|
|
*/
|
|
ECKCDSA_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits) :
|
|
EC_PrivateKey(alg_id, key_bits, true) {}
|
|
|
|
/**
|
|
* Create a private key.
|
|
* @param rng a random number generator
|
|
* @param domain parameters to used for this key
|
|
* @param x the private key (if zero, generate a new random key)
|
|
*/
|
|
ECKCDSA_PrivateKey(RandomNumberGenerator& rng,
|
|
const EC_Group& domain,
|
|
const BigInt& x = 0) :
|
|
EC_PrivateKey(rng, domain, x, true) {}
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class BOTAN_PUBLIC_API(2,2) Ed25519_PublicKey : public virtual Public_Key
|
|
{
|
|
public:
|
|
std::string algo_name() const override { return "Ed25519"; }
|
|
|
|
size_t estimated_strength() const override { return 128; }
|
|
|
|
size_t key_length() const override { return 255; }
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool strong) const override;
|
|
|
|
AlgorithmIdentifier algorithm_identifier() const override;
|
|
|
|
std::vector<uint8_t> public_key_bits() const override;
|
|
|
|
/**
|
|
* Create a Ed25519 Public Key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
Ed25519_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits);
|
|
|
|
template<typename Alloc>
|
|
Ed25519_PublicKey(const std::vector<uint8_t, Alloc>& pub) :
|
|
Ed25519_PublicKey(pub.data(), pub.size()) {}
|
|
|
|
Ed25519_PublicKey(const uint8_t pub_key[], size_t len);
|
|
|
|
std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
const std::vector<uint8_t>& get_public_key() const { return m_public; }
|
|
|
|
protected:
|
|
Ed25519_PublicKey() = default;
|
|
std::vector<uint8_t> m_public;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,2) Ed25519_PrivateKey final : public Ed25519_PublicKey,
|
|
public virtual Private_Key
|
|
{
|
|
public:
|
|
/**
|
|
* Construct a private key from the specified parameters.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits PKCS #8 structure
|
|
*/
|
|
Ed25519_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Generate a private key.
|
|
* @param rng the RNG to use
|
|
*/
|
|
explicit Ed25519_PrivateKey(RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Construct a private key from the specified parameters.
|
|
* @param secret_key the private key
|
|
*/
|
|
explicit Ed25519_PrivateKey(const secure_vector<uint8_t>& secret_key);
|
|
|
|
const secure_vector<uint8_t>& get_private_key() const { return m_private; }
|
|
|
|
secure_vector<uint8_t> private_key_bits() const override;
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool strong) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
private:
|
|
secure_vector<uint8_t> m_private;
|
|
};
|
|
|
|
void ed25519_gen_keypair(uint8_t pk[32], uint8_t sk[64], const uint8_t seed[32]);
|
|
|
|
void ed25519_sign(uint8_t sig[64],
|
|
const uint8_t msg[],
|
|
size_t msg_len,
|
|
const uint8_t sk[64],
|
|
const uint8_t domain_sep[], size_t domain_sep_len);
|
|
|
|
bool ed25519_verify(const uint8_t msg[],
|
|
size_t msg_len,
|
|
const uint8_t sig[64],
|
|
const uint8_t pk[32],
|
|
const uint8_t domain_sep[], size_t domain_sep_len);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* ElGamal Public Key
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ElGamal_PublicKey : public virtual DL_Scheme_PublicKey
|
|
{
|
|
public:
|
|
std::string algo_name() const override { return "ElGamal"; }
|
|
DL_Group::Format group_format() const override { return DL_Group::ANSI_X9_42; }
|
|
|
|
/**
|
|
* Load a public key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
ElGamal_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits) :
|
|
DL_Scheme_PublicKey(alg_id, key_bits, DL_Group::ANSI_X9_42)
|
|
{}
|
|
|
|
/**
|
|
* Create a public key.
|
|
* @param group the underlying DL group
|
|
* @param y the public value y = g^x mod p
|
|
*/
|
|
ElGamal_PublicKey(const DL_Group& group, const BigInt& y);
|
|
|
|
std::unique_ptr<PK_Ops::Encryption>
|
|
create_encryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
protected:
|
|
ElGamal_PublicKey() = default;
|
|
};
|
|
|
|
/**
|
|
* ElGamal Private Key
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ElGamal_PrivateKey final : public ElGamal_PublicKey,
|
|
public virtual DL_Scheme_PrivateKey
|
|
{
|
|
public:
|
|
bool check_key(RandomNumberGenerator& rng, bool) const override;
|
|
|
|
/**
|
|
* Load a private key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded key bits in ANSI X9.42 format
|
|
*/
|
|
ElGamal_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Create a private key.
|
|
* @param rng random number generator to use
|
|
* @param group the group to be used in the key
|
|
* @param priv_key the key's secret value (or if zero, generate a new key)
|
|
*/
|
|
ElGamal_PrivateKey(RandomNumberGenerator& rng,
|
|
const DL_Group& group,
|
|
const BigInt& priv_key = 0);
|
|
|
|
std::unique_ptr<PK_Ops::Decryption>
|
|
create_decryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(eme.h)
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Encoding Method for Encryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EME
|
|
{
|
|
public:
|
|
virtual ~EME() = default;
|
|
|
|
/**
|
|
* Return the maximum input size in bytes we can support
|
|
* @param keybits the size of the key in bits
|
|
* @return upper bound of input in bytes
|
|
*/
|
|
virtual size_t maximum_input_size(size_t keybits) const = 0;
|
|
|
|
/**
|
|
* Encode an input
|
|
* @param in the plaintext
|
|
* @param in_length length of plaintext in bytes
|
|
* @param key_length length of the key in bits
|
|
* @param rng a random number generator
|
|
* @return encoded plaintext
|
|
*/
|
|
secure_vector<uint8_t> encode(const uint8_t in[],
|
|
size_t in_length,
|
|
size_t key_length,
|
|
RandomNumberGenerator& rng) const;
|
|
|
|
/**
|
|
* Encode an input
|
|
* @param in the plaintext
|
|
* @param key_length length of the key in bits
|
|
* @param rng a random number generator
|
|
* @return encoded plaintext
|
|
*/
|
|
secure_vector<uint8_t> encode(const secure_vector<uint8_t>& in,
|
|
size_t key_length,
|
|
RandomNumberGenerator& rng) const;
|
|
|
|
/**
|
|
* Decode an input
|
|
* @param valid_mask written to specifies if output is valid
|
|
* @param in the encoded plaintext
|
|
* @param in_len length of encoded plaintext in bytes
|
|
* @return bytes of out[] written to along with
|
|
* validity mask (0xFF if valid, else 0x00)
|
|
*/
|
|
virtual secure_vector<uint8_t> unpad(uint8_t& valid_mask,
|
|
const uint8_t in[],
|
|
size_t in_len) const = 0;
|
|
|
|
/**
|
|
* Encode an input
|
|
* @param in the plaintext
|
|
* @param in_length length of plaintext in bytes
|
|
* @param key_length length of the key in bits
|
|
* @param rng a random number generator
|
|
* @return encoded plaintext
|
|
*/
|
|
virtual secure_vector<uint8_t> pad(const uint8_t in[],
|
|
size_t in_length,
|
|
size_t key_length,
|
|
RandomNumberGenerator& rng) const = 0;
|
|
};
|
|
|
|
/**
|
|
* Factory method for EME (message-encoding methods for encryption) objects
|
|
* @param algo_spec the name of the EME to create
|
|
* @return pointer to newly allocated object of that type
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) EME* get_eme(const std::string& algo_spec);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(eme_pkcs.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* EME from PKCS #1 v1.5
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EME_PKCS1v15 final : public EME
|
|
{
|
|
public:
|
|
size_t maximum_input_size(size_t) const override;
|
|
|
|
secure_vector<uint8_t> pad(const uint8_t[], size_t, size_t,
|
|
RandomNumberGenerator&) const override;
|
|
|
|
secure_vector<uint8_t> unpad(uint8_t& valid_mask,
|
|
const uint8_t in[],
|
|
size_t in_len) const override;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(eme_raw.h)
|
|
|
|
namespace Botan {
|
|
|
|
class BOTAN_PUBLIC_API(2,0) EME_Raw final : public EME
|
|
{
|
|
public:
|
|
size_t maximum_input_size(size_t i) const override;
|
|
|
|
EME_Raw() = default;
|
|
private:
|
|
secure_vector<uint8_t> pad(const uint8_t[], size_t, size_t,
|
|
RandomNumberGenerator&) const override;
|
|
|
|
secure_vector<uint8_t> unpad(uint8_t& valid_mask,
|
|
const uint8_t in[],
|
|
size_t in_len) const override;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(emsa.h)
|
|
|
|
namespace Botan {
|
|
|
|
class Private_Key;
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* EMSA, from IEEE 1363s Encoding Method for Signatures, Appendix
|
|
*
|
|
* Any way of encoding/padding signatures
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EMSA
|
|
{
|
|
public:
|
|
virtual ~EMSA() = default;
|
|
|
|
/**
|
|
* Add more data to the signature computation
|
|
* @param input some data
|
|
* @param length length of input in bytes
|
|
*/
|
|
virtual void update(const uint8_t input[], size_t length) = 0;
|
|
|
|
/**
|
|
* @return raw hash
|
|
*/
|
|
virtual secure_vector<uint8_t> raw_data() = 0;
|
|
|
|
/**
|
|
* Return the encoding of a message
|
|
* @param msg the result of raw_data()
|
|
* @param output_bits the desired output bit size
|
|
* @param rng a random number generator
|
|
* @return encoded signature
|
|
*/
|
|
virtual secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator& rng) = 0;
|
|
|
|
/**
|
|
* Verify the encoding
|
|
* @param coded the received (coded) message representative
|
|
* @param raw the computed (local, uncoded) message representative
|
|
* @param key_bits the size of the key in bits
|
|
* @return true if coded is a valid encoding of raw, otherwise false
|
|
*/
|
|
virtual bool verify(const secure_vector<uint8_t>& coded,
|
|
const secure_vector<uint8_t>& raw,
|
|
size_t key_bits) = 0;
|
|
|
|
/**
|
|
* Prepare sig_algo for use in choose_sig_format for x509 certs
|
|
*
|
|
* @param key used for checking compatibility with the encoding scheme
|
|
* @param cert_hash_name is checked to equal the hash for the encoding
|
|
* @return algorithm identifier to signatures created using this key,
|
|
* padding method and hash.
|
|
*/
|
|
virtual AlgorithmIdentifier config_for_x509(const Private_Key& key,
|
|
const std::string& cert_hash_name) const;
|
|
|
|
/**
|
|
* @return a new object representing the same encoding method as *this
|
|
*/
|
|
virtual EMSA* clone() = 0;
|
|
|
|
/**
|
|
* @return the SCAN name of the encoding/padding scheme
|
|
*/
|
|
virtual std::string name() const = 0;
|
|
};
|
|
|
|
/**
|
|
* Factory method for EMSA (message-encoding methods for signatures
|
|
* with appendix) objects
|
|
* @param algo_spec the name of the EMSA to create
|
|
* @return pointer to newly allocated object of that type
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) EMSA* get_emsa(const std::string& algo_spec);
|
|
|
|
/**
|
|
* Returns the hash function used in the given EMSA scheme
|
|
* If the hash function is not specified or not understood,
|
|
* returns "SHA-512"
|
|
* @param algo_spec the name of the EMSA
|
|
* @return hash function used in the given EMSA scheme
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::string hash_for_emsa(const std::string& algo_spec);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(emsa1.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* EMSA1 from IEEE 1363
|
|
* Essentially, sign the hash directly
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EMSA1 final : public EMSA
|
|
{
|
|
public:
|
|
/**
|
|
* @param hash the hash function to use
|
|
*/
|
|
explicit EMSA1(HashFunction* hash) : m_hash(hash) {}
|
|
|
|
EMSA* clone() override;
|
|
|
|
std::string name() const override;
|
|
|
|
AlgorithmIdentifier config_for_x509(const Private_Key& key,
|
|
const std::string& cert_hash_name) const override;
|
|
private:
|
|
size_t hash_output_length() const { return m_hash->output_length(); }
|
|
|
|
void update(const uint8_t[], size_t) override;
|
|
secure_vector<uint8_t> raw_data() override;
|
|
|
|
secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator& rng) override;
|
|
|
|
bool verify(const secure_vector<uint8_t>& coded,
|
|
const secure_vector<uint8_t>& raw,
|
|
size_t key_bits) override;
|
|
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(emsa_pkcs1.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* PKCS #1 v1.5 signature padding
|
|
* aka PKCS #1 block type 1
|
|
* aka EMSA3 from IEEE 1363
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EMSA_PKCS1v15 final : public EMSA
|
|
{
|
|
public:
|
|
/**
|
|
* @param hash the hash function to use
|
|
*/
|
|
explicit EMSA_PKCS1v15(HashFunction* hash);
|
|
|
|
EMSA* clone() override { return new EMSA_PKCS1v15(m_hash->clone()); }
|
|
|
|
void update(const uint8_t[], size_t) override;
|
|
|
|
secure_vector<uint8_t> raw_data() override;
|
|
|
|
secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>&, size_t,
|
|
RandomNumberGenerator& rng) override;
|
|
|
|
bool verify(const secure_vector<uint8_t>&, const secure_vector<uint8_t>&,
|
|
size_t) override;
|
|
|
|
std::string name() const override
|
|
{ return "EMSA3(" + m_hash->name() + ")"; }
|
|
|
|
AlgorithmIdentifier config_for_x509(const Private_Key& key,
|
|
const std::string& cert_hash_name) const override;
|
|
private:
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
std::vector<uint8_t> m_hash_id;
|
|
};
|
|
|
|
/**
|
|
* EMSA_PKCS1v15_Raw which is EMSA_PKCS1v15 without a hash or digest id
|
|
* (which according to QCA docs is "identical to PKCS#11's CKM_RSA_PKCS
|
|
* mechanism", something I have not confirmed)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EMSA_PKCS1v15_Raw final : public EMSA
|
|
{
|
|
public:
|
|
EMSA* clone() override { return new EMSA_PKCS1v15_Raw(); }
|
|
|
|
void update(const uint8_t[], size_t) override;
|
|
|
|
secure_vector<uint8_t> raw_data() override;
|
|
|
|
secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>&, size_t,
|
|
RandomNumberGenerator& rng) override;
|
|
|
|
bool verify(const secure_vector<uint8_t>&, const secure_vector<uint8_t>&,
|
|
size_t) override;
|
|
|
|
/**
|
|
* @param hash_algo if non-empty, the digest id for that hash is
|
|
* included in the signature.
|
|
*/
|
|
EMSA_PKCS1v15_Raw(const std::string& hash_algo = "");
|
|
|
|
std::string name() const override
|
|
{
|
|
if(m_hash_name.empty()) return "EMSA3(Raw)";
|
|
else return "EMSA3(Raw," + m_hash_name + ")";
|
|
}
|
|
|
|
private:
|
|
size_t m_hash_output_len = 0;
|
|
std::string m_hash_name;
|
|
std::vector<uint8_t> m_hash_id;
|
|
secure_vector<uint8_t> m_message;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(emsa_raw.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* EMSA-Raw - sign inputs directly
|
|
* Don't use this unless you know what you are doing.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EMSA_Raw final : public EMSA
|
|
{
|
|
public:
|
|
EMSA* clone() override { return new EMSA_Raw(); }
|
|
|
|
explicit EMSA_Raw(size_t expected_hash_size = 0) :
|
|
m_expected_size(expected_hash_size) {}
|
|
|
|
std::string name() const override;
|
|
private:
|
|
void update(const uint8_t[], size_t) override;
|
|
secure_vector<uint8_t> raw_data() override;
|
|
|
|
secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>&, size_t,
|
|
RandomNumberGenerator&) override;
|
|
|
|
bool verify(const secure_vector<uint8_t>&,
|
|
const secure_vector<uint8_t>&,
|
|
size_t) override;
|
|
|
|
const size_t m_expected_size;
|
|
secure_vector<uint8_t> m_message;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(emsa_x931.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* EMSA from X9.31 (EMSA2 in IEEE 1363)
|
|
* Useful for Rabin-Williams, also sometimes used with RSA in
|
|
* odd protocols.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) EMSA_X931 final : public EMSA
|
|
{
|
|
public:
|
|
/**
|
|
* @param hash the hash function to use
|
|
*/
|
|
explicit EMSA_X931(HashFunction* hash);
|
|
|
|
EMSA* clone() override { return new EMSA_X931(m_hash->clone()); }
|
|
|
|
std::string name() const override;
|
|
|
|
private:
|
|
void update(const uint8_t[], size_t) override;
|
|
secure_vector<uint8_t> raw_data() override;
|
|
|
|
secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>&, size_t,
|
|
RandomNumberGenerator& rng) override;
|
|
|
|
bool verify(const secure_vector<uint8_t>&, const secure_vector<uint8_t>&,
|
|
size_t) override;
|
|
|
|
secure_vector<uint8_t> m_empty_hash;
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
uint8_t m_hash_id;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Abstract interface to a source of entropy
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Entropy_Source
|
|
{
|
|
public:
|
|
/**
|
|
* Return a new entropy source of a particular type, or null
|
|
* Each entropy source may require substantial resources (eg, a file handle
|
|
* or socket instance), so try to share them among multiple RNGs, or just
|
|
* use the preconfigured global list accessed by Entropy_Sources::global_sources()
|
|
*/
|
|
static std::unique_ptr<Entropy_Source> create(const std::string& type);
|
|
|
|
/**
|
|
* @return name identifying this entropy source
|
|
*/
|
|
virtual std::string name() const = 0;
|
|
|
|
/**
|
|
* Perform an entropy gathering poll
|
|
* @param rng will be provided with entropy via calls to add_entropy
|
|
* @return conservative estimate of actual entropy added to rng during poll
|
|
*/
|
|
virtual size_t poll(RandomNumberGenerator& rng) = 0;
|
|
|
|
Entropy_Source() = default;
|
|
Entropy_Source(const Entropy_Source& other) = delete;
|
|
Entropy_Source(Entropy_Source&& other) = delete;
|
|
Entropy_Source& operator=(const Entropy_Source& other) = delete;
|
|
|
|
virtual ~Entropy_Source() = default;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,0) Entropy_Sources final
|
|
{
|
|
public:
|
|
static Entropy_Sources& global_sources();
|
|
|
|
void add_source(std::unique_ptr<Entropy_Source> src);
|
|
|
|
std::vector<std::string> enabled_sources() const;
|
|
|
|
size_t poll(RandomNumberGenerator& rng,
|
|
size_t bits,
|
|
std::chrono::milliseconds timeout);
|
|
|
|
/**
|
|
* Poll just a single named source. Ordinally only used for testing
|
|
*/
|
|
size_t poll_just(RandomNumberGenerator& rng, const std::string& src);
|
|
|
|
Entropy_Sources() = default;
|
|
explicit Entropy_Sources(const std::vector<std::string>& sources);
|
|
|
|
Entropy_Sources(const Entropy_Sources& other) = delete;
|
|
Entropy_Sources(Entropy_Sources&& other) = delete;
|
|
Entropy_Sources& operator=(const Entropy_Sources& other) = delete;
|
|
|
|
private:
|
|
std::vector<std::unique_ptr<Entropy_Source>> m_srcs;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Pipe;
|
|
|
|
/**
|
|
* Stream output operator; dumps the results from pipe's default
|
|
* message to the output stream.
|
|
* @param out file descriptor for an open output stream
|
|
* @param pipe the pipe
|
|
*/
|
|
int BOTAN_PUBLIC_API(2,0) operator<<(int out, Pipe& pipe);
|
|
|
|
/**
|
|
* File descriptor input operator; dumps the remaining bytes of input
|
|
* to the (assumed open) pipe message.
|
|
* @param in file descriptor for an open input stream
|
|
* @param pipe the pipe
|
|
*/
|
|
int BOTAN_PUBLIC_API(2,0) operator>>(int in, Pipe& pipe);
|
|
|
|
}
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*
|
|
This header exports some of botan's functionality via a C89 interface. This API
|
|
is uesd by the Python, OCaml, Rust and Ruby bindings via those languages
|
|
respective ctypes/FFI libraries.
|
|
|
|
The API is intended to be as easy as possible to call from other
|
|
languages, which often have easy ways to call C, because C. But some C
|
|
code is easier to deal with than others, so to make things easy this
|
|
API follows a few simple rules:
|
|
|
|
- All interactions are via pointers to opaque structs. No need to worry about
|
|
structure padding issues and the like.
|
|
|
|
- All functions return an int error code (except the version calls, which are
|
|
assumed to always have something to say).
|
|
|
|
- Use simple types: size_t for lengths, const char* NULL terminated strings,
|
|
uint8_t for binary.
|
|
|
|
- No ownership of memory transfers across the API boundary. The API will
|
|
consume data from const pointers, and will produce output by writing to
|
|
buffers provided by (and allocated by) the caller.
|
|
|
|
- If exporting a value (a string or a blob) the function takes a pointer to the
|
|
output array and a read/write pointer to the length. If the length is insufficient, an
|
|
error is returned. So passing nullptr/0 allows querying the final value.
|
|
|
|
Note this does not apply to all functions, like `botan_hash_final`
|
|
which is not idempotent and are documented specially. But it's a
|
|
general theory of operation.
|
|
|
|
TODO:
|
|
- Doxygen comments for all functions/params
|
|
- TLS
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
|
|
/**
|
|
* Error codes
|
|
*
|
|
* If you add a new value here be sure to also add it in
|
|
* botan_error_description
|
|
*/
|
|
enum BOTAN_FFI_ERROR {
|
|
BOTAN_FFI_SUCCESS = 0,
|
|
BOTAN_FFI_INVALID_VERIFIER = 1,
|
|
|
|
BOTAN_FFI_ERROR_INVALID_INPUT = -1,
|
|
BOTAN_FFI_ERROR_BAD_MAC = -2,
|
|
|
|
BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE = -10,
|
|
|
|
BOTAN_FFI_ERROR_EXCEPTION_THROWN = -20,
|
|
BOTAN_FFI_ERROR_OUT_OF_MEMORY = -21,
|
|
BOTAN_FFI_ERROR_SYSTEM_ERROR = -22,
|
|
BOTAN_FFI_ERROR_INTERNAL_ERROR = -23,
|
|
|
|
BOTAN_FFI_ERROR_BAD_FLAG = -30,
|
|
BOTAN_FFI_ERROR_NULL_POINTER = -31,
|
|
BOTAN_FFI_ERROR_BAD_PARAMETER = -32,
|
|
BOTAN_FFI_ERROR_KEY_NOT_SET = -33,
|
|
BOTAN_FFI_ERROR_INVALID_KEY_LENGTH = -34,
|
|
BOTAN_FFI_ERROR_INVALID_OBJECT_STATE = -35,
|
|
|
|
BOTAN_FFI_ERROR_NOT_IMPLEMENTED = -40,
|
|
BOTAN_FFI_ERROR_INVALID_OBJECT = -50,
|
|
|
|
BOTAN_FFI_ERROR_TLS_ERROR = -75,
|
|
BOTAN_FFI_ERROR_HTTP_ERROR = -76,
|
|
BOTAN_FFI_ERROR_ROUGHTIME_ERROR = -77,
|
|
|
|
BOTAN_FFI_ERROR_UNKNOWN_ERROR = -100,
|
|
};
|
|
|
|
/**
|
|
* Convert an error code into a string. Returns "Unknown error"
|
|
* if the error code is not a known one.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) const char* botan_error_description(int err);
|
|
|
|
/**
|
|
* Return the version of the currently supported FFI API. This is
|
|
* expressed in the form YYYYMMDD of the release date of this version
|
|
* of the API.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t botan_ffi_api_version(void);
|
|
|
|
/**
|
|
* Return 0 (ok) if the version given is one this library supports.
|
|
* botan_ffi_supports_api(botan_ffi_api_version()) will always return 0.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_ffi_supports_api(uint32_t api_version);
|
|
|
|
/**
|
|
* Return a free-form version string, e.g., 2.0.0
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) const char* botan_version_string(void);
|
|
|
|
/**
|
|
* Return the major version of the library
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t botan_version_major(void);
|
|
|
|
/**
|
|
* Return the minor version of the library
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t botan_version_minor(void);
|
|
|
|
/**
|
|
* Return the patch version of the library
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t botan_version_patch(void);
|
|
|
|
/**
|
|
* Return the date this version was released as
|
|
* an integer, or 0 if an unreleased version
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t botan_version_datestamp(void);
|
|
|
|
/**
|
|
* Returns 0 if x[0..len] == y[0..len], or otherwise -1
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3) int botan_constant_time_compare(const uint8_t* x, const uint8_t* y, size_t len);
|
|
|
|
/**
|
|
* Deprecated equivalent to botan_constant_time_compare
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len);
|
|
|
|
/**
|
|
* Clear out memory using a system specific approach to bypass elision by the
|
|
* compiler (currently using RtlSecureZeroMemory or tricks with volatile pointers).
|
|
*/
|
|
BOTAN_PUBLIC_API(2,2) int botan_scrub_mem(void* mem, size_t bytes);
|
|
|
|
#define BOTAN_FFI_HEX_LOWER_CASE 1
|
|
|
|
/**
|
|
* Perform hex encoding
|
|
* @param x is some binary data
|
|
* @param len length of x in bytes
|
|
* @param out an array of at least x*2 bytes
|
|
* @param flags flags out be upper or lower case?
|
|
* @return 0 on success, 1 on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_hex_encode(const uint8_t* x, size_t len, char* out, uint32_t flags);
|
|
|
|
/**
|
|
* Perform hex decoding
|
|
* @param hex_str a string of hex chars (whitespace is ignored)
|
|
* @param in_len the length of hex_str
|
|
* @param out the output buffer should be at least strlen(hex_str)/2 bytes
|
|
* @param out_len the size of out
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3) int botan_hex_decode(const char* hex_str, size_t in_len, uint8_t* out, size_t* out_len);
|
|
|
|
/**
|
|
* Perform base64 encoding
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3) int botan_base64_encode(const uint8_t* x, size_t len, char* out, size_t* out_len);
|
|
|
|
|
|
/**
|
|
* Perform base64 decoding
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3) int botan_base64_decode(const char* base64_str, size_t in_len,
|
|
uint8_t* out, size_t* out_len);
|
|
|
|
/**
|
|
* RNG type
|
|
*/
|
|
typedef struct botan_rng_struct* botan_rng_t;
|
|
|
|
/**
|
|
* Initialize a random number generator object
|
|
* @param rng rng object
|
|
* @param rng_type type of the rng, possible values:
|
|
* "system": system RNG
|
|
* "user": userspace RNG
|
|
* "user-threadsafe": userspace RNG, with internal locking
|
|
* "rdrand": directly read RDRAND
|
|
* Set rng_type to null to let the library choose some default.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_rng_init(botan_rng_t* rng, const char* rng_type);
|
|
|
|
/**
|
|
* Initialize a custom random number generator from a set of callback functions
|
|
* @param rng rng object
|
|
* @param rng_name name of the rng
|
|
* @param context An application-specific context passed to the callback functions
|
|
* @param get_cb Callback for getting random bytes from the rng, return 0 for success
|
|
* @param add_entry_cb Callback for adding entropy to the rng, return 0 for success, may be NULL
|
|
* @param destroy_cb Callback called when rng is destroyed, may be NULL
|
|
*/
|
|
BOTAN_PUBLIC_API(2,18) int botan_rng_init_custom(botan_rng_t* rng_out, const char* rng_name, void* context,
|
|
int(* get_cb)(void* context, uint8_t* out, size_t out_len),
|
|
int(* add_entropy_cb)(void* context, const uint8_t input[], size_t length),
|
|
void(* destroy_cb)(void* context));
|
|
|
|
/**
|
|
* Get random bytes from a random number generator
|
|
* @param rng rng object
|
|
* @param out output buffer of size out_len
|
|
* @param out_len number of requested bytes
|
|
* @return 0 on success, negative on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_rng_get(botan_rng_t rng, uint8_t* out, size_t out_len);
|
|
|
|
/**
|
|
* Reseed a random number generator
|
|
* Uses the System_RNG as a seed generator.
|
|
*
|
|
* @param rng rng object
|
|
* @param bits number of bits to to reseed with
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_rng_reseed(botan_rng_t rng, size_t bits);
|
|
|
|
/**
|
|
* Reseed a random number generator
|
|
*
|
|
* @param rng rng object
|
|
* @param source_rng the rng that will be read from
|
|
* @param bits number of bits to to reseed with
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_rng_reseed_from_rng(botan_rng_t rng,
|
|
botan_rng_t source_rng,
|
|
size_t bits);
|
|
|
|
/**
|
|
* Add some seed material to a random number generator
|
|
*
|
|
* @param rng rng object
|
|
* @param entropy the data to add
|
|
* @param entropy_len length of entropy buffer
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_rng_add_entropy(botan_rng_t rng,
|
|
const uint8_t* entropy,
|
|
size_t entropy_len);
|
|
|
|
/**
|
|
* Frees all resources of the random number generator object
|
|
* @param rng rng object
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_rng_destroy(botan_rng_t rng);
|
|
|
|
/*
|
|
* Hash type
|
|
*/
|
|
typedef struct botan_hash_struct* botan_hash_t;
|
|
|
|
/**
|
|
* Initialize a hash function object
|
|
* @param hash hash object
|
|
* @param hash_name name of the hash function, e.g., "SHA-384"
|
|
* @param flags should be 0 in current API revision, all other uses are reserved
|
|
* and return BOTAN_FFI_ERROR_BAD_FLAG
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_hash_init(botan_hash_t* hash, const char* hash_name, uint32_t flags);
|
|
|
|
/**
|
|
* Copy the state of a hash function object
|
|
* @param dest destination hash object
|
|
* @param source source hash object
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,2) int botan_hash_copy_state(botan_hash_t *dest, const botan_hash_t source);
|
|
|
|
/**
|
|
* Writes the output length of the hash function to *output_length
|
|
* @param hash hash object
|
|
* @param output_length output buffer to hold the hash function output length
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_hash_output_length(botan_hash_t hash, size_t* output_length);
|
|
|
|
/**
|
|
* Writes the block size of the hash function to *block_size
|
|
* @param hash hash object
|
|
* @param block_size output buffer to hold the hash function output length
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,2) int botan_hash_block_size(botan_hash_t hash, size_t* block_size);
|
|
|
|
/**
|
|
* Send more input to the hash function
|
|
* @param hash hash object
|
|
* @param in input buffer
|
|
* @param in_len number of bytes to read from the input buffer
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_hash_update(botan_hash_t hash, const uint8_t* in, size_t in_len);
|
|
|
|
/**
|
|
* Finalizes the hash computation and writes the output to
|
|
* out[0:botan_hash_output_length()] then reinitializes for computing
|
|
* another digest as if botan_hash_clear had been called.
|
|
* @param hash hash object
|
|
* @param out output buffer
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_hash_final(botan_hash_t hash, uint8_t out[]);
|
|
|
|
/**
|
|
* Reinitializes the state of the hash computation. A hash can
|
|
* be computed (with update/final) immediately.
|
|
* @param hash hash object
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_hash_clear(botan_hash_t hash);
|
|
|
|
/**
|
|
* Frees all resources of the hash object
|
|
* @param hash hash object
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_hash_destroy(botan_hash_t hash);
|
|
|
|
/**
|
|
* Get the name of this hash function
|
|
* @param hash the object to read
|
|
* @param name output buffer
|
|
* @param name_len on input, the length of buffer, on success the number of bytes written
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_hash_name(botan_hash_t hash, char* name, size_t* name_len);
|
|
|
|
/*
|
|
* Message Authentication type
|
|
*/
|
|
typedef struct botan_mac_struct* botan_mac_t;
|
|
|
|
/**
|
|
* Initialize a message authentication code object
|
|
* @param mac mac object
|
|
* @param mac_name name of the hash function, e.g., "HMAC(SHA-384)"
|
|
* @param flags should be 0 in current API revision, all other uses are reserved
|
|
* and return a negative value (error code)
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_mac_init(botan_mac_t* mac, const char* mac_name, uint32_t flags);
|
|
|
|
/**
|
|
* Writes the output length of the message authentication code to *output_length
|
|
* @param mac mac object
|
|
* @param output_length output buffer to hold the MAC output length
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_mac_output_length(botan_mac_t mac, size_t* output_length);
|
|
|
|
/**
|
|
* Sets the key on the MAC
|
|
* @param mac mac object
|
|
* @param key buffer holding the key
|
|
* @param key_len size of the key buffer in bytes
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_mac_set_key(botan_mac_t mac, const uint8_t* key, size_t key_len);
|
|
|
|
/**
|
|
* Send more input to the message authentication code
|
|
* @param mac mac object
|
|
* @param buf input buffer
|
|
* @param len number of bytes to read from the input buffer
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_mac_update(botan_mac_t mac, const uint8_t* buf, size_t len);
|
|
|
|
/**
|
|
* Finalizes the MAC computation and writes the output to
|
|
* out[0:botan_mac_output_length()] then reinitializes for computing
|
|
* another MAC as if botan_mac_clear had been called.
|
|
* @param mac mac object
|
|
* @param out output buffer
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_mac_final(botan_mac_t mac, uint8_t out[]);
|
|
|
|
/**
|
|
* Reinitializes the state of the MAC computation. A MAC can
|
|
* be computed (with update/final) immediately.
|
|
* @param mac mac object
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_mac_clear(botan_mac_t mac);
|
|
|
|
/**
|
|
* Get the name of this MAC
|
|
* @param mac the object to read
|
|
* @param name output buffer
|
|
* @param name_len on input, the length of buffer, on success the number of bytes written
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_mac_name(botan_mac_t mac, char* name, size_t* name_len);
|
|
|
|
/**
|
|
* Get the key length limits of this auth code
|
|
* @param mac the object to read
|
|
* @param out_minimum_keylength if non-NULL, will be set to minimum keylength of MAC
|
|
* @param out_maximum_keylength if non-NULL, will be set to maximum keylength of MAC
|
|
* @param out_keylength_modulo if non-NULL will be set to byte multiple of valid keys
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_mac_get_keyspec(botan_mac_t mac,
|
|
size_t* out_minimum_keylength,
|
|
size_t* out_maximum_keylength,
|
|
size_t* out_keylength_modulo);
|
|
|
|
/**
|
|
* Frees all resources of the MAC object
|
|
* @param mac mac object
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_mac_destroy(botan_mac_t mac);
|
|
|
|
/*
|
|
* Cipher modes
|
|
*/
|
|
typedef struct botan_cipher_struct* botan_cipher_t;
|
|
|
|
#define BOTAN_CIPHER_INIT_FLAG_MASK_DIRECTION 1
|
|
#define BOTAN_CIPHER_INIT_FLAG_ENCRYPT 0
|
|
#define BOTAN_CIPHER_INIT_FLAG_DECRYPT 1
|
|
|
|
/**
|
|
* Initialize a cipher object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_init(botan_cipher_t* cipher, const char* name, uint32_t flags);
|
|
|
|
/**
|
|
* Return the name of the cipher object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_cipher_name(botan_cipher_t cipher, char* name, size_t* name_len);
|
|
|
|
/**
|
|
* Return the output length of this cipher, for a particular input length.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_cipher_output_length(botan_cipher_t cipher, size_t in_len, size_t* out_len);
|
|
|
|
/**
|
|
* Return if the specified nonce length is valid for this cipher
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_valid_nonce_length(botan_cipher_t cipher, size_t nl);
|
|
|
|
/**
|
|
* Get the tag length of the cipher (0 for non-AEAD modes)
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_get_tag_length(botan_cipher_t cipher, size_t* tag_size);
|
|
|
|
/**
|
|
* Get the default nonce length of this cipher
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_get_default_nonce_length(botan_cipher_t cipher, size_t* nl);
|
|
|
|
/**
|
|
* Return the update granularity of the cipher; botan_cipher_update must be
|
|
* called with blocks of this size, except for the final.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_get_update_granularity(botan_cipher_t cipher, size_t* ug);
|
|
|
|
/**
|
|
* Get information about the key lengths. Prefer botan_cipher_get_keyspec
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_query_keylen(botan_cipher_t,
|
|
size_t* out_minimum_keylength,
|
|
size_t* out_maximum_keylength);
|
|
|
|
/**
|
|
* Get information about the supported key lengths.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_cipher_get_keyspec(botan_cipher_t,
|
|
size_t* min_keylen,
|
|
size_t* max_keylen,
|
|
size_t* mod_keylen);
|
|
|
|
/**
|
|
* Set the key for this cipher object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_set_key(botan_cipher_t cipher,
|
|
const uint8_t* key, size_t key_len);
|
|
|
|
/**
|
|
* Reset the message specific state for this cipher.
|
|
* Without resetting the keys, this resets the nonce, and any state
|
|
* associated with any message bits that have been processed so far.
|
|
*
|
|
* It is conceptually equivalent to calling botan_cipher_clear followed
|
|
* by botan_cipher_set_key with the original key.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_cipher_reset(botan_cipher_t cipher);
|
|
|
|
/**
|
|
* Set the associated data. Will fail if cipher is not an AEAD
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_set_associated_data(botan_cipher_t cipher,
|
|
const uint8_t* ad, size_t ad_len);
|
|
|
|
/**
|
|
* Begin processing a new message using the provided nonce
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_start(botan_cipher_t cipher,
|
|
const uint8_t* nonce, size_t nonce_len);
|
|
|
|
#define BOTAN_CIPHER_UPDATE_FLAG_FINAL (1U << 0)
|
|
|
|
/**
|
|
* Encrypt some data
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_update(botan_cipher_t cipher,
|
|
uint32_t flags,
|
|
uint8_t output[],
|
|
size_t output_size,
|
|
size_t* output_written,
|
|
const uint8_t input_bytes[],
|
|
size_t input_size,
|
|
size_t* input_consumed);
|
|
|
|
/**
|
|
* Reset the key, nonce, AD and all other state on this cipher object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_clear(botan_cipher_t hash);
|
|
|
|
/**
|
|
* Destroy the cipher object
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_cipher_destroy(botan_cipher_t cipher);
|
|
|
|
/*
|
|
* Derive a key from a passphrase for a number of iterations
|
|
* @param pbkdf_algo PBKDF algorithm, e.g., "PBKDF2(SHA-256)"
|
|
* @param out buffer to store the derived key, must be of out_len bytes
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
* @param iterations the number of iterations to use (use 10K or more)
|
|
* @return 0 on success, a negative value on failure
|
|
*
|
|
* Deprecated: use
|
|
* botan_pwdhash(pbkdf_algo, iterations, 0, 0, out, out_len,
|
|
* passphrase, 0, salt, salt_len);
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int
|
|
BOTAN_DEPRECATED("Use botan_pwdhash")
|
|
botan_pbkdf(const char* pbkdf_algo,
|
|
uint8_t out[], size_t out_len,
|
|
const char* passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t iterations);
|
|
|
|
/**
|
|
* Derive a key from a passphrase, running until msec time has elapsed.
|
|
* @param pbkdf_algo PBKDF algorithm, e.g., "PBKDF2(SHA-256)"
|
|
* @param out buffer to store the derived key, must be of out_len bytes
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
* @param milliseconds_to_run if iterations is zero, then instead the PBKDF is
|
|
* run until milliseconds_to_run milliseconds has passed
|
|
* @param out_iterations_used set to the number iterations executed
|
|
* @return 0 on success, a negative value on failure
|
|
*
|
|
* Deprecated: use
|
|
*
|
|
* botan_pwdhash_timed(pbkdf_algo,
|
|
* static_cast<uint32_t>(ms_to_run),
|
|
* iterations_used,
|
|
* nullptr,
|
|
* nullptr,
|
|
* out, out_len,
|
|
* password, 0,
|
|
* salt, salt_len);
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_pbkdf_timed(const char* pbkdf_algo,
|
|
uint8_t out[], size_t out_len,
|
|
const char* passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t milliseconds_to_run,
|
|
size_t* out_iterations_used);
|
|
|
|
|
|
/*
|
|
* Derive a key from a passphrase
|
|
* @param algo PBKDF algorithm, e.g., "PBKDF2(SHA-256)" or "Scrypt"
|
|
* @param param1 the first PBKDF algorithm parameter
|
|
* @param param2 the second PBKDF algorithm parameter (may be zero if unneeded)
|
|
* @param param3 the third PBKDF algorithm parameter (may be zero if unneeded)
|
|
* @param out buffer to store the derived key, must be of out_len bytes
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param passphrase_len if > 0, specifies length of password. If len == 0, then
|
|
* strlen will be called on passphrase to compute the length.
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
int BOTAN_PUBLIC_API(2,8) botan_pwdhash(
|
|
const char* algo,
|
|
size_t param1,
|
|
size_t param2,
|
|
size_t param3,
|
|
uint8_t out[],
|
|
size_t out_len,
|
|
const char* passphrase,
|
|
size_t passphrase_len,
|
|
const uint8_t salt[],
|
|
size_t salt_len);
|
|
|
|
/*
|
|
* Derive a key from a passphrase
|
|
* @param pbkdf_algo PBKDF algorithm, e.g., "Scrypt" or "PBKDF2(SHA-256)"
|
|
* @param msec the desired runtime in milliseconds
|
|
* @param param1 will be set to the first password hash parameter
|
|
* @param param2 will be set to the second password hash parameter
|
|
* @param param3 will be set to the third password hash parameter
|
|
* @param out buffer to store the derived key, must be of out_len bytes
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param passphrase_len if > 0, specifies length of password. If len == 0, then
|
|
* strlen will be called on passphrase to compute the length.
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
int BOTAN_PUBLIC_API(2,8) botan_pwdhash_timed(
|
|
const char* algo,
|
|
uint32_t msec,
|
|
size_t* param1,
|
|
size_t* param2,
|
|
size_t* param3,
|
|
uint8_t out[],
|
|
size_t out_len,
|
|
const char* passphrase,
|
|
size_t passphrase_len,
|
|
const uint8_t salt[],
|
|
size_t salt_len);
|
|
|
|
/**
|
|
* Derive a key using scrypt
|
|
* Deprecated; use
|
|
* botan_pwdhash("Scrypt", N, r, p, out, out_len, password, 0, salt, salt_len);
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int
|
|
BOTAN_DEPRECATED("Use botan_pwdhash")
|
|
botan_scrypt(uint8_t out[], size_t out_len,
|
|
const char* passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t N, size_t r, size_t p);
|
|
|
|
/**
|
|
* Derive a key
|
|
* @param kdf_algo KDF algorithm, e.g., "SP800-56C"
|
|
* @param out buffer holding the derived key, must be of length out_len
|
|
* @param out_len the desired output length in bytes
|
|
* @param secret the secret input
|
|
* @param secret_len size of secret in bytes
|
|
* @param salt a diversifier
|
|
* @param salt_len size of salt in bytes
|
|
* @param label purpose for the derived keying material
|
|
* @param label_len size of label in bytes
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_kdf(const char* kdf_algo,
|
|
uint8_t out[], size_t out_len,
|
|
const uint8_t secret[], size_t secret_len,
|
|
const uint8_t salt[], size_t salt_len,
|
|
const uint8_t label[], size_t label_len);
|
|
|
|
/*
|
|
* Raw Block Cipher (PRP) interface
|
|
*/
|
|
typedef struct botan_block_cipher_struct* botan_block_cipher_t;
|
|
|
|
/**
|
|
* Initialize a block cipher object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_init(botan_block_cipher_t* bc,
|
|
const char* cipher_name);
|
|
|
|
/**
|
|
* Destroy a block cipher object
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_destroy(botan_block_cipher_t bc);
|
|
|
|
/**
|
|
* Reinitializes the block cipher
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_clear(botan_block_cipher_t bc);
|
|
|
|
/**
|
|
* Set the key for a block cipher instance
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_set_key(botan_block_cipher_t bc,
|
|
const uint8_t key[], size_t len);
|
|
|
|
/**
|
|
* Return the positive block size of this block cipher, or negative to
|
|
* indicate an error
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_block_size(botan_block_cipher_t bc);
|
|
|
|
/**
|
|
* Encrypt one or more blocks with the cipher
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_encrypt_blocks(botan_block_cipher_t bc,
|
|
const uint8_t in[],
|
|
uint8_t out[],
|
|
size_t blocks);
|
|
|
|
/**
|
|
* Decrypt one or more blocks with the cipher
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_block_cipher_decrypt_blocks(botan_block_cipher_t bc,
|
|
const uint8_t in[],
|
|
uint8_t out[],
|
|
size_t blocks);
|
|
|
|
/**
|
|
* Get the name of this block cipher
|
|
* @param cipher the object to read
|
|
* @param name output buffer
|
|
* @param name_len on input, the length of buffer, on success the number of bytes written
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_block_cipher_name(botan_block_cipher_t cipher,
|
|
char* name, size_t* name_len);
|
|
|
|
|
|
/**
|
|
* Get the key length limits of this block cipher
|
|
* @param cipher the object to read
|
|
* @param out_minimum_keylength if non-NULL, will be set to minimum keylength of cipher
|
|
* @param out_maximum_keylength if non-NULL, will be set to maximum keylength of cipher
|
|
* @param out_keylength_modulo if non-NULL will be set to byte multiple of valid keys
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_block_cipher_get_keyspec(botan_block_cipher_t cipher,
|
|
size_t* out_minimum_keylength,
|
|
size_t* out_maximum_keylength,
|
|
size_t* out_keylength_modulo);
|
|
|
|
/*
|
|
* Multiple precision integers (MPI)
|
|
*/
|
|
typedef struct botan_mp_struct* botan_mp_t;
|
|
|
|
/**
|
|
* Initialize an MPI
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_init(botan_mp_t* mp);
|
|
|
|
/**
|
|
* Destroy (deallocate) an MPI
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_destroy(botan_mp_t mp);
|
|
|
|
/**
|
|
* Convert the MPI to a hex string. Writes botan_mp_num_bytes(mp)*2 + 1 bytes
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_to_hex(const botan_mp_t mp, char* out);
|
|
|
|
/**
|
|
* Convert the MPI to a string. Currently base == 10 and base == 16 are supported.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_to_str(const botan_mp_t mp, uint8_t base, char* out, size_t* out_len);
|
|
|
|
/**
|
|
* Set the MPI to zero
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_clear(botan_mp_t mp);
|
|
|
|
/**
|
|
* Set the MPI value from an int
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_set_from_int(botan_mp_t mp, int initial_value);
|
|
|
|
/**
|
|
* Set the MPI value from another MP object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_set_from_mp(botan_mp_t dest, const botan_mp_t source);
|
|
|
|
/**
|
|
* Set the MPI value from a string
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_set_from_str(botan_mp_t dest, const char* str);
|
|
|
|
/**
|
|
* Set the MPI value from a string with arbitrary radix.
|
|
* For arbitrary being 10 or 16.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_set_from_radix_str(botan_mp_t dest, const char* str, size_t radix);
|
|
|
|
/**
|
|
* Return the number of significant bits in the MPI
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_num_bits(const botan_mp_t n, size_t* bits);
|
|
|
|
/**
|
|
* Return the number of significant bytes in the MPI
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_num_bytes(const botan_mp_t n, size_t* bytes);
|
|
|
|
/*
|
|
* Convert the MPI to a big-endian binary string. Writes botan_mp_num_bytes to vec
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_to_bin(const botan_mp_t mp, uint8_t vec[]);
|
|
|
|
/*
|
|
* Set an MP to the big-endian binary value
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_from_bin(const botan_mp_t mp, const uint8_t vec[], size_t vec_len);
|
|
|
|
/*
|
|
* Convert the MPI to a uint32_t, if possible. Fails if MPI is negative or too large.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_to_uint32(const botan_mp_t mp, uint32_t* val);
|
|
|
|
/**
|
|
* This function should have been named mp_is_non_negative. Returns 1
|
|
* iff mp is greater than *or equal to* zero. Use botan_mp_is_negative
|
|
* to detect negative numbers, botan_mp_is_zero to check for zero.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_is_positive(const botan_mp_t mp);
|
|
|
|
/**
|
|
* Return 1 iff mp is less than 0
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_is_negative(const botan_mp_t mp);
|
|
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_flip_sign(botan_mp_t mp);
|
|
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_is_zero(const botan_mp_t mp);
|
|
|
|
BOTAN_PUBLIC_API(2,1) BOTAN_DEPRECATED("Use botan_mp_get_bit(0)")
|
|
int botan_mp_is_odd(const botan_mp_t mp);
|
|
BOTAN_PUBLIC_API(2,1) BOTAN_DEPRECATED("Use botan_mp_get_bit(0)")
|
|
int botan_mp_is_even(const botan_mp_t mp);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_mp_add_u32(botan_mp_t result, const botan_mp_t x, uint32_t y);
|
|
BOTAN_PUBLIC_API(2,8) int botan_mp_sub_u32(botan_mp_t result, const botan_mp_t x, uint32_t y);
|
|
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_add(botan_mp_t result, const botan_mp_t x, const botan_mp_t y);
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_sub(botan_mp_t result, const botan_mp_t x, const botan_mp_t y);
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_mul(botan_mp_t result, const botan_mp_t x, const botan_mp_t y);
|
|
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_div(botan_mp_t quotient,
|
|
botan_mp_t remainder,
|
|
const botan_mp_t x, const botan_mp_t y);
|
|
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_mod_mul(botan_mp_t result, const botan_mp_t x,
|
|
const botan_mp_t y, const botan_mp_t mod);
|
|
|
|
/*
|
|
* Returns 0 if x != y
|
|
* Returns 1 if x == y
|
|
* Returns negative number on error
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_equal(const botan_mp_t x, const botan_mp_t y);
|
|
|
|
/*
|
|
* Sets *result to comparison result:
|
|
* -1 if x < y, 0 if x == y, 1 if x > y
|
|
* Returns negative number on error or zero on success
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_cmp(int* result, const botan_mp_t x, const botan_mp_t y);
|
|
|
|
/*
|
|
* Swap two botan_mp_t
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_swap(botan_mp_t x, botan_mp_t y);
|
|
|
|
/* Return (base^exponent) % modulus */
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_powmod(botan_mp_t out, const botan_mp_t base, const botan_mp_t exponent, const botan_mp_t modulus);
|
|
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_lshift(botan_mp_t out, const botan_mp_t in, size_t shift);
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_rshift(botan_mp_t out, const botan_mp_t in, size_t shift);
|
|
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_mod_inverse(botan_mp_t out, const botan_mp_t in, const botan_mp_t modulus);
|
|
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_rand_bits(botan_mp_t rand_out, botan_rng_t rng, size_t bits);
|
|
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_rand_range(botan_mp_t rand_out, botan_rng_t rng,
|
|
const botan_mp_t lower_bound, const botan_mp_t upper_bound);
|
|
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_gcd(botan_mp_t out, const botan_mp_t x, const botan_mp_t y);
|
|
|
|
/**
|
|
* Returns 0 if n is not prime
|
|
* Returns 1 if n is prime
|
|
* Returns negative number on error
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_is_prime(const botan_mp_t n, botan_rng_t rng, size_t test_prob);
|
|
|
|
/**
|
|
* Returns 0 if specified bit of n is not set
|
|
* Returns 1 if specified bit of n is set
|
|
* Returns negative number on error
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_get_bit(const botan_mp_t n, size_t bit);
|
|
|
|
/**
|
|
* Set the specified bit
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_set_bit(botan_mp_t n, size_t bit);
|
|
|
|
/**
|
|
* Clear the specified bit
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) int botan_mp_clear_bit(botan_mp_t n, size_t bit);
|
|
|
|
/* Bcrypt password hashing */
|
|
|
|
/**
|
|
* Create a password hash using Bcrypt
|
|
* @param out buffer holding the password hash, should be of length 64 bytes
|
|
* @param out_len the desired output length in bytes
|
|
* @param password the password
|
|
* @param rng a random number generator
|
|
* @param work_factor how much work to do to slow down guessing attacks
|
|
* @param flags should be 0 in current API revision, all other uses are reserved
|
|
* and return BOTAN_FFI_ERROR_BAD_FLAG
|
|
* @return 0 on success, a negative value on failure
|
|
|
|
* Output is formatted bcrypt $2a$...
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_bcrypt_generate(uint8_t* out, size_t* out_len,
|
|
const char* password,
|
|
botan_rng_t rng,
|
|
size_t work_factor,
|
|
uint32_t flags);
|
|
|
|
/**
|
|
* Check a previously created password hash
|
|
* @param pass the password to check against
|
|
* @param hash the stored hash to check against
|
|
* @return 0 if if this password/hash combination is valid,
|
|
* 1 if the combination is not valid (but otherwise well formed),
|
|
* negative on error
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_bcrypt_is_valid(const char* pass, const char* hash);
|
|
|
|
/*
|
|
* Public/private key creation, import, ...
|
|
*/
|
|
typedef struct botan_privkey_struct* botan_privkey_t;
|
|
|
|
/**
|
|
* Create a new private key
|
|
* @param key the new object will be placed here
|
|
* @param algo_name something like "RSA" or "ECDSA"
|
|
* @param algo_params is specific to the algorithm. For RSA, specifies
|
|
* the modulus bit length. For ECC is the name of the curve.
|
|
* @param rng a random number generator
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_create(botan_privkey_t* key,
|
|
const char* algo_name,
|
|
const char* algo_params,
|
|
botan_rng_t rng);
|
|
|
|
#define BOTAN_CHECK_KEY_EXPENSIVE_TESTS 1
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_check_key(botan_privkey_t key, botan_rng_t rng, uint32_t flags);
|
|
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_privkey_create")
|
|
int botan_privkey_create_rsa(botan_privkey_t* key, botan_rng_t rng, size_t n_bits);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_privkey_create")
|
|
int botan_privkey_create_ecdsa(botan_privkey_t* key, botan_rng_t rng, const char* params);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_privkey_create")
|
|
int botan_privkey_create_ecdh(botan_privkey_t* key, botan_rng_t rng, const char* params);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_privkey_create")
|
|
int botan_privkey_create_mceliece(botan_privkey_t* key, botan_rng_t rng, size_t n, size_t t);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_privkey_create")
|
|
int botan_privkey_create_dh(botan_privkey_t* key, botan_rng_t rng, const char* param);
|
|
|
|
/**
|
|
* Generates DSA key pair. Gives to a caller control over key length
|
|
* and order of a subgroup 'q'.
|
|
*
|
|
* @param key handler to the resulting key
|
|
* @param rng initialized PRNG
|
|
* @param pbits length of the key in bits. Must be between in range (1024, 3072)
|
|
* and multiple of 64. Bit size of the prime 'p'
|
|
* @param qbits order of the subgroup. Must be in range (160, 256) and multiple
|
|
* of 8
|
|
*
|
|
* @returns BOTAN_FFI_SUCCESS Success, `key' initialized with DSA key
|
|
* @returns BOTAN_FFI_ERROR_NULL_POINTER either `key' or `rng' is NULL
|
|
* @returns BOTAN_FFI_ERROR_BAD_PARAMETER unexpected value for either `pbits' or
|
|
* `qbits'
|
|
* @returns BOTAN_FFI_ERROR_NOT_IMPLEMENTED functionality not implemented
|
|
*
|
|
*/
|
|
BOTAN_PUBLIC_API(2,5) int botan_privkey_create_dsa(
|
|
botan_privkey_t* key,
|
|
botan_rng_t rng,
|
|
size_t pbits,
|
|
size_t qbits);
|
|
|
|
/**
|
|
* Generates ElGamal key pair. Caller has a control over key length
|
|
* and order of a subgroup 'q'. Function is able to use two types of
|
|
* primes:
|
|
* * if pbits-1 == qbits then safe primes are used for key generation
|
|
* * otherwise generation uses group of prime order
|
|
*
|
|
* @param key handler to the resulting key
|
|
* @param rng initialized PRNG
|
|
* @param pbits length of the key in bits. Must be at least 1024
|
|
* @param qbits order of the subgroup. Must be at least 160
|
|
*
|
|
* @returns BOTAN_FFI_SUCCESS Success, `key' initialized with DSA key
|
|
* @returns BOTAN_FFI_ERROR_NULL_POINTER either `key' or `rng' is NULL
|
|
* @returns BOTAN_FFI_ERROR_BAD_PARAMETER unexpected value for either `pbits' or
|
|
* `qbits'
|
|
* @returns BOTAN_FFI_ERROR_NOT_IMPLEMENTED functionality not implemented
|
|
*
|
|
*/
|
|
BOTAN_PUBLIC_API(2,5) int botan_privkey_create_elgamal(
|
|
botan_privkey_t* key,
|
|
botan_rng_t rng,
|
|
size_t pbits,
|
|
size_t qbits);
|
|
|
|
/**
|
|
* Input currently assumed to be PKCS #8 structure;
|
|
* Set password to NULL to indicate no encryption expected
|
|
* Starting in 2.8.0, the rng parameter is unused and may be set to null
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_load(botan_privkey_t* key,
|
|
botan_rng_t rng,
|
|
const uint8_t bits[], size_t len,
|
|
const char* password);
|
|
|
|
/**
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_destroy(botan_privkey_t key);
|
|
|
|
#define BOTAN_PRIVKEY_EXPORT_FLAG_DER 0
|
|
#define BOTAN_PRIVKEY_EXPORT_FLAG_PEM 1
|
|
|
|
/**
|
|
* On input *out_len is number of bytes in out[]
|
|
* On output *out_len is number of bytes written (or required)
|
|
* If out is not big enough no output is written, *out_len is set and 1 is returned
|
|
* Returns 0 on success and sets
|
|
* If some other error occurs a negative integer is returned.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_export(botan_privkey_t key,
|
|
uint8_t out[], size_t* out_len,
|
|
uint32_t flags);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_privkey_algo_name(botan_privkey_t key, char out[], size_t* out_len);
|
|
|
|
/**
|
|
* Set encryption_algo to NULL or "" to have the library choose a default (recommended)
|
|
*/
|
|
BOTAN_DEPRECATED("Use botan_privkey_export_encrypted_pbkdf_{msec,iter}")
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_export_encrypted(botan_privkey_t key,
|
|
uint8_t out[], size_t* out_len,
|
|
botan_rng_t rng,
|
|
const char* passphrase,
|
|
const char* encryption_algo,
|
|
uint32_t flags);
|
|
|
|
/*
|
|
* Export a private key, running PBKDF for specified amount of time
|
|
* @param key the private key to export
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_export_encrypted_pbkdf_msec(botan_privkey_t key,
|
|
uint8_t out[], size_t* out_len,
|
|
botan_rng_t rng,
|
|
const char* passphrase,
|
|
uint32_t pbkdf_msec_runtime,
|
|
size_t* pbkdf_iterations_out,
|
|
const char* cipher_algo,
|
|
const char* pbkdf_algo,
|
|
uint32_t flags);
|
|
|
|
/**
|
|
* Export a private key using the specified number of iterations.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_export_encrypted_pbkdf_iter(botan_privkey_t key,
|
|
uint8_t out[], size_t* out_len,
|
|
botan_rng_t rng,
|
|
const char* passphrase,
|
|
size_t pbkdf_iterations,
|
|
const char* cipher_algo,
|
|
const char* pbkdf_algo,
|
|
uint32_t flags);
|
|
|
|
typedef struct botan_pubkey_struct* botan_pubkey_t;
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_load(botan_pubkey_t* key, const uint8_t bits[], size_t len);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_export_pubkey(botan_pubkey_t* out, botan_privkey_t in);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out_len, uint32_t flags);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len);
|
|
|
|
/**
|
|
* Returns 0 if key is valid, negative if invalid key or some other error
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_check_key(botan_pubkey_t key, botan_rng_t rng, uint32_t flags);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_estimated_strength(botan_pubkey_t key, size_t* estimate);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_fingerprint(botan_pubkey_t key, const char* hash,
|
|
uint8_t out[], size_t* out_len);
|
|
|
|
/**
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_destroy(botan_pubkey_t key);
|
|
|
|
/*
|
|
* Get arbitrary named fields from public or privat keys
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_get_field(botan_mp_t output,
|
|
botan_pubkey_t key,
|
|
const char* field_name);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_get_field(botan_mp_t output,
|
|
botan_privkey_t key,
|
|
const char* field_name);
|
|
|
|
/*
|
|
* Algorithm specific key operations: RSA
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_load_rsa(botan_privkey_t* key,
|
|
botan_mp_t p,
|
|
botan_mp_t q,
|
|
botan_mp_t e);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_privkey_load_rsa_pkcs1(botan_privkey_t* key,
|
|
const uint8_t bits[],
|
|
size_t len);
|
|
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_privkey_get_field")
|
|
int botan_privkey_rsa_get_p(botan_mp_t p, botan_privkey_t rsa_key);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_privkey_get_field")
|
|
int botan_privkey_rsa_get_q(botan_mp_t q, botan_privkey_t rsa_key);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_privkey_get_field")
|
|
int botan_privkey_rsa_get_d(botan_mp_t d, botan_privkey_t rsa_key);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_privkey_get_field")
|
|
int botan_privkey_rsa_get_n(botan_mp_t n, botan_privkey_t rsa_key);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_privkey_get_field")
|
|
int botan_privkey_rsa_get_e(botan_mp_t e, botan_privkey_t rsa_key);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_privkey_rsa_get_privkey(botan_privkey_t rsa_key,
|
|
uint8_t out[], size_t* out_len,
|
|
uint32_t flags);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_load_rsa(botan_pubkey_t* key,
|
|
botan_mp_t n,
|
|
botan_mp_t e);
|
|
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_pubkey_get_field")
|
|
int botan_pubkey_rsa_get_e(botan_mp_t e, botan_pubkey_t rsa_key);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_pubkey_get_field")
|
|
int botan_pubkey_rsa_get_n(botan_mp_t n, botan_pubkey_t rsa_key);
|
|
|
|
/*
|
|
* Algorithm specific key operations: DSA
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_load_dsa(botan_privkey_t* key,
|
|
botan_mp_t p,
|
|
botan_mp_t q,
|
|
botan_mp_t g,
|
|
botan_mp_t x);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_load_dsa(botan_pubkey_t* key,
|
|
botan_mp_t p,
|
|
botan_mp_t q,
|
|
botan_mp_t g,
|
|
botan_mp_t y);
|
|
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_privkey_get_field")
|
|
int botan_privkey_dsa_get_x(botan_mp_t n, botan_privkey_t key);
|
|
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_pubkey_get_field")
|
|
int botan_pubkey_dsa_get_p(botan_mp_t p, botan_pubkey_t key);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_pubkey_get_field")
|
|
int botan_pubkey_dsa_get_q(botan_mp_t q, botan_pubkey_t key);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_pubkey_get_field")
|
|
int botan_pubkey_dsa_get_g(botan_mp_t d, botan_pubkey_t key);
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use botan_pubkey_get_field")
|
|
int botan_pubkey_dsa_get_y(botan_mp_t y, botan_pubkey_t key);
|
|
|
|
/*
|
|
* Loads Diffie Hellman private key
|
|
*
|
|
* @param key variable populated with key material
|
|
* @param p prime order of a Z_p group
|
|
* @param g group generator
|
|
* @param x private key
|
|
*
|
|
* @pre key is NULL on input
|
|
* @post function allocates memory and assigns to `key'
|
|
*
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_load_dh(botan_privkey_t* key,
|
|
botan_mp_t p,
|
|
botan_mp_t g,
|
|
botan_mp_t x);
|
|
/**
|
|
* Loads Diffie Hellman public key
|
|
*
|
|
* @param key variable populated with key material
|
|
* @param p prime order of a Z_p group
|
|
* @param g group generator
|
|
* @param y public key
|
|
*
|
|
* @pre key is NULL on input
|
|
* @post function allocates memory and assigns to `key'
|
|
*
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_load_dh(botan_pubkey_t* key,
|
|
botan_mp_t p,
|
|
botan_mp_t g,
|
|
botan_mp_t y);
|
|
|
|
/*
|
|
* Algorithm specific key operations: ElGamal
|
|
*/
|
|
|
|
/**
|
|
* Loads ElGamal public key
|
|
* @param key variable populated with key material
|
|
* @param p prime order of a Z_p group
|
|
* @param g group generator
|
|
* @param y public key
|
|
*
|
|
* @pre key is NULL on input
|
|
* @post function allocates memory and assigns to `key'
|
|
*
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_pubkey_load_elgamal(botan_pubkey_t* key,
|
|
botan_mp_t p,
|
|
botan_mp_t g,
|
|
botan_mp_t y);
|
|
|
|
/**
|
|
* Loads ElGamal private key
|
|
*
|
|
* @param key variable populated with key material
|
|
* @param p prime order of a Z_p group
|
|
* @param g group generator
|
|
* @param x private key
|
|
*
|
|
* @pre key is NULL on input
|
|
* @post function allocates memory and assigns to `key'
|
|
*
|
|
* @return 0 on success, a negative value on failure
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_privkey_load_elgamal(botan_privkey_t* key,
|
|
botan_mp_t p,
|
|
botan_mp_t g,
|
|
botan_mp_t x);
|
|
|
|
/*
|
|
* Algorithm specific key operations: Ed25519
|
|
*/
|
|
|
|
BOTAN_PUBLIC_API(2,2) int botan_privkey_load_ed25519(botan_privkey_t* key,
|
|
const uint8_t privkey[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,2) int botan_pubkey_load_ed25519(botan_pubkey_t* key,
|
|
const uint8_t pubkey[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,2) int botan_privkey_ed25519_get_privkey(botan_privkey_t key,
|
|
uint8_t output[64]);
|
|
|
|
BOTAN_PUBLIC_API(2,2) int botan_pubkey_ed25519_get_pubkey(botan_pubkey_t key,
|
|
uint8_t pubkey[32]);
|
|
|
|
/*
|
|
* Algorithm specific key operations: X25519
|
|
*/
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_privkey_load_x25519(botan_privkey_t* key,
|
|
const uint8_t privkey[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_pubkey_load_x25519(botan_pubkey_t* key,
|
|
const uint8_t pubkey[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_privkey_x25519_get_privkey(botan_privkey_t key,
|
|
uint8_t output[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_pubkey_x25519_get_pubkey(botan_pubkey_t key,
|
|
uint8_t pubkey[32]);
|
|
|
|
/*
|
|
* Algorithm specific key operations: ECDSA and ECDH
|
|
*/
|
|
BOTAN_PUBLIC_API(2,2)
|
|
int botan_privkey_load_ecdsa(botan_privkey_t* key,
|
|
const botan_mp_t scalar,
|
|
const char* curve_name);
|
|
|
|
BOTAN_PUBLIC_API(2,2)
|
|
int botan_pubkey_load_ecdsa(botan_pubkey_t* key,
|
|
const botan_mp_t public_x,
|
|
const botan_mp_t public_y,
|
|
const char* curve_name);
|
|
|
|
BOTAN_PUBLIC_API(2,2)
|
|
int botan_pubkey_load_ecdh(botan_pubkey_t* key,
|
|
const botan_mp_t public_x,
|
|
const botan_mp_t public_y,
|
|
const char* curve_name);
|
|
|
|
BOTAN_PUBLIC_API(2,2)
|
|
int botan_privkey_load_ecdh(botan_privkey_t* key,
|
|
const botan_mp_t scalar,
|
|
const char* curve_name);
|
|
|
|
BOTAN_PUBLIC_API(2,2)
|
|
int botan_pubkey_load_sm2(botan_pubkey_t* key,
|
|
const botan_mp_t public_x,
|
|
const botan_mp_t public_y,
|
|
const char* curve_name);
|
|
|
|
BOTAN_PUBLIC_API(2,2)
|
|
int botan_privkey_load_sm2(botan_privkey_t* key,
|
|
const botan_mp_t scalar,
|
|
const char* curve_name);
|
|
|
|
BOTAN_PUBLIC_API(2,2) BOTAN_DEPRECATED("Use botan_pubkey_load_sm2")
|
|
int botan_pubkey_load_sm2_enc(botan_pubkey_t* key,
|
|
const botan_mp_t public_x,
|
|
const botan_mp_t public_y,
|
|
const char* curve_name);
|
|
|
|
BOTAN_PUBLIC_API(2,2) BOTAN_DEPRECATED("Use botan_privkey_load_sm2")
|
|
int botan_privkey_load_sm2_enc(botan_privkey_t* key,
|
|
const botan_mp_t scalar,
|
|
const char* curve_name);
|
|
|
|
BOTAN_PUBLIC_API(2,3)
|
|
int botan_pubkey_sm2_compute_za(uint8_t out[],
|
|
size_t* out_len,
|
|
const char* ident,
|
|
const char* hash_algo,
|
|
const botan_pubkey_t key);
|
|
|
|
/*
|
|
* Public Key Encryption
|
|
*/
|
|
typedef struct botan_pk_op_encrypt_struct* botan_pk_op_encrypt_t;
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_encrypt_create(botan_pk_op_encrypt_t* op,
|
|
botan_pubkey_t key,
|
|
const char* padding,
|
|
uint32_t flags);
|
|
|
|
/**
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_encrypt_destroy(botan_pk_op_encrypt_t op);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_pk_op_encrypt_output_length(botan_pk_op_encrypt_t op,
|
|
size_t ptext_len,
|
|
size_t* ctext_len);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_encrypt(botan_pk_op_encrypt_t op,
|
|
botan_rng_t rng,
|
|
uint8_t out[],
|
|
size_t* out_len,
|
|
const uint8_t plaintext[],
|
|
size_t plaintext_len);
|
|
|
|
/*
|
|
* Public Key Decryption
|
|
*/
|
|
typedef struct botan_pk_op_decrypt_struct* botan_pk_op_decrypt_t;
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_decrypt_create(botan_pk_op_decrypt_t* op,
|
|
botan_privkey_t key,
|
|
const char* padding,
|
|
uint32_t flags);
|
|
|
|
/**
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_decrypt_destroy(botan_pk_op_decrypt_t op);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_pk_op_decrypt_output_length(botan_pk_op_decrypt_t op,
|
|
size_t ctext_len,
|
|
size_t* ptext_len);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_decrypt(botan_pk_op_decrypt_t op,
|
|
uint8_t out[], size_t* out_len,
|
|
const uint8_t ciphertext[], size_t ciphertext_len);
|
|
|
|
/*
|
|
* Signature Generation
|
|
*/
|
|
|
|
#define BOTAN_PUBKEY_DER_FORMAT_SIGNATURE 1
|
|
|
|
typedef struct botan_pk_op_sign_struct* botan_pk_op_sign_t;
|
|
|
|
BOTAN_PUBLIC_API(2,0)
|
|
int botan_pk_op_sign_create(botan_pk_op_sign_t* op,
|
|
botan_privkey_t key,
|
|
const char* hash_and_padding,
|
|
uint32_t flags);
|
|
|
|
/**
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_sign_destroy(botan_pk_op_sign_t op);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_pk_op_sign_output_length(botan_pk_op_sign_t op, size_t* olen);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_sign_update(botan_pk_op_sign_t op, const uint8_t in[], size_t in_len);
|
|
|
|
BOTAN_PUBLIC_API(2,0)
|
|
int botan_pk_op_sign_finish(botan_pk_op_sign_t op, botan_rng_t rng,
|
|
uint8_t sig[], size_t* sig_len);
|
|
|
|
/*
|
|
* Signature Verification
|
|
*/
|
|
typedef struct botan_pk_op_verify_struct* botan_pk_op_verify_t;
|
|
|
|
BOTAN_PUBLIC_API(2,0)
|
|
int botan_pk_op_verify_create(botan_pk_op_verify_t* op,
|
|
botan_pubkey_t key,
|
|
const char* hash_and_padding,
|
|
uint32_t flags);
|
|
|
|
/**
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_verify_destroy(botan_pk_op_verify_t op);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_verify_update(botan_pk_op_verify_t op, const uint8_t in[], size_t in_len);
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_verify_finish(botan_pk_op_verify_t op, const uint8_t sig[], size_t sig_len);
|
|
|
|
/*
|
|
* Key Agreement
|
|
*/
|
|
typedef struct botan_pk_op_ka_struct* botan_pk_op_ka_t;
|
|
|
|
BOTAN_PUBLIC_API(2,0)
|
|
int botan_pk_op_key_agreement_create(botan_pk_op_ka_t* op,
|
|
botan_privkey_t key,
|
|
const char* kdf,
|
|
uint32_t flags);
|
|
|
|
/**
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_key_agreement_destroy(botan_pk_op_ka_t op);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pk_op_key_agreement_export_public(botan_privkey_t key,
|
|
uint8_t out[], size_t* out_len);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_pk_op_key_agreement_size(botan_pk_op_ka_t op, size_t* out_len);
|
|
|
|
BOTAN_PUBLIC_API(2,0)
|
|
int botan_pk_op_key_agreement(botan_pk_op_ka_t op,
|
|
uint8_t out[], size_t* out_len,
|
|
const uint8_t other_key[], size_t other_key_len,
|
|
const uint8_t salt[], size_t salt_len);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_pkcs_hash_id(const char* hash_name, uint8_t pkcs_id[], size_t* pkcs_id_len);
|
|
|
|
|
|
/*
|
|
*
|
|
* @param mce_key must be a McEliece key
|
|
* ct_len should be pt_len + n/8 + a few?
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Poorly specified, avoid in new code")
|
|
int botan_mceies_encrypt(botan_pubkey_t mce_key,
|
|
botan_rng_t rng,
|
|
const char* aead,
|
|
const uint8_t pt[], size_t pt_len,
|
|
const uint8_t ad[], size_t ad_len,
|
|
uint8_t ct[], size_t* ct_len);
|
|
|
|
BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Poorly specified, avoid in new code")
|
|
int botan_mceies_decrypt(botan_privkey_t mce_key,
|
|
const char* aead,
|
|
const uint8_t ct[], size_t ct_len,
|
|
const uint8_t ad[], size_t ad_len,
|
|
uint8_t pt[], size_t* pt_len);
|
|
|
|
/*
|
|
* X.509 certificates
|
|
**************************/
|
|
|
|
typedef struct botan_x509_cert_struct* botan_x509_cert_t;
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_load(botan_x509_cert_t* cert_obj, const uint8_t cert[], size_t cert_len);
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_load_file(botan_x509_cert_t* cert_obj, const char* filename);
|
|
|
|
/**
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_destroy(botan_x509_cert_t cert);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_x509_cert_dup(botan_x509_cert_t* new_cert, botan_x509_cert_t cert);
|
|
|
|
/* Prefer botan_x509_cert_not_before and botan_x509_cert_not_after */
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_get_time_starts(botan_x509_cert_t cert, char out[], size_t* out_len);
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len);
|
|
|
|
BOTAN_PUBLIC_API(2,8) int botan_x509_cert_not_before(botan_x509_cert_t cert, uint64_t* time_since_epoch);
|
|
BOTAN_PUBLIC_API(2,8) int botan_x509_cert_not_after(botan_x509_cert_t cert, uint64_t* time_since_epoch);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_get_fingerprint(botan_x509_cert_t cert, const char* hash, uint8_t out[], size_t* out_len);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len);
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len);
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert,
|
|
uint8_t out[], size_t* out_len);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key);
|
|
|
|
BOTAN_PUBLIC_API(2,0)
|
|
int botan_x509_cert_get_issuer_dn(botan_x509_cert_t cert,
|
|
const char* key, size_t index,
|
|
uint8_t out[], size_t* out_len);
|
|
|
|
BOTAN_PUBLIC_API(2,0)
|
|
int botan_x509_cert_get_subject_dn(botan_x509_cert_t cert,
|
|
const char* key, size_t index,
|
|
uint8_t out[], size_t* out_len);
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len);
|
|
|
|
/* Must match values of Key_Constraints in key_constraints.h */
|
|
enum botan_x509_cert_key_constraints {
|
|
NO_CONSTRAINTS = 0,
|
|
DIGITAL_SIGNATURE = 32768,
|
|
NON_REPUDIATION = 16384,
|
|
KEY_ENCIPHERMENT = 8192,
|
|
DATA_ENCIPHERMENT = 4096,
|
|
KEY_AGREEMENT = 2048,
|
|
KEY_CERT_SIGN = 1024,
|
|
CRL_SIGN = 512,
|
|
ENCIPHER_ONLY = 256,
|
|
DECIPHER_ONLY = 128
|
|
};
|
|
|
|
BOTAN_PUBLIC_API(2,0) int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage);
|
|
|
|
/**
|
|
* Check if the certificate matches the specified hostname via alternative name or CN match.
|
|
* RFC 5280 wildcards also supported.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,5) int botan_x509_cert_hostname_match(botan_x509_cert_t cert, const char* hostname);
|
|
|
|
/**
|
|
* Returns 0 if the validation was successful, 1 if validation failed,
|
|
* and negative on error. A status code with details is written to
|
|
* *validation_result
|
|
*
|
|
* Intermediates or trusted lists can be null
|
|
* Trusted path can be null
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) int botan_x509_cert_verify(
|
|
int* validation_result,
|
|
botan_x509_cert_t cert,
|
|
const botan_x509_cert_t* intermediates,
|
|
size_t intermediates_len,
|
|
const botan_x509_cert_t* trusted,
|
|
size_t trusted_len,
|
|
const char* trusted_path,
|
|
size_t required_strength,
|
|
const char* hostname,
|
|
uint64_t reference_time);
|
|
|
|
/**
|
|
* Returns a pointer to a static character string explaining the status code,
|
|
* or else NULL if unknown.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) const char* botan_x509_cert_validation_status(int code);
|
|
|
|
/*
|
|
* X.509 CRL
|
|
**************************/
|
|
|
|
typedef struct botan_x509_crl_struct* botan_x509_crl_t;
|
|
|
|
BOTAN_PUBLIC_API(2,13) int botan_x509_crl_load_file(botan_x509_crl_t* crl_obj, const char* crl_path);
|
|
BOTAN_PUBLIC_API(2,13) int botan_x509_crl_load(botan_x509_crl_t* crl_obj, const uint8_t crl_bits[], size_t crl_bits_len);
|
|
|
|
BOTAN_PUBLIC_API(2,13) int botan_x509_crl_destroy(botan_x509_crl_t crl);
|
|
|
|
/**
|
|
* Given a CRL and a certificate,
|
|
* check if the certificate is revoked on that particular CRL
|
|
*/
|
|
BOTAN_PUBLIC_API(2,13) int botan_x509_is_revoked(botan_x509_crl_t crl, botan_x509_cert_t cert);
|
|
|
|
/**
|
|
* Different flavor of `botan_x509_cert_verify`, supports revocation lists.
|
|
* CRLs are passed as an array, same as intermediates and trusted CAs
|
|
*/
|
|
BOTAN_PUBLIC_API(2,13) int botan_x509_cert_verify_with_crl(
|
|
int* validation_result,
|
|
botan_x509_cert_t cert,
|
|
const botan_x509_cert_t* intermediates,
|
|
size_t intermediates_len,
|
|
const botan_x509_cert_t* trusted,
|
|
size_t trusted_len,
|
|
const botan_x509_crl_t* crls,
|
|
size_t crls_len,
|
|
const char* trusted_path,
|
|
size_t required_strength,
|
|
const char* hostname,
|
|
uint64_t reference_time);
|
|
|
|
/**
|
|
* Key wrapping as per RFC 3394
|
|
*/
|
|
BOTAN_PUBLIC_API(2,2)
|
|
int botan_key_wrap3394(const uint8_t key[], size_t key_len,
|
|
const uint8_t kek[], size_t kek_len,
|
|
uint8_t wrapped_key[], size_t *wrapped_key_len);
|
|
|
|
BOTAN_PUBLIC_API(2,2)
|
|
int botan_key_unwrap3394(const uint8_t wrapped_key[], size_t wrapped_key_len,
|
|
const uint8_t kek[], size_t kek_len,
|
|
uint8_t key[], size_t *key_len);
|
|
|
|
/**
|
|
* HOTP
|
|
*/
|
|
|
|
typedef struct botan_hotp_struct* botan_hotp_t;
|
|
|
|
/**
|
|
* Initialize a HOTP instance
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_hotp_init(botan_hotp_t* hotp,
|
|
const uint8_t key[], size_t key_len,
|
|
const char* hash_algo,
|
|
size_t digits);
|
|
|
|
/**
|
|
* Destroy a HOTP instance
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_hotp_destroy(botan_hotp_t hotp);
|
|
|
|
/**
|
|
* Generate a HOTP code for the provided counter
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_hotp_generate(botan_hotp_t hotp,
|
|
uint32_t* hotp_code,
|
|
uint64_t hotp_counter);
|
|
|
|
/**
|
|
* Verify a HOTP code
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_hotp_check(botan_hotp_t hotp,
|
|
uint64_t* next_hotp_counter,
|
|
uint32_t hotp_code,
|
|
uint64_t hotp_counter,
|
|
size_t resync_range);
|
|
|
|
|
|
/**
|
|
* TOTP
|
|
*/
|
|
|
|
typedef struct botan_totp_struct* botan_totp_t;
|
|
|
|
/**
|
|
* Initialize a TOTP instance
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_totp_init(botan_totp_t* totp,
|
|
const uint8_t key[], size_t key_len,
|
|
const char* hash_algo,
|
|
size_t digits,
|
|
size_t time_step);
|
|
|
|
/**
|
|
* Destroy a TOTP instance
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_totp_destroy(botan_totp_t totp);
|
|
|
|
/**
|
|
* Generate a TOTP code for the provided timestamp
|
|
* @param totp the TOTP object
|
|
* @param totp_code the OTP code will be written here
|
|
* @param timestamp the current local timestamp
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_totp_generate(botan_totp_t totp,
|
|
uint32_t* totp_code,
|
|
uint64_t timestamp);
|
|
|
|
/**
|
|
* Verify a TOTP code
|
|
* @param totp the TOTP object
|
|
* @param totp_code the presented OTP
|
|
* @param timestamp the current local timestamp
|
|
* @param acceptable_clock_drift specifies the acceptable amount
|
|
* of clock drift (in terms of time steps) between the two hosts.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_totp_check(botan_totp_t totp,
|
|
uint32_t totp_code,
|
|
uint64_t timestamp,
|
|
size_t acceptable_clock_drift);
|
|
|
|
|
|
/**
|
|
* Format Preserving Encryption
|
|
*/
|
|
|
|
typedef struct botan_fpe_struct* botan_fpe_t;
|
|
|
|
#define BOTAN_FPE_FLAG_FE1_COMPAT_MODE 1
|
|
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_fpe_fe1_init(botan_fpe_t* fpe, botan_mp_t n,
|
|
const uint8_t key[], size_t key_len,
|
|
size_t rounds, uint32_t flags);
|
|
|
|
/**
|
|
* @return 0 if success, error if invalid object handle
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_fpe_destroy(botan_fpe_t fpe);
|
|
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_fpe_encrypt(botan_fpe_t fpe, botan_mp_t x, const uint8_t tweak[], size_t tweak_len);
|
|
|
|
BOTAN_PUBLIC_API(2,8)
|
|
int botan_fpe_decrypt(botan_fpe_t fpe, botan_mp_t x, const uint8_t tweak[], size_t tweak_len);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
class Filter;
|
|
class Output_Buffers;
|
|
|
|
/**
|
|
* This class represents pipe objects.
|
|
* A set of filters can be 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.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Pipe final : public DataSource
|
|
{
|
|
public:
|
|
/**
|
|
* An opaque type that identifies a message in this Pipe
|
|
*/
|
|
typedef size_t message_id;
|
|
|
|
/**
|
|
* Exception if you use an invalid message as an argument to
|
|
* read, remaining, etc
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Invalid_Message_Number final : public Invalid_Argument
|
|
{
|
|
public:
|
|
/**
|
|
* @param where the error occurred
|
|
* @param msg the invalid message id that was used
|
|
*/
|
|
Invalid_Message_Number(const std::string& where, message_id msg) :
|
|
Invalid_Argument("Pipe::" + where + ": Invalid message number " +
|
|
std::to_string(msg))
|
|
{}
|
|
};
|
|
|
|
/**
|
|
* A meta-id for whatever the last message is
|
|
*/
|
|
static const message_id LAST_MESSAGE;
|
|
|
|
/**
|
|
* A meta-id for the default message (set with set_default_msg)
|
|
*/
|
|
static const message_id DEFAULT_MESSAGE;
|
|
|
|
/**
|
|
* Write input to the pipe, i.e. to its first filter.
|
|
* @param in the byte array to write
|
|
* @param length the length of the byte array in
|
|
*/
|
|
void write(const uint8_t in[], size_t length);
|
|
|
|
/**
|
|
* Write input to the pipe, i.e. to its first filter.
|
|
* @param in the secure_vector containing the data to write
|
|
*/
|
|
void write(const secure_vector<uint8_t>& in)
|
|
{ write(in.data(), in.size()); }
|
|
|
|
/**
|
|
* Write input to the pipe, i.e. to its first filter.
|
|
* @param in the std::vector containing the data to write
|
|
*/
|
|
void write(const std::vector<uint8_t>& in)
|
|
{ write(in.data(), in.size()); }
|
|
|
|
/**
|
|
* Write input to the pipe, i.e. to its first filter.
|
|
* @param in the string containing the data to write
|
|
*/
|
|
void write(const std::string& in);
|
|
|
|
/**
|
|
* Write input to the pipe, i.e. to its first filter.
|
|
* @param in the DataSource to read the data from
|
|
*/
|
|
void write(DataSource& in);
|
|
|
|
/**
|
|
* Write input to the pipe, i.e. to its first filter.
|
|
* @param in a single byte to be written
|
|
*/
|
|
void write(uint8_t in);
|
|
|
|
/**
|
|
* Perform start_msg(), write() and end_msg() sequentially.
|
|
* @param in the byte array containing the data to write
|
|
* @param length the length of the byte array to write
|
|
*/
|
|
void process_msg(const uint8_t in[], size_t length);
|
|
|
|
/**
|
|
* Perform start_msg(), write() and end_msg() sequentially.
|
|
* @param in the secure_vector containing the data to write
|
|
*/
|
|
void process_msg(const secure_vector<uint8_t>& in);
|
|
|
|
/**
|
|
* Perform start_msg(), write() and end_msg() sequentially.
|
|
* @param in the secure_vector containing the data to write
|
|
*/
|
|
void process_msg(const std::vector<uint8_t>& in);
|
|
|
|
/**
|
|
* Perform start_msg(), write() and end_msg() sequentially.
|
|
* @param in the string containing the data to write
|
|
*/
|
|
void process_msg(const std::string& in);
|
|
|
|
/**
|
|
* Perform start_msg(), write() and end_msg() sequentially.
|
|
* @param in the DataSource providing the data to write
|
|
*/
|
|
void process_msg(DataSource& in);
|
|
|
|
/**
|
|
* Find out how many bytes are ready to read.
|
|
* @param msg the number identifying the message
|
|
* for which the information is desired
|
|
* @return number of bytes that can still be read
|
|
*/
|
|
size_t remaining(message_id msg = DEFAULT_MESSAGE) const BOTAN_WARN_UNUSED_RESULT;
|
|
|
|
/**
|
|
* Read the default message from the pipe. Moves the internal
|
|
* offset so that every call to read will return a new portion of
|
|
* the message.
|
|
*
|
|
* @param output the byte array to write the read bytes to
|
|
* @param length the length of the byte array output
|
|
* @return number of bytes actually read into output
|
|
*/
|
|
size_t read(uint8_t output[], size_t length) override BOTAN_WARN_UNUSED_RESULT;
|
|
|
|
/**
|
|
* Read a specified message from the pipe. Moves the internal
|
|
* offset so that every call to read will return a new portion of
|
|
* the message.
|
|
* @param output the byte array to write the read bytes to
|
|
* @param length the length of the byte array output
|
|
* @param msg the number identifying the message to read from
|
|
* @return number of bytes actually read into output
|
|
*/
|
|
size_t read(uint8_t output[], size_t length, message_id msg) BOTAN_WARN_UNUSED_RESULT;
|
|
|
|
/**
|
|
* Read a single byte from the pipe. Moves the internal offset so
|
|
* that every call to read will return a new portion of the
|
|
* message.
|
|
*
|
|
* @param output the byte to write the result to
|
|
* @param msg the message to read from
|
|
* @return number of bytes actually read into output
|
|
*/
|
|
size_t read(uint8_t& output, message_id msg = DEFAULT_MESSAGE) BOTAN_WARN_UNUSED_RESULT;
|
|
|
|
/**
|
|
* Read the full contents of the pipe.
|
|
* @param msg the number identifying the message to read from
|
|
* @return secure_vector holding the contents of the pipe
|
|
*/
|
|
secure_vector<uint8_t> read_all(message_id msg = DEFAULT_MESSAGE) BOTAN_WARN_UNUSED_RESULT;
|
|
|
|
/**
|
|
* Read the full contents of the pipe.
|
|
* @param msg the number identifying the message to read from
|
|
* @return string holding the contents of the pipe
|
|
*/
|
|
std::string read_all_as_string(message_id msg = DEFAULT_MESSAGE) BOTAN_WARN_UNUSED_RESULT;
|
|
|
|
/**
|
|
* Read from the default message but do not modify the internal
|
|
* offset. Consecutive calls to peek() will return portions of
|
|
* the message starting at the same position.
|
|
* @param output the byte array to write the peeked message part to
|
|
* @param length the length of the byte array output
|
|
* @param offset the offset from the current position in message
|
|
* @return number of bytes actually peeked and written into output
|
|
*/
|
|
size_t peek(uint8_t output[], size_t length, size_t offset) const override BOTAN_WARN_UNUSED_RESULT;
|
|
|
|
/** Read from the specified message but do not modify the
|
|
* internal offset. Consecutive calls to peek() will return
|
|
* portions of the message starting at the same position.
|
|
* @param output the byte array to write the peeked message part to
|
|
* @param length the length of the byte array output
|
|
* @param offset the offset from the current position in message
|
|
* @param msg the number identifying the message to peek from
|
|
* @return number of bytes actually peeked and written into output
|
|
*/
|
|
size_t peek(uint8_t output[], size_t length,
|
|
size_t offset, message_id msg) const BOTAN_WARN_UNUSED_RESULT;
|
|
|
|
/** Read a single byte from the specified message but do not
|
|
* modify the internal offset. Consecutive calls to peek() will
|
|
* return portions of the message starting at the same position.
|
|
* @param output the byte to write the peeked message byte to
|
|
* @param offset the offset from the current position in message
|
|
* @param msg the number identifying the message to peek from
|
|
* @return number of bytes actually peeked and written into output
|
|
*/
|
|
size_t peek(uint8_t& output, size_t offset,
|
|
message_id msg = DEFAULT_MESSAGE) const BOTAN_WARN_UNUSED_RESULT;
|
|
|
|
/**
|
|
* @return the number of bytes read from the default message.
|
|
*/
|
|
size_t get_bytes_read() const override;
|
|
|
|
/**
|
|
* @return the number of bytes read from the specified message.
|
|
*/
|
|
size_t get_bytes_read(message_id msg) const;
|
|
|
|
bool check_available(size_t n) override;
|
|
bool check_available_msg(size_t n, message_id msg);
|
|
|
|
/**
|
|
* @return currently set default message
|
|
*/
|
|
size_t default_msg() const { return m_default_read; }
|
|
|
|
/**
|
|
* Set the default message
|
|
* @param msg the number identifying the message which is going to
|
|
* be the new default message
|
|
*/
|
|
void set_default_msg(message_id msg);
|
|
|
|
/**
|
|
* Get the number of messages the are in this pipe.
|
|
* @return number of messages the are in this pipe
|
|
*/
|
|
message_id message_count() const;
|
|
|
|
/**
|
|
* Test whether this pipe has any data that can be read from.
|
|
* @return true if there is more data to read, false otherwise
|
|
*/
|
|
bool end_of_data() const override;
|
|
|
|
/**
|
|
* Start a new message in the pipe. A potential other message in this pipe
|
|
* must be closed with end_msg() before this function may be called.
|
|
*/
|
|
void start_msg();
|
|
|
|
/**
|
|
* End the current message.
|
|
*/
|
|
void end_msg();
|
|
|
|
/**
|
|
* Insert a new filter at the front of the pipe
|
|
* Deprecated because runtime modification of Pipes is deprecated.
|
|
* You can instead use prepend_filter which only works before the first
|
|
* message is processed.
|
|
* @param filt the new filter to insert
|
|
*/
|
|
BOTAN_DEPRECATED("Runtime modification of Pipe deprecated")
|
|
void prepend(Filter* filt);
|
|
|
|
/**
|
|
* Insert a new filter at the back of the pipe
|
|
* Deprecated because runtime modification of Pipes is deprecated.
|
|
* You can instead use append_filter which only works before the first
|
|
* message is processed.
|
|
* @param filt the new filter to insert
|
|
*/
|
|
BOTAN_DEPRECATED("Runtime modification of Pipe deprecated")
|
|
void append(Filter* filt);
|
|
|
|
/**
|
|
* Remove the first filter at the front of the pipe.
|
|
*/
|
|
BOTAN_DEPRECATED("Runtime modification of Pipe deprecated")
|
|
void pop();
|
|
|
|
/**
|
|
* Reset this pipe to an empty pipe.
|
|
*/
|
|
BOTAN_DEPRECATED("Runtime modification of Pipe deprecated")
|
|
void reset();
|
|
|
|
/**
|
|
* Append a new filter onto the filter sequence. This may only be
|
|
* called immediately after initial construction, before _any_
|
|
* calls to start_msg have been made.
|
|
*
|
|
* This function (unlike append) is not deprecated, as it allows
|
|
* only modification of the pipe at initialization (before use)
|
|
* rather than after messages have been processed.
|
|
*/
|
|
void append_filter(Filter* filt);
|
|
|
|
/**
|
|
* Prepend a new filter onto the filter sequence. This may only be
|
|
* called immediately after initial construction, before _any_
|
|
* calls to start_msg have been made.
|
|
*
|
|
* This function (unlike prepend) is not deprecated, as it allows
|
|
* only modification of the pipe at initialization (before use)
|
|
* rather than after messages have been processed.
|
|
*/
|
|
void prepend_filter(Filter* filt);
|
|
|
|
/**
|
|
* Construct a Pipe of up to four filters. The filters are set up
|
|
* in the same order as the arguments.
|
|
*/
|
|
Pipe(Filter* = nullptr, Filter* = nullptr,
|
|
Filter* = nullptr, Filter* = nullptr);
|
|
|
|
/**
|
|
* Construct a Pipe from a list of filters
|
|
* @param filters the set of filters to use
|
|
*/
|
|
explicit Pipe(std::initializer_list<Filter*> filters);
|
|
|
|
Pipe(const Pipe&) = delete;
|
|
Pipe& operator=(const Pipe&) = delete;
|
|
|
|
~Pipe();
|
|
private:
|
|
void destruct(Filter*);
|
|
void do_append(Filter* filt);
|
|
void do_prepend(Filter* filt);
|
|
void find_endpoints(Filter*);
|
|
void clear_endpoints(Filter*);
|
|
|
|
message_id get_message_no(const std::string&, message_id) const;
|
|
|
|
Filter* m_pipe;
|
|
std::unique_ptr<Output_Buffers> m_outputs;
|
|
message_id m_default_read;
|
|
bool m_inside_msg;
|
|
};
|
|
|
|
/**
|
|
* Stream output operator; dumps the results from pipe's default
|
|
* message to the output stream.
|
|
* @param out an output stream
|
|
* @param pipe the pipe
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::ostream& operator<<(std::ostream& out, Pipe& pipe);
|
|
|
|
/**
|
|
* Stream input operator; dumps the remaining bytes of input
|
|
* to the (assumed open) pipe message.
|
|
* @param in the input stream
|
|
* @param pipe the pipe
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::istream& operator>>(std::istream& in, Pipe& pipe);
|
|
|
|
}
|
|
|
|
#if defined(BOTAN_HAS_PIPE_UNIXFD_IO)
|
|
#endif
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_THREADS)
|
|
#include <thread>
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_STREAM_CIPHER)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_HASH)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_MAC)
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Filter mixin that breaks input into blocks, useful for
|
|
* cipher modes
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Buffered_Filter
|
|
{
|
|
public:
|
|
/**
|
|
* Write bytes into the buffered filter, which will them emit them
|
|
* in calls to buffered_block in the subclass
|
|
* @param in the input bytes
|
|
* @param length of in in bytes
|
|
*/
|
|
void write(const uint8_t in[], size_t length);
|
|
|
|
template<typename Alloc>
|
|
void write(const std::vector<uint8_t, Alloc>& in, size_t length)
|
|
{
|
|
write(in.data(), length);
|
|
}
|
|
|
|
/**
|
|
* Finish a message, emitting to buffered_block and buffered_final
|
|
* Will throw an exception if less than final_minimum bytes were
|
|
* written into the filter.
|
|
*/
|
|
void end_msg();
|
|
|
|
/**
|
|
* Initialize a Buffered_Filter
|
|
* @param block_size the function buffered_block will be called
|
|
* with inputs which are a multiple of this size
|
|
* @param final_minimum the function buffered_final will be called
|
|
* with at least this many bytes.
|
|
*/
|
|
Buffered_Filter(size_t block_size, size_t final_minimum);
|
|
|
|
virtual ~Buffered_Filter() = default;
|
|
protected:
|
|
/**
|
|
* The block processor, implemented by subclasses
|
|
* @param input some input bytes
|
|
* @param length the size of input, guaranteed to be a multiple
|
|
* of block_size
|
|
*/
|
|
virtual void buffered_block(const uint8_t input[], size_t length) = 0;
|
|
|
|
/**
|
|
* The final block, implemented by subclasses
|
|
* @param input some input bytes
|
|
* @param length the size of input, guaranteed to be at least
|
|
* final_minimum bytes
|
|
*/
|
|
virtual void buffered_final(const uint8_t input[], size_t length) = 0;
|
|
|
|
/**
|
|
* @return block size of inputs
|
|
*/
|
|
size_t buffered_block_size() const { return m_main_block_mod; }
|
|
|
|
/**
|
|
* @return current position in the buffer
|
|
*/
|
|
size_t current_position() const { return m_buffer_pos; }
|
|
|
|
/**
|
|
* Reset the buffer position
|
|
*/
|
|
void buffer_reset() { m_buffer_pos = 0; }
|
|
private:
|
|
size_t m_main_block_mod, m_final_minimum;
|
|
|
|
secure_vector<uint8_t> m_buffer;
|
|
size_t m_buffer_pos;
|
|
};
|
|
|
|
/**
|
|
* This class represents keyed filters, i.e. filters that have to be
|
|
* fed with a key in order to function.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Keyed_Filter : public Filter
|
|
{
|
|
public:
|
|
/**
|
|
* Set the key of this filter
|
|
* @param key the key to use
|
|
*/
|
|
virtual void set_key(const SymmetricKey& key) = 0;
|
|
|
|
/**
|
|
* Set the initialization vector of this filter. Note: you should
|
|
* call set_iv() only after you have called set_key()
|
|
* @param iv the initialization vector to use
|
|
*/
|
|
virtual void set_iv(const InitializationVector& iv)
|
|
{
|
|
if(iv.length() != 0)
|
|
throw Invalid_IV_Length(name(), iv.length());
|
|
}
|
|
|
|
/**
|
|
* Check whether a key length is valid for this filter
|
|
* @param length the key length to be checked for validity
|
|
* @return true if the key length is valid, false otherwise
|
|
*/
|
|
bool valid_keylength(size_t length) const
|
|
{
|
|
return key_spec().valid_keylength(length);
|
|
}
|
|
|
|
/**
|
|
* @return object describing limits on key size
|
|
*/
|
|
virtual Key_Length_Specification key_spec() const = 0;
|
|
|
|
/**
|
|
* Check whether an IV length is valid for this filter
|
|
* @param length the IV length to be checked for validity
|
|
* @return true if the IV length is valid, false otherwise
|
|
*/
|
|
virtual bool valid_iv_length(size_t length) const
|
|
{ return (length == 0); }
|
|
};
|
|
|
|
/**
|
|
* Filter interface for cipher modes
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Cipher_Mode_Filter final : public Keyed_Filter,
|
|
private Buffered_Filter
|
|
{
|
|
public:
|
|
explicit Cipher_Mode_Filter(Cipher_Mode* t);
|
|
|
|
explicit Cipher_Mode_Filter(std::unique_ptr<Cipher_Mode> t) :
|
|
Cipher_Mode_Filter(t.release()) {}
|
|
|
|
void set_iv(const InitializationVector& iv) override;
|
|
|
|
void set_key(const SymmetricKey& key) override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
bool valid_iv_length(size_t length) const override;
|
|
|
|
std::string name() const override;
|
|
|
|
private:
|
|
void write(const uint8_t input[], size_t input_length) override;
|
|
void start_msg() override;
|
|
void end_msg() override;
|
|
|
|
void buffered_block(const uint8_t input[], size_t input_length) override;
|
|
void buffered_final(const uint8_t input[], size_t input_length) override;
|
|
|
|
std::unique_ptr<Cipher_Mode> m_mode;
|
|
std::vector<uint8_t> m_nonce;
|
|
secure_vector<uint8_t> m_buffer;
|
|
};
|
|
|
|
// deprecated aliases, will be removed in a future major release
|
|
typedef Cipher_Mode_Filter Transform_Filter;
|
|
typedef Transform_Filter Transformation_Filter;
|
|
|
|
/*
|
|
* Get a cipher object
|
|
*/
|
|
|
|
/**
|
|
* Factory method for general symmetric cipher filters. No key will be
|
|
* set in the filter.
|
|
*
|
|
* @param algo_spec the name of the desired cipher
|
|
* @param direction determines whether the filter will be an encrypting or
|
|
* decrypting filter
|
|
* @return pointer to the encryption or decryption filter
|
|
*/
|
|
inline Keyed_Filter* get_cipher(const std::string& algo_spec,
|
|
Cipher_Dir direction)
|
|
{
|
|
std::unique_ptr<Cipher_Mode> c(Cipher_Mode::create_or_throw(algo_spec, direction));
|
|
return new Cipher_Mode_Filter(c.release());
|
|
}
|
|
|
|
/**
|
|
* Factory method for general symmetric cipher filters.
|
|
* @param algo_spec the name of the desired cipher
|
|
* @param key the key to be used for encryption/decryption performed by
|
|
* the filter
|
|
* @param direction determines whether the filter will be an encrypting
|
|
* or decrypting filter
|
|
* @return pointer to the encryption or decryption filter
|
|
*/
|
|
inline Keyed_Filter* get_cipher(const std::string& algo_spec,
|
|
const SymmetricKey& key,
|
|
Cipher_Dir direction)
|
|
{
|
|
Keyed_Filter* cipher = get_cipher(algo_spec, direction);
|
|
cipher->set_key(key);
|
|
return cipher;
|
|
}
|
|
|
|
/**
|
|
* Factory method for general symmetric cipher filters.
|
|
* @param algo_spec the name of the desired cipher
|
|
* @param key the key to be used for encryption/decryption performed by
|
|
* the filter
|
|
* @param iv the initialization vector to be used
|
|
* @param direction determines whether the filter will be an encrypting
|
|
* or decrypting filter
|
|
* @return pointer to newly allocated encryption or decryption filter
|
|
*/
|
|
inline Keyed_Filter* get_cipher(const std::string& algo_spec,
|
|
const SymmetricKey& key,
|
|
const InitializationVector& iv,
|
|
Cipher_Dir direction)
|
|
{
|
|
Keyed_Filter* cipher = get_cipher(algo_spec, key, direction);
|
|
if(iv.length())
|
|
cipher->set_iv(iv);
|
|
return cipher;
|
|
}
|
|
|
|
#if defined(BOTAN_HAS_STREAM_CIPHER)
|
|
|
|
/**
|
|
* Stream Cipher Filter
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) StreamCipher_Filter final : public Keyed_Filter
|
|
{
|
|
public:
|
|
|
|
std::string name() const override { return m_cipher->name(); }
|
|
|
|
/**
|
|
* Write input data
|
|
* @param input data
|
|
* @param input_len length of input in bytes
|
|
*/
|
|
void write(const uint8_t input[], size_t input_len) override;
|
|
|
|
bool valid_iv_length(size_t iv_len) const override
|
|
{ return m_cipher->valid_iv_length(iv_len); }
|
|
|
|
/**
|
|
* Set the initialization vector for this filter.
|
|
* @param iv the initialization vector to set
|
|
*/
|
|
void set_iv(const InitializationVector& iv) override
|
|
{
|
|
m_cipher->set_iv(iv.begin(), iv.length());
|
|
}
|
|
|
|
/**
|
|
* Set the key of this filter.
|
|
* @param key the key to set
|
|
*/
|
|
void set_key(const SymmetricKey& key) override { m_cipher->set_key(key); }
|
|
|
|
Key_Length_Specification key_spec() const override { return m_cipher->key_spec(); }
|
|
|
|
/**
|
|
* Construct a stream cipher filter.
|
|
* @param cipher a cipher object to use
|
|
*/
|
|
explicit StreamCipher_Filter(StreamCipher* cipher);
|
|
|
|
/**
|
|
* Construct a stream cipher filter.
|
|
* @param cipher a cipher object to use
|
|
* @param key the key to use inside this filter
|
|
*/
|
|
StreamCipher_Filter(StreamCipher* cipher, const SymmetricKey& key);
|
|
|
|
/**
|
|
* Construct a stream cipher filter.
|
|
* @param cipher the name of the desired cipher
|
|
*/
|
|
explicit StreamCipher_Filter(const std::string& cipher);
|
|
|
|
/**
|
|
* Construct a stream cipher filter.
|
|
* @param cipher the name of the desired cipher
|
|
* @param key the key to use inside this filter
|
|
*/
|
|
StreamCipher_Filter(const std::string& cipher, const SymmetricKey& key);
|
|
private:
|
|
secure_vector<uint8_t> m_buffer;
|
|
std::unique_ptr<StreamCipher> m_cipher;
|
|
};
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_HASH)
|
|
|
|
/**
|
|
* Hash Filter.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Hash_Filter final : public Filter
|
|
{
|
|
public:
|
|
void write(const uint8_t input[], size_t len) override { m_hash->update(input, len); }
|
|
void end_msg() override;
|
|
|
|
std::string name() const override { return m_hash->name(); }
|
|
|
|
/**
|
|
* Construct a hash filter.
|
|
* @param hash the hash function to use
|
|
* @param len the output length of this filter. Leave the default
|
|
* value 0 if you want to use the full output of the hashfunction
|
|
* hash. Otherwise, specify a smaller value here so that the
|
|
* output of the hash algorithm will be cut off.
|
|
*/
|
|
Hash_Filter(HashFunction* hash, size_t len = 0) :
|
|
m_hash(hash), m_out_len(len) {}
|
|
|
|
/**
|
|
* Construct a hash filter.
|
|
* @param request the name of the hash algorithm to use
|
|
* @param len the output length of this filter. Leave the default
|
|
* value 0 if you want to use the full output of the hashfunction
|
|
* hash. Otherwise, specify a smaller value here so that the
|
|
* output of the hash algorithm will be cut off.
|
|
*/
|
|
Hash_Filter(const std::string& request, size_t len = 0);
|
|
|
|
private:
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
const size_t m_out_len;
|
|
};
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_MAC)
|
|
|
|
/**
|
|
* MessageAuthenticationCode Filter.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) MAC_Filter final : public Keyed_Filter
|
|
{
|
|
public:
|
|
void write(const uint8_t input[], size_t len) override { m_mac->update(input, len); }
|
|
void end_msg() override;
|
|
|
|
std::string name() const override { return m_mac->name(); }
|
|
|
|
/**
|
|
* Set the key of this filter.
|
|
* @param key the key to set
|
|
*/
|
|
void set_key(const SymmetricKey& key) override { m_mac->set_key(key); }
|
|
|
|
Key_Length_Specification key_spec() const override { return m_mac->key_spec(); }
|
|
|
|
/**
|
|
* Construct a MAC filter. The MAC key will be left empty.
|
|
* @param mac the MAC to use
|
|
* @param out_len the output length of this filter. Leave the default
|
|
* value 0 if you want to use the full output of the
|
|
* MAC. Otherwise, specify a smaller value here so that the
|
|
* output of the MAC will be cut off.
|
|
*/
|
|
MAC_Filter(MessageAuthenticationCode* mac,
|
|
size_t out_len = 0) :
|
|
m_mac(mac),
|
|
m_out_len(out_len)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Construct a MAC filter.
|
|
* @param mac the MAC to use
|
|
* @param key the MAC key to use
|
|
* @param out_len the output length of this filter. Leave the default
|
|
* value 0 if you want to use the full output of the
|
|
* MAC. Otherwise, specify a smaller value here so that the
|
|
* output of the MAC will be cut off.
|
|
*/
|
|
MAC_Filter(MessageAuthenticationCode* mac,
|
|
const SymmetricKey& key,
|
|
size_t out_len = 0) :
|
|
m_mac(mac),
|
|
m_out_len(out_len)
|
|
{
|
|
m_mac->set_key(key);
|
|
}
|
|
|
|
/**
|
|
* Construct a MAC filter. The MAC key will be left empty.
|
|
* @param mac the name of the MAC to use
|
|
* @param len the output length of this filter. Leave the default
|
|
* value 0 if you want to use the full output of the
|
|
* MAC. Otherwise, specify a smaller value here so that the
|
|
* output of the MAC will be cut off.
|
|
*/
|
|
MAC_Filter(const std::string& mac, size_t len = 0);
|
|
|
|
/**
|
|
* Construct a MAC filter.
|
|
* @param mac the name of the MAC to use
|
|
* @param key the MAC key to use
|
|
* @param len the output length of this filter. Leave the default
|
|
* value 0 if you want to use the full output of the
|
|
* MAC. Otherwise, specify a smaller value here so that the
|
|
* output of the MAC will be cut off.
|
|
*/
|
|
MAC_Filter(const std::string& mac, const SymmetricKey& key,
|
|
size_t len = 0);
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
const size_t m_out_len;
|
|
};
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_COMPRESSION)
|
|
|
|
class Compression_Algorithm;
|
|
class Decompression_Algorithm;
|
|
|
|
/**
|
|
* Filter interface for compression
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Compression_Filter final : public Filter
|
|
{
|
|
public:
|
|
void start_msg() override;
|
|
void write(const uint8_t input[], size_t input_length) override;
|
|
void end_msg() override;
|
|
|
|
void flush();
|
|
|
|
std::string name() const override;
|
|
|
|
Compression_Filter(const std::string& type,
|
|
size_t compression_level,
|
|
size_t buffer_size = 4096);
|
|
|
|
~Compression_Filter();
|
|
private:
|
|
std::unique_ptr<Compression_Algorithm> m_comp;
|
|
size_t m_buffersize, m_level;
|
|
secure_vector<uint8_t> m_buffer;
|
|
};
|
|
|
|
/**
|
|
* Filter interface for decompression
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Decompression_Filter final : public Filter
|
|
{
|
|
public:
|
|
void start_msg() override;
|
|
void write(const uint8_t input[], size_t input_length) override;
|
|
void end_msg() override;
|
|
|
|
std::string name() const override;
|
|
|
|
Decompression_Filter(const std::string& type,
|
|
size_t buffer_size = 4096);
|
|
|
|
~Decompression_Filter();
|
|
private:
|
|
std::unique_ptr<Decompression_Algorithm> m_comp;
|
|
std::size_t m_buffersize;
|
|
secure_vector<uint8_t> m_buffer;
|
|
};
|
|
|
|
#endif
|
|
|
|
/**
|
|
* This class represents a Base64 encoder.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Base64_Encoder final : public Filter
|
|
{
|
|
public:
|
|
std::string name() const override { return "Base64_Encoder"; }
|
|
|
|
/**
|
|
* Input a part of a message to the encoder.
|
|
* @param input the message to input as a byte array
|
|
* @param length the length of the byte array input
|
|
*/
|
|
void write(const uint8_t input[], size_t length) override;
|
|
|
|
/**
|
|
* Inform the Encoder that the current message shall be closed.
|
|
*/
|
|
void end_msg() override;
|
|
|
|
/**
|
|
* Create a base64 encoder.
|
|
* @param breaks whether to use line breaks in the output
|
|
* @param length the length of the lines of the output
|
|
* @param t_n whether to use a trailing newline
|
|
*/
|
|
Base64_Encoder(bool breaks = false, size_t length = 72,
|
|
bool t_n = false);
|
|
private:
|
|
void encode_and_send(const uint8_t input[], size_t length,
|
|
bool final_inputs = false);
|
|
void do_output(const uint8_t output[], size_t length);
|
|
|
|
const size_t m_line_length;
|
|
const bool m_trailing_newline;
|
|
std::vector<uint8_t> m_in, m_out;
|
|
size_t m_position, m_out_position;
|
|
};
|
|
|
|
/**
|
|
* This object represents a Base64 decoder.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Base64_Decoder final : public Filter
|
|
{
|
|
public:
|
|
std::string name() const override { return "Base64_Decoder"; }
|
|
|
|
/**
|
|
* Input a part of a message to the decoder.
|
|
* @param input the message to input as a byte array
|
|
* @param length the length of the byte array input
|
|
*/
|
|
void write(const uint8_t input[], size_t length) override;
|
|
|
|
/**
|
|
* Finish up the current message
|
|
*/
|
|
void end_msg() override;
|
|
|
|
/**
|
|
* Create a base64 decoder.
|
|
* @param checking the type of checking that shall be performed by
|
|
* the decoder
|
|
*/
|
|
explicit Base64_Decoder(Decoder_Checking checking = NONE);
|
|
private:
|
|
const Decoder_Checking m_checking;
|
|
std::vector<uint8_t> m_in, m_out;
|
|
size_t m_position;
|
|
};
|
|
|
|
/**
|
|
* Converts arbitrary binary data to hex strings, optionally with
|
|
* newlines inserted
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Hex_Encoder final : public Filter
|
|
{
|
|
public:
|
|
/**
|
|
* Whether to use uppercase or lowercase letters for the encoded string.
|
|
*/
|
|
enum Case { Uppercase, Lowercase };
|
|
|
|
std::string name() const override { return "Hex_Encoder"; }
|
|
|
|
void write(const uint8_t in[], size_t length) override;
|
|
void end_msg() override;
|
|
|
|
/**
|
|
* Create a hex encoder.
|
|
* @param the_case the case to use in the encoded strings.
|
|
*/
|
|
explicit Hex_Encoder(Case the_case);
|
|
|
|
/**
|
|
* Create a hex encoder.
|
|
* @param newlines should newlines be used
|
|
* @param line_length if newlines are used, how long are lines
|
|
* @param the_case the case to use in the encoded strings
|
|
*/
|
|
Hex_Encoder(bool newlines = false,
|
|
size_t line_length = 72,
|
|
Case the_case = Uppercase);
|
|
private:
|
|
void encode_and_send(const uint8_t[], size_t);
|
|
|
|
const Case m_casing;
|
|
const size_t m_line_length;
|
|
std::vector<uint8_t> m_in, m_out;
|
|
size_t m_position, m_counter;
|
|
};
|
|
|
|
/**
|
|
* Converts hex strings to bytes
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Hex_Decoder final : public Filter
|
|
{
|
|
public:
|
|
std::string name() const override { return "Hex_Decoder"; }
|
|
|
|
void write(const uint8_t[], size_t) override;
|
|
void end_msg() override;
|
|
|
|
/**
|
|
* Construct a Hex Decoder using the specified
|
|
* character checking.
|
|
* @param checking the checking to use during decoding.
|
|
*/
|
|
explicit Hex_Decoder(Decoder_Checking checking = NONE);
|
|
private:
|
|
const Decoder_Checking m_checking;
|
|
std::vector<uint8_t> m_in, m_out;
|
|
size_t m_position;
|
|
};
|
|
|
|
/**
|
|
* BitBucket is a filter which simply discards all inputs
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) BitBucket final : public Filter
|
|
{
|
|
public:
|
|
void write(const uint8_t[], size_t) override { /* discard */ }
|
|
|
|
std::string name() const override { return "BitBucket"; }
|
|
};
|
|
|
|
/**
|
|
* This class represents Filter chains. A Filter chain is an ordered
|
|
* concatenation of Filters, the input to a Chain sequentially passes
|
|
* through all the Filters contained in the Chain.
|
|
*/
|
|
|
|
class BOTAN_PUBLIC_API(2,0) Chain final : public Fanout_Filter
|
|
{
|
|
public:
|
|
void write(const uint8_t input[], size_t length) override { send(input, length); }
|
|
|
|
std::string name() const override { return "Chain"; }
|
|
|
|
/**
|
|
* Construct a chain of up to four filters. The filters are set
|
|
* up in the same order as the arguments.
|
|
*/
|
|
Chain(Filter* = nullptr, Filter* = nullptr,
|
|
Filter* = nullptr, Filter* = nullptr);
|
|
|
|
/**
|
|
* Construct a chain from range of filters
|
|
* @param filter_arr the list of filters
|
|
* @param length how many filters
|
|
*/
|
|
Chain(Filter* filter_arr[], size_t length);
|
|
};
|
|
|
|
/**
|
|
* This class represents a fork filter, whose purpose is to fork the
|
|
* flow of data. It causes an input message to result in n messages at
|
|
* the end of the filter, where n is the number of forks.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Fork : public Fanout_Filter
|
|
{
|
|
public:
|
|
void write(const uint8_t input[], size_t length) override { send(input, length); }
|
|
void set_port(size_t n) { Fanout_Filter::set_port(n); }
|
|
|
|
std::string name() const override { return "Fork"; }
|
|
|
|
/**
|
|
* Construct a Fork filter with up to four forks.
|
|
*/
|
|
Fork(Filter*, Filter*, Filter* = nullptr, Filter* = nullptr);
|
|
|
|
/**
|
|
* Construct a Fork from range of filters
|
|
* @param filter_arr the list of filters
|
|
* @param length how many filters
|
|
*/
|
|
Fork(Filter* filter_arr[], size_t length);
|
|
};
|
|
|
|
#if defined(BOTAN_HAS_THREAD_UTILS)
|
|
|
|
/**
|
|
* This class is a threaded version of the Fork filter. While this uses
|
|
* threads, the class itself is NOT thread-safe. This is meant as a drop-
|
|
* in replacement for Fork where performance gains are possible.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Threaded_Fork final : public Fork
|
|
{
|
|
public:
|
|
std::string name() const override;
|
|
|
|
/**
|
|
* Construct a Threaded_Fork filter with up to four forks.
|
|
*/
|
|
Threaded_Fork(Filter*, Filter*, Filter* = nullptr, Filter* = nullptr);
|
|
|
|
/**
|
|
* Construct a Threaded_Fork from range of filters
|
|
* @param filter_arr the list of filters
|
|
* @param length how many filters
|
|
*/
|
|
Threaded_Fork(Filter* filter_arr[], size_t length);
|
|
|
|
~Threaded_Fork();
|
|
|
|
private:
|
|
void set_next(Filter* f[], size_t n);
|
|
void send(const uint8_t in[], size_t length) override;
|
|
void thread_delegate_work(const uint8_t input[], size_t length);
|
|
void thread_entry(Filter* filter);
|
|
|
|
std::vector<std::shared_ptr<std::thread>> m_threads;
|
|
std::unique_ptr<struct Threaded_Fork_Data> m_thread_data;
|
|
};
|
|
#endif
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Modular_Reducer;
|
|
class MessageAuthenticationCode;
|
|
|
|
/**
|
|
* Format Preserving Encryption using the scheme FE1 from the paper
|
|
* "Format-Preserving Encryption" by Bellare, Rogaway, et al
|
|
* (https://eprint.iacr.org/2009/251)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,5) FPE_FE1 final : public SymmetricAlgorithm
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* @param n the modulus. All plaintext and ciphertext values must be
|
|
* less than this.
|
|
* @param rounds the number of rounds to use. Must be at least 3.
|
|
* @param compat_mode An error in versions before 2.5.0 chose incorrect
|
|
* values for a and b. Set compat_mode to true to select this version.
|
|
* @param mac_algo the PRF to use as the encryption function
|
|
*/
|
|
FPE_FE1(const BigInt& n,
|
|
size_t rounds = 5,
|
|
bool compat_mode = false,
|
|
const std::string& mac_algo = "HMAC(SHA-256)");
|
|
|
|
~FPE_FE1();
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
std::string name() const override;
|
|
|
|
void clear() override;
|
|
|
|
/**
|
|
* Encrypt X from and onto the group Z_n using key and tweak
|
|
* @param x the plaintext to encrypt <= n
|
|
* @param tweak will modify the ciphertext
|
|
* @param tweak_len length of tweak
|
|
*/
|
|
BigInt encrypt(const BigInt& x, const uint8_t tweak[], size_t tweak_len) const;
|
|
|
|
/**
|
|
* Decrypt X from and onto the group Z_n using key and tweak
|
|
* @param x the ciphertext to encrypt <= n
|
|
* @param tweak must match the value used to encrypt
|
|
* @param tweak_len length of tweak
|
|
*/
|
|
BigInt decrypt(const BigInt& x, const uint8_t tweak[], size_t tweak_len) const;
|
|
|
|
BigInt encrypt(const BigInt& x, uint64_t tweak) const;
|
|
|
|
BigInt decrypt(const BigInt& x, uint64_t tweak) const;
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
BigInt F(const BigInt& R, size_t round,
|
|
const secure_vector<uint8_t>& tweak,
|
|
secure_vector<uint8_t>& tmp) const;
|
|
|
|
secure_vector<uint8_t> compute_tweak_mac(const uint8_t tweak[], size_t tweak_len) const;
|
|
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
std::unique_ptr<Modular_Reducer> mod_a;
|
|
std::vector<uint8_t> m_n_bytes;
|
|
BigInt m_a;
|
|
BigInt m_b;
|
|
size_t m_rounds;
|
|
};
|
|
|
|
namespace FPE {
|
|
|
|
/**
|
|
* Format Preserving Encryption using the scheme FE1 from the paper
|
|
* "Format-Preserving Encryption" by Bellare, Rogaway, et al
|
|
* (https://eprint.iacr.org/2009/251)
|
|
*
|
|
* Encrypt X from and onto the group Z_n using key and tweak
|
|
* @param n the modulus
|
|
* @param X the plaintext as a BigInt
|
|
* @param key a random key
|
|
* @param tweak will modify the ciphertext (think of as an IV)
|
|
*
|
|
* @warning This function is hardcoded to use only 3 rounds which
|
|
* may be insecure for some values of n. Prefer FPE_FE1 class
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) fe1_encrypt(const BigInt& n, const BigInt& X,
|
|
const SymmetricKey& key,
|
|
const std::vector<uint8_t>& tweak);
|
|
|
|
/**
|
|
* Decrypt X from and onto the group Z_n using key and tweak
|
|
* @param n the modulus
|
|
* @param X the ciphertext as a BigInt
|
|
* @param key is the key used for encryption
|
|
* @param tweak the same tweak used for encryption
|
|
*
|
|
* @warning This function is hardcoded to use only 3 rounds which
|
|
* may be insecure for some values of n. Prefer FPE_FE1 class
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) fe1_decrypt(const BigInt& n, const BigInt& X,
|
|
const SymmetricKey& key,
|
|
const std::vector<uint8_t>& tweak);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(gcm.h)
|
|
|
|
namespace Botan {
|
|
|
|
class BlockCipher;
|
|
class StreamCipher;
|
|
class GHASH;
|
|
|
|
/**
|
|
* GCM Mode
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GCM_Mode : public AEAD_Mode
|
|
{
|
|
public:
|
|
void set_associated_data(const uint8_t ad[], size_t ad_len) override;
|
|
|
|
std::string name() const override;
|
|
|
|
size_t update_granularity() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
bool valid_nonce_length(size_t len) const override;
|
|
|
|
size_t tag_size() const override { return m_tag_size; }
|
|
|
|
void clear() override;
|
|
|
|
void reset() override;
|
|
|
|
std::string provider() const override;
|
|
protected:
|
|
GCM_Mode(BlockCipher* cipher, size_t tag_size);
|
|
|
|
~GCM_Mode();
|
|
|
|
static const size_t GCM_BS = 16;
|
|
|
|
const size_t m_tag_size;
|
|
const std::string m_cipher_name;
|
|
|
|
std::unique_ptr<StreamCipher> m_ctr;
|
|
std::unique_ptr<GHASH> m_ghash;
|
|
private:
|
|
void start_msg(const uint8_t nonce[], size_t nonce_len) override;
|
|
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
secure_vector<uint8_t> m_y0;
|
|
};
|
|
|
|
/**
|
|
* GCM Encryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GCM_Encryption final : public GCM_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher the 128 bit block cipher to use
|
|
* @param tag_size is how big the auth tag will be
|
|
*/
|
|
GCM_Encryption(BlockCipher* cipher, size_t tag_size = 16) :
|
|
GCM_Mode(cipher, tag_size) {}
|
|
|
|
size_t output_length(size_t input_length) const override
|
|
{ return input_length + tag_size(); }
|
|
|
|
size_t minimum_final_size() const override { return 0; }
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
};
|
|
|
|
/**
|
|
* GCM Decryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GCM_Decryption final : public GCM_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher the 128 bit block cipher to use
|
|
* @param tag_size is how big the auth tag will be
|
|
*/
|
|
GCM_Decryption(BlockCipher* cipher, size_t tag_size = 16) :
|
|
GCM_Mode(cipher, tag_size) {}
|
|
|
|
size_t output_length(size_t input_length) const override
|
|
{
|
|
BOTAN_ASSERT(input_length >= tag_size(), "Sufficient input");
|
|
return input_length - tag_size();
|
|
}
|
|
|
|
size_t minimum_final_size() const override { return tag_size(); }
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(gf2m_small_m.h)
|
|
|
|
namespace Botan {
|
|
|
|
typedef uint16_t gf2m;
|
|
|
|
/**
|
|
* GF(2^m) field for m = [2...16]
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GF2m_Field
|
|
{
|
|
public:
|
|
explicit GF2m_Field(size_t extdeg);
|
|
|
|
gf2m gf_mul(gf2m x, gf2m y) const
|
|
{
|
|
return ((x) ? gf_mul_fast(x, y) : 0);
|
|
}
|
|
|
|
gf2m gf_square(gf2m x) const
|
|
{
|
|
return ((x) ? gf_exp(_gf_modq_1(gf_log(x) << 1)) : 0);
|
|
}
|
|
|
|
gf2m square_rr(gf2m x) const
|
|
{
|
|
return _gf_modq_1(x << 1);
|
|
}
|
|
|
|
gf2m gf_mul_fast(gf2m x, gf2m y) const
|
|
{
|
|
return ((y) ? gf_exp(_gf_modq_1(gf_log(x) + gf_log(y))) : 0);
|
|
}
|
|
|
|
/*
|
|
naming convention of GF(2^m) field operations:
|
|
l logarithmic, unreduced
|
|
r logarithmic, reduced
|
|
n normal, non-zero
|
|
z normal, might be zero
|
|
*/
|
|
|
|
gf2m gf_mul_lll(gf2m a, gf2m b) const
|
|
{
|
|
return (a + b);
|
|
}
|
|
|
|
gf2m gf_mul_rrr(gf2m a, gf2m b) const
|
|
{
|
|
return (_gf_modq_1(gf_mul_lll(a, b)));
|
|
}
|
|
|
|
gf2m gf_mul_nrr(gf2m a, gf2m b) const
|
|
{
|
|
return (gf_exp(gf_mul_rrr(a, b)));
|
|
}
|
|
|
|
gf2m gf_mul_rrn(gf2m a, gf2m y) const
|
|
{
|
|
return _gf_modq_1(gf_mul_lll(a, gf_log(y)));
|
|
}
|
|
|
|
gf2m gf_mul_rnr(gf2m y, gf2m a) const
|
|
{
|
|
return gf_mul_rrn(a, y);
|
|
}
|
|
|
|
gf2m gf_mul_lnn(gf2m x, gf2m y) const
|
|
{
|
|
return (gf_log(x) + gf_log(y));
|
|
}
|
|
|
|
gf2m gf_mul_rnn(gf2m x, gf2m y) const
|
|
{
|
|
return _gf_modq_1(gf_mul_lnn(x, y));
|
|
}
|
|
|
|
gf2m gf_mul_nrn(gf2m a, gf2m y) const
|
|
{
|
|
return gf_exp(_gf_modq_1((a) + gf_log(y)));
|
|
}
|
|
|
|
/**
|
|
* zero operand allowed
|
|
*/
|
|
gf2m gf_mul_zrz(gf2m a, gf2m y) const
|
|
{
|
|
return ( (y == 0) ? 0 : gf_mul_nrn(a, y) );
|
|
}
|
|
|
|
gf2m gf_mul_zzr(gf2m a, gf2m y) const
|
|
{
|
|
return gf_mul_zrz(y, a);
|
|
}
|
|
|
|
/**
|
|
* non-zero operand
|
|
*/
|
|
gf2m gf_mul_nnr(gf2m y, gf2m a) const
|
|
{
|
|
return gf_mul_nrn(a, y);
|
|
}
|
|
|
|
gf2m gf_sqrt(gf2m x) const
|
|
{
|
|
return ((x) ? gf_exp(_gf_modq_1(gf_log(x) << (get_extension_degree()-1))) : 0);
|
|
}
|
|
|
|
gf2m gf_div_rnn(gf2m x, gf2m y) const
|
|
{
|
|
return _gf_modq_1(gf_log(x) - gf_log(y));
|
|
}
|
|
|
|
gf2m gf_div_rnr(gf2m x, gf2m b) const
|
|
{
|
|
return _gf_modq_1(gf_log(x) - b);
|
|
}
|
|
|
|
gf2m gf_div_nrr(gf2m a, gf2m b) const
|
|
{
|
|
return gf_exp(_gf_modq_1(a - b));
|
|
}
|
|
|
|
gf2m gf_div_zzr(gf2m x, gf2m b) const
|
|
{
|
|
return ((x) ? gf_exp(_gf_modq_1(gf_log(x) - b)) : 0);
|
|
}
|
|
|
|
gf2m gf_inv(gf2m x) const
|
|
{
|
|
return gf_exp(gf_ord() - gf_log(x));
|
|
}
|
|
|
|
gf2m gf_inv_rn(gf2m x) const
|
|
{
|
|
return (gf_ord() - gf_log(x));
|
|
}
|
|
|
|
gf2m gf_square_ln(gf2m x) const
|
|
{
|
|
return gf_log(x) << 1;
|
|
}
|
|
|
|
gf2m gf_square_rr(gf2m a) const
|
|
{
|
|
return a << 1;
|
|
}
|
|
|
|
gf2m gf_l_from_n(gf2m x) const
|
|
{
|
|
return gf_log(x);
|
|
}
|
|
|
|
gf2m gf_div(gf2m x, gf2m y) const;
|
|
|
|
gf2m gf_exp(gf2m i) const
|
|
{
|
|
return m_gf_exp_table.at(i); /* alpha^i */
|
|
}
|
|
|
|
gf2m gf_log(gf2m i) const
|
|
{
|
|
return m_gf_log_table.at(i); /* return i when x=alpha^i */
|
|
}
|
|
|
|
gf2m gf_ord() const
|
|
{
|
|
return m_gf_multiplicative_order;
|
|
}
|
|
|
|
size_t get_extension_degree() const
|
|
{
|
|
return m_gf_extension_degree;
|
|
}
|
|
|
|
gf2m get_cardinality() const
|
|
{
|
|
return static_cast<gf2m>(1 << get_extension_degree());
|
|
}
|
|
|
|
private:
|
|
gf2m _gf_modq_1(int32_t d) const
|
|
{
|
|
/* residual modulo q-1
|
|
when -q < d < 0, we get (q-1+d)
|
|
when 0 <= d < q, we get (d)
|
|
when q <= d < 2q-1, we get (d-q+1)
|
|
*/
|
|
return static_cast<gf2m>(((d) & gf_ord()) + ((d) >> get_extension_degree()));
|
|
}
|
|
|
|
const size_t m_gf_extension_degree;
|
|
const gf2m m_gf_multiplicative_order;
|
|
const std::vector<gf2m>& m_gf_log_table;
|
|
const std::vector<gf2m>& m_gf_exp_table;
|
|
};
|
|
|
|
uint32_t encode_gf2m(gf2m to_enc, uint8_t* mem);
|
|
|
|
gf2m decode_gf2m(const uint8_t* mem);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(ghash.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* GCM's GHASH
|
|
* This is not intended for general use, but is exposed to allow
|
|
* shared code between GCM and GMAC
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GHASH final : public SymmetricAlgorithm
|
|
{
|
|
public:
|
|
void set_associated_data(const uint8_t ad[], size_t ad_len);
|
|
|
|
secure_vector<uint8_t> BOTAN_DEPRECATED("Use other impl")
|
|
nonce_hash(const uint8_t nonce[], size_t nonce_len)
|
|
{
|
|
secure_vector<uint8_t> y0(GCM_BS);
|
|
nonce_hash(y0, nonce, nonce_len);
|
|
return y0;
|
|
}
|
|
|
|
void nonce_hash(secure_vector<uint8_t>& y0, const uint8_t nonce[], size_t len);
|
|
|
|
void start(const uint8_t nonce[], size_t len);
|
|
|
|
/*
|
|
* Assumes input len is multiple of 16
|
|
*/
|
|
void update(const uint8_t in[], size_t len);
|
|
|
|
/*
|
|
* Incremental update of associated data
|
|
*/
|
|
void update_associated_data(const uint8_t ad[], size_t len);
|
|
|
|
secure_vector<uint8_t> BOTAN_DEPRECATED("Use version taking output params") final()
|
|
{
|
|
secure_vector<uint8_t> mac(GCM_BS);
|
|
final(mac.data(), mac.size());
|
|
return mac;
|
|
}
|
|
|
|
void final(uint8_t out[], size_t out_len);
|
|
|
|
Key_Length_Specification key_spec() const override
|
|
{ return Key_Length_Specification(16); }
|
|
|
|
void clear() override;
|
|
|
|
void reset();
|
|
|
|
std::string name() const override { return "GHASH"; }
|
|
|
|
std::string provider() const;
|
|
|
|
void ghash_update(secure_vector<uint8_t>& x,
|
|
const uint8_t input[], size_t input_len);
|
|
|
|
void add_final_block(secure_vector<uint8_t>& x,
|
|
size_t ad_len, size_t pt_len);
|
|
private:
|
|
|
|
#if defined(BOTAN_HAS_GHASH_CLMUL_CPU)
|
|
static void ghash_precompute_cpu(const uint8_t H[16], uint64_t H_pow[4*2]);
|
|
|
|
static void ghash_multiply_cpu(uint8_t x[16],
|
|
const uint64_t H_pow[4*2],
|
|
const uint8_t input[], size_t blocks);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_GHASH_CLMUL_VPERM)
|
|
static void ghash_multiply_vperm(uint8_t x[16],
|
|
const uint64_t HM[256],
|
|
const uint8_t input[], size_t blocks);
|
|
#endif
|
|
|
|
void key_schedule(const uint8_t key[], size_t key_len) override;
|
|
|
|
void ghash_multiply(secure_vector<uint8_t>& x,
|
|
const uint8_t input[],
|
|
size_t blocks);
|
|
|
|
static const size_t GCM_BS = 16;
|
|
|
|
secure_vector<uint8_t> m_H;
|
|
secure_vector<uint8_t> m_H_ad;
|
|
secure_vector<uint8_t> m_ghash;
|
|
secure_vector<uint8_t> m_nonce;
|
|
secure_vector<uint64_t> m_HM;
|
|
secure_vector<uint64_t> m_H_pow;
|
|
size_t m_ad_len = 0;
|
|
size_t m_text_len = 0;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(gmac.h)
|
|
|
|
namespace Botan {
|
|
|
|
class BlockCipher;
|
|
class GHASH;
|
|
|
|
/**
|
|
* GMAC
|
|
*
|
|
* GMAC requires a unique initialization vector be used for each message.
|
|
* This must be provided via the MessageAuthenticationCode::start() API
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GMAC final : public MessageAuthenticationCode
|
|
{
|
|
public:
|
|
void clear() override;
|
|
std::string name() const override;
|
|
size_t output_length() const override;
|
|
MessageAuthenticationCode* clone() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
/**
|
|
* Creates a new GMAC instance.
|
|
*
|
|
* @param cipher the underlying block cipher to use
|
|
*/
|
|
explicit GMAC(BlockCipher* cipher);
|
|
|
|
GMAC(const GMAC&) = delete;
|
|
GMAC& operator=(const GMAC&) = delete;
|
|
|
|
~GMAC();
|
|
|
|
private:
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
void start_msg(const uint8_t nonce[], size_t nonce_len) override;
|
|
void key_schedule(const uint8_t key[], size_t size) override;
|
|
|
|
static const size_t GCM_BS = 16;
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
std::unique_ptr<GHASH> m_ghash;
|
|
secure_vector<uint8_t> m_aad_buf;
|
|
size_t m_aad_buf_pos;
|
|
bool m_initialized;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(gost_28147.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* The GOST 28147-89 block cipher uses a set of 4 bit Sboxes, however
|
|
* the standard does not actually define these Sboxes; they are
|
|
* considered a local configuration issue. Several different sets are
|
|
* used.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GOST_28147_89_Params final
|
|
{
|
|
public:
|
|
/**
|
|
* @param row the row
|
|
* @param col the column
|
|
* @return sbox entry at this row/column
|
|
*/
|
|
uint8_t sbox_entry(size_t row, size_t col) const;
|
|
|
|
/**
|
|
* @return name of this parameter set
|
|
*/
|
|
std::string param_name() const { return m_name; }
|
|
|
|
/**
|
|
* Return a representation used for building larger tables
|
|
* For internal use
|
|
*/
|
|
uint8_t sbox_pair(size_t row, size_t col) const;
|
|
|
|
/**
|
|
* Default GOST parameters are the ones given in GOST R 34.11 for
|
|
* testing purposes; these sboxes are also used by Crypto++, and,
|
|
* at least according to Wikipedia, the Central Bank of Russian
|
|
* Federation
|
|
* @param name of the parameter set
|
|
*/
|
|
explicit GOST_28147_89_Params(const std::string& name = "R3411_94_TestParam");
|
|
private:
|
|
const uint8_t* m_sboxes;
|
|
std::string m_name;
|
|
};
|
|
|
|
/**
|
|
* GOST 28147-89
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GOST_28147_89 final : public Block_Cipher_Fixed_Params<8, 32>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
|
|
std::string name() const override;
|
|
BlockCipher* clone() const override { return new GOST_28147_89(m_SBOX); }
|
|
|
|
/**
|
|
* @param params the sbox parameters to use
|
|
*/
|
|
explicit GOST_28147_89(const GOST_28147_89_Params& params);
|
|
|
|
explicit GOST_28147_89(const std::string& param_name) :
|
|
GOST_28147_89(GOST_28147_89_Params(param_name)) {}
|
|
private:
|
|
explicit GOST_28147_89(const std::vector<uint32_t>& other_SBOX) :
|
|
m_SBOX(other_SBOX), m_EK(8) {}
|
|
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
/*
|
|
* The sbox is not secret, this is just a larger expansion of it
|
|
* which we generate at runtime for faster execution
|
|
*/
|
|
std::vector<uint32_t> m_SBOX;
|
|
|
|
secure_vector<uint32_t> m_EK;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* GOST-34.10 Public Key
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GOST_3410_PublicKey : public virtual EC_PublicKey
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Construct a public key from a given public point.
|
|
* @param dom_par the domain parameters associated with this key
|
|
* @param public_point the public point defining this key
|
|
*/
|
|
GOST_3410_PublicKey(const EC_Group& dom_par,
|
|
const PointGFp& public_point) :
|
|
EC_PublicKey(dom_par, public_point) {}
|
|
|
|
/**
|
|
* Load a public key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Get this keys algorithm name.
|
|
* @result this keys algorithm name
|
|
*/
|
|
std::string algo_name() const override;
|
|
|
|
AlgorithmIdentifier algorithm_identifier() const override;
|
|
|
|
std::vector<uint8_t> public_key_bits() const override;
|
|
|
|
size_t message_parts() const override { return 2; }
|
|
|
|
size_t message_part_size() const override
|
|
{ return domain().get_order().bytes(); }
|
|
|
|
Signature_Format default_x509_signature_format() const override
|
|
{ return IEEE_1363; }
|
|
|
|
std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
protected:
|
|
GOST_3410_PublicKey() = default;
|
|
};
|
|
|
|
/**
|
|
* GOST-34.10 Private Key
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GOST_3410_PrivateKey final :
|
|
public GOST_3410_PublicKey, public EC_PrivateKey
|
|
{
|
|
public:
|
|
/**
|
|
* Load a private key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits ECPrivateKey bits
|
|
*/
|
|
GOST_3410_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits) :
|
|
EC_PrivateKey(alg_id, key_bits) {}
|
|
|
|
/**
|
|
* Generate a new private key
|
|
* @param rng a random number generator
|
|
* @param domain parameters to used for this key
|
|
* @param x the private key; if zero, a new random key is generated
|
|
*/
|
|
GOST_3410_PrivateKey(RandomNumberGenerator& rng,
|
|
const EC_Group& domain,
|
|
const BigInt& x = 0);
|
|
|
|
AlgorithmIdentifier pkcs8_algorithm_identifier() const override
|
|
{ return EC_PublicKey::algorithm_identifier(); }
|
|
|
|
std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(gost_3411.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* GOST 34.11
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) GOST_34_11 final : public HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "GOST-R-34.11-94" ; }
|
|
size_t output_length() const override { return 32; }
|
|
size_t hash_block_size() const override { return 32; }
|
|
HashFunction* clone() const override { return new GOST_34_11; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override;
|
|
|
|
GOST_34_11();
|
|
private:
|
|
void compress_n(const uint8_t input[], size_t blocks);
|
|
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
|
|
GOST_28147_89 m_cipher;
|
|
secure_vector<uint8_t> m_buffer, m_sum, m_hash;
|
|
size_t m_position;
|
|
uint64_t m_count;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Return the PKCS #1 hash identifier
|
|
* @see RFC 3447 section 9.2
|
|
* @param hash_name the name of the hash function
|
|
* @return uint8_t sequence identifying the hash
|
|
* @throw Invalid_Argument if the hash has no known PKCS #1 hash id
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::vector<uint8_t> pkcs_hash_id(const std::string& hash_name);
|
|
|
|
/**
|
|
* Return the IEEE 1363 hash identifier
|
|
* @param hash_name the name of the hash function
|
|
* @return uint8_t code identifying the hash, or 0 if not known
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint8_t ieee1363_hash_id(const std::string& hash_name);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Perform hex encoding
|
|
* @param output an array of at least input_length*2 bytes
|
|
* @param input is some binary data
|
|
* @param input_length length of input in bytes
|
|
* @param uppercase should output be upper or lower case?
|
|
*/
|
|
void BOTAN_PUBLIC_API(2,0) hex_encode(char output[],
|
|
const uint8_t input[],
|
|
size_t input_length,
|
|
bool uppercase = true);
|
|
|
|
/**
|
|
* Perform hex encoding
|
|
* @param input some input
|
|
* @param input_length length of input in bytes
|
|
* @param uppercase should output be upper or lower case?
|
|
* @return hexadecimal representation of input
|
|
*/
|
|
std::string BOTAN_PUBLIC_API(2,0) hex_encode(const uint8_t input[],
|
|
size_t input_length,
|
|
bool uppercase = true);
|
|
|
|
/**
|
|
* Perform hex encoding
|
|
* @param input some input
|
|
* @param uppercase should output be upper or lower case?
|
|
* @return hexadecimal representation of input
|
|
*/
|
|
template<typename Alloc>
|
|
std::string hex_encode(const std::vector<uint8_t, Alloc>& input,
|
|
bool uppercase = true)
|
|
{
|
|
return hex_encode(input.data(), input.size(), uppercase);
|
|
}
|
|
|
|
/**
|
|
* Perform hex decoding
|
|
* @param output an array of at least input_length/2 bytes
|
|
* @param input some hex input
|
|
* @param input_length length of input in bytes
|
|
* @param input_consumed is an output parameter which says how many
|
|
* bytes of input were actually consumed. If less than
|
|
* input_length, then the range input[consumed:length]
|
|
* should be passed in later along with more input.
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return number of bytes written to output
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,0) hex_decode(uint8_t output[],
|
|
const char input[],
|
|
size_t input_length,
|
|
size_t& input_consumed,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform hex decoding
|
|
* @param output an array of at least input_length/2 bytes
|
|
* @param input some hex input
|
|
* @param input_length length of input in bytes
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return number of bytes written to output
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,0) hex_decode(uint8_t output[],
|
|
const char input[],
|
|
size_t input_length,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform hex decoding
|
|
* @param output an array of at least input_length/2 bytes
|
|
* @param input some hex input
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return number of bytes written to output
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,0) hex_decode(uint8_t output[],
|
|
const std::string& input,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform hex decoding
|
|
* @param input some hex input
|
|
* @param input_length the length of input in bytes
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return decoded hex output
|
|
*/
|
|
std::vector<uint8_t> BOTAN_PUBLIC_API(2,0)
|
|
hex_decode(const char input[],
|
|
size_t input_length,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform hex decoding
|
|
* @param input some hex input
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return decoded hex output
|
|
*/
|
|
std::vector<uint8_t> BOTAN_PUBLIC_API(2,0)
|
|
hex_decode(const std::string& input,
|
|
bool ignore_ws = true);
|
|
|
|
|
|
/**
|
|
* Perform hex decoding
|
|
* @param input some hex input
|
|
* @param input_length the length of input in bytes
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return decoded hex output
|
|
*/
|
|
secure_vector<uint8_t> BOTAN_PUBLIC_API(2,0)
|
|
hex_decode_locked(const char input[],
|
|
size_t input_length,
|
|
bool ignore_ws = true);
|
|
|
|
/**
|
|
* Perform hex decoding
|
|
* @param input some hex input
|
|
* @param ignore_ws ignore whitespace on input; if false, throw an
|
|
exception if whitespace is encountered
|
|
* @return decoded hex output
|
|
*/
|
|
secure_vector<uint8_t> BOTAN_PUBLIC_API(2,0)
|
|
hex_decode_locked(const std::string& input,
|
|
bool ignore_ws = true);
|
|
|
|
}
|
|
|
|
/*
|
|
* The definitions of HKDF, HKDF_Extract, HKDF_Expand will be made internal
|
|
* in the future. However the function hkdf_expand_label will still be defined.
|
|
*/
|
|
//BOTAN_FUTURE_INTERNAL_HEADER(hkdf.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* HKDF from RFC 5869.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) HKDF final : public KDF
|
|
{
|
|
public:
|
|
/**
|
|
* @param prf MAC algorithm to use
|
|
*/
|
|
explicit HKDF(MessageAuthenticationCode* prf) : m_prf(prf) {}
|
|
|
|
KDF* clone() const override { return new HKDF(m_prf->clone()); }
|
|
|
|
std::string name() const override { return "HKDF(" + m_prf->name() + ")"; }
|
|
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_prf;
|
|
};
|
|
|
|
/**
|
|
* HKDF Extraction Step from RFC 5869.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) HKDF_Extract final : public KDF
|
|
{
|
|
public:
|
|
/**
|
|
* @param prf MAC algorithm to use
|
|
*/
|
|
explicit HKDF_Extract(MessageAuthenticationCode* prf) : m_prf(prf) {}
|
|
|
|
KDF* clone() const override { return new HKDF_Extract(m_prf->clone()); }
|
|
|
|
std::string name() const override { return "HKDF-Extract(" + m_prf->name() + ")"; }
|
|
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_prf;
|
|
};
|
|
|
|
/**
|
|
* HKDF Expansion Step from RFC 5869.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) HKDF_Expand final : public KDF
|
|
{
|
|
public:
|
|
/**
|
|
* @param prf MAC algorithm to use
|
|
*/
|
|
explicit HKDF_Expand(MessageAuthenticationCode* prf) : m_prf(prf) {}
|
|
|
|
KDF* clone() const override { return new HKDF_Expand(m_prf->clone()); }
|
|
|
|
std::string name() const override { return "HKDF-Expand(" + m_prf->name() + ")"; }
|
|
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_prf;
|
|
};
|
|
|
|
/**
|
|
* HKDF-Expand-Label from TLS 1.3/QUIC
|
|
* @param hash_fn the hash to use
|
|
* @param secret the secret bits
|
|
* @param secret_len the length of secret
|
|
* @param label the full label (no "TLS 1.3, " or "tls13 " prefix
|
|
* is applied)
|
|
* @param hash_val the previous hash value (used for chaining, may be empty)
|
|
* @param hash_val_len the length of hash_val
|
|
* @param length the desired output length
|
|
*/
|
|
secure_vector<uint8_t>
|
|
BOTAN_PUBLIC_API(2,3) hkdf_expand_label(
|
|
const std::string& hash_fn,
|
|
const uint8_t secret[], size_t secret_len,
|
|
const std::string& label,
|
|
const uint8_t hash_val[], size_t hash_val_len,
|
|
size_t length);
|
|
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(hmac.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* HMAC
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) HMAC final : public MessageAuthenticationCode
|
|
{
|
|
public:
|
|
void clear() override;
|
|
std::string name() const override;
|
|
MessageAuthenticationCode* clone() const override;
|
|
|
|
size_t output_length() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
/**
|
|
* @param hash the hash to use for HMACing
|
|
*/
|
|
explicit HMAC(HashFunction* hash);
|
|
|
|
HMAC(const HMAC&) = delete;
|
|
HMAC& operator=(const HMAC&) = delete;
|
|
private:
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
secure_vector<uint8_t> m_ikey, m_okey;
|
|
size_t m_hash_output_length;
|
|
size_t m_hash_block_size;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Entropy_Sources;
|
|
|
|
/**
|
|
* HMAC_DRBG from NIST SP800-90A
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) HMAC_DRBG final : public Stateful_RNG
|
|
{
|
|
public:
|
|
/**
|
|
* Initialize an HMAC_DRBG instance with the given MAC as PRF (normally HMAC)
|
|
*
|
|
* Automatic reseeding is disabled completely, as it has no access to
|
|
* any source for seed material.
|
|
*
|
|
* If a fork is detected, the RNG will be unable to reseed itself
|
|
* in response. In this case, an exception will be thrown rather
|
|
* than generating duplicated output.
|
|
*/
|
|
explicit HMAC_DRBG(std::unique_ptr<MessageAuthenticationCode> prf);
|
|
|
|
/**
|
|
* Constructor taking a string for the hash
|
|
*/
|
|
explicit HMAC_DRBG(const std::string& hmac_hash);
|
|
|
|
/**
|
|
* Initialize an HMAC_DRBG instance with the given MAC as PRF (normally HMAC)
|
|
*
|
|
* Automatic reseeding from @p underlying_rng will take place after
|
|
* @p reseed_interval many requests or after a fork was detected.
|
|
*
|
|
* @param prf MAC to use as a PRF
|
|
* @param underlying_rng is a reference to some RNG which will be used
|
|
* to perform the periodic reseeding
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed (max. 2^24)
|
|
* @param max_number_of_bytes_per_request requests that are in size higher
|
|
* than max_number_of_bytes_per_request are treated as if multiple single
|
|
* requests of max_number_of_bytes_per_request size had been made.
|
|
* In theory SP 800-90A requires that we reject any request for a DRBG
|
|
* output longer than max_number_of_bytes_per_request. To avoid inconveniencing
|
|
* the caller who wants an output larger than max_number_of_bytes_per_request,
|
|
* instead treat these requests as if multiple requests of
|
|
* max_number_of_bytes_per_request size had been made. NIST requires for
|
|
* HMAC_DRBG that every implementation set a value no more than 2**19 bits
|
|
* (or 64 KiB). Together with @p reseed_interval = 1 you can enforce that for
|
|
* example every 512 bit automatic reseeding occurs.
|
|
*/
|
|
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);
|
|
|
|
/**
|
|
* Initialize an HMAC_DRBG instance with the given MAC as PRF (normally HMAC)
|
|
*
|
|
* Automatic reseeding from @p entropy_sources will take place after
|
|
* @p reseed_interval many requests or after a fork was detected.
|
|
*
|
|
* @param prf MAC to use as a PRF
|
|
* @param entropy_sources will be polled to perform reseeding periodically
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed (max. 2^24)
|
|
* @param max_number_of_bytes_per_request requests that are in size higher
|
|
* than max_number_of_bytes_per_request are treated as if multiple single
|
|
* requests of max_number_of_bytes_per_request size had been made.
|
|
* In theory SP 800-90A requires that we reject any request for a DRBG
|
|
* output longer than max_number_of_bytes_per_request. To avoid inconveniencing
|
|
* the caller who wants an output larger than max_number_of_bytes_per_request,
|
|
* instead treat these requests as if multiple requests of
|
|
* max_number_of_bytes_per_request size had been made. NIST requires for
|
|
* HMAC_DRBG that every implementation set a value no more than 2**19 bits
|
|
* (or 64 KiB). Together with @p reseed_interval = 1 you can enforce that for
|
|
* example every 512 bit automatic reseeding occurs.
|
|
*/
|
|
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);
|
|
|
|
/**
|
|
* Initialize an HMAC_DRBG instance with the given MAC as PRF (normally HMAC)
|
|
*
|
|
* Automatic reseeding from @p underlying_rng and @p entropy_sources
|
|
* will take place after @p reseed_interval many requests or after
|
|
* a fork was detected.
|
|
*
|
|
* @param prf MAC to use as a PRF
|
|
* @param underlying_rng is a reference to some RNG which will be used
|
|
* to perform the periodic reseeding
|
|
* @param entropy_sources will be polled to perform reseeding periodically
|
|
* @param reseed_interval specifies a limit of how many times
|
|
* the RNG will be called before automatic reseeding is performed (max. 2^24)
|
|
* @param max_number_of_bytes_per_request requests that are in size higher
|
|
* than max_number_of_bytes_per_request are treated as if multiple single
|
|
* requests of max_number_of_bytes_per_request size had been made.
|
|
* In theory SP 800-90A requires that we reject any request for a DRBG
|
|
* output longer than max_number_of_bytes_per_request. To avoid inconveniencing
|
|
* the caller who wants an output larger than max_number_of_bytes_per_request,
|
|
* instead treat these requests as if multiple requests of
|
|
* max_number_of_bytes_per_request size had been made. NIST requires for
|
|
* HMAC_DRBG that every implementation set a value no more than 2**19 bits
|
|
* (or 64 KiB). Together with @p reseed_interval = 1 you can enforce that for
|
|
* example every 512 bit automatic reseeding occurs.
|
|
*/
|
|
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);
|
|
|
|
std::string name() const override;
|
|
|
|
size_t security_level() const override;
|
|
|
|
size_t max_number_of_bytes_per_request() const override
|
|
{ return m_max_number_of_bytes_per_request; }
|
|
|
|
private:
|
|
void update(const uint8_t input[], size_t input_len) override;
|
|
|
|
void generate_output(uint8_t output[], size_t output_len,
|
|
const uint8_t input[], size_t input_len) override;
|
|
|
|
void clear_state() override;
|
|
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
secure_vector<uint8_t> m_V;
|
|
const size_t m_max_number_of_bytes_per_request;
|
|
const size_t m_security_level;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(http_util.h)
|
|
|
|
namespace Botan {
|
|
|
|
namespace HTTP {
|
|
|
|
/**
|
|
* HTTP_Error Exception
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) HTTP_Error final : public Exception
|
|
{
|
|
public:
|
|
explicit HTTP_Error(const std::string& msg) :
|
|
Exception("HTTP error " + msg)
|
|
{}
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::HttpError; }
|
|
|
|
};
|
|
|
|
class Response final
|
|
{
|
|
public:
|
|
Response() : m_status_code(0), m_status_message("Uninitialized") {}
|
|
|
|
Response(unsigned int status_code, const std::string& status_message,
|
|
const std::vector<uint8_t>& body,
|
|
const std::map<std::string, std::string>& headers) :
|
|
m_status_code(status_code),
|
|
m_status_message(status_message),
|
|
m_body(body),
|
|
m_headers(headers) {}
|
|
|
|
unsigned int status_code() const { return m_status_code; }
|
|
|
|
const std::vector<uint8_t>& body() const { return m_body; }
|
|
|
|
const std::map<std::string, std::string>& headers() const { return m_headers; }
|
|
|
|
std::string status_message() const { return m_status_message; }
|
|
|
|
void throw_unless_ok()
|
|
{
|
|
if(status_code() != 200)
|
|
throw HTTP_Error(status_message());
|
|
}
|
|
|
|
private:
|
|
unsigned int m_status_code;
|
|
std::string m_status_message;
|
|
std::vector<uint8_t> m_body;
|
|
std::map<std::string, std::string> m_headers;
|
|
};
|
|
|
|
BOTAN_PUBLIC_API(2,0) std::ostream& operator<<(std::ostream& o, const Response& resp);
|
|
|
|
typedef std::function<std::string (const std::string&, const std::string&, const std::string&)> http_exch_fn;
|
|
|
|
BOTAN_PUBLIC_API(2,0) Response http_sync(http_exch_fn fn,
|
|
const std::string& verb,
|
|
const std::string& url,
|
|
const std::string& content_type,
|
|
const std::vector<uint8_t>& body,
|
|
size_t allowable_redirects);
|
|
|
|
BOTAN_PUBLIC_API(2,0) Response http_sync(const std::string& verb,
|
|
const std::string& url,
|
|
const std::string& content_type,
|
|
const std::vector<uint8_t>& body,
|
|
size_t allowable_redirects,
|
|
std::chrono::milliseconds timeout = std::chrono::milliseconds(3000));
|
|
|
|
BOTAN_PUBLIC_API(2,0) Response GET_sync(const std::string& url,
|
|
size_t allowable_redirects = 1,
|
|
std::chrono::milliseconds timeout = std::chrono::milliseconds(3000));
|
|
|
|
BOTAN_PUBLIC_API(2,0) Response POST_sync(const std::string& url,
|
|
const std::string& content_type,
|
|
const std::vector<uint8_t>& body,
|
|
size_t allowable_redirects = 1,
|
|
std::chrono::milliseconds timeout = std::chrono::milliseconds(3000));
|
|
|
|
BOTAN_PUBLIC_API(2,0) std::string url_encode(const std::string& url);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(idea.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* IDEA
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) IDEA final : public Block_Cipher_Fixed_Params<8, 16>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
|
|
std::string provider() const override;
|
|
std::string name() const override { return "IDEA"; }
|
|
BlockCipher* clone() const override { return new IDEA; }
|
|
size_t parallelism() const override;
|
|
|
|
private:
|
|
#if defined(BOTAN_HAS_IDEA_SSE2)
|
|
void sse2_idea_op_8(const uint8_t in[64], uint8_t out[64], const uint16_t EK[52]) const;
|
|
#endif
|
|
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
secure_vector<uint16_t> m_EK, m_DK;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(iso9796.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* ISO-9796-2 - Digital signature scheme 2 (probabilistic)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ISO_9796_DS2 final : public EMSA
|
|
{
|
|
public:
|
|
/**
|
|
* @param hash function to use
|
|
* @param implicit whether or not the trailer is implicit
|
|
*/
|
|
explicit ISO_9796_DS2(HashFunction* hash, bool implicit = false) : m_hash(hash), m_implicit(implicit),
|
|
m_SALT_SIZE(hash->output_length()) {}
|
|
|
|
/**
|
|
* @param hash function to use
|
|
* @param implicit whether or not the trailer is implicit
|
|
* @param salt_size size of the salt to use in bytes
|
|
*/
|
|
ISO_9796_DS2(HashFunction* hash, bool implicit, size_t salt_size) : m_hash(hash), m_implicit(implicit),
|
|
m_SALT_SIZE(salt_size) {}
|
|
|
|
EMSA* clone() override;
|
|
|
|
std::string name() const override;
|
|
private:
|
|
void update(const uint8_t input[], size_t length) override;
|
|
|
|
secure_vector<uint8_t> raw_data() override;
|
|
|
|
secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator& rng) override;
|
|
|
|
bool verify(const secure_vector<uint8_t>& coded,
|
|
const secure_vector<uint8_t>& raw,
|
|
size_t key_bits) override;
|
|
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
bool m_implicit;
|
|
size_t m_SALT_SIZE;
|
|
secure_vector<uint8_t> m_msg_buffer;
|
|
};
|
|
|
|
/**
|
|
* ISO-9796-2 - Digital signature scheme 3 (deterministic)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ISO_9796_DS3 final : public EMSA
|
|
{
|
|
public:
|
|
/**
|
|
* @param hash function to use
|
|
* @param implicit whether or not the trailer is implicit
|
|
*/
|
|
ISO_9796_DS3(HashFunction* hash, bool implicit = false) : m_hash(hash), m_implicit(implicit)
|
|
{}
|
|
|
|
EMSA* clone() override;
|
|
|
|
std::string name() const override;
|
|
private:
|
|
void update(const uint8_t input[], size_t length) override;
|
|
|
|
secure_vector<uint8_t> raw_data() override;
|
|
|
|
secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator& rng) override;
|
|
|
|
bool verify(const secure_vector<uint8_t>& coded,
|
|
const secure_vector<uint8_t>& raw,
|
|
size_t key_bits) override;
|
|
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
bool m_implicit;
|
|
secure_vector<uint8_t> m_msg_buffer;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(kasumi.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* KASUMI, the block cipher used in 3G telephony
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) KASUMI final : public Block_Cipher_Fixed_Params<8, 16>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "KASUMI"; }
|
|
BlockCipher* clone() const override { return new KASUMI; }
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
secure_vector<uint16_t> m_EK;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(kdf1.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* KDF1, from IEEE 1363
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) KDF1 final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override { return "KDF1(" + m_hash->name() + ")"; }
|
|
|
|
KDF* clone() const override { return new KDF1(m_hash->clone()); }
|
|
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
/**
|
|
* @param h hash function to use
|
|
*/
|
|
explicit KDF1(HashFunction* h) : m_hash(h) {}
|
|
private:
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(kdf1_iso18033.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* KDF1, from ISO 18033-2
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) KDF1_18033 final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override { return "KDF1-18033(" + m_hash->name() + ")"; }
|
|
|
|
KDF* clone() const override { return new KDF1_18033(m_hash->clone()); }
|
|
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
/**
|
|
* @param h hash function to use
|
|
*/
|
|
explicit KDF1_18033(HashFunction* h) : m_hash(h) {}
|
|
private:
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(kdf2.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* KDF2, from IEEE 1363
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) KDF2 final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override { return "KDF2(" + m_hash->name() + ")"; }
|
|
|
|
KDF* clone() const override { return new KDF2(m_hash->clone()); }
|
|
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
/**
|
|
* @param h hash function to use
|
|
*/
|
|
explicit KDF2(HashFunction* h) : m_hash(h) {}
|
|
private:
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(keccak.h)
|
|
|
|
/**
|
|
* Keccak[1600], a SHA-3 candidate
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Keccak_1600 final : public HashFunction
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* @param output_bits the size of the hash output; must be one of
|
|
* 224, 256, 384, or 512
|
|
*/
|
|
explicit Keccak_1600(size_t output_bits = 512);
|
|
|
|
size_t hash_block_size() const override { return m_bitrate / 8; }
|
|
size_t output_length() const override { return m_output_bits / 8; }
|
|
|
|
HashFunction* clone() const override;
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
std::string name() const override;
|
|
void clear() override;
|
|
|
|
private:
|
|
void add_data(const uint8_t input[], size_t length) override;
|
|
void final_result(uint8_t out[]) override;
|
|
|
|
size_t m_output_bits, m_bitrate;
|
|
secure_vector<uint64_t> m_S;
|
|
size_t m_S_pos;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(keypair.h)
|
|
|
|
namespace Botan {
|
|
|
|
namespace KeyPair {
|
|
|
|
/**
|
|
* Tests whether the key is consistent for encryption; whether
|
|
* encrypting and then decrypting gives to the original plaintext.
|
|
* @param rng the rng to use
|
|
* @param private_key the key to test
|
|
* @param public_key the key to test
|
|
* @param padding the encryption padding method to use
|
|
* @return true if consistent otherwise false
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) bool
|
|
encryption_consistency_check(RandomNumberGenerator& rng,
|
|
const Private_Key& private_key,
|
|
const Public_Key& public_key,
|
|
const std::string& padding);
|
|
|
|
/**
|
|
* Tests whether the key is consistent for signatures; whether a
|
|
* signature can be created and then verified
|
|
* @param rng the rng to use
|
|
* @param private_key the key to test
|
|
* @param public_key the key to test
|
|
* @param padding the signature padding method to use
|
|
* @return true if consistent otherwise false
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) bool
|
|
signature_consistency_check(RandomNumberGenerator& rng,
|
|
const Private_Key& private_key,
|
|
const Public_Key& public_key,
|
|
const std::string& padding);
|
|
|
|
/**
|
|
* Tests whether the key is consistent for encryption; whether
|
|
* encrypting and then decrypting gives to the original plaintext.
|
|
* @param rng the rng to use
|
|
* @param key the key to test
|
|
* @param padding the encryption padding method to use
|
|
* @return true if consistent otherwise false
|
|
*/
|
|
inline bool
|
|
encryption_consistency_check(RandomNumberGenerator& rng,
|
|
const Private_Key& key,
|
|
const std::string& padding)
|
|
{
|
|
return encryption_consistency_check(rng, key, key, padding);
|
|
}
|
|
|
|
/**
|
|
* Tests whether the key is consistent for signatures; whether a
|
|
* signature can be created and then verified
|
|
* @param rng the rng to use
|
|
* @param key the key to test
|
|
* @param padding the signature padding method to use
|
|
* @return true if consistent otherwise false
|
|
*/
|
|
inline bool
|
|
signature_consistency_check(RandomNumberGenerator& rng,
|
|
const Private_Key& key,
|
|
const std::string& padding)
|
|
{
|
|
return signature_consistency_check(rng, key, key, padding);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(lion.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Lion is a block cipher construction designed by Ross Anderson and
|
|
* Eli Biham, described in "Two Practical and Provably Secure Block
|
|
* Ciphers: BEAR and LION". It has a variable block size and is
|
|
* designed to encrypt very large blocks (up to a megabyte)
|
|
|
|
* https://www.cl.cam.ac.uk/~rja14/Papers/bear-lion.pdf
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Lion final : public BlockCipher
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
size_t block_size() const override { return m_block_size; }
|
|
|
|
Key_Length_Specification key_spec() const override
|
|
{
|
|
return Key_Length_Specification(2, 2*m_hash->output_length(), 2);
|
|
}
|
|
|
|
void clear() override;
|
|
std::string name() const override;
|
|
BlockCipher* clone() const override;
|
|
|
|
/**
|
|
* @param hash the hash to use internally
|
|
* @param cipher the stream cipher to use internally
|
|
* @param block_size the size of the block to use
|
|
*/
|
|
Lion(HashFunction* hash,
|
|
StreamCipher* cipher,
|
|
size_t block_size);
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
size_t left_size() const { return m_hash->output_length(); }
|
|
size_t right_size() const { return m_block_size - left_size(); }
|
|
|
|
const size_t m_block_size;
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
std::unique_ptr<StreamCipher> m_cipher;
|
|
secure_vector<uint8_t> m_key1, m_key2;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(loadstor.h)
|
|
|
|
#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
|
|
#define BOTAN_ENDIAN_N2L(x) reverse_bytes(x)
|
|
#define BOTAN_ENDIAN_L2N(x) reverse_bytes(x)
|
|
#define BOTAN_ENDIAN_N2B(x) (x)
|
|
#define BOTAN_ENDIAN_B2N(x) (x)
|
|
|
|
#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
|
|
#define BOTAN_ENDIAN_N2L(x) (x)
|
|
#define BOTAN_ENDIAN_L2N(x) (x)
|
|
#define BOTAN_ENDIAN_N2B(x) reverse_bytes(x)
|
|
#define BOTAN_ENDIAN_B2N(x) reverse_bytes(x)
|
|
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Byte extraction
|
|
* @param byte_num which byte to extract, 0 == highest byte
|
|
* @param input the value to extract from
|
|
* @return byte byte_num of input
|
|
*/
|
|
template<typename T> inline constexpr uint8_t get_byte(size_t byte_num, T input)
|
|
{
|
|
return static_cast<uint8_t>(
|
|
input >> (((~byte_num)&(sizeof(T)-1)) << 3)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Make a uint16_t from two bytes
|
|
* @param i0 the first byte
|
|
* @param i1 the second byte
|
|
* @return i0 || i1
|
|
*/
|
|
inline constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)
|
|
{
|
|
return static_cast<uint16_t>((static_cast<uint16_t>(i0) << 8) | i1);
|
|
}
|
|
|
|
/**
|
|
* Make a uint32_t from four bytes
|
|
* @param i0 the first byte
|
|
* @param i1 the second byte
|
|
* @param i2 the third byte
|
|
* @param i3 the fourth byte
|
|
* @return i0 || i1 || i2 || i3
|
|
*/
|
|
inline constexpr uint32_t make_uint32(uint8_t i0, uint8_t i1, uint8_t i2, uint8_t i3)
|
|
{
|
|
return ((static_cast<uint32_t>(i0) << 24) |
|
|
(static_cast<uint32_t>(i1) << 16) |
|
|
(static_cast<uint32_t>(i2) << 8) |
|
|
(static_cast<uint32_t>(i3)));
|
|
}
|
|
|
|
/**
|
|
* Make a uint64_t from eight bytes
|
|
* @param i0 the first byte
|
|
* @param i1 the second byte
|
|
* @param i2 the third byte
|
|
* @param i3 the fourth byte
|
|
* @param i4 the fifth byte
|
|
* @param i5 the sixth byte
|
|
* @param i6 the seventh byte
|
|
* @param i7 the eighth byte
|
|
* @return i0 || i1 || i2 || i3 || i4 || i5 || i6 || i7
|
|
*/
|
|
inline constexpr uint64_t make_uint64(uint8_t i0, uint8_t i1, uint8_t i2, uint8_t i3,
|
|
uint8_t i4, uint8_t i5, uint8_t i6, uint8_t i7)
|
|
{
|
|
return ((static_cast<uint64_t>(i0) << 56) |
|
|
(static_cast<uint64_t>(i1) << 48) |
|
|
(static_cast<uint64_t>(i2) << 40) |
|
|
(static_cast<uint64_t>(i3) << 32) |
|
|
(static_cast<uint64_t>(i4) << 24) |
|
|
(static_cast<uint64_t>(i5) << 16) |
|
|
(static_cast<uint64_t>(i6) << 8) |
|
|
(static_cast<uint64_t>(i7)));
|
|
}
|
|
|
|
/**
|
|
* Load a big-endian word
|
|
* @param in a pointer to some bytes
|
|
* @param off an offset into the array
|
|
* @return off'th T of in, as a big-endian value
|
|
*/
|
|
template<typename T>
|
|
inline T load_be(const uint8_t in[], size_t off)
|
|
{
|
|
in += off * sizeof(T);
|
|
T out = 0;
|
|
for(size_t i = 0; i != sizeof(T); ++i)
|
|
out = static_cast<T>((out << 8) | in[i]);
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* Load a little-endian word
|
|
* @param in a pointer to some bytes
|
|
* @param off an offset into the array
|
|
* @return off'th T of in, as a litte-endian value
|
|
*/
|
|
template<typename T>
|
|
inline T load_le(const uint8_t in[], size_t off)
|
|
{
|
|
in += off * sizeof(T);
|
|
T out = 0;
|
|
for(size_t i = 0; i != sizeof(T); ++i)
|
|
out = (out << 8) | in[sizeof(T)-1-i];
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* Load a big-endian uint16_t
|
|
* @param in a pointer to some bytes
|
|
* @param off an offset into the array
|
|
* @return off'th uint16_t of in, as a big-endian value
|
|
*/
|
|
template<>
|
|
inline uint16_t load_be<uint16_t>(const uint8_t in[], size_t off)
|
|
{
|
|
in += off * sizeof(uint16_t);
|
|
|
|
#if defined(BOTAN_ENDIAN_N2B)
|
|
uint16_t x;
|
|
typecast_copy(x, in);
|
|
return BOTAN_ENDIAN_N2B(x);
|
|
#else
|
|
return make_uint16(in[0], in[1]);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Load a little-endian uint16_t
|
|
* @param in a pointer to some bytes
|
|
* @param off an offset into the array
|
|
* @return off'th uint16_t of in, as a little-endian value
|
|
*/
|
|
template<>
|
|
inline uint16_t load_le<uint16_t>(const uint8_t in[], size_t off)
|
|
{
|
|
in += off * sizeof(uint16_t);
|
|
|
|
#if defined(BOTAN_ENDIAN_N2L)
|
|
uint16_t x;
|
|
typecast_copy(x, in);
|
|
return BOTAN_ENDIAN_N2L(x);
|
|
#else
|
|
return make_uint16(in[1], in[0]);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Load a big-endian uint32_t
|
|
* @param in a pointer to some bytes
|
|
* @param off an offset into the array
|
|
* @return off'th uint32_t of in, as a big-endian value
|
|
*/
|
|
template<>
|
|
inline uint32_t load_be<uint32_t>(const uint8_t in[], size_t off)
|
|
{
|
|
in += off * sizeof(uint32_t);
|
|
#if defined(BOTAN_ENDIAN_N2B)
|
|
uint32_t x;
|
|
typecast_copy(x, in);
|
|
return BOTAN_ENDIAN_N2B(x);
|
|
#else
|
|
return make_uint32(in[0], in[1], in[2], in[3]);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Load a little-endian uint32_t
|
|
* @param in a pointer to some bytes
|
|
* @param off an offset into the array
|
|
* @return off'th uint32_t of in, as a little-endian value
|
|
*/
|
|
template<>
|
|
inline uint32_t load_le<uint32_t>(const uint8_t in[], size_t off)
|
|
{
|
|
in += off * sizeof(uint32_t);
|
|
#if defined(BOTAN_ENDIAN_N2L)
|
|
uint32_t x;
|
|
typecast_copy(x, in);
|
|
return BOTAN_ENDIAN_N2L(x);
|
|
#else
|
|
return make_uint32(in[3], in[2], in[1], in[0]);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Load a big-endian uint64_t
|
|
* @param in a pointer to some bytes
|
|
* @param off an offset into the array
|
|
* @return off'th uint64_t of in, as a big-endian value
|
|
*/
|
|
template<>
|
|
inline uint64_t load_be<uint64_t>(const uint8_t in[], size_t off)
|
|
{
|
|
in += off * sizeof(uint64_t);
|
|
#if defined(BOTAN_ENDIAN_N2B)
|
|
uint64_t x;
|
|
typecast_copy(x, in);
|
|
return BOTAN_ENDIAN_N2B(x);
|
|
#else
|
|
return make_uint64(in[0], in[1], in[2], in[3],
|
|
in[4], in[5], in[6], in[7]);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Load a little-endian uint64_t
|
|
* @param in a pointer to some bytes
|
|
* @param off an offset into the array
|
|
* @return off'th uint64_t of in, as a little-endian value
|
|
*/
|
|
template<>
|
|
inline uint64_t load_le<uint64_t>(const uint8_t in[], size_t off)
|
|
{
|
|
in += off * sizeof(uint64_t);
|
|
#if defined(BOTAN_ENDIAN_N2L)
|
|
uint64_t x;
|
|
typecast_copy(x, in);
|
|
return BOTAN_ENDIAN_N2L(x);
|
|
#else
|
|
return make_uint64(in[7], in[6], in[5], in[4],
|
|
in[3], in[2], in[1], in[0]);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Load two little-endian words
|
|
* @param in a pointer to some bytes
|
|
* @param x0 where the first word will be written
|
|
* @param x1 where the second word will be written
|
|
*/
|
|
template<typename T>
|
|
inline void load_le(const uint8_t in[], T& x0, T& x1)
|
|
{
|
|
x0 = load_le<T>(in, 0);
|
|
x1 = load_le<T>(in, 1);
|
|
}
|
|
|
|
/**
|
|
* Load four little-endian words
|
|
* @param in a pointer to some bytes
|
|
* @param x0 where the first word will be written
|
|
* @param x1 where the second word will be written
|
|
* @param x2 where the third word will be written
|
|
* @param x3 where the fourth word will be written
|
|
*/
|
|
template<typename T>
|
|
inline void load_le(const uint8_t in[],
|
|
T& x0, T& x1, T& x2, T& x3)
|
|
{
|
|
x0 = load_le<T>(in, 0);
|
|
x1 = load_le<T>(in, 1);
|
|
x2 = load_le<T>(in, 2);
|
|
x3 = load_le<T>(in, 3);
|
|
}
|
|
|
|
/**
|
|
* Load eight little-endian words
|
|
* @param in a pointer to some bytes
|
|
* @param x0 where the first word will be written
|
|
* @param x1 where the second word will be written
|
|
* @param x2 where the third word will be written
|
|
* @param x3 where the fourth word will be written
|
|
* @param x4 where the fifth word will be written
|
|
* @param x5 where the sixth word will be written
|
|
* @param x6 where the seventh word will be written
|
|
* @param x7 where the eighth word will be written
|
|
*/
|
|
template<typename T>
|
|
inline void load_le(const uint8_t in[],
|
|
T& x0, T& x1, T& x2, T& x3,
|
|
T& x4, T& x5, T& x6, T& x7)
|
|
{
|
|
x0 = load_le<T>(in, 0);
|
|
x1 = load_le<T>(in, 1);
|
|
x2 = load_le<T>(in, 2);
|
|
x3 = load_le<T>(in, 3);
|
|
x4 = load_le<T>(in, 4);
|
|
x5 = load_le<T>(in, 5);
|
|
x6 = load_le<T>(in, 6);
|
|
x7 = load_le<T>(in, 7);
|
|
}
|
|
|
|
/**
|
|
* Load a variable number of little-endian words
|
|
* @param out the output array of words
|
|
* @param in the input array of bytes
|
|
* @param count how many words are in in
|
|
*/
|
|
template<typename T>
|
|
inline void load_le(T out[],
|
|
const uint8_t in[],
|
|
size_t count)
|
|
{
|
|
if(count > 0)
|
|
{
|
|
#if defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
|
|
typecast_copy(out, in, count);
|
|
|
|
#elif defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
|
|
typecast_copy(out, in, count);
|
|
|
|
const size_t blocks = count - (count % 4);
|
|
const size_t left = count - blocks;
|
|
|
|
for(size_t i = 0; i != blocks; i += 4)
|
|
bswap_4(out + i);
|
|
|
|
for(size_t i = 0; i != left; ++i)
|
|
out[blocks+i] = reverse_bytes(out[blocks+i]);
|
|
#else
|
|
for(size_t i = 0; i != count; ++i)
|
|
out[i] = load_le<T>(in, i);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load two big-endian words
|
|
* @param in a pointer to some bytes
|
|
* @param x0 where the first word will be written
|
|
* @param x1 where the second word will be written
|
|
*/
|
|
template<typename T>
|
|
inline void load_be(const uint8_t in[], T& x0, T& x1)
|
|
{
|
|
x0 = load_be<T>(in, 0);
|
|
x1 = load_be<T>(in, 1);
|
|
}
|
|
|
|
/**
|
|
* Load four big-endian words
|
|
* @param in a pointer to some bytes
|
|
* @param x0 where the first word will be written
|
|
* @param x1 where the second word will be written
|
|
* @param x2 where the third word will be written
|
|
* @param x3 where the fourth word will be written
|
|
*/
|
|
template<typename T>
|
|
inline void load_be(const uint8_t in[],
|
|
T& x0, T& x1, T& x2, T& x3)
|
|
{
|
|
x0 = load_be<T>(in, 0);
|
|
x1 = load_be<T>(in, 1);
|
|
x2 = load_be<T>(in, 2);
|
|
x3 = load_be<T>(in, 3);
|
|
}
|
|
|
|
/**
|
|
* Load eight big-endian words
|
|
* @param in a pointer to some bytes
|
|
* @param x0 where the first word will be written
|
|
* @param x1 where the second word will be written
|
|
* @param x2 where the third word will be written
|
|
* @param x3 where the fourth word will be written
|
|
* @param x4 where the fifth word will be written
|
|
* @param x5 where the sixth word will be written
|
|
* @param x6 where the seventh word will be written
|
|
* @param x7 where the eighth word will be written
|
|
*/
|
|
template<typename T>
|
|
inline void load_be(const uint8_t in[],
|
|
T& x0, T& x1, T& x2, T& x3,
|
|
T& x4, T& x5, T& x6, T& x7)
|
|
{
|
|
x0 = load_be<T>(in, 0);
|
|
x1 = load_be<T>(in, 1);
|
|
x2 = load_be<T>(in, 2);
|
|
x3 = load_be<T>(in, 3);
|
|
x4 = load_be<T>(in, 4);
|
|
x5 = load_be<T>(in, 5);
|
|
x6 = load_be<T>(in, 6);
|
|
x7 = load_be<T>(in, 7);
|
|
}
|
|
|
|
/**
|
|
* Load a variable number of big-endian words
|
|
* @param out the output array of words
|
|
* @param in the input array of bytes
|
|
* @param count how many words are in in
|
|
*/
|
|
template<typename T>
|
|
inline void load_be(T out[],
|
|
const uint8_t in[],
|
|
size_t count)
|
|
{
|
|
if(count > 0)
|
|
{
|
|
#if defined(BOTAN_TARGET_CPU_IS_BIG_ENDIAN)
|
|
typecast_copy(out, in, count);
|
|
|
|
#elif defined(BOTAN_TARGET_CPU_IS_LITTLE_ENDIAN)
|
|
typecast_copy(out, in, count);
|
|
const size_t blocks = count - (count % 4);
|
|
const size_t left = count - blocks;
|
|
|
|
for(size_t i = 0; i != blocks; i += 4)
|
|
bswap_4(out + i);
|
|
|
|
for(size_t i = 0; i != left; ++i)
|
|
out[blocks+i] = reverse_bytes(out[blocks+i]);
|
|
#else
|
|
for(size_t i = 0; i != count; ++i)
|
|
out[i] = load_be<T>(in, i);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Store a big-endian uint16_t
|
|
* @param in the input uint16_t
|
|
* @param out the byte array to write to
|
|
*/
|
|
inline void store_be(uint16_t in, uint8_t out[2])
|
|
{
|
|
#if defined(BOTAN_ENDIAN_N2B)
|
|
uint16_t o = BOTAN_ENDIAN_N2B(in);
|
|
typecast_copy(out, o);
|
|
#else
|
|
out[0] = get_byte(0, in);
|
|
out[1] = get_byte(1, in);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Store a little-endian uint16_t
|
|
* @param in the input uint16_t
|
|
* @param out the byte array to write to
|
|
*/
|
|
inline void store_le(uint16_t in, uint8_t out[2])
|
|
{
|
|
#if defined(BOTAN_ENDIAN_N2L)
|
|
uint16_t o = BOTAN_ENDIAN_N2L(in);
|
|
typecast_copy(out, o);
|
|
#else
|
|
out[0] = get_byte(1, in);
|
|
out[1] = get_byte(0, in);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Store a big-endian uint32_t
|
|
* @param in the input uint32_t
|
|
* @param out the byte array to write to
|
|
*/
|
|
inline void store_be(uint32_t in, uint8_t out[4])
|
|
{
|
|
#if defined(BOTAN_ENDIAN_B2N)
|
|
uint32_t o = BOTAN_ENDIAN_B2N(in);
|
|
typecast_copy(out, o);
|
|
#else
|
|
out[0] = get_byte(0, in);
|
|
out[1] = get_byte(1, in);
|
|
out[2] = get_byte(2, in);
|
|
out[3] = get_byte(3, in);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Store a little-endian uint32_t
|
|
* @param in the input uint32_t
|
|
* @param out the byte array to write to
|
|
*/
|
|
inline void store_le(uint32_t in, uint8_t out[4])
|
|
{
|
|
#if defined(BOTAN_ENDIAN_L2N)
|
|
uint32_t o = BOTAN_ENDIAN_L2N(in);
|
|
typecast_copy(out, o);
|
|
#else
|
|
out[0] = get_byte(3, in);
|
|
out[1] = get_byte(2, in);
|
|
out[2] = get_byte(1, in);
|
|
out[3] = get_byte(0, in);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Store a big-endian uint64_t
|
|
* @param in the input uint64_t
|
|
* @param out the byte array to write to
|
|
*/
|
|
inline void store_be(uint64_t in, uint8_t out[8])
|
|
{
|
|
#if defined(BOTAN_ENDIAN_B2N)
|
|
uint64_t o = BOTAN_ENDIAN_B2N(in);
|
|
typecast_copy(out, o);
|
|
#else
|
|
out[0] = get_byte(0, in);
|
|
out[1] = get_byte(1, in);
|
|
out[2] = get_byte(2, in);
|
|
out[3] = get_byte(3, in);
|
|
out[4] = get_byte(4, in);
|
|
out[5] = get_byte(5, in);
|
|
out[6] = get_byte(6, in);
|
|
out[7] = get_byte(7, in);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Store a little-endian uint64_t
|
|
* @param in the input uint64_t
|
|
* @param out the byte array to write to
|
|
*/
|
|
inline void store_le(uint64_t in, uint8_t out[8])
|
|
{
|
|
#if defined(BOTAN_ENDIAN_L2N)
|
|
uint64_t o = BOTAN_ENDIAN_L2N(in);
|
|
typecast_copy(out, o);
|
|
#else
|
|
out[0] = get_byte(7, in);
|
|
out[1] = get_byte(6, in);
|
|
out[2] = get_byte(5, in);
|
|
out[3] = get_byte(4, in);
|
|
out[4] = get_byte(3, in);
|
|
out[5] = get_byte(2, in);
|
|
out[6] = get_byte(1, in);
|
|
out[7] = get_byte(0, in);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Store two little-endian words
|
|
* @param out the output byte array
|
|
* @param x0 the first word
|
|
* @param x1 the second word
|
|
*/
|
|
template<typename T>
|
|
inline void store_le(uint8_t out[], T x0, T x1)
|
|
{
|
|
store_le(x0, out + (0 * sizeof(T)));
|
|
store_le(x1, out + (1 * sizeof(T)));
|
|
}
|
|
|
|
/**
|
|
* Store two big-endian words
|
|
* @param out the output byte array
|
|
* @param x0 the first word
|
|
* @param x1 the second word
|
|
*/
|
|
template<typename T>
|
|
inline void store_be(uint8_t out[], T x0, T x1)
|
|
{
|
|
store_be(x0, out + (0 * sizeof(T)));
|
|
store_be(x1, out + (1 * sizeof(T)));
|
|
}
|
|
|
|
/**
|
|
* Store four little-endian words
|
|
* @param out the output byte array
|
|
* @param x0 the first word
|
|
* @param x1 the second word
|
|
* @param x2 the third word
|
|
* @param x3 the fourth word
|
|
*/
|
|
template<typename T>
|
|
inline void store_le(uint8_t out[], T x0, T x1, T x2, T x3)
|
|
{
|
|
store_le(x0, out + (0 * sizeof(T)));
|
|
store_le(x1, out + (1 * sizeof(T)));
|
|
store_le(x2, out + (2 * sizeof(T)));
|
|
store_le(x3, out + (3 * sizeof(T)));
|
|
}
|
|
|
|
/**
|
|
* Store four big-endian words
|
|
* @param out the output byte array
|
|
* @param x0 the first word
|
|
* @param x1 the second word
|
|
* @param x2 the third word
|
|
* @param x3 the fourth word
|
|
*/
|
|
template<typename T>
|
|
inline void store_be(uint8_t out[], T x0, T x1, T x2, T x3)
|
|
{
|
|
store_be(x0, out + (0 * sizeof(T)));
|
|
store_be(x1, out + (1 * sizeof(T)));
|
|
store_be(x2, out + (2 * sizeof(T)));
|
|
store_be(x3, out + (3 * sizeof(T)));
|
|
}
|
|
|
|
/**
|
|
* Store eight little-endian words
|
|
* @param out the output byte array
|
|
* @param x0 the first word
|
|
* @param x1 the second word
|
|
* @param x2 the third word
|
|
* @param x3 the fourth word
|
|
* @param x4 the fifth word
|
|
* @param x5 the sixth word
|
|
* @param x6 the seventh word
|
|
* @param x7 the eighth word
|
|
*/
|
|
template<typename T>
|
|
inline void store_le(uint8_t out[], T x0, T x1, T x2, T x3,
|
|
T x4, T x5, T x6, T x7)
|
|
{
|
|
store_le(x0, out + (0 * sizeof(T)));
|
|
store_le(x1, out + (1 * sizeof(T)));
|
|
store_le(x2, out + (2 * sizeof(T)));
|
|
store_le(x3, out + (3 * sizeof(T)));
|
|
store_le(x4, out + (4 * sizeof(T)));
|
|
store_le(x5, out + (5 * sizeof(T)));
|
|
store_le(x6, out + (6 * sizeof(T)));
|
|
store_le(x7, out + (7 * sizeof(T)));
|
|
}
|
|
|
|
/**
|
|
* Store eight big-endian words
|
|
* @param out the output byte array
|
|
* @param x0 the first word
|
|
* @param x1 the second word
|
|
* @param x2 the third word
|
|
* @param x3 the fourth word
|
|
* @param x4 the fifth word
|
|
* @param x5 the sixth word
|
|
* @param x6 the seventh word
|
|
* @param x7 the eighth word
|
|
*/
|
|
template<typename T>
|
|
inline void store_be(uint8_t out[], T x0, T x1, T x2, T x3,
|
|
T x4, T x5, T x6, T x7)
|
|
{
|
|
store_be(x0, out + (0 * sizeof(T)));
|
|
store_be(x1, out + (1 * sizeof(T)));
|
|
store_be(x2, out + (2 * sizeof(T)));
|
|
store_be(x3, out + (3 * sizeof(T)));
|
|
store_be(x4, out + (4 * sizeof(T)));
|
|
store_be(x5, out + (5 * sizeof(T)));
|
|
store_be(x6, out + (6 * sizeof(T)));
|
|
store_be(x7, out + (7 * sizeof(T)));
|
|
}
|
|
|
|
template<typename T>
|
|
void copy_out_be(uint8_t out[], size_t out_bytes, const T in[])
|
|
{
|
|
while(out_bytes >= sizeof(T))
|
|
{
|
|
store_be(in[0], out);
|
|
out += sizeof(T);
|
|
out_bytes -= sizeof(T);
|
|
in += 1;
|
|
}
|
|
|
|
for(size_t i = 0; i != out_bytes; ++i)
|
|
out[i] = get_byte(i%8, in[0]);
|
|
}
|
|
|
|
template<typename T, typename Alloc>
|
|
void copy_out_vec_be(uint8_t out[], size_t out_bytes, const std::vector<T, Alloc>& in)
|
|
{
|
|
copy_out_be(out, out_bytes, in.data());
|
|
}
|
|
|
|
template<typename T>
|
|
void copy_out_le(uint8_t out[], size_t out_bytes, const T in[])
|
|
{
|
|
while(out_bytes >= sizeof(T))
|
|
{
|
|
store_le(in[0], out);
|
|
out += sizeof(T);
|
|
out_bytes -= sizeof(T);
|
|
in += 1;
|
|
}
|
|
|
|
for(size_t i = 0; i != out_bytes; ++i)
|
|
out[i] = get_byte(sizeof(T) - 1 - (i % 8), in[0]);
|
|
}
|
|
|
|
template<typename T, typename Alloc>
|
|
void copy_out_vec_le(uint8_t out[], size_t out_bytes, const std::vector<T, Alloc>& in)
|
|
{
|
|
copy_out_le(out, out_bytes, in.data());
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(locking_allocator.h)
|
|
|
|
namespace Botan {
|
|
|
|
class Memory_Pool;
|
|
|
|
class BOTAN_PUBLIC_API(2,0) mlock_allocator final
|
|
{
|
|
public:
|
|
static mlock_allocator& instance();
|
|
|
|
void* allocate(size_t num_elems, size_t elem_size);
|
|
|
|
bool deallocate(void* p, size_t num_elems, size_t elem_size) noexcept;
|
|
|
|
mlock_allocator(const mlock_allocator&) = delete;
|
|
|
|
mlock_allocator& operator=(const mlock_allocator&) = delete;
|
|
|
|
private:
|
|
mlock_allocator();
|
|
|
|
~mlock_allocator();
|
|
|
|
std::unique_ptr<Memory_Pool> m_pool;
|
|
std::vector<void*> m_locked_pages;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
class McEliece_PublicKey;
|
|
class McEliece_PrivateKey;
|
|
|
|
/**
|
|
* McEliece Integrated Encryption System
|
|
* Derive a shared key using MCE KEM and encrypt/authenticate the
|
|
* plaintext and AD using AES-256 in OCB mode.
|
|
*/
|
|
secure_vector<uint8_t>
|
|
BOTAN_PUBLIC_API(2,0) mceies_encrypt(const McEliece_PublicKey& pubkey,
|
|
const uint8_t pt[], size_t pt_len,
|
|
const uint8_t ad[], size_t ad_len,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& aead = "AES-256/OCB");
|
|
|
|
/**
|
|
* McEliece Integrated Encryption System
|
|
* Derive a shared key using MCE KEM and decrypt/authenticate the
|
|
* ciphertext and AD using AES-256 in OCB mode.
|
|
*/
|
|
secure_vector<uint8_t>
|
|
BOTAN_PUBLIC_API(2,0) mceies_decrypt(const McEliece_PrivateKey& privkey,
|
|
const uint8_t ct[], size_t ct_len,
|
|
const uint8_t ad[], size_t ad_len,
|
|
const std::string& aead = "AES-256/OCB");
|
|
|
|
|
|
}
|
|
|
|
// Currently must be visible for MSVC
|
|
//BOTAN_FUTURE_INTERNAL_HEADER(polyn_gf2m.h)
|
|
|
|
namespace Botan {
|
|
|
|
typedef uint16_t gf2m;
|
|
|
|
class GF2m_Field;
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
class polyn_gf2m
|
|
{
|
|
public:
|
|
/**
|
|
* create a zero polynomial:
|
|
*/
|
|
explicit polyn_gf2m(std::shared_ptr<GF2m_Field> sp_field);
|
|
|
|
polyn_gf2m() : m_deg(-1) {}
|
|
|
|
polyn_gf2m(const secure_vector<uint8_t>& encoded, std::shared_ptr<GF2m_Field> sp_field);
|
|
|
|
polyn_gf2m& operator=(const polyn_gf2m&) = default;
|
|
|
|
/**
|
|
* create zero polynomial with reservation of space for a degree d polynomial
|
|
*/
|
|
polyn_gf2m(int d, std::shared_ptr<GF2m_Field> sp_field);
|
|
|
|
polyn_gf2m(polyn_gf2m const& other);
|
|
|
|
/**
|
|
* random irreducible polynomial of degree t
|
|
*/
|
|
polyn_gf2m(size_t t, RandomNumberGenerator& rng, std::shared_ptr<GF2m_Field> sp_field);
|
|
|
|
/** decode a polynomial from memory: **/
|
|
polyn_gf2m(const uint8_t* mem, uint32_t mem_len, std::shared_ptr<GF2m_Field> sp_field);
|
|
|
|
/**
|
|
* create a polynomial from memory area (encoded)
|
|
*/
|
|
polyn_gf2m(int degree, const uint8_t* mem, size_t mem_byte_len, std::shared_ptr<GF2m_Field> sp_field);
|
|
|
|
bool operator==(const polyn_gf2m & other) const ;
|
|
|
|
bool operator!=(const polyn_gf2m & other) const { return !(*this == other); }
|
|
|
|
polyn_gf2m(polyn_gf2m&& other)
|
|
{
|
|
this->swap(other);
|
|
}
|
|
|
|
polyn_gf2m & operator=(polyn_gf2m&& other)
|
|
{
|
|
if(this != &other)
|
|
{
|
|
this->swap(other);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
void swap(polyn_gf2m& other);
|
|
|
|
secure_vector<uint8_t> encode() const;
|
|
|
|
std::shared_ptr<GF2m_Field> get_sp_field() const
|
|
{ return m_sp_field; }
|
|
|
|
gf2m& operator[](size_t i) { return coeff[i]; }
|
|
|
|
gf2m operator[](size_t i) const { return coeff[i]; }
|
|
|
|
gf2m get_lead_coef() const { return coeff[m_deg]; }
|
|
|
|
gf2m get_coef(size_t i) const { return coeff[i]; }
|
|
|
|
inline void set_coef(size_t i, gf2m v)
|
|
{
|
|
coeff[i] = v;
|
|
}
|
|
|
|
inline void add_to_coef(size_t i, gf2m v)
|
|
{
|
|
coeff[i] ^= v;
|
|
}
|
|
|
|
std::string to_string() const;
|
|
|
|
void encode(uint32_t min_numo_coeffs, uint8_t* mem, uint32_t mem_len) const;
|
|
|
|
int get_degree() const;
|
|
|
|
/**
|
|
* determine the degree in a timing secure manner. the timing of this function
|
|
* only depends on the number of allocated coefficients, not on the actual
|
|
* degree
|
|
*/
|
|
int calc_degree_secure() const;
|
|
|
|
size_t degppf(const polyn_gf2m& g);
|
|
|
|
static std::vector<polyn_gf2m> sqmod_init(const polyn_gf2m & g);
|
|
|
|
static std::vector<polyn_gf2m> sqrt_mod_init(const polyn_gf2m & g);
|
|
|
|
|
|
polyn_gf2m sqmod(const std::vector<polyn_gf2m> & sq, int d);
|
|
void set_to_zero();
|
|
gf2m eval(gf2m a);
|
|
|
|
static std::pair<polyn_gf2m, polyn_gf2m> eea_with_coefficients(const polyn_gf2m & p,
|
|
const polyn_gf2m & g,
|
|
int break_deg);
|
|
|
|
void patchup_deg_secure( uint32_t trgt_deg, volatile gf2m patch_elem);
|
|
|
|
private:
|
|
|
|
void set_degree(int d) { m_deg = d; }
|
|
|
|
void poly_shiftmod( const polyn_gf2m & g);
|
|
void realloc(uint32_t new_size);
|
|
static polyn_gf2m gcd(polyn_gf2m const& p1, polyn_gf2m const& p2);
|
|
|
|
/**
|
|
* destructive:
|
|
*/
|
|
static void remainder(polyn_gf2m & p, const polyn_gf2m & g);
|
|
|
|
static polyn_gf2m gcd_aux(polyn_gf2m& p1, polyn_gf2m& p2);
|
|
public:
|
|
// public member variable:
|
|
int m_deg;
|
|
|
|
// public member variable:
|
|
secure_vector<gf2m> coeff;
|
|
|
|
// public member variable:
|
|
std::shared_ptr<GF2m_Field> m_sp_field;
|
|
};
|
|
|
|
gf2m random_gf2m(RandomNumberGenerator& rng);
|
|
gf2m random_code_element(uint16_t code_length, RandomNumberGenerator& rng);
|
|
|
|
std::vector<polyn_gf2m> syndrome_init(polyn_gf2m const& generator, std::vector<gf2m> const& support, int n);
|
|
|
|
/**
|
|
* Find the roots of a polynomial over GF(2^m) using the method by Federenko et al.
|
|
*/
|
|
secure_vector<gf2m> find_roots_gf2m_decomp(const polyn_gf2m & polyn, size_t code_length);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
typedef uint16_t gf2m;
|
|
|
|
class polyn_gf2m;
|
|
|
|
class BOTAN_PUBLIC_API(2,0) McEliece_PublicKey : public virtual Public_Key
|
|
{
|
|
public:
|
|
explicit McEliece_PublicKey(const std::vector<uint8_t>& key_bits);
|
|
|
|
McEliece_PublicKey(const std::vector<uint8_t>& pub_matrix, size_t t, size_t the_code_length) :
|
|
m_public_matrix(pub_matrix),
|
|
m_t(t),
|
|
m_code_length(the_code_length){}
|
|
|
|
McEliece_PublicKey(const McEliece_PublicKey& other) = default;
|
|
McEliece_PublicKey& operator=(const McEliece_PublicKey& other) = default;
|
|
virtual ~McEliece_PublicKey()= default;
|
|
|
|
secure_vector<uint8_t> random_plaintext_element(RandomNumberGenerator& rng) const;
|
|
|
|
std::string algo_name() const override { return "McEliece"; }
|
|
|
|
AlgorithmIdentifier algorithm_identifier() const override;
|
|
|
|
size_t key_length() const override;
|
|
size_t estimated_strength() const override;
|
|
|
|
std::vector<uint8_t> public_key_bits() const override;
|
|
|
|
bool check_key(RandomNumberGenerator&, bool) const override
|
|
{ return true; }
|
|
|
|
size_t get_t() const { return m_t; }
|
|
size_t get_code_length() const { return m_code_length; }
|
|
size_t get_message_word_bit_length() const;
|
|
const std::vector<uint8_t>& get_public_matrix() const { return m_public_matrix; }
|
|
|
|
bool operator==(const McEliece_PublicKey& other) const;
|
|
bool operator!=(const McEliece_PublicKey& other) const { return !(*this == other); }
|
|
|
|
std::unique_ptr<PK_Ops::KEM_Encryption>
|
|
create_kem_encryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
protected:
|
|
McEliece_PublicKey() : m_t(0), m_code_length(0) {}
|
|
|
|
std::vector<uint8_t> m_public_matrix;
|
|
size_t m_t;
|
|
size_t m_code_length;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,0) McEliece_PrivateKey final : public virtual McEliece_PublicKey,
|
|
public virtual Private_Key
|
|
{
|
|
public:
|
|
|
|
/**
|
|
Generate a McEliece key pair
|
|
|
|
Suggested parameters for a given security level (SL)
|
|
|
|
SL=80 n=1632 t=33 - 59 KB pubkey 140 KB privkey
|
|
SL=107 n=2480 t=45 - 128 KB pubkey 300 KB privkey
|
|
SL=128 n=2960 t=57 - 195 KB pubkey 459 KB privkey
|
|
SL=147 n=3408 t=67 - 265 KB pubkey 622 KB privkey
|
|
SL=191 n=4624 t=95 - 516 KB pubkey 1234 KB privkey
|
|
SL=256 n=6624 t=115 - 942 KB pubkey 2184 KB privkey
|
|
*/
|
|
McEliece_PrivateKey(RandomNumberGenerator& rng, size_t code_length, size_t t);
|
|
|
|
explicit McEliece_PrivateKey(const secure_vector<uint8_t>& key_bits);
|
|
|
|
McEliece_PrivateKey(polyn_gf2m const& goppa_polyn,
|
|
std::vector<uint32_t> const& parity_check_matrix_coeffs,
|
|
std::vector<polyn_gf2m> const& square_root_matrix,
|
|
std::vector<gf2m> const& inverse_support,
|
|
std::vector<uint8_t> const& public_matrix );
|
|
|
|
~McEliece_PrivateKey();
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool strong) const override;
|
|
|
|
polyn_gf2m const& get_goppa_polyn() const;
|
|
std::vector<uint32_t> const& get_H_coeffs() const { return m_coeffs; }
|
|
std::vector<gf2m> const& get_Linv() const { return m_Linv; }
|
|
std::vector<polyn_gf2m> const& get_sqrtmod() const { return m_sqrtmod; }
|
|
|
|
inline size_t get_dimension() const { return m_dimension; }
|
|
|
|
inline size_t get_codimension() const { return m_codimension; }
|
|
|
|
secure_vector<uint8_t> private_key_bits() const override;
|
|
|
|
bool operator==(const McEliece_PrivateKey & other) const;
|
|
|
|
bool operator!=(const McEliece_PrivateKey& other) const { return !(*this == other); }
|
|
|
|
std::unique_ptr<PK_Ops::KEM_Decryption>
|
|
create_kem_decryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
private:
|
|
std::vector<polyn_gf2m> m_g; // single element
|
|
std::vector<polyn_gf2m> m_sqrtmod;
|
|
std::vector<gf2m> m_Linv;
|
|
std::vector<uint32_t> m_coeffs;
|
|
|
|
size_t m_codimension;
|
|
size_t m_dimension;
|
|
};
|
|
|
|
/**
|
|
* Estimate work factor for McEliece
|
|
* @return estimated security level for these key parameters
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) size_t mceliece_work_factor(size_t code_size, size_t t);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(mdx_hash.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* MDx Hash Function Base Class
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) MDx_HashFunction : public HashFunction
|
|
{
|
|
public:
|
|
/**
|
|
* @param block_length is the number of bytes per block, which must
|
|
* be a power of 2 and at least 8.
|
|
* @param big_byte_endian specifies if the hash uses big-endian bytes
|
|
* @param big_bit_endian specifies if the hash uses big-endian bits
|
|
* @param counter_size specifies the size of the counter var in bytes
|
|
*/
|
|
MDx_HashFunction(size_t block_length,
|
|
bool big_byte_endian,
|
|
bool big_bit_endian,
|
|
uint8_t counter_size = 8);
|
|
|
|
size_t hash_block_size() const override final { return m_buffer.size(); }
|
|
protected:
|
|
void add_data(const uint8_t input[], size_t length) override final;
|
|
void final_result(uint8_t output[]) override final;
|
|
|
|
/**
|
|
* Run the hash's compression function over a set of blocks
|
|
* @param blocks the input
|
|
* @param block_n the number of blocks
|
|
*/
|
|
virtual void compress_n(const uint8_t blocks[], size_t block_n) = 0;
|
|
|
|
void clear() override;
|
|
|
|
/**
|
|
* Copy the output to the buffer
|
|
* @param buffer to put the output into
|
|
*/
|
|
virtual void copy_out(uint8_t buffer[]) = 0;
|
|
|
|
/**
|
|
* Write the count, if used, to this spot
|
|
* @param out where to write the counter to
|
|
*/
|
|
virtual void write_count(uint8_t out[]);
|
|
private:
|
|
const uint8_t m_pad_char;
|
|
const uint8_t m_counter_size;
|
|
const uint8_t m_block_bits;
|
|
const bool m_count_big_endian;
|
|
|
|
uint64_t m_count;
|
|
secure_vector<uint8_t> m_buffer;
|
|
size_t m_position;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(md4.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* MD4
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) MD4 final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "MD4"; }
|
|
size_t output_length() const override { return 16; }
|
|
HashFunction* clone() const override { return new MD4; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override;
|
|
|
|
MD4() : MDx_HashFunction(64, false, true), m_digest(4)
|
|
{ clear(); }
|
|
|
|
private:
|
|
void compress_n(const uint8_t input[], size_t blocks) override;
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
/**
|
|
* The digest value
|
|
*/
|
|
secure_vector<uint32_t> m_digest;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(md5.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* MD5
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) MD5 final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "MD5"; }
|
|
size_t output_length() const override { return 16; }
|
|
HashFunction* clone() const override { return new MD5; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override;
|
|
|
|
MD5() : MDx_HashFunction(64, false, true), m_M(16), m_digest(4)
|
|
{ clear(); }
|
|
|
|
private:
|
|
void compress_n(const uint8_t[], size_t blocks) override;
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
/**
|
|
* The message buffer
|
|
*/
|
|
secure_vector<uint32_t> m_M;
|
|
|
|
/**
|
|
* The digest value
|
|
*/
|
|
secure_vector<uint32_t> m_digest;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class HashFunction;
|
|
|
|
/**
|
|
* MGF1 from PKCS #1 v2.0
|
|
* @param hash hash function to use
|
|
* @param in input buffer
|
|
* @param in_len size of the input buffer in bytes
|
|
* @param out output buffer
|
|
* @param out_len size of the output buffer in bytes
|
|
*/
|
|
void BOTAN_PUBLIC_API(2,0) mgf1_mask(HashFunction& hash,
|
|
const uint8_t in[], size_t in_len,
|
|
uint8_t out[], size_t out_len);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(misty1.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* MISTY1 with 8 rounds
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) MISTY1 final : public Block_Cipher_Fixed_Params<8, 16>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "MISTY1"; }
|
|
BlockCipher* clone() const override { return new MISTY1; }
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
secure_vector<uint16_t> m_EK, m_DK;
|
|
};
|
|
|
|
}
|
|
BOTAN_FUTURE_INTERNAL_HEADER(monty.h)
|
|
|
|
namespace Botan {
|
|
|
|
class Modular_Reducer;
|
|
|
|
class Montgomery_Params;
|
|
|
|
/**
|
|
* The Montgomery representation of an integer
|
|
*/
|
|
class BOTAN_UNSTABLE_API Montgomery_Int final
|
|
{
|
|
public:
|
|
/**
|
|
* Create a zero-initialized Montgomery_Int
|
|
*/
|
|
Montgomery_Int(std::shared_ptr<const Montgomery_Params> params) : m_params(params) {}
|
|
|
|
/**
|
|
* Create a Montgomery_Int
|
|
*/
|
|
Montgomery_Int(std::shared_ptr<const Montgomery_Params> params,
|
|
const BigInt& v,
|
|
bool redc_needed = true);
|
|
|
|
/**
|
|
* Create a Montgomery_Int
|
|
*/
|
|
Montgomery_Int(std::shared_ptr<const Montgomery_Params> params,
|
|
const uint8_t bits[], size_t len,
|
|
bool redc_needed = true);
|
|
|
|
/**
|
|
* Create a Montgomery_Int
|
|
*/
|
|
Montgomery_Int(std::shared_ptr<const Montgomery_Params> params,
|
|
const word words[], size_t len,
|
|
bool redc_needed = true);
|
|
|
|
bool operator==(const Montgomery_Int& other) const;
|
|
bool operator!=(const Montgomery_Int& other) const { return (m_v != other.m_v); }
|
|
|
|
std::vector<uint8_t> serialize() const;
|
|
|
|
size_t size() const;
|
|
bool is_one() const;
|
|
bool is_zero() const;
|
|
|
|
void fix_size();
|
|
|
|
/**
|
|
* Return the value to normal mod-p space
|
|
*/
|
|
BigInt value() const;
|
|
|
|
/**
|
|
* Return the Montgomery representation
|
|
*/
|
|
const BigInt& repr() const { return m_v; }
|
|
|
|
Montgomery_Int operator+(const Montgomery_Int& other) const;
|
|
|
|
Montgomery_Int operator-(const Montgomery_Int& other) const;
|
|
|
|
Montgomery_Int& operator+=(const Montgomery_Int& other);
|
|
|
|
Montgomery_Int& operator-=(const Montgomery_Int& other);
|
|
|
|
Montgomery_Int operator*(const Montgomery_Int& other) const;
|
|
|
|
Montgomery_Int& operator*=(const Montgomery_Int& other);
|
|
|
|
Montgomery_Int& operator*=(const secure_vector<word>& other);
|
|
|
|
Montgomery_Int& add(const Montgomery_Int& other,
|
|
secure_vector<word>& ws);
|
|
|
|
Montgomery_Int& sub(const Montgomery_Int& other,
|
|
secure_vector<word>& ws);
|
|
|
|
Montgomery_Int mul(const Montgomery_Int& other,
|
|
secure_vector<word>& ws) const;
|
|
|
|
Montgomery_Int& mul_by(const Montgomery_Int& other,
|
|
secure_vector<word>& ws);
|
|
|
|
Montgomery_Int& mul_by(const secure_vector<word>& other,
|
|
secure_vector<word>& ws);
|
|
|
|
Montgomery_Int square(secure_vector<word>& ws) const;
|
|
|
|
Montgomery_Int& square_this(secure_vector<word>& ws);
|
|
|
|
Montgomery_Int& square_this_n_times(secure_vector<word>& ws, size_t n);
|
|
|
|
Montgomery_Int multiplicative_inverse() const;
|
|
|
|
Montgomery_Int additive_inverse() const;
|
|
|
|
Montgomery_Int& mul_by_2(secure_vector<word>& ws);
|
|
|
|
Montgomery_Int& mul_by_3(secure_vector<word>& ws);
|
|
|
|
Montgomery_Int& mul_by_4(secure_vector<word>& ws);
|
|
|
|
Montgomery_Int& mul_by_8(secure_vector<word>& ws);
|
|
|
|
void const_time_poison() const { m_v.const_time_poison(); }
|
|
void const_time_unpoison() const { return m_v.const_time_unpoison(); }
|
|
|
|
private:
|
|
std::shared_ptr<const Montgomery_Params> m_params;
|
|
BigInt m_v;
|
|
};
|
|
|
|
/**
|
|
* Parameters for Montgomery Reduction
|
|
*/
|
|
class BOTAN_UNSTABLE_API Montgomery_Params final
|
|
{
|
|
public:
|
|
/**
|
|
* Initialize a set of Montgomery reduction parameters. These values
|
|
* can be shared by all values in a specific Montgomery domain.
|
|
*/
|
|
Montgomery_Params(const BigInt& p, const Modular_Reducer& mod_p);
|
|
|
|
/**
|
|
* Initialize a set of Montgomery reduction parameters. These values
|
|
* can be shared by all values in a specific Montgomery domain.
|
|
*/
|
|
Montgomery_Params(const BigInt& p);
|
|
|
|
const BigInt& p() const { return m_p; }
|
|
const BigInt& R1() const { return m_r1; }
|
|
const BigInt& R2() const { return m_r2; }
|
|
const BigInt& R3() const { return m_r3; }
|
|
|
|
word p_dash() const { return m_p_dash; }
|
|
|
|
size_t p_words() const { return m_p_words; }
|
|
|
|
BigInt redc(const BigInt& x,
|
|
secure_vector<word>& ws) const;
|
|
|
|
BigInt mul(const BigInt& x,
|
|
const BigInt& y,
|
|
secure_vector<word>& ws) const;
|
|
|
|
BigInt mul(const BigInt& x,
|
|
const secure_vector<word>& y,
|
|
secure_vector<word>& ws) const;
|
|
|
|
void mul_by(BigInt& x,
|
|
const secure_vector<word>& y,
|
|
secure_vector<word>& ws) const;
|
|
|
|
void mul_by(BigInt& x, const BigInt& y,
|
|
secure_vector<word>& ws) const;
|
|
|
|
BigInt sqr(const BigInt& x,
|
|
secure_vector<word>& ws) const;
|
|
|
|
void square_this(BigInt& x,
|
|
secure_vector<word>& ws) const;
|
|
|
|
BigInt inv_mod_p(const BigInt& x) const;
|
|
|
|
private:
|
|
BigInt m_p;
|
|
BigInt m_r1;
|
|
BigInt m_r2;
|
|
BigInt m_r3;
|
|
word m_p_dash;
|
|
size_t m_p_words;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(mul128.h)
|
|
|
|
namespace Botan {
|
|
|
|
#if defined(__SIZEOF_INT128__) && defined(BOTAN_TARGET_CPU_HAS_NATIVE_64BIT)
|
|
#define BOTAN_TARGET_HAS_NATIVE_UINT128
|
|
|
|
// Prefer TI mode over __int128 as GCC rejects the latter in pendantic mode
|
|
#if defined(__GNUG__)
|
|
typedef unsigned int uint128_t __attribute__((mode(TI)));
|
|
#else
|
|
typedef unsigned __int128 uint128_t;
|
|
#endif
|
|
#endif
|
|
|
|
}
|
|
|
|
#if defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
|
|
|
|
#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) \
|
|
do { \
|
|
const uint128_t r = static_cast<uint128_t>(a) * b; \
|
|
*hi = (r >> 64) & 0xFFFFFFFFFFFFFFFF; \
|
|
*lo = (r ) & 0xFFFFFFFFFFFFFFFF; \
|
|
} while(0)
|
|
|
|
#elif defined(BOTAN_BUILD_COMPILER_IS_MSVC) && defined(BOTAN_TARGET_CPU_HAS_NATIVE_64BIT)
|
|
|
|
#include <intrin.h>
|
|
#pragma intrinsic(_umul128)
|
|
|
|
#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) \
|
|
do { *lo = _umul128(a, b, hi); } while(0)
|
|
|
|
#elif defined(BOTAN_USE_GCC_INLINE_ASM)
|
|
|
|
#if defined(BOTAN_TARGET_ARCH_IS_X86_64)
|
|
|
|
#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) do { \
|
|
asm("mulq %3" : "=d" (*hi), "=a" (*lo) : "a" (a), "rm" (b) : "cc"); \
|
|
} while(0)
|
|
|
|
#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA)
|
|
|
|
#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) do { \
|
|
asm("umulh %1,%2,%0" : "=r" (*hi) : "r" (a), "r" (b)); \
|
|
*lo = a * b; \
|
|
} while(0)
|
|
|
|
#elif defined(BOTAN_TARGET_ARCH_IS_IA64)
|
|
|
|
#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) do { \
|
|
asm("xmpy.hu %0=%1,%2" : "=f" (*hi) : "f" (a), "f" (b)); \
|
|
*lo = a * b; \
|
|
} while(0)
|
|
|
|
#elif defined(BOTAN_TARGET_ARCH_IS_PPC64)
|
|
|
|
#define BOTAN_FAST_64X64_MUL(a,b,lo,hi) do { \
|
|
asm("mulhdu %0,%1,%2" : "=r" (*hi) : "r" (a), "r" (b) : "cc"); \
|
|
*lo = a * b; \
|
|
} while(0)
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Perform a 64x64->128 bit multiplication
|
|
*/
|
|
inline void mul64x64_128(uint64_t a, uint64_t b, uint64_t* lo, uint64_t* hi)
|
|
{
|
|
#if defined(BOTAN_FAST_64X64_MUL)
|
|
BOTAN_FAST_64X64_MUL(a, b, lo, hi);
|
|
#else
|
|
|
|
/*
|
|
* Do a 64x64->128 multiply using four 32x32->64 multiplies plus
|
|
* some adds and shifts. Last resort for CPUs like UltraSPARC (with
|
|
* 64-bit registers/ALU, but no 64x64->128 multiply) or 32-bit CPUs.
|
|
*/
|
|
const size_t HWORD_BITS = 32;
|
|
const uint32_t HWORD_MASK = 0xFFFFFFFF;
|
|
|
|
const uint32_t a_hi = (a >> HWORD_BITS);
|
|
const uint32_t a_lo = (a & HWORD_MASK);
|
|
const uint32_t b_hi = (b >> HWORD_BITS);
|
|
const uint32_t b_lo = (b & HWORD_MASK);
|
|
|
|
uint64_t x0 = static_cast<uint64_t>(a_hi) * b_hi;
|
|
uint64_t x1 = static_cast<uint64_t>(a_lo) * b_hi;
|
|
uint64_t x2 = static_cast<uint64_t>(a_hi) * b_lo;
|
|
uint64_t x3 = static_cast<uint64_t>(a_lo) * b_lo;
|
|
|
|
// this cannot overflow as (2^32-1)^2 + 2^32-1 < 2^64-1
|
|
x2 += x3 >> HWORD_BITS;
|
|
|
|
// this one can overflow
|
|
x2 += x1;
|
|
|
|
// propagate the carry if any
|
|
x0 += static_cast<uint64_t>(static_cast<bool>(x2 < x1)) << HWORD_BITS;
|
|
|
|
*hi = x0 + (x2 >> HWORD_BITS);
|
|
*lo = ((x2 & HWORD_MASK) << HWORD_BITS) + (x3 & HWORD_MASK);
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class BlockCipher;
|
|
|
|
/**
|
|
* Key wrap. See RFC 3394 and NIST SP800-38F
|
|
* @param input the value to be encrypted
|
|
* @param input_len length of input, must be a multiple of 8
|
|
* @param bc a keyed 128-bit block cipher that will be used to encrypt input
|
|
* @return input encrypted under NIST key wrap algorithm
|
|
*/
|
|
std::vector<uint8_t> BOTAN_PUBLIC_API(2,4)
|
|
nist_key_wrap(const uint8_t input[],
|
|
size_t input_len,
|
|
const BlockCipher& bc);
|
|
|
|
/**
|
|
* @param input the value to be decrypted, output of nist_key_wrap
|
|
* @param input_len length of input
|
|
* @param bc a keyed 128-bit block cipher that will be used to decrypt input
|
|
* @return input decrypted under NIST key wrap algorithm
|
|
* Throws an exception if decryption fails.
|
|
*/
|
|
secure_vector<uint8_t> BOTAN_PUBLIC_API(2,4)
|
|
nist_key_unwrap(const uint8_t input[],
|
|
size_t input_len,
|
|
const BlockCipher& bc);
|
|
|
|
/**
|
|
* KWP (key wrap with padding). See RFC 5649 and NIST SP800-38F
|
|
* @param input the value to be encrypted
|
|
* @param input_len length of input
|
|
* @param bc a keyed 128-bit block cipher that will be used to encrypt input
|
|
* @return input encrypted under NIST key wrap algorithm
|
|
*/
|
|
std::vector<uint8_t> BOTAN_PUBLIC_API(2,4)
|
|
nist_key_wrap_padded(const uint8_t input[],
|
|
size_t input_len,
|
|
const BlockCipher& bc);
|
|
|
|
/**
|
|
* @param input the value to be decrypted, output of nist_key_wrap
|
|
* @param input_len length of input
|
|
* @param bc a keyed 128-bit block cipher that will be used to decrypt input
|
|
* @return input decrypted under NIST key wrap algorithm
|
|
* Throws an exception if decryption fails.
|
|
*/
|
|
secure_vector<uint8_t> BOTAN_PUBLIC_API(2,4)
|
|
nist_key_unwrap_padded(const uint8_t input[],
|
|
size_t input_len,
|
|
const BlockCipher& bc);
|
|
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(noekeon.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Noekeon
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Noekeon final : public Block_Cipher_Fixed_Params<16, 16>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
std::string provider() const override;
|
|
void clear() override;
|
|
std::string name() const override { return "Noekeon"; }
|
|
BlockCipher* clone() const override { return new Noekeon; }
|
|
size_t parallelism() const override;
|
|
|
|
private:
|
|
#if defined(BOTAN_HAS_NOEKEON_SIMD)
|
|
void simd_encrypt_4(const uint8_t in[], uint8_t out[]) const;
|
|
void simd_decrypt_4(const uint8_t in[], uint8_t out[]) const;
|
|
#endif
|
|
|
|
/**
|
|
* The Noekeon round constants
|
|
*/
|
|
static const uint8_t RC[17];
|
|
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
secure_vector<uint32_t> m_EK, m_DK;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(oaep.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* OAEP (called EME1 in IEEE 1363 and in earlier versions of the library)
|
|
* as specified in PKCS#1 v2.0 (RFC 2437)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) OAEP final : public EME
|
|
{
|
|
public:
|
|
size_t maximum_input_size(size_t) const override;
|
|
|
|
/**
|
|
* @param hash function to use for hashing (takes ownership)
|
|
* @param P an optional label. Normally empty.
|
|
*/
|
|
OAEP(HashFunction* hash, const std::string& P = "");
|
|
|
|
/**
|
|
* @param hash function to use for hashing (takes ownership)
|
|
* @param mgf1_hash function to use for MGF1 (takes ownership)
|
|
* @param P an optional label. Normally empty.
|
|
*/
|
|
OAEP(HashFunction* hash,
|
|
HashFunction* mgf1_hash,
|
|
const std::string& P = "");
|
|
private:
|
|
secure_vector<uint8_t> pad(const uint8_t in[],
|
|
size_t in_length,
|
|
size_t key_length,
|
|
RandomNumberGenerator& rng) const override;
|
|
|
|
secure_vector<uint8_t> unpad(uint8_t& valid_mask,
|
|
const uint8_t in[],
|
|
size_t in_len) const override;
|
|
|
|
secure_vector<uint8_t> m_Phash;
|
|
std::unique_ptr<HashFunction> m_mgf1_hash;
|
|
};
|
|
|
|
secure_vector<uint8_t>
|
|
BOTAN_TEST_API oaep_find_delim(uint8_t& valid_mask,
|
|
const uint8_t input[], size_t input_len,
|
|
const secure_vector<uint8_t>& Phash);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(ocb.h)
|
|
|
|
namespace Botan {
|
|
|
|
class BlockCipher;
|
|
class L_computer;
|
|
|
|
/**
|
|
* OCB Mode (base class for OCB_Encryption and OCB_Decryption). Note
|
|
* that OCB is patented, but is freely licensed in some circumstances.
|
|
*
|
|
* @see "The OCB Authenticated-Encryption Algorithm" RFC 7253
|
|
* https://tools.ietf.org/html/rfc7253
|
|
* @see "OCB For Block Ciphers Without 128-Bit Blocks"
|
|
* (draft-krovetz-ocb-wide-d3) for the extension of OCB to
|
|
* block ciphers with larger block sizes.
|
|
* @see Free Licenses http://www.cs.ucdavis.edu/~rogaway/ocb/license.htm
|
|
* @see OCB home page http://www.cs.ucdavis.edu/~rogaway/ocb
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) OCB_Mode : public AEAD_Mode
|
|
{
|
|
public:
|
|
void set_associated_data(const uint8_t ad[], size_t ad_len) override;
|
|
|
|
std::string name() const override;
|
|
|
|
size_t update_granularity() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
bool valid_nonce_length(size_t) const override;
|
|
|
|
size_t tag_size() const override { return m_tag_size; }
|
|
|
|
void clear() override;
|
|
|
|
void reset() override;
|
|
|
|
~OCB_Mode();
|
|
protected:
|
|
/**
|
|
* @param cipher the block cipher to use
|
|
* @param tag_size is how big the auth tag will be
|
|
*/
|
|
OCB_Mode(BlockCipher* cipher, size_t tag_size);
|
|
|
|
size_t block_size() const { return m_block_size; }
|
|
size_t par_blocks() const { return m_par_blocks; }
|
|
size_t par_bytes() const { return m_checksum.size(); }
|
|
|
|
// fixme make these private
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
std::unique_ptr<L_computer> m_L;
|
|
|
|
size_t m_block_index = 0;
|
|
|
|
secure_vector<uint8_t> m_checksum;
|
|
secure_vector<uint8_t> m_ad_hash;
|
|
private:
|
|
void start_msg(const uint8_t nonce[], size_t nonce_len) override;
|
|
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
const secure_vector<uint8_t>& update_nonce(const uint8_t nonce[], size_t nonce_len);
|
|
|
|
const size_t m_tag_size;
|
|
const size_t m_block_size;
|
|
const size_t m_par_blocks;
|
|
secure_vector<uint8_t> m_last_nonce;
|
|
secure_vector<uint8_t> m_stretch;
|
|
secure_vector<uint8_t> m_nonce_buf;
|
|
secure_vector<uint8_t> m_offset;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,0) OCB_Encryption final : public OCB_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher the block cipher to use
|
|
* @param tag_size is how big the auth tag will be
|
|
*/
|
|
OCB_Encryption(BlockCipher* cipher, size_t tag_size = 16) :
|
|
OCB_Mode(cipher, tag_size) {}
|
|
|
|
size_t output_length(size_t input_length) const override
|
|
{ return input_length + tag_size(); }
|
|
|
|
size_t minimum_final_size() const override { return 0; }
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
private:
|
|
void encrypt(uint8_t input[], size_t blocks);
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,0) OCB_Decryption final : public OCB_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher the block cipher to use
|
|
* @param tag_size is how big the auth tag will be
|
|
*/
|
|
OCB_Decryption(BlockCipher* cipher, size_t tag_size = 16) :
|
|
OCB_Mode(cipher, tag_size) {}
|
|
|
|
size_t output_length(size_t input_length) const override
|
|
{
|
|
BOTAN_ASSERT(input_length >= tag_size(), "Sufficient input");
|
|
return input_length - tag_size();
|
|
}
|
|
|
|
size_t minimum_final_size() const override { return tag_size(); }
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
private:
|
|
void decrypt(uint8_t input[], size_t blocks);
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Certificate_Store;
|
|
|
|
namespace OCSP {
|
|
|
|
class BOTAN_PUBLIC_API(2,0) CertID final : public ASN1_Object
|
|
{
|
|
public:
|
|
CertID() = default;
|
|
|
|
CertID(const X509_Certificate& issuer,
|
|
const BigInt& subject_serial);
|
|
|
|
bool is_id_for(const X509_Certificate& issuer,
|
|
const X509_Certificate& subject) const;
|
|
|
|
void encode_into(class DER_Encoder& to) const override;
|
|
|
|
void decode_from(class BER_Decoder& from) override;
|
|
|
|
const std::vector<uint8_t>& issuer_key_hash() const { return m_issuer_key_hash; }
|
|
|
|
private:
|
|
AlgorithmIdentifier m_hash_id;
|
|
std::vector<uint8_t> m_issuer_dn_hash;
|
|
std::vector<uint8_t> m_issuer_key_hash;
|
|
BigInt m_subject_serial;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,0) SingleResponse final : public ASN1_Object
|
|
{
|
|
public:
|
|
const CertID& certid() const { return m_certid; }
|
|
|
|
size_t cert_status() const { return m_cert_status; }
|
|
|
|
X509_Time this_update() const { return m_thisupdate; }
|
|
|
|
X509_Time next_update() const { return m_nextupdate; }
|
|
|
|
void encode_into(class DER_Encoder& to) const override;
|
|
|
|
void decode_from(class BER_Decoder& from) override;
|
|
private:
|
|
CertID m_certid;
|
|
size_t m_cert_status = 2; // unknown
|
|
X509_Time m_thisupdate;
|
|
X509_Time m_nextupdate;
|
|
};
|
|
|
|
/**
|
|
* An OCSP request.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Request final
|
|
{
|
|
public:
|
|
/**
|
|
* Create an OCSP request.
|
|
* @param issuer_cert issuer certificate
|
|
* @param subject_cert subject certificate
|
|
*/
|
|
Request(const X509_Certificate& issuer_cert,
|
|
const X509_Certificate& subject_cert);
|
|
|
|
Request(const X509_Certificate& issuer_cert,
|
|
const BigInt& subject_serial);
|
|
|
|
/**
|
|
* @return BER-encoded OCSP request
|
|
*/
|
|
std::vector<uint8_t> BER_encode() const;
|
|
|
|
/**
|
|
* @return Base64-encoded OCSP request
|
|
*/
|
|
std::string base64_encode() const;
|
|
|
|
/**
|
|
* @return issuer certificate
|
|
*/
|
|
const X509_Certificate& issuer() const { return m_issuer; }
|
|
|
|
/**
|
|
* @return subject certificate
|
|
*/
|
|
const X509_Certificate& subject() const { throw Not_Implemented("Method have been deprecated"); }
|
|
|
|
const std::vector<uint8_t>& issuer_key_hash() const
|
|
{ return m_certid.issuer_key_hash(); }
|
|
private:
|
|
X509_Certificate m_issuer;
|
|
CertID m_certid;
|
|
};
|
|
|
|
/**
|
|
* OCSP response status.
|
|
*
|
|
* see https://tools.ietf.org/html/rfc6960#section-4.2.1
|
|
*/
|
|
enum class Response_Status_Code {
|
|
Successful = 0,
|
|
Malformed_Request = 1,
|
|
Internal_Error = 2,
|
|
Try_Later = 3,
|
|
Sig_Required = 5,
|
|
Unauthorized = 6
|
|
};
|
|
|
|
/**
|
|
* OCSP response.
|
|
*
|
|
* Note this class is only usable as an OCSP client
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Response final
|
|
{
|
|
public:
|
|
/**
|
|
* Creates an empty OCSP response.
|
|
*/
|
|
Response() = default;
|
|
|
|
/**
|
|
* Create a fake OCSP response from a given status code.
|
|
* @param status the status code the check functions will return
|
|
*/
|
|
Response(Certificate_Status_Code status);
|
|
|
|
/**
|
|
* Parses an OCSP response.
|
|
* @param response_bits response bits received
|
|
*/
|
|
Response(const std::vector<uint8_t>& response_bits) :
|
|
Response(response_bits.data(), response_bits.size())
|
|
{}
|
|
|
|
/**
|
|
* Parses an OCSP response.
|
|
* @param response_bits response bits received
|
|
* @param response_bits_len length of response in bytes
|
|
*/
|
|
Response(const uint8_t response_bits[],
|
|
size_t response_bits_len);
|
|
|
|
/**
|
|
* Check signature and return status
|
|
* The optional cert_path is the (already validated!) certificate path of
|
|
* the end entity which is being inquired about
|
|
* @param trust_roots list of certstores containing trusted roots
|
|
* @param cert_path optionally, the (already verified!) certificate path for the certificate
|
|
* this is an OCSP response for. This is necessary to find the correct intermediate CA in
|
|
* some cases.
|
|
*/
|
|
Certificate_Status_Code check_signature(const std::vector<Certificate_Store*>& trust_roots,
|
|
const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path = {}) const;
|
|
|
|
/**
|
|
* Verify that issuer's key signed this response
|
|
* @param issuer certificate of issuer
|
|
* @return if signature valid OCSP_SIGNATURE_OK else an error code
|
|
*/
|
|
Certificate_Status_Code verify_signature(const X509_Certificate& issuer) const;
|
|
|
|
/**
|
|
* @return the status of the response
|
|
*/
|
|
Response_Status_Code status() const { return m_status; }
|
|
|
|
/**
|
|
* @return the time this OCSP response was supposedly produced at
|
|
*/
|
|
const X509_Time& produced_at() const { return m_produced_at; }
|
|
|
|
/**
|
|
* @return DN of signer, if provided in response (may be empty)
|
|
*/
|
|
const X509_DN& signer_name() const { return m_signer_name; }
|
|
|
|
/**
|
|
* @return key hash, if provided in response (may be empty)
|
|
*/
|
|
const std::vector<uint8_t>& signer_key_hash() const { return m_key_hash; }
|
|
|
|
const std::vector<uint8_t>& raw_bits() const { return m_response_bits; }
|
|
|
|
/**
|
|
* Searches the OCSP response for issuer and subject certificate.
|
|
* @param issuer issuer certificate
|
|
* @param subject subject certificate
|
|
* @param ref_time the reference time
|
|
* @param max_age the maximum age the response should be considered valid
|
|
* if next_update is not set
|
|
* @return OCSP status code, possible values:
|
|
* CERT_IS_REVOKED,
|
|
* OCSP_NOT_YET_VALID,
|
|
* OCSP_HAS_EXPIRED,
|
|
* OCSP_IS_TOO_OLD,
|
|
* OCSP_RESPONSE_GOOD,
|
|
* OCSP_BAD_STATUS,
|
|
* OCSP_CERT_NOT_LISTED
|
|
*/
|
|
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(),
|
|
std::chrono::seconds max_age = std::chrono::seconds::zero()) const;
|
|
|
|
/**
|
|
* @return the certificate chain, if provided in response
|
|
*/
|
|
const std::vector<X509_Certificate> &certificates() const { return m_certs; }
|
|
|
|
private:
|
|
Response_Status_Code m_status;
|
|
std::vector<uint8_t> m_response_bits;
|
|
X509_Time m_produced_at;
|
|
X509_DN m_signer_name;
|
|
std::vector<uint8_t> m_key_hash;
|
|
std::vector<uint8_t> m_tbs_bits;
|
|
AlgorithmIdentifier m_sig_algo;
|
|
std::vector<uint8_t> m_signature;
|
|
std::vector<X509_Certificate> m_certs;
|
|
|
|
std::vector<SingleResponse> m_responses;
|
|
|
|
Certificate_Status_Code m_dummy_response_status;
|
|
};
|
|
|
|
#if defined(BOTAN_HAS_HTTP_UTIL)
|
|
|
|
/**
|
|
* Makes an online OCSP request via HTTP and returns the OCSP response.
|
|
* @param issuer issuer certificate
|
|
* @param subject_serial the subject's serial number
|
|
* @param ocsp_responder the OCSP responder to query
|
|
* @param trusted_roots trusted roots for the OCSP response
|
|
* @param timeout a timeout on the HTTP request
|
|
* @return OCSP response
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1)
|
|
Response online_check(const X509_Certificate& issuer,
|
|
const BigInt& subject_serial,
|
|
const std::string& ocsp_responder,
|
|
Certificate_Store* trusted_roots,
|
|
std::chrono::milliseconds timeout = std::chrono::milliseconds(3000));
|
|
|
|
/**
|
|
* Makes an online OCSP request via HTTP and returns the OCSP response.
|
|
* @param issuer issuer certificate
|
|
* @param subject subject certificate
|
|
* @param trusted_roots trusted roots for the OCSP response
|
|
* @param timeout a timeout on the HTTP request
|
|
* @return OCSP response
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0)
|
|
Response online_check(const X509_Certificate& issuer,
|
|
const X509_Certificate& subject,
|
|
Certificate_Store* trusted_roots,
|
|
std::chrono::milliseconds timeout = std::chrono::milliseconds(3000));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(ofb.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Output Feedback Mode
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) OFB final : public StreamCipher
|
|
{
|
|
public:
|
|
void cipher(const uint8_t in[], uint8_t out[], size_t length) override;
|
|
|
|
void set_iv(const uint8_t iv[], size_t iv_len) override;
|
|
|
|
size_t default_iv_length() const override;
|
|
|
|
bool valid_iv_length(size_t iv_len) const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
std::string name() const override;
|
|
|
|
OFB* clone() const override;
|
|
|
|
void clear() override;
|
|
|
|
/**
|
|
* @param cipher the block cipher to use
|
|
*/
|
|
explicit OFB(BlockCipher* cipher);
|
|
|
|
void seek(uint64_t offset) override;
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t key_len) override;
|
|
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
secure_vector<uint8_t> m_buffer;
|
|
size_t m_buf_pos;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace OIDS {
|
|
|
|
/**
|
|
* Register an OID to string mapping.
|
|
* @param oid the oid to register
|
|
* @param name the name to be associated with the oid
|
|
*/
|
|
BOTAN_UNSTABLE_API void add_oid(const OID& oid, const std::string& name);
|
|
|
|
BOTAN_UNSTABLE_API void add_oid2str(const OID& oid, const std::string& name);
|
|
BOTAN_UNSTABLE_API void add_str2oid(const OID& oid, const std::string& name);
|
|
|
|
BOTAN_UNSTABLE_API void add_oidstr(const char* oidstr, const char* name);
|
|
|
|
std::unordered_map<std::string, std::string> load_oid2str_map();
|
|
std::unordered_map<std::string, OID> load_str2oid_map();
|
|
|
|
/**
|
|
* Resolve an OID
|
|
* @param oid the OID to look up
|
|
* @return name associated with this OID, or an empty string
|
|
*/
|
|
BOTAN_UNSTABLE_API std::string oid2str_or_empty(const OID& oid);
|
|
|
|
/**
|
|
* Find the OID to a name. The lookup will be performed in the
|
|
* general OID section of the configuration.
|
|
* @param name the name to resolve
|
|
* @return OID associated with the specified name
|
|
*/
|
|
BOTAN_UNSTABLE_API OID str2oid_or_empty(const std::string& name);
|
|
|
|
BOTAN_UNSTABLE_API std::string oid2str_or_throw(const OID& oid);
|
|
|
|
/**
|
|
* See if an OID exists in the internal table.
|
|
* @param oid the oid to check for
|
|
* @return true if the oid is registered
|
|
*/
|
|
BOTAN_UNSTABLE_API bool BOTAN_DEPRECATED("Just lookup the value instead") have_oid(const std::string& oid);
|
|
|
|
/**
|
|
* Tests whether the specified OID stands for the specified name.
|
|
* @param oid the OID to check
|
|
* @param name the name to check
|
|
* @return true if the specified OID stands for the specified name
|
|
*/
|
|
inline bool BOTAN_DEPRECATED("Use oid == OID::from_string(name)") name_of(const OID& oid, const std::string& name)
|
|
{
|
|
return (oid == str2oid_or_empty(name));
|
|
}
|
|
|
|
/**
|
|
* Prefer oid2str_or_empty
|
|
*/
|
|
inline std::string lookup(const OID& oid)
|
|
{
|
|
return oid2str_or_empty(oid);
|
|
}
|
|
|
|
/**
|
|
* Prefer str2oid_or_empty
|
|
*/
|
|
inline OID lookup(const std::string& name)
|
|
{
|
|
return str2oid_or_empty(name);
|
|
}
|
|
|
|
inline std::string BOTAN_DEPRECATED("Use oid2str_or_empty") oid2str(const OID& oid)
|
|
{
|
|
return oid2str_or_empty(oid);
|
|
}
|
|
|
|
inline OID BOTAN_DEPRECATED("Use str2oid_or_empty") str2oid(const std::string& name)
|
|
{
|
|
return str2oid_or_empty(name);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* HOTP one time passwords (RFC 4226)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) HOTP final
|
|
{
|
|
public:
|
|
/**
|
|
* @param key the secret key shared between client and server
|
|
* @param hash_algo the hash algorithm to use, should be SHA-1 or SHA-256
|
|
* @param digits the number of digits in the OTP (must be 6, 7, or 8)
|
|
*/
|
|
HOTP(const SymmetricKey& key, const std::string& hash_algo = "SHA-1", size_t digits = 6) :
|
|
HOTP(key.begin(), key.size(), hash_algo, digits) {}
|
|
|
|
/**
|
|
* @param key the secret key shared between client and server
|
|
* @param key_len length of key param
|
|
* @param hash_algo the hash algorithm to use, should be SHA-1 or SHA-256
|
|
* @param digits the number of digits in the OTP (must be 6, 7, or 8)
|
|
*/
|
|
HOTP(const uint8_t key[], size_t key_len,
|
|
const std::string& hash_algo = "SHA-1",
|
|
size_t digits = 6);
|
|
|
|
/**
|
|
* Generate the HOTP for a particular counter value
|
|
* @warning if the counter value is repeated the OTP ceases to be one-time
|
|
*/
|
|
uint32_t generate_hotp(uint64_t counter);
|
|
|
|
/**
|
|
* Check an OTP value using a starting counter and a resync range
|
|
* @param otp the client provided OTP
|
|
* @param starting_counter the server's guess as to the current counter state
|
|
* @param resync_range if 0 then only HOTP(starting_counter) is accepted
|
|
* If larger than 0, up to resync_range values after HOTP are also checked.
|
|
* @return (valid,next_counter). If the OTP does not validate, always
|
|
* returns (false,starting_counter). Otherwise returns (true,next_counter)
|
|
* where next_counter is at most starting_counter + resync_range + 1
|
|
*/
|
|
std::pair<bool,uint64_t> verify_hotp(uint32_t otp, uint64_t starting_counter, size_t resync_range = 0);
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
uint32_t m_digit_mod;
|
|
};
|
|
|
|
/**
|
|
* TOTP (time based) one time passwords (RFC 6238)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) TOTP final
|
|
{
|
|
public:
|
|
/**
|
|
* @param key the secret key shared between client and server
|
|
* @param hash_algo the hash algorithm to use, should be SHA-1, SHA-256 or SHA-512
|
|
* @param digits the number of digits in the OTP (must be 6, 7, or 8)
|
|
* @param time_step granularity of OTP in seconds
|
|
*/
|
|
TOTP(const SymmetricKey& key,
|
|
const std::string& hash_algo = "SHA-1",
|
|
size_t digits = 6, size_t time_step = 30) :
|
|
TOTP(key.begin(), key.size(), hash_algo, digits, time_step) {}
|
|
|
|
/**
|
|
* @param key the secret key shared between client and server
|
|
* @param key_len length of key
|
|
* @param hash_algo the hash algorithm to use, should be SHA-1, SHA-256 or SHA-512
|
|
* @param digits the number of digits in the OTP (must be 6, 7, or 8)
|
|
* @param time_step granularity of OTP in seconds
|
|
*/
|
|
TOTP(const uint8_t key[], size_t key_len,
|
|
const std::string& hash_algo = "SHA-1",
|
|
size_t digits = 6,
|
|
size_t time_step = 30);
|
|
|
|
/**
|
|
* Convert the provided time_point to a Unix timestamp and call generate_totp
|
|
*/
|
|
uint32_t generate_totp(std::chrono::system_clock::time_point time_point);
|
|
|
|
/**
|
|
* Generate the OTP corresponding the the provided "Unix timestamp" (ie
|
|
* number of seconds since midnight Jan 1, 1970)
|
|
*/
|
|
uint32_t generate_totp(uint64_t unix_time);
|
|
|
|
bool verify_totp(uint32_t otp,
|
|
std::chrono::system_clock::time_point time,
|
|
size_t clock_drift_accepted = 0);
|
|
|
|
bool verify_totp(uint32_t otp, uint64_t unix_time,
|
|
size_t clock_drift_accepted = 0);
|
|
|
|
private:
|
|
HOTP m_hotp;
|
|
size_t m_time_step;
|
|
std::chrono::system_clock::time_point m_unix_epoch;
|
|
};
|
|
|
|
}
|
|
|
|
|
|
#define CK_PTR *
|
|
|
|
#if defined(_MSC_VER)
|
|
#define CK_DECLARE_FUNCTION(returnType, name) \
|
|
returnType __declspec(dllimport) name
|
|
#else
|
|
#define CK_DECLARE_FUNCTION(returnType, name) \
|
|
returnType name
|
|
#endif
|
|
|
|
#if defined(_MSC_VER)
|
|
#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
|
|
returnType __declspec(dllimport) (* name)
|
|
#else
|
|
#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
|
|
returnType (* name)
|
|
#endif
|
|
|
|
#define CK_CALLBACK_FUNCTION(returnType, name) \
|
|
returnType (* name)
|
|
|
|
#ifndef NULL_PTR
|
|
#define NULL_PTR nullptr
|
|
#endif
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma pack(push, cryptoki, 1)
|
|
#endif
|
|
|
|
#include "pkcs11.h"
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma pack(pop, cryptoki)
|
|
#endif
|
|
|
|
static_assert(CRYPTOKI_VERSION_MAJOR == 2 && CRYPTOKI_VERSION_MINOR == 40,
|
|
"The Botan PKCS#11 module was implemented against PKCS#11 v2.40. Please use the correct PKCS#11 headers.");
|
|
|
|
namespace Botan {
|
|
|
|
class Dynamically_Loaded_Library;
|
|
|
|
namespace PKCS11 {
|
|
|
|
using secure_string = secure_vector<uint8_t>;
|
|
|
|
enum class AttributeType : CK_ATTRIBUTE_TYPE
|
|
{
|
|
Class = CKA_CLASS,
|
|
Token = CKA_TOKEN,
|
|
Private = CKA_PRIVATE,
|
|
Label = CKA_LABEL,
|
|
Application = CKA_APPLICATION,
|
|
Value = CKA_VALUE,
|
|
ObjectId = CKA_OBJECT_ID,
|
|
CertificateType = CKA_CERTIFICATE_TYPE,
|
|
Issuer = CKA_ISSUER,
|
|
SerialNumber = CKA_SERIAL_NUMBER,
|
|
AcIssuer = CKA_AC_ISSUER,
|
|
Owner = CKA_OWNER,
|
|
AttrTypes = CKA_ATTR_TYPES,
|
|
Trusted = CKA_TRUSTED,
|
|
CertificateCategory = CKA_CERTIFICATE_CATEGORY,
|
|
JavaMidpSecurityDomain = CKA_JAVA_MIDP_SECURITY_DOMAIN,
|
|
Url = CKA_URL,
|
|
HashOfSubjectPublicKey = CKA_HASH_OF_SUBJECT_PUBLIC_KEY,
|
|
HashOfIssuerPublicKey = CKA_HASH_OF_ISSUER_PUBLIC_KEY,
|
|
NameHashAlgorithm = CKA_NAME_HASH_ALGORITHM,
|
|
CheckValue = CKA_CHECK_VALUE,
|
|
KeyType = CKA_KEY_TYPE,
|
|
Subject = CKA_SUBJECT,
|
|
Id = CKA_ID,
|
|
Sensitive = CKA_SENSITIVE,
|
|
Encrypt = CKA_ENCRYPT,
|
|
Decrypt = CKA_DECRYPT,
|
|
Wrap = CKA_WRAP,
|
|
Unwrap = CKA_UNWRAP,
|
|
Sign = CKA_SIGN,
|
|
SignRecover = CKA_SIGN_RECOVER,
|
|
Verify = CKA_VERIFY,
|
|
VerifyRecover = CKA_VERIFY_RECOVER,
|
|
Derive = CKA_DERIVE,
|
|
StartDate = CKA_START_DATE,
|
|
EndDate = CKA_END_DATE,
|
|
Modulus = CKA_MODULUS,
|
|
ModulusBits = CKA_MODULUS_BITS,
|
|
PublicExponent = CKA_PUBLIC_EXPONENT,
|
|
PrivateExponent = CKA_PRIVATE_EXPONENT,
|
|
Prime1 = CKA_PRIME_1,
|
|
Prime2 = CKA_PRIME_2,
|
|
Exponent1 = CKA_EXPONENT_1,
|
|
Exponent2 = CKA_EXPONENT_2,
|
|
Coefficient = CKA_COEFFICIENT,
|
|
PublicKeyInfo = CKA_PUBLIC_KEY_INFO,
|
|
Prime = CKA_PRIME,
|
|
Subprime = CKA_SUBPRIME,
|
|
Base = CKA_BASE,
|
|
PrimeBits = CKA_PRIME_BITS,
|
|
SubprimeBits = CKA_SUBPRIME_BITS,
|
|
SubPrimeBits = CKA_SUB_PRIME_BITS,
|
|
ValueBits = CKA_VALUE_BITS,
|
|
ValueLen = CKA_VALUE_LEN,
|
|
Extractable = CKA_EXTRACTABLE,
|
|
Local = CKA_LOCAL,
|
|
NeverExtractable = CKA_NEVER_EXTRACTABLE,
|
|
AlwaysSensitive = CKA_ALWAYS_SENSITIVE,
|
|
KeyGenMechanism = CKA_KEY_GEN_MECHANISM,
|
|
Modifiable = CKA_MODIFIABLE,
|
|
Copyable = CKA_COPYABLE,
|
|
Destroyable = CKA_DESTROYABLE,
|
|
EcdsaParams = CKA_ECDSA_PARAMS,
|
|
EcParams = CKA_EC_PARAMS,
|
|
EcPoint = CKA_EC_POINT,
|
|
SecondaryAuth = CKA_SECONDARY_AUTH,
|
|
AuthPinFlags = CKA_AUTH_PIN_FLAGS,
|
|
AlwaysAuthenticate = CKA_ALWAYS_AUTHENTICATE,
|
|
WrapWithTrusted = CKA_WRAP_WITH_TRUSTED,
|
|
WrapTemplate = CKA_WRAP_TEMPLATE,
|
|
UnwrapTemplate = CKA_UNWRAP_TEMPLATE,
|
|
DeriveTemplate = CKA_DERIVE_TEMPLATE,
|
|
OtpFormat = CKA_OTP_FORMAT,
|
|
OtpLength = CKA_OTP_LENGTH,
|
|
OtpTimeInterval = CKA_OTP_TIME_INTERVAL,
|
|
OtpUserFriendlyMode = CKA_OTP_USER_FRIENDLY_MODE,
|
|
OtpChallengeRequirement = CKA_OTP_CHALLENGE_REQUIREMENT,
|
|
OtpTimeRequirement = CKA_OTP_TIME_REQUIREMENT,
|
|
OtpCounterRequirement = CKA_OTP_COUNTER_REQUIREMENT,
|
|
OtpPinRequirement = CKA_OTP_PIN_REQUIREMENT,
|
|
OtpCounter = CKA_OTP_COUNTER,
|
|
OtpTime = CKA_OTP_TIME,
|
|
OtpUserIdentifier = CKA_OTP_USER_IDENTIFIER,
|
|
OtpServiceIdentifier = CKA_OTP_SERVICE_IDENTIFIER,
|
|
OtpServiceLogo = CKA_OTP_SERVICE_LOGO,
|
|
OtpServiceLogoType = CKA_OTP_SERVICE_LOGO_TYPE,
|
|
Gostr3410Params = CKA_GOSTR3410_PARAMS,
|
|
Gostr3411Params = CKA_GOSTR3411_PARAMS,
|
|
Gost28147Params = CKA_GOST28147_PARAMS,
|
|
HwFeatureType = CKA_HW_FEATURE_TYPE,
|
|
ResetOnInit = CKA_RESET_ON_INIT,
|
|
HasReset = CKA_HAS_RESET,
|
|
PixelX = CKA_PIXEL_X,
|
|
PixelY = CKA_PIXEL_Y,
|
|
Resolution = CKA_RESOLUTION,
|
|
CharRows = CKA_CHAR_ROWS,
|
|
CharColumns = CKA_CHAR_COLUMNS,
|
|
Color = CKA_COLOR,
|
|
BitsPerPixel = CKA_BITS_PER_PIXEL,
|
|
CharSets = CKA_CHAR_SETS,
|
|
EncodingMethods = CKA_ENCODING_METHODS,
|
|
MimeTypes = CKA_MIME_TYPES,
|
|
MechanismType = CKA_MECHANISM_TYPE,
|
|
RequiredCmsAttributes = CKA_REQUIRED_CMS_ATTRIBUTES,
|
|
DefaultCmsAttributes = CKA_DEFAULT_CMS_ATTRIBUTES,
|
|
SupportedCmsAttributes = CKA_SUPPORTED_CMS_ATTRIBUTES,
|
|
AllowedMechanisms = CKA_ALLOWED_MECHANISMS,
|
|
VendorDefined = CKA_VENDOR_DEFINED,
|
|
};
|
|
|
|
enum class CertificateType : CK_CERTIFICATE_TYPE
|
|
{
|
|
X509 = CKC_X_509,
|
|
X509AttrCert = CKC_X_509_ATTR_CERT,
|
|
Wtls = CKC_WTLS,
|
|
VendorDefined = CKC_VENDOR_DEFINED,
|
|
};
|
|
|
|
/// Indicates if a stored certificate is a user certificate for which the corresponding private key is available
|
|
/// on the token ("token user"), a CA certificate ("authority"), or another end-entity certificate ("other entity").
|
|
enum class CertificateCategory : CK_ULONG
|
|
{
|
|
Unspecified = CK_CERTIFICATE_CATEGORY_UNSPECIFIED,
|
|
TokenUser = CK_CERTIFICATE_CATEGORY_TOKEN_USER,
|
|
Authority = CK_CERTIFICATE_CATEGORY_AUTHORITY,
|
|
OtherEntity = CK_CERTIFICATE_CATEGORY_OTHER_ENTITY
|
|
};
|
|
|
|
enum class KeyDerivation : CK_ULONG
|
|
{
|
|
Null = CKD_NULL,
|
|
Sha1Kdf = CKD_SHA1_KDF,
|
|
Sha1KdfAsn1 = CKD_SHA1_KDF_ASN1,
|
|
Sha1KdfConcatenate = CKD_SHA1_KDF_CONCATENATE,
|
|
Sha224Kdf = CKD_SHA224_KDF,
|
|
Sha256Kdf = CKD_SHA256_KDF,
|
|
Sha384Kdf = CKD_SHA384_KDF,
|
|
Sha512Kdf = CKD_SHA512_KDF,
|
|
CpdiversifyKdf = CKD_CPDIVERSIFY_KDF,
|
|
};
|
|
|
|
enum class Flag : CK_FLAGS
|
|
{
|
|
None = 0,
|
|
TokenPresent = CKF_TOKEN_PRESENT,
|
|
RemovableDevice = CKF_REMOVABLE_DEVICE,
|
|
HwSlot = CKF_HW_SLOT,
|
|
Rng = CKF_RNG,
|
|
WriteProtected = CKF_WRITE_PROTECTED,
|
|
LoginRequired = CKF_LOGIN_REQUIRED,
|
|
UserPinInitialized = CKF_USER_PIN_INITIALIZED,
|
|
RestoreKeyNotNeeded = CKF_RESTORE_KEY_NOT_NEEDED,
|
|
ClockOnToken = CKF_CLOCK_ON_TOKEN,
|
|
ProtectedAuthenticationPath = CKF_PROTECTED_AUTHENTICATION_PATH,
|
|
DualCryptoOperations = CKF_DUAL_CRYPTO_OPERATIONS,
|
|
TokenInitialized = CKF_TOKEN_INITIALIZED,
|
|
SecondaryAuthentication = CKF_SECONDARY_AUTHENTICATION,
|
|
UserPinCountLow = CKF_USER_PIN_COUNT_LOW,
|
|
UserPinFinalTry = CKF_USER_PIN_FINAL_TRY,
|
|
UserPinLocked = CKF_USER_PIN_LOCKED,
|
|
UserPinToBeChanged = CKF_USER_PIN_TO_BE_CHANGED,
|
|
SoPinCountLow = CKF_SO_PIN_COUNT_LOW,
|
|
SoPinFinalTry = CKF_SO_PIN_FINAL_TRY,
|
|
SoPinLocked = CKF_SO_PIN_LOCKED,
|
|
SoPinToBeChanged = CKF_SO_PIN_TO_BE_CHANGED,
|
|
ErrorState = CKF_ERROR_STATE,
|
|
RwSession = CKF_RW_SESSION,
|
|
SerialSession = CKF_SERIAL_SESSION,
|
|
ArrayAttribute = CKF_ARRAY_ATTRIBUTE,
|
|
Hw = CKF_HW,
|
|
Encrypt = CKF_ENCRYPT,
|
|
Decrypt = CKF_DECRYPT,
|
|
Digest = CKF_DIGEST,
|
|
Sign = CKF_SIGN,
|
|
SignRecover = CKF_SIGN_RECOVER,
|
|
Verify = CKF_VERIFY,
|
|
VerifyRecover = CKF_VERIFY_RECOVER,
|
|
Generate = CKF_GENERATE,
|
|
GenerateKeyPair = CKF_GENERATE_KEY_PAIR,
|
|
Wrap = CKF_WRAP,
|
|
Unwrap = CKF_UNWRAP,
|
|
Derive = CKF_DERIVE,
|
|
EcFP = CKF_EC_F_P,
|
|
EcF2m = CKF_EC_F_2M,
|
|
EcEcparameters = CKF_EC_ECPARAMETERS,
|
|
EcNamedcurve = CKF_EC_NAMEDCURVE,
|
|
EcUncompress = CKF_EC_UNCOMPRESS,
|
|
EcCompress = CKF_EC_COMPRESS,
|
|
Extension = CKF_EXTENSION,
|
|
LibraryCantCreateOsThreads = CKF_LIBRARY_CANT_CREATE_OS_THREADS,
|
|
OsLockingOk = CKF_OS_LOCKING_OK,
|
|
DontBlock = CKF_DONT_BLOCK,
|
|
NextOtp = CKF_NEXT_OTP,
|
|
ExcludeTime = CKF_EXCLUDE_TIME,
|
|
ExcludeCounter = CKF_EXCLUDE_COUNTER,
|
|
ExcludeChallenge = CKF_EXCLUDE_CHALLENGE,
|
|
ExcludePin = CKF_EXCLUDE_PIN,
|
|
UserFriendlyOtp = CKF_USER_FRIENDLY_OTP,
|
|
};
|
|
|
|
inline Flag operator | (Flag a, Flag b)
|
|
{
|
|
return static_cast< Flag >(static_cast< CK_FLAGS >(a) | static_cast< CK_FLAGS >(b));
|
|
}
|
|
|
|
enum class MGF : CK_RSA_PKCS_MGF_TYPE
|
|
{
|
|
Mgf1Sha1 = CKG_MGF1_SHA1,
|
|
Mgf1Sha256 = CKG_MGF1_SHA256,
|
|
Mgf1Sha384 = CKG_MGF1_SHA384,
|
|
Mgf1Sha512 = CKG_MGF1_SHA512,
|
|
Mgf1Sha224 = CKG_MGF1_SHA224,
|
|
};
|
|
|
|
enum class HardwareType : CK_HW_FEATURE_TYPE
|
|
{
|
|
MonotonicCounter = CKH_MONOTONIC_COUNTER,
|
|
Clock = CKH_CLOCK,
|
|
UserInterface = CKH_USER_INTERFACE,
|
|
VendorDefined = CKH_VENDOR_DEFINED,
|
|
};
|
|
|
|
enum class KeyType : CK_KEY_TYPE
|
|
{
|
|
Rsa = CKK_RSA,
|
|
Dsa = CKK_DSA,
|
|
Dh = CKK_DH,
|
|
Ecdsa = CKK_ECDSA,
|
|
Ec = CKK_EC,
|
|
X942Dh = CKK_X9_42_DH,
|
|
Kea = CKK_KEA,
|
|
GenericSecret = CKK_GENERIC_SECRET,
|
|
Rc2 = CKK_RC2,
|
|
Rc4 = CKK_RC4,
|
|
Des = CKK_DES,
|
|
Des2 = CKK_DES2,
|
|
Des3 = CKK_DES3,
|
|
Cast = CKK_CAST,
|
|
Cast3 = CKK_CAST3,
|
|
Cast5 = CKK_CAST5,
|
|
Cast128 = CKK_CAST128,
|
|
Rc5 = CKK_RC5,
|
|
Idea = CKK_IDEA,
|
|
Skipjack = CKK_SKIPJACK,
|
|
Baton = CKK_BATON,
|
|
Juniper = CKK_JUNIPER,
|
|
Cdmf = CKK_CDMF,
|
|
Aes = CKK_AES,
|
|
Blowfish = CKK_BLOWFISH,
|
|
Twofish = CKK_TWOFISH,
|
|
Securid = CKK_SECURID,
|
|
Hotp = CKK_HOTP,
|
|
Acti = CKK_ACTI,
|
|
Camellia = CKK_CAMELLIA,
|
|
Aria = CKK_ARIA,
|
|
Md5Hmac = CKK_MD5_HMAC,
|
|
Sha1Hmac = CKK_SHA_1_HMAC,
|
|
Ripemd128Hmac = CKK_RIPEMD128_HMAC,
|
|
Ripemd160Hmac = CKK_RIPEMD160_HMAC,
|
|
Sha256Hmac = CKK_SHA256_HMAC,
|
|
Sha384Hmac = CKK_SHA384_HMAC,
|
|
Sha512Hmac = CKK_SHA512_HMAC,
|
|
Sha224Hmac = CKK_SHA224_HMAC,
|
|
Seed = CKK_SEED,
|
|
Gostr3410 = CKK_GOSTR3410,
|
|
Gostr3411 = CKK_GOSTR3411,
|
|
Gost28147 = CKK_GOST28147,
|
|
VendorDefined = CKK_VENDOR_DEFINED,
|
|
};
|
|
|
|
enum class MechanismType : CK_MECHANISM_TYPE
|
|
{
|
|
RsaPkcsKeyPairGen = CKM_RSA_PKCS_KEY_PAIR_GEN,
|
|
RsaPkcs = CKM_RSA_PKCS,
|
|
Rsa9796 = CKM_RSA_9796,
|
|
RsaX509 = CKM_RSA_X_509,
|
|
Md2RsaPkcs = CKM_MD2_RSA_PKCS,
|
|
Md5RsaPkcs = CKM_MD5_RSA_PKCS,
|
|
Sha1RsaPkcs = CKM_SHA1_RSA_PKCS,
|
|
Ripemd128RsaPkcs = CKM_RIPEMD128_RSA_PKCS,
|
|
Ripemd160RsaPkcs = CKM_RIPEMD160_RSA_PKCS,
|
|
RsaPkcsOaep = CKM_RSA_PKCS_OAEP,
|
|
RsaX931KeyPairGen = CKM_RSA_X9_31_KEY_PAIR_GEN,
|
|
RsaX931 = CKM_RSA_X9_31,
|
|
Sha1RsaX931 = CKM_SHA1_RSA_X9_31,
|
|
RsaPkcsPss = CKM_RSA_PKCS_PSS,
|
|
Sha1RsaPkcsPss = CKM_SHA1_RSA_PKCS_PSS,
|
|
DsaKeyPairGen = CKM_DSA_KEY_PAIR_GEN,
|
|
Dsa = CKM_DSA,
|
|
DsaSha1 = CKM_DSA_SHA1,
|
|
DsaSha224 = CKM_DSA_SHA224,
|
|
DsaSha256 = CKM_DSA_SHA256,
|
|
DsaSha384 = CKM_DSA_SHA384,
|
|
DsaSha512 = CKM_DSA_SHA512,
|
|
DhPkcsKeyPairGen = CKM_DH_PKCS_KEY_PAIR_GEN,
|
|
DhPkcsDerive = CKM_DH_PKCS_DERIVE,
|
|
X942DhKeyPairGen = CKM_X9_42_DH_KEY_PAIR_GEN,
|
|
X942DhDerive = CKM_X9_42_DH_DERIVE,
|
|
X942DhHybridDerive = CKM_X9_42_DH_HYBRID_DERIVE,
|
|
X942MqvDerive = CKM_X9_42_MQV_DERIVE,
|
|
Sha256RsaPkcs = CKM_SHA256_RSA_PKCS,
|
|
Sha384RsaPkcs = CKM_SHA384_RSA_PKCS,
|
|
Sha512RsaPkcs = CKM_SHA512_RSA_PKCS,
|
|
Sha256RsaPkcsPss = CKM_SHA256_RSA_PKCS_PSS,
|
|
Sha384RsaPkcsPss = CKM_SHA384_RSA_PKCS_PSS,
|
|
Sha512RsaPkcsPss = CKM_SHA512_RSA_PKCS_PSS,
|
|
Sha224RsaPkcs = CKM_SHA224_RSA_PKCS,
|
|
Sha224RsaPkcsPss = CKM_SHA224_RSA_PKCS_PSS,
|
|
Sha512224 = CKM_SHA512_224,
|
|
Sha512224Hmac = CKM_SHA512_224_HMAC,
|
|
Sha512224HmacGeneral = CKM_SHA512_224_HMAC_GENERAL,
|
|
Sha512224KeyDerivation = CKM_SHA512_224_KEY_DERIVATION,
|
|
Sha512256 = CKM_SHA512_256,
|
|
Sha512256Hmac = CKM_SHA512_256_HMAC,
|
|
Sha512256HmacGeneral = CKM_SHA512_256_HMAC_GENERAL,
|
|
Sha512256KeyDerivation = CKM_SHA512_256_KEY_DERIVATION,
|
|
Sha512T = CKM_SHA512_T,
|
|
Sha512THmac = CKM_SHA512_T_HMAC,
|
|
Sha512THmacGeneral = CKM_SHA512_T_HMAC_GENERAL,
|
|
Sha512TKeyDerivation = CKM_SHA512_T_KEY_DERIVATION,
|
|
Rc2KeyGen = CKM_RC2_KEY_GEN,
|
|
Rc2Ecb = CKM_RC2_ECB,
|
|
Rc2Cbc = CKM_RC2_CBC,
|
|
Rc2Mac = CKM_RC2_MAC,
|
|
Rc2MacGeneral = CKM_RC2_MAC_GENERAL,
|
|
Rc2CbcPad = CKM_RC2_CBC_PAD,
|
|
Rc4KeyGen = CKM_RC4_KEY_GEN,
|
|
Rc4 = CKM_RC4,
|
|
DesKeyGen = CKM_DES_KEY_GEN,
|
|
DesEcb = CKM_DES_ECB,
|
|
DesCbc = CKM_DES_CBC,
|
|
DesMac = CKM_DES_MAC,
|
|
DesMacGeneral = CKM_DES_MAC_GENERAL,
|
|
DesCbcPad = CKM_DES_CBC_PAD,
|
|
Des2KeyGen = CKM_DES2_KEY_GEN,
|
|
Des3KeyGen = CKM_DES3_KEY_GEN,
|
|
Des3Ecb = CKM_DES3_ECB,
|
|
Des3Cbc = CKM_DES3_CBC,
|
|
Des3Mac = CKM_DES3_MAC,
|
|
Des3MacGeneral = CKM_DES3_MAC_GENERAL,
|
|
Des3CbcPad = CKM_DES3_CBC_PAD,
|
|
Des3CmacGeneral = CKM_DES3_CMAC_GENERAL,
|
|
Des3Cmac = CKM_DES3_CMAC,
|
|
CdmfKeyGen = CKM_CDMF_KEY_GEN,
|
|
CdmfEcb = CKM_CDMF_ECB,
|
|
CdmfCbc = CKM_CDMF_CBC,
|
|
CdmfMac = CKM_CDMF_MAC,
|
|
CdmfMacGeneral = CKM_CDMF_MAC_GENERAL,
|
|
CdmfCbcPad = CKM_CDMF_CBC_PAD,
|
|
DesOfb64 = CKM_DES_OFB64,
|
|
DesOfb8 = CKM_DES_OFB8,
|
|
DesCfb64 = CKM_DES_CFB64,
|
|
DesCfb8 = CKM_DES_CFB8,
|
|
Md2 = CKM_MD2,
|
|
Md2Hmac = CKM_MD2_HMAC,
|
|
Md2HmacGeneral = CKM_MD2_HMAC_GENERAL,
|
|
Md5 = CKM_MD5,
|
|
Md5Hmac = CKM_MD5_HMAC,
|
|
Md5HmacGeneral = CKM_MD5_HMAC_GENERAL,
|
|
Sha1 = CKM_SHA_1,
|
|
Sha1Hmac = CKM_SHA_1_HMAC,
|
|
Sha1HmacGeneral = CKM_SHA_1_HMAC_GENERAL,
|
|
Ripemd128 = CKM_RIPEMD128,
|
|
Ripemd128Hmac = CKM_RIPEMD128_HMAC,
|
|
Ripemd128HmacGeneral = CKM_RIPEMD128_HMAC_GENERAL,
|
|
Ripemd160 = CKM_RIPEMD160,
|
|
Ripemd160Hmac = CKM_RIPEMD160_HMAC,
|
|
Ripemd160HmacGeneral = CKM_RIPEMD160_HMAC_GENERAL,
|
|
Sha256 = CKM_SHA256,
|
|
Sha256Hmac = CKM_SHA256_HMAC,
|
|
Sha256HmacGeneral = CKM_SHA256_HMAC_GENERAL,
|
|
Sha224 = CKM_SHA224,
|
|
Sha224Hmac = CKM_SHA224_HMAC,
|
|
Sha224HmacGeneral = CKM_SHA224_HMAC_GENERAL,
|
|
Sha384 = CKM_SHA384,
|
|
Sha384Hmac = CKM_SHA384_HMAC,
|
|
Sha384HmacGeneral = CKM_SHA384_HMAC_GENERAL,
|
|
Sha512 = CKM_SHA512,
|
|
Sha512Hmac = CKM_SHA512_HMAC,
|
|
Sha512HmacGeneral = CKM_SHA512_HMAC_GENERAL,
|
|
SecuridKeyGen = CKM_SECURID_KEY_GEN,
|
|
Securid = CKM_SECURID,
|
|
HotpKeyGen = CKM_HOTP_KEY_GEN,
|
|
Hotp = CKM_HOTP,
|
|
Acti = CKM_ACTI,
|
|
ActiKeyGen = CKM_ACTI_KEY_GEN,
|
|
CastKeyGen = CKM_CAST_KEY_GEN,
|
|
CastEcb = CKM_CAST_ECB,
|
|
CastCbc = CKM_CAST_CBC,
|
|
CastMac = CKM_CAST_MAC,
|
|
CastMacGeneral = CKM_CAST_MAC_GENERAL,
|
|
CastCbcPad = CKM_CAST_CBC_PAD,
|
|
Cast3KeyGen = CKM_CAST3_KEY_GEN,
|
|
Cast3Ecb = CKM_CAST3_ECB,
|
|
Cast3Cbc = CKM_CAST3_CBC,
|
|
Cast3Mac = CKM_CAST3_MAC,
|
|
Cast3MacGeneral = CKM_CAST3_MAC_GENERAL,
|
|
Cast3CbcPad = CKM_CAST3_CBC_PAD,
|
|
Cast5KeyGen = CKM_CAST5_KEY_GEN,
|
|
Cast128KeyGen = CKM_CAST128_KEY_GEN,
|
|
Cast5Ecb = CKM_CAST5_ECB,
|
|
Cast128Ecb = CKM_CAST128_ECB,
|
|
Cast5Cbc = CKM_CAST5_CBC,
|
|
Cast128Cbc = CKM_CAST128_CBC,
|
|
Cast5Mac = CKM_CAST5_MAC,
|
|
Cast128Mac = CKM_CAST128_MAC,
|
|
Cast5MacGeneral = CKM_CAST5_MAC_GENERAL,
|
|
Cast128MacGeneral = CKM_CAST128_MAC_GENERAL,
|
|
Cast5CbcPad = CKM_CAST5_CBC_PAD,
|
|
Cast128CbcPad = CKM_CAST128_CBC_PAD,
|
|
Rc5KeyGen = CKM_RC5_KEY_GEN,
|
|
Rc5Ecb = CKM_RC5_ECB,
|
|
Rc5Cbc = CKM_RC5_CBC,
|
|
Rc5Mac = CKM_RC5_MAC,
|
|
Rc5MacGeneral = CKM_RC5_MAC_GENERAL,
|
|
Rc5CbcPad = CKM_RC5_CBC_PAD,
|
|
IdeaKeyGen = CKM_IDEA_KEY_GEN,
|
|
IdeaEcb = CKM_IDEA_ECB,
|
|
IdeaCbc = CKM_IDEA_CBC,
|
|
IdeaMac = CKM_IDEA_MAC,
|
|
IdeaMacGeneral = CKM_IDEA_MAC_GENERAL,
|
|
IdeaCbcPad = CKM_IDEA_CBC_PAD,
|
|
GenericSecretKeyGen = CKM_GENERIC_SECRET_KEY_GEN,
|
|
ConcatenateBaseAndKey = CKM_CONCATENATE_BASE_AND_KEY,
|
|
ConcatenateBaseAndData = CKM_CONCATENATE_BASE_AND_DATA,
|
|
ConcatenateDataAndBase = CKM_CONCATENATE_DATA_AND_BASE,
|
|
XorBaseAndData = CKM_XOR_BASE_AND_DATA,
|
|
ExtractKeyFromKey = CKM_EXTRACT_KEY_FROM_KEY,
|
|
Ssl3PreMasterKeyGen = CKM_SSL3_PRE_MASTER_KEY_GEN,
|
|
Ssl3MasterKeyDerive = CKM_SSL3_MASTER_KEY_DERIVE,
|
|
Ssl3KeyAndMacDerive = CKM_SSL3_KEY_AND_MAC_DERIVE,
|
|
Ssl3MasterKeyDeriveDh = CKM_SSL3_MASTER_KEY_DERIVE_DH,
|
|
TlsPreMasterKeyGen = CKM_TLS_PRE_MASTER_KEY_GEN,
|
|
TlsMasterKeyDerive = CKM_TLS_MASTER_KEY_DERIVE,
|
|
TlsKeyAndMacDerive = CKM_TLS_KEY_AND_MAC_DERIVE,
|
|
TlsMasterKeyDeriveDh = CKM_TLS_MASTER_KEY_DERIVE_DH,
|
|
TlsPrf = CKM_TLS_PRF,
|
|
Ssl3Md5Mac = CKM_SSL3_MD5_MAC,
|
|
Ssl3Sha1Mac = CKM_SSL3_SHA1_MAC,
|
|
Md5KeyDerivation = CKM_MD5_KEY_DERIVATION,
|
|
Md2KeyDerivation = CKM_MD2_KEY_DERIVATION,
|
|
Sha1KeyDerivation = CKM_SHA1_KEY_DERIVATION,
|
|
Sha256KeyDerivation = CKM_SHA256_KEY_DERIVATION,
|
|
Sha384KeyDerivation = CKM_SHA384_KEY_DERIVATION,
|
|
Sha512KeyDerivation = CKM_SHA512_KEY_DERIVATION,
|
|
Sha224KeyDerivation = CKM_SHA224_KEY_DERIVATION,
|
|
PbeMd2DesCbc = CKM_PBE_MD2_DES_CBC,
|
|
PbeMd5DesCbc = CKM_PBE_MD5_DES_CBC,
|
|
PbeMd5CastCbc = CKM_PBE_MD5_CAST_CBC,
|
|
PbeMd5Cast3Cbc = CKM_PBE_MD5_CAST3_CBC,
|
|
PbeMd5Cast5Cbc = CKM_PBE_MD5_CAST5_CBC,
|
|
PbeMd5Cast128Cbc = CKM_PBE_MD5_CAST128_CBC,
|
|
PbeSha1Cast5Cbc = CKM_PBE_SHA1_CAST5_CBC,
|
|
PbeSha1Cast128Cbc = CKM_PBE_SHA1_CAST128_CBC,
|
|
PbeSha1Rc4128 = CKM_PBE_SHA1_RC4_128,
|
|
PbeSha1Rc440 = CKM_PBE_SHA1_RC4_40,
|
|
PbeSha1Des3EdeCbc = CKM_PBE_SHA1_DES3_EDE_CBC,
|
|
PbeSha1Des2EdeCbc = CKM_PBE_SHA1_DES2_EDE_CBC,
|
|
PbeSha1Rc2128Cbc = CKM_PBE_SHA1_RC2_128_CBC,
|
|
PbeSha1Rc240Cbc = CKM_PBE_SHA1_RC2_40_CBC,
|
|
Pkcs5Pbkd2 = CKM_PKCS5_PBKD2,
|
|
PbaSha1WithSha1Hmac = CKM_PBA_SHA1_WITH_SHA1_HMAC,
|
|
WtlsPreMasterKeyGen = CKM_WTLS_PRE_MASTER_KEY_GEN,
|
|
WtlsMasterKeyDerive = CKM_WTLS_MASTER_KEY_DERIVE,
|
|
WtlsMasterKeyDeriveDhEcc = CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC,
|
|
WtlsPrf = CKM_WTLS_PRF,
|
|
WtlsServerKeyAndMacDerive = CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE,
|
|
WtlsClientKeyAndMacDerive = CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE,
|
|
Tls10MacServer = CKM_TLS10_MAC_SERVER,
|
|
Tls10MacClient = CKM_TLS10_MAC_CLIENT,
|
|
Tls12Mac = CKM_TLS12_MAC,
|
|
Tls12Kdf = CKM_TLS12_KDF,
|
|
Tls12MasterKeyDerive = CKM_TLS12_MASTER_KEY_DERIVE,
|
|
Tls12KeyAndMacDerive = CKM_TLS12_KEY_AND_MAC_DERIVE,
|
|
Tls12MasterKeyDeriveDh = CKM_TLS12_MASTER_KEY_DERIVE_DH,
|
|
Tls12KeySafeDerive = CKM_TLS12_KEY_SAFE_DERIVE,
|
|
TlsMac = CKM_TLS_MAC,
|
|
TlsKdf = CKM_TLS_KDF,
|
|
KeyWrapLynks = CKM_KEY_WRAP_LYNKS,
|
|
KeyWrapSetOaep = CKM_KEY_WRAP_SET_OAEP,
|
|
CmsSig = CKM_CMS_SIG,
|
|
KipDerive = CKM_KIP_DERIVE,
|
|
KipWrap = CKM_KIP_WRAP,
|
|
KipMac = CKM_KIP_MAC,
|
|
CamelliaKeyGen = CKM_CAMELLIA_KEY_GEN,
|
|
CamelliaEcb = CKM_CAMELLIA_ECB,
|
|
CamelliaCbc = CKM_CAMELLIA_CBC,
|
|
CamelliaMac = CKM_CAMELLIA_MAC,
|
|
CamelliaMacGeneral = CKM_CAMELLIA_MAC_GENERAL,
|
|
CamelliaCbcPad = CKM_CAMELLIA_CBC_PAD,
|
|
CamelliaEcbEncryptData = CKM_CAMELLIA_ECB_ENCRYPT_DATA,
|
|
CamelliaCbcEncryptData = CKM_CAMELLIA_CBC_ENCRYPT_DATA,
|
|
CamelliaCtr = CKM_CAMELLIA_CTR,
|
|
AriaKeyGen = CKM_ARIA_KEY_GEN,
|
|
AriaEcb = CKM_ARIA_ECB,
|
|
AriaCbc = CKM_ARIA_CBC,
|
|
AriaMac = CKM_ARIA_MAC,
|
|
AriaMacGeneral = CKM_ARIA_MAC_GENERAL,
|
|
AriaCbcPad = CKM_ARIA_CBC_PAD,
|
|
AriaEcbEncryptData = CKM_ARIA_ECB_ENCRYPT_DATA,
|
|
AriaCbcEncryptData = CKM_ARIA_CBC_ENCRYPT_DATA,
|
|
SeedKeyGen = CKM_SEED_KEY_GEN,
|
|
SeedEcb = CKM_SEED_ECB,
|
|
SeedCbc = CKM_SEED_CBC,
|
|
SeedMac = CKM_SEED_MAC,
|
|
SeedMacGeneral = CKM_SEED_MAC_GENERAL,
|
|
SeedCbcPad = CKM_SEED_CBC_PAD,
|
|
SeedEcbEncryptData = CKM_SEED_ECB_ENCRYPT_DATA,
|
|
SeedCbcEncryptData = CKM_SEED_CBC_ENCRYPT_DATA,
|
|
SkipjackKeyGen = CKM_SKIPJACK_KEY_GEN,
|
|
SkipjackEcb64 = CKM_SKIPJACK_ECB64,
|
|
SkipjackCbc64 = CKM_SKIPJACK_CBC64,
|
|
SkipjackOfb64 = CKM_SKIPJACK_OFB64,
|
|
SkipjackCfb64 = CKM_SKIPJACK_CFB64,
|
|
SkipjackCfb32 = CKM_SKIPJACK_CFB32,
|
|
SkipjackCfb16 = CKM_SKIPJACK_CFB16,
|
|
SkipjackCfb8 = CKM_SKIPJACK_CFB8,
|
|
SkipjackWrap = CKM_SKIPJACK_WRAP,
|
|
SkipjackPrivateWrap = CKM_SKIPJACK_PRIVATE_WRAP,
|
|
SkipjackRelayx = CKM_SKIPJACK_RELAYX,
|
|
KeaKeyPairGen = CKM_KEA_KEY_PAIR_GEN,
|
|
KeaKeyDerive = CKM_KEA_KEY_DERIVE,
|
|
KeaDerive = CKM_KEA_DERIVE,
|
|
FortezzaTimestamp = CKM_FORTEZZA_TIMESTAMP,
|
|
BatonKeyGen = CKM_BATON_KEY_GEN,
|
|
BatonEcb128 = CKM_BATON_ECB128,
|
|
BatonEcb96 = CKM_BATON_ECB96,
|
|
BatonCbc128 = CKM_BATON_CBC128,
|
|
BatonCounter = CKM_BATON_COUNTER,
|
|
BatonShuffle = CKM_BATON_SHUFFLE,
|
|
BatonWrap = CKM_BATON_WRAP,
|
|
EcdsaKeyPairGen = CKM_ECDSA_KEY_PAIR_GEN,
|
|
EcKeyPairGen = CKM_EC_KEY_PAIR_GEN,
|
|
Ecdsa = CKM_ECDSA,
|
|
EcdsaSha1 = CKM_ECDSA_SHA1,
|
|
EcdsaSha224 = CKM_ECDSA_SHA224,
|
|
EcdsaSha256 = CKM_ECDSA_SHA256,
|
|
EcdsaSha384 = CKM_ECDSA_SHA384,
|
|
EcdsaSha512 = CKM_ECDSA_SHA512,
|
|
Ecdh1Derive = CKM_ECDH1_DERIVE,
|
|
Ecdh1CofactorDerive = CKM_ECDH1_COFACTOR_DERIVE,
|
|
EcmqvDerive = CKM_ECMQV_DERIVE,
|
|
EcdhAesKeyWrap = CKM_ECDH_AES_KEY_WRAP,
|
|
RsaAesKeyWrap = CKM_RSA_AES_KEY_WRAP,
|
|
JuniperKeyGen = CKM_JUNIPER_KEY_GEN,
|
|
JuniperEcb128 = CKM_JUNIPER_ECB128,
|
|
JuniperCbc128 = CKM_JUNIPER_CBC128,
|
|
JuniperCounter = CKM_JUNIPER_COUNTER,
|
|
JuniperShuffle = CKM_JUNIPER_SHUFFLE,
|
|
JuniperWrap = CKM_JUNIPER_WRAP,
|
|
Fasthash = CKM_FASTHASH,
|
|
AesKeyGen = CKM_AES_KEY_GEN,
|
|
AesEcb = CKM_AES_ECB,
|
|
AesCbc = CKM_AES_CBC,
|
|
AesMac = CKM_AES_MAC,
|
|
AesMacGeneral = CKM_AES_MAC_GENERAL,
|
|
AesCbcPad = CKM_AES_CBC_PAD,
|
|
AesCtr = CKM_AES_CTR,
|
|
AesGcm = CKM_AES_GCM,
|
|
AesCcm = CKM_AES_CCM,
|
|
AesCts = CKM_AES_CTS,
|
|
AesCmac = CKM_AES_CMAC,
|
|
AesCmacGeneral = CKM_AES_CMAC_GENERAL,
|
|
AesXcbcMac = CKM_AES_XCBC_MAC,
|
|
AesXcbcMac96 = CKM_AES_XCBC_MAC_96,
|
|
AesGmac = CKM_AES_GMAC,
|
|
BlowfishKeyGen = CKM_BLOWFISH_KEY_GEN,
|
|
BlowfishCbc = CKM_BLOWFISH_CBC,
|
|
TwofishKeyGen = CKM_TWOFISH_KEY_GEN,
|
|
TwofishCbc = CKM_TWOFISH_CBC,
|
|
BlowfishCbcPad = CKM_BLOWFISH_CBC_PAD,
|
|
TwofishCbcPad = CKM_TWOFISH_CBC_PAD,
|
|
DesEcbEncryptData = CKM_DES_ECB_ENCRYPT_DATA,
|
|
DesCbcEncryptData = CKM_DES_CBC_ENCRYPT_DATA,
|
|
Des3EcbEncryptData = CKM_DES3_ECB_ENCRYPT_DATA,
|
|
Des3CbcEncryptData = CKM_DES3_CBC_ENCRYPT_DATA,
|
|
AesEcbEncryptData = CKM_AES_ECB_ENCRYPT_DATA,
|
|
AesCbcEncryptData = CKM_AES_CBC_ENCRYPT_DATA,
|
|
Gostr3410KeyPairGen = CKM_GOSTR3410_KEY_PAIR_GEN,
|
|
Gostr3410 = CKM_GOSTR3410,
|
|
Gostr3410WithGostr3411 = CKM_GOSTR3410_WITH_GOSTR3411,
|
|
Gostr3410KeyWrap = CKM_GOSTR3410_KEY_WRAP,
|
|
Gostr3410Derive = CKM_GOSTR3410_DERIVE,
|
|
Gostr3411 = CKM_GOSTR3411,
|
|
Gostr3411Hmac = CKM_GOSTR3411_HMAC,
|
|
Gost28147KeyGen = CKM_GOST28147_KEY_GEN,
|
|
Gost28147Ecb = CKM_GOST28147_ECB,
|
|
Gost28147 = CKM_GOST28147,
|
|
Gost28147Mac = CKM_GOST28147_MAC,
|
|
Gost28147KeyWrap = CKM_GOST28147_KEY_WRAP,
|
|
DsaParameterGen = CKM_DSA_PARAMETER_GEN,
|
|
DhPkcsParameterGen = CKM_DH_PKCS_PARAMETER_GEN,
|
|
X942DhParameterGen = CKM_X9_42_DH_PARAMETER_GEN,
|
|
DsaProbablisticParameterGen = CKM_DSA_PROBABLISTIC_PARAMETER_GEN,
|
|
DsaShaweTaylorParameterGen = CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN,
|
|
AesOfb = CKM_AES_OFB,
|
|
AesCfb64 = CKM_AES_CFB64,
|
|
AesCfb8 = CKM_AES_CFB8,
|
|
AesCfb128 = CKM_AES_CFB128,
|
|
AesCfb1 = CKM_AES_CFB1,
|
|
AesKeyWrap = CKM_AES_KEY_WRAP,
|
|
AesKeyWrapPad = CKM_AES_KEY_WRAP_PAD,
|
|
RsaPkcsTpm11 = CKM_RSA_PKCS_TPM_1_1,
|
|
RsaPkcsOaepTpm11 = CKM_RSA_PKCS_OAEP_TPM_1_1,
|
|
VendorDefined = CKM_VENDOR_DEFINED,
|
|
};
|
|
|
|
enum class Notification : CK_NOTIFICATION
|
|
{
|
|
Surrender = CKN_SURRENDER,
|
|
OtpChanged = CKN_OTP_CHANGED,
|
|
};
|
|
|
|
enum class ObjectClass : CK_OBJECT_CLASS
|
|
{
|
|
Data = CKO_DATA,
|
|
Certificate = CKO_CERTIFICATE,
|
|
PublicKey = CKO_PUBLIC_KEY,
|
|
PrivateKey = CKO_PRIVATE_KEY,
|
|
SecretKey = CKO_SECRET_KEY,
|
|
HwFeature = CKO_HW_FEATURE,
|
|
DomainParameters = CKO_DOMAIN_PARAMETERS,
|
|
Mechanism = CKO_MECHANISM,
|
|
OtpKey = CKO_OTP_KEY,
|
|
VendorDefined = CKO_VENDOR_DEFINED,
|
|
};
|
|
|
|
enum class PseudoRandom : CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE
|
|
{
|
|
Pkcs5Pbkd2HmacSha1 = CKP_PKCS5_PBKD2_HMAC_SHA1,
|
|
Pkcs5Pbkd2HmacGostr3411 = CKP_PKCS5_PBKD2_HMAC_GOSTR3411,
|
|
Pkcs5Pbkd2HmacSha224 = CKP_PKCS5_PBKD2_HMAC_SHA224,
|
|
Pkcs5Pbkd2HmacSha256 = CKP_PKCS5_PBKD2_HMAC_SHA256,
|
|
Pkcs5Pbkd2HmacSha384 = CKP_PKCS5_PBKD2_HMAC_SHA384,
|
|
Pkcs5Pbkd2HmacSha512 = CKP_PKCS5_PBKD2_HMAC_SHA512,
|
|
Pkcs5Pbkd2HmacSha512224 = CKP_PKCS5_PBKD2_HMAC_SHA512_224,
|
|
Pkcs5Pbkd2HmacSha512256 = CKP_PKCS5_PBKD2_HMAC_SHA512_256,
|
|
};
|
|
|
|
enum class SessionState : CK_STATE
|
|
{
|
|
RoPublicSession = CKS_RO_PUBLIC_SESSION,
|
|
RoUserFunctions = CKS_RO_USER_FUNCTIONS,
|
|
RwPublicSession = CKS_RW_PUBLIC_SESSION,
|
|
RwUserFunctions = CKS_RW_USER_FUNCTIONS,
|
|
RwSoFunctions = CKS_RW_SO_FUNCTIONS,
|
|
};
|
|
|
|
enum class ReturnValue : CK_RV
|
|
{
|
|
OK = CKR_OK,
|
|
Cancel = CKR_CANCEL,
|
|
HostMemory = CKR_HOST_MEMORY,
|
|
SlotIdInvalid = CKR_SLOT_ID_INVALID,
|
|
GeneralError = CKR_GENERAL_ERROR,
|
|
FunctionFailed = CKR_FUNCTION_FAILED,
|
|
ArgumentsBad = CKR_ARGUMENTS_BAD,
|
|
NoEvent = CKR_NO_EVENT,
|
|
NeedToCreateThreads = CKR_NEED_TO_CREATE_THREADS,
|
|
CantLock = CKR_CANT_LOCK,
|
|
AttributeReadOnly = CKR_ATTRIBUTE_READ_ONLY,
|
|
AttributeSensitive = CKR_ATTRIBUTE_SENSITIVE,
|
|
AttributeTypeInvalid = CKR_ATTRIBUTE_TYPE_INVALID,
|
|
AttributeValueInvalid = CKR_ATTRIBUTE_VALUE_INVALID,
|
|
ActionProhibited = CKR_ACTION_PROHIBITED,
|
|
DataInvalid = CKR_DATA_INVALID,
|
|
DataLenRange = CKR_DATA_LEN_RANGE,
|
|
DeviceError = CKR_DEVICE_ERROR,
|
|
DeviceMemory = CKR_DEVICE_MEMORY,
|
|
DeviceRemoved = CKR_DEVICE_REMOVED,
|
|
EncryptedDataInvalid = CKR_ENCRYPTED_DATA_INVALID,
|
|
EncryptedDataLenRange = CKR_ENCRYPTED_DATA_LEN_RANGE,
|
|
FunctionCanceled = CKR_FUNCTION_CANCELED,
|
|
FunctionNotParallel = CKR_FUNCTION_NOT_PARALLEL,
|
|
FunctionNotSupported = CKR_FUNCTION_NOT_SUPPORTED,
|
|
KeyHandleInvalid = CKR_KEY_HANDLE_INVALID,
|
|
KeySizeRange = CKR_KEY_SIZE_RANGE,
|
|
KeyTypeInconsistent = CKR_KEY_TYPE_INCONSISTENT,
|
|
KeyNotNeeded = CKR_KEY_NOT_NEEDED,
|
|
KeyChanged = CKR_KEY_CHANGED,
|
|
KeyNeeded = CKR_KEY_NEEDED,
|
|
KeyIndigestible = CKR_KEY_INDIGESTIBLE,
|
|
KeyFunctionNotPermitted = CKR_KEY_FUNCTION_NOT_PERMITTED,
|
|
KeyNotWrappable = CKR_KEY_NOT_WRAPPABLE,
|
|
KeyUnextractable = CKR_KEY_UNEXTRACTABLE,
|
|
MechanismInvalid = CKR_MECHANISM_INVALID,
|
|
MechanismParamInvalid = CKR_MECHANISM_PARAM_INVALID,
|
|
ObjectHandleInvalid = CKR_OBJECT_HANDLE_INVALID,
|
|
OperationActive = CKR_OPERATION_ACTIVE,
|
|
OperationNotInitialized = CKR_OPERATION_NOT_INITIALIZED,
|
|
PinIncorrect = CKR_PIN_INCORRECT,
|
|
PinInvalid = CKR_PIN_INVALID,
|
|
PinLenRange = CKR_PIN_LEN_RANGE,
|
|
PinExpired = CKR_PIN_EXPIRED,
|
|
PinLocked = CKR_PIN_LOCKED,
|
|
SessionClosed = CKR_SESSION_CLOSED,
|
|
SessionCount = CKR_SESSION_COUNT,
|
|
SessionHandleInvalid = CKR_SESSION_HANDLE_INVALID,
|
|
SessionParallelNotSupported = CKR_SESSION_PARALLEL_NOT_SUPPORTED,
|
|
SessionReadOnly = CKR_SESSION_READ_ONLY,
|
|
SessionExists = CKR_SESSION_EXISTS,
|
|
SessionReadOnlyExists = CKR_SESSION_READ_ONLY_EXISTS,
|
|
SessionReadWriteSoExists = CKR_SESSION_READ_WRITE_SO_EXISTS,
|
|
SignatureInvalid = CKR_SIGNATURE_INVALID,
|
|
SignatureLenRange = CKR_SIGNATURE_LEN_RANGE,
|
|
TemplateIncomplete = CKR_TEMPLATE_INCOMPLETE,
|
|
TemplateInconsistent = CKR_TEMPLATE_INCONSISTENT,
|
|
TokenNotPresent = CKR_TOKEN_NOT_PRESENT,
|
|
TokenNotRecognized = CKR_TOKEN_NOT_RECOGNIZED,
|
|
TokenWriteProtected = CKR_TOKEN_WRITE_PROTECTED,
|
|
UnwrappingKeyHandleInvalid = CKR_UNWRAPPING_KEY_HANDLE_INVALID,
|
|
UnwrappingKeySizeRange = CKR_UNWRAPPING_KEY_SIZE_RANGE,
|
|
UnwrappingKeyTypeInconsistent = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,
|
|
UserAlreadyLoggedIn = CKR_USER_ALREADY_LOGGED_IN,
|
|
UserNotLoggedIn = CKR_USER_NOT_LOGGED_IN,
|
|
UserPinNotInitialized = CKR_USER_PIN_NOT_INITIALIZED,
|
|
UserTypeInvalid = CKR_USER_TYPE_INVALID,
|
|
UserAnotherAlreadyLoggedIn = CKR_USER_ANOTHER_ALREADY_LOGGED_IN,
|
|
UserTooManyTypes = CKR_USER_TOO_MANY_TYPES,
|
|
WrappedKeyInvalid = CKR_WRAPPED_KEY_INVALID,
|
|
WrappedKeyLenRange = CKR_WRAPPED_KEY_LEN_RANGE,
|
|
WrappingKeyHandleInvalid = CKR_WRAPPING_KEY_HANDLE_INVALID,
|
|
WrappingKeySizeRange = CKR_WRAPPING_KEY_SIZE_RANGE,
|
|
WrappingKeyTypeInconsistent = CKR_WRAPPING_KEY_TYPE_INCONSISTENT,
|
|
RandomSeedNotSupported = CKR_RANDOM_SEED_NOT_SUPPORTED,
|
|
RandomNoRng = CKR_RANDOM_NO_RNG,
|
|
DomainParamsInvalid = CKR_DOMAIN_PARAMS_INVALID,
|
|
CurveNotSupported = CKR_CURVE_NOT_SUPPORTED,
|
|
BufferTooSmall = CKR_BUFFER_TOO_SMALL,
|
|
SavedStateInvalid = CKR_SAVED_STATE_INVALID,
|
|
InformationSensitive = CKR_INFORMATION_SENSITIVE,
|
|
StateUnsaveable = CKR_STATE_UNSAVEABLE,
|
|
CryptokiNotInitialized = CKR_CRYPTOKI_NOT_INITIALIZED,
|
|
CryptokiAlreadyInitialized = CKR_CRYPTOKI_ALREADY_INITIALIZED,
|
|
MutexBad = CKR_MUTEX_BAD,
|
|
MutexNotLocked = CKR_MUTEX_NOT_LOCKED,
|
|
NewPinMode = CKR_NEW_PIN_MODE,
|
|
NextOtp = CKR_NEXT_OTP,
|
|
ExceededMaxIterations = CKR_EXCEEDED_MAX_ITERATIONS,
|
|
FipsSelfTestFailed = CKR_FIPS_SELF_TEST_FAILED,
|
|
LibraryLoadFailed = CKR_LIBRARY_LOAD_FAILED,
|
|
PinTooWeak = CKR_PIN_TOO_WEAK,
|
|
PublicKeyInvalid = CKR_PUBLIC_KEY_INVALID,
|
|
FunctionRejected = CKR_FUNCTION_REJECTED,
|
|
VendorDefined = CKR_VENDOR_DEFINED,
|
|
};
|
|
|
|
enum class UserType : CK_USER_TYPE
|
|
{
|
|
SO = CKU_SO,
|
|
User = CKU_USER,
|
|
ContextSpecific = CKU_CONTEXT_SPECIFIC,
|
|
};
|
|
|
|
enum class PublicPointEncoding : uint32_t
|
|
{
|
|
Raw,
|
|
Der
|
|
};
|
|
|
|
using FunctionListPtr = CK_FUNCTION_LIST_PTR;
|
|
using VoidPtr = CK_VOID_PTR;
|
|
using C_InitializeArgs = CK_C_INITIALIZE_ARGS;
|
|
using CreateMutex = CK_CREATEMUTEX;
|
|
using DestroyMutex = CK_DESTROYMUTEX;
|
|
using LockMutex = CK_LOCKMUTEX;
|
|
using UnlockMutex = CK_UNLOCKMUTEX;
|
|
using Flags = CK_FLAGS;
|
|
using Info = CK_INFO;
|
|
using Bbool = CK_BBOOL;
|
|
using SlotId = CK_SLOT_ID;
|
|
using Ulong = CK_ULONG;
|
|
using SlotInfo = CK_SLOT_INFO;
|
|
using TokenInfo = CK_TOKEN_INFO;
|
|
using Mechanism = CK_MECHANISM;
|
|
using MechanismInfo = CK_MECHANISM_INFO;
|
|
using Utf8Char = CK_UTF8CHAR;
|
|
using Notify = CK_NOTIFY;
|
|
using SessionHandle = CK_SESSION_HANDLE;
|
|
using SessionInfo = CK_SESSION_INFO;
|
|
using Attribute = CK_ATTRIBUTE;
|
|
using ObjectHandle = CK_OBJECT_HANDLE;
|
|
using Byte = CK_BYTE;
|
|
using RsaPkcsOaepParams = CK_RSA_PKCS_OAEP_PARAMS;
|
|
using RsaPkcsPssParams = CK_RSA_PKCS_PSS_PARAMS;
|
|
using Ecdh1DeriveParams = CK_ECDH1_DERIVE_PARAMS;
|
|
using Date = CK_DATE;
|
|
|
|
BOTAN_PUBLIC_API(2,0) extern ReturnValue* ThrowException;
|
|
|
|
const Bbool True = CK_TRUE;
|
|
const Bbool False = CK_FALSE;
|
|
|
|
inline Flags flags(Flag flags)
|
|
{
|
|
return static_cast<Flags>(flags);
|
|
}
|
|
|
|
class Slot;
|
|
|
|
/**
|
|
* Initializes a token
|
|
* @param slot The slot with the attached token that should be initialized
|
|
* @param label The token label
|
|
* @param so_pin PIN of the security officer. Will be set if the token is uninitialized other this has to be the current SO_PIN
|
|
* @param pin The user PIN that will be set
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) void initialize_token(Slot& slot, const std::string& label, const secure_string& so_pin,
|
|
const secure_string& pin);
|
|
|
|
/**
|
|
* Change PIN with old PIN to new PIN
|
|
* @param slot The slot with the attached token
|
|
* @param old_pin The old user PIN
|
|
* @param new_pin The new user PIN
|
|
*/
|
|
|
|
BOTAN_PUBLIC_API(2,0) void change_pin(Slot& slot, const secure_string& old_pin, const secure_string& new_pin);
|
|
|
|
/**
|
|
* Change SO_PIN with old SO_PIN to new SO_PIN
|
|
* @param slot The slot with the attached token
|
|
* @param old_so_pin The old SO_PIN
|
|
* @param new_so_pin The new SO_PIN
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) void change_so_pin(Slot& slot, const secure_string& old_so_pin, const secure_string& new_so_pin);
|
|
|
|
/**
|
|
* Sets user PIN with SO_PIN
|
|
* @param slot The slot with the attached token
|
|
* @param so_pin PIN of the security officer
|
|
* @param pin The user PIN that should be set
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) void set_pin(Slot& slot, const secure_string& so_pin, const secure_string& pin);
|
|
|
|
/// Provides access to all PKCS#11 functions
|
|
class BOTAN_PUBLIC_API(2,0) LowLevel
|
|
{
|
|
public:
|
|
/// @param ptr the functon list pointer to use. Can be retrieved via `LowLevel::C_GetFunctionList`
|
|
explicit LowLevel(FunctionListPtr ptr);
|
|
|
|
/****************************** General purpose functions ******************************/
|
|
|
|
/**
|
|
* C_Initialize initializes the Cryptoki library.
|
|
* @param init_args if this is not nullptr, it gets cast to (`C_InitializeArgs`) and dereferenced
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CantLock \li CryptokiAlreadyInitialized
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li NeedToCreateThreads \li OK
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_Initialize(VoidPtr init_args,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Finalize indicates that an application is done with the Cryptoki library.
|
|
* @param reserved reserved. Should be nullptr
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_Finalize(VoidPtr reserved,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetInfo returns general information about Cryptoki.
|
|
* @param info_ptr location that receives information
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetInfo(Info* info_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetFunctionList returns the function list.
|
|
* @param pkcs11_module The PKCS#11 module
|
|
* @param function_list_ptr_ptr receives pointer to function list
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK
|
|
* @return true on success, false otherwise
|
|
*/
|
|
static bool C_GetFunctionList(Dynamically_Loaded_Library& pkcs11_module, FunctionListPtr* function_list_ptr_ptr,
|
|
ReturnValue* return_value = ThrowException);
|
|
|
|
/****************************** Slot and token management functions ******************************/
|
|
|
|
/**
|
|
* C_GetSlotList obtains a list of slots in the system.
|
|
* @param token_present only slots with tokens
|
|
* @param slot_list_ptr receives array of slot IDs
|
|
* @param count_ptr receives number of slots
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetSlotList(Bbool token_present,
|
|
SlotId* slot_list_ptr,
|
|
Ulong* count_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetSlotList obtains a list of slots in the system.
|
|
* @param token_present only slots with tokens
|
|
* @param slot_ids receives vector of slot IDs
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetSlotList(bool token_present,
|
|
std::vector<SlotId>& slot_ids,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetSlotInfo obtains information about a particular slot in the system.
|
|
* @param slot_id the ID of the slot
|
|
* @param info_ptr receives the slot information
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li SlotIdInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetSlotInfo(SlotId slot_id,
|
|
SlotInfo* info_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetTokenInfo obtains information about a particular token in the system.
|
|
* @param slot_id ID of the token's slot
|
|
* @param info_ptr receives the token information
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li SlotIdInvalid
|
|
* \li TokenNotPresent \li TokenNotRecognized \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetTokenInfo(SlotId slot_id,
|
|
TokenInfo* info_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_WaitForSlotEvent waits for a slot event (token insertion, removal, etc.) to occur.
|
|
* @param flags blocking/nonblocking flag
|
|
* @param slot_ptr location that receives the slot ID
|
|
* @param reserved reserved. Should be NULL_PTR
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li NoEvent
|
|
* \li OK
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_WaitForSlotEvent(Flags flags,
|
|
SlotId* slot_ptr,
|
|
VoidPtr reserved,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetMechanismList obtains a list of mechanism types supported by a token.
|
|
* @param slot_id ID of token's slot
|
|
* @param mechanism_list_ptr gets mech. array
|
|
* @param count_ptr gets # of mechs.
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li BufferTooSmall \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li SlotIdInvalid \li TokenNotPresent \li TokenNotRecognized
|
|
* \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetMechanismList(SlotId slot_id,
|
|
MechanismType* mechanism_list_ptr,
|
|
Ulong* count_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetMechanismList obtains a list of mechanism types supported by a token.
|
|
* @param slot_id ID of token's slot
|
|
* @param mechanisms receives vector of supported mechanisms
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li BufferTooSmall \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li SlotIdInvalid \li TokenNotPresent \li TokenNotRecognized
|
|
* \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetMechanismList(SlotId slot_id,
|
|
std::vector<MechanismType>& mechanisms,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetMechanismInfo obtains information about a particular mechanism possibly supported by a token.
|
|
* @param slot_id ID of the token's slot
|
|
* @param type type of mechanism
|
|
* @param info_ptr receives mechanism info
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li MechanismInvalid \li OK
|
|
* \li SlotIdInvalid \li TokenNotPresent \li TokenNotRecognized
|
|
* \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetMechanismInfo(SlotId slot_id,
|
|
MechanismType type,
|
|
MechanismInfo* info_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_InitToken initializes a token.
|
|
* @param slot_id ID of the token's slot
|
|
* @param so_pin_ptr the SO's initial PIN
|
|
* @param so_pin_len length in bytes of the SO_PIN
|
|
* @param label_ptr 32-byte token label (blank padded)
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li PinIncorrect \li PinLocked \li SessionExists
|
|
* \li SlotIdInvalid \li TokenNotPresent \li TokenNotRecognized
|
|
* \li TokenWriteProtected \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_InitToken(SlotId slot_id,
|
|
Utf8Char* so_pin_ptr,
|
|
Ulong so_pin_len,
|
|
Utf8Char* label_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_InitToken initializes a token.
|
|
* @param slot_id ID of the token's slot
|
|
* @param so_pin the SO's initial PIN
|
|
* @param label token label (at max 32 bytes long)
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li PinIncorrect \li PinLocked \li SessionExists
|
|
* \li SlotIdInvalid \li TokenNotPresent \li TokenNotRecognized
|
|
* \li TokenWriteProtected \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAlloc>
|
|
bool C_InitToken(SlotId slot_id,
|
|
const std::vector<uint8_t, TAlloc>& so_pin,
|
|
const std::string& label,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
std::string padded_label = label;
|
|
if(label.size() < 32)
|
|
{
|
|
padded_label.insert(padded_label.end(), 32 - label.size(), ' ');
|
|
}
|
|
|
|
return C_InitToken(slot_id,
|
|
reinterpret_cast< Utf8Char* >(const_cast< uint8_t* >(so_pin.data())),
|
|
static_cast<Ulong>(so_pin.size()),
|
|
reinterpret_cast< Utf8Char* >(const_cast< char* >(padded_label.c_str())),
|
|
return_value);
|
|
}
|
|
|
|
/**
|
|
* C_InitPIN initializes the normal user's PIN.
|
|
* @param session the session's handle
|
|
* @param pin_ptr the normal user's PIN
|
|
* @param pin_len length in bytes of the PIN
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li PinInvalid \li PinLenRange \li SessionClosed
|
|
* \li SessionReadOnly \li SessionHandleInvalid \li TokenWriteProtected
|
|
* \li UserNotLoggedIn \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_InitPIN(SessionHandle session,
|
|
Utf8Char* pin_ptr,
|
|
Ulong pin_len,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_InitPIN initializes the normal user's PIN.
|
|
* @param session the session's handle
|
|
* @param pin the normal user's PIN
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li PinInvalid \li PinLenRange \li SessionClosed
|
|
* \li SessionReadOnly \li SessionHandleInvalid \li TokenWriteProtected
|
|
* \li UserNotLoggedIn \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAlloc>
|
|
bool C_InitPIN(SessionHandle session,
|
|
const std::vector<uint8_t, TAlloc>& pin,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
return C_InitPIN(session,
|
|
reinterpret_cast< Utf8Char* >(const_cast< uint8_t* >(pin.data())),
|
|
static_cast<Ulong>(pin.size()),
|
|
return_value);
|
|
}
|
|
|
|
/**
|
|
* C_SetPIN modifies the PIN of the user who is logged in.
|
|
* @param session the session's handle
|
|
* @param old_pin_ptr the old PIN
|
|
* @param old_len length of the old PIN
|
|
* @param new_pin_ptr the new PIN
|
|
* @param new_len length of the new PIN
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li PinIncorrect \li PinInvalid \li PinLenRange
|
|
* \li PinLocked \li SessionClosed \li SessionHandleInvalid
|
|
* \li SessionReadOnly \li TokenWriteProtected \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_SetPIN(SessionHandle session,
|
|
Utf8Char* old_pin_ptr,
|
|
Ulong old_len,
|
|
Utf8Char* new_pin_ptr,
|
|
Ulong new_len,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_SetPIN modifies the PIN of the user who is logged in.
|
|
* @param session the session's handle
|
|
* @param old_pin the old PIN
|
|
* @param new_pin the new PIN
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li PinIncorrect \li PinInvalid \li PinLenRange
|
|
* \li PinLocked \li SessionClosed \li SessionHandleInvalid
|
|
* \li SessionReadOnly \li TokenWriteProtected \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAlloc>
|
|
bool C_SetPIN(SessionHandle session,
|
|
const std::vector<uint8_t, TAlloc>& old_pin,
|
|
const std::vector<uint8_t, TAlloc>& new_pin,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
return C_SetPIN(session,
|
|
reinterpret_cast< Utf8Char* >(const_cast< uint8_t* >(old_pin.data())),
|
|
static_cast<Ulong>(old_pin.size()),
|
|
reinterpret_cast< Utf8Char* >(const_cast< uint8_t* >(new_pin.data())),
|
|
static_cast<Ulong>(new_pin.size()),
|
|
return_value);
|
|
}
|
|
|
|
|
|
/****************************** Session management ******************************/
|
|
|
|
/**
|
|
* C_OpenSession opens a session between an application and a token.
|
|
* @param slot_id the slot's ID
|
|
* @param flags from CK_SESSION_INFO
|
|
* @param application passed to callback
|
|
* @param notify callback function
|
|
* @param session_ptr gets session handle
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li SessionCount
|
|
* \li SessionParallelNotSupported \li SessionReadWriteSoExists \li SlotIdInvalid
|
|
* \li TokenNotPresent \li TokenNotRecognized \li TokenWriteProtected
|
|
* \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_OpenSession(SlotId slot_id,
|
|
Flags flags,
|
|
VoidPtr application,
|
|
Notify notify,
|
|
SessionHandle* session_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_CloseSession closes a session between an application and a token.
|
|
* @param session the session's handle
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li SessionClosed
|
|
* \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_CloseSession(SessionHandle session,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_CloseAllSessions closes all sessions with a token.
|
|
* @param slot_id the token's slot
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li SlotIdInvalid
|
|
* \li TokenNotPresent
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_CloseAllSessions(SlotId slot_id,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetSessionInfo obtains information about the session.
|
|
* @param session the session's handle
|
|
* @param info_ptr receives session info
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li SessionClosed
|
|
* \li SessionHandleInvalid \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetSessionInfo(SessionHandle session,
|
|
SessionInfo* info_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetOperationState obtains the state of the cryptographic operation in a session.
|
|
* @param session session's handle
|
|
* @param operation_state_ptr gets state
|
|
* @param operation_state_len_ptr gets state length
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li BufferTooSmall \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li OperationNotInitialized \li SessionClosed \li SessionHandleInvalid
|
|
* \li StateUnsaveable \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetOperationState(SessionHandle session,
|
|
Byte* operation_state_ptr,
|
|
Ulong* operation_state_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_SetOperationState restores the state of the cryptographic operation in a session.
|
|
* @param session session's handle
|
|
* @param operation_state_ptr holds state
|
|
* @param operation_state_len holds state length
|
|
* @param encryption_key en/decryption key
|
|
* @param authentication_key sign/verify key
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li KeyChanged \li KeyNeeded
|
|
* \li KeyNotNeeded \li OK \li SavedStateInvalid
|
|
* \li SessionClosed \li SessionHandleInvalid \li ArgumentsBad
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_SetOperationState(SessionHandle session,
|
|
Byte* operation_state_ptr,
|
|
Ulong operation_state_len,
|
|
ObjectHandle encryption_key,
|
|
ObjectHandle authentication_key,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Login logs a user into a token.
|
|
* @param session the session's handle
|
|
* @param user_type the user type
|
|
* @param pin_ptr the user's PIN
|
|
* @param pin_len the length of the PIN
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li PinIncorrect
|
|
* \li PinLocked \li SessionClosed \li SessionHandleInvalid
|
|
* \li SessionReadOnlyExists \li UserAlreadyLoggedIn \li UserAnotherAlreadyLoggedIn
|
|
* \li UserPinNotInitialized \li UserTooManyTypes \li UserTypeInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_Login(SessionHandle session,
|
|
UserType user_type,
|
|
Utf8Char* pin_ptr,
|
|
Ulong pin_len,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Login logs a user into a token.
|
|
* @param session the session's handle
|
|
* @param user_type the user type
|
|
* @param pin the user or security officer's PIN
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li PinIncorrect
|
|
* \li PinLocked \li SessionClosed \li SessionHandleInvalid
|
|
* \li SessionReadOnlyExists \li UserAlreadyLoggedIn \li UserAnotherAlreadyLoggedIn
|
|
* \li UserPinNotInitialized \li UserTooManyTypes \li UserTypeInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAlloc>
|
|
bool C_Login(SessionHandle session,
|
|
UserType user_type,
|
|
const std::vector<uint8_t, TAlloc>& pin,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
return C_Login(session, user_type,
|
|
reinterpret_cast< Utf8Char* >(const_cast< uint8_t* >(pin.data())),
|
|
static_cast<Ulong>(pin.size()),
|
|
return_value);
|
|
}
|
|
|
|
/**
|
|
* C_Logout logs a user out from a token.
|
|
* @param session the session's handle
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li SessionClosed
|
|
* \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_Logout(SessionHandle session,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/****************************** Object management functions ******************************/
|
|
|
|
/**
|
|
* C_CreateObject creates a new object.
|
|
* @param session the session's handle
|
|
* @param attribute_template_ptr the object's template
|
|
* @param count attributes in template
|
|
* @param object_ptr gets new object's handle.
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li AttributeReadOnly \li AttributeTypeInvalid
|
|
* \li AttributeValueInvalid \li CryptokiNotInitialized \li CurveNotSupported
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li DomainParamsInvalid \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li PinExpired
|
|
* \li SessionClosed \li SessionHandleInvalid \li SessionReadOnly
|
|
* \li TemplateIncomplete \li TemplateInconsistent \li TokenWriteProtected
|
|
* \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_CreateObject(SessionHandle session,
|
|
Attribute* attribute_template_ptr,
|
|
Ulong count,
|
|
ObjectHandle* object_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_CopyObject copies an object, creating a new object for the copy.
|
|
* @param session the session's handle
|
|
* @param object the object's handle
|
|
* @param attribute_template_ptr template for new object
|
|
* @param count attributes in template
|
|
* @param new_object_ptr receives handle of copy
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ActionProhibited \li ArgumentsBad \li AttributeReadOnly
|
|
* \li AttributeTypeInvalid \li AttributeValueInvalid \li CryptokiNotInitialized
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li ObjectHandleInvalid \li OK \li PinExpired
|
|
* \li SessionClosed \li SessionHandleInvalid \li SessionReadOnly
|
|
* \li TemplateInconsistent \li TokenWriteProtected \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_CopyObject(SessionHandle session,
|
|
ObjectHandle object,
|
|
Attribute* attribute_template_ptr,
|
|
Ulong count,
|
|
ObjectHandle* new_object_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_DestroyObject destroys an object.
|
|
* @param session the session's handle
|
|
* @param object the object's handle
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ActionProhibited \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li ObjectHandleInvalid
|
|
* \li OK \li PinExpired \li SessionClosed
|
|
* \li SessionHandleInvalid \li SessionReadOnly \li TokenWriteProtected
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DestroyObject(SessionHandle session,
|
|
ObjectHandle object,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetObjectSize gets the size of an object in bytes.
|
|
* @param session the session's handle
|
|
* @param object the object's handle
|
|
* @param size_ptr receives size of object
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li InformationSensitive
|
|
* \li ObjectHandleInvalid \li OK \li SessionClosed
|
|
* \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetObjectSize(SessionHandle session,
|
|
ObjectHandle object,
|
|
Ulong* size_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetAttributeValue obtains the value of one or more object attributes.
|
|
* @param session the session's handle
|
|
* @param object the object's handle
|
|
* @param attribute_template_ptr specifies attrs; gets vals
|
|
* @param count attributes in template
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li AttributeSensitive \li AttributeTypeInvalid
|
|
* \li BufferTooSmall \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li ObjectHandleInvalid
|
|
* \li OK \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetAttributeValue(SessionHandle session,
|
|
ObjectHandle object,
|
|
Attribute* attribute_template_ptr,
|
|
Ulong count,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GetAttributeValue obtains the value of one or more object attributes.
|
|
* @param session the session's handle
|
|
* @param object the object's handle
|
|
* @param attribute_values specifies attrs; gets vals
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li AttributeSensitive \li AttributeTypeInvalid
|
|
* \li BufferTooSmall \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li ObjectHandleInvalid
|
|
* \li OK \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAlloc>
|
|
bool C_GetAttributeValue(SessionHandle session,
|
|
ObjectHandle object,
|
|
std::map<AttributeType, std::vector<uint8_t, TAlloc>>& attribute_values,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
std::vector<Attribute> getter_template;
|
|
|
|
for(const auto& entry : attribute_values)
|
|
{
|
|
getter_template.emplace_back(Attribute{ static_cast< CK_ATTRIBUTE_TYPE >(entry.first), nullptr, 0 });
|
|
}
|
|
|
|
bool success = C_GetAttributeValue(session,
|
|
object,
|
|
const_cast< Attribute* >(getter_template.data()),
|
|
static_cast<Ulong>(getter_template.size()),
|
|
return_value);
|
|
|
|
if(!success)
|
|
{
|
|
return success;
|
|
}
|
|
|
|
size_t i = 0;
|
|
for(auto& entry : attribute_values)
|
|
{
|
|
entry.second.clear();
|
|
entry.second.resize(getter_template.at(i).ulValueLen);
|
|
getter_template.at(i).pValue = const_cast< uint8_t* >(entry.second.data());
|
|
i++;
|
|
}
|
|
|
|
return C_GetAttributeValue(session, object,
|
|
const_cast< Attribute* >(getter_template.data()),
|
|
static_cast<Ulong>(getter_template.size()),
|
|
return_value);
|
|
}
|
|
|
|
/**
|
|
* C_SetAttributeValue modifies the value of one or more object attributes.
|
|
* @param session the session's handle
|
|
* @param object the object's handle
|
|
* @param attribute_template_ptr specifies attrs and values
|
|
* @param count attributes in template
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ActionProhibited \li ArgumentsBad \li AttributeReadOnly
|
|
* \li AttributeTypeInvalid \li AttributeValueInvalid \li CryptokiNotInitialized
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li ObjectHandleInvalid \li OK \li SessionClosed
|
|
* \li SessionHandleInvalid \li SessionReadOnly \li TemplateInconsistent
|
|
* \li TokenWriteProtected \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_SetAttributeValue(SessionHandle session,
|
|
ObjectHandle object,
|
|
Attribute* attribute_template_ptr,
|
|
Ulong count,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_SetAttributeValue modifies the value of one or more object attributes.
|
|
* @param session the session's handle
|
|
* @param object the object's handle
|
|
* @param attribute_values specifies attrs and values
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ActionProhibited \li ArgumentsBad \li AttributeReadOnly
|
|
* \li AttributeTypeInvalid \li AttributeValueInvalid \li CryptokiNotInitialized
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li ObjectHandleInvalid \li OK \li SessionClosed
|
|
* \li SessionHandleInvalid \li SessionReadOnly \li TemplateInconsistent
|
|
* \li TokenWriteProtected \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAlloc>
|
|
bool C_SetAttributeValue(SessionHandle session,
|
|
ObjectHandle object,
|
|
std::map<AttributeType, std::vector<uint8_t, TAlloc>>& attribute_values,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
std::vector<Attribute> setter_template;
|
|
|
|
for(auto& entry : attribute_values)
|
|
{
|
|
setter_template.emplace_back(Attribute{ static_cast< CK_ATTRIBUTE_TYPE >(entry.first), entry.second.data(), static_cast<CK_ULONG>(entry.second.size()) });
|
|
}
|
|
|
|
return C_SetAttributeValue(session, object,
|
|
const_cast< Attribute* >(setter_template.data()),
|
|
static_cast<Ulong>(setter_template.size()),
|
|
return_value);
|
|
}
|
|
|
|
/**
|
|
* C_FindObjectsInit initializes a search for token and session objects that match a template.
|
|
* @param session the session's handle
|
|
* @param attribute_template_ptr attribute values to match
|
|
* @param count attrs in search template
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li AttributeTypeInvalid \li AttributeValueInvalid
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li OperationActive
|
|
* \li PinExpired \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_FindObjectsInit(SessionHandle session,
|
|
Attribute* attribute_template_ptr,
|
|
Ulong count,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_FindObjects continues a search for token and session objects that match a template, obtaining additional object handles.
|
|
* @param session session's handle
|
|
* @param object_ptr gets obj. handles
|
|
* @param max_object_count max handles to get
|
|
* @param object_count_ptr actual # returned
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li OperationNotInitialized \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_FindObjects(SessionHandle session,
|
|
ObjectHandle* object_ptr,
|
|
Ulong max_object_count,
|
|
Ulong* object_count_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_FindObjectsFinal finishes a search for token and session objects.
|
|
* @param session the session's handle
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li OperationNotInitialized
|
|
* \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_FindObjectsFinal(SessionHandle session,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/****************************** Encryption functions ******************************/
|
|
|
|
/**
|
|
* C_EncryptInit initializes an encryption operation.
|
|
* @param session the session's handle
|
|
* @param mechanism_ptr the encryption mechanism
|
|
* @param key handle of encryption key
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li KeyFunctionNotPermitted
|
|
* \li KeyHandleInvalid \li KeySizeRange \li KeyTypeInconsistent
|
|
* \li MechanismInvalid \li MechanismParamInvalid \li OK
|
|
* \li OperationActive \li PinExpired \li SessionClosed
|
|
* \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_EncryptInit(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
ObjectHandle key,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Encrypt encrypts single-part data.
|
|
* @param session session's handle
|
|
* @param data_ptr the plaintext data
|
|
* @param data_len size of plaintext data in bytes
|
|
* @param encrypted_data gets ciphertext
|
|
* @param encrypted_data_len_ptr gets c-text size
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataInvalid \li DataLenRange \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_Encrypt(SessionHandle session,
|
|
Byte* data_ptr,
|
|
Ulong data_len,
|
|
Byte* encrypted_data,
|
|
Ulong* encrypted_data_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Encrypt encrypts single-part data.
|
|
* @param session session's handle
|
|
* @param plaintext_data the plaintext data
|
|
* @param encrypted_data gets ciphertext
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataInvalid \li DataLenRange \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAllocA, typename TAllocB>
|
|
bool C_Encrypt(SessionHandle session,
|
|
const std::vector<uint8_t, TAllocA>& plaintext_data,
|
|
std::vector<uint8_t, TAllocB>& encrypted_data,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
Ulong encrypted_size = 0;
|
|
if(!C_Encrypt(session,
|
|
const_cast<Byte*>((plaintext_data.data())),
|
|
static_cast<Ulong>(plaintext_data.size()),
|
|
nullptr, &encrypted_size,
|
|
return_value))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
encrypted_data.resize(encrypted_size);
|
|
if (!C_Encrypt(session,
|
|
const_cast<Byte*>(plaintext_data.data()),
|
|
static_cast<Ulong>(plaintext_data.size()),
|
|
encrypted_data.data(),
|
|
&encrypted_size, return_value))
|
|
{
|
|
return false;
|
|
}
|
|
encrypted_data.resize(encrypted_size);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* C_EncryptUpdate continues a multiple-part encryption operation.
|
|
* @param session session's handle
|
|
* @param part_ptr the plaintext data
|
|
* @param part_len plaintext data len
|
|
* @param encrypted_part_ptr gets ciphertext
|
|
* @param encrypted_part_len_ptr gets c-text size
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataLenRange \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li OperationNotInitialized \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_EncryptUpdate(SessionHandle session,
|
|
Byte* part_ptr,
|
|
Ulong part_len,
|
|
Byte* encrypted_part_ptr,
|
|
Ulong* encrypted_part_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_EncryptFinal finishes a multiple-part encryption operation.
|
|
* @param session session handle
|
|
* @param last_encrypted_part_ptr last c-text
|
|
* @param last_encrypted_part_len_ptr gets last size
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataLenRange \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li OperationNotInitialized \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_EncryptFinal(SessionHandle session,
|
|
Byte* last_encrypted_part_ptr,
|
|
Ulong* last_encrypted_part_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/****************************** Decryption functions ******************************/
|
|
|
|
/**
|
|
* C_DecryptInit initializes a decryption operation.
|
|
* @param session the session's handle
|
|
* @param mechanism_ptr the decryption mechanism
|
|
* @param key handle of decryption key
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li KeyFunctionNotPermitted \li KeyHandleInvalid \li KeySizeRange
|
|
* \li KeyTypeInconsistent \li MechanismInvalid \li MechanismParamInvalid
|
|
* \li OK \li OperationActive \li PinExpired
|
|
* \li SessionClosed \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DecryptInit(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
ObjectHandle key,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Decrypt decrypts encrypted data in a single part.
|
|
* @param session session's handle
|
|
* @param encrypted_data_ptr ciphertext
|
|
* @param encrypted_data_len ciphertext length
|
|
* @param data_ptr gets plaintext
|
|
* @param data_len_ptr gets p-text size
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li EncryptedDataInvalid \li EncryptedDataLenRange \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_Decrypt(SessionHandle session,
|
|
Byte* encrypted_data_ptr,
|
|
Ulong encrypted_data_len,
|
|
Byte* data_ptr,
|
|
Ulong* data_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Decrypt decrypts encrypted data in a single part.
|
|
* @param session session's handle
|
|
* @param encrypted_data ciphertext
|
|
* @param decrypted_data gets plaintext
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li EncryptedDataInvalid \li EncryptedDataLenRange \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAllocA, typename TAllocB>
|
|
bool C_Decrypt(SessionHandle session,
|
|
const std::vector<uint8_t, TAllocA>& encrypted_data,
|
|
std::vector<uint8_t, TAllocB>& decrypted_data,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
Ulong decrypted_size = 0;
|
|
if(!C_Decrypt(session,
|
|
const_cast<Byte*>((encrypted_data.data())),
|
|
static_cast<Ulong>(encrypted_data.size()),
|
|
nullptr, &decrypted_size,
|
|
return_value))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
decrypted_data.resize(decrypted_size);
|
|
if(!C_Decrypt(session,
|
|
const_cast<Byte*>(encrypted_data.data()),
|
|
static_cast<Ulong>(encrypted_data.size()),
|
|
decrypted_data.data(),
|
|
&decrypted_size, return_value))
|
|
{
|
|
return false;
|
|
}
|
|
decrypted_data.resize(decrypted_size);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* C_DecryptUpdate continues a multiple-part decryption operation.
|
|
* @param session session's handle
|
|
* @param encrypted_part_ptr encrypted data
|
|
* @param encrypted_part_len input length
|
|
* @param part_ptr gets plaintext
|
|
* @param part_len_ptr p-text size
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li EncryptedDataInvalid \li EncryptedDataLenRange \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DecryptUpdate(SessionHandle session,
|
|
Byte* encrypted_part_ptr,
|
|
Ulong encrypted_part_len,
|
|
Byte* part_ptr,
|
|
Ulong* part_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_DecryptFinal finishes a multiple-part decryption operation.
|
|
* @param session the session's handle
|
|
* @param last_part_ptr gets plaintext
|
|
* @param last_part_len_ptr p-text size
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li EncryptedDataInvalid \li EncryptedDataLenRange \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DecryptFinal(SessionHandle session,
|
|
Byte* last_part_ptr,
|
|
Ulong* last_part_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/****************************** Message digesting functions ******************************/
|
|
|
|
/**
|
|
* C_DigestInit initializes a message-digesting operation.
|
|
* @param session the session's handle
|
|
* @param mechanism_ptr the digesting mechanism
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li MechanismInvalid \li MechanismParamInvalid \li OK
|
|
* \li OperationActive \li PinExpired \li SessionClosed
|
|
* \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DigestInit(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Digest digests data in a single part.
|
|
* @param session the session's handle
|
|
* @param data_ptr data to be digested
|
|
* @param data_len bytes of data to digest
|
|
* @param digest_ptr gets the message digest
|
|
* @param digest_len_ptr gets digest length
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionCanceled \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li OperationNotInitialized
|
|
* \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_Digest(SessionHandle session,
|
|
Byte* data_ptr,
|
|
Ulong data_len,
|
|
Byte* digest_ptr,
|
|
Ulong* digest_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_DigestUpdate continues a multiple-part message-digesting operation.
|
|
* @param session the session's handle
|
|
* @param part_ptr data to be digested
|
|
* @param part_len bytes of data to be digested
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DigestUpdate(SessionHandle session,
|
|
Byte* part_ptr,
|
|
Ulong part_len,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_DigestKey continues a multi-part message-digesting operation, by digesting the value of a secret key as part of the data already digested.
|
|
* @param session the session's handle
|
|
* @param key secret key to digest
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li KeyHandleInvalid
|
|
* \li KeyIndigestible \li KeySizeRange \li OK
|
|
* \li OperationNotInitialized \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DigestKey(SessionHandle session,
|
|
ObjectHandle key,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_DigestFinal finishes a multiple-part message-digesting operation.
|
|
* @param session the session's handle
|
|
* @param digest_ptr gets the message digest
|
|
* @param digest_len_ptr gets uint8_t count of digest
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionCanceled \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li OperationNotInitialized
|
|
* \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DigestFinal(SessionHandle session,
|
|
Byte* digest_ptr,
|
|
Ulong* digest_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/****************************** Signing and MACing functions ******************************/
|
|
|
|
/**
|
|
* C_SignInit initializes a signature (private key encryption) operation, where the signature is (will be) an appendix to the data, and plaintext cannot be recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param mechanism_ptr the signature mechanism
|
|
* @param key handle of signature key
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li KeyFunctionNotPermitted \li KeyHandleInvalid \li KeySizeRange
|
|
* \li KeyTypeInconsistent \li MechanismInvalid \li MechanismParamInvalid
|
|
* \li OK \li OperationActive \li PinExpired
|
|
* \li SessionClosed \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_SignInit(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
ObjectHandle key,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Sign signs (encrypts with private key) data in a single part, where the signature is (will be) an appendix to the data, and plaintext cannot be recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param data_ptr the data to sign
|
|
* @param data_len count of bytes to sign
|
|
* @param signature_ptr gets the signature
|
|
* @param signature_len_ptr gets signature length
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataInvalid \li DataLenRange \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid \li UserNotLoggedIn \li FunctionRejected
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_Sign(SessionHandle session,
|
|
Byte* data_ptr,
|
|
Ulong data_len,
|
|
Byte* signature_ptr,
|
|
Ulong* signature_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Sign signs (encrypts with private key) data in a single part, where the signature is (will be) an appendix to the data, and plaintext cannot be recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param data the data to sign
|
|
* @param signature gets the signature
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataInvalid \li DataLenRange \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid \li UserNotLoggedIn \li FunctionRejected
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAllocA, typename TAllocB>
|
|
bool C_Sign(SessionHandle session,
|
|
const std::vector<uint8_t, TAllocA>& data,
|
|
std::vector<uint8_t, TAllocB>& signature,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
Ulong signature_size = 0;
|
|
if(!C_Sign(session,
|
|
const_cast<Byte*>((data.data())),
|
|
static_cast<Ulong>(data.size()),
|
|
nullptr,
|
|
&signature_size,
|
|
return_value))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
signature.resize(signature_size);
|
|
if (!C_Sign(session,
|
|
const_cast<Byte*>(data.data()),
|
|
static_cast<Ulong>(data.size()),
|
|
signature.data(),
|
|
&signature_size,
|
|
return_value))
|
|
{
|
|
return false;
|
|
}
|
|
signature.resize(signature_size);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* C_SignUpdate continues a multiple-part signature operation, where the signature is (will be) an appendix to the data, and plaintext cannot be recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param part_ptr the data to sign
|
|
* @param part_len count of bytes to sign
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DataLenRange
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionCanceled \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li OperationNotInitialized
|
|
* \li SessionClosed \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_SignUpdate(SessionHandle session,
|
|
Byte* part_ptr,
|
|
Ulong part_len,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_SignUpdate continues a multiple-part signature operation, where the signature is (will be) an appendix to the data, and plaintext cannot be recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param part the data to sign
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DataLenRange
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionCanceled \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li OperationNotInitialized
|
|
* \li SessionClosed \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAlloc>
|
|
bool C_SignUpdate(SessionHandle session,
|
|
const std::vector<uint8_t, TAlloc>& part,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
return C_SignUpdate(session,
|
|
const_cast<Byte*>(part.data()),
|
|
static_cast<Ulong>(part.size()),
|
|
return_value);
|
|
}
|
|
|
|
/**
|
|
* C_SignFinal finishes a multiple-part signature operation, returning the signature.
|
|
* @param session the session's handle
|
|
* @param signature_ptr gets the signature
|
|
* @param signature_len_ptr gets signature length
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataLenRange \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li OperationNotInitialized \li SessionClosed \li SessionHandleInvalid
|
|
* \li UserNotLoggedIn \li FunctionRejected
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_SignFinal(SessionHandle session,
|
|
Byte* signature_ptr,
|
|
Ulong* signature_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_SignFinal finishes a multiple-part signature operation, returning the signature.
|
|
* @param session the session's handle
|
|
* @param signature gets the signature
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataLenRange \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li OperationNotInitialized \li SessionClosed \li SessionHandleInvalid
|
|
* \li UserNotLoggedIn \li FunctionRejected
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAlloc>
|
|
bool C_SignFinal(SessionHandle session,
|
|
std::vector<uint8_t, TAlloc>& signature,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
Ulong signature_size = 0;
|
|
if(!C_SignFinal(session, nullptr, &signature_size, return_value))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
signature.resize(signature_size);
|
|
if (!C_SignFinal(session, signature.data(), &signature_size, return_value))
|
|
{
|
|
return false;
|
|
}
|
|
signature.resize(signature_size);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* C_SignRecoverInit initializes a signature operation, where the data can be recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param mechanism_ptr the signature mechanism
|
|
* @param key handle of the signature key
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li KeyFunctionNotPermitted \li KeyHandleInvalid \li KeySizeRange
|
|
* \li KeyTypeInconsistent \li MechanismInvalid \li MechanismParamInvalid
|
|
* \li OK \li OperationActive \li PinExpired
|
|
* \li SessionClosed \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_SignRecoverInit(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
ObjectHandle key,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_SignRecover signs data in a single operation, where the data can be recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param data_ptr the data to sign
|
|
* @param data_len count of bytes to sign
|
|
* @param signature_ptr gets the signature
|
|
* @param signature_len_ptr gets signature length
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataInvalid \li DataLenRange \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_SignRecover(SessionHandle session,
|
|
Byte* data_ptr,
|
|
Ulong data_len,
|
|
Byte* signature_ptr,
|
|
Ulong* signature_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/****************************** Functions for verifying signatures and MACs ******************************/
|
|
|
|
/**
|
|
* C_VerifyInit initializes a verification operation, where the signature is an appendix to the data, and plaintext cannot be recovered from the signature (e.g. DSA).
|
|
* @param session the session's handle
|
|
* @param mechanism_ptr the verification mechanism
|
|
* @param key verification key
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li KeyFunctionNotPermitted \li KeyHandleInvalid \li KeySizeRange
|
|
* \li KeyTypeInconsistent \li MechanismInvalid \li MechanismParamInvalid
|
|
* \li OK \li OperationActive \li PinExpired
|
|
* \li SessionClosed \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_VerifyInit(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
ObjectHandle key,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Verify verifies a signature in a single-part operation, where the signature is an appendix to the data, and plaintext cannot be recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param data_ptr signed data
|
|
* @param data_len length of signed data
|
|
* @param signature_ptr signature
|
|
* @param signature_len signature length
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DataInvalid
|
|
* \li DataLenRange \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li OperationNotInitialized \li SessionClosed \li SessionHandleInvalid
|
|
* \li SignatureInvalid \li SignatureLenRange
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_Verify(SessionHandle session,
|
|
Byte* data_ptr,
|
|
Ulong data_len,
|
|
Byte* signature_ptr,
|
|
Ulong signature_len,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_Verify verifies a signature in a single-part operation, where the signature is an appendix to the data, and plaintext cannot be recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param data signed data
|
|
* @param signature signature
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DataInvalid
|
|
* \li DataLenRange \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li OperationNotInitialized \li SessionClosed \li SessionHandleInvalid
|
|
* \li SignatureInvalid \li SignatureLenRange
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAllocA, typename TAllocB>
|
|
bool C_Verify(SessionHandle session,
|
|
const std::vector<uint8_t, TAllocA>& data,
|
|
std::vector<uint8_t, TAllocB>& signature,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
return C_Verify(session,
|
|
const_cast<Byte*>(data.data()),
|
|
static_cast<Ulong>(data.size()),
|
|
signature.data(),
|
|
static_cast<Ulong>(signature.size()),
|
|
return_value);
|
|
}
|
|
|
|
/**
|
|
* C_VerifyUpdate continues a multiple-part verification operation, where the signature is an appendix to the data, and plaintext cannot be recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param part_ptr signed data
|
|
* @param part_len length of signed data
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DataLenRange
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionCanceled \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li OperationNotInitialized
|
|
* \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_VerifyUpdate(SessionHandle session,
|
|
Byte* part_ptr,
|
|
Ulong part_len,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_VerifyUpdate continues a multiple-part verification operation, where the signature is an appendix to the data, and plaintext cannot be recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param part signed data
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DataLenRange
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionCanceled \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li OperationNotInitialized
|
|
* \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
template<typename TAlloc>
|
|
bool C_VerifyUpdate(SessionHandle session,
|
|
std::vector<uint8_t, TAlloc> part,
|
|
ReturnValue* return_value = ThrowException) const
|
|
{
|
|
return C_VerifyUpdate(session, part.data(), static_cast<Ulong>(part.size()), return_value);
|
|
}
|
|
|
|
/**
|
|
* C_VerifyFinal finishes a multiple-part verification operation, checking the signature.
|
|
* @param session the session's handle
|
|
* @param signature_ptr signature to verify
|
|
* @param signature_len signature length
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DataLenRange
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionCanceled \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li OperationNotInitialized
|
|
* \li SessionClosed \li SessionHandleInvalid \li SignatureInvalid
|
|
* \li SignatureLenRange
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_VerifyFinal(SessionHandle session,
|
|
Byte* signature_ptr,
|
|
Ulong signature_len,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_VerifyRecoverInit initializes a signature verification operation, where the data is recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param mechanism_ptr the verification mechanism
|
|
* @param key verification key
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li KeyFunctionNotPermitted \li KeyHandleInvalid \li KeySizeRange
|
|
* \li KeyTypeInconsistent \li MechanismInvalid \li MechanismParamInvalid
|
|
* \li OK \li OperationActive \li PinExpired
|
|
* \li SessionClosed \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_VerifyRecoverInit(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
ObjectHandle key,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_VerifyRecover verifies a signature in a single-part operation, where the data is recovered from the signature.
|
|
* @param session the session's handle
|
|
* @param signature_ptr signature to verify
|
|
* @param signature_len signature length
|
|
* @param data_ptr gets signed data
|
|
* @param data_len_ptr gets signed data len
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataInvalid \li DataLenRange \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid \li SignatureLenRange \li SignatureInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_VerifyRecover(SessionHandle session,
|
|
Byte* signature_ptr,
|
|
Ulong signature_len,
|
|
Byte* data_ptr,
|
|
Ulong* data_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/****************************** Dual-purpose cryptographic functions ******************************/
|
|
|
|
/**
|
|
* C_DigestEncryptUpdate continues a multiple-part digesting and encryption operation.
|
|
* @param session session's handle
|
|
* @param part_ptr the plaintext data
|
|
* @param part_len plaintext length
|
|
* @param encrypted_part_ptr gets ciphertext
|
|
* @param encrypted_part_len_ptr gets c-text length
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataLenRange \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li OperationNotInitialized \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DigestEncryptUpdate(SessionHandle session,
|
|
Byte* part_ptr,
|
|
Ulong part_len,
|
|
Byte* encrypted_part_ptr,
|
|
Ulong* encrypted_part_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const ;
|
|
|
|
/**
|
|
* C_DecryptDigestUpdate continues a multiple-part decryption and digesting operation.
|
|
* @param session session's handle
|
|
* @param encrypted_part_ptr ciphertext
|
|
* @param encrypted_part_len ciphertext length
|
|
* @param part_ptr gets plaintext
|
|
* @param part_len_ptr gets plaintext len
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li EncryptedDataInvalid \li EncryptedDataLenRange \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationNotInitialized \li SessionClosed
|
|
* \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DecryptDigestUpdate(SessionHandle session,
|
|
Byte* encrypted_part_ptr,
|
|
Ulong encrypted_part_len,
|
|
Byte* part_ptr,
|
|
Ulong* part_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_SignEncryptUpdate continues a multiple-part signing and encryption operation.
|
|
* @param session session's handle
|
|
* @param part_ptr the plaintext data
|
|
* @param part_len plaintext length
|
|
* @param encrypted_part_ptr gets ciphertext
|
|
* @param encrypted_part_len_ptr gets c-text length
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataLenRange \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li OK
|
|
* \li OperationNotInitialized \li SessionClosed \li SessionHandleInvalid
|
|
* \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_SignEncryptUpdate(SessionHandle session,
|
|
Byte* part_ptr,
|
|
Ulong part_len,
|
|
Byte* encrypted_part_ptr,
|
|
Ulong* encrypted_part_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_DecryptVerifyUpdate continues a multiple-part decryption and verify operation.
|
|
* @param session session's handle
|
|
* @param encrypted_part_ptr ciphertext
|
|
* @param encrypted_part_len ciphertext length
|
|
* @param part_ptr gets plaintext
|
|
* @param part_len_ptr gets p-text length
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DataLenRange \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li EncryptedDataInvalid \li EncryptedDataLenRange
|
|
* \li FunctionCanceled \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li OK \li OperationNotInitialized
|
|
* \li SessionClosed \li SessionHandleInvalid
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DecryptVerifyUpdate(SessionHandle session,
|
|
Byte* encrypted_part_ptr,
|
|
Ulong encrypted_part_len,
|
|
Byte* part_ptr,
|
|
Ulong* part_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/****************************** Key management functions ******************************/
|
|
|
|
/**
|
|
* C_GenerateKey generates a secret key, creating a new key object.
|
|
* @param session the session's handle
|
|
* @param mechanism_ptr key generation mech.
|
|
* @param attribute_template_ptr template for new key
|
|
* @param count # of attrs in template
|
|
* @param key_ptr gets handle of new key
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li AttributeReadOnly \li AttributeTypeInvalid
|
|
* \li AttributeValueInvalid \li CryptokiNotInitialized \li CurveNotSupported
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionCanceled \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li MechanismInvalid \li MechanismParamInvalid
|
|
* \li OK \li OperationActive \li PinExpired
|
|
* \li SessionClosed \li SessionHandleInvalid \li SessionReadOnly
|
|
* \li TemplateIncomplete \li TemplateInconsistent \li TokenWriteProtected
|
|
* \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GenerateKey(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
Attribute* attribute_template_ptr,
|
|
Ulong count,
|
|
ObjectHandle* key_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GenerateKeyPair generates a public-key/private-key pair, creating new key objects.
|
|
* @param session session handle
|
|
* @param mechanism_ptr key-gen mech.
|
|
* @param public_key_template_ptr template for pub. key
|
|
* @param public_key_attribute_count # pub. attrs.
|
|
* @param private_key_template_ptr template for priv. key
|
|
* @param private_key_attribute_count # priv. attrs.
|
|
* @param public_key_ptr gets pub. key handle
|
|
* @param private_key_ptr gets priv. key handle
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li AttributeReadOnly \li AttributeTypeInvalid
|
|
* \li AttributeValueInvalid \li CryptokiNotInitialized \li CurveNotSupported
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li DomainParamsInvalid \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li MechanismInvalid
|
|
* \li MechanismParamInvalid \li OK \li OperationActive
|
|
* \li PinExpired \li SessionClosed \li SessionHandleInvalid
|
|
* \li SessionReadOnly \li TemplateIncomplete \li TemplateInconsistent
|
|
* \li TokenWriteProtected \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GenerateKeyPair(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
Attribute* public_key_template_ptr,
|
|
Ulong public_key_attribute_count,
|
|
Attribute* private_key_template_ptr,
|
|
Ulong private_key_attribute_count,
|
|
ObjectHandle* public_key_ptr,
|
|
ObjectHandle* private_key_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_WrapKey wraps (i.e., encrypts) a key.
|
|
* @param session the session's handle
|
|
* @param mechanism_ptr the wrapping mechanism
|
|
* @param wrapping_key wrapping key
|
|
* @param key key to be wrapped
|
|
* @param wrapped_key_ptr gets wrapped key
|
|
* @param wrapped_key_len_ptr gets wrapped key size
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li FunctionCanceled \li FunctionFailed \li GeneralError
|
|
* \li HostMemory \li KeyHandleInvalid \li KeyNotWrappable
|
|
* \li KeySizeRange \li KeyUnextractable \li MechanismInvalid
|
|
* \li MechanismParamInvalid \li OK \li OperationActive
|
|
* \li PinExpired \li SessionClosed \li SessionHandleInvalid
|
|
* \li UserNotLoggedIn \li WrappingKeyHandleInvalid \li WrappingKeySizeRange
|
|
* \li WrappingKeyTypeInconsistent
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_WrapKey(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
ObjectHandle wrapping_key,
|
|
ObjectHandle key,
|
|
Byte* wrapped_key_ptr,
|
|
Ulong* wrapped_key_len_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object.
|
|
* @param session session's handle
|
|
* @param mechanism_ptr unwrapping mech.
|
|
* @param unwrapping_key unwrapping key
|
|
* @param wrapped_key_ptr the wrapped key
|
|
* @param wrapped_key_len wrapped key len
|
|
* @param attribute_template_ptr new key template
|
|
* @param attribute_count template length
|
|
* @param key_ptr gets new handle
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li AttributeReadOnly \li AttributeTypeInvalid
|
|
* \li AttributeValueInvalid \li BufferTooSmall \li CryptokiNotInitialized
|
|
* \li CurveNotSupported \li DeviceError \li DeviceMemory
|
|
* \li DeviceRemoved \li DomainParamsInvalid \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li MechanismInvalid \li MechanismParamInvalid \li OK
|
|
* \li OperationActive \li PinExpired \li SessionClosed
|
|
* \li SessionHandleInvalid \li SessionReadOnly \li TemplateIncomplete
|
|
* \li TemplateInconsistent \li TokenWriteProtected \li UnwrappingKeyHandleInvalid
|
|
* \li UnwrappingKeySizeRange \li UnwrappingKeyTypeInconsistent \li UserNotLoggedIn
|
|
* \li WrappedKeyInvalid \li WrappedKeyLenRange
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_UnwrapKey(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
ObjectHandle unwrapping_key,
|
|
Byte* wrapped_key_ptr,
|
|
Ulong wrapped_key_len,
|
|
Attribute* attribute_template_ptr,
|
|
Ulong attribute_count,
|
|
ObjectHandle* key_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_DeriveKey derives a key from a base key, creating a new key object.
|
|
* @param session session's handle
|
|
* @param mechanism_ptr key deriv. mech.
|
|
* @param base_key base key
|
|
* @param attribute_template_ptr new key template
|
|
* @param attribute_count template length
|
|
* @param key_ptr gets new handle
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li AttributeReadOnly \li AttributeTypeInvalid
|
|
* \li AttributeValueInvalid \li CryptokiNotInitialized \li CurveNotSupported
|
|
* \li DeviceError \li DeviceMemory \li DeviceRemoved
|
|
* \li DomainParamsInvalid \li FunctionCanceled \li FunctionFailed
|
|
* \li GeneralError \li HostMemory \li KeyHandleInvalid
|
|
* \li KeySizeRange \li KeyTypeInconsistent \li MechanismInvalid
|
|
* \li MechanismParamInvalid \li OK \li OperationActive
|
|
* \li PinExpired \li SessionClosed \li SessionHandleInvalid
|
|
* \li SessionReadOnly \li TemplateIncomplete \li TemplateInconsistent
|
|
* \li TokenWriteProtected \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_DeriveKey(SessionHandle session,
|
|
Mechanism* mechanism_ptr,
|
|
ObjectHandle base_key,
|
|
Attribute* attribute_template_ptr,
|
|
Ulong attribute_count,
|
|
ObjectHandle* key_ptr,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/****************************** Random number generation functions ******************************/
|
|
|
|
/**
|
|
* C_SeedRandom mixes additional seed material into the token's random number generator.
|
|
* @param session the session's handle
|
|
* @param seed_ptr the seed material
|
|
* @param seed_len length of seed material
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationActive \li RandomSeedNotSupported
|
|
* \li RandomNoRng \li SessionClosed \li SessionHandleInvalid
|
|
* \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_SeedRandom(SessionHandle session,
|
|
Byte* seed_ptr,
|
|
Ulong seed_len,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_GenerateRandom generates random data.
|
|
* @param session the session's handle
|
|
* @param random_data_ptr receives the random data
|
|
* @param random_len # of bytes to generate
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li ArgumentsBad \li CryptokiNotInitialized \li DeviceError
|
|
* \li DeviceMemory \li DeviceRemoved \li FunctionCanceled
|
|
* \li FunctionFailed \li GeneralError \li HostMemory
|
|
* \li OK \li OperationActive \li RandomNoRng
|
|
* \li SessionClosed \li SessionHandleInvalid \li UserNotLoggedIn
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GenerateRandom(SessionHandle session,
|
|
Byte* random_data_ptr,
|
|
Ulong random_len,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/****************************** Parallel function management functions ******************************/
|
|
|
|
/**
|
|
* C_GetFunctionStatus is a legacy function; it obtains an updated status of a function running in parallel with an application.
|
|
* @param session the session's handle
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li FunctionFailed \li FunctionNotParallel
|
|
* \li GeneralError \li HostMemory \li SessionHandleInvalid
|
|
* \li SessionClosed
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_GetFunctionStatus(SessionHandle session,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
/**
|
|
* C_CancelFunction is a legacy function; it cancels a function running in parallel.
|
|
* @param session the session's handle
|
|
* @param return_value default value (`ThrowException`): throw exception on error.
|
|
* if a non-NULL pointer is passed: return_value receives the return value of the PKCS#11 function and no exception is thrown.
|
|
* At least the following PKCS#11 return values may be returned:
|
|
* \li CryptokiNotInitialized \li FunctionFailed \li FunctionNotParallel
|
|
* \li GeneralError \li HostMemory \li SessionHandleInvalid
|
|
* \li SessionClosed
|
|
* @return true on success, false otherwise
|
|
*/
|
|
bool C_CancelFunction(SessionHandle session,
|
|
ReturnValue* return_value = ThrowException) const;
|
|
|
|
private:
|
|
const FunctionListPtr m_func_list_ptr;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_Error : public Exception
|
|
{
|
|
public:
|
|
explicit PKCS11_Error(const std::string& what) :
|
|
Exception("PKCS11 error", what)
|
|
{
|
|
}
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::Pkcs11Error; }
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_ReturnError final : public PKCS11_Error
|
|
{
|
|
public:
|
|
explicit PKCS11_ReturnError(ReturnValue return_val) :
|
|
PKCS11_Error(std::to_string(static_cast< uint32_t >(return_val))),
|
|
m_return_val(return_val)
|
|
{}
|
|
|
|
inline ReturnValue get_return_value() const
|
|
{
|
|
return m_return_val;
|
|
}
|
|
|
|
int error_code() const noexcept override
|
|
{
|
|
return static_cast<int>(m_return_val);
|
|
}
|
|
|
|
private:
|
|
const ReturnValue m_return_val;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Dynamically_Loaded_Library;
|
|
|
|
namespace PKCS11 {
|
|
|
|
/**
|
|
* Loads the PKCS#11 shared library
|
|
* Calls C_Initialize on load and C_Finalize on destruction
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Module final
|
|
{
|
|
public:
|
|
/**
|
|
* Loads the shared library and calls C_Initialize
|
|
* @param file_path the path to the PKCS#11 shared library
|
|
* @param init_args flags to use for `C_Initialize`
|
|
*/
|
|
Module(const std::string& file_path, C_InitializeArgs init_args = { nullptr, nullptr, nullptr, nullptr, static_cast< CK_FLAGS >(Flag::OsLockingOk), nullptr });
|
|
|
|
Module(Module&& other);
|
|
Module& operator=(Module&& other) = delete;
|
|
|
|
// Dtor calls C_Finalize(). A copy could be deleted while the origin still exists
|
|
// Furthermore std::unique_ptr member -> not copyable
|
|
Module(const Module& other) = delete;
|
|
Module& operator=(const Module& other) = delete;
|
|
|
|
/// Calls C_Finalize()
|
|
~Module() noexcept;
|
|
|
|
/**
|
|
* Reloads the module and reinitializes it
|
|
* @param init_args flags to use for `C_Initialize`
|
|
*/
|
|
void reload(C_InitializeArgs init_args = { nullptr, nullptr, nullptr, nullptr, static_cast< CK_FLAGS >(Flag::OsLockingOk), nullptr });
|
|
|
|
inline LowLevel* operator->() const
|
|
{
|
|
return m_low_level.get();
|
|
}
|
|
|
|
/// @return general information about Cryptoki
|
|
inline Info get_info() const
|
|
{
|
|
Info info;
|
|
m_low_level->C_GetInfo(&info);
|
|
return info;
|
|
}
|
|
|
|
private:
|
|
const std::string m_file_path;
|
|
FunctionListPtr m_func_list = nullptr;
|
|
std::unique_ptr<Dynamically_Loaded_Library> m_library;
|
|
std::unique_ptr<LowLevel> m_low_level = nullptr;
|
|
};
|
|
|
|
/// Represents a PKCS#11 Slot, i.e., a card reader
|
|
class BOTAN_PUBLIC_API(2,0) Slot final
|
|
{
|
|
public:
|
|
/**
|
|
* @param module the PKCS#11 module to use
|
|
* @param slot_id the slot id to use
|
|
*/
|
|
Slot(Module& module, SlotId slot_id);
|
|
|
|
/// @return a reference to the module that is used
|
|
inline Module& module() const
|
|
{
|
|
return m_module;
|
|
}
|
|
|
|
/// @return the slot id
|
|
inline SlotId slot_id() const
|
|
{
|
|
return m_slot_id;
|
|
}
|
|
|
|
/**
|
|
* Get available slots
|
|
* @param module the module to use
|
|
* @param token_present true if only slots with attached tokens should be returned, false for all slots
|
|
* @return a list of available slots (calls C_GetSlotList)
|
|
*/
|
|
static std::vector<SlotId> get_available_slots(Module& module, bool token_present);
|
|
|
|
/// @return information about the slot (`C_GetSlotInfo`)
|
|
SlotInfo get_slot_info() const;
|
|
|
|
/// Obtains a list of mechanism types supported by the slot (`C_GetMechanismList`)
|
|
std::vector<MechanismType> get_mechanism_list() const;
|
|
|
|
/// Obtains information about a particular mechanism possibly supported by a slot (`C_GetMechanismInfo`)
|
|
MechanismInfo get_mechanism_info(MechanismType mechanism_type) const;
|
|
|
|
/// Obtains information about a particular token in the system (`C_GetTokenInfo`)
|
|
TokenInfo get_token_info() const;
|
|
|
|
/**
|
|
* Calls `C_InitToken` to initialize the token
|
|
* @param label the label for the token (must not exceed 32 bytes according to PKCS#11)
|
|
* @param so_pin the PIN of the security officer
|
|
*/
|
|
void initialize(const std::string& label, const secure_string& so_pin) const;
|
|
|
|
private:
|
|
const std::reference_wrapper<Module> m_module;
|
|
const SlotId m_slot_id;
|
|
};
|
|
|
|
/// Represents a PKCS#11 session
|
|
class BOTAN_PUBLIC_API(2,0) Session final
|
|
{
|
|
public:
|
|
/**
|
|
* @param slot the slot to use
|
|
* @param read_only true if the session should be read only, false to create a read-write session
|
|
*/
|
|
Session(Slot& slot, bool read_only);
|
|
|
|
/**
|
|
* @param slot the slot to use
|
|
* @param flags the flags to use for the session. Remark: Flag::SerialSession is mandatory
|
|
* @param callback_data application-defined pointer to be passed to the notification callback
|
|
* @param notify_callback address of the notification callback function
|
|
*/
|
|
Session(Slot& slot, Flags flags, VoidPtr callback_data, Notify notify_callback);
|
|
|
|
/// Takes ownership of a session
|
|
Session(Slot& slot, SessionHandle handle);
|
|
|
|
Session(Session&& other) = default;
|
|
Session& operator=(Session&& other) = delete;
|
|
|
|
// Dtor calls C_CloseSession() and eventually C_Logout. A copy could close the session while the origin still exists
|
|
Session(const Session& other) = delete;
|
|
Session& operator=(const Session& other) = delete;
|
|
|
|
/// Logout user and close the session on destruction
|
|
~Session() noexcept;
|
|
|
|
/// @return a reference to the slot
|
|
inline const Slot& slot() const
|
|
{
|
|
return m_slot;
|
|
}
|
|
|
|
/// @return the session handle of this session
|
|
inline SessionHandle handle() const
|
|
{
|
|
return m_handle;
|
|
}
|
|
|
|
/// @return a reference to the used module
|
|
inline Module& module() const
|
|
{
|
|
return m_slot.module();
|
|
}
|
|
|
|
/// @return the released session handle
|
|
SessionHandle release();
|
|
|
|
/**
|
|
* Login to this session
|
|
* @param userType the user type to use for the login
|
|
* @param pin the PIN of the user
|
|
*/
|
|
void login(UserType userType, const secure_string& pin);
|
|
|
|
/// Logout from this session
|
|
void logoff();
|
|
|
|
/// @return information about this session
|
|
SessionInfo get_info() const;
|
|
|
|
/// Calls `C_SetPIN` to change the PIN using the old PIN (requires a logged in session)
|
|
void set_pin(const secure_string& old_pin, const secure_string& new_pin) const;
|
|
|
|
/// Calls `C_InitPIN` to change or initialize the PIN using the SO_PIN (requires a logged in session)
|
|
void init_pin(const secure_string& new_pin);
|
|
|
|
private:
|
|
const Slot& m_slot;
|
|
SessionHandle m_handle;
|
|
bool m_logged_in;
|
|
};
|
|
|
|
}
|
|
}
|
|
|
|
|
|
namespace Botan {
|
|
namespace PKCS11 {
|
|
|
|
class Module;
|
|
|
|
/// Helper class to build the Attribute / CK_ATTRIBUTE structures
|
|
class BOTAN_PUBLIC_API(2,0) AttributeContainer
|
|
{
|
|
public:
|
|
AttributeContainer() = default;
|
|
|
|
/// @param object_class the class type of this container
|
|
AttributeContainer(ObjectClass object_class);
|
|
|
|
virtual ~AttributeContainer() = default;
|
|
|
|
AttributeContainer(AttributeContainer&& other) = default;
|
|
AttributeContainer& operator=(AttributeContainer&& other) = default;
|
|
|
|
// Warning when implementing copy/assignment: m_attributes contains pointers to the other members which must be updated after a copy
|
|
AttributeContainer(const AttributeContainer& other) = delete;
|
|
AttributeContainer& operator=(const AttributeContainer& other) = delete;
|
|
|
|
/// @return the attributes this container contains
|
|
inline const std::vector<Attribute>& attributes() const
|
|
{
|
|
return m_attributes;
|
|
}
|
|
|
|
/// @return raw attribute data
|
|
inline Attribute* data() const
|
|
{
|
|
return const_cast< Attribute* >(m_attributes.data());
|
|
}
|
|
|
|
/// @return the number of attributes in this container
|
|
inline size_t count() const
|
|
{
|
|
return m_attributes.size();
|
|
}
|
|
|
|
/**
|
|
* Add a class attribute (CKA_CLASS / AttributeType::Class).
|
|
* @param object_class class attribute to add
|
|
*/
|
|
void add_class(ObjectClass object_class);
|
|
|
|
/**
|
|
* Add a string attribute (e.g. CKA_LABEL / AttributeType::Label).
|
|
* @param attribute attribute type
|
|
* @param value string value to add
|
|
*/
|
|
void add_string(AttributeType attribute, const std::string& value);
|
|
|
|
/**
|
|
* Add a binary attribute (e.g. CKA_ID / AttributeType::Id).
|
|
* @param attribute attribute type
|
|
* @param value binary attribute value to add
|
|
* @param length size of the binary attribute value in bytes
|
|
*/
|
|
void add_binary(AttributeType attribute, const uint8_t* value, size_t length);
|
|
|
|
/**
|
|
* Add a binary attribute (e.g. CKA_ID / AttributeType::Id).
|
|
* @param attribute attribute type
|
|
* @param binary binary attribute value to add
|
|
*/
|
|
template<typename TAlloc>
|
|
void add_binary(AttributeType attribute, const std::vector<uint8_t, TAlloc>& binary)
|
|
{
|
|
add_binary(attribute, binary.data(), binary.size());
|
|
}
|
|
|
|
/**
|
|
* Add a bool attribute (e.g. CKA_SENSITIVE / AttributeType::Sensitive).
|
|
* @param attribute attribute type
|
|
* @param value boolean value to add
|
|
*/
|
|
void add_bool(AttributeType attribute, bool value);
|
|
|
|
/**
|
|
* Add a numeric attribute (e.g. CKA_MODULUS_BITS / AttributeType::ModulusBits).
|
|
* @param attribute attribute type
|
|
* @param value numeric value to add
|
|
*/
|
|
template<typename T>
|
|
void add_numeric(AttributeType attribute, T value)
|
|
{
|
|
static_assert(std::is_integral<T>::value, "Numeric value required.");
|
|
m_numerics.push_back(static_cast< uint64_t >(value));
|
|
add_attribute(attribute, reinterpret_cast< uint8_t* >(&m_numerics.back()), sizeof(T));
|
|
}
|
|
|
|
protected:
|
|
/// Add an attribute with the given value and size to the attribute collection `m_attributes`
|
|
void add_attribute(AttributeType attribute, const uint8_t* value, uint32_t size);
|
|
|
|
private:
|
|
std::vector<Attribute> m_attributes;
|
|
std::list<uint64_t> m_numerics;
|
|
std::list<std::string> m_strings;
|
|
std::list<secure_vector<uint8_t>> m_vectors;
|
|
};
|
|
|
|
/// Manages calls to C_FindObjects* functions (C_FindObjectsInit -> C_FindObjects -> C_FindObjectsFinal)
|
|
class BOTAN_PUBLIC_API(2,0) ObjectFinder final
|
|
{
|
|
public:
|
|
/**
|
|
* Initializes a search for token and session objects that match a template (calls C_FindObjectsInit)
|
|
* @param session the session to use for the search
|
|
* @param search_template the search_template as a vector of `Attribute`
|
|
*/
|
|
ObjectFinder(Session& session, const std::vector<Attribute>& search_template);
|
|
|
|
ObjectFinder(const ObjectFinder& other) = default;
|
|
ObjectFinder& operator=(const ObjectFinder& other) = delete;
|
|
|
|
ObjectFinder(ObjectFinder&& other) = default;
|
|
ObjectFinder& operator=(ObjectFinder&& other) = delete;
|
|
|
|
/// Terminates a search for token and session objects (calls C_FindObjectsFinal)
|
|
~ObjectFinder() noexcept;
|
|
|
|
/**
|
|
* Starts or continues a search for token and session objects that match a template, obtaining additional object handles (calls C_FindObjects)
|
|
* @param max_count maximum amount of object handles to retrieve. Default = 100
|
|
* @return the result of the search as a vector of `ObjectHandle`
|
|
*/
|
|
std::vector<ObjectHandle> find(std::uint32_t max_count = 100) const;
|
|
|
|
/// Finishes the search operation manually to allow a new ObjectFinder to exist
|
|
void finish();
|
|
|
|
/// @return the module this `ObjectFinder` belongs to
|
|
inline Module& module() const
|
|
{
|
|
return m_session.get().module();
|
|
}
|
|
|
|
private:
|
|
const std::reference_wrapper<Session> m_session;
|
|
bool m_search_terminated;
|
|
};
|
|
|
|
/// Common attributes of all objects
|
|
class BOTAN_PUBLIC_API(2,0) ObjectProperties : public AttributeContainer
|
|
{
|
|
public:
|
|
/// @param object_class the object class of the object
|
|
ObjectProperties(ObjectClass object_class);
|
|
|
|
/// @return the object class of this object
|
|
inline ObjectClass object_class() const
|
|
{
|
|
return m_object_class;
|
|
}
|
|
|
|
private:
|
|
const ObjectClass m_object_class;
|
|
};
|
|
|
|
/// Common attributes of all storage objects
|
|
class BOTAN_PUBLIC_API(2,0) StorageObjectProperties : public ObjectProperties
|
|
{
|
|
public:
|
|
/// @param object_class the CK_OBJECT_CLASS this storage object belongs to
|
|
StorageObjectProperties(ObjectClass object_class);
|
|
|
|
/// @param label description of the object (RFC2279 string)
|
|
inline void set_label(const std::string& label)
|
|
{
|
|
add_string(AttributeType::Label, label);
|
|
}
|
|
|
|
/// @param value if true the object is a token object; otherwise the object is a session object
|
|
inline void set_token(bool value)
|
|
{
|
|
add_bool(AttributeType::Token, value);
|
|
}
|
|
|
|
/**
|
|
* @param value if true the object is a private object; otherwise the object is a public object
|
|
* When private, a user may not access the object until the user has been authenticated to the token
|
|
*/
|
|
inline void set_private(bool value)
|
|
{
|
|
add_bool(AttributeType::Private, value);
|
|
}
|
|
|
|
/// @param value if true the object can be modified, otherwise it is read-only
|
|
void set_modifiable(bool value)
|
|
{
|
|
add_bool(AttributeType::Modifiable, value);
|
|
}
|
|
|
|
/// @param value if true the object can be copied using C_CopyObject
|
|
void set_copyable(bool value)
|
|
{
|
|
add_bool(AttributeType::Copyable, value);
|
|
}
|
|
|
|
/// @param value if true the object can be destroyed using C_DestroyObject
|
|
void set_destroyable(bool value)
|
|
{
|
|
add_bool(AttributeType::Destroyable, value);
|
|
}
|
|
};
|
|
|
|
/// Common attributes of all data objects
|
|
class BOTAN_PUBLIC_API(2,0) DataObjectProperties final : public StorageObjectProperties
|
|
{
|
|
public:
|
|
DataObjectProperties();
|
|
|
|
/// @param value description of the application that manages the object (RFC2279 string)
|
|
inline void set_application(const std::string& value)
|
|
{
|
|
add_string(AttributeType::Application, value);
|
|
}
|
|
|
|
/// @param object_id DER-encoding of the object identifier indicating the data object type
|
|
inline void set_object_id(const std::vector<uint8_t>& object_id)
|
|
{
|
|
add_binary(AttributeType::ObjectId, object_id);
|
|
}
|
|
|
|
/// @param value value of the object
|
|
inline void set_value(const secure_vector<uint8_t>& value)
|
|
{
|
|
add_binary(AttributeType::Value, value);
|
|
}
|
|
};
|
|
|
|
/// Common attributes of all certificate objects
|
|
class BOTAN_PUBLIC_API(2,0) CertificateProperties : public StorageObjectProperties
|
|
{
|
|
public:
|
|
/// @param cert_type type of certificate
|
|
CertificateProperties(CertificateType cert_type);
|
|
|
|
/// @param value the certificate can be trusted for the application that it was created (can only be set to true by SO user)
|
|
inline void set_trusted(bool value)
|
|
{
|
|
add_bool(AttributeType::Trusted, value);
|
|
}
|
|
|
|
/// @param category one of `CertificateCategory`
|
|
inline void set_category(CertificateCategory category)
|
|
{
|
|
add_numeric(AttributeType::CertificateCategory, static_cast< CK_CERTIFICATE_CATEGORY >(category));
|
|
}
|
|
|
|
/**
|
|
* @param checksum the value of this attribute is derived from the certificate by taking the
|
|
* first three bytes of the SHA - 1 hash of the certificate object's `CKA_VALUE` attribute
|
|
*/
|
|
inline void set_check_value(const std::vector<uint8_t>& checksum)
|
|
{
|
|
add_binary(AttributeType::CheckValue, checksum);
|
|
}
|
|
|
|
/// @param date start date for the certificate
|
|
inline void set_start_date(Date date)
|
|
{
|
|
add_binary(AttributeType::StartDate, reinterpret_cast<uint8_t*>(&date), sizeof(Date));
|
|
}
|
|
|
|
/// @param date end date for the certificate
|
|
inline void set_end_date(Date date)
|
|
{
|
|
add_binary(AttributeType::EndDate, reinterpret_cast<uint8_t*>(&date), sizeof(Date));
|
|
}
|
|
|
|
/// @param pubkey_info DER-encoding of the SubjectPublicKeyInfo for the public key contained in this certificate
|
|
inline void set_public_key_info(const std::vector<uint8_t>& pubkey_info)
|
|
{
|
|
add_binary(AttributeType::PublicKeyInfo, pubkey_info);
|
|
}
|
|
|
|
/// @return the certificate type of this certificate object
|
|
inline CertificateType cert_type() const
|
|
{
|
|
return m_cert_type;
|
|
}
|
|
|
|
private:
|
|
const CertificateType m_cert_type;
|
|
};
|
|
|
|
/// Common attributes of all key objects
|
|
class BOTAN_PUBLIC_API(2,0) KeyProperties : public StorageObjectProperties
|
|
{
|
|
public:
|
|
/**
|
|
* @param object_class the `CK_OBJECT_CLASS` this key object belongs to
|
|
* @param key_type type of key
|
|
*/
|
|
KeyProperties(ObjectClass object_class, KeyType key_type);
|
|
|
|
/// @param id key identifier for key
|
|
inline void set_id(const std::vector<uint8_t>& id)
|
|
{
|
|
add_binary(AttributeType::Id, id);
|
|
}
|
|
|
|
/// @param date start date for the key
|
|
inline void set_start_date(Date date)
|
|
{
|
|
add_binary(AttributeType::StartDate, reinterpret_cast<uint8_t*>(&date), sizeof(Date));
|
|
}
|
|
|
|
/// @param date end date for the key
|
|
inline void set_end_date(Date date)
|
|
{
|
|
add_binary(AttributeType::EndDate, reinterpret_cast<uint8_t*>(&date), sizeof(Date));
|
|
}
|
|
|
|
/// @param value true if key supports key derivation (i.e., if other keys can be derived from this one)
|
|
inline void set_derive(bool value)
|
|
{
|
|
add_bool(AttributeType::Derive, value);
|
|
}
|
|
|
|
/**
|
|
* Sets a list of mechanisms allowed to be used with this key
|
|
* Not implemented
|
|
*/
|
|
inline void set_allowed_mechanisms(const std::vector<MechanismType>&)
|
|
{
|
|
throw Not_Implemented("KeyProperties::set_allowed_mechanisms");
|
|
}
|
|
|
|
/// @return the key type of this key object
|
|
inline KeyType key_type() const
|
|
{
|
|
return m_key_type;
|
|
}
|
|
|
|
private:
|
|
const KeyType m_key_type;
|
|
};
|
|
|
|
/// Common attributes of all public key objects
|
|
class BOTAN_PUBLIC_API(2,0) PublicKeyProperties : public KeyProperties
|
|
{
|
|
public:
|
|
/// @param key_type type of key
|
|
PublicKeyProperties(KeyType key_type);
|
|
|
|
/// @param subject DER-encoding of the key subject name
|
|
inline void set_subject(const std::vector<uint8_t>& subject)
|
|
{
|
|
add_binary(AttributeType::Subject, subject);
|
|
}
|
|
|
|
/// @param value true if the key supports encryption
|
|
inline void set_encrypt(bool value)
|
|
{
|
|
add_bool(AttributeType::Encrypt, value);
|
|
}
|
|
|
|
/// @param value true if the key supports verification where the signature is an appendix to the data
|
|
inline void set_verify(bool value)
|
|
{
|
|
add_bool(AttributeType::Verify, value);
|
|
}
|
|
|
|
/// @param value true if the key supports verification where the data is recovered from the signature
|
|
inline void set_verify_recover(bool value)
|
|
{
|
|
add_bool(AttributeType::VerifyRecover, value);
|
|
}
|
|
|
|
/// @param value true if the key supports wrapping (i.e., can be used to wrap other keys)
|
|
inline void set_wrap(bool value)
|
|
{
|
|
add_bool(AttributeType::Wrap, value);
|
|
}
|
|
|
|
/**
|
|
* @param value true if the key can be trusted for the application that it was created.
|
|
* The wrapping key can be used to wrap keys with `CKA_WRAP_WITH_TRUSTED` set to `CK_TRUE`
|
|
*/
|
|
inline void set_trusted(bool value)
|
|
{
|
|
add_bool(AttributeType::Trusted, value);
|
|
}
|
|
|
|
/**
|
|
* For wrapping keys
|
|
* The attribute template to match against any keys wrapped using this wrapping key.
|
|
* Keys that do not match cannot be wrapped
|
|
* Not implemented
|
|
*/
|
|
inline void set_wrap_template(const AttributeContainer&)
|
|
{
|
|
throw Not_Implemented("PublicKeyProperties::set_wrap_template");
|
|
}
|
|
|
|
/// @param pubkey_info DER-encoding of the SubjectPublicKeyInfo for this public key
|
|
inline void set_public_key_info(const std::vector<uint8_t>& pubkey_info)
|
|
{
|
|
add_binary(AttributeType::PublicKeyInfo, pubkey_info);
|
|
}
|
|
};
|
|
|
|
/// Common attributes of all private keys
|
|
class BOTAN_PUBLIC_API(2,0) PrivateKeyProperties : public KeyProperties
|
|
{
|
|
public:
|
|
/// @param key_type type of key
|
|
PrivateKeyProperties(KeyType key_type);
|
|
|
|
/// @param subject DER-encoding of the key subject name
|
|
inline void set_subject(const std::vector<uint8_t>& subject)
|
|
{
|
|
add_binary(AttributeType::Subject, subject);
|
|
}
|
|
|
|
/// @param value true if the key is sensitive
|
|
inline void set_sensitive(bool value)
|
|
{
|
|
add_bool(AttributeType::Sensitive, value);
|
|
}
|
|
|
|
/// @param value true if the key supports decryption
|
|
inline void set_decrypt(bool value)
|
|
{
|
|
add_bool(AttributeType::Decrypt, value);
|
|
}
|
|
|
|
/// @param value true if the key supports signatures where the signature is an appendix to the data
|
|
inline void set_sign(bool value)
|
|
{
|
|
add_bool(AttributeType::Sign, value);
|
|
}
|
|
|
|
/// @param value true if the key supports signatures where the data can be recovered from the signature
|
|
inline void set_sign_recover(bool value)
|
|
{
|
|
add_bool(AttributeType::SignRecover, value);
|
|
}
|
|
|
|
/// @param value true if the key supports unwrapping (i.e., can be used to unwrap other keys)
|
|
inline void set_unwrap(bool value)
|
|
{
|
|
add_bool(AttributeType::Unwrap, value);
|
|
}
|
|
|
|
/// @param value true if the key is extractable and can be wrapped
|
|
inline void set_extractable(bool value)
|
|
{
|
|
add_bool(AttributeType::Extractable, value);
|
|
}
|
|
|
|
/// @param value true if the key can only be wrapped with a wrapping key that has `CKA_TRUSTED` set to `CK_TRUE`
|
|
inline void set_wrap_with_trusted(bool value)
|
|
{
|
|
add_bool(AttributeType::WrapWithTrusted, value);
|
|
}
|
|
|
|
/// @param value If true, the user has to supply the PIN for each use (sign or decrypt) with the key
|
|
inline void set_always_authenticate(bool value)
|
|
{
|
|
add_bool(AttributeType::AlwaysAuthenticate, value);
|
|
}
|
|
|
|
/**
|
|
* For wrapping keys
|
|
* The attribute template to apply to any keys unwrapped using this wrapping key.
|
|
* Any user supplied template is applied after this template as if the object has already been created
|
|
* Not implemented
|
|
*/
|
|
inline void set_unwrap_template(const AttributeContainer&)
|
|
{
|
|
throw Not_Implemented("PrivateKeyProperties::set_unwrap_template");
|
|
}
|
|
|
|
/// @param pubkey_info DER-encoding of the SubjectPublicKeyInfo for this public key
|
|
inline void set_public_key_info(const std::vector<uint8_t>& pubkey_info)
|
|
{
|
|
add_binary(AttributeType::PublicKeyInfo, pubkey_info);
|
|
}
|
|
};
|
|
|
|
/// Common attributes of all secret (symmetric) keys
|
|
class BOTAN_PUBLIC_API(2,0) SecretKeyProperties final : public KeyProperties
|
|
{
|
|
public:
|
|
/// @param key_type type of key
|
|
SecretKeyProperties(KeyType key_type);
|
|
|
|
/// @param value true if the key is sensitive
|
|
inline void set_sensitive(bool value)
|
|
{
|
|
add_bool(AttributeType::Sensitive, value);
|
|
}
|
|
|
|
/// @param value true if the key supports encryption
|
|
inline void set_encrypt(bool value)
|
|
{
|
|
add_bool(AttributeType::Encrypt, value);
|
|
}
|
|
|
|
/// @param value true if the key supports decryption
|
|
inline void set_decrypt(bool value)
|
|
{
|
|
add_bool(AttributeType::Decrypt, value);
|
|
}
|
|
|
|
/// @param value true if the key supports signatures where the signature is an appendix to the data
|
|
inline void set_sign(bool value)
|
|
{
|
|
add_bool(AttributeType::Sign, value);
|
|
}
|
|
|
|
/// @param value true if the key supports verification where the signature is an appendix to the data
|
|
inline void set_verify(bool value)
|
|
{
|
|
add_bool(AttributeType::Verify, value);
|
|
}
|
|
|
|
/// @param value true if the key supports unwrapping (i.e., can be used to unwrap other keys)
|
|
inline void set_unwrap(bool value)
|
|
{
|
|
add_bool(AttributeType::Unwrap, value);
|
|
}
|
|
|
|
/// @param value true if the key is extractable and can be wrapped
|
|
inline void set_extractable(bool value)
|
|
{
|
|
add_bool(AttributeType::Extractable, value);
|
|
}
|
|
|
|
/// @param value true if the key can only be wrapped with a wrapping key that has `CKA_TRUSTED` set to `CK_TRUE`
|
|
inline void set_wrap_with_trusted(bool value)
|
|
{
|
|
add_bool(AttributeType::WrapWithTrusted, value);
|
|
}
|
|
|
|
/// @param value if true, the user has to supply the PIN for each use (sign or decrypt) with the key
|
|
inline void set_always_authenticate(bool value)
|
|
{
|
|
add_bool(AttributeType::AlwaysAuthenticate, value);
|
|
}
|
|
|
|
/// @param value true if the key supports wrapping (i.e., can be used to wrap other keys)
|
|
inline void set_wrap(bool value)
|
|
{
|
|
add_bool(AttributeType::Wrap, value);
|
|
}
|
|
|
|
/**
|
|
* @param value the key can be trusted for the application that it was created.
|
|
* The wrapping key can be used to wrap keys with `CKA_WRAP_WITH_TRUSTED` set to `CK_TRUE`
|
|
*/
|
|
inline void set_trusted(bool value)
|
|
{
|
|
add_bool(AttributeType::Trusted, value);
|
|
}
|
|
|
|
/// @param checksum the key check value of this key
|
|
inline void set_check_value(const std::vector<uint8_t>& checksum)
|
|
{
|
|
add_binary(AttributeType::CheckValue, checksum);
|
|
}
|
|
|
|
/**
|
|
* For wrapping keys
|
|
* The attribute template to match against any keys wrapped using this wrapping key.
|
|
* Keys that do not match cannot be wrapped
|
|
* Not implemented
|
|
*/
|
|
inline void set_wrap_template(const AttributeContainer&)
|
|
{
|
|
throw Not_Implemented("SecretKeyProperties::set_wrap_template");
|
|
}
|
|
|
|
/**
|
|
* For wrapping keys
|
|
* The attribute template to apply to any keys unwrapped using this wrapping key
|
|
* Any user supplied template is applied after this template as if the object has already been created
|
|
* Not Implemented
|
|
*/
|
|
inline void set_unwrap_template(const AttributeContainer&)
|
|
{
|
|
throw Not_Implemented("SecretKeyProperties::set_unwrap_template");
|
|
}
|
|
};
|
|
|
|
/// Common attributes of domain parameter
|
|
class BOTAN_PUBLIC_API(2,0) DomainParameterProperties final : public StorageObjectProperties
|
|
{
|
|
public:
|
|
/// @param key_type type of key the domain parameters can be used to generate
|
|
DomainParameterProperties(KeyType key_type);
|
|
|
|
/// @return the key type
|
|
inline KeyType key_type() const
|
|
{
|
|
return m_key_type;
|
|
}
|
|
|
|
private:
|
|
const KeyType m_key_type;
|
|
};
|
|
|
|
/**
|
|
* Represents a PKCS#11 object.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Object
|
|
{
|
|
public:
|
|
/**
|
|
* Creates an `Object` from an existing PKCS#11 object
|
|
* @param session the session the object belongs to
|
|
* @param handle handle of the object
|
|
*/
|
|
|
|
Object(Session& session, ObjectHandle handle);
|
|
|
|
/**
|
|
* Creates the object
|
|
* @param session the session in which the object should be created
|
|
* @param obj_props properties of this object
|
|
*/
|
|
Object(Session& session, const ObjectProperties& obj_props);
|
|
|
|
Object(const Object&) = default;
|
|
Object& operator=(const Object&) = delete;
|
|
virtual ~Object() = default;
|
|
|
|
/// Searches for all objects of the given type that match `search_template`
|
|
template<typename T>
|
|
static std::vector<T> search(Session& session, const std::vector<Attribute>& search_template);
|
|
|
|
/// Searches for all objects of the given type using the label (`CKA_LABEL`)
|
|
template<typename T>
|
|
static std::vector<T> search(Session& session, const std::string& label);
|
|
|
|
/// Searches for all objects of the given type using the id (`CKA_ID`)
|
|
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 label (`CKA_LABEL`) and id (`CKA_ID`)
|
|
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
|
|
template<typename T>
|
|
static std::vector<T> search(Session& session);
|
|
|
|
/// @returns the value of the given attribute (using `C_GetAttributeValue`)
|
|
secure_vector<uint8_t> get_attribute_value(AttributeType attribute) const;
|
|
|
|
/// Sets the given value for the attribute (using `C_SetAttributeValue`)
|
|
void set_attribute_value(AttributeType attribute, const secure_vector<uint8_t>& value) const;
|
|
|
|
/// Destroys the object
|
|
void destroy() const;
|
|
|
|
/**
|
|
* Copies the object
|
|
* @param modified_attributes the attributes of the copied object
|
|
*/
|
|
ObjectHandle copy(const AttributeContainer& modified_attributes) const;
|
|
|
|
/// @return the handle of this object.
|
|
inline ObjectHandle handle() const
|
|
{
|
|
return m_handle;
|
|
}
|
|
|
|
/// @return the session this objects belongs to
|
|
inline Session& session() const
|
|
{
|
|
return m_session;
|
|
}
|
|
|
|
/// @return the module this object belongs to
|
|
inline Module& module() const
|
|
{
|
|
return m_session.get().module();
|
|
}
|
|
protected:
|
|
Object(Session& session)
|
|
: m_session(session)
|
|
{}
|
|
|
|
void reset_handle(ObjectHandle handle)
|
|
{
|
|
if(m_handle != CK_INVALID_HANDLE)
|
|
throw Invalid_Argument("Cannot reset handle on already valid PKCS11 object");
|
|
m_handle = handle;
|
|
}
|
|
|
|
private:
|
|
const std::reference_wrapper<Session> m_session;
|
|
ObjectHandle m_handle = CK_INVALID_HANDLE;
|
|
};
|
|
|
|
template<typename T>
|
|
std::vector<T> Object::search(Session& session, const std::vector<Attribute>& search_template)
|
|
{
|
|
ObjectFinder finder(session, search_template);
|
|
std::vector<ObjectHandle> handles = finder.find();
|
|
std::vector<T> result;
|
|
result.reserve(handles.size());
|
|
for(const auto& handle : handles)
|
|
{
|
|
result.emplace_back(T(session, handle));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template<typename T>
|
|
std::vector<T> Object::search(Session& session, const std::string& label)
|
|
{
|
|
AttributeContainer search_template(T::Class);
|
|
search_template.add_string(AttributeType::Label, label);
|
|
return search<T>(session, search_template.attributes());
|
|
}
|
|
|
|
template<typename T>
|
|
std::vector<T> Object::search(Session& session, const std::vector<uint8_t>& id)
|
|
{
|
|
AttributeContainer search_template(T::Class);
|
|
search_template.add_binary(AttributeType::Id, id);
|
|
return search<T>(session, search_template.attributes());
|
|
}
|
|
|
|
template<typename T>
|
|
std::vector<T> Object::search(Session& session, const std::string& label, const std::vector<uint8_t>& id)
|
|
{
|
|
AttributeContainer search_template(T::Class);
|
|
search_template.add_string(AttributeType::Label, label);
|
|
search_template.add_binary(AttributeType::Id, id);
|
|
return search<T>(session, search_template.attributes());
|
|
}
|
|
|
|
template<typename T>
|
|
std::vector<T> Object::search(Session& session)
|
|
{
|
|
return search<T>(session, AttributeContainer(T::Class).attributes());
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
|
|
|
|
namespace Botan {
|
|
namespace PKCS11 {
|
|
|
|
class Session;
|
|
|
|
/// Properties for generating a PKCS#11 EC public key
|
|
class BOTAN_PUBLIC_API(2,0) EC_PublicKeyGenerationProperties final : public PublicKeyProperties
|
|
{
|
|
public:
|
|
/// @param ec_params DER-encoding of an ANSI X9.62 Parameters value
|
|
EC_PublicKeyGenerationProperties(const std::vector<uint8_t>& ec_params);
|
|
|
|
/// @return the DER-encoding of the ec parameters according to ANSI X9.62
|
|
inline const std::vector<uint8_t>& ec_params() const
|
|
{
|
|
return m_ec_params;
|
|
}
|
|
|
|
private:
|
|
const std::vector<uint8_t> m_ec_params;
|
|
};
|
|
|
|
/// Properties for importing a PKCS#11 EC public key
|
|
class BOTAN_PUBLIC_API(2,0) EC_PublicKeyImportProperties final : public PublicKeyProperties
|
|
{
|
|
public:
|
|
/**
|
|
* @param ec_params DER-encoding of an ANSI X9.62 Parameters value
|
|
* @param ec_point DER-encoding of ANSI X9.62 ECPoint value Q
|
|
*/
|
|
EC_PublicKeyImportProperties(const std::vector<uint8_t>& ec_params, const std::vector<uint8_t>& ec_point);
|
|
|
|
/// @return the DER-encoding of the ec parameters according to ANSI X9.62
|
|
inline const std::vector<uint8_t>& ec_params() const
|
|
{
|
|
return m_ec_params;
|
|
}
|
|
|
|
/// @return the DER-encoding of the ec public point according to ANSI X9.62
|
|
inline const std::vector<uint8_t>& ec_point() const
|
|
{
|
|
return m_ec_point;
|
|
}
|
|
|
|
private:
|
|
const std::vector<uint8_t> m_ec_params;
|
|
const std::vector<uint8_t> m_ec_point;
|
|
};
|
|
|
|
/// Represents a PKCS#11 EC public key
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_EC_PublicKey : public virtual EC_PublicKey,
|
|
public Object
|
|
{
|
|
public:
|
|
static const ObjectClass Class = ObjectClass::PublicKey;
|
|
|
|
/**
|
|
* Creates a PKCS11_EC_PublicKey object from an existing PKCS#11 EC public key
|
|
* @param session the session to use
|
|
* @param handle the handle of the ecc public key
|
|
*/
|
|
PKCS11_EC_PublicKey(Session& session, ObjectHandle handle);
|
|
|
|
/**
|
|
* Imports an EC public key
|
|
* @param session the session to use
|
|
* @param props the attributes of the public key
|
|
*/
|
|
PKCS11_EC_PublicKey(Session& session, const EC_PublicKeyImportProperties& props);
|
|
};
|
|
|
|
/// Properties for generating a PKCS#11 EC private key
|
|
class BOTAN_PUBLIC_API(2,0) EC_PrivateKeyGenerationProperties final : public PrivateKeyProperties
|
|
{
|
|
public:
|
|
EC_PrivateKeyGenerationProperties()
|
|
: PrivateKeyProperties(KeyType::Ec)
|
|
{}
|
|
};
|
|
|
|
/// Properties for importing a PKCS#11 EC private key
|
|
class BOTAN_PUBLIC_API(2,0) EC_PrivateKeyImportProperties final : public PrivateKeyProperties
|
|
{
|
|
public:
|
|
/**
|
|
* @param ec_params DER-encoding of an ANSI X9.62 Parameters value
|
|
* @param value ANSI X9.62 private value d
|
|
*/
|
|
EC_PrivateKeyImportProperties(const std::vector<uint8_t>& ec_params, const BigInt& value);
|
|
|
|
/// @return the DER-encoding of the ec parameters according to ANSI X9.62
|
|
inline const std::vector<uint8_t>& ec_params() const
|
|
{
|
|
return m_ec_params;
|
|
}
|
|
|
|
/// @return the value of the ec private key
|
|
inline const BigInt& value() const
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
private:
|
|
const std::vector<uint8_t> m_ec_params;
|
|
const BigInt m_value;
|
|
};
|
|
|
|
// note: don't inherit from PKCS11_EC_PublicKey: a private key object IS NOT A public key object on a smartcard (-> two different objects)
|
|
// note: don't inherit from EC_PublicKey: the public key can not be extracted from a PKCS11-EC-PrivateKey (its only attributes are CKA_EC_PARAMS and CKA_VALUE)
|
|
/// Represents a PKCS#11 EC private key
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_EC_PrivateKey : public virtual Private_Key,
|
|
public Object
|
|
{
|
|
public:
|
|
static const ObjectClass Class = ObjectClass::PrivateKey;
|
|
|
|
/**
|
|
* Creates a PKCS11_EC_PrivateKey object from an existing PKCS#11 EC private key
|
|
* @param session the session to use
|
|
* @param handle the handle of the EC private key
|
|
*/
|
|
PKCS11_EC_PrivateKey(Session& session, ObjectHandle handle);
|
|
|
|
/**
|
|
* Imports an EC private key
|
|
* @param session the session to use
|
|
* @param props the attributes of the private key
|
|
*/
|
|
PKCS11_EC_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props);
|
|
|
|
/**
|
|
* Generates a PKCS#11 EC private key
|
|
* @param session the session to use
|
|
* @param ec_params DER-encoding of an ANSI X9.62 Parameters value
|
|
* @param props the attributes of the private key
|
|
* @note no persistent public key object will be created
|
|
*/
|
|
PKCS11_EC_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params,
|
|
const EC_PrivateKeyGenerationProperties& props);
|
|
|
|
/// @returns the domain of the EC private key
|
|
inline const EC_Group& domain() const
|
|
{
|
|
return m_domain_params;
|
|
}
|
|
|
|
/**
|
|
* Sets the associated public point of this private key
|
|
* @param point the public point
|
|
* @param point_encoding encoding of the point (default DER-encoded)
|
|
*/
|
|
void set_public_point(const PointGFp& point, PublicPointEncoding point_encoding = PublicPointEncoding::Der)
|
|
{
|
|
m_public_key = point;
|
|
m_point_encoding = point_encoding;
|
|
}
|
|
|
|
/**
|
|
* Gets the public_point
|
|
* @note the public key must be set using `set_public_point`
|
|
* because it is not possible to infer the public key from a PKCS#11 EC private key
|
|
* @return the public point of the private key
|
|
* @throws Exception if the public point was not set using set_public_point()
|
|
*/
|
|
const PointGFp& public_point() const
|
|
{
|
|
if(m_public_key.is_zero())
|
|
{
|
|
throw Invalid_State("Public point not set. Inferring the public key from a PKCS#11 ec private key is not possible.");
|
|
}
|
|
return m_public_key;
|
|
}
|
|
|
|
/// @return the encoding format for the public point when it is passed to cryptoki functions as an argument
|
|
PublicPointEncoding point_encoding() const
|
|
{
|
|
return m_point_encoding;
|
|
}
|
|
|
|
// Private_Key methods
|
|
|
|
std::vector<uint8_t> public_key_bits() const override;
|
|
|
|
std::size_t key_length() const override;
|
|
|
|
std::size_t estimated_strength() const override;
|
|
|
|
bool check_key(RandomNumberGenerator&, bool) const override;
|
|
|
|
AlgorithmIdentifier algorithm_identifier() const override;
|
|
|
|
private:
|
|
EC_Group m_domain_params;
|
|
PointGFp m_public_key;
|
|
PublicPointEncoding m_point_encoding = PublicPointEncoding::Der;
|
|
};
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ECDH)
|
|
|
|
|
|
|
|
namespace Botan {
|
|
namespace PKCS11 {
|
|
class Session;
|
|
|
|
/// Represents a PKCS#11 ECDH public key
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_ECDH_PublicKey : public PKCS11_EC_PublicKey
|
|
{
|
|
public:
|
|
/**
|
|
* Create a PKCS11_ECDH_PublicKey object from an existing PKCS#11 ECDH public key
|
|
* @param session the session to use
|
|
* @param handle the handle of the ECDH public key
|
|
*/
|
|
PKCS11_ECDH_PublicKey(Session& session, ObjectHandle handle)
|
|
: EC_PublicKey(), PKCS11_EC_PublicKey(session, handle)
|
|
{}
|
|
|
|
/**
|
|
* Imports a ECDH public key
|
|
* @param session the session to use
|
|
* @param props the attributes of the public key
|
|
*/
|
|
PKCS11_ECDH_PublicKey(Session& session, const EC_PublicKeyImportProperties& props)
|
|
: EC_PublicKey(), PKCS11_EC_PublicKey(session, props)
|
|
{}
|
|
|
|
inline std::string algo_name() const override
|
|
{
|
|
return "ECDH";
|
|
}
|
|
|
|
/// @return the exported ECDH public key
|
|
ECDH_PublicKey export_key() const;
|
|
};
|
|
|
|
/// Represents a PKCS#11 ECDH private key
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_ECDH_PrivateKey final : public virtual PKCS11_EC_PrivateKey, public virtual PK_Key_Agreement_Key
|
|
{
|
|
public:
|
|
/**
|
|
* Creates a PKCS11_ECDH_PrivateKey object from an existing PKCS#11 ECDH private key
|
|
* @param session the session to use
|
|
* @param handle the handle of the ECDH private key
|
|
*/
|
|
PKCS11_ECDH_PrivateKey(Session& session, ObjectHandle handle)
|
|
: PKCS11_EC_PrivateKey(session, handle)
|
|
{}
|
|
|
|
/**
|
|
* Imports an ECDH private key
|
|
* @param session the session to use
|
|
* @param props the attributes of the private key
|
|
*/
|
|
PKCS11_ECDH_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props)
|
|
: PKCS11_EC_PrivateKey(session, props)
|
|
{}
|
|
|
|
/**
|
|
* Generates a PKCS#11 ECDH private key
|
|
* @param session the session to use
|
|
* @param ec_params DER-encoding of an ANSI X9.62 Parameters value
|
|
* @param props the attributes of the private key
|
|
* @note no persistent public key object will be created
|
|
*/
|
|
PKCS11_ECDH_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params,
|
|
const EC_PrivateKeyGenerationProperties& props)
|
|
: PKCS11_EC_PrivateKey(session, ec_params, props)
|
|
{}
|
|
|
|
inline std::string algo_name() const override
|
|
{
|
|
return "ECDH";
|
|
}
|
|
|
|
inline std::vector<uint8_t> public_value() const override
|
|
{
|
|
return public_point().encode(PointGFp::UNCOMPRESSED);
|
|
}
|
|
|
|
/// @return the exported ECDH private key
|
|
ECDH_PrivateKey export_key() const;
|
|
|
|
secure_vector<uint8_t> private_key_bits() const override;
|
|
|
|
std::unique_ptr<PK_Ops::Key_Agreement>
|
|
create_key_agreement_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
using PKCS11_ECDH_KeyPair = std::pair<PKCS11_ECDH_PublicKey, PKCS11_ECDH_PrivateKey>;
|
|
|
|
/**
|
|
* PKCS#11 ECDH key pair generation
|
|
* @param session the session that should be used for the key generation
|
|
* @param pub_props the properties of the public key
|
|
* @param priv_props the properties of the private key
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) PKCS11_ECDH_KeyPair generate_ecdh_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props,
|
|
const EC_PrivateKeyGenerationProperties& priv_props);
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_ECDSA)
|
|
|
|
|
|
|
|
namespace Botan {
|
|
namespace PKCS11 {
|
|
class Session;
|
|
|
|
/// Represents a PKCS#11 ECDSA public key
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_ECDSA_PublicKey final : public PKCS11_EC_PublicKey, public virtual ECDSA_PublicKey
|
|
{
|
|
public:
|
|
/**
|
|
* Creates a PKCS11_ECDSA_PublicKey object from an existing PKCS#11 ECDSA public key
|
|
* @param session the session to use
|
|
* @param handle the handle of the ECDSA public key
|
|
*/
|
|
PKCS11_ECDSA_PublicKey(Session& session, ObjectHandle handle)
|
|
: EC_PublicKey(), PKCS11_EC_PublicKey(session, handle)
|
|
{}
|
|
|
|
/**
|
|
* Imports an ECDSA public key
|
|
* @param session the session to use
|
|
* @param props the attributes of the public key
|
|
*/
|
|
PKCS11_ECDSA_PublicKey(Session& session, const EC_PublicKeyImportProperties& props)
|
|
: EC_PublicKey(), PKCS11_EC_PublicKey(session, props)
|
|
{}
|
|
|
|
inline std::string algo_name() const override
|
|
{
|
|
return "ECDSA";
|
|
}
|
|
|
|
/// @return the exported ECDSA public key
|
|
ECDSA_PublicKey export_key() const;
|
|
|
|
std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
/// Represents a PKCS#11 ECDSA private key
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_ECDSA_PrivateKey final : public PKCS11_EC_PrivateKey
|
|
{
|
|
public:
|
|
/**
|
|
* Creates a PKCS11_ECDSA_PrivateKey object from an existing PKCS#11 ECDSA private key
|
|
* @param session the session to use
|
|
* @param handle the handle of the ECDSA private key
|
|
*/
|
|
PKCS11_ECDSA_PrivateKey(Session& session, ObjectHandle handle)
|
|
: PKCS11_EC_PrivateKey(session, handle)
|
|
{}
|
|
|
|
/**
|
|
* Imports a ECDSA private key
|
|
* @param session the session to use
|
|
* @param props the attributes of the private key
|
|
*/
|
|
PKCS11_ECDSA_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props)
|
|
: PKCS11_EC_PrivateKey(session, props)
|
|
{}
|
|
|
|
/**
|
|
* Generates a PKCS#11 ECDSA private key
|
|
* @param session the session to use
|
|
* @param ec_params DER-encoding of an ANSI X9.62 Parameters value
|
|
* @param props the attributes of the private key
|
|
* @note no persistent public key object will be created
|
|
*/
|
|
PKCS11_ECDSA_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params,
|
|
const EC_PrivateKeyGenerationProperties& props)
|
|
: PKCS11_EC_PrivateKey(session, ec_params, props)
|
|
{}
|
|
|
|
inline std::string algo_name() const override
|
|
{
|
|
return "ECDSA";
|
|
}
|
|
|
|
size_t message_parts() const override { return 2; }
|
|
|
|
size_t message_part_size() const override
|
|
{ return domain().get_order().bytes(); }
|
|
|
|
/// @return the exported ECDSA private key
|
|
ECDSA_PrivateKey export_key() const;
|
|
|
|
secure_vector<uint8_t> private_key_bits() const override;
|
|
|
|
bool check_key(RandomNumberGenerator&, bool) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
using PKCS11_ECDSA_KeyPair = std::pair<PKCS11_ECDSA_PublicKey, PKCS11_ECDSA_PrivateKey>;
|
|
|
|
/**
|
|
* ECDSA key pair generation
|
|
* @param session the session that should be used for the key generation
|
|
* @param pub_props the properties of the public key
|
|
* @param priv_props the properties of the private key
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) PKCS11_ECDSA_KeyPair generate_ecdsa_keypair(Session& session,
|
|
const EC_PublicKeyGenerationProperties& pub_props, const EC_PrivateKeyGenerationProperties& priv_props);
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
namespace Botan {
|
|
namespace PKCS11 {
|
|
|
|
class Module;
|
|
|
|
/// A random generator that only fetches random from the PKCS#11 RNG
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_RNG final : public Hardware_RNG
|
|
{
|
|
public:
|
|
/// Initialize the RNG with the PKCS#11 session that provides access to the cryptoki functions
|
|
explicit PKCS11_RNG(Session& session);
|
|
|
|
std::string name() const override
|
|
{
|
|
return "PKCS11_RNG";
|
|
}
|
|
|
|
/// Always returns true
|
|
bool is_seeded() const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/// No operation - always returns 0
|
|
size_t reseed(Entropy_Sources&, size_t, std::chrono::milliseconds) override
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/// @return the module used by this RNG
|
|
inline Module& module() const
|
|
{
|
|
return m_session.get().module();
|
|
}
|
|
|
|
/// Calls `C_GenerateRandom` to generate random data
|
|
void randomize(uint8_t output[], std::size_t length) override;
|
|
|
|
/// Calls `C_SeedRandom` to add entropy to the random generation function of the token/middleware
|
|
void add_entropy(const uint8_t in[], std::size_t length) override;
|
|
|
|
// C_SeedRandom may suceed
|
|
bool accepts_input() const override { return true; }
|
|
|
|
private:
|
|
const std::reference_wrapper<Session> m_session;
|
|
};
|
|
}
|
|
|
|
}
|
|
|
|
#if defined(BOTAN_HAS_RSA)
|
|
|
|
namespace Botan {
|
|
|
|
class RSA_Public_Data;
|
|
class RSA_Private_Data;
|
|
|
|
/**
|
|
* RSA Public Key
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) RSA_PublicKey : public virtual Public_Key
|
|
{
|
|
public:
|
|
/**
|
|
* Load a public key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
RSA_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Create a public key.
|
|
* @arg n the modulus
|
|
* @arg e the exponent
|
|
*/
|
|
RSA_PublicKey(const BigInt& n, const BigInt& e);
|
|
|
|
std::string algo_name() const override { return "RSA"; }
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool) const override;
|
|
|
|
AlgorithmIdentifier algorithm_identifier() const override;
|
|
|
|
std::vector<uint8_t> public_key_bits() const override;
|
|
|
|
/**
|
|
* @return public modulus
|
|
*/
|
|
const BigInt& get_n() const;
|
|
|
|
/**
|
|
* @return public exponent
|
|
*/
|
|
const BigInt& get_e() const;
|
|
|
|
size_t key_length() const override;
|
|
size_t estimated_strength() const override;
|
|
|
|
// internal functions:
|
|
std::shared_ptr<const RSA_Public_Data> public_data() const;
|
|
|
|
std::unique_ptr<PK_Ops::Encryption>
|
|
create_encryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
std::unique_ptr<PK_Ops::KEM_Encryption>
|
|
create_kem_encryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
protected:
|
|
RSA_PublicKey() = default;
|
|
|
|
void init(BigInt&& n, BigInt&& e);
|
|
|
|
std::shared_ptr<const RSA_Public_Data> m_public;
|
|
};
|
|
|
|
/**
|
|
* RSA Private Key
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) RSA_PrivateKey final : public Private_Key, public RSA_PublicKey
|
|
{
|
|
public:
|
|
/**
|
|
* Load a private key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits PKCS#1 RSAPrivateKey bits
|
|
*/
|
|
RSA_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Construct a private key from the specified parameters.
|
|
* @param p the first prime
|
|
* @param q the second prime
|
|
* @param e the exponent
|
|
* @param d if specified, this has to be d with
|
|
* exp * d = 1 mod (p - 1, q - 1). Leave it as 0 if you wish to
|
|
* the constructor to calculate it.
|
|
* @param n if specified, this must be n = p * q. Leave it as 0
|
|
* if you wish to the constructor to calculate it.
|
|
*/
|
|
RSA_PrivateKey(const BigInt& p, const BigInt& q,
|
|
const BigInt& e, const BigInt& d = 0,
|
|
const BigInt& n = 0);
|
|
|
|
/**
|
|
* Create a new private key with the specified bit length
|
|
* @param rng the random number generator to use
|
|
* @param bits the desired bit length of the private key
|
|
* @param exp the public exponent to be used
|
|
*/
|
|
RSA_PrivateKey(RandomNumberGenerator& rng,
|
|
size_t bits, size_t exp = 65537);
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool) const override;
|
|
|
|
/**
|
|
* Get the first prime p.
|
|
* @return prime p
|
|
*/
|
|
const BigInt& get_p() const;
|
|
|
|
/**
|
|
* Get the second prime q.
|
|
* @return prime q
|
|
*/
|
|
const BigInt& get_q() const;
|
|
|
|
/**
|
|
* Get d with exp * d = 1 mod (p - 1, q - 1).
|
|
* @return d
|
|
*/
|
|
const BigInt& get_d() const;
|
|
|
|
const BigInt& get_c() const;
|
|
const BigInt& get_d1() const;
|
|
const BigInt& get_d2() const;
|
|
|
|
secure_vector<uint8_t> private_key_bits() const override;
|
|
|
|
// internal functions:
|
|
std::shared_ptr<const RSA_Private_Data> private_data() const;
|
|
|
|
std::unique_ptr<PK_Ops::Decryption>
|
|
create_decryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
std::unique_ptr<PK_Ops::KEM_Decryption>
|
|
create_kem_decryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
private:
|
|
|
|
void init(BigInt&& d, BigInt&& p, BigInt&& q, BigInt&& d1, BigInt&& d2, BigInt&& c);
|
|
|
|
std::shared_ptr<const RSA_Private_Data> m_private;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
namespace PKCS11 {
|
|
|
|
/// Properties for generating a PKCS#11 RSA public key
|
|
class BOTAN_PUBLIC_API(2,0) RSA_PublicKeyGenerationProperties final : public PublicKeyProperties
|
|
{
|
|
public:
|
|
/// @param bits length in bits of modulus n
|
|
explicit RSA_PublicKeyGenerationProperties(Ulong bits);
|
|
|
|
/// @param pub_exponent public exponent e
|
|
inline void set_pub_exponent(const BigInt& pub_exponent = BigInt(0x10001))
|
|
{
|
|
add_binary(AttributeType::PublicExponent, BigInt::encode(pub_exponent));
|
|
}
|
|
|
|
virtual ~RSA_PublicKeyGenerationProperties() = default;
|
|
};
|
|
|
|
/// Properties for importing a PKCS#11 RSA public key
|
|
class BOTAN_PUBLIC_API(2,0) RSA_PublicKeyImportProperties final : public PublicKeyProperties
|
|
{
|
|
public:
|
|
/// @param modulus modulus n
|
|
/// @param pub_exponent public exponent e
|
|
RSA_PublicKeyImportProperties(const BigInt& modulus, const BigInt& pub_exponent);
|
|
|
|
/// @return the modulus
|
|
inline const BigInt& modulus() const
|
|
{
|
|
return m_modulus;
|
|
}
|
|
|
|
/// @return the public exponent
|
|
inline const BigInt& pub_exponent() const
|
|
{
|
|
return m_pub_exponent;
|
|
}
|
|
|
|
virtual ~RSA_PublicKeyImportProperties() = default;
|
|
private:
|
|
const BigInt m_modulus;
|
|
const BigInt m_pub_exponent;
|
|
};
|
|
|
|
/// Represents a PKCS#11 RSA public key
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_RSA_PublicKey : public Object, public RSA_PublicKey
|
|
{
|
|
public:
|
|
static const ObjectClass Class = ObjectClass::PublicKey;
|
|
|
|
/**
|
|
* Creates a PKCS11_RSA_PublicKey object from an existing PKCS#11 RSA public key
|
|
* @param session the session to use
|
|
* @param handle the handle of the RSA public key
|
|
*/
|
|
PKCS11_RSA_PublicKey(Session& session, ObjectHandle handle);
|
|
|
|
/**
|
|
* Imports a RSA public key
|
|
* @param session the session to use
|
|
* @param pubkey_props the attributes of the public key
|
|
*/
|
|
PKCS11_RSA_PublicKey(Session& session, const RSA_PublicKeyImportProperties& pubkey_props);
|
|
|
|
std::unique_ptr<PK_Ops::Encryption>
|
|
create_encryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
/// Properties for importing a PKCS#11 RSA private key
|
|
class BOTAN_PUBLIC_API(2,0) RSA_PrivateKeyImportProperties final : public PrivateKeyProperties
|
|
{
|
|
public:
|
|
/**
|
|
* @param modulus modulus n
|
|
* @param priv_exponent private exponent d
|
|
*/
|
|
RSA_PrivateKeyImportProperties(const BigInt& modulus, const BigInt& priv_exponent);
|
|
|
|
/// @param pub_exponent public exponent e
|
|
inline void set_pub_exponent(const BigInt& pub_exponent)
|
|
{
|
|
add_binary(AttributeType::PublicExponent, BigInt::encode(pub_exponent));
|
|
}
|
|
|
|
/// @param prime1 prime p
|
|
inline void set_prime_1(const BigInt& prime1)
|
|
{
|
|
add_binary(AttributeType::Prime1, BigInt::encode(prime1));
|
|
}
|
|
|
|
/// @param prime2 prime q
|
|
inline void set_prime_2(const BigInt& prime2)
|
|
{
|
|
add_binary(AttributeType::Prime2, BigInt::encode(prime2));
|
|
}
|
|
|
|
/// @param exp1 private exponent d modulo p-1
|
|
inline void set_exponent_1(const BigInt& exp1)
|
|
{
|
|
add_binary(AttributeType::Exponent1, BigInt::encode(exp1));
|
|
}
|
|
|
|
/// @param exp2 private exponent d modulo q-1
|
|
inline void set_exponent_2(const BigInt& exp2)
|
|
{
|
|
add_binary(AttributeType::Exponent2, BigInt::encode(exp2));
|
|
}
|
|
|
|
/// @param coeff CRT coefficient q^-1 mod p
|
|
inline void set_coefficient(const BigInt& coeff)
|
|
{
|
|
add_binary(AttributeType::Coefficient, BigInt::encode(coeff));
|
|
}
|
|
|
|
/// @return the modulus
|
|
inline const BigInt& modulus() const
|
|
{
|
|
return m_modulus;
|
|
}
|
|
|
|
/// @return the private exponent
|
|
inline const BigInt& priv_exponent() const
|
|
{
|
|
return m_priv_exponent;
|
|
}
|
|
|
|
virtual ~RSA_PrivateKeyImportProperties() = default;
|
|
|
|
private:
|
|
const BigInt m_modulus;
|
|
const BigInt m_priv_exponent;
|
|
};
|
|
|
|
/// Properties for generating a PKCS#11 RSA private key
|
|
class BOTAN_PUBLIC_API(2,0) RSA_PrivateKeyGenerationProperties final : public PrivateKeyProperties
|
|
{
|
|
public:
|
|
RSA_PrivateKeyGenerationProperties()
|
|
: PrivateKeyProperties(KeyType::Rsa)
|
|
{}
|
|
|
|
virtual ~RSA_PrivateKeyGenerationProperties() = default;
|
|
};
|
|
|
|
/// Represents a PKCS#11 RSA private key
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_RSA_PrivateKey final :
|
|
public Object, public Private_Key, public RSA_PublicKey
|
|
{
|
|
public:
|
|
static const ObjectClass Class = ObjectClass::PrivateKey;
|
|
|
|
/// Creates a PKCS11_RSA_PrivateKey object from an existing PKCS#11 RSA private key
|
|
PKCS11_RSA_PrivateKey(Session& session, ObjectHandle handle);
|
|
|
|
/**
|
|
* Imports a RSA private key
|
|
* @param session the session to use
|
|
* @param priv_key_props the properties of the RSA private key
|
|
*/
|
|
PKCS11_RSA_PrivateKey(Session& session, const RSA_PrivateKeyImportProperties& priv_key_props);
|
|
|
|
/**
|
|
* Generates a PKCS#11 RSA private key
|
|
* @param session the session to use
|
|
* @param bits length in bits of modulus n
|
|
* @param priv_key_props the properties of the RSA private key
|
|
* @note no persistent public key object will be created
|
|
*/
|
|
PKCS11_RSA_PrivateKey(Session& session, uint32_t bits, const RSA_PrivateKeyGenerationProperties& priv_key_props);
|
|
|
|
/// @return the exported RSA private key
|
|
RSA_PrivateKey export_key() const;
|
|
|
|
secure_vector<uint8_t> private_key_bits() const override;
|
|
|
|
std::unique_ptr<PK_Ops::Decryption>
|
|
create_decryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
};
|
|
|
|
using PKCS11_RSA_KeyPair = std::pair<PKCS11_RSA_PublicKey, PKCS11_RSA_PrivateKey>;
|
|
|
|
/**
|
|
* RSA key pair generation
|
|
* @param session the session that should be used for the key generation
|
|
* @param pub_props properties of the public key
|
|
* @param priv_props properties of the private key
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) PKCS11_RSA_KeyPair generate_rsa_keypair(Session& session, const RSA_PublicKeyGenerationProperties& pub_props,
|
|
const RSA_PrivateKeyGenerationProperties& priv_props);
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_X509_CERTIFICATES)
|
|
|
|
|
|
namespace Botan {
|
|
namespace PKCS11 {
|
|
|
|
class Session;
|
|
|
|
/// Common attributes of all PKCS#11 X509 certificates
|
|
class BOTAN_PUBLIC_API(2,0) X509_CertificateProperties final : public CertificateProperties
|
|
{
|
|
public:
|
|
/**
|
|
* @param subject DER-encoding of the certificate subject name
|
|
* @param value BER-encoding of the certificate
|
|
*/
|
|
X509_CertificateProperties(const std::vector<uint8_t>& subject, const std::vector<uint8_t>& value);
|
|
|
|
X509_CertificateProperties(const X509_Certificate& cert) :
|
|
X509_CertificateProperties(cert.raw_subject_dn(), cert.BER_encode())
|
|
{}
|
|
|
|
/// @param id key identifier for public/private key pair
|
|
inline void set_id(const std::vector<uint8_t>& id)
|
|
{
|
|
add_binary(AttributeType::Id, id);
|
|
}
|
|
|
|
/// @param issuer DER-encoding of the certificate issuer name
|
|
inline void set_issuer(const std::vector<uint8_t>& issuer)
|
|
{
|
|
add_binary(AttributeType::Issuer, issuer);
|
|
}
|
|
|
|
/// @param serial DER-encoding of the certificate serial number
|
|
inline void set_serial(const std::vector<uint8_t>& serial)
|
|
{
|
|
add_binary(AttributeType::SerialNumber, serial);
|
|
}
|
|
|
|
/// @param hash hash value of the subject public key
|
|
inline void set_subject_pubkey_hash(const std::vector<uint8_t>& hash)
|
|
{
|
|
add_binary(AttributeType::HashOfSubjectPublicKey, hash);
|
|
}
|
|
|
|
/// @param hash hash value of the issuer public key
|
|
inline void set_issuer_pubkey_hash(const std::vector<uint8_t>& hash)
|
|
{
|
|
add_binary(AttributeType::HashOfIssuerPublicKey, hash);
|
|
}
|
|
|
|
/// @param alg defines the mechanism used to calculate `CKA_HASH_OF_SUBJECT_PUBLIC_KEY` and `CKA_HASH_OF_ISSUER_PUBLIC_KEY`
|
|
inline void set_hash_alg(MechanismType alg)
|
|
{
|
|
add_numeric(AttributeType::NameHashAlgorithm, static_cast<Ulong>(alg));
|
|
}
|
|
|
|
/// @return the subject
|
|
inline const std::vector<uint8_t>& subject() const
|
|
{
|
|
return m_subject;
|
|
}
|
|
|
|
/// @return the BER-encoding of the certificate
|
|
inline const std::vector<uint8_t>& value() const
|
|
{
|
|
return m_value;
|
|
}
|
|
|
|
private:
|
|
const std::vector<uint8_t> m_subject;
|
|
const std::vector<uint8_t> m_value;
|
|
};
|
|
|
|
/// Represents a PKCS#11 X509 certificate
|
|
class BOTAN_PUBLIC_API(2,0) PKCS11_X509_Certificate final : public Object, public X509_Certificate
|
|
{
|
|
public:
|
|
static const ObjectClass Class = ObjectClass::Certificate;
|
|
|
|
/**
|
|
* Create a PKCS11_X509_Certificate object from an existing PKCS#11 X509 cert
|
|
* @param session the session to use
|
|
* @param handle the handle of the X.509 certificate
|
|
*/
|
|
PKCS11_X509_Certificate(Session& session, ObjectHandle handle);
|
|
|
|
/**
|
|
* Imports a X.509 certificate
|
|
* @param session the session to use
|
|
* @param props the attributes of the X.509 certificate
|
|
*/
|
|
PKCS11_X509_Certificate(Session& session, const X509_CertificateProperties& props);
|
|
};
|
|
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Rivest's Package Tranform
|
|
* @param rng the random number generator to use
|
|
* @param cipher the block cipher to use (aont_package takes ownership)
|
|
* @param input the input data buffer
|
|
* @param input_len the length of the input data in bytes
|
|
* @param output the output data buffer (must be at least
|
|
* input_len + cipher->BLOCK_SIZE bytes long)
|
|
*/
|
|
BOTAN_DEPRECATED("Possibly broken, avoid")
|
|
void BOTAN_PUBLIC_API(2,0)
|
|
aont_package(RandomNumberGenerator& rng,
|
|
BlockCipher* cipher,
|
|
const uint8_t input[], size_t input_len,
|
|
uint8_t output[]);
|
|
|
|
/**
|
|
* Rivest's Package Tranform (Inversion)
|
|
* @param cipher the block cipher to use (aont_package takes ownership)
|
|
* @param input the input data buffer
|
|
* @param input_len the length of the input data in bytes
|
|
* @param output the output data buffer (must be at least
|
|
* input_len - cipher->BLOCK_SIZE bytes long)
|
|
*/
|
|
BOTAN_DEPRECATED("Possibly broken, avoid")
|
|
void BOTAN_PUBLIC_API(2,0)
|
|
aont_unpackage(BlockCipher* cipher,
|
|
const uint8_t input[], size_t input_len,
|
|
uint8_t output[]);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(par_hash.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Parallel Hashes
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Parallel final : public HashFunction
|
|
{
|
|
public:
|
|
void clear() override;
|
|
std::string name() const override;
|
|
HashFunction* clone() const override;
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
size_t output_length() const override;
|
|
|
|
/**
|
|
* @param hashes a set of hashes to compute in parallel
|
|
* Takes ownership of all pointers
|
|
*/
|
|
explicit Parallel(std::vector<std::unique_ptr<HashFunction>>& hashes);
|
|
|
|
Parallel(const Parallel&) = delete;
|
|
Parallel& operator=(const Parallel&) = delete;
|
|
private:
|
|
Parallel() = delete;
|
|
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
|
|
std::vector<std::unique_ptr<HashFunction>> m_hashes;
|
|
};
|
|
|
|
}
|
|
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(parsing.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Parse a SCAN-style algorithm name
|
|
* @param scan_name the name
|
|
* @return the name components
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::vector<std::string>
|
|
parse_algorithm_name(const std::string& scan_name);
|
|
|
|
/**
|
|
* Split a string
|
|
* @param str the input string
|
|
* @param delim the delimitor
|
|
* @return string split by delim
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::vector<std::string> split_on(
|
|
const std::string& str, char delim);
|
|
|
|
/**
|
|
* Split a string on a character predicate
|
|
* @param str the input string
|
|
* @param pred the predicate
|
|
*
|
|
* This function will likely be removed in a future release
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::vector<std::string>
|
|
split_on_pred(const std::string& str,
|
|
std::function<bool (char)> pred);
|
|
|
|
/**
|
|
* Erase characters from a string
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0)
|
|
BOTAN_DEPRECATED("Unused")
|
|
std::string erase_chars(const std::string& str, const std::set<char>& chars);
|
|
|
|
/**
|
|
* Replace a character in a string
|
|
* @param str the input string
|
|
* @param from_char the character to replace
|
|
* @param to_char the character to replace it with
|
|
* @return str with all instances of from_char replaced by to_char
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0)
|
|
BOTAN_DEPRECATED("Unused")
|
|
std::string replace_char(const std::string& str,
|
|
char from_char,
|
|
char to_char);
|
|
|
|
/**
|
|
* Replace a character in a string
|
|
* @param str the input string
|
|
* @param from_chars the characters to replace
|
|
* @param to_char the character to replace it with
|
|
* @return str with all instances of from_chars replaced by to_char
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0)
|
|
BOTAN_DEPRECATED("Unused")
|
|
std::string replace_chars(const std::string& str,
|
|
const std::set<char>& from_chars,
|
|
char to_char);
|
|
|
|
/**
|
|
* Join a string
|
|
* @param strs strings to join
|
|
* @param delim the delimitor
|
|
* @return string joined by delim
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0)
|
|
std::string string_join(const std::vector<std::string>& strs,
|
|
char delim);
|
|
|
|
/**
|
|
* Parse an ASN.1 OID
|
|
* @param oid the OID in string form
|
|
* @return OID components
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::vector<uint32_t>
|
|
BOTAN_DEPRECATED("Use OID::from_string(oid).get_components()") parse_asn1_oid(const std::string& oid);
|
|
|
|
/**
|
|
* Compare two names using the X.509 comparison algorithm
|
|
* @param name1 the first name
|
|
* @param name2 the second name
|
|
* @return true if name1 is the same as name2 by the X.509 comparison rules
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0)
|
|
bool x500_name_cmp(const std::string& name1,
|
|
const std::string& name2);
|
|
|
|
/**
|
|
* Convert a string to a number
|
|
* @param str the string to convert
|
|
* @return number value of the string
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t to_u32bit(const std::string& str);
|
|
|
|
/**
|
|
* Convert a string to a number
|
|
* @param str the string to convert
|
|
* @return number value of the string
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3) uint16_t to_uint16(const std::string& str);
|
|
|
|
/**
|
|
* Convert a time specification to a number
|
|
* @param timespec the time specification
|
|
* @return number of seconds represented by timespec
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t BOTAN_DEPRECATED("Not used anymore")
|
|
timespec_to_u32bit(const std::string& timespec);
|
|
|
|
/**
|
|
* Convert a string representation of an IPv4 address to a number
|
|
* @param ip_str the string representation
|
|
* @return integer IPv4 address
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t string_to_ipv4(const std::string& ip_str);
|
|
|
|
/**
|
|
* Convert an IPv4 address to a string
|
|
* @param ip_addr the IPv4 address to convert
|
|
* @return string representation of the IPv4 address
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::string ipv4_to_string(uint32_t ip_addr);
|
|
|
|
std::map<std::string, std::string> BOTAN_PUBLIC_API(2,0) read_cfg(std::istream& is);
|
|
|
|
/**
|
|
* Accepts key value pairs deliminated by commas:
|
|
*
|
|
* "" (returns empty map)
|
|
* "K=V" (returns map {'K': 'V'})
|
|
* "K1=V1,K2=V2"
|
|
* "K1=V1,K2=V2,K3=V3"
|
|
* "K1=V1,K2=V2,K3=a_value\,with\,commas_and_\=equals"
|
|
*
|
|
* Values may be empty, keys must be non-empty and unique. Duplicate
|
|
* keys cause an exception.
|
|
*
|
|
* Within both key and value, comma and equals can be escaped with
|
|
* backslash. Backslash can also be escaped.
|
|
*/
|
|
std::map<std::string, std::string> BOTAN_PUBLIC_API(2,8) read_kv(const std::string& kv);
|
|
|
|
std::string BOTAN_PUBLIC_API(2,0) clean_ws(const std::string& s);
|
|
|
|
std::string tolower_string(const std::string& s);
|
|
|
|
/**
|
|
* Check if the given hostname is a match for the specified wildcard
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,0) host_wildcard_match(const std::string& wildcard,
|
|
const std::string& host);
|
|
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Create a password hash using PBKDF2
|
|
* @param password the password
|
|
* @param rng a random number generator
|
|
* @param work_factor how much work to do to slow down guessing attacks
|
|
* @param alg_id specifies which PRF to use with PBKDF2
|
|
* 0 is HMAC(SHA-1)
|
|
* 1 is HMAC(SHA-256)
|
|
* 2 is CMAC(Blowfish)
|
|
* 3 is HMAC(SHA-384)
|
|
* 4 is HMAC(SHA-512)
|
|
* all other values are currently undefined
|
|
*/
|
|
std::string BOTAN_PUBLIC_API(2,0) generate_passhash9(const std::string& password,
|
|
RandomNumberGenerator& rng,
|
|
uint16_t work_factor = 15,
|
|
uint8_t alg_id = 4);
|
|
|
|
/**
|
|
* Check a previously created password hash
|
|
* @param password the password to check against
|
|
* @param hash the stored hash to check against
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,0) check_passhash9(const std::string& password,
|
|
const std::string& hash);
|
|
|
|
/**
|
|
* Check if the PRF used with PBKDF2 is supported
|
|
* @param alg_id alg_id used in generate_passhash9()
|
|
*/
|
|
bool BOTAN_PUBLIC_API(2,3) is_passhash9_alg_supported(uint8_t alg_id);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(pbes2.h)
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* Encrypt with PBES2 from PKCS #5 v2.0
|
|
* @param key_bits the input
|
|
* @param passphrase the passphrase to use for encryption
|
|
* @param msec how many milliseconds to run PBKDF2
|
|
* @param cipher specifies the block cipher to use to encrypt
|
|
* @param digest specifies the PRF to use with PBKDF2 (eg "HMAC(SHA-1)")
|
|
* @param rng a random number generator
|
|
*/
|
|
std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
|
|
BOTAN_PUBLIC_API(2,0) pbes2_encrypt(const secure_vector<uint8_t>& key_bits,
|
|
const std::string& passphrase,
|
|
std::chrono::milliseconds msec,
|
|
const std::string& cipher,
|
|
const std::string& digest,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Encrypt with PBES2 from PKCS #5 v2.0
|
|
* @param key_bits the input
|
|
* @param passphrase the passphrase to use for encryption
|
|
* @param msec how many milliseconds to run PBKDF2
|
|
* @param out_iterations_if_nonnull if not null, set to the number
|
|
* of PBKDF iterations used
|
|
* @param cipher specifies the block cipher to use to encrypt
|
|
* @param digest specifies the PRF to use with PBKDF2 (eg "HMAC(SHA-1)")
|
|
* @param rng a random number generator
|
|
*/
|
|
std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
|
|
BOTAN_PUBLIC_API(2,1) pbes2_encrypt_msec(const secure_vector<uint8_t>& key_bits,
|
|
const std::string& passphrase,
|
|
std::chrono::milliseconds msec,
|
|
size_t* out_iterations_if_nonnull,
|
|
const std::string& cipher,
|
|
const std::string& digest,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Encrypt with PBES2 from PKCS #5 v2.0
|
|
* @param key_bits the input
|
|
* @param passphrase the passphrase to use for encryption
|
|
* @param iterations how many iterations to run PBKDF2
|
|
* @param cipher specifies the block cipher to use to encrypt
|
|
* @param digest specifies the PRF to use with PBKDF2 (eg "HMAC(SHA-1)")
|
|
* @param rng a random number generator
|
|
*/
|
|
std::pair<AlgorithmIdentifier, std::vector<uint8_t>>
|
|
BOTAN_PUBLIC_API(2,1) pbes2_encrypt_iter(const secure_vector<uint8_t>& key_bits,
|
|
const std::string& passphrase,
|
|
size_t iterations,
|
|
const std::string& cipher,
|
|
const std::string& digest,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Decrypt a PKCS #5 v2.0 encrypted stream
|
|
* @param key_bits the input
|
|
* @param passphrase the passphrase to use for decryption
|
|
* @param params the PBES2 parameters
|
|
*/
|
|
secure_vector<uint8_t>
|
|
BOTAN_PUBLIC_API(2,0) pbes2_decrypt(const secure_vector<uint8_t>& key_bits,
|
|
const std::string& passphrase,
|
|
const std::vector<uint8_t>& params);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Base class for PBKDF (password based key derivation function)
|
|
* implementations. Converts a password into a key using a salt
|
|
* and iterated hashing to make brute force attacks harder.
|
|
*
|
|
* Starting in 2.8 this functionality is also offered by PasswordHash.
|
|
* The PBKDF interface may be removed in a future release.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PBKDF
|
|
{
|
|
public:
|
|
/**
|
|
* Create an instance based on a name
|
|
* If provider is empty then best available is chosen.
|
|
* @param algo_spec algorithm name
|
|
* @param provider provider implementation to choose
|
|
* @return a null pointer if the algo/provider combination cannot be found
|
|
*/
|
|
static std::unique_ptr<PBKDF> create(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* Create an instance based on a name, or throw if the
|
|
* algo/provider combination cannot be found. If provider is
|
|
* empty then best available is chosen.
|
|
*/
|
|
static std::unique_ptr<PBKDF>
|
|
create_or_throw(const std::string& algo_spec,
|
|
const std::string& provider = "");
|
|
|
|
/**
|
|
* @return list of available providers for this algorithm, empty if not available
|
|
*/
|
|
static std::vector<std::string> providers(const std::string& algo_spec);
|
|
|
|
/**
|
|
* @return new instance of this same algorithm
|
|
*/
|
|
virtual PBKDF* clone() const = 0;
|
|
|
|
/**
|
|
* @return name of this PBKDF
|
|
*/
|
|
virtual std::string name() const = 0;
|
|
|
|
virtual ~PBKDF() = default;
|
|
|
|
/**
|
|
* Derive a key from a passphrase for a number of iterations
|
|
* specified by either iterations or if iterations == 0 then
|
|
* running until msec time has elapsed.
|
|
*
|
|
* @param out buffer to store the derived key, must be of out_len bytes
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
* @param iterations the number of iterations to use (use 10K or more)
|
|
* @param msec if iterations is zero, then instead the PBKDF is
|
|
* run until msec milliseconds has passed.
|
|
* @return the number of iterations performed
|
|
*/
|
|
virtual size_t pbkdf(uint8_t out[], size_t out_len,
|
|
const std::string& passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t iterations,
|
|
std::chrono::milliseconds msec) const = 0;
|
|
|
|
/**
|
|
* Derive a key from a passphrase for a number of iterations.
|
|
*
|
|
* @param out buffer to store the derived key, must be of out_len bytes
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
* @param iterations the number of iterations to use (use 10K or more)
|
|
*/
|
|
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;
|
|
|
|
/**
|
|
* Derive a key from a passphrase, running until msec time has elapsed.
|
|
*
|
|
* @param out buffer to store the derived key, must be of out_len bytes
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
* @param msec if iterations is zero, then instead the PBKDF is
|
|
* run until msec milliseconds has passed.
|
|
* @param iterations set to the number iterations executed
|
|
*/
|
|
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;
|
|
|
|
/**
|
|
* Derive a key from a passphrase for a number of iterations.
|
|
*
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
* @param iterations the number of iterations to use (use 10K or more)
|
|
* @return the derived key
|
|
*/
|
|
secure_vector<uint8_t> pbkdf_iterations(size_t out_len,
|
|
const std::string& passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t iterations) const;
|
|
|
|
/**
|
|
* Derive a key from a passphrase, running until msec time has elapsed.
|
|
*
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
* @param msec if iterations is zero, then instead the PBKDF is
|
|
* run until msec milliseconds has passed.
|
|
* @param iterations set to the number iterations executed
|
|
* @return the derived key
|
|
*/
|
|
secure_vector<uint8_t> pbkdf_timed(size_t out_len,
|
|
const std::string& passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
std::chrono::milliseconds msec,
|
|
size_t& iterations) const;
|
|
|
|
// Following kept for compat with 1.10:
|
|
|
|
/**
|
|
* Derive a key from a passphrase
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
* @param iterations the number of iterations to use (use 10K or more)
|
|
*/
|
|
OctetString derive_key(size_t out_len,
|
|
const std::string& passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t iterations) const
|
|
{
|
|
return pbkdf_iterations(out_len, passphrase, salt, salt_len, iterations);
|
|
}
|
|
|
|
/**
|
|
* Derive a key from a passphrase
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param salt a randomly chosen salt
|
|
* @param iterations the number of iterations to use (use 10K or more)
|
|
*/
|
|
template<typename Alloc>
|
|
OctetString derive_key(size_t out_len,
|
|
const std::string& passphrase,
|
|
const std::vector<uint8_t, Alloc>& salt,
|
|
size_t iterations) const
|
|
{
|
|
return pbkdf_iterations(out_len, passphrase, salt.data(), salt.size(), iterations);
|
|
}
|
|
|
|
/**
|
|
* Derive a key from a passphrase
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param salt a randomly chosen salt
|
|
* @param salt_len length of salt in bytes
|
|
* @param msec is how long to run the PBKDF
|
|
* @param iterations is set to the number of iterations used
|
|
*/
|
|
OctetString derive_key(size_t out_len,
|
|
const std::string& passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
std::chrono::milliseconds msec,
|
|
size_t& iterations) const
|
|
{
|
|
return pbkdf_timed(out_len, passphrase, salt, salt_len, msec, iterations);
|
|
}
|
|
|
|
/**
|
|
* Derive a key from a passphrase using a certain amount of time
|
|
* @param out_len the desired length of the key to produce
|
|
* @param passphrase the password to derive the key from
|
|
* @param salt a randomly chosen salt
|
|
* @param msec is how long to run the PBKDF
|
|
* @param iterations is set to the number of iterations used
|
|
*/
|
|
template<typename Alloc>
|
|
OctetString derive_key(size_t out_len,
|
|
const std::string& passphrase,
|
|
const std::vector<uint8_t, Alloc>& salt,
|
|
std::chrono::milliseconds msec,
|
|
size_t& iterations) const
|
|
{
|
|
return pbkdf_timed(out_len, passphrase, salt.data(), salt.size(), msec, iterations);
|
|
}
|
|
};
|
|
|
|
/*
|
|
* Compatibility typedef
|
|
*/
|
|
typedef PBKDF S2K;
|
|
|
|
/**
|
|
* Password based key derivation function factory method
|
|
* @param algo_spec the name of the desired PBKDF algorithm
|
|
* @param provider the provider to use
|
|
* @return pointer to newly allocated object of that type
|
|
*/
|
|
inline PBKDF* get_pbkdf(const std::string& algo_spec,
|
|
const std::string& provider = "")
|
|
{
|
|
return PBKDF::create_or_throw(algo_spec, provider).release();
|
|
}
|
|
|
|
inline PBKDF* get_s2k(const std::string& algo_spec)
|
|
{
|
|
return get_pbkdf(algo_spec);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(pbkdf1.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* PKCS #5 v1 PBKDF, aka PBKDF1
|
|
* Can only generate a key up to the size of the hash output.
|
|
* Unless needed for backwards compatibility, use PKCS5_PBKDF2
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PKCS5_PBKDF1 final : public PBKDF
|
|
{
|
|
public:
|
|
/**
|
|
* Create a PKCS #5 instance using the specified hash function.
|
|
* @param hash pointer to a hash function object to use
|
|
*/
|
|
explicit PKCS5_PBKDF1(HashFunction* hash) : m_hash(hash) {}
|
|
|
|
std::string name() const override
|
|
{
|
|
return "PBKDF1(" + m_hash->name() + ")";
|
|
}
|
|
|
|
PBKDF* clone() const override
|
|
{
|
|
return new PKCS5_PBKDF1(m_hash->clone());
|
|
}
|
|
|
|
size_t pbkdf(uint8_t output_buf[], size_t output_len,
|
|
const std::string& passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t iterations,
|
|
std::chrono::milliseconds msec) const override;
|
|
private:
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(pbkdf2.h)
|
|
|
|
namespace Botan {
|
|
|
|
BOTAN_PUBLIC_API(2,0) size_t pbkdf2(MessageAuthenticationCode& prf,
|
|
uint8_t out[],
|
|
size_t out_len,
|
|
const std::string& passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t iterations,
|
|
std::chrono::milliseconds msec);
|
|
|
|
/**
|
|
* Perform PBKDF2. The prf is assumed to be keyed already.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,8) void pbkdf2(MessageAuthenticationCode& prf,
|
|
uint8_t out[], size_t out_len,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t iterations);
|
|
|
|
/**
|
|
* PBKDF2
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,8) PBKDF2 final : public PasswordHash
|
|
{
|
|
public:
|
|
PBKDF2(const MessageAuthenticationCode& prf, size_t iter) :
|
|
m_prf(prf.clone()),
|
|
m_iterations(iter)
|
|
{}
|
|
|
|
PBKDF2(const MessageAuthenticationCode& prf, size_t olen, std::chrono::milliseconds msec);
|
|
|
|
size_t iterations() const override { return m_iterations; }
|
|
|
|
std::string to_string() const override;
|
|
|
|
void derive_key(uint8_t out[], size_t out_len,
|
|
const char* password, size_t password_len,
|
|
const uint8_t salt[], size_t salt_len) const override;
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_prf;
|
|
size_t m_iterations;
|
|
};
|
|
|
|
/**
|
|
* Family of PKCS #5 PBKDF2 operations
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,8) PBKDF2_Family final : public PasswordHashFamily
|
|
{
|
|
public:
|
|
PBKDF2_Family(MessageAuthenticationCode* prf) : m_prf(prf) {}
|
|
|
|
std::string name() const override;
|
|
|
|
std::unique_ptr<PasswordHash> tune(size_t output_len,
|
|
std::chrono::milliseconds msec,
|
|
size_t max_memory) const override;
|
|
|
|
/**
|
|
* Return some default parameter set for this PBKDF that should be good
|
|
* enough for most users. The value returned may change over time as
|
|
* processing power and attacks improve.
|
|
*/
|
|
std::unique_ptr<PasswordHash> default_params() const override;
|
|
|
|
std::unique_ptr<PasswordHash> from_iterations(size_t iter) const override;
|
|
|
|
std::unique_ptr<PasswordHash> from_params(
|
|
size_t iter, size_t, size_t) const override;
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_prf;
|
|
};
|
|
|
|
/**
|
|
* PKCS #5 PBKDF2 (old interface)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PKCS5_PBKDF2 final : public PBKDF
|
|
{
|
|
public:
|
|
std::string name() const override;
|
|
|
|
PBKDF* clone() const override;
|
|
|
|
size_t pbkdf(uint8_t output_buf[], size_t output_len,
|
|
const std::string& passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t iterations,
|
|
std::chrono::milliseconds msec) const override;
|
|
|
|
/**
|
|
* Create a PKCS #5 instance using the specified message auth code
|
|
* @param mac_fn the MAC object to use as PRF
|
|
*/
|
|
explicit PKCS5_PBKDF2(MessageAuthenticationCode* mac_fn) : m_mac(mac_fn) {}
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class DataSource;
|
|
|
|
namespace PEM_Code {
|
|
|
|
/**
|
|
* Encode some binary data in PEM format
|
|
* @param data binary data to encode
|
|
* @param data_len length of binary data in bytes
|
|
* @param label PEM label put after BEGIN and END
|
|
* @param line_width after this many characters, a new line is inserted
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::string encode(const uint8_t data[],
|
|
size_t data_len,
|
|
const std::string& label,
|
|
size_t line_width = 64);
|
|
|
|
/**
|
|
* Encode some binary data in PEM format
|
|
* @param data binary data to encode
|
|
* @param label PEM label
|
|
* @param line_width after this many characters, a new line is inserted
|
|
*/
|
|
template<typename Alloc>
|
|
std::string encode(const std::vector<uint8_t, Alloc>& data,
|
|
const std::string& label,
|
|
size_t line_width = 64)
|
|
{
|
|
return encode(data.data(), data.size(), label, line_width);
|
|
}
|
|
|
|
/**
|
|
* Decode PEM data
|
|
* @param pem a datasource containing PEM encoded data
|
|
* @param label is set to the PEM label found for later inspection
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) secure_vector<uint8_t> decode(DataSource& pem,
|
|
std::string& label);
|
|
|
|
/**
|
|
* Decode PEM data
|
|
* @param pem a string containing PEM encoded data
|
|
* @param label is set to the PEM label found for later inspection
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) secure_vector<uint8_t> decode(const std::string& pem,
|
|
std::string& label);
|
|
|
|
/**
|
|
* Decode PEM data
|
|
* @param pem a datasource containing PEM encoded data
|
|
* @param label is what we expect the label to be
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0)
|
|
secure_vector<uint8_t> decode_check_label(DataSource& pem,
|
|
const std::string& label);
|
|
|
|
/**
|
|
* Decode PEM data
|
|
* @param pem a string containing PEM encoded data
|
|
* @param label is what we expect the label to be
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0)
|
|
secure_vector<uint8_t> decode_check_label(const std::string& pem,
|
|
const std::string& label);
|
|
|
|
/**
|
|
* Heuristic test for PEM data.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) bool matches(DataSource& source,
|
|
const std::string& extra = "",
|
|
size_t search_range = 4096);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
This header will not be fully internal - the RFC4880 count
|
|
encoding functions will remain here. But the definition of
|
|
OpenPGP_S2K will be made internal
|
|
*/
|
|
|
|
//BOTAN_FUTURE_INTERNAL_HEADER(pgp_s2k.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* RFC 4880 encodes the iteration count to a single-byte value
|
|
*/
|
|
uint8_t BOTAN_PUBLIC_API(2,8) RFC4880_encode_count(size_t iterations);
|
|
|
|
/**
|
|
* Decode the iteration count from RFC 4880 encoding
|
|
*/
|
|
size_t BOTAN_PUBLIC_API(2,8) RFC4880_decode_count(uint8_t encoded_iter);
|
|
|
|
/**
|
|
* Round an arbitrary iteration count to next largest iteration count
|
|
* supported by RFC4880 encoding.
|
|
*/
|
|
inline size_t RFC4880_round_iterations(size_t iterations)
|
|
{
|
|
return RFC4880_decode_count(RFC4880_encode_count(iterations));
|
|
}
|
|
|
|
/**
|
|
* OpenPGP's S2K
|
|
*
|
|
* See RFC 4880 sections 3.7.1.1, 3.7.1.2, and 3.7.1.3
|
|
* If the salt is empty and iterations == 1, "simple" S2K is used
|
|
* If the salt is non-empty and iterations == 1, "salted" S2K is used
|
|
* If the salt is non-empty and iterations > 1, "iterated" S2K is used
|
|
*
|
|
* Due to complexities of the PGP S2K algorithm, time-based derivation
|
|
* is not supported. So if iterations == 0 and msec.count() > 0, an
|
|
* exception is thrown. In the future this may be supported, in which
|
|
* case "iterated" S2K will be used and the number of iterations
|
|
* performed is returned.
|
|
*
|
|
* Note that unlike PBKDF2, OpenPGP S2K's "iterations" are defined as
|
|
* the number of bytes hashed.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) OpenPGP_S2K final : public PBKDF
|
|
{
|
|
public:
|
|
/**
|
|
* @param hash the hash function to use
|
|
*/
|
|
explicit OpenPGP_S2K(HashFunction* hash) : m_hash(hash) {}
|
|
|
|
std::string name() const override
|
|
{
|
|
return "OpenPGP-S2K(" + m_hash->name() + ")";
|
|
}
|
|
|
|
PBKDF* clone() const override
|
|
{
|
|
return new OpenPGP_S2K(m_hash->clone());
|
|
}
|
|
|
|
size_t pbkdf(uint8_t output_buf[], size_t output_len,
|
|
const std::string& passphrase,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t iterations,
|
|
std::chrono::milliseconds msec) const override;
|
|
|
|
/**
|
|
* RFC 4880 encodes the iteration count to a single-byte value
|
|
*/
|
|
static uint8_t encode_count(size_t iterations)
|
|
{
|
|
return RFC4880_encode_count(iterations);
|
|
}
|
|
|
|
static size_t decode_count(uint8_t encoded_iter)
|
|
{
|
|
return RFC4880_decode_count(encoded_iter);
|
|
}
|
|
|
|
private:
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
};
|
|
|
|
/**
|
|
* OpenPGP's S2K
|
|
*
|
|
* See RFC 4880 sections 3.7.1.1, 3.7.1.2, and 3.7.1.3
|
|
* If the salt is empty and iterations == 1, "simple" S2K is used
|
|
* If the salt is non-empty and iterations == 1, "salted" S2K is used
|
|
* If the salt is non-empty and iterations > 1, "iterated" S2K is used
|
|
*
|
|
* Note that unlike PBKDF2, OpenPGP S2K's "iterations" are defined as
|
|
* the number of bytes hashed.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,8) RFC4880_S2K final : public PasswordHash
|
|
{
|
|
public:
|
|
/**
|
|
* @param hash the hash function to use
|
|
* @param iterations is rounded due to PGP formatting
|
|
*/
|
|
RFC4880_S2K(HashFunction* hash, size_t iterations);
|
|
|
|
std::string to_string() const override;
|
|
|
|
size_t iterations() const override { return m_iterations; }
|
|
|
|
void derive_key(uint8_t out[], size_t out_len,
|
|
const char* password, size_t password_len,
|
|
const uint8_t salt[], size_t salt_len) const override;
|
|
|
|
private:
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
size_t m_iterations;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,8) RFC4880_S2K_Family final : public PasswordHashFamily
|
|
{
|
|
public:
|
|
RFC4880_S2K_Family(HashFunction* hash) : m_hash(hash) {}
|
|
|
|
std::string name() const override;
|
|
|
|
std::unique_ptr<PasswordHash> tune(size_t output_len,
|
|
std::chrono::milliseconds msec,
|
|
size_t max_mem) const override;
|
|
|
|
/**
|
|
* Return some default parameter set for this PBKDF that should be good
|
|
* enough for most users. The value returned may change over time as
|
|
* processing power and attacks improve.
|
|
*/
|
|
std::unique_ptr<PasswordHash> default_params() const override;
|
|
|
|
std::unique_ptr<PasswordHash> from_iterations(size_t iter) const override;
|
|
|
|
std::unique_ptr<PasswordHash> from_params(
|
|
size_t iter, size_t, size_t) const override;
|
|
private:
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
BOTAN_PUBLIC_API(2,0) std::unique_ptr<Public_Key>
|
|
load_public_key(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits);
|
|
|
|
BOTAN_PUBLIC_API(2,0) std::unique_ptr<Private_Key>
|
|
load_private_key(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Create a new key
|
|
* For ECC keys, algo_params specifies EC group (eg, "secp256r1")
|
|
* For DH/DSA/ElGamal keys, algo_params is DL group (eg, "modp/ietf/2048")
|
|
* For RSA, algo_params is integer keylength
|
|
* For McEliece, algo_params is n,t
|
|
* If algo_params is left empty, suitable default parameters are chosen.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::unique_ptr<Private_Key>
|
|
create_private_key(const std::string& algo_name,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& algo_params = "",
|
|
const std::string& provider = "");
|
|
|
|
BOTAN_PUBLIC_API(2,2)
|
|
std::vector<std::string>
|
|
probe_provider_private_key(const std::string& algo_name,
|
|
const std::vector<std::string> possible);
|
|
|
|
}
|
|
/**
|
|
* Ordinary applications should never need to include or use this
|
|
* header. It is exposed only for specialized applications which want
|
|
* to implement new versions of public key crypto without merging them
|
|
* as changes to the library. One actual example of such usage is an
|
|
* application which creates RSA signatures using a custom TPM library.
|
|
* Unless you're doing something like that, you don't need anything
|
|
* here. Instead use pubkey.h which wraps these types safely and
|
|
* provides a stable application-oriented API.
|
|
*/
|
|
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
class EME;
|
|
class KDF;
|
|
class EMSA;
|
|
|
|
namespace PK_Ops {
|
|
|
|
/**
|
|
* Public key encryption interface
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Encryption
|
|
{
|
|
public:
|
|
virtual secure_vector<uint8_t> encrypt(const uint8_t msg[],
|
|
size_t msg_len,
|
|
RandomNumberGenerator& rng) = 0;
|
|
|
|
virtual size_t max_input_bits() const = 0;
|
|
|
|
virtual size_t ciphertext_length(size_t ptext_len) const = 0;
|
|
|
|
virtual ~Encryption() = default;
|
|
};
|
|
|
|
/**
|
|
* Public key decryption interface
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Decryption
|
|
{
|
|
public:
|
|
virtual secure_vector<uint8_t> decrypt(uint8_t& valid_mask,
|
|
const uint8_t ciphertext[],
|
|
size_t ciphertext_len) = 0;
|
|
|
|
virtual size_t plaintext_length(size_t ctext_len) const = 0;
|
|
|
|
virtual ~Decryption() = default;
|
|
};
|
|
|
|
/**
|
|
* Public key signature verification interface
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Verification
|
|
{
|
|
public:
|
|
/*
|
|
* Add more data to the message currently being signed
|
|
* @param msg the message
|
|
* @param msg_len the length of msg in bytes
|
|
*/
|
|
virtual void update(const uint8_t msg[], size_t msg_len) = 0;
|
|
|
|
/*
|
|
* Perform a verification operation
|
|
* @param rng a random number generator
|
|
*/
|
|
virtual bool is_valid_signature(const uint8_t sig[], size_t sig_len) = 0;
|
|
|
|
virtual ~Verification() = default;
|
|
};
|
|
|
|
/**
|
|
* Public key signature creation interface
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Signature
|
|
{
|
|
public:
|
|
/*
|
|
* Add more data to the message currently being signed
|
|
* @param msg the message
|
|
* @param msg_len the length of msg in bytes
|
|
*/
|
|
virtual void update(const uint8_t msg[], size_t msg_len) = 0;
|
|
|
|
/*
|
|
* Perform a signature operation
|
|
* @param rng a random number generator
|
|
*/
|
|
virtual secure_vector<uint8_t> sign(RandomNumberGenerator& rng) = 0;
|
|
|
|
/*
|
|
* Return an upper bound on the length of the output signature
|
|
*/
|
|
virtual size_t signature_length() const = 0;
|
|
|
|
virtual ~Signature() = default;
|
|
};
|
|
|
|
/**
|
|
* A generic key agreement operation (eg DH or ECDH)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Key_Agreement
|
|
{
|
|
public:
|
|
virtual secure_vector<uint8_t> agree(size_t key_len,
|
|
const uint8_t other_key[], size_t other_key_len,
|
|
const uint8_t salt[], size_t salt_len) = 0;
|
|
|
|
virtual size_t agreed_value_size() const = 0;
|
|
|
|
virtual ~Key_Agreement() = default;
|
|
};
|
|
|
|
/**
|
|
* KEM (key encapsulation)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) KEM_Encryption
|
|
{
|
|
public:
|
|
virtual void kem_encrypt(secure_vector<uint8_t>& out_encapsulated_key,
|
|
secure_vector<uint8_t>& out_shared_key,
|
|
size_t desired_shared_key_len,
|
|
Botan::RandomNumberGenerator& rng,
|
|
const uint8_t salt[],
|
|
size_t salt_len) = 0;
|
|
|
|
virtual ~KEM_Encryption() = default;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,0) KEM_Decryption
|
|
{
|
|
public:
|
|
virtual secure_vector<uint8_t> kem_decrypt(const uint8_t encap_key[],
|
|
size_t len,
|
|
size_t desired_shared_key_len,
|
|
const uint8_t salt[],
|
|
size_t salt_len) = 0;
|
|
|
|
virtual ~KEM_Decryption() = default;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
struct PKCS10_Data;
|
|
|
|
class Private_Key;
|
|
class Extensions;
|
|
class X509_DN;
|
|
class AlternativeName;
|
|
|
|
/**
|
|
* PKCS #10 Certificate Request.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PKCS10_Request final : public X509_Object
|
|
{
|
|
public:
|
|
/**
|
|
* Get the subject public key.
|
|
* @return subject public key
|
|
*/
|
|
Public_Key* subject_public_key() const;
|
|
|
|
/**
|
|
* Get the raw DER encoded public key.
|
|
* @return raw DER encoded public key
|
|
*/
|
|
const std::vector<uint8_t>& raw_public_key() const;
|
|
|
|
/**
|
|
* Get the subject DN.
|
|
* @return subject DN
|
|
*/
|
|
const X509_DN& subject_dn() const;
|
|
|
|
/**
|
|
* Get the subject alternative name.
|
|
* @return subject alternative name.
|
|
*/
|
|
const AlternativeName& subject_alt_name() const;
|
|
|
|
/**
|
|
* Get the key constraints for the key associated with this
|
|
* PKCS#10 object.
|
|
* @return key constraints
|
|
*/
|
|
Key_Constraints constraints() const;
|
|
|
|
/**
|
|
* Get the extendend key constraints (if any).
|
|
* @return extended key constraints
|
|
*/
|
|
std::vector<OID> ex_constraints() const;
|
|
|
|
/**
|
|
* Find out whether this is a CA request.
|
|
* @result true if it is a CA request, false otherwise.
|
|
*/
|
|
bool is_CA() const;
|
|
|
|
/**
|
|
* Return the constraint on the path length defined
|
|
* in the BasicConstraints extension.
|
|
* @return path limit
|
|
*/
|
|
size_t path_limit() const;
|
|
|
|
/**
|
|
* Get the challenge password for this request
|
|
* @return challenge password for this request
|
|
*/
|
|
std::string challenge_password() const;
|
|
|
|
/**
|
|
* Get the X509v3 extensions.
|
|
* @return X509v3 extensions
|
|
*/
|
|
const Extensions& extensions() const;
|
|
|
|
/**
|
|
* Create a PKCS#10 Request from a data source.
|
|
* @param source the data source providing the DER encoded request
|
|
*/
|
|
explicit PKCS10_Request(DataSource& source);
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
|
|
/**
|
|
* Create a PKCS#10 Request from a file.
|
|
* @param filename the name of the file containing the DER or PEM
|
|
* encoded request file
|
|
*/
|
|
explicit PKCS10_Request(const std::string& filename);
|
|
#endif
|
|
|
|
/**
|
|
* Create a PKCS#10 Request from binary data.
|
|
* @param vec a std::vector containing the DER value
|
|
*/
|
|
explicit PKCS10_Request(const std::vector<uint8_t>& vec);
|
|
|
|
/**
|
|
* Create a new PKCS10 certificate request
|
|
* @param key the key that will be included in the certificate request
|
|
* @param subject_dn the DN to be placed in the request
|
|
* @param extensions extensions to include in the request
|
|
* @param hash_fn the hash function to use to create the signature
|
|
* @param rng a random number generator
|
|
* @param padding_scheme if set specifies the padding scheme, otherwise an
|
|
* algorithm-specific default is used.
|
|
* @param challenge a challenge string to be included in the PKCS10 request,
|
|
* sometimes used for revocation purposes.
|
|
*/
|
|
static 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 = "");
|
|
|
|
private:
|
|
std::string PEM_label() const override;
|
|
|
|
std::vector<std::string> alternate_PEM_labels() const override;
|
|
|
|
void force_decode() override;
|
|
|
|
const PKCS10_Data& data() const;
|
|
|
|
std::shared_ptr<PKCS10_Data> m_data;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class DataSource;
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* PKCS #8 General Exception
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PKCS8_Exception final : public Decoding_Error
|
|
{
|
|
public:
|
|
explicit PKCS8_Exception(const std::string& error) :
|
|
Decoding_Error("PKCS #8: " + error) {}
|
|
};
|
|
|
|
/**
|
|
* This namespace contains functions for handling PKCS #8 private keys
|
|
*/
|
|
namespace PKCS8 {
|
|
|
|
/**
|
|
* BER encode a private key
|
|
* @param key the private key to encode
|
|
* @return BER encoded key
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) secure_vector<uint8_t> BER_encode(const Private_Key& key);
|
|
|
|
/**
|
|
* Get a string containing a PEM encoded private key.
|
|
* @param key the key to encode
|
|
* @return encoded key
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::string PEM_encode(const Private_Key& key);
|
|
|
|
/**
|
|
* Encrypt a key using PKCS #8 encryption
|
|
* @param key the key to encode
|
|
* @param rng the rng to use
|
|
* @param pass the password to use for encryption
|
|
* @param msec number of milliseconds to run the password derivation
|
|
* @param pbe_algo the name of the desired password-based encryption
|
|
* algorithm; if empty ("") a reasonable (portable/secure)
|
|
* default will be chosen.
|
|
* @return encrypted key in binary BER form
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::vector<uint8_t>
|
|
BER_encode(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass,
|
|
std::chrono::milliseconds msec = std::chrono::milliseconds(300),
|
|
const std::string& pbe_algo = "");
|
|
|
|
/**
|
|
* Get a string containing a PEM encoded private key, encrypting it with a
|
|
* password.
|
|
* @param key the key to encode
|
|
* @param rng the rng to use
|
|
* @param pass the password to use for encryption
|
|
* @param msec number of milliseconds to run the password derivation
|
|
* @param pbe_algo the name of the desired password-based encryption
|
|
* algorithm; if empty ("") a reasonable (portable/secure)
|
|
* default will be chosen.
|
|
* @return encrypted key in PEM form
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::string
|
|
PEM_encode(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass,
|
|
std::chrono::milliseconds msec = std::chrono::milliseconds(300),
|
|
const std::string& pbe_algo = "");
|
|
|
|
/**
|
|
* Encrypt a key using PKCS #8 encryption and a fixed iteration count
|
|
* @param key the key to encode
|
|
* @param rng the rng to use
|
|
* @param pass the password to use for encryption
|
|
* @param pbkdf_iter number of interations to run PBKDF2
|
|
* @param cipher if non-empty specifies the cipher to use. CBC and GCM modes
|
|
* are supported, for example "AES-128/CBC", "AES-256/GCM", "Serpent/CBC".
|
|
* If empty a suitable default is chosen.
|
|
* @param pbkdf_hash if non-empty specifies the PBKDF hash function to use.
|
|
* For example "SHA-256" or "SHA-384". If empty a suitable default is chosen.
|
|
* @return encrypted key in binary BER form
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) std::vector<uint8_t>
|
|
BER_encode_encrypted_pbkdf_iter(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass,
|
|
size_t pbkdf_iter,
|
|
const std::string& cipher = "",
|
|
const std::string& pbkdf_hash = "");
|
|
|
|
/**
|
|
* Get a string containing a PEM encoded private key, encrypting it with a
|
|
* password.
|
|
* @param key the key to encode
|
|
* @param rng the rng to use
|
|
* @param pass the password to use for encryption
|
|
* @param pbkdf_iter number of iterations to run PBKDF
|
|
* @param cipher if non-empty specifies the cipher to use. CBC and GCM modes
|
|
* are supported, for example "AES-128/CBC", "AES-256/GCM", "Serpent/CBC".
|
|
* If empty a suitable default is chosen.
|
|
* @param pbkdf_hash if non-empty specifies the PBKDF hash function to use.
|
|
* For example "SHA-256" or "SHA-384". If empty a suitable default is chosen.
|
|
* @return encrypted key in PEM form
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) std::string
|
|
PEM_encode_encrypted_pbkdf_iter(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass,
|
|
size_t pbkdf_iter,
|
|
const std::string& cipher = "",
|
|
const std::string& pbkdf_hash = "");
|
|
|
|
/**
|
|
* Encrypt a key using PKCS #8 encryption and a variable iteration count
|
|
* @param key the key to encode
|
|
* @param rng the rng to use
|
|
* @param pass the password to use for encryption
|
|
* @param pbkdf_msec how long to run PBKDF2
|
|
* @param pbkdf_iterations if non-null, set to the number of iterations used
|
|
* @param cipher if non-empty specifies the cipher to use. CBC and GCM modes
|
|
* are supported, for example "AES-128/CBC", "AES-256/GCM", "Serpent/CBC".
|
|
* If empty a suitable default is chosen.
|
|
* @param pbkdf_hash if non-empty specifies the PBKDF hash function to use.
|
|
* For example "SHA-256" or "SHA-384". If empty a suitable default is chosen.
|
|
* @return encrypted key in binary BER form
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) std::vector<uint8_t>
|
|
BER_encode_encrypted_pbkdf_msec(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass,
|
|
std::chrono::milliseconds pbkdf_msec,
|
|
size_t* pbkdf_iterations,
|
|
const std::string& cipher = "",
|
|
const std::string& pbkdf_hash = "");
|
|
|
|
/**
|
|
* Get a string containing a PEM encoded private key, encrypting it with a
|
|
* password.
|
|
* @param key the key to encode
|
|
* @param rng the rng to use
|
|
* @param pass the password to use for encryption
|
|
* @param pbkdf_msec how long in milliseconds to run PBKDF2
|
|
* @param pbkdf_iterations (output argument) number of iterations of PBKDF
|
|
* that ended up being used
|
|
* @param cipher if non-empty specifies the cipher to use. CBC and GCM modes
|
|
* are supported, for example "AES-128/CBC", "AES-256/GCM", "Serpent/CBC".
|
|
* If empty a suitable default is chosen.
|
|
* @param pbkdf_hash if non-empty specifies the PBKDF hash function to use.
|
|
* For example "SHA-256" or "SHA-384". If empty a suitable default is chosen.
|
|
* @return encrypted key in PEM form
|
|
*/
|
|
BOTAN_PUBLIC_API(2,1) std::string
|
|
PEM_encode_encrypted_pbkdf_msec(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass,
|
|
std::chrono::milliseconds pbkdf_msec,
|
|
size_t* pbkdf_iterations,
|
|
const std::string& cipher = "",
|
|
const std::string& pbkdf_hash = "");
|
|
|
|
/**
|
|
* Load an encrypted key from a data source.
|
|
* @param source the data source providing the encoded key
|
|
* @param rng ignored for compatibility
|
|
* @param get_passphrase a function that returns passphrases
|
|
* @return loaded private key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) Private_Key* load_key(DataSource& source,
|
|
RandomNumberGenerator& rng,
|
|
std::function<std::string ()> get_passphrase);
|
|
|
|
/** Load an encrypted key from a data source.
|
|
* @param source the data source providing the encoded key
|
|
* @param rng ignored for compatibility
|
|
* @param pass the passphrase to decrypt the key
|
|
* @return loaded private key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) Private_Key* load_key(DataSource& source,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass);
|
|
|
|
/** Load an unencrypted key from a data source.
|
|
* @param source the data source providing the encoded key
|
|
* @param rng ignored for compatibility
|
|
* @return loaded private key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) Private_Key* load_key(DataSource& source,
|
|
RandomNumberGenerator& rng);
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
|
|
/**
|
|
* Load an encrypted key from a file.
|
|
* @param filename the path to the file containing the encoded key
|
|
* @param rng ignored for compatibility
|
|
* @param get_passphrase a function that returns passphrases
|
|
* @return loaded private key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) Private_Key* load_key(const std::string& filename,
|
|
RandomNumberGenerator& rng,
|
|
std::function<std::string ()> get_passphrase);
|
|
|
|
/** Load an encrypted key from a file.
|
|
* @param filename the path to the file containing the encoded key
|
|
* @param rng ignored for compatibility
|
|
* @param pass the passphrase to decrypt the key
|
|
* @return loaded private key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) Private_Key* load_key(const std::string& filename,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& pass);
|
|
|
|
/** Load an unencrypted key from a file.
|
|
* @param filename the path to the file containing the encoded key
|
|
* @param rng ignored for compatibility
|
|
* @return loaded private key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) Private_Key* load_key(const std::string& filename,
|
|
RandomNumberGenerator& rng);
|
|
#endif
|
|
|
|
/**
|
|
* Copy an existing encoded key object.
|
|
* @param key the key to copy
|
|
* @param rng ignored for compatibility
|
|
* @return new copy of the key
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) Private_Key* copy_key(const Private_Key& key,
|
|
RandomNumberGenerator& rng);
|
|
|
|
|
|
/**
|
|
* Load an encrypted key from a data source.
|
|
* @param source the data source providing the encoded key
|
|
* @param get_passphrase a function that returns passphrases
|
|
* @return loaded private key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3)
|
|
std::unique_ptr<Private_Key> load_key(DataSource& source,
|
|
std::function<std::string ()> get_passphrase);
|
|
|
|
/** Load an encrypted key from a data source.
|
|
* @param source the data source providing the encoded key
|
|
* @param pass the passphrase to decrypt the key
|
|
* @return loaded private key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3)
|
|
std::unique_ptr<Private_Key> load_key(DataSource& source,
|
|
const std::string& pass);
|
|
|
|
/** Load an unencrypted key from a data source.
|
|
* @param source the data source providing the encoded key
|
|
* @return loaded private key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3)
|
|
std::unique_ptr<Private_Key> load_key(DataSource& source);
|
|
|
|
/**
|
|
* Copy an existing encoded key object.
|
|
* @param key the key to copy
|
|
* @return new copy of the key
|
|
*/
|
|
BOTAN_PUBLIC_API(2,3)
|
|
std::unique_ptr<Private_Key> copy_key(const Private_Key& key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(poly1305.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* DJB's Poly1305
|
|
* Important note: each key can only be used once
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Poly1305 final : public MessageAuthenticationCode
|
|
{
|
|
public:
|
|
std::string name() const override { return "Poly1305"; }
|
|
|
|
MessageAuthenticationCode* clone() const override { return new Poly1305; }
|
|
|
|
void clear() override;
|
|
|
|
size_t output_length() const override { return 16; }
|
|
|
|
Key_Length_Specification key_spec() const override
|
|
{
|
|
return Key_Length_Specification(32);
|
|
}
|
|
|
|
private:
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
secure_vector<uint64_t> m_poly;
|
|
secure_vector<uint8_t> m_buf;
|
|
size_t m_buf_pos = 0;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(pow_mod.h)
|
|
|
|
namespace Botan {
|
|
|
|
class Modular_Exponentiator;
|
|
|
|
/**
|
|
* Modular Exponentiator Proxy
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Power_Mod
|
|
{
|
|
public:
|
|
|
|
enum Usage_Hints {
|
|
NO_HINTS = 0x0000,
|
|
|
|
BASE_IS_FIXED = 0x0001,
|
|
BASE_IS_SMALL = 0x0002,
|
|
BASE_IS_LARGE = 0x0004,
|
|
BASE_IS_2 = 0x0008,
|
|
|
|
EXP_IS_FIXED = 0x0100,
|
|
EXP_IS_SMALL = 0x0200,
|
|
EXP_IS_LARGE = 0x0400
|
|
};
|
|
|
|
/*
|
|
* Try to choose a good window size
|
|
*/
|
|
static size_t window_bits(size_t exp_bits, size_t base_bits,
|
|
Power_Mod::Usage_Hints hints);
|
|
|
|
/**
|
|
* @param modulus the modulus
|
|
* @param hints Passed to set_modulus if modulus > 0
|
|
* @param disable_montgomery_arith Disables use of Montgomery
|
|
* representation. Likely only useful for testing.
|
|
*/
|
|
void set_modulus(const BigInt& modulus,
|
|
Usage_Hints hints = NO_HINTS,
|
|
bool disable_montgomery_arith = false) const;
|
|
|
|
/**
|
|
* Set the base
|
|
*/
|
|
void set_base(const BigInt& base) const;
|
|
|
|
/**
|
|
* Set the exponent
|
|
*/
|
|
void set_exponent(const BigInt& exponent) const;
|
|
|
|
/**
|
|
* All three of the above functions must have already been called.
|
|
* @return result of g^x%p
|
|
*/
|
|
BigInt execute() const;
|
|
|
|
Power_Mod& operator=(const Power_Mod&);
|
|
|
|
/**
|
|
* @param modulus Optionally call set_modulus
|
|
* @param hints Passed to set_modulus if modulus > 0
|
|
* @param disable_montgomery_arith Disables use of Montgomery
|
|
* representation. Likely only useful for testing.
|
|
*/
|
|
Power_Mod(const BigInt& modulus = 0,
|
|
Usage_Hints hints = NO_HINTS,
|
|
bool disable_montgomery_arith = false);
|
|
Power_Mod(const Power_Mod&);
|
|
virtual ~Power_Mod();
|
|
private:
|
|
mutable std::unique_ptr<Modular_Exponentiator> m_core;
|
|
};
|
|
|
|
/**
|
|
* Fixed Exponent Modular Exponentiator Proxy
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Fixed_Exponent_Power_Mod final : public Power_Mod
|
|
{
|
|
public:
|
|
BigInt operator()(const BigInt& b) const
|
|
{ set_base(b); return execute(); }
|
|
|
|
Fixed_Exponent_Power_Mod() = default;
|
|
|
|
Fixed_Exponent_Power_Mod(const BigInt& exponent,
|
|
const BigInt& modulus,
|
|
Usage_Hints hints = NO_HINTS);
|
|
};
|
|
|
|
/**
|
|
* Fixed Base Modular Exponentiator Proxy
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Fixed_Base_Power_Mod final : public Power_Mod
|
|
{
|
|
public:
|
|
BigInt operator()(const BigInt& e) const
|
|
{ set_exponent(e); return execute(); }
|
|
|
|
Fixed_Base_Power_Mod() = default;
|
|
|
|
Fixed_Base_Power_Mod(const BigInt& base,
|
|
const BigInt& modulus,
|
|
Usage_Hints hints = NO_HINTS);
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(prf_tls.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* PRF used in TLS 1.0/1.1
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) TLS_PRF final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override { return "TLS-PRF"; }
|
|
|
|
KDF* clone() const override { return new TLS_PRF; }
|
|
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
TLS_PRF(std::unique_ptr<MessageAuthenticationCode> hmac_md5,
|
|
std::unique_ptr<MessageAuthenticationCode> hmac_sha1) :
|
|
m_hmac_md5(std::move(hmac_md5)),
|
|
m_hmac_sha1(std::move(hmac_sha1))
|
|
{}
|
|
|
|
TLS_PRF();
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_hmac_md5;
|
|
std::unique_ptr<MessageAuthenticationCode> m_hmac_sha1;
|
|
};
|
|
|
|
/**
|
|
* PRF used in TLS 1.2
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) TLS_12_PRF final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override { return "TLS-12-PRF(" + m_mac->name() + ")"; }
|
|
|
|
KDF* clone() const override { return new TLS_12_PRF(m_mac->clone()); }
|
|
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
/**
|
|
* @param mac MAC algorithm to use
|
|
*/
|
|
explicit TLS_12_PRF(MessageAuthenticationCode* mac) : m_mac(mac) {}
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(prf_x942.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* PRF from ANSI X9.42
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) X942_PRF final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override;
|
|
|
|
KDF* clone() const override { return new X942_PRF(m_key_wrap_oid); }
|
|
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
explicit X942_PRF(const std::string& oid) : m_key_wrap_oid(OID::from_string(oid)) {}
|
|
|
|
explicit X942_PRF(const OID& oid) : m_key_wrap_oid(oid) {}
|
|
private:
|
|
OID m_key_wrap_oid;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Directly invokes a CPU specific instruction to generate random numbers.
|
|
* On x86, the RDRAND instruction is used.
|
|
* on POWER, the DARN instruction is used.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,15) Processor_RNG final : public Hardware_RNG
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor will throw if CPU does not have RDRAND bit set
|
|
*/
|
|
Processor_RNG();
|
|
|
|
/**
|
|
* Return true if RNG instruction is available on the current processor
|
|
*/
|
|
static bool available();
|
|
|
|
bool accepts_input() const override { return false; }
|
|
bool is_seeded() const override { return true; }
|
|
|
|
void randomize(uint8_t out[], size_t out_len) override;
|
|
|
|
/*
|
|
* No way to provide entropy to RDRAND generator, so add_entropy is ignored
|
|
*/
|
|
void add_entropy(const uint8_t[], size_t) override;
|
|
|
|
/*
|
|
* No way to reseed processor provided generator, so reseed is ignored
|
|
*/
|
|
size_t reseed(Entropy_Sources&, size_t, std::chrono::milliseconds) override;
|
|
|
|
std::string name() const override;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class BlockCipher;
|
|
class MessageAuthenticationCode;
|
|
|
|
/**
|
|
* This is an interface to a generic PSK (pre-shared key) database.
|
|
* It might be implemented as a plaintext storage or via some mechanism
|
|
* that encrypts the keys and/or values.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,4) PSK_Database
|
|
{
|
|
public:
|
|
/**
|
|
* Return the set of names for which get() will return a value.
|
|
*/
|
|
virtual std::set<std::string> list_names() const = 0;
|
|
|
|
/**
|
|
* Return the value associated with the specified @param name or otherwise
|
|
* throw an exception.
|
|
*/
|
|
virtual secure_vector<uint8_t> get(const std::string& name) const = 0;
|
|
|
|
/**
|
|
* Set a value that can later be accessed with get().
|
|
* If name already exists in the database, the old value will be overwritten.
|
|
*/
|
|
virtual void set(const std::string& name, const uint8_t psk[], size_t psk_len) = 0;
|
|
|
|
/**
|
|
* Remove a PSK from the database
|
|
*/
|
|
virtual void remove(const std::string& name) = 0;
|
|
|
|
/**
|
|
* Returns if the values in the PSK database are encrypted. If
|
|
* false, saved values are being stored in plaintext.
|
|
*/
|
|
virtual bool is_encrypted() const = 0;
|
|
|
|
/**
|
|
* Get a PSK in the form of a string (eg if the PSK is a password)
|
|
*/
|
|
std::string get_str(const std::string& name) const
|
|
{
|
|
secure_vector<uint8_t> psk = get(name);
|
|
return std::string(cast_uint8_ptr_to_char(psk.data()), psk.size());
|
|
}
|
|
|
|
void set_str(const std::string& name, const std::string& psk)
|
|
{
|
|
set(name, cast_char_ptr_to_uint8(psk.data()), psk.size());
|
|
}
|
|
|
|
template<typename Alloc>
|
|
void set_vec(const std::string& name,
|
|
const std::vector<uint8_t, Alloc>& psk)
|
|
|
|
{
|
|
set(name, psk.data(), psk.size());
|
|
}
|
|
|
|
virtual ~PSK_Database() = default;
|
|
};
|
|
|
|
/**
|
|
* A mixin for an encrypted PSK database.
|
|
* Both keys and values are encrypted with NIST AES-256 key wrapping.
|
|
* Values are padded to obscure their length before encryption, allowing
|
|
* it to be used as a password vault.
|
|
*
|
|
* Subclasses must implement the virtual calls to handle storing and
|
|
* getting raw (base64 encoded) values.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,4) Encrypted_PSK_Database : public PSK_Database
|
|
{
|
|
public:
|
|
/**
|
|
* @param master_key specifies the master key used to encrypt all
|
|
* keys and value. It can be of any length, but should be at least 256 bits.
|
|
*
|
|
* Subkeys for the cryptographic algorithms used are derived from this
|
|
* master key. No key stretching is performed; if encrypting a PSK database
|
|
* using a password, it is recommended to use PBKDF2 to derive the database
|
|
* master key.
|
|
*/
|
|
Encrypted_PSK_Database(const secure_vector<uint8_t>& master_key);
|
|
|
|
~Encrypted_PSK_Database();
|
|
|
|
std::set<std::string> list_names() const override;
|
|
|
|
secure_vector<uint8_t> get(const std::string& name) const override;
|
|
|
|
void set(const std::string& name, const uint8_t psk[], size_t psk_len) override;
|
|
|
|
void remove(const std::string& name) override;
|
|
|
|
bool is_encrypted() const override { return true; }
|
|
|
|
protected:
|
|
/**
|
|
* Save a encrypted (name.value) pair to the database. Both will be base64 encoded strings.
|
|
*/
|
|
virtual void kv_set(const std::string& index, const std::string& value) = 0;
|
|
|
|
/**
|
|
* Get a value previously saved with set_raw_value. Should return an empty
|
|
* string if index is not found.
|
|
*/
|
|
virtual std::string kv_get(const std::string& index) const = 0;
|
|
|
|
/**
|
|
* Remove an index
|
|
*/
|
|
virtual void kv_del(const std::string& index) = 0;
|
|
|
|
/**
|
|
* Return all indexes in the table.
|
|
*/
|
|
virtual std::set<std::string> kv_get_all() const = 0;
|
|
|
|
private:
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
std::unique_ptr<MessageAuthenticationCode> m_hmac;
|
|
secure_vector<uint8_t> m_wrap_key;
|
|
};
|
|
|
|
class SQL_Database;
|
|
|
|
class BOTAN_PUBLIC_API(2,4) Encrypted_PSK_Database_SQL : public Encrypted_PSK_Database
|
|
{
|
|
public:
|
|
Encrypted_PSK_Database_SQL(const secure_vector<uint8_t>& master_key,
|
|
std::shared_ptr<SQL_Database> db,
|
|
const std::string& table_name);
|
|
|
|
~Encrypted_PSK_Database_SQL();
|
|
private:
|
|
void kv_set(const std::string& index, const std::string& value) override;
|
|
std::string kv_get(const std::string& index) const override;
|
|
void kv_del(const std::string& index) override;
|
|
std::set<std::string> kv_get_all() const override;
|
|
|
|
std::shared_ptr<SQL_Database> m_db;
|
|
const std::string m_table_name;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(pssr.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* PSSR (called EMSA4 in IEEE 1363 and in old versions of the library)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) PSSR final : public EMSA
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* @param hash the hash function to use
|
|
*/
|
|
explicit PSSR(HashFunction* hash);
|
|
|
|
/**
|
|
* @param hash the hash function to use
|
|
* @param salt_size the size of the salt to use in bytes
|
|
*/
|
|
PSSR(HashFunction* hash, size_t salt_size);
|
|
|
|
EMSA* clone() override;
|
|
|
|
std::string name() const override;
|
|
|
|
AlgorithmIdentifier config_for_x509(const Private_Key& key,
|
|
const std::string& cert_hash_name) const override;
|
|
private:
|
|
void update(const uint8_t input[], size_t length) override;
|
|
|
|
secure_vector<uint8_t> raw_data() override;
|
|
|
|
secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator& rng) override;
|
|
|
|
bool verify(const secure_vector<uint8_t>& coded,
|
|
const secure_vector<uint8_t>& raw,
|
|
size_t key_bits) override;
|
|
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
size_t m_salt_size;
|
|
bool m_required_salt_len;
|
|
};
|
|
|
|
/**
|
|
* PSSR_Raw
|
|
* This accepts a pre-hashed buffer
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,3) PSSR_Raw final : public EMSA
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* @param hash the hash function to use
|
|
*/
|
|
explicit PSSR_Raw(HashFunction* hash);
|
|
|
|
/**
|
|
* @param hash the hash function to use
|
|
* @param salt_size the size of the salt to use in bytes
|
|
*/
|
|
PSSR_Raw(HashFunction* hash, size_t salt_size);
|
|
|
|
EMSA* clone() override;
|
|
|
|
std::string name() const override;
|
|
private:
|
|
void update(const uint8_t input[], size_t length) override;
|
|
|
|
secure_vector<uint8_t> raw_data() override;
|
|
|
|
secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
|
|
size_t output_bits,
|
|
RandomNumberGenerator& rng) override;
|
|
|
|
bool verify(const secure_vector<uint8_t>& coded,
|
|
const secure_vector<uint8_t>& raw,
|
|
size_t key_bits) override;
|
|
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
secure_vector<uint8_t> m_msg;
|
|
size_t m_salt_size;
|
|
bool m_required_salt_len;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(rc4.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* RC4 stream cipher
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) RC4 final : public StreamCipher
|
|
{
|
|
public:
|
|
void cipher(const uint8_t in[], uint8_t out[], size_t length) override;
|
|
|
|
void set_iv(const uint8_t iv[], size_t iv_len) override;
|
|
|
|
void clear() override;
|
|
std::string name() const override;
|
|
|
|
StreamCipher* clone() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
/**
|
|
* @param skip skip this many initial bytes in the keystream
|
|
*/
|
|
explicit RC4(size_t skip = 0);
|
|
|
|
~RC4() { clear(); }
|
|
|
|
void seek(uint64_t offset) override;
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
void generate();
|
|
|
|
const size_t m_SKIP;
|
|
uint8_t m_X = 0;
|
|
uint8_t m_Y = 0;
|
|
secure_vector<uint8_t> m_state;
|
|
secure_vector<uint8_t> m_buffer;
|
|
size_t m_position = 0;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class BOTAN_PUBLIC_API(2,0) RDRAND_RNG final : public Hardware_RNG
|
|
{
|
|
public:
|
|
/**
|
|
* Constructor will throw if CPU does not have RDRAND bit set
|
|
*/
|
|
BOTAN_DEPRECATED("Use Processor_RNG instead") RDRAND_RNG();
|
|
|
|
/**
|
|
* Return true if RDRAND is available on the current processor
|
|
*/
|
|
static bool available();
|
|
|
|
bool accepts_input() const override { return false; }
|
|
|
|
/**
|
|
* Uses RDRAND to produce output
|
|
*/
|
|
void randomize(uint8_t out[], size_t out_len) override;
|
|
|
|
/*
|
|
* No way to provide entropy to RDRAND generator, so add_entropy is ignored
|
|
*/
|
|
void add_entropy(const uint8_t[], size_t) override
|
|
{ /* no op */ }
|
|
|
|
/*
|
|
* No way to reseed RDRAND generator, so reseed is ignored
|
|
*/
|
|
size_t reseed(Entropy_Sources&, size_t, std::chrono::milliseconds) override
|
|
{ return 0; /* no op */ }
|
|
|
|
std::string name() const override { return "RDRAND"; }
|
|
|
|
bool is_seeded() const override { return true; }
|
|
|
|
/**
|
|
* On correctly working hardware, RDRAND is always supposed to
|
|
* succeed within a set number of retries. If after that many
|
|
* retries RDRAND has still not suceeded, sets ok = false and
|
|
* returns 0.
|
|
*/
|
|
static uint32_t BOTAN_DEPRECATED("Use Processor_RNG::randomize") rdrand_status(bool& ok);
|
|
|
|
/*
|
|
* Calls RDRAND until it succeeds, this could hypothetically
|
|
* loop forever on broken hardware.
|
|
*/
|
|
static uint32_t BOTAN_DEPRECATED("Use Processor_RNG::randomize") rdrand();
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Encrypt a key under a key encryption key using the algorithm
|
|
* described in RFC 3394
|
|
*
|
|
* @param key the plaintext key to encrypt
|
|
* @param kek the key encryption key
|
|
* @return key encrypted under kek
|
|
*/
|
|
secure_vector<uint8_t> BOTAN_PUBLIC_API(2,0) rfc3394_keywrap(const secure_vector<uint8_t>& key,
|
|
const SymmetricKey& kek);
|
|
|
|
/**
|
|
* Decrypt a key under a key encryption key using the algorithm
|
|
* described in RFC 3394
|
|
*
|
|
* @param key the encrypted key to decrypt
|
|
* @param kek the key encryption key
|
|
* @return key decrypted under kek
|
|
*/
|
|
secure_vector<uint8_t> BOTAN_PUBLIC_API(2,0) rfc3394_keyunwrap(const secure_vector<uint8_t>& key,
|
|
const SymmetricKey& kek);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(rfc6979.h)
|
|
|
|
namespace Botan {
|
|
|
|
class HMAC_DRBG;
|
|
|
|
class BOTAN_PUBLIC_API(2,0) RFC6979_Nonce_Generator final
|
|
{
|
|
public:
|
|
/**
|
|
* Note: keeps persistent reference to order
|
|
*/
|
|
RFC6979_Nonce_Generator(const std::string& hash,
|
|
const BigInt& order,
|
|
const BigInt& x);
|
|
|
|
~RFC6979_Nonce_Generator();
|
|
|
|
const BigInt& nonce_for(const BigInt& m);
|
|
private:
|
|
const BigInt& m_order;
|
|
BigInt m_k;
|
|
size_t m_qlen, m_rlen;
|
|
std::unique_ptr<HMAC_DRBG> m_hmac_drbg;
|
|
secure_vector<uint8_t> m_rng_in, m_rng_out;
|
|
};
|
|
|
|
/**
|
|
* @param x the secret (EC)DSA key
|
|
* @param q the group order
|
|
* @param h the message hash already reduced mod q
|
|
* @param hash the hash function used to generate h
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0) generate_rfc6979_nonce(const BigInt& x,
|
|
const BigInt& q,
|
|
const BigInt& h,
|
|
const std::string& hash);
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(rmd160.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* RIPEMD-160
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) RIPEMD_160 final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "RIPEMD-160"; }
|
|
size_t output_length() const override { return 20; }
|
|
HashFunction* clone() const override { return new RIPEMD_160; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override;
|
|
|
|
RIPEMD_160() : MDx_HashFunction(64, false, true), m_M(16), m_digest(5)
|
|
{ clear(); }
|
|
private:
|
|
void compress_n(const uint8_t[], size_t blocks) override;
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
secure_vector<uint32_t> m_M, m_digest;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(rotate.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Bit rotation left by a compile-time constant amount
|
|
* @param input the input word
|
|
* @return input rotated left by ROT bits
|
|
*/
|
|
template<size_t ROT, typename T>
|
|
inline constexpr T rotl(T input)
|
|
{
|
|
static_assert(ROT > 0 && ROT < 8*sizeof(T), "Invalid rotation constant");
|
|
return static_cast<T>((input << ROT) | (input >> (8*sizeof(T) - ROT)));
|
|
}
|
|
|
|
/**
|
|
* Bit rotation right by a compile-time constant amount
|
|
* @param input the input word
|
|
* @return input rotated right by ROT bits
|
|
*/
|
|
template<size_t ROT, typename T>
|
|
inline constexpr T rotr(T input)
|
|
{
|
|
static_assert(ROT > 0 && ROT < 8*sizeof(T), "Invalid rotation constant");
|
|
return static_cast<T>((input >> ROT) | (input << (8*sizeof(T) - ROT)));
|
|
}
|
|
|
|
/**
|
|
* Bit rotation left, variable rotation amount
|
|
* @param input the input word
|
|
* @param rot the number of bits to rotate, must be between 0 and sizeof(T)*8-1
|
|
* @return input rotated left by rot bits
|
|
*/
|
|
template<typename T>
|
|
inline T rotl_var(T input, size_t rot)
|
|
{
|
|
return rot ? static_cast<T>((input << rot) | (input >> (sizeof(T)*8 - rot))) : input;
|
|
}
|
|
|
|
/**
|
|
* Bit rotation right, variable rotation amount
|
|
* @param input the input word
|
|
* @param rot the number of bits to rotate, must be between 0 and sizeof(T)*8-1
|
|
* @return input rotated right by rot bits
|
|
*/
|
|
template<typename T>
|
|
inline T rotr_var(T input, size_t rot)
|
|
{
|
|
return rot ? static_cast<T>((input >> rot) | (input << (sizeof(T)*8 - rot))) : input;
|
|
}
|
|
|
|
#if defined(BOTAN_USE_GCC_INLINE_ASM)
|
|
|
|
#if defined(BOTAN_TARGET_ARCH_IS_X86_64) || defined(BOTAN_TARGET_ARCH_IS_X86_32)
|
|
|
|
template<>
|
|
inline uint32_t rotl_var(uint32_t input, size_t rot)
|
|
{
|
|
asm("roll %1,%0"
|
|
: "+r" (input)
|
|
: "c" (static_cast<uint8_t>(rot))
|
|
: "cc");
|
|
return input;
|
|
}
|
|
|
|
template<>
|
|
inline uint32_t rotr_var(uint32_t input, size_t rot)
|
|
{
|
|
asm("rorl %1,%0"
|
|
: "+r" (input)
|
|
: "c" (static_cast<uint8_t>(rot))
|
|
: "cc");
|
|
return input;
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
template<typename T>
|
|
BOTAN_DEPRECATED("Use rotl<N> or rotl_var")
|
|
inline T rotate_left(T input, size_t rot)
|
|
{
|
|
// rotl_var does not reduce
|
|
return rotl_var(input, rot % (8 * sizeof(T)));
|
|
}
|
|
|
|
template<typename T>
|
|
BOTAN_DEPRECATED("Use rotr<N> or rotr_var")
|
|
inline T rotate_right(T input, size_t rot)
|
|
{
|
|
// rotr_var does not reduce
|
|
return rotr_var(input, rot % (8 * sizeof(T)));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
namespace Roughtime {
|
|
|
|
const unsigned request_min_size = 1024;
|
|
|
|
class BOTAN_PUBLIC_API(2, 13) Roughtime_Error final : public Decoding_Error
|
|
{
|
|
public:
|
|
explicit Roughtime_Error(const std::string& s) : Decoding_Error("Roughtime " + s) {}
|
|
ErrorType error_type() const noexcept override { return ErrorType::RoughtimeError; }
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2, 13) Nonce final
|
|
{
|
|
public:
|
|
Nonce() = default;
|
|
Nonce(const std::vector<uint8_t>& nonce);
|
|
Nonce(RandomNumberGenerator& rng);
|
|
Nonce(const std::array<uint8_t, 64>& nonce)
|
|
{
|
|
m_nonce = nonce;
|
|
}
|
|
bool operator==(const Nonce& rhs) const { return m_nonce == rhs.m_nonce; }
|
|
const std::array<uint8_t, 64>& get_nonce() const { return m_nonce; }
|
|
private:
|
|
std::array<uint8_t, 64> m_nonce;
|
|
};
|
|
|
|
|
|
/**
|
|
* An Roughtime request.
|
|
*/
|
|
BOTAN_PUBLIC_API(2, 13)
|
|
std::array<uint8_t, request_min_size> encode_request(const Nonce& nonce);
|
|
|
|
/**
|
|
* An Roughtime response.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2, 13) Response final
|
|
{
|
|
public:
|
|
using microseconds32 = std::chrono::duration<uint32_t, std::micro>;
|
|
using microseconds64 = std::chrono::duration<uint64_t, std::micro>;
|
|
using sys_microseconds64 = std::chrono::time_point<std::chrono::system_clock, microseconds64>;
|
|
|
|
static Response from_bits(const std::vector<uint8_t>& response, const Nonce& nonce);
|
|
|
|
bool validate(const Ed25519_PublicKey& pk) const;
|
|
|
|
sys_microseconds64 utc_midpoint() const { return m_utc_midpoint; }
|
|
|
|
microseconds32 utc_radius() const { return m_utc_radius; }
|
|
private:
|
|
Response(const std::array<uint8_t, 72>& dele,
|
|
const std::array<uint8_t, 64>& sig,
|
|
sys_microseconds64 utc_midp,
|
|
microseconds32 utc_radius)
|
|
: m_cert_dele(dele)
|
|
, m_cert_sig(sig)
|
|
, m_utc_midpoint {utc_midp}
|
|
, m_utc_radius {utc_radius}
|
|
{}
|
|
const std::array<uint8_t, 72> m_cert_dele;
|
|
const std::array<uint8_t, 64> m_cert_sig;
|
|
const sys_microseconds64 m_utc_midpoint;
|
|
const microseconds32 m_utc_radius;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2, 13) Link final
|
|
{
|
|
public:
|
|
Link(const std::vector<uint8_t>& response,
|
|
const Ed25519_PublicKey& public_key,
|
|
const Nonce& nonce_or_blind)
|
|
: m_response{response}
|
|
, m_public_key{public_key}
|
|
, m_nonce_or_blind{nonce_or_blind}
|
|
{}
|
|
const std::vector<uint8_t>& response() const { return m_response; }
|
|
const Ed25519_PublicKey& public_key() const { return m_public_key; }
|
|
const Nonce& nonce_or_blind() const { return m_nonce_or_blind; }
|
|
Nonce& nonce_or_blind() { return m_nonce_or_blind; }
|
|
|
|
private:
|
|
std::vector<uint8_t> m_response;
|
|
Ed25519_PublicKey m_public_key;
|
|
Nonce m_nonce_or_blind;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2, 13) Chain final
|
|
{
|
|
public:
|
|
Chain() = default; //empty
|
|
Chain(const std::string& str);
|
|
const std::vector<Link>& links() const { return m_links; }
|
|
std::vector<Response> responses() const;
|
|
Nonce next_nonce(const Nonce& blind) const;
|
|
void append(const Link& new_link, size_t max_chain_size);
|
|
std::string to_string() const;
|
|
private:
|
|
std::vector<Link> m_links;
|
|
};
|
|
|
|
/**
|
|
*/
|
|
BOTAN_PUBLIC_API(2, 13)
|
|
Nonce nonce_from_blind(const std::vector<uint8_t>& previous_response,
|
|
const Nonce& blind);
|
|
|
|
/**
|
|
* Makes an online Roughtime request via UDP and returns the Roughtime response.
|
|
* @param url Roughtime server UDP endpoint (host:port)
|
|
* @param nonce the nonce to send to the server
|
|
* @param timeout a timeout on the UDP request
|
|
* @return Roughtime response
|
|
*/
|
|
BOTAN_PUBLIC_API(2, 13)
|
|
std::vector<uint8_t> online_request(const std::string& url,
|
|
const Nonce& nonce,
|
|
std::chrono::milliseconds timeout = std::chrono::seconds(3));
|
|
|
|
struct BOTAN_PUBLIC_API(2, 13) Server_Information final
|
|
{
|
|
public:
|
|
Server_Information(const std::string& name,
|
|
const Botan::Ed25519_PublicKey& public_key,
|
|
const std::vector<std::string>& addresses)
|
|
: m_name { name }
|
|
, m_public_key { public_key }
|
|
, m_addresses { addresses }
|
|
{}
|
|
const std::string& name() const {return m_name;}
|
|
const Botan::Ed25519_PublicKey& public_key() const {return m_public_key;}
|
|
const std::vector<std::string>& addresses() const {return m_addresses;}
|
|
|
|
private:
|
|
std::string m_name;
|
|
Botan::Ed25519_PublicKey m_public_key;
|
|
std::vector<std::string> m_addresses;
|
|
};
|
|
|
|
BOTAN_PUBLIC_API(2, 13)
|
|
std::vector<Server_Information> servers_from_str(const std::string& str);
|
|
|
|
}
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(salsa20.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* DJB's Salsa20 (and XSalsa20)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Salsa20 final : public StreamCipher
|
|
{
|
|
public:
|
|
void cipher(const uint8_t in[], uint8_t out[], size_t length) override;
|
|
|
|
void set_iv(const uint8_t iv[], size_t iv_len) override;
|
|
|
|
bool valid_iv_length(size_t iv_len) const override;
|
|
|
|
size_t default_iv_length() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override;
|
|
StreamCipher* clone() const override;
|
|
|
|
static void salsa_core(uint8_t output[64], const uint32_t input[16], size_t rounds);
|
|
static void hsalsa20(uint32_t output[8], const uint32_t input[16]);
|
|
|
|
void seek(uint64_t offset) override;
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t key_len) override;
|
|
|
|
void initialize_state();
|
|
|
|
secure_vector<uint32_t> m_key;
|
|
secure_vector<uint32_t> m_state;
|
|
secure_vector<uint8_t> m_buffer;
|
|
size_t m_position = 0;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(scan_name.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
A class encapsulating a SCAN name (similar to JCE conventions)
|
|
http://www.users.zetnet.co.uk/hopwood/crypto/scan/
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SCAN_Name final
|
|
{
|
|
public:
|
|
/**
|
|
* Create a SCAN_Name
|
|
* @param algo_spec A SCAN-format name
|
|
*/
|
|
explicit SCAN_Name(const char* algo_spec);
|
|
|
|
/**
|
|
* Create a SCAN_Name
|
|
* @param algo_spec A SCAN-format name
|
|
*/
|
|
explicit SCAN_Name(std::string algo_spec);
|
|
|
|
/**
|
|
* @return original input string
|
|
*/
|
|
const std::string& to_string() const { return m_orig_algo_spec; }
|
|
|
|
BOTAN_DEPRECATED("Use SCAN_Name::to_string") const std::string& as_string() const
|
|
{
|
|
return this->to_string();
|
|
}
|
|
|
|
/**
|
|
* @return algorithm name
|
|
*/
|
|
const std::string& algo_name() const { return m_alg_name; }
|
|
|
|
/**
|
|
* @return number of arguments
|
|
*/
|
|
size_t arg_count() const { return m_args.size(); }
|
|
|
|
/**
|
|
* @param lower is the lower bound
|
|
* @param upper is the upper bound
|
|
* @return if the number of arguments is between lower and upper
|
|
*/
|
|
bool arg_count_between(size_t lower, size_t upper) const
|
|
{ return ((arg_count() >= lower) && (arg_count() <= upper)); }
|
|
|
|
/**
|
|
* @param i which argument
|
|
* @return ith argument
|
|
*/
|
|
std::string arg(size_t i) const;
|
|
|
|
/**
|
|
* @param i which argument
|
|
* @param def_value the default value
|
|
* @return ith argument or the default value
|
|
*/
|
|
std::string arg(size_t i, const std::string& def_value) const;
|
|
|
|
/**
|
|
* @param i which argument
|
|
* @param def_value the default value
|
|
* @return ith argument as an integer, or the default value
|
|
*/
|
|
size_t arg_as_integer(size_t i, size_t def_value) const;
|
|
|
|
/**
|
|
* @return cipher mode (if any)
|
|
*/
|
|
std::string cipher_mode() const
|
|
{ return (m_mode_info.size() >= 1) ? m_mode_info[0] : ""; }
|
|
|
|
/**
|
|
* @return cipher mode padding (if any)
|
|
*/
|
|
std::string cipher_mode_pad() const
|
|
{ return (m_mode_info.size() >= 2) ? m_mode_info[1] : ""; }
|
|
|
|
private:
|
|
std::string m_orig_algo_spec;
|
|
std::string m_alg_name;
|
|
std::vector<std::string> m_args;
|
|
std::vector<std::string> m_mode_info;
|
|
};
|
|
|
|
// This is unrelated but it is convenient to stash it here
|
|
template<typename T>
|
|
std::vector<std::string> probe_providers_of(const std::string& algo_spec,
|
|
const std::vector<std::string>& possible)
|
|
{
|
|
std::vector<std::string> providers;
|
|
for(auto&& prov : possible)
|
|
{
|
|
std::unique_ptr<T> o(T::create(algo_spec, prov));
|
|
if(o)
|
|
{
|
|
providers.push_back(prov); // available
|
|
}
|
|
}
|
|
return providers;
|
|
}
|
|
|
|
}
|
|
|
|
//BOTAN_FUTURE_INTERNAL_HEADER(scrypt.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Scrypt key derivation function (RFC 7914)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,8) Scrypt final : public PasswordHash
|
|
{
|
|
public:
|
|
Scrypt(size_t N, size_t r, size_t p);
|
|
|
|
Scrypt(const Scrypt& other) = default;
|
|
Scrypt& operator=(const Scrypt&) = default;
|
|
|
|
/**
|
|
* Derive a new key under the current Scrypt parameter set
|
|
*/
|
|
void derive_key(uint8_t out[], size_t out_len,
|
|
const char* password, size_t password_len,
|
|
const uint8_t salt[], size_t salt_len) const override;
|
|
|
|
std::string to_string() const override;
|
|
|
|
size_t N() const { return m_N; }
|
|
size_t r() const { return m_r; }
|
|
size_t p() const { return m_p; }
|
|
|
|
size_t iterations() const override { return r(); }
|
|
|
|
size_t parallelism() const override { return p(); }
|
|
|
|
size_t memory_param() const override { return N(); }
|
|
|
|
size_t total_memory_usage() const override;
|
|
|
|
private:
|
|
size_t m_N, m_r, m_p;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,8) Scrypt_Family final : public PasswordHashFamily
|
|
{
|
|
public:
|
|
std::string name() const override;
|
|
|
|
std::unique_ptr<PasswordHash> tune(size_t output_length,
|
|
std::chrono::milliseconds msec,
|
|
size_t max_memory) const override;
|
|
|
|
std::unique_ptr<PasswordHash> default_params() const override;
|
|
|
|
std::unique_ptr<PasswordHash> from_iterations(size_t iter) const override;
|
|
|
|
std::unique_ptr<PasswordHash> from_params(
|
|
size_t N, size_t r, size_t p) const override;
|
|
};
|
|
|
|
/**
|
|
* Scrypt key derivation function (RFC 7914)
|
|
*
|
|
* @param output the output will be placed here
|
|
* @param output_len length of output
|
|
* @param password the user password
|
|
* @param password_len length of password
|
|
* @param salt the salt
|
|
* @param salt_len length of salt
|
|
* @param N the CPU/Memory cost parameter, must be power of 2
|
|
* @param r the block size parameter
|
|
* @param p the parallelization parameter
|
|
*
|
|
* Suitable parameters for most uses would be N = 32768, r = 8, p = 1
|
|
*
|
|
* Scrypt uses approximately (p + N + 1) * 128 * r bytes of memory
|
|
*/
|
|
void BOTAN_PUBLIC_API(2,8) scrypt(uint8_t output[], size_t output_len,
|
|
const char* password, size_t password_len,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t N, size_t r, size_t p);
|
|
|
|
/**
|
|
* Scrypt key derivation function (RFC 7914)
|
|
* Before 2.8 this function was the primary interface for scrypt
|
|
*
|
|
* @param output the output will be placed here
|
|
* @param output_len length of output
|
|
* @param password the user password
|
|
* @param salt the salt
|
|
* @param salt_len length of salt
|
|
* @param N the CPU/Memory cost parameter, must be power of 2
|
|
* @param r the block size parameter
|
|
* @param p the parallelization parameter
|
|
*
|
|
* Suitable parameters for most uses would be N = 32768, r = 8, p = 1
|
|
*
|
|
* Scrypt uses approximately (p + N + 1) * 128 * r bytes of memory
|
|
*/
|
|
inline void scrypt(uint8_t output[], size_t output_len,
|
|
const std::string& password,
|
|
const uint8_t salt[], size_t salt_len,
|
|
size_t N, size_t r, size_t p)
|
|
{
|
|
return scrypt(output, output_len,
|
|
password.c_str(), password.size(),
|
|
salt, salt_len,
|
|
N, r, p);
|
|
}
|
|
|
|
inline size_t scrypt_memory_usage(size_t N, size_t r, size_t p)
|
|
{
|
|
return 128 * r * (N + p);
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(secqueue.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* A queue that knows how to zeroize itself
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SecureQueue final : public Fanout_Filter, public DataSource
|
|
{
|
|
public:
|
|
std::string name() const override { return "Queue"; }
|
|
|
|
void write(const uint8_t[], size_t) override;
|
|
|
|
size_t read(uint8_t[], size_t) override;
|
|
size_t peek(uint8_t[], size_t, size_t = 0) const override;
|
|
size_t get_bytes_read() const override;
|
|
|
|
bool end_of_data() const override;
|
|
|
|
bool empty() const;
|
|
|
|
bool check_available(size_t n) override { return n <= size(); }
|
|
|
|
/**
|
|
* @return number of bytes available in the queue
|
|
*/
|
|
size_t size() const;
|
|
|
|
bool attachable() override { return false; }
|
|
|
|
/**
|
|
* SecureQueue assignment
|
|
* @param other the queue to copy
|
|
*/
|
|
SecureQueue& operator=(const SecureQueue& other);
|
|
|
|
/**
|
|
* SecureQueue default constructor (creates empty queue)
|
|
*/
|
|
SecureQueue();
|
|
|
|
/**
|
|
* SecureQueue copy constructor
|
|
* @param other the queue to copy
|
|
*/
|
|
SecureQueue(const SecureQueue& other);
|
|
|
|
~SecureQueue() { destroy(); }
|
|
|
|
private:
|
|
void destroy();
|
|
size_t m_bytes_read;
|
|
class SecureQueueNode* m_head;
|
|
class SecureQueueNode* m_tail;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(seed.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* SEED, a Korean block cipher
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SEED final : public Block_Cipher_Fixed_Params<16, 16>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "SEED"; }
|
|
BlockCipher* clone() const override { return new SEED; }
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
secure_vector<uint32_t> m_K;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(serpent.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Serpent is the most conservative of the AES finalists
|
|
* https://www.cl.cam.ac.uk/~rja14/serpent.html
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Serpent final : public Block_Cipher_Fixed_Params<16, 16, 32, 8>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string provider() const override;
|
|
std::string name() const override { return "Serpent"; }
|
|
BlockCipher* clone() const override { return new Serpent; }
|
|
|
|
size_t parallelism() const override { return 4; }
|
|
|
|
private:
|
|
|
|
#if defined(BOTAN_HAS_SERPENT_SIMD)
|
|
void simd_encrypt_4(const uint8_t in[64], uint8_t out[64]) const;
|
|
void simd_decrypt_4(const uint8_t in[64], uint8_t out[64]) const;
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_SERPENT_AVX2)
|
|
void avx2_encrypt_8(const uint8_t in[64], uint8_t out[64]) const;
|
|
void avx2_decrypt_8(const uint8_t in[64], uint8_t out[64]) const;
|
|
#endif
|
|
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
secure_vector<uint32_t> m_round_key;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(sha160.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* NIST's SHA-160
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHA_160 final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "SHA-160"; }
|
|
size_t output_length() const override { return 20; }
|
|
HashFunction* clone() const override { return new SHA_160; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override;
|
|
|
|
SHA_160() : MDx_HashFunction(64, true, true), m_digest(5)
|
|
{
|
|
clear();
|
|
}
|
|
|
|
private:
|
|
void compress_n(const uint8_t[], size_t blocks) override;
|
|
|
|
#if defined(BOTAN_HAS_SHA1_ARMV8)
|
|
static void sha1_armv8_compress_n(secure_vector<uint32_t>& digest,
|
|
const uint8_t blocks[],
|
|
size_t block_count);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_SHA1_SSE2)
|
|
static void sse2_compress_n(secure_vector<uint32_t>& digest,
|
|
const uint8_t blocks[],
|
|
size_t block_count);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_SHA1_X86_SHA_NI)
|
|
// Using x86 SHA instructions in Intel Goldmont and Cannonlake
|
|
static void sha1_compress_x86(secure_vector<uint32_t>& digest,
|
|
const uint8_t blocks[],
|
|
size_t block_count);
|
|
#endif
|
|
|
|
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
/**
|
|
* The digest value
|
|
*/
|
|
secure_vector<uint32_t> m_digest;
|
|
|
|
/**
|
|
* The message buffer
|
|
*/
|
|
secure_vector<uint32_t> m_W;
|
|
};
|
|
|
|
typedef SHA_160 SHA_1;
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(sha2_32.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* SHA-224
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHA_224 final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "SHA-224"; }
|
|
size_t output_length() const override { return 28; }
|
|
HashFunction* clone() const override { return new SHA_224; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override;
|
|
|
|
std::string provider() const override;
|
|
|
|
SHA_224() : MDx_HashFunction(64, true, true), m_digest(8)
|
|
{ clear(); }
|
|
private:
|
|
void compress_n(const uint8_t[], size_t blocks) override;
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
secure_vector<uint32_t> m_digest;
|
|
};
|
|
|
|
/**
|
|
* SHA-256
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHA_256 final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "SHA-256"; }
|
|
size_t output_length() const override { return 32; }
|
|
HashFunction* clone() const override { return new SHA_256; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override;
|
|
|
|
std::string provider() const override;
|
|
|
|
SHA_256() : MDx_HashFunction(64, true, true), m_digest(8)
|
|
{ clear(); }
|
|
|
|
/*
|
|
* Perform a SHA-256 compression. For internal use
|
|
*/
|
|
static void compress_digest(secure_vector<uint32_t>& digest,
|
|
const uint8_t input[],
|
|
size_t blocks);
|
|
|
|
private:
|
|
|
|
#if defined(BOTAN_HAS_SHA2_32_ARMV8)
|
|
static void compress_digest_armv8(secure_vector<uint32_t>& digest,
|
|
const uint8_t input[],
|
|
size_t blocks);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_SHA2_32_X86_BMI2)
|
|
static void compress_digest_x86_bmi2(secure_vector<uint32_t>& digest,
|
|
const uint8_t input[],
|
|
size_t blocks);
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_SHA2_32_X86)
|
|
static void compress_digest_x86(secure_vector<uint32_t>& digest,
|
|
const uint8_t input[],
|
|
size_t blocks);
|
|
#endif
|
|
|
|
void compress_n(const uint8_t[], size_t blocks) override;
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
secure_vector<uint32_t> m_digest;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(sha2_64.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* SHA-384
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHA_384 final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "SHA-384"; }
|
|
size_t output_length() const override { return 48; }
|
|
HashFunction* clone() const override { return new SHA_384; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
std::string provider() const override;
|
|
|
|
void clear() override;
|
|
|
|
SHA_384() : MDx_HashFunction(128, true, true, 16), m_digest(8)
|
|
{ clear(); }
|
|
private:
|
|
void compress_n(const uint8_t[], size_t blocks) override;
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
secure_vector<uint64_t> m_digest;
|
|
};
|
|
|
|
/**
|
|
* SHA-512
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHA_512 final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "SHA-512"; }
|
|
size_t output_length() const override { return 64; }
|
|
HashFunction* clone() const override { return new SHA_512; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
std::string provider() const override;
|
|
|
|
void clear() override;
|
|
|
|
/*
|
|
* Perform a SHA-512 compression. For internal use
|
|
*/
|
|
static void compress_digest(secure_vector<uint64_t>& digest,
|
|
const uint8_t input[],
|
|
size_t blocks);
|
|
|
|
SHA_512() : MDx_HashFunction(128, true, true, 16), m_digest(8)
|
|
{ clear(); }
|
|
private:
|
|
void compress_n(const uint8_t[], size_t blocks) override;
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
static const uint64_t K[80];
|
|
|
|
#if defined(BOTAN_HAS_SHA2_64_BMI2)
|
|
static void compress_digest_bmi2(secure_vector<uint64_t>& digest,
|
|
const uint8_t input[],
|
|
size_t blocks);
|
|
#endif
|
|
|
|
secure_vector<uint64_t> m_digest;
|
|
};
|
|
|
|
/**
|
|
* SHA-512/256
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHA_512_256 final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "SHA-512-256"; }
|
|
size_t output_length() const override { return 32; }
|
|
HashFunction* clone() const override { return new SHA_512_256; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
std::string provider() const override;
|
|
|
|
void clear() override;
|
|
|
|
SHA_512_256() : MDx_HashFunction(128, true, true, 16), m_digest(8) { clear(); }
|
|
private:
|
|
void compress_n(const uint8_t[], size_t blocks) override;
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
secure_vector<uint64_t> m_digest;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(sha3.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* SHA-3
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHA_3 : public HashFunction
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* @param output_bits the size of the hash output; must be one of
|
|
* 224, 256, 384, or 512
|
|
*/
|
|
explicit SHA_3(size_t output_bits);
|
|
|
|
size_t hash_block_size() const override { return m_bitrate / 8; }
|
|
size_t output_length() const override { return m_output_bits / 8; }
|
|
|
|
HashFunction* clone() const override;
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
std::string name() const override;
|
|
void clear() override;
|
|
std::string provider() const override;
|
|
|
|
// Static functions for internal usage
|
|
|
|
/**
|
|
* Absorb data into the provided state
|
|
* @param bitrate the bitrate to absorb into the sponge
|
|
* @param S the sponge state
|
|
* @param S_pos where to begin absorbing into S
|
|
* @param input the input data
|
|
* @param length size of input in bytes
|
|
*/
|
|
static size_t absorb(size_t bitrate,
|
|
secure_vector<uint64_t>& S, size_t S_pos,
|
|
const uint8_t input[], size_t length);
|
|
|
|
/**
|
|
* Add final padding and permute. The padding is assumed to be
|
|
* init_pad || 00... || fini_pad
|
|
*
|
|
* @param bitrate the bitrate to absorb into the sponge
|
|
* @param S the sponge state
|
|
* @param S_pos where to begin absorbing into S
|
|
* @param init_pad the leading pad bits
|
|
* @param fini_pad the final pad bits
|
|
*/
|
|
static void finish(size_t bitrate,
|
|
secure_vector<uint64_t>& S, size_t S_pos,
|
|
uint8_t init_pad, uint8_t fini_pad);
|
|
|
|
/**
|
|
* Expand from provided state
|
|
* @param bitrate sponge parameter
|
|
* @param S the state
|
|
* @param output the output buffer
|
|
* @param output_length the size of output in bytes
|
|
*/
|
|
static void expand(size_t bitrate,
|
|
secure_vector<uint64_t>& S,
|
|
uint8_t output[], size_t output_length);
|
|
|
|
/**
|
|
* The bare Keccak-1600 permutation
|
|
*/
|
|
static void permute(uint64_t A[25]);
|
|
|
|
private:
|
|
void add_data(const uint8_t input[], size_t length) override;
|
|
void final_result(uint8_t out[]) override;
|
|
|
|
#if defined(BOTAN_HAS_SHA3_BMI2)
|
|
static void permute_bmi2(uint64_t A[25]);
|
|
#endif
|
|
|
|
size_t m_output_bits, m_bitrate;
|
|
secure_vector<uint64_t> m_S;
|
|
size_t m_S_pos;
|
|
};
|
|
|
|
/**
|
|
* SHA-3-224
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHA_3_224 final : public SHA_3
|
|
{
|
|
public:
|
|
SHA_3_224() : SHA_3(224) {}
|
|
};
|
|
|
|
/**
|
|
* SHA-3-256
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHA_3_256 final : public SHA_3
|
|
{
|
|
public:
|
|
SHA_3_256() : SHA_3(256) {}
|
|
};
|
|
|
|
/**
|
|
* SHA-3-384
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHA_3_384 final : public SHA_3
|
|
{
|
|
public:
|
|
SHA_3_384() : SHA_3(384) {}
|
|
};
|
|
|
|
/**
|
|
* SHA-3-512
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHA_3_512 final : public SHA_3
|
|
{
|
|
public:
|
|
SHA_3_512() : SHA_3(512) {}
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(shacal2.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* SHACAL2
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,3) SHACAL2 final : public Block_Cipher_Fixed_Params<32, 16, 64, 4>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
std::string provider() const override;
|
|
void clear() override;
|
|
std::string name() const override { return "SHACAL2"; }
|
|
BlockCipher* clone() const override { return new SHACAL2; }
|
|
size_t parallelism() const override;
|
|
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
#if defined(BOTAN_HAS_SHACAL2_SIMD)
|
|
void simd_encrypt_4(const uint8_t in[], uint8_t out[]) const;
|
|
void simd_decrypt_4(const uint8_t in[], uint8_t out[]) const;
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_SHACAL2_AVX2)
|
|
void avx2_encrypt_8(const uint8_t in[], uint8_t out[]) const;
|
|
void avx2_decrypt_8(const uint8_t in[], uint8_t out[]) const;
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_SHACAL2_X86)
|
|
void x86_encrypt_blocks(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
#endif
|
|
|
|
secure_vector<uint32_t> m_RK;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(shake.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* SHAKE-128
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHAKE_128 final : public HashFunction
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* @param output_bits the desired output size in bits
|
|
* must be a multiple of 8
|
|
*/
|
|
explicit SHAKE_128(size_t output_bits);
|
|
|
|
size_t hash_block_size() const override { return SHAKE_128_BITRATE / 8; }
|
|
size_t output_length() const override { return m_output_bits / 8; }
|
|
|
|
HashFunction* clone() const override;
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
std::string name() const override;
|
|
void clear() override;
|
|
|
|
private:
|
|
void add_data(const uint8_t input[], size_t length) override;
|
|
void final_result(uint8_t out[]) override;
|
|
|
|
static const size_t SHAKE_128_BITRATE = 1600 - 256;
|
|
|
|
size_t m_output_bits;
|
|
secure_vector<uint64_t> m_S;
|
|
size_t m_S_pos;
|
|
};
|
|
|
|
/**
|
|
* SHAKE-256
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHAKE_256 final : public HashFunction
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* @param output_bits the desired output size in bits
|
|
* must be a multiple of 8
|
|
*/
|
|
explicit SHAKE_256(size_t output_bits);
|
|
|
|
size_t hash_block_size() const override { return SHAKE_256_BITRATE / 8; }
|
|
size_t output_length() const override { return m_output_bits / 8; }
|
|
|
|
HashFunction* clone() const override;
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
std::string name() const override;
|
|
void clear() override;
|
|
|
|
private:
|
|
void add_data(const uint8_t input[], size_t length) override;
|
|
void final_result(uint8_t out[]) override;
|
|
|
|
static const size_t SHAKE_256_BITRATE = 1600 - 512;
|
|
|
|
size_t m_output_bits;
|
|
secure_vector<uint64_t> m_S;
|
|
size_t m_S_pos;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(shake_cipher.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* SHAKE-128 XOF presented as a stream cipher
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SHAKE_128_Cipher final : public StreamCipher
|
|
{
|
|
public:
|
|
SHAKE_128_Cipher();
|
|
|
|
/**
|
|
* Produce more XOF output
|
|
*/
|
|
void cipher(const uint8_t in[], uint8_t out[], size_t length) override;
|
|
|
|
/**
|
|
* Seeking is not supported, this function will throw
|
|
*/
|
|
void seek(uint64_t offset) override;
|
|
|
|
/**
|
|
* IV not supported, this function will throw unless iv_len == 0
|
|
*/
|
|
void set_iv(const uint8_t iv[], size_t iv_len) override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override;
|
|
StreamCipher* clone() const override;
|
|
|
|
private:
|
|
void key_schedule(const uint8_t key[], size_t key_len) override;
|
|
|
|
secure_vector<uint64_t> m_state; // internal state
|
|
secure_vector<uint8_t> m_buffer; // ciphertext buffer
|
|
size_t m_buf_pos; // position in m_buffer
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(siphash.h)
|
|
|
|
namespace Botan {
|
|
|
|
class BOTAN_PUBLIC_API(2,0) SipHash final : public MessageAuthenticationCode
|
|
{
|
|
public:
|
|
SipHash(size_t c = 2, size_t d = 4) : m_C(c), m_D(d) {}
|
|
|
|
void clear() override;
|
|
std::string name() const override;
|
|
|
|
MessageAuthenticationCode* clone() const override;
|
|
|
|
size_t output_length() const override { return 8; }
|
|
|
|
Key_Length_Specification key_spec() const override
|
|
{
|
|
return Key_Length_Specification(16);
|
|
}
|
|
private:
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
const size_t m_C, m_D;
|
|
secure_vector<uint64_t> m_V;
|
|
uint64_t m_mbuf = 0;
|
|
size_t m_mbuf_pos = 0;
|
|
uint8_t m_words = 0;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(siv.h)
|
|
|
|
namespace Botan {
|
|
|
|
class BlockCipher;
|
|
class MessageAuthenticationCode;
|
|
|
|
/**
|
|
* Base class for SIV encryption and decryption (@see RFC 5297)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SIV_Mode : public AEAD_Mode
|
|
{
|
|
public:
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
/**
|
|
* Sets the nth element of the vector of associated data
|
|
* @param n index into the AD vector
|
|
* @param ad associated data
|
|
* @param ad_len length of associated data in bytes
|
|
*/
|
|
void set_associated_data_n(size_t n, const uint8_t ad[], size_t ad_len) override;
|
|
|
|
size_t maximum_associated_data_inputs() const override;
|
|
|
|
void set_associated_data(const uint8_t ad[], size_t ad_len) override
|
|
{
|
|
set_associated_data_n(0, ad, ad_len);
|
|
}
|
|
|
|
std::string name() const override;
|
|
|
|
size_t update_granularity() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
bool valid_nonce_length(size_t) const override;
|
|
|
|
void clear() override;
|
|
|
|
void reset() override;
|
|
|
|
size_t tag_size() const override { return 16; }
|
|
|
|
~SIV_Mode();
|
|
|
|
protected:
|
|
explicit SIV_Mode(BlockCipher* cipher);
|
|
|
|
size_t block_size() const { return m_bs; }
|
|
|
|
StreamCipher& ctr() { return *m_ctr; }
|
|
|
|
void set_ctr_iv(secure_vector<uint8_t> V);
|
|
|
|
secure_vector<uint8_t>& msg_buf() { return m_msg_buf; }
|
|
|
|
secure_vector<uint8_t> S2V(const uint8_t text[], size_t text_len);
|
|
private:
|
|
void start_msg(const uint8_t nonce[], size_t nonce_len) override;
|
|
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
const std::string m_name;
|
|
std::unique_ptr<StreamCipher> m_ctr;
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
secure_vector<uint8_t> m_nonce, m_msg_buf;
|
|
std::vector<secure_vector<uint8_t>> m_ad_macs;
|
|
const size_t m_bs;
|
|
};
|
|
|
|
/**
|
|
* SIV Encryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SIV_Encryption final : public SIV_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher a block cipher
|
|
*/
|
|
explicit SIV_Encryption(BlockCipher* cipher) : SIV_Mode(cipher) {}
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
|
|
size_t output_length(size_t input_length) const override
|
|
{ return input_length + tag_size(); }
|
|
|
|
size_t minimum_final_size() const override { return 0; }
|
|
};
|
|
|
|
/**
|
|
* SIV Decryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SIV_Decryption final : public SIV_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher a 128-bit block cipher
|
|
*/
|
|
explicit SIV_Decryption(BlockCipher* cipher) : SIV_Mode(cipher) {}
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
|
|
size_t output_length(size_t input_length) const override
|
|
{
|
|
BOTAN_ASSERT(input_length >= tag_size(), "Sufficient input");
|
|
return input_length - tag_size();
|
|
}
|
|
|
|
size_t minimum_final_size() const override { return tag_size(); }
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(threefish_512.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Threefish-512
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Threefish_512 final :
|
|
public Block_Cipher_Fixed_Params<64, 64, 0, 1, Tweakable_Block_Cipher>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void set_tweak(const uint8_t tweak[], size_t len) override;
|
|
|
|
void clear() override;
|
|
std::string provider() const override;
|
|
std::string name() const override { return "Threefish-512"; }
|
|
BlockCipher* clone() const override { return new Threefish_512; }
|
|
size_t parallelism() const override;
|
|
|
|
private:
|
|
|
|
#if defined(BOTAN_HAS_THREEFISH_512_AVX2)
|
|
void avx2_encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
void avx2_decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
#endif
|
|
|
|
void key_schedule(const uint8_t key[], size_t key_len) override;
|
|
|
|
// Interface for Skein
|
|
friend class Skein_512;
|
|
|
|
void skein_feedfwd(const secure_vector<uint64_t>& M,
|
|
const secure_vector<uint64_t>& T);
|
|
|
|
// Private data
|
|
secure_vector<uint64_t> m_T;
|
|
secure_vector<uint64_t> m_K;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(skin_512.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Skein-512, a SHA-3 candidate
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Skein_512 final : public HashFunction
|
|
{
|
|
public:
|
|
/**
|
|
* @param output_bits the output size of Skein in bits
|
|
* @param personalization is a string that will parameterize the
|
|
* hash output
|
|
*/
|
|
Skein_512(size_t output_bits = 512,
|
|
const std::string& personalization = "");
|
|
|
|
size_t hash_block_size() const override { return 64; }
|
|
size_t output_length() const override { return m_output_bits / 8; }
|
|
|
|
HashFunction* clone() const override;
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
std::string name() const override;
|
|
void clear() override;
|
|
private:
|
|
enum type_code {
|
|
SKEIN_KEY = 0,
|
|
SKEIN_CONFIG = 4,
|
|
SKEIN_PERSONALIZATION = 8,
|
|
SKEIN_PUBLIC_KEY = 12,
|
|
SKEIN_KEY_IDENTIFIER = 16,
|
|
SKEIN_NONCE = 20,
|
|
SKEIN_MSG = 48,
|
|
SKEIN_OUTPUT = 63
|
|
};
|
|
|
|
void add_data(const uint8_t input[], size_t length) override;
|
|
void final_result(uint8_t out[]) override;
|
|
|
|
void ubi_512(const uint8_t msg[], size_t msg_len);
|
|
|
|
void initial_block();
|
|
void reset_tweak(type_code type, bool is_final);
|
|
|
|
std::string m_personalization;
|
|
size_t m_output_bits;
|
|
|
|
std::unique_ptr<Threefish_512> m_threefish;
|
|
secure_vector<uint64_t> m_T;
|
|
secure_vector<uint8_t> m_buffer;
|
|
size_t m_buf_pos;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This class represents SM2 public keys
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) SM2_PublicKey : public virtual EC_PublicKey
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Create a public key from a given public point.
|
|
* @param dom_par the domain parameters associated with this key
|
|
* @param public_point the public point defining this key
|
|
*/
|
|
SM2_PublicKey(const EC_Group& dom_par,
|
|
const PointGFp& public_point) :
|
|
EC_PublicKey(dom_par, public_point) {}
|
|
|
|
/**
|
|
* Load a public key.
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
SM2_PublicKey(const AlgorithmIdentifier& alg_id,
|
|
const std::vector<uint8_t>& key_bits) :
|
|
EC_PublicKey(alg_id, key_bits) {}
|
|
|
|
/**
|
|
* Get this keys algorithm name.
|
|
* @result this keys algorithm name
|
|
*/
|
|
std::string algo_name() const override;
|
|
|
|
size_t message_parts() const override { return 2; }
|
|
|
|
size_t message_part_size() const override
|
|
{ return domain().get_order().bytes(); }
|
|
|
|
std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Encryption>
|
|
create_encryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
protected:
|
|
SM2_PublicKey() = default;
|
|
};
|
|
|
|
/**
|
|
* This class represents SM2 private keys
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) SM2_PrivateKey final :
|
|
public SM2_PublicKey, public EC_PrivateKey
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Load a private key
|
|
* @param alg_id the X.509 algorithm identifier
|
|
* @param key_bits ECPrivateKey bits
|
|
*/
|
|
SM2_PrivateKey(const AlgorithmIdentifier& alg_id,
|
|
const secure_vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Create a private key.
|
|
* @param rng a random number generator
|
|
* @param domain parameters to used for this key
|
|
* @param x the private key (if zero, generate a new random key)
|
|
*/
|
|
SM2_PrivateKey(RandomNumberGenerator& rng,
|
|
const EC_Group& domain,
|
|
const BigInt& x = 0);
|
|
|
|
bool check_key(RandomNumberGenerator& rng, bool) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
std::unique_ptr<PK_Ops::Decryption>
|
|
create_decryption_op(RandomNumberGenerator& rng,
|
|
const std::string& params,
|
|
const std::string& provider) const override;
|
|
|
|
const BigInt& get_da_inv() const { return m_da_inv; }
|
|
private:
|
|
BigInt m_da_inv;
|
|
};
|
|
|
|
class HashFunction;
|
|
|
|
std::vector<uint8_t>
|
|
BOTAN_PUBLIC_API(2,5) sm2_compute_za(HashFunction& hash,
|
|
const std::string& user_id,
|
|
const EC_Group& domain,
|
|
const PointGFp& pubkey);
|
|
|
|
// For compat with versions 2.2 - 2.7
|
|
typedef SM2_PublicKey SM2_Signature_PublicKey;
|
|
typedef SM2_PublicKey SM2_Encryption_PublicKey;
|
|
|
|
typedef SM2_PrivateKey SM2_Signature_PrivateKey;
|
|
typedef SM2_PrivateKey SM2_Encryption_PrivateKey;
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(sm3.h)
|
|
|
|
namespace Botan {
|
|
|
|
enum {
|
|
SM3_BLOCK_BYTES = 64,
|
|
SM3_DIGEST_BYTES = 32
|
|
};
|
|
|
|
/**
|
|
* SM3
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) SM3 final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "SM3"; }
|
|
size_t output_length() const override { return SM3_DIGEST_BYTES; }
|
|
HashFunction* clone() const override { return new SM3; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override;
|
|
|
|
SM3() : MDx_HashFunction(SM3_BLOCK_BYTES, true, true), m_digest(SM3_DIGEST_BYTES)
|
|
{ clear(); }
|
|
private:
|
|
void compress_n(const uint8_t[], size_t blocks) override;
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
/**
|
|
* The digest value
|
|
*/
|
|
secure_vector<uint32_t> m_digest;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(sm4.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* SM4
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) SM4 final : public Block_Cipher_Fixed_Params<16, 16>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "SM4"; }
|
|
BlockCipher* clone() const override { return new SM4; }
|
|
|
|
std::string provider() const override;
|
|
size_t parallelism() const override;
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
#if defined(BOTAN_HAS_SM4_ARMV8)
|
|
void sm4_armv8_encrypt(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
void sm4_armv8_decrypt(const uint8_t in[], uint8_t out[], size_t blocks) const;
|
|
#endif
|
|
|
|
secure_vector<uint32_t> m_RK;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* The Sodium namespace contains a partial implementation of the
|
|
* libsodium API.
|
|
*/
|
|
namespace Sodium {
|
|
|
|
// sodium/randombytes.h
|
|
enum Sodium_Constants : size_t {
|
|
SODIUM_SIZE_MAX = 0xFFFFFFFF,
|
|
|
|
crypto_aead_chacha20poly1305_ABYTES = 16,
|
|
crypto_aead_chacha20poly1305_KEYBYTES = 32,
|
|
crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX = SODIUM_SIZE_MAX,
|
|
crypto_aead_chacha20poly1305_NPUBBYTES = 8,
|
|
crypto_aead_chacha20poly1305_NSECBYTES = 0,
|
|
|
|
crypto_aead_chacha20poly1305_ietf_ABYTES = 16,
|
|
crypto_aead_chacha20poly1305_ietf_KEYBYTES = 32,
|
|
crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX = SODIUM_SIZE_MAX,
|
|
crypto_aead_chacha20poly1305_ietf_NPUBBYTES = 12,
|
|
crypto_aead_chacha20poly1305_ietf_NSECBYTES = 0,
|
|
|
|
crypto_aead_xchacha20poly1305_ietf_ABYTES = 16,
|
|
crypto_aead_xchacha20poly1305_ietf_KEYBYTES = 32,
|
|
crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX = SODIUM_SIZE_MAX,
|
|
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES = 24,
|
|
crypto_aead_xchacha20poly1305_ietf_NSECBYTES = 0,
|
|
|
|
crypto_auth_hmacsha256_BYTES = 32,
|
|
crypto_auth_hmacsha256_KEYBYTES = 32,
|
|
crypto_auth_hmacsha512256_BYTES = 32,
|
|
crypto_auth_hmacsha512256_KEYBYTES = 32,
|
|
crypto_auth_hmacsha512_BYTES = 64,
|
|
crypto_auth_hmacsha512_KEYBYTES = 32,
|
|
|
|
crypto_auth_BYTES = crypto_auth_hmacsha512256_BYTES,
|
|
crypto_auth_KEYBYTES = crypto_auth_hmacsha512256_KEYBYTES,
|
|
|
|
crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES = 32,
|
|
crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES = 16,
|
|
crypto_box_curve25519xsalsa20poly1305_MACBYTES = 16,
|
|
crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX = SODIUM_SIZE_MAX,
|
|
crypto_box_curve25519xsalsa20poly1305_NONCEBYTES = 24,
|
|
crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES = 32,
|
|
crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES = 32,
|
|
crypto_box_curve25519xsalsa20poly1305_SEEDBYTES = 32,
|
|
crypto_box_curve25519xsalsa20poly1305_ZEROBYTES = crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES + crypto_box_curve25519xsalsa20poly1305_MACBYTES,
|
|
|
|
crypto_box_BEFORENMBYTES = crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES,
|
|
crypto_box_BOXZEROBYTES = crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES,
|
|
crypto_box_MACBYTES = crypto_box_curve25519xsalsa20poly1305_MACBYTES,
|
|
crypto_box_MESSAGEBYTES_MAX = crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX,
|
|
crypto_box_NONCEBYTES = crypto_box_curve25519xsalsa20poly1305_NONCEBYTES,
|
|
crypto_box_PUBLICKEYBYTES = crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES,
|
|
crypto_box_SECRETKEYBYTES = crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES,
|
|
crypto_box_SEEDBYTES = crypto_box_curve25519xsalsa20poly1305_SEEDBYTES,
|
|
crypto_box_ZEROBYTES = crypto_box_curve25519xsalsa20poly1305_ZEROBYTES,
|
|
|
|
crypto_core_hchacha20_CONSTBYTES = 16,
|
|
crypto_core_hchacha20_INPUTBYTES = 16,
|
|
crypto_core_hchacha20_KEYBYTES = 32,
|
|
crypto_core_hchacha20_OUTPUTBYTES = 32,
|
|
|
|
crypto_core_hsalsa20_CONSTBYTES = 16,
|
|
crypto_core_hsalsa20_INPUTBYTES = 16,
|
|
crypto_core_hsalsa20_KEYBYTES = 32,
|
|
crypto_core_hsalsa20_OUTPUTBYTES = 32,
|
|
|
|
crypto_hash_sha256_BYTES = 32,
|
|
crypto_hash_sha512_BYTES = 64,
|
|
crypto_hash_BYTES = crypto_hash_sha512_BYTES,
|
|
|
|
crypto_onetimeauth_poly1305_BYTES = 16,
|
|
crypto_onetimeauth_poly1305_KEYBYTES = 32,
|
|
crypto_onetimeauth_BYTES = crypto_onetimeauth_poly1305_BYTES,
|
|
crypto_onetimeauth_KEYBYTES = crypto_onetimeauth_poly1305_KEYBYTES,
|
|
|
|
crypto_scalarmult_curve25519_BYTES = 32,
|
|
crypto_scalarmult_curve25519_SCALARBYTES = 32,
|
|
crypto_scalarmult_BYTES = crypto_scalarmult_curve25519_BYTES,
|
|
crypto_scalarmult_SCALARBYTES = crypto_scalarmult_curve25519_SCALARBYTES,
|
|
|
|
crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES = 16,
|
|
crypto_secretbox_xsalsa20poly1305_KEYBYTES = 32,
|
|
crypto_secretbox_xsalsa20poly1305_MACBYTES = 16,
|
|
crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX = SODIUM_SIZE_MAX,
|
|
crypto_secretbox_xsalsa20poly1305_NONCEBYTES = 24,
|
|
crypto_secretbox_xsalsa20poly1305_ZEROBYTES = crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES + crypto_secretbox_xsalsa20poly1305_MACBYTES,
|
|
|
|
crypto_secretbox_BOXZEROBYTES = crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES,
|
|
crypto_secretbox_KEYBYTES = crypto_secretbox_xsalsa20poly1305_KEYBYTES,
|
|
crypto_secretbox_MACBYTES = crypto_secretbox_xsalsa20poly1305_MACBYTES,
|
|
crypto_secretbox_MESSAGEBYTES_MAX = crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX,
|
|
crypto_secretbox_NONCEBYTES = crypto_secretbox_xsalsa20poly1305_NONCEBYTES,
|
|
crypto_secretbox_ZEROBYTES = crypto_secretbox_xsalsa20poly1305_ZEROBYTES,
|
|
|
|
crypto_shorthash_siphash24_BYTES = 8,
|
|
crypto_shorthash_siphash24_KEYBYTES = 16,
|
|
crypto_shorthash_BYTES = crypto_shorthash_siphash24_BYTES,
|
|
crypto_shorthash_KEYBYTES = crypto_shorthash_siphash24_KEYBYTES,
|
|
|
|
crypto_sign_ed25519_BYTES = 64,
|
|
crypto_sign_ed25519_MESSAGEBYTES_MAX = (SODIUM_SIZE_MAX - crypto_sign_ed25519_BYTES),
|
|
crypto_sign_ed25519_PUBLICKEYBYTES = 32,
|
|
crypto_sign_ed25519_SECRETKEYBYTES = (32 + 32),
|
|
crypto_sign_ed25519_SEEDBYTES = 32,
|
|
crypto_sign_BYTES = crypto_sign_ed25519_BYTES,
|
|
crypto_sign_MESSAGEBYTES_MAX = crypto_sign_ed25519_MESSAGEBYTES_MAX,
|
|
crypto_sign_PUBLICKEYBYTES = crypto_sign_ed25519_PUBLICKEYBYTES,
|
|
crypto_sign_SECRETKEYBYTES = crypto_sign_ed25519_SECRETKEYBYTES,
|
|
crypto_sign_SEEDBYTES = crypto_sign_ed25519_SEEDBYTES,
|
|
|
|
crypto_stream_chacha20_KEYBYTES = 32,
|
|
crypto_stream_chacha20_MESSAGEBYTES_MAX = SODIUM_SIZE_MAX,
|
|
crypto_stream_chacha20_NONCEBYTES = 8,
|
|
crypto_stream_chacha20_ietf_KEYBYTES = 32,
|
|
crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX = SODIUM_SIZE_MAX,
|
|
crypto_stream_chacha20_ietf_NONCEBYTES = 12,
|
|
crypto_stream_salsa20_KEYBYTES = 32,
|
|
crypto_stream_salsa20_MESSAGEBYTES_MAX = SODIUM_SIZE_MAX,
|
|
crypto_stream_salsa20_NONCEBYTES = 8,
|
|
crypto_stream_xchacha20_KEYBYTES = 32,
|
|
crypto_stream_xchacha20_MESSAGEBYTES_MAX = SODIUM_SIZE_MAX,
|
|
crypto_stream_xchacha20_NONCEBYTES = 24,
|
|
crypto_stream_xsalsa20_KEYBYTES = 32,
|
|
crypto_stream_xsalsa20_MESSAGEBYTES_MAX = SODIUM_SIZE_MAX,
|
|
crypto_stream_xsalsa20_NONCEBYTES = 24,
|
|
crypto_stream_KEYBYTES = crypto_stream_xsalsa20_KEYBYTES,
|
|
crypto_stream_MESSAGEBYTES_MAX = crypto_stream_xsalsa20_MESSAGEBYTES_MAX,
|
|
crypto_stream_NONCEBYTES = crypto_stream_xsalsa20_NONCEBYTES,
|
|
|
|
crypto_verify_16_BYTES = 16,
|
|
crypto_verify_32_BYTES = 32,
|
|
crypto_verify_64_BYTES = 64,
|
|
|
|
randombytes_SEEDBYTES = 32,
|
|
};
|
|
|
|
inline const char* sodium_version_string() { return "Botan Sodium Compat"; }
|
|
|
|
inline int sodium_library_version_major() { return 0; }
|
|
|
|
inline int sodium_library_version_minor() { return 0; }
|
|
|
|
inline int sodium_library_minimal() { return 0; }
|
|
|
|
inline int sodium_init() { return 0; }
|
|
|
|
// sodium/crypto_verify_{16,32,64}.h
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_verify_16(const uint8_t x[16], const uint8_t y[16]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_verify_32(const uint8_t x[32], const uint8_t y[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_verify_64(const uint8_t x[64], const uint8_t y[64]);
|
|
|
|
// sodium/utils.h
|
|
BOTAN_PUBLIC_API(2,11)
|
|
void sodium_memzero(void* ptr, size_t len);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int sodium_memcmp(const void* x, const void* y, size_t len);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int sodium_compare(const uint8_t x[], const uint8_t y[], size_t len);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int sodium_is_zero(const uint8_t nonce[], size_t nlen);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
void sodium_increment(uint8_t n[], size_t nlen);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
void sodium_add(uint8_t a[], const uint8_t b[], size_t len);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
void* sodium_malloc(size_t size);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
void* sodium_allocarray(size_t count, size_t size);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
void sodium_free(void* ptr);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int sodium_mprotect_noaccess(void* ptr);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int sodium_mprotect_readwrite(void* ptr);
|
|
|
|
// sodium/randombytes.h
|
|
|
|
inline size_t randombytes_seedbytes() { return randombytes_SEEDBYTES; }
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
void randombytes_buf(void* buf, size_t size);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
void randombytes_buf_deterministic(void* buf, size_t size,
|
|
const uint8_t seed[randombytes_SEEDBYTES]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
uint32_t randombytes_uniform(uint32_t upper_bound);
|
|
|
|
inline uint32_t randombytes_random()
|
|
{
|
|
uint32_t x = 0;
|
|
randombytes_buf(&x, 4);
|
|
return x;
|
|
}
|
|
|
|
inline void randombytes_stir() {}
|
|
|
|
inline int randombytes_close() { return 0; }
|
|
|
|
inline const char* randombytes_implementation_name()
|
|
{
|
|
return "botan";
|
|
}
|
|
|
|
inline void randombytes(uint8_t buf[], size_t buf_len)
|
|
{
|
|
return randombytes_buf(buf, buf_len);
|
|
}
|
|
|
|
// sodium/crypto_secretbox_xsalsa20poly1305.h
|
|
|
|
inline size_t crypto_secretbox_xsalsa20poly1305_keybytes()
|
|
{
|
|
return crypto_secretbox_xsalsa20poly1305_KEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_secretbox_xsalsa20poly1305_noncebytes()
|
|
{
|
|
return crypto_secretbox_xsalsa20poly1305_NONCEBYTES;
|
|
}
|
|
|
|
inline size_t crypto_secretbox_xsalsa20poly1305_macbytes()
|
|
{
|
|
return crypto_secretbox_xsalsa20poly1305_MACBYTES;
|
|
}
|
|
|
|
inline size_t crypto_secretbox_xsalsa20poly1305_messagebytes_max()
|
|
{
|
|
return crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_secretbox_xsalsa20poly1305(uint8_t ctext[],
|
|
const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_secretbox_xsalsa20poly1305_open(uint8_t ptext[],
|
|
const uint8_t ctext[],
|
|
size_t ctext_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_secretbox_xsalsa20poly1305_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, 32);
|
|
}
|
|
|
|
inline size_t crypto_secretbox_xsalsa20poly1305_boxzerobytes()
|
|
{
|
|
return crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES;
|
|
}
|
|
|
|
inline size_t crypto_secretbox_xsalsa20poly1305_zerobytes()
|
|
{
|
|
return crypto_secretbox_xsalsa20poly1305_ZEROBYTES;
|
|
}
|
|
|
|
// sodium/crypto_secretbox.h
|
|
|
|
inline size_t crypto_secretbox_keybytes() { return crypto_secretbox_KEYBYTES; }
|
|
|
|
inline size_t crypto_secretbox_noncebytes() { return crypto_secretbox_NONCEBYTES; }
|
|
|
|
inline size_t crypto_secretbox_macbytes() { return crypto_secretbox_MACBYTES; }
|
|
|
|
inline size_t crypto_secretbox_messagebytes_max() { return crypto_secretbox_xsalsa20poly1305_MESSAGEBYTES_MAX; }
|
|
|
|
inline const char* crypto_secretbox_primitive() { return "xsalsa20poly1305"; }
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_secretbox_detached(uint8_t ctext[], uint8_t mac[],
|
|
const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_secretbox_open_detached(uint8_t ptext[],
|
|
const uint8_t ctext[],
|
|
const uint8_t mac[],
|
|
size_t ctext_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
inline int crypto_secretbox_easy(uint8_t ctext[], const uint8_t ptext[],
|
|
size_t ptext_len, const uint8_t nonce[],
|
|
const uint8_t key[])
|
|
{
|
|
return crypto_secretbox_detached(ctext + crypto_secretbox_MACBYTES, ctext,
|
|
ptext, ptext_len, nonce, key);
|
|
}
|
|
|
|
inline int crypto_secretbox_open_easy(uint8_t out[], const uint8_t ctext[], size_t ctext_len,
|
|
const uint8_t nonce[], const uint8_t key[])
|
|
{
|
|
if(ctext_len < crypto_secretbox_MACBYTES)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return crypto_secretbox_open_detached(out, ctext + crypto_secretbox_MACBYTES,
|
|
ctext, ctext_len - crypto_secretbox_MACBYTES,
|
|
nonce, key);
|
|
}
|
|
|
|
inline void crypto_secretbox_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, 32);
|
|
}
|
|
|
|
inline size_t crypto_secretbox_zerobytes()
|
|
{
|
|
return crypto_secretbox_ZEROBYTES;
|
|
}
|
|
|
|
inline size_t crypto_secretbox_boxzerobytes()
|
|
{
|
|
return crypto_secretbox_BOXZEROBYTES;
|
|
}
|
|
|
|
inline int crypto_secretbox(uint8_t ctext[], const uint8_t ptext[],
|
|
size_t ptext_len, const uint8_t nonce[],
|
|
const uint8_t key[])
|
|
{
|
|
return crypto_secretbox_xsalsa20poly1305(ctext, ptext, ptext_len, nonce, key);
|
|
}
|
|
|
|
inline int crypto_secretbox_open(uint8_t ptext[], const uint8_t ctext[],
|
|
size_t ctext_len, const uint8_t nonce[],
|
|
const uint8_t key[])
|
|
{
|
|
return crypto_secretbox_xsalsa20poly1305_open(ptext, ctext, ctext_len, nonce, key);
|
|
}
|
|
|
|
// sodium/crypto_aead_xchacha20poly1305.h
|
|
|
|
inline size_t crypto_aead_chacha20poly1305_ietf_keybytes()
|
|
{
|
|
return crypto_aead_chacha20poly1305_ietf_KEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_chacha20poly1305_ietf_nsecbytes()
|
|
{
|
|
return crypto_aead_chacha20poly1305_ietf_NSECBYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_chacha20poly1305_ietf_npubbytes()
|
|
{
|
|
return crypto_aead_chacha20poly1305_ietf_NPUBBYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_chacha20poly1305_ietf_abytes()
|
|
{
|
|
return crypto_aead_chacha20poly1305_ietf_ABYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_chacha20poly1305_ietf_messagebytes_max()
|
|
{
|
|
return crypto_aead_chacha20poly1305_ietf_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_chacha20poly1305_ietf_encrypt(uint8_t ctext[],
|
|
unsigned long long* ctext_len,
|
|
const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t unused_secret_nonce[],
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_chacha20poly1305_ietf_decrypt(uint8_t ptext[],
|
|
unsigned long long* ptext_len,
|
|
uint8_t unused_secret_nonce[],
|
|
const uint8_t ctext[],
|
|
size_t ctext_len,
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_chacha20poly1305_ietf_encrypt_detached(uint8_t ctext[],
|
|
uint8_t mac[],
|
|
unsigned long long* mac_len,
|
|
const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t unused_secret_nonce[],
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_chacha20poly1305_ietf_decrypt_detached(uint8_t m[],
|
|
uint8_t unused_secret_nonce[],
|
|
const uint8_t ctext[],
|
|
size_t ctext_len,
|
|
const uint8_t mac[],
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_aead_chacha20poly1305_ietf_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, crypto_aead_chacha20poly1305_ietf_KEYBYTES);
|
|
}
|
|
|
|
inline size_t crypto_aead_chacha20poly1305_keybytes()
|
|
{
|
|
return crypto_aead_chacha20poly1305_KEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_chacha20poly1305_nsecbytes()
|
|
{
|
|
return crypto_aead_chacha20poly1305_NSECBYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_chacha20poly1305_npubbytes()
|
|
{
|
|
return crypto_aead_chacha20poly1305_NPUBBYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_chacha20poly1305_abytes()
|
|
{
|
|
return crypto_aead_chacha20poly1305_ABYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_chacha20poly1305_messagebytes_max()
|
|
{
|
|
return crypto_aead_chacha20poly1305_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_chacha20poly1305_encrypt(uint8_t ctext[],
|
|
unsigned long long* ctext_len,
|
|
const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t unused_secret_nonce[],
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_chacha20poly1305_decrypt(uint8_t m[],
|
|
unsigned long long* ptext_len,
|
|
uint8_t unused_secret_nonce[],
|
|
const uint8_t ctext[],
|
|
size_t ctext_len,
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_chacha20poly1305_encrypt_detached(uint8_t ctext[],
|
|
uint8_t mac[],
|
|
unsigned long long* mac_len,
|
|
const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t unused_secret_nonce[],
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_chacha20poly1305_decrypt_detached(uint8_t m[],
|
|
uint8_t unused_secret_nonce[],
|
|
const uint8_t ctext[],
|
|
size_t ctext_len,
|
|
const uint8_t mac[],
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_aead_chacha20poly1305_keygen(uint8_t k[32])
|
|
{
|
|
randombytes_buf(k, 32);
|
|
}
|
|
|
|
// sodium/crypto_aead_xchacha20poly1305.h
|
|
|
|
inline size_t crypto_aead_xchacha20poly1305_ietf_keybytes()
|
|
{
|
|
return crypto_aead_xchacha20poly1305_ietf_KEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_xchacha20poly1305_ietf_nsecbytes()
|
|
{
|
|
return crypto_aead_xchacha20poly1305_ietf_NSECBYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_xchacha20poly1305_ietf_npubbytes()
|
|
{
|
|
return crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_xchacha20poly1305_ietf_abytes()
|
|
{
|
|
return crypto_aead_xchacha20poly1305_ietf_ABYTES;
|
|
}
|
|
|
|
inline size_t crypto_aead_xchacha20poly1305_ietf_messagebytes_max()
|
|
{
|
|
return crypto_aead_xchacha20poly1305_ietf_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_xchacha20poly1305_ietf_encrypt(uint8_t ctext[],
|
|
unsigned long long* ctext_len,
|
|
const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t unused_secret_nonce[],
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_xchacha20poly1305_ietf_decrypt(uint8_t ptext[],
|
|
unsigned long long* ptext_len,
|
|
uint8_t unused_secret_nonce[],
|
|
const uint8_t ctext[],
|
|
size_t ctext_len,
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_xchacha20poly1305_ietf_encrypt_detached(uint8_t ctext[],
|
|
uint8_t mac[],
|
|
unsigned long long* mac_len,
|
|
const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t unused_secret_nonce[],
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_aead_xchacha20poly1305_ietf_decrypt_detached(uint8_t ptext[],
|
|
uint8_t unused_secret_nonce[],
|
|
const uint8_t ctext[],
|
|
size_t ctext_len,
|
|
const uint8_t mac[],
|
|
const uint8_t ad[],
|
|
size_t ad_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_aead_xchacha20poly1305_ietf_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, 32);
|
|
}
|
|
|
|
// sodium/crypto_box_curve25519xsalsa20poly1305.h
|
|
|
|
inline size_t crypto_box_curve25519xsalsa20poly1305_seedbytes()
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_SEEDBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_curve25519xsalsa20poly1305_publickeybytes()
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_PUBLICKEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_curve25519xsalsa20poly1305_secretkeybytes()
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_SECRETKEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_curve25519xsalsa20poly1305_beforenmbytes()
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_curve25519xsalsa20poly1305_noncebytes()
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_NONCEBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_curve25519xsalsa20poly1305_macbytes()
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_MACBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_curve25519xsalsa20poly1305_messagebytes_max()
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
inline size_t crypto_box_curve25519xsalsa20poly1305_boxzerobytes()
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_BOXZEROBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_curve25519xsalsa20poly1305_zerobytes()
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_ZEROBYTES;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_box_curve25519xsalsa20poly1305_seed_keypair(uint8_t pk[32],
|
|
uint8_t sk[32],
|
|
const uint8_t seed[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_box_curve25519xsalsa20poly1305_keypair(uint8_t pk[32],
|
|
uint8_t sk[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_box_curve25519xsalsa20poly1305_beforenm(uint8_t key[],
|
|
const uint8_t pk[32],
|
|
const uint8_t sk[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_box_curve25519xsalsa20poly1305(uint8_t ctext[],
|
|
const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t pk[32],
|
|
const uint8_t sk[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_box_curve25519xsalsa20poly1305_open(uint8_t ptext[],
|
|
const uint8_t ctext[],
|
|
size_t ctext_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t pk[32],
|
|
const uint8_t sk[32]);
|
|
|
|
inline int crypto_box_curve25519xsalsa20poly1305_afternm(uint8_t ctext[],
|
|
const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[])
|
|
{
|
|
return crypto_secretbox_xsalsa20poly1305(ctext, ptext, ptext_len, nonce, key);
|
|
}
|
|
|
|
inline int crypto_box_curve25519xsalsa20poly1305_open_afternm(uint8_t ptext[],
|
|
const uint8_t ctext[],
|
|
size_t ctext_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t key[])
|
|
{
|
|
return crypto_secretbox_xsalsa20poly1305_open(ptext, ctext, ctext_len, nonce, key);
|
|
}
|
|
|
|
// sodium/crypto_box.h
|
|
|
|
inline size_t crypto_box_seedbytes()
|
|
{
|
|
return crypto_box_SEEDBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_publickeybytes()
|
|
{
|
|
return crypto_box_PUBLICKEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_secretkeybytes()
|
|
{
|
|
return crypto_box_SECRETKEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_noncebytes()
|
|
{
|
|
return crypto_box_NONCEBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_macbytes()
|
|
{
|
|
return crypto_box_MACBYTES;
|
|
}
|
|
|
|
inline size_t crypto_box_messagebytes_max()
|
|
{
|
|
return crypto_box_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
inline size_t crypto_box_beforenmbytes()
|
|
{
|
|
return crypto_box_BEFORENMBYTES;
|
|
}
|
|
|
|
inline const char* crypto_box_primitive() { return "curve25519xsalsa20poly1305"; }
|
|
|
|
inline int crypto_box_seed_keypair(uint8_t pk[32], uint8_t sk[32],
|
|
const uint8_t seed[])
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_seed_keypair(pk, sk, seed);
|
|
}
|
|
|
|
inline int crypto_box_keypair(uint8_t pk[32], uint8_t sk[32])
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_keypair(pk, sk);
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_box_detached(uint8_t ctext[], uint8_t mac[],
|
|
const uint8_t ptext[], size_t ptext_len,
|
|
const uint8_t nonce[], const uint8_t pk[32],
|
|
const uint8_t sk[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_box_open_detached(uint8_t ptext[], const uint8_t ctext[],
|
|
const uint8_t mac[],
|
|
size_t ctext_len,
|
|
const uint8_t nonce[],
|
|
const uint8_t pk[32],
|
|
const uint8_t sk[32]);
|
|
|
|
inline int crypto_box_easy(uint8_t ctext[], const uint8_t ptext[],
|
|
size_t ptext_len, const uint8_t nonce[],
|
|
const uint8_t pk[32], const uint8_t sk[32])
|
|
{
|
|
return crypto_box_detached(ctext + crypto_box_MACBYTES, ctext, ptext, ptext_len, nonce, pk, sk);
|
|
}
|
|
|
|
inline int crypto_box_open_easy(uint8_t ptext[], const uint8_t ctext[],
|
|
size_t ctext_len, const uint8_t nonce[],
|
|
const uint8_t pk[32], const uint8_t sk[32])
|
|
{
|
|
if(ctext_len < crypto_box_MACBYTES)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return crypto_box_open_detached(ptext, ctext + crypto_box_MACBYTES,
|
|
ctext, ctext_len - crypto_box_MACBYTES,
|
|
nonce, pk, sk);
|
|
}
|
|
|
|
inline int crypto_box_beforenm(uint8_t key[], const uint8_t pk[32],
|
|
const uint8_t sk[32])
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_beforenm(key, pk, sk);
|
|
}
|
|
|
|
inline int crypto_box_afternm(uint8_t ctext[], const uint8_t ptext[],
|
|
size_t ptext_len, const uint8_t nonce[],
|
|
const uint8_t key[])
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_afternm(ctext, ptext, ptext_len, nonce, key);
|
|
}
|
|
|
|
inline int crypto_box_open_afternm(uint8_t ptext[], const uint8_t ctext[],
|
|
size_t ctext_len, const uint8_t nonce[],
|
|
const uint8_t key[])
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_open_afternm(ptext, ctext, ctext_len, nonce, key);
|
|
}
|
|
|
|
inline int crypto_box_open_detached_afternm(uint8_t ptext[], const uint8_t ctext[],
|
|
const uint8_t mac[],
|
|
size_t ctext_len, const uint8_t nonce[],
|
|
const uint8_t key[])
|
|
{
|
|
return crypto_secretbox_open_detached(ptext, ctext, mac, ctext_len, nonce, key);
|
|
}
|
|
|
|
inline int crypto_box_open_easy_afternm(uint8_t ptext[], const uint8_t ctext[],
|
|
size_t ctext_len, const uint8_t nonce[],
|
|
const uint8_t key[])
|
|
{
|
|
if(ctext_len < crypto_box_MACBYTES)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return crypto_box_open_detached_afternm(ptext, ctext + crypto_box_MACBYTES,
|
|
ctext, ctext_len - crypto_box_MACBYTES,
|
|
nonce, key);
|
|
}
|
|
|
|
inline int crypto_box_detached_afternm(uint8_t ctext[], uint8_t mac[],
|
|
const uint8_t ptext[], size_t ptext_len,
|
|
const uint8_t nonce[], const uint8_t key[])
|
|
{
|
|
return crypto_secretbox_detached(ctext, mac, ptext, ptext_len, nonce, key);
|
|
}
|
|
|
|
inline int crypto_box_easy_afternm(uint8_t ctext[], const uint8_t ptext[],
|
|
size_t ptext_len, const uint8_t nonce[],
|
|
const uint8_t key[])
|
|
{
|
|
return crypto_box_detached_afternm(ctext + crypto_box_MACBYTES, ctext, ptext, ptext_len, nonce, key);
|
|
}
|
|
|
|
inline size_t crypto_box_zerobytes() { return crypto_box_ZEROBYTES; }
|
|
|
|
inline size_t crypto_box_boxzerobytes() { return crypto_box_BOXZEROBYTES; }
|
|
|
|
inline int crypto_box(uint8_t ctext[], const uint8_t ptext[],
|
|
size_t ptext_len, const uint8_t nonce[],
|
|
const uint8_t pk[32], const uint8_t sk[32])
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305(ctext, ptext, ptext_len, nonce, pk, sk);
|
|
}
|
|
|
|
inline int crypto_box_open(uint8_t ptext[], const uint8_t ctext[],
|
|
size_t ctext_len, const uint8_t nonce[],
|
|
const uint8_t pk[32], const uint8_t sk[32])
|
|
{
|
|
return crypto_box_curve25519xsalsa20poly1305_open(ptext, ctext, ctext_len, nonce, pk, sk);
|
|
}
|
|
|
|
// sodium/crypto_hash_sha512.h
|
|
|
|
inline size_t crypto_hash_sha512_bytes() { return crypto_hash_sha512_BYTES; }
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_hash_sha512(uint8_t out[64], const uint8_t in[], size_t in_len);
|
|
|
|
// sodium/crypto_auth_hmacsha512.h
|
|
|
|
inline size_t crypto_auth_hmacsha512_bytes() { return crypto_auth_hmacsha512_BYTES; }
|
|
|
|
inline size_t crypto_auth_hmacsha512_keybytes() { return crypto_auth_hmacsha512_KEYBYTES; }
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_auth_hmacsha512(uint8_t out[],
|
|
const uint8_t in[],
|
|
size_t in_len,
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_auth_hmacsha512_verify(const uint8_t h[],
|
|
const uint8_t in[],
|
|
size_t in_len,
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_auth_hmacsha512_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, 32);
|
|
}
|
|
|
|
// sodium/crypto_auth_hmacsha512256.h
|
|
|
|
inline size_t crypto_auth_hmacsha512256_bytes()
|
|
{
|
|
return crypto_auth_hmacsha512256_BYTES;
|
|
}
|
|
|
|
inline size_t crypto_auth_hmacsha512256_keybytes()
|
|
{
|
|
return crypto_auth_hmacsha512256_KEYBYTES;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_auth_hmacsha512256(uint8_t out[],
|
|
const uint8_t in[],
|
|
size_t in_len,
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_auth_hmacsha512256_verify(const uint8_t h[],
|
|
const uint8_t in[],
|
|
size_t in_len,
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_auth_hmacsha512256_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, 32);
|
|
}
|
|
|
|
// sodium/crypto_auth.h
|
|
|
|
inline size_t crypto_auth_bytes() { return crypto_auth_BYTES; }
|
|
|
|
inline size_t crypto_auth_keybytes() { return crypto_auth_KEYBYTES; }
|
|
|
|
inline const char* crypto_auth_primitive() { return "hmacsha512256"; }
|
|
|
|
inline int crypto_auth(uint8_t out[], const uint8_t in[],
|
|
size_t in_len, const uint8_t key[])
|
|
{
|
|
return crypto_auth_hmacsha512256(out, in, in_len, key);
|
|
}
|
|
|
|
inline int crypto_auth_verify(const uint8_t mac[], const uint8_t in[],
|
|
size_t in_len, const uint8_t key[])
|
|
{
|
|
return crypto_auth_hmacsha512256_verify(mac, in, in_len, key);
|
|
}
|
|
|
|
inline void crypto_auth_keygen(uint8_t k[])
|
|
{
|
|
return randombytes_buf(k, crypto_auth_KEYBYTES);
|
|
}
|
|
|
|
// sodium/crypto_hash_sha256.h
|
|
|
|
inline size_t crypto_hash_sha256_bytes()
|
|
{
|
|
return crypto_hash_sha256_BYTES;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_hash_sha256(uint8_t out[], const uint8_t in[], size_t in_len);
|
|
|
|
// sodium/crypto_auth_hmacsha256.h
|
|
|
|
inline size_t crypto_auth_hmacsha256_bytes()
|
|
{
|
|
return crypto_auth_hmacsha256_BYTES;
|
|
}
|
|
|
|
inline size_t crypto_auth_hmacsha256_keybytes()
|
|
{
|
|
return crypto_auth_hmacsha256_KEYBYTES;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_auth_hmacsha256(uint8_t out[],
|
|
const uint8_t in[],
|
|
size_t in_len,
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_auth_hmacsha256_verify(const uint8_t h[],
|
|
const uint8_t in[],
|
|
size_t in_len,
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_auth_hmacsha256_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, 32);
|
|
}
|
|
|
|
// sodium/crypto_stream_xsalsa20.h
|
|
|
|
inline size_t crypto_stream_xsalsa20_keybytes()
|
|
{
|
|
return crypto_stream_xsalsa20_KEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_stream_xsalsa20_noncebytes()
|
|
{
|
|
return crypto_stream_xsalsa20_NONCEBYTES;
|
|
}
|
|
|
|
inline size_t crypto_stream_xsalsa20_messagebytes_max()
|
|
{
|
|
return crypto_stream_xsalsa20_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_xsalsa20(uint8_t out[], size_t ctext_len,
|
|
const uint8_t nonce[], const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_xsalsa20_xor(uint8_t out[], const uint8_t ptext[],
|
|
size_t ptext_len, const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_xsalsa20_xor_ic(uint8_t out[], const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t nonce[], uint64_t ic,
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_stream_xsalsa20_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, 32);
|
|
}
|
|
|
|
// sodium/crypto_core_hsalsa20.h
|
|
|
|
inline size_t crypto_core_hsalsa20_outputbytes()
|
|
{
|
|
return crypto_core_hsalsa20_OUTPUTBYTES;
|
|
}
|
|
|
|
inline size_t crypto_core_hsalsa20_inputbytes()
|
|
{
|
|
return crypto_core_hsalsa20_INPUTBYTES;
|
|
}
|
|
|
|
inline size_t crypto_core_hsalsa20_keybytes()
|
|
{
|
|
return crypto_core_hsalsa20_KEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_core_hsalsa20_constbytes()
|
|
{
|
|
return crypto_core_hsalsa20_CONSTBYTES;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_core_hsalsa20(uint8_t out[], const uint8_t in[],
|
|
const uint8_t key[], const uint8_t c[]);
|
|
|
|
// sodium/crypto_hash.h
|
|
|
|
inline size_t crypto_hash_bytes()
|
|
{
|
|
return crypto_hash_BYTES;
|
|
}
|
|
|
|
inline int crypto_hash(uint8_t out[], const uint8_t in[], size_t in_len)
|
|
{
|
|
return crypto_hash_sha512(out, in, in_len);
|
|
}
|
|
|
|
inline const char* crypto_hash_primitive() { return "sha512"; }
|
|
|
|
// sodium/crypto_onetimeauth_poly1305.h
|
|
|
|
inline size_t crypto_onetimeauth_poly1305_bytes()
|
|
{
|
|
return crypto_onetimeauth_poly1305_BYTES;
|
|
}
|
|
|
|
inline size_t crypto_onetimeauth_poly1305_keybytes()
|
|
{
|
|
return crypto_onetimeauth_poly1305_KEYBYTES;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_onetimeauth_poly1305(uint8_t out[],
|
|
const uint8_t in[],
|
|
size_t in_len,
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_onetimeauth_poly1305_verify(const uint8_t h[],
|
|
const uint8_t in[],
|
|
size_t in_len,
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_onetimeauth_poly1305_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, 32);
|
|
}
|
|
|
|
// sodium/crypto_onetimeauth.h
|
|
|
|
inline size_t crypto_onetimeauth_bytes() { return crypto_onetimeauth_BYTES; }
|
|
|
|
inline size_t crypto_onetimeauth_keybytes() { return crypto_onetimeauth_KEYBYTES; }
|
|
|
|
inline const char* crypto_onetimeauth_primitive() { return "poly1305"; }
|
|
|
|
inline int crypto_onetimeauth(uint8_t out[], const uint8_t in[],
|
|
size_t in_len, const uint8_t key[])
|
|
{
|
|
return crypto_onetimeauth_poly1305(out, in, in_len, key);
|
|
}
|
|
|
|
inline int crypto_onetimeauth_verify(const uint8_t h[], const uint8_t in[],
|
|
size_t in_len, const uint8_t key[])
|
|
{
|
|
return crypto_onetimeauth_poly1305_verify(h, in, in_len, key);
|
|
}
|
|
|
|
inline void crypto_onetimeauth_keygen(uint8_t k[32])
|
|
{
|
|
return crypto_onetimeauth_poly1305_keygen(k);
|
|
}
|
|
|
|
// sodium/crypto_scalarmult_curve25519.h
|
|
|
|
inline size_t crypto_scalarmult_curve25519_bytes()
|
|
{
|
|
return crypto_scalarmult_curve25519_BYTES;
|
|
}
|
|
|
|
inline size_t crypto_scalarmult_curve25519_scalarbytes()
|
|
{
|
|
return crypto_scalarmult_curve25519_SCALARBYTES;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_scalarmult_curve25519(uint8_t out[32], const uint8_t scalar[32], const uint8_t basepoint[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_scalarmult_curve25519_base(uint8_t out[32], const uint8_t scalar[32]);
|
|
|
|
// sodium/crypto_scalarmult.h
|
|
|
|
inline size_t crypto_scalarmult_bytes() { return crypto_scalarmult_curve25519_bytes(); }
|
|
|
|
inline size_t crypto_scalarmult_scalarbytes() { return crypto_scalarmult_curve25519_scalarbytes(); }
|
|
|
|
inline const char* crypto_scalarmult_primitive() { return "curve25519"; }
|
|
|
|
inline int crypto_scalarmult_base(uint8_t out[], const uint8_t scalar[])
|
|
{
|
|
return crypto_scalarmult_curve25519_base(out, scalar);
|
|
}
|
|
|
|
inline int crypto_scalarmult(uint8_t out[], const uint8_t scalar[], const uint8_t base[])
|
|
{
|
|
return crypto_scalarmult_curve25519(out, scalar, base);
|
|
}
|
|
|
|
// sodium/crypto_stream_chacha20.h
|
|
|
|
inline size_t crypto_stream_chacha20_keybytes()
|
|
{
|
|
return crypto_stream_chacha20_KEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_stream_chacha20_noncebytes()
|
|
{
|
|
return crypto_stream_chacha20_NONCEBYTES;
|
|
}
|
|
|
|
inline size_t crypto_stream_chacha20_messagebytes_max()
|
|
{
|
|
return crypto_stream_chacha20_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_chacha20(uint8_t out[], size_t ctext_len,
|
|
const uint8_t nonce[], const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_chacha20_xor(uint8_t out[], const uint8_t ptext[],
|
|
size_t ptext_len, const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_chacha20_xor_ic(uint8_t out[], const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t nonce[], uint64_t ic,
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_stream_chacha20_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, 32);
|
|
}
|
|
|
|
inline size_t crypto_stream_chacha20_ietf_keybytes()
|
|
{
|
|
return crypto_stream_chacha20_ietf_KEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_stream_chacha20_ietf_noncebytes()
|
|
{
|
|
return crypto_stream_chacha20_ietf_NONCEBYTES;
|
|
}
|
|
|
|
inline size_t crypto_stream_chacha20_ietf_messagebytes_max()
|
|
{
|
|
return crypto_stream_chacha20_ietf_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_chacha20_ietf(uint8_t out[], size_t ctext_len,
|
|
const uint8_t nonce[], const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_chacha20_ietf_xor(uint8_t out[], const uint8_t ptext[],
|
|
size_t ptext_len, const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_chacha20_ietf_xor_ic(uint8_t out[], const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t nonce[], uint32_t ic,
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_stream_chacha20_ietf_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, 32);
|
|
}
|
|
|
|
// sodium/crypto_stream_xchacha20.h
|
|
|
|
inline size_t crypto_stream_xchacha20_keybytes()
|
|
{
|
|
return crypto_stream_xchacha20_KEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_stream_xchacha20_noncebytes()
|
|
{
|
|
return crypto_stream_xchacha20_NONCEBYTES;
|
|
}
|
|
|
|
inline size_t crypto_stream_xchacha20_messagebytes_max()
|
|
{
|
|
return crypto_stream_xchacha20_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_xchacha20(uint8_t out[], size_t ctext_len,
|
|
const uint8_t nonce[], const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_xchacha20_xor(uint8_t out[], const uint8_t ptext[],
|
|
size_t ptext_len, const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_xchacha20_xor_ic(uint8_t out[], const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t nonce[], uint64_t ic,
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_stream_xchacha20_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, crypto_stream_xchacha20_KEYBYTES);
|
|
}
|
|
|
|
// sodium/crypto_stream_salsa20.h
|
|
|
|
inline size_t crypto_stream_salsa20_keybytes()
|
|
{
|
|
return crypto_stream_xsalsa20_KEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_stream_salsa20_noncebytes()
|
|
{
|
|
return crypto_stream_salsa20_NONCEBYTES;
|
|
}
|
|
|
|
inline size_t crypto_stream_salsa20_messagebytes_max()
|
|
{
|
|
return crypto_stream_salsa20_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_salsa20(uint8_t out[], size_t ctext_len,
|
|
const uint8_t nonce[], const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_salsa20_xor(uint8_t out[], const uint8_t ptext[],
|
|
size_t ptext_len, const uint8_t nonce[],
|
|
const uint8_t key[]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_stream_salsa20_xor_ic(uint8_t out[], const uint8_t ptext[],
|
|
size_t ptext_len,
|
|
const uint8_t nonce[], uint64_t ic,
|
|
const uint8_t key[]);
|
|
|
|
inline void crypto_stream_salsa20_keygen(uint8_t k[32])
|
|
{
|
|
return randombytes_buf(k, 32);
|
|
}
|
|
|
|
// sodium/crypto_stream.h
|
|
|
|
inline size_t crypto_stream_keybytes() { return crypto_stream_xsalsa20_keybytes(); }
|
|
|
|
inline size_t crypto_stream_noncebytes() { return crypto_stream_xsalsa20_noncebytes(); }
|
|
|
|
inline size_t crypto_stream_messagebytes_max() { return crypto_stream_MESSAGEBYTES_MAX; }
|
|
|
|
inline const char* crypto_stream_primitive() { return "xsalsa20"; }
|
|
|
|
inline int crypto_stream(uint8_t out[], size_t out_len,
|
|
const uint8_t nonce[24], const uint8_t key[32])
|
|
{
|
|
return crypto_stream_xsalsa20(out, out_len, nonce, key);
|
|
}
|
|
|
|
inline int crypto_stream_xor(uint8_t out[], const uint8_t in[], size_t in_len,
|
|
const uint8_t nonce[24], const uint8_t key[32])
|
|
{
|
|
return crypto_stream_xsalsa20_xor(out, in, in_len, nonce, key);
|
|
}
|
|
|
|
inline void crypto_stream_keygen(uint8_t key[32])
|
|
{
|
|
return randombytes_buf(key, 32);
|
|
}
|
|
|
|
// sodium/crypto_shorthash_siphash24.h
|
|
|
|
inline size_t crypto_shorthash_siphash24_bytes() { return crypto_shorthash_siphash24_BYTES; }
|
|
|
|
inline size_t crypto_shorthash_siphash24_keybytes() { return crypto_shorthash_siphash24_KEYBYTES; }
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_shorthash_siphash24(uint8_t out[8], const uint8_t in[], size_t in_len, const uint8_t key[16]);
|
|
|
|
// sodium/crypto_shorthash.h
|
|
|
|
inline size_t crypto_shorthash_bytes() { return crypto_shorthash_siphash24_bytes(); }
|
|
|
|
inline size_t crypto_shorthash_keybytes() { return crypto_shorthash_siphash24_keybytes(); }
|
|
|
|
inline const char* crypto_shorthash_primitive() { return "siphash24"; }
|
|
|
|
inline int crypto_shorthash(uint8_t out[], const uint8_t in[],
|
|
size_t in_len, const uint8_t k[16])
|
|
{
|
|
return crypto_shorthash_siphash24(out, in, in_len, k);
|
|
}
|
|
|
|
inline void crypto_shorthash_keygen(uint8_t k[16])
|
|
{
|
|
randombytes_buf(k, crypto_shorthash_siphash24_KEYBYTES);
|
|
}
|
|
|
|
// sodium/crypto_sign_ed25519.h
|
|
|
|
inline size_t crypto_sign_ed25519_bytes()
|
|
{
|
|
return crypto_sign_ed25519_BYTES;
|
|
}
|
|
|
|
inline size_t crypto_sign_ed25519_seedbytes()
|
|
{
|
|
return crypto_sign_ed25519_SEEDBYTES;
|
|
}
|
|
|
|
inline size_t crypto_sign_ed25519_publickeybytes()
|
|
{
|
|
return crypto_sign_ed25519_PUBLICKEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_sign_ed25519_secretkeybytes()
|
|
{
|
|
return crypto_sign_ed25519_SECRETKEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_sign_ed25519_messagebytes_max()
|
|
{
|
|
return crypto_sign_ed25519_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_sign_ed25519_detached(uint8_t sig[],
|
|
unsigned long long* sig_len,
|
|
const uint8_t msg[],
|
|
size_t msg_len,
|
|
const uint8_t sk[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_sign_ed25519_verify_detached(const uint8_t sig[],
|
|
const uint8_t msg[],
|
|
size_t msg_len,
|
|
const uint8_t pk[32]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_sign_ed25519_keypair(uint8_t pk[32], uint8_t sk[64]);
|
|
|
|
BOTAN_PUBLIC_API(2,11)
|
|
int crypto_sign_ed25519_seed_keypair(uint8_t pk[], uint8_t sk[],
|
|
const uint8_t seed[]);
|
|
|
|
// sodium/crypto_sign.h
|
|
|
|
inline size_t crypto_sign_bytes()
|
|
{
|
|
return crypto_sign_BYTES;
|
|
}
|
|
|
|
inline size_t crypto_sign_seedbytes()
|
|
{
|
|
return crypto_sign_SEEDBYTES;
|
|
}
|
|
|
|
inline size_t crypto_sign_publickeybytes()
|
|
{
|
|
return crypto_sign_PUBLICKEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_sign_secretkeybytes()
|
|
{
|
|
return crypto_sign_SECRETKEYBYTES;
|
|
}
|
|
|
|
inline size_t crypto_sign_messagebytes_max()
|
|
{
|
|
return crypto_sign_MESSAGEBYTES_MAX;
|
|
}
|
|
|
|
inline const char* crypto_sign_primitive()
|
|
{
|
|
return "ed25519";
|
|
}
|
|
|
|
inline int crypto_sign_seed_keypair(uint8_t pk[32], uint8_t sk[32],
|
|
const uint8_t seed[])
|
|
{
|
|
return crypto_sign_ed25519_seed_keypair(pk, sk, seed);
|
|
}
|
|
|
|
inline int crypto_sign_keypair(uint8_t pk[32], uint8_t sk[32])
|
|
{
|
|
return crypto_sign_ed25519_keypair(pk, sk);
|
|
}
|
|
|
|
inline int crypto_sign_detached(uint8_t sig[], unsigned long long* sig_len,
|
|
const uint8_t msg[], size_t msg_len,
|
|
const uint8_t sk[32])
|
|
{
|
|
return crypto_sign_ed25519_detached(sig, sig_len, msg, msg_len, sk);
|
|
}
|
|
|
|
inline int crypto_sign_verify_detached(const uint8_t sig[],
|
|
const uint8_t in[],
|
|
size_t in_len,
|
|
const uint8_t pk[32])
|
|
{
|
|
return crypto_sign_ed25519_verify_detached(sig, in, in_len, pk);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(sp800_108.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* NIST SP 800-108 KDF in Counter Mode (5.1)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SP800_108_Counter final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override { return "SP800-108-Counter(" + m_prf->name() + ")"; }
|
|
|
|
KDF* clone() const override { return new SP800_108_Counter(m_prf->clone()); }
|
|
|
|
/**
|
|
* Derive a key using the SP800-108 KDF in Counter mode.
|
|
*
|
|
* The implementation hard codes the length of [L]_2
|
|
* and [i]_2 (the value r) to 32 bits.
|
|
*
|
|
* @param key resulting keying material
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret K_I
|
|
* @param secret_len size of K_I in bytes
|
|
* @param salt Context
|
|
* @param salt_len size of Context in bytes
|
|
* @param label Label
|
|
* @param label_len size of Label in bytes
|
|
*
|
|
* @throws Invalid_Argument key_len > 2^32
|
|
*/
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
/**
|
|
* @param mac MAC algorithm to use
|
|
*/
|
|
explicit SP800_108_Counter(MessageAuthenticationCode* mac) : m_prf(mac) {}
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_prf;
|
|
};
|
|
|
|
/**
|
|
* NIST SP 800-108 KDF in Feedback Mode (5.2)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SP800_108_Feedback final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override { return "SP800-108-Feedback(" + m_prf->name() + ")"; }
|
|
|
|
KDF* clone() const override { return new SP800_108_Feedback(m_prf->clone()); }
|
|
|
|
/**
|
|
* Derive a key using the SP800-108 KDF in Feedback mode.
|
|
*
|
|
* The implementation uses the optional counter i and hard
|
|
* codes the length of [L]_2 and [i]_2 (the value r) to 32 bits.
|
|
*
|
|
* @param key resulting keying material
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret K_I
|
|
* @param secret_len size of K_I in bytes
|
|
* @param salt IV || Context
|
|
* @param salt_len size of Context plus IV in bytes
|
|
* @param label Label
|
|
* @param label_len size of Label in bytes
|
|
*
|
|
* @throws Invalid_Argument key_len > 2^32
|
|
*/
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
explicit SP800_108_Feedback(MessageAuthenticationCode* mac) : m_prf(mac) {}
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_prf;
|
|
};
|
|
|
|
/**
|
|
* NIST SP 800-108 KDF in Double Pipeline Mode (5.3)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SP800_108_Pipeline final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override { return "SP800-108-Pipeline(" + m_prf->name() + ")"; }
|
|
|
|
KDF* clone() const override { return new SP800_108_Pipeline(m_prf->clone()); }
|
|
|
|
/**
|
|
* Derive a key using the SP800-108 KDF in Double Pipeline mode.
|
|
*
|
|
* The implementation uses the optional counter i and hard
|
|
* codes the length of [L]_2 and [i]_2 (the value r) to 32 bits.
|
|
*
|
|
* @param key resulting keying material
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret K_I
|
|
* @param secret_len size of K_I in bytes
|
|
* @param salt Context
|
|
* @param salt_len size of Context in bytes
|
|
* @param label Label
|
|
* @param label_len size of Label in bytes
|
|
*
|
|
* @throws Invalid_Argument key_len > 2^32
|
|
*/
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
explicit SP800_108_Pipeline(MessageAuthenticationCode* mac) : m_prf(mac) {}
|
|
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_prf;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(sp800_56a.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* NIST SP 800-56A KDF using hash function
|
|
* @warning This KDF ignores the provided salt value
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) SP800_56A_Hash final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override { return "SP800-56A(" + m_hash->name() + ")"; }
|
|
|
|
KDF* clone() const override { return new SP800_56A_Hash(m_hash->clone()); }
|
|
|
|
/**
|
|
* Derive a key using the SP800-56A KDF.
|
|
*
|
|
* The implementation hard codes the context value for the
|
|
* expansion step to the empty string.
|
|
*
|
|
* @param key derived keying material K_M
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret shared secret Z
|
|
* @param secret_len size of Z in bytes
|
|
* @param salt ignored
|
|
* @param salt_len ignored
|
|
* @param label label for the expansion step
|
|
* @param label_len size of label in bytes
|
|
*
|
|
* @throws Invalid_Argument key_len > 2^32
|
|
*/
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
/**
|
|
* @param hash the hash function to use as the auxiliary function
|
|
*/
|
|
explicit SP800_56A_Hash(HashFunction* hash) : m_hash(hash) {}
|
|
private:
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
};
|
|
|
|
/**
|
|
* NIST SP 800-56A KDF using HMAC
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) SP800_56A_HMAC final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override { return "SP800-56A(" + m_mac->name() + ")"; }
|
|
|
|
KDF* clone() const override { return new SP800_56A_HMAC(m_mac->clone()); }
|
|
|
|
/**
|
|
* Derive a key using the SP800-56A KDF.
|
|
*
|
|
* The implementation hard codes the context value for the
|
|
* expansion step to the empty string.
|
|
*
|
|
* @param key derived keying material K_M
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret shared secret Z
|
|
* @param secret_len size of Z in bytes
|
|
* @param salt ignored
|
|
* @param salt_len ignored
|
|
* @param label label for the expansion step
|
|
* @param label_len size of label in bytes
|
|
*
|
|
* @throws Invalid_Argument key_len > 2^32 or MAC is not a HMAC
|
|
*/
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
/**
|
|
* @param mac the HMAC to use as the auxiliary function
|
|
*/
|
|
explicit SP800_56A_HMAC(MessageAuthenticationCode* mac);
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_mac;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(sp800_56c.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* NIST SP 800-56C KDF
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SP800_56C final : public KDF
|
|
{
|
|
public:
|
|
std::string name() const override { return "SP800-56C(" + m_prf->name() + ")"; }
|
|
|
|
KDF* clone() const override { return new SP800_56C(m_prf->clone(), m_exp->clone()); }
|
|
|
|
/**
|
|
* Derive a key using the SP800-56C KDF.
|
|
*
|
|
* The implementation hard codes the context value for the
|
|
* expansion step to the empty string.
|
|
*
|
|
* @param key derived keying material K_M
|
|
* @param key_len the desired output length in bytes
|
|
* @param secret shared secret Z
|
|
* @param secret_len size of Z in bytes
|
|
* @param salt salt s of the extraction step
|
|
* @param salt_len size of s in bytes
|
|
* @param label label for the expansion step
|
|
* @param label_len size of label in bytes
|
|
*
|
|
* @throws Invalid_Argument key_len > 2^32
|
|
*/
|
|
size_t kdf(uint8_t key[], size_t key_len,
|
|
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 override;
|
|
|
|
/**
|
|
* @param mac MAC algorithm used for randomness extraction
|
|
* @param exp KDF used for key expansion
|
|
*/
|
|
SP800_56C(MessageAuthenticationCode* mac, KDF* exp) : m_prf(mac), m_exp(exp) {}
|
|
private:
|
|
std::unique_ptr<MessageAuthenticationCode> m_prf;
|
|
std::unique_ptr<KDF> m_exp;
|
|
};
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class DL_Group;
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* SRP6a Client side
|
|
* @param username the username we are attempting login for
|
|
* @param password the password we are attempting to use
|
|
* @param group_id specifies the shared SRP group
|
|
* @param hash_id specifies a secure hash function
|
|
* @param salt is the salt value sent by the server
|
|
* @param B is the server's public value
|
|
* @param rng is a random number generator
|
|
*
|
|
* @return (A,K) the client public key and the shared secret key
|
|
*/
|
|
std::pair<BigInt,SymmetricKey>
|
|
BOTAN_PUBLIC_API(2,0) 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);
|
|
|
|
|
|
/**
|
|
* SRP6a Client side
|
|
* @param username the username we are attempting login for
|
|
* @param password the password we are attempting to use
|
|
* @param group specifies the shared SRP group
|
|
* @param hash_id specifies a secure hash function
|
|
* @param salt is the salt value sent by the server
|
|
* @param B is the server's public value
|
|
* @param a_bits size of secret exponent in bits
|
|
* @param rng is a random number generator
|
|
*
|
|
* @return (A,K) the client public key and the shared secret key
|
|
*/
|
|
std::pair<BigInt,SymmetricKey> BOTAN_PUBLIC_API(2,11)
|
|
srp6_client_agree(const std::string& username,
|
|
const std::string& password,
|
|
const DL_Group& group,
|
|
const std::string& hash_id,
|
|
const std::vector<uint8_t>& salt,
|
|
const BigInt& B,
|
|
size_t a_bits,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Generate a new SRP-6 verifier
|
|
* @param identifier a username or other client identifier
|
|
* @param password the secret used to authenticate user
|
|
* @param salt a randomly chosen value, at least 128 bits long
|
|
* @param group_id specifies the shared SRP group
|
|
* @param hash_id specifies a secure hash function
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,0)
|
|
generate_srp6_verifier(const std::string& identifier,
|
|
const std::string& password,
|
|
const std::vector<uint8_t>& salt,
|
|
const std::string& group_id,
|
|
const std::string& hash_id);
|
|
|
|
/**
|
|
* Generate a new SRP-6 verifier
|
|
* @param identifier a username or other client identifier
|
|
* @param password the secret used to authenticate user
|
|
* @param salt a randomly chosen value, at least 128 bits long
|
|
* @param group specifies the shared SRP group
|
|
* @param hash_id specifies a secure hash function
|
|
*/
|
|
BigInt BOTAN_PUBLIC_API(2,11)
|
|
generate_srp6_verifier(const std::string& identifier,
|
|
const std::string& password,
|
|
const std::vector<uint8_t>& salt,
|
|
const DL_Group& group,
|
|
const std::string& hash_id);
|
|
|
|
/**
|
|
* Return the group id for this SRP param set, or else thrown an
|
|
* exception
|
|
* @param N the group modulus
|
|
* @param g the group generator
|
|
* @return group identifier
|
|
*/
|
|
std::string BOTAN_PUBLIC_API(2,0) srp6_group_identifier(const BigInt& N, const BigInt& g);
|
|
|
|
/**
|
|
* Represents a SRP-6a server session
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) SRP6_Server_Session final
|
|
{
|
|
public:
|
|
/**
|
|
* Server side step 1
|
|
* @param v the verification value saved from client registration
|
|
* @param group_id the SRP group id
|
|
* @param hash_id the SRP hash in use
|
|
* @param rng a random number generator
|
|
* @return SRP-6 B value
|
|
*/
|
|
BigInt step1(const BigInt& v,
|
|
const std::string& group_id,
|
|
const std::string& hash_id,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Server side step 1
|
|
* This version of step1 added in 2.11
|
|
*
|
|
* @param v the verification value saved from client registration
|
|
* @param group the SRP group
|
|
* @param hash_id the SRP hash in use
|
|
* @param rng a random number generator
|
|
* @param b_bits size of secret exponent in bits
|
|
* @return SRP-6 B value
|
|
*/
|
|
BigInt step1(const BigInt& v,
|
|
const DL_Group& group,
|
|
const std::string& hash_id,
|
|
const size_t b_bits,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Server side step 2
|
|
* @param A the client's value
|
|
* @return shared symmetric key
|
|
*/
|
|
SymmetricKey step2(const BigInt& A);
|
|
|
|
private:
|
|
std::string m_hash_id;
|
|
BigInt m_B, m_b, m_v, m_S, m_p;
|
|
size_t m_p_bytes = 0;
|
|
};
|
|
|
|
}
|
|
|
|
#if __cplusplus < 201402L
|
|
#endif
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(stl_compatability.h)
|
|
|
|
namespace Botan
|
|
{
|
|
/*
|
|
* std::make_unique functionality similar as we have in C++14.
|
|
* C++11 version based on proposal for C++14 implemenatation by Stephan T. Lavavej
|
|
* source: https://isocpp.org/files/papers/N3656.txt
|
|
*/
|
|
#if __cplusplus >= 201402L
|
|
template <typename T, typename ... Args>
|
|
constexpr auto make_unique(Args&&... args)
|
|
{
|
|
return std::make_unique<T>(std::forward<Args>(args)...);
|
|
}
|
|
|
|
template<class T>
|
|
constexpr auto make_unique(std::size_t size)
|
|
{
|
|
return std::make_unique<T>(size);
|
|
}
|
|
|
|
#else
|
|
namespace stlCompatibilityDetails
|
|
{
|
|
template<class T> struct _Unique_if
|
|
{
|
|
typedef std::unique_ptr<T> _Single_object;
|
|
};
|
|
|
|
template<class T> struct _Unique_if<T[]>
|
|
{
|
|
typedef std::unique_ptr<T[]> _Unknown_bound;
|
|
};
|
|
|
|
template<class T, size_t N> struct _Unique_if<T[N]>
|
|
{
|
|
typedef void _Known_bound;
|
|
};
|
|
} // namespace stlCompatibilityDetails
|
|
|
|
template<class T, class... Args>
|
|
typename stlCompatibilityDetails::_Unique_if<T>::_Single_object make_unique(Args&&... args)
|
|
{
|
|
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
|
}
|
|
|
|
template<class T>
|
|
typename stlCompatibilityDetails::_Unique_if<T>::_Unknown_bound make_unique(size_t n)
|
|
{
|
|
typedef typename std::remove_extent<T>::type U;
|
|
return std::unique_ptr<T>(new U[n]());
|
|
}
|
|
|
|
template<class T, class... Args>
|
|
typename stlCompatibilityDetails::_Unique_if<T>::_Known_bound make_unique(Args&&...) = delete;
|
|
|
|
#endif
|
|
|
|
} // namespace Botan
|
|
|
|
#if defined(BOTAN_HAS_STREAM_CIPHER)
|
|
#endif
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(stream_mode.h)
|
|
|
|
namespace Botan {
|
|
|
|
#if defined(BOTAN_HAS_STREAM_CIPHER)
|
|
|
|
class BOTAN_PUBLIC_API(2,0) Stream_Cipher_Mode final : public Cipher_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher underyling stream cipher
|
|
*/
|
|
explicit Stream_Cipher_Mode(StreamCipher* cipher) : m_cipher(cipher) {}
|
|
|
|
size_t process(uint8_t buf[], size_t sz) override
|
|
{
|
|
m_cipher->cipher1(buf, sz);
|
|
return sz;
|
|
}
|
|
|
|
void finish(secure_vector<uint8_t>& buf, size_t offset) override
|
|
{ return update(buf, offset); }
|
|
|
|
size_t output_length(size_t input_length) const override { return input_length; }
|
|
|
|
size_t update_granularity() const override { return 1; }
|
|
|
|
size_t minimum_final_size() const override { return 0; }
|
|
|
|
size_t default_nonce_length() const override { return 0; }
|
|
|
|
bool valid_nonce_length(size_t nonce_len) const override
|
|
{ return m_cipher->valid_iv_length(nonce_len); }
|
|
|
|
Key_Length_Specification key_spec() const override { return m_cipher->key_spec(); }
|
|
|
|
std::string name() const override { return m_cipher->name(); }
|
|
|
|
void clear() override
|
|
{
|
|
m_cipher->clear();
|
|
reset();
|
|
}
|
|
|
|
void reset() override { /* no msg state */ }
|
|
|
|
private:
|
|
void start_msg(const uint8_t nonce[], size_t nonce_len) override
|
|
{
|
|
if(nonce_len > 0)
|
|
{
|
|
m_cipher->set_iv(nonce, nonce_len);
|
|
}
|
|
}
|
|
|
|
void key_schedule(const uint8_t key[], size_t length) override
|
|
{
|
|
m_cipher->set_key(key, length);
|
|
}
|
|
|
|
std::unique_ptr<StreamCipher> m_cipher;
|
|
};
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(streebog.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Streebog (GOST R 34.11-2012)
|
|
* RFC 6986
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) Streebog : public HashFunction
|
|
{
|
|
public:
|
|
size_t output_length() const override { return m_output_bits / 8; }
|
|
|
|
HashFunction* clone() const override { return new Streebog(m_output_bits); }
|
|
void clear() override;
|
|
std::string name() const override;
|
|
size_t hash_block_size() const override { return 64; }
|
|
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
explicit Streebog(size_t output_bits);
|
|
protected:
|
|
void add_data(const uint8_t input[], size_t length) override;
|
|
void final_result(uint8_t out[]) override;
|
|
|
|
void compress(const uint8_t input[], bool lastblock = false);
|
|
|
|
void compress_64(const uint64_t input[], bool lastblock = false);
|
|
|
|
private:
|
|
const size_t m_output_bits;
|
|
uint64_t m_count;
|
|
size_t m_position;
|
|
secure_vector<uint8_t> m_buffer;
|
|
secure_vector<uint64_t> m_h;
|
|
secure_vector<uint64_t> m_S;
|
|
};
|
|
|
|
|
|
/**
|
|
* Streebog-256
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) Streebog_256 final : public Streebog
|
|
{
|
|
public:
|
|
Streebog_256() : Streebog(256) {}
|
|
};
|
|
|
|
/**
|
|
* Streebog-512
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,2) Streebog_512 final : public Streebog
|
|
{
|
|
public:
|
|
Streebog_512() : Streebog(512) {}
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(tiger.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Tiger
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Tiger final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override;
|
|
size_t output_length() const override { return m_hash_len; }
|
|
|
|
HashFunction* clone() const override
|
|
{
|
|
return new Tiger(output_length(), m_passes);
|
|
}
|
|
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override;
|
|
|
|
/**
|
|
* @param out_size specifies the output length; can be 16, 20, or 24
|
|
* @param passes to make in the algorithm
|
|
*/
|
|
Tiger(size_t out_size = 24, size_t passes = 3);
|
|
private:
|
|
void compress_n(const uint8_t[], size_t block) override;
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
static void pass(uint64_t& A, uint64_t& B, uint64_t& C,
|
|
const secure_vector<uint64_t>& M,
|
|
uint8_t mul);
|
|
|
|
static const uint64_t SBOX1[256];
|
|
static const uint64_t SBOX2[256];
|
|
static const uint64_t SBOX3[256];
|
|
static const uint64_t SBOX4[256];
|
|
|
|
secure_vector<uint64_t> m_X, m_digest;
|
|
const size_t m_hash_len, m_passes;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* SSL/TLS Alert Message
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Alert final
|
|
{
|
|
public:
|
|
/**
|
|
* Type codes for TLS alerts
|
|
*/
|
|
enum Type {
|
|
CLOSE_NOTIFY = 0,
|
|
UNEXPECTED_MESSAGE = 10,
|
|
BAD_RECORD_MAC = 20,
|
|
DECRYPTION_FAILED = 21,
|
|
RECORD_OVERFLOW = 22,
|
|
DECOMPRESSION_FAILURE = 30,
|
|
HANDSHAKE_FAILURE = 40,
|
|
NO_CERTIFICATE = 41, // SSLv3 only
|
|
BAD_CERTIFICATE = 42,
|
|
UNSUPPORTED_CERTIFICATE = 43,
|
|
CERTIFICATE_REVOKED = 44,
|
|
CERTIFICATE_EXPIRED = 45,
|
|
CERTIFICATE_UNKNOWN = 46,
|
|
ILLEGAL_PARAMETER = 47,
|
|
UNKNOWN_CA = 48,
|
|
ACCESS_DENIED = 49,
|
|
DECODE_ERROR = 50,
|
|
DECRYPT_ERROR = 51,
|
|
EXPORT_RESTRICTION = 60,
|
|
PROTOCOL_VERSION = 70,
|
|
INSUFFICIENT_SECURITY = 71,
|
|
INTERNAL_ERROR = 80,
|
|
INAPPROPRIATE_FALLBACK = 86,
|
|
USER_CANCELED = 90,
|
|
NO_RENEGOTIATION = 100,
|
|
UNSUPPORTED_EXTENSION = 110,
|
|
CERTIFICATE_UNOBTAINABLE = 111,
|
|
UNRECOGNIZED_NAME = 112,
|
|
BAD_CERTIFICATE_STATUS_RESPONSE = 113,
|
|
BAD_CERTIFICATE_HASH_VALUE = 114,
|
|
UNKNOWN_PSK_IDENTITY = 115,
|
|
CERTIFICATE_REQUIRED = 116, // RFC 8446
|
|
|
|
NO_APPLICATION_PROTOCOL = 120, // RFC 7301
|
|
|
|
// pseudo alert values
|
|
NULL_ALERT = 256
|
|
};
|
|
|
|
/**
|
|
* @return true iff this alert is non-empty
|
|
*/
|
|
bool is_valid() const { return (m_type_code != NULL_ALERT); }
|
|
|
|
/**
|
|
* @return if this alert is a fatal one or not
|
|
*/
|
|
bool is_fatal() const { return m_fatal; }
|
|
|
|
/**
|
|
* @return type of alert
|
|
*/
|
|
Type type() const { return m_type_code; }
|
|
|
|
/**
|
|
* @return type of alert
|
|
*/
|
|
std::string type_string() const;
|
|
|
|
/**
|
|
* Serialize an alert
|
|
*/
|
|
std::vector<uint8_t> serialize() const;
|
|
|
|
/**
|
|
* Deserialize an Alert message
|
|
* @param buf the serialized alert
|
|
*/
|
|
explicit Alert(const secure_vector<uint8_t>& buf);
|
|
|
|
/**
|
|
* Create a new Alert
|
|
* @param type_code the type of alert
|
|
* @param fatal specifies if this is a fatal alert
|
|
*/
|
|
Alert(Type type_code, bool fatal = false) :
|
|
m_fatal(fatal), m_type_code(type_code) {}
|
|
|
|
Alert() : m_fatal(false), m_type_code(NULL_ALERT) {}
|
|
private:
|
|
bool m_fatal;
|
|
Type m_type_code;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//BOTAN_FUTURE_INTERNAL_HEADER(tls_algos.h)
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
enum class Cipher_Algo {
|
|
CHACHA20_POLY1305,
|
|
|
|
AES_128_CBC_HMAC_SHA1 = 100,
|
|
AES_128_CBC_HMAC_SHA256,
|
|
AES_128_CCM,
|
|
AES_128_CCM_8,
|
|
AES_128_GCM,
|
|
AES_128_OCB,
|
|
|
|
AES_256_CBC_HMAC_SHA1 = 200,
|
|
AES_256_CBC_HMAC_SHA256,
|
|
AES_256_CBC_HMAC_SHA384,
|
|
AES_256_CCM,
|
|
AES_256_CCM_8,
|
|
AES_256_GCM,
|
|
AES_256_OCB,
|
|
|
|
CAMELLIA_128_CBC_HMAC_SHA1 = 300,
|
|
CAMELLIA_128_CBC_HMAC_SHA256,
|
|
CAMELLIA_128_GCM,
|
|
|
|
CAMELLIA_256_CBC_HMAC_SHA1 = 400,
|
|
CAMELLIA_256_CBC_HMAC_SHA256,
|
|
CAMELLIA_256_CBC_HMAC_SHA384,
|
|
CAMELLIA_256_GCM,
|
|
|
|
ARIA_128_GCM = 500,
|
|
ARIA_256_GCM,
|
|
|
|
DES_EDE_CBC_HMAC_SHA1 = 1000,
|
|
SEED_CBC_HMAC_SHA1,
|
|
};
|
|
|
|
enum class KDF_Algo {
|
|
SHA_1,
|
|
SHA_256,
|
|
SHA_384,
|
|
};
|
|
|
|
std::string BOTAN_DLL kdf_algo_to_string(KDF_Algo algo);
|
|
|
|
enum class Nonce_Format {
|
|
CBC_MODE,
|
|
AEAD_IMPLICIT_4,
|
|
AEAD_XOR_12,
|
|
};
|
|
|
|
// TODO encoding should match signature_algorithms extension
|
|
// TODO this should include hash etc as in TLS v1.3
|
|
enum class Auth_Method {
|
|
RSA,
|
|
DSA,
|
|
ECDSA,
|
|
|
|
// These are placed outside the encodable range
|
|
IMPLICIT = 0x10000,
|
|
ANONYMOUS
|
|
};
|
|
|
|
std::string BOTAN_TEST_API auth_method_to_string(Auth_Method method);
|
|
Auth_Method BOTAN_TEST_API auth_method_from_string(const std::string& str);
|
|
|
|
/*
|
|
* This matches the wire encoding
|
|
*/
|
|
enum class Signature_Scheme : uint16_t {
|
|
NONE = 0x0000,
|
|
|
|
RSA_PKCS1_SHA1 = 0x0201,
|
|
RSA_PKCS1_SHA256 = 0x0401,
|
|
RSA_PKCS1_SHA384 = 0x0501,
|
|
RSA_PKCS1_SHA512 = 0x0601,
|
|
|
|
DSA_SHA1 = 0x0202,
|
|
DSA_SHA256 = 0x0402,
|
|
DSA_SHA384 = 0x0502,
|
|
DSA_SHA512 = 0x0602,
|
|
|
|
ECDSA_SHA1 = 0x0203,
|
|
ECDSA_SHA256 = 0x0403,
|
|
ECDSA_SHA384 = 0x0503,
|
|
ECDSA_SHA512 = 0x0603,
|
|
|
|
RSA_PSS_SHA256 = 0x0804,
|
|
RSA_PSS_SHA384 = 0x0805,
|
|
RSA_PSS_SHA512 = 0x0806,
|
|
|
|
EDDSA_25519 = 0x0807,
|
|
EDDSA_448 = 0x0808,
|
|
};
|
|
|
|
BOTAN_UNSTABLE_API const std::vector<Signature_Scheme>& all_signature_schemes();
|
|
|
|
bool BOTAN_UNSTABLE_API signature_scheme_is_known(Signature_Scheme scheme);
|
|
std::string BOTAN_UNSTABLE_API sig_scheme_to_string(Signature_Scheme scheme);
|
|
std::string BOTAN_UNSTABLE_API hash_function_of_scheme(Signature_Scheme scheme);
|
|
std::string BOTAN_UNSTABLE_API padding_string_for_scheme(Signature_Scheme scheme);
|
|
std::string signature_algorithm_of_scheme(Signature_Scheme scheme);
|
|
|
|
/*
|
|
* Matches with wire encoding
|
|
*/
|
|
enum class Group_Params : uint16_t {
|
|
NONE = 0,
|
|
|
|
SECP256R1 = 23,
|
|
SECP384R1 = 24,
|
|
SECP521R1 = 25,
|
|
BRAINPOOL256R1 = 26,
|
|
BRAINPOOL384R1 = 27,
|
|
BRAINPOOL512R1 = 28,
|
|
|
|
X25519 = 29,
|
|
|
|
FFDHE_2048 = 256,
|
|
FFDHE_3072 = 257,
|
|
FFDHE_4096 = 258,
|
|
FFDHE_6144 = 259,
|
|
FFDHE_8192 = 260,
|
|
};
|
|
|
|
std::string group_param_to_string(Group_Params group);
|
|
Group_Params group_param_from_string(const std::string& group_name);
|
|
bool group_param_is_dh(Group_Params group);
|
|
|
|
enum class Kex_Algo {
|
|
STATIC_RSA,
|
|
DH,
|
|
ECDH,
|
|
CECPQ1,
|
|
SRP_SHA,
|
|
PSK,
|
|
DHE_PSK,
|
|
ECDHE_PSK,
|
|
};
|
|
|
|
std::string BOTAN_TEST_API kex_method_to_string(Kex_Algo method);
|
|
Kex_Algo BOTAN_TEST_API kex_method_from_string(const std::string& str);
|
|
|
|
inline bool key_exchange_is_psk(Kex_Algo m)
|
|
{
|
|
return (m == Kex_Algo::PSK ||
|
|
m == Kex_Algo::DHE_PSK ||
|
|
m == Kex_Algo::ECDHE_PSK);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* TLS Protocol Version
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Protocol_Version final
|
|
{
|
|
public:
|
|
enum Version_Code {
|
|
TLS_V10 = 0x0301,
|
|
TLS_V11 = 0x0302,
|
|
TLS_V12 = 0x0303,
|
|
|
|
DTLS_V10 = 0xFEFF,
|
|
DTLS_V12 = 0xFEFD
|
|
};
|
|
|
|
/**
|
|
* @return latest known TLS version
|
|
*/
|
|
static Protocol_Version latest_tls_version()
|
|
{
|
|
return Protocol_Version(TLS_V12);
|
|
}
|
|
|
|
/**
|
|
* @return latest known DTLS version
|
|
*/
|
|
static Protocol_Version latest_dtls_version()
|
|
{
|
|
return Protocol_Version(DTLS_V12);
|
|
}
|
|
|
|
Protocol_Version() : m_version(0) {}
|
|
|
|
explicit Protocol_Version(uint16_t code) : m_version(code) {}
|
|
|
|
/**
|
|
* @param named_version a specific named version of the protocol
|
|
*/
|
|
Protocol_Version(Version_Code named_version) :
|
|
Protocol_Version(static_cast<uint16_t>(named_version)) {}
|
|
|
|
/**
|
|
* @param major the major version
|
|
* @param minor the minor version
|
|
*/
|
|
Protocol_Version(uint8_t major, uint8_t minor) :
|
|
Protocol_Version(static_cast<uint16_t>((static_cast<uint16_t>(major) << 8) | minor)) {}
|
|
|
|
/**
|
|
* @return true if this is a valid protocol version
|
|
*/
|
|
bool valid() const { return (m_version != 0); }
|
|
|
|
/**
|
|
* @return true if this is a protocol version we know about
|
|
*/
|
|
bool known_version() const;
|
|
|
|
/**
|
|
* @return major version of the protocol version
|
|
*/
|
|
uint8_t major_version() const { return static_cast<uint8_t>(m_version >> 8); }
|
|
|
|
/**
|
|
* @return minor version of the protocol version
|
|
*/
|
|
uint8_t minor_version() const { return static_cast<uint8_t>(m_version & 0xFF); }
|
|
|
|
/**
|
|
* @return the version code
|
|
*/
|
|
uint16_t version_code() const { return m_version; }
|
|
|
|
/**
|
|
* @return human-readable description of this version
|
|
*/
|
|
std::string to_string() const;
|
|
|
|
/**
|
|
* @return true iff this is a DTLS version
|
|
*/
|
|
bool is_datagram_protocol() const;
|
|
|
|
/**
|
|
* @return true if this version supports negotiable signature algorithms
|
|
*/
|
|
bool supports_negotiable_signature_algorithms() const;
|
|
|
|
/**
|
|
* @return true if this version uses explicit IVs for block ciphers
|
|
*/
|
|
bool supports_explicit_cbc_ivs() const;
|
|
|
|
/**
|
|
* @return true if this version uses a ciphersuite specific PRF
|
|
*/
|
|
bool supports_ciphersuite_specific_prf() const;
|
|
|
|
bool supports_aead_modes() const;
|
|
|
|
/**
|
|
* @return if this version is equal to other
|
|
*/
|
|
bool operator==(const Protocol_Version& other) const
|
|
{
|
|
return (m_version == other.m_version);
|
|
}
|
|
|
|
/**
|
|
* @return if this version is not equal to other
|
|
*/
|
|
bool operator!=(const Protocol_Version& other) const
|
|
{
|
|
return (m_version != other.m_version);
|
|
}
|
|
|
|
/**
|
|
* @return if this version is later than other
|
|
*/
|
|
bool operator>(const Protocol_Version& other) const;
|
|
|
|
/**
|
|
* @return if this version is later than or equal to other
|
|
*/
|
|
bool operator>=(const Protocol_Version& other) const
|
|
{
|
|
return (*this == other || *this > other);
|
|
}
|
|
|
|
private:
|
|
uint16_t m_version;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* Ciphersuite Information
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Ciphersuite final
|
|
{
|
|
public:
|
|
/**
|
|
* Convert an SSL/TLS ciphersuite to algorithm fields
|
|
* @param suite the ciphersuite code number
|
|
* @return ciphersuite object
|
|
*/
|
|
static Ciphersuite by_id(uint16_t suite);
|
|
|
|
/**
|
|
* Convert an SSL/TLS ciphersuite name to algorithm fields
|
|
* @param name the IANA name for the desired ciphersuite
|
|
* @return ciphersuite object
|
|
*/
|
|
static Ciphersuite from_name(const std::string& name);
|
|
|
|
/**
|
|
* Returns true iff this suite is a known SCSV
|
|
*/
|
|
static bool is_scsv(uint16_t suite);
|
|
|
|
/**
|
|
* Generate a static list of all known ciphersuites and return it.
|
|
*
|
|
* @return list of all known ciphersuites
|
|
*/
|
|
static const std::vector<Ciphersuite>& all_known_ciphersuites();
|
|
|
|
/**
|
|
* Formats the ciphersuite back to an RFC-style ciphersuite string
|
|
* @return RFC ciphersuite string identifier
|
|
*/
|
|
std::string to_string() const { return m_iana_id; }
|
|
|
|
/**
|
|
* @return ciphersuite number
|
|
*/
|
|
uint16_t ciphersuite_code() const { return m_ciphersuite_code; }
|
|
|
|
/**
|
|
* @return true if this is a PSK ciphersuite
|
|
*/
|
|
bool psk_ciphersuite() const;
|
|
|
|
/**
|
|
* @return true if this is an ECC ciphersuite
|
|
*/
|
|
bool ecc_ciphersuite() const;
|
|
|
|
/**
|
|
* @return true if this suite uses a CBC cipher
|
|
*/
|
|
bool cbc_ciphersuite() const;
|
|
|
|
bool signature_used() const;
|
|
|
|
/**
|
|
* @return key exchange algorithm used by this ciphersuite
|
|
*/
|
|
std::string kex_algo() const { return kex_method_to_string(kex_method()); }
|
|
|
|
Kex_Algo kex_method() const { return m_kex_algo; }
|
|
|
|
/**
|
|
* @return signature algorithm used by this ciphersuite
|
|
*/
|
|
std::string sig_algo() const { return auth_method_to_string(auth_method()); }
|
|
|
|
Auth_Method auth_method() const { return m_auth_method; }
|
|
|
|
/**
|
|
* @return symmetric cipher algorithm used by this ciphersuite
|
|
*/
|
|
std::string cipher_algo() const { return m_cipher_algo; }
|
|
|
|
/**
|
|
* @return message authentication algorithm used by this ciphersuite
|
|
*/
|
|
std::string mac_algo() const { return m_mac_algo; }
|
|
|
|
std::string prf_algo() const
|
|
{
|
|
return kdf_algo_to_string(m_prf_algo);
|
|
}
|
|
|
|
/**
|
|
* @return cipher key length used by this ciphersuite
|
|
*/
|
|
size_t cipher_keylen() const { return m_cipher_keylen; }
|
|
|
|
size_t nonce_bytes_from_handshake() const;
|
|
|
|
size_t nonce_bytes_from_record(Protocol_Version version) const;
|
|
|
|
Nonce_Format nonce_format() const { return m_nonce_format; }
|
|
|
|
size_t mac_keylen() const { return m_mac_keylen; }
|
|
|
|
/**
|
|
* @return true if this is a valid/known ciphersuite
|
|
*/
|
|
bool valid() const { return m_usable; }
|
|
|
|
bool usable_in_version(Protocol_Version version) const;
|
|
|
|
bool operator<(const Ciphersuite& o) const { return ciphersuite_code() < o.ciphersuite_code(); }
|
|
bool operator<(const uint16_t c) const { return ciphersuite_code() < c; }
|
|
|
|
Ciphersuite() = default;
|
|
|
|
private:
|
|
|
|
bool is_usable() const;
|
|
|
|
Ciphersuite(uint16_t ciphersuite_code,
|
|
const char* iana_id,
|
|
Auth_Method auth_method,
|
|
Kex_Algo kex_algo,
|
|
const char* cipher_algo,
|
|
size_t cipher_keylen,
|
|
const char* mac_algo,
|
|
size_t mac_keylen,
|
|
KDF_Algo prf_algo,
|
|
Nonce_Format nonce_format) :
|
|
m_ciphersuite_code(ciphersuite_code),
|
|
m_iana_id(iana_id),
|
|
m_auth_method(auth_method),
|
|
m_kex_algo(kex_algo),
|
|
m_prf_algo(prf_algo),
|
|
m_nonce_format(nonce_format),
|
|
m_cipher_algo(cipher_algo),
|
|
m_mac_algo(mac_algo),
|
|
m_cipher_keylen(cipher_keylen),
|
|
m_mac_keylen(mac_keylen)
|
|
{
|
|
m_usable = is_usable();
|
|
}
|
|
|
|
uint16_t m_ciphersuite_code = 0;
|
|
|
|
/*
|
|
All of these const char* strings are references to compile time
|
|
constants in tls_suite_info.cpp
|
|
*/
|
|
const char* m_iana_id = nullptr;
|
|
|
|
Auth_Method m_auth_method = Auth_Method::ANONYMOUS;
|
|
Kex_Algo m_kex_algo = Kex_Algo::STATIC_RSA;
|
|
KDF_Algo m_prf_algo = KDF_Algo::SHA_1;
|
|
Nonce_Format m_nonce_format = Nonce_Format::CBC_MODE;
|
|
|
|
const char* m_cipher_algo = nullptr;
|
|
const char* m_mac_algo = nullptr;
|
|
|
|
size_t m_cipher_keylen = 0;
|
|
size_t m_mac_keylen = 0;
|
|
|
|
bool m_usable = false;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//BOTAN_FUTURE_INTERNAL_HEADER(tls_magic.h)
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* Protocol Constants for SSL/TLS
|
|
*/
|
|
enum Size_Limits {
|
|
TLS_HEADER_SIZE = 5,
|
|
DTLS_HEADER_SIZE = TLS_HEADER_SIZE + 8,
|
|
|
|
MAX_PLAINTEXT_SIZE = 16*1024,
|
|
MAX_COMPRESSED_SIZE = MAX_PLAINTEXT_SIZE + 1024,
|
|
MAX_CIPHERTEXT_SIZE = MAX_COMPRESSED_SIZE + 1024,
|
|
};
|
|
|
|
// This will become an enum class in a future major release
|
|
enum Connection_Side { CLIENT = 1, SERVER = 2 };
|
|
|
|
// This will become an enum class in a future major release
|
|
enum Record_Type {
|
|
CHANGE_CIPHER_SPEC = 20,
|
|
ALERT = 21,
|
|
HANDSHAKE = 22,
|
|
APPLICATION_DATA = 23,
|
|
|
|
NO_RECORD = 256
|
|
};
|
|
|
|
// This will become an enum class in a future major release
|
|
enum Handshake_Type {
|
|
HELLO_REQUEST = 0,
|
|
CLIENT_HELLO = 1,
|
|
SERVER_HELLO = 2,
|
|
HELLO_VERIFY_REQUEST = 3,
|
|
NEW_SESSION_TICKET = 4, // RFC 5077
|
|
CERTIFICATE = 11,
|
|
SERVER_KEX = 12,
|
|
CERTIFICATE_REQUEST = 13,
|
|
SERVER_HELLO_DONE = 14,
|
|
CERTIFICATE_VERIFY = 15,
|
|
CLIENT_KEX = 16,
|
|
FINISHED = 20,
|
|
|
|
CERTIFICATE_URL = 21,
|
|
CERTIFICATE_STATUS = 22,
|
|
|
|
HANDSHAKE_CCS = 254, // Not a wire value
|
|
HANDSHAKE_NONE = 255 // Null value
|
|
};
|
|
|
|
const char* handshake_type_to_string(Handshake_Type t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* Represents information known about a TLS server.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Server_Information final
|
|
{
|
|
public:
|
|
/**
|
|
* An empty server info - nothing known
|
|
*/
|
|
Server_Information() : m_hostname(""), m_service(""), m_port(0) {}
|
|
|
|
/**
|
|
* @param hostname the host's DNS name, if known
|
|
* @param port specifies the protocol port of the server (eg for
|
|
* TCP/UDP). Zero represents unknown.
|
|
*/
|
|
Server_Information(const std::string& hostname,
|
|
uint16_t port = 0) :
|
|
m_hostname(hostname), m_service(""), m_port(port) {}
|
|
|
|
/**
|
|
* @param hostname the host's DNS name, if known
|
|
* @param service is a text string of the service type
|
|
* (eg "https", "tor", or "git")
|
|
* @param port specifies the protocol port of the server (eg for
|
|
* TCP/UDP). Zero represents unknown.
|
|
*/
|
|
Server_Information(const std::string& hostname,
|
|
const std::string& service,
|
|
uint16_t port = 0) :
|
|
m_hostname(hostname), m_service(service), m_port(port) {}
|
|
|
|
/**
|
|
* @return the host's DNS name, if known
|
|
*/
|
|
std::string hostname() const { return m_hostname; }
|
|
|
|
/**
|
|
* @return text string of the service type, e.g.,
|
|
* "https", "tor", or "git"
|
|
*/
|
|
std::string service() const { return m_service; }
|
|
|
|
/**
|
|
* @return the protocol port of the server, or zero if unknown
|
|
*/
|
|
uint16_t port() const { return m_port; }
|
|
|
|
/**
|
|
* @return whether the hostname is known
|
|
*/
|
|
bool empty() const { return m_hostname.empty(); }
|
|
|
|
private:
|
|
std::string m_hostname, m_service;
|
|
uint16_t m_port;
|
|
};
|
|
|
|
inline bool operator==(const Server_Information& a, const Server_Information& b)
|
|
{
|
|
return (a.hostname() == b.hostname()) &&
|
|
(a.service() == b.service()) &&
|
|
(a.port() == b.port());
|
|
|
|
}
|
|
|
|
inline bool operator!=(const Server_Information& a, const Server_Information& b)
|
|
{
|
|
return !(a == b);
|
|
}
|
|
|
|
inline bool operator<(const Server_Information& a, const Server_Information& b)
|
|
{
|
|
if(a.hostname() != b.hostname())
|
|
return (a.hostname() < b.hostname());
|
|
if(a.service() != b.service())
|
|
return (a.service() < b.service());
|
|
if(a.port() != b.port())
|
|
return (a.port() < b.port());
|
|
return false; // equal
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* Class representing a TLS session state
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Session final
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Uninitialized session
|
|
*/
|
|
Session() :
|
|
m_start_time(std::chrono::system_clock::time_point::min()),
|
|
m_version(),
|
|
m_ciphersuite(0),
|
|
m_connection_side(static_cast<Connection_Side>(0)),
|
|
m_srtp_profile(0),
|
|
m_extended_master_secret(false),
|
|
m_encrypt_then_mac(false)
|
|
{}
|
|
|
|
/**
|
|
* New session (sets session start time)
|
|
*/
|
|
Session(const std::vector<uint8_t>& session_id,
|
|
const secure_vector<uint8_t>& master_secret,
|
|
Protocol_Version version,
|
|
uint16_t ciphersuite,
|
|
Connection_Side side,
|
|
bool supports_extended_master_secret,
|
|
bool supports_encrypt_then_mac,
|
|
const std::vector<X509_Certificate>& peer_certs,
|
|
const std::vector<uint8_t>& session_ticket,
|
|
const Server_Information& server_info,
|
|
const std::string& srp_identifier,
|
|
uint16_t srtp_profile);
|
|
|
|
/**
|
|
* Load a session from DER representation (created by DER_encode)
|
|
* @param ber DER representation buffer
|
|
* @param ber_len size of buffer in bytes
|
|
*/
|
|
Session(const uint8_t ber[], size_t ber_len);
|
|
|
|
/**
|
|
* Load a session from PEM representation (created by PEM_encode)
|
|
* @param pem PEM representation
|
|
*/
|
|
explicit Session(const std::string& pem);
|
|
|
|
/**
|
|
* Encode this session data for storage
|
|
* @warning if the master secret is compromised so is the
|
|
* session traffic
|
|
*/
|
|
secure_vector<uint8_t> DER_encode() const;
|
|
|
|
/**
|
|
* Encrypt a session (useful for serialization or session tickets)
|
|
*/
|
|
std::vector<uint8_t> encrypt(const SymmetricKey& key,
|
|
RandomNumberGenerator& rng) const;
|
|
|
|
|
|
/**
|
|
* Decrypt a session created by encrypt
|
|
* @param ctext the ciphertext returned by encrypt
|
|
* @param ctext_size the size of ctext in bytes
|
|
* @param key the same key used by the encrypting side
|
|
*/
|
|
static Session decrypt(const uint8_t ctext[],
|
|
size_t ctext_size,
|
|
const SymmetricKey& key);
|
|
|
|
/**
|
|
* Decrypt a session created by encrypt
|
|
* @param ctext the ciphertext returned by encrypt
|
|
* @param key the same key used by the encrypting side
|
|
*/
|
|
static inline Session decrypt(const std::vector<uint8_t>& ctext,
|
|
const SymmetricKey& key)
|
|
{
|
|
return Session::decrypt(ctext.data(), ctext.size(), key);
|
|
}
|
|
|
|
/**
|
|
* Encode this session data for storage
|
|
* @warning if the master secret is compromised so is the
|
|
* session traffic
|
|
*/
|
|
std::string PEM_encode() const;
|
|
|
|
/**
|
|
* Get the version of the saved session
|
|
*/
|
|
Protocol_Version version() const { return m_version; }
|
|
|
|
/**
|
|
* Get the ciphersuite code of the saved session
|
|
*/
|
|
uint16_t ciphersuite_code() const { return m_ciphersuite; }
|
|
|
|
/**
|
|
* Get the ciphersuite info of the saved session
|
|
*/
|
|
Ciphersuite ciphersuite() const { return Ciphersuite::by_id(m_ciphersuite); }
|
|
|
|
/**
|
|
* Get which side of the connection the resumed session we are/were
|
|
* acting as.
|
|
*/
|
|
Connection_Side side() const { return m_connection_side; }
|
|
|
|
/**
|
|
* Get the SRP identity (if sent by the client in the initial handshake)
|
|
*/
|
|
const std::string& srp_identifier() const { return m_srp_identifier; }
|
|
|
|
/**
|
|
* Get the saved master secret
|
|
*/
|
|
const secure_vector<uint8_t>& master_secret() const { return m_master_secret; }
|
|
|
|
/**
|
|
* Get the session identifier
|
|
*/
|
|
const std::vector<uint8_t>& session_id() const { return m_identifier; }
|
|
|
|
/**
|
|
* Get the negotiated DTLS-SRTP algorithm (RFC 5764)
|
|
*/
|
|
uint16_t dtls_srtp_profile() const { return m_srtp_profile; }
|
|
|
|
bool supports_extended_master_secret() const { return m_extended_master_secret; }
|
|
|
|
bool supports_encrypt_then_mac() const { return m_encrypt_then_mac; }
|
|
|
|
/**
|
|
* Return the certificate chain of the peer (possibly empty)
|
|
*/
|
|
const std::vector<X509_Certificate>& peer_certs() const { return m_peer_certs; }
|
|
|
|
/**
|
|
* Get the wall clock time this session began
|
|
*/
|
|
std::chrono::system_clock::time_point start_time() const { return m_start_time; }
|
|
|
|
/**
|
|
* Return how long this session has existed (in seconds)
|
|
*/
|
|
std::chrono::seconds session_age() const;
|
|
|
|
/**
|
|
* Return the session ticket the server gave us
|
|
*/
|
|
const std::vector<uint8_t>& session_ticket() const { return m_session_ticket; }
|
|
|
|
/**
|
|
* @return information about the TLS server
|
|
*/
|
|
const Server_Information& server_info() const { return m_server_info; }
|
|
|
|
private:
|
|
enum { TLS_SESSION_PARAM_STRUCT_VERSION = 20160812 };
|
|
|
|
std::chrono::system_clock::time_point m_start_time;
|
|
|
|
std::vector<uint8_t> m_identifier;
|
|
std::vector<uint8_t> m_session_ticket; // only used by client side
|
|
secure_vector<uint8_t> m_master_secret;
|
|
|
|
Protocol_Version m_version;
|
|
uint16_t m_ciphersuite;
|
|
Connection_Side m_connection_side;
|
|
uint16_t m_srtp_profile;
|
|
bool m_extended_master_secret;
|
|
bool m_encrypt_then_mac;
|
|
|
|
std::vector<X509_Certificate> m_peer_certs;
|
|
Server_Information m_server_info; // optional
|
|
std::string m_srp_identifier; // optional
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* Session_Manager is an interface to systems which can save
|
|
* session parameters for supporting session resumption.
|
|
*
|
|
* Saving sessions is done on a best-effort basis; an implementation is
|
|
* allowed to drop sessions due to space constraints.
|
|
*
|
|
* Implementations should strive to be thread safe
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Session_Manager
|
|
{
|
|
public:
|
|
/**
|
|
* Try to load a saved session (using session ID)
|
|
* @param session_id the session identifier we are trying to resume
|
|
* @param session will be set to the saved session data (if found),
|
|
or not modified if not found
|
|
* @return true if session was modified
|
|
*/
|
|
virtual bool load_from_session_id(const std::vector<uint8_t>& session_id,
|
|
Session& session) = 0;
|
|
|
|
/**
|
|
* Try to load a saved session (using info about server)
|
|
* @param info the information about the server
|
|
* @param session will be set to the saved session data (if found),
|
|
or not modified if not found
|
|
* @return true if session was modified
|
|
*/
|
|
virtual bool load_from_server_info(const Server_Information& info,
|
|
Session& session) = 0;
|
|
|
|
/**
|
|
* Remove this session id from the cache, if it exists
|
|
*/
|
|
virtual void remove_entry(const std::vector<uint8_t>& session_id) = 0;
|
|
|
|
/**
|
|
* Remove all sessions from the cache, return number of sessions deleted
|
|
*/
|
|
virtual size_t remove_all() = 0;
|
|
|
|
/**
|
|
* Save a session on a best effort basis; the manager may not in
|
|
* fact be able to save the session for whatever reason; this is
|
|
* not an error. Caller cannot assume that calling save followed
|
|
* immediately by load_from_* will result in a successful lookup.
|
|
*
|
|
* @param session to save
|
|
*/
|
|
virtual void save(const Session& session) = 0;
|
|
|
|
/**
|
|
* Return the allowed lifetime of a session; beyond this time,
|
|
* sessions are not resumed. Returns 0 if unknown/no explicit
|
|
* expiration policy.
|
|
*/
|
|
virtual std::chrono::seconds session_lifetime() const = 0;
|
|
|
|
virtual ~Session_Manager() = default;
|
|
};
|
|
|
|
/**
|
|
* An implementation of Session_Manager that does not save sessions at
|
|
* all, preventing session resumption.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Session_Manager_Noop final : public Session_Manager
|
|
{
|
|
public:
|
|
bool load_from_session_id(const std::vector<uint8_t>&, Session&) override
|
|
{ return false; }
|
|
|
|
bool load_from_server_info(const Server_Information&, Session&) override
|
|
{ return false; }
|
|
|
|
void remove_entry(const std::vector<uint8_t>&) override {}
|
|
|
|
size_t remove_all() override { return 0; }
|
|
|
|
void save(const Session&) override {}
|
|
|
|
std::chrono::seconds session_lifetime() const override
|
|
{ return std::chrono::seconds(0); }
|
|
};
|
|
|
|
/**
|
|
* An implementation of Session_Manager that saves values in memory.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Session_Manager_In_Memory final : public Session_Manager
|
|
{
|
|
public:
|
|
/**
|
|
* @param rng a RNG used for generating session key and for
|
|
* session encryption
|
|
* @param max_sessions a hint on the maximum number of sessions
|
|
* to keep in memory at any one time. (If zero, don't cap)
|
|
* @param session_lifetime sessions are expired after this many
|
|
* seconds have elapsed from initial handshake.
|
|
*/
|
|
Session_Manager_In_Memory(RandomNumberGenerator& rng,
|
|
size_t max_sessions = 1000,
|
|
std::chrono::seconds session_lifetime =
|
|
std::chrono::seconds(7200));
|
|
|
|
bool load_from_session_id(const std::vector<uint8_t>& session_id,
|
|
Session& session) override;
|
|
|
|
bool load_from_server_info(const Server_Information& info,
|
|
Session& session) override;
|
|
|
|
void remove_entry(const std::vector<uint8_t>& session_id) override;
|
|
|
|
size_t remove_all() override;
|
|
|
|
void save(const Session& session_data) override;
|
|
|
|
std::chrono::seconds session_lifetime() const override
|
|
{ return m_session_lifetime; }
|
|
|
|
private:
|
|
bool load_from_session_str(const std::string& session_str,
|
|
Session& session);
|
|
|
|
mutex_type m_mutex;
|
|
|
|
size_t m_max_sessions;
|
|
|
|
std::chrono::seconds m_session_lifetime;
|
|
|
|
RandomNumberGenerator& m_rng;
|
|
secure_vector<uint8_t> m_session_key;
|
|
|
|
std::map<std::string, std::vector<uint8_t>> m_sessions; // hex(session_id) -> session
|
|
std::map<Server_Information, std::string> m_info_sessions;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Certificate_Store;
|
|
class X509_Certificate;
|
|
|
|
namespace OCSP {
|
|
|
|
class Response;
|
|
|
|
}
|
|
|
|
namespace TLS {
|
|
|
|
class Handshake_Message;
|
|
class Policy;
|
|
class Extensions;
|
|
class Certificate_Status_Request;
|
|
|
|
/**
|
|
* Encapsulates the callbacks that a TLS channel will make which are due to
|
|
* channel specific operations.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Callbacks
|
|
{
|
|
public:
|
|
virtual ~Callbacks() = default;
|
|
|
|
/**
|
|
* Mandatory callback: output function
|
|
* The channel will call this with data which needs to be sent to the peer
|
|
* (eg, over a socket or some other form of IPC). The array will be overwritten
|
|
* when the function returns so a copy must be made if the data cannot be
|
|
* sent immediately.
|
|
*
|
|
* @param data the vector of data to send
|
|
*
|
|
* @param size the number of bytes to send
|
|
*/
|
|
virtual void tls_emit_data(const uint8_t data[], size_t size) = 0;
|
|
|
|
/**
|
|
* Mandatory callback: process application data
|
|
* Called when application data record is received from the peer.
|
|
* Again the array is overwritten immediately after the function returns.
|
|
*
|
|
* @param seq_no the underlying TLS/DTLS record sequence number
|
|
*
|
|
* @param data the vector containing the received record
|
|
*
|
|
* @param size the length of the received record, in bytes
|
|
*/
|
|
virtual void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size) = 0;
|
|
|
|
/**
|
|
* Mandatory callback: alert received
|
|
* Called when an alert is received from the peer
|
|
* If fatal, the connection is closing. If not fatal, the connection may
|
|
* still be closing (depending on the error and the peer).
|
|
*
|
|
* @param alert the source of the alert
|
|
*/
|
|
virtual void tls_alert(Alert alert) = 0;
|
|
|
|
/**
|
|
* Mandatory callback: session established
|
|
* Called when a session is established. Throw an exception to abort
|
|
* the connection.
|
|
*
|
|
* @param session the session descriptor
|
|
*
|
|
* @return return false to prevent the session from being cached,
|
|
* return true to cache the session in the configured session manager
|
|
*/
|
|
virtual bool tls_session_established(const Session& session) = 0;
|
|
|
|
/**
|
|
* Optional callback: session activated
|
|
* Called when a session is active and can be written to
|
|
*/
|
|
virtual void tls_session_activated() {}
|
|
|
|
/**
|
|
* Optional callback with default impl: verify cert chain
|
|
*
|
|
* Default implementation performs a standard PKIX validation
|
|
* and initiates network OCSP request for end-entity cert.
|
|
* Override to provide different behavior.
|
|
*
|
|
* Check the certificate chain is valid up to a trusted root, and
|
|
* optionally (if hostname != "") that the hostname given is
|
|
* consistent with the leaf certificate.
|
|
*
|
|
* This function should throw an exception derived from
|
|
* std::exception with an informative what() result if the
|
|
* certificate chain cannot be verified.
|
|
*
|
|
* @param cert_chain specifies a certificate chain leading to a
|
|
* trusted root CA certificate.
|
|
* @param ocsp_responses the server may have provided some
|
|
* @param trusted_roots the list of trusted certificates
|
|
* @param usage what this cert chain is being used for
|
|
* Usage_Type::TLS_SERVER_AUTH for server chains,
|
|
* Usage_Type::TLS_CLIENT_AUTH for client chains,
|
|
* Usage_Type::UNSPECIFIED for other uses
|
|
* @param hostname when authenticating a server, this is the hostname
|
|
* the client requested (eg via SNI). When authenticating a client,
|
|
* this is the server name the client is authenticating *to*.
|
|
* Empty in other cases or if no hostname was used.
|
|
* @param policy the TLS policy associated with the session being authenticated
|
|
* using the certificate chain
|
|
*/
|
|
virtual void tls_verify_cert_chain(
|
|
const std::vector<X509_Certificate>& cert_chain,
|
|
const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
|
|
const std::vector<Certificate_Store*>& trusted_roots,
|
|
Usage_Type usage,
|
|
const std::string& hostname,
|
|
const TLS::Policy& policy);
|
|
|
|
/**
|
|
* Called by default `tls_verify_cert_chain` to get the timeout to use for OCSP
|
|
* requests. Return 0 to disable online OCSP checks.
|
|
*
|
|
* This function should not be "const" since the implementation might need
|
|
* to perform some side effecting operation to compute the result.
|
|
*/
|
|
virtual std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const
|
|
{
|
|
return std::chrono::milliseconds(0);
|
|
}
|
|
|
|
/**
|
|
* Called by the TLS server whenever the client included the
|
|
* status_request extension (see RFC 6066, a.k.a OCSP stapling)
|
|
* in the ClientHello.
|
|
*
|
|
* @return the encoded OCSP response to be sent to the client which
|
|
* indicates the revocation status of the server certificate. Return an
|
|
* empty vector to indicate that no response is available, and thus
|
|
* suppress the Certificate_Status message.
|
|
*/
|
|
virtual std::vector<uint8_t> tls_provide_cert_status(const std::vector<X509_Certificate>& chain,
|
|
const Certificate_Status_Request& csr)
|
|
{
|
|
BOTAN_UNUSED(chain);
|
|
BOTAN_UNUSED(csr);
|
|
return std::vector<uint8_t>();
|
|
}
|
|
|
|
/**
|
|
* Optional callback with default impl: sign a message
|
|
*
|
|
* Default implementation uses PK_Signer::sign_message().
|
|
* Override to provide a different approach, e.g. using an external device.
|
|
*
|
|
* @param key the private key of the signer
|
|
* @param rng a random number generator
|
|
* @param emsa the encoding method to be applied to the message
|
|
* @param format the signature format
|
|
* @param msg the input data for the signature
|
|
*
|
|
* @return the signature
|
|
*/
|
|
virtual std::vector<uint8_t> tls_sign_message(
|
|
const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& emsa,
|
|
Signature_Format format,
|
|
const std::vector<uint8_t>& msg);
|
|
|
|
/**
|
|
* Optional callback with default impl: verify a message signature
|
|
*
|
|
* Default implementation uses PK_Verifier::verify_message().
|
|
* Override to provide a different approach, e.g. using an external device.
|
|
*
|
|
* @param key the public key of the signer
|
|
* @param emsa the encoding method to be applied to the message
|
|
* @param format the signature format
|
|
* @param msg the input data for the signature
|
|
* @param sig the signature to be checked
|
|
*
|
|
* @return true if the signature is valid, false otherwise
|
|
*/
|
|
virtual bool tls_verify_message(
|
|
const Public_Key& key,
|
|
const std::string& emsa,
|
|
Signature_Format format,
|
|
const std::vector<uint8_t>& msg,
|
|
const std::vector<uint8_t>& sig);
|
|
|
|
/**
|
|
* Optional callback with default impl: client side DH agreement
|
|
*
|
|
* Default implementation uses PK_Key_Agreement::derive_key().
|
|
* Override to provide a different approach, e.g. using an external device.
|
|
*
|
|
* @param modulus the modulus p of the discrete logarithm group
|
|
* @param generator the generator of the DH subgroup
|
|
* @param peer_public_value the public value of the peer
|
|
* @param policy the TLS policy associated with the session being established
|
|
* @param rng a random number generator
|
|
*
|
|
* @return a pair consisting of the agreed raw secret and our public value
|
|
*/
|
|
virtual std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> tls_dh_agree(
|
|
const std::vector<uint8_t>& modulus,
|
|
const std::vector<uint8_t>& generator,
|
|
const std::vector<uint8_t>& peer_public_value,
|
|
const Policy& policy,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Optional callback with default impl: client side ECDH agreement
|
|
*
|
|
* Default implementation uses PK_Key_Agreement::derive_key().
|
|
* Override to provide a different approach, e.g. using an external device.
|
|
*
|
|
* @param curve_name the name of the elliptic curve
|
|
* @param peer_public_value the public value of the peer
|
|
* @param policy the TLS policy associated with the session being established
|
|
* @param rng a random number generator
|
|
* @param compressed the compression preference for our public value
|
|
*
|
|
* @return a pair consisting of the agreed raw secret and our public value
|
|
*/
|
|
virtual std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> tls_ecdh_agree(
|
|
const std::string& curve_name,
|
|
const std::vector<uint8_t>& peer_public_value,
|
|
const Policy& policy,
|
|
RandomNumberGenerator& rng,
|
|
bool compressed);
|
|
|
|
/**
|
|
* Optional callback: inspect handshake message
|
|
* Throw an exception to abort the handshake.
|
|
* Default simply ignores the message.
|
|
*
|
|
* @param message the handshake message
|
|
*/
|
|
virtual void tls_inspect_handshake_msg(const Handshake_Message& message);
|
|
|
|
/**
|
|
* Optional callback for server: choose ALPN protocol
|
|
* ALPN (RFC 7301) works by the client sending a list of application
|
|
* protocols it is willing to negotiate. The server then selects which
|
|
* protocol to use, which is not necessarily even on the list that
|
|
* the client sent.
|
|
*
|
|
* @param client_protos the vector of protocols the client is willing to negotiate
|
|
*
|
|
* @return the protocol selected by the server, which need not be on the
|
|
* list that the client sent; if this is the empty string, the server ignores the
|
|
* client ALPN extension. Default return value is empty string.
|
|
*/
|
|
virtual std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos);
|
|
|
|
/**
|
|
* Optional callback: examine/modify Extensions before sending.
|
|
*
|
|
* Both client and server will call this callback on the Extensions object
|
|
* before serializing it in the client/server hellos. This allows an
|
|
* application to modify which extensions are sent during the
|
|
* handshake.
|
|
*
|
|
* Default implementation does nothing.
|
|
*
|
|
* @param extn the extensions
|
|
* @param which_side will be CLIENT or SERVER which is the current
|
|
* applications role in the exchange.
|
|
*/
|
|
virtual void tls_modify_extensions(Extensions& extn, Connection_Side which_side);
|
|
|
|
/**
|
|
* Optional callback: examine peer extensions.
|
|
*
|
|
* Both client and server will call this callback with the Extensions
|
|
* object after receiving it from the peer. This allows examining the
|
|
* Extensions, for example to implement a custom extension. It also allows
|
|
* an application to require that a particular extension be implemented;
|
|
* throw an exception from this function to abort the handshake.
|
|
*
|
|
* Default implementation does nothing.
|
|
*
|
|
* @param extn the extensions
|
|
* @param which_side will be CLIENT if these are are the clients extensions (ie we are
|
|
* the server) or SERVER if these are the server extensions (we are the client).
|
|
*/
|
|
virtual void tls_examine_extensions(const Extensions& extn, Connection_Side which_side);
|
|
|
|
/**
|
|
* Optional callback: decode TLS group ID
|
|
*
|
|
* TLS uses a 16-bit field to identify ECC and DH groups. This callback
|
|
* handles the decoding. You only need to implement this if you are using
|
|
* a custom ECC or DH group (this is extremely uncommon).
|
|
*
|
|
* Default implementation uses the standard (IETF-defined) mappings.
|
|
*/
|
|
virtual std::string tls_decode_group_param(Group_Params group_param);
|
|
|
|
/**
|
|
* Optional callback: return peer network identity
|
|
*
|
|
* There is no expected or specified format. The only expectation is this
|
|
* function will return a unique value. For example returning the peer
|
|
* host IP and port.
|
|
*
|
|
* This is used to bind the DTLS cookie to a particular network identity.
|
|
* It is only called if the dtls-cookie-secret PSK is also defined.
|
|
*/
|
|
virtual std::string tls_peer_network_identity();
|
|
|
|
/**
|
|
* Optional callback: error logging. (not currently called)
|
|
* @param err An error message related to this connection.
|
|
*/
|
|
virtual void tls_log_error(const char* err)
|
|
{
|
|
BOTAN_UNUSED(err);
|
|
}
|
|
|
|
/**
|
|
* Optional callback: debug logging. (not currently called)
|
|
* @param what Some hopefully informative string
|
|
*/
|
|
virtual void tls_log_debug(const char* what)
|
|
{
|
|
BOTAN_UNUSED(what);
|
|
}
|
|
|
|
/**
|
|
* Optional callback: debug logging taking a buffer. (not currently called)
|
|
* @param descr What this buffer is
|
|
* @param val the bytes
|
|
* @param val_len length of val
|
|
*/
|
|
virtual void tls_log_debug_bin(const char* descr, const uint8_t val[], size_t val_len)
|
|
{
|
|
BOTAN_UNUSED(descr, val, val_len);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* TLS::Callbacks using std::function for compatability with the old API signatures.
|
|
* This type is only provided for backward compatibility.
|
|
* New implementations should derive from TLS::Callbacks instead.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Compat_Callbacks final : public Callbacks
|
|
{
|
|
public:
|
|
typedef std::function<void (const uint8_t[], size_t)> output_fn;
|
|
typedef std::function<void (const uint8_t[], size_t)> data_cb;
|
|
typedef std::function<void (Alert, const uint8_t[], size_t)> alert_cb;
|
|
typedef std::function<bool (const Session&)> handshake_cb;
|
|
typedef std::function<void (const Handshake_Message&)> handshake_msg_cb;
|
|
typedef std::function<std::string (std::vector<std::string>)> next_protocol_fn;
|
|
|
|
/**
|
|
* @param data_output_fn is called with data for the outbound socket
|
|
*
|
|
* @param app_data_cb is called when new application data is received
|
|
*
|
|
* @param recv_alert_cb is called when a TLS alert is received
|
|
*
|
|
* @param hs_cb is called when a handshake is completed
|
|
*
|
|
* @param hs_msg_cb is called for each handshake message received
|
|
*
|
|
* @param next_proto is called with ALPN protocol data sent by the client
|
|
*/
|
|
BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).")
|
|
Compat_Callbacks(output_fn data_output_fn, data_cb app_data_cb, alert_cb recv_alert_cb,
|
|
handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr,
|
|
next_protocol_fn next_proto = nullptr)
|
|
: m_output_function(data_output_fn), m_app_data_cb(app_data_cb),
|
|
m_alert_cb(std::bind(recv_alert_cb, std::placeholders::_1, nullptr, 0)),
|
|
m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {}
|
|
|
|
BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).")
|
|
Compat_Callbacks(output_fn data_output_fn, data_cb app_data_cb,
|
|
std::function<void (Alert)> recv_alert_cb,
|
|
handshake_cb hs_cb,
|
|
handshake_msg_cb hs_msg_cb = nullptr,
|
|
next_protocol_fn next_proto = nullptr)
|
|
: m_output_function(data_output_fn), m_app_data_cb(app_data_cb),
|
|
m_alert_cb(recv_alert_cb),
|
|
m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {}
|
|
|
|
enum class SILENCE_DEPRECATION_WARNING { PLEASE = 0 };
|
|
Compat_Callbacks(SILENCE_DEPRECATION_WARNING,
|
|
output_fn data_output_fn, data_cb app_data_cb,
|
|
std::function<void (Alert)> recv_alert_cb,
|
|
handshake_cb hs_cb,
|
|
handshake_msg_cb hs_msg_cb = nullptr,
|
|
next_protocol_fn next_proto = nullptr)
|
|
: m_output_function(data_output_fn),
|
|
m_app_data_cb(app_data_cb),
|
|
m_alert_cb(recv_alert_cb),
|
|
m_hs_cb(hs_cb),
|
|
m_hs_msg_cb(hs_msg_cb),
|
|
m_next_proto(next_proto) {}
|
|
|
|
Compat_Callbacks(SILENCE_DEPRECATION_WARNING,
|
|
output_fn data_output_fn, data_cb app_data_cb, alert_cb recv_alert_cb,
|
|
handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr,
|
|
next_protocol_fn next_proto = nullptr)
|
|
: m_output_function(data_output_fn), m_app_data_cb(app_data_cb),
|
|
m_alert_cb(std::bind(recv_alert_cb, std::placeholders::_1, nullptr, 0)),
|
|
m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {}
|
|
|
|
|
|
void tls_emit_data(const uint8_t data[], size_t size) override
|
|
{
|
|
BOTAN_ASSERT(m_output_function != nullptr,
|
|
"Invalid TLS output function callback.");
|
|
m_output_function(data, size);
|
|
}
|
|
|
|
void tls_record_received(uint64_t /*seq_no*/, const uint8_t data[], size_t size) override
|
|
{
|
|
BOTAN_ASSERT(m_app_data_cb != nullptr,
|
|
"Invalid TLS app data callback.");
|
|
m_app_data_cb(data, size);
|
|
}
|
|
|
|
void tls_alert(Alert alert) override
|
|
{
|
|
BOTAN_ASSERT(m_alert_cb != nullptr,
|
|
"Invalid TLS alert callback.");
|
|
m_alert_cb(alert);
|
|
}
|
|
|
|
bool tls_session_established(const Session& session) override
|
|
{
|
|
BOTAN_ASSERT(m_hs_cb != nullptr,
|
|
"Invalid TLS handshake callback.");
|
|
return m_hs_cb(session);
|
|
}
|
|
|
|
std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos) override
|
|
{
|
|
if(m_next_proto != nullptr) { return m_next_proto(client_protos); }
|
|
return "";
|
|
}
|
|
|
|
void tls_inspect_handshake_msg(const Handshake_Message& hmsg) override
|
|
{
|
|
// The handshake message callback is optional so we can
|
|
// not assume it has been set.
|
|
if(m_hs_msg_cb != nullptr) { m_hs_msg_cb(hmsg); }
|
|
}
|
|
|
|
private:
|
|
const output_fn m_output_function;
|
|
const data_cb m_app_data_cb;
|
|
const std::function<void (Alert)> m_alert_cb;
|
|
const handshake_cb m_hs_cb;
|
|
const handshake_msg_cb m_hs_msg_cb;
|
|
const next_protocol_fn m_next_proto;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
class Connection_Cipher_State;
|
|
class Connection_Sequence_Numbers;
|
|
class Handshake_State;
|
|
class Handshake_Message;
|
|
class Client_Hello;
|
|
class Server_Hello;
|
|
class Policy;
|
|
|
|
/**
|
|
* Generic interface for TLS endpoint
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Channel
|
|
{
|
|
public:
|
|
typedef std::function<void (const uint8_t[], size_t)> output_fn;
|
|
typedef std::function<void (const uint8_t[], size_t)> data_cb;
|
|
typedef std::function<void (Alert, const uint8_t[], size_t)> alert_cb;
|
|
typedef std::function<bool (const Session&)> handshake_cb;
|
|
typedef std::function<void (const Handshake_Message&)> handshake_msg_cb;
|
|
static size_t IO_BUF_DEFAULT_SIZE;
|
|
|
|
/**
|
|
* Set up a new TLS session
|
|
*
|
|
* @param callbacks contains a set of callback function references
|
|
* required by the TLS endpoint.
|
|
* @param session_manager manages session state
|
|
* @param rng a random number generator
|
|
* @param policy specifies other connection policy information
|
|
* @param is_server whether this is a server session or not
|
|
* @param is_datagram whether this is a DTLS session
|
|
* @param io_buf_sz This many bytes of memory will
|
|
* be preallocated for the read and write buffers. Smaller
|
|
* values just mean reallocations and copies are more likely.
|
|
*/
|
|
Channel(Callbacks& callbacks,
|
|
Session_Manager& session_manager,
|
|
RandomNumberGenerator& rng,
|
|
const Policy& policy,
|
|
bool is_server,
|
|
bool is_datagram,
|
|
size_t io_buf_sz = IO_BUF_DEFAULT_SIZE);
|
|
|
|
/**
|
|
* DEPRECATED. This constructor is only provided for backward
|
|
* compatibility and should not be used in new implementations.
|
|
* (Not marked deprecated since it is only called internally, by
|
|
* other deprecated constructors)
|
|
*/
|
|
Channel(output_fn out,
|
|
data_cb app_data_cb,
|
|
alert_cb alert_cb,
|
|
handshake_cb hs_cb,
|
|
handshake_msg_cb hs_msg_cb,
|
|
Session_Manager& session_manager,
|
|
RandomNumberGenerator& rng,
|
|
const Policy& policy,
|
|
bool is_server,
|
|
bool is_datagram,
|
|
size_t io_buf_sz = IO_BUF_DEFAULT_SIZE);
|
|
|
|
Channel(const Channel&) = delete;
|
|
|
|
Channel& operator=(const Channel&) = delete;
|
|
|
|
virtual ~Channel();
|
|
|
|
/**
|
|
* Inject TLS traffic received from counterparty
|
|
* @return a hint as the how many more bytes we need to process the
|
|
* current record (this may be 0 if on a record boundary)
|
|
*/
|
|
size_t received_data(const uint8_t buf[], size_t buf_size);
|
|
|
|
/**
|
|
* Inject TLS traffic received from counterparty
|
|
* @return a hint as the how many more bytes we need to process the
|
|
* current record (this may be 0 if on a record boundary)
|
|
*/
|
|
size_t received_data(const std::vector<uint8_t>& buf);
|
|
|
|
/**
|
|
* Inject plaintext intended for counterparty
|
|
* Throws an exception if is_active() is false
|
|
*/
|
|
void send(const uint8_t buf[], size_t buf_size);
|
|
|
|
/**
|
|
* Inject plaintext intended for counterparty
|
|
* Throws an exception if is_active() is false
|
|
*/
|
|
void send(const std::string& val);
|
|
|
|
/**
|
|
* Inject plaintext intended for counterparty
|
|
* Throws an exception if is_active() is false
|
|
*/
|
|
template<typename Alloc>
|
|
void send(const std::vector<unsigned char, Alloc>& val)
|
|
{
|
|
send(val.data(), val.size());
|
|
}
|
|
|
|
/**
|
|
* Send a TLS alert message. If the alert is fatal, the internal
|
|
* state (keys, etc) will be reset.
|
|
* @param alert the Alert to send
|
|
*/
|
|
void send_alert(const Alert& alert);
|
|
|
|
/**
|
|
* Send a warning alert
|
|
*/
|
|
void send_warning_alert(Alert::Type type) { send_alert(Alert(type, false)); }
|
|
|
|
/**
|
|
* Send a fatal alert
|
|
*/
|
|
void send_fatal_alert(Alert::Type type) { send_alert(Alert(type, true)); }
|
|
|
|
/**
|
|
* Send a close notification alert
|
|
*/
|
|
void close() { send_warning_alert(Alert::CLOSE_NOTIFY); }
|
|
|
|
/**
|
|
* @return true iff the connection is active for sending application data
|
|
*/
|
|
bool is_active() const;
|
|
|
|
/**
|
|
* @return true iff the connection has been definitely closed
|
|
*/
|
|
bool is_closed() const;
|
|
|
|
/**
|
|
* @return certificate chain of the peer (may be empty)
|
|
*/
|
|
std::vector<X509_Certificate> peer_cert_chain() const;
|
|
|
|
/**
|
|
* Key material export (RFC 5705)
|
|
* @param label a disambiguating label string
|
|
* @param context a per-association context value
|
|
* @param length the length of the desired key in bytes
|
|
* @return key of length bytes
|
|
*/
|
|
SymmetricKey key_material_export(const std::string& label,
|
|
const std::string& context,
|
|
size_t length) const;
|
|
|
|
/**
|
|
* Attempt to renegotiate the session
|
|
* @param force_full_renegotiation if true, require a full renegotiation,
|
|
* otherwise allow session resumption
|
|
*/
|
|
void renegotiate(bool force_full_renegotiation = false);
|
|
|
|
/**
|
|
* @return true iff the counterparty supports the secure
|
|
* renegotiation extensions.
|
|
*/
|
|
bool secure_renegotiation_supported() const;
|
|
|
|
/**
|
|
* Perform a handshake timeout check. This does nothing unless
|
|
* this is a DTLS channel with a pending handshake state, in
|
|
* which case we check for timeout and potentially retransmit
|
|
* handshake packets.
|
|
*/
|
|
bool timeout_check();
|
|
|
|
virtual std::string application_protocol() const = 0;
|
|
|
|
protected:
|
|
|
|
virtual void process_handshake_msg(const Handshake_State* active_state,
|
|
Handshake_State& pending_state,
|
|
Handshake_Type type,
|
|
const std::vector<uint8_t>& contents,
|
|
bool epoch0_restart) = 0;
|
|
|
|
virtual void initiate_handshake(Handshake_State& state,
|
|
bool force_full_renegotiation) = 0;
|
|
|
|
virtual std::vector<X509_Certificate>
|
|
get_peer_cert_chain(const Handshake_State& state) const = 0;
|
|
|
|
virtual Handshake_State* new_handshake_state(class Handshake_IO* io) = 0;
|
|
|
|
Handshake_State& create_handshake_state(Protocol_Version version);
|
|
|
|
void inspect_handshake_message(const Handshake_Message& msg);
|
|
|
|
void activate_session();
|
|
|
|
void change_cipher_spec_reader(Connection_Side side);
|
|
|
|
void change_cipher_spec_writer(Connection_Side side);
|
|
|
|
/* secure renegotiation handling */
|
|
|
|
void secure_renegotiation_check(const Client_Hello* client_hello);
|
|
void secure_renegotiation_check(const Server_Hello* server_hello);
|
|
|
|
std::vector<uint8_t> secure_renegotiation_data_for_client_hello() const;
|
|
std::vector<uint8_t> secure_renegotiation_data_for_server_hello() const;
|
|
|
|
RandomNumberGenerator& rng() { return m_rng; }
|
|
|
|
Session_Manager& session_manager() { return m_session_manager; }
|
|
|
|
const Policy& policy() const { return m_policy; }
|
|
|
|
bool save_session(const Session& session);
|
|
|
|
Callbacks& callbacks() const { return m_callbacks; }
|
|
|
|
void reset_active_association_state();
|
|
|
|
private:
|
|
void init(size_t io_buf_sze);
|
|
|
|
void send_record(uint8_t record_type, const std::vector<uint8_t>& record);
|
|
|
|
void send_record_under_epoch(uint16_t epoch, uint8_t record_type,
|
|
const std::vector<uint8_t>& record);
|
|
|
|
void send_record_array(uint16_t epoch, uint8_t record_type,
|
|
const uint8_t input[], size_t length);
|
|
|
|
void write_record(Connection_Cipher_State* cipher_state,
|
|
uint16_t epoch, uint8_t type, const uint8_t input[], size_t length);
|
|
|
|
void reset_state();
|
|
|
|
Connection_Sequence_Numbers& sequence_numbers() const;
|
|
|
|
std::shared_ptr<Connection_Cipher_State> read_cipher_state_epoch(uint16_t epoch) const;
|
|
|
|
std::shared_ptr<Connection_Cipher_State> write_cipher_state_epoch(uint16_t epoch) const;
|
|
|
|
const Handshake_State* active_state() const { return m_active_state.get(); }
|
|
|
|
const Handshake_State* pending_state() const { return m_pending_state.get(); }
|
|
|
|
/* methods to handle incoming traffic through Channel::receive_data. */
|
|
void process_handshake_ccs(const secure_vector<uint8_t>& record,
|
|
uint64_t record_sequence,
|
|
Record_Type record_type,
|
|
Protocol_Version record_version,
|
|
bool epoch0_restart);
|
|
|
|
void process_application_data(uint64_t req_no, const secure_vector<uint8_t>& record);
|
|
|
|
void process_alert(const secure_vector<uint8_t>& record);
|
|
|
|
const bool m_is_server;
|
|
const bool m_is_datagram;
|
|
|
|
/* callbacks */
|
|
std::unique_ptr<Compat_Callbacks> m_compat_callbacks;
|
|
Callbacks& m_callbacks;
|
|
|
|
/* external state */
|
|
Session_Manager& m_session_manager;
|
|
const Policy& m_policy;
|
|
RandomNumberGenerator& m_rng;
|
|
|
|
/* sequence number state */
|
|
std::unique_ptr<Connection_Sequence_Numbers> m_sequence_numbers;
|
|
|
|
/* pending and active connection states */
|
|
std::unique_ptr<Handshake_State> m_active_state;
|
|
std::unique_ptr<Handshake_State> m_pending_state;
|
|
|
|
/* cipher states for each epoch */
|
|
std::map<uint16_t, std::shared_ptr<Connection_Cipher_State>> m_write_cipher_states;
|
|
std::map<uint16_t, std::shared_ptr<Connection_Cipher_State>> m_read_cipher_states;
|
|
|
|
/* I/O buffers */
|
|
secure_vector<uint8_t> m_writebuf;
|
|
secure_vector<uint8_t> m_readbuf;
|
|
secure_vector<uint8_t> m_record_buf;
|
|
|
|
bool m_has_been_closed;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Public_Key;
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* TLS Policy Base Class
|
|
* Inherit and overload as desired to suit local policy concerns
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Policy
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Returns a list of ciphers we are willing to negotiate, in
|
|
* order of preference.
|
|
*/
|
|
virtual std::vector<std::string> allowed_ciphers() const;
|
|
|
|
/**
|
|
* Returns a list of hash algorithms we are willing to use for
|
|
* signatures, in order of preference.
|
|
*/
|
|
virtual std::vector<std::string> allowed_signature_hashes() const;
|
|
|
|
/**
|
|
* Returns a list of MAC algorithms we are willing to use.
|
|
*/
|
|
virtual std::vector<std::string> allowed_macs() const;
|
|
|
|
/**
|
|
* Returns a list of key exchange algorithms we are willing to
|
|
* use, in order of preference. Allowed values: DH, empty string
|
|
* (representing RSA using server certificate key)
|
|
*/
|
|
virtual std::vector<std::string> allowed_key_exchange_methods() const;
|
|
|
|
/**
|
|
* Returns a list of signature algorithms we are willing to
|
|
* use, in order of preference. Allowed values RSA and DSA.
|
|
*/
|
|
virtual std::vector<std::string> allowed_signature_methods() const;
|
|
|
|
virtual std::vector<Signature_Scheme> allowed_signature_schemes() const;
|
|
|
|
/**
|
|
* The minimum signature strength we will accept
|
|
* Returning 80 allows RSA 1024 and SHA-1. Values larger than 80 disable SHA-1 support.
|
|
* Returning 110 allows RSA 2048.
|
|
* Return 128 to force ECC (P-256) or large (~3000 bit) RSA keys.
|
|
* Default is 110
|
|
*/
|
|
virtual size_t minimum_signature_strength() const;
|
|
|
|
/**
|
|
* Return if cert revocation info (CRL/OCSP) is required
|
|
* If true, validation will fail unless a valid CRL or OCSP response
|
|
* was examined.
|
|
*/
|
|
virtual bool require_cert_revocation_info() const;
|
|
|
|
bool allowed_signature_method(const std::string& sig_method) const;
|
|
bool allowed_signature_hash(const std::string& hash) const;
|
|
|
|
/**
|
|
* Return list of ECC curves and FFDHE groups we are willing to
|
|
* use in order of preference.
|
|
*/
|
|
virtual std::vector<Group_Params> key_exchange_groups() const;
|
|
|
|
/**
|
|
* Request that ECC curve points are sent compressed
|
|
*/
|
|
virtual bool use_ecc_point_compression() const;
|
|
|
|
/**
|
|
* Select a key exchange group to use, from the list of groups sent by the
|
|
* peer. If none are acceptable, return Group_Params::NONE
|
|
*/
|
|
virtual Group_Params choose_key_exchange_group(const std::vector<Group_Params>& peer_groups) const;
|
|
|
|
/**
|
|
* Allow renegotiation even if the counterparty doesn't
|
|
* support the secure renegotiation extension.
|
|
*
|
|
* @warning Changing this to true exposes you to injected
|
|
* plaintext attacks. Read RFC 5746 for background.
|
|
*/
|
|
virtual bool allow_insecure_renegotiation() const;
|
|
|
|
/**
|
|
* The protocol dictates that the first 32 bits of the random
|
|
* field are the current time in seconds. However this allows
|
|
* client fingerprinting attacks. Set to false to disable, in
|
|
* which case random bytes will be used instead.
|
|
*/
|
|
virtual bool include_time_in_hello_random() const;
|
|
|
|
/**
|
|
* Consulted by server side. If true, allows clients to initiate a new handshake
|
|
*/
|
|
virtual bool allow_client_initiated_renegotiation() const;
|
|
|
|
/**
|
|
* Consulted by client side. If true, allows servers to initiate a new handshake
|
|
*/
|
|
virtual bool allow_server_initiated_renegotiation() const;
|
|
|
|
/**
|
|
* If true, a request to renegotiate will close the connection with
|
|
* a fatal alert. Otherwise, a warning alert is sent.
|
|
*/
|
|
virtual bool abort_connection_on_undesired_renegotiation() const;
|
|
|
|
virtual bool only_resume_with_exact_version() const;
|
|
|
|
/**
|
|
* Allow TLS v1.0
|
|
*/
|
|
virtual bool allow_tls10() const;
|
|
|
|
/**
|
|
* Allow TLS v1.1
|
|
*/
|
|
virtual bool allow_tls11() const;
|
|
|
|
/**
|
|
* Allow TLS v1.2
|
|
*/
|
|
virtual bool allow_tls12() const;
|
|
|
|
/**
|
|
* Allow DTLS v1.0
|
|
*/
|
|
virtual bool allow_dtls10() const;
|
|
|
|
/**
|
|
* Allow DTLS v1.2
|
|
*/
|
|
virtual bool allow_dtls12() const;
|
|
|
|
virtual Group_Params default_dh_group() const;
|
|
|
|
/**
|
|
* Return the minimum DH group size we're willing to use
|
|
* Default is currently 1024 (insecure), should be 2048
|
|
*/
|
|
virtual size_t minimum_dh_group_size() const;
|
|
|
|
/**
|
|
* For ECDSA authenticated ciphersuites, the smallest key size the
|
|
* client will accept.
|
|
* This policy is currently only enforced on the server by the client.
|
|
*/
|
|
virtual size_t minimum_ecdsa_group_size() const;
|
|
|
|
/**
|
|
* Return the minimum ECDH group size we're willing to use
|
|
* for key exchange
|
|
*
|
|
* Default 255, allowing x25519 and larger
|
|
* x25519 is the smallest curve we will negotiate
|
|
* P-521 is the largest
|
|
*/
|
|
virtual size_t minimum_ecdh_group_size() const;
|
|
|
|
/**
|
|
* Return the minimum bit size we're willing to accept for RSA
|
|
* key exchange or server signatures.
|
|
*
|
|
* It does not place any requirements on the size of any RSA signature(s)
|
|
* which were used to check the server certificate. This is only
|
|
* concerned with the server's public key.
|
|
*
|
|
* Default is 2048 which is smallest RSA key size still secure
|
|
* for medium term security.
|
|
*/
|
|
virtual size_t minimum_rsa_bits() const;
|
|
|
|
/**
|
|
* Minimum DSA group size, default 2048 bits
|
|
*/
|
|
virtual size_t minimum_dsa_group_size() const;
|
|
|
|
/**
|
|
* Throw an exception if you don't like the peer's key.
|
|
* Default impl checks the key size against minimum_rsa_bits, minimum_ecdsa_group_size,
|
|
* or minimum_ecdh_group_size depending on the key's type.
|
|
* Override if you'd like to perform some other kind of test on
|
|
* (or logging of) the peer's keys.
|
|
*/
|
|
virtual void check_peer_key_acceptable(const Public_Key& public_key) const;
|
|
|
|
/**
|
|
* If this function returns false, unknown SRP/PSK identifiers
|
|
* will be rejected with an unknown_psk_identifier alert as soon
|
|
* as the non-existence is identified. Otherwise, a false
|
|
* identifier value will be used and the protocol allowed to
|
|
* proceed, causing the handshake to eventually fail without
|
|
* revealing that the username does not exist on this system.
|
|
*/
|
|
virtual bool hide_unknown_users() const;
|
|
|
|
/**
|
|
* Return the allowed lifetime of a session ticket. If 0, session
|
|
* tickets do not expire until the session ticket key rolls over.
|
|
* Expired session tickets cannot be used to resume a session.
|
|
*/
|
|
virtual uint32_t session_ticket_lifetime() const;
|
|
|
|
/**
|
|
* If this returns a non-empty vector, and DTLS is negotiated,
|
|
* then we will also attempt to negotiate the SRTP extension from
|
|
* RFC 5764 using the returned values as the profile ids.
|
|
*/
|
|
virtual std::vector<uint16_t> srtp_profiles() const;
|
|
|
|
/**
|
|
* @return true if and only if we are willing to accept this version
|
|
* Default accepts TLS v1.0 and later or DTLS v1.2 or later.
|
|
*/
|
|
virtual bool acceptable_protocol_version(Protocol_Version version) const;
|
|
|
|
/**
|
|
* Returns the more recent protocol version we are willing to
|
|
* use, for either TLS or DTLS depending on datagram param.
|
|
* Shouldn't ever need to override this unless you want to allow
|
|
* a user to disable use of TLS v1.2 (which is *not recommended*)
|
|
*/
|
|
virtual Protocol_Version latest_supported_version(bool datagram) const;
|
|
|
|
/**
|
|
* When offering this version, should we send a fallback SCSV?
|
|
* Default returns true iff version is not the latest version the
|
|
* policy allows, exists to allow override in case of interop problems.
|
|
*/
|
|
virtual bool send_fallback_scsv(Protocol_Version version) const;
|
|
|
|
/**
|
|
* Allows policy to reject any ciphersuites which are undesirable
|
|
* for whatever reason without having to reimplement ciphersuite_list
|
|
*/
|
|
virtual bool acceptable_ciphersuite(const Ciphersuite& suite) const;
|
|
|
|
/**
|
|
* @return true if servers should choose the ciphersuite matching
|
|
* their highest preference, rather than the clients.
|
|
* Has no effect on client side.
|
|
*/
|
|
virtual bool server_uses_own_ciphersuite_preferences() const;
|
|
|
|
/**
|
|
* Indicates whether the encrypt-then-MAC extension should be negotiated
|
|
* (RFC 7366)
|
|
*/
|
|
virtual bool negotiate_encrypt_then_mac() const;
|
|
|
|
/**
|
|
* Indicates whether certificate status messages should be supported
|
|
*/
|
|
virtual bool support_cert_status_message() const;
|
|
|
|
/**
|
|
* Indicate if client certificate authentication is required.
|
|
* If true, then a cert will be requested and if the client does
|
|
* not send a certificate the connection will be closed.
|
|
*/
|
|
virtual bool require_client_certificate_authentication() const;
|
|
|
|
/**
|
|
* Indicate if client certificate authentication is requested.
|
|
* If true, then a cert will be requested.
|
|
*/
|
|
virtual bool request_client_certificate_authentication() const;
|
|
|
|
/**
|
|
* If true, then allow a DTLS client to restart a connection to the
|
|
* same server association as described in section 4.2.8 of the DTLS RFC
|
|
*/
|
|
virtual bool allow_dtls_epoch0_restart() const;
|
|
|
|
/**
|
|
* Return allowed ciphersuites, in order of preference
|
|
*/
|
|
virtual std::vector<uint16_t> ciphersuite_list(Protocol_Version version,
|
|
bool have_srp) const;
|
|
|
|
/**
|
|
* @return the default MTU for DTLS
|
|
*/
|
|
virtual size_t dtls_default_mtu() const;
|
|
|
|
/**
|
|
* @return the initial timeout for DTLS
|
|
*/
|
|
virtual size_t dtls_initial_timeout() const;
|
|
|
|
/**
|
|
* @return the maximum timeout for DTLS
|
|
*/
|
|
virtual size_t dtls_maximum_timeout() const;
|
|
|
|
/**
|
|
* @return the maximum size of the certificate chain, in bytes.
|
|
* Return 0 to disable this and accept any size.
|
|
*/
|
|
virtual size_t maximum_certificate_chain_size() const;
|
|
|
|
virtual bool allow_resumption_for_renegotiation() const;
|
|
|
|
/**
|
|
* Convert this policy to a printable format.
|
|
* @param o stream to be printed to
|
|
*/
|
|
virtual void print(std::ostream& o) const;
|
|
|
|
/**
|
|
* Convert this policy to a printable format.
|
|
* Same as calling `print` on a ostringstream and reading o.str()
|
|
*/
|
|
std::string to_string() const;
|
|
|
|
virtual ~Policy() = default;
|
|
};
|
|
|
|
typedef Policy Default_Policy;
|
|
|
|
/**
|
|
* NSA Suite B 128-bit security level (RFC 6460)
|
|
*
|
|
* @warning As of August 2015 NSA indicated only the 192-bit Suite B
|
|
* should be used for all classification levels.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) NSA_Suite_B_128 : public Policy
|
|
{
|
|
public:
|
|
std::vector<std::string> allowed_ciphers() const override
|
|
{ return std::vector<std::string>({"AES-128/GCM"}); }
|
|
|
|
std::vector<std::string> allowed_signature_hashes() const override
|
|
{ return std::vector<std::string>({"SHA-256"}); }
|
|
|
|
std::vector<std::string> allowed_macs() const override
|
|
{ return std::vector<std::string>({"AEAD"}); }
|
|
|
|
std::vector<std::string> allowed_key_exchange_methods() const override
|
|
{ return std::vector<std::string>({"ECDH"}); }
|
|
|
|
std::vector<std::string> allowed_signature_methods() const override
|
|
{ return std::vector<std::string>({"ECDSA"}); }
|
|
|
|
std::vector<Group_Params> key_exchange_groups() const override
|
|
{ return {Group_Params::SECP256R1}; }
|
|
|
|
size_t minimum_signature_strength() const override { return 128; }
|
|
|
|
bool allow_tls10() const override { return false; }
|
|
bool allow_tls11() const override { return false; }
|
|
bool allow_tls12() const override { return true; }
|
|
bool allow_dtls10() const override { return false; }
|
|
bool allow_dtls12() const override { return false; }
|
|
};
|
|
|
|
/**
|
|
* NSA Suite B 192-bit security level (RFC 6460)
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,7) NSA_Suite_B_192 : public Policy
|
|
{
|
|
public:
|
|
std::vector<std::string> allowed_ciphers() const override
|
|
{ return std::vector<std::string>({"AES-256/GCM"}); }
|
|
|
|
std::vector<std::string> allowed_signature_hashes() const override
|
|
{ return std::vector<std::string>({"SHA-384"}); }
|
|
|
|
std::vector<std::string> allowed_macs() const override
|
|
{ return std::vector<std::string>({"AEAD"}); }
|
|
|
|
std::vector<std::string> allowed_key_exchange_methods() const override
|
|
{ return std::vector<std::string>({"ECDH"}); }
|
|
|
|
std::vector<std::string> allowed_signature_methods() const override
|
|
{ return std::vector<std::string>({"ECDSA"}); }
|
|
|
|
std::vector<Group_Params> key_exchange_groups() const override
|
|
{ return {Group_Params::SECP384R1}; }
|
|
|
|
size_t minimum_signature_strength() const override { return 192; }
|
|
|
|
bool allow_tls10() const override { return false; }
|
|
bool allow_tls11() const override { return false; }
|
|
bool allow_tls12() const override { return true; }
|
|
bool allow_dtls10() const override { return false; }
|
|
bool allow_dtls12() const override { return false; }
|
|
};
|
|
|
|
/**
|
|
* BSI TR-02102-2 Policy
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) BSI_TR_02102_2 : public Policy
|
|
{
|
|
public:
|
|
std::vector<std::string> allowed_ciphers() const override
|
|
{
|
|
return std::vector<std::string>({"AES-256/GCM", "AES-128/GCM", "AES-256/CCM", "AES-128/CCM", "AES-256", "AES-128"});
|
|
}
|
|
|
|
std::vector<std::string> allowed_signature_hashes() const override
|
|
{
|
|
return std::vector<std::string>({"SHA-512", "SHA-384", "SHA-256"});
|
|
}
|
|
|
|
std::vector<std::string> allowed_macs() const override
|
|
{
|
|
return std::vector<std::string>({"AEAD", "SHA-384", "SHA-256"});
|
|
}
|
|
|
|
std::vector<std::string> allowed_key_exchange_methods() const override
|
|
{
|
|
return std::vector<std::string>({"ECDH", "DH", "ECDHE_PSK", "DHE_PSK"});
|
|
}
|
|
|
|
std::vector<std::string> allowed_signature_methods() const override
|
|
{
|
|
return std::vector<std::string>({"ECDSA", "RSA", "DSA"});
|
|
}
|
|
|
|
std::vector<Group_Params> key_exchange_groups() const override
|
|
{
|
|
return std::vector<Group_Params>({
|
|
Group_Params::BRAINPOOL512R1,
|
|
Group_Params::BRAINPOOL384R1,
|
|
Group_Params::BRAINPOOL256R1,
|
|
Group_Params::SECP384R1,
|
|
Group_Params::SECP256R1,
|
|
Group_Params::FFDHE_4096,
|
|
Group_Params::FFDHE_3072,
|
|
Group_Params::FFDHE_2048
|
|
});
|
|
}
|
|
|
|
bool allow_insecure_renegotiation() const override { return false; }
|
|
bool allow_server_initiated_renegotiation() const override { return true; }
|
|
bool server_uses_own_ciphersuite_preferences() const override { return true; }
|
|
bool negotiate_encrypt_then_mac() const override { return true; }
|
|
|
|
size_t minimum_rsa_bits() const override { return 2000; }
|
|
size_t minimum_dh_group_size() const override { return 2000; }
|
|
size_t minimum_dsa_group_size() const override { return 2000; }
|
|
|
|
size_t minimum_ecdh_group_size() const override { return 250; }
|
|
size_t minimum_ecdsa_group_size() const override { return 250; }
|
|
|
|
bool allow_tls10() const override { return false; }
|
|
bool allow_tls11() const override { return false; }
|
|
bool allow_tls12() const override { return true; }
|
|
bool allow_dtls10() const override { return false; }
|
|
bool allow_dtls12() const override { return false; }
|
|
};
|
|
|
|
/**
|
|
* Policy for DTLS. We require DTLS v1.2 and an AEAD mode.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Datagram_Policy : public Policy
|
|
{
|
|
public:
|
|
std::vector<std::string> allowed_macs() const override
|
|
{ return std::vector<std::string>({"AEAD"}); }
|
|
|
|
bool allow_tls10() const override { return false; }
|
|
bool allow_tls11() const override { return false; }
|
|
bool allow_tls12() const override { return false; }
|
|
bool allow_dtls10() const override { return false; }
|
|
bool allow_dtls12() const override { return true; }
|
|
};
|
|
|
|
/*
|
|
* This policy requires a secure version of TLS and disables all insecure
|
|
* algorithms. It is compatible with other botan TLSes (including those using the
|
|
* default policy) and with many other recent implementations. It is a great idea
|
|
* to use if you control both sides of the protocol and don't have to worry
|
|
* about ancient and/or bizarre TLS implementations.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Strict_Policy : public Policy
|
|
{
|
|
public:
|
|
std::vector<std::string> allowed_ciphers() const override;
|
|
|
|
std::vector<std::string> allowed_signature_hashes() const override;
|
|
|
|
std::vector<std::string> allowed_macs() const override;
|
|
|
|
std::vector<std::string> allowed_key_exchange_methods() const override;
|
|
|
|
bool allow_tls10() const override;
|
|
bool allow_tls11() const override;
|
|
bool allow_tls12() const override;
|
|
bool allow_dtls10() const override;
|
|
bool allow_dtls12() const override;
|
|
};
|
|
|
|
class BOTAN_PUBLIC_API(2,0) Text_Policy : public Policy
|
|
{
|
|
public:
|
|
|
|
std::vector<std::string> allowed_ciphers() const override;
|
|
|
|
std::vector<std::string> allowed_signature_hashes() const override;
|
|
|
|
std::vector<std::string> allowed_macs() const override;
|
|
|
|
std::vector<std::string> allowed_key_exchange_methods() const override;
|
|
|
|
std::vector<std::string> allowed_signature_methods() const override;
|
|
|
|
std::vector<Group_Params> key_exchange_groups() const override;
|
|
|
|
bool use_ecc_point_compression() const override;
|
|
|
|
bool allow_tls10() const override;
|
|
|
|
bool allow_tls11() const override;
|
|
|
|
bool allow_tls12() const override;
|
|
|
|
bool allow_dtls10() const override;
|
|
|
|
bool allow_dtls12() const override;
|
|
|
|
bool allow_insecure_renegotiation() const override;
|
|
|
|
bool include_time_in_hello_random() const override;
|
|
|
|
bool allow_client_initiated_renegotiation() const override;
|
|
bool allow_server_initiated_renegotiation() const override;
|
|
|
|
bool server_uses_own_ciphersuite_preferences() const override;
|
|
|
|
bool negotiate_encrypt_then_mac() const override;
|
|
|
|
bool support_cert_status_message() const override;
|
|
|
|
bool require_client_certificate_authentication() const override;
|
|
|
|
size_t minimum_ecdh_group_size() const override;
|
|
|
|
size_t minimum_ecdsa_group_size() const override;
|
|
|
|
size_t minimum_dh_group_size() const override;
|
|
|
|
size_t minimum_rsa_bits() const override;
|
|
|
|
size_t minimum_signature_strength() const override;
|
|
|
|
size_t dtls_default_mtu() const override;
|
|
|
|
size_t dtls_initial_timeout() const override;
|
|
|
|
size_t dtls_maximum_timeout() const override;
|
|
|
|
bool require_cert_revocation_info() const override;
|
|
|
|
bool hide_unknown_users() const override;
|
|
|
|
uint32_t session_ticket_lifetime() const override;
|
|
|
|
bool send_fallback_scsv(Protocol_Version version) const override;
|
|
|
|
std::vector<uint16_t> srtp_profiles() const override;
|
|
|
|
void set(const std::string& k, const std::string& v);
|
|
|
|
explicit Text_Policy(const std::string& s);
|
|
|
|
explicit Text_Policy(std::istream& in);
|
|
|
|
protected:
|
|
|
|
std::vector<std::string> get_list(const std::string& key,
|
|
const std::vector<std::string>& def) const;
|
|
|
|
size_t get_len(const std::string& key, size_t def) const;
|
|
|
|
bool get_bool(const std::string& key, bool def) const;
|
|
|
|
std::string get_str(const std::string& key, const std::string& def = "") const;
|
|
|
|
bool set_value(const std::string& key, const std::string& val, bool overwrite);
|
|
|
|
private:
|
|
std::map<std::string, std::string> m_kv;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* SSL/TLS Client
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Client final : public Channel
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Set up a new TLS client session
|
|
*
|
|
* @param callbacks contains a set of callback function references
|
|
* required by the TLS client.
|
|
*
|
|
* @param session_manager manages session state
|
|
*
|
|
* @param creds manages application/user credentials
|
|
*
|
|
* @param policy specifies other connection policy information
|
|
*
|
|
* @param rng a random number generator
|
|
*
|
|
* @param server_info is identifying information about the TLS server
|
|
*
|
|
* @param offer_version specifies which version we will offer
|
|
* to the TLS server.
|
|
*
|
|
* @param next_protocols specifies protocols to advertise with ALPN
|
|
*
|
|
* @param reserved_io_buffer_size This many bytes of memory will
|
|
* be preallocated for the read and write buffers. Smaller
|
|
* values just mean reallocations and copies are more likely.
|
|
*/
|
|
Client(Callbacks& callbacks,
|
|
Session_Manager& session_manager,
|
|
Credentials_Manager& creds,
|
|
const Policy& policy,
|
|
RandomNumberGenerator& rng,
|
|
const Server_Information& server_info = Server_Information(),
|
|
const Protocol_Version& offer_version = Protocol_Version::latest_tls_version(),
|
|
const std::vector<std::string>& next_protocols = {},
|
|
size_t reserved_io_buffer_size = TLS::Client::IO_BUF_DEFAULT_SIZE
|
|
);
|
|
|
|
/**
|
|
* DEPRECATED. This constructor is only provided for backward
|
|
* compatibility and should not be used in new code. It will be
|
|
* removed in a future release.
|
|
*
|
|
* Set up a new TLS client session
|
|
*
|
|
* @param data_output_fn is called with data for the outbound socket
|
|
*
|
|
* @param app_data_cb is called when new application data is received
|
|
*
|
|
* @param recv_alert_cb is called when a TLS alert is received
|
|
*
|
|
* @param hs_cb is called when a handshake is completed
|
|
*
|
|
* @param session_manager manages session state
|
|
*
|
|
* @param creds manages application/user credentials
|
|
*
|
|
* @param policy specifies other connection policy information
|
|
*
|
|
* @param rng a random number generator
|
|
*
|
|
* @param server_info is identifying information about the TLS server
|
|
*
|
|
* @param offer_version specifies which version we will offer
|
|
* to the TLS server.
|
|
*
|
|
* @param next_protocols specifies protocols to advertise with ALPN
|
|
*
|
|
* @param reserved_io_buffer_size This many bytes of memory will
|
|
* be preallocated for the read and write buffers. Smaller
|
|
* values just mean reallocations and copies are more likely.
|
|
*/
|
|
BOTAN_DEPRECATED("Use TLS::Client(TLS::Callbacks ...)")
|
|
Client(output_fn data_output_fn,
|
|
data_cb app_data_cb,
|
|
alert_cb recv_alert_cb,
|
|
handshake_cb hs_cb,
|
|
Session_Manager& session_manager,
|
|
Credentials_Manager& creds,
|
|
const Policy& policy,
|
|
RandomNumberGenerator& rng,
|
|
const Server_Information& server_info = Server_Information(),
|
|
const Protocol_Version& offer_version = Protocol_Version::latest_tls_version(),
|
|
const std::vector<std::string>& next_protocols = {},
|
|
size_t reserved_io_buffer_size = TLS::Client::IO_BUF_DEFAULT_SIZE
|
|
);
|
|
|
|
/**
|
|
* DEPRECATED. This constructor is only provided for backward
|
|
* compatibility and should not be used in new implementations.
|
|
*/
|
|
BOTAN_DEPRECATED("Use TLS::Client(TLS::Callbacks ...)")
|
|
Client(output_fn out,
|
|
data_cb app_data_cb,
|
|
alert_cb alert_cb,
|
|
handshake_cb hs_cb,
|
|
handshake_msg_cb hs_msg_cb,
|
|
Session_Manager& session_manager,
|
|
Credentials_Manager& creds,
|
|
const Policy& policy,
|
|
RandomNumberGenerator& rng,
|
|
const Server_Information& server_info = Server_Information(),
|
|
const Protocol_Version& offer_version = Protocol_Version::latest_tls_version(),
|
|
const std::vector<std::string>& next_protocols = {}
|
|
);
|
|
|
|
/**
|
|
* @return network protocol as advertised by the TLS server, if server sent the ALPN extension
|
|
*/
|
|
std::string application_protocol() const override { return m_application_protocol; }
|
|
private:
|
|
void init(const Protocol_Version& protocol_version,
|
|
const std::vector<std::string>& next_protocols);
|
|
|
|
std::vector<X509_Certificate>
|
|
get_peer_cert_chain(const Handshake_State& state) const override;
|
|
|
|
void initiate_handshake(Handshake_State& state,
|
|
bool force_full_renegotiation) override;
|
|
|
|
void send_client_hello(Handshake_State& state,
|
|
bool force_full_renegotiation,
|
|
Protocol_Version version,
|
|
const std::string& srp_identifier = "",
|
|
const std::vector<std::string>& next_protocols = {});
|
|
|
|
void process_handshake_msg(const Handshake_State* active_state,
|
|
Handshake_State& pending_state,
|
|
Handshake_Type type,
|
|
const std::vector<uint8_t>& contents,
|
|
bool epoch0_restart) override;
|
|
|
|
Handshake_State* new_handshake_state(Handshake_IO* io) override;
|
|
|
|
Credentials_Manager& m_creds;
|
|
const Server_Information m_info;
|
|
std::string m_application_protocol;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* Blocking TLS Client
|
|
* Can be used directly, or subclass to get handshake and alert notifications
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Blocking_Client
|
|
{
|
|
public:
|
|
/*
|
|
* These functions are expected to block until completing entirely, or
|
|
* fail by throwing an exception.
|
|
*/
|
|
typedef std::function<size_t (uint8_t[], size_t)> read_fn;
|
|
typedef std::function<void (const uint8_t[], size_t)> write_fn;
|
|
|
|
BOTAN_DEPRECATED("Use the regular TLS::Client interface")
|
|
Blocking_Client(read_fn reader,
|
|
write_fn writer,
|
|
Session_Manager& session_manager,
|
|
Credentials_Manager& creds,
|
|
const Policy& policy,
|
|
RandomNumberGenerator& rng,
|
|
const Server_Information& server_info = Server_Information(),
|
|
const Protocol_Version& offer_version = Protocol_Version::latest_tls_version(),
|
|
const std::vector<std::string>& next_protos = {});
|
|
|
|
/**
|
|
* Completes full handshake then returns
|
|
*/
|
|
void do_handshake();
|
|
|
|
/**
|
|
* Number of bytes pending read in the plaintext buffer (bytes
|
|
* readable without blocking)
|
|
*/
|
|
size_t pending() const { return m_plaintext.size(); }
|
|
|
|
/**
|
|
* Blocking read, will return at least 1 byte (eventually) or else 0 if the connection
|
|
* is closed.
|
|
*/
|
|
size_t read(uint8_t buf[], size_t buf_len);
|
|
|
|
void write(const uint8_t buf[], size_t buf_len) { m_channel.send(buf, buf_len); }
|
|
|
|
const TLS::Channel& underlying_channel() const { return m_channel; }
|
|
TLS::Channel& underlying_channel() { return m_channel; }
|
|
|
|
void close() { m_channel.close(); }
|
|
|
|
bool is_closed() const { return m_channel.is_closed(); }
|
|
|
|
std::vector<X509_Certificate> peer_cert_chain() const
|
|
{ return m_channel.peer_cert_chain(); }
|
|
|
|
virtual ~Blocking_Client() = default;
|
|
|
|
protected:
|
|
/**
|
|
* Application can override to get the handshake complete notification
|
|
*/
|
|
virtual bool handshake_complete(const Session&) { return true; }
|
|
|
|
/**
|
|
* Application can override to get notification of alerts
|
|
*/
|
|
virtual void alert_notification(const Alert&) {}
|
|
|
|
private:
|
|
|
|
bool handshake_cb(const Session&);
|
|
|
|
void data_cb(const uint8_t data[], size_t data_len);
|
|
|
|
void alert_cb(const Alert& alert);
|
|
|
|
read_fn m_read;
|
|
std::unique_ptr<Compat_Callbacks> m_callbacks;
|
|
TLS::Client m_channel;
|
|
secure_vector<uint8_t> m_plaintext;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* TLS Exception Base Class
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) TLS_Exception : public Exception
|
|
{
|
|
public:
|
|
Alert::Type type() const { return m_alert_type; }
|
|
|
|
TLS_Exception(Alert::Type type,
|
|
const std::string& err_msg = "Unknown error") :
|
|
Exception(err_msg), m_alert_type(type) {}
|
|
|
|
int error_code() const noexcept override { return static_cast<int>(m_alert_type); }
|
|
|
|
ErrorType error_type() const noexcept override { return ErrorType::TLSError; }
|
|
|
|
private:
|
|
Alert::Type m_alert_type;
|
|
};
|
|
|
|
/**
|
|
* Unexpected_Message Exception
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Unexpected_Message final : public TLS_Exception
|
|
{
|
|
public:
|
|
explicit Unexpected_Message(const std::string& err) :
|
|
TLS_Exception(Alert::UNEXPECTED_MESSAGE, err) {}
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
class Policy;
|
|
|
|
class TLS_Data_Reader;
|
|
|
|
// This will become an enum class in a future major release
|
|
enum Handshake_Extension_Type {
|
|
TLSEXT_SERVER_NAME_INDICATION = 0,
|
|
TLSEXT_CERT_STATUS_REQUEST = 5,
|
|
|
|
TLSEXT_CERTIFICATE_TYPES = 9,
|
|
TLSEXT_SUPPORTED_GROUPS = 10,
|
|
TLSEXT_EC_POINT_FORMATS = 11,
|
|
TLSEXT_SRP_IDENTIFIER = 12,
|
|
TLSEXT_SIGNATURE_ALGORITHMS = 13,
|
|
TLSEXT_USE_SRTP = 14,
|
|
TLSEXT_ALPN = 16,
|
|
|
|
TLSEXT_ENCRYPT_THEN_MAC = 22,
|
|
TLSEXT_EXTENDED_MASTER_SECRET = 23,
|
|
|
|
TLSEXT_SESSION_TICKET = 35,
|
|
|
|
TLSEXT_SUPPORTED_VERSIONS = 43,
|
|
|
|
TLSEXT_SAFE_RENEGOTIATION = 65281,
|
|
};
|
|
|
|
/**
|
|
* Base class representing a TLS extension of some kind
|
|
*/
|
|
class BOTAN_UNSTABLE_API Extension
|
|
{
|
|
public:
|
|
/**
|
|
* @return code number of the extension
|
|
*/
|
|
virtual Handshake_Extension_Type type() const = 0;
|
|
|
|
/**
|
|
* @return serialized binary for the extension
|
|
*/
|
|
virtual std::vector<uint8_t> serialize(Connection_Side whoami) const = 0;
|
|
|
|
/**
|
|
* @return if we should encode this extension or not
|
|
*/
|
|
virtual bool empty() const = 0;
|
|
|
|
virtual ~Extension() = default;
|
|
};
|
|
|
|
/**
|
|
* Server Name Indicator extension (RFC 3546)
|
|
*/
|
|
class BOTAN_UNSTABLE_API Server_Name_Indicator final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_SERVER_NAME_INDICATION; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
explicit Server_Name_Indicator(const std::string& host_name) :
|
|
m_sni_host_name(host_name) {}
|
|
|
|
Server_Name_Indicator(TLS_Data_Reader& reader,
|
|
uint16_t extension_size);
|
|
|
|
std::string host_name() const { return m_sni_host_name; }
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
bool empty() const override { return m_sni_host_name.empty(); }
|
|
private:
|
|
std::string m_sni_host_name;
|
|
};
|
|
|
|
#if defined(BOTAN_HAS_SRP6)
|
|
/**
|
|
* SRP identifier extension (RFC 5054)
|
|
*/
|
|
class BOTAN_UNSTABLE_API SRP_Identifier final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_SRP_IDENTIFIER; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
explicit SRP_Identifier(const std::string& identifier) :
|
|
m_srp_identifier(identifier) {}
|
|
|
|
SRP_Identifier(TLS_Data_Reader& reader,
|
|
uint16_t extension_size);
|
|
|
|
std::string identifier() const { return m_srp_identifier; }
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
bool empty() const override { return m_srp_identifier.empty(); }
|
|
private:
|
|
std::string m_srp_identifier;
|
|
};
|
|
#endif
|
|
|
|
/**
|
|
* Renegotiation Indication Extension (RFC 5746)
|
|
*/
|
|
class BOTAN_UNSTABLE_API Renegotiation_Extension final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_SAFE_RENEGOTIATION; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
Renegotiation_Extension() = default;
|
|
|
|
explicit Renegotiation_Extension(const std::vector<uint8_t>& bits) :
|
|
m_reneg_data(bits) {}
|
|
|
|
Renegotiation_Extension(TLS_Data_Reader& reader,
|
|
uint16_t extension_size);
|
|
|
|
const std::vector<uint8_t>& renegotiation_info() const
|
|
{ return m_reneg_data; }
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
bool empty() const override { return false; } // always send this
|
|
private:
|
|
std::vector<uint8_t> m_reneg_data;
|
|
};
|
|
|
|
/**
|
|
* ALPN (RFC 7301)
|
|
*/
|
|
class BOTAN_UNSTABLE_API Application_Layer_Protocol_Notification final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type() { return TLSEXT_ALPN; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
const std::vector<std::string>& protocols() const { return m_protocols; }
|
|
|
|
const std::string& single_protocol() const;
|
|
|
|
/**
|
|
* Single protocol, used by server
|
|
*/
|
|
explicit Application_Layer_Protocol_Notification(const std::string& protocol) :
|
|
m_protocols(1, protocol) {}
|
|
|
|
/**
|
|
* List of protocols, used by client
|
|
*/
|
|
explicit Application_Layer_Protocol_Notification(const std::vector<std::string>& protocols) :
|
|
m_protocols(protocols) {}
|
|
|
|
Application_Layer_Protocol_Notification(TLS_Data_Reader& reader,
|
|
uint16_t extension_size);
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
bool empty() const override { return m_protocols.empty(); }
|
|
private:
|
|
std::vector<std::string> m_protocols;
|
|
};
|
|
|
|
/**
|
|
* Session Ticket Extension (RFC 5077)
|
|
*/
|
|
class BOTAN_UNSTABLE_API Session_Ticket final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_SESSION_TICKET; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
/**
|
|
* @return contents of the session ticket
|
|
*/
|
|
const std::vector<uint8_t>& contents() const { return m_ticket; }
|
|
|
|
/**
|
|
* Create empty extension, used by both client and server
|
|
*/
|
|
Session_Ticket() = default;
|
|
|
|
/**
|
|
* Extension with ticket, used by client
|
|
*/
|
|
explicit Session_Ticket(const std::vector<uint8_t>& session_ticket) :
|
|
m_ticket(session_ticket) {}
|
|
|
|
/**
|
|
* Deserialize a session ticket
|
|
*/
|
|
Session_Ticket(TLS_Data_Reader& reader, uint16_t extension_size);
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side) const override { return m_ticket; }
|
|
|
|
bool empty() const override { return false; }
|
|
private:
|
|
std::vector<uint8_t> m_ticket;
|
|
};
|
|
|
|
|
|
/**
|
|
* Supported Groups Extension (RFC 7919)
|
|
*/
|
|
class BOTAN_UNSTABLE_API Supported_Groups final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_SUPPORTED_GROUPS; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
std::vector<Group_Params> ec_groups() const;
|
|
std::vector<Group_Params> dh_groups() const;
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
explicit Supported_Groups(const std::vector<Group_Params>& groups);
|
|
|
|
Supported_Groups(TLS_Data_Reader& reader,
|
|
uint16_t extension_size);
|
|
|
|
bool empty() const override { return m_groups.empty(); }
|
|
private:
|
|
std::vector<Group_Params> m_groups;
|
|
};
|
|
|
|
// previously Supported Elliptic Curves Extension (RFC 4492)
|
|
//using Supported_Elliptic_Curves = Supported_Groups;
|
|
|
|
/**
|
|
* Supported Point Formats Extension (RFC 4492)
|
|
*/
|
|
class BOTAN_UNSTABLE_API Supported_Point_Formats final : public Extension
|
|
{
|
|
public:
|
|
enum ECPointFormat : uint8_t {
|
|
UNCOMPRESSED = 0,
|
|
ANSIX962_COMPRESSED_PRIME = 1,
|
|
ANSIX962_COMPRESSED_CHAR2 = 2, // don't support these curves
|
|
};
|
|
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_EC_POINT_FORMATS; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
explicit Supported_Point_Formats(bool prefer_compressed) :
|
|
m_prefers_compressed(prefer_compressed) {}
|
|
|
|
Supported_Point_Formats(TLS_Data_Reader& reader,
|
|
uint16_t extension_size);
|
|
|
|
bool empty() const override { return false; }
|
|
|
|
bool prefers_compressed() { return m_prefers_compressed; }
|
|
|
|
private:
|
|
bool m_prefers_compressed = false;
|
|
};
|
|
|
|
/**
|
|
* Signature Algorithms Extension for TLS 1.2 (RFC 5246)
|
|
*/
|
|
class BOTAN_UNSTABLE_API Signature_Algorithms final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_SIGNATURE_ALGORITHMS; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
const std::vector<Signature_Scheme>& supported_schemes() const { return m_schemes; }
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
bool empty() const override { return m_schemes.empty(); }
|
|
|
|
explicit Signature_Algorithms(const std::vector<Signature_Scheme>& schemes) :
|
|
m_schemes(schemes) {}
|
|
|
|
Signature_Algorithms(TLS_Data_Reader& reader,
|
|
uint16_t extension_size);
|
|
private:
|
|
std::vector<Signature_Scheme> m_schemes;
|
|
};
|
|
|
|
/**
|
|
* Used to indicate SRTP algorithms for DTLS (RFC 5764)
|
|
*/
|
|
class BOTAN_UNSTABLE_API SRTP_Protection_Profiles final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_USE_SRTP; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
const std::vector<uint16_t>& profiles() const { return m_pp; }
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
bool empty() const override { return m_pp.empty(); }
|
|
|
|
explicit SRTP_Protection_Profiles(const std::vector<uint16_t>& pp) : m_pp(pp) {}
|
|
|
|
explicit SRTP_Protection_Profiles(uint16_t pp) : m_pp(1, pp) {}
|
|
|
|
SRTP_Protection_Profiles(TLS_Data_Reader& reader, uint16_t extension_size);
|
|
private:
|
|
std::vector<uint16_t> m_pp;
|
|
};
|
|
|
|
/**
|
|
* Extended Master Secret Extension (RFC 7627)
|
|
*/
|
|
class BOTAN_UNSTABLE_API Extended_Master_Secret final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_EXTENDED_MASTER_SECRET; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
bool empty() const override { return false; }
|
|
|
|
Extended_Master_Secret() = default;
|
|
|
|
Extended_Master_Secret(TLS_Data_Reader& reader, uint16_t extension_size);
|
|
};
|
|
|
|
/**
|
|
* Encrypt-then-MAC Extension (RFC 7366)
|
|
*/
|
|
class BOTAN_UNSTABLE_API Encrypt_then_MAC final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_ENCRYPT_THEN_MAC; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
bool empty() const override { return false; }
|
|
|
|
Encrypt_then_MAC() = default;
|
|
|
|
Encrypt_then_MAC(TLS_Data_Reader& reader, uint16_t extension_size);
|
|
};
|
|
|
|
/**
|
|
* Certificate Status Request (RFC 6066)
|
|
*/
|
|
class BOTAN_UNSTABLE_API Certificate_Status_Request final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_CERT_STATUS_REQUEST; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
bool empty() const override { return false; }
|
|
|
|
const std::vector<uint8_t>& get_responder_id_list() const
|
|
{
|
|
return m_ocsp_names;
|
|
}
|
|
|
|
const std::vector<uint8_t>& get_request_extensions() const
|
|
{
|
|
return m_extension_bytes;
|
|
}
|
|
|
|
// Server generated version: empty
|
|
Certificate_Status_Request() {}
|
|
|
|
// Client version, both lists can be empty
|
|
Certificate_Status_Request(const std::vector<uint8_t>& ocsp_responder_ids,
|
|
const std::vector<std::vector<uint8_t>>& ocsp_key_ids);
|
|
|
|
Certificate_Status_Request(TLS_Data_Reader& reader,
|
|
uint16_t extension_size,
|
|
Connection_Side side);
|
|
private:
|
|
std::vector<uint8_t> m_ocsp_names;
|
|
std::vector<std::vector<uint8_t>> m_ocsp_keys; // is this field really needed
|
|
std::vector<uint8_t> m_extension_bytes;
|
|
};
|
|
|
|
/**
|
|
* Supported Versions from RFC 8446
|
|
*/
|
|
class BOTAN_UNSTABLE_API Supported_Versions final : public Extension
|
|
{
|
|
public:
|
|
static Handshake_Extension_Type static_type()
|
|
{ return TLSEXT_SUPPORTED_VERSIONS; }
|
|
|
|
Handshake_Extension_Type type() const override { return static_type(); }
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override;
|
|
|
|
bool empty() const override { return m_versions.empty(); }
|
|
|
|
Supported_Versions(Protocol_Version version, const Policy& policy);
|
|
|
|
Supported_Versions(Protocol_Version version)
|
|
{
|
|
m_versions.push_back(version);
|
|
}
|
|
|
|
Supported_Versions(TLS_Data_Reader& reader,
|
|
uint16_t extension_size,
|
|
Connection_Side from);
|
|
|
|
bool supports(Protocol_Version version) const;
|
|
|
|
const std::vector<Protocol_Version> versions() const { return m_versions; }
|
|
private:
|
|
std::vector<Protocol_Version> m_versions;
|
|
};
|
|
|
|
/**
|
|
* Unknown extensions are deserialized as this type
|
|
*/
|
|
class BOTAN_UNSTABLE_API Unknown_Extension final : public Extension
|
|
{
|
|
public:
|
|
Unknown_Extension(Handshake_Extension_Type type,
|
|
TLS_Data_Reader& reader,
|
|
uint16_t extension_size);
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const override; // always fails
|
|
|
|
const std::vector<uint8_t>& value() { return m_value; }
|
|
|
|
bool empty() const override { return false; }
|
|
|
|
Handshake_Extension_Type type() const override { return m_type; }
|
|
|
|
private:
|
|
Handshake_Extension_Type m_type;
|
|
std::vector<uint8_t> m_value;
|
|
};
|
|
|
|
/**
|
|
* Represents a block of extensions in a hello message
|
|
*/
|
|
class BOTAN_UNSTABLE_API Extensions final
|
|
{
|
|
public:
|
|
std::set<Handshake_Extension_Type> extension_types() const;
|
|
|
|
template<typename T>
|
|
T* get() const
|
|
{
|
|
return dynamic_cast<T*>(get(T::static_type()));
|
|
}
|
|
|
|
template<typename T>
|
|
bool has() const
|
|
{
|
|
return get<T>() != nullptr;
|
|
}
|
|
|
|
void add(Extension* extn)
|
|
{
|
|
m_extensions[extn->type()].reset(extn);
|
|
}
|
|
|
|
Extension* get(Handshake_Extension_Type type) const
|
|
{
|
|
auto i = m_extensions.find(type);
|
|
|
|
if(i != m_extensions.end())
|
|
return i->second.get();
|
|
return nullptr;
|
|
}
|
|
|
|
std::vector<uint8_t> serialize(Connection_Side whoami) const;
|
|
|
|
void deserialize(TLS_Data_Reader& reader, Connection_Side from);
|
|
|
|
/**
|
|
* Remvoe an extension from this extensions object, if it exists.
|
|
* Returns true if the extension existed (and thus is now removed),
|
|
* otherwise false (the extension wasn't set in the first place).
|
|
*/
|
|
bool remove_extension(Handshake_Extension_Type typ);
|
|
|
|
Extensions() = default;
|
|
|
|
Extensions(TLS_Data_Reader& reader, Connection_Side side)
|
|
{
|
|
deserialize(reader, side);
|
|
}
|
|
|
|
private:
|
|
Extensions(const Extensions&) = delete;
|
|
Extensions& operator=(const Extensions&) = delete;
|
|
|
|
std::map<Handshake_Extension_Type, std::unique_ptr<Extension>> m_extensions;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
class Handshake_IO;
|
|
class Handshake_Hash;
|
|
|
|
/**
|
|
* TLS Handshake Message Base Class
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Handshake_Message
|
|
{
|
|
public:
|
|
/**
|
|
* @return string representation of this message type
|
|
*/
|
|
std::string type_string() const;
|
|
|
|
/**
|
|
* @return the message type
|
|
*/
|
|
virtual Handshake_Type type() const = 0;
|
|
|
|
/**
|
|
* @return DER representation of this message
|
|
*/
|
|
virtual std::vector<uint8_t> serialize() const = 0;
|
|
|
|
virtual ~Handshake_Message() = default;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if defined(BOTAN_HAS_CECPQ1)
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_SRP6)
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
class Public_Key;
|
|
class Credentials_Manager;
|
|
|
|
namespace TLS {
|
|
|
|
class Session;
|
|
class Handshake_IO;
|
|
class Handshake_State;
|
|
class Callbacks;
|
|
|
|
std::vector<uint8_t> make_hello_random(RandomNumberGenerator& rng,
|
|
const Policy& policy);
|
|
|
|
/**
|
|
* DTLS Hello Verify Request
|
|
*/
|
|
class BOTAN_UNSTABLE_API Hello_Verify_Request final : public Handshake_Message
|
|
{
|
|
public:
|
|
std::vector<uint8_t> serialize() const override;
|
|
Handshake_Type type() const override { return HELLO_VERIFY_REQUEST; }
|
|
|
|
const std::vector<uint8_t>& cookie() const { return m_cookie; }
|
|
|
|
explicit Hello_Verify_Request(const std::vector<uint8_t>& buf);
|
|
|
|
Hello_Verify_Request(const std::vector<uint8_t>& client_hello_bits,
|
|
const std::string& client_identity,
|
|
const SymmetricKey& secret_key);
|
|
private:
|
|
std::vector<uint8_t> m_cookie;
|
|
};
|
|
|
|
/**
|
|
* Client Hello Message
|
|
*/
|
|
class BOTAN_UNSTABLE_API Client_Hello final : public Handshake_Message
|
|
{
|
|
public:
|
|
class Settings final
|
|
{
|
|
public:
|
|
Settings(const Protocol_Version version,
|
|
const std::string& hostname = "",
|
|
const std::string& srp_identifier = "") :
|
|
m_new_session_version(version),
|
|
m_hostname(hostname),
|
|
m_srp_identifier(srp_identifier) {}
|
|
|
|
const Protocol_Version protocol_version() const { return m_new_session_version; }
|
|
const std::string& hostname() const { return m_hostname; }
|
|
const std::string& srp_identifier() const { return m_srp_identifier; }
|
|
|
|
private:
|
|
const Protocol_Version m_new_session_version;
|
|
const std::string m_hostname;
|
|
const std::string m_srp_identifier;
|
|
};
|
|
|
|
Handshake_Type type() const override { return CLIENT_HELLO; }
|
|
|
|
Protocol_Version version() const { return m_version; }
|
|
|
|
std::vector<Protocol_Version> supported_versions() const;
|
|
|
|
const std::vector<uint8_t>& random() const { return m_random; }
|
|
|
|
const std::vector<uint8_t>& session_id() const { return m_session_id; }
|
|
|
|
const std::vector<uint8_t>& compression_methods() const { return m_comp_methods; }
|
|
|
|
const std::vector<uint16_t>& ciphersuites() const { return m_suites; }
|
|
|
|
bool offered_suite(uint16_t ciphersuite) const;
|
|
|
|
bool sent_fallback_scsv() const;
|
|
|
|
std::vector<Signature_Scheme> signature_schemes() const;
|
|
|
|
std::vector<Group_Params> supported_ecc_curves() const;
|
|
|
|
std::vector<Group_Params> supported_dh_groups() const;
|
|
|
|
bool prefers_compressed_ec_points() const;
|
|
|
|
std::string sni_hostname() const;
|
|
|
|
#if defined(BOTAN_HAS_SRP6)
|
|
std::string srp_identifier() const;
|
|
#endif
|
|
|
|
bool secure_renegotiation() const;
|
|
|
|
std::vector<uint8_t> renegotiation_info() const;
|
|
|
|
bool supports_session_ticket() const;
|
|
|
|
std::vector<uint8_t> session_ticket() const;
|
|
|
|
bool supports_alpn() const;
|
|
|
|
bool supports_extended_master_secret() const;
|
|
|
|
bool supports_cert_status_message() const;
|
|
|
|
bool supports_encrypt_then_mac() const;
|
|
|
|
bool sent_signature_algorithms() const;
|
|
|
|
std::vector<std::string> next_protocols() const;
|
|
|
|
std::vector<uint16_t> srtp_profiles() const;
|
|
|
|
void update_hello_cookie(const Hello_Verify_Request& hello_verify);
|
|
|
|
const std::vector<uint8_t>& cookie() const { return m_hello_cookie; }
|
|
|
|
std::vector<uint8_t> cookie_input_data() const;
|
|
|
|
std::set<Handshake_Extension_Type> extension_types() const
|
|
{ return m_extensions.extension_types(); }
|
|
|
|
const Extensions& extensions() const { return m_extensions; }
|
|
|
|
Client_Hello(Handshake_IO& io,
|
|
Handshake_Hash& hash,
|
|
const Policy& policy,
|
|
Callbacks& cb,
|
|
RandomNumberGenerator& rng,
|
|
const std::vector<uint8_t>& reneg_info,
|
|
const Client_Hello::Settings& client_settings,
|
|
const std::vector<std::string>& next_protocols);
|
|
|
|
Client_Hello(Handshake_IO& io,
|
|
Handshake_Hash& hash,
|
|
const Policy& policy,
|
|
Callbacks& cb,
|
|
RandomNumberGenerator& rng,
|
|
const std::vector<uint8_t>& reneg_info,
|
|
const Session& resumed_session,
|
|
const std::vector<std::string>& next_protocols);
|
|
|
|
explicit Client_Hello(const std::vector<uint8_t>& buf);
|
|
|
|
private:
|
|
std::vector<uint8_t> serialize() const override;
|
|
|
|
Protocol_Version m_version;
|
|
std::vector<uint8_t> m_session_id;
|
|
std::vector<uint8_t> m_random;
|
|
std::vector<uint16_t> m_suites;
|
|
std::vector<uint8_t> m_comp_methods;
|
|
std::vector<uint8_t> m_hello_cookie; // DTLS only
|
|
|
|
Extensions m_extensions;
|
|
};
|
|
|
|
/**
|
|
* Server Hello Message
|
|
*/
|
|
class BOTAN_UNSTABLE_API Server_Hello final : public Handshake_Message
|
|
{
|
|
public:
|
|
class Settings final
|
|
{
|
|
public:
|
|
Settings(const std::vector<uint8_t> new_session_id,
|
|
Protocol_Version new_session_version,
|
|
uint16_t ciphersuite,
|
|
bool offer_session_ticket) :
|
|
m_new_session_id(new_session_id),
|
|
m_new_session_version(new_session_version),
|
|
m_ciphersuite(ciphersuite),
|
|
m_offer_session_ticket(offer_session_ticket) {}
|
|
|
|
const std::vector<uint8_t>& session_id() const { return m_new_session_id; }
|
|
Protocol_Version protocol_version() const { return m_new_session_version; }
|
|
uint16_t ciphersuite() const { return m_ciphersuite; }
|
|
bool offer_session_ticket() const { return m_offer_session_ticket; }
|
|
|
|
private:
|
|
const std::vector<uint8_t> m_new_session_id;
|
|
Protocol_Version m_new_session_version;
|
|
uint16_t m_ciphersuite;
|
|
bool m_offer_session_ticket;
|
|
};
|
|
|
|
|
|
Handshake_Type type() const override { return SERVER_HELLO; }
|
|
|
|
Protocol_Version version() const { return m_version; }
|
|
|
|
const std::vector<uint8_t>& random() const { return m_random; }
|
|
|
|
const std::vector<uint8_t>& session_id() const { return m_session_id; }
|
|
|
|
uint16_t ciphersuite() const { return m_ciphersuite; }
|
|
|
|
uint8_t compression_method() const { return m_comp_method; }
|
|
|
|
bool secure_renegotiation() const
|
|
{
|
|
return m_extensions.has<Renegotiation_Extension>();
|
|
}
|
|
|
|
std::vector<uint8_t> renegotiation_info() const
|
|
{
|
|
if(Renegotiation_Extension* reneg = m_extensions.get<Renegotiation_Extension>())
|
|
return reneg->renegotiation_info();
|
|
return std::vector<uint8_t>();
|
|
}
|
|
|
|
bool supports_extended_master_secret() const
|
|
{
|
|
return m_extensions.has<Extended_Master_Secret>();
|
|
}
|
|
|
|
bool supports_encrypt_then_mac() const
|
|
{
|
|
return m_extensions.has<Encrypt_then_MAC>();
|
|
}
|
|
|
|
bool supports_certificate_status_message() const
|
|
{
|
|
return m_extensions.has<Certificate_Status_Request>();
|
|
}
|
|
|
|
bool supports_session_ticket() const
|
|
{
|
|
return m_extensions.has<Session_Ticket>();
|
|
}
|
|
|
|
uint16_t srtp_profile() const
|
|
{
|
|
if(auto srtp = m_extensions.get<SRTP_Protection_Profiles>())
|
|
{
|
|
auto prof = srtp->profiles();
|
|
if(prof.size() != 1 || prof[0] == 0)
|
|
throw Decoding_Error("Server sent malformed DTLS-SRTP extension");
|
|
return prof[0];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
std::string next_protocol() const
|
|
{
|
|
if(auto alpn = m_extensions.get<Application_Layer_Protocol_Notification>())
|
|
return alpn->single_protocol();
|
|
return "";
|
|
}
|
|
|
|
std::set<Handshake_Extension_Type> extension_types() const
|
|
{ return m_extensions.extension_types(); }
|
|
|
|
const Extensions& extensions() const { return m_extensions; }
|
|
|
|
bool prefers_compressed_ec_points() const
|
|
{
|
|
if(auto ecc_formats = m_extensions.get<Supported_Point_Formats>())
|
|
{
|
|
return ecc_formats->prefers_compressed();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool random_signals_downgrade() const;
|
|
|
|
Server_Hello(Handshake_IO& io,
|
|
Handshake_Hash& hash,
|
|
const Policy& policy,
|
|
Callbacks& cb,
|
|
RandomNumberGenerator& rng,
|
|
const std::vector<uint8_t>& secure_reneg_info,
|
|
const Client_Hello& client_hello,
|
|
const Server_Hello::Settings& settings,
|
|
const std::string next_protocol);
|
|
|
|
Server_Hello(Handshake_IO& io,
|
|
Handshake_Hash& hash,
|
|
const Policy& policy,
|
|
Callbacks& cb,
|
|
RandomNumberGenerator& rng,
|
|
const std::vector<uint8_t>& secure_reneg_info,
|
|
const Client_Hello& client_hello,
|
|
Session& resumed_session,
|
|
bool offer_session_ticket,
|
|
const std::string& next_protocol);
|
|
|
|
explicit Server_Hello(const std::vector<uint8_t>& buf);
|
|
private:
|
|
std::vector<uint8_t> serialize() const override;
|
|
|
|
Protocol_Version m_version;
|
|
std::vector<uint8_t> m_session_id, m_random;
|
|
uint16_t m_ciphersuite;
|
|
uint8_t m_comp_method;
|
|
|
|
Extensions m_extensions;
|
|
};
|
|
|
|
/**
|
|
* Client Key Exchange Message
|
|
*/
|
|
class BOTAN_UNSTABLE_API Client_Key_Exchange final : public Handshake_Message
|
|
{
|
|
public:
|
|
Handshake_Type type() const override { return CLIENT_KEX; }
|
|
|
|
const secure_vector<uint8_t>& pre_master_secret() const
|
|
{ return m_pre_master; }
|
|
|
|
Client_Key_Exchange(Handshake_IO& io,
|
|
Handshake_State& state,
|
|
const Policy& policy,
|
|
Credentials_Manager& creds,
|
|
const Public_Key* server_public_key,
|
|
const std::string& hostname,
|
|
RandomNumberGenerator& rng);
|
|
|
|
Client_Key_Exchange(const std::vector<uint8_t>& buf,
|
|
const Handshake_State& state,
|
|
const Private_Key* server_rsa_kex_key,
|
|
Credentials_Manager& creds,
|
|
const Policy& policy,
|
|
RandomNumberGenerator& rng);
|
|
|
|
private:
|
|
std::vector<uint8_t> serialize() const override
|
|
{ return m_key_material; }
|
|
|
|
std::vector<uint8_t> m_key_material;
|
|
secure_vector<uint8_t> m_pre_master;
|
|
};
|
|
|
|
/**
|
|
* Certificate Message
|
|
*/
|
|
class BOTAN_UNSTABLE_API Certificate final : public Handshake_Message
|
|
{
|
|
public:
|
|
Handshake_Type type() const override { return CERTIFICATE; }
|
|
const std::vector<X509_Certificate>& cert_chain() const { return m_certs; }
|
|
|
|
size_t count() const { return m_certs.size(); }
|
|
bool empty() const { return m_certs.empty(); }
|
|
|
|
Certificate(Handshake_IO& io,
|
|
Handshake_Hash& hash,
|
|
const std::vector<X509_Certificate>& certs);
|
|
|
|
explicit Certificate(const std::vector<uint8_t>& buf, const Policy &policy);
|
|
private:
|
|
std::vector<uint8_t> serialize() const override;
|
|
|
|
std::vector<X509_Certificate> m_certs;
|
|
};
|
|
|
|
/**
|
|
* Certificate Status (RFC 6066)
|
|
*/
|
|
class BOTAN_UNSTABLE_API Certificate_Status final : public Handshake_Message
|
|
{
|
|
public:
|
|
Handshake_Type type() const override { return CERTIFICATE_STATUS; }
|
|
|
|
//std::shared_ptr<const OCSP::Response> response() const { return m_response; }
|
|
|
|
const std::vector<uint8_t>& response() const { return m_response; }
|
|
|
|
Certificate_Status(const std::vector<uint8_t>& buf);
|
|
|
|
Certificate_Status(Handshake_IO& io,
|
|
Handshake_Hash& hash,
|
|
std::shared_ptr<const OCSP::Response> response);
|
|
|
|
/*
|
|
* Create a Certificate_Status message using an already DER encoded OCSP response.
|
|
*/
|
|
Certificate_Status(Handshake_IO& io,
|
|
Handshake_Hash& hash,
|
|
std::vector<uint8_t> const& raw_response_bytes );
|
|
|
|
private:
|
|
std::vector<uint8_t> serialize() const override;
|
|
std::vector<uint8_t> m_response;
|
|
};
|
|
|
|
/**
|
|
* Certificate Request Message
|
|
*/
|
|
class BOTAN_UNSTABLE_API Certificate_Req final : public Handshake_Message
|
|
{
|
|
public:
|
|
Handshake_Type type() const override { return CERTIFICATE_REQUEST; }
|
|
|
|
const std::vector<std::string>& acceptable_cert_types() const
|
|
{ return m_cert_key_types; }
|
|
|
|
const std::vector<X509_DN>& acceptable_CAs() const { return m_names; }
|
|
|
|
const std::vector<Signature_Scheme>& signature_schemes() const
|
|
{
|
|
return m_schemes;
|
|
}
|
|
|
|
Certificate_Req(Handshake_IO& io,
|
|
Handshake_Hash& hash,
|
|
const Policy& policy,
|
|
const std::vector<X509_DN>& allowed_cas,
|
|
Protocol_Version version);
|
|
|
|
Certificate_Req(const std::vector<uint8_t>& buf,
|
|
Protocol_Version version);
|
|
private:
|
|
std::vector<uint8_t> serialize() const override;
|
|
|
|
std::vector<X509_DN> m_names;
|
|
std::vector<std::string> m_cert_key_types;
|
|
|
|
std::vector<Signature_Scheme> m_schemes;
|
|
};
|
|
|
|
/**
|
|
* Certificate Verify Message
|
|
*/
|
|
class BOTAN_UNSTABLE_API Certificate_Verify final : public Handshake_Message
|
|
{
|
|
public:
|
|
Handshake_Type type() const override { return CERTIFICATE_VERIFY; }
|
|
|
|
/**
|
|
* Check the signature on a certificate verify message
|
|
* @param cert the purported certificate
|
|
* @param state the handshake state
|
|
* @param policy the TLS policy
|
|
*/
|
|
bool verify(const X509_Certificate& cert,
|
|
const Handshake_State& state,
|
|
const Policy& policy) const;
|
|
|
|
Certificate_Verify(Handshake_IO& io,
|
|
Handshake_State& state,
|
|
const Policy& policy,
|
|
RandomNumberGenerator& rng,
|
|
const Private_Key* key);
|
|
|
|
Certificate_Verify(const std::vector<uint8_t>& buf,
|
|
Protocol_Version version);
|
|
private:
|
|
std::vector<uint8_t> serialize() const override;
|
|
|
|
std::vector<uint8_t> m_signature;
|
|
Signature_Scheme m_scheme = Signature_Scheme::NONE;
|
|
};
|
|
|
|
/**
|
|
* Finished Message
|
|
*/
|
|
class BOTAN_UNSTABLE_API Finished final : public Handshake_Message
|
|
{
|
|
public:
|
|
Handshake_Type type() const override { return FINISHED; }
|
|
|
|
std::vector<uint8_t> verify_data() const
|
|
{ return m_verification_data; }
|
|
|
|
bool verify(const Handshake_State& state,
|
|
Connection_Side side) const;
|
|
|
|
Finished(Handshake_IO& io,
|
|
Handshake_State& state,
|
|
Connection_Side side);
|
|
|
|
explicit Finished(const std::vector<uint8_t>& buf);
|
|
private:
|
|
std::vector<uint8_t> serialize() const override;
|
|
|
|
std::vector<uint8_t> m_verification_data;
|
|
};
|
|
|
|
/**
|
|
* Hello Request Message
|
|
*/
|
|
class BOTAN_UNSTABLE_API Hello_Request final : public Handshake_Message
|
|
{
|
|
public:
|
|
Handshake_Type type() const override { return HELLO_REQUEST; }
|
|
|
|
explicit Hello_Request(Handshake_IO& io);
|
|
explicit Hello_Request(const std::vector<uint8_t>& buf);
|
|
private:
|
|
std::vector<uint8_t> serialize() const override;
|
|
};
|
|
|
|
/**
|
|
* Server Key Exchange Message
|
|
*/
|
|
class BOTAN_UNSTABLE_API Server_Key_Exchange final : public Handshake_Message
|
|
{
|
|
public:
|
|
Handshake_Type type() const override { return SERVER_KEX; }
|
|
|
|
const std::vector<uint8_t>& params() const { return m_params; }
|
|
|
|
bool verify(const Public_Key& server_key,
|
|
const Handshake_State& state,
|
|
const Policy& policy) const;
|
|
|
|
// Only valid for certain kex types
|
|
const Private_Key& server_kex_key() const;
|
|
|
|
#if defined(BOTAN_HAS_SRP6)
|
|
// Only valid for SRP negotiation
|
|
SRP6_Server_Session& server_srp_params() const
|
|
{
|
|
BOTAN_ASSERT_NONNULL(m_srp_params);
|
|
return *m_srp_params;
|
|
}
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_CECPQ1)
|
|
// Only valid for CECPQ1 negotiation
|
|
const CECPQ1_key& cecpq1_key() const
|
|
{
|
|
BOTAN_ASSERT_NONNULL(m_cecpq1_key);
|
|
return *m_cecpq1_key;
|
|
}
|
|
#endif
|
|
|
|
Server_Key_Exchange(Handshake_IO& io,
|
|
Handshake_State& state,
|
|
const Policy& policy,
|
|
Credentials_Manager& creds,
|
|
RandomNumberGenerator& rng,
|
|
const Private_Key* signing_key = nullptr);
|
|
|
|
Server_Key_Exchange(const std::vector<uint8_t>& buf,
|
|
Kex_Algo kex_alg,
|
|
Auth_Method sig_alg,
|
|
Protocol_Version version);
|
|
|
|
~Server_Key_Exchange() = default;
|
|
private:
|
|
std::vector<uint8_t> serialize() const override;
|
|
|
|
#if defined(BOTAN_HAS_SRP6)
|
|
std::unique_ptr<SRP6_Server_Session> m_srp_params;
|
|
#endif
|
|
|
|
#if defined(BOTAN_HAS_CECPQ1)
|
|
std::unique_ptr<CECPQ1_key> m_cecpq1_key;
|
|
#endif
|
|
|
|
std::unique_ptr<Private_Key> m_kex_key;
|
|
|
|
std::vector<uint8_t> m_params;
|
|
|
|
std::vector<uint8_t> m_signature;
|
|
Signature_Scheme m_scheme = Signature_Scheme::NONE;
|
|
};
|
|
|
|
/**
|
|
* Server Hello Done Message
|
|
*/
|
|
class BOTAN_UNSTABLE_API Server_Hello_Done final : public Handshake_Message
|
|
{
|
|
public:
|
|
Handshake_Type type() const override { return SERVER_HELLO_DONE; }
|
|
|
|
Server_Hello_Done(Handshake_IO& io, Handshake_Hash& hash);
|
|
explicit Server_Hello_Done(const std::vector<uint8_t>& buf);
|
|
private:
|
|
std::vector<uint8_t> serialize() const override;
|
|
};
|
|
|
|
/**
|
|
* New Session Ticket Message
|
|
*/
|
|
class BOTAN_UNSTABLE_API New_Session_Ticket final : public Handshake_Message
|
|
{
|
|
public:
|
|
Handshake_Type type() const override { return NEW_SESSION_TICKET; }
|
|
|
|
uint32_t ticket_lifetime_hint() const { return m_ticket_lifetime_hint; }
|
|
const std::vector<uint8_t>& ticket() const { return m_ticket; }
|
|
|
|
New_Session_Ticket(Handshake_IO& io,
|
|
Handshake_Hash& hash,
|
|
const std::vector<uint8_t>& ticket,
|
|
uint32_t lifetime);
|
|
|
|
New_Session_Ticket(Handshake_IO& io,
|
|
Handshake_Hash& hash);
|
|
|
|
explicit New_Session_Ticket(const std::vector<uint8_t>& buf);
|
|
private:
|
|
std::vector<uint8_t> serialize() const override;
|
|
|
|
uint32_t m_ticket_lifetime_hint = 0;
|
|
std::vector<uint8_t> m_ticket;
|
|
};
|
|
|
|
/**
|
|
* Change Cipher Spec
|
|
*/
|
|
class BOTAN_UNSTABLE_API Change_Cipher_Spec final : public Handshake_Message
|
|
{
|
|
public:
|
|
Handshake_Type type() const override { return HANDSHAKE_CCS; }
|
|
|
|
std::vector<uint8_t> serialize() const override
|
|
{ return std::vector<uint8_t>(1, 1); }
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
namespace TLS {
|
|
|
|
class Server_Handshake_State;
|
|
|
|
/**
|
|
* TLS Server
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Server final : public Channel
|
|
{
|
|
public:
|
|
typedef std::function<std::string (std::vector<std::string>)> next_protocol_fn;
|
|
|
|
/**
|
|
* Server initialization
|
|
*
|
|
* @param callbacks contains a set of callback function references
|
|
* required by the TLS client.
|
|
*
|
|
* @param session_manager manages session state
|
|
*
|
|
* @param creds manages application/user credentials
|
|
*
|
|
* @param policy specifies other connection policy information
|
|
*
|
|
* @param rng a random number generator
|
|
*
|
|
* @param is_datagram set to true if this server should expect DTLS
|
|
* connections. Otherwise TLS connections are expected.
|
|
*
|
|
* @param reserved_io_buffer_size This many bytes of memory will
|
|
* be preallocated for the read and write buffers. Smaller
|
|
* values just mean reallocations and copies are more likely.
|
|
*/
|
|
Server(Callbacks& callbacks,
|
|
Session_Manager& session_manager,
|
|
Credentials_Manager& creds,
|
|
const Policy& policy,
|
|
RandomNumberGenerator& rng,
|
|
bool is_datagram = false,
|
|
size_t reserved_io_buffer_size = TLS::Server::IO_BUF_DEFAULT_SIZE
|
|
);
|
|
|
|
/**
|
|
* DEPRECATED. This constructor is only provided for backward
|
|
* compatibility and should not be used in new implementations.
|
|
* It will be removed in a future release.
|
|
*/
|
|
BOTAN_DEPRECATED("Use TLS::Server(TLS::Callbacks ...)")
|
|
Server(output_fn output,
|
|
data_cb data_cb,
|
|
alert_cb recv_alert_cb,
|
|
handshake_cb hs_cb,
|
|
Session_Manager& session_manager,
|
|
Credentials_Manager& creds,
|
|
const Policy& policy,
|
|
RandomNumberGenerator& rng,
|
|
next_protocol_fn next_proto = next_protocol_fn(),
|
|
bool is_datagram = false,
|
|
size_t reserved_io_buffer_size = TLS::Server::IO_BUF_DEFAULT_SIZE
|
|
);
|
|
|
|
/**
|
|
* DEPRECATED. This constructor is only provided for backward
|
|
* compatibility and should not be used in new implementations.
|
|
* It will be removed in a future release.
|
|
*/
|
|
BOTAN_DEPRECATED("Use TLS::Server(TLS::Callbacks ...)")
|
|
Server(output_fn output,
|
|
data_cb data_cb,
|
|
alert_cb recv_alert_cb,
|
|
handshake_cb hs_cb,
|
|
handshake_msg_cb hs_msg_cb,
|
|
Session_Manager& session_manager,
|
|
Credentials_Manager& creds,
|
|
const Policy& policy,
|
|
RandomNumberGenerator& rng,
|
|
next_protocol_fn next_proto = next_protocol_fn(),
|
|
bool is_datagram = false
|
|
);
|
|
|
|
/**
|
|
* Return the protocol notification set by the client (using the
|
|
* ALPN extension) for this connection, if any. This value is not
|
|
* tied to the session and a later renegotiation of the same
|
|
* session can choose a new protocol.
|
|
*/
|
|
std::string next_protocol() const { return m_next_protocol; }
|
|
|
|
/**
|
|
* Return the protocol notification set by the client (using the
|
|
* ALPN extension) for this connection, if any. This value is not
|
|
* tied to the session and a later renegotiation of the same
|
|
* session can choose a new protocol.
|
|
*/
|
|
std::string application_protocol() const override { return m_next_protocol; }
|
|
|
|
private:
|
|
std::vector<X509_Certificate>
|
|
get_peer_cert_chain(const Handshake_State& state) const override;
|
|
|
|
void initiate_handshake(Handshake_State& state,
|
|
bool force_full_renegotiation) override;
|
|
|
|
void process_handshake_msg(const Handshake_State* active_state,
|
|
Handshake_State& pending_state,
|
|
Handshake_Type type,
|
|
const std::vector<uint8_t>& contents,
|
|
bool epoch0_restart) override;
|
|
|
|
void process_client_hello_msg(const Handshake_State* active_state,
|
|
Server_Handshake_State& pending_state,
|
|
const std::vector<uint8_t>& contents,
|
|
bool epoch0_restart);
|
|
|
|
void process_certificate_msg(Server_Handshake_State& pending_state,
|
|
const std::vector<uint8_t>& contents);
|
|
|
|
void process_client_key_exchange_msg(Server_Handshake_State& pending_state,
|
|
const std::vector<uint8_t>& contents);
|
|
|
|
void process_change_cipher_spec_msg(Server_Handshake_State& pending_state);
|
|
|
|
void process_certificate_verify_msg(Server_Handshake_State& pending_state,
|
|
Handshake_Type type,
|
|
const std::vector<uint8_t>& contents);
|
|
|
|
void process_finished_msg(Server_Handshake_State& pending_state,
|
|
Handshake_Type type,
|
|
const std::vector<uint8_t>& contents);
|
|
|
|
void session_resume(Server_Handshake_State& pending_state,
|
|
bool have_session_ticket_key,
|
|
Session& session_info);
|
|
|
|
void session_create(Server_Handshake_State& pending_state,
|
|
bool have_session_ticket_key);
|
|
|
|
Handshake_State* new_handshake_state(Handshake_IO* io) override;
|
|
|
|
Credentials_Manager& m_creds;
|
|
std::string m_next_protocol;
|
|
|
|
// Set by deprecated constructor, Server calls both this fn and Callbacks version
|
|
next_protocol_fn m_choose_next_protocol;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
namespace TLS {
|
|
|
|
/**
|
|
* An implementation of Session_Manager that saves values in a SQL
|
|
* database file, with the session data encrypted using a passphrase.
|
|
*
|
|
* @warning For clients, the hostnames associated with the saved
|
|
* sessions are stored in the database in plaintext. This may be a
|
|
* serious privacy risk in some situations.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Session_Manager_SQL : public Session_Manager
|
|
{
|
|
public:
|
|
/**
|
|
* @param db A connection to the database to use
|
|
The table names botan_tls_sessions and
|
|
botan_tls_sessions_metadata will be used
|
|
* @param passphrase used to encrypt the session data
|
|
* @param rng a random number generator
|
|
* @param max_sessions a hint on the maximum number of sessions
|
|
* to keep in memory at any one time. (If zero, don't cap)
|
|
* @param session_lifetime sessions are expired after this many
|
|
* seconds have elapsed from initial handshake.
|
|
*/
|
|
Session_Manager_SQL(std::shared_ptr<SQL_Database> db,
|
|
const std::string& passphrase,
|
|
RandomNumberGenerator& rng,
|
|
size_t max_sessions = 1000,
|
|
std::chrono::seconds session_lifetime = std::chrono::seconds(7200));
|
|
|
|
Session_Manager_SQL(const Session_Manager_SQL&) = delete;
|
|
|
|
Session_Manager_SQL& operator=(const Session_Manager_SQL&) = delete;
|
|
|
|
bool load_from_session_id(const std::vector<uint8_t>& session_id,
|
|
Session& session) override;
|
|
|
|
bool load_from_server_info(const Server_Information& info,
|
|
Session& session) override;
|
|
|
|
void remove_entry(const std::vector<uint8_t>& session_id) override;
|
|
|
|
size_t remove_all() override;
|
|
|
|
void save(const Session& session_data) override;
|
|
|
|
std::chrono::seconds session_lifetime() const override
|
|
{ return m_session_lifetime; }
|
|
|
|
private:
|
|
void prune_session_cache();
|
|
|
|
std::shared_ptr<SQL_Database> m_db;
|
|
secure_vector<uint8_t> m_session_key;
|
|
RandomNumberGenerator& m_rng;
|
|
size_t m_max_sessions;
|
|
std::chrono::seconds m_session_lifetime;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
/**
|
|
* A split secret, using the format from draft-mcgrew-tss-03
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) RTSS_Share final
|
|
{
|
|
public:
|
|
/**
|
|
* @param M the number of shares needed to reconstruct
|
|
* @param N the number of shares generated
|
|
* @param secret the secret to split
|
|
* @param secret_len the length of the secret
|
|
* @param identifier the 16 byte share identifier
|
|
* @param rng the random number generator to use
|
|
*/
|
|
static std::vector<RTSS_Share>
|
|
split(uint8_t M, uint8_t N,
|
|
const uint8_t secret[], uint16_t secret_len,
|
|
const uint8_t identifier[16],
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* @param M the number of shares needed to reconstruct
|
|
* @param N the number of shares generated
|
|
* @param secret the secret to split
|
|
* @param secret_len the length of the secret
|
|
* @param identifier the share identifier
|
|
* @param hash_fn the hash function to use for a checksum ("None", "SHA-1", "SHA-256")
|
|
* @param rng the random number generator to use
|
|
*/
|
|
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);
|
|
|
|
/**
|
|
* @param shares the list of shares
|
|
*/
|
|
static secure_vector<uint8_t>
|
|
reconstruct(const std::vector<RTSS_Share>& shares);
|
|
|
|
RTSS_Share() = default;
|
|
|
|
/**
|
|
* @param hex_input the share encoded in hexadecimal
|
|
*/
|
|
explicit RTSS_Share(const std::string& hex_input);
|
|
|
|
/**
|
|
* @param data the shared data
|
|
* @param len the length of data
|
|
*/
|
|
RTSS_Share(const uint8_t data[], size_t len);
|
|
|
|
/**
|
|
* @return binary representation
|
|
*/
|
|
const secure_vector<uint8_t>& data() const { return m_contents; }
|
|
|
|
/**
|
|
* @return hex representation
|
|
*/
|
|
std::string to_string() const;
|
|
|
|
/**
|
|
* @return share identifier
|
|
*/
|
|
uint8_t share_id() const;
|
|
|
|
/**
|
|
* @return size of this share in bytes
|
|
*/
|
|
size_t size() const { return m_contents.size(); }
|
|
|
|
/**
|
|
* @return if this TSS share was initialized or not
|
|
*/
|
|
bool initialized() const { return (m_contents.size() > 0); }
|
|
private:
|
|
secure_vector<uint8_t> m_contents;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(twofish.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Twofish, an AES finalist
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Twofish final : public Block_Cipher_Fixed_Params<16, 16, 32, 8>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "Twofish"; }
|
|
BlockCipher* clone() const override { return new Twofish; }
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
static const uint32_t MDS0[256];
|
|
static const uint32_t MDS1[256];
|
|
static const uint32_t MDS2[256];
|
|
static const uint32_t MDS3[256];
|
|
static const uint8_t Q0[256];
|
|
static const uint8_t Q1[256];
|
|
static const uint8_t RS[32];
|
|
static const uint8_t EXP_TO_POLY[255];
|
|
static const uint8_t POLY_TO_EXP[255];
|
|
|
|
secure_vector<uint32_t> m_SB, m_RK;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(uuid.h)
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
|
|
class BOTAN_UNSTABLE_API UUID final
|
|
{
|
|
public:
|
|
/**
|
|
* Create an uninitialized UUID object
|
|
*/
|
|
UUID() : m_uuid() {}
|
|
|
|
/**
|
|
* Create a random UUID
|
|
*/
|
|
UUID(RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Load a UUID from a 16 byte vector
|
|
*/
|
|
UUID(const std::vector<uint8_t>& blob);
|
|
|
|
UUID& operator=(const UUID& other) = default;
|
|
UUID(const UUID& other) = default;
|
|
|
|
/**
|
|
* Decode a UUID string
|
|
*/
|
|
UUID(const std::string& uuid_str);
|
|
|
|
/**
|
|
* Convert the UUID to a string
|
|
*/
|
|
std::string to_string() const;
|
|
|
|
const std::vector<uint8_t>& binary_value() const { return m_uuid; }
|
|
|
|
bool operator==(const UUID& other) const
|
|
{
|
|
return m_uuid == other.m_uuid;
|
|
}
|
|
|
|
bool operator!=(const UUID& other) const { return !(*this == other); }
|
|
|
|
bool is_valid() const { return m_uuid.size() == 16; }
|
|
|
|
private:
|
|
std::vector<uint8_t> m_uuid;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/*
|
|
* Get information describing the version
|
|
*/
|
|
|
|
/**
|
|
* Get a human-readable string identifying the version of Botan.
|
|
* No particular format should be assumed.
|
|
* @return version string
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::string version_string();
|
|
|
|
/**
|
|
* Same as version_string() except returning a pointer to a statically
|
|
* allocated string.
|
|
* @return version string
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) const char* version_cstr();
|
|
|
|
/**
|
|
* Return a version string of the form "MAJOR.MINOR.PATCH" where
|
|
* each of the values is an integer.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,4) std::string short_version_string();
|
|
|
|
/**
|
|
* Same as version_short_string except returning a pointer to the string.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,4) const char* short_version_cstr();
|
|
|
|
/**
|
|
* Return the date this version of botan was released, in an integer of
|
|
* the form YYYYMMDD. For instance a version released on May 21, 2013
|
|
* would return the integer 20130521. If the currently running version
|
|
* is not an official release, this function will return 0 instead.
|
|
*
|
|
* @return release date, or zero if unreleased
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t version_datestamp();
|
|
|
|
/**
|
|
* Get the major version number.
|
|
* @return major version number
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t version_major();
|
|
|
|
/**
|
|
* Get the minor version number.
|
|
* @return minor version number
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t version_minor();
|
|
|
|
/**
|
|
* Get the patch number.
|
|
* @return patch number
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) uint32_t version_patch();
|
|
|
|
/**
|
|
* Usable for checking that the DLL version loaded at runtime exactly
|
|
* matches the compile-time version. Call using BOTAN_VERSION_* macro
|
|
* values. Returns the empty string if an exact match, otherwise an
|
|
* appropriate message. Added with 1.11.26.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::string
|
|
runtime_version_check(uint32_t major,
|
|
uint32_t minor,
|
|
uint32_t patch);
|
|
|
|
/*
|
|
* Macros for compile-time version checks
|
|
*/
|
|
#define BOTAN_VERSION_CODE_FOR(a,b,c) ((a << 16) | (b << 8) | (c))
|
|
|
|
/**
|
|
* Compare using BOTAN_VERSION_CODE_FOR, as in
|
|
* # if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,8,0)
|
|
* # error "Botan version too old"
|
|
* # endif
|
|
*/
|
|
#define BOTAN_VERSION_CODE BOTAN_VERSION_CODE_FOR(BOTAN_VERSION_MAJOR, \
|
|
BOTAN_VERSION_MINOR, \
|
|
BOTAN_VERSION_PATCH)
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(whrlpool.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Whirlpool
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Whirlpool final : public MDx_HashFunction
|
|
{
|
|
public:
|
|
std::string name() const override { return "Whirlpool"; }
|
|
size_t output_length() const override { return 64; }
|
|
HashFunction* clone() const override { return new Whirlpool; }
|
|
std::unique_ptr<HashFunction> copy_state() const override;
|
|
|
|
void clear() override;
|
|
|
|
Whirlpool() : MDx_HashFunction(64, true, true, 32), m_M(8), m_digest(8)
|
|
{ clear(); }
|
|
private:
|
|
void compress_n(const uint8_t[], size_t blocks) override;
|
|
void copy_out(uint8_t[]) override;
|
|
|
|
static const uint64_t C0[256];
|
|
static const uint64_t C1[256];
|
|
static const uint64_t C2[256];
|
|
static const uint64_t C3[256];
|
|
static const uint64_t C4[256];
|
|
static const uint64_t C5[256];
|
|
static const uint64_t C6[256];
|
|
static const uint64_t C7[256];
|
|
|
|
secure_vector<uint64_t> m_M, m_digest;
|
|
};
|
|
|
|
}
|
|
BOTAN_FUTURE_INTERNAL_HEADER(workfactor.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Estimate work factor for discrete logarithm
|
|
* @param prime_group_size size of the group in bits
|
|
* @return estimated security level for this group
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) size_t dl_work_factor(size_t prime_group_size);
|
|
|
|
/**
|
|
* Return the appropriate exponent size to use for a particular prime
|
|
* group. This is twice the size of the estimated cost of breaking the
|
|
* key using an index calculus attack; the assumption is that if an
|
|
* arbitrary discrete log on a group of size bits would take about 2^n
|
|
* effort, and thus using an exponent of size 2^(2*n) implies that all
|
|
* available attacks are about as easy (as e.g Pollard's kangaroo
|
|
* algorithm can compute the DL in sqrt(x) operations) while minimizing
|
|
* the exponent size for performance reasons.
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) size_t dl_exponent_size(size_t prime_group_size);
|
|
|
|
/**
|
|
* Estimate work factor for integer factorization
|
|
* @param n_bits size of modulus in bits
|
|
* @return estimated security level for this modulus
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) size_t if_work_factor(size_t n_bits);
|
|
|
|
/**
|
|
* Estimate work factor for EC discrete logarithm
|
|
* @param prime_group_size size of the group in bits
|
|
* @return estimated security level for this group
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) size_t ecp_work_factor(size_t prime_group_size);
|
|
|
|
}
|
|
|
|
#if defined(BOTAN_HAS_SYSTEM_RNG)
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
class BigInt;
|
|
class Private_Key;
|
|
class PKCS10_Request;
|
|
class PK_Signer;
|
|
|
|
/**
|
|
* This class represents X.509 Certificate Authorities (CAs).
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) X509_CA final
|
|
{
|
|
public:
|
|
/**
|
|
* Sign a PKCS#10 Request.
|
|
* @param req the request to sign
|
|
* @param rng the rng to use
|
|
* @param not_before the starting time for the certificate
|
|
* @param not_after the expiration time for the certificate
|
|
* @return resulting certificate
|
|
*/
|
|
X509_Certificate sign_request(const PKCS10_Request& req,
|
|
RandomNumberGenerator& rng,
|
|
const X509_Time& not_before,
|
|
const X509_Time& not_after) const;
|
|
|
|
/**
|
|
* Sign a PKCS#10 Request.
|
|
* @param req the request to sign
|
|
* @param rng the rng to use
|
|
* @param serial_number the serial number the cert will be assigned.
|
|
* @param not_before the starting time for the certificate
|
|
* @param not_after the expiration time for the certificate
|
|
* @return resulting certificate
|
|
*/
|
|
X509_Certificate sign_request(const PKCS10_Request& req,
|
|
RandomNumberGenerator& rng,
|
|
const BigInt& serial_number,
|
|
const X509_Time& not_before,
|
|
const X509_Time& not_after) const;
|
|
|
|
/**
|
|
* Get the certificate of this CA.
|
|
* @return CA certificate
|
|
*/
|
|
X509_Certificate ca_certificate() const;
|
|
|
|
/**
|
|
* Create a new and empty CRL for this CA.
|
|
* @param rng the random number generator to use
|
|
* @param issue_time the issue time (typically system_clock::now)
|
|
* @param next_update the time interval after issue_data within which
|
|
* a new CRL will be produced.
|
|
* @return new CRL
|
|
*/
|
|
X509_CRL new_crl(RandomNumberGenerator& rng,
|
|
std::chrono::system_clock::time_point issue_time,
|
|
std::chrono::seconds next_update) const;
|
|
|
|
/**
|
|
* Create a new CRL by with additional entries.
|
|
* @param last_crl the last CRL of this CA to add the new entries to
|
|
* @param new_entries contains the new CRL entries to be added to the CRL
|
|
* @param rng the random number generator to use
|
|
* @param issue_time the issue time (typically system_clock::now)
|
|
* @param next_update the time interval after issue_data within which
|
|
* a new CRL will be produced.
|
|
*/
|
|
X509_CRL update_crl(const X509_CRL& last_crl,
|
|
const std::vector<CRL_Entry>& new_entries,
|
|
RandomNumberGenerator& rng,
|
|
std::chrono::system_clock::time_point issue_time,
|
|
std::chrono::seconds next_update) const;
|
|
|
|
/**
|
|
* Create a new and empty CRL for this CA.
|
|
* @param rng the random number generator to use
|
|
* @param next_update the time to set in next update in seconds
|
|
* as the offset from the current time
|
|
* @return new CRL
|
|
*/
|
|
X509_CRL new_crl(RandomNumberGenerator& rng,
|
|
uint32_t next_update = 604800) const;
|
|
|
|
/**
|
|
* Create a new CRL by with additional entries.
|
|
* @param last_crl the last CRL of this CA to add the new entries to
|
|
* @param new_entries contains the new CRL entries to be added to the CRL
|
|
* @param rng the random number generator to use
|
|
* @param next_update the time to set in next update in seconds
|
|
* as the offset from the current time
|
|
*/
|
|
X509_CRL update_crl(const X509_CRL& last_crl,
|
|
const std::vector<CRL_Entry>& new_entries,
|
|
RandomNumberGenerator& rng,
|
|
uint32_t next_update = 604800) const;
|
|
|
|
/**
|
|
* Interface for creating new certificates
|
|
* @param signer a signing object
|
|
* @param rng a random number generator
|
|
* @param sig_algo the signature algorithm identifier
|
|
* @param pub_key the serialized public key
|
|
* @param not_before the start time of the certificate
|
|
* @param not_after the end time of the certificate
|
|
* @param issuer_dn the DN of the issuer
|
|
* @param subject_dn the DN of the subject
|
|
* @param extensions an optional list of certificate extensions
|
|
* @returns newly minted certificate
|
|
*/
|
|
static X509_Certificate make_cert(PK_Signer* signer,
|
|
RandomNumberGenerator& rng,
|
|
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);
|
|
|
|
/**
|
|
* Interface for creating new certificates
|
|
* @param signer a signing object
|
|
* @param rng a random number generator
|
|
* @param serial_number the serial number the cert will be assigned
|
|
* @param sig_algo the signature algorithm identifier
|
|
* @param pub_key the serialized public key
|
|
* @param not_before the start time of the certificate
|
|
* @param not_after the end time of the certificate
|
|
* @param issuer_dn the DN of the issuer
|
|
* @param subject_dn the DN of the subject
|
|
* @param extensions an optional list of certificate extensions
|
|
* @returns newly minted certificate
|
|
*/
|
|
static X509_Certificate 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);
|
|
|
|
/**
|
|
* Create a new CA object.
|
|
* @param ca_certificate the certificate of the CA
|
|
* @param key the private key of the CA
|
|
* @param hash_fn name of a hash function to use for signing
|
|
* @param rng the random generator to use
|
|
*/
|
|
X509_CA(const X509_Certificate& ca_certificate,
|
|
const Private_Key& key,
|
|
const std::string& hash_fn,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Create a new CA object.
|
|
* @param ca_certificate the certificate of the CA
|
|
* @param key the private key of the CA
|
|
* @param opts additional options, e.g. padding, as key value pairs
|
|
* @param hash_fn name of a hash function to use for signing
|
|
* @param rng the random generator to use
|
|
*/
|
|
X509_CA(const X509_Certificate& ca_certificate,
|
|
const Private_Key& key,
|
|
const std::map<std::string,std::string>& opts,
|
|
const std::string& hash_fn,
|
|
RandomNumberGenerator& rng);
|
|
|
|
#if defined(BOTAN_HAS_SYSTEM_RNG)
|
|
BOTAN_DEPRECATED("Use version taking RNG object")
|
|
X509_CA(const X509_Certificate& ca_certificate,
|
|
const Private_Key& key,
|
|
const std::string& hash_fn) :
|
|
X509_CA(ca_certificate, key, hash_fn, system_rng())
|
|
{}
|
|
#endif
|
|
|
|
X509_CA(const X509_CA&) = delete;
|
|
X509_CA& operator=(const X509_CA&) = delete;
|
|
|
|
X509_CA(X509_CA&&) = default;
|
|
X509_CA& operator=(X509_CA&&) = default;
|
|
|
|
~X509_CA();
|
|
|
|
private:
|
|
X509_CRL make_crl(const std::vector<CRL_Entry>& entries,
|
|
uint32_t crl_number,
|
|
RandomNumberGenerator& rng,
|
|
std::chrono::system_clock::time_point issue_time,
|
|
std::chrono::seconds next_update) const;
|
|
|
|
AlgorithmIdentifier m_ca_sig_algo;
|
|
X509_Certificate m_ca_cert;
|
|
std::string m_hash_fn;
|
|
std::unique_ptr<PK_Signer> m_signer;
|
|
};
|
|
|
|
/**
|
|
* Choose the default signature format for a certain public key signature
|
|
* scheme.
|
|
* @param key will be the key to choose a padding scheme for
|
|
* @param rng the random generator to use
|
|
* @param hash_fn is the desired hash function
|
|
* @param alg_id will be set to the chosen scheme
|
|
* @return A PK_Signer object for generating signatures
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) PK_Signer* choose_sig_format(const Private_Key& key,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& hash_fn,
|
|
AlgorithmIdentifier& alg_id);
|
|
|
|
/**
|
|
* @verbatim
|
|
* Choose the default signature format for a certain public key signature
|
|
* scheme.
|
|
*
|
|
* The only option recognized by opts at this moment is "padding"
|
|
* Find an entry from src/build-data/oids.txt under [signature] of the form
|
|
* <sig_algo>/<padding>[(<hash_algo>)] and add {"padding",<padding>}
|
|
* to opts.
|
|
* @endverbatim
|
|
*
|
|
* @param key will be the key to choose a padding scheme for
|
|
* @param opts contains additional options for building the certificate
|
|
* @param rng the random generator to use
|
|
* @param hash_fn is the desired hash function
|
|
* @param alg_id will be set to the chosen scheme
|
|
* @return A PK_Signer object for generating signatures
|
|
*/
|
|
PK_Signer* choose_sig_format(const Private_Key& key,
|
|
const std::map<std::string,std::string>& opts,
|
|
RandomNumberGenerator& rng,
|
|
const std::string& hash_fn,
|
|
AlgorithmIdentifier& alg_id);
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class Data_Store;
|
|
class X509_Certificate;
|
|
|
|
namespace Cert_Extension {
|
|
|
|
static const size_t NO_CERT_PATH_LIMIT = 0xFFFFFFF0;
|
|
|
|
/**
|
|
* Basic Constraints Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Basic_Constraints final : public Certificate_Extension
|
|
{
|
|
public:
|
|
Basic_Constraints* copy() const override
|
|
{ return new Basic_Constraints(m_is_ca, m_path_limit); }
|
|
|
|
Basic_Constraints(bool ca = false, size_t limit = 0) :
|
|
m_is_ca(ca), m_path_limit(limit) {}
|
|
|
|
bool get_is_ca() const { return m_is_ca; }
|
|
size_t get_path_limit() const;
|
|
|
|
static OID static_oid() { return OID("2.5.29.19"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
private:
|
|
std::string oid_name() const override
|
|
{ return "X509v3.BasicConstraints"; }
|
|
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
bool m_is_ca;
|
|
size_t m_path_limit;
|
|
};
|
|
|
|
/**
|
|
* Key Usage Constraints Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Key_Usage final : public Certificate_Extension
|
|
{
|
|
public:
|
|
Key_Usage* copy() const override { return new Key_Usage(m_constraints); }
|
|
|
|
explicit Key_Usage(Key_Constraints c = NO_CONSTRAINTS) : m_constraints(c) {}
|
|
|
|
Key_Constraints get_constraints() const { return m_constraints; }
|
|
|
|
static OID static_oid() { return OID("2.5.29.15"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
private:
|
|
std::string oid_name() const override { return "X509v3.KeyUsage"; }
|
|
|
|
bool should_encode() const override
|
|
{ return (m_constraints != NO_CONSTRAINTS); }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
Key_Constraints m_constraints;
|
|
};
|
|
|
|
/**
|
|
* Subject Key Identifier Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Subject_Key_ID final : public Certificate_Extension
|
|
{
|
|
public:
|
|
Subject_Key_ID() = default;
|
|
|
|
explicit Subject_Key_ID(const std::vector<uint8_t>& k) : m_key_id(k) {}
|
|
|
|
Subject_Key_ID(const std::vector<uint8_t>& public_key,
|
|
const std::string& hash_fn);
|
|
|
|
Subject_Key_ID* copy() const override
|
|
{ return new Subject_Key_ID(m_key_id); }
|
|
|
|
const std::vector<uint8_t>& get_key_id() const { return m_key_id; }
|
|
|
|
static OID static_oid() { return OID("2.5.29.14"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
private:
|
|
|
|
std::string oid_name() const override
|
|
{ return "X509v3.SubjectKeyIdentifier"; }
|
|
|
|
bool should_encode() const override { return (m_key_id.size() > 0); }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
std::vector<uint8_t> m_key_id;
|
|
};
|
|
|
|
/**
|
|
* Authority Key Identifier Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Authority_Key_ID final : public Certificate_Extension
|
|
{
|
|
public:
|
|
Authority_Key_ID* copy() const override
|
|
{ return new Authority_Key_ID(m_key_id); }
|
|
|
|
Authority_Key_ID() = default;
|
|
explicit Authority_Key_ID(const std::vector<uint8_t>& k) : m_key_id(k) {}
|
|
|
|
const std::vector<uint8_t>& get_key_id() const { return m_key_id; }
|
|
|
|
static OID static_oid() { return OID("2.5.29.35"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
private:
|
|
std::string oid_name() const override
|
|
{ return "X509v3.AuthorityKeyIdentifier"; }
|
|
|
|
bool should_encode() const override { return (m_key_id.size() > 0); }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
std::vector<uint8_t> m_key_id;
|
|
};
|
|
|
|
/**
|
|
* Subject Alternative Name Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,4) Subject_Alternative_Name final : public Certificate_Extension
|
|
{
|
|
public:
|
|
const AlternativeName& get_alt_name() const { return m_alt_name; }
|
|
|
|
static OID static_oid() { return OID("2.5.29.17"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
Subject_Alternative_Name* copy() const override
|
|
{ return new Subject_Alternative_Name(get_alt_name()); }
|
|
|
|
explicit Subject_Alternative_Name(const AlternativeName& name = AlternativeName()) :
|
|
m_alt_name(name) {}
|
|
|
|
private:
|
|
std::string oid_name() const override { return "X509v3.SubjectAlternativeName"; }
|
|
|
|
bool should_encode() const override { return m_alt_name.has_items(); }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
AlternativeName m_alt_name;
|
|
};
|
|
|
|
/**
|
|
* Issuer Alternative Name Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Issuer_Alternative_Name final : public Certificate_Extension
|
|
{
|
|
public:
|
|
const AlternativeName& get_alt_name() const { return m_alt_name; }
|
|
|
|
static OID static_oid() { return OID("2.5.29.18"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
Issuer_Alternative_Name* copy() const override
|
|
{ return new Issuer_Alternative_Name(get_alt_name()); }
|
|
|
|
explicit Issuer_Alternative_Name(const AlternativeName& name = AlternativeName()) :
|
|
m_alt_name(name) {}
|
|
|
|
private:
|
|
std::string oid_name() const override { return "X509v3.IssuerAlternativeName"; }
|
|
|
|
bool should_encode() const override { return m_alt_name.has_items(); }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
AlternativeName m_alt_name;
|
|
};
|
|
|
|
/**
|
|
* Extended Key Usage Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Extended_Key_Usage final : public Certificate_Extension
|
|
{
|
|
public:
|
|
Extended_Key_Usage* copy() const override
|
|
{ return new Extended_Key_Usage(m_oids); }
|
|
|
|
Extended_Key_Usage() = default;
|
|
explicit Extended_Key_Usage(const std::vector<OID>& o) : m_oids(o) {}
|
|
|
|
const std::vector<OID>& get_oids() const { return m_oids; }
|
|
|
|
static OID static_oid() { return OID("2.5.29.37"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
private:
|
|
std::string oid_name() const override { return "X509v3.ExtendedKeyUsage"; }
|
|
|
|
bool should_encode() const override { return (m_oids.size() > 0); }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
std::vector<OID> m_oids;
|
|
};
|
|
|
|
/**
|
|
* Name Constraints
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Name_Constraints final : public Certificate_Extension
|
|
{
|
|
public:
|
|
Name_Constraints* copy() const override
|
|
{ return new Name_Constraints(m_name_constraints); }
|
|
|
|
Name_Constraints() = default;
|
|
Name_Constraints(const NameConstraints &nc) : m_name_constraints(nc) {}
|
|
|
|
void validate(const X509_Certificate& subject, const X509_Certificate& issuer,
|
|
const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
|
|
std::vector<std::set<Certificate_Status_Code>>& cert_status,
|
|
size_t pos) override;
|
|
|
|
const NameConstraints& get_name_constraints() const { return m_name_constraints; }
|
|
|
|
static OID static_oid() { return OID("2.5.29.30"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
private:
|
|
std::string oid_name() const override
|
|
{ return "X509v3.NameConstraints"; }
|
|
|
|
bool should_encode() const override { return true; }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
NameConstraints m_name_constraints;
|
|
};
|
|
|
|
/**
|
|
* Certificate Policies Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Certificate_Policies final : public Certificate_Extension
|
|
{
|
|
public:
|
|
Certificate_Policies* copy() const override
|
|
{ return new Certificate_Policies(m_oids); }
|
|
|
|
Certificate_Policies() = default;
|
|
explicit Certificate_Policies(const std::vector<OID>& o) : m_oids(o) {}
|
|
|
|
BOTAN_DEPRECATED("Use get_policy_oids")
|
|
std::vector<OID> get_oids() const { return m_oids; }
|
|
|
|
const std::vector<OID>& get_policy_oids() const { return m_oids; }
|
|
|
|
static OID static_oid() { return OID("2.5.29.32"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
void validate(const X509_Certificate& subject, const X509_Certificate& issuer,
|
|
const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
|
|
std::vector<std::set<Certificate_Status_Code>>& cert_status,
|
|
size_t pos) override;
|
|
private:
|
|
std::string oid_name() const override
|
|
{ return "X509v3.CertificatePolicies"; }
|
|
|
|
bool should_encode() const override { return (m_oids.size() > 0); }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
std::vector<OID> m_oids;
|
|
};
|
|
|
|
/**
|
|
* Authority Information Access Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Authority_Information_Access final : public Certificate_Extension
|
|
{
|
|
public:
|
|
Authority_Information_Access* copy() const override
|
|
{ return new Authority_Information_Access(m_ocsp_responder, m_ca_issuers); }
|
|
|
|
Authority_Information_Access() = default;
|
|
|
|
explicit Authority_Information_Access(const std::string& ocsp, const std::vector<std::string>& ca_issuers = std::vector<std::string>()) :
|
|
m_ocsp_responder(ocsp), m_ca_issuers(ca_issuers) {}
|
|
|
|
std::string ocsp_responder() const { return m_ocsp_responder; }
|
|
|
|
static OID static_oid() { return OID("1.3.6.1.5.5.7.1.1"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
const std::vector<std::string> ca_issuers() const { return m_ca_issuers; }
|
|
|
|
private:
|
|
std::string oid_name() const override
|
|
{ return "PKIX.AuthorityInformationAccess"; }
|
|
|
|
bool should_encode() const override { return (!m_ocsp_responder.empty()); }
|
|
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
std::string m_ocsp_responder;
|
|
std::vector<std::string> m_ca_issuers;
|
|
};
|
|
|
|
/**
|
|
* CRL Number Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CRL_Number final : public Certificate_Extension
|
|
{
|
|
public:
|
|
CRL_Number* copy() const override;
|
|
|
|
CRL_Number() : m_has_value(false), m_crl_number(0) {}
|
|
CRL_Number(size_t n) : m_has_value(true), m_crl_number(n) {}
|
|
|
|
size_t get_crl_number() const;
|
|
|
|
static OID static_oid() { return OID("2.5.29.20"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
private:
|
|
std::string oid_name() const override { return "X509v3.CRLNumber"; }
|
|
|
|
bool should_encode() const override { return m_has_value; }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
bool m_has_value;
|
|
size_t m_crl_number;
|
|
};
|
|
|
|
/**
|
|
* CRL Entry Reason Code Extension
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CRL_ReasonCode final : public Certificate_Extension
|
|
{
|
|
public:
|
|
CRL_ReasonCode* copy() const override
|
|
{ return new CRL_ReasonCode(m_reason); }
|
|
|
|
explicit CRL_ReasonCode(CRL_Code r = UNSPECIFIED) : m_reason(r) {}
|
|
|
|
CRL_Code get_reason() const { return m_reason; }
|
|
|
|
static OID static_oid() { return OID("2.5.29.21"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
private:
|
|
std::string oid_name() const override { return "X509v3.ReasonCode"; }
|
|
|
|
bool should_encode() const override { return (m_reason != UNSPECIFIED); }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
CRL_Code m_reason;
|
|
};
|
|
|
|
/**
|
|
* CRL Distribution Points Extension
|
|
* todo enforce restrictions from RFC 5280 4.2.1.13
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) CRL_Distribution_Points final : public Certificate_Extension
|
|
{
|
|
public:
|
|
class BOTAN_PUBLIC_API(2,0) Distribution_Point final : public ASN1_Object
|
|
{
|
|
public:
|
|
void encode_into(class DER_Encoder&) const override;
|
|
void decode_from(class BER_Decoder&) override;
|
|
|
|
const AlternativeName& point() const { return m_point; }
|
|
private:
|
|
AlternativeName m_point;
|
|
};
|
|
|
|
CRL_Distribution_Points* copy() const override
|
|
{ return new CRL_Distribution_Points(m_distribution_points); }
|
|
|
|
CRL_Distribution_Points() = default;
|
|
|
|
explicit CRL_Distribution_Points(const std::vector<Distribution_Point>& points) :
|
|
m_distribution_points(points) {}
|
|
|
|
const std::vector<Distribution_Point>& distribution_points() const
|
|
{ return m_distribution_points; }
|
|
|
|
const std::vector<std::string>& crl_distribution_urls() const
|
|
{ return m_crl_distribution_urls; }
|
|
|
|
static OID static_oid() { return OID("2.5.29.31"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
private:
|
|
std::string oid_name() const override
|
|
{ return "X509v3.CRLDistributionPoints"; }
|
|
|
|
bool should_encode() const override
|
|
{ return !m_distribution_points.empty(); }
|
|
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
std::vector<Distribution_Point> m_distribution_points;
|
|
std::vector<std::string> m_crl_distribution_urls;
|
|
};
|
|
|
|
/**
|
|
* CRL Issuing Distribution Point Extension
|
|
* todo enforce restrictions from RFC 5280 5.2.5
|
|
*/
|
|
class CRL_Issuing_Distribution_Point final : public Certificate_Extension
|
|
{
|
|
public:
|
|
CRL_Issuing_Distribution_Point() = default;
|
|
|
|
explicit CRL_Issuing_Distribution_Point(const CRL_Distribution_Points::Distribution_Point& distribution_point) :
|
|
m_distribution_point(distribution_point) {}
|
|
|
|
CRL_Issuing_Distribution_Point* copy() const override
|
|
{ return new CRL_Issuing_Distribution_Point(m_distribution_point); }
|
|
|
|
const AlternativeName& get_point() const
|
|
{ return m_distribution_point.point(); }
|
|
|
|
static OID static_oid() { return OID("2.5.29.28"); }
|
|
OID oid_of() const override { return static_oid(); }
|
|
|
|
private:
|
|
std::string oid_name() const override
|
|
{ return "X509v3.CRLIssuingDistributionPoint"; }
|
|
|
|
bool should_encode() const override { return true; }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
CRL_Distribution_Points::Distribution_Point m_distribution_point;
|
|
};
|
|
|
|
/**
|
|
* An unknown X.509 extension
|
|
* Will add a failure to the path validation result, if critical
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,4) Unknown_Extension final : public Certificate_Extension
|
|
{
|
|
public:
|
|
Unknown_Extension(const OID& oid, bool critical) :
|
|
m_oid(oid), m_critical(critical) {}
|
|
|
|
Unknown_Extension* copy() const override
|
|
{ return new Unknown_Extension(m_oid, m_critical); }
|
|
|
|
/**
|
|
* Return the OID of this unknown extension
|
|
*/
|
|
OID oid_of() const override
|
|
{ return m_oid; }
|
|
|
|
//static_oid not defined for Unknown_Extension
|
|
|
|
/**
|
|
* Return the extension contents
|
|
*/
|
|
const std::vector<uint8_t>& extension_contents() const { return m_bytes; }
|
|
|
|
/**
|
|
* Return if this extension was marked critical
|
|
*/
|
|
bool is_critical_extension() const { return m_critical; }
|
|
|
|
void validate(const X509_Certificate&, const X509_Certificate&,
|
|
const std::vector<std::shared_ptr<const X509_Certificate>>&,
|
|
std::vector<std::set<Certificate_Status_Code>>& cert_status,
|
|
size_t pos) override
|
|
{
|
|
if(m_critical)
|
|
{
|
|
cert_status.at(pos).insert(Certificate_Status_Code::UNKNOWN_CRITICAL_EXTENSION);
|
|
}
|
|
}
|
|
|
|
private:
|
|
std::string oid_name() const override { return ""; }
|
|
|
|
bool should_encode() const override { return true; }
|
|
std::vector<uint8_t> encode_inner() const override;
|
|
void decode_inner(const std::vector<uint8_t>&) override;
|
|
void contents_to(Data_Store&, Data_Store&) const override;
|
|
|
|
OID m_oid;
|
|
bool m_critical;
|
|
std::vector<uint8_t> m_bytes;
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
class DataSource;
|
|
|
|
/**
|
|
* The two types of X509 encoding supported by Botan.
|
|
* This enum is not used anymore, and will be removed in a future major release.
|
|
*/
|
|
enum X509_Encoding { RAW_BER, PEM };
|
|
|
|
/**
|
|
* This namespace contains functions for handling X.509 public keys
|
|
*/
|
|
namespace X509 {
|
|
|
|
/**
|
|
* BER encode a key
|
|
* @param key the public key to encode
|
|
* @return BER encoding of this key
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::vector<uint8_t> BER_encode(const Public_Key& key);
|
|
|
|
/**
|
|
* PEM encode a public key into a string.
|
|
* @param key the key to encode
|
|
* @return PEM encoded key
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) std::string PEM_encode(const Public_Key& key);
|
|
|
|
/**
|
|
* Create a public key from a data source.
|
|
* @param source the source providing the DER or PEM encoded key
|
|
* @return new public key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) Public_Key* load_key(DataSource& source);
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
|
|
/**
|
|
* Create a public key from a file
|
|
* @param filename pathname to the file to load
|
|
* @return new public key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) Public_Key* load_key(const std::string& filename);
|
|
#endif
|
|
|
|
/**
|
|
* Create a public key from a memory region.
|
|
* @param enc the memory region containing the DER or PEM encoded key
|
|
* @return new public key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) Public_Key* load_key(const std::vector<uint8_t>& enc);
|
|
|
|
/**
|
|
* Copy a key.
|
|
* @param key the public key to copy
|
|
* @return new public key object
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) Public_Key* copy_key(const Public_Key& key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if defined(BOTAN_TARGET_OS_HAS_THREADS) && defined(BOTAN_HAS_HTTP_UTIL)
|
|
#define BOTAN_HAS_ONLINE_REVOCATION_CHECKS
|
|
#endif
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* This type represents the validation status of an entire certificate path.
|
|
* There is one set of status codes for each certificate in the path.
|
|
*/
|
|
typedef std::vector<std::set<Certificate_Status_Code>> CertificatePathStatusCodes;
|
|
|
|
/**
|
|
* Specifies restrictions on the PKIX path validation
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Path_Validation_Restrictions final
|
|
{
|
|
public:
|
|
/**
|
|
* @param require_rev if true, revocation information is required
|
|
|
|
* @param minimum_key_strength is the minimum strength (in terms of
|
|
* operations, eg 80 means 2^80) of a signature. Signatures weaker than
|
|
* this are rejected. If more than 80, SHA-1 signatures are also
|
|
* rejected. If possible use at least setting 110.
|
|
*
|
|
* 80 bit strength requires 1024 bit RSA
|
|
* 110 bit strength requires 2k bit RSA
|
|
* 128 bit strength requires ~3k bit RSA or P-256
|
|
* @param ocsp_all_intermediates Make OCSP requests for all CAs as
|
|
* well as end entity (if OCSP enabled in path validation request)
|
|
* @param max_ocsp_age maximum age of OCSP responses w/o next_update.
|
|
* If zero, there is no maximum age
|
|
*/
|
|
Path_Validation_Restrictions(bool require_rev = false,
|
|
size_t minimum_key_strength = 110,
|
|
bool ocsp_all_intermediates = false,
|
|
std::chrono::seconds max_ocsp_age = std::chrono::seconds::zero());
|
|
|
|
/**
|
|
* @param require_rev if true, revocation information is required
|
|
* @param minimum_key_strength is the minimum strength (in terms of
|
|
* operations, eg 80 means 2^80) of a signature. Signatures
|
|
* weaker than this are rejected.
|
|
* @param ocsp_all_intermediates Make OCSP requests for all CAs as
|
|
* well as end entity (if OCSP enabled in path validation request)
|
|
* @param trusted_hashes a set of trusted hashes. Any signatures
|
|
* created using a hash other than one of these will be
|
|
* rejected.
|
|
* @param max_ocsp_age maximum age of OCSP responses w/o next_update.
|
|
* If zero, there is no maximum age
|
|
*/
|
|
Path_Validation_Restrictions(bool require_rev,
|
|
size_t minimum_key_strength,
|
|
bool ocsp_all_intermediates,
|
|
const std::set<std::string>& trusted_hashes,
|
|
std::chrono::seconds max_ocsp_age = std::chrono::seconds::zero()) :
|
|
m_require_revocation_information(require_rev),
|
|
m_ocsp_all_intermediates(ocsp_all_intermediates),
|
|
m_trusted_hashes(trusted_hashes),
|
|
m_minimum_key_strength(minimum_key_strength),
|
|
m_max_ocsp_age(max_ocsp_age) {}
|
|
|
|
/**
|
|
* @return whether revocation information is required
|
|
*/
|
|
bool require_revocation_information() const
|
|
{ return m_require_revocation_information; }
|
|
|
|
/**
|
|
* @return whether all intermediate CAs should also be OCSPed. If false
|
|
* then only end entity OCSP is required/requested.
|
|
*/
|
|
bool ocsp_all_intermediates() const
|
|
{ return m_ocsp_all_intermediates; }
|
|
|
|
/**
|
|
* @return trusted signature hash functions
|
|
*/
|
|
const std::set<std::string>& trusted_hashes() const
|
|
{ return m_trusted_hashes; }
|
|
|
|
/**
|
|
* @return minimum required key strength
|
|
*/
|
|
size_t minimum_key_strength() const
|
|
{ return m_minimum_key_strength; }
|
|
|
|
/**
|
|
* @return maximum age of OCSP responses w/o next_update.
|
|
* If zero, there is no maximum age
|
|
*/
|
|
std::chrono::seconds max_ocsp_age() const
|
|
{ return m_max_ocsp_age; }
|
|
|
|
private:
|
|
bool m_require_revocation_information;
|
|
bool m_ocsp_all_intermediates;
|
|
std::set<std::string> m_trusted_hashes;
|
|
size_t m_minimum_key_strength;
|
|
std::chrono::seconds m_max_ocsp_age;
|
|
};
|
|
|
|
/**
|
|
* Represents the result of a PKIX path validation
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) Path_Validation_Result final
|
|
{
|
|
public:
|
|
typedef Certificate_Status_Code Code;
|
|
|
|
/**
|
|
* @return the set of hash functions you are implicitly
|
|
* trusting by trusting this result.
|
|
*/
|
|
std::set<std::string> trusted_hashes() const;
|
|
|
|
/**
|
|
* @return the trust root of the validation if successful
|
|
* throws an exception if the validation failed
|
|
*/
|
|
const X509_Certificate& trust_root() const;
|
|
|
|
/**
|
|
* @return the full path from subject to trust root
|
|
* This path may be empty
|
|
*/
|
|
const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path() const { return m_cert_path; }
|
|
|
|
/**
|
|
* @return true iff the validation was successful
|
|
*/
|
|
bool successful_validation() const;
|
|
|
|
/**
|
|
* @return true iff no warnings occured during validation
|
|
*/
|
|
bool no_warnings() const;
|
|
|
|
/**
|
|
* @return overall validation result code
|
|
*/
|
|
Certificate_Status_Code result() const { return m_overall; }
|
|
|
|
/**
|
|
* @return a set of status codes for each certificate in the chain
|
|
*/
|
|
const CertificatePathStatusCodes& all_statuses() const
|
|
{ return m_all_status; }
|
|
|
|
/**
|
|
* @return the subset of status codes that are warnings
|
|
*/
|
|
CertificatePathStatusCodes warnings() const;
|
|
|
|
/**
|
|
* @return string representation of the validation result
|
|
*/
|
|
std::string result_string() const;
|
|
|
|
/**
|
|
* @return string representation of the warnings
|
|
*/
|
|
std::string warnings_string() const;
|
|
|
|
/**
|
|
* @param code validation status code
|
|
* @return corresponding validation status message
|
|
*/
|
|
static const char* status_string(Certificate_Status_Code code);
|
|
|
|
/**
|
|
* Create a Path_Validation_Result
|
|
* @param status list of validation status codes
|
|
* @param cert_chain the certificate chain that was validated
|
|
*/
|
|
Path_Validation_Result(CertificatePathStatusCodes status,
|
|
std::vector<std::shared_ptr<const X509_Certificate>>&& cert_chain);
|
|
|
|
/**
|
|
* Create a Path_Validation_Result
|
|
* @param status validation status code
|
|
*/
|
|
explicit Path_Validation_Result(Certificate_Status_Code status) : m_overall(status) {}
|
|
|
|
private:
|
|
CertificatePathStatusCodes m_all_status;
|
|
CertificatePathStatusCodes m_warnings;
|
|
std::vector<std::shared_ptr<const X509_Certificate>> m_cert_path;
|
|
Certificate_Status_Code m_overall;
|
|
};
|
|
|
|
/**
|
|
* PKIX Path Validation
|
|
* @param end_certs certificate chain to validate (with end entity certificate in end_certs[0])
|
|
* @param restrictions path validation restrictions
|
|
* @param trusted_roots list of certificate stores that contain trusted certificates
|
|
* @param hostname if not empty, compared against the DNS name in end_certs[0]
|
|
* @param usage if not set to UNSPECIFIED, compared against the key usage in end_certs[0]
|
|
* @param validation_time what reference time to use for validation
|
|
* @param ocsp_timeout timeout for OCSP operations, 0 disables OCSP check
|
|
* @param ocsp_resp additional OCSP responses to consider (eg from peer)
|
|
* @return result of the path validation
|
|
* note: when enabled, OCSP check is softfail by default: if the OCSP server is not
|
|
* reachable, Path_Validation_Result::successful_validation() will return true.
|
|
* Hardfail OCSP check can be achieve by also calling Path_Validation_Result::no_warnings().
|
|
*/
|
|
Path_Validation_Result BOTAN_PUBLIC_API(2,0) x509_path_validate(
|
|
const std::vector<X509_Certificate>& end_certs,
|
|
const Path_Validation_Restrictions& restrictions,
|
|
const std::vector<Certificate_Store*>& trusted_roots,
|
|
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::shared_ptr<const OCSP::Response>>& ocsp_resp = {});
|
|
|
|
/**
|
|
* PKIX Path Validation
|
|
* @param end_cert certificate to validate
|
|
* @param restrictions path validation restrictions
|
|
* @param trusted_roots list of stores that contain trusted certificates
|
|
* @param hostname if not empty, compared against the DNS name in end_cert
|
|
* @param usage if not set to UNSPECIFIED, compared against the key usage in end_cert
|
|
* @param validation_time what reference time to use for validation
|
|
* @param ocsp_timeout timeout for OCSP operations, 0 disables OCSP check
|
|
* @param ocsp_resp additional OCSP responses to consider (eg from peer)
|
|
* @return result of the path validation
|
|
*/
|
|
Path_Validation_Result BOTAN_PUBLIC_API(2,0) x509_path_validate(
|
|
const X509_Certificate& end_cert,
|
|
const Path_Validation_Restrictions& restrictions,
|
|
const std::vector<Certificate_Store*>& trusted_roots,
|
|
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::shared_ptr<const OCSP::Response>>& ocsp_resp = {});
|
|
|
|
/**
|
|
* PKIX Path Validation
|
|
* @param end_cert certificate to validate
|
|
* @param restrictions path validation restrictions
|
|
* @param store store that contains trusted certificates
|
|
* @param hostname if not empty, compared against the DNS name in end_cert
|
|
* @param usage if not set to UNSPECIFIED, compared against the key usage in end_cert
|
|
* @param validation_time what reference time to use for validation
|
|
* @param ocsp_timeout timeout for OCSP operations, 0 disables OCSP check
|
|
* @param ocsp_resp additional OCSP responses to consider (eg from peer)
|
|
* @return result of the path validation
|
|
*/
|
|
Path_Validation_Result BOTAN_PUBLIC_API(2,0) 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::shared_ptr<const OCSP::Response>>& ocsp_resp = {});
|
|
|
|
/**
|
|
* PKIX Path Validation
|
|
* @param end_certs certificate chain to validate
|
|
* @param restrictions path validation restrictions
|
|
* @param store store that contains trusted certificates
|
|
* @param hostname if not empty, compared against the DNS name in end_certs[0]
|
|
* @param usage if not set to UNSPECIFIED, compared against the key usage in end_certs[0]
|
|
* @param validation_time what reference time to use for validation
|
|
* @param ocsp_timeout timeout for OCSP operations, 0 disables OCSP check
|
|
* @param ocsp_resp additional OCSP responses to consider (eg from peer)
|
|
* @return result of the path validation
|
|
*/
|
|
Path_Validation_Result BOTAN_PUBLIC_API(2,0) x509_path_validate(
|
|
const std::vector<X509_Certificate>& end_certs,
|
|
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::shared_ptr<const OCSP::Response>>& ocsp_resp = {});
|
|
|
|
|
|
/**
|
|
* namespace PKIX holds the building blocks that are called by x509_path_validate.
|
|
* This allows custom validation logic to be written by applications and makes
|
|
* for easier testing, but unless you're positive you know what you're doing you
|
|
* probably want to just call x509_path_validate instead.
|
|
*/
|
|
namespace PKIX {
|
|
|
|
Certificate_Status_Code
|
|
build_all_certificate_paths(std::vector<std::vector<std::shared_ptr<const X509_Certificate>>>& cert_paths,
|
|
const std::vector<Certificate_Store*>& trusted_certstores,
|
|
const std::shared_ptr<const X509_Certificate>& end_entity,
|
|
const std::vector<std::shared_ptr<const X509_Certificate>>& end_entity_extra);
|
|
|
|
|
|
/**
|
|
* Build certificate path
|
|
* @param cert_path_out output parameter, cert_path will be appended to this vector
|
|
* @param trusted_certstores list of certificate stores that contain trusted certificates
|
|
* @param end_entity the cert to be validated
|
|
* @param end_entity_extra optional list of additional untrusted certs for path building
|
|
* @return result of the path building operation (OK or error)
|
|
*/
|
|
Certificate_Status_Code
|
|
BOTAN_PUBLIC_API(2,0) build_certificate_path(std::vector<std::shared_ptr<const X509_Certificate>>& cert_path_out,
|
|
const std::vector<Certificate_Store*>& trusted_certstores,
|
|
const std::shared_ptr<const X509_Certificate>& end_entity,
|
|
const std::vector<std::shared_ptr<const X509_Certificate>>& end_entity_extra);
|
|
|
|
/**
|
|
* Check the certificate chain, but not any revocation data
|
|
*
|
|
* @param cert_path path built by build_certificate_path with OK result
|
|
* @param ref_time whatever time you want to perform the validation
|
|
* against (normally current system clock)
|
|
* @param hostname the hostname
|
|
* @param usage end entity usage checks
|
|
* @param min_signature_algo_strength 80 or 110 typically
|
|
* Note 80 allows 1024 bit RSA and SHA-1. 110 allows 2048 bit RSA and SHA-2.
|
|
* Using 128 requires ECC (P-256) or ~3000 bit RSA keys.
|
|
* @param trusted_hashes set of trusted hash functions, empty means accept any
|
|
* hash we have an OID for
|
|
* @return vector of results on per certificate in the path, each containing a set of
|
|
* results. If all codes in the set are < Certificate_Status_Code::FIRST_ERROR_STATUS,
|
|
* then the result for that certificate is successful. If all results are
|
|
*/
|
|
CertificatePathStatusCodes
|
|
BOTAN_PUBLIC_API(2,0) check_chain(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
|
|
std::chrono::system_clock::time_point ref_time,
|
|
const std::string& hostname,
|
|
Usage_Type usage,
|
|
size_t min_signature_algo_strength,
|
|
const std::set<std::string>& trusted_hashes);
|
|
|
|
/**
|
|
* Check OCSP responses for revocation information
|
|
* @param cert_path path already validated by check_chain
|
|
* @param ocsp_responses the OCSP responses to consider
|
|
* @param certstores trusted roots
|
|
* @param ref_time whatever time you want to perform the validation against
|
|
* (normally current system clock)
|
|
* @param max_ocsp_age maximum age of OCSP responses w/o next_update. If zero,
|
|
* there is no maximum age
|
|
* @return revocation status
|
|
*/
|
|
CertificatePathStatusCodes
|
|
BOTAN_PUBLIC_API(2, 0) check_ocsp(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
|
|
const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
|
|
const std::vector<Certificate_Store*>& certstores,
|
|
std::chrono::system_clock::time_point ref_time,
|
|
std::chrono::seconds max_ocsp_age = std::chrono::seconds::zero());
|
|
|
|
/**
|
|
* Check CRLs for revocation information
|
|
* @param cert_path path already validated by check_chain
|
|
* @param crls the list of CRLs to check, it is assumed that crls[i] (if not null)
|
|
* is the associated CRL for the subject in cert_path[i].
|
|
* @param ref_time whatever time you want to perform the validation against
|
|
* (normally current system clock)
|
|
* @return revocation status
|
|
*/
|
|
CertificatePathStatusCodes
|
|
BOTAN_PUBLIC_API(2,0) check_crl(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
|
|
const std::vector<std::shared_ptr<const X509_CRL>>& crls,
|
|
std::chrono::system_clock::time_point ref_time);
|
|
|
|
/**
|
|
* Check CRLs for revocation information
|
|
* @param cert_path path already validated by check_chain
|
|
* @param certstores a list of certificate stores to query for the CRL
|
|
* @param ref_time whatever time you want to perform the validation against
|
|
* (normally current system clock)
|
|
* @return revocation status
|
|
*/
|
|
CertificatePathStatusCodes
|
|
BOTAN_PUBLIC_API(2,0) check_crl(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
|
|
const std::vector<Certificate_Store*>& certstores,
|
|
std::chrono::system_clock::time_point ref_time);
|
|
|
|
#if defined(BOTAN_HAS_ONLINE_REVOCATION_CHECKS)
|
|
|
|
/**
|
|
* Check OCSP using online (HTTP) access. Current version creates a thread and
|
|
* network connection per OCSP request made.
|
|
*
|
|
* @param cert_path path already validated by check_chain
|
|
* @param trusted_certstores a list of certstores with trusted certs
|
|
* @param ref_time whatever time you want to perform the validation against
|
|
* (normally current system clock)
|
|
* @param timeout for timing out the responses, though actually this function
|
|
* may block for up to timeout*cert_path.size()*C for some small C.
|
|
* @param ocsp_check_intermediate_CAs if true also performs OCSP on any intermediate
|
|
* CA certificates. If false, only does OCSP on the end entity cert.
|
|
* @param max_ocsp_age maximum age of OCSP responses w/o next_update. If zero,
|
|
* there is no maximum age
|
|
* @return revocation status
|
|
*/
|
|
CertificatePathStatusCodes
|
|
BOTAN_PUBLIC_API(2, 0) check_ocsp_online(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
|
|
const std::vector<Certificate_Store*>& trusted_certstores,
|
|
std::chrono::system_clock::time_point ref_time,
|
|
std::chrono::milliseconds timeout,
|
|
bool ocsp_check_intermediate_CAs,
|
|
std::chrono::seconds max_ocsp_age = std::chrono::seconds::zero());
|
|
|
|
/**
|
|
* Check CRL using online (HTTP) access. Current version creates a thread and
|
|
* network connection per CRL access.
|
|
|
|
* @param cert_path path already validated by check_chain
|
|
* @param trusted_certstores a list of certstores with trusted certs
|
|
* @param certstore_to_recv_crls optional (nullptr to disable), all CRLs
|
|
* retreived will be saved to this cert store.
|
|
* @param ref_time whatever time you want to perform the validation against
|
|
* (normally current system clock)
|
|
* @param timeout for timing out the responses, though actually this function
|
|
* may block for up to timeout*cert_path.size()*C for some small C.
|
|
* @return revocation status
|
|
*/
|
|
CertificatePathStatusCodes
|
|
BOTAN_PUBLIC_API(2,0) check_crl_online(const std::vector<std::shared_ptr<const X509_Certificate>>& cert_path,
|
|
const std::vector<Certificate_Store*>& trusted_certstores,
|
|
Certificate_Store_In_Memory* certstore_to_recv_crls,
|
|
std::chrono::system_clock::time_point ref_time,
|
|
std::chrono::milliseconds timeout);
|
|
|
|
#endif
|
|
|
|
/**
|
|
* Find overall status (OK, error) of a validation
|
|
* @param cert_status result of merge_revocation_status or check_chain
|
|
*/
|
|
Certificate_Status_Code BOTAN_PUBLIC_API(2,0) overall_status(const CertificatePathStatusCodes& cert_status);
|
|
|
|
/**
|
|
* Merge the results from CRL and/or OCSP checks into chain_status
|
|
* @param chain_status the certificate status
|
|
* @param crl_status results from check_crl
|
|
* @param ocsp_status results from check_ocsp
|
|
* @param require_rev_on_end_entity require valid CRL or OCSP on end-entity cert
|
|
* @param require_rev_on_intermediates require valid CRL or OCSP on all intermediate certificates
|
|
*/
|
|
void BOTAN_PUBLIC_API(2,0) merge_revocation_status(CertificatePathStatusCodes& chain_status,
|
|
const CertificatePathStatusCodes& crl_status,
|
|
const CertificatePathStatusCodes& ocsp_status,
|
|
bool require_rev_on_end_entity,
|
|
bool require_rev_on_intermediates);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
class Private_Key;
|
|
|
|
/**
|
|
* Options for X.509 certificates.
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) X509_Cert_Options final
|
|
{
|
|
public:
|
|
/**
|
|
* the subject common name
|
|
*/
|
|
std::string common_name;
|
|
|
|
/**
|
|
* the subject counry
|
|
*/
|
|
std::string country;
|
|
|
|
/**
|
|
* the subject organization
|
|
*/
|
|
std::string organization;
|
|
|
|
/**
|
|
* the subject organizational unit
|
|
*/
|
|
std::string org_unit;
|
|
|
|
/**
|
|
* additional subject organizational units.
|
|
*/
|
|
std::vector<std::string> more_org_units;
|
|
|
|
/**
|
|
* the subject locality
|
|
*/
|
|
std::string locality;
|
|
|
|
/**
|
|
* the subject state
|
|
*/
|
|
std::string state;
|
|
|
|
/**
|
|
* the subject serial number
|
|
*/
|
|
std::string serial_number;
|
|
|
|
/**
|
|
* the subject email adress
|
|
*/
|
|
std::string email;
|
|
|
|
/**
|
|
* the subject URI
|
|
*/
|
|
std::string uri;
|
|
|
|
/**
|
|
* the subject IPv4 address
|
|
*/
|
|
std::string ip;
|
|
|
|
/**
|
|
* the subject DNS
|
|
*/
|
|
std::string dns;
|
|
|
|
/**
|
|
* additional subject DNS entries.
|
|
*/
|
|
std::vector<std::string> more_dns;
|
|
|
|
/**
|
|
* the subject XMPP
|
|
*/
|
|
std::string xmpp;
|
|
|
|
/**
|
|
* the subject challenge password
|
|
*/
|
|
std::string challenge;
|
|
|
|
/**
|
|
* the subject notBefore
|
|
*/
|
|
X509_Time start;
|
|
/**
|
|
* the subject notAfter
|
|
*/
|
|
X509_Time end;
|
|
|
|
/**
|
|
* Indicates whether the certificate request
|
|
*/
|
|
bool is_CA;
|
|
|
|
/**
|
|
* Indicates the BasicConstraints path limit
|
|
*/
|
|
size_t path_limit;
|
|
|
|
std::string padding_scheme;
|
|
|
|
/**
|
|
* The key constraints for the subject public key
|
|
*/
|
|
Key_Constraints constraints;
|
|
|
|
/**
|
|
* The key extended constraints for the subject public key
|
|
*/
|
|
std::vector<OID> ex_constraints;
|
|
|
|
/**
|
|
* Additional X.509 extensions
|
|
*/
|
|
Extensions extensions;
|
|
|
|
/**
|
|
* Mark the certificate as a CA certificate and set the path limit.
|
|
* @param limit the path limit to be set in the BasicConstraints extension.
|
|
*/
|
|
void CA_key(size_t limit = 1);
|
|
|
|
/**
|
|
* Choose a padding scheme different from the default for the key used.
|
|
*/
|
|
void set_padding_scheme(const std::string& scheme);
|
|
|
|
/**
|
|
* Set the notBefore of the certificate.
|
|
* @param time the notBefore value of the certificate
|
|
*/
|
|
void not_before(const std::string& time);
|
|
|
|
/**
|
|
* Set the notAfter of the certificate.
|
|
* @param time the notAfter value of the certificate
|
|
*/
|
|
void not_after(const std::string& time);
|
|
|
|
/**
|
|
* Add the key constraints of the KeyUsage extension.
|
|
* @param constr the constraints to set
|
|
*/
|
|
void add_constraints(Key_Constraints constr);
|
|
|
|
/**
|
|
* Add constraints to the ExtendedKeyUsage extension.
|
|
* @param oid the oid to add
|
|
*/
|
|
void add_ex_constraint(const OID& oid);
|
|
|
|
/**
|
|
* Add constraints to the ExtendedKeyUsage extension.
|
|
* @param name the name to look up the oid to add
|
|
*/
|
|
void add_ex_constraint(const std::string& name);
|
|
|
|
/**
|
|
* Construct a new options object
|
|
* @param opts define the common name of this object. An example for this
|
|
* parameter would be "common_name/country/organization/organizational_unit".
|
|
* @param expire_time the expiration time (from the current clock in seconds)
|
|
*/
|
|
X509_Cert_Options(const std::string& opts = "",
|
|
uint32_t expire_time = 365 * 24 * 60 * 60);
|
|
};
|
|
|
|
namespace X509 {
|
|
|
|
/**
|
|
* Create a self-signed X.509 certificate.
|
|
* @param opts the options defining the certificate to create
|
|
* @param key the private key used for signing, i.e. the key
|
|
* associated with this self-signed certificate
|
|
* @param hash_fn the hash function to use
|
|
* @param rng the rng to use
|
|
* @return newly created self-signed certificate
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) X509_Certificate
|
|
create_self_signed_cert(const X509_Cert_Options& opts,
|
|
const Private_Key& key,
|
|
const std::string& hash_fn,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Create a PKCS#10 certificate request.
|
|
* @param opts the options defining the request to create
|
|
* @param key the key used to sign this request
|
|
* @param rng the rng to use
|
|
* @param hash_fn the hash function to use
|
|
* @return newly created PKCS#10 request
|
|
*/
|
|
BOTAN_PUBLIC_API(2,0) PKCS10_Request create_cert_req(const X509_Cert_Options& opts,
|
|
const Private_Key& key,
|
|
const std::string& hash_fn,
|
|
RandomNumberGenerator& rng);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(x919_mac.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* DES/3DES-based MAC from ANSI X9.19
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) ANSI_X919_MAC final : public MessageAuthenticationCode
|
|
{
|
|
public:
|
|
void clear() override;
|
|
std::string name() const override;
|
|
size_t output_length() const override { return 8; }
|
|
|
|
MessageAuthenticationCode* clone() const override;
|
|
|
|
Key_Length_Specification key_spec() const override
|
|
{
|
|
return Key_Length_Specification(8, 16, 8);
|
|
}
|
|
|
|
ANSI_X919_MAC();
|
|
|
|
ANSI_X919_MAC(const ANSI_X919_MAC&) = delete;
|
|
ANSI_X919_MAC& operator=(const ANSI_X919_MAC&) = delete;
|
|
private:
|
|
void add_data(const uint8_t[], size_t) override;
|
|
void final_result(uint8_t[]) override;
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
|
|
std::unique_ptr<BlockCipher> m_des1, m_des2;
|
|
secure_vector<uint8_t> m_state;
|
|
size_t m_position;
|
|
};
|
|
|
|
}
|
|
|
|
//BOTAN_FUTURE_INTERNAL_HEADER(xmss_hash.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* A collection of pseudorandom hash functions required for XMSS and WOTS
|
|
* computations.
|
|
**/
|
|
class XMSS_Hash final
|
|
{
|
|
public:
|
|
XMSS_Hash(const std::string& h_func_name);
|
|
XMSS_Hash(const XMSS_Hash& hash);
|
|
|
|
/**
|
|
* Pseudoranom function creating a hash out of a key and data using
|
|
* a cryptographic hash function.
|
|
*
|
|
* @param[out] result The hash calculated using key and data.
|
|
* @param[in] key An n-byte key value.
|
|
* @param[in] data A 32-byte XMSS_Address data value
|
|
**/
|
|
inline void prf(secure_vector<uint8_t>& result,
|
|
const secure_vector<uint8_t>& key,
|
|
const secure_vector<uint8_t>& data)
|
|
{
|
|
m_hash->update(m_zero_padding);
|
|
m_hash->update(m_id_prf);
|
|
m_hash->update(key);
|
|
m_hash->update(data);
|
|
m_hash->final(result);
|
|
}
|
|
|
|
/**
|
|
* Pseudoranom function creating a hash out of a key and data using
|
|
* a cryptographic hash function.
|
|
*
|
|
* @param[in] key An n-byte key value.
|
|
* @param[in] data A 32-byte XMSS_Address data value
|
|
* @return result The hash calculated using key and data.
|
|
**/
|
|
inline secure_vector<uint8_t> prf(const secure_vector<uint8_t>& key,
|
|
const secure_vector<uint8_t>& data)
|
|
{
|
|
m_hash->update(m_zero_padding);
|
|
m_hash->update(m_id_prf);
|
|
m_hash->update(key);
|
|
m_hash->update(data);
|
|
return m_hash->final();
|
|
}
|
|
|
|
/**
|
|
* F is a keyed cryptographic hash function used by the WOTS+ algorithm.
|
|
*
|
|
* @param[out] result The hash calculated using key and data.
|
|
* @param[in] key key of length n bytes.
|
|
* @param[in] data string of arbitrary length.
|
|
**/
|
|
void f(secure_vector<uint8_t>& result,
|
|
const secure_vector<uint8_t>& key,
|
|
const secure_vector<uint8_t>& data)
|
|
{
|
|
m_hash->update(m_zero_padding);
|
|
m_hash->update(m_id_f);
|
|
m_hash->update(key);
|
|
m_hash->update(data);
|
|
m_hash->final(result);
|
|
}
|
|
|
|
/**
|
|
* Cryptographic hash function h accepting n byte keys and 2n byte
|
|
* strings of data.
|
|
*
|
|
* @param[out] result The hash calculated using key and data.
|
|
* @param[in] key key of length n bytes.
|
|
* @param[in] data string of 2n bytes length.
|
|
**/
|
|
void h(secure_vector<uint8_t>& result,
|
|
const secure_vector<uint8_t>& key,
|
|
const secure_vector<uint8_t>& data);
|
|
|
|
/**
|
|
* Cryptographic hash function h accepting 3n byte keys and data
|
|
* strings of arbitrary length.
|
|
*
|
|
* @param randomness n-byte value.
|
|
* @param root n-byte root node.
|
|
* @param index_bytes Index value padded with leading zeros.
|
|
* @param data string of arbitrary length.
|
|
*
|
|
* @return hash value of n-bytes length.
|
|
**/
|
|
secure_vector<uint8_t> h_msg(const secure_vector<uint8_t>& randomness,
|
|
const secure_vector<uint8_t>& root,
|
|
const secure_vector<uint8_t>& index_bytes,
|
|
const secure_vector<uint8_t>& data);
|
|
|
|
/**
|
|
* Initializes buffered h_msg computation with prefix data.
|
|
*
|
|
* @param randomness random n-byte value.
|
|
* @param root n-byte root node.
|
|
* @param index_bytes Index value padded with leading zeros.
|
|
**/
|
|
void h_msg_init(const secure_vector<uint8_t>& randomness,
|
|
const secure_vector<uint8_t>& root,
|
|
const secure_vector<uint8_t>& index_bytes);
|
|
|
|
/**
|
|
* Adds a message block to buffered h_msg computation.
|
|
*
|
|
* @param data A message block
|
|
* @param size Length of the message block in bytes.
|
|
**/
|
|
void h_msg_update(const uint8_t data[], size_t size);
|
|
|
|
/**
|
|
* Finalizes buffered h_msg computation and retrieves the result.
|
|
*
|
|
* @return Hash calculated using the prefix set by h_msg_init() and
|
|
* message blocks provided through calls to h_msg_update().
|
|
**/
|
|
secure_vector<uint8_t> h_msg_final();
|
|
|
|
size_t output_length() const { return m_output_length; }
|
|
|
|
private:
|
|
static const uint8_t m_id_f = 0x00;
|
|
static const uint8_t m_id_h = 0x01;
|
|
static const uint8_t m_id_hmsg = 0x02;
|
|
static const uint8_t m_id_prf = 0x03;
|
|
|
|
std::unique_ptr<HashFunction> m_hash;
|
|
std::unique_ptr<HashFunction> m_msg_hash;
|
|
//32 byte id prefixes prepended to the hash input.
|
|
std::vector<uint8_t> m_zero_padding;
|
|
size_t m_output_length;
|
|
const std::string m_hash_func_name;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Descibes a signature method for XMSS Winternitz One Time Signatures,
|
|
* as defined in:
|
|
* [1] XMSS: Extended Hash-Based Signatures,
|
|
* Request for Comments: 8391
|
|
* Release: May 2018.
|
|
* https://datatracker.ietf.org/doc/rfc8391/
|
|
**/
|
|
class XMSS_WOTS_Parameters final
|
|
{
|
|
public:
|
|
enum ots_algorithm_t
|
|
{
|
|
WOTSP_SHA2_256 = 0x00000001,
|
|
WOTSP_SHA2_512 = 0x00000002,
|
|
WOTSP_SHAKE_256 = 0x00000003,
|
|
WOTSP_SHAKE_512 = 0x00000004
|
|
};
|
|
|
|
XMSS_WOTS_Parameters(const std::string& algo_name);
|
|
XMSS_WOTS_Parameters(ots_algorithm_t ots_spec);
|
|
|
|
static ots_algorithm_t xmss_wots_id_from_string(const std::string& param_set);
|
|
|
|
/**
|
|
* Algorithm 1: convert input string to base.
|
|
*
|
|
* @param msg Input string (referred to as X in [1]).
|
|
* @param out_size size of message in base w.
|
|
*
|
|
* @return Input string converted to the given base.
|
|
**/
|
|
secure_vector<uint8_t> base_w(const secure_vector<uint8_t>& msg, size_t out_size) const;
|
|
|
|
secure_vector<uint8_t> base_w(size_t value) const;
|
|
|
|
void append_checksum(secure_vector<uint8_t>& data);
|
|
|
|
/**
|
|
* @return XMSS WOTS registry name for the chosen parameter set.
|
|
**/
|
|
const std::string& name() const
|
|
{
|
|
return m_name;
|
|
}
|
|
|
|
/**
|
|
* @return Botan name for the hash function used.
|
|
**/
|
|
const std::string& hash_function_name() const
|
|
{
|
|
return m_hash_name;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the uniform length of a message, and the size of
|
|
* each node. This correlates to XMSS parameter "n" defined
|
|
* in [1].
|
|
*
|
|
* @return element length in bytes.
|
|
**/
|
|
size_t element_size() const { return m_element_size; }
|
|
|
|
/**
|
|
* The Winternitz parameter.
|
|
*
|
|
* @return numeric base used for internal representation of
|
|
* data.
|
|
**/
|
|
size_t wots_parameter() const { return m_w; }
|
|
|
|
size_t len() const { return m_len; }
|
|
|
|
size_t len_1() const { return m_len_1; }
|
|
|
|
size_t len_2() const { return m_len_2; }
|
|
|
|
size_t lg_w() const { return m_lg_w; }
|
|
|
|
ots_algorithm_t oid() const { return m_oid; }
|
|
|
|
size_t estimated_strength() const { return m_strength; }
|
|
|
|
bool operator==(const XMSS_WOTS_Parameters& p) const
|
|
{
|
|
return m_oid == p.m_oid;
|
|
}
|
|
|
|
private:
|
|
static const std::map<std::string, ots_algorithm_t> m_oid_name_lut;
|
|
ots_algorithm_t m_oid;
|
|
std::string m_name;
|
|
std::string m_hash_name;
|
|
size_t m_element_size;
|
|
size_t m_w;
|
|
size_t m_len_1;
|
|
size_t m_len_2;
|
|
size_t m_len;
|
|
size_t m_strength;
|
|
uint8_t m_lg_w;
|
|
};
|
|
|
|
class XMSS_Address;
|
|
|
|
typedef std::vector<secure_vector<uint8_t>> wots_keysig_t;
|
|
|
|
/**
|
|
* A Winternitz One Time Signature public key for use with Extended Hash-Based
|
|
* Signatures.
|
|
**/
|
|
class XMSS_WOTS_PublicKey : virtual public Public_Key
|
|
{
|
|
public:
|
|
class TreeSignature final
|
|
{
|
|
public:
|
|
TreeSignature() = default;
|
|
|
|
TreeSignature(const wots_keysig_t& ots_sig,
|
|
const wots_keysig_t& auth_path)
|
|
: m_ots_sig(ots_sig), m_auth_path(auth_path)
|
|
{}
|
|
|
|
TreeSignature(wots_keysig_t&& ots_sig,
|
|
wots_keysig_t&& auth_path)
|
|
: m_ots_sig(std::move(ots_sig)),
|
|
m_auth_path(std::move(auth_path))
|
|
{}
|
|
|
|
const wots_keysig_t& ots_signature() const
|
|
{
|
|
return m_ots_sig;
|
|
}
|
|
|
|
wots_keysig_t& ots_signature()
|
|
{
|
|
return m_ots_sig;
|
|
}
|
|
|
|
const wots_keysig_t& authentication_path() const
|
|
{
|
|
return m_auth_path;
|
|
}
|
|
|
|
wots_keysig_t& authentication_path()
|
|
{
|
|
return m_auth_path;
|
|
}
|
|
|
|
private:
|
|
wots_keysig_t m_ots_sig;
|
|
wots_keysig_t m_auth_path;
|
|
};
|
|
|
|
/**
|
|
* Creates a XMSS_WOTS_PublicKey for the signature method identified by
|
|
* oid. The public seed for this key will be initialized with a
|
|
* uniformly random n-byte value, where "n" is the element size of the
|
|
* selected signature method.
|
|
*
|
|
* @param oid Identifier for the selected signature method.
|
|
**/
|
|
XMSS_WOTS_PublicKey(XMSS_WOTS_Parameters::ots_algorithm_t oid)
|
|
: m_wots_params(oid),
|
|
m_hash(m_wots_params.hash_function_name()) {}
|
|
|
|
/**
|
|
* Creates a XMSS_WOTS_PublicKey for the signature method identified by
|
|
* oid. The public seed for this key will be initialized with a
|
|
* uniformly random n-byte value, where "n" is the element size of the
|
|
* selected signature method.
|
|
*
|
|
* @param oid Identifier for the selected signature method.
|
|
* @param rng A random number generate used to generate the public seed.
|
|
**/
|
|
XMSS_WOTS_PublicKey(XMSS_WOTS_Parameters::ots_algorithm_t oid,
|
|
RandomNumberGenerator& rng)
|
|
: m_wots_params(oid),
|
|
m_hash(m_wots_params.hash_function_name()),
|
|
m_public_seed(rng.random_vec(m_wots_params.element_size())) {}
|
|
|
|
/**
|
|
* Creates a XMSS_WOTS_PrivateKey for the signature method identified by
|
|
* oid, with a precomputed public seed.
|
|
*
|
|
* @param oid Identifier for the selected signature method.
|
|
* @param public_seed A precomputed public seed of n-bytes length.
|
|
**/
|
|
XMSS_WOTS_PublicKey(XMSS_WOTS_Parameters::ots_algorithm_t oid,
|
|
secure_vector<uint8_t> public_seed)
|
|
: m_wots_params(oid),
|
|
m_hash(m_wots_params.hash_function_name()),
|
|
m_public_seed(public_seed) {}
|
|
|
|
/**
|
|
* Creates a XMSS_WOTS_PublicKey for the signature method identified by
|
|
* oid. The public seed will be initialized with a precomputed seed and
|
|
* and precomputed key data which should be derived from a
|
|
* XMSS_WOTS_PrivateKey.
|
|
*
|
|
* @param oid Ident:s/ifier for the selected signature methods.
|
|
* @param public_seed A precomputed public seed of n-bytes length.
|
|
* @param key Precomputed raw key data of the XMSS_WOTS_PublicKey.
|
|
**/
|
|
XMSS_WOTS_PublicKey(XMSS_WOTS_Parameters::ots_algorithm_t oid,
|
|
secure_vector<uint8_t>&& public_seed,
|
|
wots_keysig_t&& key)
|
|
: m_wots_params(oid),
|
|
m_hash(m_wots_params.hash_function_name()),
|
|
m_key(std::move(key)),
|
|
m_public_seed(std::move(public_seed))
|
|
{}
|
|
|
|
/**
|
|
* Creates a XMSS_WOTS_PublicKey for the signature method identified by
|
|
* oid. The public seed will be initialized with a precomputed seed and
|
|
* and precomputed key data which should be derived from a
|
|
* XMSS_WOTS_PrivateKey.
|
|
*
|
|
* @param oid Identifier for the selected signature methods.
|
|
* @param public_seed A precomputed public seed of n-bytes length.
|
|
* @param key Precomputed raw key data of the XMSS_WOTS_PublicKey.
|
|
**/
|
|
XMSS_WOTS_PublicKey(XMSS_WOTS_Parameters::ots_algorithm_t oid,
|
|
const secure_vector<uint8_t>& public_seed,
|
|
const wots_keysig_t& key)
|
|
: m_wots_params(oid),
|
|
m_hash(m_wots_params.hash_function_name()),
|
|
m_key(key),
|
|
m_public_seed(public_seed)
|
|
{}
|
|
|
|
/**
|
|
* Creates a XMSS_WOTS_PublicKey form a message and signature using
|
|
* Algorithm 6 WOTS_pkFromSig defined in the XMSS standard. This
|
|
* overload is used to verify a message using a public key.
|
|
*
|
|
* @param oid WOTSP algorithm identifier.
|
|
* @param msg A message.
|
|
* @param sig A WOTS signature for msg.
|
|
* @param adrs An XMSS_Address.
|
|
* @param public_seed The public public_seed.
|
|
**/
|
|
XMSS_WOTS_PublicKey(XMSS_WOTS_Parameters::ots_algorithm_t oid,
|
|
const secure_vector<uint8_t>& msg,
|
|
const wots_keysig_t& sig,
|
|
XMSS_Address& adrs,
|
|
const secure_vector<uint8_t>& public_seed)
|
|
: m_wots_params(oid),
|
|
m_hash(m_wots_params.hash_function_name()),
|
|
m_key(pub_key_from_signature(msg,
|
|
sig,
|
|
adrs,
|
|
public_seed)),
|
|
m_public_seed(public_seed)
|
|
{}
|
|
|
|
/**
|
|
* Retrieves the i-th element out of the length len chain of
|
|
* n-byte elements contained in the public key.
|
|
*
|
|
* @param i index of the element.
|
|
* @returns n-byte element addressed by i.
|
|
**/
|
|
const secure_vector<uint8_t>& operator[](size_t i) const { return m_key[i]; }
|
|
secure_vector<uint8_t>& operator[](size_t i) { return m_key[i]; }
|
|
|
|
/**
|
|
* Convert the key into the raw key data. The key becomes a length
|
|
* len vector of n-byte elements.
|
|
**/
|
|
operator const wots_keysig_t& () const { return m_key; }
|
|
|
|
/**
|
|
* Convert the key into the raw key data. The key becomes a length
|
|
* len vector of n-byte elements.
|
|
**/
|
|
operator wots_keysig_t& () { return m_key; }
|
|
|
|
const secure_vector<uint8_t>& public_seed() const { return m_public_seed; }
|
|
|
|
secure_vector<uint8_t>& public_seed() { return m_public_seed; }
|
|
|
|
void set_public_seed(const secure_vector<uint8_t>& public_seed)
|
|
{
|
|
m_public_seed = public_seed;
|
|
}
|
|
|
|
void set_public_seed(secure_vector<uint8_t>&& public_seed)
|
|
{
|
|
m_public_seed = std::move(public_seed);
|
|
}
|
|
|
|
const wots_keysig_t& key_data() const { return m_key; }
|
|
|
|
wots_keysig_t& key_data() { return m_key; }
|
|
|
|
void set_key_data(const wots_keysig_t& key_data)
|
|
{
|
|
m_key = key_data;
|
|
}
|
|
|
|
void set_key_data(wots_keysig_t&& key_data)
|
|
{
|
|
m_key = std::move(key_data);
|
|
}
|
|
|
|
const XMSS_WOTS_Parameters& wots_parameters() const
|
|
{
|
|
return m_wots_params;
|
|
}
|
|
|
|
std::string algo_name() const override
|
|
{
|
|
return m_wots_params.name();
|
|
}
|
|
|
|
AlgorithmIdentifier algorithm_identifier() const override
|
|
{
|
|
throw Not_Implemented("No AlgorithmIdentifier available for XMSS-WOTS.");
|
|
}
|
|
|
|
bool check_key(RandomNumberGenerator&, bool) const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
size_t estimated_strength() const override
|
|
{
|
|
return m_wots_params.estimated_strength();
|
|
}
|
|
|
|
size_t key_length() const override
|
|
{
|
|
return m_wots_params.estimated_strength();
|
|
}
|
|
|
|
std::vector<uint8_t> public_key_bits() const override
|
|
{
|
|
throw Not_Implemented("No key format defined for XMSS-WOTS");
|
|
}
|
|
|
|
bool operator==(const XMSS_WOTS_PublicKey& key)
|
|
{
|
|
return m_key == key.m_key;
|
|
}
|
|
|
|
bool operator!=(const XMSS_WOTS_PublicKey& key)
|
|
{
|
|
return !(*this == key);
|
|
}
|
|
|
|
protected:
|
|
/**
|
|
* Algorithm 2: Chaining Function.
|
|
*
|
|
* Takes an n-byte input string and transforms it into a the function
|
|
* result iterating the cryptographic hash function "F" steps times on
|
|
* the input x using the outputs of the PRNG "G".
|
|
*
|
|
* This overload is used in multithreaded scenarios, where it is
|
|
* required to provide seperate instances of XMSS_Hash to each
|
|
* thread.
|
|
*
|
|
* @param[out] x An n-byte input string, that will be transformed into
|
|
* the chaining function result.
|
|
* @param start_idx The start index.
|
|
* @param steps A number of steps.
|
|
* @param adrs An OTS Hash Address.
|
|
* @param public_seed A public seed.
|
|
* @param hash Instance of XMSS_Hash, that may only by the thead
|
|
* executing chain.
|
|
**/
|
|
void chain(secure_vector<uint8_t>& x,
|
|
size_t start_idx,
|
|
size_t steps,
|
|
XMSS_Address& adrs,
|
|
const secure_vector<uint8_t>& public_seed,
|
|
XMSS_Hash& hash);
|
|
|
|
/**
|
|
* Algorithm 2: Chaining Function.
|
|
*
|
|
* Takes an n-byte input string and transforms it into a the function
|
|
* result iterating the cryptographic hash function "F" steps times on
|
|
* the input x using the outputs of the PRNG "G".
|
|
*
|
|
* @param[out] x An n-byte input string, that will be transformed into
|
|
* the chaining function result.
|
|
* @param start_idx The start index.
|
|
* @param steps A number of steps.
|
|
* @param adrs An OTS Hash Address.
|
|
* @param public_seed A public seed.
|
|
**/
|
|
inline void chain(secure_vector<uint8_t>& x,
|
|
size_t start_idx,
|
|
size_t steps,
|
|
XMSS_Address& adrs,
|
|
const secure_vector<uint8_t>& public_seed)
|
|
{
|
|
chain(x, start_idx, steps, adrs, public_seed, m_hash);
|
|
}
|
|
|
|
XMSS_WOTS_Parameters m_wots_params;
|
|
XMSS_Hash m_hash;
|
|
wots_keysig_t m_key;
|
|
secure_vector<uint8_t> m_public_seed;
|
|
|
|
private:
|
|
/**
|
|
* Algorithm 6: "WOTS_pkFromSig"
|
|
* Computes a Winternitz One Time Signature+ public key from a message and
|
|
* its signature.
|
|
*
|
|
* @param msg A message.
|
|
* @param sig The signature for msg.
|
|
* @param adrs An address.
|
|
* @param public_seed A public_seed.
|
|
*
|
|
* @return Temporary WOTS+ public key.
|
|
**/
|
|
wots_keysig_t pub_key_from_signature(
|
|
const secure_vector<uint8_t>& msg,
|
|
const wots_keysig_t& sig,
|
|
XMSS_Address& adrs,
|
|
const secure_vector<uint8_t>& public_seed);
|
|
};
|
|
|
|
/** A Winternitz One Time Signature private key for use with Extended Hash-Based
|
|
* Signatures.
|
|
**/
|
|
class XMSS_WOTS_PrivateKey final : public virtual XMSS_WOTS_PublicKey,
|
|
public virtual Private_Key
|
|
{
|
|
public:
|
|
/**
|
|
* Creates a WOTS private key for the chosen XMSS WOTS signature method.
|
|
* Members need to be initialized manually.
|
|
*
|
|
* @param oid Identifier for the selected signature method.
|
|
**/
|
|
XMSS_WOTS_PrivateKey(XMSS_WOTS_Parameters::ots_algorithm_t oid)
|
|
: XMSS_WOTS_PublicKey(oid)
|
|
{}
|
|
|
|
/**
|
|
* Creates a WOTS private key for the chosen XMSS WOTS signature method.
|
|
*
|
|
* @param oid Identifier for the selected signature method.
|
|
* @param rng A random number generator to use for key generation.
|
|
**/
|
|
XMSS_WOTS_PrivateKey(XMSS_WOTS_Parameters::ots_algorithm_t oid,
|
|
RandomNumberGenerator& rng)
|
|
: XMSS_WOTS_PublicKey(oid, rng),
|
|
m_private_seed(rng.random_vec(m_wots_params.element_size()))
|
|
{
|
|
set_key_data(generate(m_private_seed));
|
|
}
|
|
|
|
/**
|
|
* Constructs a WOTS private key. Chains will be generated on demand
|
|
* applying a hash function to a unique value generated from a secret
|
|
* seed and a counter. The secret seed of length n, will be
|
|
* automatically generated using AutoSeeded_RNG(). "n" equals
|
|
* the element size of the chosen WOTS security parameter set.
|
|
*
|
|
* @param oid Identifier for the selected signature method.
|
|
* @param public_seed A public seed used for the pseudo random generation
|
|
* of public keys derived from this private key.
|
|
* @param rng A random number generator to use for key generation.
|
|
**/
|
|
XMSS_WOTS_PrivateKey(XMSS_WOTS_Parameters::ots_algorithm_t oid,
|
|
const secure_vector<uint8_t>& public_seed,
|
|
RandomNumberGenerator& rng)
|
|
: XMSS_WOTS_PublicKey(oid, public_seed),
|
|
m_private_seed(rng.random_vec(m_wots_params.element_size()))
|
|
{
|
|
set_key_data(generate(m_private_seed));
|
|
}
|
|
|
|
/**
|
|
* Constructs a WOTS private key. Chains will be generated on demand
|
|
* applying a hash function to a unique value generated from a secret
|
|
* seed and a counter. The secret seed of length n, will be
|
|
* automatically generated using AutoSeeded_RNG(). "n" equals
|
|
* the element size of the chosen WOTS security parameter set.
|
|
*
|
|
* @param oid Identifier for the selected signature method.
|
|
* @param public_seed A public seed used for the pseudo random generation
|
|
* of public keys derived from this private key.
|
|
**/
|
|
XMSS_WOTS_PrivateKey(XMSS_WOTS_Parameters::ots_algorithm_t oid,
|
|
const secure_vector<uint8_t>& public_seed)
|
|
: XMSS_WOTS_PublicKey(oid, public_seed)
|
|
{}
|
|
|
|
/**
|
|
* Constructs a WOTS private key. Chains will be generated on demand
|
|
* applying a hash function to a unique value generated from the
|
|
* secret seed and a counter.
|
|
*
|
|
* @param oid Identifier for the selected signature method.
|
|
* @param public_seed A public seed used for the pseudo random generation
|
|
* of public keys derived from this private key.
|
|
* @param private_seed A secret uniformly random n-byte value.
|
|
**/
|
|
XMSS_WOTS_PrivateKey(XMSS_WOTS_Parameters::ots_algorithm_t oid,
|
|
const secure_vector<uint8_t>& public_seed,
|
|
const secure_vector<uint8_t>& private_seed)
|
|
: XMSS_WOTS_PublicKey(oid, public_seed),
|
|
m_private_seed(private_seed)
|
|
{
|
|
set_key_data(generate(private_seed));
|
|
}
|
|
|
|
/**
|
|
* Retrieves the i-th WOTS private key using pseudo random key
|
|
* (re-)generation.
|
|
*
|
|
* This overload is used in multithreaded scenarios, where it is
|
|
* required to provide seperate instances of XMSS_Hash to each
|
|
* thread.
|
|
*
|
|
* @param i Index of the key to retrieve.
|
|
* @param hash Instance of XMSS_Hash, that may only be used by the
|
|
* thead executing at.
|
|
*
|
|
* @return WOTS secret key.
|
|
**/
|
|
wots_keysig_t at(size_t i, XMSS_Hash& hash);
|
|
|
|
/**
|
|
* Retrieves the i-th WOTS private key using pseudo random key
|
|
* (re-)generation.
|
|
*
|
|
* @param i Index of the key to retrieve.
|
|
*
|
|
* @return WOTS secret key.
|
|
**/
|
|
inline wots_keysig_t operator[](size_t i)
|
|
{
|
|
return this->at(i, m_hash);
|
|
}
|
|
|
|
/**
|
|
* Retrieves the i-th WOTS private key using pseudo random key
|
|
* (re-)generation.
|
|
*
|
|
* This overload is used in multithreaded scenarios, where it is
|
|
* required to provide seperate instances of XMSS_Hash to each
|
|
* thread.
|
|
*
|
|
* @param adrs The address of the key to retrieve.
|
|
* @param hash Instance of XMSS_Hash, that may only be used by the
|
|
* thead executing at.
|
|
*
|
|
* @return WOTS secret key.
|
|
**/
|
|
wots_keysig_t at(const XMSS_Address& adrs, XMSS_Hash& hash);
|
|
|
|
inline wots_keysig_t operator[](const XMSS_Address& adrs)
|
|
{
|
|
return this->at(adrs, m_hash);
|
|
}
|
|
|
|
wots_keysig_t generate_private_key(const secure_vector<uint8_t>& priv_seed);
|
|
|
|
/**
|
|
* Algorithm 4: "WOTS_genPK"
|
|
* Generates a Winternitz One Time Signature+ (WOTS+) Public Key from a
|
|
* given private key.
|
|
*
|
|
* @param adrs Hash function address encoding the address of the WOTS+
|
|
* key pair within a greater structure.
|
|
*
|
|
* @return A XMSS_WOTS_PublicKey.
|
|
**/
|
|
XMSS_WOTS_PublicKey generate_public_key(XMSS_Address& adrs);
|
|
|
|
/**
|
|
* Algorithm 4: "WOTS_genPK"
|
|
* Initializes a Winternitz One Time Signature+ (WOTS+) Public Key's
|
|
* key_data() member, with data derived from in_key_data using the
|
|
* WOTS chaining function.
|
|
*
|
|
* This overload is used in multithreaded scenarios, where it is
|
|
* required to provide seperate instances of XMSS_Hash to each
|
|
* thread.
|
|
*
|
|
* @param[out] pub_key Public key to initialize key_data() member on.
|
|
* @param in_key_data Input key material from private key used for
|
|
* public key generation.
|
|
* @param adrs Hash function address encoding the address of
|
|
* the WOTS+ key pair within a greater structure.
|
|
* @param hash Instance of XMSS_Hash, that may only by the thead
|
|
* executing generate_public_key.
|
|
**/
|
|
void generate_public_key(XMSS_WOTS_PublicKey& pub_key,
|
|
wots_keysig_t&& in_key_data,
|
|
XMSS_Address& adrs,
|
|
XMSS_Hash& hash);
|
|
/**
|
|
* Algorithm 4: "WOTS_genPK"
|
|
* Initializes a Winternitz One Time Signature+ (WOTS+) Public Key's
|
|
* key_data() member, with data derived from in_key_data using the
|
|
* WOTS chaining function.
|
|
*
|
|
* @param[out] pub_key Public key to initialize key_data() member on.
|
|
* @param in_key_data Input key material from private key used for
|
|
* public key generation.
|
|
* @param adrs Hash function address encoding the address of
|
|
* the WOTS+ key pair within a greater structure.
|
|
**/
|
|
inline void generate_public_key(XMSS_WOTS_PublicKey& pub_key,
|
|
wots_keysig_t&& in_key_data,
|
|
XMSS_Address& adrs)
|
|
{
|
|
generate_public_key(pub_key, std::forward<wots_keysig_t>(in_key_data), adrs, m_hash);
|
|
}
|
|
|
|
/**
|
|
* Algorithm 5: "WOTS_sign"
|
|
* Generates a signature from a private key and a message.
|
|
*
|
|
* @param msg A message to sign.
|
|
* @param adrs An OTS hash address identifying the WOTS+ key pair
|
|
* used for signing.
|
|
*
|
|
* @return signature for msg.
|
|
**/
|
|
inline wots_keysig_t sign(const secure_vector<uint8_t>& msg,
|
|
XMSS_Address& adrs)
|
|
{
|
|
return sign(msg, adrs, m_hash);
|
|
}
|
|
|
|
/**
|
|
* Algorithm 5: "WOTS_sign"
|
|
* Generates a signature from a private key and a message.
|
|
*
|
|
* This overload is used in multithreaded scenarios, where it is
|
|
* required to provide seperate instances of XMSS_Hash to each
|
|
* thread.
|
|
*
|
|
* @param msg A message to sign.
|
|
* @param adrs An OTS hash address identifying the WOTS+ key pair
|
|
* used for signing.
|
|
* @param hash Instance of XMSS_Hash, that may only be used by the
|
|
* thead executing sign.
|
|
*
|
|
* @return signature for msg.
|
|
**/
|
|
wots_keysig_t sign(const secure_vector<uint8_t>& msg,
|
|
XMSS_Address& adrs,
|
|
XMSS_Hash& hash);
|
|
|
|
/**
|
|
* Retrieves the secret seed used to generate WOTS+ chains. The seed
|
|
* should be a uniformly random n-byte value.
|
|
*
|
|
* @return secret seed.
|
|
**/
|
|
const secure_vector<uint8_t>& private_seed() const
|
|
{
|
|
return m_private_seed;
|
|
}
|
|
|
|
/**
|
|
* Sets the secret seed used to generate WOTS+ chains. The seed
|
|
* should be a uniformly random n-byte value.
|
|
*
|
|
* @param private_seed Uniformly random n-byte value.
|
|
**/
|
|
void set_private_seed(const secure_vector<uint8_t>& private_seed)
|
|
{
|
|
m_private_seed = private_seed;
|
|
}
|
|
|
|
/**
|
|
* Sets the secret seed used to generate WOTS+ chains. The seed
|
|
* should be a uniformly random n-byte value.
|
|
*
|
|
* @param private_seed Uniformly random n-byte value.
|
|
**/
|
|
void set_private_seed(secure_vector<uint8_t>&& private_seed)
|
|
{
|
|
m_private_seed = std::move(private_seed);
|
|
}
|
|
|
|
AlgorithmIdentifier
|
|
pkcs8_algorithm_identifier() const override
|
|
{
|
|
throw Not_Implemented("No AlgorithmIdentifier available for XMSS-WOTS.");
|
|
}
|
|
|
|
secure_vector<uint8_t> private_key_bits() const override
|
|
{
|
|
throw Not_Implemented("No PKCS8 key format defined for XMSS-WOTS.");
|
|
}
|
|
|
|
private:
|
|
/**
|
|
* Algorithm 3: "Generating a WOTS+ Private Key".
|
|
* Generates a private key.
|
|
*
|
|
* This overload is used in multithreaded scenarios, where it is
|
|
* required to provide seperate instances of XMSS_Hash to each thread.
|
|
*
|
|
* @param private_seed Uniformly random n-byte value.
|
|
* @param[in] hash Instance of XMSS_Hash, that may only be used by the
|
|
* thead executing generate.
|
|
*
|
|
* @returns a vector of length key_size() of vectors of n bytes length
|
|
* containing uniformly random data.
|
|
**/
|
|
wots_keysig_t generate(const secure_vector<uint8_t>& private_seed,
|
|
XMSS_Hash& hash);
|
|
|
|
inline wots_keysig_t generate(const secure_vector<uint8_t>& private_seed)
|
|
{
|
|
return generate(private_seed, m_hash);
|
|
}
|
|
|
|
secure_vector<uint8_t> m_private_seed;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* Descibes a signature method for XMSS, as defined in:
|
|
* [1] XMSS: Extended Hash-Based Signatures,
|
|
* Request for Comments: 8391
|
|
* Release: May 2018.
|
|
* https://datatracker.ietf.org/doc/rfc8391/
|
|
**/
|
|
class BOTAN_PUBLIC_API(2,0) XMSS_Parameters
|
|
{
|
|
public:
|
|
enum xmss_algorithm_t
|
|
{
|
|
XMSS_SHA2_10_256 = 0x00000001,
|
|
XMSS_SHA2_16_256 = 0x00000002,
|
|
XMSS_SHA2_20_256 = 0x00000003,
|
|
XMSS_SHA2_10_512 = 0x00000004,
|
|
XMSS_SHA2_16_512 = 0x00000005,
|
|
XMSS_SHA2_20_512 = 0x00000006,
|
|
XMSS_SHAKE_10_256 = 0x00000007,
|
|
XMSS_SHAKE_16_256 = 0x00000008,
|
|
XMSS_SHAKE_20_256 = 0x00000009,
|
|
XMSS_SHAKE_10_512 = 0x0000000a,
|
|
XMSS_SHAKE_16_512 = 0x0000000b,
|
|
XMSS_SHAKE_20_512 = 0x0000000c
|
|
};
|
|
|
|
static xmss_algorithm_t xmss_id_from_string(const std::string& algo_name);
|
|
|
|
XMSS_Parameters(const std::string& algo_name);
|
|
XMSS_Parameters(xmss_algorithm_t oid);
|
|
|
|
/**
|
|
* @return XMSS registry name for the chosen parameter set.
|
|
**/
|
|
const std::string& name() const
|
|
{
|
|
return m_name;
|
|
}
|
|
|
|
const std::string& hash_function_name() const
|
|
{
|
|
return m_hash_name;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the uniform length of a message, and the size of
|
|
* each node. This correlates to XMSS parameter "n" defined
|
|
* in [1].
|
|
*
|
|
* @return element length in bytes.
|
|
**/
|
|
size_t element_size() const { return m_element_size; }
|
|
|
|
/**
|
|
* @returns The height (number of levels - 1) of the tree
|
|
**/
|
|
size_t tree_height() const { return m_tree_height; }
|
|
|
|
/**
|
|
* The Winternitz parameter.
|
|
*
|
|
* @return numeric base used for internal representation of
|
|
* data.
|
|
**/
|
|
size_t wots_parameter() const { return m_w; }
|
|
|
|
size_t len() const { return m_len; }
|
|
|
|
xmss_algorithm_t oid() const { return m_oid; }
|
|
|
|
XMSS_WOTS_Parameters::ots_algorithm_t ots_oid() const
|
|
{
|
|
return m_wots_oid;
|
|
}
|
|
|
|
/**
|
|
* Returns the estimated pre-quantum security level of
|
|
* the chosen algorithm.
|
|
**/
|
|
size_t estimated_strength() const
|
|
{
|
|
return m_strength;
|
|
}
|
|
|
|
bool operator==(const XMSS_Parameters& p) const
|
|
{
|
|
return m_oid == p.m_oid;
|
|
}
|
|
|
|
private:
|
|
xmss_algorithm_t m_oid;
|
|
XMSS_WOTS_Parameters::ots_algorithm_t m_wots_oid;
|
|
std::string m_name;
|
|
std::string m_hash_name;
|
|
size_t m_element_size;
|
|
size_t m_tree_height;
|
|
size_t m_w;
|
|
size_t m_len;
|
|
size_t m_strength;
|
|
};
|
|
|
|
}
|
|
|
|
namespace Botan {
|
|
|
|
class RandomNumberGenerator;
|
|
class XMSS_Verification_Operation;
|
|
|
|
/**
|
|
* An XMSS: Extended Hash-Based Signature public key.
|
|
*
|
|
* [1] XMSS: Extended Hash-Based Signatures,
|
|
* Request for Comments: 8391
|
|
* Release: May 2018.
|
|
* https://datatracker.ietf.org/doc/rfc8391/
|
|
**/
|
|
class BOTAN_PUBLIC_API(2,0) XMSS_PublicKey : public virtual Public_Key
|
|
{
|
|
public:
|
|
/**
|
|
* Creates a new XMSS public key for the chosen XMSS signature method.
|
|
* New public and prf seeds are generated using rng. The appropriate WOTS
|
|
* signature method will be automatically set based on the chosen XMSS
|
|
* signature method.
|
|
*
|
|
* @param xmss_oid Identifier for the selected XMSS signature method.
|
|
* @param rng A random number generator to use for key generation.
|
|
**/
|
|
XMSS_PublicKey(XMSS_Parameters::xmss_algorithm_t xmss_oid,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Loads a public key.
|
|
*
|
|
* Public key must be encoded as in RFC
|
|
* draft-vangeest-x509-hash-sigs-03.
|
|
*
|
|
* @param key_bits DER encoded public key bits
|
|
*/
|
|
XMSS_PublicKey(const std::vector<uint8_t>& key_bits);
|
|
|
|
/**
|
|
* Creates a new XMSS public key for a chosen XMSS signature method as
|
|
* well as pre-computed root node and public_seed values.
|
|
*
|
|
* @param xmss_oid Identifier for the selected XMSS signature method.
|
|
* @param root Root node value.
|
|
* @param public_seed Public seed value.
|
|
**/
|
|
XMSS_PublicKey(XMSS_Parameters::xmss_algorithm_t xmss_oid,
|
|
const secure_vector<uint8_t>& root,
|
|
const secure_vector<uint8_t>& public_seed)
|
|
: m_xmss_params(xmss_oid), m_wots_params(m_xmss_params.ots_oid()),
|
|
m_root(root), m_public_seed(public_seed) {}
|
|
|
|
/**
|
|
* Creates a new XMSS public key for a chosen XMSS signature method as
|
|
* well as pre-computed root node and public_seed values.
|
|
*
|
|
* @param xmss_oid Identifier for the selected XMSS signature method.
|
|
* @param root Root node value.
|
|
* @param public_seed Public seed value.
|
|
**/
|
|
XMSS_PublicKey(XMSS_Parameters::xmss_algorithm_t xmss_oid,
|
|
secure_vector<uint8_t>&& root,
|
|
secure_vector<uint8_t>&& public_seed)
|
|
: m_xmss_params(xmss_oid), m_wots_params(m_xmss_params.ots_oid()),
|
|
m_root(std::move(root)), m_public_seed(std::move(public_seed)) {}
|
|
|
|
/**
|
|
* Retrieves the chosen XMSS signature method.
|
|
*
|
|
* @return XMSS signature method identifier.
|
|
**/
|
|
XMSS_Parameters::xmss_algorithm_t xmss_oid() const
|
|
{
|
|
return m_xmss_params.oid();
|
|
}
|
|
|
|
/**
|
|
* Sets the chosen XMSS signature method
|
|
**/
|
|
void set_xmss_oid(XMSS_Parameters::xmss_algorithm_t xmss_oid)
|
|
{
|
|
m_xmss_params = XMSS_Parameters(xmss_oid);
|
|
m_wots_params = XMSS_WOTS_Parameters(m_xmss_params.ots_oid());
|
|
}
|
|
|
|
/**
|
|
* Retrieves the XMSS parameters determined by the chosen XMSS Signature
|
|
* method.
|
|
*
|
|
* @return XMSS parameters.
|
|
**/
|
|
const XMSS_Parameters& xmss_parameters() const
|
|
{
|
|
return m_xmss_params;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the XMSS parameters determined by the chosen XMSS Signature
|
|
* method.
|
|
*
|
|
* @return XMSS parameters.
|
|
**/
|
|
std::string xmss_hash_function() const
|
|
{
|
|
return m_xmss_params.hash_function_name();
|
|
}
|
|
|
|
/**
|
|
* Retrieves the Winternitz One Time Signature (WOTS) method,
|
|
* corresponding to the chosen XMSS signature method.
|
|
*
|
|
* @return XMSS WOTS signature method identifier.
|
|
**/
|
|
XMSS_WOTS_Parameters::ots_algorithm_t wots_oid() const
|
|
{
|
|
return m_wots_params.oid();
|
|
}
|
|
|
|
/**
|
|
* Retrieves the Winternitz One Time Signature (WOTS) parameters
|
|
* corresponding to the chosen XMSS signature method.
|
|
*
|
|
* @return XMSS WOTS signature method parameters.
|
|
**/
|
|
const XMSS_WOTS_Parameters& wots_parameters() const
|
|
{
|
|
return m_wots_params;
|
|
}
|
|
|
|
secure_vector<uint8_t>& root()
|
|
{
|
|
return m_root;
|
|
}
|
|
|
|
void set_root(const secure_vector<uint8_t>& root)
|
|
{
|
|
m_root = root;
|
|
}
|
|
|
|
void set_root(secure_vector<uint8_t>&& root)
|
|
{
|
|
m_root = std::move(root);
|
|
}
|
|
|
|
const secure_vector<uint8_t>& root() const
|
|
{
|
|
return m_root;
|
|
}
|
|
|
|
virtual secure_vector<uint8_t>& public_seed()
|
|
{
|
|
return m_public_seed;
|
|
}
|
|
|
|
virtual void set_public_seed(const secure_vector<uint8_t>& public_seed)
|
|
{
|
|
m_public_seed = public_seed;
|
|
}
|
|
|
|
virtual void set_public_seed(secure_vector<uint8_t>&& public_seed)
|
|
{
|
|
m_public_seed = std::move(public_seed);
|
|
}
|
|
|
|
virtual const secure_vector<uint8_t>& public_seed() const
|
|
{
|
|
return m_public_seed;
|
|
}
|
|
|
|
std::string algo_name() const override
|
|
{
|
|
return "XMSS";
|
|
}
|
|
|
|
AlgorithmIdentifier algorithm_identifier() const override
|
|
{
|
|
return AlgorithmIdentifier(get_oid(), AlgorithmIdentifier::USE_EMPTY_PARAM);
|
|
}
|
|
|
|
bool check_key(RandomNumberGenerator&, bool) const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
std::unique_ptr<PK_Ops::Verification>
|
|
create_verification_op(const std::string&,
|
|
const std::string& provider) const override;
|
|
|
|
size_t estimated_strength() const override
|
|
{
|
|
return m_xmss_params.estimated_strength();
|
|
}
|
|
|
|
size_t key_length() const override
|
|
{
|
|
return m_xmss_params.estimated_strength();
|
|
}
|
|
|
|
/**
|
|
* Returns the encoded public key as defined in RFC
|
|
* draft-vangeest-x509-hash-sigs-03.
|
|
*
|
|
* @return encoded public key bits
|
|
**/
|
|
std::vector<uint8_t> public_key_bits() const override;
|
|
|
|
/**
|
|
* Size in bytes of the serialized XMSS public key produced by
|
|
* raw_public_key().
|
|
*
|
|
* @return size in bytes of serialized Public Key.
|
|
**/
|
|
virtual size_t size() const
|
|
{
|
|
return sizeof(uint32_t) + 2 * m_xmss_params.element_size();
|
|
}
|
|
|
|
/**
|
|
* Generates a byte sequence representing the XMSS
|
|
* public key, as defined in [1] (p. 23, "XMSS Public Key")
|
|
*
|
|
* @return 4-byte OID, followed by n-byte root node, followed by
|
|
* public seed.
|
|
**/
|
|
virtual std::vector<uint8_t> raw_public_key() const;
|
|
|
|
protected:
|
|
std::vector<uint8_t> m_raw_key;
|
|
XMSS_Parameters m_xmss_params;
|
|
XMSS_WOTS_Parameters m_wots_params;
|
|
secure_vector<uint8_t> m_root;
|
|
secure_vector<uint8_t> m_public_seed;
|
|
|
|
private:
|
|
XMSS_Parameters::xmss_algorithm_t deserialize_xmss_oid(
|
|
const std::vector<uint8_t>& raw_key);
|
|
};
|
|
|
|
template<typename> class Atomic;
|
|
|
|
class XMSS_Index_Registry;
|
|
|
|
/**
|
|
* An XMSS: Extended Hash-Based Signature private key.
|
|
* The XMSS private key does not support the X509 and PKCS7 standard. Instead
|
|
* the raw format described in [1] is used.
|
|
*
|
|
* [1] XMSS: Extended Hash-Based Signatures,
|
|
* Request for Comments: 8391
|
|
* Release: May 2018.
|
|
* https://datatracker.ietf.org/doc/rfc8391/
|
|
**/
|
|
class BOTAN_PUBLIC_API(2,0) XMSS_PrivateKey final : public virtual XMSS_PublicKey,
|
|
public virtual Private_Key
|
|
{
|
|
public:
|
|
/**
|
|
* Creates a new XMSS private key for the chosen XMSS signature method.
|
|
* New seeds for public/private key and pseudo random function input are
|
|
* generated using the provided RNG. The appropriate WOTS signature method
|
|
* will be automatically set based on the chosen XMSS signature method.
|
|
*
|
|
* @param xmss_algo_id Identifier for the selected XMSS signature method.
|
|
* @param rng A random number generator to use for key generation.
|
|
**/
|
|
XMSS_PrivateKey(XMSS_Parameters::xmss_algorithm_t xmss_algo_id,
|
|
RandomNumberGenerator& rng);
|
|
|
|
/**
|
|
* Creates an XMSS_PrivateKey from a byte sequence produced by
|
|
* raw_private_key().
|
|
*
|
|
* @param raw_key An XMSS private key serialized using raw_private_key().
|
|
**/
|
|
XMSS_PrivateKey(const secure_vector<uint8_t>& raw_key);
|
|
|
|
/**
|
|
* Creates a new XMSS private key for the chosen XMSS signature method
|
|
* using precomputed seeds for public/private keys and pseudo random
|
|
* function input. The appropriate WOTS signature method will be
|
|
* automatically set, based on the chosen XMSS signature method.
|
|
*
|
|
* @param xmss_algo_id Identifier for the selected XMSS signature method.
|
|
* @param idx_leaf Index of the next unused leaf.
|
|
* @param wots_priv_seed A seed to generate a Winternitz-One-Time-
|
|
* Signature private key from.
|
|
* @param prf a secret n-byte key sourced from a secure source
|
|
* of uniformly random data.
|
|
* @param root Root node of the binary hash tree.
|
|
* @param public_seed The public seed.
|
|
**/
|
|
XMSS_PrivateKey(XMSS_Parameters::xmss_algorithm_t xmss_algo_id,
|
|
size_t idx_leaf,
|
|
const secure_vector<uint8_t>& wots_priv_seed,
|
|
const secure_vector<uint8_t>& prf,
|
|
const secure_vector<uint8_t>& root,
|
|
const secure_vector<uint8_t>& public_seed);
|
|
|
|
bool stateful_operation() const override { return true; }
|
|
|
|
/**
|
|
* Retrieves the last unused leaf index of the private key. Reusing a leaf
|
|
* by utilizing leaf indices lower than the last unused leaf index will
|
|
* compromise security.
|
|
*
|
|
* @return Index of the last unused leaf.
|
|
**/
|
|
size_t unused_leaf_index() const;
|
|
|
|
/**
|
|
* Sets the last unused leaf index of the private key. The leaf index
|
|
* will be updated automatically during every signing operation, and
|
|
* should not be set manually.
|
|
*
|
|
* @param idx Index of the last unused leaf.
|
|
**/
|
|
void set_unused_leaf_index(size_t idx);
|
|
|
|
size_t reserve_unused_leaf_index();
|
|
|
|
/**
|
|
* Winternitz One Time Signature Scheme key utilized for signing
|
|
* operations.
|
|
*
|
|
* @return WOTS+ private key.
|
|
**/
|
|
const XMSS_WOTS_PrivateKey& wots_private_key() const
|
|
{
|
|
return m_wots_priv_key;
|
|
}
|
|
|
|
/**
|
|
* Winternitz One Time Signature Scheme key utilized for signing
|
|
* operations.
|
|
*
|
|
* @return WOTS+ private key.
|
|
**/
|
|
XMSS_WOTS_PrivateKey& wots_private_key()
|
|
{
|
|
return m_wots_priv_key;
|
|
}
|
|
|
|
const secure_vector<uint8_t>& prf() const
|
|
{
|
|
return m_prf;
|
|
}
|
|
|
|
secure_vector<uint8_t>& prf()
|
|
{
|
|
return m_prf;
|
|
}
|
|
|
|
void set_public_seed(
|
|
const secure_vector<uint8_t>& public_seed) override
|
|
{
|
|
m_public_seed = public_seed;
|
|
m_wots_priv_key.set_public_seed(public_seed);
|
|
}
|
|
|
|
void set_public_seed(secure_vector<uint8_t>&& public_seed) override
|
|
{
|
|
m_public_seed = std::move(public_seed);
|
|
m_wots_priv_key.set_public_seed(m_public_seed);
|
|
}
|
|
|
|
const secure_vector<uint8_t>& public_seed() const override
|
|
{
|
|
return m_public_seed;
|
|
}
|
|
|
|
std::unique_ptr<PK_Ops::Signature>
|
|
create_signature_op(RandomNumberGenerator&,
|
|
const std::string&,
|
|
const std::string& provider) const override;
|
|
|
|
secure_vector<uint8_t> private_key_bits() const override;
|
|
|
|
size_t size() const override
|
|
{
|
|
return XMSS_PublicKey::size() +
|
|
sizeof(uint32_t) +
|
|
2 * XMSS_PublicKey::m_xmss_params.element_size();
|
|
}
|
|
|
|
/**
|
|
* Generates a non standartized byte sequence representing the XMSS
|
|
* private key.
|
|
*
|
|
* @return byte sequence consisting of the following elements in order:
|
|
* 4-byte OID, n-byte root node, n-byte public seed,
|
|
* 8-byte unused leaf index, n-byte prf seed, n-byte private seed.
|
|
**/
|
|
secure_vector<uint8_t> raw_private_key() const;
|
|
/**
|
|
* Algorithm 9: "treeHash"
|
|
* Computes the internal n-byte nodes of a Merkle tree.
|
|
*
|
|
* @param start_idx The start index.
|
|
* @param target_node_height Height of the target node.
|
|
* @param adrs Address of the tree containing the target node.
|
|
*
|
|
* @return The root node of a tree of height target_node height with the
|
|
* leftmost leaf being the hash of the WOTS+ pk with index
|
|
* start_idx.
|
|
**/
|
|
secure_vector<uint8_t> tree_hash(
|
|
size_t start_idx,
|
|
size_t target_node_height,
|
|
XMSS_Address& adrs);
|
|
|
|
private:
|
|
/**
|
|
* Fetches shared unused leaf index from the index registry
|
|
**/
|
|
std::shared_ptr<Atomic<size_t>> recover_global_leaf_index() const;
|
|
|
|
inline void tree_hash_subtree(secure_vector<uint8_t>& result,
|
|
size_t start_idx,
|
|
size_t target_node_height,
|
|
XMSS_Address& adrs)
|
|
{
|
|
return tree_hash_subtree(result, start_idx, target_node_height, adrs, m_hash);
|
|
}
|
|
|
|
|
|
/**
|
|
* Helper for multithreaded tree hashing.
|
|
*/
|
|
void tree_hash_subtree(secure_vector<uint8_t>& result,
|
|
size_t start_idx,
|
|
size_t target_node_height,
|
|
XMSS_Address& adrs,
|
|
XMSS_Hash& hash);
|
|
|
|
XMSS_WOTS_PrivateKey m_wots_priv_key;
|
|
XMSS_Hash m_hash;
|
|
secure_vector<uint8_t> m_prf;
|
|
XMSS_Index_Registry& m_index_reg;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(xtea.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* XTEA
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) XTEA final : public Block_Cipher_Fixed_Params<8, 16>
|
|
{
|
|
public:
|
|
void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override;
|
|
|
|
void clear() override;
|
|
std::string name() const override { return "XTEA"; }
|
|
BlockCipher* clone() const override { return new XTEA; }
|
|
|
|
private:
|
|
void key_schedule(const uint8_t[], size_t) override;
|
|
secure_vector<uint32_t> m_EK;
|
|
};
|
|
|
|
}
|
|
|
|
BOTAN_FUTURE_INTERNAL_HEADER(xts.h)
|
|
|
|
namespace Botan {
|
|
|
|
/**
|
|
* IEEE P1619 XTS Mode
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) XTS_Mode : public Cipher_Mode
|
|
{
|
|
public:
|
|
std::string name() const override;
|
|
|
|
size_t update_granularity() const override { return m_cipher_parallelism; }
|
|
|
|
size_t minimum_final_size() const override;
|
|
|
|
Key_Length_Specification key_spec() const override;
|
|
|
|
size_t default_nonce_length() const override;
|
|
|
|
bool valid_nonce_length(size_t n) const override;
|
|
|
|
void clear() override;
|
|
|
|
void reset() override;
|
|
|
|
protected:
|
|
explicit XTS_Mode(BlockCipher* cipher);
|
|
|
|
const uint8_t* tweak() const { return m_tweak.data(); }
|
|
|
|
bool tweak_set() const { return m_tweak.empty() == false; }
|
|
|
|
const BlockCipher& cipher() const { return *m_cipher; }
|
|
|
|
void update_tweak(size_t last_used);
|
|
|
|
size_t cipher_block_size() const { return m_cipher_block_size; }
|
|
|
|
private:
|
|
void start_msg(const uint8_t nonce[], size_t nonce_len) override;
|
|
void key_schedule(const uint8_t key[], size_t length) override;
|
|
|
|
std::unique_ptr<BlockCipher> m_cipher;
|
|
std::unique_ptr<BlockCipher> m_tweak_cipher;
|
|
secure_vector<uint8_t> m_tweak;
|
|
const size_t m_cipher_block_size;
|
|
const size_t m_cipher_parallelism;
|
|
};
|
|
|
|
/**
|
|
* IEEE P1619 XTS Encryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) XTS_Encryption final : public XTS_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher underlying block cipher
|
|
*/
|
|
explicit XTS_Encryption(BlockCipher* cipher) : XTS_Mode(cipher) {}
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
|
|
size_t output_length(size_t input_length) const override;
|
|
};
|
|
|
|
/**
|
|
* IEEE P1619 XTS Decryption
|
|
*/
|
|
class BOTAN_PUBLIC_API(2,0) XTS_Decryption final : public XTS_Mode
|
|
{
|
|
public:
|
|
/**
|
|
* @param cipher underlying block cipher
|
|
*/
|
|
explicit XTS_Decryption(BlockCipher* cipher) : XTS_Mode(cipher) {}
|
|
|
|
size_t process(uint8_t buf[], size_t size) override;
|
|
|
|
void finish(secure_vector<uint8_t>& final_block, size_t offset = 0) override;
|
|
|
|
size_t output_length(size_t input_length) const override;
|
|
};
|
|
|
|
}
|
|
|
|
#endif // BOTAN_AMALGAMATION_H_
|