summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/src/asn1/bc/BCObjectIdentifiers.cs21
-rw-r--r--crypto/src/bcpg/SignatureSubpacketsReader.cs58
-rw-r--r--crypto/src/crypto/encodings/OaepEncoding.cs34
-rw-r--r--crypto/src/crypto/engines/CamelliaEngine.cs12
-rw-r--r--crypto/src/crypto/engines/CamelliaLightEngine.cs12
-rw-r--r--crypto/src/crypto/engines/SEEDEngine.cs3
-rw-r--r--crypto/src/openpgp/PgpPublicKey.cs7
-rw-r--r--crypto/src/openpgp/PgpUtilities.cs62
8 files changed, 153 insertions, 56 deletions
diff --git a/crypto/src/asn1/bc/BCObjectIdentifiers.cs b/crypto/src/asn1/bc/BCObjectIdentifiers.cs
index 0ffd65dfc..7266e4b4c 100644
--- a/crypto/src/asn1/bc/BCObjectIdentifiers.cs
+++ b/crypto/src/asn1/bc/BCObjectIdentifiers.cs
@@ -110,5 +110,26 @@ namespace Org.BouncyCastle.Asn1.BC
         public static readonly DerObjectIdentifier bc_ext = bc.Branch("4");
 
         public static readonly DerObjectIdentifier linkedCertificate = bc_ext.Branch("1");
+
+        /**
+         * KEM(4) algorithms
+         */
+        public static readonly DerObjectIdentifier bc_kem = bc.Branch("5");
+
+        /**
+         * Classic McEliece
+         */
+        public static readonly DerObjectIdentifier pqc_kem_mceliece = bc_kem.Branch("1");
+
+        public static readonly DerObjectIdentifier mceliece348864_r3 = pqc_kem_mceliece.Branch("1");
+        public static readonly DerObjectIdentifier mceliece348864f_r3 = pqc_kem_mceliece.Branch("2");
+        public static readonly DerObjectIdentifier mceliece460896_r3 = pqc_kem_mceliece.Branch("3");
+        public static readonly DerObjectIdentifier mceliece460896f_r3 = pqc_kem_mceliece.Branch("4");
+        public static readonly DerObjectIdentifier mceliece6688128_r3 = pqc_kem_mceliece.Branch("5");
+        public static readonly DerObjectIdentifier mceliece6688128f_r3 = pqc_kem_mceliece.Branch("6");
+        public static readonly DerObjectIdentifier mceliece6960119_r3 = pqc_kem_mceliece.Branch("7");
+        public static readonly DerObjectIdentifier mceliece6960119f_r3 = pqc_kem_mceliece.Branch("8");
+        public static readonly DerObjectIdentifier mceliece8192128_r3 = pqc_kem_mceliece.Branch("9");
+        public static readonly DerObjectIdentifier mceliece8192128f_r3 = pqc_kem_mceliece.Branch("10");
 	}
 }
