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="620,420" title="%s" >
60 <widget name="infotext" position="10,20" zPosition="1" size="600,150" font="Regular;20" halign="center" valign="center" />
61 <widget name="resulttext" position="10,160" zPosition="1" size="600,110" font="Regular;20" halign="center" valign="center" />
62 <widget name="infotext2" position="10,280" zPosition="1" size="600,80" font="Regular;20" halign="center" valign="center" />
63 <widget name="kRed" position="185,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="185,365" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
65 <widget name="kGreen" position="330,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="330,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.\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)
92 self["resulttext"].setText("Please wait (Step 1)")
93 self.uds = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
94 self.uds.connect(("/var/run/tpmd_socket"))
95 self.uds.settimeout(5.0)
97 self["resulttext"].setText("Security service not running.")
100 if (self.stepFirst(TPMD_CMD_GET_DATA,[TPMD_DT_PROTOCOL_VERSION,TPMD_DT_TPM_VERSION,TPMD_DT_SERIAL])):
102 url = ("https://www.dream-multimedia-tv.de/verify/challenge?serial=%s&version=%s" % (self.serial,self.tpmdVersion))
103 getPage(url).addCallback(self._gotPageLoadRandom).addErrback(self.errorLoad)
105 self["resulttext"].setText("Can't connect to server. Please check your network!")
107 def _gotPageLoad(self, data):
108 authcode = data.strip().replace('+', '')
109 self.finish = "%s-%s-%s" % (authcode[0:4], authcode[4:8], authcode[8:12])
110 self["resulttext"].setText(self.finish)
113 def _gotPageLoadRandom(self, data):
114 self["resulttext"].setText("Please wait (Step 2)")
115 self.back = data.strip()
116 self.random = (self.formatList(base64.b64decode(self.back)))
117 self.stepSecond(TPMD_CMD_GET_DATA,[TPMD_DT_PROTOCOL_VERSION,TPMD_DT_TPM_VERSION,TPMD_DT_SERIAL,TPMD_DT_LEVEL2_CERT,
118 TPMD_DT_LEVEL3_CERT,TPMD_DT_FAB_CA_CERT,TPMD_DT_DATABLOCK_SIGNED] )
119 url = self.buildUrl()
120 getPage(url).addCallback(self._gotPageLoad).addErrback(self.errorLoad)
122 def errorLoad(self, error):
124 self["resulttext"].setText("Invalid response from server. Please report: %s" % str(error))
127 # NOTE: this is a modified base64 which uses -_ instead of +/ to avoid the need for escpaing + when using urlencode
128 tmpra = ("random=%s" % self.back.replace('+', '-').replace('/', '_'))
129 tmpl2 = ("&l2=%s" % base64.b64encode(self.level2_cert).replace('+', '-').replace('/', '_'))
131 tmpl3 = ("&l3=%s" % base64.b64encode(self.level3_cert).replace('+', '-').replace('/', '_'))
134 tmpfa = ("&fab=%s" % base64.b64encode(self.fab_ca_cert).replace('+', '-').replace('/', '_'))
135 tmpda = ("&data=%s" % base64.b64encode(self.datablock_signed).replace('+', '-').replace('/', '_'))
136 tmpr = ("&r=%s" % base64.b64encode(self.r).replace('+', '-').replace('/', '_'))
137 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))
139 def formatList(self,l):
145 def formatString(self,s):
148 myString = myString + chr(x)
151 def stepFirst(self,typ,daten):
152 return (self.parseResult (self.udsSend(typ,daten,len(daten)), 1))
154 def stepSecond(self,typ,daten):
155 self.parseResult(self.udsSend(typ,daten,len(daten)),2)
156 self.parseResult(self.udsSend(TPMD_CMD_COMPUTE_SIGNATURE,self.random,8),3)
158 def parseResult(self,rbuf,art):
160 buf = self.formatList(rbuf)
162 self.serial ="%d" % ((buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11])
163 self.tpmdVersion = "%d" % (buf[1])
164 self.protocolVersion = "%d" % buf[0]
165 #print "serial:%s, version:%s, prot_version:%s" % (self.serial,self.tpmdVersion,self.protocolVersion)
172 data = ''.join([chr(x) for x in buf[2:l+2]])
176 self.level2_cert = tpmdata.get(4)
177 self.level3_cert = tpmdata.get(5) # can be None
178 self.fab_ca_cert = tpmdata.get(6)
179 self.datablock_signed = tpmdata.get(7)
181 self.r = self.formatString(buf)
185 def udsSend(self, cmdTyp, data, length):
186 sbuf = [(cmdTyp >> 8) & 0xff,(cmdTyp >> 0) & 0xff,(length >> 8) & 0xff,(length >> 0) & 0xff]
187 sbuf.extend(data[:length])
188 sbuf = struct.pack(str((length + 4))+"B", *sbuf)
191 except socket.timeout:
192 self["resulttext"].setText("Invalid response from Security service pls restart your Dreambox" )
193 rbuf = self.uds.recv(4)
194 leng = [ord(rbuf[2]) << 8 | ord(rbuf[3])]
197 res = self.uds.recv(leng[0])
198 except socket.timeout:
199 self["resulttext"].setText("Invalid response from Security service pls restart your Dreambox")
214 def main(session, **kwargs):
215 session.open(genuineDreambox)
217 def Plugins(path,**kwargs):
221 PluginDescriptor(name="Genuine Dreambox", description="Genuine Dreambox",where = PluginDescriptor.WHERE_PLUGINMENU, icon="genuine.png", fnc=main),
222 PluginDescriptor(name="Genuine Dreambox", where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=main)