1 # -*- coding: utf-8 -*-
2 ###########################################################################
8 # Copyright (C) 2009 by
9 # <nixkoenner@newnigma2.to>
13 # This program is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; either version 2 of the License, or
16 # (at your option) any later version.
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 ###########################################################################
29 # thx to <kayshadow@newnigma2.to> for painting the icon
31 from Plugins.Plugin import PluginDescriptor
32 from Screens.Screen import Screen
34 from Components.ActionMap import ActionMap
35 from Components.Button import Button
36 from Components.Label import Label
42 from twisted.web.client import getPage
44 TPMD_DT_RESERVED = 0x00
45 TPMD_DT_PROTOCOL_VERSION = 0x01
46 TPMD_DT_TPM_VERSION = 0x02
48 TPMD_DT_LEVEL2_CERT = 0x04
49 TPMD_DT_LEVEL3_CERT = 0x05
50 TPMD_DT_FAB_CA_CERT = 0x06
51 TPMD_DT_DATABLOCK_SIGNED = 0x07
52 TPMD_CMD_RESERVED = 0x0000
53 TPMD_CMD_GET_DATA = 0x0001
54 TPMD_CMD_APDU = 0x0002
55 TPMD_CMD_COMPUTE_SIGNATURE = 0x0003
57 class genuineDreambox(Screen):
59 <screen position="60,80" size="420,420" title="%s" >
60 <widget name="infotext" position="10,20" zPosition="1" size="400,150" font="Regular;20" halign="center" valign="center" />
61 <widget name="resulttext" position="10,170" zPosition="1" size="400,60" font="Regular;20" halign="center" valign="center" />
62 <widget name="infotext2" position="10,240" zPosition="1" size="400,100" font="Regular;20" halign="center" valign="center" />
63 <widget name="kRed" position="55,365" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
64 <ePixmap name="red" position="55,365" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
65 <widget name="kGreen" position="200,365" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
66 <ePixmap name="green" position="200,365" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
67 </screen>"""% _("Genuine Dreambox")
69 def __init__(self, session):
70 Screen.__init__(self, session)
71 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
73 "green": self.restart,
76 self["kGreen"] = Button(_("Restart"))
77 self["kRed"] = Button(_("Cancel"))
78 self["infotext"] = Label("With this plugin you can verify the authenticity of your Dreambox.\n\nFor additional information, \nplease visit our website \nhttps://www.dream-multimedia-tv.de.")
79 self["resulttext"] = Label("... Please wait ...")
80 self["infotext2"] = Label("Please visit our website and follow the instructions.\nAlternatively you can call our customer service hotline.")
81 self.onLayoutFinish.append(self.start)
90 self["resulttext"].setText("Please wait (Step 1)")
91 self.uds = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
92 self.uds.connect(("/var/run/tpmd_socket"))
94 self["resulttext"].setText("Security service not running.")
95 if (self.stepFirst(TPMD_CMD_GET_DATA,[TPMD_DT_PROTOCOL_VERSION,TPMD_DT_TPM_VERSION,TPMD_DT_SERIAL])):
97 url = ("https://www.dream-multimedia-tv.de/verify/challenge?serial=%s&version=%s" % (self.serial,self.tpmdVersion))
98 getPage(url).addCallback(self._gotPageLoadRandom).addErrback(self.errorLoad)
100 self["resulttext"].setText("Can't connect to server. Please check your network!")
102 def _gotPageLoad(self, data):
103 authcode = data.strip().replace('+', '')
104 self.finish = "%s-%s-%s" % (authcode[0:4], authcode[4:8], authcode[8:12])
105 self["resulttext"].setText(self.finish)
108 def _gotPageLoadRandom(self, data):
109 self["resulttext"].setText("Please wait (Step 2)")
110 self.back = data.strip()
111 self.random = (self.formatList(base64.b64decode(self.back)))
112 self.stepSecond(TPMD_CMD_GET_DATA,[TPMD_DT_PROTOCOL_VERSION,TPMD_DT_TPM_VERSION,TPMD_DT_SERIAL,TPMD_DT_LEVEL2_CERT,
113 TPMD_DT_LEVEL3_CERT,TPMD_DT_FAB_CA_CERT,TPMD_DT_DATABLOCK_SIGNED] )
114 url = self.buildUrl()
115 getPage(url).addCallback(self._gotPageLoad).addErrback(self.errorLoad)
117 def errorLoad(self, error):
118 self["resulttext"].setText("Invalid response from server. Please report!", error.getErrorMessage())
121 # NOTE: this is a modified base64 which uses -_ instead of +/ to avoid the need for escpaing + when using urlencode
122 tmpra = ("random=%s" % self.back.replace('+', '-').replace('/', '_'))
123 tmpl2 = ("&l2=%s" % base64.b64encode(self.level2_cert).replace('+', '-').replace('/', '_'))
125 tmpl3 = ("&l3=%s" % base64.b64encode(self.level3_cert).replace('+', '-').replace('/', '_'))
128 tmpfa = ("&fab=%s" % base64.b64encode(self.fab_ca_cert).replace('+', '-').replace('/', '_'))
129 tmpda = ("&data=%s" % base64.b64encode(self.datablock_signed).replace('+', '-').replace('/', '_'))
130 tmpr = ("&r=%s" % base64.b64encode(self.r).replace('+', '-').replace('/', '_'))
131 return("https://www.dream-multimedia-tv.de/verify/challenge?%s%s%s%s%s%s&serial=%s" % (tmpra,tmpl2,tmpl3,tmpfa,tmpda,tmpr,self.serial))
133 def formatList(self,l):
139 def formatString(self,s):
142 myString = myString + chr(x)
145 def stepFirst(self,typ,daten):
146 return (self.parseResult (self.udsSend(typ,daten,len(daten)), 1))
148 def stepSecond(self,typ,daten):
149 self.parseResult(self.udsSend(typ,daten,len(daten)),2)
150 self.parseResult(self.udsSend(TPMD_CMD_COMPUTE_SIGNATURE,self.random,8),3)
152 def parseResult(self,rbuf,art):
154 buf = self.formatList(rbuf)
156 self.serial ="%d" % ((buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11])
157 self.tpmdVersion = "%d" % (buf[1])
158 self.protocolVersion = "%d" % buf[0]
159 #print "serial:%s, version:%s, prot_version:%s" % (self.serial,self.tpmdVersion,self.protocolVersion)
166 data = ''.join([chr(x) for x in buf[2:l+2]])
170 self.level2_cert = tpmdata.get(4)
171 self.level3_cert = tpmdata.get(5) # can be None
172 self.fab_ca_cert = tpmdata.get(6)
173 self.datablock_signed = tpmdata.get(7)
175 self.r = self.formatString(buf)
179 def udsSend(self, cmdTyp, data, length):
180 sbuf = [(cmdTyp >> 8) & 0xff,(cmdTyp >> 0) & 0xff,(length >> 8) & 0xff,(length >> 0) & 0xff]
181 sbuf.extend(data[:length])
182 sbuf = struct.pack(str((length + 4))+"B", *sbuf)
184 rbuf = self.uds.recv(4)
185 leng = [ord(rbuf[2]) << 8 | ord(rbuf[3])]
187 res = self.uds.recv(leng[0])
192 def main(session, **kwargs):
193 session.open(genuineDreambox)
195 def Plugins(path,**kwargs):
199 PluginDescriptor(name="Genuine Dreambox", description="Genuine Dreambox",where = PluginDescriptor.WHERE_PLUGINMENU, icon="genuine.png", fnc=main),
200 PluginDescriptor(name="Genuine Dreambox", where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=main)