linux/net/sunrpc/auth_gss/gss_krb5_seqnum.c
<<
>>
Prefs
   1/*
   2 *  linux/net/sunrpc/gss_krb5_seqnum.c
   3 *
   4 *  Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/util_seqnum.c
   5 *
   6 *  Copyright (c) 2000 The Regents of the University of Michigan.
   7 *  All rights reserved.
   8 *
   9 *  Andy Adamson   <andros@umich.edu>
  10 */
  11
  12/*
  13 * Copyright 1993 by OpenVision Technologies, Inc.
  14 *
  15 * Permission to use, copy, modify, distribute, and sell this software
  16 * and its documentation for any purpose is hereby granted without fee,
  17 * provided that the above copyright notice appears in all copies and
  18 * that both that copyright notice and this permission notice appear in
  19 * supporting documentation, and that the name of OpenVision not be used
  20 * in advertising or publicity pertaining to distribution of the software
  21 * without specific, written prior permission. OpenVision makes no
  22 * representations about the suitability of this software for any
  23 * purpose.  It is provided "as is" without express or implied warranty.
  24 *
  25 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  26 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  27 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  28 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  29 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  30 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  31 * PERFORMANCE OF THIS SOFTWARE.
  32 */
  33
  34#include <crypto/skcipher.h>
  35#include <linux/types.h>
  36#include <linux/sunrpc/gss_krb5.h>
  37
  38#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
  39# define RPCDBG_FACILITY        RPCDBG_AUTH
  40#endif
  41
  42static s32
  43krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
  44                      unsigned char *cksum, unsigned char *buf)
  45{
  46        struct crypto_skcipher *cipher;
  47        unsigned char *plain;
  48        s32 code;
  49
  50        dprintk("RPC:       %s:\n", __func__);
  51        cipher = crypto_alloc_skcipher(kctx->gk5e->encrypt_name, 0,
  52                                       CRYPTO_ALG_ASYNC);
  53        if (IS_ERR(cipher))
  54                return PTR_ERR(cipher);
  55
  56        plain = kmalloc(8, GFP_NOFS);
  57        if (!plain)
  58                return -ENOMEM;
  59
  60        plain[0] = (unsigned char) ((seqnum >> 24) & 0xff);
  61        plain[1] = (unsigned char) ((seqnum >> 16) & 0xff);
  62        plain[2] = (unsigned char) ((seqnum >> 8) & 0xff);
  63        plain[3] = (unsigned char) ((seqnum >> 0) & 0xff);
  64        plain[4] = direction;
  65        plain[5] = direction;
  66        plain[6] = direction;
  67        plain[7] = direction;
  68
  69        code = krb5_rc4_setup_seq_key(kctx, cipher, cksum);
  70        if (code)
  71                goto out;
  72
  73        code = krb5_encrypt(cipher, cksum, plain, buf, 8);
  74out:
  75        crypto_free_skcipher(cipher);
  76        kfree(plain);
  77        return code;
  78}
  79s32
  80krb5_make_seq_num(struct krb5_ctx *kctx,
  81                struct crypto_skcipher *key,
  82                int direction,
  83                u32 seqnum,
  84                unsigned char *cksum, unsigned char *buf)
  85{
  86        unsigned char *plain;
  87        s32 code;
  88
  89        if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
  90                return krb5_make_rc4_seq_num(kctx, direction, seqnum,
  91                                             cksum, buf);
  92
  93        plain = kmalloc(8, GFP_NOFS);
  94        if (!plain)
  95                return -ENOMEM;
  96
  97        plain[0] = (unsigned char) (seqnum & 0xff);
  98        plain[1] = (unsigned char) ((seqnum >> 8) & 0xff);
  99        plain[2] = (unsigned char) ((seqnum >> 16) & 0xff);
 100        plain[3] = (unsigned char) ((seqnum >> 24) & 0xff);
 101
 102        plain[4] = direction;
 103        plain[5] = direction;
 104        plain[6] = direction;
 105        plain[7] = direction;
 106
 107        code = krb5_encrypt(key, cksum, plain, buf, 8);
 108        kfree(plain);
 109        return code;
 110}
 111
 112static s32
 113krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum,
 114                     unsigned char *buf, int *direction, s32 *seqnum)
 115{
 116        struct crypto_skcipher *cipher;
 117        unsigned char *plain;
 118        s32 code;
 119
 120        dprintk("RPC:       %s:\n", __func__);
 121        cipher = crypto_alloc_skcipher(kctx->gk5e->encrypt_name, 0,
 122                                       CRYPTO_ALG_ASYNC);
 123        if (IS_ERR(cipher))
 124                return PTR_ERR(cipher);
 125
 126        code = krb5_rc4_setup_seq_key(kctx, cipher, cksum);
 127        if (code)
 128                goto out;
 129
 130        plain = kmalloc(8, GFP_NOFS);
 131        if (!plain) {
 132                code = -ENOMEM;
 133                goto out;
 134        }
 135
 136        code = krb5_decrypt(cipher, cksum, buf, plain, 8);
 137        if (code)
 138                goto out_plain;
 139
 140        if ((plain[4] != plain[5]) || (plain[4] != plain[6])
 141                                   || (plain[4] != plain[7])) {
 142                code = (s32)KG_BAD_SEQ;
 143                goto out_plain;
 144        }
 145
 146        *direction = plain[4];
 147
 148        *seqnum = ((plain[0] << 24) | (plain[1] << 16) |
 149                                        (plain[2] << 8) | (plain[3]));
 150out_plain:
 151        kfree(plain);
 152out:
 153        crypto_free_skcipher(cipher);
 154        return code;
 155}
 156
 157s32
 158krb5_get_seq_num(struct krb5_ctx *kctx,
 159               unsigned char *cksum,
 160               unsigned char *buf,
 161               int *direction, u32 *seqnum)
 162{
 163        s32 code;
 164        struct crypto_skcipher *key = kctx->seq;
 165        unsigned char *plain;
 166
 167        dprintk("RPC:       krb5_get_seq_num:\n");
 168
 169        if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
 170                return krb5_get_rc4_seq_num(kctx, cksum, buf,
 171                                            direction, seqnum);
 172        plain = kmalloc(8, GFP_NOFS);
 173        if (!plain)
 174                return -ENOMEM;
 175
 176        if ((code = krb5_decrypt(key, cksum, buf, plain, 8)))
 177                goto out;
 178
 179        if ((plain[4] != plain[5]) || (plain[4] != plain[6]) ||
 180            (plain[4] != plain[7])) {
 181                code = (s32)KG_BAD_SEQ;
 182                goto out;
 183        }
 184
 185        *direction = plain[4];
 186
 187        *seqnum = ((plain[0]) |
 188                   (plain[1] << 8) | (plain[2] << 16) | (plain[3] << 24));
 189
 190out:
 191        kfree(plain);
 192        return code;
 193}
 194