Пример #1
0
/** Terminate the chain
  @param cfb    The CFB chain to terminate
  @return CRYPT_OK on success
*/
int cfb_done(symmetric_CFB *cfb)
{
   int err;
   LTC_ARGCHK(cfb != NULL);

   if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
      return err;
   }
   cipher_descriptor[cfb->cipher].done(&cfb->key);
   return CRYPT_OK;
}
Пример #2
0
/**
   Terminate the hash to get the digest
   @param md   The hash state
   @param out [out] The destination of the hash (length of the block size of the block cipher)
   @return CRYPT_OK if successful
*/
int chc_done(hash_state *md, unsigned char *out)
{
    int err;

    LTC_ARGCHK(md   != NULL);
    LTC_ARGCHK(out  != NULL);

    /* is the cipher valid? */
    if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) {
       return err;
    }
    if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) {
       return CRYPT_INVALID_CIPHER;
    }

    if (md->chc.curlen >= sizeof(md->chc.buf)) {
       return CRYPT_INVALID_ARG;
    }

    /* increase the length of the message */
    md->chc.length += md->chc.curlen * 8;

    /* append the '1' bit */
    md->chc.buf[md->chc.curlen++] = (unsigned char)0x80;

    /* if the length is currently above l-8 bytes we append zeros
     * then compress.  Then we can fall back to padding zeros and length
     * encoding like normal.
     */
    if (md->chc.curlen > (unsigned long)(cipher_blocksize - 8)) {
        while (md->chc.curlen < (unsigned long)cipher_blocksize) {
            md->chc.buf[md->chc.curlen++] = (unsigned char)0;
        }
        chc_compress(md, md->chc.buf);
        md->chc.curlen = 0;
    }

    /* pad upto l-8 bytes of zeroes */
    while (md->chc.curlen < (unsigned long)(cipher_blocksize - 8)) {
        md->chc.buf[md->chc.curlen++] = (unsigned char)0;
    }

    /* store length */
    STORE64L(md->chc.length, md->chc.buf+(cipher_blocksize-8));
    chc_compress(md, md->chc.buf);

    /* copy output */
    XMEMCPY(out, md->chc.state, cipher_blocksize);

#ifdef LTC_CLEAN_STACK
    zeromem(md, sizeof(hash_state));
#endif
    return CRYPT_OK;
}
Пример #3
0
/** Terminate the chain
  @param ofb    The OFB chain to terminate
  @return CRYPT_OK on success
*/
INT ofb_done(symmetric_OFB *ofb)
{
   INT err;
   LTC_ARGCHK(ofb != NULL);

   if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) {
      return err;
   }
   cipher_descriptor[ofb->cipher].done(&ofb->key);
   return CRYPT_OK;
}
Пример #4
0
/**
   Initialize a CTR context
   @param cipher      The index of the cipher desired
   @param IV          The initial vector
   @param key         The secret key 
   @param keylen      The length of the secret key (octets)
   @param num_rounds  Number of rounds in the cipher desired (0 for default)
   @param ctr_mode    The counter mode (CTR_COUNTER_LITTLE_ENDIAN or CTR_COUNTER_BIG_ENDIAN)
   @param ctr         The CTR state to initialize
   @return CRYPT_OK if successful
*/
int ctr_start(               int   cipher, 
              const unsigned char *IV, 
              const unsigned char *key,       int keylen, 
                             int  num_rounds, int ctr_mode,
                   symmetric_CTR *ctr)
{
   int x, err;

   LTC_ARGCHK(IV  != NULL);
   LTC_ARGCHK(key != NULL);
   LTC_ARGCHK(ctr != NULL);

   /* bad param? */
   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
      return err;
   }

   /* setup cipher */
   if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) {
      return err;
   }

   /* copy ctr */
   ctr->blocklen = cipher_descriptor[cipher].block_length;
   ctr->cipher   = cipher;
   ctr->padlen   = 0;
   ctr->mode     = ctr_mode & 1;
   for (x = 0; x < ctr->blocklen; x++) {
       ctr->ctr[x] = IV[x];
   }

   if (ctr_mode & LTC_CTR_RFC3686) {
      /* increment the IV as per RFC 3686 */
      if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) {
         /* little-endian */
         for (x = 0; x < ctr->blocklen; x++) {
             ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
             if (ctr->ctr[x] != (unsigned char)0) {
                break;
             }
         }
      } else {
         /* big-endian */
         for (x = ctr->blocklen-1; x >= 0; x--) {
             ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
             if (ctr->ctr[x] != (unsigned char)0) {
                break;
             }
         }
      }
   }

   return cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key); 
}
Пример #5
0
int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen)
{
   unsigned long n, x;
   int           err;

   LTC_ARGCHK(omac  != NULL);
   LTC_ARGCHK(in    != NULL);
   if ((err = cipher_is_valid(omac->cipher_idx)) != CRYPT_OK) {
      return err;
   }

   if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) ||
       (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) {
      return CRYPT_INVALID_ARG;
   }

