9#include <botan/internal/pbes2.h> 
   11#include <botan/asn1_obj.h> 
   12#include <botan/ber_dec.h> 
   13#include <botan/cipher_mode.h> 
   14#include <botan/der_enc.h> 
   15#include <botan/pwdhash.h> 
   17#include <botan/internal/fmt.h> 
   18#include <botan/internal/parsing.h> 
   24bool known_pbes_cipher_mode(std::string_view mode) {
 
   25   return (mode == 
"CBC" || mode == 
"GCM" || mode == 
"SIV");
 
   30                                  size_t default_key_size) {
 
   33      size_t iterations = 0;
 
   34      size_t key_length = 0;
 
   53         key_length = default_key_size;
 
   56      const std::string prf = prf_algo.oid().human_name_or_empty();
 
   57      if(prf.empty() || !prf.starts_with(
"HMAC")) {
 
   62      auto pbkdf = pbkdf_fam->from_params(iterations);
 
   65      pbkdf->hash(derived_key, passphrase, salt);
 
   72      size_t key_length = 0;
 
   85         key_length = default_key_size;
 
   91      auto pwdhash = pwdhash_fam->from_params(N, r, p);
 
   92      pwdhash->hash(derived_key, passphrase, salt);
 
   96      throw Decoding_Error(
fmt(
"PBE-PKCS5 v2.0: Unknown KDF algorithm {}", kdf_algo.oid()));
 
  101                                  std::string_view digest,
 
  103                                  size_t* msec_in_iterations_out,
 
  104                                  size_t iterations_if_msec_null,
 
  106                                  bool include_key_length_in_struct,
 
  108   const size_t salt_len = 16;
 
  111   if(digest == 
"Scrypt") {
 
  114      std::unique_ptr<PasswordHash> pwhash;
 
  116      if(msec_in_iterations_out != 
nullptr) {
 
  117         const std::chrono::milliseconds msec(*msec_in_iterations_out);
 
  118         pwhash = pwhash_fam->tune(key_length, msec);
 
  120         pwhash = pwhash_fam->from_iterations(iterations_if_msec_null);
 
  124      pwhash->hash(key, passphrase, salt);
 
  126      const size_t N = pwhash->memory_param();
 
  127      const size_t r = pwhash->iterations();
 
  128      const size_t p = pwhash->parallelism();
 
  130      if(msec_in_iterations_out != 
nullptr) {
 
  131         *msec_in_iterations_out = 0;
 
  134      std::vector<uint8_t> scrypt_params;
 
  141         .
encode_if(include_key_length_in_struct, key_length)
 
  147      const std::string prf = 
fmt(
"HMAC({})", digest);
 
  148      const std::string pbkdf_name = 
fmt(
"PBKDF2({})", prf);
 
  155      std::unique_ptr<PasswordHash> pwhash;
 
  157      if(msec_in_iterations_out != 
nullptr) {
 
  158         const std::chrono::milliseconds msec(*msec_in_iterations_out);
 
  159         pwhash = pwhash_fam->tune(key_length, msec);
 
  161         pwhash = pwhash_fam->from_iterations(iterations_if_msec_null);
 
  165      pwhash->hash(key, passphrase, salt);
 
  167      std::vector<uint8_t> pbkdf2_params;
 
  169      const size_t iterations = pwhash->iterations();
 
  171      if(msec_in_iterations_out != 
nullptr) {
 
  172         *msec_in_iterations_out = iterations;
 
  179         .
encode_if(include_key_length_in_struct, key_length)
 
  191std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbes2_encrypt_shared(std::span<const uint8_t> key_bits,
 
  192                                                                          std::string_view passphrase,
 
  193                                                                          size_t* msec_in_iterations_out,
 
  194                                                                          size_t iterations_if_msec_null,
 
  195                                                                          std::string_view cipher,
 
  196                                                                          std::string_view prf,
 
  200   const auto cipher_spec = 
split_on(cipher, 
'/');
 
  202   if(cipher_spec.size() != 2 || !known_pbes_cipher_mode(cipher_spec[1]) || !enc) {
 
  203      throw Encoding_Error(
fmt(
"PBE-PKCS5 v2.0: Invalid or unavailable cipher '{}'", cipher));
 
  206   const size_t key_length = 
enc->key_spec().maximum_keylength();
 
  212   const bool include_key_length_in_struct = 
enc->key_spec().minimum_keylength() != 
enc->key_spec().maximum_keylength();
 
  214   const auto derived_key = derive_key(passphrase,
 
  217                                       msec_in_iterations_out,
 
  218                                       iterations_if_msec_null,
 
  220                                       include_key_length_in_struct,
 
  223   enc->set_key(derived_key);
 
  228   std::vector<uint8_t> encoded_iv;
 
  231   std::vector<uint8_t> pbes2_params;
 
  240   return std::make_pair(
id, 
unlock(ctext));
 
  245std::pair<AlgorithmIdentifier, std::vector<uint8_t>> 
pbes2_encrypt(std::span<const uint8_t> key_bits,
 
  246                                                                   std::string_view passphrase,
 
  247                                                                   std::chrono::milliseconds msec,
 
  248                                                                   std::string_view cipher,
 
  249                                                                   std::string_view digest,
 
  251   size_t msec_in_iterations_out = 
static_cast<size_t>(msec.count());
 
  252   return pbes2_encrypt_shared(key_bits, passphrase, &msec_in_iterations_out, 0, cipher, digest, rng);
 
 
  256std::pair<AlgorithmIdentifier, std::vector<uint8_t>> 
pbes2_encrypt_msec(std::span<const uint8_t> key_bits,
 
  257                                                                        std::string_view passphrase,
 
  258                                                                        std::chrono::milliseconds msec,
 
  259                                                                        size_t* out_iterations_if_nonnull,
 
  260                                                                        std::string_view cipher,
 
  261                                                                        std::string_view digest,
 
  263   size_t msec_in_iterations_out = 
static_cast<size_t>(msec.count());
 
  265   auto ret = pbes2_encrypt_shared(key_bits, passphrase, &msec_in_iterations_out, 0, cipher, digest, rng);
 
  267   if(out_iterations_if_nonnull != 
nullptr) {
 
  268      *out_iterations_if_nonnull = msec_in_iterations_out;
 
 
  274std::pair<AlgorithmIdentifier, std::vector<uint8_t>> 
pbes2_encrypt_iter(std::span<const uint8_t> key_bits,
 
  275                                                                        std::string_view passphrase,
 
  277                                                                        std::string_view cipher,
 
  278                                                                        std::string_view digest,
 
  280   return pbes2_encrypt_shared(key_bits, passphrase, 
nullptr, pbkdf_iter, cipher, digest, rng);
 
 
  284                                     std::string_view passphrase,
 
  285                                     const std::vector<uint8_t>& params) {
 
  292   const auto cipher_spec = 
split_on(cipher, 
'/');
 
  293   if(cipher_spec.size() != 2 || !known_pbes_cipher_mode(cipher_spec[1])) {
 
  305   dec->set_key(derive_key(passphrase, kdf_algo, dec->key_spec().maximum_keylength()));
 
 
const std::vector< uint8_t > & parameters() const
 
BER_Decoder & decode(bool &out)
 
BER_Decoder & verify_end()
 
BER_Decoder start_sequence()
 
BER_Decoder & decode_optional(T &out, ASN1_Type type_tag, ASN1_Class class_tag, const T &default_value=T())
 
static std::unique_ptr< Cipher_Mode > create(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
 
DER_Encoder & start_sequence()
 
DER_Encoder & encode_if(bool pred, DER_Encoder &enc)
 
DER_Encoder & encode(bool b)
 
std::string human_name_or_empty() const
 
static OID from_string(std::string_view str)
 
static std::unique_ptr< PasswordHashFamily > create_or_throw(std::string_view algo_spec, std::string_view provider="")
 
static std::unique_ptr< PasswordHashFamily > create(std::string_view algo_spec, std::string_view provider="")
 
BOTAN_FORCE_INLINE BOTAN_FN_ISA_AES void enc(uint8x16_t &B, uint8x16_t K)
 
std::string fmt(std::string_view format, const T &... args)
 
std::vector< std::string > split_on(std::string_view str, char delim)
 
std::pair< AlgorithmIdentifier, std::vector< uint8_t > > pbes2_encrypt_iter(std::span< const uint8_t > key_bits, std::string_view passphrase, size_t pbkdf_iter, std::string_view cipher, std::string_view digest, RandomNumberGenerator &rng)
 
secure_vector< uint8_t > pbes2_decrypt(std::span< const uint8_t > key_bits, std::string_view passphrase, const std::vector< uint8_t > ¶ms)
 
std::vector< T > unlock(const secure_vector< T > &in)
 
std::pair< AlgorithmIdentifier, std::vector< uint8_t > > pbes2_encrypt_msec(std::span< const uint8_t > key_bits, std::string_view passphrase, std::chrono::milliseconds msec, size_t *out_iterations_if_nonnull, std::string_view cipher, std::string_view digest, RandomNumberGenerator &rng)
 
std::vector< T, secure_allocator< T > > secure_vector
 
std::pair< AlgorithmIdentifier, std::vector< uint8_t > > pbes2_encrypt(std::span< const uint8_t > key_bits, std::string_view passphrase, std::chrono::milliseconds msec, std::string_view cipher, std::string_view digest, RandomNumberGenerator &rng)