summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-10-20 18:23:49 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-10-20 18:23:49 +0700
commit1a2ca44e3fa181180e9aa65692a55111c32353f1 (patch)
treee6af5a363b8fb35ad094dc0d5a6d7d9dde16a78d
parentAdd Inverse64 method (diff)
downloadBouncyCastle.NET-ed25519-1a2ca44e3fa181180e9aa65692a55111c32353f1.tar.xz
Fix BinaryReader usage in Pqc.Crypto.Lms
-rw-r--r--crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs35
-rw-r--r--crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs7
-rw-r--r--crypto/src/pqc/crypto/lms/HSSSignature.cs6
-rw-r--r--crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs18
-rw-r--r--crypto/src/pqc/crypto/lms/LMOtsSignature.cs22
-rw-r--r--crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs107
-rw-r--r--crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs38
-rw-r--r--crypto/src/pqc/crypto/lms/LMSSignature.cs12
-rw-r--r--crypto/src/util/io/Streams.cs7
-rw-r--r--crypto/test/src/pqc/crypto/lms/test/LmsTests.cs16
10 files changed, 104 insertions, 164 deletions
diff --git a/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs b/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs
index bcbccef1a..535654fd8 100644
--- a/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs
+++ b/crypto/src/pqc/crypto/lms/HSSPrivateKeyParameters.cs
@@ -61,7 +61,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             return pKey;
         }
 
