internal void CertifyExistingFromCsr(int chainLen)
        {
            var req = (Pkcs10CertificationRequest)Helpers.ReadPemObject(ToPath(Program.DeviceIDCSR));

            //var req = (Pkcs10CertificationRequest)Helpers.ReadPemObject(fileName);

            if (!req.Verify())
            {
                Helpers.Notify("PKCS10 csr is not properly self-signed");
                return;
            }
            // todo: should propagate the subject in the CSR into the DeviceID certificate.

            var info = req.GetCertificationRequestInfo();
            AsymmetricKeyParameter deviceIdKey = PublicKeyFactory.CreateKey(info.SubjectPublicKeyInfo);

            DeviceBundle bundle = new DeviceBundle();

            bundle.AliasCert      = (X509Certificate)Helpers.ReadPemObject(ToPath(Program.AliasCert));
            bundle.DeviceIDPublic = (AsymmetricKeyParameter)deviceIdKey;
            bundle.AliasKeyPair   = (AsymmetricCipherKeyPair)Helpers.ReadPemObject(ToPath(Program.AliasKey));

            if (bundle.AliasCert.IssuerDN.ToString() != info.Subject.ToString())
            {
                Helpers.Notify("CSR Subject Name does not match Alias Certificate Issuer Name: Chain will not build.", true);
                return;
            }
            // todo (maybe).  Check that the Alias extension claimed DeviceID matches the DeviceID CSR key.

            MakeCertChain(bundle, chainLen, 0);
        }
