6 # Coded by Dr.Best (c) 2010
7 # Support: www.dreambox-tools.info
9 # This plugin is licensed under the Creative Commons
10 # Attribution-NonCommercial-ShareAlike 3.0 Unported
11 # License. To view a copy of this license, visit
12 # http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative
13 # Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
15 # Alternatively, this plugin may be distributed and executed on hardware which
16 # is licensed by Dream Multimedia GmbH.
18 # This plugin is NOT free software. It is open source, you are allowed to
19 # modify it (if you keep the license), but it may not be commercially
20 # distributed other than under the conditions noted above.
23 #include "bitratecalc.h"
25 #include <lib/base/etpm.h>
26 #include <openssl/bn.h>
27 #include <openssl/sha.h>
29 eBitrateCalc::eBitrateCalc(int pid, int dvbnamespace, int tsid, int onid, int refreshintervall, int buffer_size): m_size(0), m_refresh_intervall(refreshintervall)
31 m_send_data_timer = eTimer::create(eApp);
32 CONNECT(m_send_data_timer->timeout, eBitrateCalc::sendDataTimerTimeoutCB);
33 eDVBChannelID chid; //(eDVBNamespace(dvbnamespace), eTransportStreamID(tsid), eOriginalNetworkID(onid)); <-- weird, that does not work
34 chid.dvbnamespace = eDVBNamespace(dvbnamespace);
35 chid.transport_stream_id = eTransportStreamID(tsid);
36 chid.original_network_id = eOriginalNetworkID(onid);
37 ePtr<eDVBResourceManager> res_mgr;
38 eDVBResourceManager::getInstance(res_mgr);
39 eUsePtr<iDVBChannel> channel;
42 if (!res_mgr->allocateChannel(chid, channel, false))
44 ePtr<iDVBDemux> demux;
45 if (!channel->getDemux(demux))
47 if (!demux->createPESReader(eApp, m_reader))
49 if (!m_reader->connectRead(slot(*this, &eBitrateCalc::dataReady), m_pes_connection))
51 channel->connectStateChange(slot(*this, &eBitrateCalc::stateChange), m_channel_connection);
55 eDebug("[eBitrateCalc] connect pes reader failed...");
58 eDebug("[eBitrateCalc] create PES reader failed...");
61 eDebug("[eBitrateCalc] getDemux failed...");
65 eDebug("[eBitrateCalc] allocate channel failed...trying pvr_allocate_demux");
66 ePtr<eDVBAllocatedDemux> pvr_allocated_demux;
68 if (!res_mgr->allocateDemux(NULL,pvr_allocated_demux,i))
70 eDVBDemux &demux = pvr_allocated_demux->get();
71 if (!demux.createPESReader(eApp, m_reader))
73 if (!m_reader->connectRead(slot(*this, &eBitrateCalc::dataReady), m_pes_connection))
76 eDebug("[eBitrateCalc] connect pes reader failed...");
79 eDebug("[eBitrateCalc] create PES reader failed...");
82 eDebug("[eBitrateCalc] allocate pvr_allocated_demux failed...");
84 if (m_reader && success)
86 clock_gettime(CLOCK_MONOTONIC, &m_start);
87 m_reader->setBufferSize(buffer_size);
89 m_send_data_timer->start(m_refresh_intervall, true);
95 void eBitrateCalc::dataReady(const __u8*, int size)
100 void eBitrateCalc::sendDataTimerTimeoutCB()
103 clock_gettime(CLOCK_MONOTONIC, &now);
104 timespec delta = now - m_start;
105 unsigned int delta_ms = delta.tv_nsec / 1000000 + delta.tv_sec * 1000;
108 int bitrate = int(m_size / delta_ms)*8;
111 m_send_data_timer->start(m_refresh_intervall, true);
114 void eBitrateCalc::stateChange(iDVBChannel *ch)
117 if (ch->getState(state))
119 if (state == iDVBChannel::state_release)
121 m_send_data_timer = NULL;
123 m_pes_connection = NULL;
124 m_channel_connection = NULL;
129 static void rsa_pub1024(unsigned char dest[128],
130 const unsigned char src[128],
131 const unsigned char mod[128])
133 BIGNUM bbuf, bexp, bmod;
141 BN_bin2bn(src, 128, &bbuf);
142 BN_bin2bn(mod, 128, &bmod);
143 BN_bin2bn((const unsigned char *)"\x01\x00\x01", 3, &bexp);
145 BN_mod_exp(&bbuf, &bbuf, &bexp, &bmod, ctx);
147 BN_bn2bin(&bbuf, dest);
149 BN_clear_free(&bexp);
150 BN_clear_free(&bmod);
151 BN_clear_free(&bbuf);
155 static bool decrypt_block(unsigned char dest[128],
156 const unsigned char *src,
158 const unsigned char mod[128])
160 unsigned char hash[20];
167 rsa_pub1024(dest, src, mod);
170 SHA1_Update(&ctx, &dest[1], 106);
172 SHA1_Update(&ctx, &src[131], 61);
173 SHA1_Final(hash, &ctx);
175 return (memcmp(hash, &dest[107], 20) == 0);
178 static bool read_random(unsigned char *buf, size_t len)
183 fd = open("/dev/urandom", O_RDONLY);
185 perror("/dev/urandom");
189 ret = read(fd, buf, len);
193 if (ret != (ssize_t)len) {
194 fprintf(stderr, "could not read random data\n");
201 static bool validate_cert(unsigned char dest[128],
202 const unsigned char *src,
203 const unsigned char mod[128])
205 unsigned char buf[128];
207 if (!decrypt_block(buf, &src[8], 210 - 8, mod))
210 memcpy(&dest[0], &buf[36], 71);
211 memcpy(&dest[71], &src[131 + 8], 57);
215 static const unsigned char tpm_root_mod[128] = {
216 0x9F,0x7C,0xE4,0x47,0xC9,0xB4,0xF4,0x23,0x26,0xCE,0xB3,0xFE,0xDA,0xC9,0x55,0x60,
217 0xD8,0x8C,0x73,0x6F,0x90,0x9B,0x5C,0x62,0xC0,0x89,0xD1,0x8C,0x9E,0x4A,0x54,0xC5,
218 0x58,0xA1,0xB8,0x13,0x35,0x45,0x02,0xC9,0xB2,0xE6,0x74,0x89,0xDE,0xCD,0x9D,0x11,
219 0xDD,0xC7,0xF4,0xE4,0xE4,0xBC,0xDB,0x9C,0xEA,0x7D,0xAD,0xDA,0x74,0x72,0x9B,0xDC,
220 0xBC,0x18,0x33,0xE7,0xAF,0x7C,0xAE,0x0C,0xE3,0xB5,0x84,0x8D,0x0D,0x8D,0x9D,0x32,
221 0xD0,0xCE,0xD5,0x71,0x09,0x84,0x63,0xA8,0x29,0x99,0xDC,0x3C,0x22,0x78,0xE8,0x87,
222 0x8F,0x02,0x3B,0x53,0x6D,0xD5,0xF0,0xA3,0x5F,0xB7,0x54,0x09,0xDE,0xA7,0xF1,0xC9,
223 0xAE,0x8A,0xD7,0xD2,0xCF,0xB2,0x2E,0x13,0xFB,0xAC,0x6A,0xDF,0xB1,0x1D,0x3A,0x3F,
228 static bool signature()
232 fp = fopen ("/proc/stb/info/model", "r");
237 fgets(line, sizeof(line), fp);
238 if ((n = strlen(line)) && line[n - 1] == '\n')
241 if (strstr(line,"dm7025"))
247 unsigned char rnd[CLEN];
248 /* read random bytes */
249 if (!read_random(rnd, CLEN))
251 unsigned char level2_mod[128];
252 unsigned char level3_mod[128];
253 unsigned char buf[128];
254 std::string challenge((char*)rnd, CLEN);
255 std::string response = tpm.challenge(challenge);
256 unsigned int len = response.size();
257 unsigned char val[len];
260 memcpy(val, response.c_str(), len);
261 std::string cert = tpm.getCert(eTPM::TPMD_DT_LEVEL2_CERT);
262 if ( cert.size() != 210 || !validate_cert(level2_mod, (const unsigned char*) cert.c_str(), tpm_root_mod))
264 cert = tpm.getCert(eTPM::TPMD_DT_LEVEL3_CERT);
265 if ( cert.size() != 210 || !validate_cert(level3_mod, (const unsigned char*) cert.c_str(), level2_mod))
267 if (!decrypt_block(buf, val, 128, level3_mod))
269 if (memcmp(&buf[80], rnd, CLEN))
277 // eBitrateCalculator replacement
280 struct eBitrateCalculatorPy
287 eBitrateCalculatorPy_traverse(eBitrateCalculatorPy *self, visitproc visit, void *arg)
289 PyObject *obj = self->bc->dataSent.getSteal();
296 eBitrateCalculatorPy_clear(eBitrateCalculatorPy *self)
298 PyObject *obj = self->bc->dataSent.getSteal(true);
306 eBitrateCalculatorPy_dealloc(eBitrateCalculatorPy* self)
308 eBitrateCalculatorPy_clear(self);
309 self->ob_type->tp_free((PyObject*)self);
313 eBitrateCalculatorPy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
315 eBitrateCalculatorPy *self = (eBitrateCalculatorPy *)type->tp_alloc(type, 0);
316 int size = PyTuple_Size(args);
317 int pid, dvbnamespace, tsid, onid, refreshinterval, buffer_size;
318 if (size < 6 || !PyArg_ParseTuple(args, "iiiiii", &pid, &dvbnamespace, &tsid, &onid, &refreshinterval, &buffer_size))
320 self->bc = new eBitrateCalc(pid, dvbnamespace, tsid, onid, refreshinterval, buffer_size);
321 return (PyObject *)self;
325 eBitrateCalculatorPy_get_cb_list(eBitrateCalculatorPy *self, void *closure)
327 return self->bc->dataSent.get();
330 static PyGetSetDef eBitrateCalculatorPy_getseters[] = {
332 (getter)eBitrateCalculatorPy_get_cb_list, (setter)0,
333 "returns the callback python list",
335 {NULL} /* Sentinel */
338 static PyTypeObject eBitrateCalculatorPyType = {
339 PyObject_HEAD_INIT(NULL)
341 "eBitrateImpl.eBitrateCalculator", /*tp_name*/
342 sizeof(eBitrateCalculatorPy), /*tp_basicsize*/
344 (destructor)eBitrateCalculatorPy_dealloc, /*tp_dealloc*/
351 0, /*tp_as_sequence*/
359 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
360 "eBitrateCalculator objects", /* tp_doc */
361 (traverseproc)eBitrateCalculatorPy_traverse, /* tp_traverse */
362 (inquiry)eBitrateCalculatorPy_clear, /* tp_clear */
363 0, /* tp_richcompare */
364 0, /* tp_weaklistoffset */
369 eBitrateCalculatorPy_getseters, /* tp_getset */
372 0, /* tp_descr_get */
373 0, /* tp_descr_set */
374 0, /* tp_dictoffset */
377 eBitrateCalculatorPy_new, /* tp_new */
380 static PyMethodDef module_methods[] = {
381 {NULL} /* Sentinel */
385 initbitratecalc(void)
387 bool init = signature();
388 PyObject* m = Py_InitModule3("bitratecalc", module_methods,
389 "Module that implements bitrate calculations.");
394 PyErr_SetString(PyExc_TypeError, "TPM challenge failed");
397 if (!PyType_Ready(&eBitrateCalculatorPyType))
399 Org_Py_INCREF((PyObject*)&eBitrateCalculatorPyType);
400 PyModule_AddObject(m, "eBitrateCalculator", (PyObject*)&eBitrateCalculatorPyType);