Skip to content

Commit e8cc790

Browse files
committed
Merge branch 'pqc-snova' into 'main'
Snova See merge request root/bc-java!83
2 parents 547257e + 8c13a64 commit e8cc790

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+5153
-134
lines changed

core/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,4 +637,53 @@ public interface BCObjectIdentifiers
637637
// ASN1ObjectIdentifier ov_v_pkc_skc = new ASN1ObjectIdentifier("1.3.9999.9.12.1");
638638
// /** 1.3.9999.9.12.2 OQS_OID_P521_OV_V_PKC_SKC */
639639
// ASN1ObjectIdentifier p521_ov_v_pkc_skc = new ASN1ObjectIdentifier("1.3.9999.9.12.2");
640+
641+
/**
642+
* Snova
643+
*/
644+
ASN1ObjectIdentifier snova = bc_sig.branch("11");
645+
ASN1ObjectIdentifier snova_24_5_4_ssk = snova.branch("1");
646+
ASN1ObjectIdentifier snova_24_5_4_esk = snova.branch("2");
647+
ASN1ObjectIdentifier snova_24_5_4_shake_ssk = snova.branch("3");
648+
ASN1ObjectIdentifier snova_24_5_4_shake_esk = snova.branch("4");
649+
ASN1ObjectIdentifier snova_24_5_5_ssk = snova.branch("5");
650+
ASN1ObjectIdentifier snova_24_5_5_esk = snova.branch("6");
651+
ASN1ObjectIdentifier snova_24_5_5_shake_ssk = snova.branch("7");
652+
ASN1ObjectIdentifier snova_24_5_5_shake_esk = snova.branch("8");
653+
ASN1ObjectIdentifier snova_25_8_3_ssk = snova.branch("9");
654+
ASN1ObjectIdentifier snova_25_8_3_esk = snova.branch("10");
655+
ASN1ObjectIdentifier snova_25_8_3_shake_ssk = snova.branch("11");
656+
ASN1ObjectIdentifier snova_25_8_3_shake_esk = snova.branch("12");
657+
ASN1ObjectIdentifier snova_29_6_5_ssk = snova.branch("13");
658+
ASN1ObjectIdentifier snova_29_6_5_esk = snova.branch("14");
659+
ASN1ObjectIdentifier snova_29_6_5_shake_ssk = snova.branch("15");
660+
ASN1ObjectIdentifier snova_29_6_5_shake_esk = snova.branch("16");
661+
ASN1ObjectIdentifier snova_37_8_4_ssk = snova.branch("17");
662+
ASN1ObjectIdentifier snova_37_8_4_esk = snova.branch("18");
663+
ASN1ObjectIdentifier snova_37_8_4_shake_ssk = snova.branch("19");
664+
ASN1ObjectIdentifier snova_37_8_4_shake_esk = snova.branch("20");
665+
ASN1ObjectIdentifier snova_37_17_2_ssk = snova.branch("21");
666+
ASN1ObjectIdentifier snova_37_17_2_esk = snova.branch("22");
667+
ASN1ObjectIdentifier snova_37_17_2_shake_ssk = snova.branch("23");
668+
ASN1ObjectIdentifier snova_37_17_2_shake_esk = snova.branch("24");
669+
ASN1ObjectIdentifier snova_49_11_3_ssk = snova.branch("25");
670+
ASN1ObjectIdentifier snova_49_11_3_esk = snova.branch("26");
671+
ASN1ObjectIdentifier snova_49_11_3_shake_ssk = snova.branch("27");
672+
ASN1ObjectIdentifier snova_49_11_3_shake_esk = snova.branch("28");
673+
ASN1ObjectIdentifier snova_56_25_2_ssk = snova.branch("29");
674+
ASN1ObjectIdentifier snova_56_25_2_esk = snova.branch("30");
675+
ASN1ObjectIdentifier snova_56_25_2_shake_ssk = snova.branch("31");
676+
ASN1ObjectIdentifier snova_56_25_2_shake_esk = snova.branch("32");
677+
ASN1ObjectIdentifier snova_60_10_4_ssk = snova.branch("33");
678+
ASN1ObjectIdentifier snova_60_10_4_esk = snova.branch("34");
679+
ASN1ObjectIdentifier snova_60_10_4_shake_ssk = snova.branch("35");
680+
ASN1ObjectIdentifier snova_60_10_4_shake_esk = snova.branch("36");
681+
ASN1ObjectIdentifier snova_66_15_3_ssk = snova.branch("37");
682+
ASN1ObjectIdentifier snova_66_15_3_esk = snova.branch("38");
683+
ASN1ObjectIdentifier snova_66_15_3_shake_ssk = snova.branch("39");
684+
ASN1ObjectIdentifier snova_66_15_3_shake_esk = snova.branch("40");
685+
ASN1ObjectIdentifier snova_75_33_2_ssk = snova.branch("41");
686+
ASN1ObjectIdentifier snova_75_33_2_esk = snova.branch("42");
687+
ASN1ObjectIdentifier snova_75_33_2_shake_ssk = snova.branch("43");
688+
ASN1ObjectIdentifier snova_75_33_2_shake_esk = snova.branch("44");
640689
}

