/*SHELL-AES encryption for plaintexts with a length longer than one block but not a multiple of block length: parameters follow those of function shellaesEnc */ void shellaesEnc_nfb(const u8 key[], const u8 nonce[], const u8 ad[], unsigned long long int adlen, const u8 p[], unsigned long long int ptlen, u8 c[], u8 tag[]){ u8 V[16], U[16], checksum[16], F[16], keyprime[16], L[16], Lprime[16]; u8* S; u8* I; u8* Z; unsigned long long int pt_fblen; unsigned int pt_nfblen; pt_nfblen=ptlen%16; pt_fblen=ptlen-pt_nfblen; S= (u8 *) malloc(ptlen); I= (u8 *) malloc(ptlen); Z= (u8 *) malloc(pt_fblen); memset(V, 0, 16); memset(U, 0, 16); memset(checksum, 0, 16); memset(keyprime, 0, 16); memset(F, 0, 16); memset(L, 0, 16); memset(Lprime, 0, 16); u32 mk[4*d], sk[12*d], rk[44], rkprime[44]; /*key setup*/ aesKeySetupEnc(rk, key); KeySetupEnc(mk, sk, L, Lprime, keyprime, rk, key); aesKeySetupEnc(rkprime, keyprime); /*process the plaintext except the last non-full block*/ PXMAC(mk, sk, L, V, rk, ad, adlen); CENC(rkprime, S, F, nonce, ptlen); memcpy(I, p, ptlen); xor_byte_string(S, I, ptlen); checksum_state_string(I, checksum, pt_fblen); PXENC(mk, sk, L, V, Z, rk, I, pt_fblen); memcpy(U, V, 16); XEXLayerEnc(rk, Lprime, Z, c, pt_fblen); tagGen(rk, checksum, Lprime, U, F, tag, pt_fblen); /*XLS: process the last non-full block*/ XLS(rk, Lprime, p+pt_fblen, pt_fblen, pt_nfblen, c+pt_fblen, tag); /* printf("ciphertext is: \n"); printf_byte_string(c, ptlen); printf("tag value is: \n"); printf_byte_string(tag, 16); */ free(I); free(Z); free(S); }
/*SHELL-AES encryption for plaintexts of mutiple blocks long: parameters follow those of function shellaesEnc */ void shellaesEnc_fb(const u8 key[], const u8 nonce[], const u8 ad[], unsigned long long int adlen, const u8 p[], unsigned long long int ptlen, u8 c[], u8 tag[]){ u8 V[16], U[16], checksum[16], F[16], keyprime[16], L[16], Lprime[16]; u8* S; u8* I; u8* Z; S= (u8 *) malloc(ptlen); I= (u8 *) malloc(ptlen); Z= (u8 *) malloc(ptlen); memset(V, 0, 16); memset(U, 0, 16); memset(checksum, 0, 16); memset(keyprime, 0, 16); memset(F, 0, 16); memset(L, 0, 16); memset(Lprime, 0, 16); u32 mk[4*d], sk[12*d], rk[44], rkprime[44]; /* key setup */ aesKeySetupEnc(rk, key); KeySetupEnc(mk, sk, L, Lprime, keyprime, rk, key); aesKeySetupEnc(rkprime, keyprime); /*PXMAC: process associated data, and save output to V[]*/ PXMAC(mk, sk, L, V, rk, ad, adlen); /*CENC: process nonce, and save output to S[] and F[]*/ CENC(rkprime, S, F, nonce, ptlen); /*mask plaintext by xoring the output S[] of CENC, and save it to I[]*/ memcpy(I, S, ptlen); xor_byte_string(p, I, ptlen); /*PXENC: save outputs to Z[] and U[] */ PXENC(mk, sk, L, V, Z, rk, I, ptlen); memcpy(U, V, 16); /*XEX: produce the ciphertext*/ XEXLayerEnc(rk, Lprime, Z, c, ptlen); /*generate tag*/ checksum_state_string(I, checksum, ptlen); tagGen(rk, checksum, Lprime, U, F, tag, ptlen); /* printf("ciphertext is: \n"); printf_byte_string(c, ptlen); printf("tag value is: \n"); printf_byte_string(tag, 16); */ free(I); free(Z); free(S); }
static void entryInit(Entry *e) { e->gen = 0; e->dsize = bsize; e->psize = bsize/VtEntrySize*VtEntrySize; e->flags = VtEntryActive; e->depth = 0; e->size = 0; memmove(e->score, vtZeroScore, VtScoreSize); e->tag = tagGen(); e->snap = 0; e->archive = 0; }
/* * Change the depth of the source r. * The entry e for r is contained in block p. */ static int sourceGrowDepth(Source *r, Block *p, Entry *e, int depth) { Block *b, *bb; uint32_t tag; int type; Entry oe; assert(sourceIsLocked(r)); assert(depth <= VtPointerDepth); type = entryType(e); b = cacheGlobal(r->fs->cache, e->score, type, e->tag, OReadWrite); if(b == nil) return 0; tag = e->tag; if(tag == 0) tag = tagGen(); oe = *e; /* * Keep adding layers until we get to the right depth * or an error occurs. */ while(e->depth < depth) { bb = cacheAllocBlock(r->fs->cache, type+1, tag, r->fs->ehi, r->fs->elo); if(bb == nil) break; //fprint(2, "alloc %lux grow %V\n", bb->addr, b->score); memmove(bb->data, b->score, VtScoreSize); memmove(e->score, bb->score, VtScoreSize); e->depth++; type++; e->tag = tag; e->flags |= VtEntryLocal; blockDependency(bb, b, 0, vtZeroScore, nil); blockPut(b); b = bb; blockDirty(b); } entryPack(e, p->data, r->offset % r->epb); blockDependency(p, b, r->offset % r->epb, nil, &oe); blockPut(b); blockDirty(p); return e->depth == depth; }
/*verify the validness of the tag T[]*/ int tagVef(const u32 rk[], const u8 checksum[], const u8 Lprime[], const u8 U[], const u8 F[], const u8 T[], unsigned long long int ptlen){ u8 tempT[16]; int flag=1; int i; tagGen(rk, checksum, Lprime, U, F, tempT, ptlen); for(i=0; i<16; ++i){ if(tempT[i]!=T[i]){ flag=0; } } return flag; }
/*SHELL-AES decryption for plaintexts with a length longer than one block but not a multiple of block length: shellaesDec_fb is used to decrypt of the ciphertext without the last non-full block; parameters follow those of function shellaesEnc */ void shellaesDec_fb(const u8 key[], const u8 nonce[], const u8 ad[], unsigned long long int adlen, const u8 c[], unsigned long long int ctlen, u8 p[], u8 tag[]){ u8 V[16], U[16], checksum[16], keyprime[16], F[16], L[16], Lprime[16]; u8* S; u8* I; u8* Z; S=(u8 *) malloc(ctlen); I=(u8 *) malloc(ctlen); Z=(u8 *) malloc(ctlen); memset(V, 0, 16); memset(U, 0, 16); memset(checksum, 0, 16); memset(keyprime, 0, 16); memset(F, 0, 16); memset(L, 0, 16); memset(Lprime, 0, 16); u32 mk[4*d], sk[12*d], isk[12*d], rk[44], irk[44], rkprime[44]; aesKeySetupEnc(rk, key); aesKeySetupDec(irk, key); KeySetupDec(mk, sk, isk, L, Lprime, keyprime, rk, key); aesKeySetupEnc(rkprime, keyprime); PXMAC(mk, sk, L, V, rk, ad, adlen); XEXLayerDec(irk, Lprime, c, Z, ctlen); PXDEC(mk, isk, L, V, Z, rk, I, ctlen); memcpy(U, V, 16); checksum_state_string(I, checksum, ctlen); CENC(rkprime, S, F, nonce, ctlen); memcpy(p, S, ctlen); xor_byte_string(I, p, ctlen); tagGen(rk, checksum, Lprime, U, F, tag, ctlen); free(I); free(S); free(Z); }
static void rootMetaInit(Entry *e) { u32int addr; u32int tag; DirEntry de; MetaBlock mb; MetaEntry me; memset(&de, 0, sizeof(de)); de.elem = vtStrDup("root"); de.entry = 0; de.gen = 0; de.mentry = 1; de.mgen = 0; de.size = 0; de.qid = qid++; de.uid = vtStrDup("adm"); de.gid = vtStrDup("adm"); de.mid = vtStrDup("adm"); de.mtime = time(0); de.mcount = 0; de.ctime = time(0); de.atime = time(0); de.mode = ModeDir | 0555; tag = tagGen(); addr = blockAlloc(BtData, tag); /* build up meta block */ memset(buf, 0, bsize); mbInit(&mb, buf, bsize, bsize/100); me.size = deSize(&de); me.p = mbAlloc(&mb, me.size); assert(me.p != nil); dePack(&de, &me); mbInsert(&mb, 0, &me); mbPack(&mb); blockWrite(PartData, addr); deCleanup(&de); /* build up entry for meta block */ entryInit(e); e->flags |= VtEntryLocal; e->size = bsize; e->tag = tag; localToGlobal(addr, e->score); }
static u32int rootInit(Entry *e) { ulong addr; u32int tag; tag = tagGen(); addr = blockAlloc(BtDir, tag); memset(buf, 0, bsize); /* root meta data is in the third entry */ entryPack(e, buf, 2); entryInit(e); e->flags |= VtEntryDir; entryPack(e, buf, 0); entryInit(e); entryPack(e, buf, 1); blockWrite(PartData, addr); entryInit(e); e->flags |= VtEntryLocal|VtEntryDir; e->size = VtEntrySize*3; e->tag = tag; localToGlobal(addr, e->score); addr = blockAlloc(BtDir, RootTag); memset(buf, 0, bsize); entryPack(e, buf, 0); blockWrite(PartData, addr); return addr; }
/*SHELL-AES decryption for ciphertexts with a length longer than one block but not a multiple of block length: parameters follow those of function shellaesEnc */ int shellaesDec_nfb(const u8 key[], const u8 nonce[], const u8 ad[], unsigned long long int adlen, const u8 c[], unsigned long long int ctlen, u8 p[], const u8 tag[]){ u8 V[16], U[16], checksum[16], F[16], keyprime[16], L[16], Lprime[16]; u8* S; u8* I; u8* Z; u8 tempTag[16], tempTag2[16]; int i, flag; unsigned long long int ct_fblen; unsigned int ct_nfblen; ct_nfblen=ctlen%16; ct_fblen=ctlen-ct_nfblen; S= (u8 *) malloc(ctlen); I= (u8 *) malloc(ctlen); Z= (u8 *) malloc(ct_fblen); memset(V, 0, 16); memset(U, 0, 16); memset(checksum, 0, 16); memset(keyprime, 0, 16); memset(F, 0, 16); memset(L, 0, 16); memset(Lprime, 0, 16); u32 mk[4*d], sk[12*d], isk[12*d], rk[44], irk[44], rkprime[44]; /*setup key*/ aesKeySetupEnc(rk, key); aesKeySetupDec(irk, key); KeySetupDec(mk, sk, isk, L, Lprime, keyprime, rk, key); aesKeySetupEnc(rkprime, keyprime); /*decrypt the last non-full block*/ memcpy(tempTag, tag, 16); XLSInv(irk, Lprime, c+ct_fblen, ct_fblen, ct_nfblen, p+ct_fblen, tempTag); /*process associated data*/ PXMAC(mk, sk, L, V, rk, ad, adlen); /*decryption of XEX layer*/ XEXLayerDec(irk, Lprime, c, Z, ct_fblen); /*decryption of PXENC layer*/ PXDEC(mk, isk, L, V, Z, rk, I, ct_fblen); memcpy(U, V, 16); /*process nonce*/ CENC(rkprime, S, F, nonce, ctlen); /*produce plaintext*/ memcpy(p, I, ct_fblen); xor_byte_string(S, p, ct_fblen); /*verify the validness of tag*/ checksum_state_string(I, checksum, ct_fblen); tagGen(rk, checksum, Lprime, U, F, tempTag2, ct_fblen); flag=1; for(i=0; i<16; ++i){ if(tempTag[i]!=tempTag2[i]){ flag=0; } } /* if(flag){ printf("the plaintext is: \n"); printf_byte_string(p, ctlen); } else{ printf("the tag is invalid!"); } */ return flag; }
static u32int ventiRoot(char *host, char *s) { int i, n; uchar score[VtScoreSize]; u32int addr, tag; DirEntry de; MetaBlock mb; MetaEntry me; Entry e; VtRoot root; if(!parseScore(score, s)) vtFatal("bad score '%s'", s); if((z = vtDial(host, 0)) == nil || !vtConnect(z, nil)) vtFatal("connect to venti: %R"); tag = tagGen(); addr = blockAlloc(BtDir, tag); ventiRead(score, VtRootType); if(!vtRootUnpack(&root, buf)) vtFatal("corrupted root: vtRootUnpack"); n = ventiRead(root.score, VtDirType); /* * Fossil's vac archives start with an extra layer of source, * but vac's don't. */ if(n <= 2*VtEntrySize){ if(!entryUnpack(&e, buf, 0)) vtFatal("bad root: top entry"); n = ventiRead(e.score, VtDirType); } /* * There should be three root sources (and nothing else) here. */ for(i=0; i<3; i++){ if(!entryUnpack(&e, buf, i) || !(e.flags&VtEntryActive) || e.psize < 256 || e.dsize < 256) vtFatal("bad root: entry %d", i); fprint(2, "%V\n", e.score); } if(n > 3*VtEntrySize) vtFatal("bad root: entry count"); blockWrite(PartData, addr); /* * Maximum qid is recorded in root's msource, entry #2 (conveniently in e). */ ventiRead(e.score, VtDataType); if(!mbUnpack(&mb, buf, bsize)) vtFatal("bad root: mbUnpack"); meUnpack(&me, &mb, 0); if(!deUnpack(&de, &me)) vtFatal("bad root: dirUnpack"); if(!de.qidSpace) vtFatal("bad root: no qidSpace"); qid = de.qidMax; /* * Recreate the top layer of source. */ entryInit(&e); e.flags |= VtEntryLocal|VtEntryDir; e.size = VtEntrySize*3; e.tag = tag; localToGlobal(addr, e.score); addr = blockAlloc(BtDir, RootTag); memset(buf, 0, bsize); entryPack(&e, buf, 0); blockWrite(PartData, addr); return addr; }
static int sourceShrinkDepth(Source *r, Block *p, Entry *e, int depth) { Block *b, *nb, *ob, *rb; uint32_t tag; int type, d; Entry oe; assert(sourceIsLocked(r)); assert(depth <= VtPointerDepth); type = entryType(e); rb = cacheGlobal(r->fs->cache, e->score, type, e->tag, OReadWrite); if(rb == nil) return 0; tag = e->tag; if(tag == 0) tag = tagGen(); /* * Walk down to the new root block. * We may stop early, but something is better than nothing. */ oe = *e; ob = nil; b = rb; /* BUG: explain type++. i think it is a real bug */ for(d=e->depth; d > depth; d--, type++) { nb = cacheGlobal(r->fs->cache, b->data, type-1, tag, OReadWrite); if(nb == nil) break; if(ob!=nil && ob!=rb) blockPut(ob); ob = b; b = nb; } if(b == rb) { blockPut(rb); return 0; } /* * Right now, e points at the root block rb, b is the new root block, * and ob points at b. To update: * * (i) change e to point at b * (ii) zero the pointer ob -> b * (iii) free the root block * * p (the block containing e) must be written before * anything else. */ /* (i) */ e->depth = d; /* might have been local and now global; reverse cannot happen */ if(globalToLocal(b->score) == NilBlock) e->flags &= ~VtEntryLocal; memmove(e->score, b->score, VtScoreSize); entryPack(e, p->data, r->offset % r->epb); blockDependency(p, b, r->offset % r->epb, nil, &oe); blockDirty(p); /* (ii) */ memmove(ob->data, vtZeroScore, VtScoreSize); blockDependency(ob, p, 0, b->score, nil); blockDirty(ob); /* (iii) */ if(rb->addr != NilBlock) blockRemoveLink(p, rb->addr, rb->l.type, rb->l.tag, 1); blockPut(rb); if(ob!=nil && ob!=rb) blockPut(ob); blockPut(b); return d == depth; }
static Block * blockWalk(Block *p, int index, int mode, Fs *fs, Entry *e) { Block *b; Cache *c; uint32_t addr; int type; uint8_t oscore[VtScoreSize], score[VtScoreSize]; Entry oe; c = fs->cache; if((p->l.type & BtLevelMask) == 0) { assert(p->l.type == BtDir); type = entryType(e); b = cacheGlobal(c, e->score, type, e->tag, mode); } else { type = p->l.type - 1; b = cacheGlobal(c, p->data + index*VtScoreSize, type, e->tag, mode); } if(b) b->pc = getcallerpc(&p); if(b == nil || mode == OReadOnly) return b; if(p->l.epoch != fs->ehi) { fprint(2, "blockWalk: parent not writable\n"); abort(); } if(b->l.epoch == fs->ehi) return b; oe = *e; /* * Copy on write. */ if(e->tag == 0) { assert(p->l.type == BtDir); e->tag = tagGen(); e->flags |= VtEntryLocal; } addr = b->addr; b = blockCopy(b, e->tag, fs->ehi, fs->elo); if(b == nil) return nil; b->pc = getcallerpc(&p); assert(b->l.epoch == fs->ehi); blockDirty(b); memmove(score, b->score, VtScoreSize); if(p->l.type == BtDir) { memmove(e->score, b->score, VtScoreSize); entryPack(e, p->data, index); blockDependency(p, b, index, nil, &oe); } else { memmove(oscore, p->data+index*VtScoreSize, VtScoreSize); memmove(p->data+index*VtScoreSize, b->score, VtScoreSize); blockDependency(p, b, index, oscore, nil); } blockDirty(p); if(addr != NilBlock) blockRemoveLink(p, addr, type, e->tag, 0); return b; }