#ifdef LTC_FAST
   if (omac->buflen == 0 && inlen > 16) {
      int y;
      for (x = 0; x < (inlen - 16); x += 16) {
          for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
              *((LTC_FAST_TYPE*)(&omac->prev[y])) ^= *((LTC_FAST_TYPE*)(&in[y]));
          }
          in += 16;
          if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->prev, omac->prev, &omac->key)) != CRYPT_OK) {
             return err;
          }
      }
      inlen -= x;
    }
#endif

   while (inlen != 0) { 
       /* ok if the block is full we xor in prev, encrypt and replace prev */
       if (omac->buflen == omac->blklen) {
          for (x = 0; x < (unsigned long)omac->blklen; x++) {
              omac->block[x] ^= omac->prev[x];
          }
          if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->block, omac->prev, &omac->key)) != CRYPT_OK) {
             return err;
          }
          omac->buflen = 0;
       }

       /* add bytes */
       n = MIN(inlen, (unsigned long)(omac->blklen - omac->buflen));
       XMEMCPY(omac->block + omac->buflen, in, n);
       omac->buflen  += n;
       inlen         -= n;
       in            += n;
   }

   return CRYPT_OK;
}
Пример #6
0
/** Terminate the chain
  @param f8    The F8 chain to terminate
  @return CRYPT_OK on success
*/
int f8_done(symmetric_F8 *f8)
{
   int err;
   LTC_ARGCHK(f8 != NULL);

   if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) {
      return err;
   }
   cipher_descriptor[f8->cipher].done(&f8->key);
   return CRYPT_OK;
}
Пример #7
0
/** Terminate the chain
  @param ecb    The ECB chain to terminate
  @return CRYPT_OK on success
*/
int ecb_done(symmetric_ECB *ecb)
{
   int err;
   LTC_ARGCHK(ecb != NULL);

   if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
      return err;
   }
   cipher_descriptor[ecb->cipher].done(&ecb->key);
   return CRYPT_OK;
}
Пример #8
0
/**
   Initialize an F8 context
   @param cipher      The index of the cipher desired
   @param IV          The initial vector
   @param key         The secret key 
   @param keylen      The length of the secret key (octets)
   @param salt_key    The salting key for the IV
   @param skeylen     The length of the salting key (octets)
   @param num_rounds  Number of rounds in the cipher desired (0 for default)
   @param f8          The F8 state to initialize
   @return CRYPT_OK if successful
*/
int f8_start(                int  cipher, const unsigned char *IV, 
             const unsigned char *key,                    int  keylen, 
             const unsigned char *salt_key,               int  skeylen,
                             int  num_rounds,   symmetric_F8  *f8)
{
   int           x, err;
   unsigned char tkey[MAXBLOCKSIZE];

   LTC_ARGCHK(IV       != NULL);
   LTC_ARGCHK(key      != NULL);
   LTC_ARGCHK(salt_key != NULL);
   LTC_ARGCHK(f8       != NULL);

   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
      return err;
   }

   /* copy details */
   f8->blockcnt = 0;
   f8->cipher   = cipher;
   f8->blocklen = cipher_descriptor[cipher].block_length;
   f8->padlen   = f8->blocklen;
   
   /* now get key ^ salt_key [extend salt_ket with 0x55 as required to match length] */
   zeromem(tkey, sizeof(tkey));
   for (x = 0; x < keylen && x < (int)sizeof(tkey); x++) {
       tkey[x] = key[x];
   }
   for (x = 0; x < skeylen && x < (int)sizeof(tkey); x++) {
       tkey[x] ^= salt_key[x];
   }       
   for (; x < keylen && x < (int)sizeof(tkey); x++) {
       tkey[x] ^= 0x55;
   }
   
   /* now encrypt with tkey[0..keylen-1] the IV and use that as the IV */
   if ((err = cipher_descriptor[cipher].setup(tkey, keylen, num_rounds, &f8->key)) != CRYPT_OK) {
      return err;
   }
   
   /* encrypt IV */
   if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(IV, f8->MIV, &f8->key)) != CRYPT_OK) {
      cipher_descriptor[f8->cipher].done(&f8->key);
      return err;
   }
   zeromem(tkey, sizeof(tkey));
   zeromem(f8->IV, sizeof(f8->IV));
   
   /* terminate this cipher */
   cipher_descriptor[f8->cipher].done(&f8->key);
   
   /* init the cipher */
   return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &f8->key);
}
Пример #9
0
/** Terminate the chain
  @param cbc    The CBC chain to terminate
  @return CRYPT_OK on success
*/
INT cbc_done(symmetric_CBC *cbc)
{
   INT err;
   LTC_ARGCHK(cbc != NULL);

   if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
      return err;
   }
   cipher_descriptor[cbc->cipher].done(&cbc->key);
   return CRYPT_OK;
}
Пример #10
0
/**
  CTR encrypt
  @param pt     Plaintext
  @param ct     [out] Ciphertext
  @param len    Length of plaintext (octets)
  @param ctr    CTR state
  @return CRYPT_OK if successful
*/
int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)
{
   unsigned long incr;
   int err;

   LTC_ARGCHK(pt != NULL);
   LTC_ARGCHK(ct != NULL);
   LTC_ARGCHK(ctr != NULL);

   if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
       return err;
   }

   /* is blocklen/padlen valid? */
   if (ctr->blocklen < 1 || ctr->blocklen > (int)sizeof(ctr->ctr) ||
       ctr->padlen   < 0 || ctr->padlen   > (int)sizeof(ctr->pad)) {
      return CRYPT_INVALID_ARG;
   }

