Generic glitching application.
authortravisutk <travisutk@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Sun, 7 Mar 2010 19:11:38 +0000 (19:11 +0000)
committertravisutk <travisutk@12e2690d-a6be-4b82-a7b7-67c4a43b65c8>
Sun, 7 Mar 2010 19:11:38 +0000 (19:11 +0000)
git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@394 12e2690d-a6be-4b82-a7b7-67c4a43b65c8

client/GoodFETGlitch.py [new file with mode: 0644]
client/goodfet.glitch [new file with mode: 0755]

diff --git a/client/GoodFETGlitch.py b/client/GoodFETGlitch.py
new file mode 100644 (file)
index 0000000..2790367
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+# GoodFET Client Library
+# 
+# (C) 2009 Travis Goodspeed <travis at radiantmachines.com>
+#
+# This code is being rewritten and refactored.  You've been warned!
+
+import sys, time, string, cStringIO, struct, glob, serial, os, random;
+import sqlite3;
+
+from GoodFET import *;
+
+class GoodFETGlitch(GoodFET):
+    
+    def __init__(self, *args, **kargs):
+        print "Initializing GoodFET Glitcher."
+        #Database connection and tables.
+        self.db=sqlite3.connect("glitch.db");
+        self.db.execute("create table if not exists glitches(time,vcc,gnd,trials,glitchcount,count,lock)");
+        self.client=0;
+    def setup(self,arch="avr"):
+        self.client=getClient(arch);
+    def learn(self):
+        #Learning phase
+        trials=1;
+        lock=0;  #1 locks, 0 unlocked
+        vstart=0;
+        vstop=0xFFF;  #Smaller range sometimes helps.
+        vstep=1;
+        tstart=0;
+        tstop=-1; #<0 defaults to full range
+        tstep=0x1; #Must be 1
+        self.scan(lock,trials,vstart,vstop,tstart,tstop);
+    def scan(self,lock,trials=1,vstart=0,vstop=0xfff,tstart=0,tstop=-1):
+        client=self.client;
+        self.lock=lock;
+        client.serInit();
+        if tstop<0:
+            tstop=client.glitchstarttime();  #Really long; only use for initial investigation.
+            print "-- Start takes %04i cycles." % tstop;
+        client.start();
+        client.erase();
+        
+        self.secret=0x69;
+
+        while(client.eeprompeek(0)!=self.secret):
+            print "-- Setting secret";
+            client.start();
+            
+            #Flash the secret to the first two bytes of CODE memory.
+            client.erase();
+            client.eeprompoke(0,self.secret);
+            client.eeprompoke(1,self.secret);
+            sys.stdout.flush()
+
+        #Lock chip to unlock it later.
+        if lock>0:
+            client.lock();
+        voltages=range(vstart,vstop,1);
+        times=range(tstart,tstop,1);
+        
+        gnd=0;     #TODO, glitch GND.
+        vcc=0xfff;
+        random.shuffle(voltages);
+        random.shuffle(times);
+        
+        count=0; #Commit counter.
+        for vcc in voltages:
+            for time in times:
+                self.scanat(trials,vcc,gnd,time)
+                sys.stdout.flush()
+                count+=trials;
+                if count>1000:
+                    count=0;
+                    self.db.commit();
+
+    def scanat(self,trials,vcc,gnd,time):
+        client=self.client;
+        db=self.db;
+        client.glitchRate(time);
+        client.glitchVoltages(gnd, vcc);  #drop voltage target
+        gcount=0;
+        scount=0;
+        print "-- (%i,%i)" % (time,vcc);
+        sys.stdout.flush();
+        for i in range(0,trials):
+            client.glitchstart();
+            
+            #Try to read *0, which is secret if read works.
+            a=client.eeprompeek(0x0);
+            if self.lock>0: #locked
+                if(a!=0 and a!=0xFF and a!=self.secret):
+                    gcount+=1;
+                if(a==self.secret):
+                    print "-- %04x: %02x HELL YEAH! " % (time, a);
+                    scount+=1;
+            else: #unlocked
+                if(a!=self.secret):
+                    gcount+=1;
+                if(a==self.secret):
+                    scount+=1;
+        print "values (%i,%i,%i,%i,%i);" % (
+            time,vcc,gnd,gcount,scount);
+        self.db.execute("insert into glitches(time,vcc,gnd,trials,glitchcount,count,lock)"
+                   "values (%i,%i,%i,%i,%i,%i,%i);" % (
+                time,vcc,gnd,trials,gcount,scount,self.lock));
diff --git a/client/goodfet.glitch b/client/goodfet.glitch
new file mode 100755 (executable)
index 0000000..edce100
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+
+import sys,binascii,time,random;
+
+sys.path.append('../../../trunk/client/')
+
+from GoodFETAVR import GoodFETAVR;
+from GoodFETGlitch import *;
+from intelhex import IntelHex16bit, IntelHex;
+
+import sqlite3;
+
+
+glitcher=GoodFETGlitch();
+
+if(len(sys.argv)==1):
+    print "Usage: %s chip verb [objects]\n" % sys.argv[0];
+    print "%s avr learn" % sys.argv[0];
+    print """
+This populates a database, glitch.db, with a record of all attempted
+glitches.  Graphs can then be generated from the results, allowing
+results to be replicated on different hardware and models.  The general
+sequence for a new chip is to first run 'goodfet $foo learn' for an evening,
+then to FINISHME"""
+    sys.exit();
+
+
+glitcher.setup(sys.argv[1]);
+
+if(sys.argv[2]=="learn"):
+    glitcher.learn();