From d6a7aece0826e0c115eb21912527c77596c1305e Mon Sep 17 00:00:00 2001
From: Sergei Golubchik <serg@mariadb.org>
Date: Mon, 6 Mar 2017 13:06:03 +0100
Subject: [PATCH] my_sha2 service

---
 include/mysql/plugin.h                        |   4 +-
 include/mysql/plugin_audit.h.pp               |  50 +++++++
 include/mysql/plugin_auth.h.pp                |  50 +++++++
 include/mysql/plugin_encryption.h.pp          |  50 +++++++
 include/mysql/plugin_ftparser.h.pp            |  50 +++++++
 include/mysql/plugin_password_validation.h.pp |  50 +++++++
 include/mysql/service_sha2.h                  | 130 ++++++++++++++++++
 include/mysql/services.h                      |   3 +-
 include/service_versions.h                    |   3 +-
 libservices/CMakeLists.txt                    |   1 +
 libservices/HOWTO                             |   4 +-
 libservices/my_sha2_service.c                 |  18 +++
 mysql-test/r/handlersocket.result             |   2 +-
 mysql-test/r/plugin.result                    |   6 +-
 .../plugins/r/cracklib_password_check.result  |   2 +-
 .../suite/plugins/r/show_all_plugins.result   |   4 +-
 .../plugins/r/simple_password_check.result    |   2 +-
 mysys_ssl/CMakeLists.txt                      |  26 ++--
 mysys_ssl/my_sha.ic                           |   4 +-
 mysys_ssl/my_sha224.cc                        |  18 +++
 mysys_ssl/my_sha256.cc                        |  18 +++
 mysys_ssl/my_sha384.cc                        |  18 +++
 mysys_ssl/my_sha512.cc                        |  18 +++
 sql/sql_plugin_services.ic                    |  28 ++++
 24 files changed, 534 insertions(+), 25 deletions(-)
 create mode 100644 include/mysql/service_sha2.h
 create mode 100644 libservices/my_sha2_service.c
 create mode 100644 mysys_ssl/my_sha224.cc
 create mode 100644 mysys_ssl/my_sha256.cc
 create mode 100644 mysys_ssl/my_sha384.cc
 create mode 100644 mysys_ssl/my_sha512.cc

diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h
index b3c71c65488..255d009f029 100644
--- a/include/mysql/plugin.h
+++ b/include/mysql/plugin.h
@@ -1,5 +1,5 @@
 /* Copyright (c) 2005, 2013, Oracle and/or its affiliates
-   Copyright (C) 2009, 2013, Monty Program Ab
+   Copyright (C) 2009, 2017, MariaDB
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -75,7 +75,7 @@ typedef struct st_mysql_xid MYSQL_XID;
 #define MYSQL_PLUGIN_INTERFACE_VERSION 0x0104
 
 /* MariaDB plugin interface version */
-#define MARIA_PLUGIN_INTERFACE_VERSION 0x010b
+#define MARIA_PLUGIN_INTERFACE_VERSION 0x010c
 
 /*
   The allowable types of plugins
diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp
index 24f2c69345d..d69da914215 100644
--- a/include/mysql/plugin_audit.h.pp
+++ b/include/mysql/plugin_audit.h.pp
@@ -98,6 +98,56 @@ extern struct thd_timezone_service_st {
 } *thd_timezone_service;
 my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode);
 void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t);
+extern struct my_sha2_service_st {
+  void (*my_sha224_type)(unsigned char*, const char*, size_t);
+  void (*my_sha224_multi_type)(unsigned char*, ...);
+  size_t (*my_sha224_context_size_type)();
+  void (*my_sha224_init_type)(void *);
+  void (*my_sha224_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha224_result_type)(void *, unsigned char *);
+  void (*my_sha256_type)(unsigned char*, const char*, size_t);
+  void (*my_sha256_multi_type)(unsigned char*, ...);
+  size_t (*my_sha256_context_size_type)();
+  void (*my_sha256_init_type)(void *);
+  void (*my_sha256_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha256_result_type)(void *, unsigned char *);
+  void (*my_sha384_type)(unsigned char*, const char*, size_t);
+  void (*my_sha384_multi_type)(unsigned char*, ...);
+  size_t (*my_sha384_context_size_type)();
+  void (*my_sha384_init_type)(void *);
+  void (*my_sha384_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha384_result_type)(void *, unsigned char *);
+  void (*my_sha512_type)(unsigned char*, const char*, size_t);
+  void (*my_sha512_multi_type)(unsigned char*, ...);
+  size_t (*my_sha512_context_size_type)();
+  void (*my_sha512_init_type)(void *);
+  void (*my_sha512_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha512_result_type)(void *, unsigned char *);
+} *my_sha2_service;
+void my_sha224(unsigned char*, const char*, size_t);
+void my_sha224_multi(unsigned char*, ...);
+size_t my_sha224_context_size();
+void my_sha224_init(void *context);
+void my_sha224_input(void *context, const unsigned char *buf, size_t len);
+void my_sha224_result(void *context, unsigned char *digest);
+void my_sha256(unsigned char*, const char*, size_t);
+void my_sha256_multi(unsigned char*, ...);
+size_t my_sha256_context_size();
+void my_sha256_init(void *context);
+void my_sha256_input(void *context, const unsigned char *buf, size_t len);
+void my_sha256_result(void *context, unsigned char *digest);
+void my_sha384(unsigned char*, const char*, size_t);
+void my_sha384_multi(unsigned char*, ...);
+size_t my_sha384_context_size();
+void my_sha384_init(void *context);
+void my_sha384_input(void *context, const unsigned char *buf, size_t len);
+void my_sha384_result(void *context, unsigned char *digest);
+void my_sha512(unsigned char*, const char*, size_t);
+void my_sha512_multi(unsigned char*, ...);
+size_t my_sha512_context_size();
+void my_sha512_init(void *context);
+void my_sha512_input(void *context, const unsigned char *buf, size_t len);
+void my_sha512_result(void *context, unsigned char *digest);
 extern struct my_sha1_service_st {
   void (*my_sha1_type)(unsigned char*, const char*, size_t);
   void (*my_sha1_multi_type)(unsigned char*, ...);
diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp
index 10cd10bf9c8..274208c177d 100644
--- a/include/mysql/plugin_auth.h.pp
+++ b/include/mysql/plugin_auth.h.pp
@@ -98,6 +98,56 @@ extern struct thd_timezone_service_st {
 } *thd_timezone_service;
 my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode);
 void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t);
+extern struct my_sha2_service_st {
+  void (*my_sha224_type)(unsigned char*, const char*, size_t);
+  void (*my_sha224_multi_type)(unsigned char*, ...);
+  size_t (*my_sha224_context_size_type)();
+  void (*my_sha224_init_type)(void *);
+  void (*my_sha224_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha224_result_type)(void *, unsigned char *);
+  void (*my_sha256_type)(unsigned char*, const char*, size_t);
+  void (*my_sha256_multi_type)(unsigned char*, ...);
+  size_t (*my_sha256_context_size_type)();
+  void (*my_sha256_init_type)(void *);
+  void (*my_sha256_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha256_result_type)(void *, unsigned char *);
+  void (*my_sha384_type)(unsigned char*, const char*, size_t);
+  void (*my_sha384_multi_type)(unsigned char*, ...);
+  size_t (*my_sha384_context_size_type)();
+  void (*my_sha384_init_type)(void *);
+  void (*my_sha384_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha384_result_type)(void *, unsigned char *);
+  void (*my_sha512_type)(unsigned char*, const char*, size_t);
+  void (*my_sha512_multi_type)(unsigned char*, ...);
+  size_t (*my_sha512_context_size_type)();
+  void (*my_sha512_init_type)(void *);
+  void (*my_sha512_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha512_result_type)(void *, unsigned char *);
+} *my_sha2_service;
+void my_sha224(unsigned char*, const char*, size_t);
+void my_sha224_multi(unsigned char*, ...);
+size_t my_sha224_context_size();
+void my_sha224_init(void *context);
+void my_sha224_input(void *context, const unsigned char *buf, size_t len);
+void my_sha224_result(void *context, unsigned char *digest);
+void my_sha256(unsigned char*, const char*, size_t);
+void my_sha256_multi(unsigned char*, ...);
+size_t my_sha256_context_size();
+void my_sha256_init(void *context);
+void my_sha256_input(void *context, const unsigned char *buf, size_t len);
+void my_sha256_result(void *context, unsigned char *digest);
+void my_sha384(unsigned char*, const char*, size_t);
+void my_sha384_multi(unsigned char*, ...);
+size_t my_sha384_context_size();
+void my_sha384_init(void *context);
+void my_sha384_input(void *context, const unsigned char *buf, size_t len);
+void my_sha384_result(void *context, unsigned char *digest);
+void my_sha512(unsigned char*, const char*, size_t);
+void my_sha512_multi(unsigned char*, ...);
+size_t my_sha512_context_size();
+void my_sha512_init(void *context);
+void my_sha512_input(void *context, const unsigned char *buf, size_t len);
+void my_sha512_result(void *context, unsigned char *digest);
 extern struct my_sha1_service_st {
   void (*my_sha1_type)(unsigned char*, const char*, size_t);
   void (*my_sha1_multi_type)(unsigned char*, ...);
diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp
index 46d3c3d5a55..604f5386f7d 100644
--- a/include/mysql/plugin_encryption.h.pp
+++ b/include/mysql/plugin_encryption.h.pp
@@ -98,6 +98,56 @@ extern struct thd_timezone_service_st {
 } *thd_timezone_service;
 my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode);
 void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t);
+extern struct my_sha2_service_st {
+  void (*my_sha224_type)(unsigned char*, const char*, size_t);
+  void (*my_sha224_multi_type)(unsigned char*, ...);
+  size_t (*my_sha224_context_size_type)();
+  void (*my_sha224_init_type)(void *);
+  void (*my_sha224_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha224_result_type)(void *, unsigned char *);
+  void (*my_sha256_type)(unsigned char*, const char*, size_t);
+  void (*my_sha256_multi_type)(unsigned char*, ...);
+  size_t (*my_sha256_context_size_type)();
+  void (*my_sha256_init_type)(void *);
+  void (*my_sha256_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha256_result_type)(void *, unsigned char *);
+  void (*my_sha384_type)(unsigned char*, const char*, size_t);
+  void (*my_sha384_multi_type)(unsigned char*, ...);
+  size_t (*my_sha384_context_size_type)();
+  void (*my_sha384_init_type)(void *);
+  void (*my_sha384_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha384_result_type)(void *, unsigned char *);
+  void (*my_sha512_type)(unsigned char*, const char*, size_t);
+  void (*my_sha512_multi_type)(unsigned char*, ...);
+  size_t (*my_sha512_context_size_type)();
+  void (*my_sha512_init_type)(void *);
+  void (*my_sha512_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha512_result_type)(void *, unsigned char *);
+} *my_sha2_service;
+void my_sha224(unsigned char*, const char*, size_t);
+void my_sha224_multi(unsigned char*, ...);
+size_t my_sha224_context_size();
+void my_sha224_init(void *context);
+void my_sha224_input(void *context, const unsigned char *buf, size_t len);
+void my_sha224_result(void *context, unsigned char *digest);
+void my_sha256(unsigned char*, const char*, size_t);
+void my_sha256_multi(unsigned char*, ...);
+size_t my_sha256_context_size();
+void my_sha256_init(void *context);
+void my_sha256_input(void *context, const unsigned char *buf, size_t len);
+void my_sha256_result(void *context, unsigned char *digest);
+void my_sha384(unsigned char*, const char*, size_t);
+void my_sha384_multi(unsigned char*, ...);
+size_t my_sha384_context_size();
+void my_sha384_init(void *context);
+void my_sha384_input(void *context, const unsigned char *buf, size_t len);
+void my_sha384_result(void *context, unsigned char *digest);
+void my_sha512(unsigned char*, const char*, size_t);
+void my_sha512_multi(unsigned char*, ...);
+size_t my_sha512_context_size();
+void my_sha512_init(void *context);
+void my_sha512_input(void *context, const unsigned char *buf, size_t len);
+void my_sha512_result(void *context, unsigned char *digest);
 extern struct my_sha1_service_st {
   void (*my_sha1_type)(unsigned char*, const char*, size_t);
   void (*my_sha1_multi_type)(unsigned char*, ...);
diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp
index 17de800875e..b11ced22a96 100644
--- a/include/mysql/plugin_ftparser.h.pp
+++ b/include/mysql/plugin_ftparser.h.pp
@@ -98,6 +98,56 @@ extern struct thd_timezone_service_st {
 } *thd_timezone_service;
 my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode);
 void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t);
+extern struct my_sha2_service_st {
+  void (*my_sha224_type)(unsigned char*, const char*, size_t);
+  void (*my_sha224_multi_type)(unsigned char*, ...);
+  size_t (*my_sha224_context_size_type)();
+  void (*my_sha224_init_type)(void *);
+  void (*my_sha224_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha224_result_type)(void *, unsigned char *);
+  void (*my_sha256_type)(unsigned char*, const char*, size_t);
+  void (*my_sha256_multi_type)(unsigned char*, ...);
+  size_t (*my_sha256_context_size_type)();
+  void (*my_sha256_init_type)(void *);
+  void (*my_sha256_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha256_result_type)(void *, unsigned char *);
+  void (*my_sha384_type)(unsigned char*, const char*, size_t);
+  void (*my_sha384_multi_type)(unsigned char*, ...);
+  size_t (*my_sha384_context_size_type)();
+  void (*my_sha384_init_type)(void *);
+  void (*my_sha384_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha384_result_type)(void *, unsigned char *);
+  void (*my_sha512_type)(unsigned char*, const char*, size_t);
+  void (*my_sha512_multi_type)(unsigned char*, ...);
+  size_t (*my_sha512_context_size_type)();
+  void (*my_sha512_init_type)(void *);
+  void (*my_sha512_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha512_result_type)(void *, unsigned char *);
+} *my_sha2_service;
+void my_sha224(unsigned char*, const char*, size_t);
+void my_sha224_multi(unsigned char*, ...);
+size_t my_sha224_context_size();
+void my_sha224_init(void *context);
+void my_sha224_input(void *context, const unsigned char *buf, size_t len);
+void my_sha224_result(void *context, unsigned char *digest);
+void my_sha256(unsigned char*, const char*, size_t);
+void my_sha256_multi(unsigned char*, ...);
+size_t my_sha256_context_size();
+void my_sha256_init(void *context);
+void my_sha256_input(void *context, const unsigned char *buf, size_t len);
+void my_sha256_result(void *context, unsigned char *digest);
+void my_sha384(unsigned char*, const char*, size_t);
+void my_sha384_multi(unsigned char*, ...);
+size_t my_sha384_context_size();
+void my_sha384_init(void *context);
+void my_sha384_input(void *context, const unsigned char *buf, size_t len);
+void my_sha384_result(void *context, unsigned char *digest);
+void my_sha512(unsigned char*, const char*, size_t);
+void my_sha512_multi(unsigned char*, ...);
+size_t my_sha512_context_size();
+void my_sha512_init(void *context);
+void my_sha512_input(void *context, const unsigned char *buf, size_t len);
+void my_sha512_result(void *context, unsigned char *digest);
 extern struct my_sha1_service_st {
   void (*my_sha1_type)(unsigned char*, const char*, size_t);
   void (*my_sha1_multi_type)(unsigned char*, ...);
diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp
index 1abdbd30f57..ecadc9440b0 100644
--- a/include/mysql/plugin_password_validation.h.pp
+++ b/include/mysql/plugin_password_validation.h.pp
@@ -98,6 +98,56 @@ extern struct thd_timezone_service_st {
 } *thd_timezone_service;
 my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode);
 void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t);
+extern struct my_sha2_service_st {
+  void (*my_sha224_type)(unsigned char*, const char*, size_t);
+  void (*my_sha224_multi_type)(unsigned char*, ...);
+  size_t (*my_sha224_context_size_type)();
+  void (*my_sha224_init_type)(void *);
+  void (*my_sha224_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha224_result_type)(void *, unsigned char *);
+  void (*my_sha256_type)(unsigned char*, const char*, size_t);
+  void (*my_sha256_multi_type)(unsigned char*, ...);
+  size_t (*my_sha256_context_size_type)();
+  void (*my_sha256_init_type)(void *);
+  void (*my_sha256_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha256_result_type)(void *, unsigned char *);
+  void (*my_sha384_type)(unsigned char*, const char*, size_t);
+  void (*my_sha384_multi_type)(unsigned char*, ...);
+  size_t (*my_sha384_context_size_type)();
+  void (*my_sha384_init_type)(void *);
+  void (*my_sha384_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha384_result_type)(void *, unsigned char *);
+  void (*my_sha512_type)(unsigned char*, const char*, size_t);
+  void (*my_sha512_multi_type)(unsigned char*, ...);
+  size_t (*my_sha512_context_size_type)();
+  void (*my_sha512_init_type)(void *);
+  void (*my_sha512_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha512_result_type)(void *, unsigned char *);
+} *my_sha2_service;
+void my_sha224(unsigned char*, const char*, size_t);
+void my_sha224_multi(unsigned char*, ...);
+size_t my_sha224_context_size();
+void my_sha224_init(void *context);
+void my_sha224_input(void *context, const unsigned char *buf, size_t len);
+void my_sha224_result(void *context, unsigned char *digest);
+void my_sha256(unsigned char*, const char*, size_t);
+void my_sha256_multi(unsigned char*, ...);
+size_t my_sha256_context_size();
+void my_sha256_init(void *context);
+void my_sha256_input(void *context, const unsigned char *buf, size_t len);
+void my_sha256_result(void *context, unsigned char *digest);
+void my_sha384(unsigned char*, const char*, size_t);
+void my_sha384_multi(unsigned char*, ...);
+size_t my_sha384_context_size();
+void my_sha384_init(void *context);
+void my_sha384_input(void *context, const unsigned char *buf, size_t len);
+void my_sha384_result(void *context, unsigned char *digest);
+void my_sha512(unsigned char*, const char*, size_t);
+void my_sha512_multi(unsigned char*, ...);
+size_t my_sha512_context_size();
+void my_sha512_init(void *context);
+void my_sha512_input(void *context, const unsigned char *buf, size_t len);
+void my_sha512_result(void *context, unsigned char *digest);
 extern struct my_sha1_service_st {
   void (*my_sha1_type)(unsigned char*, const char*, size_t);
   void (*my_sha1_multi_type)(unsigned char*, ...);
diff --git a/include/mysql/service_sha2.h b/include/mysql/service_sha2.h
new file mode 100644
index 00000000000..ee4975f7f24
--- /dev/null
+++ b/include/mysql/service_sha2.h
@@ -0,0 +1,130 @@
+#ifndef MYSQL_SERVICE_SHA2_INCLUDED
+/* Copyright (c) 2017, MariaDB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
+
+/**
+  @file
+  my sha2 service
+
+  Functions to calculate SHA2 hash from a memory buffer
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef MYSQL_ABI_CHECK
+#include <stdlib.h>
+#endif
+
+extern struct my_sha2_service_st {
+  void (*my_sha224_type)(unsigned char*, const char*, size_t);
+  void (*my_sha224_multi_type)(unsigned char*, ...);
+  size_t (*my_sha224_context_size_type)();
+  void (*my_sha224_init_type)(void *);
+  void (*my_sha224_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha224_result_type)(void *, unsigned char *);
+
+  void (*my_sha256_type)(unsigned char*, const char*, size_t);
+  void (*my_sha256_multi_type)(unsigned char*, ...);
+  size_t (*my_sha256_context_size_type)();
+  void (*my_sha256_init_type)(void *);
+  void (*my_sha256_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha256_result_type)(void *, unsigned char *);
+
+  void (*my_sha384_type)(unsigned char*, const char*, size_t);
+  void (*my_sha384_multi_type)(unsigned char*, ...);
+  size_t (*my_sha384_context_size_type)();
+  void (*my_sha384_init_type)(void *);
+  void (*my_sha384_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha384_result_type)(void *, unsigned char *);
+
+  void (*my_sha512_type)(unsigned char*, const char*, size_t);
+  void (*my_sha512_multi_type)(unsigned char*, ...);
+  size_t (*my_sha512_context_size_type)();
+  void (*my_sha512_init_type)(void *);
+  void (*my_sha512_input_type)(void *, const unsigned char *, size_t);
+  void (*my_sha512_result_type)(void *, unsigned char *);
+} *my_sha2_service;
+
+#ifdef MYSQL_DYNAMIC_PLUGIN
+
+#define my_sha224(A,B,C) my_sha2_service->my_sha224_type(A,B,C)
+#define my_sha224_multi my_sha2_service->my_sha224_multi_type
+#define my_sha224_context_size() my_sha2_service->my_sha224_context_size_type()
+#define my_sha224_init(A) my_sha2_service->my_sha224_init_type(A)
+#define my_sha224_input(A,B,C) my_sha2_service->my_sha224_input_type(A,B,C)
+#define my_sha224_result(A,B) my_sha2_service->my_sha224_result_type(A,B)
+
+#define my_sha256(A,B,C) my_sha2_service->my_sha256_type(A,B,C)
+#define my_sha256_multi my_sha2_service->my_sha256_multi_type
+#define my_sha256_context_size() my_sha2_service->my_sha256_context_size_type()
+#define my_sha256_init(A) my_sha2_service->my_sha256_init_type(A)
+#define my_sha256_input(A,B,C) my_sha2_service->my_sha256_input_type(A,B,C)
+#define my_sha256_result(A,B) my_sha2_service->my_sha256_result_type(A,B)
+
+#define my_sha384(A,B,C) my_sha2_service->my_sha384_type(A,B,C)
+#define my_sha384_multi my_sha2_service->my_sha384_multi_type
+#define my_sha384_context_size() my_sha2_service->my_sha384_context_size_type()
+#define my_sha384_init(A) my_sha2_service->my_sha384_init_type(A)
+#define my_sha384_input(A,B,C) my_sha2_service->my_sha384_input_type(A,B,C)
+#define my_sha384_result(A,B) my_sha2_service->my_sha384_result_type(A,B)
+
+#define my_sha512(A,B,C) my_sha2_service->my_sha512_type(A,B,C)
+#define my_sha512_multi my_sha2_service->my_sha512_multi_type
+#define my_sha512_context_size() my_sha2_service->my_sha512_context_size_type()
+#define my_sha512_init(A) my_sha2_service->my_sha512_init_type(A)
+#define my_sha512_input(A,B,C) my_sha2_service->my_sha512_input_type(A,B,C)
+#define my_sha512_result(A,B) my_sha2_service->my_sha512_result_type(A,B)
+
+#else
+
+void my_sha224(unsigned char*, const char*, size_t);
+void my_sha224_multi(unsigned char*, ...);
+size_t my_sha224_context_size();
+void my_sha224_init(void *context);
+void my_sha224_input(void *context, const unsigned char *buf, size_t len);
+void my_sha224_result(void *context, unsigned char *digest);
+
+void my_sha256(unsigned char*, const char*, size_t);
+void my_sha256_multi(unsigned char*, ...);
+size_t my_sha256_context_size();
+void my_sha256_init(void *context);
+void my_sha256_input(void *context, const unsigned char *buf, size_t len);
+void my_sha256_result(void *context, unsigned char *digest);
+
+void my_sha384(unsigned char*, const char*, size_t);
+void my_sha384_multi(unsigned char*, ...);
+size_t my_sha384_context_size();
+void my_sha384_init(void *context);
+void my_sha384_input(void *context, const unsigned char *buf, size_t len);
+void my_sha384_result(void *context, unsigned char *digest);
+
+void my_sha512(unsigned char*, const char*, size_t);
+void my_sha512_multi(unsigned char*, ...);
+size_t my_sha512_context_size();
+void my_sha512_init(void *context);
+void my_sha512_input(void *context, const unsigned char *buf, size_t len);
+void my_sha512_result(void *context, unsigned char *digest);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define MYSQL_SERVICE_SHA2_INCLUDED
+#endif
+
diff --git a/include/mysql/services.h b/include/mysql/services.h
index 9d031a9b094..89c177ce7ad 100644
--- a/include/mysql/services.h
+++ b/include/mysql/services.h
@@ -1,6 +1,6 @@
 #ifndef MYSQL_SERVICES_INCLUDED
 /* Copyright (c) 2009, 2010, Oracle and/or its affiliates.
-   Copyright (c) 2012, 2013, Monty Program Ab
+   Copyright (c) 2012, 2017, MariaDB
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@ extern "C" {
 #include <mysql/service_debug_sync.h>
 #include <mysql/service_kill_statement.h>
 #include <mysql/service_thd_timezone.h>
+#include <mysql/service_sha2.h>
 #include <mysql/service_sha1.h>
 #include <mysql/service_md5.h>
 #include <mysql/service_logger.h>
diff --git a/include/service_versions.h b/include/service_versions.h
index 0f0990d43b3..9b333127858 100644
--- a/include/service_versions.h
+++ b/include/service_versions.h
@@ -1,5 +1,5 @@
 /* Copyright (c) 2009, 2010, Oracle and/or its affiliates.
-   Copyright (c) 2012, 2013, Monty Program Ab
+   Copyright (c) 2012, 2017, MariaDB
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
 #define VERSION_thd_wait                0x0100
 #define VERSION_progress_report         0x0100
 #define VERSION_thd_timezone            0x0100
+#define VERSION_my_sha2                 0x0100
 #define VERSION_my_sha1                 0x0101
 #define VERSION_my_md5                  0x0100
 #define VERSION_wsrep                   0x0201
diff --git a/libservices/CMakeLists.txt b/libservices/CMakeLists.txt
index 62181a00aa2..66ceb3087de 100644
--- a/libservices/CMakeLists.txt
+++ b/libservices/CMakeLists.txt
@@ -25,6 +25,7 @@ SET(MYSQLSERVICES_SOURCES
   thd_specifics_service.c
   progress_report_service.c
   debug_sync_service.c
+  my_sha2_service.c
   my_sha1_service.c
   my_md5_service.c
   wsrep_service.c
diff --git a/libservices/HOWTO b/libservices/HOWTO
index 69d96f8aa25..6a581bf22e2 100644
--- a/libservices/HOWTO
+++ b/libservices/HOWTO
@@ -74,7 +74,7 @@ it should also declare all the accompanying data structures, as necessary
     #define VERSION_foo 0x0100
 ==================================================================
 
-6. create a new file libservices/foo_service.h using the following template:
+6. create a new file libservices/foo_service.c using the following template:
 ==================================================================
   /* GPL header */
   #include <service_versions.h>
