strongswan/src/libstrongswan/plugins/bliss/bliss_signature.c

234 lines
5.4 KiB
C

/*
* Copyright (C) 2014 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* 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; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* 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.
*/
#include "bliss_signature.h"
#include "bliss_bitpacker.h"
#include "bliss_huffman_coder.h"
typedef struct private_bliss_signature_t private_bliss_signature_t;
/**
* Private data of a bliss_signature_t object.
*/
struct private_bliss_signature_t {
/**
* Public interface for this signer.
*/
bliss_signature_t public;
/**
* BLISS signature parameter set
*/
const bliss_param_set_t *set;
/**
* BLISS signature vector z1 of size n
*/
int32_t *z1;
/**
* BLISS signature vector z2d of size n
*/
int16_t *z2d;
/**
* Indices of sparse BLISS challenge vector c of size kappa
*/
uint16_t *c_indices;
};
METHOD(bliss_signature_t, get_encoding, chunk_t,
private_bliss_signature_t *this)
{
bliss_bitpacker_t *packer;
bliss_huffman_coder_t *coder;
bliss_huffman_code_t *code;
int32_t z1;
uint32_t z1_sign;
uint16_t z2d_bits;
chunk_t encoding = chunk_empty;
int i;
z2d_bits = this->set->z1_bits - this->set->d;
/* Get Huffman code for this BLISS parameter set */
code = bliss_huffman_code_get_by_id(this->set->id);
if (!code)
{
DBG1(DBG_LIB, "no Huffman code found for parameter set %N",
bliss_param_set_id_names, this->set->id);
return chunk_empty;
}
packer = bliss_bitpacker_create(this->set->n * this->set->z1_bits +
this->set->n * z2d_bits +
this->set->kappa * this->set->n_bits);
coder = bliss_huffman_coder_create(code, packer);
for (i = 0; i < this->set->n; i++)
{
/* determine and remove the sign of z1[i]*/
z1_sign = this->z1[i] < 0;
z1 = z1_sign ? -this->z1[i] : this->z1[i];
if (!packer->write_bits(packer, z1_sign, 1) ||
!packer->write_bits(packer, z1 & 0xff, 8) ||
!coder->encode(coder, z1 >> 8, this->z2d[i]))
{
goto end;
}
}
for (i = 0; i < this->set->kappa; i++)
{
if (!packer->write_bits(packer, this->c_indices[i], this->set->n_bits))
{
goto end;
}
}
encoding = packer->extract_buf(packer);
DBG2(DBG_LIB, "efficiency of Huffman coder is %6.4f bits/tuple (%u bits)",
coder->get_bits(coder)/(double)(this->set->n),
coder->get_bits(coder));
DBG2(DBG_LIB, "generated BLISS signature (%u bits encoded in %u bytes)",
packer->get_bits(packer), encoding.len);
end:
coder->destroy(coder);
packer->destroy(packer);
return encoding;
}
METHOD(bliss_signature_t, get_parameters, void,
private_bliss_signature_t *this, int32_t **z1, int16_t **z2d,
uint16_t **c_indices)
{
*z1 = this->z1;
*z2d = this->z2d;
*c_indices = this->c_indices;
}
METHOD(bliss_signature_t, destroy, void,
private_bliss_signature_t *this)
{
free(this->z1);
free(this->z2d);
free(this->c_indices);
free(this);
}
/**
* See header.
*/
bliss_signature_t *bliss_signature_create(const bliss_param_set_t *set)
{
private_bliss_signature_t *this;
INIT(this,
.public = {
.get_encoding = _get_encoding,
.get_parameters = _get_parameters,
.destroy = _destroy,
},
.set = set,
.z1 = malloc(set->n * sizeof(int32_t)),
.z2d = malloc(set->n * sizeof(int16_t)),
.c_indices = malloc(set->n * sizeof(uint16_t)),
);
return &this->public;
}
/**
* See header.
*/
bliss_signature_t *bliss_signature_create_from_data(const bliss_param_set_t *set,
chunk_t encoding)
{
private_bliss_signature_t *this;
bliss_bitpacker_t *packer;
bliss_huffman_coder_t *coder;
bliss_huffman_code_t *code;
uint32_t z1_sign, z1_low, value;
int32_t z1;
int16_t z2;
int i;
/* Get Huffman code for this BLISS parameter set */
code = bliss_huffman_code_get_by_id(set->id);
if (!code)
{
DBG1(DBG_LIB, "no Huffman code found for parameter set %N",
bliss_param_set_id_names, set->id);
return NULL;
}
if (encoding.len == 0)
{
DBG1(DBG_LIB, "zero length BLISS signature");
return NULL;
}
INIT(this,
.public = {
.get_encoding = _get_encoding,
.get_parameters = _get_parameters,
.destroy = _destroy,
},
.set = set,
.z1 = malloc(set->n * sizeof(int32_t)),
.z2d = malloc(set->n * sizeof(int16_t)),
.c_indices = malloc(set->n * sizeof(uint16_t)),
);
packer = bliss_bitpacker_create_from_data(encoding);
coder = bliss_huffman_coder_create(code, packer);
for (i = 0; i < set->n; i++)
{
if (!packer->read_bits(packer, &z1_sign, 1) ||
!packer->read_bits(packer, &z1_low, 8) ||
!coder->decode(coder, &z1, &z2))
{
DBG1(DBG_LIB, "truncated BLISS signature encoding of z1/z2");
coder->destroy(coder);
packer->destroy(packer);
destroy(this);
return NULL;
}
z1 = (z1 << 8) + z1_low;
this->z1[i] = z1_sign ? -z1 : z1;
this->z2d[i] = z2;
}
coder->destroy(coder);
for (i = 0; i < set->kappa; i++)
{
if (!packer->read_bits(packer, &value, set->n_bits))
{
DBG1(DBG_LIB, "truncated BLISS signature encoding of c_indices");
packer->destroy(packer);
destroy(this);
return NULL;
}
this->c_indices[i] = value;
}
packer->destroy(packer);
return &this->public;
}