Skip to content

Commit 0df73aa

Browse files
committed
Merge branch 'pqc-mayo' into 'main'
Mayo See merge request root/bc-java!75
2 parents 5989d52 + 0e88a50 commit 0df73aa

37 files changed

+3688
-103
lines changed

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ public interface BCObjectIdentifiers
248248
ASN1ObjectIdentifier falcon = bc_sig.branch("7");
249249

250250
ASN1ObjectIdentifier falcon_512 = new ASN1ObjectIdentifier("1.3.9999.3.6"); // falcon.branch("1");
251-
ASN1ObjectIdentifier falcon_1024 = new ASN1ObjectIdentifier("1.3.9999.3.9"); // falcon.branch("2");
251+
ASN1ObjectIdentifier falcon_1024 = new ASN1ObjectIdentifier("1.3.9999.3.9"); // falcon.branch("2");
252252

253253
/*
254254
* Dilithium
@@ -403,15 +403,15 @@ public interface BCObjectIdentifiers
403403
ASN1ObjectIdentifier ntrulpr953 = pqc_kem_ntrulprime.branch("4");
404404
ASN1ObjectIdentifier ntrulpr1013 = pqc_kem_ntrulprime.branch("5");
405405
ASN1ObjectIdentifier ntrulpr1277 = pqc_kem_ntrulprime.branch("6");
406-
406+
407407
ASN1ObjectIdentifier pqc_kem_sntruprime = pqc_kem_ntruprime.branch("2");
408408
ASN1ObjectIdentifier sntrup653 = pqc_kem_sntruprime.branch("1");
409409
ASN1ObjectIdentifier sntrup761 = pqc_kem_sntruprime.branch("2");
410410
ASN1ObjectIdentifier sntrup857 = pqc_kem_sntruprime.branch("3");
411411
ASN1ObjectIdentifier sntrup953 = pqc_kem_sntruprime.branch("4");
412412
ASN1ObjectIdentifier sntrup1013 = pqc_kem_sntruprime.branch("5");
413413
ASN1ObjectIdentifier sntrup1277 = pqc_kem_sntruprime.branch("6");
414-
414+
415415
/**
416416
* BIKE
417417
**/
@@ -432,7 +432,6 @@ public interface BCObjectIdentifiers
432432

433433
/**
434434
* ML-KEM/ML-DSA seed parameters algorithms - temporary
435-
*
436435
*/
437436
//TODO: delete before release
438437
ASN1ObjectIdentifier id_id_alg_seed = bc.branch("10");
@@ -443,4 +442,13 @@ public interface BCObjectIdentifiers
443442
ASN1ObjectIdentifier id_id_alg_ml_kem_512_seed = id_id_alg_seed.branch("4");
444443
ASN1ObjectIdentifier id_id_alg_ml_kem_768_seed = id_id_alg_seed.branch("5");
445444
ASN1ObjectIdentifier id_id_alg_ml_kem_1024_seed = id_id_alg_seed.branch("6");
445+
446+
/**
447+
* Mayo
448+
*/
449+
ASN1ObjectIdentifier mayo = bc_sig.branch("10");
450+
ASN1ObjectIdentifier mayo1 = mayo.branch("1");
451+
ASN1ObjectIdentifier mayo2 = mayo.branch("2");
452+
ASN1ObjectIdentifier mayo3 = mayo.branch("3");
453+
ASN1ObjectIdentifier mayo5 = mayo.branch("4");
446454
}
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
package org.bouncycastle.pqc.crypto.mayo;
2+
3+
class GF16Utils
4+
{
5+
static final long NIBBLE_MASK_MSB = 0x7777777777777777L;
6+
static final long MASK_MSB = 0x8888888888888888L;
7+
static final long MASK_LSB = 0x1111111111111111L;
8+
static final long NIBBLE_MASK_LSB = ~MASK_LSB;
9+
10+
/**
11+
* Multiplies each limb of a GF(16) vector (subarray of 'in') by the GF(16) element 'a'
12+
* and XORs the result into the corresponding subarray of acc.
13+
* <p>
14+
* This version uses explicit array offsets.
15+
*
16+
* @param mVecLimbs the number of limbs in the vector
17+
* @param in the input long array containing the vector; the vector starts at index inOffset
18+
* @param inOffset the starting index in 'in'
19+
* @param b the GF(16) element (0–255) to multiply by
20+
* @param acc the accumulator long array; the target vector starts at index accOffset
21+
* @param accOffset the starting index in 'acc'
22+
*/
23+
static void mVecMulAdd(int mVecLimbs, long[] in, int inOffset, int b, long[] acc, int accOffset)
24+
{
25+
long a, r64, a_msb, a_msb3;
26+
long b32 = b & 0x00000000FFFFFFFFL;
27+
long b32and1 = b32 & 1;
28+
long b32_1_1 = ((b32 >>> 1) & 1);
29+
long b32_2_1 = ((b32 >>> 2) & 1);
30+
long b32_3_1 = ((b32 >>> 3) & 1);
31+
for (int i = 0; i < mVecLimbs; i++)
32+
{
33+
// In the original code there is a conditional XOR with unsigned_char_blocker;
34+
// here we simply use b directly.
35+
a = in[inOffset++];
36+
r64 = a & -b32and1;
37+
38+
a_msb = a & MASK_MSB;
39+
a &= NIBBLE_MASK_MSB;
40+
a_msb3 = a_msb >>> 3;
41+
a = (a << 1) ^ (a_msb3 + (a_msb3 << 1));
42+
r64 ^= a & -b32_1_1;
43+
44+
a_msb = a & MASK_MSB;
45+
a &= NIBBLE_MASK_MSB;
46+
a_msb3 = a_msb >>> 3;
47+
a = (a << 1) ^ (a_msb3 + (a_msb3 << 1));
48+
r64 ^= a & -b32_2_1;
49+
50+
a_msb = a & MASK_MSB;
51+
a &= NIBBLE_MASK_MSB;
52+
a_msb3 = a_msb >>> 3;
53+
a = (a << 1) ^ (a_msb3 + (a_msb3 << 1));
54+
acc[accOffset++] ^= r64 ^ (a & -b32_3_1);
55+
}
56+
}
57+
58+
59+
/**
60+
* Performs the multiplication and accumulation of a block of an upper‐triangular matrix
61+
* times a second matrix.
62+
*
63+
* @param mVecLimbs number of limbs per m-vector.
64+
* @param bsMat the “basis” matrix (as a flat long[] array); each entry occupies mVecLimbs elements.
65+
* @param mat the second matrix (as a flat byte[] array) stored row‐major,
66+
* with dimensions (bsMatCols x matCols).
67+
* @param acc the accumulator (as a flat long[] array) with dimensions (bsMatRows x matCols);
68+
* each “entry” is an m‐vector (length mVecLimbs).
69+
* @param bsMatRows number of rows in the bsMat (the “triangular” matrix’s row count).
70+
* @param matCols number of columns in the matrix “mat.”
71+
*/
72+
static void mulAddMUpperTriangularMatXMat(int mVecLimbs, long[] bsMat, byte[] mat, long[] acc, int accOff,
73+
int bsMatRows, int matCols)
74+
{
75+
int bsMatEntriesUsed = 0;
76+
int matColsmVecLimbs = matCols * mVecLimbs;
77+
for (int r = 0, rmatCols = 0, rmatColsmVecLimbs = 0; r < bsMatRows; r++, rmatCols += matCols, rmatColsmVecLimbs += matColsmVecLimbs)
78+
{
79+
// For each row r, the inner loop goes from column triangular*r to bsMatCols-1.
80+
for (int c = r, cmatCols = rmatCols; c < bsMatRows; c++, cmatCols += matCols)
81+
{
82+
for (int k = 0, kmVecLimbs = 0; k < matCols; k++, kmVecLimbs += mVecLimbs)
83+
{
84+
// For acc: add into the m-vector at row r, column k.
85+
mVecMulAdd(mVecLimbs, bsMat, bsMatEntriesUsed, mat[cmatCols + k], acc, accOff + rmatColsmVecLimbs + kmVecLimbs);
86+
}
87+
bsMatEntriesUsed += mVecLimbs;
88+
}
89+
}
90+
}
91+
92+
/**
93+
* Multiplies the transpose of a single matrix with m matrices and adds the result into acc.
94+
*
95+
* @param mVecLimbs number of limbs per m-vector.
96+
* @param mat the matrix to be transposed (as a flat byte[] array), dimensions: (matRows x matCols).
97+
* @param bsMat the m-matrix (as a flat long[] array), with each entry of length mVecLimbs.
98+
* Its logical dimensions: (matRows x bsMatCols).
99+
* @param acc the accumulator (as a flat long[] array) with dimensions (matCols x bsMatCols);
100+
* each entry is an m-vector.
101+
* @param matRows number of rows in the matrix “mat.”
102+
* @param matCols number of columns in “mat.”
103+
*/
104+
static void mulAddMatTransXMMat(int mVecLimbs, byte[] mat, long[] bsMat, int bsMatOff, long[] acc,
105+
int matRows, int matCols)
106+
{
107+
int multiply = matCols * mVecLimbs;
108+
for (int r = 0, rmultiply = 0; r < matCols; r++, rmultiply += multiply)
109+
{
110+
for (int c = 0, cmatCols = 0, cmultiply = 0; c < matRows; c++, cmatCols += matCols, cmultiply += multiply)
111+
{
112+
byte matVal = mat[cmatCols + r];
113+
for (int k = 0, kmVecLimbs = 0; k < matCols; k++, kmVecLimbs += mVecLimbs)
114+
{
115+
mVecMulAdd(mVecLimbs, bsMat, bsMatOff + cmultiply + kmVecLimbs, matVal, acc, rmultiply + kmVecLimbs);
116+
}
117+
}
118+
}
119+
}
120+
121+
/**
122+
* Multiplies a matrix (given as a byte array) with a bit‐sliced matrix (given as a long array)
123+
* and accumulates the result into the acc array.
124+
*
125+
* <p>
126+
* The operation iterates over the rows and columns of the matrix. For each element in the matrix,
127+
* it multiplies a corresponding vector (from bsMat) by the scalar value (from mat) and adds the
128+
* result to the accumulator vector in acc.
129+
* </p>
130+
*
131+
* @param mVecLimbs the number of limbs (elements) in each vector
132+
* @param mat the matrix as a byte array with dimensions [matRows x matCols]
133+
* @param bsMat the bit‐sliced matrix as a long array
134+
* @param acc the accumulator array (long[]) where results are accumulated
135+
* @param matRows the number of rows in the matrix
136+
* @param matCols the number of columns in the matrix
137+
*/
138+
static void mulAddMatXMMat(int mVecLimbs, byte[] mat, long[] bsMat, long[] acc, int matRows, int matCols)
139+
{
140+
int multiply = mVecLimbs * matRows;
141+
for (int r = 0, rmatCols = 0, rmultiply = 0; r < matRows; r++, rmatCols += matCols, rmultiply += multiply)
142+
{
143+
for (int c = 0, cmultiply = 0; c < matCols; c++, cmultiply += multiply)
144+
{
145+
// Retrieve the scalar from the matrix for row r and column c.
146+
byte matVal = mat[rmatCols + c];
147+
for (int k = 0, kmVecLimbs = 0; k < matRows; k++, kmVecLimbs += mVecLimbs)
148+
{
149+
mVecMulAdd(mVecLimbs, bsMat, cmultiply + kmVecLimbs, matVal, acc, rmultiply + kmVecLimbs);
150+
}
151+
}
152+
}
153+
}
154+
155+
static void mulAddMatXMMat(int mVecLimbs, byte[] mat, long[] bsMat, int bsMatOff, long[] acc,
156+
int matRows, int matCols, int bsMatCols)
157+
{
158+
int multiply = mVecLimbs * bsMatCols;
159+
for (int r = 0, rmultiply = 0, rmatCols = 0; r < matRows; r++, rmultiply += multiply, rmatCols += matCols)
160+
{
161+
for (int c = 0, cmultiply = 0; c < matCols; c++, cmultiply += multiply)
162+
{
163+
// Retrieve the scalar from the matrix for row r and column c.
164+
byte matVal = mat[rmatCols + c];
165+
for (int k = 0, kmVecLimbs = 0; k < bsMatCols; k++, kmVecLimbs += mVecLimbs)
166+
{
167+
mVecMulAdd(mVecLimbs, bsMat, cmultiply + kmVecLimbs + bsMatOff, matVal, acc, rmultiply + kmVecLimbs);
168+
}
169+
}
170+
}
171+
}
172+
173+
/**
174+
* Multiplies m (possibly upper triangular) matrices with the transpose of a single matrix
175+
* and adds the result to the accumulator.
176+
*
177+
* <p>
178+
* For each row {@code r} in the bit‑sliced matrix and for each column {@code c} (starting from
179+
* {@code triangular * r}) in the bit‑sliced matrix, this method iterates over all rows {@code k}
180+
* of the single matrix, and for each element, it multiplies the vector (from {@code bsMat})
181+
* by the scalar (from {@code mat}) and adds the result to the corresponding vector in {@code acc}.
182+
* </p>
183+
*
184+
* @param mVecLimbs the number of limbs (elements) in each vector.
185+
* @param bsMat the bit‑sliced matrix stored as a long array.
186+
* @param mat the matrix stored as a byte array.
187+
* @param acc the accumulator array where the results are added.
188+
* @param bsMatRows the number of rows in the bit‑sliced matrix.
189+
* @param matRows the number of rows in the matrix.
190+
*/
191+
static void mulAddMUpperTriangularMatXMatTrans(int mVecLimbs, long[] bsMat, byte[] mat, long[] acc, int bsMatRows, int matRows)
192+
{
193+
int bsMatEntriesUsed = 0;
194+
int multiply = mVecLimbs * matRows;
195+
for (int r = 0, rmultiply = 0; r < bsMatRows; r++, rmultiply += multiply)
196+
{
197+
// For upper triangular, start c at triangular * r; otherwise, triangular is zero.
198+
for (int c = r; c < bsMatRows; c++)
199+
{
200+
for (int k = 0, kbsMatRows = 0, kmVecLimbs = 0; k < matRows; k++, kbsMatRows += bsMatRows, kmVecLimbs += mVecLimbs)
201+
{
202+
mVecMulAdd(mVecLimbs, bsMat, bsMatEntriesUsed, mat[kbsMatRows + c], acc, rmultiply + kmVecLimbs);
203+
}
204+
bsMatEntriesUsed += mVecLimbs;
205+
}
206+
}
207+
}
208+
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+
241+
/**
242+
* Performs a GF(16) carryless multiplication of a nibble (lower 4 bits of a)
243+
* with a 64-bit word b, then reduces modulo the polynomial x⁴ + x + 1 on each byte.
244+
*
245+
* @param a a GF(16) element (only the low 4 bits are used)
246+
* @param b a 64-bit word representing 16 GF(16) elements (packed 4 bits per element)
247+
* @return the reduced 64-bit word after multiplication
248+
*/
249+
static long mulFx8(byte a, long b)
250+
{
251+
// Convert 'a' to an unsigned int so that bit operations work as expected.
252+
int aa = a & 0xFF;
253+
// Carryless multiplication: for each bit in 'aa' (considering only the lower 4 bits),
254+
// if that bit is set, multiply 'b' (by 1, 2, 4, or 8) and XOR the result.
255+
long p = (-(aa & 1) & b) ^ (-((aa >> 1) & 1) & (b << 1)) ^ (-((aa >> 2) & 1) & (b << 2)) ^ (-((aa >> 3) & 1) & (b << 3));
256+
257+
// Reduction mod (x^4 + x + 1): process each byte in parallel.
258+
long topP = p & 0xf0f0f0f0f0f0f0f0L;
259+
return (p ^ (topP >>> 4) ^ (topP >>> 3)) & 0x0f0f0f0f0f0f0f0fL;
260+
}
261+
262+
static void matMul(byte[] a, byte[] b, int bOff, byte[] c, int colrowAB, int rowA)
263+
{
264+
for (int i = 0, aRowStart = 0, cOff = 0; i < rowA; i++)
265+
{
266+
byte result = 0;
267+
for (int k = 0; k < colrowAB; k++)
268+
{
269+
result ^= mulF(a[aRowStart++], b[bOff + k]);
270+
}
271+
c[cOff++] = result;
272+
}
273+
}
274+
}
275+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.bouncycastle.pqc.crypto.mayo;
2+
3+
import java.security.SecureRandom;
4+
5+
import org.bouncycastle.crypto.KeyGenerationParameters;
6+
7+
public class MayoKeyGenerationParameters
8+
extends KeyGenerationParameters
9+
{
10+
private final MayoParameters params;
11+
12+
public MayoKeyGenerationParameters(
13+
SecureRandom random,
14+
MayoParameters mayoParameters)
15+
{
16+
super(random, 256);
17+
this.params = mayoParameters;
18+
}
19+
20+
public MayoParameters getParameters()
21+
{
22+
return params;
23+
}
24+
}

0 commit comments

Comments
 (0)