Path: blob/master/net/sunrpc/auth_gss/gss_krb5_mech.c
15112 views
/*1* linux/net/sunrpc/gss_krb5_mech.c2*3* Copyright (c) 2001-2008 The Regents of the University of Michigan.4* All rights reserved.5*6* Andy Adamson <[email protected]>7* J. Bruce Fields <[email protected]>8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12*13* 1. Redistributions of source code must retain the above copyright14* notice, this list of conditions and the following disclaimer.15* 2. Redistributions in binary form must reproduce the above copyright16* notice, this list of conditions and the following disclaimer in the17* documentation and/or other materials provided with the distribution.18* 3. Neither the name of the University nor the names of its19* contributors may be used to endorse or promote products derived20* from this software without specific prior written permission.21*22* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED23* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF24* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE25* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE26* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR27* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF28* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR29* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF30* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING31* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS32* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.33*34*/3536#include <linux/err.h>37#include <linux/module.h>38#include <linux/init.h>39#include <linux/types.h>40#include <linux/slab.h>41#include <linux/sunrpc/auth.h>42#include <linux/sunrpc/gss_krb5.h>43#include <linux/sunrpc/xdr.h>44#include <linux/crypto.h>45#include <linux/sunrpc/gss_krb5_enctypes.h>4647#ifdef RPC_DEBUG48# define RPCDBG_FACILITY RPCDBG_AUTH49#endif5051static struct gss_api_mech gss_kerberos_mech; /* forward declaration */5253static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {54/*55* DES (All DES enctypes are mapped to the same gss functionality)56*/57{58.etype = ENCTYPE_DES_CBC_RAW,59.ctype = CKSUMTYPE_RSA_MD5,60.name = "des-cbc-crc",61.encrypt_name = "cbc(des)",62.cksum_name = "md5",63.encrypt = krb5_encrypt,64.decrypt = krb5_decrypt,65.mk_key = NULL,66.signalg = SGN_ALG_DES_MAC_MD5,67.sealalg = SEAL_ALG_DES,68.keybytes = 7,69.keylength = 8,70.blocksize = 8,71.conflen = 8,72.cksumlength = 8,73.keyed_cksum = 0,74},75/*76* RC4-HMAC77*/78{79.etype = ENCTYPE_ARCFOUR_HMAC,80.ctype = CKSUMTYPE_HMAC_MD5_ARCFOUR,81.name = "rc4-hmac",82.encrypt_name = "ecb(arc4)",83.cksum_name = "hmac(md5)",84.encrypt = krb5_encrypt,85.decrypt = krb5_decrypt,86.mk_key = NULL,87.signalg = SGN_ALG_HMAC_MD5,88.sealalg = SEAL_ALG_MICROSOFT_RC4,89.keybytes = 16,90.keylength = 16,91.blocksize = 1,92.conflen = 8,93.cksumlength = 8,94.keyed_cksum = 1,95},96/*97* 3DES98*/99{100.etype = ENCTYPE_DES3_CBC_RAW,101.ctype = CKSUMTYPE_HMAC_SHA1_DES3,102.name = "des3-hmac-sha1",103.encrypt_name = "cbc(des3_ede)",104.cksum_name = "hmac(sha1)",105.encrypt = krb5_encrypt,106.decrypt = krb5_decrypt,107.mk_key = gss_krb5_des3_make_key,108.signalg = SGN_ALG_HMAC_SHA1_DES3_KD,109.sealalg = SEAL_ALG_DES3KD,110.keybytes = 21,111.keylength = 24,112.blocksize = 8,113.conflen = 8,114.cksumlength = 20,115.keyed_cksum = 1,116},117/*118* AES128119*/120{121.etype = ENCTYPE_AES128_CTS_HMAC_SHA1_96,122.ctype = CKSUMTYPE_HMAC_SHA1_96_AES128,123.name = "aes128-cts",124.encrypt_name = "cts(cbc(aes))",125.cksum_name = "hmac(sha1)",126.encrypt = krb5_encrypt,127.decrypt = krb5_decrypt,128.mk_key = gss_krb5_aes_make_key,129.encrypt_v2 = gss_krb5_aes_encrypt,130.decrypt_v2 = gss_krb5_aes_decrypt,131.signalg = -1,132.sealalg = -1,133.keybytes = 16,134.keylength = 16,135.blocksize = 16,136.conflen = 16,137.cksumlength = 12,138.keyed_cksum = 1,139},140/*141* AES256142*/143{144.etype = ENCTYPE_AES256_CTS_HMAC_SHA1_96,145.ctype = CKSUMTYPE_HMAC_SHA1_96_AES256,146.name = "aes256-cts",147.encrypt_name = "cts(cbc(aes))",148.cksum_name = "hmac(sha1)",149.encrypt = krb5_encrypt,150.decrypt = krb5_decrypt,151.mk_key = gss_krb5_aes_make_key,152.encrypt_v2 = gss_krb5_aes_encrypt,153.decrypt_v2 = gss_krb5_aes_decrypt,154.signalg = -1,155.sealalg = -1,156.keybytes = 32,157.keylength = 32,158.blocksize = 16,159.conflen = 16,160.cksumlength = 12,161.keyed_cksum = 1,162},163};164165static const int num_supported_enctypes =166ARRAY_SIZE(supported_gss_krb5_enctypes);167168static int169supported_gss_krb5_enctype(int etype)170{171int i;172for (i = 0; i < num_supported_enctypes; i++)173if (supported_gss_krb5_enctypes[i].etype == etype)174return 1;175return 0;176}177178static const struct gss_krb5_enctype *179get_gss_krb5_enctype(int etype)180{181int i;182for (i = 0; i < num_supported_enctypes; i++)183if (supported_gss_krb5_enctypes[i].etype == etype)184return &supported_gss_krb5_enctypes[i];185return NULL;186}187188static const void *189simple_get_bytes(const void *p, const void *end, void *res, int len)190{191const void *q = (const void *)((const char *)p + len);192if (unlikely(q > end || q < p))193return ERR_PTR(-EFAULT);194memcpy(res, p, len);195return q;196}197198static const void *199simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)200{201const void *q;202unsigned int len;203204p = simple_get_bytes(p, end, &len, sizeof(len));205if (IS_ERR(p))206return p;207q = (const void *)((const char *)p + len);208if (unlikely(q > end || q < p))209return ERR_PTR(-EFAULT);210res->data = kmemdup(p, len, GFP_NOFS);211if (unlikely(res->data == NULL))212return ERR_PTR(-ENOMEM);213res->len = len;214return q;215}216217static inline const void *218get_key(const void *p, const void *end,219struct krb5_ctx *ctx, struct crypto_blkcipher **res)220{221struct xdr_netobj key;222int alg;223224p = simple_get_bytes(p, end, &alg, sizeof(alg));225if (IS_ERR(p))226goto out_err;227228switch (alg) {229case ENCTYPE_DES_CBC_CRC:230case ENCTYPE_DES_CBC_MD4:231case ENCTYPE_DES_CBC_MD5:232/* Map all these key types to ENCTYPE_DES_CBC_RAW */233alg = ENCTYPE_DES_CBC_RAW;234break;235}236237if (!supported_gss_krb5_enctype(alg)) {238printk(KERN_WARNING "gss_kerberos_mech: unsupported "239"encryption key algorithm %d\n", alg);240p = ERR_PTR(-EINVAL);241goto out_err;242}243p = simple_get_netobj(p, end, &key);244if (IS_ERR(p))245goto out_err;246247*res = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,248CRYPTO_ALG_ASYNC);249if (IS_ERR(*res)) {250printk(KERN_WARNING "gss_kerberos_mech: unable to initialize "251"crypto algorithm %s\n", ctx->gk5e->encrypt_name);252*res = NULL;253goto out_err_free_key;254}255if (crypto_blkcipher_setkey(*res, key.data, key.len)) {256printk(KERN_WARNING "gss_kerberos_mech: error setting key for "257"crypto algorithm %s\n", ctx->gk5e->encrypt_name);258goto out_err_free_tfm;259}260261kfree(key.data);262return p;263264out_err_free_tfm:265crypto_free_blkcipher(*res);266out_err_free_key:267kfree(key.data);268p = ERR_PTR(-EINVAL);269out_err:270return p;271}272273static int274gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)275{276int tmp;277278p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));279if (IS_ERR(p))280goto out_err;281282/* Old format supports only DES! Any other enctype uses new format */283ctx->enctype = ENCTYPE_DES_CBC_RAW;284285ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);286if (ctx->gk5e == NULL) {287p = ERR_PTR(-EINVAL);288goto out_err;289}290291/* The downcall format was designed before we completely understood292* the uses of the context fields; so it includes some stuff we293* just give some minimal sanity-checking, and some we ignore294* completely (like the next twenty bytes): */295if (unlikely(p + 20 > end || p + 20 < p)) {296p = ERR_PTR(-EFAULT);297goto out_err;298}299p += 20;300p = simple_get_bytes(p, end, &tmp, sizeof(tmp));301if (IS_ERR(p))302goto out_err;303if (tmp != SGN_ALG_DES_MAC_MD5) {304p = ERR_PTR(-ENOSYS);305goto out_err;306}307p = simple_get_bytes(p, end, &tmp, sizeof(tmp));308if (IS_ERR(p))309goto out_err;310if (tmp != SEAL_ALG_DES) {311p = ERR_PTR(-ENOSYS);312goto out_err;313}314p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));315if (IS_ERR(p))316goto out_err;317p = simple_get_bytes(p, end, &ctx->seq_send, sizeof(ctx->seq_send));318if (IS_ERR(p))319goto out_err;320p = simple_get_netobj(p, end, &ctx->mech_used);321if (IS_ERR(p))322goto out_err;323p = get_key(p, end, ctx, &ctx->enc);324if (IS_ERR(p))325goto out_err_free_mech;326p = get_key(p, end, ctx, &ctx->seq);327if (IS_ERR(p))328goto out_err_free_key1;329if (p != end) {330p = ERR_PTR(-EFAULT);331goto out_err_free_key2;332}333334return 0;335336out_err_free_key2:337crypto_free_blkcipher(ctx->seq);338out_err_free_key1:339crypto_free_blkcipher(ctx->enc);340out_err_free_mech:341kfree(ctx->mech_used.data);342out_err:343return PTR_ERR(p);344}345346struct crypto_blkcipher *347context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key)348{349struct crypto_blkcipher *cp;350351cp = crypto_alloc_blkcipher(cname, 0, CRYPTO_ALG_ASYNC);352if (IS_ERR(cp)) {353dprintk("gss_kerberos_mech: unable to initialize "354"crypto algorithm %s\n", cname);355return NULL;356}357if (crypto_blkcipher_setkey(cp, key, ctx->gk5e->keylength)) {358dprintk("gss_kerberos_mech: error setting key for "359"crypto algorithm %s\n", cname);360crypto_free_blkcipher(cp);361return NULL;362}363return cp;364}365366static inline void367set_cdata(u8 cdata[GSS_KRB5_K5CLENGTH], u32 usage, u8 seed)368{369cdata[0] = (usage>>24)&0xff;370cdata[1] = (usage>>16)&0xff;371cdata[2] = (usage>>8)&0xff;372cdata[3] = usage&0xff;373cdata[4] = seed;374}375376static int377context_derive_keys_des3(struct krb5_ctx *ctx, gfp_t gfp_mask)378{379struct xdr_netobj c, keyin, keyout;380u8 cdata[GSS_KRB5_K5CLENGTH];381u32 err;382383c.len = GSS_KRB5_K5CLENGTH;384c.data = cdata;385386keyin.data = ctx->Ksess;387keyin.len = ctx->gk5e->keylength;388keyout.len = ctx->gk5e->keylength;389390/* seq uses the raw key */391ctx->seq = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,392ctx->Ksess);393if (ctx->seq == NULL)394goto out_err;395396ctx->enc = context_v2_alloc_cipher(ctx, ctx->gk5e->encrypt_name,397ctx->Ksess);398if (ctx->enc == NULL)399goto out_free_seq;400401/* derive cksum */402set_cdata(cdata, KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM);403keyout.data = ctx->cksum;404err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);405if (err) {406dprintk("%s: Error %d deriving cksum key\n",407__func__, err);408goto out_free_enc;409}410411return 0;412413out_free_enc:414crypto_free_blkcipher(ctx->enc);415out_free_seq:416crypto_free_blkcipher(ctx->seq);417out_err:418return -EINVAL;419}420421/*422* Note that RC4 depends on deriving keys using the sequence423* number or the checksum of a token. Therefore, the final keys424* cannot be calculated until the token is being constructed!425*/426static int427context_derive_keys_rc4(struct krb5_ctx *ctx)428{429struct crypto_hash *hmac;430char sigkeyconstant[] = "signaturekey";431int slen = strlen(sigkeyconstant) + 1; /* include null terminator */432struct hash_desc desc;433struct scatterlist sg[1];434int err;435436dprintk("RPC: %s: entered\n", __func__);437/*438* derive cksum (aka Ksign) key439*/440hmac = crypto_alloc_hash(ctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);441if (IS_ERR(hmac)) {442dprintk("%s: error %ld allocating hash '%s'\n",443__func__, PTR_ERR(hmac), ctx->gk5e->cksum_name);444err = PTR_ERR(hmac);445goto out_err;446}447448err = crypto_hash_setkey(hmac, ctx->Ksess, ctx->gk5e->keylength);449if (err)450goto out_err_free_hmac;451452sg_init_table(sg, 1);453sg_set_buf(sg, sigkeyconstant, slen);454455desc.tfm = hmac;456desc.flags = 0;457458err = crypto_hash_init(&desc);459if (err)460goto out_err_free_hmac;461462err = crypto_hash_digest(&desc, sg, slen, ctx->cksum);463if (err)464goto out_err_free_hmac;465/*466* allocate hash, and blkciphers for data and seqnum encryption467*/468ctx->enc = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,469CRYPTO_ALG_ASYNC);470if (IS_ERR(ctx->enc)) {471err = PTR_ERR(ctx->enc);472goto out_err_free_hmac;473}474475ctx->seq = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,476CRYPTO_ALG_ASYNC);477if (IS_ERR(ctx->seq)) {478crypto_free_blkcipher(ctx->enc);479err = PTR_ERR(ctx->seq);480goto out_err_free_hmac;481}482483dprintk("RPC: %s: returning success\n", __func__);484485err = 0;486487out_err_free_hmac:488crypto_free_hash(hmac);489out_err:490dprintk("RPC: %s: returning %d\n", __func__, err);491return err;492}493494static int495context_derive_keys_new(struct krb5_ctx *ctx, gfp_t gfp_mask)496{497struct xdr_netobj c, keyin, keyout;498u8 cdata[GSS_KRB5_K5CLENGTH];499u32 err;500501c.len = GSS_KRB5_K5CLENGTH;502c.data = cdata;503504keyin.data = ctx->Ksess;505keyin.len = ctx->gk5e->keylength;506keyout.len = ctx->gk5e->keylength;507508/* initiator seal encryption */509set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);510keyout.data = ctx->initiator_seal;511err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);512if (err) {513dprintk("%s: Error %d deriving initiator_seal key\n",514__func__, err);515goto out_err;516}517ctx->initiator_enc = context_v2_alloc_cipher(ctx,518ctx->gk5e->encrypt_name,519ctx->initiator_seal);520if (ctx->initiator_enc == NULL)521goto out_err;522523/* acceptor seal encryption */524set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_ENCRYPTION);525keyout.data = ctx->acceptor_seal;526err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);527if (err) {528dprintk("%s: Error %d deriving acceptor_seal key\n",529__func__, err);530goto out_free_initiator_enc;531}532ctx->acceptor_enc = context_v2_alloc_cipher(ctx,533ctx->gk5e->encrypt_name,534ctx->acceptor_seal);535if (ctx->acceptor_enc == NULL)536goto out_free_initiator_enc;537538/* initiator sign checksum */539set_cdata(cdata, KG_USAGE_INITIATOR_SIGN, KEY_USAGE_SEED_CHECKSUM);540keyout.data = ctx->initiator_sign;541err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);542if (err) {543dprintk("%s: Error %d deriving initiator_sign key\n",544__func__, err);545goto out_free_acceptor_enc;546}547548/* acceptor sign checksum */549set_cdata(cdata, KG_USAGE_ACCEPTOR_SIGN, KEY_USAGE_SEED_CHECKSUM);550keyout.data = ctx->acceptor_sign;551err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);552if (err) {553dprintk("%s: Error %d deriving acceptor_sign key\n",554__func__, err);555goto out_free_acceptor_enc;556}557558/* initiator seal integrity */559set_cdata(cdata, KG_USAGE_INITIATOR_SEAL, KEY_USAGE_SEED_INTEGRITY);560keyout.data = ctx->initiator_integ;561err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);562if (err) {563dprintk("%s: Error %d deriving initiator_integ key\n",564__func__, err);565goto out_free_acceptor_enc;566}567568/* acceptor seal integrity */569set_cdata(cdata, KG_USAGE_ACCEPTOR_SEAL, KEY_USAGE_SEED_INTEGRITY);570keyout.data = ctx->acceptor_integ;571err = krb5_derive_key(ctx->gk5e, &keyin, &keyout, &c, gfp_mask);572if (err) {573dprintk("%s: Error %d deriving acceptor_integ key\n",574__func__, err);575goto out_free_acceptor_enc;576}577578switch (ctx->enctype) {579case ENCTYPE_AES128_CTS_HMAC_SHA1_96:580case ENCTYPE_AES256_CTS_HMAC_SHA1_96:581ctx->initiator_enc_aux =582context_v2_alloc_cipher(ctx, "cbc(aes)",583ctx->initiator_seal);584if (ctx->initiator_enc_aux == NULL)585goto out_free_acceptor_enc;586ctx->acceptor_enc_aux =587context_v2_alloc_cipher(ctx, "cbc(aes)",588ctx->acceptor_seal);589if (ctx->acceptor_enc_aux == NULL) {590crypto_free_blkcipher(ctx->initiator_enc_aux);591goto out_free_acceptor_enc;592}593}594595return 0;596597out_free_acceptor_enc:598crypto_free_blkcipher(ctx->acceptor_enc);599out_free_initiator_enc:600crypto_free_blkcipher(ctx->initiator_enc);601out_err:602return -EINVAL;603}604605static int606gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,607gfp_t gfp_mask)608{609int keylen;610611p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));612if (IS_ERR(p))613goto out_err;614ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR;615616p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));617if (IS_ERR(p))618goto out_err;619p = simple_get_bytes(p, end, &ctx->seq_send64, sizeof(ctx->seq_send64));620if (IS_ERR(p))621goto out_err;622/* set seq_send for use by "older" enctypes */623ctx->seq_send = ctx->seq_send64;624if (ctx->seq_send64 != ctx->seq_send) {625dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__,626(long unsigned)ctx->seq_send64, ctx->seq_send);627p = ERR_PTR(-EINVAL);628goto out_err;629}630p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype));631if (IS_ERR(p))632goto out_err;633/* Map ENCTYPE_DES3_CBC_SHA1 to ENCTYPE_DES3_CBC_RAW */634if (ctx->enctype == ENCTYPE_DES3_CBC_SHA1)635ctx->enctype = ENCTYPE_DES3_CBC_RAW;636ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);637if (ctx->gk5e == NULL) {638dprintk("gss_kerberos_mech: unsupported krb5 enctype %u\n",639ctx->enctype);640p = ERR_PTR(-EINVAL);641goto out_err;642}643keylen = ctx->gk5e->keylength;644645p = simple_get_bytes(p, end, ctx->Ksess, keylen);646if (IS_ERR(p))647goto out_err;648649if (p != end) {650p = ERR_PTR(-EINVAL);651goto out_err;652}653654ctx->mech_used.data = kmemdup(gss_kerberos_mech.gm_oid.data,655gss_kerberos_mech.gm_oid.len, gfp_mask);656if (unlikely(ctx->mech_used.data == NULL)) {657p = ERR_PTR(-ENOMEM);658goto out_err;659}660ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;661662switch (ctx->enctype) {663case ENCTYPE_DES3_CBC_RAW:664return context_derive_keys_des3(ctx, gfp_mask);665case ENCTYPE_ARCFOUR_HMAC:666return context_derive_keys_rc4(ctx);667case ENCTYPE_AES128_CTS_HMAC_SHA1_96:668case ENCTYPE_AES256_CTS_HMAC_SHA1_96:669return context_derive_keys_new(ctx, gfp_mask);670default:671return -EINVAL;672}673674out_err:675return PTR_ERR(p);676}677678static int679gss_import_sec_context_kerberos(const void *p, size_t len,680struct gss_ctx *ctx_id,681gfp_t gfp_mask)682{683const void *end = (const void *)((const char *)p + len);684struct krb5_ctx *ctx;685int ret;686687ctx = kzalloc(sizeof(*ctx), gfp_mask);688if (ctx == NULL)689return -ENOMEM;690691if (len == 85)692ret = gss_import_v1_context(p, end, ctx);693else694ret = gss_import_v2_context(p, end, ctx, gfp_mask);695696if (ret == 0)697ctx_id->internal_ctx_id = ctx;698else699kfree(ctx);700701dprintk("RPC: %s: returning %d\n", __func__, ret);702return ret;703}704705static void706gss_delete_sec_context_kerberos(void *internal_ctx) {707struct krb5_ctx *kctx = internal_ctx;708709crypto_free_blkcipher(kctx->seq);710crypto_free_blkcipher(kctx->enc);711crypto_free_blkcipher(kctx->acceptor_enc);712crypto_free_blkcipher(kctx->initiator_enc);713crypto_free_blkcipher(kctx->acceptor_enc_aux);714crypto_free_blkcipher(kctx->initiator_enc_aux);715kfree(kctx->mech_used.data);716kfree(kctx);717}718719static const struct gss_api_ops gss_kerberos_ops = {720.gss_import_sec_context = gss_import_sec_context_kerberos,721.gss_get_mic = gss_get_mic_kerberos,722.gss_verify_mic = gss_verify_mic_kerberos,723.gss_wrap = gss_wrap_kerberos,724.gss_unwrap = gss_unwrap_kerberos,725.gss_delete_sec_context = gss_delete_sec_context_kerberos,726};727728static struct pf_desc gss_kerberos_pfs[] = {729[0] = {730.pseudoflavor = RPC_AUTH_GSS_KRB5,731.service = RPC_GSS_SVC_NONE,732.name = "krb5",733},734[1] = {735.pseudoflavor = RPC_AUTH_GSS_KRB5I,736.service = RPC_GSS_SVC_INTEGRITY,737.name = "krb5i",738},739[2] = {740.pseudoflavor = RPC_AUTH_GSS_KRB5P,741.service = RPC_GSS_SVC_PRIVACY,742.name = "krb5p",743},744};745746static struct gss_api_mech gss_kerberos_mech = {747.gm_name = "krb5",748.gm_owner = THIS_MODULE,749.gm_oid = {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"},750.gm_ops = &gss_kerberos_ops,751.gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs),752.gm_pfs = gss_kerberos_pfs,753.gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES,754};755756static int __init init_kerberos_module(void)757{758int status;759760status = gss_mech_register(&gss_kerberos_mech);761if (status)762printk("Failed to register kerberos gss mechanism!\n");763return status;764}765766static void __exit cleanup_kerberos_module(void)767{768gss_mech_unregister(&gss_kerberos_mech);769}770771MODULE_LICENSE("GPL");772module_init(init_kerberos_module);773module_exit(cleanup_kerberos_module);774775776