void crypto777_encrypt(HUFF *dest,HUFF *src,int32_t len,struct crypto777_user *sender,uint32_t timestamp) { bits256 hash; bits384 xorpad; int32_t i; uint64_t *ptr = (uint64_t *)src->buf; hseek(dest,len << 3,SEEK_SET), hrewind(dest), hseek(src,len << 3,SEEK_SET), hrewind(src); calc_sha256cat(hash.bytes,(uint8_t *)&sender->nxt64bits,sizeof(sender->nxt64bits),(uint8_t *)×tamp,sizeof(timestamp)); SaM_Initialize(&sender->XORpad); SaM_Absorb(&sender->XORpad,hash.bytes,sizeof(hash.bytes),sender->shared_SaM.bytes,sizeof(sender->shared_SaM)); while ( len >= sizeof(xorpad) ) { SaM_emit(&sender->XORpad); for (i=0; i<6; i++) xorpad.ulongs[i] = (sender->XORpad.bits.ulongs[i] ^ ptr[i]);//, printf("%llx ",(long long)xorpad.ulongs[i]); ptr += 6; hmemcpy(0,xorpad.bytes,dest,sizeof(xorpad)), len -= sizeof(xorpad); } if ( len > 0 ) { SaM_emit(&sender->XORpad); for (i=0; i<len; i++) xorpad.bytes[i] = (sender->XORpad.bits.bytes[i] ^ ((uint8_t *)ptr)[i]);//, printf("%2x ",xorpad.bytes[i]); hmemcpy(0,xorpad.bytes,dest,len), len -= sizeof(xorpad); } //printf(" dest %llu\n",(long long)sender->nxt64bits); }
int main(void) { static const int size[] = { 1, 13, 403, 999, 30000 }; char buffer[40000]; char *original; int c, i; ssize_t n; off_t off; reopen("vcf.c", "test/hfile1.tmp"); while ((c = hgetc(fin)) != EOF) { if (hputc(c, fout) == EOF) fail("hputc"); } if (herrno(fin)) { errno = herrno(fin); fail("hgetc"); } reopen("test/hfile1.tmp", "test/hfile2.tmp"); if (hpeek(fin, buffer, 50) < 0) fail("hpeek"); while ((n = hread(fin, buffer, 17)) > 0) { if (hwrite(fout, buffer, n) != n) fail("hwrite"); } if (n < 0) fail("hread"); reopen("test/hfile2.tmp", "test/hfile3.tmp"); while ((n = hread(fin, buffer, sizeof buffer)) > 0) { if (hwrite(fout, buffer, n) != n) fail("hwrite"); if (hpeek(fin, buffer, 700) < 0) fail("hpeek"); } if (n < 0) fail("hread"); reopen("test/hfile3.tmp", "test/hfile4.tmp"); i = 0; off = 0; while ((n = hread(fin, buffer, size[i++ % 5])) > 0) { off += n; buffer[n] = '\0'; check_offset(fin, off, "pre-peek"); if (hputs(buffer, fout) == EOF) fail("hputs"); if ((n = hpeek(fin, buffer, size[(i+3) % 5])) < 0) fail("hpeek"); check_offset(fin, off, "post-peek"); } if (n < 0) fail("hread"); reopen("test/hfile4.tmp", "test/hfile5.tmp"); n = hread(fin, buffer, 200); if (n < 0) fail("hread"); else if (n != 200) fail("hread only got %d", (int)n); if (hwrite(fout, buffer, 1000) != 1000) fail("hwrite"); check_offset(fin, 200, "input/first200"); check_offset(fout, 1000, "output/first200"); if (hseek(fin, 800, SEEK_CUR) < 0) fail("hseek/cur"); check_offset(fin, 1000, "input/seek"); for (off = 1000; (n = hread(fin, buffer, sizeof buffer)) > 0; off += n) if (hwrite(fout, buffer, n) != n) fail("hwrite"); if (n < 0) fail("hread"); check_offset(fin, off, "input/eof"); check_offset(fout, off, "output/eof"); if (hseek(fin, 200, SEEK_SET) < 0) fail("hseek/set"); if (hseek(fout, 200, SEEK_SET) < 0) fail("hseek(output)"); check_offset(fin, 200, "input/backto200"); check_offset(fout, 200, "output/backto200"); n = hread(fin, buffer, 800); if (n < 0) fail("hread"); else if (n != 800) fail("hread only got %d", (int)n); if (hwrite(fout, buffer, 800) != 800) fail("hwrite"); check_offset(fin, 1000, "input/wrote800"); check_offset(fout, 1000, "output/wrote800"); if (hflush(fout) == EOF) fail("hflush"); original = slurp("vcf.c"); for (i = 1; i <= 5; i++) { char *text; sprintf(buffer, "test/hfile%d.tmp", i); text = slurp(buffer); if (strcmp(original, text) != 0) { fprintf(stderr, "%s differs from vcf.c\n", buffer); return EXIT_FAILURE; } free(text); } free(original); if (hclose(fin) != 0) fail("hclose(input)"); if (hclose(fout) != 0) fail("hclose(output)"); fout = hopen("test/hfile_chars.tmp", "w"); if (fout == NULL) fail("hopen(\"test/hfile_chars.tmp\")"); for (i = 0; i < 256; i++) if (hputc(i, fout) != i) fail("chars: hputc (%d)", i); if (hclose(fout) != 0) fail("hclose(test/hfile_chars.tmp)"); fin = hopen("test/hfile_chars.tmp", "r"); if (fin == NULL) fail("hopen(\"test/hfile_chars.tmp\") for reading"); for (i = 0; i < 256; i++) if ((c = hgetc(fin)) != i) fail("chars: hgetc (%d = 0x%x) returned %d = 0x%x", i, i, c, c); if ((c = hgetc(fin)) != EOF) fail("chars: hgetc (EOF) returned %d", c); if (hclose(fin) != 0) fail("hclose(test/hfile_chars.tmp) for reading"); fin = hopen("data:hello, world!\n", "r"); if (fin == NULL) fail("hopen(\"data:...\")"); n = hread(fin, buffer, 300); if (n < 0) fail("hread"); buffer[n] = '\0'; if (strcmp(buffer, "hello, world!\n") != 0) fail("hread result"); if (hclose(fin) != 0) fail("hclose(\"data:...\")"); return EXIT_SUCCESS; }
/* * Reads a version 3 CRAM file and replaces the header in-place, * provided the header is small enough to fit without growing the * entire file. * * Version 3 format has a SAM header held as an (optionally) * compressed block within the header container. Additional * uncompressed blocks or simply unallocated space (the difference * between total block sizes and the container size) are used to * provide room for growth or contraction of the compressed header. * * Returns 0 on success; * -1 on general failure; * -2 on failure due to insufficient size */ int cram_reheader_inplace3(cram_fd *fd, const bam_hdr_t *h, const char *arg_list, int add_PG) { cram_container *c = NULL; cram_block *b = NULL; SAM_hdr *hdr = NULL; off_t start, sz, end; int container_sz, max_container_sz; char *buf = NULL; int ret = -1; if (cram_major_vers(fd) < 2 || cram_major_vers(fd) > 3) { fprintf(stderr, "[%s] unsupported CRAM version %d\n", __func__, cram_major_vers(fd)); goto err; } if (!(hdr = sam_hdr_parse_(h->text, h->l_text))) goto err; if (add_PG && sam_hdr_add_PG(hdr, "samtools", "VN", samtools_version(), arg_list ? "CL": NULL, arg_list ? arg_list : NULL, NULL)) goto err; int header_len = sam_hdr_length(hdr); /* Fix M5 strings? Maybe out of scope for this tool */ // Find current size of SAM header block if ((start = hseek(cram_fd_get_fp(fd), 26, SEEK_SET)) != 26) goto err; if (!(c = cram_read_container(fd))) goto err; // +5 allows num_landmarks to increase from 0 to 1 (Cramtools) max_container_sz = cram_container_size(c)+5; sz = htell(cram_fd_get_fp(fd)) + cram_container_get_length(c) - start; end = htell(cram_fd_get_fp(fd)) + cram_container_get_length(c); // We force 1 block instead of (optionally) 2. C CRAM // implementations for v3 were writing 1 compressed block followed // by 1 uncompressed block. However this is tricky to deal with // as changing block sizes can mean the block header also changes // size due to itf8 and variable size integers. // // If we had 1 block, this doesn't change anything. // If we had 2 blocks, the new container header will be smaller by // 1+ bytes, requiring the cram_container_get_length(c) to be larger in value. // However this is an int32 instead of itf8 so the container // header structure stays the same size. This means we can always // reduce the number of blocks without running into size problems. cram_container_set_num_blocks(c, 1); int32_t *landmark; int32_t num_landmarks; landmark = cram_container_get_landmarks(c, &num_landmarks); if (num_landmarks && landmark) { num_landmarks = 1; landmark[0] = 0; } else { num_landmarks = 0; } cram_container_set_landmarks(c, num_landmarks, landmark); buf = malloc(max_container_sz); container_sz = max_container_sz; if (cram_store_container(fd, c, buf, &container_sz) != 0) goto err; if (!buf) goto err; // Proposed new length, but changing cram_container_get_length(c) may change the // container_sz and thus the remainder (cram_container_get_length(c) itself). cram_container_set_length(c, sz - container_sz); int old_container_sz = container_sz; container_sz = max_container_sz; if (cram_store_container(fd, c, buf, &container_sz) != 0) goto err; if (old_container_sz != container_sz) { fprintf(stderr, "Quirk of fate makes this troublesome! " "Please use non-inplace version.\n"); goto err; } // Version 3.0 supports compressed header b = cram_new_block(FILE_HEADER, 0); int32_put_blk(b, header_len); cram_block_append(b, sam_hdr_str(hdr), header_len); cram_block_update_size(b); cram_compress_block(fd, b, NULL, -1, -1); if (hseek(cram_fd_get_fp(fd), 26, SEEK_SET) != 26) goto err; if (cram_block_size(b) > cram_container_get_length(c)) { fprintf(stderr, "New header will not fit. Use non-inplace version" " (%d > %d)\n", (int)cram_block_size(b), cram_container_get_length(c)); ret = -2; goto err; } if (cram_write_container(fd, c) == -1) goto err; if (cram_write_block(fd, b) == -1) goto err; // Blank out the remainder int rsz = end - htell(cram_fd_get_fp(fd)); assert(rsz >= 0); if (rsz) { char *rem = calloc(1, rsz); ret = hwrite(cram_fd_get_fp(fd), rem, rsz) == rsz ? 0 : -1; free(rem); } err: if (c) cram_free_container(c); if (buf) free(buf); if (b) cram_free_block(b); if (hdr) sam_hdr_free(hdr); return ret; }
/* * Reads a version 2 CRAM file and replaces the header in-place, * provided the header is small enough to fit without growing the * entire file. * * Version 2 format has an uncompressed SAM header with multiple nul * termination bytes to permit inline header editing. * * Returns 0 on success; * -1 on general failure; * -2 on failure due to insufficient size */ int cram_reheader_inplace2(cram_fd *fd, const bam_hdr_t *h, const char *arg_list, int add_PG) { cram_container *c = NULL; cram_block *b = NULL; SAM_hdr *hdr = NULL; off_t start; int ret = -1; if (cram_major_vers(fd) < 2 || cram_major_vers(fd) > 3) { fprintf(stderr, "[%s] unsupported CRAM version %d\n", __func__, cram_major_vers(fd)); goto err; } if (!(hdr = sam_hdr_parse_(h->text, h->l_text))) goto err; if (add_PG && sam_hdr_add_PG(hdr, "samtools", "VN", samtools_version(), arg_list ? "CL": NULL, arg_list ? arg_list : NULL, NULL)) goto err; int header_len = sam_hdr_length(hdr); /* Fix M5 strings? Maybe out of scope for this tool */ // Load the existing header if ((start = hseek(cram_fd_get_fp(fd), 26, SEEK_SET)) != 26) goto err; if (!(c = cram_read_container(fd))) goto err; // Version 2.1 has a single uncompressed block which is nul // terminated with many nuls to permit growth. // // So load old block and keep all contents identical bar the // header text itself if (!(b = cram_read_block(fd))) goto err; if (cram_block_get_uncomp_size(b) < header_len+4) { fprintf(stderr, "New header will not fit. Use non-inplace version (%d > %d)\n", header_len+4, cram_block_get_uncomp_size(b)); ret = -2; goto err; } cram_block_set_offset(b, 0); // rewind block int32_put_blk(b, header_len); cram_block_append(b, sam_hdr_str(hdr), header_len); // Zero the remaining block memset(cram_block_get_data(b)+cram_block_get_offset(b), 0, cram_block_get_uncomp_size(b) - cram_block_get_offset(b)); // Make sure all sizes and byte-offsets are consistent after memset cram_block_set_offset(b, cram_block_get_uncomp_size(b)); cram_block_set_comp_size(b, cram_block_get_uncomp_size(b)); if (hseek(cram_fd_get_fp(fd), start, SEEK_SET) != start) goto err; if (cram_write_container(fd, c) == -1) goto err; if (cram_write_block(fd, b) == -1) goto err; ret = 0; err: if (c) cram_free_container(c); if (b) cram_free_block(b); if (hdr) sam_hdr_free(hdr); return ret; }
struct crypto777_packet *crypto777_packet(struct crypto777_link *conn,uint32_t *timestamp,uint8_t *msg,int32_t len,int32_t leverage,int32_t maxmillis,uint64_t dest64bits) { static uint32_t rseed = 1234; uint64_t hit = SAMHIT_LIMIT; int32_t defnumrounds=NUMROUNDS_NONCE,numrounds,codersize,netsize,allocsize = MAX_UDPSIZE; struct crypto777_packet *bufs; struct SaMhdr *hdr; bits384 checksig; if ( *timestamp == 0 ) *timestamp = (uint32_t)time(NULL); netsize = (allocsize - 2*sizeof(uint32_t)); if ( conn->my64bits == conn->send.nxt64bits && conn->recv.nxt64bits == dest64bits && memcmp(conn->send.prevmsg,msg,len) == 0 && *timestamp == conn->send.prevtimestamp ) while ( conn->send.prevtimestamp == time(NULL) ) msleep(250), fprintf(stderr,". "), *timestamp = (uint32_t)time(NULL); if ( Debuglevel > 0 ) printf("(%llu %llu) packet.(%s) timestamp.%u [%llx] len.%d -> %llu\n",(long long)conn->send.nxt64bits,(long long)conn->recv.nxt64bits,(conn->send.nxt64bits != dest64bits) ? (char *)&msg[sizeof(struct SaMhdr)] : "ENCRYPTED",*timestamp,*(long long *)msg,len,(long long)dest64bits); codersize = (sizeof(*bufs->coder) + sizeof(uint16_t)*(0x100 + 2)); bufs = calloc(1,sizeof(struct crypto777_packet) + codersize + (2 * sizeof(struct crypto777_bits)) + (sizeof(struct SaMhdr) + len) + MAX_CRYPTO777_MSG); //bufs->DL.ptr = bufs; bufs->coder = (struct ramcoder *)bufs->space, memset(bufs->coder,0,codersize); bufs->plaintext = (struct crypto777_bits *)&bufs->space[codersize], _init_HUFF(&bufs->plainH,netsize,bufs->plaintext->bits); bufs->encrypted = &bufs->plaintext[1], _init_HUFF(&bufs->encryptedH,netsize,&bufs->encrypted->bits); bufs->origmsg = (uint8_t *)&bufs->plaintext[2]; bufs->recvbuf = &bufs->origmsg[sizeof(struct SaMhdr) + len]; // must be last! if ( dest64bits != 0 && conn->send.nxt64bits != 0 ) calc_sha256cat(bufs->coderseed.bytes,(uint8_t *)timestamp,sizeof(*timestamp),conn->shared_curve25519.bytes,sizeof(conn->shared_curve25519)); bufs->encrypted->plaintext_timestamp = bufs->plaintext->plaintext_timestamp = *timestamp; bufs->origlen = len; //printf("hdr.%ld len.%d\n",sizeof(struct SaMhdr),len); if ( conn->recv.nxt64bits == dest64bits && maxmillis > 0 ) { hdr = (struct SaMhdr *)bufs->origmsg; memcpy(&bufs->origmsg[sizeof(*hdr)],msg,len); hdr->timestamp = *timestamp, hdr->leverage = leverage, hdr->numrounds = defnumrounds; bufs->threshold = SaM_threshold(leverage); len += (int32_t)(sizeof(*hdr) - sizeof(hdr->sig)); //printf("+= %d | %ld = (%ld - %ld)\n",len,sizeof(*hdr) - sizeof(hdr->sig),sizeof(*hdr),sizeof(hdr->sig)); /*if ( (hit = SaMnonce(&hdr->sig,&hdr->nonce,&bufs->origmsg[sizeof(hdr->sig)],len,bufs->threshold,rseed,maxmillis)) == 0 ) { printf("crypto777_packet cant find nonce: numrounds.%d leverage.%d\n",hdr->numrounds,leverage); free(bufs); return(0); }*/printf("deprecated SaMnonce\n"); while ( 1 ) sleep(60); if ( Debuglevel > 0 ) printf(">>>>>>>>>>>> outbound timestamp.%u nonce.%u hit.%llu (%s) | sig.%llx\n",hdr->timestamp,hdr->nonce,(long long)hit,&bufs->origmsg[sizeof(*hdr)],(long long)hdr->sig.txid); rseed = (uint32_t)(hdr->sig.txid ^ hit); len += sizeof(hdr->sig); if ( dest64bits != 0 ) { ramcoder_encoder(bufs->coder,1,bufs->origmsg,len,&bufs->plainH,&bufs->coderseed); if ( (bufs->newlen= hconv_bitlen(bufs->plainH.bitoffset)) >= bufs->plainH.allocsize ) { printf("crypto777_packet overflow: newlen.%d doesnt fit into %d\n",bufs->newlen,bufs->plainH.allocsize); free(bufs); return(0); } else _randombytes(&bufs->plainH.buf[bufs->newlen],bufs->plainH.allocsize - bufs->newlen,(uint32_t)hdr->sig.txid); if ( dest64bits != 0 ) crypto777_encrypt(&bufs->encryptedH,&bufs->plainH,netsize,&conn->send,*timestamp); } conn->send.prevlen = bufs->origlen, memcpy(conn->send.prevmsg,msg,bufs->origlen), conn->send.prevtimestamp = *timestamp; } else if ( conn->send.nxt64bits == dest64bits && milliseconds() > conn->recv.blacklist ) { if ( dest64bits != 0 ) { if ( dest64bits != 0 ) memcpy(bufs->encryptedH.buf,msg,len), crypto777_encrypt(&bufs->plainH,&bufs->encryptedH,len,&conn->recv,*timestamp); else memcpy(bufs->plainH.buf,msg,len); hseek(&bufs->plainH,len << 3,SEEK_SET), hrewind(&bufs->plainH); bufs->recvlen = ramcoder_decoder(bufs->coder,1,bufs->recvbuf,len,&bufs->plainH,&bufs->coderseed); } else memcpy(bufs->recvbuf,msg,len), bufs->recvlen = len; hdr = (struct SaMhdr *)bufs->recvbuf; leverage = hdr->leverage, numrounds = hdr->numrounds; if ( Debuglevel > 0 ) printf("<<<<<<<< nonce.%u len.%d leverage.%d numrounds.%d\n",hdr->nonce,len,leverage,(int)numrounds); if ( leverage < CRYPTO777_MAXLEVERAGE && numrounds == defnumrounds ) { bufs->threshold = SaM_threshold(leverage); len = bufs->recvlen - sizeof(hdr->sig); hit = SaM(&checksig,&bufs->recvbuf[sizeof(hdr->sig)],len,0,0); len -= (sizeof(*hdr) - sizeof(hdr->sig)); if ( hit >= bufs->threshold || memcmp(checksig.bytes,hdr->sig.bytes,sizeof(checksig)) != 0 ) { conn->recv.blacklist = (milliseconds() + 10000); printf("crypto777_packet invalid AUTH: hit %llu >= threshold.%llu || sig mismatch.%d (%llx v %llx) from %llu leverage.%d numrounds.%d\n",(long long)hit,(long long)bufs->threshold,memcmp(checksig.bytes,hdr->sig.bytes,sizeof(checksig)),(long long)checksig.txid,(long long)hdr->sig.txid,(long long)conn->recv.nxt64bits,hdr->leverage,hdr->numrounds); free(bufs); return(0); } else if ( Debuglevel > 0 ) printf("AUTHENTICATED packet from %llu len.%d leverage.%d numrounds.%d | hit %.2f%%\n",(long long)conn->recv.nxt64bits,len,leverage,numrounds,100.*(double)hit/bufs->threshold); } else printf("AUTH failure from %llu: hit.%llu >= threshold.%llu leverage.%d numrounds.%d\n",(long long)conn->recv.nxt64bits,(long long)hit,(long long)bufs->threshold,leverage,numrounds); } else printf("crypto777_packet warning invalid dest64bits %llu\n",(long long)dest64bits); return(bufs); }