From 4f8ffd4fb328bdbacaa8ea516efc79adb44c1ca8 Mon Sep 17 00:00:00 2001 From: Bruno Valente <140794260+bruno-valante@users.noreply.github.com> Date: Thu, 5 Sep 2024 18:33:09 +0800 Subject: [PATCH 1/2] Fix Critical Security Vulnerability Caused by Circom Operator Misuse --- circuits/ctr.circom | 73 +++++++++++++---- circuits/finite_field.circom | 149 ++++++++++++++++++++++++++++++++++ circuits/key_expansion.circom | 10 +-- circuits/mix_columns.circom | 18 ++-- circuits/sbox128.circom | 27 ++---- circuits/tbox.circom | 38 ++------- circuits/utils.circom | 5 +- 7 files changed, 235 insertions(+), 85 deletions(-) create mode 100644 circuits/finite_field.circom diff --git a/circuits/ctr.circom b/circuits/ctr.circom index c388d99..96f05a0 100644 --- a/circuits/ctr.circom +++ b/circuits/ctr.circom @@ -2,6 +2,8 @@ pragma circom 2.1.9; include "cipher.circom"; include "transformations.circom"; +include "circomlib/circuits/comparators.circom"; +include "circomlib/circuits/bitify.circom"; template EncryptCTR(l,nk){ signal input plainText[l]; @@ -9,6 +11,24 @@ template EncryptCTR(l,nk){ signal input key[nk * 4]; signal output cipher[l]; + component checkPlainText[l]; + for (var i = 0; i < l; i++) { + checkPlainText[i] = Num2Bits(8); + checkPlainText[i].in <== plainText[i]; + } + + component checkIv[16]; + for (var i = 0; i < 16; i++) { + checkIv[i] = Num2Bits(8); + checkIv[i].in <== iv[i]; + } + + component checkKey[nk * 4]; + for (var i = 0; i < nk * 4; i++) { + checkKey[i] = Num2Bits(8); + checkKey[i].in <== key[i]; + } + var n = l\16; if(l%16 > 0){ n = n + 1; @@ -114,31 +134,52 @@ template AddCipher(){ } } +template ByteInc() { + signal input in; + signal input control; + signal output out; + signal output carry; + + signal added; + added <== in + control; + + signal addedDiff; + addedDiff <== added - 256; + carry <== IsZero()(addedDiff); + + out <== added - carry * 256; +} + // converts iv to counter blocks // iv is 16 bytes template GenerateCounterBlocks(n){ assert(n < 0xffffffff); signal input iv[16]; + signal blockNonce[n][16]; signal output counterBlocks[n][4][4]; - - var ivr[16] = iv; - component toBlocks[n]; + + component ivByteInc[n-1][16]; + + + toBlocks[0] = ToBlocks(16); + toBlocks[0].stream <== iv; + counterBlocks[0] <== toBlocks[0].blocks[0]; + + for (var i = 1; i < n; i++) { + for (var j = 15; j >= 0; j--) { + ivByteInc[i-1][j] = ByteInc(); + ivByteInc[i-1][j].in <== toBlocks[i-1].stream[j]; + if (j==15) { + ivByteInc[i-1][j].control <== 1; + } else { + ivByteInc[i-1][j].control <== ivByteInc[i-1][j+1].carry; + } + blockNonce[i][j] <== ivByteInc[i-1][j].out; + } - for (var i = 0; i < n; i++) { toBlocks[i] = ToBlocks(16); - toBlocks[i].stream <-- ivr; + toBlocks[i].stream <== blockNonce[i]; counterBlocks[i] <== toBlocks[i].blocks[0]; - ivr[15] = (ivr[15] + 1)%256; - if (ivr[15] == 0){ - ivr[14] = (ivr[14] + 1)%256; - if (ivr[14] == 0){ - ivr[13] = (ivr[13] + 1)%256; - if (ivr[13] == 0){ - ivr[12] = (ivr[12] + 1)%256; - } - } - } - } } \ No newline at end of file diff --git a/circuits/finite_field.circom b/circuits/finite_field.circom new file mode 100644 index 0000000..9916350 --- /dev/null +++ b/circuits/finite_field.circom @@ -0,0 +1,149 @@ +pragma circom 2.1.9; + +include "circomlib/circuits/bitify.circom"; + +template FieldAddConst(c) { + signal input in[8]; + signal input control; + signal output out[8]; + + for (var i=0; i<8; i++) { + if(c & (1<> multiplication by 2 //tbox[1] =>> multiplication by 3 -function TBox(index, subbyte) { - var tbox[2][256] = [ - [ - 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, - 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, - 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, - 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, - 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, - 254, 27, 25, 31, 29, 19, 17, 23, 21, 11, 9, 15, 13, 3, 1, 7, 5, 59, 57, 63, 61, 51, 49, 55, 53, 43, 41, 47, 45, 35, - 33, 39, 37, 91, 89, 95, 93, 83, 81, 87, 85, 75, 73, 79, 77, 67, 65, 71, 69, 123, 121, 127, 125, 115, 113, 119, 117, - 107, 105, 111, 109, 99, 97, 103, 101, 155, 153, 159, 157, 147, 145, 151, 149, 139, 137, 143, 141, 131, 129, 135, 133, - 187, 185, 191, 189, 179, 177, 183, 181, 171, 169, 175, 173, 163, 161, 167, 165, 219, 217, 223, 221, 211, 209, 215, - 213, 203, 201, 207, 205, 195, 193, 199, 197, 251, 249, 255, 253, 243, 241, 247, 245, 235, 233, 239, 237, 227, 225, - 231, 229 - ], - [ - 0, 3, 6, 5, 12, 15, 10, 9, 24, 27, 30, 29, 20, 23, 18, 17, 48, 51, 54, 53, 60, 63, 58, 57, 40, 43, 46, 45, 36, 39, 34, - 33, 96, 99, 102, 101, 108, 111, 106, 105, 120, 123, 126, 125, 116, 119, 114, 113, 80, 83, 86, 85, 92, 95, 90, 89, 72, - 75, 78, 77, 68, 71, 66, 65, 192, 195, 198, 197, 204, 207, 202, 201, 216, 219, 222, 221, 212, 215, 210, 209, 240, 243, - 246, 245, 252, 255, 250, 249, 232, 235, 238, 237, 228, 231, 226, 225, 160, 163, 166, 165, 172, 175, 170, 169, 184, - 187, 190, 189, 180, 183, 178, 177, 144, 147, 150, 149, 156, 159, 154, 153, 136, 139, 142, 141, 132, 135, 130, 129, - 155, 152, 157, 158, 151, 148, 145, 146, 131, 128, 133, 134, 143, 140, 137, 138, 171, 168, 173, 174, 167, 164, 161, - 162, 179, 176, 181, 182, 191, 188, 185, 186, 251, 248, 253, 254, 247, 244, 241, 242, 227, 224, 229, 230, 239, 236, - 233, 234, 203, 200, 205, 206, 199, 196, 193, 194, 211, 208, 213, 214, 223, 220, 217, 218, 91, 88, 93, 94, 87, 84, 81, - 82, 67, 64, 69, 70, 79, 76, 73, 74, 107, 104, 109, 110, 103, 100, 97, 98, 115, 112, 117, 118, 127, 124, 121, 122, 59, - 56, 61, 62, 55, 52, 49, 50, 35, 32, 37, 38, 47, 44, 41, 42, 11, 8, 13, 14, 7, 4, 1, 2, 19, 16, 21, 22, 31, 28, 25, 26 - ] - ]; +template TBox(index) { + signal input in; + signal output out; - return tbox[index][subbyte]; + if (index == 0) { + out <== FieldMul2()(in); + } else if (index == 1) { + out <== FieldMul3()(in); + } } \ No newline at end of file diff --git a/circuits/utils.circom b/circuits/utils.circom index d9b6bea..1a4ada5 100644 --- a/circuits/utils.circom +++ b/circuits/utils.circom @@ -48,8 +48,7 @@ template SubstituteWord() { } // Outputs a round constant for a given round number -template RCon() { - signal input round; +template RCon(round) { signal output out[4]; assert(round > 0 && round <= 10); @@ -67,7 +66,7 @@ template RCon() { [0x36, 0x00, 0x00, 0x00] ]; - out <-- rcon[round-1]; + out <== rcon[round-1]; } From f1668bd20f4fd36963a3376c4f456460f4447b73 Mon Sep 17 00:00:00 2001 From: Bruno Valente <140794260+bruno-valante@users.noreply.github.com> Date: Thu, 5 Sep 2024 19:11:22 +0800 Subject: [PATCH 2/2] Add comments --- circuits/finite_field.circom | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/circuits/finite_field.circom b/circuits/finite_field.circom index 9916350..f7cf239 100644 --- a/circuits/finite_field.circom +++ b/circuits/finite_field.circom @@ -2,13 +2,16 @@ pragma circom 2.1.9; include "circomlib/circuits/bitify.circom"; +// Finite field addition, the signal variable plus a compile-time constant template FieldAddConst(c) { signal input in[8]; + // control bit, if 0, then do not perform addition signal input control; signal output out[8]; for (var i=0; i<8; i++) { if(c & (1<