diff --git a/diplomatic/src/rocket/CryptoNIST.scala b/rocket/src/CryptoNIST.scala similarity index 99% rename from diplomatic/src/rocket/CryptoNIST.scala rename to rocket/src/CryptoNIST.scala index f616c3a88..2d1bdb07e 100644 --- a/diplomatic/src/rocket/CryptoNIST.scala +++ b/rocket/src/CryptoNIST.scala @@ -4,7 +4,7 @@ package org.chipsalliance.rocket import chisel3._ import chisel3.util._ -import freechips.rocketchip.util._ +import org.chipsalliance.rocket.util._ class CryptoNISTInterface(xLen: Int) extends Bundle { val fn = Input(UInt(ABLUFN().SZ_ZKN_FN.W)) diff --git a/diplomatic/src/rocket/CryptoSM.scala b/rocket/src/CryptoSM.scala similarity index 97% rename from diplomatic/src/rocket/CryptoSM.scala rename to rocket/src/CryptoSM.scala index 1a759f341..5942749d0 100644 --- a/diplomatic/src/rocket/CryptoSM.scala +++ b/rocket/src/CryptoSM.scala @@ -4,7 +4,7 @@ package org.chipsalliance.rocket import chisel3._ import chisel3.util._ -import freechips.rocketchip.util._ +import org.chipsalliance.rocket.util._ class CryptoSMInterface(xLen: Int) extends Bundle { val fn = Input(UInt(ABLUFN().SZ_ZKS_FN.W)) diff --git a/rocket/src/util/BarrelShifter.scala b/rocket/src/util/BarrelShifter.scala new file mode 100644 index 000000000..b72fdfee7 --- /dev/null +++ b/rocket/src/util/BarrelShifter.scala @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: Apache-2.0 + +// FIXME: use chisel3.stdlib.BarrelShifter after chisel3 3.6.0 +package org.chipsalliance.rocket.util + +import chisel3._ +import chisel3.util.{Mux1H, UIntToOH} + +/** A Barrel Shifter implementation for Vec type. + * + * @param inputs input signal to be shifted, should be a [[Vec]] type. + * @param shiftInput input signal to indicate the shift number, encoded in UInt. + * @param shiftGranularity how many bits will be resolved in each layer. + * For a smaller `shiftGranularity`, latency will be high, but area is smaller. + * For a large `shiftGranularity`, latency will be low, but area is higher. + * + * @example {{{ + * val input = 0xAABBCCDD.U(32.W) + * val bytes = VecInit(input.asBools.grouped(8).map(VecInit(_).asUInt).toSeq) + * val shamt = 1.U(2.W) + * val output = BarrelShifter.leftRotate(bytes, shamt).asUInt // big endian + * // output = 0xDDAABBCC.U(32.W) + * // The depth of Mux is 2, whereas originally + * // the depth of Mux is log(32) = 5 + * val output = BarrelShifter.leftRotate(bytes, shamt, 2).asUInt // depth is 1 now + * }}} + */ +object BarrelShifter { + private trait ShiftType + + private object LeftShift extends ShiftType + + private object RightShift extends ShiftType + + private object LeftRotate extends ShiftType + + private object RightRotate extends ShiftType + + private def apply[T <: Data]( + inputs: Vec[T], + shiftInput: UInt, + shiftType: ShiftType, + shiftGranularity: Int = 1 + ): Vec[T] = { + require(shiftGranularity > 0) + val elementType: T = chiselTypeOf(inputs.head) + shiftInput.asBools + .grouped(shiftGranularity) + .map(VecInit(_).asUInt) + .zipWithIndex + .foldLeft(inputs) { + case (prev, (shiftBits, layer)) => + Mux1H( + UIntToOH(shiftBits), + Seq.tabulate(1 << shiftBits.getWidth)(i => { + // For each layer of barrel shifter, it needs to + // Mux between shift 0 and i * 2^(depthOfLayer*granularity) + // + // e.g, when depth = 2 and granu = 1, the first layer Mux between 0 and 1 + // while the second layer Mux between 0 and 2, thus Vec.shift(UInt(2.W)) + // + // e.g, when depth = 2 and granu = 2, the first layer Mux between 0, 1, 2 and 3 + // while the second layer Mux between 0, 4, 8, and 12, thus achieving Vec.shift(UInt(4.W)) + // + // Also, shift no more than inputs length since prev.drop will not warn about overflow + // this is for Vec with length not the exponential of 2, e.g. 13 + val layerShift: Int = (i * (1 << (layer * shiftGranularity))).min(prev.length) + VecInit(shiftType match { + case LeftRotate => + prev.drop(layerShift) ++ prev.take(layerShift) + case LeftShift => + prev.drop(layerShift) ++ Seq.fill(layerShift)(0.U.asTypeOf(elementType)) + case RightRotate => + prev.takeRight(layerShift) ++ prev.dropRight(layerShift) + case RightShift => + Seq.fill(layerShift)(0.U.asTypeOf(elementType)) ++ prev.dropRight(layerShift) + }) + }) + ) + } + } + + def leftShift[T <: Data](inputs: Vec[T], shift: UInt, layerSize: Int = 1): Vec[T] = + apply(inputs, shift, LeftShift, layerSize) + + def rightShift[T <: Data](inputs: Vec[T], shift: UInt, layerSize: Int = 1): Vec[T] = + apply(inputs, shift, RightShift, layerSize) + + def leftRotate[T <: Data](inputs: Vec[T], shift: UInt, layerSize: Int = 1): Vec[T] = + apply(inputs, shift, LeftRotate, layerSize) + + def rightRotate[T <: Data](inputs: Vec[T], shift: UInt, layerSize: Int = 1): Vec[T] = + apply(inputs, shift, RightRotate, layerSize) +} \ No newline at end of file diff --git a/rocket/src/util/SBox.scala b/rocket/src/util/SBox.scala new file mode 100644 index 000000000..854f5d94e --- /dev/null +++ b/rocket/src/util/SBox.scala @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// This is translated from https://github.com/riscv/riscv-crypto +// +// 2020-01-29 Markku-Juhani O. Saarinen +// Copyright (c) 2020, PQShield Ltd. All rights reserved. +// Converted to Chisel in 2022 + +/* + [BoPe12] Boyar J., Peralta R. "A Small Depth-16 Circuit for the AES + S-Box." Proc.SEC 2012. IFIP AICT 376. Springer, pp. 287-298 (2012) + DOI: https://doi.org/10.1007/978-3-642-30436-1_24 + Preprint: https://eprint.iacr.org/2011/332.pdf + + [Ny93] Nyberg K., "Differentially Uniform Mappings for Cryptography", + Proc. EUROCRYPT '93, LNCS 765, Springer, pp. 55-64 (1993) + DOI: https://doi.org/10.1007/3-540-48285-7_6 +*/ + +package org.chipsalliance.rocket.util + +import chisel3._ + +// top (inner) linear layer for AES +object SBoxAESEncIn { + def apply(x: UInt): UInt = { + val t = Wire(Vec(6, Bool())) + val y = Wire(Vec(21, Bool())) + t( 0) := x( 3) ^ x( 1) + t( 1) := x( 6) ^ x( 5) + t( 2) := x( 6) ^ x( 2) + t( 3) := x( 5) ^ x( 2) + t( 4) := x( 4) ^ x( 0) + t( 5) := x( 1) ^ x( 0) + y( 0) := x( 0) + y( 1) := x( 7) ^ x( 4) + y( 2) := x( 7) ^ x( 2) + y( 3) := x( 7) ^ x( 1) + y( 4) := x( 4) ^ x( 2) + y( 5) := y( 1) ^ t( 0) + y( 6) := x( 0) ^ y( 5) + y( 7) := x( 0) ^ t( 1) + y( 8) := y( 5) ^ t( 1) + y( 9) := y( 3) ^ y( 4) + y(10) := y( 5) ^ t( 2) + y(11) := t( 0) ^ t( 2) + y(12) := t( 0) ^ t( 3) + y(13) := y( 7) ^ y(12) + y(14) := t( 1) ^ t( 4) + y(15) := y( 1) ^ y(14) + y(16) := t( 1) ^ t( 5) + y(17) := y( 2) ^ y(16) + y(18) := y( 2) ^ y( 8) + y(19) := y(15) ^ y(13) + y(20) := y( 1) ^ t( 3) + y.asUInt + } +} + +// top (inner) linear layer for AES^-1 +object SBoxAESDecIn { + def apply(x: UInt): UInt = { + val t = Wire(Vec(5, Bool())) + val y = Wire(Vec(21, Bool())) + t( 0) := x( 1) ^ x( 0) + t( 1) := x( 6) ^ x( 1) + t( 2) := x( 5) ^ ~x( 2) + t( 3) := x( 2) ^ ~x( 1) + t( 4) := x( 5) ^ ~x( 3) + y( 0) := x( 7) ^ t( 2) + y( 1) := x( 4) ^ x( 3) + y( 2) := x( 7) ^ ~x( 6) + y( 3) := y( 1) ^ t( 0) + y( 4) := x( 3) ^ y( 6) + y( 5) := y(16) ^ t( 2) + y( 6) := x( 6) ^ ~y(17) + y( 7) := x( 0) ^ ~y( 1) + y( 8) := y( 2) ^ y(18) + y( 9) := y( 2) ^ t( 0) + y(10) := y( 8) ^ t( 3) + y(11) := y( 8) ^ y(20) + y(12) := t( 1) ^ t( 4) + y(13) := x( 5) ^ ~y(14) + y(14) := y(16) ^ t( 0) + y(15) := y(18) ^ t( 1) + y(16) := x( 6) ^ ~x( 4) + y(17) := x( 7) ^ x( 4) + y(18) := x( 3) ^ ~x( 0) + y(19) := x( 5) ^ ~y( 1) + y(20) := y( 1) ^ t( 3) + y.asUInt + } +} + +// top (inner) linear layer for SM4 +object SBoxSM4In { + def apply(x: UInt): UInt = { + val t = Wire(Vec(7, Bool())) + val y = Wire(Vec(21, Bool())) + t( 0) := x(3) ^ x( 4) + t( 1) := x(2) ^ x( 7) + t( 2) := x(7) ^ y(18) + t( 3) := x(1) ^ t( 1) + t( 4) := x(6) ^ x( 7) + t( 5) := x(0) ^ y(18) + t( 6) := x(3) ^ x( 6) + y( 0) := x(5) ^ ~y(10) + y( 1) := t(0) ^ t( 3) + y( 2) := x(0) ^ t( 0) + y( 3) := x(3) ^ y( 4) + y( 4) := x(0) ^ t( 3) + y( 5) := x(5) ^ t( 5) + y( 6) := x(0) ^ ~x( 1) + y( 7) := t(0) ^ ~y(10) + y( 8) := t(0) ^ t( 5) + y( 9) := x(3) + y(10) := x(1) ^ y(18) + y(11) := t(0) ^ t( 4) + y(12) := x(5) ^ t( 4) + y(13) := x(5) ^ ~y( 1) + y(14) := x(4) ^ ~t( 2) + y(15) := x(1) ^ ~t( 6) + y(16) := x(0) ^ ~t( 2) + y(17) := t(0) ^ ~t( 2) + y(18) := x(2) ^ x( 6) + y(19) := x(5) ^ ~y(14) + y(20) := x(0) ^ t( 1) + y.asUInt + } +} + +// The shared non-linear middle part for AES, AES^-1, and SM4. +object SBoxMid { + def apply(x: UInt): UInt = { + val t = Wire(Vec(46, Bool())) + val y = Wire(Vec(18, Bool())) + t( 0) := x( 3) ^ x(12) + t( 1) := x( 9) & x( 5) + t( 2) := x(17) & x( 6) + t( 3) := x(10) ^ t( 1) + t( 4) := x(14) & x( 0) + t( 5) := t( 4) ^ t( 1) + t( 6) := x( 3) & x(12) + t( 7) := x(16) & x( 7) + t( 8) := t( 0) ^ t( 6) + t( 9) := x(15) & x(13) + t(10) := t( 9) ^ t( 6) + t(11) := x( 1) & x(11) + t(12) := x( 4) & x(20) + t(13) := t(12) ^ t(11) + t(14) := x( 2) & x( 8) + t(15) := t(14) ^ t(11) + t(16) := t( 3) ^ t( 2) + t(17) := t( 5) ^ x(18) + t(18) := t( 8) ^ t( 7) + t(19) := t(10) ^ t(15) + t(20) := t(16) ^ t(13) + t(21) := t(17) ^ t(15) + t(22) := t(18) ^ t(13) + t(23) := t(19) ^ x(19) + t(24) := t(22) ^ t(23) + t(25) := t(22) & t(20) + t(26) := t(21) ^ t(25) + t(27) := t(20) ^ t(21) + t(28) := t(23) ^ t(25) + t(29) := t(28) & t(27) + t(30) := t(26) & t(24) + t(31) := t(20) & t(23) + t(32) := t(27) & t(31) + t(33) := t(27) ^ t(25) + t(34) := t(21) & t(22) + t(35) := t(24) & t(34) + t(36) := t(24) ^ t(25) + t(37) := t(21) ^ t(29) + t(38) := t(32) ^ t(33) + t(39) := t(23) ^ t(30) + t(40) := t(35) ^ t(36) + t(41) := t(38) ^ t(40) + t(42) := t(37) ^ t(39) + t(43) := t(37) ^ t(38) + t(44) := t(39) ^ t(40) + t(45) := t(42) ^ t(41) + y( 0) := t(38) & x( 7) + y( 1) := t(37) & x(13) + y( 2) := t(42) & x(11) + y( 3) := t(45) & x(20) + y( 4) := t(41) & x( 8) + y( 5) := t(44) & x( 9) + y( 6) := t(40) & x(17) + y( 7) := t(39) & x(14) + y( 8) := t(43) & x( 3) + y( 9) := t(38) & x(16) + y(10) := t(37) & x(15) + y(11) := t(42) & x( 1) + y(12) := t(45) & x( 4) + y(13) := t(41) & x( 2) + y(14) := t(44) & x( 5) + y(15) := t(40) & x( 6) + y(16) := t(39) & x( 0) + y(17) := t(43) & x(12) + y.asUInt + } +} + +// bottom (outer) linear layer for AES +object SBoxAESEncOut { + def apply(x: UInt): UInt = { + val t = Wire(Vec(30, Bool())) + val y = Wire(Vec(8, Bool())) + t( 0) := x(11) ^ x(12) + t( 1) := x( 0) ^ x( 6) + t( 2) := x(14) ^ x(16) + t( 3) := x(15) ^ x( 5) + t( 4) := x( 4) ^ x( 8) + t( 5) := x(17) ^ x(11) + t( 6) := x(12) ^ t( 5) + t( 7) := x(14) ^ t( 3) + t( 8) := x( 1) ^ x( 9) + t( 9) := x( 2) ^ x( 3) + t(10) := x( 3) ^ t( 4) + t(11) := x(10) ^ t( 2) + t(12) := x(16) ^ x( 1) + t(13) := x( 0) ^ t( 0) + t(14) := x( 2) ^ x(11) + t(15) := x( 5) ^ t( 1) + t(16) := x( 6) ^ t( 0) + t(17) := x( 7) ^ t( 1) + t(18) := x( 8) ^ t( 8) + t(19) := x(13) ^ t( 4) + t(20) := t( 0) ^ t( 1) + t(21) := t( 1) ^ t( 7) + t(22) := t( 3) ^ t(12) + t(23) := t(18) ^ t( 2) + t(24) := t(15) ^ t( 9) + t(25) := t( 6) ^ t(10) + t(26) := t( 7) ^ t( 9) + t(27) := t( 8) ^ t(10) + t(28) := t(11) ^ t(14) + t(29) := t(11) ^ t(17) + y( 0) := t( 6) ^ ~t(23) + y( 1) := t(13) ^ ~t(27) + y( 2) := t(25) ^ t(29) + y( 3) := t(20) ^ t(22) + y( 4) := t( 6) ^ t(21) + y( 5) := t(19) ^ ~t(28) + y( 6) := t(16) ^ ~t(26) + y( 7) := t( 6) ^ t(24) + y.asUInt + } +} + +// bottom (outer) linear layer for AES^-1 +object SBoxAESDecOut { + def apply(x: UInt): UInt = { + val t = Wire(Vec(30, Bool())) + val y = Wire(Vec(8, Bool())) + t( 0) := x( 2) ^ x(11) + t( 1) := x( 8) ^ x( 9) + t( 2) := x( 4) ^ x(12) + t( 3) := x(15) ^ x( 0) + t( 4) := x(16) ^ x( 6) + t( 5) := x(14) ^ x( 1) + t( 6) := x(17) ^ x(10) + t( 7) := t( 0) ^ t( 1) + t( 8) := x( 0) ^ x( 3) + t( 9) := x( 5) ^ x(13) + t(10) := x( 7) ^ t( 4) + t(11) := t( 0) ^ t( 3) + t(12) := x(14) ^ x(16) + t(13) := x(17) ^ x( 1) + t(14) := x(17) ^ x(12) + t(15) := x( 4) ^ x( 9) + t(16) := x( 7) ^ x(11) + t(17) := x( 8) ^ t( 2) + t(18) := x(13) ^ t( 5) + t(19) := t( 2) ^ t( 3) + t(20) := t( 4) ^ t( 6) + t(21) := 0.U + t(22) := t( 2) ^ t( 7) + t(23) := t( 7) ^ t( 8) + t(24) := t( 5) ^ t( 7) + t(25) := t( 6) ^ t(10) + t(26) := t( 9) ^ t(11) + t(27) := t(10) ^ t(18) + t(28) := t(11) ^ t(25) + t(29) := t(15) ^ t(20) + y( 0) := t( 9) ^ t(16) + y( 1) := t(14) ^ t(23) + y( 2) := t(19) ^ t(24) + y( 3) := t(23) ^ t(27) + y( 4) := t(12) ^ t(22) + y( 5) := t(17) ^ t(28) + y( 6) := t(26) ^ t(29) + y( 7) := t(13) ^ t(22) + y.asUInt + } +} + +// bottom (outer) linear layer for SM4 +object SBoxSM4Out { + def apply(x: UInt): UInt = { + val t = Wire(Vec(30, Bool())) + val y = Wire(Vec(8, Bool())) + t( 0) := x( 4) ^ x( 7) + t( 1) := x(13) ^ x(15) + t( 2) := x( 2) ^ x(16) + t( 3) := x( 6) ^ t( 0) + t( 4) := x(12) ^ t( 1) + t( 5) := x( 9) ^ x(10) + t( 6) := x(11) ^ t( 2) + t( 7) := x( 1) ^ t( 4) + t( 8) := x( 0) ^ x(17) + t( 9) := x( 3) ^ x(17) + t(10) := x( 8) ^ t( 3) + t(11) := t( 2) ^ t( 5) + t(12) := x(14) ^ t( 6) + t(13) := t( 7) ^ t( 9) + t(14) := x( 0) ^ x( 6) + t(15) := x( 7) ^ x(16) + t(16) := x( 5) ^ x(13) + t(17) := x( 3) ^ x(15) + t(18) := x(10) ^ x(12) + t(19) := x( 9) ^ t( 1) + t(20) := x( 4) ^ t( 4) + t(21) := x(14) ^ t( 3) + t(22) := x(16) ^ t( 5) + t(23) := t( 7) ^ t(14) + t(24) := t( 8) ^ t(11) + t(25) := t( 0) ^ t(12) + t(26) := t(17) ^ t( 3) + t(27) := t(18) ^ t(10) + t(28) := t(19) ^ t( 6) + t(29) := t( 8) ^ t(10) + y( 0) := t(11) ^ ~t(13) + y( 1) := t(15) ^ ~t(23) + y( 2) := t(20) ^ t(24) + y( 3) := t(16) ^ t(25) + y( 4) := t(26) ^ ~t(22) + y( 5) := t(21) ^ t(13) + y( 6) := t(27) ^ ~t(12) + y( 7) := t(28) ^ ~t(29) + y.asUInt + } +} \ No newline at end of file