-        public static HSSPrivateKeyParameters GetInstance(Object src)
+        public static HSSPrivateKeyParameters GetInstance(object src)
         {
             if (src is HSSPrivateKeyParameters hssPrivateKeyParameters)
             {
@@ -69,28 +69,17 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             }
             else if (src is BinaryReader binaryReader)
             {
-                byte[] data = binaryReader.ReadBytes(4);
-                Array.Reverse(data);
-                int version = BitConverter.ToInt32(data, 0);
+                int version = BinaryReaders.ReadInt32BigEndian(binaryReader);
                 if (version != 0)
-                {
-                    throw new Exception("unknown version for hss private key");
-                }
-                data = binaryReader.ReadBytes(4);
-                Array.Reverse(data);
-                int d = BitConverter.ToInt32(data, 0);
-                
-                data = binaryReader.ReadBytes(8);
-                Array.Reverse(data);
-                long index = BitConverter.ToInt64(data, 0);
-                
-                data = binaryReader.ReadBytes(8);
-                Array.Reverse(data);
-                long maxIndex = BitConverter.ToInt64(data, 0);;
-                
-                data = binaryReader.ReadBytes(1);
-                Array.Reverse(data);
-                bool limited = BitConverter.ToBoolean(data, 0);
+                    throw new Exception("unknown version for HSS private key");
+
+                int d = BinaryReaders.ReadInt32BigEndian(binaryReader);
+
+                long index = BinaryReaders.ReadInt64BigEndian(binaryReader);
+
+                long maxIndex = BinaryReaders.ReadInt64BigEndian(binaryReader);
+
+                bool limited = binaryReader.ReadBoolean();
 
                 var keys = new List<LMSPrivateKeyParameters>();
                 var signatures = new List<LMSSignature>();
@@ -133,7 +122,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
 
         public int L => l;
 
-        public  long GetIndex()
+        public long GetIndex()
         {
             lock (this)
                 return index;
diff --git a/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs b/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs
index f6641d9c1..788b00fbd 100644
--- a/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs
+++ b/crypto/src/pqc/crypto/lms/HSSPublicKeyParameters.cs
@@ -26,10 +26,9 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             }
             else if (src is BinaryReader binaryReader)
             {
-                byte[] data = binaryReader.ReadBytes(4);
-                Array.Reverse(data);
-                int L = BitConverter.ToInt32(data, 0);
-                LMSPublicKeyParameters lmsPublicKey = LMSPublicKeyParameters.GetInstance(src);// todo check endianness
+                int L = BinaryReaders.ReadInt32BigEndian(binaryReader);
+
+                LMSPublicKeyParameters lmsPublicKey = LMSPublicKeyParameters.GetInstance(src);
                 return new HSSPublicKeyParameters(L, lmsPublicKey);
             }
             else if (src is byte[] bytes)
diff --git a/crypto/src/pqc/crypto/lms/HSSSignature.cs b/crypto/src/pqc/crypto/lms/HSSSignature.cs
index 793beda66..bd4af1bb8 100644
--- a/crypto/src/pqc/crypto/lms/HSSSignature.cs
+++ b/crypto/src/pqc/crypto/lms/HSSSignature.cs
@@ -27,7 +27,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
      * @return An HSSSignature instance.
      * @throws IOException
      */
-        public static HSSSignature GetInstance(Object src, int L)
+        public static HSSSignature GetInstance(object src, int L)
         {
             if (src is HSSSignature hssSignature)
             {
@@ -35,9 +35,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             }
             else if (src is BinaryReader binaryReader)
             {
-                byte[] data = binaryReader.ReadBytes(4);
-                Array.Reverse(data);
-                int lminus = BitConverter.ToInt32(data, 0);
+                int lminus = BinaryReaders.ReadInt32BigEndian(binaryReader);
                 if (lminus != L - 1)
                     throw new Exception("nspk exceeded maxNspk");
 
diff --git a/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs b/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs
index 49c0871f5..480cb3dbd 100644
--- a/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs
+++ b/crypto/src/pqc/crypto/lms/LMOtsPublicKey.cs
@@ -32,22 +32,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             }
             else if (src is BinaryReader binaryReader)
             {
-                byte[] data = binaryReader.ReadBytes(4);
-                Array.Reverse(data);
-                int index = BitConverter.ToInt32(data, 0);
-                
+                int index = BinaryReaders.ReadInt32BigEndian(binaryReader);
                 LMOtsParameters parameter = LMOtsParameters.GetParametersByID(index);
-                byte[] I = new byte[16];
-                binaryReader.Read(I, 0, I.Length);
-                
-                Array.Reverse(data);
-                int q = BitConverter.ToInt32(data, 0);
 
-                byte[] K = new byte[parameter.N];
-                binaryReader.Read(K, 0, K.Length);
+                byte[] I = BinaryReaders.ReadBytesFully(binaryReader, 16);
 
-                return new LMOtsPublicKey(parameter, I, q, K);
+                int q = BinaryReaders.ReadInt32BigEndian(binaryReader);
+
+                byte[] K = BinaryReaders.ReadBytesFully(binaryReader, parameter.N);
 
+                return new LMOtsPublicKey(parameter, I, q, K);
             }
             else if (src is byte[] bytes)
             {
diff --git a/crypto/src/pqc/crypto/lms/LMOtsSignature.cs b/crypto/src/pqc/crypto/lms/LMOtsSignature.cs
index db4b25641..c55866661 100644
--- a/crypto/src/pqc/crypto/lms/LMOtsSignature.cs
+++ b/crypto/src/pqc/crypto/lms/LMOtsSignature.cs
@@ -13,9 +13,9 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
         private readonly byte[] m_C;
         private readonly byte[] m_y;
 
-        public LMOtsSignature(LMOtsParameters ParamType, byte[] c, byte[] y)
+        public LMOtsSignature(LMOtsParameters paramType, byte[] c, byte[] y)
         {
-            m_paramType = ParamType;
+            m_paramType = paramType;
             m_C = c;
             m_y = y;
         }
@@ -26,22 +26,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             {
                 return lmOtsSignature;
             }
-            //TODO replace inputstreams with something
-            
             else if (src is BinaryReader binaryReader)
             {
-                byte[] data = binaryReader.ReadBytes(4);
-                Array.Reverse(data);
-                int index = BitConverter.ToInt32(data, 0);
-                LMOtsParameters type = LMOtsParameters.GetParametersByID(index);
-                byte[] C = new byte[type.N];
+                int index = BinaryReaders.ReadInt32BigEndian(binaryReader);
+                LMOtsParameters parameter = LMOtsParameters.GetParametersByID(index);
 
-                binaryReader.Read(C, 0, C.Length);
-            
-                byte[] sig = new byte[type.P * type.N];
-                binaryReader.Read(sig, 0, sig.Length);
+                byte[] C = BinaryReaders.ReadBytesFully(binaryReader, parameter.N);
 
-                return new LMOtsSignature(type, C, sig);
+                byte[] sig = BinaryReaders.ReadBytesFully(binaryReader, parameter.P * parameter.N);
+
+                return new LMOtsSignature(parameter, C, sig);
             }
             else if (src is byte[] bytes)
             {
diff --git a/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs b/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs
index f83cdc5f4..ff1a9f6fd 100644
--- a/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs
+++ b/crypto/src/pqc/crypto/lms/LMSPrivateKeyParameters.cs
@@ -42,7 +42,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
         private LMSPublicKeyParameters publicKey;
 
 
-        public LMSPrivateKeyParameters(LMSigParameters lmsParameter, LMOtsParameters otsParameters, int q, byte[] I, int maxQ, byte[] masterSecret)
+        public LMSPrivateKeyParameters(LMSigParameters lmsParameter, LMOtsParameters otsParameters, int q, byte[] I,
+            int maxQ, byte[] masterSecret)
             : base(true)
         {
             this.parameters = lmsParameter;
@@ -80,83 +81,44 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             return pKey;
         }
 
-        public static LMSPrivateKeyParameters GetInstance(Object src)
+        public static LMSPrivateKeyParameters GetInstance(object src)
         {
-            if (src is LMSPrivateKeyParameters)
+            if (src is LMSPrivateKeyParameters lmsPrivateKeyParameters)
             {
-                return (LMSPrivateKeyParameters)src;
+                return lmsPrivateKeyParameters;
             }
-            //TODO
-            else if (src is BinaryReader)
+            else if (src is BinaryReader binaryReader)
             {
-                BinaryReader dIn = (BinaryReader)src;
-            
-                /*
-                .u32str(0) // version
-                .u32str(parameters.getType()) // type
-                .u32str(otsParameters.getType()) // ots type
-                .bytes(I) // I at 16 bytes
-                .u32str(q) // q
-                .u32str(maxQ) // maximum q
-                .u32str(masterSecret.length) // length of master secret.
-                .bytes(masterSecret) // the master secret
-                .build();
-                 */
-            
-            
-                if (dIn.ReadInt32() != 0) // todo check endienness
-                {
+                int version = BinaryReaders.ReadInt32BigEndian(binaryReader);
+                if (version != 0)
                     throw new Exception("expected version 0 lms private key");
-                }
-                
-                // todo check endienness
-                byte[] data = ((BinaryReader) src).ReadBytes(4);
-                Array.Reverse(data);
-                int paramType = BitConverter.ToInt32(data, 0);
-                LMSigParameters parameter = LMSigParameters.GetParametersByID(paramType);
-
-                data = ((BinaryReader) src).ReadBytes(4);
-                Array.Reverse(data);
-                paramType = BitConverter.ToInt32(data, 0);
-                
-                LMOtsParameters otsParameter = LMOtsParameters.GetParametersByID(paramType);
-                byte[] I = new byte[16];
-                dIn.Read(I, 0, I.Length);
-            
-                
-                data = ((BinaryReader) src).ReadBytes(4);
-                Array.Reverse(data);
-                int q =  BitConverter.ToInt32(data, 0);
-                
-                data = ((BinaryReader) src).ReadBytes(4);
-                Array.Reverse(data);
-                int maxQ = BitConverter.ToInt32(data, 0);
-                
-                data = ((BinaryReader) src).ReadBytes(4);
-                Array.Reverse(data);
-                int l = BitConverter.ToInt32(data, 0);
-                
-                
+
+                int sigParamType = BinaryReaders.ReadInt32BigEndian(binaryReader);
+                LMSigParameters sigParameter = LMSigParameters.GetParametersByID(sigParamType);
+
+                int otsParamType = BinaryReaders.ReadInt32BigEndian(binaryReader);
+                LMOtsParameters otsParameter = LMOtsParameters.GetParametersByID(otsParamType);
+
+                byte[] I = BinaryReaders.ReadBytesFully(binaryReader, 16);
+
+                int q = BinaryReaders.ReadInt32BigEndian(binaryReader);
+
+                int maxQ = BinaryReaders.ReadInt32BigEndian(binaryReader);
+
+                int l = BinaryReaders.ReadInt32BigEndian(binaryReader);
                 if (l < 0)
-                {
                     throw new Exception("secret length less than zero");
-                }
-                if (l > dIn.BaseStream.Length)
-                {
-                    throw new IOException("secret length exceeded " + dIn.BaseStream.Length);
-                }
-                byte[] masterSecret = new byte[l];
-                dIn.Read(masterSecret, 0, masterSecret.Length);
-            
-                return new LMSPrivateKeyParameters(parameter, otsParameter, q, I, maxQ, masterSecret);
-            
+
+                byte[] masterSecret = BinaryReaders.ReadBytesFully(binaryReader, l);
+
+                return new LMSPrivateKeyParameters(sigParameter, otsParameter, q, I, maxQ, masterSecret);
             }
-            else if (src is byte[])
+            else if (src is byte[] bytes)
             {
                 BinaryReader input = null;
                 try // 1.5 / 1.6 compatibility
                 {
-                    input = new BinaryReader(new MemoryStream((byte[])src, false));
+                    input = new BinaryReader(new MemoryStream(bytes, false));
                     return GetInstance(input);
                 }
                 finally
@@ -167,9 +129,9 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
                     }
                 }
             }
-            else if (src is MemoryStream)
+            else if (src is MemoryStream memoryStream)
             {
-                return GetInstance(Streams.ReadAll((Stream)src));
+                return GetInstance(Streams.ReadAll(memoryStream));
             }
 
             throw new ArgumentException($"cannot parse {src}");
@@ -181,9 +143,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             lock (this)
             {
                 if (q >= maxQ)
-                {
                     throw new Exception("ots private keys expired");
-                }
+
                 return new LMOtsPrivateKey(otsParameters, I, q, masterSecret);
             }
         }
@@ -247,9 +208,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             lock (this)
             {
                 if (q >= maxQ)
-                {
                     throw new Exception("ots private key exhausted");
-                }
+
                 LMOtsPrivateKey otsPrivateKey = new LMOtsPrivateKey(otsParameters, I, q, masterSecret);
                 IncIndex();
                 return otsPrivateKey;
@@ -270,9 +230,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             lock (this)
             {
                 if (q + usageCount >= maxQ)
-                {
                     throw new ArgumentException("usageCount exceeds usages remaining");
-                }
+
                 LMSPrivateKeyParameters keyParameters = new LMSPrivateKeyParameters(this, q, q + usageCount);
                 q += usageCount;
 
diff --git a/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs b/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs
index 1bf857f60..80cf15827 100644
--- a/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs
+++ b/crypto/src/pqc/crypto/lms/LMSPublicKeyParameters.cs
@@ -23,33 +23,27 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             this.T1 = Arrays.Clone(T1);
         }
 
-        public static LMSPublicKeyParameters GetInstance(Object src)
+        public static LMSPublicKeyParameters GetInstance(object src)
         {
             if (src is LMSPublicKeyParameters lmsPublicKeyParameters)
             {
                 return lmsPublicKeyParameters;
             }
-            // todo
-             else if (src is BinaryReader binaryReader)
-             {
-                 byte[] data = binaryReader.ReadBytes(4);
-                 Array.Reverse(data);
-                 int pubType = BitConverter.ToInt32(data, 0);
-                 LMSigParameters lmsParameter = LMSigParameters.GetParametersByID(pubType);
-                 
-                 data = binaryReader.ReadBytes(4);
-                 Array.Reverse(data);
-                 int index = BitConverter.ToInt32(data, 0);
-                 LMOtsParameters ostTypeCode = LMOtsParameters.GetParametersByID(index);
-            
-                 byte[] I = new byte[16];
-                binaryReader.Read(I, 0, I.Length);//change to readbytes?
-            
-                 byte[] T1 = new byte[lmsParameter.M];
-                binaryReader.Read(T1, 0, T1.Length);
-                 return new LMSPublicKeyParameters(lmsParameter, ostTypeCode, T1, I);
-             }
-             else if (src is byte[] bytes)
+            else if (src is BinaryReader binaryReader)
+            {
+                int pubType = BinaryReaders.ReadInt32BigEndian(binaryReader);
+                LMSigParameters lmsParameter = LMSigParameters.GetParametersByID(pubType);
+
+                int index = BinaryReaders.ReadInt32BigEndian(binaryReader);
+                LMOtsParameters ostTypeCode = LMOtsParameters.GetParametersByID(index);
+
+                byte[] I = BinaryReaders.ReadBytesFully(binaryReader, 16);
+
+                byte[] T1 = BinaryReaders.ReadBytesFully(binaryReader, lmsParameter.M);
+
+                return new LMSPublicKeyParameters(lmsParameter, ostTypeCode, T1, I);
+            }
+            else if (src is byte[] bytes)
              {
                  BinaryReader input = null;
                  try // 1.5 / 1.6 compatibility
diff --git a/crypto/src/pqc/crypto/lms/LMSSignature.cs b/crypto/src/pqc/crypto/lms/LMSSignature.cs
index 48026e2f6..3f95ec516 100644
--- a/crypto/src/pqc/crypto/lms/LMSSignature.cs
+++ b/crypto/src/pqc/crypto/lms/LMSSignature.cs
@@ -30,15 +30,11 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
             }
             else if (src is BinaryReader binaryReader)
             {
-                byte[] data = binaryReader.ReadBytes(4);
-                Array.Reverse(data);
-                int q = BitConverter.ToInt32(data, 0);
-                
+                int q = BinaryReaders.ReadInt32BigEndian(binaryReader);
+
                 LMOtsSignature otsSignature = LMOtsSignature.GetInstance(src);
 
-                data = binaryReader.ReadBytes(4);
-                Array.Reverse(data);
-                int index = BitConverter.ToInt32(data, 0);
+                int index = BinaryReaders.ReadInt32BigEndian(binaryReader);
                 LMSigParameters type = LMSigParameters.GetParametersByID(index);
 
                 byte[][] path = new byte[type.H][];
@@ -47,7 +43,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms
                     path[h] = new byte[type.M];
                     binaryReader.Read(path[h], 0, path[h].Length);
                 }
-            
+
                 return new LMSSignature(q, otsSignature, type, path);
             }
             else if (src is byte[] bytes)
diff --git a/crypto/src/util/io/Streams.cs b/crypto/src/util/io/Streams.cs
index ac4bd3ae6..da8f01068 100644
--- a/crypto/src/util/io/Streams.cs
+++ b/crypto/src/util/io/Streams.cs
@@ -60,7 +60,12 @@ namespace Org.BouncyCastle.Utilities.IO
 			return buf.ToArray();
 		}
 
-		public static byte[] ReadAllLimited(Stream inStr, int limit)
+        public static byte[] ReadAll(MemoryStream inStr)
+        {
+			return inStr.ToArray();
+        }
+
+        public static byte[] ReadAllLimited(Stream inStr, int limit)
 		{
 			MemoryStream buf = new MemoryStream();
 			PipeAllLimited(inStr, limit, buf);
diff --git a/crypto/test/src/pqc/crypto/lms/test/LmsTests.cs b/crypto/test/src/pqc/crypto/lms/test/LmsTests.cs
index 5a7a84031..a5bc26252 100644
--- a/crypto/test/src/pqc/crypto/lms/test/LmsTests.cs
+++ b/crypto/test/src/pqc/crypto/lms/test/LmsTests.cs
@@ -42,10 +42,22 @@ namespace Org.BouncyCastle.Pqc.Crypto.Lms.Tests
             LMOtsSignature sig = LM_OTS.LMOtsGenerateSignature(privateKey, ctx.GetQ(), ctx.C);
             Assert.True(LM_OTS.LMOtsValidateSignature(publicKey, sig, ms, false));
 
-            //  Vandalise signature
+            // Recreate signature
+            {
+                byte[] recreatedSignature = sig.GetEncoded();
+                Assert.True(LM_OTS.LMOtsValidateSignature(publicKey, LMOtsSignature.GetInstance(recreatedSignature), ms, false));
+            }
+
+            // Recreate public key.
+            {
+                byte[] recreatedPubKey = Arrays.Clone(publicKey.GetEncoded());
+                Assert.True(LM_OTS.LMOtsValidateSignature(LMOtsPublicKey.GetInstance(recreatedPubKey), sig, ms, false));
+            }
+
+            // Vandalise signature
             {
 
-                byte[] vandalisedSignature = sig.GetEncoded(); // Arrays.clone(sig);
+                byte[] vandalisedSignature = sig.GetEncoded();
                 vandalisedSignature[256] ^= 1; // Single bit error
                 Assert.False(LM_OTS.LMOtsValidateSignature(publicKey, LMOtsSignature.GetInstance(vandalisedSignature), ms, false));
             }