Skip to content

Commit 8a190b4

Browse files
author
gefeili
committed
Merge branch 'main' into 1857-1-javadoc
2 parents 4a7757e + d95afbf commit 8a190b4

35 files changed

+577
-131
lines changed

core/src/main/java/org/bouncycastle/pqc/crypto/lms/HSSPrivateKeyParameters.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ else if (src instanceof byte[])
129129
{
130130
// old style single LMS key.
131131
LMSPrivateKeyParameters lmsKey = LMSPrivateKeyParameters.getInstance(src);
132-
return new HSSPrivateKeyParameters(lmsKey, lmsKey.getIndex(), lmsKey.getIndex() + lmsKey.getUsagesRemaining());
132+
return new HSSPrivateKeyParameters(lmsKey, lmsKey.getIndex(), lmsKey.getIndexLimit());
133133
}
134134
}
135135
finally
@@ -212,7 +212,7 @@ long getIndexLimit()
212212

213213
public long getUsagesRemaining()
214214
{
215-
return indexLimit - index;
215+
return getIndexLimit() - getIndex();
216216
}
217217

218218
LMSPrivateKeyParameters getRootKey()
@@ -233,32 +233,33 @@ public HSSPrivateKeyParameters extractKeyShard(int usageCount)
233233
{
234234
synchronized (this)
235235
{
236-
237-
if (getUsagesRemaining() < usageCount)
236+
if (usageCount < 0)
237+
{
238+
throw new IllegalArgumentException("usageCount cannot be negative");
239+
}
240+
if (usageCount > indexLimit - index)
238241
{
239242
throw new IllegalArgumentException("usageCount exceeds usages remaining in current leaf");
240243
}
241244

242-
long maxIndexForShard = index + usageCount;
243-
long shardStartIndex = index;
245+
long shardIndex = index;
246+
long shardIndexLimit = index + usageCount;
244247

245-
//
246-
// Move this keys index along
247-
//
248-
index += usageCount;
248+
// Move this key's index along
249+
index = shardIndexLimit;
249250

250251
List<LMSPrivateKeyParameters> keys = new ArrayList<LMSPrivateKeyParameters>(this.getKeys());
251252
List<LMSSignature> sig = new ArrayList<LMSSignature>(this.getSig());
252253

253-
HSSPrivateKeyParameters shard = makeCopy(new HSSPrivateKeyParameters(l, keys, sig, shardStartIndex, maxIndexForShard, true));
254+
HSSPrivateKeyParameters shard = makeCopy(
255+
new HSSPrivateKeyParameters(l, keys, sig, shardIndex, shardIndexLimit, true));
254256

255257
resetKeyToIndex();
256258

257259
return shard;
258260
}
259261
}
260262

261-
262263
synchronized List<LMSPrivateKeyParameters> getKeys()
263264
{
264265
return keys;

core/src/main/java/org/bouncycastle/pqc/crypto/lms/LMSPrivateKeyParameters.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,22 @@ public LMSPrivateKeyParameters extractKeyShard(int usageCount)
253253
{
254254
synchronized (this)
255255
{
256-
if (q + usageCount >= maxQ)
256+
if (usageCount < 0)
257+
{
258+
throw new IllegalArgumentException("usageCount cannot be negative");
259+
}
260+
if (usageCount > maxQ - q)
257261
{
258262
throw new IllegalArgumentException("usageCount exceeds usages remaining");
259263
}
260-
LMSPrivateKeyParameters keyParameters = new LMSPrivateKeyParameters(this, q, q + usageCount);
261-
q += usageCount;
262264

263-
return keyParameters;
265+
int shardIndex = q;
266+
int shardIndexLimit = q + usageCount;
267+
268+
// Move this key's index along
269+
q = shardIndexLimit;
270+
271+
return new LMSPrivateKeyParameters(this, shardIndex, shardIndexLimit);
264272
}
265273
}
266274

@@ -284,9 +292,15 @@ public byte[] getMasterSecret()
284292
return Arrays.clone(masterSecret);
285293
}
286294

295+
public int getIndexLimit()
296+
{
297+
return maxQ;
298+
}
299+
300+
// TODO Only needs 'int'
287301
public long getUsagesRemaining()
288302
{
289-
return maxQ - getIndex();
303+
return getIndexLimit() - getIndex();
290304
}
291305

292306
public LMSPublicKeyParameters getPublicKey()

core/src/main/java/org/bouncycastle/pqc/crypto/lms/LMSSigner.java

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,41 @@ public void init(boolean forSigning, CipherParameters param)
1515
{
1616
if (forSigning)
1717
{
18-
privKey = (LMSPrivateKeyParameters)param;
18+
if (param instanceof HSSPrivateKeyParameters)
19+
{
20+
HSSPrivateKeyParameters hssPriv = (HSSPrivateKeyParameters)param;
21+
if (hssPriv.getL() == 1)
22+
{
23+
privKey = hssPriv.getRootKey();
24+
}
25+
else
26+
{
27+
throw new IllegalArgumentException("only a single level HSS key can be used with LMS");
28+
}
29+
}
30+
else
31+
{
32+
privKey = (LMSPrivateKeyParameters)param;
33+
}
1934
}
2035
else
2136
{
22-
pubKey = (LMSPublicKeyParameters)param;
37+
if (param instanceof HSSPublicKeyParameters)
38+
{
39+
HSSPublicKeyParameters hssPub = (HSSPublicKeyParameters)param;
40+
if (hssPub.getL() == 1)
41+
{
42+
pubKey = hssPub.getLMSPublicKey();
43+
}
44+
else
45+
{
46+
throw new IllegalArgumentException("only a single level HSS key can be used with LMS");
47+
}
48+
}
49+
else
50+
{
51+
pubKey = (LMSPublicKeyParameters)param;
52+
}
2353
}
2454
}
2555

core/src/main/java/org/bouncycastle/pqc/crypto/lms/LMSigParameters.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public ASN1ObjectIdentifier getDigestOID()
9494
return digestOid;
9595
}
9696

97-
static LMSigParameters getParametersForType(int type)
97+
public static LMSigParameters getParametersForType(int type)
9898
{
9999
return paramBuilders.get(type);
100100
}

core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/MLKEMEngine.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,16 @@ public void init(SecureRandom random)
187187
this.random = random;
188188
}
189189

190+
public byte[][] generateKemKeyPair()
191+
{
192+
byte[] d = new byte[KyberSymBytes];
193+
byte[] z = new byte[KyberSymBytes];
194+
random.nextBytes(d);
195+
random.nextBytes(z);
196+
197+
return generateKemKeyPairInternal(d, z);
198+
}
199+
190200
//Internal functions are deterministic. No randomness is sampled inside them
191201
public byte[][] generateKemKeyPairInternal(byte[] d, byte[] z)
192202
{
@@ -202,7 +212,15 @@ public byte[][] generateKemKeyPairInternal(byte[] d, byte[] z)
202212

203213
byte[] outputPublicKey = new byte[KyberIndCpaPublicKeyBytes];
204214
System.arraycopy(indCpaKeyPair[0], 0, outputPublicKey, 0, KyberIndCpaPublicKeyBytes);
205-
return new byte[][]{ Arrays.copyOfRange(outputPublicKey, 0, outputPublicKey.length - 32), Arrays.copyOfRange(outputPublicKey, outputPublicKey.length - 32, outputPublicKey.length), s, hashedPublicKey, z, Arrays.concatenate(d, z)};
215+
return new byte[][]
216+
{
217+
Arrays.copyOfRange(outputPublicKey, 0, outputPublicKey.length - 32),
218+
Arrays.copyOfRange(outputPublicKey, outputPublicKey.length - 32, outputPublicKey.length),
219+
s,
220+
hashedPublicKey,
221+
z,
222+
Arrays.concatenate(d, z)
223+
};
206224
}
207225

208226
public byte[][] kemEncryptInternal(byte[] publicKeyInput, byte[] randBytes)
@@ -263,16 +281,6 @@ public byte[] kemDecryptInternal(byte[] secretKey, byte[] cipherText)
263281
return Arrays.copyOfRange(kr, 0, sessionKeyLength);
264282
}
265283

266-
public byte[][] generateKemKeyPair()
267-
{
268-
byte[] d = new byte[KyberSymBytes];
269-
byte[] z = new byte[KyberSymBytes];
270-
random.nextBytes(d);
271-
random.nextBytes(z);
272-
273-
return generateKemKeyPairInternal(d, z);
274-
}
275-
276284
public byte[][] kemEncrypt(byte[] publicKeyInput, byte[] randBytes)
277285
{
278286
//TODO: do input validation elsewhere?

core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/MLKEMIndCpa.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package org.bouncycastle.pqc.crypto.mlkem;
22

3-
import org.bouncycastle.crypto.digests.SHAKEDigest;
43
import org.bouncycastle.util.Arrays;
54

65
class MLKEMIndCpa
76
{
87
private MLKEMEngine engine;
98
private int kyberK;
10-
private int eta1;
119
private int indCpaPublicKeyBytes;
1210
private int polyVecBytes;
1311
private int indCpaBytes;
@@ -20,7 +18,6 @@ public MLKEMIndCpa(MLKEMEngine engine)
2018
{
2119
this.engine = engine;
2220
this.kyberK = engine.getKyberK();
23-
this.eta1 = engine.getKyberEta1();
2421
this.indCpaPublicKeyBytes = engine.getKyberPublicKeyBytes();
2522
this.polyVecBytes = engine.getKyberPolyVecBytes();
2623
this.indCpaBytes = engine.getKyberIndCpaBytes();
@@ -54,9 +51,7 @@ byte[][] generateKeyPair(byte[] d)
5451
// (p, sigma) <- G(d || k)
5552

5653
byte[] buf = new byte[64];
57-
byte[] k = new byte[1];
58-
k[0] = (byte)kyberK;
59-
symmetric.hash_g(buf, Arrays.concatenate(d, k));
54+
symmetric.hash_g(buf, Arrays.append(d, (byte)kyberK));
6055

6156
byte[] publicSeed = new byte[32]; // p in docs
6257
byte[] noiseSeed = new byte[32]; // sigma in docs
@@ -320,7 +315,6 @@ public void unpackSecretKey(PolyVec secretKeyPolyVec, byte[] secretKey)
320315
public void generateMatrix(PolyVec[] aMatrix, byte[] seed, boolean transposed)
321316
{
322317
int i, j, k, ctr, off;
323-
SHAKEDigest kyberXOF;
324318
byte[] buf = new byte[KyberGenerateMatrixNBlocks * symmetric.xofBlockBytes + 2];
325319
for (i = 0; i < kyberK; i++)
326320
{
@@ -383,7 +377,6 @@ private static int rejectionSampling(Poly outputBuffer, int coeffOff, int len, b
383377

384378
public byte[] decrypt(byte[] secretKey, byte[] cipherText)
385379
{
386-
int i;
387380
byte[] outputMessage = new byte[MLKEMEngine.getKyberIndCpaMsgBytes()];
388381

389382
PolyVec bp = new PolyVec(engine), secretKeyPolyVec = new PolyVec(engine);

core/src/main/java/org/bouncycastle/pqc/crypto/mlkem/MLKEMKeyPairGenerator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,8 @@ public AsymmetricCipherKeyPair internalGenerateKeyPair(byte[] d, byte[] z)
5050
byte[][] keyPair = mlkemParams.getEngine().generateKemKeyPairInternal(d, z);
5151

5252
MLKEMPublicKeyParameters pubKey = new MLKEMPublicKeyParameters(mlkemParams, keyPair[0], keyPair[1]);
53-
MLKEMPrivateKeyParameters privKey = new MLKEMPrivateKeyParameters(mlkemParams, keyPair[2], keyPair[3], keyPair[4], keyPair[0], keyPair[1]);
53+
MLKEMPrivateKeyParameters privKey = new MLKEMPrivateKeyParameters(mlkemParams, keyPair[2], keyPair[3], keyPair[4], keyPair[0], keyPair[1], keyPair[5]);
5454

5555
return new AsymmetricCipherKeyPair(pubKey, privKey);
5656
}
57-
5857
}

core/src/main/java/org/bouncycastle/pqc/crypto/ntru/NTRUKEMExtractor.java

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
public class NTRUKEMExtractor
1212
implements EncapsulatedSecretExtractor
1313
{
14-
private final NTRUParameters params;
1514
private final NTRUPrivateKeyParameters ntruPrivateKey;
1615

1716
/**
@@ -22,53 +21,50 @@ public class NTRUKEMExtractor
2221
*/
2322
public NTRUKEMExtractor(NTRUPrivateKeyParameters ntruPrivateKey)
2423
{
25-
this.params = ntruPrivateKey.getParameters();
24+
if (ntruPrivateKey == null)
25+
{
26+
throw new NullPointerException("'ntruPrivateKey' cannot be null");
27+
}
28+
2629
this.ntruPrivateKey = ntruPrivateKey;
2730
}
2831

29-
30-
@Override
3132
public byte[] extractSecret(byte[] encapsulation)
3233
{
33-
// assert this.ntruPrivateKey != null;
34-
NTRUParameterSet parameterSet = this.params.parameterSet;
34+
NTRUParameterSet parameterSet = ntruPrivateKey.getParameters().getParameterSet();
35+
36+
if (encapsulation == null)
37+
{
38+
throw new NullPointerException("'encapsulation' cannot be null");
39+
}
40+
if (encapsulation.length != parameterSet.ntruCiphertextBytes())
41+
{
42+
throw new IllegalArgumentException("encapsulation");
43+
}
3544

3645
byte[] sk = this.ntruPrivateKey.privateKey;
37-
int i, fail;
38-
byte[] rm;
39-
byte[] buf = new byte[parameterSet.prfKeyBytes() + parameterSet.ntruCiphertextBytes()];
4046

4147
NTRUOWCPA owcpa = new NTRUOWCPA(parameterSet);
42-
OWCPADecryptResult owcpaResult = owcpa.decrypt(encapsulation, ntruPrivateKey.privateKey);
43-
rm = owcpaResult.rm;
44-
fail = owcpaResult.fail;
48+
OWCPADecryptResult owcpaResult = owcpa.decrypt(encapsulation, sk);
49+
byte[] rm = owcpaResult.rm;
50+
int fail = owcpaResult.fail;
4551
/* If fail = 0 then c = Enc(h, rm). There is no need to re-encapsulate. */
4652
/* See comment in owcpa_dec for details. */
4753

4854
SHA3Digest sha3256 = new SHA3Digest(256);
49-
5055
byte[] k = new byte[sha3256.getDigestSize()];
5156

5257
sha3256.update(rm, 0, rm.length);
5358
sha3256.doFinal(k, 0);
5459

5560
/* shake(secret PRF key || input ciphertext) */
56-
for (i = 0; i < parameterSet.prfKeyBytes(); i++)
57-
{
58-
buf[i] = sk[i + parameterSet.owcpaSecretKeyBytes()];
59-
}
60-
for (i = 0; i < parameterSet.ntruCiphertextBytes(); i++)
61-
{
62-
buf[parameterSet.prfKeyBytes() + i] = encapsulation[i];
63-
}
64-
sha3256.reset();
65-
sha3256.update(buf, 0, buf.length);
61+
sha3256.update(sk, parameterSet.owcpaSecretKeyBytes(), parameterSet.prfKeyBytes());
62+
sha3256.update(encapsulation, 0, encapsulation.length);
6663
sha3256.doFinal(rm, 0);
6764

6865
cmov(k, rm, (byte)fail);
6966

7067
byte[] sharedKey = Arrays.copyOfRange(k, 0, parameterSet.sharedKeyBytes());
71-
7268
Arrays.clear(k);
7369

7470
return sharedKey;
@@ -85,6 +81,6 @@ private void cmov(byte[] r, byte[] x, byte b)
8581

8682
public int getEncapsulationLength()
8783
{
88-
return params.parameterSet.ntruCiphertextBytes();
84+
return ntruPrivateKey.getParameters().getParameterSet().ntruCiphertextBytes();
8985
}
9086
}

0 commit comments

Comments
 (0)