3921 Nirbhay Choubey 2012-02-17
WL#6008 : Replace custom encryption code with approved
encryption packages
added:
sql/md5.cc
sql/sha1.cc
modified:
include/my_md5.h
include/sha1.h
libmysql/CMakeLists.txt
mysys/CMakeLists.txt
mysys/md5.c
mysys/sha1.c
sql/CMakeLists.txt
sql/item_strfunc.cc
sql/password.c
sql/table.cc
3920 Marko Mäkelä 2012-02-17 [merge]
Merge mysql-5.5 to mysql-trunk.
added:
mysql-test/suite/innodb/r/innodb-blob.result
mysql-test/suite/innodb/t/innodb-blob.test
modified:
storage/innobase/btr/btr0btr.cc
storage/innobase/btr/btr0cur.cc
storage/innobase/buf/buf0dblwr.cc
storage/innobase/fsp/fsp0fsp.cc
storage/innobase/ibuf/ibuf0ibuf.cc
storage/innobase/include/btr0btr.h
storage/innobase/include/btr0cur.h
storage/innobase/include/btr0cur.ic
storage/innobase/include/fsp0fsp.h
storage/innobase/include/mtr0mtr.h
storage/innobase/include/mtr0mtr.ic
storage/innobase/include/trx0rec.ic
storage/innobase/include/trx0undo.h
storage/innobase/mtr/mtr0mtr.cc
storage/innobase/row/row0ins.cc
storage/innobase/row/row0upd.cc
storage/innobase/trx/trx0rec.cc
storage/innobase/trx/trx0undo.cc
=== modified file 'include/my_md5.h'
--- a/include/my_md5.h 2009-09-23 21:32:31 +0000
+++ b/include/my_md5.h 2012-02-17 10:30:31 +0000
@@ -22,6 +22,36 @@
* $FreeBSD: src/contrib/cvs/lib/md5.h,v 1.2 1999/12/11 15:10:02 peter Exp $
*/
+#if defined(HAVE_YASSL) || defined(HAVE_OPENSSL)
+/*
+ Use MD5 implementation provided by the SSL libraries.
+*/
+
+#if defined(HAVE_YASSL)
+
+C_MODE_START
+
+void my_md5_hash(char *digest, const char *buf, int len);
+
+C_MODE_END
+
+#else /* HAVE_YASSL */
+
+#include <openssl/md5.h>
+
+#define MY_MD5_HASH(digest, buf, len) \
+do { \
+ MD5_CTX ctx; \
+ MD5_Init (&ctx); \
+ MD5_Update (&ctx, buf, len); \
+ MD5_Final (digest, &ctx); \
+} while (0)
+
+#endif /* HAVE_YASSL */
+
+#else /* HAVE_YASSL || HAVE_OPENSSL */
+/* Fallback to the MySQL's implementation. */
+
/* Unlike previous versions of this code, uint32 need not be exactly
32 bits, merely 32 bits or more. Choosing a data type which is 32
bits instead of 64 is not important; speed is considerably more
@@ -35,18 +65,15 @@ typedef struct {
unsigned char in[64];
} my_MD5Context;
-#ifdef __cplusplus
-extern "C" {
-#endif
+C_MODE_START
+
void my_MD5Init (my_MD5Context *context);
void my_MD5Update (my_MD5Context *context,
unsigned char const *buf, unsigned len);
void my_MD5Final (unsigned char digest[16],
my_MD5Context *context);
-#ifdef __cplusplus
-}
-#endif
+C_MODE_END
#define MY_MD5_HASH(digest,buf,len) \
do { \
@@ -56,4 +83,12 @@ do { \
my_MD5Final (digest, &ctx); \
} while (0)
-#endif /* MY_MD__INCLUDED */
+#endif /* defined(HAVE_YASSL) || defined(HAVE_OPENSSL) */
+
+C_MODE_START
+
+void compute_md5_hash(char *digest, const char *buf, int len);
+
+C_MODE_END
+
+#endif /* MY_MD5_INCLUDED */
=== modified file 'include/sha1.h'
--- a/include/sha1.h 2011-06-30 15:46:53 +0000
+++ b/include/sha1.h 2012-02-17 10:30:31 +0000
@@ -64,6 +64,28 @@
Internet Society.
*/
+#define SHA1_HASH_SIZE 20 /* Hash size in bytes */
+
+/*
+ Use SHA1 implementation provided by the SSL libraries if available.
+*/
+
+#if defined(HAVE_YASSL)
+
+C_MODE_START
+
+void mysql_sha1_yassl(uint8 *digest, const char *buf, int len);
+void mysql_sha1_multi_yassl(uint8 *digest, const char *buf1, int len1,
+ const char *buf2, int len2);
+
+C_MODE_END
+
+#elif defined(HAVE_OPENSSL)
+
+#include <openssl/sha.h>
+#define SHA1_CONTEXT SHA_CTX
+
+# else
enum sha_result_codes
{
@@ -73,8 +95,6 @@ enum sha_result_codes
SHA_STATE_ERROR /* called Input after Result */
};
-#define SHA1_HASH_SIZE 20 /* Hash size in bytes */
-
/*
This structure will hold context information for the SHA-1
hashing operation
@@ -90,8 +110,11 @@ typedef struct SHA1_CONTEXT
uint8 Message_Block[64]; /* 512-bit message blocks */
} SHA1_CONTEXT;
+#endif /* HAVE_YASSL */
+
+#ifndef HAVE_YASSL
/*
- Function Prototypes
+ Function Prototypes (shared by MySQL & OpenSSL's SHA1 implementation )
*/
C_MODE_START
@@ -102,4 +125,14 @@ int mysql_sha1_result(SHA1_CONTEXT* , ui
C_MODE_END
-#endif /* SHA__INCLUDED */
+#endif /* HAVE_YASSL */
+
+C_MODE_START
+
+void compute_sha1_hash(uint8 *digest, const char *buf, int len);
+void compute_sha1_hash_multi(uint8 *digest, const char *buf1, int len1,
+ const char *buf2, int len2);
+
+C_MODE_END
+
+#endif /* SHA1_INCLUDED */
=== modified file 'libmysql/CMakeLists.txt'
--- a/libmysql/CMakeLists.txt 2012-02-16 10:52:45 +0000
+++ b/libmysql/CMakeLists.txt 2012-02-17 10:30:31 +0000
@@ -145,6 +145,8 @@ SET(CLIENT_SOURCES
../sql-common/client_plugin.c
../sql/net_serv.cc
../sql-common/pack.c
+ ../sql/md5.cc
+ ../sql/sha1.cc
../sql/password.c
../sql/my_rnd.cc
)
=== modified file 'mysys/CMakeLists.txt'
--- a/mysys/CMakeLists.txt 2011-10-11 04:27:52 +0000
+++ b/mysys/CMakeLists.txt 2012-02-17 10:30:31 +0000
@@ -15,6 +15,10 @@
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/mysys)
+IF(SSL_DEFINES)
+ADD_DEFINITIONS(${SSL_DEFINES})
+ENDIF()
+
SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c
errors.c hash.c list.c md5.c mf_cache.c mf_dirname.c mf_fn_ext.c
mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c
=== modified file 'mysys/md5.c'
--- a/mysys/md5.c 2009-03-09 18:57:03 +0000
+++ b/mysys/md5.c 2012-02-17 10:30:31 +0000
@@ -38,6 +38,11 @@
copyright in any changes I have made; this code remains in the
public domain. */
+/*
+ Skip entirely if built with OpenSSL/YaSSL support.
+*/
+#if !defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
+
#include <my_global.h>
#include <m_string.h>
#include "my_md5.h"
@@ -323,3 +328,5 @@ main (int argc, char **argv)
return 0;
}
#endif /* TEST */
+
+#endif /* !defined(HAVE_OPENSSL) && !defined(HAVE_YASSL) */
=== modified file 'mysys/sha1.c'
--- a/mysys/sha1.c 2011-06-30 15:50:45 +0000
+++ b/mysys/sha1.c 2012-02-17 10:30:31 +0000
@@ -84,6 +84,41 @@
#include "sha1.h"
/*
+ Skip entire file if built with YaSSL.
+*/
+#ifndef HAVE_YASSL
+
+#ifdef HAVE_OPENSSL
+
+/*
+ Wrapper for OpenSSL SH1 methods.
+*/
+
+int mysql_sha1_reset(SHA1_CONTEXT *context)
+{
+ return SHA1_Init(context);
+}
+
+
+int mysql_sha1_input(SHA1_CONTEXT *context, const uint8 *message_array,
+ unsigned length)
+{
+ return SHA1_Update(context, message_array, length);
+}
+
+
+int mysql_sha1_result(SHA1_CONTEXT *context,
+ uint8 Message_Digest[SHA1_HASH_SIZE])
+{
+ return SHA1_Final(Message_Digest, context);
+}
+
+#else /* HAVE_OPENSSL */
+/*
+ Native MySQL SHA1 implementation.
+*/
+
+/*
Define the SHA1 circular left shift macro
*/
@@ -420,3 +455,6 @@ static void SHA1PadMessage(SHA1_CONTEXT
SHA1ProcessMessageBlock(context);
}
+#endif /* HAVE_OPENSSL */
+
+#endif /* HAVE_YASSL */
=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt 2012-02-16 10:52:45 +0000
+++ b/sql/CMakeLists.txt 2012-02-17 10:30:31 +0000
@@ -69,6 +69,7 @@ SET(SQL_SHARED_SOURCES
keycaches.cc
lock.cc
log.cc
+ md5.cc
mdl.cc
mf_iocache.cc
my_decimal.cc
@@ -88,6 +89,7 @@ SET(SQL_SHARED_SOURCES
rpl_handler.cc
scheduler.cc
set_var.cc
+ sha1.cc
sha2.cc
signal_handler.cc
sp.cc
=== modified file 'sql/item_strfunc.cc'
--- a/sql/item_strfunc.cc 2012-02-16 09:51:14 +0000
+++ b/sql/item_strfunc.cc 2012-02-17 10:30:31 +0000
@@ -181,7 +181,7 @@ String *Item_func_md5::val_str_ascii(Str
uchar digest[16];
null_value=0;
- MY_MD5_HASH(digest,(uchar *) sptr->ptr(), sptr->length());
+ compute_md5_hash((char *) digest, (const char *) sptr->ptr(), sptr->length());
if (str->alloc(32)) // Ensure that memory is free
{
null_value=1;
@@ -217,16 +217,11 @@ String *Item_func_sha::val_str_ascii(Str
str->set_charset(&my_charset_bin);
if (sptr) /* If we got value different from NULL */
{
- SHA1_CONTEXT context; /* Context used to generate SHA1 hash */
/* Temporary buffer to store 160bit digest */
uint8 digest[SHA1_HASH_SIZE];
- mysql_sha1_reset(&context); /* We do not have to check for error here */
- /* No need to check error as the only case would be too long message */
- mysql_sha1_input(&context,
- (const uchar *) sptr->ptr(), sptr->length());
- /* Ensure that memory is free and we got result */
- if (!( str->alloc(SHA1_HASH_SIZE*2) ||
- (mysql_sha1_result(&context,digest))))
+ compute_sha1_hash(digest, (const char *) sptr->ptr(), sptr->length());
+ /* Ensure that memory is free */
+ if (!(str->alloc(SHA1_HASH_SIZE * 2)))
{
array_to_hex((char *) str->ptr(), digest, SHA1_HASH_SIZE);
str->length((uint) SHA1_HASH_SIZE*2);
=== added file 'sql/md5.cc'
--- a/sql/md5.cc 1970-01-01 00:00:00 +0000
+++ b/sql/md5.cc 2012-02-17 10:30:31 +0000
@@ -0,0 +1,68 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+ 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 */
+
+
+/**
+ @file
+
+ @brief
+ Wrapper functions for OpenSSL, YaSSL and MySQL's MD5
+ implementations. Also provides a Compatibility layer
+ to make available YaSSL's MD5 implementation.
+*/
+
+#include <my_global.h>
+#include <my_md5.h>
+
+#ifdef HAVE_YASSL
+
+#include "md5.hpp"
+
+/**
+ Compute MD5 message digest.
+
+ @param digest [out] Computed MD5 digest
+ @param buf [in] Message to be computed
+ @param len [in] Length of the message
+
+ @return void
+*/
+void my_md5_hash(char *digest, const char *buf, int len)
+{
+ TaoCrypt::MD5 hasher;
+ hasher.Update((TaoCrypt::byte *) buf, len);
+ hasher.Final((TaoCrypt::byte *) digest);
+}
+#endif /* HAVE_YASSL */
+
+
+/**
+ Wrapper function to compute MD5 message digest.
+
+ @param digest [out] Computed MD5 digest
+ @param buf [in] Message to be computed
+ @param len [in] Length of the message
+
+ @return void
+*/
+void compute_md5_hash(char *digest, const char *buf, int len)
+{
+#ifdef HAVE_YASSL
+ my_md5_hash(digest, buf, len);
+#else
+ MY_MD5_HASH((unsigned char *) digest, (unsigned char const *) buf, len);
+#endif /* HAVE_YASSL */
+}
+
=== modified file 'sql/password.c'
--- a/sql/password.c 2012-02-16 10:52:45 +0000
+++ b/sql/password.c 2012-02-17 10:30:31 +0000
@@ -399,6 +399,29 @@ my_crypt(char *to, const uchar *s1, cons
*to++= *s1++ ^ *s2++;
}
+/**
+ Compute two stage SHA1 hash of the password :
+
+ hash_stage1=sha1("password")
+ hash_stage2=sha1(hash_stage1)
+
+ @param password [IN] Password string.
+ @param pass_len [IN] Length of the password.
+ @param hash_stage1 [OUT] sha1(password)
+ @param hash_stage2 [OUT] sha1(hash_stage1)
+*/
+
+inline static
+void compute_two_stage_sha1_hash(const char *password, size_t pass_len,
+ uint8 *hash_stage1, uint8 *hash_stage2)
+{
+ /* Stage 1: hash password */
+ compute_sha1_hash(hash_stage1, password, pass_len);
+
+ /* Stage 2 : hash first stage's output. */
+ compute_sha1_hash(hash_stage2, (const char *) hash_stage1, SHA1_HASH_SIZE);
+}
+
/*
MySQL 4.1.1 password hashing: SHA conversion (see RFC 2289, 3174) twice
@@ -416,18 +439,11 @@ my_crypt(char *to, const uchar *s1, cons
void my_make_scrambled_password(char *to, const char *password,
size_t pass_len)
{
- SHA1_CONTEXT sha1_context;
uint8 hash_stage2[SHA1_HASH_SIZE];
- mysql_sha1_reset(&sha1_context);
- /* stage 1: hash password */
- mysql_sha1_input(&sha1_context, (uint8 *) password, (uint) pass_len);
- mysql_sha1_result(&sha1_context, (uint8 *) to);
- /* stage 2: hash stage1 output */
- mysql_sha1_reset(&sha1_context);
- mysql_sha1_input(&sha1_context, (uint8 *) to, SHA1_HASH_SIZE);
- /* separate buffer is used to pass 'to' in octet2hex */
- mysql_sha1_result(&sha1_context, hash_stage2);
+ /* Two stage SHA1 hash of the password. */
+ compute_two_stage_sha1_hash(password, pass_len, (uint8 *) to, hash_stage2);
+
/* convert hash_stage2 to hex string */
*to++= PVERSION41_CHAR;
octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE);
@@ -471,24 +487,16 @@ void make_scrambled_password(char *to, c
void
scramble(char *to, const char *message, const char *password)
{
- SHA1_CONTEXT sha1_context;
uint8 hash_stage1[SHA1_HASH_SIZE];
uint8 hash_stage2[SHA1_HASH_SIZE];
- mysql_sha1_reset(&sha1_context);
- /* stage 1: hash password */
- mysql_sha1_input(&sha1_context, (uint8 *) password, (uint) strlen(password));
- mysql_sha1_result(&sha1_context, hash_stage1);
- /* stage 2: hash stage 1; note that hash_stage2 is stored in the database */
- mysql_sha1_reset(&sha1_context);
- mysql_sha1_input(&sha1_context, hash_stage1, SHA1_HASH_SIZE);
- mysql_sha1_result(&sha1_context, hash_stage2);
+ /* Two stage SHA1 hash of the password. */
+ compute_two_stage_sha1_hash(password, strlen(password), hash_stage1,
+ hash_stage2);
+
/* create crypt string as sha1(message, hash_stage2) */;
- mysql_sha1_reset(&sha1_context);
- mysql_sha1_input(&sha1_context, (const uint8 *) message, SCRAMBLE_LENGTH);
- mysql_sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
- /* xor allows 'from' and 'to' overlap: lets take advantage of it */
- mysql_sha1_result(&sha1_context, (uint8 *) to);
+ compute_sha1_hash_multi((uint8 *) to, message, SCRAMBLE_LENGTH,
+ (const char *) hash_stage2, SHA1_HASH_SIZE);
my_crypt(to, (const uchar *) to, hash_stage1, SCRAMBLE_LENGTH);
}
@@ -517,21 +525,18 @@ my_bool
check_scramble(const uchar *scramble_arg, const char *message,
const uint8 *hash_stage2)
{
- SHA1_CONTEXT sha1_context;
uint8 buf[SHA1_HASH_SIZE];
uint8 hash_stage2_reassured[SHA1_HASH_SIZE];
- mysql_sha1_reset(&sha1_context);
/* create key to encrypt scramble */
- mysql_sha1_input(&sha1_context, (const uint8 *) message, SCRAMBLE_LENGTH);
- mysql_sha1_input(&sha1_context, hash_stage2, SHA1_HASH_SIZE);
- mysql_sha1_result(&sha1_context, buf);
+ compute_sha1_hash_multi(buf, message, SCRAMBLE_LENGTH,
+ (const char *) hash_stage2, SHA1_HASH_SIZE);
/* encrypt scramble */
- my_crypt((char *) buf, buf, scramble_arg, SCRAMBLE_LENGTH);
+ my_crypt((char *) buf, buf, scramble_arg, SCRAMBLE_LENGTH);
+
/* now buf supposedly contains hash_stage1: so we can get hash_stage2 */
- mysql_sha1_reset(&sha1_context);
- mysql_sha1_input(&sha1_context, buf, SHA1_HASH_SIZE);
- mysql_sha1_result(&sha1_context, hash_stage2_reassured);
+ compute_sha1_hash(hash_stage2_reassured, (const char *) buf, SHA1_HASH_SIZE);
+
return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE);
}
=== added file 'sql/sha1.cc'
--- a/sql/sha1.cc 1970-01-01 00:00:00 +0000
+++ b/sql/sha1.cc 2012-02-17 10:30:31 +0000
@@ -0,0 +1,121 @@
+/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+
+ 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 */
+
+
+/**
+ @file
+
+ @brief
+ Wrapper functions for OpenSSL, YaSSL and MySQL's SHA1
+ implementations. Also provides a Compatibility layer
+ to make available YaSSL's SHA1 implementation.
+*/
+
+#include <my_global.h>
+#include <sha1.h>
+
+#ifdef HAVE_YASSL
+#include "sha.hpp"
+
+/**
+ Compute SHA1 message digest using YaSSL.
+
+ @param digest [out] Computed SHA1 digest
+ @param buf [in] Message to be computed
+ @param len [in] Length of the message
+
+ @return void
+*/
+void mysql_sha1_yassl(uint8 *digest, const char *buf, int len)
+{
+ TaoCrypt::SHA hasher;
+ hasher.Update((const TaoCrypt::byte *) buf, len);
+ hasher.Final ((TaoCrypt::byte *) digest);
+}
+
+/**
+ Compute SHA1 message digest for two messages in order to
+ emulate sha1(msg1, msg2) using YaSSL.
+
+ @param digest [out] Computed SHA1 digest
+ @param buf1 [in] First message
+ @param len1 [in] Length of first message
+ @param buf2 [in] Second message
+ @param len2 [in] Length of second message
+
+ @return void
+*/
+void mysql_sha1_multi_yassl(uint8 *digest, const char *buf1, int len1,
+ const char *buf2, int len2)
+{
+ TaoCrypt::SHA hasher;
+ hasher.Update((const TaoCrypt::byte *) buf1, len1);
+ hasher.Update((const TaoCrypt::byte *) buf2, len2);
+ hasher.Final((TaoCrypt::byte *) digest);
+}
+
+#endif /* HAVE_YASSL */
+
+
+/**
+ Wrapper function to compute SHA1 message digest.
+
+ @param digest [out] Computed SHA1 digest
+ @param buf [in] Message to be computed
+ @param len [in] Length of the message
+
+ @return void
+*/
+void compute_sha1_hash(uint8 *digest, const char *buf, int len)
+{
+#ifdef HAVE_YASSL
+ mysql_sha1_yassl(digest, buf, len);
+#else
+ SHA1_CONTEXT sha1_context;
+
+ mysql_sha1_reset(&sha1_context);
+ mysql_sha1_input(&sha1_context, (const uint8 *) buf, len);
+ mysql_sha1_result(&sha1_context, digest);
+#endif /* HAVE_YASSL */
+}
+
+
+/**
+ Wrapper function to compute SHA1 message digest for
+ two messages in order to emulate sha1(msg1, msg2).
+
+ @param digest [out] Computed SHA1 digest
+ @param buf1 [in] First message
+ @param len1 [in] Length of first message
+ @param buf2 [in] Second message
+ @param len2 [in] Length of second message
+
+ @return void
+*/
+void compute_sha1_hash_multi(uint8 *digest, const char *buf1, int len1,
+ const char *buf2, int len2)
+{
+#ifdef HAVE_YASSL
+ mysql_sha1_multi_yassl(digest, buf1, len1, buf2, len2);
+#else
+ SHA1_CONTEXT sha1_context;
+
+ mysql_sha1_reset(&sha1_context);
+ mysql_sha1_input(&sha1_context, (const uint8 *) buf1, len1);
+ mysql_sha1_input(&sha1_context, (const uint8 *) buf2, len2);
+ mysql_sha1_result(&sha1_context, digest);
+#endif /* HAVE_YASSL */
+}
+
=== modified file 'sql/table.cc'
--- a/sql/table.cc 2012-02-02 13:44:26 +0000
+++ b/sql/table.cc 2012-02-17 10:30:31 +0000
@@ -3532,7 +3532,8 @@ void TABLE::reset_item_list(List<Item> *
void TABLE_LIST::calc_md5(char *buffer)
{
uchar digest[16];
- MY_MD5_HASH(digest, (uchar *) select_stmt.str, select_stmt.length);
+ compute_md5_hash((char *) digest, (const char *) select_stmt.str,
+ select_stmt.length);
sprintf((char *) buffer,
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[0], digest[1], digest[2], digest[3],
No bundle (reason: useless for push emails).| Thread |
|---|
| • bzr push into mysql-trunk branch (nirbhay.choubey:3920 to 3921) WL#6008 | Nirbhay Choubey | 20 Feb |