📄 packet.c
字号:
/* PKCIPE - public key based configuration tool for CIPE packet.c - packet handling and signing Copyright 2000 Olaf Titz <olaf@bigred.inka.de> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.*//* $Id: packet.c,v 1.12 2002/05/30 11:40:18 olaf Exp $ */#include <alloca.h>#include <string.h>#include <unistd.h>#include <sys/uio.h>#include <openssl/evp.h>#include "pkcipe.h"int timeout=60;/* Data is sent in packets. The packet format is as follows: 1 byte marker 0x2a 2 byte length bigendian, each byte is XORed with 0x50 n byte data starting with type + signed/encrypted 1 byte check sum of plaintext data mod 256 +*/static EVP_MD_CTX signCtx;static EVP_MD_CTX vrfyCtx;static EVP_CIPHER_CTX encSendCtx;static EVP_CIPHER_CTX encRecvCtx;static int encSend=0;static int encRecv=0;void signInit(void){ EVP_SignInit(&signCtx, EVP_sha1());}void vrfyInit(void){ EVP_VerifyInit(&vrfyCtx, EVP_sha1());}void setSendKey(const unsigned char *key){ if (key) { EVP_EncryptInit(&encSendCtx, EVP_rc4(), /*XXOCONST*/(unsigned char *)key, NULL); if (protoVersion>1) EVP_CIPHER_CTX_set_key_length(&encSendCtx, 20); encSend=1; } else { EVP_CIPHER_CTX_cleanup(&encSendCtx); encSend=0; } debug((DEB_KEY, "setSendKey %s", encSend ? hexstr(key, EVP_CIPHER_key_length(&encSendCtx)) : "*"));}void setRecvKey(const unsigned char *key){ if (key) { EVP_DecryptInit(&encRecvCtx, EVP_rc4(), /*XXOCONST*/(unsigned char *)key, NULL); if (protoVersion>1) EVP_CIPHER_CTX_set_key_length(&encRecvCtx, 20); encRecv=1; } else { EVP_CIPHER_CTX_cleanup(&encRecvCtx); encRecv=0; } debug((DEB_KEY, "setRecvKey %s", encRecv ? hexstr(key, EVP_CIPHER_key_length(&encRecvCtx)) : "*"));}int packetSendP(int fd, unsigned char *d, int len, int prot){ int i, ll; unsigned char hb[3]; unsigned char c; struct iovec iov[2]; unsigned char *b0; if (len<0 || len>PKTMAXLEN-2) return -1; hb[0]='*'; hb[1]=(len>>8)^0x50; hb[2]=(len&255)^0x50; debug((DEB_PKT, "packetSend: %02x %02x %02x (%d)", hb[0], hb[1], hb[2], len)); if (prot<3) { for (c=i=0; i<len; ++i) c+=d[i]; d[len++]=c; } else { EVP_MD_CTX md; EVP_DigestInit(&md, EVP_sha1()); EVP_DigestUpdate(&md, d, len); EVP_DigestFinal(&md, d+len, NULL); len+=20; } if (*d&PKTF_SIGNED) { EVP_SignUpdate(&signCtx, d, len); debug((DEB_SIGN, "SignUpdate %d", len)); } if (*d&PKTF_REVSIGN) { EVP_VerifyUpdate(&vrfyCtx, d, len); debug((DEB_SIGN, "VerifyUpdate rev %d", len)); }#ifdef DEBUG if (debugging&DEB_PDUMP) hexdump(d, len);#endif iov[0].iov_base=hb; iov[0].iov_len=3; if (encSend) { b0=alloca(len); if (!b0) return -1; ll=len; EVP_EncryptUpdate(&encSendCtx, b0, &ll, /*XXOCONST*/(unsigned char *)d, len); if (ll!=len) { Log(LOG_ERR, "packetSend: EncryptUpdate %d/%d", ll, len); return -1; } iov[1].iov_base=b0; } else { iov[1].iov_base=d; } iov[1].iov_len=len; if ((i=xwritev(fd, iov, 2))<0) { Log(LOG_ERR, "packetSend: writev: %m"); return -1; } d[len-(prot<3?1:20)]=0; /* make the buffer re-usable as string */ return i;}int packetSendBN(int fd, int typ, const BIGNUM *a){ unsigned short l; unsigned char *b; l=BN_num_bytes(a); if (!(b=alloca(l+22))) return -1; b[0]=typ; BN_bn2bin(a, b+1); debug((DEB_BNUM, "packetSendBN: %d %s", l, hexstr(a->d, l))); return packetSend(fd, b, l+1);}int packetRecvP(int fd, unsigned char *d, int len, int prot){ int e, i, ll; unsigned char hb[3]; /*memset(d, 0, len);*/ alarm(timeout); if ((e=xread(fd, hb, 3))<0) { Log(LOG_ERR, "packetRecv: read error"); return -1; } if (!e) return 0; ll=((hb[1]<<8)+(hb[2]))^0x5050; debug((DEB_PKT, "packetRecv: %02x %02x %02x (%d)", hb[0], hb[1], hb[2], ll)); if (ll<1 || ll>PKTMAXLEN-2 || ll>len-2 || hb[0]!='*') { Log(LOG_ERR, "packetRecv: frame error"); if (debugging&DEB_PKTERR) { memcpy(d, hb, 3); e=read(fd, d+3, len-3); /* not xread! */ Log(LOG_DEBUG, "packetRecv: frame error, received stuff follows"); hexdump(d, e+3); } return -1; } ll+=(prot<3?1:20); if (encRecv) { unsigned char *b0=alloca(ll); if (!b0) { Log(LOG_ERR, "packetRecv: alloca failure"); return -1; } if (xread(fd, b0, ll)<ll) { Log(LOG_ERR, "packetRecv: read error"); return -1; } e=ll; EVP_DecryptUpdate(&encRecvCtx, d, &e, b0, ll); if (e!=ll) { Log(LOG_ERR, "packetRecv: DecryptUpdate %d/%d", e, ll); return -1; } } else { if (xread(fd, d, ll)<ll) { Log(LOG_ERR, "packetRecv: read error"); return -1; } } if (*d&PKTF_SIGNED) { EVP_VerifyUpdate(&vrfyCtx, d, ll); debug((DEB_SIGN, "VerifyUpdate %d", ll)); } if (*d&PKTF_REVSIGN) { EVP_SignUpdate(&signCtx, d, ll); debug((DEB_SIGN, "SignUpdate rev %d", ll)); }#ifdef DEBUG if (debugging&DEB_PDUMP) hexdump(d, ll);#endif if (prot<3) { --ll; for (e=i=0; i<ll; ++i) e+=d[i]; if ((e&255)!=d[ll]) { Log(LOG_ERR, "packetRecv: checksum mismatch"); return -1; } } else { EVP_MD_CTX md; char cs[20]; ll-=20; EVP_DigestInit(&md, EVP_sha1()); EVP_DigestUpdate(&md, d, ll); EVP_DigestFinal(&md, cs, NULL); if (memcmp(cs, d+ll, 20)) { Log(LOG_ERR, "packetRecv: checksum mismatch"); return -1; } } d[ll]=0; return ll;}BIGNUM *packetExtrBN(const unsigned char *d, int l){ BIGNUM *a=BN_bin2bn(d+1, l-1, NULL); debug((DEB_BNUM, "packetExtrBN: %d %s", l-1, hexstr(a->d, l-1))); return a;}int signFinal(unsigned char *dst, int *len, const EVP_PKEY *key){ return EVP_SignFinal(&signCtx, dst, len, /*XXOCONST*/(EVP_PKEY *)key);}int vrfyFinal(const unsigned char *dst, int len, const EVP_PKEY *key){ return EVP_VerifyFinal(&vrfyCtx, /*XXOCONST*/(unsigned char *)dst, len, /*XXOCONST*/(EVP_PKEY *)key);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -