1098 lines
28 KiB
C
1098 lines
28 KiB
C
/*
|
|
* Copyright 2023 The Tongsuo Project Authors. All Rights Reserved.
|
|
*
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
* in the file LICENSE in the source distribution or at
|
|
* https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt
|
|
*/
|
|
|
|
#include <openssl/err.h>
|
|
#include "internal/endian.h"
|
|
#include <crypto/zkp/common/zkp_util.h>
|
|
#include "nizk.h"
|
|
#include "nizk_plaintext_knowledge.h"
|
|
#include "nizk_plaintext_equality.h"
|
|
#include "nizk_dlog_knowledge.h"
|
|
#include "nizk_dlog_equality.h"
|
|
|
|
DEFINE_STACK_OF(BIGNUM)
|
|
DEFINE_STACK_OF(EC_POINT)
|
|
|
|
static point_conversion_form_t form = POINT_CONVERSION_COMPRESSED;
|
|
|
|
/** Encodes NIZK_PUB_PARAM to binary
|
|
* \param pp NIZK_PUB_PARAM object
|
|
* \param out the buffer for the result (if NULL the function returns
|
|
* number of bytes needed).
|
|
* \param size The memory size of the out pointer object
|
|
* \return the length of the encoded octet string or 0 if an error occurred
|
|
*/
|
|
size_t NIZK_PUB_PARAM_encode(const NIZK_PUB_PARAM *pp, unsigned char *out, size_t size)
|
|
{
|
|
int *q, curve_id;
|
|
size_t point_len, ret = 0, len;
|
|
unsigned char *p;
|
|
BN_CTX *bn_ctx = NULL;
|
|
EC_GROUP *group = NULL;
|
|
|
|
if (pp == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return ret;
|
|
}
|
|
|
|
group = pp->group;
|
|
|
|
curve_id = EC_GROUP_get_curve_name(group);
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
if (bn_ctx == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto end;
|
|
}
|
|
|
|
point_len = EC_POINT_point2oct(group, EC_GROUP_get0_generator(group),
|
|
form, NULL, 0, bn_ctx);
|
|
|
|
len = sizeof(int) + point_len * 2;
|
|
if (out == NULL) {
|
|
ret = len;
|
|
goto end;
|
|
}
|
|
|
|
if (size < len)
|
|
goto end;
|
|
|
|
memset(out, 0, size);
|
|
|
|
q = (int *)out;
|
|
*q++ = zkp_l2n((int)curve_id);
|
|
p = (unsigned char *)q;
|
|
|
|
if (EC_POINT_point2oct(group, pp->G, form, p, point_len, bn_ctx) == 0)
|
|
goto end;
|
|
|
|
p += point_len;
|
|
|
|
if (EC_POINT_point2oct(group, pp->H, form, p, point_len, bn_ctx) == 0)
|
|
goto end;
|
|
|
|
p += point_len;
|
|
|
|
ret = p - out;
|
|
|
|
end:
|
|
BN_CTX_free(bn_ctx);
|
|
return ret;
|
|
}
|
|
|
|
/** Decodes binary to NIZK_PUB_PARAM
|
|
* \param in Memory buffer with the encoded NIZK_PUB_PARAM
|
|
* object
|
|
* \param size The memory size of the in pointer object
|
|
* \return NIZK_PUB_PARAM object pointer on success and NULL otherwise
|
|
*/
|
|
NIZK_PUB_PARAM *NIZK_PUB_PARAM_decode(const unsigned char *in, size_t size)
|
|
{
|
|
unsigned char *p;
|
|
int curve_id, *q = (int *)in;
|
|
size_t point_len;
|
|
NIZK_PUB_PARAM *pp = NULL;
|
|
BN_CTX *bn_ctx = NULL;
|
|
EC_GROUP *group = NULL;
|
|
EC_POINT *G = NULL, *H = NULL;
|
|
|
|
if (in == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return NULL;
|
|
}
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
if (bn_ctx == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto err;
|
|
}
|
|
|
|
curve_id = zkp_n2l(*q);
|
|
q++;
|
|
p = (unsigned char *)q;
|
|
|
|
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, curve_id);
|
|
if (group == NULL)
|
|
goto err;
|
|
|
|
point_len = EC_POINT_point2oct(group, EC_GROUP_get0_generator(group),
|
|
form, NULL, 0, bn_ctx);
|
|
if (point_len <= 0)
|
|
goto err;
|
|
|
|
if (size < (sizeof(int) + point_len * 2)) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto err;
|
|
}
|
|
|
|
G = EC_POINT_new(group);
|
|
H = EC_POINT_new(group);
|
|
if (G == NULL || H == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto err;
|
|
}
|
|
|
|
if (!EC_POINT_oct2point(group, G, p, point_len, bn_ctx))
|
|
goto err;
|
|
|
|
p += point_len;
|
|
|
|
if (!EC_POINT_oct2point(group, H, p, point_len, bn_ctx))
|
|
goto err;
|
|
|
|
p += point_len;
|
|
|
|
pp = NIZK_PUB_PARAM_new(group, G, H);
|
|
if (pp == NULL)
|
|
goto err;
|
|
|
|
EC_POINT_free(G);
|
|
EC_POINT_free(H);
|
|
EC_GROUP_free(group);
|
|
BN_CTX_free(bn_ctx);
|
|
return pp;
|
|
|
|
err:
|
|
EC_POINT_free(G);
|
|
EC_POINT_free(H);
|
|
EC_GROUP_free(group);
|
|
NIZK_PUB_PARAM_free(pp);
|
|
BN_CTX_free(bn_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
/** Encodes NIZK_WITNESS to binary
|
|
* \param pp NIZK_WITNESS object
|
|
* \param out The buffer for the result (if NULL the function returns
|
|
* number of bytes needed).
|
|
* \param size The memory size of the out pointer object
|
|
* \param flag The flag is an indicator for encoding random number 'r'
|
|
* and plaintext 'v', with 1 indicating encoding and 0
|
|
* indicating no encoding.
|
|
* \return the length of the encoded octet string or 0 if an error occurred
|
|
*/
|
|
size_t NIZK_WITNESS_encode(const NIZK_WITNESS *witness, unsigned char *out,
|
|
size_t size, int flag)
|
|
{
|
|
int *q, bn_len;
|
|
size_t ret = 0, len;
|
|
unsigned char *p;
|
|
BN_CTX *bn_ctx = NULL;
|
|
EC_GROUP *group = NULL;
|
|
|
|
if (witness == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return ret;
|
|
}
|
|
|
|
bn_len = BN_num_bytes(witness->order);
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
if (bn_ctx == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto end;
|
|
}
|
|
|
|
len = sizeof(int) + bn_len * 2;
|
|
|
|
if (flag == 1)
|
|
len += bn_len;
|
|
|
|
if (out == NULL) {
|
|
ret = len;
|
|
goto end;
|
|
}
|
|
|
|
if (size < len)
|
|
goto end;
|
|
|
|
memset(out, 0, size);
|
|
|
|
q = (int *)out;
|
|
*q++ = zkp_l2n((int)bn_len);
|
|
p = (unsigned char *)q;
|
|
|
|
len = zkp_bignum_encode(witness->order, p, bn_len);
|
|
if (len <= 0)
|
|
goto end;
|
|
|
|
p += len;
|
|
|
|
len = zkp_bignum_encode(witness->r, p, bn_len);
|
|
if (len <= 0)
|
|
goto end;
|
|
|
|
p += len;
|
|
|
|
if (flag == 1) {
|
|
len = zkp_bignum_encode(witness->v, p, bn_len);
|
|
if (len <= 0)
|
|
goto end;
|
|
|
|
p += len;
|
|
}
|
|
|
|
ret = p - out;
|
|
|
|
end:
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
return ret;
|
|
}
|
|
|
|
/** Decodes binary to NIZK_WITNESS
|
|
* \param in Memory buffer with the encoded NIZK_WITNESS
|
|
* object
|
|
* \param size The memory size of the in pointer object
|
|
* \param flag The flag is an indicator for decoding random number 'r'
|
|
* and plaintext 'v', with 1 indicating decoding and 0
|
|
* indicating no decoding.
|
|
* \return NIZK_WITNESS object pointer on success and NULL otherwise
|
|
*/
|
|
NIZK_WITNESS *NIZK_WITNESS_decode(const unsigned char *in, size_t size, int flag)
|
|
{
|
|
unsigned char *p;
|
|
int *q = (int *)in, bn_len;
|
|
NIZK_WITNESS *witness = NULL;
|
|
|
|
if (in == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return NULL;
|
|
}
|
|
|
|
bn_len = zkp_n2l(*q);
|
|
q++;
|
|
p = (unsigned char *)q;
|
|
|
|
if (size < (sizeof(int) + bn_len * 2)) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
return NULL;
|
|
}
|
|
|
|
if (!(witness = OPENSSL_zalloc(sizeof(*witness)))) {
|
|
goto err;
|
|
}
|
|
|
|
witness->order = zkp_bignum_decode(p, NULL, bn_len);
|
|
if (witness->order == NULL) {
|
|
goto err;
|
|
}
|
|
|
|
p += bn_len;
|
|
|
|
witness->r = zkp_bignum_decode(p, NULL, bn_len);
|
|
if (witness->r == NULL) {
|
|
goto err;
|
|
}
|
|
|
|
p += bn_len;
|
|
|
|
if (flag == 1) {
|
|
if (size < (sizeof(int) + bn_len * 3)) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
return NULL;
|
|
}
|
|
|
|
witness->v = zkp_bignum_decode(p, NULL, bn_len);
|
|
if (witness->v == NULL) {
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
witness->references = 1;
|
|
if ((witness->lock = CRYPTO_THREAD_lock_new()) == NULL)
|
|
goto err;
|
|
|
|
return witness;
|
|
|
|
err:
|
|
NIZK_WITNESS_free(witness);
|
|
return NULL;
|
|
}
|
|
|
|
/** Encodes NIZK_PLAINTEXT_KNOWLEDGE_PROOF to binary
|
|
* \param proof NIZK_PLAINTEXT_KNOWLEDGE_PROOF object
|
|
* \param out the buffer for the result (if NULL the function returns
|
|
* number of bytes needed).
|
|
* \param size The memory size of the out pointer object
|
|
* \return the length of the encoded octet string or 0 if an error occurred
|
|
*/
|
|
size_t NIZK_PLAINTEXT_KNOWLEDGE_PROOF_encode(const NIZK_PLAINTEXT_KNOWLEDGE_PROOF *proof,
|
|
unsigned char *out, size_t size)
|
|
{
|
|
int *q, curve_id, bn_len, ret = 0, sk_len;
|
|
size_t len;
|
|
unsigned char *p = NULL;
|
|
BN_CTX *bn_ctx = NULL;
|
|
EC_GROUP *group = NULL;
|
|
STACK_OF(EC_POINT) *sk_point = NULL;
|
|
STACK_OF(BIGNUM) *sk_bn = NULL;
|
|
|
|
if (proof == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return 0;
|
|
}
|
|
|
|
sk_point = sk_EC_POINT_new_reserve(NULL, 2);
|
|
sk_bn = sk_BIGNUM_new_reserve(NULL, 2);
|
|
if (sk_point == NULL || sk_bn == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
return 0;
|
|
}
|
|
|
|
if ((curve_id = EC_POINT_get_curve_name(proof->A)) == NID_undef) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto end;
|
|
}
|
|
|
|
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, curve_id);
|
|
if (group == NULL)
|
|
goto end;
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
if (bn_ctx == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto end;
|
|
}
|
|
|
|
bn_len = BN_num_bytes(EC_GROUP_get0_order(group));
|
|
len = sizeof(int);
|
|
|
|
if (sk_EC_POINT_push(sk_point, proof->A) <= 0
|
|
|| sk_EC_POINT_push(sk_point, proof->B) <= 0)
|
|
goto end;
|
|
|
|
sk_len = zkp_stack_of_point_encode(sk_point, NULL, group, bn_ctx);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
len += sk_len;
|
|
|
|
if (sk_BIGNUM_push(sk_bn, proof->z1) <= 0
|
|
|| sk_BIGNUM_push(sk_bn, proof->z2) <= 0)
|
|
goto end;
|
|
|
|
sk_len = zkp_stack_of_bignum_encode(sk_bn, NULL, bn_len);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
len += sk_len;
|
|
|
|
if (out == NULL) {
|
|
ret = len;
|
|
goto end;
|
|
}
|
|
|
|
if (size < len)
|
|
goto end;
|
|
|
|
memset(out, 0, size);
|
|
|
|
/* encoding proof */
|
|
q = (int *)out;
|
|
*q++ = zkp_l2n(curve_id);
|
|
p = (unsigned char *)q;
|
|
|
|
sk_len = zkp_stack_of_point_encode(sk_point, p, group, bn_ctx);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
p += sk_len;
|
|
|
|
sk_len = zkp_stack_of_bignum_encode(sk_bn, p, bn_len);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
p += sk_len;
|
|
|
|
ret = p - out;
|
|
end:
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
sk_BIGNUM_free(sk_bn);
|
|
sk_EC_POINT_free(sk_point);
|
|
return ret;
|
|
}
|
|
|
|
/** Decodes binary to NIZK_PLAINTEXT_KNOWLEDGE_PROOF
|
|
* \param in Memory buffer with the encoded NIZK_PLAINTEXT_KNOWLEDGE_PROOF object
|
|
* \param size The memory size of the in pointer object
|
|
* \return NIZK_RANGE_PROOF object pointer on success and NULL otherwise
|
|
*/
|
|
NIZK_PLAINTEXT_KNOWLEDGE_PROOF *NIZK_PLAINTEXT_KNOWLEDGE_PROOF_decode(const unsigned char *in,
|
|
size_t size)
|
|
{
|
|
unsigned char *p;
|
|
int *q = (int *)in, curve_id, len;
|
|
size_t point_len, bn_len, proof_len;
|
|
NIZK_PLAINTEXT_KNOWLEDGE_PROOF *proof = NULL;
|
|
BN_CTX *bn_ctx = NULL;
|
|
EC_GROUP *group = NULL;
|
|
STACK_OF(EC_POINT) *sk_point = NULL;
|
|
STACK_OF(BIGNUM) *sk_bn = NULL;
|
|
|
|
if (in == NULL || size <= 4) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return NULL;
|
|
}
|
|
|
|
curve_id = zkp_n2l(*q);
|
|
q++;
|
|
|
|
if (curve_id <= 0) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto err;
|
|
}
|
|
|
|
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, curve_id);
|
|
if (group == NULL)
|
|
goto err;
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
if (bn_ctx == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto err;
|
|
}
|
|
|
|
p = (unsigned char *)q;
|
|
|
|
bn_len = BN_num_bytes(EC_GROUP_get0_order(group));
|
|
|
|
point_len = EC_POINT_point2oct(group, EC_GROUP_get0_generator(group),
|
|
form, NULL, 0, bn_ctx);
|
|
if (point_len <= 0)
|
|
goto err;
|
|
|
|
/* len(curve_id) + len(A+B) + len(z1+z2) */
|
|
proof_len = 4 + point_len * 2 + bn_len * 2;
|
|
if (size < proof_len) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto err;
|
|
}
|
|
|
|
proof = OPENSSL_zalloc(sizeof(*proof));
|
|
if (proof == NULL)
|
|
goto err;
|
|
|
|
sk_point = zkp_stack_of_point_decode(p, &len, group, bn_ctx);
|
|
if (sk_point == NULL)
|
|
goto err;
|
|
p += len;
|
|
|
|
if (sk_EC_POINT_num(sk_point) < 2)
|
|
goto err;
|
|
|
|
proof->A = sk_EC_POINT_value(sk_point, 0);
|
|
proof->B = sk_EC_POINT_value(sk_point, 1);
|
|
|
|
sk_bn = zkp_stack_of_bignum_decode(p, &len, bn_len);
|
|
if (sk_point == NULL)
|
|
goto err;
|
|
p += len;
|
|
|
|
if (sk_BIGNUM_num(sk_bn) < 2)
|
|
goto err;
|
|
|
|
proof->z1 = sk_BIGNUM_value(sk_bn, 0);
|
|
proof->z2 = sk_BIGNUM_value(sk_bn, 1);
|
|
|
|
sk_BIGNUM_free(sk_bn);
|
|
sk_EC_POINT_free(sk_point);
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
return proof;
|
|
|
|
err:
|
|
sk_BIGNUM_pop_free(sk_bn, BN_free);
|
|
sk_EC_POINT_pop_free(sk_point, EC_POINT_free);
|
|
OPENSSL_free(proof);
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
return NULL;
|
|
}
|
|
|
|
/** Encodes NIZK_PLAINTEXT_EQUALITY_PROOF to binary
|
|
* \param proof NIZK_PLAINTEXT_EQUALITY_PROOF object
|
|
* \param out the buffer for the result (if NULL the function returns
|
|
* number of bytes needed).
|
|
* \param size The memory size of the out pointer object
|
|
* \return the length of the encoded octet string or 0 if an error occurred
|
|
*/
|
|
size_t NIZK_PLAINTEXT_EQUALITY_PROOF_encode(const NIZK_PLAINTEXT_EQUALITY_PROOF *proof,
|
|
unsigned char *out, size_t size)
|
|
{
|
|
int *q, curve_id, bn_len, ret = 0, sk_len;
|
|
size_t len;
|
|
unsigned char *p = NULL;
|
|
BN_CTX *bn_ctx = NULL;
|
|
EC_GROUP *group = NULL;
|
|
STACK_OF(EC_POINT) *sk_point = NULL;
|
|
STACK_OF(BIGNUM) *sk_bn = NULL;
|
|
|
|
if (proof == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return 0;
|
|
}
|
|
|
|
sk_point = sk_EC_POINT_dup(proof->sk_A);
|
|
sk_bn = sk_BIGNUM_new_reserve(NULL, 2);
|
|
if (sk_point == NULL || sk_bn == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
return 0;
|
|
}
|
|
|
|
if ((curve_id = EC_POINT_get_curve_name(proof->B)) == NID_undef) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto end;
|
|
}
|
|
|
|
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, curve_id);
|
|
if (group == NULL)
|
|
goto end;
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
if (bn_ctx == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto end;
|
|
}
|
|
|
|
bn_len = BN_num_bytes(EC_GROUP_get0_order(group));
|
|
len = sizeof(int);
|
|
|
|
if (sk_EC_POINT_push(sk_point, proof->B) <= 0)
|
|
goto end;
|
|
|
|
sk_len = zkp_stack_of_point_encode(sk_point, NULL, group, bn_ctx);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
len += sk_len;
|
|
|
|
if (sk_BIGNUM_push(sk_bn, proof->z) <= 0
|
|
|| sk_BIGNUM_push(sk_bn, proof->t) <= 0)
|
|
goto end;
|
|
|
|
sk_len = zkp_stack_of_bignum_encode(sk_bn, NULL, bn_len);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
len += sk_len;
|
|
|
|
if (out == NULL) {
|
|
ret = len;
|
|
goto end;
|
|
}
|
|
|
|
if (size < len)
|
|
goto end;
|
|
|
|
memset(out, 0, size);
|
|
|
|
/* encoding proof */
|
|
q = (int *)out;
|
|
*q++ = zkp_l2n(curve_id);
|
|
p = (unsigned char *)q;
|
|
|
|
sk_len = zkp_stack_of_point_encode(sk_point, p, group, bn_ctx);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
p += sk_len;
|
|
|
|
sk_len = zkp_stack_of_bignum_encode(sk_bn, p, bn_len);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
p += sk_len;
|
|
|
|
ret = p - out;
|
|
end:
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
sk_BIGNUM_free(sk_bn);
|
|
sk_EC_POINT_free(sk_point);
|
|
return ret;
|
|
}
|
|
|
|
/** Decodes binary to NIZK_PLAINTEXT_EQUALITY_PROOF
|
|
* \param in Memory buffer with the encoded NIZK_PLAINTEXT_EQUALITY_PROOF object
|
|
* \param size The memory size of the in pointer object
|
|
* \return NIZK_RANGE_PROOF object pointer on success and NULL otherwise
|
|
*/
|
|
NIZK_PLAINTEXT_EQUALITY_PROOF *NIZK_PLAINTEXT_EQUALITY_PROOF_decode(const unsigned char *in,
|
|
size_t size)
|
|
{
|
|
unsigned char *p;
|
|
int *q = (int *)in, curve_id, len;
|
|
size_t point_len, bn_len, proof_len;
|
|
NIZK_PLAINTEXT_EQUALITY_PROOF *proof = NULL;
|
|
BN_CTX *bn_ctx = NULL;
|
|
EC_GROUP *group = NULL;
|
|
STACK_OF(EC_POINT) *sk_point = NULL;
|
|
STACK_OF(BIGNUM) *sk_bn = NULL;
|
|
|
|
if (in == NULL || size <= 4) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return NULL;
|
|
}
|
|
|
|
curve_id = zkp_n2l(*q);
|
|
q++;
|
|
|
|
if (curve_id <= 0) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto err;
|
|
}
|
|
|
|
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, curve_id);
|
|
if (group == NULL)
|
|
goto err;
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
if (bn_ctx == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto err;
|
|
}
|
|
|
|
p = (unsigned char *)q;
|
|
|
|
bn_len = BN_num_bytes(EC_GROUP_get0_order(group));
|
|
|
|
point_len = EC_POINT_point2oct(group, EC_GROUP_get0_generator(group),
|
|
form, NULL, 0, bn_ctx);
|
|
if (point_len <= 0)
|
|
goto err;
|
|
|
|
/* len(curve_id) + len(sk_A+B) + len(z1+z2) */
|
|
proof_len = 4 + point_len + bn_len * 2;
|
|
if (size < proof_len) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto err;
|
|
}
|
|
|
|
proof = OPENSSL_zalloc(sizeof(*proof));
|
|
if (proof == NULL)
|
|
goto err;
|
|
|
|
sk_point = zkp_stack_of_point_decode(p, &len, group, bn_ctx);
|
|
if (sk_point == NULL)
|
|
goto err;
|
|
p += len;
|
|
|
|
if (sk_EC_POINT_num(sk_point) < 1)
|
|
goto err;
|
|
|
|
proof->sk_A = sk_point;
|
|
proof->B = sk_EC_POINT_pop(sk_point);
|
|
|
|
sk_bn = zkp_stack_of_bignum_decode(p, &len, bn_len);
|
|
if (sk_point == NULL)
|
|
goto err;
|
|
p += len;
|
|
|
|
if (sk_BIGNUM_num(sk_bn) < 2)
|
|
goto err;
|
|
|
|
proof->z = sk_BIGNUM_value(sk_bn, 0);
|
|
proof->t = sk_BIGNUM_value(sk_bn, 1);
|
|
|
|
sk_BIGNUM_free(sk_bn);
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
return proof;
|
|
|
|
err:
|
|
sk_BIGNUM_pop_free(sk_bn, BN_free);
|
|
sk_EC_POINT_pop_free(sk_point, EC_POINT_free);
|
|
OPENSSL_free(proof);
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
return NULL;
|
|
}
|
|
|
|
/** Encodes NIZK_DLOG_KNOWLEDGE_PROOF to binary
|
|
* \param proof NIZK_DLOG_KNOWLEDGE_PROOF object
|
|
* \param out the buffer for the result (if NULL the function returns
|
|
* number of bytes needed).
|
|
* \param size The memory size of the out pointer object
|
|
* \return the length of the encoded octet string or 0 if an error occurred
|
|
*/
|
|
size_t NIZK_DLOG_KNOWLEDGE_PROOF_encode(const NIZK_DLOG_KNOWLEDGE_PROOF *proof,
|
|
unsigned char *out, size_t size)
|
|
{
|
|
int *q, curve_id, bn_len, ret = 0, sk_len;
|
|
size_t len;
|
|
unsigned char *p = NULL;
|
|
BN_CTX *bn_ctx = NULL;
|
|
EC_GROUP *group = NULL;
|
|
STACK_OF(EC_POINT) *sk_point = NULL;
|
|
STACK_OF(BIGNUM) *sk_bn = NULL;
|
|
|
|
if (proof == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return 0;
|
|
}
|
|
|
|
sk_point = sk_EC_POINT_new_reserve(NULL, 1);
|
|
sk_bn = sk_BIGNUM_new_reserve(NULL, 1);
|
|
if (sk_point == NULL || sk_bn == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
return 0;
|
|
}
|
|
|
|
if ((curve_id = EC_POINT_get_curve_name(proof->A)) == NID_undef) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto end;
|
|
}
|
|
|
|
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, curve_id);
|
|
if (group == NULL)
|
|
goto end;
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
if (bn_ctx == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto end;
|
|
}
|
|
|
|
bn_len = BN_num_bytes(EC_GROUP_get0_order(group));
|
|
len = sizeof(int);
|
|
|
|
if (sk_EC_POINT_push(sk_point, proof->A) <= 0)
|
|
goto end;
|
|
|
|
sk_len = zkp_stack_of_point_encode(sk_point, NULL, group, bn_ctx);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
len += sk_len;
|
|
|
|
if (sk_BIGNUM_push(sk_bn, proof->z) <= 0)
|
|
goto end;
|
|
|
|
sk_len = zkp_stack_of_bignum_encode(sk_bn, NULL, bn_len);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
len += sk_len;
|
|
|
|
if (out == NULL) {
|
|
ret = len;
|
|
goto end;
|
|
}
|
|
|
|
if (size < len)
|
|
goto end;
|
|
|
|
memset(out, 0, size);
|
|
|
|
/* encoding proof */
|
|
q = (int *)out;
|
|
*q++ = zkp_l2n(curve_id);
|
|
p = (unsigned char *)q;
|
|
|
|
sk_len = zkp_stack_of_point_encode(sk_point, p, group, bn_ctx);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
p += sk_len;
|
|
|
|
sk_len = zkp_stack_of_bignum_encode(sk_bn, p, bn_len);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
p += sk_len;
|
|
|
|
ret = p - out;
|
|
end:
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
sk_BIGNUM_free(sk_bn);
|
|
sk_EC_POINT_free(sk_point);
|
|
return ret;
|
|
}
|
|
|
|
/** Decodes binary to NIZK_DLOG_KNOWLEDGE_PROOF
|
|
* \param in Memory buffer with the encoded NIZK_DLOG_KNOWLEDGE_PROOF object
|
|
* \param size The memory size of the in pointer object
|
|
* \return NIZK_RANGE_PROOF object pointer on success and NULL otherwise
|
|
*/
|
|
NIZK_DLOG_KNOWLEDGE_PROOF *NIZK_DLOG_KNOWLEDGE_PROOF_decode(const unsigned char *in,
|
|
size_t size)
|
|
{
|
|
unsigned char *p;
|
|
int *q = (int *)in, curve_id, len;
|
|
size_t point_len, bn_len, proof_len;
|
|
NIZK_DLOG_KNOWLEDGE_PROOF *proof = NULL;
|
|
BN_CTX *bn_ctx = NULL;
|
|
EC_GROUP *group = NULL;
|
|
STACK_OF(EC_POINT) *sk_point = NULL;
|
|
STACK_OF(BIGNUM) *sk_bn = NULL;
|
|
|
|
if (in == NULL || size <= 4) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return NULL;
|
|
}
|
|
|
|
curve_id = zkp_n2l(*q);
|
|
q++;
|
|
|
|
if (curve_id <= 0) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto err;
|
|
}
|
|
|
|
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, curve_id);
|
|
if (group == NULL)
|
|
goto err;
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
if (bn_ctx == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto err;
|
|
}
|
|
|
|
p = (unsigned char *)q;
|
|
|
|
bn_len = BN_num_bytes(EC_GROUP_get0_order(group));
|
|
|
|
point_len = EC_POINT_point2oct(group, EC_GROUP_get0_generator(group),
|
|
form, NULL, 0, bn_ctx);
|
|
if (point_len <= 0)
|
|
goto err;
|
|
|
|
/* len(curve_id) + len(A) + len(z) */
|
|
proof_len = 4 + point_len + bn_len;
|
|
if (size < proof_len) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto err;
|
|
}
|
|
|
|
proof = OPENSSL_zalloc(sizeof(*proof));
|
|
if (proof == NULL)
|
|
goto err;
|
|
|
|
sk_point = zkp_stack_of_point_decode(p, &len, group, bn_ctx);
|
|
if (sk_point == NULL)
|
|
goto err;
|
|
p += len;
|
|
|
|
if (sk_EC_POINT_num(sk_point) < 1)
|
|
goto err;
|
|
|
|
proof->A = sk_EC_POINT_value(sk_point, 0);
|
|
|
|
sk_bn = zkp_stack_of_bignum_decode(p, &len, bn_len);
|
|
if (sk_point == NULL)
|
|
goto err;
|
|
p += len;
|
|
|
|
if (sk_BIGNUM_num(sk_bn) < 1)
|
|
goto err;
|
|
|
|
proof->z = sk_BIGNUM_value(sk_bn, 0);
|
|
|
|
sk_BIGNUM_free(sk_bn);
|
|
sk_EC_POINT_free(sk_point);
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
return proof;
|
|
|
|
err:
|
|
sk_BIGNUM_pop_free(sk_bn, BN_free);
|
|
sk_EC_POINT_pop_free(sk_point, EC_POINT_free);
|
|
OPENSSL_free(proof);
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
return NULL;
|
|
}
|
|
|
|
/** Encodes NIZK_DLOG_EQUALITY_PROOF to binary
|
|
* \param proof NIZK_DLOG_EQUALITY_PROOF object
|
|
* \param out the buffer for the result (if NULL the function returns
|
|
* number of bytes needed).
|
|
* \param size The memory size of the out pointer object
|
|
* \return the length of the encoded octet string or 0 if an error occurred
|
|
*/
|
|
size_t NIZK_DLOG_EQUALITY_PROOF_encode(const NIZK_DLOG_EQUALITY_PROOF *proof,
|
|
unsigned char *out, size_t size)
|
|
{
|
|
int *q, curve_id, bn_len, ret = 0, sk_len;
|
|
size_t len;
|
|
unsigned char *p = NULL;
|
|
BN_CTX *bn_ctx = NULL;
|
|
EC_GROUP *group = NULL;
|
|
STACK_OF(EC_POINT) *sk_point = NULL;
|
|
STACK_OF(BIGNUM) *sk_bn = NULL;
|
|
|
|
if (proof == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return 0;
|
|
}
|
|
|
|
sk_point = sk_EC_POINT_new_reserve(NULL, 2);
|
|
sk_bn = sk_BIGNUM_new_reserve(NULL, 1);
|
|
if (sk_point == NULL || sk_bn == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
return 0;
|
|
}
|
|
|
|
if ((curve_id = EC_POINT_get_curve_name(proof->A1)) == NID_undef) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto end;
|
|
}
|
|
|
|
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, curve_id);
|
|
if (group == NULL)
|
|
goto end;
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
if (bn_ctx == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto end;
|
|
}
|
|
|
|
bn_len = BN_num_bytes(EC_GROUP_get0_order(group));
|
|
len = sizeof(int);
|
|
|
|
if (sk_EC_POINT_push(sk_point, proof->A1) <= 0
|
|
|| sk_EC_POINT_push(sk_point, proof->A2) <= 0)
|
|
goto end;
|
|
|
|
sk_len = zkp_stack_of_point_encode(sk_point, NULL, group, bn_ctx);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
len += sk_len;
|
|
|
|
if (sk_BIGNUM_push(sk_bn, proof->z) <= 0)
|
|
goto end;
|
|
|
|
sk_len = zkp_stack_of_bignum_encode(sk_bn, NULL, bn_len);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
len += sk_len;
|
|
|
|
if (out == NULL) {
|
|
ret = len;
|
|
goto end;
|
|
}
|
|
|
|
if (size < len)
|
|
goto end;
|
|
|
|
memset(out, 0, size);
|
|
|
|
/* encoding proof */
|
|
q = (int *)out;
|
|
*q++ = zkp_l2n(curve_id);
|
|
p = (unsigned char *)q;
|
|
|
|
sk_len = zkp_stack_of_point_encode(sk_point, p, group, bn_ctx);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
p += sk_len;
|
|
|
|
sk_len = zkp_stack_of_bignum_encode(sk_bn, p, bn_len);
|
|
if (sk_len == 0)
|
|
goto end;
|
|
p += sk_len;
|
|
|
|
ret = p - out;
|
|
end:
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
sk_BIGNUM_free(sk_bn);
|
|
sk_EC_POINT_free(sk_point);
|
|
return ret;
|
|
}
|
|
|
|
/** Decodes binary to NIZK_DLOG_EQUALITY_PROOF
|
|
* \param in Memory buffer with the encoded NIZK_DLOG_EQUALITY_PROOF object
|
|
* \param size The memory size of the in pointer object
|
|
* \return NIZK_RANGE_PROOF object pointer on success and NULL otherwise
|
|
*/
|
|
NIZK_DLOG_EQUALITY_PROOF *NIZK_DLOG_EQUALITY_PROOF_decode(const unsigned char *in,
|
|
size_t size)
|
|
{
|
|
unsigned char *p;
|
|
int *q = (int *)in, curve_id, len;
|
|
size_t point_len, bn_len, proof_len;
|
|
NIZK_DLOG_EQUALITY_PROOF *proof = NULL;
|
|
BN_CTX *bn_ctx = NULL;
|
|
EC_GROUP *group = NULL;
|
|
STACK_OF(EC_POINT) *sk_point = NULL;
|
|
STACK_OF(BIGNUM) *sk_bn = NULL;
|
|
|
|
if (in == NULL || size <= 4) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_NULL_PARAMETER);
|
|
return NULL;
|
|
}
|
|
|
|
curve_id = zkp_n2l(*q);
|
|
q++;
|
|
|
|
if (curve_id <= 0) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto err;
|
|
}
|
|
|
|
group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, curve_id);
|
|
if (group == NULL)
|
|
goto err;
|
|
|
|
bn_ctx = BN_CTX_new();
|
|
if (bn_ctx == NULL) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_MALLOC_FAILURE);
|
|
goto err;
|
|
}
|
|
|
|
p = (unsigned char *)q;
|
|
|
|
bn_len = BN_num_bytes(EC_GROUP_get0_order(group));
|
|
|
|
point_len = EC_POINT_point2oct(group, EC_GROUP_get0_generator(group),
|
|
form, NULL, 0, bn_ctx);
|
|
if (point_len <= 0)
|
|
goto err;
|
|
|
|
/* len(curve_id) + len(A1+A2) + len(z) */
|
|
proof_len = 4 + point_len*2 + bn_len;
|
|
if (size < proof_len) {
|
|
ERR_raise(ERR_LIB_ZKP_NIZK, ERR_R_PASSED_INVALID_ARGUMENT);
|
|
goto err;
|
|
}
|
|
|
|
proof = OPENSSL_zalloc(sizeof(*proof));
|
|
if (proof == NULL)
|
|
goto err;
|
|
|
|
sk_point = zkp_stack_of_point_decode(p, &len, group, bn_ctx);
|
|
if (sk_point == NULL)
|
|
goto err;
|
|
p += len;
|
|
|
|
if (sk_EC_POINT_num(sk_point) < 2)
|
|
goto err;
|
|
|
|
proof->A1 = sk_EC_POINT_value(sk_point, 0);
|
|
proof->A2 = sk_EC_POINT_value(sk_point, 1);
|
|
|
|
sk_bn = zkp_stack_of_bignum_decode(p, &len, bn_len);
|
|
if (sk_point == NULL)
|
|
goto err;
|
|
p += len;
|
|
|
|
if (sk_BIGNUM_num(sk_bn) < 1)
|
|
goto err;
|
|
|
|
proof->z = sk_BIGNUM_value(sk_bn, 0);
|
|
|
|
sk_BIGNUM_free(sk_bn);
|
|
sk_EC_POINT_free(sk_point);
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
return proof;
|
|
|
|
err:
|
|
sk_BIGNUM_pop_free(sk_bn, BN_free);
|
|
sk_EC_POINT_pop_free(sk_point, EC_POINT_free);
|
|
OPENSSL_free(proof);
|
|
BN_CTX_free(bn_ctx);
|
|
EC_GROUP_free(group);
|
|
return NULL;
|
|
}
|