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); }
/// <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); }