这是 pgbouncer 1.12.0 的部分源码:
pgbouncer/lib/usual/crypto/digest.h 里有部分内容:
typedef void (DigestInitFunc)(void *ctx);
typedef void (DigestUpdateFunc)(void *ctx, const void *, unsigned);
typedef void (DigestFinalFunc)(void *ctx, uint8_t *);
/**
* Algoright info.
*/
struct DigestInfo {
DigestInitFunc *init;
DigestUpdateFunc *update;
DigestFinalFunc *final;
short state_len;
short result_len;
short block_len;
};
pgbouncer/lib/usual/crypto/md5.h 里的内容:
#ifndef _USUAL_CRYPTO_MD5_H_
#define _USUAL_CRYPTO_MD5_H_
#include <usual/base.h>
/** Block length for MD5 */
#define MD5_BLOCK_LENGTH 64
/** Result length for MD5 */
#define MD5_DIGEST_LENGTH 16
/** MD5 state */
struct md5_ctx {
uint64_t nbytes;
uint32_t a, b, c, d;
uint32_t buf[16];
};
/** Clean state */
void md5_reset(struct md5_ctx *ctx);
/** Update state with more data */
void md5_update(struct md5_ctx *ctx, const void *data, unsigned int len);
/** Get final result */
void md5_final(struct md5_ctx *ctx, uint8_t *dst);
#endif
pgbouncer/lib/usual/crypto/md5.c 里的内容:
#include <usual/crypto/md5.h>
#include <usual/crypto/digest.h>
#include <usual/endian.h>
#include <usual/bits.h>
/*
* Support functions.
*/
#define bufpos(ctx) ((ctx)->nbytes & (MD5_BLOCK_LENGTH - 1))
static inline void swap_words(uint32_t *w, int n)
{
#ifdef WORDS_BIGENDIAN
for (; n > 0; w++, n--)
*w = le32toh(*w);
#endif
}
/*
* MD5 core.
*/
#define F(X,Y,Z) ((X & Y) | ((~X) & Z))
#define G(X,Y,Z) ((X & Z) | (Y & (~Z)))
#define H(X,Y,Z) (X ^ Y ^ Z)
#define I(X,Y,Z) (Y ^ (X | (~Z)))
#define OP(fn, a, b, c, d, k, s, T_i) \
a = b + rol32(a + fn(b, c, d) + X[k] + T_i, s)
static void md5_mix(struct md5_ctx *ctx, const uint32_t *X)
{
uint32_t a, b, c, d;
a = ctx->a;
b = ctx->b;
c = ctx->c;
d = ctx->d;
/* Round 1. */
OP(F, a, b, c, d, 0, 7, 0xd76aa478);
OP(F, d, a, b, c, 1, 12, 0xe8c7b756);
OP(F, c, d, a, b, 2, 17, 0x242070db);
OP(F, b, c, d, a, 3, 22, 0xc1bdceee);
OP(F, a, b, c, d, 4, 7, 0xf57c0faf);
OP(F, d, a, b, c, 5, 12, 0x4787c62a);
OP(F, c, d, a, b, 6, 17, 0xa8304613);
OP(F, b, c, d, a, 7, 22, 0xfd469501);
OP(F, a, b, c, d, 8, 7, 0x698098d8);
OP(F, d, a, b, c, 9, 12, 0x8b44f7af);
OP(F, c, d, a, b, 10, 17, 0xffff5bb1);
OP(F, b, c, d, a, 11, 22, 0x895cd7be);
OP(F, a, b, c, d, 12, 7, 0x6b901122);
OP(F, d, a, b, c, 13, 12, 0xfd987193);
OP(F, c, d, a, b, 14, 17, 0xa679438e);
OP(F, b, c, d, a, 15, 22, 0x49b40821);
/* Round 2. */
OP(G, a, b, c, d, 1, 5, 0xf61e2562);
OP(G, d, a, b, c, 6, 9, 0xc040b340);
OP(G, c, d, a, b, 11, 14, 0x265e5a51);
OP(G, b, c, d, a, 0, 20, 0xe9b6c7aa);
OP(G, a, b, c, d, 5, 5, 0xd62f105d);
OP(G, d, a, b, c, 10, 9, 0x02441453);
OP(G, c, d, a, b, 15, 14, 0xd8a1e681);
OP(G, b, c, d, a, 4, 20, 0xe7d3fbc8);
OP(G, a, b, c, d, 9, 5, 0x21e1cde6);
OP(G, d, a, b, c, 14, 9, 0xc33707d6);
OP(G, c, d, a, b, 3, 14, 0xf4d50d87);
OP(G, b, c, d, a, 8, 20, 0x455a14ed);
OP(G, a, b, c, d, 13, 5, 0xa9e3e905);
OP(G, d, a, b, c, 2, 9, 0xfcefa3f8);
OP(G, c, d, a, b, 7, 14, 0x676f02d9);
OP(G, b, c, d, a, 12, 20, 0x8d2a4c8a);
/* Round 3. */
OP(H, a, b, c, d, 5, 4, 0xfffa3942);
OP(H, d, a, b, c, 8, 11, 0x8771f681);
OP(H, c, d, a, b, 11, 16, 0x6d9d6122);
OP(H, b, c, d, a, 14, 23, 0xfde5380c);
OP(H, a, b, c, d, 1, 4, 0xa4beea44);
OP(H, d, a, b, c, 4, 11, 0x4bdecfa9);
OP(H, c, d, a, b, 7, 16, 0xf6bb4b60);
OP(H, b, c, d, a, 10, 23, 0xbebfbc70);
OP(H, a, b, c, d, 13, 4, 0x289b7ec6);
OP(H, d, a, b, c, 0, 11, 0xeaa127fa);
OP(H, c, d, a, b, 3, 16, 0xd4ef3085);
OP(H, b, c, d, a, 6, 23, 0x04881d05);
OP(H, a, b, c, d, 9, 4, 0xd9d4d039);
OP(H, d, a, b, c, 12, 11, 0xe6db99e5);
OP(H, c, d, a, b, 15, 16, 0x1fa27cf8);
OP(H, b, c, d, a, 2, 23, 0xc4ac5665);
/* Round 4. */
OP(I, a, b, c, d, 0, 6, 0xf4292244);
OP(I, d, a, b, c, 7, 10, 0x432aff97);
OP(I, c, d, a, b, 14, 15, 0xab9423a7);
OP(I, b, c, d, a, 5, 21, 0xfc93a039);
OP(I, a, b, c, d, 12, 6, 0x655b59c3);
OP(I, d, a, b, c, 3, 10, 0x8f0ccc92);
OP(I, c, d, a, b, 10, 15, 0xffeff47d);
OP(I, b, c, d, a, 1, 21, 0x85845dd1);
OP(I, a, b, c, d, 8, 6, 0x6fa87e4f);
OP(I, d, a, b, c, 15, 10, 0xfe2ce6e0);
OP(I, c, d, a, b, 6, 15, 0xa3014314);
OP(I, b, c, d, a, 13, 21, 0x4e0811a1);
OP(I, a, b, c, d, 4, 6, 0xf7537e82);
OP(I, d, a, b, c, 11, 10, 0xbd3af235);
OP(I, c, d, a, b, 2, 15, 0x2ad7d2bb);
OP(I, b, c, d, a, 9, 21, 0xeb86d391);
ctx->a += a;
ctx->b += b;
ctx->c += c;
ctx->d += d;
}
/*
* Public API.
*/
void md5_reset(struct md5_ctx *ctx)
{
ctx->nbytes = 0;
ctx->a = 0x67452301;
ctx->b = 0xefcdab89;
ctx->c = 0x98badcfe;
ctx->d = 0x10325476;
}
void md5_update(struct md5_ctx *ctx, const void *data, unsigned int len)
{
unsigned int n;
const uint8_t *ptr = data;
uint8_t *buf = (uint8_t *)ctx->buf;
while (len > 0) {
n = MD5_BLOCK_LENGTH - bufpos(ctx);
if (n > len)
n = len;
memcpy(buf + bufpos(ctx), ptr, n);
ptr += n;
len -= n;
ctx->nbytes += n;
if (bufpos(ctx) == 0) {
swap_words(ctx->buf, 16);
md5_mix(ctx, ctx->buf);
}
}
}
void md5_final(struct md5_ctx *ctx, uint8_t *dst)
{
static const uint8_t padding[MD5_BLOCK_LENGTH] = { 0x80 };
uint64_t final_len = ctx->nbytes * 8;
int pad_len, pos = bufpos(ctx);
/* add padding */
pad_len = MD5_BLOCK_LENGTH - 8 - pos;
if (pad_len <= 0)
pad_len += MD5_BLOCK_LENGTH;
md5_update(ctx, padding, pad_len);
/* add length directly */
swap_words(ctx->buf, 14);
ctx->buf[14] = final_len;
ctx->buf[15] = final_len >> 32;
/* final result */
md5_mix(ctx, ctx->buf);
le32enc(dst + 0, ctx->a);
le32enc(dst + 4, ctx->b);
le32enc(dst + 8, ctx->c);
le32enc(dst + 12, ctx->d);
}
/*
* DigestInfo
*/
static const struct DigestInfo md5 = {
(DigestInitFunc *)md5_reset,
(DigestUpdateFunc *)md5_update,
(DigestFinalFunc *)md5_final,
sizeof(struct md5_ctx),
MD5_DIGEST_LENGTH,
MD5_BLOCK_LENGTH
};
const struct DigestInfo *digest_MD5(void)
{
return &md5;
}
原生pgbouncer不支持sm3,需要在pgbouncer 1.12.0 源码的基础上添加sm3支持。
在 pgbouncer/lib/usual/crypto/sm3.h 里添加:
#ifndef _USUAL_CRYPTO_SM3_H_
#define _USUAL_CRYPTO_SM3_H_
#include <usual/base.h>
/** Block size for SM3 */
#define SM3_BLOCK_SIZE 64
/** Result length for SM3 */
#define SM3_DIGEST_LENGTH 32
/** SM3 state */
struct sm3_ctx {
uint32 digest[8]; // 哈希值
uint64 nblocks; // 总分块数
unsigned char block[64]; // 当前处理块
int num; // 缓冲区填充量
};
void sm3_reset(sm3_ctx *ctx);
void sm3_update(sm3_ctx *ctx, const unsigned char *data, size_t data_len);
void sm3_final(sm3_ctx *ctx, unsigned char *digest);
#endif
在 pgbouncer/lib/usual/crypto/sm3.c 里添加:
#include <usual/crypto/sm3.h>
#include <usual/crypto/digest.h>
#define GETU32(p) ((uint32)(p)[0]<<24|(uint32)(p)[1]<<16|(uint32)(p)[2]<<8|(uint32)(p)[3])
#define PUT32(p,v) ((p)[0]=(uint8)((v)>>24),(p)[1]=(uint8)((v)>>16),(p)[2]=(uint8)((v)>>8),(p)[3]=(uint8)(v))
/* 32bit data rotate left n bit */
#define ROL32(a,n) (((a)<<(n)) | (((a)&0xffffffff)>>(32-(n))))
/* base on SM3 Algorithm's function definition */
#define FF00(x,y,z) ((x) ^ (y) ^ (z))
#define FF16(x,y,z) (((x)&(y)) | ((x)&(z)) | ((y)&(z)))
#define GG00(x,y,z) ((x) ^ (y) ^ (z))
#define GG16(x,y,z) (((x)&(y)) | ((~x)&(z)))
#define P0(x) ((x) ^ ROL32((x),9) ^ ROL32((x),17))
#define P1(x) ((x) ^ ROL32((x),15) ^ ROL32((x),23))
/* constant quantity */
#define T00 0x79cc4519U
#define T16 0x7a879d8aU
#define K0 0x79cc4519U
#define K1 0xf3988a32U
#define K2 0xe7311465U
#define K3 0xce6228cbU
#define K4 0x9cc45197U
#define K5 0x3988a32fU
#define K6 0x7311465eU
#define K7 0xe6228cbcU
#define K8 0xcc451979U
#define K9 0x988a32f3U
#define K10 0x311465e7U
#define K11 0x6228cbceU
#define K12 0xc451979cU
#define K13 0x88a32f39U
#define K14 0x11465e73U
#define K15 0x228cbce6U
#define K16 0x9d8a7a87U
#define K17 0x3b14f50fU
#define K18 0x7629ea1eU
#define K19 0xec53d43cU
#define K20 0xd8a7a879U
#define K21 0xb14f50f3U
#define K22 0x629ea1e7U
#define K23 0xc53d43ceU
#define K24 0x8a7a879dU
#define K25 0x14f50f3bU
#define K26 0x29ea1e76U
#define K27 0x53d43cecU
#define K28 0xa7a879d8U
#define K29 0x4f50f3b1U
#define K30 0x9ea1e762U
#define K31 0x3d43cec5U
#define K32 0x7a879d8aU
#define K33 0xf50f3b14U
#define K34 0xea1e7629U
#define K35 0xd43cec53U
#define K36 0xa879d8a7U
#define K37 0x50f3b14fU
#define K38 0xa1e7629eU
#define K39 0x43cec53dU
#define K40 0x879d8a7aU
#define K41 0x0f3b14f5U
#define K42 0x1e7629eaU
#define K43 0x3cec53d4U
#define K44 0x79d8a7a8U
#define K45 0xf3b14f50U
#define K46 0xe7629ea1U
#define K47 0xcec53d43U
#define K48 0x9d8a7a87U
#define K49 0x3b14f50fU
#define K50 0x7629ea1eU
#define K51 0xec53d43cU
#define K52 0xd8a7a879U
#define K53 0xb14f50f3U
#define K54 0x629ea1e7U
#define K55 0xc53d43ceU
#define K56 0x8a7a879dU
#define K57 0x14f50f3bU
#define K58 0x29ea1e76U
#define K59 0x53d43cecU
#define K60 0xa7a879d8U
#define K61 0x4f50f3b1U
#define K62 0x9ea1e762U
#define K63 0x3d43cec5U
uint32 K[64] = {
K0, K1, K2, K3, K4, K5, K6, K7,
K8, K9, K10, K11, K12, K13, K14, K15,
K16, K17, K18, K19, K20, K21, K22, K23,
K24, K25, K26, K27, K28, K29, K30, K31,
K32, K33, K34, K35, K36, K37, K38, K39,
K40, K41, K42, K43, K44, K45, K46, K47,
K48, K49, K50, K51, K52, K53, K54, K55,
K56, K57, K58, K59, K60, K61, K62, K63,
};
static void
sm3_compress_blocks(uint32_t digest[8], const unsigned char *data, size_t blocks)
{
uint32 A;
uint32 B;
uint32 C;
uint32 D;
uint32 E;
uint32 F;
uint32 G;
uint32 H;
uint32 W[68];
int j = 0;
uint32 SS1, SS2, TT1, TT2;
while (blocks--)
{
A = digest[0];
B = digest[1];
C = digest[2];
D = digest[3];
E = digest[4];
F = digest[5];
G = digest[6];
H = digest[7];
for (j = 0; j < 16; j++)
{
W[j] = GETU32(data + j*4);
}
for (j = 16; j < 68; j++)
{
W[j] = P1(W[j - 16] ^ W[j - 9] ^ ROL32(W[j - 3], 15)) ^ ROL32(W[j -13], 7) ^ W[j - 6];
}
for (j = 0; j < 16; j++)
{
SS1 = ROL32((ROL32(A, 12) + E + K[j]), 7);
SS2 = SS1 ^ ROL32(A, 12);
TT1 = FF00(A, B, C) + D + SS2 + (W[j] ^ W[j + 4]);
TT2 = GG00(E, F, G) + H + SS1 + W[j];
D = C;
C = ROL32(B, 9);
B = A;
A = TT1;
H = G;
G = ROL32(F, 19);
F = E;
E = P0(TT2);
}
for (j = 16; j < 64; j++)
{
SS1 = ROL32((ROL32(A, 12) + E + K[j]), 7);
SS2 = SS1 ^ ROL32(A, 12);
TT1 = FF16(A, B, C) + D + SS2 + (W[j] ^ W[j + 4]);
TT2 = GG16(E, F, G) + H + SS1 + W[j];
D = C;
C = ROL32(B, 9);
B = A;
A = TT1;
H = G;
G = ROL32(F, 19);
F = E;
E = P0(TT2);
}
digest[0] ^= A;
digest[1] ^= B;
digest[2] ^= C;
digest[3] ^= D;
digest[4] ^= E;
digest[5] ^= F;
digest[6] ^= G;
digest[7] ^= H;
data += 64;
}
}
static void
sm3_compress(uint32_t digest[8], const unsigned char block[64])
{
return sm3_compress_blocks(digest, block, 1);
}
/*
* Public API.
*/
void
sm3_reset(sm3_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->digest[0] = 0x7380166F;
ctx->digest[1] = 0x4914B2B9;
ctx->digest[2] = 0x172442D7;
ctx->digest[3] = 0xDA8A0600;
ctx->digest[4] = 0xA96F30BC;
ctx->digest[5] = 0x163138AA;
ctx->digest[6] = 0xE38DEE4D;
ctx->digest[7] = 0xB0FB0E4E;
}
void
sm3_update(sm3_ctx *ctx, const unsigned char *data, size_t data_len)
{
size_t blocks;
if (ctx->num)
{
unsigned int left = SM3_BLOCK_SIZE - ctx->num;
if (data_len < left)
{
memcpy(ctx->block + ctx->num, data, data_len);
ctx->num += data_len;
return;
}
else
{
memcpy(ctx->block + ctx->num, data, left);
sm3_compress_blocks(ctx->digest, ctx->block, 1);
ctx->nblocks++;
data += left;
data_len -= left;
}
}
blocks = data_len / SM3_BLOCK_SIZE;
sm3_compress_blocks(ctx->digest, data, blocks);
ctx->nblocks += blocks;
data += SM3_BLOCK_SIZE * blocks;
data_len -= SM3_BLOCK_SIZE * blocks;
ctx->num = data_len;
if (data_len)
{
memcpy(ctx->block, data, data_len);
}
}
void
sm3_final(sm3_ctx *ctx, unsigned char *digest)
{
int i;
ctx->block[ctx->num] = 0x80;
if (ctx->num + 9 <= SM3_BLOCK_SIZE)
{
memset(ctx->block + ctx->num + 1, 0, SM3_BLOCK_SIZE - ctx->num - 9);
}
else
{
memset(ctx->block + ctx->num + 1, 0, SM3_BLOCK_SIZE - ctx->num - 1);
sm3_compress(ctx->digest, ctx->block);
memset(ctx->block, 0, SM3_BLOCK_SIZE - 8);
}
PUTU32(ctx->block + 56, ctx->nblocks >> 23);
PUTU32(ctx->block + 60, (ctx->nblocks << 9) + (ctx->num << 3));
sm3_compress(ctx->digest, ctx->block);
for (i = 0; i < 8; i++)
{
PUTU32(digest + i*4, ctx->digest[i]);
}
}
/*
* DigestInfo
*/
static const struct DigestInfo sm3 = {
(DigestInitFunc *)sm3_reset,
(DigestUpdateFunc *)sm3_update,
(DigestFinalFunc *)sm3_final,
sizeof(struct sm3_ctx),
SM3_DIGEST_LENGTH,
SM3_BLOCK_SIZE
};
const struct DigestInfo *digest_SM3(void)
{
return &sm3;
}
注意:pgbouncer的源码中不支持sm3。sm3相关的都是我自己添加的。
结合源码中md5,讲下我添加的sm3,整体上正确吗?(不考虑其他未涉及到的文件)