示例#2
0
        /// <summary>
        /// If the device is not "vendor certified" it will only present the Alias Certificate, which is
        /// validated in this routine.  The essential security checks are:
        ///     1) Does it have a RIoT extension containing the DeviceID?
        ///     2) Is the certificate signed by the corresponding private DeviceID?
        ///     3) Is the DeviceID "authorized."  In the simple case, is it exactly the device DeviceID
        ///             indicated by the code that instantiated the TLSServer object.
        /// </summary>
        /// <param name="certificate"></param>
        /// <returns></returns>
        internal static bool ValidateBareCertificate(X509Certificate2 certificate)
        {
            Helpers.Notify($"Device presented a bare certificate");

            var deviceInfo = ExtensionDecoder.Decode(certificate);

            // check we have a good extension
            if (deviceInfo == null)
            {
                Helpers.Notify("Certificate does not have well-formed RIoT extension", true);
                return(false);
            }
            var devIdPubKeyDEREncoded = deviceInfo.EncodedDeviceIDKey;

            if (devIdPubKeyDEREncoded.Length != 65)
            {
                Helpers.Notify("Public key in extension has incorrect length", true);
                return(false);
            }

            // validating the certificate is signed with the public key encoded in the extension.
            // This is a critical security check.
            // Note: this uses the Bouncy Castle libraries
            var                   bcCert     = new X509CertificateParser().ReadCertificate(certificate.GetRawCertData());
            X9ECParameters        p          = NistNamedCurves.GetByName("P-256");
            ECDomainParameters    parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H);
            var                   pt         = parameters.Curve.DecodePoint(deviceInfo.EncodedDeviceIDKey);
            ECPublicKeyParameters bcPubKey   = new ECPublicKeyParameters(pt, parameters);

            try
            {
                bcCert.Verify(bcPubKey);
            }
            catch (Exception e)
            {
                Helpers.Notify($"Certificate is not signed using key in extension {e.ToString()}", true);
                return(false);
            }
            if (DeviceIDPEMFile != null)
            {
                // Is this key one of the keys registered with DRS (this test code only has one.)
                ECPublicKeyParameters authorizedDevice = (ECPublicKeyParameters)Helpers.ReadPemObject(DeviceIDPEMFile);
                // todo: there are probably better equality tests than this!
                bool keyIsRecognized =
                    (authorizedDevice.Q.XCoord.ToString() == bcPubKey.Q.XCoord.ToString()) &&
                    (authorizedDevice.Q.YCoord.ToString() == bcPubKey.Q.YCoord.ToString());

                if (!keyIsRecognized)
                {
                    Helpers.Notify($"DeviceID is not known", true);
                    return(false);
                }
                return(true);
            }
            // this code supports the "FakeDRSServer.  Here, any device that connects to us is presumed good

            return(true);
        }
        internal void CertifyExistingForJava(int chainLen)
        {
            DeviceBundle bundle = new DeviceBundle();

            bundle.AliasCert      = (X509Certificate)Helpers.ReadPemObject(ToPath(Program.AliasCert));
            bundle.DeviceIDPublic = (AsymmetricKeyParameter)Helpers.ReadPemObject(ToPath(Program.DeviceIDPublic));

            // The current Java implementation stores the public and provate keys separately.  Put them back
            // together
            ECPrivateKeyParameters  opriv = (ECPrivateKeyParameters)Helpers.ReadPemObject(ToPath("AliasPrivate.PEM"));
            ECPublicKeyParameters   opub  = (ECPublicKeyParameters)Helpers.ReadPemObject(ToPath("AliasPublic.PEM"));
            AsymmetricCipherKeyPair kpx   = new AsymmetricCipherKeyPair(opub, opriv);

            Helpers.WritePEMObject(ToPath(Program.AliasKey), kpx);

            bundle.AliasKeyPair = (AsymmetricCipherKeyPair)Helpers.ReadPemObject(ToPath(Program.AliasKey));


            MakeCertChain(bundle, chainLen, 0);
        }
        internal void CertifyExisting(int chainLen)
        {
            DeviceBundle bundle = new DeviceBundle();

            bundle.AliasCert      = (X509Certificate)Helpers.ReadPemObject(ToPath(Program.AliasCert));
            bundle.DeviceIDPublic = (AsymmetricKeyParameter)Helpers.ReadPemObject(ToPath(Program.DeviceIDPublic));

            bundle.AliasKeyPair = (AsymmetricCipherKeyPair)Helpers.ReadPemObject(ToPath(Program.AliasKey));

            //ECPrivateKeyParameters opriv = (ECPrivateKeyParameters) Helpers.ReadPemObject(ToPath("AliasPrivate.PEM"));
            //ECPublicKeyParameters opub = (ECPublicKeyParameters)Helpers.ReadPemObject(ToPath("AliasPublic.PEM"));
            //AsymmetricCipherKeyPair kpx = new AsymmetricCipherKeyPair(opub, opriv);
            //bundle.AliasKeyPair = kpx;
            //var privKey = PrivateKeyInfoFactory.CreatePrivateKeyInfo(oo);
            //oo.
            //var  kp = PrivateKeyInfoFactory.CreatePrivateKeyInfo(oo);

            //AsymmetricCipherKeyPair kp = (AsymmetricCipherKeyPair)KeyIn.CreatePrivateKeyInfo(oo);

            //ECPrivateKeyParameters parms = (ECPrivateKeyParameters) Helpers.ReadPemObject(ToPath(Program.AliasKey));
            //bundle.AliasKeyPair = new A

            MakeCertChain(bundle, chainLen, 0);
        }
        /// <summary>
        /// Make a new Alias Cert.  If refresh=false, a new DevID and Alias are created.  If refresh=true
        /// then just the Alias is created and re-certified using the stored DevID key.
        /// </summary>
        /// <param name="refresh"></param>
        /// <returns></returns>
        internal DeviceBundle MakeAliasCert(bool refresh, int fwidSeed)
        {
            DateTime now = DateTime.Now;

            byte[] fwid = Helpers.HashData(new byte[1] {
                (byte)fwidSeed
            }, 0, 1);

            const int keyStrength           = 256;
            CryptoApiRandomGenerator rg     = new CryptoApiRandomGenerator();
            SecureRandom             random = new SecureRandom(rg);
            KeyGenerationParameters  keyGenerationParameters = new KeyGenerationParameters(random, keyStrength);
            var keyPairGenerator = new ECKeyPairGenerator();

            keyPairGenerator.Init(keyGenerationParameters);

            AsymmetricCipherKeyPair devIdKey = null;

            if (refresh)
            {
                devIdKey = (AsymmetricCipherKeyPair)Helpers.ReadPemObject(ToPath(Program.DeviceIDPrivate));
            }
            else
            {
                devIdKey = keyPairGenerator.GenerateKeyPair();
            }

            // test - remove
            var oids = new List <Object>()
            {
                X509Name.UnstructuredName
            };
            var values = new List <Object>()
            {
                "ljkljljklkjlkjlkjlkjlkjlkjlkjlkjlkjljklkjlkjlkjlkjljk"
            };
            X509Name name = new X509Name(oids, values);



            AsymmetricCipherKeyPair aliasKey = keyPairGenerator.GenerateKeyPair();

            // make a string name based on DevID public.  Note that the authoritative information
            // is encoded in the RIoT-extension: this is just for quick-and-dirty device identification.
            var pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(devIdKey.Public);

            byte[] pubEncoded      = pubInfo.GetDerEncoded();
            var    pubHashed       = Helpers.HashData(pubEncoded, 0, pubEncoded.Length);
            var    shortNameBytes  = Helpers.CopyArray(pubHashed, 0, 8);
            var    shortNameString = Helpers.Hexify(shortNameBytes);

            X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
            var serialNumber = new byte[8];

            rg.NextBytes(serialNumber);
            serialNumber[0] &= 0x7F;
            certGen.SetSerialNumber(new BigInteger(serialNumber));
            // The important name-related stuff is encoded in the RIoT extension
            certGen.SetIssuerDN(new X509Name($"CN=[I]DevID:{shortNameString}, O=MSR_TEST, C=US"));
            // test REMOVE
            //certGen.SetSubjectDN(name);
            certGen.SetSubjectDN(new X509Name($"CN=[S]DevID:{shortNameString}, O=MSR_TEST, C=US"));
            certGen.SetNotBefore(now);
            certGen.SetNotAfter(now + new TimeSpan(365 * 10, 0, 0, 0, 0));
            certGen.SetPublicKey(aliasKey.Public);

            // Add the extensions (todo: not sure about KeyUsage.DigitalSiganture
            certGen.AddExtension(X509Extensions.ExtendedKeyUsage, true,
                                 ExtendedKeyUsage.GetInstance(new DerSequence(KeyPurposeID.IdKPClientAuth)));
            certGen.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DigitalSignature));
            AddRIoTExtension(certGen, fwid, devIdKey);

            // sign it
            ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA256WITHECDSA", devIdKey.Private, random);
            var certificate = certGen.Generate(signatureFactory);
            // and return the bundle
            DeviceBundle bundle = new DeviceBundle
            {
                AliasCert      = certificate,
                DeviceIDPublic = devIdKey.Public,
                AliasKeyPair   = aliasKey
            };

            // Just the AliasCert
            Helpers.WritePEMObject(ToPath(Program.AliasCert), bundle.AliasCert);
            // The Alias Key Pair
            Helpers.WritePEMObject(ToPath(Program.AliasKey), bundle.AliasKeyPair);
            // The encoded DevID
            Helpers.WritePEMObject(ToPath(Program.DeviceIDPublic), bundle.DeviceIDPublic);
            // DeviceIDPrivate (just for the update demo)
            Helpers.WritePEMObject(ToPath(Program.DeviceIDPrivate), devIdKey.Private);

            return(bundle);
        }