You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

517 lines
18 KiB

/*
* This file is Copyright Daniel Silverstone <dsilvers@digital-scurf.org> 2006
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
//#include "config.h"
#include "OS_portable.h"
#include "../includes/libgfshare.h"
//#include "../includes/libgfshare_tables.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#define XMALLOC malloc
#define XFREE free
struct _gfshare_ctx
{
uint32_t sharecount,threshold,size,buffersize;
uint8_t sharenrs[255],buffer[];
};
uint8_t ctx_logs[256] = {
0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6,
0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81,
0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71,
0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21,
0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45,
0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9,
0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6,
0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd,
0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88,
0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd,
0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40,
0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e,
0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d,
0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b,
0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57,
0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d,
0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18,
0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c,
0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e,
0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd,
0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61,
0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e,
0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2,
0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76,
0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6,
0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa,
0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a,
0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51,
0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7,
0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8,
0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf };
uint8_t ctx_exps[510] = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9,
0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35,
0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0,
0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc,
0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f,
0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88,
0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93,
0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9,
0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa,
0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e,
0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4,
0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e,
0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef,
0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5,
0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83,
0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01,
0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d,
0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, 0x4c,
0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f,
0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x9d,
0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a,
0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, 0x46,
0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d,
0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, 0x5f,
0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65,
0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 0xfd,
0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe,
0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, 0xd9,
0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d,
0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, 0x81,
0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b,
0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, 0x85,
0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f,
0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, 0xa8,
0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49,
0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, 0xe6,
0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc,
0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, 0xe3,
0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95,
0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, 0x82,
0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c,
0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, 0x51,
0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3,
0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, 0x12,
0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7,
0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, 0x2c,
0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b,
0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e };
/*void _gfshare_fill_rand_using_random(uint8_t *buffer,unsigned long long count)
{
uint32_t i;
for (i=0; i<count; i++)
buffer[i] = (random() & 0xff00) >> 8; // apparently the bottom 8 aren't very random but the middles ones are
}*/
//void randombytes(uint8_t *x,long xlen);
//gfshare_rand_func_t gfshare_fill_rand = _gfshare_fill_rand_using_random;
//gfshare_rand_func_t gfshare_fill_rand = OS_randombytes;
// ------------------------------------------------------[ Preparation ]----
gfshare_ctx *_gfshare_ctx_init_core(uint8_t *sharenrs,uint32_t sharecount,uint8_t threshold,uint32_t size)
{
gfshare_ctx *ctx;
ctx = XMALLOC(sizeof(struct _gfshare_ctx) + threshold * size);
if ( ctx == NULL )
return(NULL); // errno should still be set from XMALLOC()
ctx->sharecount = sharecount;
ctx->threshold = threshold;
ctx->size = size;
memcpy(ctx->sharenrs,sharenrs,sharecount);
ctx->buffersize = threshold * size;
return(ctx);
}
// Initialise a gfshare context for producing shares
gfshare_ctx *gfshare_ctx_init_enc(uint8_t *sharenrs,uint32_t sharecount,uint8_t threshold,uint32_t size)
{
uint32_t i;
// can't have x[i] = 0 - that would just be a copy of the secret, in theory
// in fact, due to the way we use exp/log for multiplication and treat log(0) as 0, it ends up as a copy of x[i] = 1
for (i=0; i<sharecount; i++)
{
if ( sharenrs[i] == 0 )
{
printf("null sharenrs error\n");
errno = EINVAL;
return NULL;
}
}
return(_gfshare_ctx_init_core(sharenrs,sharecount,threshold,size));
}
// Initialise a gfshare context for recombining shares
gfshare_ctx *gfshare_ctx_init_dec(uint8_t *sharenrs,uint32_t sharecount,uint32_t size)
{
gfshare_ctx *ctx = _gfshare_ctx_init_core(sharenrs,sharecount,sharecount,size);
if ( ctx != NULL )
ctx->threshold = 0;
return(ctx);
}
// Free a share context's memory.
void gfshare_ctx_free(gfshare_ctx *ctx)
{
long len = sizeof(struct _gfshare_ctx) + ctx->buffersize;
//gfshare_fill_rand((uint8_t*)ctx,len);
OS_randombytes((uint8_t *)ctx,len);
XFREE(ctx);
}
// --------------------------------------------------------[ Splitting ]----
// Provide a secret to the encoder. (this re-scrambles the coefficients)
void gfshare_ctx_enc_setsecret(gfshare_ctx *ctx,uint8_t *secret)
{
memcpy(ctx->buffer + ((ctx->threshold-1) * ctx->size),secret,ctx->size);
//gfshare_fill_rand(ctx->buffer,(ctx->threshold-1) * ctx->size);
OS_randombytes(ctx->buffer,(ctx->threshold-1) * ctx->size);
}
// Extract a share from the context. 'share' must be preallocated and at least 'size' bytes long.
// 'sharenr' is the index into the 'sharenrs' array of the share you want.
void calc_share(uint8_t *buffer,int32_t size,int32_t M,uint32_t ilog,uint8_t *share)
{
uint32_t pos,coefficient;//,ilog = ctx_logs[ctx->sharenrs[sharenr]];
//uint8_t *coefficient_ptr = buffer;
uint8_t *share_ptr,share_byte;
for (pos=0; pos<size; pos++)
share[pos] = *(buffer++);
for (coefficient=1; coefficient<M; coefficient++)
{
share_ptr = share;
for (pos=0; pos<size; pos++)
{
share_byte = *share_ptr;
if ( share_byte != 0 )
share_byte = ctx_exps[ilog + ctx_logs[share_byte]];
*share_ptr++ = (share_byte ^ *buffer++);
}
}
}
void gfshare_ctx_enc_getshare(gfshare_ctx *ctx,uint8_t sharenr,uint8_t *share)
{
calc_share(ctx->buffer,ctx->size,ctx->threshold,ctx_logs[ctx->sharenrs[sharenr]],share);
}
#ifdef notnow
void calc_shares(uint8_t *shares,uint8_t *secret,int32_t size,int32_t width,int32_t M,int32_t N,uint8_t *sharenrs)
{
int32_t i;
uint8_t *buffer = calloc(M,width);
memset(shares,0,N*width);
memcpy(buffer + ((M - 1) * size),secret,size);
//gfshare_fill_rand(buffer,(M - 1) * size);
OS_randombytes(buffer,(M - 1) * size);
for (i=0; i<N; i++)
{
//uint32_t _crc32(uint32_t crc, const void *buf, size_t size);
calc_share(buffer,size,M,ctx_logs[sharenrs[i]],&shares[i * width]);
printf("(%02x %08x) ",sharenrs[i],calc_crc32(0,&shares[i*width],size));
}
free(buffer);
}
#endif
// ----------------------------------------------------[ Recombination ]----
// Inform a recombination context of a change in share indexes
void gfshare_ctx_dec_newshares(gfshare_ctx *ctx,uint8_t *sharenrs)
{
memcpy(ctx->sharenrs,sharenrs,ctx->sharecount);
}
// Provide a share context with one of the shares. The 'sharenr' is the index into the 'sharenrs' array
void gfshare_ctx_dec_giveshare(gfshare_ctx *ctx,uint8_t sharenr,uint8_t *share)
{
memcpy(ctx->buffer + (sharenr * ctx->size),share,ctx->size);
}
// Extract the secret by interpolation of the shares. secretbuf must be allocated and at least 'size' bytes long
void gfshare_extract(uint8_t *secretbuf,uint8_t *sharenrs,int32_t N,uint8_t *buffer,int32_t size,int32_t width)
{
uint32_t i,j,Li_top,Li_bottom; uint8_t *secret_ptr,*share_ptr,sharei,sharej;
memset(secretbuf,0,width);
for (i=0; i<N; i++)
{
// Compute L(i) as per Lagrange Interpolation
Li_top = Li_bottom = 0;
if ( (sharei= sharenrs[i]) == 0 )
continue; // this share is not provided.
for (j=0; j<N; j++)
{
if ( i == j )
continue;
if ( (sharej= sharenrs[j]) == 0 )
continue; // skip empty share
Li_top += ctx_logs[sharej];
if ( Li_top >= 0xff )
Li_top -= 0xff;
Li_bottom += ctx_logs[sharei ^ sharej];
if ( Li_bottom >= 0xff )
Li_bottom -= 0xff;
}
if ( Li_bottom > Li_top )
Li_top += 0xff;
Li_top -= Li_bottom; // Li_top is now log(L(i))
secret_ptr = secretbuf;
share_ptr = buffer + (width * i);
for (j=0; j<size; j++)
{
if ( *share_ptr != 0 )
(*secret_ptr) ^= ctx_exps[Li_top + ctx_logs[*share_ptr]];
share_ptr++;
secret_ptr++;
}
}
}
void gfshare_ctx_dec_extract(gfshare_ctx *ctx,uint8_t *secretbuf)
{
gfshare_extract(secretbuf,ctx->sharenrs,ctx->sharecount,ctx->buffer,ctx->size,ctx->size);
}
int32_t init_sharenrs(uint8_t sharenrs[255],uint8_t *orig,int32_t m,int32_t n)
{
uint8_t *randvals,valid[255];
int32_t i,j,r,remains,orign;
if ( m > n || n >= 0xff ) // reserve 255 for illegal sharei
{
printf("illegal M.%d of N.%d\n",m,n);
return(-1);
}
randvals = calloc(1,65536);
OS_randombytes(randvals,65536);
memset(sharenrs,0,n);
if ( orig == 0 && n == m )
{
for (i=0; i<255; i++)
valid[i] = (i + 1);
remains = orign = 255;
for (i=0; i<n; i++)
{
r = (randvals[i] % remains);
sharenrs[i] = valid[r];
printf("%d ",sharenrs[i]);
valid[r] = valid[--remains];
}
printf("FULL SET\n");
}
else
{
remains = n;
orign = n;
memcpy(valid,sharenrs,n);
i = j = 0;
memset(sharenrs,0,n);
for (i=0; i<m; i++)
{
r = (rand() >> 8) % remains;
sharenrs[i] = valid[r];
valid[r] = valid[--remains];
}
/*while ( i < m )
{
if ( j >= 65536 )
{
gfshare_fill_rand(randvals,65536);
printf("refill j.%d\n",j);
j = 0;
}
r = (randvals[j++] % n);
if ( valid[r] != 0 )
{
remains--;
i++;
sharenrs[r] = valid[r];
//printf("%d ",sharenrs[i]);
valid[r] = 0;
}
}*/
for (i=0; i<n; i++)
printf("%d ",valid[i]);
printf("valid\n");
for (i=0; i<m; i++)
printf("%d ",sharenrs[i]);
printf("sharenrs vals m.%d of n.%d\n",m,n);
//getchar();
}
free(randvals);
//printf("sharenrs m.%d of n.%d\n",m,n);
if ( remains != (orign - m) )
{
printf("remains algo error??\n");
return(-1);
}
for (i=0; i<m; i++)
{
for (j=0; j<m; j++)
{
if ( i == j )
continue;
if ( sharenrs[i] != 0 && sharenrs[i] == sharenrs[j] )
{
printf("FATAL: duplicate entry sharenrs[%d] %d vs %d sharenrs[%d]\n",i,sharenrs[i],sharenrs[j],j);
return(-1);
}
}
}
return(0);
}
// test
int test_m_of_n(int m,int n,int size,int maxiters)
{
int32_t i,j,r,err = -1;
uint8_t *secret,*recomb,**shares,*allshares,sharenrs[255],testnrs[255];
gfshare_ctx *G;
if ( init_sharenrs(sharenrs,0,n,n) < 0 )
return(err);
secret = malloc(size);
recomb = malloc(size);
shares = calloc(n,sizeof(*shares));
allshares = calloc(254,size);
for (i=0; i<n; i++)
shares[i] = malloc(size);
// Stage 1, make a secret
OS_randombytes(secret,size);
err = 0;
r = m;
for (j=0; j<maxiters; j++)
{
memset(allshares,0,254*size);
// Stage 2, split it n ways with a threshold of m
if ( 1 )
{
G = gfshare_ctx_init_enc(sharenrs,n,r,size);
gfshare_ctx_enc_setsecret(G,secret);
for (i=0; i<n; i++)
gfshare_ctx_enc_getshare(G,i,shares[i]);
gfshare_ctx_free(G);
}
else calc_shares(allshares,secret,size,size,r,n,sharenrs);
// Prep the decode shape
memset(testnrs,0,n);
if ( init_sharenrs(testnrs,sharenrs,r,n) < 0 )
{
printf("iter.%d error init_sharenrs(m.%d of n.%d)\n",j,r,n);
goto cleanup;
}
G = gfshare_ctx_init_dec(testnrs,n,size);
for (i=0; i<n; i++)
if ( testnrs[i] == sharenrs[i] )
gfshare_ctx_dec_giveshare(G,i,&allshares[i*size]);//shares[i]); //
gfshare_ctx_dec_newshares(G,testnrs);
gfshare_ctx_dec_extract(G,recomb);
if ( memcmp(secret,recomb,size) != 0 )
fprintf(stderr,"(ERRROR M.%d)\n",r), err++;
else fprintf(stderr,"M.%d\n",r);
r = ((rand() >> 8) % n) + 1;
}
err = 0;
printf("err.%d\n",err);
//#ifdef hardcoded_m_of_n_test
int32_t ok;
// Stage 3, attempt a recombination with shares 1 and 2
sharenrs[2] = 0;
gfshare_ctx_dec_newshares(G,sharenrs);
gfshare_ctx_dec_extract( G, recomb );
for( i = 0; i < 512; ++i )
if( secret[i] != recomb[i] )
ok = 0;
printf("shares 1 + 2: ok.%d\n",ok);
err += (ok == 0), ok = 1;
// Stage 4, attempt a recombination with shares 1 and 3
sharenrs[2] = '2';
sharenrs[1] = 0;
gfshare_ctx_dec_newshares( G, sharenrs );
gfshare_ctx_dec_extract( G, recomb );
for( i = 0; i < 512; ++i )
if( secret[i] != recomb[i] )
ok = 0;
printf("shares 1 + 3: ok.%d\n",ok);
err += (ok == 0), ok = 1;
// Stage 5, attempt a recombination with shares 2 and 3
sharenrs[0] = 0;
sharenrs[1] = '1';
gfshare_ctx_dec_newshares( G, sharenrs );
gfshare_ctx_dec_extract( G, recomb );
for( i = 0; i < 512; ++i )
if( secret[i] != recomb[i] )
ok = 0;
printf("shares 2 + 3: ok.%d\n",ok);
err += (ok == 0), ok = 1;
// Stage 6, attempt a recombination with shares 1, 2 and 3
sharenrs[0] = '0';
gfshare_ctx_dec_newshares( G, sharenrs );
gfshare_ctx_dec_extract( G, recomb );
for( i = 0; i < 512; ++i )
if( secret[i] != recomb[i] )
ok = 0;
printf("shares 1 + 2 + 3: ok.%d\n",ok);
err += (ok == 0), ok = 1;
gfshare_ctx_free( G );
printf("total error test_m_of_n %d\n",err);
//#endif
cleanup:
for (i=0; i<n; i++)
free(shares[i]);
free(shares);
free(allshares);
free(secret);
free(recomb);
return(-err);
}