2019-02-11 11:25:15 -05:00
// SPDX-License-Identifier: BSD-3-Clause
2005-04-16 15:20:36 -07:00
/*
* linux / net / sunrpc / gss_krb5_mech . c
*
2010-03-17 13:02:51 -04:00
* Copyright ( c ) 2001 - 2008 The Regents of the University of Michigan .
2005-04-16 15:20:36 -07:00
* All rights reserved .
*
* Andy Adamson < andros @ umich . edu >
* J . Bruce Fields < bfields @ umich . edu >
*/
2016-01-24 21:17:59 +08:00
# include <crypto/hash.h>
# include <crypto/skcipher.h>
2006-08-22 20:33:54 +10:00
# include <linux/err.h>
2005-04-16 15:20:36 -07:00
# include <linux/module.h>
# include <linux/init.h>
# include <linux/types.h>
# include <linux/slab.h>
# include <linux/sunrpc/auth.h>
# include <linux/sunrpc/gss_krb5.h>
# include <linux/sunrpc/xdr.h>
2011-05-31 12:24:58 -04:00
# include <linux/sunrpc/gss_krb5_enctypes.h>
2005-04-16 15:20:36 -07:00
2021-01-21 16:17:23 -05:00
# include "auth_gss_internal.h"
2014-11-17 16:58:04 -05:00
# if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
2005-04-16 15:20:36 -07:00
# define RPCDBG_FACILITY RPCDBG_AUTH
# endif
2010-03-17 13:02:54 -04:00
static struct gss_api_mech gss_kerberos_mech ; /* forward declaration */
2010-03-17 13:02:51 -04:00
static const struct gss_krb5_enctype supported_gss_krb5_enctypes [ ] = {
2019-02-11 11:24:43 -05:00
# ifndef CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES
2010-03-17 13:02:51 -04:00
/*
* DES ( All DES enctypes are mapped to the same gss functionality )
*/
{
. etype = ENCTYPE_DES_CBC_RAW ,
. ctype = CKSUMTYPE_RSA_MD5 ,
. name = " des-cbc-crc " ,
. encrypt_name = " cbc(des) " ,
. cksum_name = " md5 " ,
. encrypt = krb5_encrypt ,
. decrypt = krb5_decrypt ,
2010-03-17 13:02:53 -04:00
. mk_key = NULL ,
2010-03-17 13:02:51 -04:00
. signalg = SGN_ALG_DES_MAC_MD5 ,
. sealalg = SEAL_ALG_DES ,
. keybytes = 7 ,
. keylength = 8 ,
. cksumlength = 8 ,
2010-03-17 13:02:52 -04:00
. keyed_cksum = 0 ,
2010-03-17 13:02:51 -04:00
} ,
2019-02-11 11:24:43 -05:00
# endif /* CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES */
2010-03-17 13:02:55 -04:00
/*
* 3 DES
*/
{
. etype = ENCTYPE_DES3_CBC_RAW ,
. ctype = CKSUMTYPE_HMAC_SHA1_DES3 ,
. name = " des3-hmac-sha1 " ,
. encrypt_name = " cbc(des3_ede) " ,
. cksum_name = " hmac(sha1) " ,
. encrypt = krb5_encrypt ,
. decrypt = krb5_decrypt ,
. mk_key = gss_krb5_des3_make_key ,
. signalg = SGN_ALG_HMAC_SHA1_DES3_KD ,
. sealalg = SEAL_ALG_DES3KD ,
. keybytes = 21 ,
. keylength = 24 ,
. cksumlength = 20 ,
. keyed_cksum = 1 ,
} ,
2010-03-17 13:03:00 -04:00
/*
* AES128
*/
{
. etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96 ,
. ctype = CKSUMTYPE_HMAC_SHA1_96_AES128 ,
. name = " aes128-cts " ,
. encrypt_name = " cts(cbc(aes)) " ,
2023-01-15 12:20:54 -05:00
. aux_cipher = " cbc(aes) " ,
2010-03-17 13:03:00 -04:00
. cksum_name = " hmac(sha1) " ,
. encrypt = krb5_encrypt ,
. decrypt = krb5_decrypt ,
. mk_key = gss_krb5_aes_make_key ,
. encrypt_v2 = gss_krb5_aes_encrypt ,
. decrypt_v2 = gss_krb5_aes_decrypt ,
. signalg = - 1 ,
. sealalg = - 1 ,
. keybytes = 16 ,
. keylength = 16 ,
. cksumlength = 12 ,
. keyed_cksum = 1 ,
} ,
/*
* AES256
*/
{
. etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96 ,
. ctype = CKSUMTYPE_HMAC_SHA1_96_AES256 ,
. name = " aes256-cts " ,
. encrypt_name = " cts(cbc(aes)) " ,
2023-01-15 12:20:54 -05:00
. aux_cipher = " cbc(aes) " ,
2010-03-17 13:03:00 -04:00
. cksum_name = " hmac(sha1) " ,
. encrypt = krb5_encrypt ,
. decrypt = krb5_decrypt ,
. mk_key = gss_krb5_aes_make_key ,
. encrypt_v2 = gss_krb5_aes_encrypt ,
. decrypt_v2 = gss_krb5_aes_decrypt ,
. signalg = - 1 ,
. sealalg = - 1 ,
. keybytes = 32 ,
. keylength = 32 ,
. cksumlength = 12 ,
. keyed_cksum = 1 ,
} ,
2010-03-17 13:02:51 -04:00
} ;
static const int num_supported_enctypes =
ARRAY_SIZE ( supported_gss_krb5_enctypes ) ;
static int
supported_gss_krb5_enctype ( int etype )
{
int i ;
for ( i = 0 ; i < num_supported_enctypes ; i + + )
if ( supported_gss_krb5_enctypes [ i ] . etype = = etype )
return 1 ;
return 0 ;
}
static const struct gss_krb5_enctype *
get_gss_krb5_enctype ( int etype )
{
int i ;
for ( i = 0 ; i < num_supported_enctypes ; i + + )
if ( supported_gss_krb5_enctypes [ i ] . etype = = etype )
return & supported_gss_krb5_enctypes [ i ] ;
return NULL ;
}
2005-04-16 15:20:36 -07:00
static inline const void *
2010-03-17 13:02:51 -04:00
get_key ( const void * p , const void * end ,
2018-09-18 19:10:39 -07:00
struct krb5_ctx * ctx , struct crypto_sync_skcipher * * res )
2005-04-16 15:20:36 -07:00
{
struct xdr_netobj key ;
2006-08-22 20:33:54 +10:00
int alg ;
2005-04-16 15:20:36 -07:00
p = simple_get_bytes ( p , end , & alg , sizeof ( alg ) ) ;
if ( IS_ERR ( p ) )
goto out_err ;
2010-03-17 13:02:51 -04:00
switch ( alg ) {
case ENCTYPE_DES_CBC_CRC :
case ENCTYPE_DES_CBC_MD4 :
case ENCTYPE_DES_CBC_MD5 :
/* Map all these key types to ENCTYPE_DES_CBC_RAW */
alg = ENCTYPE_DES_CBC_RAW ;
break ;
}
if ( ! supported_gss_krb5_enctype ( alg ) ) {
printk ( KERN_WARNING " gss_kerberos_mech: unsupported "
" encryption key algorithm %d \n " , alg ) ;
2010-09-12 19:55:25 -04:00
p = ERR_PTR ( - EINVAL ) ;
2010-03-17 13:02:51 -04:00
goto out_err ;
}
2005-04-16 15:20:36 -07:00
p = simple_get_netobj ( p , end , & key ) ;
if ( IS_ERR ( p ) )
goto out_err ;
2018-09-18 19:10:39 -07:00
* res = crypto_alloc_sync_skcipher ( ctx - > gk5e - > encrypt_name , 0 , 0 ) ;
2006-08-22 20:33:54 +10:00
if ( IS_ERR ( * res ) ) {
2010-03-17 13:02:51 -04:00
printk ( KERN_WARNING " gss_kerberos_mech: unable to initialize "
" crypto algorithm %s \n " , ctx - > gk5e - > encrypt_name ) ;
2006-08-22 20:33:54 +10:00
* res = NULL ;
2005-04-16 15:20:36 -07:00
goto out_err_free_key ;
2006-01-03 09:56:01 +01:00
}
2018-09-18 19:10:39 -07:00
if ( crypto_sync_skcipher_setkey ( * res , key . data , key . len ) ) {
2010-03-17 13:02:51 -04:00
printk ( KERN_WARNING " gss_kerberos_mech: error setting key for "
" crypto algorithm %s \n " , ctx - > gk5e - > encrypt_name ) ;
2005-04-16 15:20:36 -07:00
goto out_err_free_tfm ;
2006-01-03 09:56:01 +01:00
}
2005-04-16 15:20:36 -07:00
kfree ( key . data ) ;
return p ;
out_err_free_tfm :
2018-09-18 19:10:39 -07:00
crypto_free_sync_skcipher ( * res ) ;
2005-04-16 15:20:36 -07:00
out_err_free_key :
kfree ( key . data ) ;
p = ERR_PTR ( - EINVAL ) ;
out_err :
return p ;
}
static int
2010-03-17 13:02:50 -04:00
gss_import_v1_context ( const void * p , const void * end , struct krb5_ctx * ctx )
2005-04-16 15:20:36 -07:00
{
2018-11-01 17:51:34 +00:00
u32 seq_send ;
2006-12-04 20:22:35 -05:00
int tmp ;
2018-06-07 17:02:50 +02:00
u32 time32 ;
2005-04-16 15:20:36 -07:00
p = simple_get_bytes ( p , end , & ctx - > initiate , sizeof ( ctx - > initiate ) ) ;
if ( IS_ERR ( p ) )
2010-03-17 13:02:50 -04:00
goto out_err ;
/* Old format supports only DES! Any other enctype uses new format */
2010-03-17 13:02:49 -04:00
ctx - > enctype = ENCTYPE_DES_CBC_RAW ;
2010-03-17 13:02:50 -04:00
2010-03-17 13:02:51 -04:00
ctx - > gk5e = get_gss_krb5_enctype ( ctx - > enctype ) ;
2010-09-12 19:55:25 -04:00
if ( ctx - > gk5e = = NULL ) {
p = ERR_PTR ( - EINVAL ) ;
2010-03-17 13:02:51 -04:00
goto out_err ;
2010-09-12 19:55:25 -04:00
}
2010-03-17 13:02:51 -04:00
2006-12-04 20:22:41 -05:00
/* The downcall format was designed before we completely understood
* the uses of the context fields ; so it includes some stuff we
* just give some minimal sanity - checking , and some we ignore
* completely ( like the next twenty bytes ) : */
2010-09-12 19:55:25 -04:00
if ( unlikely ( p + 20 > end | | p + 20 < p ) ) {
p = ERR_PTR ( - EFAULT ) ;
2010-03-17 13:02:50 -04:00
goto out_err ;
2010-09-12 19:55:25 -04:00
}
2006-12-04 20:22:41 -05:00
p + = 20 ;
2006-12-04 20:22:35 -05:00
p = simple_get_bytes ( p , end , & tmp , sizeof ( tmp ) ) ;
2005-04-16 15:20:36 -07:00
if ( IS_ERR ( p ) )
2010-03-17 13:02:50 -04:00
goto out_err ;
2007-11-09 18:42:09 -05:00
if ( tmp ! = SGN_ALG_DES_MAC_MD5 ) {
p = ERR_PTR ( - ENOSYS ) ;
2010-03-17 13:02:50 -04:00
goto out_err ;
2007-11-09 18:42:09 -05:00
}
2006-12-04 20:22:40 -05:00
p = simple_get_bytes ( p , end , & tmp , sizeof ( tmp ) ) ;
2005-04-16 15:20:36 -07:00
if ( IS_ERR ( p ) )
2010-03-17 13:02:50 -04:00
goto out_err ;
2007-11-09 18:42:09 -05:00
if ( tmp ! = SEAL_ALG_DES ) {
p = ERR_PTR ( - ENOSYS ) ;
2010-03-17 13:02:50 -04:00
goto out_err ;
2007-11-09 18:42:09 -05:00
}
2018-06-07 17:02:50 +02:00
p = simple_get_bytes ( p , end , & time32 , sizeof ( time32 ) ) ;
2005-04-16 15:20:36 -07:00
if ( IS_ERR ( p ) )
2010-03-17 13:02:50 -04:00
goto out_err ;
2018-06-07 17:02:50 +02:00
/* unsigned 32-bit time overflows in year 2106 */
ctx - > endtime = ( time64_t ) time32 ;
2018-11-01 17:51:34 +00:00
p = simple_get_bytes ( p , end , & seq_send , sizeof ( seq_send ) ) ;
2005-04-16 15:20:36 -07:00
if ( IS_ERR ( p ) )
2010-03-17 13:02:50 -04:00
goto out_err ;
2018-11-01 17:51:34 +00:00
atomic_set ( & ctx - > seq_send , seq_send ) ;
2005-04-16 15:20:36 -07:00
p = simple_get_netobj ( p , end , & ctx - > mech_used ) ;
if ( IS_ERR ( p ) )
2010-03-17 13:02:50 -04:00
goto out_err ;
2010-03-17 13:02:51 -04:00
p = get_key ( p , end , ctx , & ctx - > enc ) ;
2005-04-16 15:20:36 -07:00
if ( IS_ERR ( p ) )
goto out_err_free_mech ;
2010-03-17 13:02:51 -04:00
p = get_key ( p , end , ctx , & ctx - > seq ) ;
2005-04-16 15:20:36 -07:00
if ( IS_ERR ( p ) )
goto out_err_free_key1 ;
if ( p ! = end ) {
p = ERR_PTR ( - EFAULT ) ;
goto out_err_free_key2 ;
}
return 0 ;
out_err_free_key2 :
2018-09-18 19:10:39 -07:00
crypto_free_sync_skcipher ( ctx - > seq ) ;
2005-04-16 15:20:36 -07:00
out_err_free_key1 :
2018-09-18 19:10:39 -07:00
crypto_free_sync_skcipher ( ctx - > enc ) ;
2005-04-16 15:20:36 -07:00
out_err_free_mech :
kfree ( ctx - > mech_used . data ) ;
out_err :
return PTR_ERR ( p ) ;
}
2018-09-18 19:10:39 -07:00
static struct crypto_sync_skcipher *
2010-03-17 13:03:00 -04:00
context_v2_alloc_cipher ( struct krb5_ctx * ctx , const char * cname , u8 * key )
2010-03-17 13:02:54 -04:00
{
2018-09-18 19:10:39 -07:00
struct crypto_sync_skcipher * cp ;
2010-03-17 13:02:54 -04:00
2018-09-18 19:10:39 -07:00
cp = crypto_alloc_sync_skcipher ( cname , 0 , 0 ) ;
2010-03-17 13:02:54 -04:00
if ( IS_ERR ( cp ) ) {
dprintk ( " gss_kerberos_mech: unable to initialize "
2010-03-17 13:03:00 -04:00
" crypto algorithm %s \n " , cname ) ;
2010-03-17 13:02:54 -04:00
return NULL ;
}
2018-09-18 19:10:39 -07:00
if ( crypto_sync_skcipher_setkey ( cp , key , ctx - > gk5e - > keylength ) ) {
2010-03-17 13:02:54 -04:00
dprintk ( " gss_kerberos_mech: error setting key for "
2010-03-17 13:03:00 -04:00
" crypto algorithm %s \n " , cname ) ;
2018-09-18 19:10:39 -07:00
crypto_free_sync_skcipher ( cp ) ;
2010-03-17 13:02:54 -04:00
return NULL ;
}
return cp ;
}
static inline void
set_cdata ( u8 cdata [ GSS_KRB5_K5CLENGTH ] , u32 usage , u8 seed )
{
cdata [ 0 ] = ( usage > > 24 ) & 0xff ;
cdata [ 1 ] = ( usage > > 16 ) & 0xff ;
cdata [ 2 ] = ( usage > > 8 ) & 0xff ;
cdata [ 3 ] = usage & 0xff ;
cdata [ 4 ] = seed ;
}
static int
2010-05-13 12:51:02 -04:00
context_derive_keys_des3 ( struct krb5_ctx * ctx , gfp_t gfp_mask )
2010-03-17 13:02:54 -04:00
{
struct xdr_netobj c , keyin , keyout ;
u8 cdata [ GSS_KRB5_K5CLENGTH ] ;
u32 err ;
c . len = GSS_KRB5_K5CLENGTH ;
c . data = cdata ;
2010-03-17 13:03:03 -04:00
keyin . data = ctx - > Ksess ;
keyin . len = ctx - > gk5e - > keylength ;
keyout . len = ctx - > gk5e - > keylength ;
2010-03-17 13:02:54 -04:00
/* seq uses the raw key */
2010-03-17 13:03:00 -04:00
ctx - > seq = context_v2_alloc_cipher ( ctx , ctx - > gk5e - > encrypt_name ,
2010-03-17 13:03:03 -04:00
ctx - > Ksess ) ;
2010-03-17 13:02:54 -04:00
if ( ctx - > seq = = NULL )
goto out_err ;
2010-03-17 13:03:00 -04:00
ctx - > enc = context_v2_alloc_cipher ( ctx , ctx - > gk5e - > encrypt_name ,
2010-03-17 13:03:03 -04:00
ctx - > Ksess ) ;
2010-03-17 13:02:54 -04:00
if ( ctx - > enc = = NULL )
goto out_free_seq ;
/* derive cksum */
set_cdata ( cdata , KG_USAGE_SIGN , KEY_USAGE_SEED_CHECKSUM ) ;
keyout . data = ctx - > cksum ;
2010-05-13 12:51:02 -04:00
err = krb5_derive_key ( ctx - > gk5e , & keyin , & keyout , & c , gfp_mask ) ;
2010-03-17 13:02:54 -04:00
if ( err ) {
dprintk ( " %s: Error %d deriving cksum key \n " ,
__func__ , err ) ;
goto out_free_enc ;
}
return 0 ;
out_free_enc :
2018-09-18 19:10:39 -07:00
crypto_free_sync_skcipher ( ctx - > enc ) ;
2010-03-17 13:02:54 -04:00
out_free_seq :
2018-09-18 19:10:39 -07:00
crypto_free_sync_skcipher ( ctx - > seq ) ;
2010-03-17 13:02:54 -04:00
out_err :
return - EINVAL ;
}
static int
2010-05-13 12:51:02 -04:00
context_derive_keys_new ( struct krb5_ctx * ctx , gfp_t gfp_mask )
2010-03-17 13:02:54 -04:00
{
struct xdr_netobj c , keyin , keyout ;
u8 cdata [ GSS_KRB5_K5CLENGTH ] ;
u32 err ;
c . len = GSS_KRB5_K5CLENGTH ;
c . data = cdata ;
2010-03-17 13:03:03 -04:00
keyin . data = ctx - > Ksess ;
keyin . len = ctx - > gk5e - > keylength ;
keyout . len = ctx - > gk5e - > keylength ;
2010-03-17 13:02:54 -04:00
/* initiator seal encryption */
set_cdata ( cdata , KG_USAGE_INITIATOR_SEAL , KEY_USAGE_SEED_ENCRYPTION ) ;
keyout . data = ctx - > initiator_seal ;
2010-05-13 12:51:02 -04:00
err = krb5_derive_key ( ctx - > gk5e , & keyin , & keyout , & c , gfp_mask ) ;
2010-03-17 13:02:54 -04:00
if ( err ) {
dprintk ( " %s: Error %d deriving initiator_seal key \n " ,
__func__ , err ) ;
goto out_err ;
}
2010-03-17 13:03:00 -04:00
ctx - > initiator_enc = context_v2_alloc_cipher ( ctx ,
ctx - > gk5e - > encrypt_name ,
ctx - > initiator_seal ) ;
2010-03-17 13:02:54 -04:00
if ( ctx - > initiator_enc = = NULL )
goto out_err ;
2023-01-15 12:20:54 -05:00
if ( ctx - > gk5e - > aux_cipher ) {
ctx - > initiator_enc_aux =
context_v2_alloc_cipher ( ctx , ctx - > gk5e - > aux_cipher ,
ctx - > initiator_seal ) ;
if ( ctx - > initiator_enc_aux = = NULL )
goto out_free ;
}
2010-03-17 13:02:54 -04:00
/* acceptor seal encryption */
set_cdata ( cdata , KG_USAGE_ACCEPTOR_SEAL , KEY_USAGE_SEED_ENCRYPTION ) ;
keyout . data = ctx - > acceptor_seal ;
2010-05-13 12:51:02 -04:00
err = krb5_derive_key ( ctx - > gk5e , & keyin , & keyout , & c , gfp_mask ) ;
2010-03-17 13:02:54 -04:00
if ( err ) {
dprintk ( " %s: Error %d deriving acceptor_seal key \n " ,
__func__ , err ) ;
2023-01-15 12:20:54 -05:00
goto out_free ;
2010-03-17 13:02:54 -04:00
}
2010-03-17 13:03:00 -04:00
ctx - > acceptor_enc = context_v2_alloc_cipher ( ctx ,
ctx - > gk5e - > encrypt_name ,
ctx - > acceptor_seal ) ;
2010-03-17 13:02:54 -04:00
if ( ctx - > acceptor_enc = = NULL )
2023-01-15 12:20:54 -05:00
goto out_free ;
if ( ctx - > gk5e - > aux_cipher ) {
ctx - > acceptor_enc_aux =
context_v2_alloc_cipher ( ctx , ctx - > gk5e - > aux_cipher ,
ctx - > acceptor_seal ) ;
if ( ctx - > acceptor_enc_aux = = NULL )
goto out_free ;
}
2010-03-17 13:02:54 -04:00
/* initiator sign checksum */
set_cdata ( cdata , KG_USAGE_INITIATOR_SIGN , KEY_USAGE_SEED_CHECKSUM ) ;
keyout . data = ctx - > initiator_sign ;
2010-05-13 12:51:02 -04:00
err = krb5_derive_key ( ctx - > gk5e , & keyin , & keyout , & c , gfp_mask ) ;
2010-03-17 13:02:54 -04:00
if ( err ) {
dprintk ( " %s: Error %d deriving initiator_sign key \n " ,
__func__ , err ) ;
2023-01-15 12:20:54 -05:00
goto out_free ;
2010-03-17 13:02:54 -04:00
}
/* acceptor sign checksum */
set_cdata ( cdata , KG_USAGE_ACCEPTOR_SIGN , KEY_USAGE_SEED_CHECKSUM ) ;
keyout . data = ctx - > acceptor_sign ;
2010-05-13 12:51:02 -04:00
err = krb5_derive_key ( ctx - > gk5e , & keyin , & keyout , & c , gfp_mask ) ;
2010-03-17 13:02:54 -04:00
if ( err ) {
dprintk ( " %s: Error %d deriving acceptor_sign key \n " ,
__func__ , err ) ;
2023-01-15 12:20:54 -05:00
goto out_free ;
2010-03-17 13:02:54 -04:00
}
/* initiator seal integrity */
set_cdata ( cdata , KG_USAGE_INITIATOR_SEAL , KEY_USAGE_SEED_INTEGRITY ) ;
keyout . data = ctx - > initiator_integ ;
2010-05-13 12:51:02 -04:00
err = krb5_derive_key ( ctx - > gk5e , & keyin , & keyout , & c , gfp_mask ) ;
2010-03-17 13:02:54 -04:00
if ( err ) {
dprintk ( " %s: Error %d deriving initiator_integ key \n " ,
__func__ , err ) ;
2023-01-15 12:20:54 -05:00
goto out_free ;
2010-03-17 13:02:54 -04:00
}
/* acceptor seal integrity */
set_cdata ( cdata , KG_USAGE_ACCEPTOR_SEAL , KEY_USAGE_SEED_INTEGRITY ) ;
keyout . data = ctx - > acceptor_integ ;
2010-05-13 12:51:02 -04:00
err = krb5_derive_key ( ctx - > gk5e , & keyin , & keyout , & c , gfp_mask ) ;
2010-03-17 13:02:54 -04:00
if ( err ) {
dprintk ( " %s: Error %d deriving acceptor_integ key \n " ,
__func__ , err ) ;
2023-01-15 12:20:54 -05:00
goto out_free ;
2010-03-17 13:03:00 -04:00
}
2010-03-17 13:02:54 -04:00
return 0 ;
2023-01-15 12:20:54 -05:00
out_free :
crypto_free_sync_skcipher ( ctx - > acceptor_enc_aux ) ;
2018-09-18 19:10:39 -07:00
crypto_free_sync_skcipher ( ctx - > acceptor_enc ) ;
2023-01-15 12:20:54 -05:00
crypto_free_sync_skcipher ( ctx - > initiator_enc_aux ) ;
2018-09-18 19:10:39 -07:00
crypto_free_sync_skcipher ( ctx - > initiator_enc ) ;
2010-03-17 13:02:54 -04:00
out_err :
return - EINVAL ;
}
static int
2010-05-13 12:51:02 -04:00
gss_import_v2_context ( const void * p , const void * end , struct krb5_ctx * ctx ,
gfp_t gfp_mask )
2010-03-17 13:02:54 -04:00
{
2018-11-01 17:51:34 +00:00
u64 seq_send64 ;
2010-03-17 13:02:54 -04:00
int keylen ;
2018-06-07 17:02:50 +02:00
u32 time32 ;
2010-03-17 13:02:54 -04:00
p = simple_get_bytes ( p , end , & ctx - > flags , sizeof ( ctx - > flags ) ) ;
if ( IS_ERR ( p ) )
goto out_err ;
ctx - > initiate = ctx - > flags & KRB5_CTX_FLAG_INITIATOR ;
2018-06-07 17:02:50 +02:00
p = simple_get_bytes ( p , end , & time32 , sizeof ( time32 ) ) ;
2010-03-17 13:02:54 -04:00
if ( IS_ERR ( p ) )
goto out_err ;
2018-06-07 17:02:50 +02:00
/* unsigned 32-bit time overflows in year 2106 */
ctx - > endtime = ( time64_t ) time32 ;
2018-11-01 17:51:34 +00:00
p = simple_get_bytes ( p , end , & seq_send64 , sizeof ( seq_send64 ) ) ;
2010-03-17 13:02:54 -04:00
if ( IS_ERR ( p ) )
goto out_err ;
2018-11-01 17:51:34 +00:00
atomic64_set ( & ctx - > seq_send64 , seq_send64 ) ;
2010-03-17 13:02:54 -04:00
/* set seq_send for use by "older" enctypes */
2018-11-01 17:51:34 +00:00
atomic_set ( & ctx - > seq_send , seq_send64 ) ;
if ( seq_send64 ! = atomic_read ( & ctx - > seq_send ) ) {
dprintk ( " %s: seq_send64 %llx, seq_send %x overflow? \n " , __func__ ,
seq_send64 , atomic_read ( & ctx - > seq_send ) ) ;
2010-09-12 19:55:25 -04:00
p = ERR_PTR ( - EINVAL ) ;
2010-03-17 13:02:54 -04:00
goto out_err ;
}
p = simple_get_bytes ( p , end , & ctx - > enctype , sizeof ( ctx - > enctype ) ) ;
if ( IS_ERR ( p ) )
goto out_err ;
2010-03-17 13:02:55 -04:00
/* Map ENCTYPE_DES3_CBC_SHA1 to ENCTYPE_DES3_CBC_RAW */
if ( ctx - > enctype = = ENCTYPE_DES3_CBC_SHA1 )
ctx - > enctype = ENCTYPE_DES3_CBC_RAW ;
2010-03-17 13:02:54 -04:00
ctx - > gk5e = get_gss_krb5_enctype ( ctx - > enctype ) ;
if ( ctx - > gk5e = = NULL ) {
dprintk ( " gss_kerberos_mech: unsupported krb5 enctype %u \n " ,
ctx - > enctype ) ;
p = ERR_PTR ( - EINVAL ) ;
goto out_err ;
}
keylen = ctx - > gk5e - > keylength ;
2010-03-17 13:03:03 -04:00
p = simple_get_bytes ( p , end , ctx - > Ksess , keylen ) ;
2010-03-17 13:02:54 -04:00
if ( IS_ERR ( p ) )
goto out_err ;
if ( p ! = end ) {
p = ERR_PTR ( - EINVAL ) ;
goto out_err ;
}
ctx - > mech_used . data = kmemdup ( gss_kerberos_mech . gm_oid . data ,
2010-05-13 12:51:02 -04:00
gss_kerberos_mech . gm_oid . len , gfp_mask ) ;
2010-03-17 13:02:54 -04:00
if ( unlikely ( ctx - > mech_used . data = = NULL ) ) {
p = ERR_PTR ( - ENOMEM ) ;
goto out_err ;
}
ctx - > mech_used . len = gss_kerberos_mech . gm_oid . len ;
switch ( ctx - > enctype ) {
case ENCTYPE_DES3_CBC_RAW :
2010-05-13 12:51:02 -04:00
return context_derive_keys_des3 ( ctx , gfp_mask ) ;
2010-03-17 13:02:54 -04:00
case ENCTYPE_AES128_CTS_HMAC_SHA1_96 :
case ENCTYPE_AES256_CTS_HMAC_SHA1_96 :
2010-05-13 12:51:02 -04:00
return context_derive_keys_new ( ctx , gfp_mask ) ;
2010-03-17 13:02:54 -04:00
default :
return - EINVAL ;
}
out_err :
return PTR_ERR ( p ) ;
}
2010-03-17 13:02:50 -04:00
static int
gss_import_sec_context_kerberos ( const void * p , size_t len ,
2010-05-13 12:51:02 -04:00
struct gss_ctx * ctx_id ,
2018-06-07 17:02:50 +02:00
time64_t * endtime ,
2010-05-13 12:51:02 -04:00
gfp_t gfp_mask )
2010-03-17 13:02:50 -04:00
{
const void * end = ( const void * ) ( ( const char * ) p + len ) ;
struct krb5_ctx * ctx ;
int ret ;
2010-05-13 12:51:02 -04:00
ctx = kzalloc ( sizeof ( * ctx ) , gfp_mask ) ;
2010-03-17 13:02:50 -04:00
if ( ctx = = NULL )
return - ENOMEM ;
if ( len = = 85 )
ret = gss_import_v1_context ( p , end , ctx ) ;
else
2010-05-13 12:51:02 -04:00
ret = gss_import_v2_context ( p , end , ctx , gfp_mask ) ;
2023-01-15 12:20:48 -05:00
memzero_explicit ( & ctx - > Ksess , sizeof ( ctx - > Ksess ) ) ;
2023-01-15 12:20:41 -05:00
if ( ret ) {
2010-03-17 13:02:50 -04:00
kfree ( ctx ) ;
2023-01-15 12:20:41 -05:00
return ret ;
}
2010-03-17 13:02:50 -04:00
2023-01-15 12:20:41 -05:00
ctx_id - > internal_ctx_id = ctx ;
if ( endtime )
* endtime = ctx - > endtime ;
return 0 ;
2010-03-17 13:02:50 -04:00
}
2005-04-16 15:20:36 -07:00
static void
gss_delete_sec_context_kerberos ( void * internal_ctx ) {
struct krb5_ctx * kctx = internal_ctx ;
2018-09-18 19:10:39 -07:00
crypto_free_sync_skcipher ( kctx - > seq ) ;
crypto_free_sync_skcipher ( kctx - > enc ) ;
crypto_free_sync_skcipher ( kctx - > acceptor_enc ) ;
crypto_free_sync_skcipher ( kctx - > initiator_enc ) ;
crypto_free_sync_skcipher ( kctx - > acceptor_enc_aux ) ;
crypto_free_sync_skcipher ( kctx - > initiator_enc_aux ) ;
2005-09-01 17:44:29 -07:00
kfree ( kctx - > mech_used . data ) ;
2005-04-16 15:20:36 -07:00
kfree ( kctx ) ;
}
2007-06-23 20:17:58 -04:00
static const struct gss_api_ops gss_kerberos_ops = {
2005-04-16 15:20:36 -07:00
. gss_import_sec_context = gss_import_sec_context_kerberos ,
. gss_get_mic = gss_get_mic_kerberos ,
. gss_verify_mic = gss_verify_mic_kerberos ,
2005-10-13 16:55:13 -04:00
. gss_wrap = gss_wrap_kerberos ,
. gss_unwrap = gss_unwrap_kerberos ,
2005-04-16 15:20:36 -07:00
. gss_delete_sec_context = gss_delete_sec_context_kerberos ,
} ;
static struct pf_desc gss_kerberos_pfs [ ] = {
[ 0 ] = {
. pseudoflavor = RPC_AUTH_GSS_KRB5 ,
2013-03-16 15:55:01 -04:00
. qop = GSS_C_QOP_DEFAULT ,
2005-04-16 15:20:36 -07:00
. service = RPC_GSS_SVC_NONE ,
. name = " krb5 " ,
} ,
[ 1 ] = {
. pseudoflavor = RPC_AUTH_GSS_KRB5I ,
2013-03-16 15:55:01 -04:00
. qop = GSS_C_QOP_DEFAULT ,
2005-04-16 15:20:36 -07:00
. service = RPC_GSS_SVC_INTEGRITY ,
. name = " krb5i " ,
2016-06-29 13:55:06 -04:00
. datatouch = true ,
2005-04-16 15:20:36 -07:00
} ,
2005-10-13 16:55:13 -04:00
[ 2 ] = {
. pseudoflavor = RPC_AUTH_GSS_KRB5P ,
2013-03-16 15:55:01 -04:00
. qop = GSS_C_QOP_DEFAULT ,
2005-10-13 16:55:13 -04:00
. service = RPC_GSS_SVC_PRIVACY ,
. name = " krb5p " ,
2016-06-29 13:55:06 -04:00
. datatouch = true ,
2005-10-13 16:55:13 -04:00
} ,
2005-04-16 15:20:36 -07:00
} ;
2011-06-22 10:50:08 -04:00
MODULE_ALIAS ( " rpc-auth-gss-krb5 " ) ;
MODULE_ALIAS ( " rpc-auth-gss-krb5i " ) ;
MODULE_ALIAS ( " rpc-auth-gss-krb5p " ) ;
MODULE_ALIAS ( " rpc-auth-gss-390003 " ) ;
MODULE_ALIAS ( " rpc-auth-gss-390004 " ) ;
MODULE_ALIAS ( " rpc-auth-gss-390005 " ) ;
2013-03-16 15:54:52 -04:00
MODULE_ALIAS ( " rpc-auth-gss-1.2.840.113554.1.2.2 " ) ;
2011-06-22 10:50:08 -04:00
2005-04-16 15:20:36 -07:00
static struct gss_api_mech gss_kerberos_mech = {
. gm_name = " krb5 " ,
. gm_owner = THIS_MODULE ,
2013-03-16 15:54:34 -04:00
. gm_oid = { 9 , " \x2a \x86 \x48 \x86 \xf7 \x12 \x01 \x02 \x02 " } ,
2005-04-16 15:20:36 -07:00
. gm_ops = & gss_kerberos_ops ,
. gm_pf_num = ARRAY_SIZE ( gss_kerberos_pfs ) ,
. gm_pfs = gss_kerberos_pfs ,
2011-05-31 12:24:58 -04:00
. gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES ,
2005-04-16 15:20:36 -07:00
} ;
static int __init init_kerberos_module ( void )
{
int status ;
status = gss_mech_register ( & gss_kerberos_mech ) ;
if ( status )
printk ( " Failed to register kerberos gss mechanism! \n " ) ;
return status ;
}
static void __exit cleanup_kerberos_module ( void )
{
gss_mech_unregister ( & gss_kerberos_mech ) ;
}
MODULE_LICENSE ( " GPL " ) ;
module_init ( init_kerberos_module ) ;
module_exit ( cleanup_kerberos_module ) ;