3 * Implements both normal and PGP-specific CFB mode.
5 * Copyright (c) 2005 Marko Kreen
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * contrib/pgcrypto/pgp-cfb.c
37 typedef int (*mix_data_t
) (PGP_CFB
*ctx
, const uint8
*data
, int len
, uint8
*dst
);
46 uint8 fr
[PGP_MAX_BLOCK
];
47 uint8 fre
[PGP_MAX_BLOCK
];
48 uint8 encbuf
[PGP_MAX_BLOCK
];
52 pgp_cfb_create(PGP_CFB
**ctx_p
, int algo
, const uint8
*key
, int key_len
,
53 int resync
, uint8
*iv
)
59 res
= pgp_load_cipher(algo
, &ciph
);
63 res
= px_cipher_init(ciph
, key
, key_len
, NULL
);
70 ctx
= palloc0(sizeof(*ctx
));
72 ctx
->block_size
= px_cipher_block_size(ciph
);
76 memcpy(ctx
->fr
, iv
, ctx
->block_size
);
83 pgp_cfb_free(PGP_CFB
*ctx
)
85 px_cipher_free(ctx
->ciph
);
86 px_memset(ctx
, 0, sizeof(*ctx
));
91 * Data processing for normal CFB. (PGP_PKT_SYMENCRYPTED_DATA_MDC)
94 mix_encrypt_normal(PGP_CFB
*ctx
, const uint8
*data
, int len
, uint8
*dst
)
98 for (i
= ctx
->pos
; i
< ctx
->pos
+ len
; i
++)
99 *dst
++ = ctx
->encbuf
[i
] = ctx
->fre
[i
] ^ (*data
++);
105 mix_decrypt_normal(PGP_CFB
*ctx
, const uint8
*data
, int len
, uint8
*dst
)
109 for (i
= ctx
->pos
; i
< ctx
->pos
+ len
; i
++)
111 ctx
->encbuf
[i
] = *data
++;
112 *dst
++ = ctx
->fre
[i
] ^ ctx
->encbuf
[i
];
119 * Data processing for old PGP CFB mode. (PGP_PKT_SYMENCRYPTED_DATA)
121 * The goal is to hide the horror from the rest of the code,
122 * thus its all concentrated here.
125 mix_encrypt_resync(PGP_CFB
*ctx
, const uint8
*data
, int len
, uint8
*dst
)
130 /* block #2 is 2 bytes long */
131 if (ctx
->block_no
== 2)
136 for (i
= ctx
->pos
; i
< ctx
->pos
+ n
; i
++)
137 *dst
++ = ctx
->encbuf
[i
] = ctx
->fre
[i
] ^ (*data
++);
144 memcpy(ctx
->fr
, ctx
->encbuf
+ 2, ctx
->block_size
- 2);
145 memcpy(ctx
->fr
+ ctx
->block_size
- 2, ctx
->encbuf
, 2);
150 for (i
= ctx
->pos
; i
< ctx
->pos
+ len
; i
++)
151 *dst
++ = ctx
->encbuf
[i
] = ctx
->fre
[i
] ^ (*data
++);
157 mix_decrypt_resync(PGP_CFB
*ctx
, const uint8
*data
, int len
, uint8
*dst
)
162 /* block #2 is 2 bytes long */
163 if (ctx
->block_no
== 2)
168 for (i
= ctx
->pos
; i
< ctx
->pos
+ n
; i
++)
170 ctx
->encbuf
[i
] = *data
++;
171 *dst
++ = ctx
->fre
[i
] ^ ctx
->encbuf
[i
];
178 memcpy(ctx
->fr
, ctx
->encbuf
+ 2, ctx
->block_size
- 2);
179 memcpy(ctx
->fr
+ ctx
->block_size
- 2, ctx
->encbuf
, 2);
184 for (i
= ctx
->pos
; i
< ctx
->pos
+ len
; i
++)
186 ctx
->encbuf
[i
] = *data
++;
187 *dst
++ = ctx
->fre
[i
] ^ ctx
->encbuf
[i
];
194 * common code for both encrypt and decrypt.
197 cfb_process(PGP_CFB
*ctx
, const uint8
*data
, int len
, uint8
*dst
,
203 while (len
> 0 && ctx
->pos
> 0)
205 n
= ctx
->block_size
- ctx
->pos
;
209 n
= mix_data(ctx
, data
, n
, dst
);
214 if (ctx
->pos
== ctx
->block_size
)
216 memcpy(ctx
->fr
, ctx
->encbuf
, ctx
->block_size
);
225 px_cipher_encrypt(ctx
->ciph
, 0, ctx
->fr
, ctx
->block_size
, ctx
->fre
, &rlen
);
226 if (ctx
->block_no
< 5)
233 res
= mix_data(ctx
, data
, n
, dst
);
238 if (ctx
->pos
== ctx
->block_size
)
240 memcpy(ctx
->fr
, ctx
->encbuf
, ctx
->block_size
);
252 pgp_cfb_encrypt(PGP_CFB
*ctx
, const uint8
*data
, int len
, uint8
*dst
)
254 mix_data_t mix
= ctx
->resync
? mix_encrypt_resync
: mix_encrypt_normal
;
256 return cfb_process(ctx
, data
, len
, dst
, mix
);
260 pgp_cfb_decrypt(PGP_CFB
*ctx
, const uint8
*data
, int len
, uint8
*dst
)
262 mix_data_t mix
= ctx
->resync
? mix_decrypt_resync
: mix_decrypt_normal
;
264 return cfb_process(ctx
, data
, len
, dst
, mix
);