#ifdef LTC_FAST
   if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) {
      return CRYPT_INVALID_ARG;
   }
#endif

   if (cipher_descriptor[ctr->cipher]->accel_ctr_encrypt != NULL ) {
     /* handle acceleration only if not in the middle of a block, accelerator is present and length is >= a block size */
     if ((ctr->padlen == 0 || ctr->padlen == ctr->blocklen) && len >= (unsigned long)ctr->blocklen) {
       if ((err = cipher_descriptor[ctr->cipher]->accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) {
         return err;
       }
       pt += (len / ctr->blocklen) * ctr->blocklen;
       ct += (len / ctr->blocklen) * ctr->blocklen;
       len %= ctr->blocklen;
       /* counter was changed by accelerator so mark pad empty (will need updating in ctr_encrypt_sub()) */
       ctr->padlen = ctr->blocklen;
     }

     /* try to re-synchronize on a block boundary for maximum use of acceleration */
     incr = ctr->blocklen - ctr->padlen;
     if (len >= incr + (unsigned long)ctr->blocklen) {
       if ((err = ctr_encrypt_sub(pt, ct, incr, ctr)) != CRYPT_OK) {
         return err;
       }
       pt += incr;
       ct += incr;
       len -= incr;
       return ctr_encrypt(pt, ct, len, ctr);
     }
   }

   return ctr_encrypt_sub(pt, ct, len, ctr);
}
Пример #11
0
/**
  Terminate an OMAC stream
  @param omac   The OMAC state
  @param out    [out] Destination for the authentication tag
  @param outlen [in/out]  The max size and resulting size of the authentication tag
  @return CRYPT_OK if successful
*/
int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen)
{
   int       err, mode;
   unsigned  x;

   LTC_ARGCHK(omac   != NULL);
   LTC_ARGCHK(out    != NULL);
   LTC_ARGCHK(outlen != NULL);
   if ((err = cipher_is_valid(omac->cipher_idx)) != CRYPT_OK) {
      return err;
   }

   if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) ||
       (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) {
      return CRYPT_INVALID_ARG;
   }

   /* figure out mode */
   if (omac->buflen != omac->blklen) {
      /* add the 0x80 byte */
      omac->block[omac->buflen++] = 0x80;

      /* pad with 0x00 */
      while (omac->buflen < omac->blklen) {
         omac->block[omac->buflen++] = 0x00;
      }
      mode = 1;
   } else {
      mode = 0;
   }

   /* now xor prev + Lu[mode] */
   for (x = 0; x < (unsigned)omac->blklen; x++) {
       omac->block[x] ^= omac->prev[x] ^ omac->Lu[mode][x];
   }

   /* encrypt it */
   if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->block, omac->block, &omac->key)) != CRYPT_OK) {
      return err;
   }
   cipher_descriptor[omac->cipher_idx].done(&omac->key);
 
   /* output it */
   for (x = 0; x < (unsigned)omac->blklen && x < *outlen; x++) {
       out[x] = omac->block[x];
   }
   *outlen = x;

#ifdef LTC_CLEAN_STACK
   zeromem(omac, sizeof(*omac));
