/* * common code for both encrypt and decrypt. */ static int cfb_process(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst, mix_data_t mix_data) { int n; int res; while (len > 0 && ctx->pos > 0) { n = ctx->block_size - ctx->pos; if (len < n) n = len; n = mix_data(ctx, data, n, dst); data += n; dst += n; len -= n; if (ctx->pos == ctx->block_size) { memcpy(ctx->fr, ctx->encbuf, ctx->block_size); ctx->pos = 0; } } while (len > 0) { px_cipher_encrypt(ctx->ciph, ctx->fr, ctx->block_size, ctx->fre); if (ctx->block_no < 5) ctx->block_no++; n = ctx->block_size; if (len < n) n = len; res = mix_data(ctx, data, n, dst); data += res; dst += res; len -= res; if (ctx->pos == ctx->block_size) { memcpy(ctx->fr, ctx->encbuf, ctx->block_size); ctx->pos = 0; } } return 0; }
static int combo_encrypt(PX_Combo *cx, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen) { int err = 0; uint8 *bbuf; unsigned bs, bpos, i, pad; PX_Cipher *c = cx->cipher; bbuf = NULL; bs = px_cipher_block_size(c); /* encrypt */ if (bs > 1) { bbuf = px_alloc(bs * 4); bpos = dlen % bs; *rlen = dlen - bpos; memcpy(bbuf, data + *rlen, bpos); /* encrypt full-block data */ if (*rlen) { err = px_cipher_encrypt(c, data, *rlen, res); if (err) goto out; } /* bbuf has now bpos bytes of stuff */ if (cx->padding) { pad = bs - (bpos % bs); for (i = 0; i < pad; i++) bbuf[bpos++] = pad; } else if (bpos % bs) { /* ERROR? */ pad = bs - (bpos % bs); for (i = 0; i < pad; i++) bbuf[bpos++] = 0; } /* encrypt the rest - pad */ if (bpos) { err = px_cipher_encrypt(c, bbuf, bpos, res + *rlen); *rlen += bpos; } } else { /* stream cipher/mode - no pad needed */ err = px_cipher_encrypt(c, data, dlen, res); if (err) goto out; *rlen = dlen; } out: if (bbuf) px_free(bbuf); return err; }