int32_t test(int32_t M,int32_t N,int32_t datasize) { int ok = 1, i; uint8_t * secret = malloc(datasize); uint8_t *shares[255]; uint8_t *recomb = malloc(datasize); uint8_t sharenrs[255],newsharenrs[255];// = (uint8_t *)strdup("0124z89abehtr"); gfshare_ctx *G; gfshare_fill_rand = gfshare_bad_idea_but_fill_rand_using_random; for (i=0; i<N; i++) { sharenrs[i] = i+1; shares[i] = malloc(datasize); } /* Stage 1, make a secret */ for( i = 0; i < datasize; ++i ) secret[i] = (rand() & 0xff00) >> 8; /* Stage 2, split it N ways with a threshold of M */ G = gfshare_ctx_init_enc( sharenrs, N, M, datasize ); gfshare_ctx_enc_setsecret( G, secret ); for (i=0; i<N; i++) gfshare_ctx_enc_getshare( G, i, shares[i] ); gfshare_ctx_free( G ); /* Prep the decode shape */ G = gfshare_ctx_init_dec( sharenrs, N, datasize ); memset(newsharenrs,0,N); int32_t j,r; for (i=0; i<M; i++) { r = rand() % N; while ( (j= sharenrs[r]) == 0 || newsharenrs[r] != 0 ) r = rand() % N; newsharenrs[r] = j; sharenrs[r] = 0; } for (i=0; i<N; i++) { if ( newsharenrs[i] != 0 ) gfshare_ctx_dec_giveshare( G, i, shares[i] ); //newsharenrs[i] = sharenrs[i]; } /* Stage 3, attempt a recombination with shares 1 and 2 */ //sharenrs[2] = 0; gfshare_ctx_dec_newshares( G, newsharenrs ); gfshare_ctx_dec_extract( G, recomb ); for( i = 0; i < datasize; ++i ) if( secret[i] != recomb[i] ) ok = 0; printf("M.%-3d N.%-3d ok.%d datalen.%d\n",M,N,ok,datasize); free(recomb), free(secret); for (i=0; i<N; i++) free(shares[i]); return ok!=1; }
uint8_t *recoverdata(uint8_t *shares[],uint8_t *sharenrs,int32_t M,int32_t datasize,int32_t N) { void *G; int32_t i; uint8_t *recover,recovernrs[255]; if ( (recover= calloc(1,datasize)) == 0 ) { printf("cards777_recover: unexpected out of memory error\n"); return(0); } memset(recovernrs,0,sizeof(recovernrs)); for (i=0; i<N; i++) if ( shares[i] != 0 ) recovernrs[i] = sharenrs[i]; G = gfshare_ctx_init_dec(recovernrs,N,datasize); for (i=0; i<N; i++) if ( shares[i] != 0 ) gfshare_ctx_dec_giveshare(G,i,shares[i]); gfshare_ctx_dec_newshares(G,recovernrs); gfshare_ctx_dec_extract(G,recover); gfshare_ctx_free(G); return(recover); }
int sharefarm_read(const char *path, size_t *len, char **buf) { sharefarm_content *c = NULL, *cc = NULL; int ret, i; gfshare_ctx *gfc = NULL; unsigned char *sharenrs = NULL; unsigned char *sparebuf = NULL; if ((ret = find_all_shares(&c)) < 0) return ret; cc = find_content(c, path); if (cc == NULL) { free_content(c); return -ENOENT; } sharenrs = malloc(cc->sharecount); if (sharenrs == NULL) { free_content(c); return -ENOMEM; } for (i = 0; i < cc->sharecount; ++i) sharenrs[i] = (unsigned char)(cc->shares[i].sharenum); *len = cc->statinfo.st_size; *buf = calloc(1, *len); if (*buf == NULL) { ret = -ENOMEM; goto out; } mlock(*buf, *len); sparebuf = malloc(*len); if (sparebuf == NULL) { ret = -ENOMEM; goto out; } gfc = gfshare_ctx_init_dec(sharenrs, cc->sharecount, cc->statinfo.st_size); if (gfc == NULL) { ret = -ENOMEM; goto out; } for (i = 0; i < cc->sharecount; ++i) { int fd = open(cc->shares[i].fname, O_RDONLY); if (fd == -1) { ret = -errno; goto out; } if (read(fd, sparebuf, *len) != *len) { ret = -errno; close(fd); goto out; } close(fd); gfshare_ctx_dec_giveshare(gfc, i, sparebuf); } gfshare_ctx_dec_extract(gfc, (unsigned char *)*buf); out: if (ret < 0 ) { if (*buf != NULL) { munlock(*buf, *len); free(*buf); } } if (gfc != NULL) { gfshare_ctx_free(gfc); } free(sharenrs); free_content(c); return ret; }
PPH_ERROR pph_unlock_password_data(pph_context *ctx,unsigned int username_count, const uint8 *usernames[], unsigned int username_lengths[], const uint8 *passwords[]){ uint8 share_numbers[MAX_NUMBER_OF_SHARES]; gfshare_ctx *G; unsigned int i; uint8 secret[SHARE_LENGTH]; uint8 salted_password[MAX_USERNAME_LENGTH+MAX_SALT_LENGTH]; uint8 estimated_digest[DIGEST_LENGTH]; uint8 estimated_share[SHARE_LENGTH]; pph_entry *entry; pph_account_node *current_user; //sanitize the data. if(ctx == NULL || usernames == NULL || passwords == NULL || username_lengths == NULL){ return PPH_BAD_PTR; } if(username_count < ctx->threshold){ return PPH_ACCOUNT_IS_INVALID; } // initialize the share numbers for(i=0;i<MAX_NUMBER_OF_SHARES;i++){ share_numbers[i] = 0; } // initialize a recombination context G = gfshare_ctx_init_dec( share_numbers, MAX_NUMBER_OF_SHARES-1, SHARE_LENGTH-ctx->partial_bytes); // traverse our possible users current_user=ctx->account_data; while(current_user!=NULL){ // check if each of the provided users is inside the context. We traverse // our user list inside the while, and compare against the provided users // inside this for loop. for(i = 0; i<username_count;i++){ //compare the proposed against existing users. if(username_lengths[i] == current_user->account.username_length && (!memcmp(usernames[i],current_user->account.username, current_user->account.username_length))){ // this is an existing user entry = current_user->account.entries; // check if he is a threshold account. if(entry->share_number != 0){ // if he is a threshold account, we must attempt to reconstruct the // shares using their information, traverse his entries while(entry!=NULL){ // calulate the digest given the password. memcpy(salted_password,entry->salt,entry->salt_length); memcpy(salted_password+entry->salt_length, passwords[i], entry->password_length); _calculate_digest(estimated_digest,salted_password, MAX_SALT_LENGTH + current_user->account.entries->password_length); // xor the obtained digest with the polyhashed value to obtain // our share. _xor_share_with_digest(estimated_share,entry->polyhashed_value, estimated_digest,SHARE_LENGTH-ctx->partial_bytes); // give share to the recombinator. share_numbers[entry->share_number] = entry->share_number+1; gfshare_ctx_dec_giveshare(G, entry->share_number,estimated_share); // move to the next entry. entry = entry->next; } } } } current_user = current_user->next; } // now we attempt to recombine the secret, we have given him all of the // obtained shares. gfshare_ctx_dec_newshares(G, share_numbers); gfshare_ctx_dec_extract(G, secret); // verify that we got a proper secret back. if(check_pph_secret(secret, SIGNATURE_RANDOM_BYTE_LENGTH-ctx->partial_bytes, SIGNATURE_HASH_BYTE_LENGTH) != PPH_ERROR_OK){ return PPH_ACCOUNT_IS_INVALID; } // else, we have a correct secret and we will copy it back to the provided // context. if(ctx->secret == NULL){ ctx->secret = calloc(sizeof(ctx->secret),SHARE_LENGTH-ctx->partial_bytes); } memcpy(ctx->secret,secret,SHARE_LENGTH-ctx->partial_bytes); // if the share context is not initialized, initialize one with the // information we have about our context. if(ctx->share_context == NULL){ for(i=0;i<MAX_NUMBER_OF_SHARES;i++){ share_numbers[i]=(unsigned char)i+1; } ctx->share_context = gfshare_ctx_init_enc( share_numbers, MAX_NUMBER_OF_SHARES-1, ctx->threshold, SHARE_LENGTH-ctx->partial_bytes); } // we have an initialized share context, we set the recombined secret to it // and set the unlock flag to one so it is ready to use. gfshare_ctx_enc_setsecret(ctx->share_context, ctx->secret); ctx->is_unlocked = true; ctx->AES_key = ctx->secret; return PPH_ERROR_OK; }