Skip to content

Commit

Permalink
Add support for encrypted shifts and constant shifts
Browse files Browse the repository at this point in the history
  • Loading branch information
cgouert committed Sep 3, 2023
1 parent 47eb2e0 commit b23ba93
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 1 deletion.
2 changes: 1 addition & 1 deletion hdl-benchmarks
17 changes: 17 additions & 0 deletions src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,10 @@ impl<'a> EvalCircuit<FheType> for ArithCircuit<'a> {
gate.evaluate_encrypted_mul_block_plain(&ct_op, ptxt_operand, cycle)
} else if gate.get_gate_type() == GateType::Div {
gate.evaluate_encrypted_div_block_plain(&ct_op, ptxt_operand, cycle)
} else if gate.get_gate_type() == GateType::Shl {
gate.evaluate_encrypted_shift_block_plain(&ct_op, ptxt_operand, cycle, true)
} else if gate.get_gate_type() == GateType::Shr {
gate.evaluate_encrypted_shift_block_plain(&ct_op, ptxt_operand, cycle, false)
} else {
unreachable!();
}
Expand Down Expand Up @@ -875,6 +879,19 @@ impl<'a> EvalCircuit<FheType> for ArithCircuit<'a> {
&input_values[1],
cycle,
)
} else if gate.get_gate_type() == GateType::Shl {
gate.evaluate_encrypted_shift_block(
&input_values[0],
&input_values[1],
cycle,
true,
)
} else if gate.get_gate_type() == GateType::Shr {
gate.evaluate_encrypted_shift_block(
&input_values[0],
&input_values[1],
cycle,
false)
} else {
gate.evaluate_encrypted_mul_block(
&input_values[0],
Expand Down
120 changes: 120 additions & 0 deletions src/gates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub enum GateType {
Add, // add ID(in0, in1, out);
Sub, // sub ID(in0, in1, out);
Div, // div ID(in0, in1, out);
Shl, // shl ID(in0, in1, out);
Shr, // shr ID(in0, in1, out);
}

#[derive(Clone)]
Expand Down Expand Up @@ -176,6 +178,8 @@ impl Gate {
GateType::Div => unreachable!(),
GateType::Add => unreachable!(),
GateType::Sub => unreachable!(),
GateType::Shl => unreachable!(),
GateType::Shr => unreachable!(),
GateType::Mux => match (&input_values[2], &input_values[0], &input_values[1]) {
(PtxtType::Bool(select), PtxtType::Bool(in_0), PtxtType::Bool(in_1)) => {
PtxtType::Bool((*select && *in_0) || (!select && *in_1))
Expand Down Expand Up @@ -249,6 +253,8 @@ impl Gate {
GateType::Mult => panic!("Mult gates can't be mixed with Boolean ops!"),
GateType::Div => panic!("Div gates can't be mixed with Boolean ops!"),
GateType::Sub => panic!("Sub gates can't be mixed with Boolean ops!"),
GateType::Shl => panic!("Left shifts can't be mixed with Boolean ops!"),
GateType::Shr => panic!("Right shifts can't be mixed with Boolean ops!"),
GateType::Mux => server_key.mux(&input_values[2], &input_values[0], &input_values[1]),
GateType::Nand => server_key.nand(&input_values[0], &input_values[1]),
GateType::Nor => server_key.nor(&input_values[0], &input_values[1]),
Expand Down Expand Up @@ -454,6 +460,120 @@ impl Gate {
self.encrypted_multibit_output.clone()
}

pub fn evaluate_encrypted_shift_block(
&mut self,
ct1: &FheType,
ct2: &FheType,
cycle: usize,
dir : bool, // true for left shifts
) -> FheType {
if self.cycle == cycle {
match self.encrypted_multibit_output {
FheType::None => (),
_ => return self.encrypted_multibit_output.clone(),
}
}

self.encrypted_multibit_output = match (ct1, ct2) {
(FheType::U8(ct1_value), FheType::U8(ct2_value)) => {
if dir {
FheType::U8(ct1_value << ct2_value)
} else {
FheType::U8(ct1_value >> ct2_value)
}
}
(FheType::U16(ct1_value), FheType::U16(ct2_value)) => {
if dir {
FheType::U16(ct1_value << ct2_value)
} else {
FheType::U16(ct1_value >> ct2_value)
}
}
(FheType::U32(ct1_value), FheType::U32(ct2_value)) => {
if dir {
FheType::U32(ct1_value << ct2_value)
} else {
FheType::U32(ct1_value >> ct2_value)
}
}
(FheType::U64(ct1_value), FheType::U64(ct2_value)) => {
if dir {
FheType::U64(ct1_value << ct2_value)
} else {
FheType::U64(ct1_value >> ct2_value)
}
}
(FheType::U128(ct1_value), FheType::U128(ct2_value)) => {
if dir {
FheType::U128(ct1_value << ct2_value)
} else {
FheType::U128(ct1_value >> ct2_value)
}
}
_ => panic!("evaluate_encrypted_shift_block"),
};

self.cycle = cycle;
self.encrypted_multibit_output.clone()
}

pub fn evaluate_encrypted_shift_block_plain(
&mut self,
ct1: &FheType,
pt1: PtxtType,
cycle: usize,
dir: bool, // true for left shifts
) -> FheType {
if self.cycle == cycle {
match self.encrypted_multibit_output {
FheType::None => (),
_ => return self.encrypted_multibit_output.clone(),
}
}

self.encrypted_multibit_output = match (ct1, pt1) {
(FheType::U8(ct1_value), PtxtType::U8(pt1_value)) => {
if dir {
FheType::U8(ct1_value << pt1_value)
} else {
FheType::U8(ct1_value >> pt1_value)
}
}
(FheType::U16(ct1_value), PtxtType::U16(pt1_value)) => {
if dir {
FheType::U16(ct1_value << pt1_value)
} else {
FheType::U16(ct1_value >> pt1_value)
}
}
(FheType::U32(ct1_value), PtxtType::U32(pt1_value)) => {
if dir {
FheType::U32(ct1_value << pt1_value)
} else {
FheType::U32(ct1_value >> pt1_value)
}
}
(FheType::U64(ct1_value), PtxtType::U64(pt1_value)) => {
if dir {
FheType::U64(ct1_value << pt1_value)
} else {
FheType::U64(ct1_value >> pt1_value)
}
}
(FheType::U128(ct1_value), PtxtType::U128(pt1_value)) => {
if dir {
FheType::U128(ct1_value << pt1_value)
} else {
FheType::U128(ct1_value >> pt1_value)
}
}
_ => panic!("evaluate_encrypted_shift_block_plain"),
};

self.cycle = cycle;
self.encrypted_multibit_output.clone()
}

pub fn evaluate_encrypted_add_block_plain(
&mut self,
ct1: &FheType,
Expand Down
4 changes: 4 additions & 0 deletions src/verilog_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ fn parse_gate(tokens: &[&str]) -> Gate {
"mult" => GateType::Mult,
"div" => GateType::Div,
"sub" => GateType::Sub,
"shl" => GateType::Shl,
"shr" => GateType::Shr,
_ => panic!("Invalid gate type \"{}\"", tokens[0]),
};

Expand Down Expand Up @@ -221,6 +223,8 @@ pub fn read_verilog_file(
|| gate.get_gate_type() == GateType::Sub
|| gate.get_gate_type() == GateType::Mult
|| gate.get_gate_type() == GateType::Div
|| gate.get_gate_type() == GateType::Shl
|| gate.get_gate_type() == GateType::Shr
{
has_arith = true;
}
Expand Down

0 comments on commit b23ba93

Please sign in to comment.