Determing compiled sketch size from within program -UNO- Is it possible?

We are teaching technology to students from 4th grade-12th grade via robotics competitions. One of the platforms used is Arduino. Our challenge in the younger grades is to ensure over zealous/helpful parents don't "help" too much. We use an UNO based system for the younger grades. The teams ir control system comes with a preloaded program that is not to be modified. (This particular program is focused on the mechanical aspects of engineering.)

Each robot must pass inspection before each competition and we thought by coding in a sequence of LED flashes, triggered by something unique to the official program, i.e. program size, would be a good way to allow a simple sight verification of adherence to the rule. We understand that it would not be fool proof, but would eliminate most of the potential issues. (We will not release the source code as that obviously would render this potential solution virtually useless.)

We are not married to this idea. If there is a better way to accomplish our goal we certainly would appreciate those ideas.

Thanks
Jim

Could use avrdude commands to download the flash contents and compare against official upload, see if its different.
Or have a unique IR command that is not shared and have the program send out the data from some specific address via serial port.

jjschulte:
If there is a better way to accomplish our goal we certainly would appreciate those ideas.

I may have misunderstood, but if your goal is to ensure that the Arduino is running the sketch you provided and hasn't been modified then there are things that you can do to the Arduino to make it much harder to upload a new sketch - the most obvious being to remove the bootloader. Alternatively, I seem to remember that somebody (Nick Gammon?) described a technique for downloading the installed sketch and if you want to make absolutely certain they're running your sketch then you could download it and verify it against your original.

CrossRoads:
Could use avrdude commands to download the flash contents and compare against official upload, see if its different.
Or have a unique IR command that is not shared and have the program send out the data from some specific address via serial port.

Unfortunately we are using pins 0 and 1 to control motors which precludes using serial communication. (When the program executes the command that set the serial baud rate we lose the ability to control motors on those two pins.)

So we need a solution that will allow for a non-serial means of communicating authenticity. Hence the idea of using the LEDs.

Jim

PeterH:

jjschulte:
If there is a better way to accomplish our goal we certainly would appreciate those ideas.

I may have misunderstood, but if your goal is to ensure that the Arduino is running the sketch you provided and hasn't been modified then there are things that you can do to the Arduino to make it much harder to upload a new sketch - the most obvious being to remove the bootloader. Alternatively, I seem to remember that somebody (Nick Gammon?) described a technique for downloading the installed sketch and if you want to make absolutely certain they're running your sketch then you could download it and verify it against your original.

You are correct in your understanding. We want to make sure the sketch has not been modified.

We don't want to remove the bootloader as we want to encourage the students/teachers to play and learn. We will also provide code to act as a starting point for them to modify and play with. Thus the need to download code is very important and we would not want to do anything to make that more difficult.

We just want to ensure that when they come to a competition they are running the proper competition code.

We may just have to download it every time they come to a competition, but would prefer not to do that. (We also realize there is another issue we need to deal with and that is how can a team, after having downloaded their own sketches to the UNO then download the competition sketch WITHOUT access to the source code. If we get this first issue resolved then we planned on posting a request about that.)

Are you using the ISP pins? (11,12,13)

Also, how large is your competition code?

after having downloaded their own sketches to the UNO then download the competition sketch WITHOUT access to the source code

That is possible also - supply them a .hex file that is the compiled competition code, it can be installed via the serial port with avrdude commands. Have your LED blink confirmation as part of that.

jjschulte:
You are correct in your understanding. We want to make sure the sketch has not been modified.

We don't want to remove the bootloader as we want to encourage the students/teachers to play and learn. We will also provide code to act as a starting point for them to modify and play with. Thus the need to download code is very important and we would not want to do anything to make that more difficult.

We just want to ensure that when they come to a competition they are running the proper competition code.

We may just have to download it every time they come to a competition, but would prefer not to do that. (We also realize there is another issue we need to deal with and that is how can a team, after having downloaded their own sketches to the UNO then download the competition sketch WITHOUT access to the source code. If we get this first issue resolved then we planned on posting a request about that.)

