Botan  1.11.15
src/lib/ffi/ffi.cpp
Go to the documentation of this file.
00001 /*
00002 * (C) 2015 Jack Lloyd
00003 *
00004 * Botan is released under the Simplified BSD License (see license.txt)
00005 */
00006 
00007 #include <botan/ffi.h>
00008 #include <botan/system_rng.h>
00009 #include <botan/auto_rng.h>
00010 #include <botan/lookup.h>
00011 #include <botan/aead.h>
00012 #include <botan/hash.h>
00013 #include <botan/mac.h>
00014 #include <botan/pbkdf.h>
00015 #include <botan/version.h>
00016 #include <botan/pubkey.h>
00017 #include <botan/data_src.h>
00018 #include <botan/mem_ops.h>
00019 #include <cstring>
00020 #include <memory>
00021 
00022 #if defined(BOTAN_HAS_RSA)
00023   #include <botan/rsa.h>
00024 #endif
00025 
00026 #if defined(BOTAN_HAS_ECDSA)
00027   #include <botan/ecdsa.h>
00028 #endif
00029 
00030 #if defined(BOTAN_HAS_ECDH)
00031   #include <botan/ecdh.h>
00032 #endif
00033 
00034 #if defined(BOTAN_HAS_CURVE_25519)
00035   #include <botan/curve25519.h>
00036 #endif
00037 
00038 #if defined(BOTAN_HAS_BCRYPT)
00039   #include <botan/bcrypt.h>
00040 #endif
00041 
00042 namespace {
00043 
00044 #define BOTAN_ASSERT_ARG_NON_NULL(p) \
00045    do { if(!p) throw std::invalid_argument("Argument " #p " is null"); } while(0)
00046 
00047 template<typename T, uint32_t MAGIC>
00048 struct botan_struct
00049    {
00050    public:
00051       botan_struct(T* obj) : m_magic(MAGIC), m_obj(obj) {}
00052       ~botan_struct() { m_magic = 0; m_obj.reset(); }
00053 
00054       T* get() const
00055          {
00056          if(m_magic != MAGIC)
00057             throw std::runtime_error("Bad magic " + std::to_string(m_magic) +
00058                                      " in ffi object expected" + std::to_string(MAGIC));
00059          return m_obj.get();
00060          }
00061    private:
00062       uint32_t m_magic = 0;
00063       std::unique_ptr<T> m_obj;
00064    };
00065 
00066 void log_exception(const char* func_name, const char* what)
00067    {
00068    fprintf(stderr, "%s: %s\n", func_name, what);
00069    }
00070 
00071 template<typename T, uint32_t M>
00072 T& safe_get(botan_struct<T,M>* p)
00073    {
00074    if(!p)
00075       throw std::runtime_error("Null pointer argument");
00076    if(T* t = p->get())
00077       return *t;
00078    throw std::runtime_error("Invalid object pointer");
00079    }
00080 
00081 template<typename T, uint32_t M, typename F>
00082 int apply_fn(botan_struct<T, M>* o, const char* func_name, F func)
00083    {
00084    try
00085       {
00086       if(!o)
00087          throw std::runtime_error("Null object to " + std::string(func_name));
00088       if(T* t = o->get())
00089          return func(*t);
00090       }
00091    catch(std::exception& e)
00092       {
00093       log_exception(func_name, e.what());
00094       return -1;
00095       }
00096    catch(...)
00097       {
00098       log_exception(func_name, "unknown exception type");
00099       return -2;
00100       }
00101 
00102    return -1;
00103    }
00104 
00105 inline int write_output(uint8_t out[], size_t* out_len, const uint8_t buf[], size_t buf_len)
00106    {
00107    Botan::clear_mem(out, *out_len);
00108    const size_t avail = *out_len;
00109    *out_len = buf_len;
00110    if(avail >= buf_len)
00111       {
00112       Botan::copy_mem(out, &buf[0], buf_len);
00113       return 0;
00114       }
00115    return -1;
00116    }
00117 
00118 template<typename Alloc>
00119 int write_vec_output(uint8_t out[], size_t* out_len, const std::vector<uint8_t, Alloc>& buf)
00120    {
00121    return write_output(out, out_len, &buf[0], buf.size());
00122    }
00123 
00124 inline int write_str_output(uint8_t out[], size_t* out_len, const std::string& str)
00125    {
00126    return write_output(out, out_len,
00127                        reinterpret_cast<const uint8_t*>(str.c_str()),
00128                        str.size() + 1);
00129    }
00130 
00131 inline int write_str_output(char out[], size_t* out_len, const std::string& str)
00132    {
00133    return write_str_output(reinterpret_cast<uint8_t*>(out), out_len, str);
00134    }
00135 
00136 #define BOTAN_FFI_DO(T, obj, block) apply_fn(obj, BOTAN_CURRENT_FUNCTION, [=](T& obj) { do { block } while(0); return 0; })
00137 
00138 }
00139 
00140 extern "C" {
00141 
00142 struct botan_rng_struct : public botan_struct<Botan::RandomNumberGenerator, 0x4901F9C1>
00143    {
00144    using botan_struct::botan_struct;
00145    };
00146 
00147 struct botan_hash_struct : public botan_struct<Botan::HashFunction, 0x1F0A4F84>
00148    {
00149    using botan_struct::botan_struct;
00150    };
00151 
00152 struct botan_mac_struct : public botan_struct<Botan::MessageAuthenticationCode, 0xA06E8FC1>
00153    {
00154    using botan_struct::botan_struct;
00155    };
00156 
00157 struct botan_cipher_struct : public botan_struct<Botan::Cipher_Mode, 0xB4A2BF9C>
00158    {
00159    using botan_struct::botan_struct;
00160    Botan::secure_vector<uint8_t> m_buf;
00161    };
00162 
00163 struct botan_pubkey_struct : public botan_struct<Botan::Public_Key, 0x2C286519>
00164    {
00165    using botan_struct::botan_struct;
00166    };
00167 
00168 struct botan_privkey_struct : public botan_struct<Botan::Private_Key, 0x7F96385E>
00169    {
00170    using botan_struct::botan_struct;
00171    };
00172 
00173 struct botan_pk_op_encrypt_struct : public botan_struct<Botan::PK_Encryptor, 0x891F3FC3>
00174    {
00175    using botan_struct::botan_struct;
00176    };
00177 
00178 struct botan_pk_op_decrypt_struct : public botan_struct<Botan::PK_Decryptor, 0x912F3C37>
00179    {
00180    using botan_struct::botan_struct;
00181    };
00182 
00183 struct botan_pk_op_sign_struct : public botan_struct<Botan::PK_Signer, 0x1AF0C39F>
00184    {
00185    using botan_struct::botan_struct;
00186    };
00187 
00188 struct botan_pk_op_verify_struct : public botan_struct<Botan::PK_Verifier, 0x2B91F936>
00189    {
00190    using botan_struct::botan_struct;
00191    };
00192 
00193 struct botan_pk_op_ka_struct : public botan_struct<Botan::PK_Key_Agreement, 0x2939CAB1>
00194    {
00195    using botan_struct::botan_struct;
00196    };
00197 
00198 /*
00199 * Versioning
00200 */
00201 uint32_t botan_ffi_api_version()
00202    {
00203    return 20150210; // should match value in info.txt
00204    }
00205 
00206 const char* botan_version_string()
00207    {
00208    return Botan::version_cstr();
00209    }
00210 
00211 uint32_t botan_version_major() { return Botan::version_major(); }
00212 uint32_t botan_version_minor() { return Botan::version_minor(); }
00213 uint32_t botan_version_patch() { return Botan::version_patch(); }
00214 uint32_t botan_version_datestamp()  { return Botan::version_datestamp(); }
00215 
00216 int botan_rng_init(botan_rng_t* rng_out, const char* rng_type)
00217    {
00218    // Just gives unique_ptr something to delete, really
00219    class RNG_Wrapper : public Botan::RandomNumberGenerator
00220       {
00221       public:
00222          RNG_Wrapper(Botan::RandomNumberGenerator& rng) : m_rng(rng) {}
00223          void randomize(Botan::byte out[], size_t len) override { m_rng.randomize(out, len); }
00224          bool is_seeded() const override { return m_rng.is_seeded(); }
00225          void clear() override { m_rng.clear(); }
00226          std::string name() const { return m_rng.name(); }
00227          void reseed(size_t poll_bits = 256) { m_rng.reseed(poll_bits); }
00228          void add_entropy(const Botan::byte in[], size_t len) { m_rng.add_entropy(in, len); }
00229       private:
00230          Botan::RandomNumberGenerator& m_rng;
00231       };
00232 
00233    try
00234       {
00235       BOTAN_ASSERT_ARG_NON_NULL(rng_out);
00236 
00237       if(rng_type == nullptr || *rng_type == 0)
00238          rng_type = "system";
00239 
00240       const std::string rng_type_s(rng_type);
00241 
00242       std::unique_ptr<Botan::RandomNumberGenerator> rng;
00243 
00244       if(rng_type_s == "system")
00245          rng.reset(new RNG_Wrapper(Botan::system_rng()));
00246       else if(rng_type_s == "user")
00247          rng.reset(new Botan::AutoSeeded_RNG);
00248 
00249       if(rng)
00250          {
00251          *rng_out = new botan_rng_struct(rng.release());
00252          return 0;
00253          }
00254       }
00255    catch(std::exception& e)
00256       {
00257       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00258       }
00259    catch(...)
00260       {
00261       log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
00262       }
00263 
00264    return -1;
00265    }
00266 
00267 int botan_rng_destroy(botan_rng_t rng)
00268    {
00269    delete rng;
00270    return 0;
00271    }
00272 
00273 int botan_rng_get(botan_rng_t rng, uint8_t* out, size_t out_len)
00274    {
00275    return BOTAN_FFI_DO(Botan::RandomNumberGenerator, rng, { rng.randomize(out, out_len); });
00276    }
00277 
00278 int botan_rng_reseed(botan_rng_t rng, size_t bits)
00279    {
00280    return BOTAN_FFI_DO(Botan::RandomNumberGenerator, rng, { rng.reseed(bits); });
00281    }
00282 
00283 int botan_hash_init(botan_hash_t* hash, const char* hash_name, uint32_t flags)
00284    {
00285    try
00286       {
00287       if(hash == nullptr || hash_name == nullptr || *hash_name == 0)
00288          return BOTAN_FFI_ERROR_NULL_POINTER;
00289       if(flags != 0)
00290          return BOTAN_FFI_ERROR_BAD_FLAG;
00291 
00292       if(auto h = Botan::get_hash_function(hash_name))
00293          {
00294          *hash = new botan_hash_struct(h);
00295          return 0;
00296          }
00297       }
00298    catch(std::exception& e)
00299       {
00300       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00301       }
00302    catch(...)
00303       {
00304       log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
00305       }
00306 
00307    return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
00308    }
00309 
00310 int botan_hash_destroy(botan_hash_t hash)
00311    {
00312    delete hash;
00313    return 0;
00314    }
00315 
00316 int botan_hash_output_length(botan_hash_t hash, size_t* out)
00317    {
00318    return BOTAN_FFI_DO(Botan::HashFunction, hash, { *out = hash.output_length(); });
00319    }
00320 
00321 int botan_hash_clear(botan_hash_t hash)
00322    {
00323    return BOTAN_FFI_DO(Botan::HashFunction, hash, { hash.clear(); });
00324    }
00325 
00326 int botan_hash_update(botan_hash_t hash, const uint8_t* buf, size_t len)
00327    {
00328    return BOTAN_FFI_DO(Botan::HashFunction, hash, { hash.update(buf, len); });
00329    }
00330 
00331 int botan_hash_final(botan_hash_t hash, uint8_t out[])
00332    {
00333    return BOTAN_FFI_DO(Botan::HashFunction, hash, { hash.final(out); });
00334    }
00335 
00336 int botan_mac_init(botan_mac_t* mac, const char* mac_name, uint32_t flags)
00337    {
00338    try
00339       {
00340       if(!mac || !mac_name || flags != 0)
00341          return -1;
00342 
00343       if(auto m = Botan::get_mac(mac_name))
00344          {
00345          *mac = new botan_mac_struct(m);
00346          return 0;
00347          }
00348       }
00349    catch(std::exception& e)
00350       {
00351       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00352       }
00353    catch(...)
00354       {
00355       log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
00356       }
00357 
00358    return -2;
00359    }
00360 
00361 int botan_mac_destroy(botan_mac_t mac)
00362    {
00363    delete mac;
00364    return 0;
00365    }
00366 
00367 int botan_mac_set_key(botan_mac_t mac, const uint8_t* key, size_t key_len)
00368    {
00369    return BOTAN_FFI_DO(Botan::MessageAuthenticationCode, mac, { mac.set_key(key, key_len); });
00370    }
00371 
00372 int botan_mac_output_length(botan_mac_t mac, size_t* out)
00373    {
00374    return BOTAN_FFI_DO(Botan::MessageAuthenticationCode, mac, { *out = mac.output_length(); });
00375    }
00376 
00377 int botan_mac_clear(botan_mac_t mac)
00378    {
00379    return BOTAN_FFI_DO(Botan::MessageAuthenticationCode, mac, { mac.clear(); });
00380    }
00381 
00382 int botan_mac_update(botan_mac_t mac, const uint8_t* buf, size_t len)
00383    {
00384    return BOTAN_FFI_DO(Botan::MessageAuthenticationCode, mac, { mac.update(buf, len); });
00385    }
00386 
00387 int botan_mac_final(botan_mac_t mac, uint8_t out[])
00388    {
00389    return BOTAN_FFI_DO(Botan::MessageAuthenticationCode, mac, { mac.final(out); });
00390    }
00391 
00392 int botan_cipher_init(botan_cipher_t* cipher, const char* cipher_name, uint32_t flags)
00393    {
00394    try
00395       {
00396       const bool encrypt_p = ((flags & BOTAN_CIPHER_INIT_FLAG_MASK_DIRECTION) == BOTAN_CIPHER_INIT_FLAG_ENCRYPT);
00397       const Botan::Cipher_Dir dir = encrypt_p ? Botan::ENCRYPTION : Botan::DECRYPTION;
00398       std::unique_ptr<Botan::Cipher_Mode> mode(Botan::get_cipher_mode(cipher_name, dir));
00399       if(!mode)
00400          return -1;
00401       *cipher = new botan_cipher_struct(mode.release());
00402       return 0;
00403       }
00404    catch(std::exception& e)
00405       {
00406       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00407       }
00408    catch(...)
00409       {
00410       log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
00411       }
00412 
00413    return -1;
00414    }
00415 
00416 int botan_cipher_destroy(botan_cipher_t cipher)
00417    {
00418    delete cipher;
00419    return 0;
00420    }
00421 
00422 int botan_cipher_clear(botan_cipher_t cipher)
00423    {
00424    return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, { cipher.clear(); });
00425    }
00426 
00427 int botan_cipher_set_key(botan_cipher_t cipher,
00428                          const uint8_t* key, size_t key_len)
00429    {
00430    return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, { cipher.set_key(key, key_len); });
00431    }
00432 
00433 int botan_cipher_start(botan_cipher_t cipher_obj,
00434                        const uint8_t* nonce, size_t nonce_len)
00435    {
00436    try
00437       {
00438       Botan::Cipher_Mode& cipher = safe_get(cipher_obj);
00439       BOTAN_ASSERT(cipher.start(nonce, nonce_len).empty(), "Ciphers have no prefix");
00440       cipher_obj->m_buf.reserve(cipher.update_granularity());
00441       return 0;
00442       }
00443    catch(std::exception& e)
00444       {
00445       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00446       }
00447 
00448    return -1;
00449    }
00450 
00451 int botan_cipher_update(botan_cipher_t cipher_obj,
00452                         uint32_t flags,
00453                         uint8_t output[],
00454                         size_t output_size,
00455                         size_t* output_written,
00456                         const uint8_t input[],
00457                         size_t input_size,
00458                         size_t* input_consumed)
00459    {
00460    using namespace Botan;
00461 
00462    try
00463       {
00464       Cipher_Mode& cipher = safe_get(cipher_obj);
00465       secure_vector<uint8_t>& mbuf = cipher_obj->m_buf;
00466 
00467       const bool final_input = (flags & BOTAN_CIPHER_UPDATE_FLAG_FINAL);
00468 
00469       if(final_input)
00470          {
00471          mbuf.assign(input, input + input_size);
00472          *input_consumed = input_size;
00473          *output_written = 0;
00474 
00475          try
00476             {
00477             cipher.finish(mbuf);
00478             }
00479          catch(Integrity_Failure& e)
00480             {
00481             log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00482             return -2;
00483             }
00484 
00485          *output_written = mbuf.size();
00486 
00487          if(mbuf.size() <= output_size)
00488             {
00489             copy_mem(output, &mbuf[0], mbuf.size());
00490             mbuf.clear();
00491             return 0;
00492             }
00493 
00494          return -1;
00495          }
00496 
00497       if(input_size == 0)
00498          {
00499          // Currently must take entire buffer in this case
00500          *output_written = mbuf.size();
00501          if(output_size >= mbuf.size())
00502             {
00503             copy_mem(output, &mbuf[0], mbuf.size());
00504             mbuf.clear();
00505             return 0;
00506             }
00507 
00508          return -1;
00509          }
00510 
00511       const size_t ud = cipher.update_granularity();
00512       BOTAN_ASSERT(cipher.update_granularity() > cipher.minimum_final_size(), "logic error");
00513 
00514 #if 0
00515       // Avoiding double copy:
00516       if(Online_Cipher_Mode* ocm = dynamic_cast<Online_Cipher_Mode*>(&cipher))
00517          {
00518          const size_t taken = round_down(input_size, ud);
00519          *input_consumed = taken;
00520          *output_size = taken;
00521          copy_mem(&output[0], input, taken);
00522          ocm->update_in_place(output, taken);
00523          return 0;
00524          }
00525 #endif
00526 
00527       mbuf.resize(ud);
00528       size_t taken = 0, written = 0;
00529 
00530       while(input_size >= ud && output_size >= ud)
00531          {
00532          copy_mem(&mbuf[0], input, ud);
00533          cipher.update(mbuf);
00534 
00535          input_size -= ud;
00536          input += ud;
00537          taken += ud;
00538 
00539          output_size -= ud;
00540          output += ud;
00541          written += ud;
00542          }
00543 
00544       *output_written = written;
00545       *input_consumed = taken;
00546 
00547       }
00548    catch(std::exception& e)
00549       {
00550       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00551       }
00552 
00553    return -1;
00554    }
00555 
00556 int botan_cipher_set_associated_data(botan_cipher_t cipher,
00557                                      const uint8_t* ad,
00558                                      size_t ad_len)
00559    {
00560    return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, {
00561       if(Botan::AEAD_Mode* aead = dynamic_cast<Botan::AEAD_Mode*>(&cipher))
00562          {
00563          aead->set_associated_data(ad, ad_len);
00564          return 0;
00565          }
00566       return -1;
00567       });
00568    }
00569 
00570 int botan_cipher_valid_nonce_length(botan_cipher_t cipher, size_t nl)
00571    {
00572    return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, { return cipher.valid_nonce_length(nl) ? 1 : 0; });
00573    }
00574 
00575 int botan_cipher_get_default_nonce_length(botan_cipher_t cipher, size_t* nl)
00576    {
00577    return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, { *nl = cipher.default_nonce_length(); });
00578    }
00579 
00580 int botan_cipher_get_tag_length(botan_cipher_t cipher, size_t* tl)
00581    {
00582    return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, { *tl = cipher.tag_size(); });
00583    }
00584 
00585 int botan_pbkdf(const char* pbkdf_algo, uint8_t out[], size_t out_len,
00586                 const char* pass, const uint8_t salt[], size_t salt_len,
00587                 size_t iterations)
00588    {
00589    try
00590       {
00591       std::unique_ptr<Botan::PBKDF> pbkdf(Botan::get_pbkdf(pbkdf_algo));
00592       pbkdf->pbkdf_iterations(out, out_len, pass, salt, salt_len, iterations);
00593       }
00594    catch(std::exception& e)
00595       {
00596       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00597       }
00598 
00599    return -1;
00600    }
00601 
00602 int botan_pbkdf_timed(const char* pbkdf_algo,
00603                       uint8_t out[], size_t out_len,
00604                       const char* password,
00605                       const uint8_t salt[], size_t salt_len,
00606                       size_t ms_to_run,
00607                       size_t* iterations_used)
00608    {
00609    try
00610       {
00611       std::unique_ptr<Botan::PBKDF> pbkdf(Botan::get_pbkdf(pbkdf_algo));
00612       pbkdf->pbkdf_timed(out, out_len, password, salt, salt_len,
00613                          std::chrono::milliseconds(ms_to_run),
00614                          *iterations_used);
00615       }
00616    catch(std::exception& e)
00617       {
00618       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00619       }
00620 
00621    return -1;
00622    }
00623 
00624 int botan_kdf(const char* kdf_algo,
00625               uint8_t out[], size_t out_len,
00626               const uint8_t secret[], size_t secret_len,
00627               const uint8_t salt[], size_t salt_len)
00628    {
00629    try
00630       {
00631       std::unique_ptr<Botan::KDF> kdf(Botan::get_kdf(kdf_algo));
00632       kdf->kdf(out, out_len, secret, secret_len, salt, salt_len);
00633       }
00634    catch(std::exception& e)
00635       {
00636       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00637       }
00638 
00639    return -1;
00640    }
00641 
00642 #if defined(BOTAN_HAS_BCRYPT)
00643 int botan_bcrypt_generate(uint8_t* out, size_t* out_len,
00644                           const char* pass,
00645                           botan_rng_t rng_obj, size_t wf,
00646                           uint32_t flags)
00647    {
00648    try
00649       {
00650       BOTAN_ASSERT_ARG_NON_NULL(out);
00651       BOTAN_ASSERT_ARG_NON_NULL(out_len);
00652       BOTAN_ASSERT_ARG_NON_NULL(pass);
00653 
00654       if(flags != 0)
00655          return BOTAN_FFI_ERROR_BAD_FLAG;
00656 
00657       if(wf < 2 || wf > 30)
00658          throw std::runtime_error("Bad bcrypt work factor " + std::to_string(wf));
00659 
00660       Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
00661       const std::string bcrypt = Botan::generate_bcrypt(pass, rng, wf);
00662       return write_str_output(out, out_len, bcrypt);
00663       }
00664    catch(std::exception& e)
00665       {
00666       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00667       }
00668    catch(...)
00669       {
00670       log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
00671       }
00672 
00673    return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
00674    }
00675 
00676 int botan_bcrypt_is_valid(const char* pass, const char* hash)
00677    {
00678    try
00679       {
00680       if(Botan::check_bcrypt(pass, hash))
00681          return 0; // success
00682       return 1;
00683       }
00684    catch(std::exception& e)
00685       {
00686       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00687       }
00688    catch(...)
00689       {
00690       log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
00691       }
00692 
00693    return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
00694    }
00695 
00696 #endif
00697 
00698 int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits)
00699    {
00700    try
00701       {
00702       if(key_obj == nullptr || rng_obj == nullptr)
00703          return -1;
00704       if(n_bits < 1024 || n_bits > 16*1024)
00705          return -2;
00706 
00707       *key_obj = nullptr;
00708 
00709 #if defined(BOTAN_HAS_RSA)
00710       Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
00711       std::unique_ptr<Botan::Private_Key> key(new Botan::RSA_PrivateKey(rng, n_bits));
00712       *key_obj = new botan_privkey_struct(key.release());
00713       return 0;
00714 #endif
00715       }
00716    catch(std::exception& e)
00717       {
00718       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00719       }
00720 
00721    return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
00722    }
00723 
00724 
00725 int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str)
00726    {
00727    try
00728       {
00729       if(key_obj == nullptr || rng_obj == nullptr || param_str == nullptr || *param_str == 0)
00730          return -1;
00731 
00732       *key_obj = nullptr;
00733 
00734 #if defined(BOTAN_HAS_ECDSA)
00735       Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
00736       Botan::EC_Group grp(param_str);
00737       std::unique_ptr<Botan::Private_Key> key(new Botan::ECDSA_PrivateKey(rng, grp));
00738       *key_obj = new botan_privkey_struct(key.release());
00739       return 0;
00740 #endif
00741       }
00742    catch(std::exception& e)
00743       {
00744       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00745       }
00746 
00747    return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
00748    }
00749 
00750 int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str)
00751    {
00752    try
00753       {
00754       if(key_obj == nullptr || rng_obj == nullptr || param_str == nullptr || *param_str == 0)
00755          return -1;
00756 
00757       *key_obj = nullptr;
00758 
00759       const std::string params(param_str);
00760 
00761 #if defined(BOTAN_HAS_CURVE_25519)
00762       if(params == "curve25519")
00763          {
00764          std::unique_ptr<Botan::Private_Key> key(new Botan::Curve25519_PrivateKey(safe_get(rng_obj)));
00765          *key_obj = new botan_privkey_struct(key.release());
00766          return 0;
00767          }
00768 #endif
00769 
00770 #if defined(BOTAN_HAS_ECDH)
00771       Botan::EC_Group grp(params);
00772       std::unique_ptr<Botan::Private_Key> key(new Botan::ECDH_PrivateKey(safe_get(rng_obj), grp));
00773       *key_obj = new botan_privkey_struct(key.release());
00774       return 0;
00775 #endif
00776       }
00777    catch(std::exception& e)
00778       {
00779       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00780       }
00781 
00782    return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
00783    }
00784 
00785 int botan_privkey_load(botan_privkey_t* key, botan_rng_t rng_obj,
00786                        const uint8_t bits[], size_t len,
00787                        const char* password)
00788    {
00789    try
00790       {
00791       Botan::DataSource_Memory src(bits, len);
00792 
00793       if(password == nullptr)
00794          password = "";
00795 
00796       Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
00797 
00798       std::unique_ptr<Botan::PKCS8_PrivateKey> pkcs8;
00799       pkcs8.reset(Botan::PKCS8::load_key(src, rng, password));
00800 
00801       if(pkcs8)
00802          {
00803          *key = new botan_privkey_struct(pkcs8.release());
00804          return 0;
00805          }
00806       }
00807    catch(std::exception& e)
00808       {
00809       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00810       }
00811 
00812    return -1;
00813    *key = nullptr;
00814    return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
00815    }
00816 
00817 int botan_privkey_destroy(botan_privkey_t key)
00818    {
00819    delete key;
00820    return 0;
00821    }
00822 
00823 int botan_pubkey_destroy(botan_privkey_t key)
00824    {
00825    delete key;
00826    return 0;
00827    }
00828 
00829 int botan_privkey_export_pubkey(botan_pubkey_t* pubout, botan_privkey_t key_obj)
00830    {
00831    try
00832       {
00833       std::unique_ptr<Botan::Public_Key> pubkey(
00834          Botan::X509::load_key(
00835             Botan::X509::BER_encode(safe_get(key_obj))));
00836       *pubout = new botan_pubkey_struct(pubkey.release());
00837       return 0;
00838       }
00839    catch(std::exception& e)
00840       {
00841       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00842       }
00843 
00844    return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
00845    }
00846 
00847 int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len)
00848    {
00849    return BOTAN_FFI_DO(Botan::Public_Key, key, { return write_str_output(out, out_len, key.algo_name()); });
00850    }
00851 
00852 int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out_len, uint32_t flags)
00853    {
00854    return BOTAN_FFI_DO(Botan::Public_Key, key, {
00855       if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
00856          return write_vec_output(out, out_len, Botan::X509::BER_encode(key));
00857       else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
00858          return write_str_output(out, out_len, Botan::X509::PEM_encode(key));
00859       else
00860          return -2;
00861       });
00862    }
00863 
00864 int botan_privkey_export(botan_privkey_t key, uint8_t out[], size_t* out_len, uint32_t flags)
00865    {
00866    return BOTAN_FFI_DO(Botan::Private_Key, key, {
00867       if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
00868          return write_vec_output(out, out_len, Botan::PKCS8::BER_encode(key));
00869       else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
00870          return write_str_output(out, out_len, Botan::PKCS8::PEM_encode(key));
00871       else
00872          return -2;
00873       });
00874    }
00875 
00876 int botan_privkey_export_encrypted(botan_privkey_t key,
00877                                    uint8_t out[], size_t* out_len,
00878                                    botan_rng_t rng_obj,
00879                                    const char* pass,
00880                                    const char* pbe,
00881                                    uint32_t flags)
00882    {
00883    return BOTAN_FFI_DO(Botan::Private_Key, key, {
00884       auto pbkdf_time = std::chrono::milliseconds(300);
00885       Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
00886 
00887       if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
00888          return write_vec_output(out, out_len, Botan::PKCS8::BER_encode(key, rng, pass, pbkdf_time, pbe));
00889       else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
00890          return write_str_output(out, out_len, Botan::PKCS8::PEM_encode(key, rng, pass, pbkdf_time, pbe));
00891       else
00892          return -2;
00893       });
00894    }
00895 
00896 int botan_pubkey_estimated_strength(botan_pubkey_t key, size_t* estimate)
00897    {
00898    return BOTAN_FFI_DO(Botan::Public_Key, key, { *estimate = key.estimated_strength(); });
00899    }
00900 
00901 int botan_pubkey_fingerprint(botan_pubkey_t key, const char* hash_fn,
00902                              uint8_t out[], size_t* out_len)
00903    {
00904    return BOTAN_FFI_DO(Botan::Public_Key, key, {
00905       std::unique_ptr<Botan::HashFunction> h(Botan::get_hash(hash_fn));
00906       return write_vec_output(out, out_len, h->process(key.x509_subject_public_key()));
00907       });
00908    }
00909 
00910 int botan_pk_op_encrypt_create(botan_pk_op_encrypt_t* op,
00911                                botan_pubkey_t key_obj,
00912                                const char* padding,
00913                                uint32_t flags)
00914    {
00915    try
00916       {
00917       BOTAN_ASSERT_NONNULL(op);
00918 
00919       if(flags != 0)
00920          return BOTAN_FFI_ERROR_BAD_FLAG;
00921 
00922       std::unique_ptr<Botan::PK_Encryptor> pk(new Botan::PK_Encryptor_EME(safe_get(key_obj), padding));
00923       *op = new botan_pk_op_encrypt_struct(pk.release());
00924       return 0;
00925       }
00926    catch(std::exception& e)
00927       {
00928       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00929       }
00930 
00931    return -1;
00932    }
00933 
00934 int botan_pk_op_encrypt_destroy(botan_pk_op_encrypt_t op)
00935    {
00936    delete op;
00937    return 0;
00938    }
00939 
00940 int botan_pk_op_encrypt(botan_pk_op_encrypt_t op,
00941                         botan_rng_t rng_obj,
00942                         uint8_t out[], size_t* out_len,
00943                         const uint8_t plaintext[], size_t plaintext_len)
00944    {
00945    return BOTAN_FFI_DO(Botan::PK_Encryptor, op, {
00946       return write_vec_output(out, out_len, op.encrypt(plaintext, plaintext_len, safe_get(rng_obj)));
00947       });
00948    }
00949 
00950 /*
00951 * Public Key Decryption
00952 */
00953 int botan_pk_op_decrypt_create(botan_pk_op_decrypt_t* op,
00954                                botan_privkey_t key_obj,
00955                                const char* padding,
00956                                uint32_t flags)
00957    {
00958    try
00959       {
00960       BOTAN_ASSERT_NONNULL(op);
00961 
00962       if(flags != 0)
00963          return BOTAN_FFI_ERROR_BAD_FLAG;
00964 
00965       std::unique_ptr<Botan::PK_Decryptor> pk(new Botan::PK_Decryptor_EME(safe_get(key_obj), padding));
00966       *op = new botan_pk_op_decrypt_struct(pk.release());
00967       return 0;
00968       }
00969    catch(std::exception& e)
00970       {
00971       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
00972       }
00973 
00974    return -1;
00975    }
00976 
00977 int botan_pk_op_decrypt_destroy(botan_pk_op_decrypt_t op)
00978    {
00979    delete op;
00980    return 0;
00981    }
00982 
00983 int botan_pk_op_decrypt(botan_pk_op_decrypt_t op,
00984                         uint8_t out[], size_t* out_len,
00985                         uint8_t ciphertext[], size_t ciphertext_len)
00986    {
00987    return BOTAN_FFI_DO(Botan::PK_Decryptor, op, {
00988       return write_vec_output(out, out_len, op.decrypt(ciphertext, ciphertext_len));
00989       });
00990    }
00991 
00992 /*
00993 * Signature Generation
00994 */
00995 int botan_pk_op_sign_create(botan_pk_op_sign_t* op,
00996                             botan_privkey_t key_obj,
00997                             const char* hash,
00998                             uint32_t flags)
00999    {
01000    try
01001       {
01002       BOTAN_ASSERT_NONNULL(op);
01003 
01004       if(flags != 0)
01005          return BOTAN_FFI_ERROR_BAD_FLAG;
01006 
01007       std::unique_ptr<Botan::PK_Signer> pk(new Botan::PK_Signer(safe_get(key_obj), hash));
01008       *op = new botan_pk_op_sign_struct(pk.release());
01009       return 0;
01010       }
01011    catch(std::exception& e)
01012       {
01013       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
01014       }
01015 
01016    return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
01017    }
01018 
01019 int botan_pk_op_sign_destroy(botan_pk_op_sign_t op)
01020    {
01021    delete op;
01022    return 0;
01023    }
01024 
01025 int botan_pk_op_sign_update(botan_pk_op_sign_t op, const uint8_t in[], size_t in_len)
01026    {
01027    return BOTAN_FFI_DO(Botan::PK_Signer, op, { op.update(in, in_len); });
01028    }
01029 
01030 int botan_pk_op_sign_finish(botan_pk_op_sign_t op, botan_rng_t rng_obj, uint8_t out[], size_t* out_len)
01031    {
01032    return BOTAN_FFI_DO(Botan::PK_Signer, op, {
01033       return write_vec_output(out, out_len, op.signature(safe_get(rng_obj)));
01034       });
01035    }
01036 
01037 int botan_pk_op_verify_create(botan_pk_op_verify_t* op,
01038                               botan_pubkey_t key_obj,
01039                               const char* hash,
01040                               uint32_t flags)
01041    {
01042    try
01043       {
01044       BOTAN_ASSERT_NONNULL(op);
01045 
01046       if(flags != 0)
01047          return BOTAN_FFI_ERROR_BAD_FLAG;
01048 
01049       std::unique_ptr<Botan::PK_Verifier> pk(new Botan::PK_Verifier(safe_get(key_obj), hash));
01050       *op = new botan_pk_op_verify_struct(pk.release());
01051       return 0;
01052       }
01053    catch(std::exception& e)
01054       {
01055       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
01056       }
01057 
01058    return -1;
01059    }
01060 
01061 int botan_pk_op_verify_destroy(botan_pk_op_verify_t op)
01062    {
01063    delete op;
01064    return 0;
01065    }
01066 
01067 int botan_pk_op_verify_update(botan_pk_op_verify_t op, const uint8_t in[], size_t in_len)
01068    {
01069    return BOTAN_FFI_DO(Botan::PK_Verifier, op, { op.update(in, in_len); });
01070    }
01071 
01072 int botan_pk_op_verify_finish(botan_pk_op_verify_t op, const uint8_t sig[], size_t sig_len)
01073    {
01074    return BOTAN_FFI_DO(Botan::PK_Verifier, op, {
01075       const bool legit = op.check_signature(sig, sig_len);
01076 
01077       if(legit)
01078          return 0;
01079       else
01080          return 1;
01081       });
01082    }
01083 
01084 int botan_pk_op_key_agreement_create(botan_pk_op_ka_t* op,
01085                                      botan_privkey_t key_obj,
01086                                      const char* kdf,
01087                                      uint32_t flags)
01088    {
01089    try
01090       {
01091       BOTAN_ASSERT_NONNULL(op);
01092 
01093       if(flags != 0)
01094          return BOTAN_FFI_ERROR_BAD_FLAG;
01095 
01096       std::unique_ptr<Botan::PK_Key_Agreement> pk(new Botan::PK_Key_Agreement(safe_get(key_obj), kdf));
01097       *op = new botan_pk_op_ka_struct(pk.release());
01098       return 0;
01099       }
01100    catch(std::exception& e)
01101       {
01102       log_exception(BOTAN_CURRENT_FUNCTION, e.what());
01103       }
01104 
01105    return -1;
01106    }
01107 
01108 int botan_pk_op_key_agreement_destroy(botan_pk_op_ka_t op)
01109    {
01110    delete op;
01111    return 0;
01112    }
01113 
01114 int botan_pk_op_key_agreement_export_public(botan_privkey_t key,
01115                                             uint8_t out[], size_t* out_len)
01116    {
01117    return BOTAN_FFI_DO(Botan::Private_Key, key, {
01118       if(auto kak = dynamic_cast<const Botan::PK_Key_Agreement_Key*>(&key))
01119          return write_vec_output(out, out_len, kak->public_value());
01120       return -2;
01121       });
01122    }
01123 
01124 int botan_pk_op_key_agreement(botan_pk_op_ka_t op,
01125                               uint8_t out[], size_t* out_len,
01126                               const uint8_t other_key[], size_t other_key_len,
01127                               const uint8_t salt[], size_t salt_len)
01128    {
01129    return BOTAN_FFI_DO(Botan::PK_Key_Agreement, op, {
01130       auto k = op.derive_key(*out_len, other_key, other_key_len, salt, salt_len).bits_of();
01131       return write_vec_output(out, out_len, k);
01132       });
01133    }
01134 
01135 }
01136