File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / ecp_dese_bis.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:39:23 2021 UTC (3 years, 2 months ago) by misho
Branches: mpd, MAIN
CVS tags: v5_9p16, v5_9, HEAD
mpd 5.9


/*
 * ecp_dese.c
 *
 * Rewritten by Alexander Motin <mav@FreeBSD.org>
 * Written by Archie Cobbs <archie@freebsd.org>
 * Copyright (c) 1998-1999 Whistle Communications, Inc. All rights reserved.
 * See ``COPYRIGHT.whistle''
 */

#include "ppp.h"
#include "ecp.h"
#include "log.h"

/*
 * DEFINITIONS
 */

  #define DES_OVERHEAD		2

/*
 * INTERNAL FUNCTIONS
 */

  static int	DeseBisInit(Bund b, int dir);
  static void	DeseBisConfigure(Bund b);
  static int	DeseBisSubtractBloat(Bund b, int size);
  static Mbuf	DeseBisEncrypt(Bund b, Mbuf plain);
  static Mbuf	DeseBisDecrypt(Bund b, Mbuf cypher);
  static void	DeseBisCleanup(Bund b, int dir);
  static int    DeseBisStat(Context ctx, int dir);

  static u_char	*DeseBisBuildConfigReq(Bund b, u_char *cp);
  static void	DeseBisDecodeConfigReq(Fsm fp, FsmOption opt, int mode);

/*
 * GLOBAL VARIABLES
 */

  const struct enctype	gDeseBisEncType =
  {
    "dese-bis",
    ECP_TY_DESE_bis,
    DeseBisInit,
    DeseBisConfigure,
    NULL,
    DeseBisSubtractBloat,
    DeseBisCleanup,
    DeseBisBuildConfigReq,
    DeseBisDecodeConfigReq,
    NULL,
    NULL,
    NULL,
    DeseBisStat,
    DeseBisEncrypt,
    DeseBisDecrypt,
  };

/*
 * DeseBisInit()
 */

static int
DeseBisInit(Bund b, int dir)
{
  EcpState	const ecp = &b->ecp;
  DeseBisInfo	const des = &ecp->desebis;

  switch (dir) {
    case ECP_DIR_XMIT:
	des->xmit_seq = 0;
      break;
    case ECP_DIR_RECV:
	des->recv_seq = 0;
      break;
    default:
      assert(0);
      return(-1);
  }
  return(0);
}

/*
 * DeseBisConfigure()
 */

static void
DeseBisConfigure(Bund b)
{
  EcpState	const ecp = &b->ecp;
  DeseBisInfo	const des = &ecp->desebis;
  DES_cblock	key;

  DES_string_to_key(ecp->key, &key);
  DES_set_key(&key, &des->ks);
  des->xmit_seq = 0;
  des->recv_seq = 0;
}

/*
 * DeseBisSubtractBloat()
 */

static int
DeseBisSubtractBloat(Bund b, int size)
{
  (void)b;
  size -= DES_OVERHEAD;	/* reserve space for header */
  size &= ~0x7;
  size--;	 	/* reserve space for possible padding */
  return(size);
}

static int
DeseBisStat(Context ctx, int dir) 
{
    EcpState	const ecp = &ctx->bund->ecp;
    DeseBisInfo	const des = &ecp->desebis;
    
    switch (dir) {
	case ECP_DIR_XMIT:
	    Printf("\tBytes\t: %llu -> %llu (%+lld%%)\r\n",
		(unsigned long long)des->xmit_stats.OctetsIn,
		(unsigned long long)des->xmit_stats.OctetsOut,
		((des->xmit_stats.OctetsIn!=0)?
		    ((long long)(des->xmit_stats.OctetsOut - des->xmit_stats.OctetsIn)
			*100/(long long)des->xmit_stats.OctetsIn):
		    0));
	    Printf("\tFrames\t: %llu -> %llu\r\n",
		(unsigned long long)des->xmit_stats.FramesIn,
		(unsigned long long)des->xmit_stats.FramesOut);
	    Printf("\tErrors\t: %llu\r\n",
		(unsigned long long)des->xmit_stats.Errors);
	    break;
	case ECP_DIR_RECV:
	    Printf("\tBytes\t: %llu <- %llu (%+lld%%)\r\n",
		(unsigned long long)des->recv_stats.OctetsOut,
		(unsigned long long)des->recv_stats.OctetsIn,
		((des->recv_stats.OctetsOut!=0)?
		    ((long long)(des->recv_stats.OctetsIn - des->recv_stats.OctetsOut)
			*100/(long long)des->recv_stats.OctetsOut):
		    0));
	    Printf("\tFrames\t: %llu <- %llu\r\n",
		(unsigned long long)des->xmit_stats.FramesOut,
		(unsigned long long)des->xmit_stats.FramesIn);
	    Printf("\tErrors\t: %llu\r\n",
		(unsigned long long)des->recv_stats.Errors);
    	    break;
	default:
    	    assert(0);
    }
    return (0);
}

/*
 * DeseBisEncrypt()
 */

