⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cbcmodem.nc

📁 传感器网络中的嵌入式操作系统源代码
💻 NC
📖 第 1 页 / 共 2 页
字号:
        return SUCCESS;      }            // else we know there are 2 or more blocks (though the last one may be a      // partial).      dumpBuffer( "CBC.decrypt cipher:", cipherBlock, numBytes);            // find the start of the last whole block:      bc = bsize;      while (bc  < numBytes) bc += bsize;      // and the block before it      bc -= (bsize << 1);      partialSize = numBytes - bc - bsize;            dbg (DBG_CRYPTO, "CBC.decrypt bc: %d; partial %d \n", bc, partialSize);      // split up the computation: depending on whether  the last block      // is full or not.       if (partialSize) {        // decrypt C_n        if (call BlockCipher.decrypt (&context->cc, cipherBlock + bc,                                      spillblock) != SUCCESS) {          return FAIL;        }        // recover C_{n-1}, [in spillblock2] and P_{n} [in spillblock]        for (i = 0; i < partialSize; i++) {          // bit convoluted for the case where we          // alias plainBlock and CipherBlock          spillblock[i] ^= cipherBlock [bc + bsize + i];          spillblock2[i] = cipherBlock[bc + bsize + i];          plainBlock[bc + bsize + i] = spillblock[i];        }        // copy over the remaining portion of the spillblock        for (i = partialSize; i < bsize; i++) {          spillblock2[i] = spillblock[i];        }        // and decrypt the spillblock (C_{n-1}) into position.        if (call BlockCipher.decrypt (&context->cc, spillblock2,                                      plainBlock + bc) != SUCCESS) {          return FAIL;        }        // NOW xor pref [iv or prev block]. We work from the end forward.        // that happens after the if / else        dumpBuffer ("CBC.decrypt partial", plainBlock, numBytes);      } else {        // bit simpler - just decrypt C_{n-1} into the spillblock        if (call BlockCipher.decrypt (&context->cc, cipherBlock + bc,                                      spillblock) != SUCCESS) {          return FAIL;        }        // xor to recover C_{n} and decrypt into place        for (i = 0; i < bsize; i++) {          spillblock[i] ^= cipherBlock[bc + i + bsize];        }        if (call BlockCipher.decrypt (&context->cc, cipherBlock + bc + bsize,                                      plainBlock + bc) != SUCCESS) {          return FAIL;        }        // copy P_{n-1} into place        for (i = 0; i < bsize; i++) {          plainBlock[bc + bsize + i] = spillblock[i];        }        // NOW xor prev [iv or prev block in]      }      // handle blocks 0.. n-2      // by xoring in the n-1 ciphertext and decrypting.      while (bc) {        bc -= bsize;        for (i = 0 ; i < bsize; i++) {          plainBlock [ bc + bsize + i] ^= cipherBlock [bc + i];        }        if (call BlockCipher.decrypt (&context->cc, cipherBlock + bc,                                      plainBlock + bc) != SUCCESS) {          return FAIL;        }      }      // xor the iv to recover P_0      for (i = 0 ; i < bsize; i++) {        plainBlock[i] ^= IV[i];      }      dumpBuffer( "CBC.decrypt cipher:", plainBlock, numBytes);            return SUCCESS;    }  /**   * Initializes the mode for an incremental decryption operation. This step   * is necessary for incremental decryption where the incoming data stream is   * processed a byte at a time and cipher operations are done as soon as   * possible. This is meant to allow for better overlapping of decryption   * with a slower process that receives the encrypted stream (say via the   * network ).   *   * This call may induce a block cipher call.      * @param context holds the module specific opaque data related to the   *        key (perhaps key expansions) and other internal state.   * @param IV The initialization vector that was used to encrypt this   *        particular data stream. This array must have a length equal to   *        one block size.   * @param The exact length of the data stream in bytes; this must be at   *        least the underlying block cipher size.   * @return Whether the initialization was successful. Possible failure   *        reasons include not calling init() or an underlying failure in the   *        block cipher.   */  async command result_t BlockCipherMode.initIncrementalDecrypt (						 CipherModeContext * context,						 uint8_t * IV,						 uint16_t length)    {      CBCModeContext * mcontext = (CBCModeContext*)(context->context);      if (!length) return SUCCESS;      if ( length < mcontext->bsize) return FAIL;            mcontext->remaining = length;      // decrypt the IV.       if (call BlockCipher.encrypt (&context->cc, IV, mcontext->spill1) !=                                    SUCCESS) {        return FAIL;      }      dumpBuffer ("E(IV)", mcontext->spill1, 8);      // prime the pump:      mcontext->offset = mcontext->completed = 0; // done amt      mcontext->accum = FALSE;      // figure out our state based on the amount of ciphertext that we're      // gonna get:      if (length == mcontext->bsize) {        mcontext->state = ONE_BLOCK;      } else if (length <= mcontext->bsize * 2) {        mcontext->state = TWO_LEFT_A;      } else {        mcontext->state = GENERAL;      }      return SUCCESS;    }  /**   * Performs an incremental decryption operation. It executes roughly one   * block cipher call for every block's worth of ciphertext provided, placing   * the result into the plaintext buffer. The done out parameter gives an   * indication of the amount of data that has been successfully been   * decrypted.   *   * @param context holds the module specific opaque data related to the   *        key (perhaps key expansions) and other internal state.   * @param ciphertext Pointer to the start of the next ciphertext buffer.   * @param plaintext Pointer to the start of the buffer which is large enough   *        to hold the entire ciphertext. This buffer must be passed in every   *        time to the incrementalDecrypt function.  After this call,   *        <i>done</i> bytes of the plaintext buffer will be available for   *        consumption.    * @param length The number of bytes that is being provided in the ciphertext   * @param done A pointer to an int which will be filled in after the call   *        completes with the number of bytes of plaintext which is   *        available.    * @return Whether the call was successful or not. Possible failure reasons   *        include not calling init(), an underlying failure in the block   *        cipher, or providing more ciphertext than is expected.   */  async command result_t BlockCipherMode.incrementalDecrypt (					       CipherModeContext * context,                                               uint8_t * cipher,                                               uint8_t * plain,                                               uint16_t length,                                               uint16_t * done)    {      CBCModeContext * mcontext = (CBCModeContext*)(context->context);      int i, j;      uint8_t * accum ;      uint8_t * lastCipher ;      uint8_t bsize = mcontext->bsize;      uint16_t completed = mcontext->completed;      // We run this deal as a simple state machine. See above for a diagram      // of states and their transitions.      // first, start with some simple checking:      dbg(DBG_CRYPTO, "CBCModeM:incrementalDecrypt: <entry>length %d\n",          length);      if (!length) { *done = mcontext->completed; return SUCCESS; }      if (length > mcontext->remaining) {        dbg(DBG_CRYPTO,"Fail 1\n"); return FAIL; }      while (length) {        // determine which is the accumulator and which contains the previous        // ciphertext. the accumulator is our temp storage space for the        // current ciphertext. once it gets full, we decrypt it.        if (mcontext->accum) {          accum = mcontext->spill1;          lastCipher = mcontext->spill2;        } else {          accum = mcontext->spill2;          lastCipher = mcontext->spill1;                }        // all but the TWO_LEFT_B state can use this common code to populate        // the accumulator witht he code from the ciphertext.        if (mcontext->state != TWO_LEFT_B) {          if (mcontext->offset + length < bsize) {            // this means we haven't filled up a block. so we copy into the            // accumulator, and update a few counters and ext.            dbg(DBG_CRYPTO, "incrementalDecrypt: Moved %d; 0 left this run\n",                length);              memcpy(accum + mcontext->offset, cipher, length);            *done = mcontext->completed = completed;            mcontext->offset += length;            mcontext->remaining -= length;            return SUCCESS;          }          // we can fill up a block's worth of data. so do so, update some          // state, and move on down to the appropriate state below.          j = bsize - mcontext->offset ;          memcpy(accum + mcontext->offset, cipher, j);                       dbg(DBG_CRYPTO, "incrementalDecrypt: Moved %d bytes; "                          "%d remaining this run\n", j, length - j);           mcontext->remaining -= j;          cipher += j;          length -= j;          mcontext->offset = 0;        }        // reaching this block indicates we have filled up the accumulator.        if (mcontext->state == ONE_BLOCK) {          // decrypt the one block:          dbg(DBG_CRYPTO, "CBCModeM: incrementalDecrypt. State ONE_BLOCK\n");          if (call BlockCipher.decrypt (&context->cc, accum,                                        plain) != SUCCESS) {            return FAIL;          }          // and xor with E(IV), which is stored in lastCipher.          for (i = 0; i < bsize; i++) {            plain[i] ^= lastCipher[i];          }          dumpBuffer ("plain", plain, 8);          // and fill in some stats and exit.          *done = mcontext->completed = bsize;          return SUCCESS;        }        if (mcontext->state == GENERAL) {          // we're in block i, where 0 <= i <= n-2          dbg(DBG_CRYPTO, "CBCModeM: incrementalDecrypt. State GENERAL\n");          // decrypt          if (call BlockCipher.decrypt (&context->cc, accum,                                        plain + completed) != SUCCESS) {	    dbg(DBG_CRYPTO,"Fail 3\n");            return FAIL;          }          // xor with the prev ciphertext          for (i = 0; i < bsize; i++) {            plain[i + completed] ^= lastCipher[i];          }          // update state:          completed += bsize;          mcontext->accum = !mcontext->accum;          // transition if there are only 2 blocks to go.          if (mcontext->remaining <= bsize * 2) {            mcontext->state = TWO_LEFT_A;            continue;          }        }        if (mcontext->state == TWO_LEFT_A) {          // two blocks to go, one after this stage completes.          // we have now accumulated C_n          dbg(DBG_CRYPTO, "CBCModeM: incrementalDecrypt. State 2LEFTA\n");          // decrypt. note we decrypt INTO the accumulator, which now holds          // C_{n-1}/+L ^ P_n || C_{n-1}/-L          // we need to wait to receive C_{n-1}/+L to recover P_n as well          // as C_{n-1}, which we'll then use to recover P_{n-1}          if (call BlockCipher.decrypt (&context->cc, accum, accum) !=                                                                     SUCCESS) {	    dbg(DBG_CRYPTO,"Fail 4\n");	    return FAIL;          }          // transition state:          mcontext->state = TWO_LEFT_B;          dbg(DBG_CRYPTO, "DBCModeM: ** Switched to state 2LEFTB "              "with %d remaining\n", mcontext->remaining);          continue;        }        if (mcontext->state == TWO_LEFT_B) {          // last block. this can't use the accum population code from          // above since it's a bit convoluted. recall from TWO_LEFT_A, that          // accum contains C_{n-1}/+L ^ P_n || C_{n-1}/-L          // cipher contains C_{n-1}+L          //          dbg(DBG_CRYPTO, "CBCModeM: incrementalDecrypt. State 2LEFTB\n");          j = mcontext->offset + length; // stop pos          // iterate over each block of cipher          for (i = mcontext->offset; i < j; i++) {            dbg(DBG_CRYPTO, "incrementalDecrypt:  %d %d\n", i, j);            // recover P_n            plain[completed + bsize + i] =              accum[i] ^ cipher[i-mcontext->offset];            // and set up accum to be C_{n-1}            accum[i] = cipher[i-mcontext->offset];          }          mcontext->remaining -= length;          if (mcontext->remaining) {            mcontext->offset += length;            length =0;          } else {            // if we've received all of C_{n-1}, decrypt it, which is            // P_{n-1} ^ C_{n-2}; C{n-2} conveniently lives in lastCipher,            // so we can xor to recover.            if (call BlockCipher.decrypt (&context->cc, accum,                                     plain + completed) != SUCCESS) {	      dbg(DBG_CRYPTO,"Fail 5\n");	      return FAIL;            }            for (i = 0; i < bsize; i++) {              plain[i + completed] ^= lastCipher[i];            }            // set some state.            mcontext->remaining = 0;            mcontext->completed +=              bsize + length + mcontext->offset;             *done = mcontext->completed;            return SUCCESS;          }        }      }      // and voilla! we're done.      *done = mcontext->completed = completed;      return SUCCESS;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -