Skip to content

Commit bf2da3c

Browse files
author
royb
committed
Added AES and Uniform variant for SABER with test vectors.
1 parent 8e37200 commit bf2da3c

File tree

18 files changed

+6525
-85
lines changed

18 files changed

+6525
-85
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,15 @@ public interface BCObjectIdentifiers
308308
ASN1ObjectIdentifier lightsaberkem256r3 = pqc_kem_saber.branch("7");
309309
ASN1ObjectIdentifier saberkem256r3 = pqc_kem_saber.branch("8");
310310
ASN1ObjectIdentifier firesaberkem256r3 = pqc_kem_saber.branch("9");
311+
ASN1ObjectIdentifier ulightsaberkemr3 = pqc_kem_saber.branch("10");
312+
ASN1ObjectIdentifier usaberkemr3 = pqc_kem_saber.branch("11");
313+
ASN1ObjectIdentifier ufiresaberkemr3 = pqc_kem_saber.branch("12");
314+
ASN1ObjectIdentifier lightsaberkem90sr3 = pqc_kem_saber.branch("13");
315+
ASN1ObjectIdentifier saberkem90sr3 = pqc_kem_saber.branch("14");
316+
ASN1ObjectIdentifier firesaberkem90sr3 = pqc_kem_saber.branch("15");
317+
ASN1ObjectIdentifier ulightsaberkem90sr3 = pqc_kem_saber.branch("16");
318+
ASN1ObjectIdentifier usaberkem90sr3 = pqc_kem_saber.branch("17");
319+
ASN1ObjectIdentifier ufiresaberkem90sr3 = pqc_kem_saber.branch("18");
311320

312321
/**
313322
* SIKE

core/src/main/java/org/bouncycastle/pqc/crypto/saber/Poly.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ public void GenMatrix(short[][][] A, byte[] seed)
3535
byte[] buf = new byte[SABER_L * engine.getSABER_POLYVECBYTES()];
3636
int i;
3737

38-
Xof digest = new SHAKEDigest(128);
39-
digest.update(seed, 0, engine.getSABER_SEEDBYTES());
40-
digest.doFinal(buf, 0, buf.length);
38+
engine.symmetric.prf(buf, seed, engine.getSABER_SEEDBYTES(), buf.length);
4139

4240
for (i = 0; i < SABER_L; i++)
4341
{
@@ -49,13 +47,25 @@ public void GenSecret(short[][] s, byte[] seed)
4947
{
5048
byte[] buf = new byte[SABER_L * engine.getSABER_POLYCOINBYTES()];
5149
int i;
52-
Xof digest = new SHAKEDigest(128);
53-
digest.update(seed, 0, engine.getSABER_NOISE_SEEDBYTES());
54-
digest.doFinal(buf, 0, buf.length);
50+
51+
engine.symmetric.prf(buf, seed, engine.getSABER_NOISE_SEEDBYTES(), buf.length);
5552

5653
for (i = 0; i < SABER_L; i++)
5754
{
58-
cbd(s[i], buf, i * engine.getSABER_POLYCOINBYTES());
55+
if(!engine.usingEffectiveMasking)
56+
{
57+
cbd(s[i], buf, i * engine.getSABER_POLYCOINBYTES());
58+
}
59+
else
60+
{
61+
for(int j = 0; j<SABER_N/4; j++)
62+
{
63+
s[i][4*j] = (short) ((((buf[j + i * engine.getSABER_POLYCOINBYTES()]) & 0x03) ^ 2) - 2);
64+
s[i][4*j+1] = (short) ((((buf[j + i * engine.getSABER_POLYCOINBYTES()] >>> 2) & 0x03) ^ 2) - 2);
65+
s[i][4*j+2] = (short) ((((buf[j + i * engine.getSABER_POLYCOINBYTES()] >>> 4) & 0x03) ^ 2) - 2);
66+
s[i][4*j+3] = (short) ((((buf[j + i * engine.getSABER_POLYCOINBYTES()] >>> 6) & 0x03) ^ 2) - 2);
67+
}
68+
}
5969
}
6070

6171
}

core/src/main/java/org/bouncycastle/pqc/crypto/saber/SABEREngine.java

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
class SABEREngine
1111
{
1212
// constant parameters
13-
public static final int SABER_EQ = 13;
1413
public static final int SABER_EP = 10;
1514
public static final int SABER_N = 256;
1615

@@ -26,6 +25,8 @@ class SABEREngine
2625
private final int SABER_ET;
2726

2827
private final int SABER_POLYCOINBYTES;
28+
private final int SABER_EQ;
29+
2930
private final int SABER_POLYBYTES;
3031
private final int SABER_POLYVECBYTES;
3132
private final int SABER_POLYCOMPRESSEDBYTES;
@@ -106,7 +107,6 @@ public Utils getUtils()
106107

107108
public int getSessionKeySize()
108109
{
109-
// return SABER_KEYBYTES;
110110
return defaultKeySize / 8;
111111
}
112112
public int getCipherTextSize()
@@ -122,9 +122,16 @@ public int getPrivateKeySize()
122122
return SABER_SECRETKEYBYTES;
123123
}
124124

125-
public SABEREngine(int l, int defaultKeySize)
125+
private final boolean usingAES;
126+
protected final boolean usingEffectiveMasking;
127+
128+
protected final Symmetric symmetric;
129+
130+
public SABEREngine(int l, int defaultKeySize, boolean usingAES, boolean usingEffectiveMasking)
126131
{
127132
this.defaultKeySize = defaultKeySize;
133+
this.usingAES = usingAES;
134+
this.usingEffectiveMasking = usingEffectiveMasking;
128135

129136
this.SABER_L = l;
130137
if (l == 2)
@@ -142,7 +149,27 @@ else if(l == 3)
142149
this.SABER_MU = 6;
143150
this.SABER_ET = 6;
144151
}
145-
this.SABER_POLYCOINBYTES = (SABER_MU * SABER_N / 8);
152+
153+
if(usingAES)
154+
{
155+
symmetric = new Symmetric.AesSymmetric();
156+
}
157+
else
158+
{
159+
symmetric = new Symmetric.ShakeSymmetric();
160+
}
161+
162+
if(usingEffectiveMasking)
163+
{
164+
this.SABER_EQ = 12;
165+
this.SABER_POLYCOINBYTES = (2 * SABER_N / 8);
166+
}
167+
else
168+
{
169+
this.SABER_EQ = 13;
170+
this.SABER_POLYCOINBYTES = (SABER_MU * SABER_N / 8);
171+
}
172+
146173
this.SABER_POLYBYTES = (SABER_EQ * SABER_N / 8);
147174
this.SABER_POLYVECBYTES = (SABER_L * SABER_POLYBYTES);
148175
this.SABER_POLYCOMPRESSEDBYTES = (SABER_EP * SABER_N / 8);
@@ -172,9 +199,7 @@ private void indcpa_kem_keypair(byte[] pk, byte[] sk, SecureRandom random)
172199

173200
random.nextBytes(seed_A);
174201

175-
Xof digest = new SHAKEDigest(128);
176-
digest.update(seed_A, 0, SABER_SEEDBYTES);
177-
digest.doFinal(seed_A, 0, SABER_SEEDBYTES);
202+
symmetric.prf(seed_A, seed_A, SABER_SEEDBYTES, SABER_SEEDBYTES);
178203

179204
random.nextBytes(seed_s);
180205

@@ -203,12 +228,12 @@ public int crypto_kem_keypair(byte[] pk, byte[]sk, SecureRandom random)
203228
int i;
204229
indcpa_kem_keypair(pk, sk, random); // sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk
205230
for (i = 0; i < SABER_INDCPA_PUBLICKEYBYTES; i++)
231+
{
206232
sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i]; // sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk
233+
}
207234

208235
// Then hash(pk) is appended.
209-
SHA3Digest digest = new SHA3Digest(256);
210-
digest.update(pk, 0, SABER_INDCPA_PUBLICKEYBYTES);
211-
digest.doFinal(sk, SABER_SECRETKEYBYTES - 64);
236+
symmetric.hash_h(sk, pk, SABER_SECRETKEYBYTES - 64);
212237

213238
// Remaining part of sk contains a pseudo-random number.
214239
byte[] nonce = new byte[SABER_KEYBYTES];
@@ -265,40 +290,30 @@ public int crypto_kem_enc(byte[] c, byte[] k, byte[] pk, SecureRandom random)
265290
byte[] nonce = new byte[32];
266291
random.nextBytes(nonce);
267292

268-
SHA3Digest digest_256 = new SHA3Digest(256);
269-
SHA3Digest digest_512 = new SHA3Digest(512);
270-
271293
// BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output
272-
digest_256.update(nonce, 0, 32);
273-
digest_256.doFinal(nonce, 0);
294+
symmetric.hash_h(nonce, nonce, 0);
274295
System.arraycopy(nonce, 0, buf, 0, 32);
275296

276297
// BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM
277-
digest_256.update(pk, 0, SABER_INDCPA_PUBLICKEYBYTES);
278-
digest_256.doFinal(buf, 32);
298+
symmetric.hash_h(buf, pk, 32);
279299

280300
// kr[0:63] <-- Hash(buf[0:63]);
281-
digest_512.update(buf, 0, 64);
282-
digest_512.doFinal(kr, 0);
301+
symmetric.hash_g(kr, buf);
283302

284303
// K^ <-- kr[0:31]
285304
// noiseseed (r) <-- kr[32:63];
286305
// buf[0:31] contains message; kr[32:63] contains randomness r;
287306
indcpa_kem_enc(buf, Arrays.copyOfRange(kr, 32, kr.length), pk, c);
288307

289-
digest_256.update(c, 0, SABER_BYTES_CCA_DEC);
290-
digest_256.doFinal(kr, 32);
308+
symmetric.hash_h(kr, c, 32);
291309

292310
// hash concatenation of pre-k and h(c) to k
293311
//todo support 128 and 192 bit keys
294312
byte[] temp_k = new byte[32];
295-
digest_256.update(kr, 0, 64);
296-
digest_256.doFinal(temp_k, 0);
297313

314+
symmetric.hash_h(temp_k, kr, 0);
298315
System.arraycopy(temp_k,0, k, 0, defaultKeySize/8);
299316

300-
301-
302317
return 0;
303318
}
304319

@@ -335,31 +350,27 @@ public int crypto_kem_dec(byte[] k, byte[] c, byte[] sk)
335350

336351
// Multitarget countermeasure for coins + contributory KEM
337352
for (i = 0; i < 32; i++) // Save hash by storing h(pk) in sk
353+
{
338354
buf[32 + i] = sk[SABER_SECRETKEYBYTES - 64 + i];
355+
}
339356

340-
341-
SHA3Digest digest_256 = new SHA3Digest(256);
342-
SHA3Digest digest_512 = new SHA3Digest(512);
343-
344-
digest_512.update(buf, 0, 64);
345-
digest_512.doFinal(kr, 0);
357+
symmetric.hash_g(kr, buf);
346358

347359
indcpa_kem_enc(buf, Arrays.copyOfRange(kr, 32, kr.length), pk, cmp);
348360

349361
fail = verify(c, cmp, SABER_BYTES_CCA_DEC);
350362

351363
// overwrite coins in kr with h(c)
352364

353-
digest_256.update(c, 0, SABER_BYTES_CCA_DEC);
354-
digest_256.doFinal(kr, 32);
365+
symmetric.hash_h(kr, c, 32);
355366

356367
cmov(kr, sk, SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES, (byte) fail);
357368

358369
// hash concatenation of pre-k and h(c) to k
359370
//todo support 128 and 192 bit keys
360371
byte[] temp_k = new byte[32];
361-
digest_256.update(kr, 0, 64);
362-
digest_256.doFinal(temp_k, 0);
372+
373+
symmetric.hash_h(temp_k, kr, 0);
363374

364375
System.arraycopy(temp_k,0, k, 0, defaultKeySize/8);
365376
return 0;

core/src/main/java/org/bouncycastle/pqc/crypto/saber/SABERParameters.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,42 @@ public class SABERParameters
66
implements CipherParameters
77
{
88

9-
public static final SABERParameters lightsaberkem128r3 = new SABERParameters("lightsaberkem128r3", 2, 128);
10-
public static final SABERParameters saberkem128r3 = new SABERParameters("saberkem128r3", 3, 128);
11-
public static final SABERParameters firesaberkem128r3 = new SABERParameters("firesaberkem128r3", 4, 128);
9+
public static final SABERParameters lightsaberkem128r3 = new SABERParameters("lightsaberkem128r3", 2, 128, false, false);
10+
public static final SABERParameters saberkem128r3 = new SABERParameters("saberkem128r3", 3, 128, false, false);
11+
public static final SABERParameters firesaberkem128r3 = new SABERParameters("firesaberkem128r3", 4, 128, false, false);
1212

13-
public static final SABERParameters lightsaberkem192r3 = new SABERParameters("lightsaberkem192r3", 2, 192);
14-
public static final SABERParameters saberkem192r3 = new SABERParameters("saberkem192r3", 3, 192);
15-
public static final SABERParameters firesaberkem192r3 = new SABERParameters("firesaberkem192r3", 4, 192);
13+
public static final SABERParameters lightsaberkem192r3 = new SABERParameters("lightsaberkem192r3", 2, 192, false, false);
14+
public static final SABERParameters saberkem192r3 = new SABERParameters("saberkem192r3", 3, 192, false, false);
15+
public static final SABERParameters firesaberkem192r3 = new SABERParameters("firesaberkem192r3", 4, 192, false, false);
1616

17-
public static final SABERParameters lightsaberkem256r3 = new SABERParameters("lightsaberkem256r3", 2, 256);
18-
public static final SABERParameters saberkem256r3 = new SABERParameters("saberkem256r3", 3, 256);
19-
public static final SABERParameters firesaberkem256r3 = new SABERParameters("firesaberkem256r3", 4, 256);
17+
public static final SABERParameters lightsaberkem256r3 = new SABERParameters("lightsaberkem256r3", 2, 256, false, false);
18+
public static final SABERParameters saberkem256r3 = new SABERParameters("saberkem256r3", 3, 256, false, false);
19+
public static final SABERParameters firesaberkem256r3 = new SABERParameters("firesaberkem256r3", 4, 256, false, false);
20+
21+
22+
public static final SABERParameters lightsaberkem90sr3 = new SABERParameters("lightsaberkem90sr3", 2, 256, true, false);
23+
public static final SABERParameters saberkem90sr3 = new SABERParameters("saberkem90sr3", 3, 256, true, false);
24+
public static final SABERParameters firesaberkem90sr3 = new SABERParameters("firesaberkem90sr3", 4, 256, true, false);
25+
26+
public static final SABERParameters ulightsaberkemr3 = new SABERParameters("ulightsaberkemr3", 2, 256, false, true);
27+
public static final SABERParameters usaberkemr3 = new SABERParameters("usaberkemr3", 3, 256, false, true);
28+
public static final SABERParameters ufiresaberkemr3 = new SABERParameters("ufiresaberkemr3", 4, 256, false, true);
29+
30+
public static final SABERParameters ulightsaberkem90sr3 = new SABERParameters("ulightsaberkem90sr3", 2, 256, true, true);
31+
public static final SABERParameters usaberkem90sr3 = new SABERParameters("usaberkem90sr3", 3, 256, true, true);
32+
public static final SABERParameters ufiresaberkem90sr3 = new SABERParameters("ufiresaberkem90sr3", 4, 256, true, true);
2033

2134
private final String name;
2235
private final int l;
2336
private final int defaultKeySize;
2437
private final SABEREngine engine;
2538

26-
public SABERParameters(String name, int l, int defaultKeySize)
39+
public SABERParameters(String name, int l, int defaultKeySize, boolean usingAes, boolean usingEffectiveMasking)
2740
{
2841
this.name = name;
2942
this.l = l;
3043
this.defaultKeySize = defaultKeySize;
31-
this.engine = new SABEREngine(l, defaultKeySize);
44+
this.engine = new SABEREngine(l, defaultKeySize, usingAes, usingEffectiveMasking);
3245
}
3346

3447
public String getName()

0 commit comments

Comments
 (0)