@@ -82,7 +82,7 @@ it should also declare all the accompanying data structures, as necessary
 ==================================================================
 
 7. add the new file to libservices/CMakeLists.txt (MYSQLSERVICES_SOURCES)
-8. Add all new files to repository (bzr add)
+8. Add all new files to repository (git add)
 9. and finally, register your service for dynamic linking in
     sql/sql_plugin_services.ic as follows:
 9.1 fill in the service structure:
diff --git a/libservices/my_sha2_service.c b/libservices/my_sha2_service.c
new file mode 100644
index 00000000000..aa174e7d1f0
--- /dev/null
+++ b/libservices/my_sha2_service.c
@@ -0,0 +1,18 @@
+/* Copyright (c) 2017 MariaDB
+   Use is subject to license terms.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
+
+#include <service_versions.h>
+SERVICE_VERSION my_sha2_service= (void*)VERSION_my_sha2;
diff --git a/mysql-test/r/handlersocket.result b/mysql-test/r/handlersocket.result
index e38de6bf5c2..26c77813b26 100644
--- a/mysql-test/r/handlersocket.result
+++ b/mysql-test/r/handlersocket.result
@@ -5,7 +5,7 @@ plugin_version	1.0
 plugin_status	ACTIVE
 plugin_type	DAEMON
 plugin_library	handlersocket.so
-plugin_library_version	1.11
+plugin_library_version	1.12
 plugin_author	higuchi dot akira at dena dot jp
 plugin_description	Direct access into InnoDB
 plugin_license	BSD
diff --git a/mysql-test/r/plugin.result b/mysql-test/r/plugin.result
index c23c4f2d8a2..f278724cc9a 100644
--- a/mysql-test/r/plugin.result
+++ b/mysql-test/r/plugin.result
@@ -12,7 +12,7 @@ PLUGIN_STATUS	ACTIVE
 PLUGIN_TYPE	STORAGE ENGINE
 PLUGIN_TYPE_VERSION	#
 PLUGIN_LIBRARY	ha_example.so
-PLUGIN_LIBRARY_VERSION	1.11
+PLUGIN_LIBRARY_VERSION	1.12
 PLUGIN_AUTHOR	Brian Aker, MySQL AB
 PLUGIN_DESCRIPTION	Example storage engine
 PLUGIN_LICENSE	GPL
@@ -25,7 +25,7 @@ PLUGIN_STATUS	ACTIVE
 PLUGIN_TYPE	DAEMON
 PLUGIN_TYPE_VERSION	#
 PLUGIN_LIBRARY	ha_example.so
-PLUGIN_LIBRARY_VERSION	1.11
+PLUGIN_LIBRARY_VERSION	1.12
 PLUGIN_AUTHOR	Sergei Golubchik
 PLUGIN_DESCRIPTION	Unusable Daemon
 PLUGIN_LICENSE	GPL
@@ -64,7 +64,7 @@ PLUGIN_STATUS	DELETED
 PLUGIN_TYPE	STORAGE ENGINE
 PLUGIN_TYPE_VERSION	#
 PLUGIN_LIBRARY	ha_example.so
-PLUGIN_LIBRARY_VERSION	1.11
+PLUGIN_LIBRARY_VERSION	1.12
 PLUGIN_AUTHOR	Brian Aker, MySQL AB
 PLUGIN_DESCRIPTION	Example storage engine
 PLUGIN_LICENSE	GPL
diff --git a/mysql-test/suite/plugins/r/cracklib_password_check.result b/mysql-test/suite/plugins/r/cracklib_password_check.result
index 158a7501240..479b4b00698 100644
--- a/mysql-test/suite/plugins/r/cracklib_password_check.result
+++ b/mysql-test/suite/plugins/r/cracklib_password_check.result
@@ -6,7 +6,7 @@ PLUGIN_STATUS	ACTIVE
 PLUGIN_TYPE	PASSWORD VALIDATION
 PLUGIN_TYPE_VERSION	1.0
 PLUGIN_LIBRARY	cracklib_password_check.so
-PLUGIN_LIBRARY_VERSION	1.11
+PLUGIN_LIBRARY_VERSION	1.12
 PLUGIN_AUTHOR	Sergei Golubchik
 PLUGIN_DESCRIPTION	Password validation via CrackLib
 PLUGIN_LICENSE	GPL
diff --git a/mysql-test/suite/plugins/r/show_all_plugins.result b/mysql-test/suite/plugins/r/show_all_plugins.result
index 623e8e9314b..c91a360d1d7 100644
--- a/mysql-test/suite/plugins/r/show_all_plugins.result
+++ b/mysql-test/suite/plugins/r/show_all_plugins.result
@@ -4,8 +4,8 @@ Variable_name	Value
 Opened_plugin_libraries	0
 select * from information_schema.all_plugins where plugin_library='ha_example.so';
 PLUGIN_NAME	PLUGIN_VERSION	PLUGIN_STATUS	PLUGIN_TYPE	PLUGIN_TYPE_VERSION	PLUGIN_LIBRARY	PLUGIN_LIBRARY_VERSION	PLUGIN_AUTHOR	PLUGIN_DESCRIPTION	PLUGIN_LICENSE	LOAD_OPTION	PLUGIN_MATURITY	PLUGIN_AUTH_VERSION
-EXAMPLE	0.1	NOT INSTALLED	STORAGE ENGINE	MYSQL_VERSION_ID	ha_example.so	1.11	Brian Aker, MySQL AB	Example storage engine	GPL	OFF	Experimental	0.1
-UNUSABLE	3.14	NOT INSTALLED	DAEMON	MYSQL_VERSION_ID	ha_example.so	1.11	Sergei Golubchik	Unusable Daemon	GPL	OFF	Experimental	3.14.15.926
+EXAMPLE	0.1	NOT INSTALLED	STORAGE ENGINE	MYSQL_VERSION_ID	ha_example.so	1.12	Brian Aker, MySQL AB	Example storage engine	GPL	OFF	Experimental	0.1
+UNUSABLE	3.14	NOT INSTALLED	DAEMON	MYSQL_VERSION_ID	ha_example.so	1.12	Sergei Golubchik	Unusable Daemon	GPL	OFF	Experimental	3.14.15.926
 show status like '%libraries%';
 Variable_name	Value
 Opened_plugin_libraries	1
diff --git a/mysql-test/suite/plugins/r/simple_password_check.result b/mysql-test/suite/plugins/r/simple_password_check.result
index 015a26adc87..11385bd6b01 100644
--- a/mysql-test/suite/plugins/r/simple_password_check.result
+++ b/mysql-test/suite/plugins/r/simple_password_check.result
@@ -6,7 +6,7 @@ PLUGIN_STATUS	ACTIVE
 PLUGIN_TYPE	PASSWORD VALIDATION
 PLUGIN_TYPE_VERSION	1.0
 PLUGIN_LIBRARY	simple_password_check.so
-PLUGIN_LIBRARY_VERSION	1.11
+PLUGIN_LIBRARY_VERSION	1.12
 PLUGIN_AUTHOR	Sergei Golubchik
 PLUGIN_DESCRIPTION	Simple password strength checks
 PLUGIN_LICENSE	GPL
diff --git a/mysys_ssl/CMakeLists.txt b/mysys_ssl/CMakeLists.txt
index b00213bc492..7251d8777f8 100644
--- a/mysys_ssl/CMakeLists.txt
+++ b/mysys_ssl/CMakeLists.txt
@@ -21,24 +21,30 @@ IF(SSL_DEFINES)
 ADD_DEFINITIONS(${SSL_DEFINES})
 ENDIF()
 
+SET(MYSYS_SSL_HIDDEN_SOURCES
+    my_sha1.cc
+    my_sha224.cc
+    my_sha256.cc
+    my_sha384.cc
+    my_sha512.cc
+    my_sha2.cc
+    my_md5.cc
+   )
+
+SET(MYSYS_SSL_SOURCES
+    ${MYSYS_SSL_HIDDEN_SOURCES}
+    my_crypt.cc
+   )
+
 # We do RESTRICT_SYMBOL_EXPORTS(yassl) elsewhere.
 # In order to get correct symbol visibility, these files
 # must be compiled with "-fvisibility=hidden"
 IF(WITH_SSL STREQUAL "bundled" AND HAVE_VISIBILITY_HIDDEN)
   SET_SOURCE_FILES_PROPERTIES(
-    my_md5.cc
-    my_sha1.cc
-    my_sha2.cc
+    ${MYSYS_SSL_HIDDEN_SOURCES}
     PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
 ENDIF()
 
-SET(MYSYS_SSL_SOURCES
-    my_sha1.cc
-    my_sha2.cc
-    my_md5.cc
-    my_crypt.cc
-   )
-
 ADD_CONVENIENCE_LIBRARY(mysys_ssl ${MYSYS_SSL_SOURCES})
 TARGET_LINK_LIBRARIES(mysys_ssl dbug strings ${SSL_LIBRARIES})
 DTRACE_INSTRUMENT(mysys_ssl)
diff --git a/mysys_ssl/my_sha.ic b/mysys_ssl/my_sha.ic
index 5a95c9c4682..a7ec8bad593 100644
--- a/mysys_ssl/my_sha.ic
+++ b/mysys_ssl/my_sha.ic
@@ -26,7 +26,7 @@
 #include <my_global.h>
 #include <stdarg.h>
 
-#define HASH_SIZE 20
+#define HASH_SIZE (NUM > 1 ? NUM/8 : 20)
 
 #if defined(HAVE_YASSL)
 #include "sha.hpp"
@@ -66,6 +66,8 @@ static void sha_result(CONTEXT *context, uchar digest[HASH_SIZE])
 #define yCONTEXT(y)     xCONTEXT(y)
 #define CONTEXT         yCONTEXT(NUM)
 #define SHA1_CTX        SHA_CTX
+#define SHA224_CTX      SHA256_CTX
+#define SHA384_CTX      SHA512_CTX
 
 #define xSHA_Init(x)    SHA ## x ## _Init
 #define xSHA_Update(x)  SHA ## x ## _Update
diff --git a/mysys_ssl/my_sha224.cc b/mysys_ssl/my_sha224.cc
new file mode 100644
index 00000000000..7e8b481256b
--- /dev/null
+++ b/mysys_ssl/my_sha224.cc
@@ -0,0 +1,18 @@
+/* Copyright (c) 2017, MariaDB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#define NUM 224
+
+#include "my_sha.ic"
diff --git a/mysys_ssl/my_sha256.cc b/mysys_ssl/my_sha256.cc
new file mode 100644
index 00000000000..8c1a4662009
--- /dev/null
+++ b/mysys_ssl/my_sha256.cc
@@ -0,0 +1,18 @@
+/* Copyright (c) 2017, MariaDB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#define NUM 256
+
+#include "my_sha.ic"
diff --git a/mysys_ssl/my_sha384.cc b/mysys_ssl/my_sha384.cc
new file mode 100644
index 00000000000..3bad6b39248
--- /dev/null
+++ b/mysys_ssl/my_sha384.cc
@@ -0,0 +1,18 @@
+/* Copyright (c) 2017, MariaDB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#define NUM 384
+
+#include "my_sha.ic"
diff --git a/mysys_ssl/my_sha512.cc b/mysys_ssl/my_sha512.cc
new file mode 100644
index 00000000000..8077efd3b57
--- /dev/null
+++ b/mysys_ssl/my_sha512.cc
@@ -0,0 +1,18 @@
+/* Copyright (c) 2017, MariaDB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
+
+#define NUM 512
+
+#include "my_sha.ic"
diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic
index c3dfde18ab6..e4a9732e888 100644
--- a/sql/sql_plugin_services.ic
+++ b/sql/sql_plugin_services.ic
@@ -60,6 +60,33 @@ static struct thd_timezone_service_st thd_timezone_handler= {
   thd_gmt_sec_to_TIME
 };
 
+static struct my_sha2_service_st my_sha2_handler = {
+  my_sha224,
+  my_sha224_multi,
+  my_sha224_context_size,
+  my_sha224_init,
+  my_sha224_input,
+  my_sha224_result,
+  my_sha256,
+  my_sha256_multi,
+  my_sha256_context_size,
+  my_sha256_init,
+  my_sha256_input,
+  my_sha256_result,
+  my_sha384,
+  my_sha384_multi,
+  my_sha384_context_size,
+  my_sha384_init,
+  my_sha384_input,
+  my_sha384_result,
+  my_sha512,
+  my_sha512_multi,
+  my_sha512_context_size,
+  my_sha512_init,
+  my_sha512_input,
+  my_sha512_result,
+};
+
 static struct my_sha1_service_st my_sha1_handler = {
   my_sha1,
   my_sha1_multi,
@@ -164,6 +191,7 @@ static struct st_service_ref list_of_services[]=
   { "debug_sync_service",          VERSION_debug_sync,          0 }, // updated in plugin_init()
   { "thd_kill_statement_service",  VERSION_kill_statement,      &thd_kill_statement_handler },
   { "thd_timezone_service",        VERSION_thd_timezone,        &thd_timezone_handler },
+  { "my_sha2_service",             VERSION_my_sha2,             &my_sha2_handler},
   { "my_sha1_service",             VERSION_my_sha1,             &my_sha1_handler},
   { "my_md5_service",              VERSION_my_md5,              &my_md5_handler},
   { "logger_service",              VERSION_logger,              &logger_service_handler },
-- 
2.30.9