diff --git a/crypto/src/bcpg/SignatureSubpacketsReader.cs b/crypto/src/bcpg/SignatureSubpacketsReader.cs
index 45dc96885..86ad11207 100644
--- a/crypto/src/bcpg/SignatureSubpacketsReader.cs
+++ b/crypto/src/bcpg/SignatureSubpacketsReader.cs
@@ -90,33 +90,37 @@ namespace Org.BouncyCastle.Bcpg
 
             switch (type)
 			{
-				case SignatureSubpacketTag.CreationTime:
-					return new SignatureCreationTime(isCritical, isLongLength, data);
-				case SignatureSubpacketTag.KeyExpireTime:
-                    return new KeyExpirationTime(isCritical, isLongLength, data);
-				case SignatureSubpacketTag.ExpireTime:
-                    return new SignatureExpirationTime(isCritical, isLongLength, data);
-				case SignatureSubpacketTag.Revocable:
-                    return new Revocable(isCritical, isLongLength, data);
-				case SignatureSubpacketTag.Exportable:
-                    return new Exportable(isCritical, isLongLength, data);
-				case SignatureSubpacketTag.IssuerKeyId:
-                    return new IssuerKeyId(isCritical, isLongLength, data);
-				case SignatureSubpacketTag.TrustSig:
-                    return new TrustSignature(isCritical, isLongLength, data);
-				case SignatureSubpacketTag.PreferredCompressionAlgorithms:
-				case SignatureSubpacketTag.PreferredHashAlgorithms:
-				case SignatureSubpacketTag.PreferredSymmetricAlgorithms:
-                    return new PreferredAlgorithms(type, isCritical, isLongLength, data);
-				case SignatureSubpacketTag.KeyFlags:
-                    return new KeyFlags(isCritical, isLongLength, data);
-				case SignatureSubpacketTag.PrimaryUserId:
-                    return new PrimaryUserId(isCritical, isLongLength, data);
-				case SignatureSubpacketTag.SignerUserId:
-                    return new SignerUserId(isCritical, isLongLength, data);
-				case SignatureSubpacketTag.NotationData:
-                    return new NotationData(isCritical, isLongLength, data);
-			}
+			case SignatureSubpacketTag.CreationTime:
+				return new SignatureCreationTime(isCritical, isLongLength, data);
+			case SignatureSubpacketTag.KeyExpireTime:
+                return new KeyExpirationTime(isCritical, isLongLength, data);
+			case SignatureSubpacketTag.ExpireTime:
+                return new SignatureExpirationTime(isCritical, isLongLength, data);
+			case SignatureSubpacketTag.Revocable:
+                return new Revocable(isCritical, isLongLength, data);
+			case SignatureSubpacketTag.Exportable:
+                return new Exportable(isCritical, isLongLength, data);
+			case SignatureSubpacketTag.IssuerKeyId:
+                return new IssuerKeyId(isCritical, isLongLength, data);
+			case SignatureSubpacketTag.TrustSig:
+                return new TrustSignature(isCritical, isLongLength, data);
+			case SignatureSubpacketTag.PreferredCompressionAlgorithms:
+			case SignatureSubpacketTag.PreferredHashAlgorithms:
+			case SignatureSubpacketTag.PreferredSymmetricAlgorithms:
+                return new PreferredAlgorithms(type, isCritical, isLongLength, data);
+			case SignatureSubpacketTag.KeyFlags:
+                return new KeyFlags(isCritical, isLongLength, data);
+			case SignatureSubpacketTag.PrimaryUserId:
+                return new PrimaryUserId(isCritical, isLongLength, data);
+			case SignatureSubpacketTag.SignerUserId:
+                return new SignerUserId(isCritical, isLongLength, data);
+			case SignatureSubpacketTag.NotationData:
+                return new NotationData(isCritical, isLongLength, data);
+            case SignatureSubpacketTag.RevocationReason:
+                return new RevocationReason(isCritical, isLongLength, data);
+            case SignatureSubpacketTag.RevocationKey:
+                return new RevocationKey(isCritical, isLongLength, data);
+            }
             return new SignatureSubpacket(type, isCritical, isLongLength, data);
 		}
 
diff --git a/crypto/src/crypto/encodings/OaepEncoding.cs b/crypto/src/crypto/encodings/OaepEncoding.cs
index 295a43aac..f3550b9cd 100644
--- a/crypto/src/crypto/encodings/OaepEncoding.cs
+++ b/crypto/src/crypto/encodings/OaepEncoding.cs
@@ -213,7 +213,8 @@ namespace Org.BouncyCastle.Crypto.Encodings
             // on encryption, we need to make sure our decrypted block comes back
             // the same size.
             //
-            bool wrongData = (block.Length < (2 * defHash.Length) + 1);
+            // i.e. wrong when block.length < (2 * defHash.length) + 1
+            int wrongMask = (block.Length - ((2 * defHash.Length) + 1)) >> 31;
 
             if (data.Length <= block.Length)
             {
@@ -222,7 +223,7 @@ namespace Org.BouncyCastle.Crypto.Encodings
             else
             {
                 Array.Copy(data, 0, block, 0, block.Length);
-                wrongData = true;
+                wrongMask |= 1;
             }
 
             //
@@ -250,39 +251,38 @@ namespace Org.BouncyCastle.Crypto.Encodings
             // check the hash of the encoding params.
             // long check to try to avoid this been a source of a timing attack.
             //
-            bool defHashWrong = false;
-
             for (int i = 0; i != defHash.Length; i++)
             {
-                if (defHash[i] != block[defHash.Length + i])
-                {
-                    defHashWrong = true;
-                }
+                wrongMask |= defHash[i] ^ block[defHash.Length + i];
             }
 
             //
             // find the data block
             //
-            int start = block.Length;
+            int start = -1;
 
             for (int index = 2 * defHash.Length; index != block.Length; index++)
             {
-                if (block[index] != 0 & start == block.Length)
-                {
-                    start = index;
-                }
-            }
+                int octet = block[index];
 
-            bool dataStartWrong = (start > (block.Length - 1) | block[start] != 1);
+                // i.e. mask will be 0xFFFFFFFF if octet is non-zero and start is (still) negative, else 0.
+                int shouldSetMask = (-octet & start) >> 31;
 
-            start++;
+                start += index & shouldSetMask;
+            }
 
-            if (defHashWrong | wrongData | dataStartWrong)
+            wrongMask |= start >> 31;
+            ++start;
+            wrongMask |= block[start] ^ 1;
+
+            if (wrongMask != 0)
             {
                 Arrays.Fill(block, 0);
                 throw new InvalidCipherTextException("data wrong");
             }
 
+            ++start;
+
             //
             // extract the data block
             //
diff --git a/crypto/src/crypto/engines/CamelliaEngine.cs b/crypto/src/crypto/engines/CamelliaEngine.cs
index 71bd1b0dc..2222e4b7c 100644
--- a/crypto/src/crypto/engines/CamelliaEngine.cs
+++ b/crypto/src/crypto/engines/CamelliaEngine.cs
@@ -18,7 +18,6 @@ namespace Org.BouncyCastle.Crypto.Engines
 		private uint[] subkey = new uint[24 * 4];
 		private uint[] kw = new uint[4 * 2]; // for whitening
 		private uint[] ke = new uint[6 * 2]; // for FL and FL^(-1)
-		private uint[] state = new uint[4]; // for encryption and decryption
 
 		private static readonly uint[] SIGMA = new uint[]{
 			0xa09e667f, 0x3bcc908b,
@@ -540,10 +539,11 @@ namespace Org.BouncyCastle.Crypto.Engines
 
 		private int processBlock128(byte[] input, int inOff, byte[] output, int outOff)
 		{
+			uint[] state = new uint[4];
+
 			for (int i = 0; i < 4; i++)
 			{
-				state[i] = bytes2uint(input, inOff + (i * 4));
-				state[i] ^= kw[i];
+				state[i] = bytes2uint(input, inOff + (i * 4)) ^ kw[i];
 			}
 
 			camelliaF2(state, subkey, 0);
@@ -573,10 +573,11 @@ namespace Org.BouncyCastle.Crypto.Engines
 
 		private int processBlock192or256(byte[] input, int inOff, byte[] output, int outOff)
 		{
+			uint[] state = new uint[4];
+
 			for (int i = 0; i < 4; i++)
 			{
-				state[i] = bytes2uint(input, inOff + (i * 4));
-				state[i] ^= kw[i];
+				state[i] = bytes2uint(input, inOff + (i * 4)) ^ kw[i];
 			}
 
 			camelliaF2(state, subkey, 0);
@@ -604,6 +605,7 @@ namespace Org.BouncyCastle.Crypto.Engines
 			uint2bytes(state[3], output, outOff + 4);
 			uint2bytes(state[0], output, outOff + 8);
 			uint2bytes(state[1], output, outOff + 12);
+
 			return BLOCK_SIZE;
 		}
 
diff --git a/crypto/src/crypto/engines/CamelliaLightEngine.cs b/crypto/src/crypto/engines/CamelliaLightEngine.cs
index a132227c5..daf0316e2 100644
--- a/crypto/src/crypto/engines/CamelliaLightEngine.cs
+++ b/crypto/src/crypto/engines/CamelliaLightEngine.cs
@@ -18,7 +18,6 @@ namespace Org.BouncyCastle.Crypto.Engines
 		private uint[] subkey = new uint[24 * 4];
 		private uint[] kw = new uint[4 * 2]; // for whitening
 		private uint[] ke = new uint[6 * 2]; // for FL and FL^(-1)
-		private uint[] state = new uint[4]; // for encryption and decryption
 
 		private static readonly uint[] SIGMA = {
 			0xa09e667f, 0x3bcc908b,
@@ -452,10 +451,11 @@ namespace Org.BouncyCastle.Crypto.Engines
 
 		private int processBlock128(byte[] input, int inOff, byte[] output, int outOff)
 		{
+			uint[] state = new uint[4];
+
 			for (int i = 0; i < 4; i++)
 			{
-				state[i] = bytes2uint(input, inOff + (i * 4));
-				state[i] ^= kw[i];
+				state[i] = bytes2uint(input, inOff + (i * 4)) ^ kw[i];
 			}
 
 			camelliaF2(state, subkey, 0);
@@ -485,10 +485,11 @@ namespace Org.BouncyCastle.Crypto.Engines
 
 		private int processBlock192or256(byte[] input, int inOff, byte[] output, int outOff)
 		{
+			uint[] state = new uint[4];
+
 			for (int i = 0; i < 4; i++)
 			{
-				state[i] = bytes2uint(input, inOff + (i * 4));
-				state[i] ^= kw[i];
+				state[i] = bytes2uint(input, inOff + (i * 4)) ^ kw[i];
 			}
 
 			camelliaF2(state, subkey, 0);
@@ -516,6 +517,7 @@ namespace Org.BouncyCastle.Crypto.Engines
 			uint2bytes(state[3], output, outOff + 4);
 			uint2bytes(state[0], output, outOff + 8);
 			uint2bytes(state[1], output, outOff + 12);
+
 			return BLOCK_SIZE;
 		}
 
diff --git a/crypto/src/crypto/engines/SEEDEngine.cs b/crypto/src/crypto/engines/SEEDEngine.cs
index f615b8476..d4142c867 100644
--- a/crypto/src/crypto/engines/SEEDEngine.cs
+++ b/crypto/src/crypto/engines/SEEDEngine.cs
@@ -240,6 +240,9 @@ namespace Org.BouncyCastle.Crypto.Engines
 		private int[] createWorkingKey(
 			byte[] inKey)
 		{
+			if (inKey.Length != 16)
+				throw new ArgumentException("key size must be 128 bits");
+
 			int[] key = new int[32];
 			long lower = bytesToLong(inKey, 0);
 			long upper = bytesToLong(inKey, 8);
diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs
index 9b8a956f2..33fabc8aa 100644
--- a/crypto/src/openpgp/PgpPublicKey.cs
+++ b/crypto/src/openpgp/PgpPublicKey.cs
@@ -460,7 +460,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
         /// <summary>True, if this could be a master key.</summary>
         public bool IsMasterKey
         {
-            get { return (subSigs == null) && !(this.IsEncryptionKey && publicPk.Algorithm != PublicKeyAlgorithmTag.RsaGeneral); }
+            get
+            {
+                // this might seem a bit excessive, but we're also trying to flag something can't be a master key.
+                return !(publicPk is PublicSubkeyPacket)
+                    && !(this.IsEncryptionKey && publicPk.Algorithm != PublicKeyAlgorithmTag.RsaGeneral);
+            }
         }
 
         /// <summary>The algorithm code associated with the public key.</summary>
diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs
index fd5ab6232..fcc4f672c 100644
--- a/crypto/src/openpgp/PgpUtilities.cs
+++ b/crypto/src/openpgp/PgpUtilities.cs
@@ -1,8 +1,12 @@
 using System;
+using System.Collections;
 using System.IO;
 using System.Text;
 
 using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.EdEC;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Math;
@@ -16,6 +20,37 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 	/// <remarks>Basic utility class.</remarks>
     public sealed class PgpUtilities
     {
+        private static IDictionary NameToHashID = CreateNameToHashID();
+        private static IDictionary OidToName = CreateOidToName();
+
+        private static IDictionary CreateNameToHashID()
+        {
+            IDictionary d = Platform.CreateHashtable();
+            d.Add("sha1", HashAlgorithmTag.Sha1);
+            d.Add("sha224", HashAlgorithmTag.Sha224);
+            d.Add("sha256", HashAlgorithmTag.Sha256);
+            d.Add("sha384", HashAlgorithmTag.Sha384);
+            d.Add("sha512", HashAlgorithmTag.Sha512);
+            d.Add("ripemd160", HashAlgorithmTag.RipeMD160);
+            d.Add("rmd160", HashAlgorithmTag.RipeMD160);
+            d.Add("md2", HashAlgorithmTag.MD2);
+            d.Add("tiger", HashAlgorithmTag.Tiger192);
+            d.Add("haval", HashAlgorithmTag.Haval5pass160);
+            d.Add("md5", HashAlgorithmTag.MD5);
+            return d;
+        }
+
+        private static IDictionary CreateOidToName()
+        {
+            IDictionary d = Platform.CreateHashtable();
+            d.Add(EdECObjectIdentifiers.id_X25519, "Curve25519");
+            d.Add(EdECObjectIdentifiers.id_Ed25519, "Ed25519");
+            d.Add(SecObjectIdentifiers.SecP256r1, "NIST P-256");
+            d.Add(SecObjectIdentifiers.SecP384r1, "NIST P-384");
+            d.Add(SecObjectIdentifiers.SecP521r1, "NIST P-521");
+            return d;
+        }
+
         private PgpUtilities()
         {
         }
@@ -75,7 +110,32 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 			}
         }
 
-		public static string GetSignatureName(
+        public static int GetDigestIDForName(string name)
+        {
+            name = Platform.ToLowerInvariant(name);
+            if (NameToHashID.Contains(name))
+                return (Int32)NameToHashID[name];
+
+            throw new ArgumentException("unable to map " + name + " to a hash id", "name");
+        }
+
+        /**
+         * Return the EC curve name for the passed in OID.
+         *
+         * @param oid the EC curve object identifier in the PGP key
+         * @return  a string representation of the OID.
+         */
+        public static string GetCurveName(DerObjectIdentifier oid)
+        {
+            string name = (string)OidToName[oid];
+            if (name != null)
+                return name;
+
+            // fall back
+            return ECNamedCurveTable.GetName(oid);
+        }
+
+        public static string GetSignatureName(
             PublicKeyAlgorithmTag	keyAlgorithm,
             HashAlgorithmTag		hashAlgorithm)
         {