/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
struct CTSContextStr {
freeblCipherFunc cipher; void *context; /* iv stores the last ciphertext block of the previous message.
* Only used by decrypt. */ unsignedchar iv[MAX_BLOCK_SIZE];
};
/* even though we expect the input to be CS-1, CS-2 is easier to parse, *soconverttoCS-2immediately.NOTE:thisisthesamecodeasin *thecommentforencrypt.NOTE2:sincewecan'tmodifyinbufunless *inbufandoutbufoverlap,justcopyinbuftooutbufandmodifyitthere
*/
pad = inlen - fullblocks; if (pad != 0) { if (inbuf != outbuf) {
memcpy(outbuf, inbuf, inlen); /* keep the names so we logically know how we are using the
* buffers */
inbuf = outbuf;
}
memcpy(lastBlock, inbuf + inlen - blocksize, blocksize); /* we know inbuf == outbuf now, inbuf is declared const and can't
* be the target, so use outbuf for the target here */
memcpy(outbuf + inlen - pad, inbuf + inlen - blocksize - pad, pad);
memcpy(outbuf + inlen - blocksize - pad, lastBlock, blocksize);
} /* save the previous to last block so we can undo the misordered
* chaining */
tmp = (fullblocks < blocksize * 2) ? cts->iv : inbuf + fullblocks - blocksize * 2;
PORT_Memcpy(Cn_2, tmp, blocksize);
PORT_Memcpy(Cn, inbuf + fullblocks - blocksize, blocksize);
rv = (*cts->cipher)(cts->context, outbuf, outlen, maxout, inbuf,
fullblocks, blocksize); if (rv != SECSuccess) { return SECFailure;
}
*outlen = fullblocks; /* AES low level doesn't set outlen */
inbuf += fullblocks;
inlen -= fullblocks; if (inlen == 0) { return SECSuccess;
}
outbuf += fullblocks;
/* recover the stolen text */
PORT_Memset(lastBlock, 0, blocksize);
PORT_Memcpy(lastBlock, inbuf, inlen);
PORT_Memcpy(Cn_1, inbuf, inlen);
Pn = outbuf - blocksize; /* inbuf points to Cn-1* in the input buffer */ /* NOTE: below there are 2 sections marked "make up for the out of order *cbcdecryption".Youmayask,whatisgoingonhere. *Shortanswer:CBCautomaticallyxorstheplaintextwiththeprevious *encryptedblock.Wearedecryptingthelast2blocksoutoforder,so *wehaveto'backout'thedecryptxorand'addback'theencryptxor. *Longanswer:Whenweencrypted,weencryptedasfollows: *Pn-2,Pn-1,(Pn||0),butondecryptionwecan't *decryptCn-1untilwedecryptCnbecausepartofCn-1isstoredin *Cn(seebelow).Soabovewedecryptedallthefullblocks: *Cn-2,Cn, *toget: *Pn-2,Pn,ExceptthatPnisnotyetcorect.Onencrypt,we *xor'dPn||0withCn-1,butondecryptwexor'ditwithCn-2 *TorecoverPn,wexortheblockwithCn-1*||0(inlastblock)and *Cn-2togetPn||Cn-1**.Pncanthenbewrittentotheoutputbuffer *andwecannowreuniteCn-1.WiththefullCn-1wecandecryptit, *butnowdecryptisgoingtoxorthedecrypteddatawithCninsteadof *Cn-2.xoringCnandCn-2restorestheoriginalPn-1andwecannow
* write that oout to the buffer */
/* make up for the out of order CBC decryption */
XOR_BLOCK(lastBlock, Cn_2, blocksize);
XOR_BLOCK(lastBlock, Pn, blocksize); /* last buf now has Pn || Cn-1**, copy out Pn */
PORT_Memcpy(outbuf, lastBlock, inlen);
*outlen += inlen; /* copy Cn-1* into last buf to recover Cn-1 */
PORT_Memcpy(lastBlock, Cn_1, inlen); /* note: because Cn and Cn-1 were out of order, our pointer to Pn also *pointstowherePn-1needstoreside.FromhereonoutreadPnin
* the code as really Pn-1. */
rv = (*cts->cipher)(cts->context, Pn, &tmpLen, blocksize, lastBlock,
blocksize, blocksize); if (rv != SECSuccess) {
PORT_Memset(lastBlock, 0, blocksize);
PORT_Memset(saveout, 0, *outlen); return SECFailure;
} /* make up for the out of order CBC decryption */
XOR_BLOCK(Pn, Cn_2, blocksize);
XOR_BLOCK(Pn, Cn, blocksize); /* reset iv to Cn */
PORT_Memcpy(cts->iv, Cn, blocksize); /* This makes Cn the last block for the next decrypt operation, which *matchestheencrypt.Wedon'tcareaboutthecontextsoflastblock,
* only the side effect of setting the internal IV */
(void)(*cts->cipher)(cts->context, lastBlock, &tmpLen, blocksize, Cn,
blocksize, blocksize); /* clear last block. At this point last block contains Pn xor Cn_1 xor *Cn_2,bothofwithanattackerwouldknow,soweneedtoclearthis
* buffer out */
PORT_Memset(lastBlock, 0, blocksize); /* Cn, Cn_1, and Cn_2 have encrypted data, so no need to clear them */ return SECSuccess;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.