【GMSSL】函数 i2o_SM2CiphertextValue中存在的 BUG 分析与解决方法

1. 写在前面

  最近,需要协助硬件IC的同事验证SM2的加密、解密、签名、验签、秘钥交换等功能。为此我们以GMSSL的软算法为基准,验证IC的硬件实现,但是在验证SM2加密时,发现了i2o_SM2CiphertextValue中的bug,如下:

2. 问题描述

  下面是我自己写的一个调用GMSSL接口实现SM2加密的函数接口,测试中发现指针*c中输出的数据并非我们想要的。经过打印c的地址,发现在调用函数i2o_SM2CiphertextValue前后指针c的地址竟然发生了变化。

uint32_t Simu_Sm2_Encrypt(uint8_t *m, uint32_t mLen,
                         uint8_t *rand_key, uint8_t *pubkey,
                         uint8_t *c, uint32_t *cLen)
{
    
    
	......
    printf("Before c = %p\n", c); /* 测试,打印c的地址 */
    if ((*cLen = i2o_SM2CiphertextValue(group, cv, &c)) <= 0)
    {
    
    
        printf("ERROR: %s %d\n", __func__, __LINE__);
        goto ERR;
    }
    printf("After c = %p\n", c); /* 测试,打印c的地址 */

#if SIMU_DPI_SM2_DEBUG == 1
    printf("Ciphertext[%d bytes] -->\n", *cLen);
    BIO_dump_fp(stdout, (const char *)(c - *cLen), *cLen);
#endif
	......
}

运行后打印的指针c的地址如下:

Before c = 0x7ffdb2603520
After c = 0x7ffdb26035a1

那么可以肯定的是函数i2o_SM2CiphertextValue修改了指针c的地址。经过排查发现了是如下代码的问题:

int i2o_SM2CiphertextValue(const EC_GROUP *group, const SM2CiphertextValue *cv,
	unsigned char **pout)
{
    
    
	int ret = 0, outlen = 0, nbytes;
	EC_POINT *point = NULL;
	BN_CTX *bn_ctx = NULL;
	unsigned char *buf;
	unsigned char *p;
	size_t siz;
	......
	if (*pout) {
    
    
		p = *pout;	// 若*pout非空,则使用外部传递的地址,存储数据,而我们传递的是c,所以非空
	} else {
    
    
		......
	}
	......
	p += siz;	// p指向的地址一直在增加
	outlen += siz;

	/* encode ciphertext */
	memcpy(p, ASN1_STRING_get0_data(cv->ciphertext),
		ASN1_STRING_length(cv->ciphertext));
	p += ASN1_STRING_length(cv->ciphertext);
	outlen += ASN1_STRING_length(cv->ciphertext);

	/* encode hash */
	memcpy(p, ASN1_STRING_get0_data(cv->hash),
		ASN1_STRING_length(cv->hash));
	p += ASN1_STRING_length(cv->hash); // p指向的地址一直在增加
	outlen += ASN1_STRING_length(cv->hash);

	/* output */
	if (*pout) {
    
    
		*pout = p; // 这里又将p的地址重新赋给了*pout,这是问题的关键所在
	} else {
    
    
		*pout = buf;
		buf = NULL;
	}
	ret = outlen;
}

经过上面代码的分析,是该函数对指针c的地址进行了修改,导致了c指向的内容并非我们想要的。

3. 解决办法

i2o_SM2CiphertextValue的如下代码屏蔽掉即可:

/* output */
if (*pout) {
    
    
	//*pout = p;
} else {
    
    
	*pout = buf;
	buf = NULL;
}

猜你喜欢

转载自blog.csdn.net/KXue0703/article/details/129079586