./ MultiCS.r82 / msg-camd35.c
#define CAMD_ECM_REQUEST 0 #define CAMD_ECM_REPLY 1 #define CAMD_KEEPALIVE 0x37 #define CAMD_CEX_IDREQUEST 0x3D #define CAMD_CEX_IDREPLY 0x3E #define CAMD_CEX_PUSH 0x3F /////////////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////////// void aes_set_keys( uint8_t *key, AES_KEY *dkey, AES_KEY *ekey) { AES_set_decrypt_key( key, 128, dkey); AES_set_encrypt_key( key, 128, ekey); } void aes_decrypt(AES_KEY *dkey, uint8_t *buf, int n) { int32_t i; for (i=0; i<n; i+=16) { AES_decrypt(buf+i, buf+i, dkey); } } void aes_encrypt(AES_KEY *ekey, uint8_t *buf, int n) { int32_t i; for (i=0; i<n; i+=16) { AES_encrypt(buf+i, buf+i, ekey); } } void camd35_init_data( char *user, char *pass, AES_KEY *encryptkey, AES_KEY *decryptkey, uint32_t *ucrc) { unsigned char md5tmp[MD5_DIGEST_LENGTH]; *ucrc = crc32( 0L, MD5( (uint8_t*)user, strlen(user), md5tmp), MD5_DIGEST_LENGTH ); // user aes_set_keys( MD5( (uint8_t*)pass, strlen(pass), md5tmp) , decryptkey, encryptkey); // pass } /////////////////////////////////////////////////////////////////////////////// inline int camd35_padding( int len ) { if (len&0x0f) return ( (len&0xfff0)+0x10 ); else return len; } /////////////////////////////////////////////////////////////////////////////// // for connected udp sockets void camd35_send( int handle, AES_KEY *encryptkey, uint32_t ucrc, unsigned char *buf, int len) { uint8_t sbuf[1024]; sbuf[0] = ucrc>>24; sbuf[1] = ucrc>>16; sbuf[2] = ucrc>>8; sbuf[3] = ucrc; memcpy( sbuf+4, buf, len ); memset( sbuf+4+len, 0xFF, 15); // uint32_t datacrc = crc32(0L, buf+20, len-20); sbuf[8] = datacrc>>24; sbuf[9] = datacrc>>16; sbuf[10] = datacrc>>8; sbuf[11] = datacrc; int newlen = camd35_padding(len); #ifdef DEBUG_NETWORK if (flag_debugnet) { debugf(0," camd35: Send data length %d\n", newlen+4); debughex(sbuf, newlen+4); } #endif aes_encrypt( encryptkey, sbuf+4, newlen); // SEND send( handle, sbuf, newlen+4, 0); } void camd35_sendto( int handle, uint32_t ip, int port, AES_KEY *encryptkey, uint32_t ucrc, unsigned char *buf, int len) { uint8_t sbuf[1024]; sbuf[0] = ucrc>>24; sbuf[1] = ucrc>>16; sbuf[2] = ucrc>>8; sbuf[3] = ucrc; memcpy( sbuf+4, buf, len ); memset( sbuf+4+len, 0xFF, 15); // uint32_t datacrc = crc32(0L, buf+20, len-20); sbuf[8] = datacrc>>24; sbuf[9] = datacrc>>16; sbuf[10] = datacrc>>8; sbuf[11] = datacrc; int newlen = camd35_padding(len); #ifdef DEBUG_NETWORK if (flag_debugnet) { debugf(0," camd35: Send data to (%s:%d) length %d\n", ip2string(ip), port, newlen+4); debughex(sbuf, newlen+4); } #endif aes_encrypt( encryptkey, sbuf+4, newlen); // SEND struct sockaddr_in si_other; int slen = sizeof(si_other); memset((char *) &si_other, 0, sizeof(si_other)); si_other.sin_family = AF_INET; si_other.sin_port = htons( port ); si_other.sin_addr.s_addr = ip; sendto( handle, sbuf, newlen+4, 0, (struct sockaddr *)&si_other, slen); } int cs378x_send( int handle, AES_KEY *encryptkey, uint32_t ucrc, unsigned char *buf, int len) { uint8_t sbuf[1024]; sbuf[0] = ucrc>>24; sbuf[1] = ucrc>>16; sbuf[2] = ucrc>>8; sbuf[3] = ucrc; memcpy( sbuf+4, buf, len ); memset( sbuf+4+len, 0xFF, 15); // uint32_t datacrc = crc32(0L, buf+20, len-20); sbuf[8] = datacrc>>24; sbuf[9] = datacrc>>16; sbuf[10] = datacrc>>8; sbuf[11] = datacrc; int newlen = camd35_padding(len); //debugf(0, " cs378x: send data\n"); debughex(sbuf, newlen+4); aes_encrypt( encryptkey, sbuf+4, newlen); return send_nonb( handle, sbuf, newlen+4, 100 ); } int cs378x_recv(int handle, uint32_t ucrc, AES_KEY *decryptkey, unsigned char *buf) { int received = recv_nonb( handle, buf, 32+4, 1000); // Get minimum packet size if (received<=0) return received; // Disconnect uint32_t ucrc1 = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|buf[3]; if (ucrc!=ucrc1) return -2; // wrong ucrc aes_decrypt( decryptkey, buf+4, received-4); //Fix for ECM request size > 255 (use ecm length field) int datalen = buf[5]; if (buf[4] == 0) datalen = (((buf[25] & 0x0f) << 8) | buf[26]) + 3; // ECM else if ( (buf[4]&0xFC)==0x3C ) datalen = buf[5] | (buf[6] << 8); // cacheex else datalen = buf[5]; // Normal int newlen = 4+camd35_padding(20+datalen); if (received<newlen) { int n = recv_nonb( handle, buf+received, newlen-received, 500); if ( n != (newlen-received) ) return -3; // receive timeout or wrong packet size aes_decrypt( decryptkey, buf+received, n); } //debugf(getdbgflag(DBG_SERVER,0,srv->id)," msg from cs378x server (%s:%d)\n", srv->host->name, srv->port); debughex(buf, newlen); return newlen; }