Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(449)

Unified Diff: nss/lib/freebl/cts.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « nss/lib/freebl/cts.h ('k') | nss/lib/freebl/des.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: nss/lib/freebl/cts.c
diff --git a/nss/lib/freebl/cts.c b/nss/lib/freebl/cts.c
deleted file mode 100644
index 984e05b95071021fe5869ce305b7c3885015f832..0000000000000000000000000000000000000000
--- a/nss/lib/freebl/cts.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifdef FREEBL_NO_DEPEND
-#include "stubs.h"
-#endif
-#include "blapit.h"
-#include "blapii.h"
-#include "cts.h"
-#include "secerr.h"
-
-struct CTSContextStr {
- freeblCipherFunc cipher;
- void *context;
- /* iv stores the last ciphertext block of the previous message.
- * Only used by decrypt. */
- unsigned char iv[MAX_BLOCK_SIZE];
-};
-
-CTSContext *
-CTS_CreateContext(void *context, freeblCipherFunc cipher,
- const unsigned char *iv, unsigned int blocksize)
-{
- CTSContext *cts;
-
- if (blocksize > MAX_BLOCK_SIZE) {
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return NULL;
- }
- cts = PORT_ZNew(CTSContext);
- if (cts == NULL) {
- return NULL;
- }
- PORT_Memcpy(cts->iv, iv, blocksize);
- cts->cipher = cipher;
- cts->context = context;
- return cts;
-}
-
-void
-CTS_DestroyContext(CTSContext *cts, PRBool freeit)
-{
- if (freeit) {
- PORT_Free(cts);
- }
-}
-
-/*
- * See addemdum to NIST SP 800-38A
- * Generically handle cipher text stealing. Basically this is doing CBC
- * operations except someone can pass us a partial block.
- *
- * Output Order:
- * CS-1: C1||C2||C3..Cn-1(could be partial)||Cn (NIST)
- * CS-2: pad == 0 C1||C2||C3...Cn-1(is full)||Cn (Schneier)
- * CS-2: pad != 0 C1||C2||C3...Cn||Cn-1(is partial)(Schneier)
- * CS-3: C1||C2||C3...Cn||Cn-1(could be partial) (Kerberos)
- *
- * The characteristics of these three options:
- * - NIST & Schneier (CS-1 & CS-2) are identical to CBC if there are no
- * partial blocks on input.
- * - Scheier and Kerberos (CS-2 and CS-3) have no embedded partial blocks,
- * which make decoding easier.
- * - NIST & Kerberos (CS-1 and CS-3) have consistent block order independent
- * of padding.
- *
- * PKCS #11 did not specify which version to implement, but points to the NIST
- * spec, so this code implements CTS-CS-1 from NIST.
- *
- * To convert the returned buffer to:
- * CS-2 (Schneier): do
- * unsigned char tmp[MAX_BLOCK_SIZE];
- * pad = *outlen % blocksize;
- * if (pad) {
- * memcpy(tmp, outbuf+*outlen-blocksize, blocksize);
- * memcpy(outbuf+*outlen-pad,outbuf+*outlen-blocksize-pad, pad);
- * memcpy(outbuf+*outlen-blocksize-pad, tmp, blocksize);
- * }
- * CS-3 (Kerberos): do
- * unsigned char tmp[MAX_BLOCK_SIZE];
- * pad = *outlen % blocksize;
- * if (pad == 0) {
- * pad = blocksize;
- * }
- * memcpy(tmp, outbuf+*outlen-blocksize, blocksize);
- * memcpy(outbuf+*outlen-pad,outbuf+*outlen-blocksize-pad, pad);
- * memcpy(outbuf+*outlen-blocksize-pad, tmp, blocksize);
- */
-SECStatus
-CTS_EncryptUpdate(CTSContext *cts, unsigned char *outbuf,
- unsigned int *outlen, unsigned int maxout,
- const unsigned char *inbuf, unsigned int inlen,
- unsigned int blocksize)
-{
- unsigned char lastBlock[MAX_BLOCK_SIZE];
- unsigned int tmp;
- int fullblocks;
- int written;
- SECStatus rv;
-
- if (inlen < blocksize) {
- PORT_SetError(SEC_ERROR_INPUT_LEN);
- return SECFailure;
- }
-
- if (maxout < inlen) {
- *outlen = inlen;
- PORT_SetError(SEC_ERROR_OUTPUT_LEN);
- return SECFailure;
- }
- fullblocks = (inlen/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;
- }
- written = *outlen - (blocksize - inlen);
- outbuf += written;
- maxout -= written;
-
- /*
- * here's the CTS magic, we pad our final block with zeros,
- * then do a CBC encrypt. CBC will xor our plain text with
- * the previous block (Cn-1), capturing part of that block (Cn-1**) as it
- * xors with the zero pad. We then write this full block, overwritting
- * (Cn-1**) in our buffer. This allows us to have input data == output
- * data since Cn contains enough information to reconver Cn-1** when
- * we decrypt (at the cost of some complexity as you can see in decrypt
- * below */
- PORT_Memcpy(lastBlock, inbuf, inlen);
- PORT_Memset(lastBlock + inlen, 0, blocksize - inlen);
- rv = (*cts->cipher)(cts->context, outbuf, &tmp, maxout, lastBlock,
- blocksize, blocksize);
- PORT_Memset(lastBlock, 0, blocksize);
- if (rv == SECSuccess) {
- *outlen = written + blocksize;
- }
- return rv;
-}
-
-
-#define XOR_BLOCK(x,y,count) for(i=0; i < count; i++) x[i] = x[i] ^ y[i]
-
-/*
- * See addemdum to NIST SP 800-38A
- * Decrypt, Expect CS-1: input. See the comment on the encrypt side
- * to understand what CS-2 and CS-3 mean.
- *
- * To convert the input buffer to CS-1 from ...
- * CS-2 (Schneier): do
- * unsigned char tmp[MAX_BLOCK_SIZE];
- * pad = inlen % blocksize;
- * if (pad) {
- * memcpy(tmp, inbuf+inlen-blocksize-pad, blocksize);
- * memcpy(inbuf+inlen-blocksize-pad,inbuf+inlen-pad, pad);
- * memcpy(inbuf+inlen-blocksize, tmp, blocksize);
- * }
- * CS-3 (Kerberos): do
- * unsigned char tmp[MAX_BLOCK_SIZE];
- * pad = inlen % blocksize;
- * if (pad == 0) {
- * pad = blocksize;
- * }
- * memcpy(tmp, inbuf+inlen-blocksize-pad, blocksize);
- * memcpy(inbuf+inlen-blocksize-pad,inbuf+inlen-pad, pad);
- * memcpy(inbuf+inlen-blocksize, tmp, blocksize);
- */
-SECStatus
-CTS_DecryptUpdate(CTSContext *cts, unsigned char *outbuf,
- unsigned int *outlen, unsigned int maxout,
- const unsigned char *inbuf, unsigned int inlen,
- unsigned int blocksize)
-{
- unsigned char *Pn;
- unsigned char Cn_2[MAX_BLOCK_SIZE]; /* block Cn-2 */
- unsigned char Cn_1[MAX_BLOCK_SIZE]; /* block Cn-1 */
- unsigned char Cn[MAX_BLOCK_SIZE]; /* block Cn */
- unsigned char lastBlock[MAX_BLOCK_SIZE];
- const unsigned char *tmp;
- unsigned int tmpLen;
- unsigned int fullblocks, pad;
- unsigned int i;
- SECStatus rv;
-
- if (inlen < blocksize) {
- PORT_SetError(SEC_ERROR_INPUT_LEN);
- return SECFailure;
- }
-
- if (maxout < inlen) {
- *outlen = inlen;
- PORT_SetError(SEC_ERROR_OUTPUT_LEN);
- return SECFailure;
- }
-
- fullblocks = (inlen/blocksize)*blocksize;
-
- /* even though we expect the input to be CS-1, CS-2 is easier to parse,
- * so convert to CS-2 immediately. NOTE: this is the same code as in
- * the comment for encrypt. NOTE2: since we can't modify inbuf unless
- * inbuf and outbuf overlap, just copy inbuf to outbuf and modify it there
- */
- 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
- * cbc decryption". You may ask, what is going on here.
- * Short answer: CBC automatically xors the plain text with the previous
- * encrypted block. We are decrypting the last 2 blocks out of order, so
- * we have to 'back out' the decrypt xor and 'add back' the encrypt xor.
- * Long answer: When we encrypted, we encrypted as follows:
- * Pn-2, Pn-1, (Pn || 0), but on decryption we can't
- * decrypt Cn-1 until we decrypt Cn because part of Cn-1 is stored in
- * Cn (see below). So above we decrypted all the full blocks:
- * Cn-2, Cn,
- * to get:
- * Pn-2, Pn, Except that Pn is not yet corect. On encrypt, we
- * xor'd Pn || 0 with Cn-1, but on decrypt we xor'd it with Cn-2
- * To recover Pn, we xor the block with Cn-1* || 0 (in last block) and
- * Cn-2 to get Pn || Cn-1**. Pn can then be written to the output buffer
- * and we can now reunite Cn-1. With the full Cn-1 we can decrypt it,
- * but now decrypt is going to xor the decrypted data with Cn instead of
- * Cn-2. xoring Cn and Cn-2 restores the original Pn-1 and we can now
- * 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
- * points to where Pn-1 needs to reside. From here on out read Pn in
- * the code as really Pn-1. */
- rv = (*cts->cipher)(cts->context, Pn, &tmpLen, blocksize, lastBlock,
- blocksize, blocksize);
- if (rv != SECSuccess) {
- 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
- * matches the encrypt. We don't care about the contexts of last block,
- * 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, both of with an attacker would know, so we need to clear this
- * buffer out */
- PORT_Memset(lastBlock, 0, blocksize);
- /* Cn, Cn_1, and Cn_2 have encrypted data, so no need to clear them */
- return SECSuccess;
-}
« no previous file with comments | « nss/lib/freebl/cts.h ('k') | nss/lib/freebl/des.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698