Skip to content

Instantly share code, notes, and snippets.

@gaurav36
Last active July 19, 2018 11:54
Show Gist options
  • Save gaurav36/ced2e5d985f5691db2da21b5ee15f8f7 to your computer and use it in GitHub Desktop.
Save gaurav36/ced2e5d985f5691db2da21b5ee15f8f7 to your computer and use it in GitHub Desktop.
own key generation for keyring file plugin in mysql-server
diff --git a/plugin/keyring/CMakeLists.txt b/plugin/keyring/CMakeLists.txt
index d098f27..dc24720 100644
--- a/plugin/keyring/CMakeLists.txt
+++ b/plugin/keyring/CMakeLists.txt
@@ -24,6 +24,7 @@ INCLUDE(${MYSQL_CMAKE_SCRIPT_DIR}/compile_flags.cmake)
ADD_DEFINITIONS(-DLOG_COMPONENT_TAG="keyring_file")
+set (CMAKE_CXX_FLAGS "-lcurl")
SET (KEYRING_FILE_SOURCES
common/keyring_key.cc
common/keys_container.cc
diff --git a/plugin/keyring/common/keyring_impl.cc b/plugin/keyring/common/keyring_impl.cc
index 5de31ad..b6cbdb6 100644
--- a/plugin/keyring/common/keyring_impl.cc
+++ b/plugin/keyring/common/keyring_impl.cc
@@ -188,7 +188,6 @@ bool mysql_key_store(std::unique_ptr<IKey> key_to_store) {
if (check_key_for_writing(key_to_store.get(), "storing")) return true;
- if (key_to_store->get_key_data_size() > 0) key_to_store->xor_data();
mysql_rwlock_wrlock(&LOCK_keyring);
if (keys->store_key(key_to_store.get())) {
mysql_rwlock_unlock(&LOCK_keyring);
diff --git a/plugin/keyring/keyring.cc b/plugin/keyring/keyring.cc
index 995c67f..244828d 100644
--- a/plugin/keyring/keyring.cc
+++ b/plugin/keyring/keyring.cc
@@ -27,6 +27,7 @@
#include <mysql/components/my_service.h>
#include <mysql/components/services/log_builtins.h>
+#include <curl/curl.h>
#include "my_compiler.h"
#include "my_inttypes.h"
#include "my_io.h"
@@ -180,6 +181,62 @@ static bool mysql_key_remove(const char *key_id, const char *user_id) {
return mysql_key_remove<keyring::Key>(key_id, user_id, "keyring_file");
}
+struct key_data {
+ char *master_key;
+ size_t len;
+};
+
+size_t writefunc(char *ptr, size_t size, size_t nmemb, struct key_data *s)
+{
+ s->master_key=ptr;
+ return size*nmemb;
+}
+
+char * get_secret_from_server()
+{
+
+ CURL *curl;
+ CURLcode res;
+
+ struct key_data s;
+ // get a curl handle /
+ curl = curl_easy_init();
+ if(curl) {
+ // First set the URL that is about to receive our POST. This URL can
+ // just as well be a https:// URL if that is what should receive the
+ // data.
+ curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:8189");
+
+ // Now specify the POST data
+ curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
+
+ curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, writefunc);
+
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
+
+ // Perform the request, res will get the return code /
+ res = curl_easy_perform(curl);
+
+ // Check for errors
+ if(res != CURLE_OK)
+ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
+
+ //cleaning up
+ curl_easy_cleanup(curl);
+ }
+
+ char *dummy_key = s.master_key;
+ return dummy_key;
+}
+
+
static bool mysql_key_generate(const char *key_id, const char *key_type,
const char *user_id, size_t key_len) {
try {
@@ -189,9 +246,12 @@ static bool mysql_key_generate(const char *key_id, const char *key_type,
std::unique_ptr<uchar[]> key(new uchar[key_len]);
if (key.get() == NULL) return true;
memset(key.get(), 0, key_len);
+
+ char *secret_key = get_secret_from_server();
+
if (is_keys_container_initialized == false ||
check_key_for_writing(key_candidate.get(), "generating") ||
- my_rand_buffer(key.get(), key_len))
+ !memcpy (key.get(), secret_key, strlen(secret_key)+1))
return true;
return mysql_key_store(key_id, key_type, user_id, key.get(), key_len) ==
@gaurav36
Copy link
Author

gaurav36 commented Jul 19, 2018

When user apply this patch then user will be able to store their own master key which is coming from http server.

More information can be found on my blog

When InnoDB request keyring plugin for new key generation (it request for new key generation only in two cases: when you install keyring file plugin first time or when you rotate master key) then keyring file plugin execute

// file: mysql-server/plugin/keyring/keyring.cc
static bool mysql_key_generate(const char *key_id, const char *key_type,
                                                   const char *user_id, size_t key_len) {

here in this function, it execute my_rand_buffer(key.get(), key_len)) for getting random byte. after successfully getting random byte it store the key by executing " return mysql_key_store(key_id, key_type, user_id, key.get(), key_len) == true " function.

mysql_key_store (file: mysql-server/plugin/keyring/common/keyring_impl.cc ) basically recompute the key by xor operation
if (key_to_store->get_key_data_size() > 0) key_to_store->xor_data();

it execute following code (file: mysql-server/plugin/keyring/common/keyring_key.cc)

void Key::xor_data() {
  if (key == NULL) return;
  static const char *obfuscate_str = "*305=Ljt0*!@$Hnm(*-9-w;:";
  for (uint i = 0, l = 0; i < key_len;
       ++i, l = ((l + 1) % strlen(obfuscate_str)))
    key.get()[i] ^= obfuscate_str[l];
}

**what i have done in above patch is:

  1. getting the key from secure http server (currently i am getting it from "http://localhost:8189") and
  2. removing xor logic (re-computation)**

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment