• Nenhum resultado encontrado

3. Implementação

3.2. Implementação em Hardware Sem Contramedidas

A implementação em hardware, sem qualquer tipo de contramedida serviu para estabelecer um ponto de comparação base para a eficiência das contramedidas posteriormente implementadas, bem como para permitir o desenvolvimento e teste da porta série para comunicação por parte do hardware.

Para realizar esta implementação foi necessário perceber as operações matemáticas por detrás da construção da cifra AES. Essas operações, descritas e explicadas no ponto 1.2, deverão ser agora implementadas em código Verilog.

De relembrar, também, que para a implementação deste demonstrador foi também necessária a implementação de um periférico porta série para permitir a comunicação com o computador, e daí com o terminal, de modo a poder receber plaintexts e enviar o ciphertext correspondente de volta.

Comece-se por analisar a rotina Add Round Key, que soma a chave da ronda com o texto daquele estado. Para implementar esta operação recorresse ao uso de um XOR entre os dois valores a somar, uma vez que todas a operações ocorrem num espaço numérico finito. Pode se ver na Imagem 22 o excerto do código que executa a operação.

Imagem 22 - Operação de soma (Add Round Key)

A operação Sub. Bytes consiste na execução de uma substituição byte a byte do valor endereçado pelo conteúdo deste numa S-Box. Para esse efeito recorre-se ao seu nibble mais significativo para endereçar a linha e ao menos para endereçar a coluna, como se pode ver analisando os dois excertos de código presentes nas Imagem 23 e Imagem 24.

49

Imagem 23 - Acesso à S-Box

A execução desta substituição é feita recorrendo ao módulo cuja parte de interesse do código está presentes na Imagem 24.

Imagem 24 - Endereçamento S-Box

s_box s15( bytes [15] [7:4],bytes [15] [3:0],sOut [15]);

module s_box( input [3:0]linha, input [3:0]coluna, output [7:0]valor );

(…)

assign sbox_linha = sbox[linha];

assign valor = (coluna == 15)? sbox_linha[7 :0 ]:

(coluna == 14)? sbox_linha[15 :8 ]: (coluna == 13)? sbox_linha[23 :16 ]: (coluna == 12)? sbox_linha[31 :24 ]: (coluna == 11)? sbox_linha[39 :32 ]: (coluna == 10)? sbox_linha[47 :40 ]: (coluna == 9 )? sbox_linha[55 :48 ]: (coluna == 8 )? sbox_linha[63 :56 ]: (coluna == 7 )? sbox_linha[71 :64 ]: (coluna == 6 )? sbox_linha[79 :72 ]: (coluna == 5 )? sbox_linha[87 :80 ]: (coluna == 4 )? sbox_linha[95 :88 ]: (coluna == 3 )? sbox_linha[103:96 ]: (coluna == 2 )? sbox_linha[111:104]: (coluna == 1 )? sbox_linha[119:112]: sbox_linha[127:120];

50

Para executar o processo de desencriptação, inverse Sub. Bytes, substitui-se apenas a S- Box por uma inverse S-Box. Os valores de ambas as S-Box podem ser vistos no ponto 1.2.3.

A operação Shift Row consiste numa rotação variável dos dados, dependendo da sua posição no estado, como explicado no ponto 1.2.4. Para realizar essa operação o código desenvolvido para este demonstrador pode ser visto na Imagem 25.

Imagem 25 - Operação Shift Row

O processo iShift Row implica a que a rotação dos dados seja executado da forma inversa, sendo o código usado para o implementar semelhante ao presente na Imagem 25.

A última operação em falta, Mix Columns, implica executar múltiplas operações matemáticas, que consistem em multiplicações e somas, segundo o polinómio descrito no ponto 1.2.5. module shift_row( input [127:0] plaintext, output [127:0] state ); wire [31:0]pt[3:0]; assign pt[0] = {plaintext[127:120],plaintext[119:112],plaintext[111:104],plaintext[ 103:96] };

assign pt[1] = {plaintext[87:80] ,plaintext[79:72] ,plaintext[71:64] ,plaintext[95:88] };

assign pt[2] = {plaintext[47:40] ,plaintext[39:32] ,plaintext[63:56] ,plaintext[55:48] };

assign pt[3] = {plaintext[7:0] ,plaintext[31:24] ,plaintext[23:16] ,plaintext[15:8] };

assign state = {pt[0],pt[1],pt[2],pt[3]};

51

Imagem 26 - Multiplicação por 2

A complexidade desta operação em termos de implementação advém exactamente da natureza das operações nela envolvida. Uma implementação eficiente da multiplicação em FPGA exige uma abordagem apropriada, para esse efeito, e para multiplicar por 2, recorre-se à execução de um shift left, para a multiplicação por 3 recorre-se à execução de um shift left seguido de uma soma com recurso a um XOR do valor original. Para esta operação é ainda necessário, caso o bit mais significativo do valor seja igual a 1, somar 0x1B.

Imagem 27 - Multiplicação por 3

O código para execução destas duas operações matemáticas pode ser visto na Imagem 26 e na Imagem 27.

Com os módulos da multiplicação desenvolvidos podemos implementar a restante parte desta operação, a soma dos valores calculados, para obter o resultado do polinómio. Para esse efeito foi desenvolvido o excerto de código presente na Imagem 28.

Imagem 28 - Operação Mix Columns para o MSB

Face às diferenças entre a encriptação e a desencriptação nesta operação é de sublinhar que o conceito da implementação da multiplicação se estende para os restantes números, sendo para os pares apenas necessário realizar o shift left por multiplicação e para os ímpares somar o valor original.

assign out = (val [7])? (val<<1)^8'b00011011 : val<<1;

assign out = (val [7])? ((val<<1)^8'b00011011)^val : (val<<1)^val;

//byte 15

mux2 m15a0 (bytes [15],t [0][15]); mux3 m15a1 (bytes [11],t [0][11]);

assign t[0][7 ] = bytes [7 ];

assign t[0][3 ] = bytes [3 ];

52

Com todas as operações, que manipulam o plaintext, implementadas resta uma rotina constituinte do protocolo por implementar, a Key Expansion. Esta rotina, que visa garantir a protecção contra, por exemplo, ataques related key, incorpora na sua constituição, tal como referido no ponto 1.2.1, um conjunto de operações na qual se incluem o recurso a S-box, a soma da constante da ronda, r con, executada em todas as palavras cuja posição na chave seja múltipla de 4, e a execução de um XOR com a palavra que a precede na quarta posição a contar da mesma. Podemos ver um excerto do código usado, neste caso para gerar a chave das 3 primeiras rondas, na Imagem 29.

Imagem 29 - Primeiras 3 chaves de ronda (Key Expansion)

Olhe-se agora para o código que implementa a rotina g, constituída pela S-Box e pela soma com a constante r con. A primeira operação a executar é a Rot. Word, na qual se executa a rotação do byte menos significativo da palavra, constituída por 4 bytes, para a posição mais significativa, rodando os restantes um byte à direita. Pode-se ver o código necessário para executar esta tarefa na Imagem 30.

Imagem 30 - Rot. Work (Key Expansion)

Depois da execução da operação Rot. Words é necessário executar a substituição dos bytes constituintes da palavra com recurso às S-Box. Para esse efeito a implementação é em tudo semelhante ao executado durante a operação Sub. Bytes.

assign w[0] = {key[15],key[14],key[13],key[12]}; assign w[1] = {key[11],key[10],key[9],key[8]}; assign w[2] = {key[7],key[6],key[5],key[4]}; assign w[3] = {key[3],key[2],key[1],key[0]}; assign w[4] = g0_ ^ w[0]; assign w[5] = w[4] ^ w[1]; assign w[6] = w[5] ^ w[2]; assign w[7] = w[6] ^ w[3]; assign w[8] = g1_ ^ w[4]; assign w[9] = w[8] ^ w[5]; assign w[10] = w[9] ^ w[6]; assign w[11] = w[10] ^ w[7]; //rot word assign R1[7 :0] = in [31:24]; assign R1[31:8] = in [23:0 ];

53 É de seguida executada a soma da constante da ronda, como é visível na Imagem 31.

Imagem 31 - Soma da R Con

Com a conjugação da totalidade das operações discutidas neste ponto foi possível criar um demonstrador AES sem contramedidas, testando sobre a sua funcionalidade e vulnerabilidade.