@@ -193,47 +193,98 @@ uint32_t gp_init_creds_handle(uint32_t *min, const char *svc_name,
193193 return ret_maj ;
194194}
195195
196- /* We need to include a length in our payloads because krb5_c_decrypt() will
197- * pad the contents for some enctypes, and gss_import_cred() doesn't like
198- * having extra bytes on tokens. */
196+ #define ENC_MIN_PAD_LEN 8
197+
198+ /* We need to pad our payloads because krb5_c_decrypt() may pad the
199+ * contents for some enctypes, and gss_import_cred() doesn't like
200+ * having extra bytes on tokens.
201+ * Explicit padding and depadding is used in order to maintain backwards
202+ * compatibility over upgrades (and downgrades), it would have been
203+ * better if we simply had a better formatting of the returned blob
204+ * so we could simply change a "blob version" number */
199205static int gp_encrypt_buffer (krb5_context context , krb5_keyblock * key ,
200206 size_t len , void * buf , octet_string * out )
201207{
202208 int ret ;
203209 krb5_data data_in ;
204210 krb5_enc_data enc_handle ;
205211 size_t cipherlen ;
206- char * packed = NULL ;
207- uint32_t netlen ;
212+ size_t padcheck ;
213+ uint8_t pad = 0 ;
214+ char * padded = NULL ;
208215
209216 if (len > (uint32_t )(-1 )) {
210217 /* Needs to fit in 4 bytes of payload, so... */
211218 ret = ENOMEM ;
212219 goto done ;
213220 }
214221
215- packed = malloc (len );
216- if (!packed ) {
217- ret = errno ;
222+ ret = krb5_c_encrypt_length (context ,
223+ key -> enctype ,
224+ len , & cipherlen );
225+ if (ret ) {
218226 goto done ;
219227 }
220228
221- netlen = htonl (len );
222- memcpy (packed , (uint8_t * )& netlen , 4 );
223- memcpy (packed + 4 , buf , len );
224-
225- data_in .length = len + 4 ;
226- data_in .data = packed ;
227-
228- memset (& enc_handle , '\0' , sizeof (krb5_enc_data ));
229-
229+ /* try again with len + 1 to see if padding is required */
230230 ret = krb5_c_encrypt_length (context ,
231231 key -> enctype ,
232- data_in .length ,
233- & cipherlen );
232+ len + 1 , & padcheck );
234233 if (ret ) {
235234 goto done ;
236235 }
236+ if (padcheck == cipherlen ) {
237+ int i ;
238+ /* padding required */
239+ pad = ENC_MIN_PAD_LEN ;
240+ /* always add enough padding that it makes it extremely unlikley
241+ * legitimate plaintext will be incorrectly depadded in the
242+ * decrypt function */
243+ ret = krb5_c_encrypt_length (context ,
244+ key -> enctype ,
245+ len + pad , & cipherlen );
246+ if (ret ) {
247+ goto done ;
248+ }
249+ /* we support only block sizes up to 16 bytes as this is the largest
250+ * supported block size in krb ciphers for now */
251+ for (i = 0 ; i < 15 ; i ++ ) {
252+ /* find the point at which padcheck increases, that's when we
253+ * cross a blocksize boundary internally and we can calculate
254+ * the padding that will be used */
255+ ret = krb5_c_encrypt_length (context ,
256+ key -> enctype ,
257+ len + pad + i + 1 , & padcheck );
258+ if (ret ) {
259+ goto done ;
260+ }
261+ if (padcheck > cipherlen ) {
262+ pad += i ;
263+ break ;
264+ }
265+ }
266+ if (i > 15 ) {
267+ ret = EINVAL ;
268+ goto done ;
269+ }
270+ }
271+
272+ if (pad != 0 ) {
273+ padded = malloc (len + pad );
274+ if (!padded ) {
275+ ret = errno ;
276+ goto done ;
277+ }
278+
279+ memcpy (padded , buf , len );
280+ memset (padded + len , pad , pad );
281+
282+ data_in .length = len + pad ;
283+ data_in .data = padded ;
284+ } else {
285+ data_in .length = len ;
286+ data_in .data = buf ;
287+ }
237288
238289 enc_handle .ciphertext .length = cipherlen ;
239290 enc_handle .ciphertext .data = malloc (enc_handle .ciphertext .length );
@@ -261,7 +312,7 @@ static int gp_encrypt_buffer(krb5_context context, krb5_keyblock *key,
261312 }
262313
263314done :
264- free (packed );
315+ free (padded );
265316 free (enc_handle .ciphertext .data );
266317 return ret ;
267318}
@@ -273,7 +324,8 @@ static int gp_decrypt_buffer(krb5_context context, krb5_keyblock *key,
273324 int ret ;
274325 krb5_data data_out ;
275326 krb5_enc_data enc_handle ;
276- uint32_t netlen ;
327+ uint8_t pad ;
328+ int i , j ;
277329
278330 memset (& enc_handle , '\0' , sizeof (krb5_enc_data ));
279331
@@ -295,9 +347,19 @@ static int gp_decrypt_buffer(krb5_context context, krb5_keyblock *key,
295347 }
296348
297349 /* And handle the padding. */
298- memcpy (& netlen , buf , 4 );
299- * len = ntohl (netlen );
300- memmove (buf , buf + 4 , * len );
350+ i = data_out .length - 1 ;
351+ pad = data_out .data [i ];
352+ if (pad >= ENC_MIN_PAD_LEN && pad < i ) {
353+ j = pad ;
354+ while (j > 0 ) {
355+ j -- ;
356+ if (pad != data_out .data [i - j ]) break ;
357+ }
358+ if (j == 0 ) {
359+ data_out .length -= pad ;
360+ }
361+ }
362+ * len = data_out .length ;
301363
302364 return 0 ;
303365}
0 commit comments