Autor Tema: Bootloader encriptado para Attiny88  (Leído 5228 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Conectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 6121
Re: Bootloader encriptado para Attiny88
« Respuesta #105 en: 05 de Octubre de 2015, 18:30:50 »
Si es lo feo que tiene ASM. Yo estoy escribiendo sobre el dsPIC en ASM con el compilador XC16. Hay cosas que si son demasiado engorrosas hacerlas que en C hubiera sido mucho mas facil, aunque todavia lo que no encuentro es como en C crea o usar una instruccion MAC con lo compleja que es, Pero bueno eso esta en ASM, y seguro que hay una funcion que lo hace :P.

En cierto, yo cuando me puse los AVR tambien extrañe algunas cosas que tenia el PIC, no por su corto set de intrucciones, sino por que me parece que habia cosas que faltaban. Los AVR funcionan parecido como los otros nucleos de microcontroladores tales como ARM/PIC24/dsPIC/MIPS. En el que es necesario traer de la memoria a los registros trabajarlos y enviarlos de nuevo. Que a diferencia de los PIC16/18 podes acceder directo. Otra de las buenas es que su memoria no esta dividida en bancos.
Y por ultimo el tema de las instrucciones depende mucho si necesitas tomar datos desde la memoria trabajrlas y guardarlas te lleva varios ciclos mas, pero que por suerte tiene muchos registros los cuales podes llenar con cosas, aunque C por ahi no lo aproveche a full a esto, como uno lo puede hacer en ASM.

En fin toda la pelea Atmel vs PIC se basa en: utilizar 4 ciclos de reloj para 1 instruccion y la memoria separada en bancos. Y como un codigo se ejecuta mas rapido en uno que en otro.

Lo que a mi me extraño tambien como bien decis son los perifericos, para mi el attiny tiene mejores timers que unos PIC, pero solo tener I2C ? una UART no? hasta me parecio raro que tuviera I2C y no UART.
Pero nada compite contra el precio. Lo bueno de ahora Picuino es que con esto Podes usarlo en casi todos los micros de AVR, tal ves lo unico que cambie es la direccion de pagina donde va a estar ubicada, un ifdef solucionaria la vida para hacerlo portable para todos los atmel.
Siempre y cuando mantengan los registros en el mismo lugar :P

En fin, ya que lo terminaste, a mi me parecio un hermoso desafio, y me gusto mientras duro.


Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4342
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #106 en: 05 de Octubre de 2015, 19:08:55 »
Bueno, el proyecto aún no está terminado.
Funciona el código ASM del lado del Attiny, que no es poco. Pero aún me queda:

1. Programar un encriptador que transforme automáticamente el archivo *.hex en un archivo *.xtea encriptado (casi lo tengo terminado)
2. Programar un bootloader para enviar los datos encriptados desde un PC al Attiny (casi lo tengo terminado)
3. Generar automáticamente un programa para que Arduino envíe los datos encriptados al bootloader
4. Probar los bootloader con diferentes problemas externos (cortes de corriente, ruido, desconexión de cables, etc)
5. Testear que funcionan todos los mecanismos de detección de errores (checksum  de transmisión y checksum de flash)
6. Programar el attiny con los fuses más seguros que se pueda

Y seguro que aparecen algunos puntos más.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4342
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #107 en: 06 de Octubre de 2015, 08:18:39 »
Primer programa en Python (este lenguaje cada día me gusta más)
Este programa lee y convierte todos los archivos del directorio con formato *.hex de intel, en archivos en formato *.cyp con la información encriptada con el algoritmo XTEA

Primero se parte de una tabla de memoria llena de números aleatorios, que comienza en la dirección después del bootloader
A continuación se colocan en esa tabla los datos del programa, provenientes del archivo *.hex. Todos los datos que no caben en la tabla anterior se desechan.
Después se encripta toda la tabla en grupos de 8 bytes (algoritmo XTEA)
Por último se guarda en el disco toda la tabla en un archivo *.cyp
Este archivo *.cyp se compone de líneas que comienzan con ':', después la dirección de memoria, 8 bytes codificados y al final un checksum de línea.

Programa Python:
Código: Python
  1. import os
  2. import ctypes
  3. import random
  4.  
  5. flash_range = [64*7, 1024*8]
  6.  
  7. xtea_key = [0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF]
  8. xtea_rounds = 32
  9.  
  10.  
  11. def main():
  12.    print 'XTEA Cypher.\nMem range = 0x%04X .. 0x%04X\n' % tuple(flash_range)
  13.    hexfiles = [f for f in os.listdir('.') if f[-4:].lower() == '.hex']
  14.    for hexfile in hexfiles:
  15.       print hexfile
  16.       flash = randflash(flash_range[0], flash_range[1])
  17.       data = read_hexfile(hexfile)
  18.       filldata(flash, data)
  19.       coded = encode(flash)
  20.       dump(coded, hexfile)
  21.  
  22.  
  23. def dump(coded, hexfile):
  24.    xtea_file = hexfile[:-4] + '.cyp'
  25.    data = []
  26.    for line in coded:
  27.       data.append(':%04X %02X%02X%02X%02X%02X%02X%02X%02X %02X\n' % ((line[0],) + tuple(line[1:]) + (256-checksum(line),)))
  28.    fo = open(xtea_file, 'wt')
  29.    fo.write(''.join(data))
  30.    fo.close()
  31.  
  32.  
  33. def filldata(flash, data):
  34.    for line in data:
  35.       addr = line[0]
  36.       for i in range(1, len(line)):
  37.          if addr < flash_range[0] or addr > flash_range[1]:
  38.             continue
  39.          flash[addr - flash_range[0]] = line[i]
  40.          addr += 1
  41.      
  42.  
  43. def encode(flash):
  44.    xtea = []
  45.    addr = flash_range[0]
  46.    for j in range(0, len(flash), 8):
  47.       xtea.append([addr] + xtea_encode(flash[j:j+8]))
  48.       addr += 8
  49.    return xtea
  50.      
  51.  
  52.  
  53. def xtea_encode(data):
  54.    global xtea_key
  55.    XTEA_DELTA = 0x9E3779B9
  56.    data0 = data[0] + (data[1]<<8) + (data[2]<<16) + (data[3]<<24)
  57.    data1 = data[4] + (data[5]<<8) + (data[6]<<16) + (data[7]<<24)
  58.    suma = 0
  59.    rounds = xtea_rounds
  60.    while(rounds):
  61.       data0 += (((data1<<4) ^ (data1>>5)) + data1) ^ (suma + xtea_key[suma & 3])
  62.       data0 = uint32(data0)
  63.       suma = uint32(suma + XTEA_DELTA)
  64.       data1 += (((data0<<4) ^ (data0>>5)) + data0) ^ (suma + xtea_key[(suma>>11) & 3])
  65.       data1 = uint32(data1)
  66.       rounds -= 1
  67.    data[0] = int(data0 & 0xFF)
  68.    data[1] = int((data0>>8) & 0xFF)
  69.    data[2] = int((data0>>16) & 0xFF)
  70.    data[3] = int((data0>>24) & 0xFF)
  71.    data[4] = int(data1 & 0xFF)
  72.    data[5] = int((data1>>8) & 0xFF)
  73.    data[6] = int((data1>>16)& 0xFF)
  74.    data[7] = int((data1>>24)& 0xFF)
  75.    return data  
  76.  
  77.  
  78. def uint32(data):
  79.     return ctypes.c_uint32(data).value
  80.  
  81.  
  82. def randflash(addr_init, addr_end):
  83.    random.seed(1)
  84.    length = int((addr_end - addr_init + 7) / 8) * 8
  85.    return [random.randint(0, 255) for i in range(length)]
  86.  
  87.  
  88. def read_hexfile(filename):
  89.    data = []
  90.    f = open(filename, 'rt')
  91.    for line in f:
  92.       hexdata(data, line)
  93.    f.close()
  94.    return data
  95.  
  96.  
  97. def hexdata(data, line):
  98.    DATA = 0
  99.    if line[0] != ':':
  100.       return
  101.    line = line.strip()
  102.    tam  = int(line[1:1+2], 16)
  103.    addr = int(line[3:3+4], 16)
  104.    typ  = int(line[7:7+2], 16)
  105.    byte = []
  106.    for i in range(tam):
  107.       byte.append(int(line[9+i*2:9+i*2+2], 16))
  108.    if checksum(line) == 0 and typ == DATA:
  109.       data.append([addr] + byte)
  110.  
  111.  
  112. def checksum(line):
  113.    checksum = 0
  114.    if type(line) == type('text'):
  115.       for i in range(1, len(line), 2):
  116.          checksum += int(line[i:i+2], 16)
  117.          checksum = checksum % 256
  118.    if type(line) == type(['list']):
  119.       for i in line:
  120.          checksum += i
  121.          checksum = checksum % 256
  122.    return checksum
  123.    
  124. main()


Ejemplo *.cyp:
Código: [Seleccionar]
:01C0 E391AA3F274F9036 A7
:01C8 9952CA230F0FE373 EC
:01D0 6E00D2742C2B5400 D1
:01D8 982F2B26E0C5FB63 0D
:01E0 750C0B74DFC0B697 34
:01E8 F3292371DBC89993 99
:01F0 504AFC40DC8BB05B C8
:01F8 42BC51B4C58281A4 99
:0200 24B2F6572142D214 94
:0208 06E84E19224A1BF2 2A
:0210 932E9BA3A91A2802 04
:0218 FCA3EDE3E4D65180 EE
:0220 887C7570ABE1E431 56
:0228 A0B75783D7887F67 62
:0230 43D010914743126D 13
:0238 085972BD421545DD BF
:0240 4BF7928A298C2DAD D3
:0248 A2A1901D92ECE85A 08
:0250 935F43C8626895B1 A3
:0258 8B675B29D7B005DA CC
:0260 FE87AD9D378B8B19 6B
:0268 B5764E916825ACDF 76
:0270 174A6F93B4EB6915 10
:0278 83536D8C42311A2E FE
:0280 130FCFB298A026FB 84
:0288 309E881FB9C0D2EC CC
:0290 D9C2080DE1F4FC67 88
:0298 750B6426D50FE80B 87
:02A0 7AE7AACB09E00D7D 17

« Última modificación: 06 de Octubre de 2015, 08:28:16 por Picuino »


 

anything