Mbuf
DeseBisEncrypt(Bund b, Mbuf plain)
{
  EcpState	const ecp = &b->ecp;
  DeseBisInfo	const des = &ecp->desebis;
  const int	plen = MBLEN(plain);
  int		padlen = roundup2(plen + 1, 8) - plen;
  int		clen = plen + padlen;
  Mbuf		cypher;
  int		k;

  des->xmit_stats.FramesIn++;
  des->xmit_stats.OctetsIn += plen;

/* Get mbuf for encrypted frame */

  cypher = mballoc(DES_OVERHEAD + clen);

/* Copy in sequence number */

  MBDATAU(cypher)[0] = des->xmit_seq >> 8;
  MBDATAU(cypher)[1] = des->xmit_seq & 0xff;
  des->xmit_seq++;

/* Copy in plaintext */

  mbcopy(plain, 0, MBDATA(cypher) + DES_OVERHEAD, plen);

/* Correct and add padding */

  if ((padlen>7) &&
    ((MBDATA(cypher)[DES_OVERHEAD + plen - 1]==0) ||
     (MBDATA(cypher)[DES_OVERHEAD + plen - 1]>8))) {
        padlen -=8;
	clen = plen + padlen;
  }
  for (k = 0; k < padlen; k++) {
    MBDATA(cypher)[DES_OVERHEAD + plen + k] = k + 1;
  }
  
  cypher->cnt = DES_OVERHEAD + clen;
  
/* Copy in plaintext and encrypt it */
  
  for (k = 0; k < clen; k += 8)
  {
    u_char	*const block = MBDATA(cypher) + DES_OVERHEAD + k;

    DES_cbc_encrypt(block, block, 8, &des->ks, &des->xmit_ivec, TRUE);
    memcpy(des->xmit_ivec, block, 8);
  }

  des->xmit_stats.FramesOut++;
  des->xmit_stats.OctetsOut += DES_OVERHEAD + clen;

/* Return cyphertext */

  mbfree(plain);
  return(cypher);
}

/*
 * DeseBisDecrypt()
 */

Mbuf
DeseBisDecrypt(Bund b, Mbuf cypher)
{
  EcpState	const ecp = &b->ecp;
  DeseBisInfo	des = &ecp->desebis;
  int		clen = MBLEN(cypher) - DES_OVERHEAD;
  u_int16_t	seq;
  Mbuf		plain;
  int		k;

  des->recv_stats.FramesIn++;
  des->recv_stats.OctetsIn += clen + DES_OVERHEAD;

/* Get mbuf for plaintext */

  if (clen < 8 || (clen & 0x7))
  {
    Log(LG_ECP, ("[%s] DESE-bis: rec'd bogus DES cypher: len=%d",
      b->name, clen + DES_OVERHEAD));
    des->recv_stats.Errors++;
    return(NULL);
  }

/* Check sequence number */

  cypher = mbread(cypher, &seq, DES_OVERHEAD);
  seq = ntohs(seq);
  if (seq != des->recv_seq)
  {
    Mbuf	tail;

  /* Recover from dropped packet */

    Log(LG_ECP, ("[%s] DESE-bis: rec'd wrong seq=%u, expected %u",
      b->name, seq, des->recv_seq));
    tail = mbadj(cypher, clen - 8);
    tail = mbread(tail, &des->recv_ivec, 8);
    assert(!tail);
    des->recv_seq = seq + 1;
    des->recv_stats.Errors++;
    return(NULL);
  }
  des->recv_seq++;

/* Decrypt frame */

  plain = cypher;
  for (k = 0; k < clen; k += 8)
  {
    u_char	*const block = MBDATA(plain) + k;
    DES_cblock	next_ivec;

    memcpy(next_ivec, block, 8);
    DES_cbc_encrypt(block, block, 8, &des->ks, &des->recv_ivec, FALSE);
    memcpy(des->recv_ivec, next_ivec, 8);
  }

/* Strip padding */
  if (MBDATAU(plain)[clen-1]>0 &&
    MBDATAU(plain)[clen-1]<=8) {
      clen -= MBDATAU(plain)[clen-1];
      mbtrunc(plain, clen);
  }

  des->recv_stats.FramesOut++;
  des->recv_stats.OctetsOut += clen;

/* Done */

  return(plain);
}

/*
 * DeseBisCleanup()
 */

static void
DeseBisCleanup(Bund b, int dir)
{
  EcpState	const ecp = &b->ecp;
  DeseBisInfo	const des = &ecp->desebis;
  
  if (dir == ECP_DIR_RECV)
  {
    memset(&des->recv_stats, 0, sizeof(des->recv_stats));
  }
  if (dir == ECP_DIR_XMIT)
  {
    memset(&des->xmit_stats, 0, sizeof(des->xmit_stats));
  }
}

/*
 * DeseBisBuildConfigReq()
 */

static u_char *
DeseBisBuildConfigReq(Bund b, u_char *cp)
{
  EcpState	const ecp = &b->ecp;
  DeseBisInfo	const des = &ecp->desebis;

  ((u_int32_t *)(void *) des->xmit_ivec)[0] = random();
  ((u_int32_t *)(void *) des->xmit_ivec)[1] = random();
  return(FsmConfValue(cp, ECP_TY_DESE_bis, 8, des->xmit_ivec));
}

/*
 * DeseBisDecodeConfigReq()
 */

static void
DeseBisDecodeConfigReq(Fsm fp, FsmOption opt, int mode)
{
    Bund 	b = (Bund)fp->arg;
  DeseBisInfo	const des = &b->ecp.desebis;

  if (opt->len != 10)
  {
    Log(LG_ECP, ("[%s]   bogus length %d", b->name, opt->len));
    if (mode == MODE_REQ)
      FsmRej(fp, opt);
    return;
  }
  Log(LG_ECP, ("[%s]   nonce 0x%02x%02x%02x%02x%02x%02x%02x%02x", b->name,
    opt->data[0], opt->data[1],opt->data[2],opt->data[3],
    opt->data[4], opt->data[5],opt->data[6],opt->data[7]));
  switch (mode)
  {
    case MODE_REQ:
      memcpy(des->recv_ivec, opt->data, 8);
      FsmAck(fp, opt);
      break;
    case MODE_NAK:
      break;
  }
}


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>