Skip to content

Commit 392d5ea

Browse files
author
gefeili
committed
Merge branch 'main' into ascon-update
2 parents 3c400c9 + 4580acc commit 392d5ea

File tree

85 files changed

+2248
-420
lines changed

Some content is hidden

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

85 files changed

+2248
-420
lines changed

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,23 @@ public class HSSPrivateKeyParameters
2626

2727
private HSSPublicKeyParameters publicKey;
2828

29+
public HSSPrivateKeyParameters(LMSPrivateKeyParameters key, long index, long indexLimit)
30+
{
31+
super(true);
32+
33+
this.l = 1;
34+
this.keys = Collections.singletonList(key);
35+
this.sig = Collections.emptyList();
36+
this.index = index;
37+
this.indexLimit = indexLimit;
38+
this.isShard = false;
39+
40+
//
41+
// Correct Intermediate LMS values will be constructed during reset to index.
42+
//
43+
resetKeyToIndex();
44+
}
45+
2946
public HSSPrivateKeyParameters(int l, List<LMSPrivateKeyParameters> keys, List<LMSSignature> sig, long index, long indexLimit)
3047
{
3148
super(true);
@@ -104,7 +121,16 @@ else if (src instanceof byte[])
104121
try // 1.5 / 1.6 compatibility
105122
{
106123
in = new DataInputStream(new ByteArrayInputStream((byte[])src));
107-
return getInstance(in);
124+
try
125+
{
126+
return getInstance(in);
127+
}
128+
catch (Exception e)
129+
{
130+
// old style single LMS key.
131+
LMSPrivateKeyParameters lmsKey = LMSPrivateKeyParameters.getInstance(src);
132+
return new HSSPrivateKeyParameters(lmsKey, lmsKey.getIndex(), lmsKey.getIndex() + lmsKey.getUsagesRemaining());
133+
}
108134
}
109135
finally
110136
{

core/src/main/java/org/bouncycastle/pqc/crypto/mldsa/MLDSAEngine.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,53 @@ byte[][] generateKeyPairInternal(byte[] seed)
300300

301301
byte[][] sk = Packing.packSecretKey(rho, tr, key, t0, s1, s2, this);
302302

303-
return new byte[][]{ sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], encT1, seed};
303+
return new byte[][]{sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], encT1, seed};
304+
}
305+
306+
byte[] deriveT1(byte[] rho, byte[] key, byte[] tr, byte[] s1Enc, byte[] s2Enc, byte[] t0Enc)
307+
{
308+
PolyVecMatrix aMatrix = new PolyVecMatrix(this);
309+
310+
PolyVecL s1 = new PolyVecL(this), s1hat;
311+
PolyVecK s2 = new PolyVecK(this), t1 = new PolyVecK(this), t0 = new PolyVecK(this);
312+
313+
Packing.unpackSecretKey(t0, s1, s2, t0Enc, s1Enc, s2Enc, this);
314+
315+
// System.out.print("rho = ");
316+
// Helper.printByteArray(rho);
317+
318+
// System.out.println("key = ");
319+
// Helper.printByteArray(key);
320+
321+
aMatrix.expandMatrix(rho);
322+
// System.out.print(aMatrix.toString("aMatrix"));
323+
324+
s1hat = new PolyVecL(this);
325+
326+
s1.copyPolyVecL(s1hat);
327+
s1hat.polyVecNtt();
328+
329+
// System.out.println(s1hat.toString("s1hat"));
330+
331+
aMatrix.pointwiseMontgomery(t1, s1hat);
332+
// System.out.println(t1.toString("t1"));
333+
334+
t1.reduce();
335+
t1.invNttToMont();
336+
337+
t1.addPolyVecK(s2);
338+
// System.out.println(s2.toString("s2"));
339+
// System.out.println(t1.toString("t1"));
340+
t1.conditionalAddQ();
341+
t1.power2Round(t0);
342+
343+
// System.out.println(t1.toString("t1"));
344+
// System.out.println(t0.toString("t0"));
345+
346+
byte[] encT1 = Packing.packPublicKey(t1, this);
347+
// System.out.println("enc t1 = ");
348+
// Helper.printByteArray(encT1);
349+
return encT1;
304350
}
305351

306352
SHAKEDigest getShake256Digest()

core/src/main/java/org/bouncycastle/pqc/crypto/mldsa/MLDSAPrivateKeyParameters.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,16 @@ public MLDSAPrivateKeyParameters(MLDSAParameters params, byte[] encoding, MLDSAP
7474
delta = eng.getDilithiumK() * MLDSAEngine.DilithiumPolyT0PackedBytes;
7575
this.t0 = Arrays.copyOfRange(encoding, index, index + delta);
7676
index += delta;
77+
this.t1 = eng.deriveT1(rho, k, tr, s1, s2, t0);
7778

7879
if (pubKey != null)
7980
{
80-
this.t1 = pubKey.getT1();
81-
}
82-
else
83-
{
84-
this.t1 = null;
81+
if (!Arrays.constantTimeAreEqual(this.t1, pubKey.getT1()))
82+
{
83+
throw new IllegalArgumentException("passed in public key does not match private values");
84+
}
8585
}
86+
8687
this.seed = null;
8788
}
8889
}
@@ -117,6 +118,11 @@ public byte[] getSeed()
117118

118119
public MLDSAPublicKeyParameters getPublicKeyParameters()
119120
{
121+
if (this.t1 == null)
122+
{
123+
return null;
124+
}
125+
120126
return new MLDSAPublicKeyParameters(getParameters(), rho, t1);
121127
}
122128

core/src/main/java/org/bouncycastle/pqc/crypto/mldsa/MLDSAPublicKeyParameters.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,23 @@ public MLDSAPublicKeyParameters(MLDSAParameters params, byte[] encoding)
1818
super(false, params);
1919
this.rho = Arrays.copyOfRange(encoding, 0, MLDSAEngine.SeedBytes);
2020
this.t1 = Arrays.copyOfRange(encoding, MLDSAEngine.SeedBytes, encoding.length);
21+
if (t1.length == 0)
22+
{
23+
throw new IllegalArgumentException("encoding too short");
24+
}
2125
}
2226

2327
public MLDSAPublicKeyParameters(MLDSAParameters params, byte[] rho, byte[] t1)
2428
{
2529
super(false, params);
30+
if (rho == null)
31+
{
32+
throw new NullPointerException("rho cannot be null");
33+
}
34+
if (t1 == null)
35+
{
36+
throw new NullPointerException("t1 cannot be null");
37+
}
2638
this.rho = Arrays.clone(rho);
2739
this.t1 = Arrays.clone(t1);
2840
}

core/src/main/java/org/bouncycastle/pqc/crypto/util/PrivateKeyFactory.java

Lines changed: 11 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.bouncycastle.pqc.crypto.util;
22

3-
import java.io.ByteArrayInputStream;
43
import java.io.IOException;
54
import java.io.InputStream;
65

@@ -12,7 +11,6 @@
1211
import org.bouncycastle.asn1.ASN1OctetString;
1312
import org.bouncycastle.asn1.ASN1Primitive;
1413
import org.bouncycastle.asn1.ASN1Sequence;
15-
import org.bouncycastle.asn1.BERTags;
1614
import org.bouncycastle.asn1.DEROctetString;
1715
import org.bouncycastle.asn1.bc.BCObjectIdentifiers;
1816
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
@@ -45,7 +43,6 @@
4543
import org.bouncycastle.pqc.crypto.hqc.HQCParameters;
4644
import org.bouncycastle.pqc.crypto.hqc.HQCPrivateKeyParameters;
4745
import org.bouncycastle.pqc.crypto.lms.HSSPrivateKeyParameters;
48-
import org.bouncycastle.pqc.crypto.lms.LMSPrivateKeyParameters;
4946
import org.bouncycastle.pqc.crypto.mldsa.MLDSAParameters;
5047
import org.bouncycastle.pqc.crypto.mldsa.MLDSAPrivateKeyParameters;
5148
import org.bouncycastle.pqc.crypto.mldsa.MLDSAPublicKeyParameters;
@@ -156,29 +153,17 @@ else if (algOID.equals(PQCObjectIdentifiers.newHope))
156153
}
157154
else if (algOID.equals(PKCSObjectIdentifiers.id_alg_hss_lms_hashsig))
158155
{
159-
byte[] keyEnc = ASN1OctetString.getInstance(keyInfo.parsePrivateKey()).getOctets();
156+
ASN1OctetString lmsKey = parseOctetString(keyInfo.getPrivateKey(), 64);
157+
byte[] keyEnc = lmsKey.getOctets();
160158
ASN1BitString pubKey = keyInfo.getPublicKeyData();
161159

162-
if (Pack.bigEndianToInt(keyEnc, 0) == 1)
160+
if (pubKey != null)
163161
{
164-
if (pubKey != null)
165-
{
166-
byte[] pubEnc = pubKey.getOctets();
162+
byte[] pubEnc = pubKey.getOctets();
167163

168-
return LMSPrivateKeyParameters.getInstance(Arrays.copyOfRange(keyEnc, 4, keyEnc.length), Arrays.copyOfRange(pubEnc, 4, pubEnc.length));
169-
}
170-
return LMSPrivateKeyParameters.getInstance(Arrays.copyOfRange(keyEnc, 4, keyEnc.length));
171-
}
172-
else
173-
{
174-
if (pubKey != null)
175-
{
176-
byte[] pubEnc = pubKey.getOctets();
177-
178-
return HSSPrivateKeyParameters.getInstance(Arrays.copyOfRange(keyEnc, 4, keyEnc.length), pubEnc);
179-
}
180-
return HSSPrivateKeyParameters.getInstance(Arrays.copyOfRange(keyEnc, 4, keyEnc.length));
164+
return HSSPrivateKeyParameters.getInstance(Arrays.copyOfRange(keyEnc, 4, keyEnc.length), pubEnc);
181165
}
166+
return HSSPrivateKeyParameters.getInstance(Arrays.copyOfRange(keyEnc, 4, keyEnc.length));
182167
}
183168
else if (algOID.on(BCObjectIdentifiers.sphincsPlus) || algOID.on(BCObjectIdentifiers.sphincsPlus_interop))
184169
{
@@ -466,6 +451,7 @@ else if (algOID.equals(PQCObjectIdentifiers.mcElieceCca2))
466451
* So it seems for the new PQC algorithms, there's a couple of approaches to what goes in the OCTET STRING
467452
*/
468453
private static ASN1OctetString parseOctetString(ASN1OctetString octStr, int expectedLength)
454+
throws IOException
469455
{
470456
byte[] data = octStr.getOctets();
471457
//
@@ -478,37 +464,15 @@ private static ASN1OctetString parseOctetString(ASN1OctetString octStr, int expe
478464

479465
//
480466
// possible internal OCTET STRING, possibly long form with or without the internal OCTET STRING
481-
ByteArrayInputStream bIn = new ByteArrayInputStream(data);
482-
483-
int tag = bIn.read();
484-
int len = readLen(bIn);
485-
if (tag == BERTags.OCTET_STRING)
467+
data = Utils.readOctetString(data);
468+
if (data != null)
486469
{
487-
if (len == bIn.available())
488-
{
489-
return ASN1OctetString.getInstance(data);
490-
}
470+
return new DEROctetString(data);
491471
}
492472

493473
return octStr;
494474
}
495-
496-
private static int readLen(ByteArrayInputStream bIn)
497-
{
498-
int length = bIn.read();
499-
if (length != (length & 0x7f))
500-
{
501-
int count = length & 0x7f;
502-
length = 0;
503-
while (count-- != 0)
504-
{
505-
length = (length << 8) + bIn.read();
506-
}
507-
}
508-
509-
return length;
510-
}
511-
475+
512476
private static short[] convert(byte[] octets)
513477
{
514478
short[] rv = new short[octets.length / 2];

0 commit comments

Comments
 (0)