#endif
   return CRYPT_OK;
}
Пример #12
0
/**
  ECB encrypt
  @param pt     Plaintext
  @param ct     [out] Ciphertext
  @param ecb    ECB state
  @return CRYPT_OK if successful
*/
int ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ECB *ecb)
{
   int err;
   LTC_ARGCHK(pt != NULL);
   LTC_ARGCHK(ct != NULL);
   LTC_ARGCHK(ecb != NULL);

   if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
       return err;
   }
   cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key);
   return CRYPT_OK;
}
Пример #13
0
/**
  Terminate a LRW state
  @param lrw   The state to terminate
  @return CRYPT_OK if successful
*/
int lrw_done(symmetric_LRW *lrw)
{
   int err;

   LTC_ARGCHK(lrw != NULL);

   if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) {
      return err;
   }
   cipher_descriptor[lrw->cipher].done(&lrw->key);

   return CRYPT_OK;
}
Пример #14
0
/**
   Initialize a ECB context
   @param cipher      The index of the cipher desired
   @param key         The secret key 
   @param keylen      The length of the secret key (octets)
   @param num_rounds  Number of rounds in the cipher desired (0 for default)
   @param ecb         The ECB state to initialize
   @return CRYPT_OK if successful
*/
int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb)
{
   int err;
   LTC_ARGCHK(key != NULL);
   LTC_ARGCHK(ecb != NULL);

   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
      return err;
   }
   ecb->cipher = cipher;
   ecb->blocklen = cipher_descriptor[cipher].block_length;
   return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ecb->key);
}
Пример #15
0
/**
  Initialize a CCM state
  @param ccm     The CCM state to initialize
  @param cipher  The index of the cipher to use
  @param key     The secret key
  @param keylen  The length of the secret key
  @param ptlen   The length of the plain/cipher text that will be processed
  @param taglen  The max length of the MAC tag
  @param aadlen  The length of the AAD

  @return CRYPT_OK on success
 */
int ccm_init(ccm_state *ccm, int cipher,
             const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen)
{
   int            err;

   LTC_ARGCHK(ccm    != NULL);
   LTC_ARGCHK(key    != NULL);
   LTC_ARGCHK(taglen != 0);

   XMEMSET(ccm, 0, sizeof(ccm_state));

   /* check cipher input */
   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
      return err;
   }
   if (cipher_descriptor[cipher].block_length != 16) {
      return CRYPT_INVALID_CIPHER;
   }

   /* make sure the taglen is even and <= 16 */
   ccm->taglen = taglen;
   ccm->taglen &= ~1;
   if (ccm->taglen > 16) {
      ccm->taglen = 16;
   }

   /* can't use < 4 */
   if (ccm->taglen < 4) {
      return CRYPT_INVALID_ARG;
   }

   /* schedule key */
   if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ccm->K)) != CRYPT_OK) {
      return err;
   }
   ccm->cipher = cipher;

   /* let's get the L value */
   ccm->ptlen = ptlen;
   ccm->L   = 0;
   while (ptlen) {
      ++ccm->L;
      ptlen >>= 8;
   }
   if (ccm->L <= 1) {
      ccm->L = 2;
   }

   ccm->aadlen = aadlen;
   return CRYPT_OK;
}
Пример #16
0
/**
  Terminate a GCM stream
  @param gcm     The GCM state
  @param tag     [out] The destination for the MAC tag
  @param taglen  [in/out]  The length of the MAC tag
  @return CRYPT_OK on success
 */