If you want them to have a fully-functional Arduino and access to your sample sketch and the means to develop their own and all of that then the only sticking point seems to be that you also require that they are running your standard sketch when they enter the competition. Can't you enforce that by uploading the standard sketch yourself at the point you certify the 'bot as ready to compete? I don't why that would be any harder to execute than any of the other options you're considering and it would eliminate all uncertainty.

If you want to enable the teams to upload a standard sketch without having access to the source code for that sketch then that is certainly possible - you would just give them the binary files ready to upload, and arrange for them to run avrdude to upload them.

Can you imbed another command in your IR control system?
If not then you need to define the "event" to trigger the check.
The event can call a function to blink the built in led on pin 13.

Pressing the reset button seems like an obvious choice.
Just modify "blinky" and put it at the top of your program.

This waits 5 seconds after reset.
Then it blinks the LED 4 time with progressively longer blinks.
(of course anyone with a watch can figure out how to duplicate it)

// 
const byte builtinled = 13;
int DelayTime=1000;

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(builtinled, OUTPUT);
  digitalWrite(builtinled, LOW);
  delay (5000); // normal reset blins LED as well, make this obvious diffence
  do {digitalWrite(builtinled, HIGH);
      delay (DelayTime);
      digitalWrite (builtinled, LOW);
      delay (DelayTime);
      DelayTime=DelayTime + 1000;
    } while (DelayTime < 5000);
 /* continue here with the rest of your setup code */
}

void loop() {
/* program code */
}

You could also create a const at the top of the declares and check its value in startup.
Something like a signature. This would require a bit more effort to duplicate.
In this manner you could also have a different "HEX" file for each student.

// 
const byte builtinled = 13;
const unsigned long MyId = 123456789;


// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(builtinled, OUTPUT);
  digitalWrite(builtinled, LOW);
  delay (5000); // normal reset blins LED as well, make this obvious diffence
  
  if (MyId == 123456789)
    for (int i= 0; i<5; ++i) 
    { digitalWrite(builtinled, HIGH);
      delay (500);
      digitalWrite (builtinled, LOW);
      delay (500);
    }
  else
    { digitalWrite(builtinled, HIGH);
      delay (5000);
      digitalWrite (builtinled, LOW);
    }
  // end if
  
 /* continue here with the rest of your setup code */
}

void loop() {
/* program code */
}

If you want more sophisticated: your free ram at start up should always be the same.
You can check that value easily and blink a different sequence if it does not match the known value.
This would take a bit of trial and error to get the right "test" number.
This of course assumes that any new code would need to use RAM space.

/* http://stackoverflow.com/questions/960389/how-can-i-visualise-the-memory-sram-usage-of-an-avr-program */
int freeRam () {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); 
}

Even more sophisticated would be to read all the progmem and build a checksum to match.
Mark Sproul wrote a program called "Arduino Exploer" in 2010. It shows how to dump various memory locations.
The copy I have uses the depreciated PROGMEM syntax.
Still you might be able to get some ideas from that.

http://playground.arduino.cc/Main/ShowInfo
http://www.avr-developers.com/arduino_exp.html

By going to preferences and selecting "Show verbose output during: " upload
you can capture the avrdude command line from the console window:

C:\Program Files (x86)\Arduino\hardware/tools/avr/bin/avrdude 
-CC:\Program Files (x86)\Arduino\hardware/tools/avr/etc/avrdude.conf 
-v -v -v -v -patmega328p -carduino -P\\.\COM12 -b57600 -D -Uflash:w:
C:\Users\last.first.domain\Documents\Arduino\Build\My_ID.cpp.hex:i

I broke it into separate lines to make it easier to read.

You will find the HEX file in your build directory and the build directory is much easier to find if you set the "build.path" in preferences.txt
Your students would likely need to change the com port (Microsoft Windows is NOT known for consistency).

jjschulte:
Each robot must pass inspection before each competition and we thought by coding in a sequence of LED flashes, triggered by something unique to the official program, i.e. program size, would be a good way to allow a simple sight verification of adherence to the rule.

A few solutions spring to mind. First, you could simply remove the bootloader. That way the program stays where it is, and the students can't (easily) replace it. They would have to purchase a stand-alone programmer (in itself not too hard) or get a second Arduino to reprogram the first. It could be done, but it would take a fairly zealous student.