core/src/main/java/org/bouncycastle/pqc/crypto/mayo/GF16Utils.java

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.bouncycastle.pqc.crypto.mayo;
22

3+
import org.bouncycastle.util.GF16;
4+
35
class GF16Utils
46
{
57
static final long NIBBLE_MASK_MSB = 0x7777777777777777L;
@@ -206,38 +208,6 @@ static void mulAddMUpperTriangularMatXMatTrans(int mVecLimbs, long[] bsMat, byte
206208
}
207209
}
208210

209-
/**
210-
* GF(16) multiplication mod x^4 + x + 1.
211-
* <p>
212-
* This method multiplies two elements in GF(16) (represented as integers 0–15)
213-
* using carryless multiplication followed by reduction modulo x^4 + x + 1.
214-
*
215-
* @param a an element in GF(16) (only the lower 4 bits are used)
216-
* @param b an element in GF(16) (only the lower 4 bits are used)
217-
* @return the product a * b in GF(16)
218-
*/
219-
static int mulF(int a, int b)
220-
{
221-
// Carryless multiply: multiply b by each bit of a and XOR.
222-
int p = (-(a & 1) & b) ^ (-((a >> 1) & 1) & (b << 1)) ^ (-((a >> 2) & 1) & (b << 2)) ^ (-((a >> 3) & 1) & (b << 3));
223-
// Reduce modulo f(X) = x^4 + x + 1.
224-
int topP = p & 0xF0;
225-
return (p ^ (topP >> 4) ^ (topP >> 3)) & 0x0F;
226-
}
227-
228-
/**
229-
* Computes the multiplicative inverse in GF(16) for a GF(16) element.
230-
*/
231-
static byte inverseF(int a)
232-
{
233-
// In GF(16), the inverse can be computed via exponentiation.
234-
int a2 = mulF(a, a);
235-
int a4 = mulF(a2, a2);
236-
int a8 = mulF(a4, a4);
237-
int a6 = mulF(a2, a4);
238-
return (byte)mulF(a8, a6);
239-
}
240-
241211
/**
242212
* Performs a GF(16) carryless multiplication of a nibble (lower 4 bits of a)
243213
* with a 64-bit word b, then reduces modulo the polynomial x⁴ + x + 1 on each byte.
@@ -266,7 +236,7 @@ static void matMul(byte[] a, byte[] b, int bOff, byte[] c, int colrowAB, int row
266236
byte result = 0;
267237
for (int k = 0; k < colrowAB; k++)
268238
{
269-
result ^= mulF(a[aRowStart++], b[bOff + k]);
239+
result ^= GF16.mul(a[aRowStart++], b[bOff + k]);
270240
}
271241
c[cOff++] = result;
272242
}

core/src/main/java/org/bouncycastle/pqc/crypto/mayo/MayoKeyPairGenerator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.bouncycastle.crypto.KeyGenerationParameters;
88
import org.bouncycastle.crypto.digests.SHAKEDigest;
99
import org.bouncycastle.util.Arrays;
10+
import org.bouncycastle.util.GF16;
1011
import org.bouncycastle.util.Longs;
1112

1213
/**
@@ -94,7 +95,7 @@ public AsymmetricCipherKeyPair generateKeyPair()
9495
// o ← Decode_o(S[ param_pk_seed_bytes : param_pk_seed_bytes + O_bytes ])
9596
// Decode nibbles from S starting at offset param_pk_seed_bytes into O,
9697
// with expected output length = param_v * param_o.
97-
Utils.decode(seed_pk, pkSeedBytes, O, 0, O.length);
98+
GF16.decode(seed_pk, pkSeedBytes, O, 0, O.length);
9899

99100
// Expand P1 and P2 into the array P using seed_pk.
100101
Utils.expandP1P2(p, P, seed_pk);

core/src/main/java/org/bouncycastle/pqc/crypto/mayo/MayoSigner.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import org.bouncycastle.util.Arrays;
1212
import org.bouncycastle.util.Bytes;
13+
import org.bouncycastle.util.GF16;
1314
import org.bouncycastle.util.Longs;
1415
import org.bouncycastle.util.Pack;
1516

@@ -50,7 +51,6 @@ public class MayoSigner
5051
@Override
5152
public void init(boolean forSigning, CipherParameters param)
5253
{
53-
5454
if (forSigning)
5555
{
5656
pubKey = null;
@@ -135,7 +135,7 @@ public byte[] generateSignature(byte[] message)
135135

136136
// Decode the portion of S after the first param_pk_seed_bytes into O.
137137
// (In C, this is: decode(S + param_pk_seed_bytes, O, param_v * param_o))
138-
Utils.decode(seed_pk, pk_seed_bytes, O, 0, O.length);
138+
GF16.decode(seed_pk, pk_seed_bytes, O, 0, O.length);
139139

140140
// Expand P1 and P2 into the long array P using seed_pk.
141141
Utils.expandP1P2(params, P, seed_pk);
@@ -187,7 +187,7 @@ public byte[] generateSignature(byte[] message)
187187
System.arraycopy(salt, 0, tmp, digestBytes, saltBytes);
188188
shake.update(tmp, 0, digestBytes + saltBytes);
189189
shake.doFinal(tenc, 0, params.getMBytes());
190-
Utils.decode(tenc, t, m);
190+
GF16.decode(tenc, t, m);
191191
int size = v * k * mVecLimbs;
192192
long[] Pv = new long[size];
193193
byte[] Ox = new byte[v];
@@ -202,7 +202,7 @@ public byte[] generateSignature(byte[] message)
202202
// Decode vectors
203203
for (int i = 0; i < k; i++)
204204
{
205-
Utils.decode(V, i * vbytes, Vdec, i * v, v);
205+
GF16.decode(V, i * vbytes, Vdec, i * v, v);
206206
}
207207

208208
//computeMandVPV(params, Vdec, P, params.getP1Limbs(), P, Mtmp, vPv);
@@ -225,7 +225,7 @@ public byte[] generateSignature(byte[] message)
225225
// A[(i + 1) * (ok + 1) - 1] = 0;
226226
// }
227227

228-
Utils.decode(V, k * vbytes, r, 0, ok);
228+
GF16.decode(V, k * vbytes, r, 0, ok);
229229

230230
if (sampleSolution(A, y, r, x))
231231
{
@@ -248,7 +248,7 @@ public byte[] generateSignature(byte[] message)
248248
}
249249

250250
// Encode and add salt
251-
Utils.encode(s, sig, nk);
251+
GF16.encode(s, sig, nk);
252252
System.arraycopy(salt, 0, sig, sig.length - saltBytes, saltBytes);
253253

254254
return Arrays.concatenate(sig, message);
@@ -316,10 +316,10 @@ public boolean verifySignature(byte[] message, byte[] signature)
316316
shake.update(tmp, 0, digestBytes);
317317
shake.update(signature, sigBytes - saltBytes, saltBytes);
318318
shake.doFinal(tEnc, 0, mBytes);
319-
Utils.decode(tEnc, t, m);
319+
GF16.decode(tEnc, t, m);
320320

321321
// Decode signature
322-
Utils.decode(signature, s, kn);
322+
GF16.decode(signature, s, kn);
323323

324324
// Evaluate public map
325325
//evalPublicMap(params, s, P1, P2, P3, y);
@@ -385,7 +385,7 @@ void computeRHS(long[] vPv, byte[] t, byte[] y)
385385
continue;
386386
}
387387

388-
long product = GF16Utils.mulF(top, ft);
388+
long product = GF16.mul(top, ft);
389389
if ((jj & 1) == 0)
390390
{
391391
tempBytes[jj >> 1] ^= (byte)(product & 0xF);
@@ -515,10 +515,10 @@ void computeA(long[] Mtmp, byte[] AOut)
515515
for (int i = 0, idx = 0; i < F_TAIL_LEN; i++)
516516
{
517517
int ft = fTailArr[i];
518-
tab[idx++] = (byte)GF16Utils.mulF(ft, 1);
519-
tab[idx++] = (byte)GF16Utils.mulF(ft, 2);
520-
tab[idx++] = (byte)GF16Utils.mulF(ft, 4);
521-
tab[idx++] = (byte)GF16Utils.mulF(ft, 8);
518+
tab[idx++] = (byte)GF16.mul(ft, 1);
519+
tab[idx++] = (byte)GF16.mul(ft, 2);
520+
tab[idx++] = (byte)GF16.mul(ft, 4);
521+
tab[idx++] = (byte)GF16.mul(ft, 8);
522522
}
523523

524524
// Final processing
@@ -550,7 +550,7 @@ void computeA(long[] Mtmp, byte[] AOut)
550550
{
551551
for (int i = 0; i + r < m; i++)
552552
{
553-
Utils.decode(Abytes, (((r * AWidth) >> 4) + c + i) << 3,
553+
GF16.decode(Abytes, (((r * AWidth) >> 4) + c + i) << 3,
554554
AOut, (r + i) * ACols + c, Math.min(16, ACols - 1 - c));
555555
}
556556
}
@@ -762,7 +762,7 @@ void ef(byte[] A, int nrows, int ncols)
762762
}
763763

764764
// Multiply the pivot row by the inverse of the pivot element.
765-
vecMulAddU64(rowLen, pivotRow, GF16Utils.inverseF(pivot), pivotRow2);
765+
vecMulAddU64(rowLen, pivotRow, GF16.inv((byte)pivot), pivotRow2);
766766

767767
// Conditionally write the pivot row back into the correct row (if pivot is nonzero).
768768
for (int row = lowerBound, rowRowLen = lowerBound * rowLen; row <= upperBound; row++, rowRowLen += rowLen)
@@ -798,7 +798,7 @@ void ef(byte[] A, int nrows, int ncols)
798798
for (int i = 0, irowLen = 0; i < nrows; i++, irowLen += rowLen)
799799
{
800800
Pack.longToLittleEndian(packedA, irowLen, len_4, bytes, 0);
801-
Utils.decode(bytes, 0, A, outIndex, ncols);
801+
GF16.decode(bytes, 0, A, outIndex, ncols);
802802
outIndex += ncols;
803803
}
804804
}

core/src/main/java/org/bouncycastle/pqc/crypto/mayo/Utils.java

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -11,78 +11,6 @@
1111

1212
class Utils
1313
{
14-
/**
15-
* Decodes an encoded byte array.
16-
* Each byte in the input contains two nibbles (4-bit values); the lower nibble is stored first,
17-
* followed by the upper nibble.
18-
*
19-
* @param m the input byte array (each byte holds two 4-bit values)
20-
* @param mdec the output array that will hold the decoded nibbles (one per byte)
21-
* @param mdecLen the total number of nibbles to decode
22-
*/
23-
public static void decode(byte[] m, byte[] mdec, int mdecLen)
24-
{
25-
int i, decIndex = 0, blocks = mdecLen >> 1;
26-
// Process pairs of nibbles from each byte
27-
for (i = 0; i < blocks; i++)
28-
{
29-
// Extract the lower nibble
30-
mdec[decIndex++] = (byte)(m[i] & 0x0F);
31-
// Extract the upper nibble (shift right 4 bits)
32-
mdec[decIndex++] = (byte)((m[i] >> 4) & 0x0F);
33-
}
34-
// If there is an extra nibble (odd number of nibbles), decode only the lower nibble
35-
if ((mdecLen & 1) == 1)
36-
{
37-
mdec[decIndex] = (byte)(m[i] & 0x0F);
38-
}
39-
}
40-
41-
public static void decode(byte[] m, int mOff, byte[] mdec, int decIndex, int mdecLen)
42-
{
43-
// Process pairs of nibbles from each byte
44-
int blocks = mdecLen >> 1;
45-
for (int i = 0; i < blocks; i++)
46-
{
47-
// Extract the lower nibble
48-
mdec[decIndex++] = (byte)(m[mOff] & 0x0F);
49-
// Extract the upper nibble (shift right 4 bits)
50-
mdec[decIndex++] = (byte)((m[mOff++] >> 4) & 0x0F);
51-
}
52-
// If there is an extra nibble (odd number of nibbles), decode only the lower nibble
53-
if ((mdecLen & 1) == 1)
54-
{
55-
mdec[decIndex] = (byte)(m[mOff] & 0x0F);
56-
}
57-
}
58-
59-
/**
60-
* Encodes an array of 4-bit values into a byte array.
61-
* Two 4-bit values are packed into one byte, with the first nibble stored in the lower 4 bits
62-
* and the second nibble stored in the upper 4 bits.
63-
*
64-
* @param m the input array of 4-bit values (stored as bytes, only lower 4 bits used)
65-
* @param menc the output byte array that will hold the encoded bytes
66-
* @param mlen the number of nibbles in the input array
67-
*/
68-
public static void encode(byte[] m, byte[] menc, int mlen)
69-
{
70-
int i, srcIndex = 0;
71-
// Process pairs of 4-bit values
72-
for (i = 0; i < mlen / 2; i++)
73-
{
74-
int lowerNibble = m[srcIndex] & 0x0F;
75-
int upperNibble = (m[srcIndex + 1] & 0x0F) << 4;
76-
menc[i] = (byte)(lowerNibble | upperNibble);
77-
srcIndex += 2;
78-
}
79-
// If there is an extra nibble (odd number of nibbles), store it directly in lower 4 bits.
80-
if ((mlen & 1) == 1)
81-
{
82-
menc[i] = (byte)(m[srcIndex] & 0x0F);
83-
}
84-
}
85-
8614
public static void unpackMVecs(byte[] in, int inOff, long[] out, int outOff, int vecs, int m)
8715
{
8816
int mVecLimbs = (m + 15) >> 4;

0 commit comments

Comments
 (0)