linux/net/sunrpc/auth_gss/gss_spkm3_token.c
<<
>>
Prefs
   1/*
   2 *  linux/net/sunrpc/gss_spkm3_token.c
   3 *
   4 *  Copyright (c) 2003 The Regents of the University of Michigan.
   5 *  All rights reserved.
   6 *
   7 *  Andy Adamson <andros@umich.edu>
   8 *
   9 *  Redistribution and use in source and binary forms, with or without
  10 *  modification, are permitted provided that the following conditions
  11 *  are met:
  12 *
  13 *  1. Redistributions of source code must retain the above copyright
  14 *     notice, this list of conditions and the following disclaimer.
  15 *  2. Redistributions in binary form must reproduce the above copyright
  16 *     notice, this list of conditions and the following disclaimer in the
  17 *     documentation and/or other materials provided with the distribution.
  18 *  3. Neither the name of the University nor the names of its
  19 *     contributors may be used to endorse or promote products derived
  20 *     from this software without specific prior written permission.
  21 *
  22 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  23 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  24 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  25 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  29 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  30 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  31 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33 *
  34 */
  35
  36#include <linux/types.h>
  37#include <linux/slab.h>
  38#include <linux/jiffies.h>
  39#include <linux/sunrpc/gss_spkm3.h>
  40#include <linux/random.h>
  41#include <linux/crypto.h>
  42
  43#ifdef RPC_DEBUG
  44# define RPCDBG_FACILITY        RPCDBG_AUTH
  45#endif
  46
  47/*
  48 * asn1_bitstring_len()
  49 *
  50 * calculate the asn1 bitstring length of the xdr_netobject
  51 */
  52void
  53asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits)
  54{
  55        int i, zbit = 0,elen = in->len;
  56        char *ptr;
  57
  58        ptr = &in->data[in->len -1];
  59
  60        /* count trailing 0's */
  61        for(i = in->len; i > 0; i--) {
  62                if (*ptr == 0) {
  63                        ptr--;
  64                        elen--;
  65                } else
  66                        break;
  67        }
  68
  69        /* count number of 0 bits in final octet */
  70        ptr = &in->data[elen - 1];
  71        for(i = 0; i < 8; i++) {
  72                short mask = 0x01;
  73
  74                if (!((mask << i) & *ptr))
  75                        zbit++;
  76                else
  77                        break;
  78        }
  79        *enclen = elen;
  80        *zerobits = zbit;
  81}
  82
  83/*
  84 * decode_asn1_bitstring()
  85 *
  86 * decode a bitstring into a buffer of the expected length.
  87 * enclen = bit string length
  88 * explen = expected length (define in rfc)
  89 */
  90int
  91decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, int explen)
  92{
  93        if (!(out->data = kzalloc(explen,GFP_NOFS)))
  94                return 0;
  95        out->len = explen;
  96        memcpy(out->data, in, enclen);
  97        return 1;
  98}
  99
 100/*
 101 * SPKMInnerContextToken choice SPKM_MIC asn1 token layout
 102 *
 103 * contextid is always 16 bytes plain data. max asn1 bitstring len = 17.
 104 *
 105 * tokenlen = pos[0] to end of token (max pos[45] with MD5 cksum)
 106 *
 107 * pos  value
 108 * ----------
 109 * [0]  a4  SPKM-MIC tag
 110 * [1]  ??  innertoken length  (max 44)
 111 *
 112 *
 113 * tok_hdr piece of checksum data starts here
 114 *
 115 * the maximum mic-header len = 9 + 17 = 26
 116 *      mic-header
 117 *      ----------
 118 * [2]  30      SEQUENCE tag
 119 * [3]  ??      mic-header length: (max 23) = TokenID + ContextID
 120 *
 121 *              TokenID  - all fields constant and can be hardcoded
 122 *              -------
 123 * [4]    02    Type 2
 124 * [5]    02    Length 2
 125 * [6][7] 01 01 TokenID (SPKM_MIC_TOK)
 126 *
 127 *              ContextID  - encoded length not constant, calculated
 128 *              ---------
 129 * [8]  03      Type 3
 130 * [9]  ??      encoded length
 131 * [10] ??      ctxzbit
 132 * [11]         contextid
 133 *
 134 * mic_header piece of checksum data ends here.
 135 *
 136 *      int-cksum - encoded length not constant, calculated
 137 *      ---------
 138 * [??] 03      Type 3
 139 * [??] ??      encoded length
 140 * [??] ??      md5zbit
 141 * [??]         int-cksum (NID_md5 = 16)
 142 *
 143 * maximum SPKM-MIC innercontext token length =
 144 *       10 + encoded contextid_size(17 max) + 2 + encoded
 145 *       cksum_size (17 maxfor NID_md5) = 46
 146 */
 147
 148/*
 149 * spkm3_mic_header()
 150 *
 151 * Prepare the SPKM_MIC_TOK mic-header for check-sum calculation
 152 * elen: 16 byte context id asn1 bitstring encoded length
 153 */
 154void
 155spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, unsigned char *ctxdata, int elen, int zbit)
 156{
 157        char *hptr = *hdrbuf;
 158        char *top = *hdrbuf;
 159
 160        *(u8 *)hptr++ = 0x30;
 161        *(u8 *)hptr++ = elen + 7;  /* on the wire header length */
 162
 163        /* tokenid */
 164        *(u8 *)hptr++ = 0x02;
 165        *(u8 *)hptr++ = 0x02;
 166        *(u8 *)hptr++ = 0x01;
 167        *(u8 *)hptr++ = 0x01;
 168
 169        /* coniextid */
 170        *(u8 *)hptr++ = 0x03;
 171        *(u8 *)hptr++ = elen + 1; /* add 1 to include zbit */
 172        *(u8 *)hptr++ = zbit;
 173        memcpy(hptr, ctxdata, elen);
 174        hptr += elen;
 175        *hdrlen = hptr - top;
 176}
 177
 178/*
 179 * spkm3_mic_innercontext_token()
 180 *
 181 * *tokp points to the beginning of the SPKM_MIC token  described
 182 * in rfc 2025, section 3.2.1:
 183 *
 184 * toklen is the inner token length
 185 */
 186void
 187spkm3_make_mic_token(unsigned char **tokp, int toklen, struct xdr_netobj *mic_hdr, struct xdr_netobj *md5cksum, int md5elen, int md5zbit)
 188{
 189        unsigned char *ict = *tokp;
 190
 191        *(u8 *)ict++ = 0xa4;
 192        *(u8 *)ict++ = toklen;
 193        memcpy(ict, mic_hdr->data, mic_hdr->len);
 194        ict += mic_hdr->len;
 195
 196        *(u8 *)ict++ = 0x03;
 197        *(u8 *)ict++ = md5elen + 1; /* add 1 to include zbit */
 198        *(u8 *)ict++ = md5zbit;
 199        memcpy(ict, md5cksum->data, md5elen);
 200}
 201
 202u32
 203spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, unsigned char **cksum)
 204{
 205        struct xdr_netobj       spkm3_ctx_id = {.len =0, .data = NULL};
 206        unsigned char           *ptr = *tokp;
 207        int                     ctxelen;
 208        u32                     ret = GSS_S_DEFECTIVE_TOKEN;
 209
 210        /* spkm3 innercontext token preamble */
 211        if ((ptr[0] != 0xa4) || (ptr[2] != 0x30)) {
 212                dprintk("RPC:       BAD SPKM ictoken preamble\n");
 213                goto out;
 214        }
 215
 216        *mic_hdrlen = ptr[3];
 217
 218        /* token type */
 219        if ((ptr[4] != 0x02) || (ptr[5] != 0x02)) {
 220                dprintk("RPC:       BAD asn1 SPKM3 token type\n");
 221                goto out;
 222        }
 223
 224        /* only support SPKM_MIC_TOK */
 225        if((ptr[6] != 0x01) || (ptr[7] != 0x01)) {
 226                dprintk("RPC:       ERROR unsupported SPKM3 token \n");
 227                goto out;
 228        }
 229
 230        /* contextid */
 231        if (ptr[8] != 0x03) {
 232                dprintk("RPC:       BAD SPKM3 asn1 context-id type\n");
 233                goto out;
 234        }
 235
 236        ctxelen = ptr[9];
 237        if (ctxelen > 17) {  /* length includes asn1 zbit octet */
 238                dprintk("RPC:       BAD SPKM3 contextid len %d\n", ctxelen);
 239                goto out;
 240        }
 241
 242        /* ignore ptr[10] */
 243
 244        if(!decode_asn1_bitstring(&spkm3_ctx_id, &ptr[11], ctxelen - 1, 16))
 245                goto out;
 246
 247        /*
 248        * in the current implementation: the optional int-alg is not present
 249        * so the default int-alg (md5) is used the optional snd-seq field is
 250        * also not present
 251        */
 252
 253        if (*mic_hdrlen != 6 + ctxelen) {
 254                dprintk("RPC:       BAD SPKM_ MIC_TOK header len %d: we only "
 255                                "support default int-alg (should be absent) "
 256                                "and do not support snd-seq\n", *mic_hdrlen);
 257                goto out;
 258        }
 259        /* checksum */
 260        *cksum = (&ptr[10] + ctxelen); /* ctxelen includes ptr[10] */
 261
 262        ret = GSS_S_COMPLETE;
 263out:
 264        kfree(spkm3_ctx_id.data);
 265        return ret;
 266}
 267
 268
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.