3
$\begingroup$

I am trying to adapt the following function from SJCL, which does "AES-CCM" style CTR encryption, to do "pure CTR" encryption. I am playing around with SIV and would rather use this well-reviewed implementation rather than build my own CTR cipher from scratch. However, I'm having trouble understanding exactly what the CCM part does, and how I would go about modifying this routine to "strip out" the CCM functionality (the part that deals with the tag and the L parameter). My question is: what exactly is (are) the difference between the two CTR "styles", and how does that translate in the snippet below? Any help is appreciated.

_ctrMode: function(prf, data, iv, tag, tlen, L) {
  var enc, i, w=sjcl.bitArray, xor = w._xor4, ctr, b, l = data.length, bl=w.bitLength(data);

  // start the ctr
  ctr = w.concat([w.partial(8,L-1)],iv).concat([0,0,0]).slice(0,4);

  // en/decrypt the tag
  tag = w.bitSlice(xor(tag,prf.encrypt(ctr)), 0, tlen);

  // en/decrypt the data
  if (!l) { return {tag:tag, data:[]}; }

  for (i=0; i<l; i+=4) {
    ctr[3]++;
    enc = prf.encrypt(ctr);
    data[i]   ^= enc[0];
    data[i+1] ^= enc[1];
    data[i+2] ^= enc[2];
    data[i+3] ^= enc[3];
  }
  return { tag:tag, data:w.clamp(data,bl) };
}
$\endgroup$
3
  • $\begingroup$ Unfortunately there isn't one standard CTR mode, different protocols use different ways of combining the counter with the IV and incrementing it. $\endgroup$ Commented Apr 10, 2014 at 18:45
  • $\begingroup$ In this case the ctr is initialized with an array of 4 big-endian words, each 4 bytes in length. From what I can tell, this array is used a) to store the L parameter + the IV (up to 12 bytes) and b) to store the counter (4 bytes). Can I just replace the L+IV part with a 12-byte IV, keep the 4-byte counter and do away with all of the rest of the code that deals with authentication? $\endgroup$ Commented Apr 10, 2014 at 19:01
  • $\begingroup$ Is there a reason you're starting at this stage rather than trying to find an implementation of SIV directly? $\endgroup$ Commented Apr 10, 2014 at 22:21

1 Answer 1

2
$\begingroup$

The CTR part of CCM is basically the last for loop in the _ctrMode function:

  for (i=0; i<l; i+=4) {
    ctr[3]++;
    enc = prf.encrypt(ctr);
    data[i]   ^= enc[0];
    data[i+1] ^= enc[1];
    data[i+2] ^= enc[2];
    data[i+3] ^= enc[3];
  }

i.e. CTR is simply: encrypt a counter block with a block cipher, xor the encrypted block into the data, increment the counter, repeat...

(For those not used to the SJCL APIs, they tend to operate on 32 bit words rather than bytes).

As CodesInChaos mentions, while a CTR mode has been standardised (in NIST SP800-38A), 'CTR' is used as a component of a lot of other modes (e.g. CCM, GCM, SIV, EAX) and they differ substantially in how the initial counter is constructed (although most will follow the same basic approach once that is done).

$\endgroup$
2
  • 1
    $\begingroup$ Technically, a correct CTR implementation would have bounds checking for the size of the input block that is not populated by the nonce, or force the nonce to be 96 bits and only increment the remaining uInt32. We all know how many problems incorrect bounds checking can cause... $\endgroup$ Commented Apr 11, 2014 at 1:24
  • $\begingroup$ This was helpful re: "standard" CTR functionality: security.stackexchange.com/questions/4606/… $\endgroup$ Commented Apr 11, 2014 at 17:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.