Or even, change the BOOTRST fuse so that the bootloader is there, but just not active. Again that would stop them uploading new programs through the serial port.

Second, you could have the sketch use software serial to output some string to any pin you choose (doesn't have to be pin 1) of some "secret message". However this really wouldn't be foolproof, because if I knew you were doing that I would just check to see what the secret message is and make sure my replacement sketch also output it. (Of course, the sequence of LED flashes could suffer the same fate).

Most reliable would be to simply check that the flash memory still contains the sketch you put there. Probably a check of the first few hundred bytes would do, as it would be unlikely someone could make a new sketch and have the first part be the same.

I have a sketch here that detects chip signatures and takes a sumcheck of the bootloader. A small modification and you could take a sumcheck of the sketch instead. Then just compare that to the "official" sumcheck.

You can make up a connecting cable like this:

It only takes a second to plug the 6-pin socket into the ICSP header, then do a "check" of the target board, and see what the sumcheck is.

We just want to ensure that when they come to a competition they are running the proper competition code.

Of course that would be pretty foolproof too. Just use avrdude to upload the .hex file of the competition code before sending the board off to compete. Then you would need to keep an eye on them that they don't put their own code back, of course. However again, changing the BOOTRST fuse should stop that.

Thanks to all for you excellent, useful and quick responses.

We believe we have a solution that will allow us to "secure" things, make inspections easy and still allow those teams that would like to "play" with the arduino based control system we are using to do so outside of the competitions. (Thanks to those of you that pointed us in the right direction in downloading hex/binary files.)

Many responses were valuable in getting us to a possible solution. After it has been coded and tested we will post our results. For now let us say it involves a combination of remote input (we had not initially thought of using it...we were stuck on the reset button as the trigger), checking the memory left (thanks for the code) and information sent back to the PS3 remote we are using. By using it's 4 LED lights it makes it much easier for our inspectors to see the results.

Thank you all.

jjschulte:
We want to make sure the sketch has not been modified.

We don't want to remove the bootloader as we want to encourage the students/teachers to play and learn. We will also provide code to act as a starting point for them to modify and play with. Thus the need to download code is very important and we would not want to do anything to make that more difficult.

These two requirements seem to be directly opposite. You want to make sure the sketch is not modified, but you want them to be able to upload sketches? Surely the only thing you can do then is re-install the competition sketch at the start of the competition?

Daddy used to say:
"Locks only keep honest people honest."

I believe the level of security that they are looking for is for honest people.

I still say you should just re-upload the code. However if the robots are identical you could simply randomly shuffle them just prior to testing. So person A gets person B's robot.

I found this in ShowInfo (I was looking for something else ...).
I think that it is what you were looking for originally.
http://playground.arduino.cc/Main/ShowInfo

// Helper function for sketch size.
// The sketch size is runtime calculated.
// From user "Coding Badly" in his post:
//   http://arduino.cc/forum/index.php/topic,115870.msg872309.html#msg872309
// Changed into unsigned long for code size larger than 64kB.
//
// This function returns the sketch size 
// for a size between 0 and 32k. If the code
// size is larger (for example with an Arduino Mega),
// the return value is not valid.
//
unsigned long sketchSize(void)
{
  extern int _etext;
  extern int _edata;

  return ((unsigned long)(&_etext) + ((unsigned long)(&_edata) - 256L));
}

As promised here is a description of our final solution.

  • We did not (as many suggested above) end up using the remaining memory call to secure things. However knowing how to do this is very valuable as we have another application for it.
  • We have always planned on having the binary available for downloading directly to the UNO. With the info. provided above, and a little research, we now have this in place. However this will be done only when it is clear that the proper sketch is not loaded. We still needed a way to easily determine that, preferably without the aid of anything other than the teams' robot and remote.
  • We have coded multiple input sequences (via the PS3 remote), say 100 out of millions, that return a specific message (via vibration and the 4 LEDs on the PS3 remote). The input and output sequences are not shared and all input sequences return a "message" making it very difficult to decode.

The overall solution is not perfect, but until we get to quantum computing, no security measure is. We believe this to be appropriate to the circumstance and appreciate all the input that helped arrive at our solution.