* FILE: sha2.cpp
* AUTHOR: Aaron D. Gifford <me@aarongifford.com>
*
* Copyright (c) 2000-2001, Aaron D. Gifford
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $From: sha2.cpp,v 1.1 2001/11/08 00:01:51 adg Exp adg $
*
*/
#include "postgres_fe.h"
#ifndef FRONTEND_PARSER
#endif
#include <sys/param.h>
#include "libpq/sha2.h"
#include "openssl/evp.h"
#include "cipher.h"
* You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
* loop version for the hash transform rounds (defined using macros
* later in this file). Either define on the command line, for example:
*
* cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
*
* or define below:
*
* #define SHA2_UNROLL_TRANSFORM
*
*/
#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
#ifndef WORDS_BIGENDIAN
#define REVERSE32(w, x) \
{ \
uint32 tmp = (w); \
tmp = (tmp >> 16) | (tmp << 16); \
(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
}
#define REVERSE64(w, x) \
{ \
uint64 tmp = (w); \
tmp = (tmp >> 32) | (tmp << 32); \
tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | ((tmp & 0x0000ffff0000ffffULL) << 16); \
}
#endif
* Macro for incrementally adding the unsigned 64-bit integer n to the
* unsigned 128-bit integer (represented using a two-element array of
* 64-bit words):
*/
#define ADDINC128(w, n) \
do { \
(w)[0] += (uint64)(n); \
if ((w)[0] < (n)) { \
(w)[1]++; \
} \
} while (0)
* So we can't use securec_check, securec_check_ss and elog.
*/
#define SECUREC_CHECK(rc) securec_check_c(rc, "", "")
#define SECUREC_CHECK_SS(rc) securec_check_ss_c(rc, "", "")
* Bit shifting and rotation (used by the six SHA-XYZ logical functions:
*
* NOTE: The naming of R and S appears backwards here (R is a SHIFT and
* S is a ROTATION) because the SHA-256/384/512 description document
* (see http://www.iwar.org.uk/comsec/resources/cipher/sha256-384-512.pdf)
* uses this same "backwards" definition.
*/
#define R(b, x) ((x) >> (b))
#define S32(b, x) (((x) >> (b)) | ((x) << (32 - (b))))
#define Ch(x, y, z) (((x) & (y)) ^ ((~(x)) & (z)))
#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x)))
#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x)))
#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3, (x)))
#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x)))
* library -- they are intended for private internal visibility/use
* only.
*/
static void SHA256_Transform(SHA256_CTX2*, const uint8*);
static const uint32 K256[64] = {0x428a2f98UL,
0x71374491UL,
0xb5c0fbcfUL,
0xe9b5dba5UL,
0x3956c25bUL,
0x59f111f1UL,
0x923f82a4UL,
0xab1c5ed5UL,
0xd807aa98UL,
0x12835b01UL,
0x243185beUL,
0x550c7dc3UL,
0x72be5d74UL,
0x80deb1feUL,
0x9bdc06a7UL,
0xc19bf174UL,
0xe49b69c1UL,
0xefbe4786UL,
0x0fc19dc6UL,
0x240ca1ccUL,
0x2de92c6fUL,
0x4a7484aaUL,
0x5cb0a9dcUL,
0x76f988daUL,
0x983e5152UL,
0xa831c66dUL,
0xb00327c8UL,
0xbf597fc7UL,
0xc6e00bf3UL,
0xd5a79147UL,
0x06ca6351UL,
0x14292967UL,
0x27b70a85UL,
0x2e1b2138UL,
0x4d2c6dfcUL,
0x53380d13UL,
0x650a7354UL,
0x766a0abbUL,
0x81c2c92eUL,
0x92722c85UL,
0xa2bfe8a1UL,
0xa81a664bUL,
0xc24b8b70UL,
0xc76c51a3UL,
0xd192e819UL,
0xd6990624UL,
0xf40e3585UL,
0x106aa070UL,
0x19a4c116UL,
0x1e376c08UL,
0x2748774cUL,
0x34b0bcb5UL,
0x391c0cb3UL,
0x4ed8aa4aUL,
0x5b9cca4fUL,
0x682e6ff3UL,
0x748f82eeUL,
0x78a5636fUL,
0x84c87814UL,
0x8cc70208UL,
0x90befffaUL,
0xa4506cebUL,
0xbef9a3f7UL,
0xc67178f2UL};
static const uint32 sha256_initial_hash_value[8] = {
0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL, 0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL};
void SHA256_Init2(SHA256_CTX2* context)
{
errno_t rc = 0;
if (context == NULL)
return;
rc = memcpy_s(context->state, SHA256_DIGEST_LENGTH, sha256_initial_hash_value, sizeof(sha256_initial_hash_value));
SECUREC_CHECK(rc);
rc = memset_s(context->buffer, SHA256_BLOCK_LENGTH, 0, SHA256_BLOCK_LENGTH);
SECUREC_CHECK(rc);
context->bitcount = 0;
}
#ifdef SHA2_UNROLL_TRANSFORM
#define ROUND256_0_TO_15(a, b, c, d, e, f, g, h) \
do { \
W256[j] = (uint32)data[3] | ((uint32)data[2] << 8) | ((uint32)data[1] << 16) | ((uint32)data[0] << 24); \
data += 4; \
T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + W256[j]; \
(d) += T1; \
(h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \
j++; \
} while (0)
#define ROUND256(a, b, c, d, e, f, g, h) \
do { \
s0 = W256[(j + 1) & 0x0f]; \
s0 = sigma0_256(s0); \
s1 = W256[(j + 14) & 0x0f]; \
s1 = sigma1_256(s1); \
T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + (W256[j & 0x0f] += s1 + W256[(j + 9) & 0x0f] + s0); \
(d) += T1; \
(h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \
j++; \
} while (0)
static void SHA256_Transform(SHA256_CTX2* context, const uint8* data)
{
uint32 a, b, c, d, e, f, g, h, s0, s1;
uint32 T1, *W256 = NULL;
int j;
W256 = (uint32*)context->buffer;
a = context->state[0];
b = context->state[1];
c = context->state[2];
d = context->state[3];
e = context->state[4];
f = context->state[5];
g = context->state[6];
h = context->state[7];
j = 0;
do {
ROUND256_0_TO_15(a, b, c, d, e, f, g, h);
ROUND256_0_TO_15(h, a, b, c, d, e, f, g);
ROUND256_0_TO_15(g, h, a, b, c, d, e, f);
ROUND256_0_TO_15(f, g, h, a, b, c, d, e);
ROUND256_0_TO_15(e, f, g, h, a, b, c, d);
ROUND256_0_TO_15(d, e, f, g, h, a, b, c);
ROUND256_0_TO_15(c, d, e, f, g, h, a, b);
ROUND256_0_TO_15(b, c, d, e, f, g, h, a);
} while (j < 16);
do {
ROUND256(a, b, c, d, e, f, g, h);
ROUND256(h, a, b, c, d, e, f, g);
ROUND256(g, h, a, b, c, d, e, f);
ROUND256(f, g, h, a, b, c, d, e);
ROUND256(e, f, g, h, a, b, c, d);
ROUND256(d, e, f, g, h, a, b, c);
ROUND256(c, d, e, f, g, h, a, b);
ROUND256(b, c, d, e, f, g, h, a);
} while (j < 64);
context->state[0] += a;
context->state[1] += b;
context->state[2] += c;
context->state[3] += d;
context->state[4] += e;
context->state[5] += f;
context->state[6] += g;
context->state[7] += h;
a = b = c = d = e = f = g = h = T1 = 0;
}
#else
static void SHA256_Transform(SHA256_CTX2* context, const uint8* data)
{
uint32 a, b, c, d, e, f, g, h, temp_s0, temp_s1;
uint32 T1, T2;
uint32 *W256 = NULL;
unsigned int j;
W256 = (uint32*)context->buffer;
a = context->state[0];
b = context->state[1];
c = context->state[2];
d = context->state[3];
e = context->state[4];
f = context->state[5];
g = context->state[6];
h = context->state[7];
j = 0;
do {
W256[j] = (uint32)data[3] | ((uint32)data[2] << 8) | ((uint32)data[1] << 16) | ((uint32)data[0] << 24);
data += 4;
T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
T2 = Sigma0_256(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
j++;
} while (j < 16);
do {
temp_s0 = W256[(j + 1) & 0x0f];
temp_s0 = sigma0_256(temp_s0);
temp_s1 = W256[(j + 14) & 0x0f];
temp_s1 = sigma1_256(temp_s1);
T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j & 0x0f] += temp_s1 + W256[(j + 9) & 0x0f] + temp_s0);
T2 = Sigma0_256(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
j++;
} while (j < 64);
context->state[0] += a;
context->state[1] += b;
context->state[2] += c;
context->state[3] += d;
context->state[4] += e;
context->state[5] += f;
context->state[6] += g;
context->state[7] += h;
}
#endif
void SHA256_Update2(SHA256_CTX2* context, const uint8* data, size_t len)
{
size_t freespace, usedspace;
errno_t rc = 0;
if (len == 0) {
return;
}
usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
if (usedspace > 0) {
freespace = SHA256_BLOCK_LENGTH - usedspace;
if (len >= freespace) {
rc = memcpy_s(&context->buffer[usedspace], freespace, data, freespace);
SECUREC_CHECK(rc);
context->bitcount += freespace << 3;
len -= freespace;
data += freespace;
SHA256_Transform(context, context->buffer);
} else {
rc = memcpy_s(&context->buffer[usedspace], len, data, len);
SECUREC_CHECK(rc);
context->bitcount += len << 3;
return;
}
}
while (len >= SHA256_BLOCK_LENGTH) {
SHA256_Transform(context, data);
context->bitcount += SHA256_BLOCK_LENGTH << 3;
len -= SHA256_BLOCK_LENGTH;
data += SHA256_BLOCK_LENGTH;
}
if (len > 0) {
rc = memcpy_s(context->buffer, len, data, len);
SECUREC_CHECK(rc);
context->bitcount += len << 3;
}
}
static void SHA256_Last(SHA256_CTX2* context)
{
unsigned int usedspace;
errno_t rc = 0;
usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
#ifndef WORDS_BIGENDIAN
REVERSE64(context->bitcount, context->bitcount);
#endif
if (usedspace > 0) {
context->buffer[usedspace++] = 0x80;
if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
rc = memset_s(&context->buffer[usedspace],
SHA256_SHORT_BLOCK_LENGTH - usedspace,
0,
SHA256_SHORT_BLOCK_LENGTH - usedspace);
SECUREC_CHECK(rc);
} else {
if (usedspace < SHA256_BLOCK_LENGTH) {
rc = memset_s(
&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace, 0, SHA256_BLOCK_LENGTH - usedspace);
SECUREC_CHECK(rc);
}
SHA256_Transform(context, context->buffer);
rc = memset_s(context->buffer, SHA256_SHORT_BLOCK_LENGTH, 0, SHA256_SHORT_BLOCK_LENGTH);
SECUREC_CHECK(rc);
}
} else {
rc = memset_s(context->buffer, SHA256_SHORT_BLOCK_LENGTH, 0, SHA256_SHORT_BLOCK_LENGTH);
SECUREC_CHECK(rc);
*context->buffer = 0x80;
}
*(uint64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
SHA256_Transform(context, context->buffer);
}
void SHA256_Final2(uint8 digest[], SHA256_CTX2* context)
{
errno_t rc = 0;
if (digest != NULL) {
SHA256_Last(context);
#ifndef WORDS_BIGENDIAN
{
int j;
for (j = 0; j < 8; j++) {
REVERSE32(context->state[j], context->state[j]);
}
}
#endif
rc = memcpy_s(digest, SHA256_DIGEST_LENGTH, context->state, sizeof(context->state));
SECUREC_CHECK(rc);
}
rc = memset_s(context, sizeof(*context), 0, sizeof(*context));
SECUREC_CHECK(rc);
}
void sha_bytes_to_hex64(uint8 b[32], char* s)
{
static const char* hex = "0123456789abcdef";
int q = 0;
int w = 0;
for (q = 0, w = 0; q < 32; q++) {
s[w++] = hex[(b[q] >> 4) & 0x0F];
s[w++] = hex[b[q] & 0x0F];
}
s[w] = '\0';
}
void sha_bytes_to_hex8(uint8 b[4], char* s)
{
static const char* hex = "0123456789abcdef";
int q = 0;
int w = 0;
for (q = 0, w = 0; q < 4; q++) {
s[w++] = hex[(b[q] >> 4) & 0x0F];
s[w++] = hex[b[q] & 0x0F];
}
s[w] = '\0';
}
void sha_hex_to_bytes32(char* s, const char b[64])
{
int i = 0;
uint8 v1, v2;
for (i = 0; i < 64; i += 2) {
v1 = (b[i] >= 'a') ? (b[i] - 'a' + 10) : (b[i] - '0');
v2 = (*((b + i) + 1)) >= 'a' ? (*((b + i) + 1)) - 'a' + 10 : (*((b + i) + 1)) - '0';
s[i / 2] = (v1 << 4) + v2;
}
}
void sha_hex_to_bytes4(char* s, const char b[8])
{
int i = 0;
uint8 v1, v2;
for (i = 0; i < 8; i += 2) {
v1 = (b[i] >= 'a') ? (b[i] - 'a' + 10) : (b[i] - '0');
v2 = (*((b + i) + 1)) >= 'a' ? (*((b + i) + 1)) - 'a' + 10 : (*((b + i) + 1)) - '0';
s[i / 2] = (v1 << 4) + v2;
}
}
bool pg_sha256_encrypt(
const char* password, const char* salt_s, size_t salt_len, char* buf, char* client_key_buf, int iteration_count)
{
size_t password_len = 0;
char k[K_LENGTH + 1] = {0};
char client_key[CLIENT_KEY_BYTES_LENGTH + 1] = {0};
char sever_key[HMAC_LENGTH + 1] = {0};
char stored_key[STORED_KEY_LENGTH + 1] = {0};
char salt[SALT_LENGTH + 1] = {0};
char sever_key_string[HMAC_LENGTH * 2 + 1] = {0};
char stored_key_string[STORED_KEY_LENGTH * 2 + 1] = {0};
int pkcs_ret;
int sever_ret;
int client_ret;
int hash_ret;
int hmac_length = HMAC_LENGTH;
int stored_key_length = STORED_KEY_LENGTH;
int total_encrypt_length;
char sever_string[SEVER_STRING_LENGTH] = "Sever Key";
char client_string[CLIENT_STRING_LENGTH] = "Client Key";
errno_t rc = 0;
if (password == NULL || buf == NULL) {
return false;
}
password_len = strlen(password);
sha_hex_to_bytes32(salt, (char*)salt_s);
pkcs_ret = PKCS5_PBKDF2_HMAC((char*)password,
password_len,
(unsigned char*)salt,
SALT_LENGTH,
iteration_count,
(EVP_MD*)EVP_sha1(),
K_LENGTH,
(unsigned char*)k);
if (!pkcs_ret) {
rc = memset_s(k, K_LENGTH + 1, 0, K_LENGTH + 1);
SECUREC_CHECK(rc);
return false;
}
* then calculate stored key by using client key */
sever_ret = CRYPT_hmac(NID_hmacWithSHA256,
(GS_UCHAR*)k,
K_LENGTH,
(GS_UCHAR*)sever_string,
SEVER_STRING_LENGTH - 1,
(GS_UCHAR*)sever_key,
(GS_UINT32*)&hmac_length);
if (sever_ret) {
rc = memset_s(k, K_LENGTH + 1, 0, K_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(sever_key, HMAC_LENGTH + 1, 0, HMAC_LENGTH + 1);
SECUREC_CHECK(rc);
return false;
}
client_ret = CRYPT_hmac(NID_hmacWithSHA256,
(GS_UCHAR*)k,
K_LENGTH,
(GS_UCHAR*)client_string,
CLIENT_STRING_LENGTH - 1,
(GS_UCHAR*)client_key,
(GS_UINT32*)&hmac_length);
if (client_ret) {
rc = memset_s(k, K_LENGTH + 1, 0, K_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(client_key, CLIENT_KEY_BYTES_LENGTH + 1, 0, CLIENT_KEY_BYTES_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(sever_key, HMAC_LENGTH + 1, 0, HMAC_LENGTH + 1);
SECUREC_CHECK(rc);
return false;
}
if (NULL != client_key_buf) {
sha_bytes_to_hex64((uint8*)client_key, client_key_buf);
}
#ifndef WIN32
hash_ret = EVP_Digest(
(GS_UCHAR*)client_key, HMAC_LENGTH, (GS_UCHAR*)stored_key, (GS_UINT32*)&stored_key_length, EVP_sha256(), NULL);
#else
hash_ret = EVP_Digest(
(GS_UCHAR*)client_key, HMAC_LENGTH, (GS_UCHAR*)stored_key, (unsigned int *)&stored_key_length,
EVP_sha256(), NULL);
#endif
if (!hash_ret) {
rc = memset_s(k, K_LENGTH + 1, 0, K_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(client_key, CLIENT_KEY_BYTES_LENGTH + 1, 0, CLIENT_KEY_BYTES_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(sever_key, HMAC_LENGTH + 1, 0, HMAC_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(stored_key, STORED_KEY_LENGTH + 1, 0, STORED_KEY_LENGTH + 1);
SECUREC_CHECK(rc);
return false;
}
rc = strncpy_s(buf, SHA256_LENGTH + 1, "sha256", SHA256_LENGTH);
SECUREC_CHECK(rc);
buf[SHA256_LENGTH] = '\0';
total_encrypt_length = SALT_LENGTH * 2 + HMAC_LENGTH * 2 + STORED_KEY_LENGTH * 2;
sha_bytes_to_hex64((uint8*)sever_key, sever_key_string);
sha_bytes_to_hex64((uint8*)stored_key, stored_key_string);
rc = snprintf_s(buf + SHA256_LENGTH,
total_encrypt_length + 1,
total_encrypt_length,
"%s%s%s",
salt_s,
sever_key_string,
stored_key_string);
SECUREC_CHECK_SS(rc);
buf[(unsigned int)(SHA256_LENGTH + total_encrypt_length)] = '\0';
rc = memset_s(k, K_LENGTH + 1, 0, K_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(client_key, CLIENT_KEY_BYTES_LENGTH + 1, 0, CLIENT_KEY_BYTES_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(sever_key, HMAC_LENGTH + 1, 0, HMAC_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(stored_key, STORED_KEY_LENGTH + 1, 0, STORED_KEY_LENGTH + 1);
SECUREC_CHECK(rc);
return true;
}
#ifdef ENABLE_LITE_MODE
bool pg_sha256_encrypt_v1(
const char* password, const char* salt_s, size_t salt_len, char* buf, char* client_key_buf)
{
return pg_sha256_encrypt(password, salt_s, salt_len, buf, client_key_buf, ITERATION_COUNT_V1);
}
#endif
int XOR_between_password(const char* password1, const char* password2, char* r, int length)
{
int i;
if (password1 == NULL || password2 == NULL || length < 0) {
return -1;
}
for (i = 0; i < length; i++) {
*r++ = (unsigned char)*password1++ ^ (unsigned char)*password2++;
}
return 0;
}
bool pg_sha256_encrypt_for_md5(const char* password, const char* salt, size_t salt_len, char* buf)
{
size_t password_len = 0;
SHA256_CTX2 sha_contest;
uint8 digest[SHA256_DIGEST_LENGTH] = {0};
char* crypt_buf = NULL;
errno_t rc = 0;
if (password == NULL || salt == NULL || buf == NULL) {
return false;
}
password_len = strlen(password);
crypt_buf = (char*)malloc(password_len + salt_len + 1);
if (crypt_buf == NULL) {
return false;
}
rc = memset_s(&sha_contest, sizeof(sha_contest), 0, sizeof(sha_contest));
securec_check_c(rc, crypt_buf, "");
* Place salt at the end because it may be known by users trying to crack
* the SHA256 output.
*/
rc = memcpy_s(crypt_buf, password_len + 1, password, password_len);
securec_check_c(rc, crypt_buf, "");
rc = memcpy_s(crypt_buf + password_len, salt_len + 1, salt, salt_len);
securec_check_c(rc, crypt_buf, "");
rc = strncpy_s(buf, SHA256_LENGTH + 1, "sha256", SHA256_LENGTH);
SECUREC_CHECK(rc);
buf[SHA256_LENGTH] = '\0';
SHA256_Init2(&sha_contest);
SHA256_Update2(&sha_contest, (const uint8*)crypt_buf, password_len + salt_len);
SHA256_Final2(digest, &sha_contest);
sha_bytes_to_hex64(digest, buf + 6);
rc = memset_s(crypt_buf, password_len + salt_len + 1, 0, password_len + salt_len + 1);
securec_check_c(rc, crypt_buf, "");
free(crypt_buf);
crypt_buf = NULL;
return true;
}
bool GsSm3Encrypt(
const char* password, const char* salt_s, size_t salt_len, char* buf, char* client_key_buf, int iteration_count)
{
size_t password_len = 0;
char k[K_LENGTH + 1] = {0};
char client_key[CLIENT_KEY_BYTES_LENGTH + 1] = {0};
char sever_key[HMAC_LENGTH + 1] = {0};
char stored_key[STORED_KEY_LENGTH + 1] = {0};
char salt[SALT_LENGTH + 1] = {0};
char serverKeyString[HMAC_LENGTH * ENCRY_LENGTH_DOUBLE + 1] = {0};
char stored_key_string[STORED_KEY_LENGTH * 2 + 1] = {0};
int pkcs_ret;
int sever_ret;
int client_ret;
int hash_ret;
int hmac_length = HMAC_LENGTH;
int stored_key_length = STORED_KEY_LENGTH;
int total_encrypt_length;
char server_string[SEVER_STRING_LENGTH_SM3] = "Server Key";
char client_string[CLIENT_STRING_LENGTH] = "Client Key";
errno_t rc = 0;
if (NULL == password || NULL == buf) {
return false;
}
password_len = strlen(password);
sha_hex_to_bytes32(salt, (char*)salt_s);
pkcs_ret = PKCS5_PBKDF2_HMAC((char*)password,
password_len,
(unsigned char*)salt,
SALT_LENGTH,
iteration_count,
(EVP_MD*)EVP_sha1(),
K_LENGTH,
(unsigned char*)k);
if (!pkcs_ret) {
rc = memset_s(k, K_LENGTH + 1, 0, K_LENGTH + 1);
SECUREC_CHECK(rc);
return false;
}
* then calculate stored key by using client key */
sever_ret = CRYPT_hmac(NID_hmacWithSHA256,
(GS_UCHAR*)k,
K_LENGTH,
(GS_UCHAR*)server_string,
SEVER_STRING_LENGTH_SM3 - 1,
(GS_UCHAR*)sever_key,
(GS_UINT32*)&hmac_length);
if (sever_ret) {
rc = memset_s(k, K_LENGTH + 1, 0, K_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(sever_key, HMAC_LENGTH + 1, 0, HMAC_LENGTH + 1);
SECUREC_CHECK(rc);
return false;
}
client_ret = CRYPT_hmac(NID_hmacWithSHA256,
(GS_UCHAR*)k,
K_LENGTH,
(GS_UCHAR*)client_string,
CLIENT_STRING_LENGTH - 1,
(GS_UCHAR*)client_key,
(GS_UINT32*)&hmac_length);
if (client_ret) {
rc = memset_s(k, K_LENGTH + 1, 0, K_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(client_key, CLIENT_KEY_BYTES_LENGTH + 1, 0, CLIENT_KEY_BYTES_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(sever_key, HMAC_LENGTH + 1, 0, HMAC_LENGTH + 1);
SECUREC_CHECK(rc);
return false;
}
if (NULL != client_key_buf) {
sha_bytes_to_hex64((uint8*)client_key, client_key_buf);
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
hash_ret = EVP_Digest(
(GS_UCHAR*)client_key, HMAC_LENGTH, (GS_UCHAR*)stored_key, (GS_UINT32*)&stored_key_length, EVP_sm3(), NULL);
#endif
if (!hash_ret) {
rc = memset_s(k, K_LENGTH + 1, 0, K_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(client_key, CLIENT_KEY_BYTES_LENGTH + 1, 0, CLIENT_KEY_BYTES_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(sever_key, HMAC_LENGTH + 1, 0, HMAC_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(stored_key, STORED_KEY_LENGTH + 1, 0, STORED_KEY_LENGTH + 1);
SECUREC_CHECK(rc);
return false;
}
rc = strncpy_s(buf, SM3_LENGTH + 1, "sm3", SM3_LENGTH);
SECUREC_CHECK(rc);
buf[SM3_LENGTH] = '\0';
total_encrypt_length = SALT_LENGTH * 2 + HMAC_LENGTH * 2 + STORED_KEY_LENGTH * 2;
sha_bytes_to_hex64((uint8*)sever_key, serverKeyString);
sha_bytes_to_hex64((uint8*)stored_key, stored_key_string);
rc = snprintf_s(buf + SM3_LENGTH,
total_encrypt_length + 1,
total_encrypt_length,
"%s%s%s",
salt_s,
serverKeyString,
stored_key_string);
SECUREC_CHECK_SS(rc);
buf[(unsigned int)(SM3_LENGTH + total_encrypt_length)] = '\0';
rc = memset_s(k, K_LENGTH + 1, 0, K_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(client_key, CLIENT_KEY_BYTES_LENGTH + 1, 0, CLIENT_KEY_BYTES_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(sever_key, HMAC_LENGTH + 1, 0, HMAC_LENGTH + 1);
SECUREC_CHECK(rc);
rc = memset_s(stored_key, STORED_KEY_LENGTH + 1, 0, STORED_KEY_LENGTH + 1);
SECUREC_CHECK(rc);
return true;
}