diff --git a/Makefile b/Makefile index 90ea879b..404903cd 100644 --- a/Makefile +++ b/Makefile @@ -55,9 +55,9 @@ checks: check_tools # gosec rule G115: Is exluded because there are int->uin64 conversions # and the rule currently contains false positives - @GOSECOUT=$$(gosec -quiet -exclude=G115 ./...); \ + @GOSECOUT=$$(gosec -quiet ./...); \ if [ -z "$$GOSECOUT" ]; then\ - echo "gosec: OK (excluding G115)";\ + echo "gosec: OK";\ else \ echo "gosec: problems in files:";\ echo "$$GOSECOUT";\ diff --git a/circuits/bgv/polynomial/polynomial_evaluator_sim.go b/circuits/bgv/polynomial/polynomial_evaluator_sim.go index f6210e55..20c9b269 100644 --- a/circuits/bgv/polynomial/polynomial_evaluator_sim.go +++ b/circuits/bgv/polynomial/polynomial_evaluator_sim.go @@ -1,6 +1,7 @@ package polynomial import ( + "fmt" "math/big" "math/bits" @@ -25,6 +26,12 @@ func (d simEvaluator) PolynomialDepth(degree int) int { if d.InvariantTensoring { return 0 } + + if degree < 0 { + panic(fmt.Errorf("invalid degree: cannot be negative")) + } + + /* #nosec G115 -- degree cannot be negative */ return bits.Len64(uint64(degree)) - 1 } diff --git a/circuits/ckks/bootstrapping/parameters.go b/circuits/ckks/bootstrapping/parameters.go index 26fcd7bf..05bf207e 100644 --- a/circuits/ckks/bootstrapping/parameters.go +++ b/circuits/ckks/bootstrapping/parameters.go @@ -67,6 +67,7 @@ func NewParametersFromLiteral(residualParameters ckks.Parameters, btpLit Paramet } // Takes the greatest NthRoot between the residualParameters NthRoot and the bootstrapping NthRoot + /* #nosec G115 -- N cannot be negative */ NthRoot = utils.Max(uint64(residualParameters.N()<<2), uint64(2< 1 && p.MaxDeg > (1< cannot evaluate poly", level, depth) } + /* #nosec G115 -- Degree cannot be negative */ logDegree := bits.Len64(uint64(polyVec.Value[0].Degree())) logSplit := bignum.OptimalSplit(logDegree) @@ -205,6 +206,7 @@ func (eval Evaluator[T]) EvaluateGianStep(i int, giantSteps []int, babySteps []* even, odd := babySteps[i], babySteps[i+1] + /* #nosec G115 -- Degree cannot be negative */ deg := 1 << bits.Len64(uint64(babySteps[i].Degree)) if err = eval.EvaluateMonomial(even.Value, odd.Value, pb.Value[deg]); err != nil { diff --git a/circuits/common/polynomial/power_basis.go b/circuits/common/polynomial/power_basis.go index b41bbe67..5ec5a93f 100644 --- a/circuits/common/polynomial/power_basis.go +++ b/circuits/common/polynomial/power_basis.go @@ -33,11 +33,16 @@ func NewPowerBasis(ct *rlwe.Ciphertext, basis bignum.Basis) (p PowerBasis) { // with a and/or b odd if possible. func SplitDegree(n int) (a, b int) { + if n < 0 { + panic(fmt.Errorf("invalid n: cannot be negative")) + } + if n&(n-1) == 0 { a, b = n/2, n/2 //Necessary for optimal depth } else { // [Lee et al. 2020] : High-Precision and Low-Complexity Approximate Homomorphic Encryption by Error Variance Minimization // Maximize the number of odd terms of Chebyshev basis + /* #nosec G115 -- n cannot be negative */ k := bits.Len64(uint64(n-1)) - 1 a = (1 << k) - 1 b = n + 1 - (1 << k) @@ -199,6 +204,7 @@ func (p PowerBasis) WriteTo(w io.Writer) (n int64, err error) { var inc int64 + /* #nosec G115 -- Basis cannot be negative if receiver is valid */ if inc, err = buffer.WriteUint8(w, uint8(p.Basis)); err != nil { return n + inc, err } diff --git a/core/rgsw/blindrot/evaluator.go b/core/rgsw/blindrot/evaluator.go index a6d0dff7..b766f1c9 100644 --- a/core/rgsw/blindrot/evaluator.go +++ b/core/rgsw/blindrot/evaluator.go @@ -80,6 +80,7 @@ func (eval *Evaluator) Evaluate(ct *rlwe.Ciphertext, testPolyWithSlotIndex map[i tmp1 := acc.Value[1].Coeffs[0] tmp0[0] = tmp1[0] NLWE := ringQLWE.N() + /* #nosec G115 -- N cannot be negative */ mask := uint64(ringQBR.N()<<1) - 1 for j := 1; j < NLWE; j++ { tmp0[j] = -tmp1[ringQLWE.N()-j] & mask @@ -103,6 +104,7 @@ func (eval *Evaluator) Evaluate(ct *rlwe.Ciphertext, testPolyWithSlotIndex map[i // Line 2 of Algorithm 7 of https://eprint.iacr.org/2022/198 // Acc = (f(X^{-g}) * X^{-g * b}, 0) + /* #nosec G115 -- b is ensured to be small enough */ Xb := ringQBR.NewMonomialXi(int(b)) ringQBR.NTT(Xb, Xb) ringQBR.MForm(Xb, Xb) @@ -231,6 +233,7 @@ func getGaloisElementInverseMap(GaloisGen uint64, N int) (GaloisGenDiscreteLog m twoN := N << 1 NHalf := N >> 1 + /* #nosec G115 -- twoN cannot be negative */ mask := uint64(twoN - 1) GaloisGenDiscreteLog = map[uint64]int{} @@ -238,6 +241,7 @@ func getGaloisElementInverseMap(GaloisGen uint64, N int) (GaloisGenDiscreteLog m var pow uint64 = 1 for i := 0; i < NHalf; i++ { GaloisGenDiscreteLog[pow] = i + /* #nosec G115 -- twoN cannot be negative */ GaloisGenDiscreteLog[uint64(twoN)-pow] = -i pow *= GaloisGen pow &= mask @@ -282,6 +286,7 @@ func (eval *Evaluator) modSwitchRLWETo2NLvl(level int, polQ, pol2N ring.Poly, ma QBig := ringQ.ModulusAtLevel[level] + /* #nosec G115 -- N cannot be negative */ twoN := uint64(eval.paramsBR.N() << 1) twoNBig := bignum.NewInt(twoN) tmp := pol2N.Coeffs[0] diff --git a/core/rlwe/element.go b/core/rlwe/element.go index a6713c71..8466172e 100644 --- a/core/rlwe/element.go +++ b/core/rlwe/element.go @@ -107,6 +107,7 @@ func (op Element[T]) N() int { // LogN returns the log2 of the ring degree used by the target element. func (op Element[T]) LogN() int { + /* #nosec G115 -- N cannot be negative */ return bits.Len64(uint64(op.N() - 1)) } diff --git a/core/rlwe/inner_sum.go b/core/rlwe/inner_sum.go index d41fd462..9dba444f 100644 --- a/core/rlwe/inner_sum.go +++ b/core/rlwe/inner_sum.go @@ -61,6 +61,7 @@ func (eval Evaluator) Trace(ctIn *Ciphertext, logN int, opOut *Ciphertext) (err gap >>= 1 // We skip the last step that applies phi(5^{-1}) } + /* #nosec G115 -- gap cannot be negative */ NInv := new(big.Int).SetUint64(uint64(gap)) NInv.ModInverse(NInv, ringQ.ModulusAtLevel[level]) diff --git a/core/rlwe/metadata.go b/core/rlwe/metadata.go index ea0fe327..d9a92167 100644 --- a/core/rlwe/metadata.go +++ b/core/rlwe/metadata.go @@ -216,6 +216,7 @@ func (m PlaintextMetaData) MarshalJSON() (p []byte, err error) { Scale: m.Scale, IsBatched: fmt.Sprintf("0x%02x", IsBatched), IsBitReversed: fmt.Sprintf("0x%02x", IsBitReversed), + /* #nosec G115 -- Rows and Cols cannot be negative if valid */ LogDimensions: [2]string{fmt.Sprintf("0x%02x", uint8(m.LogDimensions.Rows)), fmt.Sprintf("0x%02x", uint8(m.LogDimensions.Cols))}, } @@ -271,6 +272,7 @@ func (m *PlaintextMetaData) UnmarshalJSON(p []byte) (err error) { return err } + /* #nosec G115 -- logRows and logCols are < 256 if valid */ m.LogDimensions = ring.Dimensions{Rows: int(int8(logRows)), Cols: int(int8(logCols))} return diff --git a/core/rlwe/params.go b/core/rlwe/params.go index 18b2467f..faef686b 100644 --- a/core/rlwe/params.go +++ b/core/rlwe/params.go @@ -288,6 +288,7 @@ func (p Parameters) LogN() int { // NthRoot returns the NthRoot of the ring. func (p Parameters) NthRoot() int { if p.RingQ() != nil { + /* #nosec G115 -- NthRoot of valid [rlwe.Ring] is positive */ return int(p.RingQ().NthRoot()) } @@ -296,6 +297,7 @@ func (p Parameters) NthRoot() int { // LogNthRoot returns the log2(NthRoot) of the ring. func (p Parameters) LogNthRoot() int { + /* #nosec G115 -- NthRoot cannot be negative */ return bits.Len64(uint64(p.NthRoot() - 1)) } @@ -576,6 +578,7 @@ func (p Parameters) GaloisElements(k []int) (galEls []uint64) { // GaloisElement takes an integer k and returns GaloisGen^{k} mod NthRoot. func (p Parameters) GaloisElement(k int) uint64 { + /* #nosec G115 -- implicit reduction modulo 2^64 */ return ring.ModExp(GaloisGen, uint64(k)&(p.ringQ.NthRoot()-1), p.ringQ.NthRoot()) } @@ -609,6 +612,7 @@ func (p Parameters) SolveDiscreteLogGaloisElement(galEl uint64) (k int) { } if x == 1 { + /* #nosec G115 -- kuint is ensured to be smaller than NthRoot */ return int(kuint) } @@ -732,6 +736,7 @@ func (p Parameters) BinarySize() int { func CheckModuli(q, p []uint64) error { for i, qi := range q { + /* #nosec G115 -- error is returned if integer overflow conversion */ if uint64(bits.Len64(qi)-1) > MaxModuliSize+1 { return fmt.Errorf("a Qi bit-size (i=%d) is larger than %d", i, MaxModuliSize) } @@ -746,6 +751,7 @@ func CheckModuli(q, p []uint64) error { if p != nil { for i, pi := range p { + /* #nosec G115 -- error is triggered if integer overflow conversion */ if uint64(bits.Len64(pi)-1) > MaxModuliSize+2 { return fmt.Errorf("a Pi bit-size (i=%d) is larger than %d", i, MaxModuliSize) } @@ -826,6 +832,7 @@ func GenModuli(LogNthRoot int, logQ, logP []int) (q, p []uint64, err error) { primes := make(map[int][]uint64) for bitsize, value := range primesbitlen { + /* #nosec G115 -- bitsize cannot be negative */ g := ring.NewNTTFriendlyPrimesGenerator(uint64(bitsize), uint64(1< int = int64 */ qoverqiinvqi[i] = ModexpMontgomery(qiStar, int(qi-2), qi, mredQ[i], bredQ[i]) for j, pj := range P { diff --git a/ring/interpolation.go b/ring/interpolation.go index ba44a4bd..0b9ccee3 100644 --- a/ring/interpolation.go +++ b/ring/interpolation.go @@ -1,6 +1,7 @@ package ring import ( + "fmt" "math/bits" "unsafe" ) @@ -17,8 +18,14 @@ type Interpolator struct { // prime or not congruent to 1 mod 2N, where N is the next power of two greater // than degree+1. func NewInterpolator(degree int, T uint64) (itp *Interpolator, err error) { + + if degree < 0 { + panic(fmt.Errorf("invalid degree: cannot be negative")) + } + itp = new(Interpolator) + /* #nosec G115 -- degree cannot be negative */ if itp.r, err = NewRing(1< int = int64 */ coeffs[j] = ModexpMontgomery(coeffs[j], int(T-2), T, mredParams, bredParams) } diff --git a/ring/ntt.go b/ring/ntt.go index cc1ad774..ce37f18b 100644 --- a/ring/ntt.go +++ b/ring/ntt.go @@ -314,6 +314,7 @@ func nttUnrolled16Lazy(p1, p2 []uint64, N int, Q, MRedConstant uint64, roots []u for m := 2; m < N; m <<= 1 { + /* #nosec G115 -- m cannot be negative */ reduce = (bits.Len64(uint64(m))&1 == 1) t >>= 1 @@ -848,6 +849,7 @@ func nttConjugateInvariantLazyUnrolled16(p1, p2 []uint64, N int, Q, MRedConstant // Continue the rest of the second to the n-1 butterflies on p2 with approximate reduction for m := 2; m < 2*N; m <<= 1 { + /* #nosec G115 -- m cannot be negative */ reduce = (bits.Len64(uint64(m))&1 == 1) t >>= 1 diff --git a/ring/ring.go b/ring/ring.go index 85d5c585..92d6651e 100644 --- a/ring/ring.go +++ b/ring/ring.go @@ -100,6 +100,7 @@ func (r Ring) ConjugateInvariantRing() (*Ring, error) { for i, s := range r.SubRings { + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ if cr.SubRings[i], err = NewSubRingWithCustomNTT(s.N>>1, s.Modulus, NewNumberTheoreticTransformerConjugateInvariant, int(s.NthRoot)); err != nil { return nil, err } @@ -130,6 +131,7 @@ func (r Ring) StandardRing() (*Ring, error) { for i, s := range r.SubRings { + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ if sr.SubRings[i], err = NewSubRingWithCustomNTT(s.N<<1, s.Modulus, NewNumberTheoreticTransformerStandard, int(s.NthRoot)); err != nil { return nil, err } @@ -147,6 +149,7 @@ func (r Ring) N() int { // LogN returns log2(ring degree). func (r Ring) LogN() int { + /* #nosec G115 -- N cannot be negative */ return bits.Len64(uint64(r.N() - 1)) } diff --git a/ring/sampler_gaussian.go b/ring/sampler_gaussian.go index 1e186194..a8fdaf50 100644 --- a/ring/sampler_gaussian.go +++ b/ring/sampler_gaussian.go @@ -139,6 +139,7 @@ func (g *GaussianSampler) read(pol Poly, f func(a, b, c uint64) uint64) { normInt.Add(normInt, bignum.RandInt(g.prng, normIntLowBits)) } + /* #nosec G115 -- sign is 0 or 1 */ normInt.Mul(normInt, bignum.NewInt(2*int64(sign)-1)) if normInt.Cmp(boundInt) < 1 { @@ -222,6 +223,7 @@ func (g *GaussianSampler) normFloat64() (float64, uint64) { juint32 := randU32() + /* #nosec G115 -- juint32 is masked to 31 bits */ j := int32(juint32 & 0x7fffffff) sign := uint64(juint32 >> 31) @@ -230,6 +232,7 @@ func (g *GaussianSampler) normFloat64() (float64, uint64) { x := float64(j) * float64(wn[i]) // 1 (>99%) + /* #nosec G115 -- j cannot be negative */ if uint32(j) < kn[i] { g.ptr = ptr return x, sign diff --git a/ring/sampler_ternary.go b/ring/sampler_ternary.go index fd3c6d39..5c6b0b12 100644 --- a/ring/sampler_ternary.go +++ b/ring/sampler_ternary.go @@ -111,6 +111,7 @@ func (ts *TernarySampler) computeMatrixTernary(p float64) { x = uint64(g) for j := uint64(0); j < ternarySamplerPrecision-1; j++ { + /* #nosec G115 -- value is 1 bit */ ts.matrixProba[0][j] = uint8((x >> (ternarySamplerPrecision - j - 1)) & 1) } @@ -119,6 +120,7 @@ func (ts *TernarySampler) computeMatrixTernary(p float64) { x = uint64(g) for j := uint64(0); j < ternarySamplerPrecision-1; j++ { + /* #nosec G115 -- value is 1 bit */ ts.matrixProba[1][j] = uint8((x >> (ternarySamplerPrecision - j - 1)) & 1) } @@ -223,9 +225,11 @@ func (ts *TernarySampler) sampleSparse(pol Poly, f func(a, b, c uint64) uint64) m := ts.matrixValues for i := 0; i < ts.hw; i++ { + /* #nosec G115 -- N-i and bits(N-i) cannot be negative */ mask = (1 << uint64(bits.Len64(uint64(N-i)))) - 1 // rejection sampling of a random variable between [0, len(index)] j = randInt32(ts.prng, mask) + /* #nosec G115 -- N-i cannot be negative */ for j >= uint64(N-i) { j = randInt32(ts.prng, mask) } @@ -307,6 +311,7 @@ func (ts *TernarySampler) kysampling(prng sampling.PRNG, randomBytes []byte, poi sign = uint8(randomBytes[bytePointer]>>(i+1)) & 1 } + /* #nosec G115 -- row and sign cannot be negative */ return uint64(row), uint64(sign), randomBytes, pointer + 1, bytePointer } } diff --git a/ring/scalar.go b/ring/scalar.go index c3ceb53a..f1af5204 100644 --- a/ring/scalar.go +++ b/ring/scalar.go @@ -70,6 +70,7 @@ func (r *Ring) MulRNSScalar(s1, s2, sout RNSScalar) { // The inversion is done in-place and assumes that a is in Montgomery form. func (r *Ring) Inverse(a RNSScalar) { for i, s := range r.SubRings[:r.level+1] { + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ a[i] = ModexpMontgomery(a[i], int(s.Modulus-2), s.Modulus, s.MRedConstant, s.BRedConstant) } } diff --git a/ring/subring.go b/ring/subring.go index aa9c54b3..9decee73 100644 --- a/ring/subring.go +++ b/ring/subring.go @@ -50,11 +50,16 @@ func NewSubRingWithCustomNTT(N int, Modulus uint64, ntt func(*SubRing, int) Numb return nil, fmt.Errorf("invalid ring degree: must be a power of 2 greater than %d", MinimumRingDegreeForLoopUnrolledOperations) } + if NthRoot < 0 { + panic(fmt.Errorf("invalid NthRoot: cannot be negative")) + } + s = &SubRing{} s.N = N s.Modulus = Modulus + /* #nosec G115 -- Modulus-1 cannot be negative */ s.Mask = (1 << uint64(bits.Len64(Modulus-1))) - 1 // Computes the fast modular reduction constants for the Ring @@ -67,6 +72,7 @@ func NewSubRingWithCustomNTT(N int, Modulus uint64, ntt func(*SubRing, int) Numb } s.NTTTable = new(NTTTable) + /* #nosec G115 -- NthRoot cannot be negative */ s.NthRoot = uint64(NthRoot) s.ntt = ntt(s, N) @@ -246,8 +252,11 @@ func (s *SubRing) parametersLiteral() subRingParametersLiteral { Factors := make([]uint64, len(s.Factors)) copy(Factors, s.Factors) return subRingParametersLiteral{ - Type: uint8(s.Type()), - LogN: uint8(bits.Len64(uint64(s.N - 1))), + /* #nosec G115 -- s.Type has is 0 or 1 */ + Type: uint8(s.Type()), + /* #nosec G115 -- N cannot be negative if SubRing is valid */ + LogN: uint8(bits.Len64(uint64(s.N - 1))), + /* #nosec G115 -- NthRoot cannot be negative if SubRing is valid */ NthRoot: uint8(int(s.NthRoot) / s.N), Modulus: s.Modulus, Factors: Factors, @@ -263,6 +272,8 @@ func newSubRingFromParametersLiteral(p subRingParametersLiteral) (s *SubRing, er s.N = 1 << int(p.LogN) s.NTTTable = new(NTTTable) + + /* #nosec G115 -- deserialization from valid subring -> N and NthRoot cannot be negative */ s.NthRoot = uint64(s.N) * uint64(p.NthRoot) s.Modulus = p.Modulus @@ -272,6 +283,7 @@ func newSubRingFromParametersLiteral(p subRingParametersLiteral) (s *SubRing, er s.PrimitiveRoot = p.PrimitiveRoot + /* #nosec G115 -- Modulus cannot be negative */ s.Mask = (1 << uint64(bits.Len64(s.Modulus-1))) - 1 // Computes the fast modular reduction parameters for the Ring @@ -288,7 +300,9 @@ func newSubRingFromParametersLiteral(p subRingParametersLiteral) (s *SubRing, er s.ntt = NewNumberTheoreticTransformerStandard(s, s.N) + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ if int(s.NthRoot) < s.N<<1 { + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ return nil, fmt.Errorf("invalid ring type: NthRoot must be at least 2N but is %dN", int(s.NthRoot)/s.N) } @@ -296,7 +310,9 @@ func newSubRingFromParametersLiteral(p subRingParametersLiteral) (s *SubRing, er s.ntt = NewNumberTheoreticTransformerConjugateInvariant(s, s.N) + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ if int(s.NthRoot) < s.N<<2 { + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ return nil, fmt.Errorf("invalid ring type: NthRoot must be at least 4N but is %dN", int(s.NthRoot)/s.N) } diff --git a/schemes/bgv/encoder.go b/schemes/bgv/encoder.go index 44e9c9f5..00a3e533 100644 --- a/schemes/bgv/encoder.go +++ b/schemes/bgv/encoder.go @@ -103,6 +103,7 @@ func permuteMatrix(logN int) (perm []uint64) { perm = make([]uint64, N) + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ halfN := int(N >> 1) for i, j := 0, halfN; i < halfN; i, j = i+1, j+1 { @@ -157,7 +158,9 @@ func (ecd Encoder) Encode(values interface{}, pt *rlwe.Plaintext) (err error) { var sign, abs uint64 for i, c := range values { + /* #nosec G115 -- type conversion purposefully used */ sign = uint64(c) >> 63 + /* #nosec G115 -- converted value is ensured to be positive */ abs = ring.BRedAdd(uint64(c*((int64(sign)^1)-int64(sign))), T, BRC) ptT[i] = sign*(T-abs) | (sign^1)*abs } @@ -217,7 +220,9 @@ func (ecd Encoder) EncodeRingT(values IntegerSlice, scale rlwe.Scale, pT ring.Po var sign, abs uint64 for i, c := range values { + /* #nosec G115 -- c cannot be negative */ sign = uint64(c) >> 63 + /* #nosec G115 -- converted value is ensured to be positive */ abs = ring.BRedAdd(uint64(c*((int64(sign)^1)-int64(sign))), T, BRC) pt[perm[i]] = sign*(T-abs) | (sign^1)*abs } @@ -328,10 +333,12 @@ func (ecd Encoder) DecodeRingT(pT ring.Poly, scale rlwe.Scale, values IntegerSli values[i] = tmp[ecd.indexMatrix[i]] } case []int64: + /* #nosec G115 -- PlaintextModulus <= 61 bits */ modulus := int64(ecd.parameters.PlaintextModulus()) modulusHalf := modulus >> 1 var value int64 for i := range values { + /* #nosec G115 -- values <= 61 bits */ if value = int64(tmp[ecd.indexMatrix[i]]); value >= modulusHalf { values[i] = value - modulus } else { @@ -457,11 +464,13 @@ func (ecd Encoder) Decode(pt *rlwe.Plaintext, values interface{}) (err error) { ptT := bufT.Coeffs[0] N := ecd.parameters.RingT().N() + /* #nosec G115 -- PlaintextModulus <= 61 bits */ modulus := int64(ecd.parameters.PlaintextModulus()) modulusHalf := modulus >> 1 var value int64 for i := 0; i < N; i++ { + /* #nosec G115 -- values <= 61 bits */ if value = int64(ptT[i]); value >= modulusHalf { values[i] = value - modulus } else { diff --git a/schemes/bgv/params.go b/schemes/bgv/params.go index 6b24b19b..b0edb9d1 100644 --- a/schemes/bgv/params.go +++ b/schemes/bgv/params.go @@ -97,6 +97,7 @@ func NewParameters(rlweParams rlwe.Parameters, t uint64) (p Parameters, err erro var ringQMul *ring.Ring nbQiMul := int(math.Ceil(float64(rlweParams.RingQ().ModulusAtLevel[rlweParams.MaxLevel()].BitLen()+rlweParams.LogN()) / 61.0)) + /* #nosec G115 -- NthRoot cannot be negative */ g := ring.NewNTTFriendlyPrimesGenerator(61, uint64(rlweParams.NthRoot())) primes, err := g.NextDownstreamPrimes(nbQiMul) if err != nil { @@ -116,6 +117,7 @@ func NewParameters(rlweParams rlwe.Parameters, t uint64) (p Parameters, err erro } var ringT *ring.Ring + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ if ringT, err = ring.NewRing(utils.Min(rlweParams.N(), int(order>>1)), []uint64{t}); err != nil { return Parameters{}, fmt.Errorf("provided plaintext modulus t is invalid: %w", err) } diff --git a/schemes/ckks/ckks_vector_ops.go b/schemes/ckks/ckks_vector_ops.go index 5eeb6f14..dd964946 100644 --- a/schemes/ckks/ckks_vector_ops.go +++ b/schemes/ckks/ckks_vector_ops.go @@ -18,11 +18,13 @@ const ( func SpecialIFFTDouble(values []complex128, N, M int, rotGroup []int, roots []complex128) { // Sanity check - if len(values) < N || len(rotGroup) < N || len(roots) < M+1 { + if N < 0 || M < N || len(values) < N || len(rotGroup) < N || len(roots) < M+1 { panic(fmt.Sprintf("invalid call of SpecialIFFTDouble: len(values)=%d or len(rotGroup)=%d < N=%d or len(roots)=%d < M+1=%d", len(values), len(rotGroup), N, len(roots), M)) } + /* #nosec G115 -- N cannot be negative */ logN := int(bits.Len64(uint64(N))) - 1 + /* #nosec G115 -- M cannot be negative */ logM := int(bits.Len64(uint64(M))) - 1 for loglen := logN; loglen > 0; loglen-- { len := 1 << loglen @@ -48,12 +50,15 @@ func SpecialIFFTDouble(values []complex128, N, M int, rotGroup []int, roots []co func SpecialFFTDouble(values []complex128, N, M int, rotGroup []int, roots []complex128) { // Sanity check - if len(values) < N || len(rotGroup) < N || len(roots) < M+1 { + if N < 0 || M < N || len(values) < N || len(rotGroup) < N || len(roots) < M+1 { panic(fmt.Sprintf("invalid call of SpecialFFTDouble: len(values)=%d or len(rotGroup)=%d < N=%d or len(roots)=%d < M+1=%d", len(values), len(rotGroup), N, len(roots), M)) } utils.BitReverseInPlaceSlice(values, N) + + /* #nosec G115 -- N cannot be negative */ logN := int(bits.Len64(uint64(N))) - 1 + /* #nosec G115 -- M cannot be negative */ logM := int(bits.Len64(uint64(M))) - 1 for loglen := 1; loglen <= logN; loglen++ { len := 1 << loglen @@ -74,7 +79,7 @@ func SpecialFFTDouble(values []complex128, N, M int, rotGroup []int, roots []com func SpecialFFTArbitrary(values []*bignum.Complex, N, M int, rotGroup []int, roots []*bignum.Complex) { // Sanity check - if len(values) < N || len(rotGroup) < N || len(roots) < M+1 { + if N < 0 || M < N || len(values) < N || len(rotGroup) < N || len(roots) < M+1 { panic(fmt.Sprintf("invalid call of SpecialFFTArbitrary: len(values)=%d or len(rotGroup)=%d < N=%d or len(roots)=%d < M+1=%d", len(values), len(rotGroup), N, len(roots), M)) } @@ -85,7 +90,9 @@ func SpecialFFTArbitrary(values []*bignum.Complex, N, M int, rotGroup []int, roo cMul := bignum.NewComplexMultiplier() + /* #nosec G115 -- N cannot be negative */ logN := int(bits.Len64(uint64(N))) - 1 + /* #nosec G115 -- M cannot be negative */ logM := int(bits.Len64(uint64(M))) - 1 for loglen := 1; loglen <= logN; loglen++ { len := 1 << loglen @@ -109,7 +116,7 @@ func SpecialFFTArbitrary(values []*bignum.Complex, N, M int, rotGroup []int, roo func SpecialIFFTArbitrary(values []*bignum.Complex, N, M int, rotGroup []int, roots []*bignum.Complex) { // Sanity check - if len(values) < N || len(rotGroup) < N || len(roots) < M+1 { + if N < 0 || M < N || len(values) < N || len(rotGroup) < N || len(roots) < M+1 { panic(fmt.Sprintf("invalid call of SpecialIFFTArbitrary: len(values)=%d or len(rotGroup)=%d < N=%d or len(roots)=%d < M+1=%d", len(values), len(rotGroup), N, len(roots), M)) } @@ -118,7 +125,9 @@ func SpecialIFFTArbitrary(values []*bignum.Complex, N, M int, rotGroup []int, ro cMul := bignum.NewComplexMultiplier() + /* #nosec G115 -- N cannot be negative */ logN := int(bits.Len64(uint64(N))) - 1 + /* #nosec G115 -- M cannot be negative */ logM := int(bits.Len64(uint64(M))) - 1 for loglen := logN; loglen > 0; loglen-- { len := 1 << loglen @@ -156,13 +165,15 @@ func SpecialFFTDoubleUL8(values []complex128, N, M int, rotGroup []int, roots [] } // Sanity check - if len(values) < N || len(rotGroup) < N || len(roots) < M+1 { + if N < 0 || M < N || len(values) < N || len(rotGroup) < N || len(roots) < M+1 { panic(fmt.Sprintf("invalid call of SpecialFFTDoubleUL8: len(values)=%d or len(rotGroup)=%d < N=%d or len(roots)=%d < M+1=%d", len(values), len(rotGroup), N, len(roots), M)) } utils.BitReverseInPlaceSlice(values, N) + /* #nosec G115 -- B cannot be negative */ logN := int(bits.Len64(uint64(N))) - 1 + /* #nosec G115 -- M cannot be negative */ logM := int(bits.Len64(uint64(M))) - 1 for loglen := 1; loglen <= logN; loglen++ { @@ -337,11 +348,13 @@ func SpecialiFFTDoubleUnrolled8(values []complex128, N, M int, rotGroup []int, r } // Sanity check - if len(values) < N || len(rotGroup) < N || len(roots) < M+1 { + if N < 0 || M < N || len(values) < N || len(rotGroup) < N || len(roots) < M+1 { panic(fmt.Sprintf("invalid call of SpecialiFFTDoubleUnrolled8: len(values)=%d or len(rotGroup)=%d < N=%d or len(roots)=%d < M+1=%d", len(values), len(rotGroup), N, len(roots), M)) } + /* #nosec G115 -- N cannot be negative */ logN := int(bits.Len64(uint64(N))) - 1 + /* #nosec G115 -- M cannot be negative */ logM := int(bits.Len64(uint64(M))) - 1 for loglen := logN; loglen > 0; loglen-- { diff --git a/schemes/ckks/encoder.go b/schemes/ckks/encoder.go index 328046e9..2d37283c 100644 --- a/schemes/ckks/encoder.go +++ b/schemes/ckks/encoder.go @@ -71,6 +71,7 @@ type Encoder struct { // perform the encoding. Else *[big.Float] and *[bignum.Complex] will be used. func NewEncoder(parameters Parameters, precision ...uint) (ecd *Encoder) { + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ m := int(parameters.RingQ().NthRoot()) rotGroup := make([]int, m>>2) @@ -793,6 +794,7 @@ func (ecd Encoder) FFT(values FloatSlice, logN int) (err error) { func polyToComplexNoCRT(coeffs []uint64, values FloatSlice, scale rlwe.Scale, logSlots int, isreal bool, ringQ *ring.Ring) (err error) { slots := 1 << logSlots + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ maxCols := int(ringQ.NthRoot() >> 2) gap := maxCols / slots Q := ringQ.SubRings[0].Modulus @@ -844,8 +846,10 @@ func polyToComplexNoCRT(coeffs []uint64, values FloatSlice, scale rlwe.Scale, lo } if c = coeffs[idx]; c >= Q>>1 { + /* #nosec G115 -- Q - c <= 61 bits */ values[i][0].SetInt64(-int64(Q - c)) } else { + /* #nosec G115 -- c <= 61 bits */ values[i][0].SetInt64(int64(c)) } } @@ -858,8 +862,10 @@ func polyToComplexNoCRT(coeffs []uint64, values FloatSlice, scale rlwe.Scale, lo } if c = coeffs[idx]; c >= Q>>1 { + /* #nosec G115 -- Q - c <= 61 bits */ values[i][1].SetInt64(-int64(Q - c)) } else { + /* #nosec G115 -- c <= 61 bits */ values[i][1].SetInt64(int64(c)) } } @@ -888,6 +894,7 @@ func polyToComplexNoCRT(coeffs []uint64, values FloatSlice, scale rlwe.Scale, lo // polyToComplexNoCRT decodes a multiple-level CRT poly on a complex valued [FloatSlice]. func polyToComplexCRT(poly ring.Poly, bigintCoeffs []*big.Int, values FloatSlice, scale rlwe.Scale, logSlots int, isreal bool, ringQ *ring.Ring) (err error) { + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ maxCols := int(ringQ.NthRoot() >> 2) slots := 1 << logSlots gap := maxCols / slots @@ -1130,8 +1137,10 @@ func (ecd *Encoder) polyToFloatNoCRT(coeffs []uint64, values FloatSlice, scale r } if coeffs[i] >= Q>>1 { + /* #nosec G115 -- Q - coeffs[i] <= 61 bits */ values[i].SetInt64(-int64(Q - coeffs[i])) } else { + /* #nosec G115 -- coeffs[i] <= 61 bits */ values[i].SetInt64(int64(coeffs[i])) } @@ -1156,8 +1165,10 @@ func (ecd *Encoder) polyToFloatNoCRT(coeffs []uint64, values FloatSlice, scale r } if coeffs[i] >= Q>>1 { + /* #nosec G115 -- Q - coeffs[i] <= 61 bits */ values[i][0].SetInt64(-int64(Q - coeffs[i])) } else { + /* #nosec G115 -- coeffs[i] <= 61 bits */ values[i][0].SetInt64(int64(coeffs[i])) } diff --git a/schemes/ckks/linear_transformation.go b/schemes/ckks/linear_transformation.go index 9a1fe3ee..36865ca4 100644 --- a/schemes/ckks/linear_transformation.go +++ b/schemes/ckks/linear_transformation.go @@ -40,6 +40,7 @@ func (eval Evaluator) Average(ctIn *rlwe.Ciphertext, logBatchSize int, opOut *rl // pre-multiplication by n^-1 for i, s := range ringQ.SubRings[:level+1] { + /* #nosec G115 -- n cannot be negative */ invN := ring.ModExp(uint64(n), s.Modulus-2, s.Modulus) invN = ring.MForm(invN, s.Modulus, s.BRedConstant) diff --git a/utils/bignum/minimax_approximation.go b/utils/bignum/minimax_approximation.go index a30b1075..e82dc34c 100644 --- a/utils/bignum/minimax_approximation.go +++ b/utils/bignum/minimax_approximation.go @@ -611,6 +611,7 @@ func findLocalMaximum(fErr func(x *big.Float) (y *big.Float), start, end *big.Fl quarter := new(big.Float).Sub(windowEnd, windowStart) quarter.Quo(quarter, NewFloat(4, prec)) + /* #nosec G115 -- prec is a bit-size */ for i := 0; i < int(prec); i++ { // Obtains the sign of the err Function in the interval (normalized and zeroed) @@ -673,6 +674,7 @@ func findLocalMinimum(fErr func(x *big.Float) (y *big.Float), start, end *big.Fl quarter := new(big.Float).Sub(windowEnd, windowStart) quarter.Quo(quarter, NewFloat(4, prec)) + /* #nosec G115 -- prec is a bit-size */ for i := 0; i < int(prec); i++ { // Obtains the sign of the err Function in the interval (normalized and zeroed) diff --git a/utils/factorization/factorization.go b/utils/factorization/factorization.go index b353770d..5a0fa6e1 100644 --- a/utils/factorization/factorization.go +++ b/utils/factorization/factorization.go @@ -107,6 +107,7 @@ func GetFactorPollardRho(m *big.Int) (d *big.Int) { x, y, d = new(big.Int).SetUint64(2), new(big.Int).SetUint64(2), new(big.Int).SetUint64(1) + /* #nosec G115 -- i cannot be negative */ c := new(big.Int).SetUint64(uint64(i)) counter := 0 diff --git a/utils/structs/map.go b/utils/structs/map.go index 4ffa91aa..cb93a7fe 100644 --- a/utils/structs/map.go +++ b/utils/structs/map.go @@ -52,7 +52,7 @@ func (m *Map[K, T]) WriteTo(w io.Writer) (n int64, err error) { var inc int64 - if inc, err = buffer.WriteUint32(w, uint32(len(*m))); err != nil { + if inc, err = buffer.WriteUint64(w, uint64(len(*m))); err != nil { return n + inc, err } n += inc @@ -100,8 +100,8 @@ func (m *Map[K, T]) ReadFrom(r io.Reader) (n int64, err error) { case buffer.Reader: var inc int64 - var size uint32 - if inc, err = buffer.ReadUint32(r, &size); err != nil { + var size uint64 + if inc, err = buffer.ReadUint64(r, &size); err != nil { return n + inc, err } n += inc @@ -110,6 +110,7 @@ func (m *Map[K, T]) ReadFrom(r io.Reader) (n int64, err error) { *m = make(Map[K, T], size) } + /* #nosec G115 -- library requires 64-bit system -> int = int64 */ for i := 0; i < int(size); i++ { var key uint64 @@ -141,7 +142,7 @@ func (m Map[K, T]) BinarySize() (size int) { panic(fmt.Errorf("vector component of type %T does not comply to %T", new(T), s)) } - size = 4 // #Ct + size = 8 // #Ct for _, v := range m { size += 8