int gcm_done(gcm_state *gcm, 
                     unsigned char *tag,    unsigned long *taglen)
{
   unsigned long x;
   int err;

   LTC_ARGCHK(gcm     != NULL);
   LTC_ARGCHK(tag     != NULL);
   LTC_ARGCHK(taglen  != NULL);

   if (gcm->buflen > 16 || gcm->buflen < 0) {
      return CRYPT_INVALID_ARG;
   }

   if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) {
      return err;
   }


   if (gcm->mode != LTC_GCM_MODE_TEXT) {
      return CRYPT_INVALID_ARG;
   }

   /* handle remaining ciphertext */
   if (gcm->buflen) {
      gcm->pttotlen += gcm->buflen * CONST64(8);
      gcm_mult_h(gcm, gcm->X);
   }

   /* length */
   STORE64H(gcm->totlen, gcm->buf);
   STORE64H(gcm->pttotlen, gcm->buf+8);
   for (x = 0; x < 16; x++) {
       gcm->X[x] ^= gcm->buf[x];
   }
   gcm_mult_h(gcm, gcm->X);

   /* encrypt original counter */
   if ((err = cipher_descriptor[gcm->cipher]->ecb_encrypt(gcm->Y_0, gcm->buf, &gcm->K)) != CRYPT_OK) {
      return err;
   }
   for (x = 0; x < 16 && x < *taglen; x++) {
       tag[x] = gcm->buf[x] ^ gcm->X[x];
   }
   *taglen = x;

   cipher_descriptor[gcm->cipher]->done(&gcm->K);

   return CRYPT_OK;
}
Пример #17
0
/**
   LTC_OMAC a block of memory 
   @param cipher    The index of the desired cipher
   @param key       The secret key
   @param keylen    The length of the secret key (octets)
   @param in        The data to send through LTC_OMAC
   @param inlen     The length of the data to send through LTC_OMAC (octets)
   @param out       [out] The destination of the authentication tag
   @param outlen    [in/out]  The max size and resulting size of the authentication tag (octets)
   @return CRYPT_OK if successful
*/
int omac_memory(int cipher, 
                const unsigned char *key, unsigned long keylen,
                const unsigned char *in,  unsigned long inlen,
                      unsigned char *out, unsigned long *outlen)
{
   int err;
   omac_state *omac;

   LTC_ARGCHK(key    != NULL);
   LTC_ARGCHK(in     != NULL);
   LTC_ARGCHK(out    != NULL);
   LTC_ARGCHK(outlen != NULL);

   /* is the cipher valid? */
   if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
      return err;
   }

   /* Use accelerator if found */
   if (cipher_descriptor[cipher].omac_memory != NULL) {
      return cipher_descriptor[cipher].omac_memory(key, keylen, in, inlen, out, outlen);
   }

   /* allocate ram for omac state */
   omac = XMALLOC(sizeof(omac_state));
   if (omac == NULL) {
      return CRYPT_MEM;
   }

   /* omac process the message */
   if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) {
      goto LBL_ERR;
   }
   if ((err = omac_process(omac, in, inlen)) != CRYPT_OK) {
      goto LBL_ERR;
   }
   if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) {
      goto LBL_ERR;
   }

   err = CRYPT_OK;
LBL_ERR:
#ifdef LTC_CLEAN_STACK
   zeromem(omac, sizeof(omac_state));
#endif

   XFREE(omac);
   return err;   
}
Пример #18
0
int pmac_done(pmac_state *state, unsigned char *out, unsigned long *outlen)
{
   int err, x;

   LTC_ARGCHK(state != NULL);
   LTC_ARGCHK(out   != NULL);
   if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) {
      return err;
   }

   if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) ||
       (state->block_len > (int)sizeof(state->block)) || (state->buflen > state->block_len)) {
      return CRYPT_INVALID_ARG;
   }


   /* handle padding.  If multiple xor in L/x */

   if (state->buflen == state->block_len) {
      /* xor Lr against the checksum */
      for (x = 0; x < state->block_len; x++) {
          state->checksum[x] ^= state->block[x] ^ state->Lr[x];
      }
   } else {
      /* otherwise xor message bytes then the 0x80 byte */
      for (x = 0; x < state->buflen; x++) {
          state->checksum[x] ^= state->block[x];
      }
      state->checksum[x] ^= 0x80;
   }

   /* encrypt it */
   if ((err = cipher_descriptor[state->cipher_idx].ecb_encrypt(state->checksum, state->checksum, &state->key)) != CRYPT_OK) {
      return err;
   }
   cipher_descriptor[state->cipher_idx].done(&state->key);

   /* store it */
   for (x = 0; x < state->block_len && x < (int)*outlen; x++) {
       out[x] = state->checksum[x];
   }
   *outlen = x;

#ifdef LTC_CLEAN_STACK
   zeromem(state, sizeof(*state));
#endif
   return CRYPT_OK;
}
Пример #19
0
/**
  CTR encrypt
  @param pt     Plaintext
  @param ct     [out] Ciphertext
  @param len    Length of plaintext (octets)
  @param ctr    CTR state
  @return CRYPT_OK if successful
*/
int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)
{
   int err, fr;

   LTC_ARGCHK(pt != NULL);
   LTC_ARGCHK(ct != NULL);
   LTC_ARGCHK(ctr != NULL);

   if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
       return err;
   }

   /* is blocklen/padlen valid? */
   if ((ctr->blocklen < 1) || (ctr->blocklen > (int)sizeof(ctr->ctr)) ||
       (ctr->padlen   < 0) || (ctr->padlen   > (int)sizeof(ctr->pad))) {
      return CRYPT_INVALID_ARG;
   }

#ifdef LTC_FAST
   if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) {
      return CRYPT_INVALID_ARG;
   }
#endif

   /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */
   if ((cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL) && (len >= (unsigned long)ctr->blocklen)) {
     if (ctr->padlen < ctr->blocklen) {
       fr = ctr->blocklen - ctr->padlen;
       if ((err = _ctr_encrypt(pt, ct, fr, ctr)) != CRYPT_OK) {
          return err;
       }
       pt += fr;
       ct += fr;
       len -= fr;
     }

     if (len >= (unsigned long)ctr->blocklen) {
       if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) {
          return err;
       }
       pt += (len / ctr->blocklen) * ctr->blocklen;
       ct += (len / ctr->blocklen) * ctr->blocklen;
       len %= ctr->blocklen;
     }
   }

   return _ctr_encrypt(pt, ct, len, ctr);
}
Пример #20
0
/**
  Set the IV for LRW
  @param IV      The IV, must be 16 octets
  @param len     Length ... must be 16 :-)
  @param lrw     The LRW state to update
  @return CRYPT_OK if successful
*/
int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw)
{
   int           err;
#ifdef LTC_LRW_TABLES
   unsigned char T[16];
   int           x, y;
#endif
   LTC_ARGCHK(IV != NULL);
   LTC_ARGCHK(lrw != NULL);

   if (len != 16) {
      return CRYPT_INVALID_ARG;
   }

   if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) {
      return err;
   }

   /* copy the IV */
   XMEMCPY(lrw->IV, IV, 16);

   /* check if we have to actually do work */
   if (cipher_descriptor[lrw->cipher].accel_lrw_encrypt != NULL && cipher_descriptor[lrw->cipher].accel_lrw_decrypt != NULL) {
       /* we have accelerators, let's bail since they don't use lrw->pad anyways */
       return CRYPT_OK;
   }

#ifdef LTC_LRW_TABLES
   XMEMCPY(T, &lrw->PC[0][IV[0]][0], 16);
   for (x = 1; x < 16; x++) {
#ifdef LTC_FAST
       for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) {
           *((LTC_FAST_TYPE *)(T + y)) ^= *((LTC_FAST_TYPE *)(&lrw->PC[x][IV[x]][y]));
       }
#else
       for (y = 0; y < 16; y++) {
           T[y] ^= lrw->PC[x][IV[x]][y];
       }
#endif
   }
   XMEMCPY(lrw->pad, T, 16);
#else
   gcm_gf_mult(lrw->tweak, IV, lrw->pad);
#endif

   return CRYPT_OK;
}
Пример #21
0
/**
   Process a block of memory though the hash
   @param md   The hash state
   @param in   The data to hash
   @param inlen  The length of the data (octets)
   @return CRYPT_OK if successful
*/
int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen)
{
   int err;

   LTC_ARGCHK(md   != NULL);
   LTC_ARGCHK(in  != NULL);

   /* is the cipher valid? */
   if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) {
      return err;
   }
   if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) {
      return CRYPT_INVALID_CIPHER;
   }

   return _chc_process(md, in, inlen);
}
Пример #22
0
/** Process data through f9-MAC
  @param f9       The f9-MAC state
  @param in       Input data to process
  @param inlen    Length of input in octets
  Return CRYPT_OK on success
*/
int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen)
{
   int err, x;

   LTC_ARGCHK(f9 != NULL);
   LTC_ARGCHK(in   != NULL);

   /* check structure */
   if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) {
      return err;
   }

   if ((f9->blocksize > cipher_descriptor[f9->cipher].block_length) || (f9->blocksize < 0) ||
       (f9->buflen > f9->blocksize) || (f9->buflen < 0)) {
      return CRYPT_INVALID_ARG;
   }

#ifdef LTC_FAST
   if (f9->buflen == 0) {
       while (inlen >= (unsigned long)f9->blocksize) {
           for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) {
              *((LTC_FAST_TYPE*)&(f9->IV[x])) ^= *((LTC_FAST_TYPE*)&(in[x]));
           }
           cipher_descriptor[f9->cipher].ecb_encrypt(f9->IV, f9->IV, &f9->key);
           for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) {
              *((LTC_FAST_TYPE*)&(f9->ACC[x])) ^= *((LTC_FAST_TYPE*)&(f9->IV[x]));
           }
           in    += f9->blocksize;
           inlen -= f9->blocksize;
       }
  }
#endif

   while (inlen) {
     if (f9->buflen == f9->blocksize) {
         cipher_descriptor[f9->cipher].ecb_encrypt(f9->IV, f9->IV, &f9->key);
         for (x = 0; x < f9->blocksize; x++) {
            f9->ACC[x] ^= f9->IV[x];
         }
         f9->buflen = 0;
     }
     f9->IV[f9->buflen++] ^= *in++;
     --inlen;
  }
  return CRYPT_OK;       
}
Пример #23
0
/**
  Decrypt a block with OCB.
  @param ocb    The OCB state
  @param ct     The ciphertext (length of the block size of the block cipher)
  @param pt     [out] The plaintext (length of ct)
  @return CRYPT_OK if successful
*/
int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt)
{
   unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE];
   int err, x;

   LTC_ARGCHK(ocb != NULL);
   LTC_ARGCHK(pt  != NULL);
   LTC_ARGCHK(ct  != NULL);

   /* check if valid cipher */
   if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
      return err;
   }
   LTC_ARGCHK(cipher_descriptor[ocb->cipher].ecb_decrypt != NULL);

   /* check length */
   if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) {
      return CRYPT_INVALID_ARG;
   }

   /* Get Z[i] value */
   ocb_shift_xor(ocb, Z);

   /* xor ct in, encrypt, xor Z out */
   for (x = 0; x < ocb->block_len; x++) {
       tmp[x] = ct[x] ^ Z[x];
   }
   if ((err = cipher_descriptor[ocb->cipher].ecb_decrypt(tmp, pt, &ocb->key)) != CRYPT_OK) {
      return err;
   }
   for (x = 0; x < ocb->block_len; x++) {
       pt[x] ^= Z[x];
   }

   /* compute checksum */
   for (x = 0; x < ocb->block_len; x++) {
       ocb->checksum[x] ^= pt[x];
   }


#ifdef LTC_CLEAN_STACK
   zeromem(Z, sizeof(Z));
   zeromem(tmp, sizeof(tmp));
#endif
   return CRYPT_OK;
}
Пример #24
0
/** Terminate the f9-MAC state
  @param f9     f9 state to terminate
  @param out      [out] Destination for the MAC tag
  @param outlen   [in/out] Destination size and final tag size
  Return CRYPT_OK on success
*/
int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen)
{
   int err, x;
   LTC_ARGCHK(f9 != NULL);
   LTC_ARGCHK(out  != NULL);

   /* check structure */
   if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) {
      return err;
   }

   if ((f9->blocksize > cipher_descriptor[f9->cipher].block_length) || (f9->blocksize < 0) ||
       (f9->buflen > f9->blocksize) || (f9->buflen < 0)) {
      return CRYPT_INVALID_ARG;
   }

   if (f9->buflen != 0) {
      /* encrypt */
      cipher_descriptor[f9->cipher].ecb_encrypt(f9->IV, f9->IV, &f9->key);
      f9->buflen = 0;
      for (x = 0; x < f9->blocksize; x++) {
         f9->ACC[x] ^= f9->IV[x];
      }
   }

   /* schedule modified key */
   if ((err = cipher_descriptor[f9->cipher].setup(f9->akey, f9->keylen, 0, &f9->key)) != CRYPT_OK) {
      return err;
   }

   /* encrypt the ACC */
   cipher_descriptor[f9->cipher].ecb_encrypt(f9->ACC, f9->ACC, &f9->key);
   cipher_descriptor[f9->cipher].done(&f9->key);

   /* extract tag */
   for (x = 0; x < f9->blocksize && (unsigned long)x < *outlen; x++) {
      out[x] = f9->ACC[x];
   }
   *outlen = x;

#ifdef LTC_CLEAN_STACK
   zeromem(f9, sizeof(*f9));
