#include <stdint.h>
#include "params.h"
#include "xmss_core.h"
#include "utils.h"
#include "xmss.h"
#if defined(__GNUC__) || defined(__clang__)
#define XMSS_UNUSED_ATT __attribute__((unused))
#else
#define XMSS_UNUSED_ATT
#endif
#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN
int xmss_keypair(XMSS_UNUSED_ATT unsigned char *pk, XMSS_UNUSED_ATT unsigned char *sk, XMSS_UNUSED_ATT const uint32_t oid)
{
return -1;
}
#else
int xmss_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid)
{
xmss_params params;
unsigned int i;
if (xmss_parse_oid(¶ms, oid)) {
return -1;
}
for (i = 0; i < XMSS_OID_LEN; i++) {
pk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF;
sk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF;
}
return xmss_core_keypair(¶ms, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN);
}
#endif
#ifndef OQS_ALLOW_XMSS_KEY_AND_SIG_GEN
int xmss_sign(XMSS_UNUSED_ATT unsigned char *sk, XMSS_UNUSED_ATT unsigned char *sm, XMSS_UNUSED_ATT unsigned long long *smlen,
XMSS_UNUSED_ATT const unsigned char *m, XMSS_UNUSED_ATT unsigned long long mlen)
{
return -1;
}
#else
int xmss_sign(unsigned char *sk,
unsigned char *sm, unsigned long long *smlen,
const unsigned char *m, unsigned long long mlen)
{
xmss_params params;
uint32_t oid = 0;
unsigned int i;
for (i = 0; i < XMSS_OID_LEN; i++) {
oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8);
}
if (xmss_parse_oid(¶ms, oid)) {
return -1;
}
return xmss_core_sign(¶ms, sk + XMSS_OID_LEN, sm, smlen, m, mlen);
}
#endif
int xmss_sign_open(const unsigned char *m, unsigned long long mlen,
const unsigned char *sm, unsigned long long smlen,
const unsigned char *pk)
{
xmss_params params;
uint32_t oid = 0;
unsigned int i;
for (i = 0; i < XMSS_OID_LEN; i++) {
oid |= pk[XMSS_OID_LEN - i - 1] << (i * 8);
}
if (xmss_parse_oid(¶ms, oid)) {
return -1;
}
return xmss_core_sign_open(¶ms, m, mlen, sm, smlen, pk + XMSS_OID_LEN);
}
int xmss_remaining_signatures(unsigned long long *remain, const unsigned char *sk)
{
xmss_params params;
uint32_t oid = 0;
unsigned int i;
unsigned long long idx, max;
for (i = 0; i < XMSS_OID_LEN; i++) {
oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8);
}
if (xmss_parse_oid(¶ms, oid)) {
*remain = 0;
return -1;
}
idx = bytes_to_ull(sk + XMSS_OID_LEN, params.index_bytes);
max = ((1ULL << params.full_height) - 1);
*remain = max - idx;
return 0;
}
int xmss_total_signatures(unsigned long long *max, const unsigned char *sk)
{
xmss_params params;
uint32_t oid = 0;
for (unsigned i = 0; i < XMSS_OID_LEN; i++) {
oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8);
}
if (xmss_parse_oid(¶ms, oid)) {
*max = 0;
return -1;
}
*max = ((1ULL << params.full_height) - 1);
return 0;
}
int xmssmt_keypair(unsigned char *pk, unsigned char *sk, const uint32_t oid)
{
xmss_params params;
unsigned int i;
if (xmssmt_parse_oid(¶ms, oid)) {
return -1;
}
for (i = 0; i < XMSS_OID_LEN; i++) {
pk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF;
sk[XMSS_OID_LEN - i - 1] = (oid >> (8 * i)) & 0xFF;
}
return xmssmt_core_keypair(¶ms, pk + XMSS_OID_LEN, sk + XMSS_OID_LEN);
}
int xmssmt_sign(unsigned char *sk,
unsigned char *sm, unsigned long long *smlen,
const unsigned char *m, unsigned long long mlen)
{
xmss_params params;
uint32_t oid = 0;
unsigned int i;
for (i = 0; i < XMSS_OID_LEN; i++) {
oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8);
}
if (xmssmt_parse_oid(¶ms, oid)) {
return -1;
}
return xmssmt_core_sign(¶ms, sk + XMSS_OID_LEN, sm, smlen, m, mlen);
}
int xmssmt_sign_open(const unsigned char *m, unsigned long long mlen,
const unsigned char *sm, unsigned long long smlen,
const unsigned char *pk)
{
xmss_params params;
uint32_t oid = 0;
unsigned int i;
for (i = 0; i < XMSS_OID_LEN; i++) {
oid |= pk[XMSS_OID_LEN - i - 1] << (i * 8);
}
if (xmssmt_parse_oid(¶ms, oid)) {
return -1;
}
return xmssmt_core_sign_open(¶ms, m, mlen, sm, smlen, pk + XMSS_OID_LEN);
}
int xmssmt_remaining_signatures(unsigned long long *remain, const unsigned char *sk)
{
xmss_params params;
uint32_t oid = 0;
unsigned int i;
unsigned long long idx, max;
for (i = 0; i < XMSS_OID_LEN; i++) {
oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8);
}
if (xmssmt_parse_oid(¶ms, oid)) {
*remain = 0;
return -1;
}
idx = bytes_to_ull(sk + XMSS_OID_LEN, params.index_bytes);
max = ((1ULL << params.full_height) - 1);
*remain = max - idx;
return 0;
}
int xmssmt_total_signatures(unsigned long long *max, const unsigned char *sk)
{
xmss_params params;
uint32_t oid = 0;
for (unsigned i = 0; i < XMSS_OID_LEN; i++) {
oid |= sk[XMSS_OID_LEN - i - 1] << (i * 8);
}
if (xmssmt_parse_oid(¶ms, oid)) {
*max = 0;
return -1;
}
*max = ((1ULL << params.full_height) - 1);
return 0;
}