4848# define RPCDBG_FACILITY RPCDBG_AUTH
4949#endif
5050
51+ static struct gss_api_mech gss_kerberos_mech ; /* forward declaration */
52+
5153static const struct gss_krb5_enctype supported_gss_krb5_enctypes [] = {
5254 /*
5355 * DES (All DES enctypes are mapped to the same gss functionality)
@@ -247,6 +249,237 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
247249 return PTR_ERR (p );
248250}
249251
252+ struct crypto_blkcipher *
253+ context_v2_alloc_cipher (struct krb5_ctx * ctx , u8 * key )
254+ {
255+ struct crypto_blkcipher * cp ;
256+
257+ cp = crypto_alloc_blkcipher (ctx -> gk5e -> encrypt_name ,
258+ 0 , CRYPTO_ALG_ASYNC );
259+ if (IS_ERR (cp )) {
260+ dprintk ("gss_kerberos_mech: unable to initialize "
261+ "crypto algorithm %s\n" , ctx -> gk5e -> encrypt_name );
262+ return NULL ;
263+ }
264+ if (crypto_blkcipher_setkey (cp , key , ctx -> gk5e -> keylength )) {
265+ dprintk ("gss_kerberos_mech: error setting key for "
266+ "crypto algorithm %s\n" , ctx -> gk5e -> encrypt_name );
267+ crypto_free_blkcipher (cp );
268+ return NULL ;
269+ }
270+ return cp ;
271+ }
272+
273+ static inline void
274+ set_cdata (u8 cdata [GSS_KRB5_K5CLENGTH ], u32 usage , u8 seed )
275+ {
276+ cdata [0 ] = (usage >>24 )& 0xff ;
277+ cdata [1 ] = (usage >>16 )& 0xff ;
278+ cdata [2 ] = (usage >>8 )& 0xff ;
279+ cdata [3 ] = usage & 0xff ;
280+ cdata [4 ] = seed ;
281+ }
282+
283+ static int
284+ context_derive_keys_des3 (struct krb5_ctx * ctx , u8 * rawkey , u32 keylen )
285+ {
286+ struct xdr_netobj c , keyin , keyout ;
287+ u8 cdata [GSS_KRB5_K5CLENGTH ];
288+ u32 err ;
289+
290+ c .len = GSS_KRB5_K5CLENGTH ;
291+ c .data = cdata ;
292+
293+ keyin .data = rawkey ;
294+ keyin .len = keylen ;
295+ keyout .len = keylen ;
296+
297+ /* seq uses the raw key */
298+ ctx -> seq = context_v2_alloc_cipher (ctx , rawkey );
299+ if (ctx -> seq == NULL )
300+ goto out_err ;
301+
302+ ctx -> enc = context_v2_alloc_cipher (ctx , rawkey );
303+ if (ctx -> enc == NULL )
304+ goto out_free_seq ;
305+
306+ /* derive cksum */
307+ set_cdata (cdata , KG_USAGE_SIGN , KEY_USAGE_SEED_CHECKSUM );
308+ keyout .data = ctx -> cksum ;
309+ err = krb5_derive_key (ctx -> gk5e , & keyin , & keyout , & c );
310+ if (err ) {
311+ dprintk ("%s: Error %d deriving cksum key\n" ,
312+ __func__ , err );
313+ goto out_free_enc ;
314+ }
315+
316+ return 0 ;
317+
318+ out_free_enc :
319+ crypto_free_blkcipher (ctx -> enc );
320+ out_free_seq :
321+ crypto_free_blkcipher (ctx -> seq );
322+ out_err :
323+ return - EINVAL ;
324+ }
325+
326+ static int
327+ context_derive_keys_new (struct krb5_ctx * ctx , u8 * rawkey , u32 keylen )
328+ {
329+ struct xdr_netobj c , keyin , keyout ;
330+ u8 cdata [GSS_KRB5_K5CLENGTH ];
331+ u32 err ;
332+
333+ c .len = GSS_KRB5_K5CLENGTH ;
334+ c .data = cdata ;
335+
336+ keyin .data = rawkey ;
337+ keyin .len = keylen ;
338+ keyout .len = keylen ;
339+
340+ /* initiator seal encryption */
341+ set_cdata (cdata , KG_USAGE_INITIATOR_SEAL , KEY_USAGE_SEED_ENCRYPTION );
342+ keyout .data = ctx -> initiator_seal ;
343+ err = krb5_derive_key (ctx -> gk5e , & keyin , & keyout , & c );
344+ if (err ) {
345+ dprintk ("%s: Error %d deriving initiator_seal key\n" ,
346+ __func__ , err );
347+ goto out_err ;
348+ }
349+ ctx -> initiator_enc = context_v2_alloc_cipher (ctx , ctx -> initiator_seal );
350+ if (ctx -> initiator_enc == NULL )
351+ goto out_err ;
352+
353+ /* acceptor seal encryption */
354+ set_cdata (cdata , KG_USAGE_ACCEPTOR_SEAL , KEY_USAGE_SEED_ENCRYPTION );
355+ keyout .data = ctx -> acceptor_seal ;
356+ err = krb5_derive_key (ctx -> gk5e , & keyin , & keyout , & c );
357+ if (err ) {
358+ dprintk ("%s: Error %d deriving acceptor_seal key\n" ,
359+ __func__ , err );
360+ goto out_free_initiator_enc ;
361+ }
362+ ctx -> acceptor_enc = context_v2_alloc_cipher (ctx , ctx -> acceptor_seal );
363+ if (ctx -> acceptor_enc == NULL )
364+ goto out_free_initiator_enc ;
365+
366+ /* initiator sign checksum */
367+ set_cdata (cdata , KG_USAGE_INITIATOR_SIGN , KEY_USAGE_SEED_CHECKSUM );
368+ keyout .data = ctx -> initiator_sign ;
369+ err = krb5_derive_key (ctx -> gk5e , & keyin , & keyout , & c );
370+ if (err ) {
371+ dprintk ("%s: Error %d deriving initiator_sign key\n" ,
372+ __func__ , err );
373+ goto out_free_acceptor_enc ;
374+ }
375+
376+ /* acceptor sign checksum */
377+ set_cdata (cdata , KG_USAGE_ACCEPTOR_SIGN , KEY_USAGE_SEED_CHECKSUM );
378+ keyout .data = ctx -> acceptor_sign ;
379+ err = krb5_derive_key (ctx -> gk5e , & keyin , & keyout , & c );
380+ if (err ) {
381+ dprintk ("%s: Error %d deriving acceptor_sign key\n" ,
382+ __func__ , err );
383+ goto out_free_acceptor_enc ;
384+ }
385+
386+ /* initiator seal integrity */
387+ set_cdata (cdata , KG_USAGE_INITIATOR_SEAL , KEY_USAGE_SEED_INTEGRITY );
388+ keyout .data = ctx -> initiator_integ ;
389+ err = krb5_derive_key (ctx -> gk5e , & keyin , & keyout , & c );
390+ if (err ) {
391+ dprintk ("%s: Error %d deriving initiator_integ key\n" ,
392+ __func__ , err );
393+ goto out_free_acceptor_enc ;
394+ }
395+
396+ /* acceptor seal integrity */
397+ set_cdata (cdata , KG_USAGE_ACCEPTOR_SEAL , KEY_USAGE_SEED_INTEGRITY );
398+ keyout .data = ctx -> acceptor_integ ;
399+ err = krb5_derive_key (ctx -> gk5e , & keyin , & keyout , & c );
400+ if (err ) {
401+ dprintk ("%s: Error %d deriving acceptor_integ key\n" ,
402+ __func__ , err );
403+ goto out_free_acceptor_enc ;
404+ }
405+
406+ return 0 ;
407+
408+ out_free_acceptor_enc :
409+ crypto_free_blkcipher (ctx -> acceptor_enc );
410+ out_free_initiator_enc :
411+ crypto_free_blkcipher (ctx -> initiator_enc );
412+ out_err :
413+ return - EINVAL ;
414+ }
415+
416+ static int
417+ gss_import_v2_context (const void * p , const void * end , struct krb5_ctx * ctx )
418+ {
419+ u8 rawkey [GSS_KRB5_MAX_KEYLEN ];
420+ int keylen ;
421+
422+ p = simple_get_bytes (p , end , & ctx -> flags , sizeof (ctx -> flags ));
423+ if (IS_ERR (p ))
424+ goto out_err ;
425+ ctx -> initiate = ctx -> flags & KRB5_CTX_FLAG_INITIATOR ;
426+
427+ p = simple_get_bytes (p , end , & ctx -> endtime , sizeof (ctx -> endtime ));
428+ if (IS_ERR (p ))
429+ goto out_err ;
430+ p = simple_get_bytes (p , end , & ctx -> seq_send64 , sizeof (ctx -> seq_send64 ));
431+ if (IS_ERR (p ))
432+ goto out_err ;
433+ /* set seq_send for use by "older" enctypes */
434+ ctx -> seq_send = ctx -> seq_send64 ;
435+ if (ctx -> seq_send64 != ctx -> seq_send ) {
436+ dprintk ("%s: seq_send64 %lx, seq_send %x overflow?\n" , __func__ ,
437+ (long unsigned )ctx -> seq_send64 , ctx -> seq_send );
438+ goto out_err ;
439+ }
440+ p = simple_get_bytes (p , end , & ctx -> enctype , sizeof (ctx -> enctype ));
441+ if (IS_ERR (p ))
442+ goto out_err ;
443+ ctx -> gk5e = get_gss_krb5_enctype (ctx -> enctype );
444+ if (ctx -> gk5e == NULL ) {
445+ dprintk ("gss_kerberos_mech: unsupported krb5 enctype %u\n" ,
446+ ctx -> enctype );
447+ p = ERR_PTR (- EINVAL );
448+ goto out_err ;
449+ }
450+ keylen = ctx -> gk5e -> keylength ;
451+
452+ p = simple_get_bytes (p , end , rawkey , keylen );
453+ if (IS_ERR (p ))
454+ goto out_err ;
455+
456+ if (p != end ) {
457+ p = ERR_PTR (- EINVAL );
458+ goto out_err ;
459+ }
460+
461+ ctx -> mech_used .data = kmemdup (gss_kerberos_mech .gm_oid .data ,
462+ gss_kerberos_mech .gm_oid .len , GFP_KERNEL );
463+ if (unlikely (ctx -> mech_used .data == NULL )) {
464+ p = ERR_PTR (- ENOMEM );
465+ goto out_err ;
466+ }
467+ ctx -> mech_used .len = gss_kerberos_mech .gm_oid .len ;
468+
469+ switch (ctx -> enctype ) {
470+ case ENCTYPE_DES3_CBC_RAW :
471+ return context_derive_keys_des3 (ctx , rawkey , keylen );
472+ case ENCTYPE_AES128_CTS_HMAC_SHA1_96 :
473+ case ENCTYPE_AES256_CTS_HMAC_SHA1_96 :
474+ return context_derive_keys_new (ctx , rawkey , keylen );
475+ default :
476+ return - EINVAL ;
477+ }
478+
479+ out_err :
480+ return PTR_ERR (p );
481+ }
482+
250483static int
251484gss_import_sec_context_kerberos (const void * p , size_t len ,
252485 struct gss_ctx * ctx_id )
@@ -262,7 +495,7 @@ gss_import_sec_context_kerberos(const void *p, size_t len,
262495 if (len == 85 )
263496 ret = gss_import_v1_context (p , end , ctx );
264497 else
265- ret = - EINVAL ;
498+ ret = gss_import_v2_context ( p , end , ctx ) ;
266499
267500 if (ret == 0 )
268501 ctx_id -> internal_ctx_id = ctx ;
@@ -279,6 +512,8 @@ gss_delete_sec_context_kerberos(void *internal_ctx) {
279512
280513 crypto_free_blkcipher (kctx -> seq );
281514 crypto_free_blkcipher (kctx -> enc );
515+ crypto_free_blkcipher (kctx -> acceptor_enc );
516+ crypto_free_blkcipher (kctx -> initiator_enc );
282517 kfree (kctx -> mech_used .data );
283518 kfree (kctx );
284519}
0 commit comments