#endif
   return CRYPT_OK;
}
Пример #25
0
/** Terminate the XCBC-MAC state
  @param xcbc     XCBC state to terminate
  @param out      [out] Destination for the MAC tag
  @param outlen   [in/out] Destination size and final tag size
  Return CRYPT_OK on success
*/
int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen)
{
   int err, x;
   LTC_ARGCHK(xcbc != NULL);
   LTC_ARGCHK(out  != NULL);

   /* check structure */
   if ((err = cipher_is_valid(xcbc->cipher)) != CRYPT_OK) {
      return err;
   }

   if ((xcbc->blocksize > cipher_descriptor[xcbc->cipher].block_length) || (xcbc->blocksize < 0) ||
       (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) {
      return CRYPT_INVALID_ARG;
   }

   /* which key do we use? */
   if (xcbc->buflen == xcbc->blocksize) {
      /* k2 */
      for (x = 0; x < xcbc->blocksize; x++) {
         xcbc->IV[x] ^= xcbc->K[1][x];
      }
   } else {
      xcbc->IV[xcbc->buflen] ^= 0x80;
      /* k3 */
      for (x = 0; x < xcbc->blocksize; x++) {
         xcbc->IV[x] ^= xcbc->K[2][x];
      }
   }

   /* encrypt */
   cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key);
   cipher_descriptor[xcbc->cipher].done(&xcbc->key);

   /* extract tag */
   for (x = 0; x < xcbc->blocksize && (unsigned long)x < *outlen; x++) {
      out[x] = xcbc->IV[x];
   }
   *outlen = x;
  
#ifdef LTC_CLEAN_STACK
   zeromem(xcbc, sizeof(*xcbc));
#endif
   return CRYPT_OK;
}
Пример #26
0
/**
  LRW decrypt blocks
  @param ct     The ciphertext
  @param pt     [out] The plaintext
  @param len    The length in octets, must be a multiple of 16
  @param lrw    The LRW state
*/
int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw)
{
   int err;

   LTC_ARGCHK(pt  != NULL);
   LTC_ARGCHK(ct  != NULL);
   LTC_ARGCHK(lrw != NULL);

   if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) {
      return err;
   }

   if (cipher_descriptor[lrw->cipher].accel_lrw_decrypt != NULL) {
      return cipher_descriptor[lrw->cipher].accel_lrw_decrypt(ct, pt, len, lrw->IV, lrw->tweak, &lrw->key);
   }

   return lrw_process(ct, pt, len, LRW_DECRYPT, lrw);
}
Пример #27
0
/**
   Set an initial vector
   @param IV   The initial vector
   @param len  The length of the vector (in octets)
   @param cfb  The CFB state
   @return CRYPT_OK if successful
*/
int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb)
{
   int err;
   
   LTC_ARGCHK(IV  != NULL);
   LTC_ARGCHK(cfb != NULL);

   if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
       return err;
   }
   
   if (len != (unsigned long)cfb->blocklen) {
      return CRYPT_INVALID_ARG;
   }
      
   /* force next block */
   cfb->padlen = 0;
   return cipher_descriptor[cfb->cipher].ecb_encrypt(IV, cfb->IV, &cfb->key);
}
Пример #28
0
/** Process data through XCBC-MAC
  @param xcbc     The XCBC-MAC state
  @param in       Input data to process
  @param inlen    Length of input in octets
  Return CRYPT_OK on success
*/
int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen)
{
   int err;
#ifdef LTC_FAST
   int x;
#endif

   LTC_ARGCHK(xcbc != NULL);
   LTC_ARGCHK(in   != NULL);

   /* check structure */
   if ((err = cipher_is_valid(xcbc->cipher)) != CRYPT_OK) {
      return err;
   }

   if ((xcbc->blocksize > cipher_descriptor[xcbc->cipher].block_length) || (xcbc->blocksize < 0) ||
       (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) {
      return CRYPT_INVALID_ARG;
   }

#ifdef LTC_FAST
   if (xcbc->buflen == 0) {
       while (inlen > (unsigned long)xcbc->blocksize) {
           for (x = 0; x < xcbc->blocksize; x += sizeof(LTC_FAST_TYPE)) {
              *(LTC_FAST_TYPE_PTR_CAST(&(xcbc->IV[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(in[x])));
           }
           cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key);
           in    += xcbc->blocksize;
           inlen -= xcbc->blocksize;
       }
   }
#endif

   while (inlen) {
      if (xcbc->buflen == xcbc->blocksize) {
         cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key);
         xcbc->buflen = 0;
      }
      xcbc->IV[xcbc->buflen++] ^= *in++;
      --inlen;
   }
   return CRYPT_OK;
}
Пример #29
0
/**
   Set an initial vector
   @param IV   The initial vector
   @param len  The length of the vector (in octets)
   @param f8   The F8 state
   @return CRYPT_OK if successful
*/
int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8)
{
   int err;

   LTC_ARGCHK(IV != NULL);
   LTC_ARGCHK(f8 != NULL);

   if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) {
       return err;
   }

   if (len != (unsigned long)f8->blocklen) {
      return CRYPT_INVALID_ARG;
   }

   /* force next block */
   f8->padlen = 0;
   return cipher_descriptor[f8->cipher].ecb_encrypt(IV, f8->IV, &f8->key);
}
Пример #30
0
int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb)
{
   int err;

   _ARGCHK(IV  != NULL);
   _ARGCHK(ofb != NULL);

   if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) {
       return err;
   }

   if (len != (unsigned long)ofb->blocklen) {
      return CRYPT_INVALID_ARG;
   }

   /* force next block */
   ofb->padlen = 0;
   cipher_descriptor[ofb->cipher].ecb_encrypt(IV, ofb->IV, &ofb->key);
   return CRYPT_OK;
}