Botan
1.11.15
|
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