Exemple #1
0
        private void Init(byte[] data)
        {
            GXAsn1Sequence seq = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(data);

            if (seq.Count < 3)
            {
                throw new System.ArgumentException("Wrong number of elements in sequence.");
            }
            if (!(seq[0] is sbyte))
            {
                PkcsType type = GXAsn1Converter.GetCertificateType(data, seq);
                switch (type)
                {
                case PkcsType.Pkcs10:
                    throw new GXDLMSCertificateException("Invalid Certificate. This is PKCS 10 certification requests, not PKCS 8.");

                case PkcsType.x509Certificate:
                    throw new GXDLMSCertificateException("Invalid Certificate. This is PKCS x509 certificate, not PKCS 8.");
                }
                throw new GXDLMSCertificateException("Invalid Certificate Version.");
            }
            Version = (CertificateVersion)seq[0];
            GXAsn1Sequence tmp = (GXAsn1Sequence)seq[1];

            Algorithm  = X9ObjectIdentifierConverter.FromString(tmp[0].ToString());
            PrivateKey = GXPrivateKey.FromRawBytes((byte[])((GXAsn1Sequence)seq[2])[1]);
            if (PrivateKey == null)
            {
                throw new Exception("Invalid private key.");
            }
            PublicKey = GXPublicKey.FromRawBytes(((GXAsn1BitString)((List <object>)((GXAsn1Sequence)seq[2])[2])[0]).Value);
            GXEcdsa.Validate(PublicKey);
        }
 /// <summary>
 /// Get the signature for the image.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void SignBtn_Click(object sender, EventArgs e)
 {
     try
     {
         OpenFileDialog dlg = new OpenFileDialog();
         dlg.Multiselect = false;
         if (SigningKeyTb.Text == "" || Path.GetFileName(SigningKeyTb.Text) == "")
         {
             dlg.InitialDirectory = Directory.GetCurrentDirectory();
             dlg.Filter           = Properties.Resources.PemFilterTxt;
             dlg.DefaultExt       = ".pem";
             dlg.ValidateNames    = true;
             if (dlg.ShowDialog(this) == DialogResult.OK)
             {
                 SigningKeyTb.Text = dlg.FileName;
             }
             else
             {
                 return;
             }
         }
         GXPkcs8 key   = GXPkcs8.Load(SigningKeyTb.Text);
         GXEcdsa ecdsa = new GXEcdsa(key.PrivateKey);
         SignatureTb.Text = GXDLMSTranslator.ToHex(ecdsa.Sign(File.ReadAllBytes(FileNameTb.Text)));
     }
     catch (Exception ex)
     {
         MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
     }
 }
Exemple #3
0
        /// <summary>
        /// Sign
        /// </summary>
        /// <param name="key">Private key. </param>
        /// <param name="HashAlgorithm">Used algorithm for signing. </param>
        void Sign(GXPrivateKey key, HashAlgorithm HashAlgorithm)
        {
            byte[]  data = GXAsn1Converter.ToByteArray(Getdata());
            GXEcdsa e    = new GXEcdsa(key);

            SignatureAlgorithm = HashAlgorithm;
            Signature          = e.Sign(data);
        }
Exemple #4
0
        private void Init(byte[] data)
        {
            GXAsn1Sequence seq = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(data);

            if (seq.Count < 3)
            {
                throw new System.ArgumentException("Wrong number of elements in sequence.");
            }
            /////////////////////////////
            // CertificationRequestInfo ::= SEQUENCE {
            // version INTEGER { v1(0) } (v1,...),
            // subject Name,
            // subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
            // attributes [0] Attributes{{ CRIAttributes }}
            // }

            GXAsn1Sequence reqInfo = (GXAsn1Sequence)seq[0];

            Version = (CertificateVersion)(sbyte)reqInfo[0];
            Subject = GXAsn1Converter.GetSubject((GXAsn1Sequence)reqInfo[1]);
            // subject Public key info.
            GXAsn1Sequence subjectPKInfo = (GXAsn1Sequence)reqInfo[2];

            if (reqInfo.Count > 3)
            {
                Attributes = reqInfo[3];
            }
            GXAsn1Sequence tmp = (GXAsn1Sequence)subjectPKInfo[0];

            Algorithm = PkcsObjectIdentifierConverter.FromString(tmp[0].ToString());
            if ((PkcsObjectIdentifier)Algorithm == PkcsObjectIdentifier.None)
            {
                Algorithm = X9ObjectIdentifierConverter.FromString(tmp[0].ToString());
            }
            byte[] encodedKey = GXAsn1Converter.ToByteArray(subjectPKInfo);
            PublicKey = GXPublicKey.FromRawBytes(encodedKey);
            /////////////////////////////
            // signatureAlgorithm
            GXAsn1Sequence sign = (GXAsn1Sequence)seq[1];

            SignatureAlgorithm = HashAlgorithmConverter.FromString(sign[0].ToString());
            if (sign.Count != 1)
            {
                SignatureParameters = sign[1];
            }
            /////////////////////////////
            // signature
            Signature = ((GXAsn1BitString)seq[2]).Value;
            GXEcdsa e = new GXEcdsa(PublicKey);

            if (!e.Verify(GXAsn1Converter.ToByteArray(reqInfo), data))
            {
                throw new ArgumentException("Invalid Signature.");
            }
        }
Exemple #5
0
        /// <summary>
        /// Get Ephemeral Public Key Signature.
        /// </summary>
        /// <param name="keyId">Key ID.</param>
        /// <param name="ephemeralKey">Ephemeral key.</param>
        /// <param name="signKey">Private Key.</param>
        /// <returns>Ephemeral Public Key Signature.</returns>
        public static byte[] GetEphemeralPublicKeySignature(
            int keyId,
            GXPublicKey ephemeralKey,
            GXPrivateKey signKey)
        {
            byte[] epk = GetEphemeralPublicKeyData(keyId, ephemeralKey);
            // Add ephemeral public key signature.
            GXEcdsa c = new GXEcdsa(signKey);

            byte[] sign = c.Sign(epk);
            return(sign);
        }
Exemple #6
0
        /// <summary>
        /// Sign
        /// </summary>
        /// <param name="key">Private key. </param>
        /// <param name="HashAlgorithm">Used algorithm for signing. </param>
        void Sign(GXPrivateKey key, HashAlgorithm HashAlgorithm)
        {
            byte[]  data = GXAsn1Converter.ToByteArray(GetData());
            GXEcdsa e    = new GXEcdsa(key);

            SignatureAlgorithm = HashAlgorithm;
            GXByteBuffer bb = new GXByteBuffer();

            bb.Set(e.Sign(data));
            int size = SignatureAlgorithm == HashAlgorithm.Sha256WithEcdsa ? 32 : 48;

            object[] tmp = new object[] { new GXAsn1Integer(bb.SubArray(0, size)), new GXAsn1Integer(bb.SubArray(size, size)) };
            Signature = GXAsn1Converter.ToByteArray(tmp);
        }
Exemple #7
0
 /// <summary>
 /// Generate new private key.
 /// </summary>
 private void GenerateBtn_Click(object sender, EventArgs e)
 {
     try
     {
         PrivateKey.Text     = "";
         GeneratedKeyTb.Text = "";
         KeyValuePair <GXPublicKey, GXPrivateKey> k = GXEcdsa.GenerateKeyPair(Key256.Checked ? Ecc.P256 : Ecc.P384);
         GXEcdsa.Validate(k.Key);
         Key = new GXPkcs8(k);
         GXEcdsa.Validate(Key.PublicKey);
         PrivateKey.Text = Key.ToPem();
         UpdateGeneratedKey();
     }
     catch (Exception ex)
     {
         Key = null;
         MessageBox.Show(this, ex.Message);
     }
 }
Exemple #8
0
        private void Init(byte[] data)
        {
            GXAsn1Sequence seq = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(data);

            if (seq.Count < 3)
            {
                throw new System.ArgumentException("Wrong number of elements in sequence.");
            }
            Version = (CertificateVersion)seq[0];
            GXAsn1Sequence tmp = (GXAsn1Sequence)seq[1];

            Algorithm  = X9ObjectIdentifierConverter.FromString(tmp[0].ToString());
            PrivateKey = GXPrivateKey.FromRawBytes((byte[])((GXAsn1Sequence)seq[2])[1]);
            if (PrivateKey == null)
            {
                throw new Exception("Invalid private key.");
            }
            PublicKey = GXPublicKey.FromRawBytes(((GXAsn1BitString)((List <object>)((GXAsn1Sequence)seq[2])[2])[0]).Value);
            GXEcdsa.Validate(PublicKey);
        }
Exemple #9
0
        /// <summary>
        /// Validate ephemeral public key signature.
        /// </summary>
        /// <param name="data">Data to validate.</param>
        /// <param name="sign">Sign</param>
        /// <param name="publicSigningKey">Public Signing key from other party.</param>
        /// <returns>Is verify succeeded.</returns>
        public static bool ValidateEphemeralPublicKeySignature(
            byte[] data,
            byte[] sign,
            GXPublicKey publicSigningKey)
        {
            GXAsn1Integer  a = new GXAsn1Integer(sign, 0, 32);
            GXAsn1Integer  b = new GXAsn1Integer(sign, 32, 32);
            GXAsn1Sequence s = new GXAsn1Sequence();

            s.Add(a);
            s.Add(b);
            byte[]  tmp = GXAsn1Converter.ToByteArray(s);
            GXEcdsa c   = new GXEcdsa(publicSigningKey);
            bool    ret = c.Verify(sign, data);

            if (!ret)
            {
                System.Diagnostics.Debug.WriteLine("Data:" + GXCommon.ToHex(data, true));
                System.Diagnostics.Debug.WriteLine("Sign:" + GXCommon.ToHex(sign, true));
            }
            return(ret);
        }
Exemple #10
0
 private void TransformBtn_Click(object sender, EventArgs e)
 {
     try
     {
         GeneratedKeyTb.Text = "";
         if (string.IsNullOrEmpty(PrivateKey.Text))
         {
             KeyValuePair <GXPublicKey, GXPrivateKey> k = GXEcdsa.GenerateKeyPair(Key256.Checked ? Ecc.P256 : Ecc.P384);
             Key = new GXPkcs8(k);
             GXEcdsa.Validate(k.Key);
         }
         else
         {
             Key = GXPkcs8.Import(PrivateKey.Text);
         }
         UpdateGeneratedKey();
     }
     catch (Exception ex)
     {
         Key = null;
         MessageBox.Show(this, ex.Message);
     }
 }
Exemple #11
0
        /// <summary>
        /// Test is x509 file certified by the certifier.
        /// </summary>
        /// <param name="certifier">Public key of the certifier.</param>
        /// <returns>True, if certifier has certified the certificate.</returns>
        public bool IsCertified(GXPublicKey certifier)
        {
            if (certifier == null)
            {
                throw new ArgumentNullException(nameof(certifier));
            }
            //Get raw data
            GXByteBuffer tmp2 = new GXByteBuffer();

            tmp2.Set(Encoded);
            GXAsn1Converter.GetNext(tmp2);
            tmp2.Size     = tmp2.Position;
            tmp2.Position = 1;
            GXCommon.GetObjectCount(tmp2);
            GXEcdsa        e    = new GXEcdsa(certifier);
            GXAsn1Sequence tmp3 = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(Signature);
            GXByteBuffer   bb   = new GXByteBuffer();
            int            size = SignatureAlgorithm == HashAlgorithm.Sha256WithEcdsa ? 32 : 48;

            //Some implementations might add extra byte. It must removed.
            bb.Set(((GXAsn1Integer)tmp3[0]).Value, ((GXAsn1Integer)tmp3[0]).Value.Length == size ? 0 : 1, size);
            bb.Set(((GXAsn1Integer)tmp3[1]).Value, ((GXAsn1Integer)tmp3[1]).Value.Length == size ? 0 : 1, size);
            return(e.Verify(bb.Array(), tmp2.SubArray(tmp2.Position, tmp2.Available)));
        }
        /// <summary>
        /// Update ephemeral keys.
        /// </summary>
        /// <param name="client">DLMS Client.</param>
        /// <param name="value">Received reply from the server.</param>
        /// <returns>List of Parsed key id and GUAK. This is for debugging purpose.</returns>
        public List <KeyValuePair <GlobalKeyType, byte[]> > UpdateEphemeralKeys(GXDLMSSecureClient client, GXByteBuffer value)
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }
            if (value.GetUInt8() != (byte)DataType.Array)
            {
                throw new ArgumentOutOfRangeException("Invalid tag.");
            }
            GXEcdsa c     = new GXEcdsa(client.Ciphering.EphemeralKeyPair.Key);
            int     count = GXCommon.GetObjectCount(value);
            List <KeyValuePair <GlobalKeyType, byte[]> > list = new List <KeyValuePair <GlobalKeyType, byte[]> >();

            for (int pos = 0; pos != count; ++pos)
            {
                if (value.GetUInt8() != (byte)DataType.Structure)
                {
                    throw new ArgumentOutOfRangeException("Invalid tag.");
                }
                if (value.GetUInt8() != 2)
                {
                    throw new ArgumentOutOfRangeException("Invalid length.");
                }
                if (value.GetUInt8() != (byte)DataType.Enum)
                {
                    throw new ArgumentOutOfRangeException("Invalid key id data type.");
                }
                int keyId = value.GetUInt8();
                if (keyId > 4)
                {
                    throw new ArgumentOutOfRangeException("Invalid key type.");
                }
                if (value.GetUInt8() != (byte)DataType.OctetString)
                {
                    throw new ArgumentOutOfRangeException("Invalid tag.");
                }
                if (GXCommon.GetObjectCount(value) != 128)
                {
                    throw new ArgumentOutOfRangeException("Invalid length.");
                }
                //Get ephemeral public key server.
                GXByteBuffer key = new GXByteBuffer();
                key.SetUInt8(4);
                key.Set(value, 64);
                GXPublicKey targetEphemeralKey = GXPublicKey.FromRawBytes(key.Array());
                //Get ephemeral public key signature server.
                byte[] signature = new byte[64];
                value.Get(signature);
                key.SetUInt8(0, (byte)keyId);
                //Verify signature.
                if (!GXSecure.ValidateEphemeralPublicKeySignature(key.Array(), signature, client.Ciphering.SigningKeyPair.Value))
                {
                    throw new GXDLMSCipherException("Invalid signature.");
                }
                byte[] z = c.GenerateSecret(targetEphemeralKey);
                System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true));
                GXByteBuffer kdf = new GXByteBuffer();
                kdf.Set(GXSecure.GenerateKDF(client.SecuritySuite, z,
                                             AlgorithmId.AesGcm128,
                                             client.Ciphering.SystemTitle,
                                             client.Settings.SourceSystemTitle, null, null));
                System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString());
                list.Add(new KeyValuePair <GlobalKeyType, byte[]>((GlobalKeyType)keyId, kdf.SubArray(0, 16)));
            }
            //Update ephemeral keys.
            foreach (KeyValuePair <GlobalKeyType, byte[]> it in list)
            {
                switch (it.Key)
                {
                case GlobalKeyType.UnicastEncryption:
                    client.Settings.EphemeralBlockCipherKey = it.Value;
                    break;

                case GlobalKeyType.BroadcastEncryption:
                    client.Settings.EphemeralBroadcastBlockCipherKey = it.Value;
                    break;

                case GlobalKeyType.Authentication:
                    client.Settings.EphemeralAuthenticationKey = it.Value;
                    break;

                case GlobalKeyType.Kek:
                    client.Settings.EphemeralKek = it.Value;
                    break;
                }
            }
            return(list);
        }
Exemple #13
0
        public GXKeyForm(IGXUpdater updater, string address, string keyFolder, string certificateFolder, string title, SecuritySuite securitySuite, byte[] systemTitle)
        {
            InitializeComponent();
            _updater           = updater;
            _address           = address;
            _certificateFolder = certificateFolder;
            _systemTitle       = systemTitle;
            privateKeys        = new GXPkcs8Collection();
            KeyFolder          = keyFolder;
            Title = title;

            foreach (string p in Directory.GetFiles(keyFolder))
            {
                string ext = Path.GetExtension(p);
                if (string.Compare(ext, ".pem", true) == 0 || string.Compare(ext, ".cer", true) == 0)
                {
                    try
                    {
                        GXPkcs8 cert = GXPkcs8.Load(p);
                        AddKey(cert, p);
                    }
                    catch (Exception)
                    {
                        Debug.WriteLine("Failed to open " + p);
                    }
                }
            }
            if (_systemTitle != null)
            {
                string path = Path.Combine(KeyFolder, "D" + GXDLMSTranslator.ToHex(_systemTitle, false)) + ".pem";
                //Generate private key for digital signature.
                GXPkcs8 digitalSignature = new GXPkcs8(GXEcdsa.GenerateKeyPair(securitySuite == SecuritySuite.Suite1 ? Ecc.P256 : Ecc.P384));
                digitalSignature.Save(path);
                AddKey(digitalSignature, path);
                path = Path.Combine(KeyFolder, "A" + GXDLMSTranslator.ToHex(_systemTitle, false)) + ".pem";
                //Generate private key for Key agreement.
                GXPkcs8 keyAgreement = new GXPkcs8(GXEcdsa.GenerateKeyPair(Ecc.P256));
                keyAgreement.Save(path);
                AddKey(keyAgreement, path);

                //Get CRS.
                KeyValuePair <GXPublicKey, GXPrivateKey> kp = new KeyValuePair <GXPublicKey, GXPrivateKey>(digitalSignature.PublicKey, digitalSignature.PrivateKey);
                //Generate certificate request and ask new x509Certificate.
                //Note! There is a limit how many request you can do in a day.
                List <GXCertificateRequest> certifications = new List <GXCertificateRequest>();
                GXCertificateRequest        it             = new GXCertificateRequest();
                it.Certificate     = GXPkcs10.CreateCertificateSigningRequest(kp, GXAsn1Converter.SystemTitleToSubject(_systemTitle));
                it.CertificateType = CertificateType.DigitalSignature;
                certifications.Add(it);
                it                 = new GXCertificateRequest();
                it.Certificate     = GXPkcs10.CreateCertificateSigningRequest(kp, GXAsn1Converter.SystemTitleToSubject(_systemTitle));
                it.CertificateType = CertificateType.KeyAgreement;
                certifications.Add(it);
                GXx509Certificate[] certificates = GXPkcs10.GetCertificate(address, certifications);
                foreach (GXx509Certificate cert in certificates)
                {
                    if (cert.KeyUsage == KeyUsage.DigitalSignature)
                    {
                        path = "D" + GXDLMSTranslator.ToHex(_systemTitle, false);
                    }
                    else if (cert.KeyUsage == KeyUsage.KeyAgreement)
                    {
                        path = "A" + GXDLMSTranslator.ToHex(_systemTitle, false);
                    }
                    else if (cert.KeyUsage == (KeyUsage.KeyAgreement | KeyUsage.DigitalSignature))
                    {
                        path = "T" + GXDLMSTranslator.ToHex(_systemTitle, false);
                    }
                    else
                    {
                        path = "O" + GXDLMSTranslator.ToHex(_systemTitle, false);
                    }
                    path = Path.Combine(_certificateFolder, path) + ".pem";
                    cert.Save(path);
                }
            }
        }
Exemple #14
0
        //  https://tools.ietf.org/html/rfc5280#section-4.1
        private void Init(byte[] data)
        {
            rawData = data;
            GXAsn1Sequence seq = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(data);

            if (seq.Count != 3)
            {
                throw new GXDLMSCertificateException("Invalid Certificate Version. Wrong number of elements in sequence.");
            }
            if (!(seq[0] is GXAsn1Sequence))
            {
                PkcsType type = GXAsn1Converter.GetCertificateType(data, seq);
                switch (type)
                {
                case PkcsType.Pkcs8:
                    throw new GXDLMSCertificateException("Invalid Certificate. This is PKCS 8 private key, not x509 certificate.");

                case PkcsType.Pkcs10:
                    throw new GXDLMSCertificateException("Invalid Certificate. This is PKCS 10 certification requests, not x509 certificate.");
                }
                throw new GXDLMSCertificateException("Invalid Certificate Version.");
            }
            GXAsn1Sequence reqInfo = (GXAsn1Sequence)seq[0];

            if ((reqInfo[0] is GXAsn1Integer))
            {
                throw new GXDLMSCertificateException("Invalid Certificate. DLMS certificate version number must be 3.");
            }
            Version = (CertificateVersion)((GXAsn1Context)reqInfo[0])[0];
            if (reqInfo[1] is sbyte)
            {
                SerialNumber = Convert.ToUInt64(reqInfo[1]);
            }
            else
            {
                SerialNumber = new BigInteger(((GXAsn1Integer)reqInfo[1]).Value);
            }
            string tmp = ((GXAsn1Sequence)reqInfo[2])[0].ToString();

            // Signature Algorithm
            SignatureAlgorithm = HashAlgorithmConverter.FromString(tmp);
            if (SignatureAlgorithm != HashAlgorithm.Sha256WithEcdsa)
            {
                throw new Exception("DLMS certificate must be signed with ecdsa-with-SHA256.");
            }
            // Optional.
            if (((GXAsn1Sequence)reqInfo[2]).Count > 1)
            {
                SignatureParameters = ((GXAsn1Sequence)reqInfo[2])[1];
            }
            // Issuer
            Issuer = GXAsn1Converter.GetSubject((GXAsn1Sequence)reqInfo[3]);
            bool basicConstraintsExists = false;

            // Validity
            ValidFrom = (DateTime)((GXAsn1Sequence)reqInfo[4])[0];
            ValidTo   = (DateTime)((GXAsn1Sequence)reqInfo[4])[1];
            Subject   = GXAsn1Converter.GetSubject((GXAsn1Sequence)reqInfo[5]);
            string CN = X509NameConverter.GetString(X509Name.CN);
            // Subject public key Info
            GXAsn1Sequence subjectPKInfo = (GXAsn1Sequence)reqInfo[6];

            PublicKey = GXPublicKey.FromRawBytes(((GXAsn1BitString)subjectPKInfo[1]).Value);
            GXEcdsa.Validate(PublicKey);
            // Get Standard Extensions.
            if (reqInfo.Count > 7)
            {
                foreach (GXAsn1Sequence s in (GXAsn1Sequence)((GXAsn1Context)reqInfo[7])[0])
                {
                    GXAsn1ObjectIdentifier id = (GXAsn1ObjectIdentifier)s[0];
                    object value          = s[1];
                    X509CertificateType t = X509CertificateTypeConverter.FromString(id.ToString());
                    switch (t)
                    {
                    case X509CertificateType.SubjectKeyIdentifier:
                        SubjectKeyIdentifier = (byte[])value;
                        break;

                    case X509CertificateType.AuthorityKeyIdentifier:
                        foreach (GXAsn1Context it in (GXAsn1Sequence)value)
                        {
                            switch (it.Index)
                            {
                            case 0:
                                //Authority Key Identifier.
                                AuthorityKeyIdentifier = (byte[])it[0];
                                break;

                            case 1:
                            {
                                StringBuilder sb = new StringBuilder();
                                //authorityCertIssuer
                                foreach (KeyValuePair <object, object> it2 in ((GXAsn1Sequence)((GXAsn1Context)it[0])[0]))
                                {
                                    if (sb.Length != 0)
                                    {
                                        sb.Append(", ");
                                    }
                                    sb.Append(X509NameConverter.FromString(Convert.ToString(it2.Key)));
                                    sb.Append("=");
                                    sb.Append(Convert.ToString(it2.Value));
                                }
                                AuthorityCertIssuer = sb.ToString();
                            }
                            break;

                            case 2:
                                //Authority cert serial number .
                                AuthorityCertificationSerialNumber = (byte[])it[0];
                                break;

                            default:
                                throw new ArgumentOutOfRangeException("Invalid context." + it.Index);
                            }
                        }
                        break;

                    case X509CertificateType.KeyUsage:
                        if (value is GXAsn1BitString)
                        {
                            // critical is optional. BOOLEAN DEFAULT FALSE,
                            KeyUsage = (KeyUsage)((GXAsn1BitString)value).ToInteger();
                        }
                        else if (value is bool?)
                        {
                            value    = s[2];
                            KeyUsage = (KeyUsage)((GXAsn1BitString)value).ToInteger();
                        }
                        else
                        {
                            throw new ArgumentException("Invalid key usage.");
                        }
                        break;

                    case X509CertificateType.BasicConstraints:
                        basicConstraintsExists = true;
                        if (value is GXAsn1Sequence)
                        {
                            if (((GXAsn1Sequence)value).Count != 0)
                            {
                                BasicConstraints = (bool)((GXAsn1Sequence)value)[0];
                            }
                        }
                        else if (value is bool?)
                        {
                            BasicConstraints = (bool)value;
                        }
                        else
                        {
                            throw new ArgumentException("Invalid key usage.");
                        }
                        break;

                    default:
                        System.Diagnostics.Debug.WriteLine("Unknown extensions: " + t.ToString());
                        break;
                    }
                }
            }
            if (!basicConstraintsExists)
            {
                // Verify that subject Common Name includes system title.
                bool commonNameFound = false;
                foreach (KeyValuePair <object, object> it in (GXAsn1Sequence)reqInfo[5])
                {
                    if (CN == it.Key.ToString())
                    {
                        if (Convert.ToString(it.Value).Length != 16)
                        {
                            throw new GXDLMSCertificateException("System title is not included in Common Name.");
                        }
                        commonNameFound = true;
                        break;
                    }
                }
                if (!commonNameFound)
                {
                    throw new GXDLMSCertificateException("Common name doesn't exist.");
                }
            }

            if (KeyUsage == KeyUsage.None)
            {
                throw new Exception("Key usage not present. It's mandotory.");
            }
            if ((KeyUsage & (KeyUsage.KeyCertSign | KeyUsage.CrlSign)) != 0 && !basicConstraintsExists)
            {
                throw new Exception("Basic Constraints value not present. It's mandotory.");
            }
            PublicKeyAlgorithm = HashAlgorithmConverter.FromString(((GXAsn1Sequence)seq[1])[0].ToString());
            if (PublicKeyAlgorithm != HashAlgorithm.Sha256WithEcdsa)
            {
                throw new Exception("DLMS certificate must be signed with ecdsa-with-SHA256.");
            }
            // Optional.
            if (((GXAsn1Sequence)seq[1]).Count > 1)
            {
                PublicKeyParameters = ((GXAsn1Sequence)seq[1])[1];
            }
            /////////////////////////////
            //Get signature.
            Signature = ((GXAsn1BitString)seq[2]).Value;
        }
Exemple #15
0
        private void Init(byte[] data)
        {
            Attributes = new List <KeyValuePair <PkcsObjectIdentifier, object[]> >();
            GXAsn1Sequence seq = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(data);

            if (seq.Count < 3)
            {
                throw new System.ArgumentException("Wrong number of elements in sequence.");
            }
            /////////////////////////////
            // CertificationRequestInfo ::= SEQUENCE {
            // version INTEGER { v1(0) } (v1,...),
            // subject Name,
            // subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
            // attributes [0] Attributes{{ CRIAttributes }}
            // }

            GXAsn1Sequence reqInfo = (GXAsn1Sequence)seq[0];

            Version = (CertificateVersion)(sbyte)reqInfo[0];
            Subject = GXAsn1Converter.GetSubject((GXAsn1Sequence)reqInfo[1]);
            // subject Public key info.
            GXAsn1Sequence subjectPKInfo = (GXAsn1Sequence)reqInfo[2];

            if (reqInfo.Count > 3)
            {
                //PkcsObjectIdentifier
                foreach (GXAsn1Sequence it in (GXAsn1Context)reqInfo[3])
                {
                    List <object> values = new List <object>();
                    foreach (object v in (List <object>)((KeyValuePair <object, object>)it[1]).Key)
                    {
                        values.Add(v);
                    }
                    Attributes.Add(new KeyValuePair <PkcsObjectIdentifier, object[]>(PkcsObjectIdentifierConverter.FromString(it[0].ToString()), values.ToArray()));
                }
            }
            GXAsn1Sequence tmp = (GXAsn1Sequence)subjectPKInfo[0];

            Algorithm = X9ObjectIdentifierConverter.FromString(tmp[0].ToString());
            if (Algorithm != X9ObjectIdentifier.IdECPublicKey)
            {
                object algorithm = Algorithm;
                if (Algorithm == X9ObjectIdentifier.None)
                {
                    algorithm = PkcsObjectIdentifierConverter.FromString(tmp[0].ToString());
                    if ((PkcsObjectIdentifier)algorithm == PkcsObjectIdentifier.None)
                    {
                        algorithm = tmp[0].ToString();
                    }
                }
                throw new Exception("Invalid PKCS #10 certificate algorithm. " + algorithm);
            }
            PublicKey = GXPublicKey.FromRawBytes(((GXAsn1BitString)subjectPKInfo[1]).Value);
            GXEcdsa.Validate(PublicKey);
            /////////////////////////////
            // signatureAlgorithm
            GXAsn1Sequence sign = (GXAsn1Sequence)seq[1];

            SignatureAlgorithm = HashAlgorithmConverter.FromString(sign[0].ToString());
            if (SignatureAlgorithm != HashAlgorithm.Sha256WithEcdsa && SignatureAlgorithm != HashAlgorithm.Sha384WithEcdsa)
            {
                throw new GXDLMSCertificateException("Invalid signature algorithm. " + sign[0].ToString());
            }
            if (sign.Count != 1)
            {
                SignatureParameters = sign[1];
            }
            /////////////////////////////
            // signature
            Signature = ((GXAsn1BitString)seq[2]).Value;
            GXEcdsa        e    = new GXEcdsa(PublicKey);
            GXAsn1Sequence tmp2 = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(Signature);
            GXByteBuffer   bb   = new GXByteBuffer();
            int            size = SignatureAlgorithm == HashAlgorithm.Sha256WithEcdsa ? 32 : 48;

            //Some implementations might add extra byte. It must removed.
            bb.Set(((GXAsn1Integer)tmp2[0]).Value, ((GXAsn1Integer)tmp2[0]).Value.Length == size ? 0 : 1, size);
            bb.Set(((GXAsn1Integer)tmp2[1]).Value, ((GXAsn1Integer)tmp2[1]).Value.Length == size ? 0 : 1, size);
            if (!e.Verify(bb.Array(), GXAsn1Converter.ToByteArray(reqInfo)))
            {
                throw new ArgumentException("Invalid Signature.");
            }
        }
Exemple #16
0
        /// <summary>
        /// Decrypt data.
        /// </summary>
        /// <param name="p">Decryption parameters</param>
        /// <returns>Decrypted data.</returns>
        public static byte[] DecryptAesGcm(AesGcmParameter p, GXByteBuffer data)
        {
            if (data == null || data.Size < 2)
            {
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            byte[]  tmp;
            int     len;
            Command cmd = (Command)data.GetUInt8();

            switch (cmd)
            {
            case Command.GeneralGloCiphering:
            case Command.GeneralDedCiphering:
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    p.SystemTitle = new byte[len];
                    data.Get(p.SystemTitle);
                    if (p.Xml != null && p.Xml.Comments)
                    {
                        p.Xml.AppendComment(GXCommon.SystemTitleToString(Standard.DLMS, p.SystemTitle, true));
                    }
                }
                if (p.SystemTitle == null || p.SystemTitle.Length != 8)
                {
                    if (p.Xml == null)
                    {
                        throw new ArgumentNullException("Invalid sender system title.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Invalid sender system title.");
                    }
                }
                break;

            case Command.GeneralCiphering:
            case Command.GloInitiateRequest:
            case Command.GloInitiateResponse:
            case Command.GloReadRequest:
            case Command.GloReadResponse:
            case Command.GloWriteRequest:
            case Command.GloWriteResponse:
            case Command.GloGetRequest:
            case Command.GloGetResponse:
            case Command.GloSetRequest:
            case Command.GloSetResponse:
            case Command.GloMethodRequest:
            case Command.GloMethodResponse:
            case Command.GloEventNotification:
            case Command.DedInitiateRequest:
            case Command.DedInitiateResponse:
            case Command.DedGetRequest:
            case Command.DedGetResponse:
            case Command.DedSetRequest:
            case Command.DedSetResponse:
            case Command.DedMethodRequest:
            case Command.DedMethodResponse:
            case Command.DedEventNotification:
            case Command.DedReadRequest:
            case Command.DedReadResponse:
            case Command.DedWriteRequest:
            case Command.DedWriteResponse:
            case Command.GloConfirmedServiceError:
            case Command.DedConfirmedServiceError:
                break;

            default:
                throw new ArgumentOutOfRangeException("cryptedData");
            }
            int          value         = 0;
            GXPrivateKey key           = null;
            GXPublicKey  pub           = null;
            GXByteBuffer transactionId = null;

            if (cmd == Command.GeneralCiphering)
            {
                transactionId = new GXByteBuffer();
                len           = GXCommon.GetObjectCount(data);
                GXCommon.SetObjectCount(len, transactionId);
                transactionId.Set(data, len);
                p.TransactionId = transactionId.GetUInt64(1);
                len             = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.SystemTitle = tmp;
                }
                if (p.SystemTitle == null || p.SystemTitle.Length != 8)
                {
                    if (p.Xml == null)
                    {
                        throw new ArgumentNullException("Invalid sender system title.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Invalid sender system title.");
                    }
                }
                len = GXCommon.GetObjectCount(data);
                tmp = new byte[len];
                data.Get(tmp);
                p.RecipientSystemTitle = tmp;
                // Get date time.
                len = GXCommon.GetObjectCount(data);
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.DateTime = tmp;
                }
                // other-information
                len = data.GetUInt8();
                if (len != 0)
                {
                    tmp = new byte[len];
                    data.Get(tmp);
                    p.OtherInformation = tmp;
                }
                // KeyInfo OPTIONAL
                len = data.GetUInt8();
                // AgreedKey CHOICE tag.
                data.GetUInt8();
                // key-parameters
                len             = data.GetUInt8();
                value           = data.GetUInt8();
                p.KeyParameters = value;
                if (value == (int)KeyAgreementScheme.OnePassDiffieHellman)
                {
                    // key-ciphered-data
                    len = GXCommon.GetObjectCount(data);
                    GXByteBuffer bb = new GXByteBuffer();
                    bb.Set(data, len);
                    if (p.Xml != null)
                    {
                        p.KeyCipheredData = bb.Array();
                        //Find key agreement key using subject.
                        string subject = GXAsn1Converter.SystemTitleToSubject(p.SystemTitle);
                        foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                        {
                            if (it.Key != null && it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                            {
                                key = it.Key.PrivateKey;
                                //Get recipient Ephemeral public key.
                                subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle);
                                foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it2 in p.Settings.Keys)
                                {
                                    if (it2.Value != null && it2.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it2.Value.Subject.Contains(subject))
                                    {
                                        pub = it2.Value.PublicKey;
                                        break;
                                    }
                                }
                                break;
                            }
                        }
                        if (key == null)
                        {
                            //Find key agreement key using subject.
                            subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle);
                            foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                            {
                                if (it.Key != null && it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                                {
                                    key = it.Key.PrivateKey;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        key = p.Settings.Cipher.KeyAgreementKeyPair.Key;
                    }
                    if (key != null && pub == null)
                    {
                        //Get Ephemeral public key.
                        int keySize = len / 2;
                        pub = GXPublicKey.FromRawBytes(bb.SubArray(0, keySize));
                    }
                }
                else if (value == (int)KeyAgreementScheme.StaticUnifiedModel)
                {
                    len = GXCommon.GetObjectCount(data);
                    if (len != 0)
                    {
                        throw new ArgumentException("Invalid key parameters");
                    }
                    if (p.Xml != null)
                    {
                        //Find key agreement key using subject.
                        string subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle);
                        foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                        {
                            if (it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                            {
                                key = it.Key.PrivateKey;
                                break;
                            }
                        }
                        if (key != null)
                        {
                            //Find key agreement key using subject.
                            subject = GXAsn1Converter.SystemTitleToSubject(p.Settings.SourceSystemTitle);
                            foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys)
                            {
                                if (it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject))
                                {
                                    pub = it.Value.PublicKey;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        key = p.Settings.Cipher.KeyAgreementKeyPair.Key;
                        pub = p.Settings.Cipher.KeyAgreementKeyPair.Value;
                    }
                }
                else
                {
                    throw new ArgumentException("key-parameters");
                }
            }
            len = GXCommon.GetObjectCount(data);
            if (len > data.Available)
            {
                throw new Exception("Not enought data.");
            }
            p.CipheredContent = data.Remaining();
            byte sc = data.GetUInt8();

            p.SecuritySuite = (SecuritySuite)(sc & 0x3);
            p.Security      = (Security)(sc & 0x30);
            if ((sc & 0x80) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Compression is used.");
            }
            if ((sc & 0x40) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Error: Key_Set is used.");
            }
            if ((sc & 0x20) != 0)
            {
                System.Diagnostics.Debug.WriteLine("Encryption is applied.");
            }
            if (key != null)
            {
                if (value == (int)KeyAgreementScheme.OnePassDiffieHellman)
                {
                    GXEcdsa c = new GXEcdsa(key);
                    //Get Ephemeral signing key and verify it.
                    byte[] z = c.GenerateSecret(pub);
                    System.Diagnostics.Debug.WriteLine("Originator ephemeral public key: " + pub.ToHex());
                    System.Diagnostics.Debug.WriteLine("Recipient private agreement key: " + key.ToHex());
                    System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true));

                    GXByteBuffer kdf = new GXByteBuffer();
                    kdf.Set(GXSecure.GenerateKDF(p.SecuritySuite, z,
                                                 p.SecuritySuite == SecuritySuite.Ecdsa256 ? AlgorithmId.AesGcm128 : AlgorithmId.AesGcm256,
                                                 p.SystemTitle,
                                                 p.RecipientSystemTitle,
                                                 null, null));
                    System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString());
                    p.BlockCipherKey = kdf.SubArray(0, 16);
                }
                else if (value == (int)KeyAgreementScheme.StaticUnifiedModel)
                {
                    GXEcdsa c = new GXEcdsa(key);
                    byte[]  z = c.GenerateSecret(pub);
                    System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true));
                    GXByteBuffer kdf = new GXByteBuffer();
                    kdf.Set(GXSecure.GenerateKDF(p.SecuritySuite, z,
                                                 p.SecuritySuite == SecuritySuite.Ecdsa256 ? AlgorithmId.AesGcm128 : AlgorithmId.AesGcm256,
                                                 p.SystemTitle,
                                                 transactionId.Array(),
                                                 p.RecipientSystemTitle,
                                                 null));
                    System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString());
                    p.BlockCipherKey = kdf.SubArray(0, 16);
                }
                else
                {
                    throw new ArgumentOutOfRangeException("Invalid Key-id value.");
                }
            }
            UInt32 invocationCounter = data.GetUInt32();

            p.InvocationCounter = invocationCounter;
            System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString());
            System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Data,
                                                                              false, data.Position, data.Size - data.Position));
            byte[] tag = new byte[12];
            byte[] encryptedData;
            int    length;

            if (p.Security == Security.Authentication)
            {
                length        = data.Size - data.Position - 12;
                encryptedData = new byte[length];
                data.Get(encryptedData);
                data.Get(tag);
                // Check tag.
                EncryptAesGcm(p, encryptedData);
                if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag))
                {
                    if (p.Xml == null)
                    {
                        throw new GXDLMSException("Decrypt failed. Invalid tag.");
                    }
                    else
                    {
                        p.Xml.AppendComment("Decrypt failed. Invalid tag.");
                    }
                }
                return(encryptedData);
            }
            byte[] ciphertext = null;
            if (p.Security == Security.Encryption)
            {
                length     = data.Size - data.Position;
                ciphertext = new byte[length];
                data.Get(ciphertext);
            }
            else if (p.Security == Security.AuthenticationEncryption)
            {
                length     = data.Size - data.Position - 12;
                ciphertext = new byte[length];
                data.Get(ciphertext);
                data.Get(tag);
            }
            byte[] aad = GetAuthenticatedData(p, ciphertext),
            iv = GetNonse(invocationCounter, p.SystemTitle);
            GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(p.Security, true,
                                                                    p.BlockCipherKey, aad, iv, tag);

            gcm.Write(ciphertext);
            byte[] decrypted = gcm.FlushFinalBlock();
            System.Diagnostics.Debug.WriteLine("Decrypted: " + GXCommon.ToHex(decrypted, true));
            if (p.Security != Security.Encryption)
            {
                if (!GXCommon.Compare(gcm.GetTag(), tag))
                {
                    if (p.Xml == null)
                    {
                        throw new Exception("Decrypt failed. Invalid authentication tag.");
                    }
                    p.Xml.AppendComment("Decrypt failed. Invalid authentication tag.");
                }
            }
            return(decrypted);
        }
Exemple #17
0
        ///<summary>
        /// Chipher text.
        ///</summary>
        ///<param name="settings">
        ///DLMS settings.
        ///</param>
        ///<param name="cipher">
        ///Cipher.
        ///</param>
        ///<param name="ic">
        ///Invocation counter.
        ///</param>
        ///<param name="data">
        ///Text to chipher.
        ///</param>
        ///<param name="secret">
        ///Secret.
        ///</param>
        ///<returns>
        ///Chiphered text.
        ///</returns>
        internal static byte[] Secure(GXDLMSSettings settings, GXICipher cipher, UInt32 ic, byte[] data, byte[] secret)
        {
            byte[] tmp;
            if (settings.Authentication == Authentication.High)
            {
                int len = secret.Length;
                if (len % 16 != 0)
                {
                    len += 16 - (secret.Length % 16);
                }
                byte[] p = new byte[len];
                byte[] s = new byte[16];
                byte[] x = new byte[16];
                int    i;
                data.CopyTo(p, 0);
                secret.CopyTo(s, 0);
                for (i = 0; i < p.Length; i += 16)
                {
                    Buffer.BlockCopy(p, i, x, 0, 16);
                    GXAes128.Encrypt(x, s);
                    Buffer.BlockCopy(x, 0, p, i, 16);
                }
                Buffer.BlockCopy(p, 0, x, 0, 16);
                return(x);
            }
            // Get server Challenge.
            GXByteBuffer challenge = new GXByteBuffer();

            // Get shared secret
            if (settings.Authentication == Authentication.HighGMAC ||
                settings.Authentication == Authentication.HighECDSA)
            {
                challenge.Set(data);
            }
            else if (settings.Authentication == Authentication.HighSHA256)
            {
                challenge.Set(secret);
            }
            else
            {
                challenge.Set(data);
                challenge.Set(secret);
            }
            tmp = challenge.Array();
            if (settings.Authentication == Authentication.HighMD5)
            {
#if !WINDOWS_UWP
                using (MD5 md5Hash = MD5.Create())
                {
                    tmp = md5Hash.ComputeHash(tmp);
                    return(tmp);
                }
#endif
            }
            else if (settings.Authentication == Authentication.HighSHA1)
            {
#if !WINDOWS_UWP
                using (SHA1 sha = new SHA1CryptoServiceProvider())
                {
                    tmp = sha.ComputeHash(tmp);
                    return(tmp);
                }
#endif
            }
            else if (settings.Authentication == Authentication.HighSHA256)
            {
                //Windows UWP, IOS ad Android don't support this.
#if !WINDOWS_UWP && !__IOS__ && !__ANDROID__
                using (SHA256 sha = new SHA256CryptoServiceProvider())
                {
                    tmp = sha.ComputeHash(tmp);
                    return(tmp);
                }
#endif
            }
            else if (settings.Authentication == Authentication.HighGMAC)
            {
                //SC is always Security.Authentication.
                AesGcmParameter p = new AesGcmParameter(0, Security.Authentication,
                                                        cipher.SecuritySuite,
                                                        ic,
                                                        secret,
                                                        cipher.BlockCipherKey,
                                                        cipher.AuthenticationKey);
                p.Type = CountType.Tag;
                challenge.Clear();
                //Security suite is 0.
                challenge.SetUInt8((byte)Security.Authentication);
                challenge.SetUInt32((UInt32)p.InvocationCounter);
                challenge.Set(GXDLMSChippering.EncryptAesGcm(p, tmp));
                tmp = challenge.Array();
                return(tmp);
            }
            else if (settings.Authentication == Authentication.HighECDSA)
            {
                if (cipher.SigningKeyPair.Key == null)
                {
                    throw new ArgumentNullException("SigningKeyPair is not set.");
                }
                GXEcdsa      sig = new GXEcdsa(cipher.SigningKeyPair.Key);
                GXByteBuffer bb  = new GXByteBuffer();
                bb.Set(settings.Cipher.SystemTitle);
                bb.Set(settings.SourceSystemTitle);
                if (settings.IsServer)
                {
                    bb.Set(settings.CtoSChallenge);
                    bb.Set(settings.StoCChallenge);
                }
                else
                {
                    bb.Set(settings.StoCChallenge);
                    bb.Set(settings.CtoSChallenge);
                }
                data = sig.Sign(bb.Array());
            }
            return(data);
        }
        byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, ValueEventArgs e)
        {
            if (e.Index == 1)
            {
                SecurityPolicy = (SecurityPolicy)e.Parameters;
            }
            else if (e.Index == 2)
            {
                try
                {
                    foreach (List <object> item in e.Parameters as List <object> )
                    {
                        GlobalKeyType type = (GlobalKeyType)Convert.ToInt32(item[0]);
                        byte[]        data = (byte[])item[1];
                        //if settings.Cipher is null non secure server is used.
                        //Keys are take in action after reply is generated.
                        switch (type)
                        {
                        case GlobalKeyType.UnicastEncryption:
                            GXDLMSSecureClient.Decrypt(settings.Kek, data);
                            break;

                        case GlobalKeyType.BroadcastEncryption:
                            //Invalid type
                            e.Error = ErrorCode.ReadWriteDenied;
                            break;

                        case GlobalKeyType.Authentication:
                            GXDLMSSecureClient.Decrypt(settings.Kek, data);
                            break;

                        case GlobalKeyType.Kek:
                            GXDLMSSecureClient.Decrypt(settings.Kek, data);
                            break;

                        default:
                            //Invalid type
                            e.Error = ErrorCode.ReadWriteDenied;
                            break;
                        }
                    }
                }
                catch (Exception)
                {
                    e.Error = ErrorCode.ReadWriteDenied;
                }
            }
            else if (e.Index == 3)
            {
                // key_agreement
                try
                {
                    List <Object> tmp   = (List <Object>)(e.Parameters as List <Object>)[0];
                    byte          keyId = (byte)tmp[0];
                    if (keyId != 0)
                    {
                        e.Error = ErrorCode.InconsistentClass;
                    }
                    else
                    {
                        byte[] data = (byte[])tmp[0];
                        // ephemeral public key
                        GXByteBuffer data2 = new GXByteBuffer(65);
                        data2.SetUInt8(keyId);
                        data2.Set(data, 0, 64);
                        GXByteBuffer sign = new GXByteBuffer();
                        sign.Set(data, 64, 64);
                        GXPublicKey pk      = null;
                        string      subject = SystemTitleToSubject(settings.SourceSystemTitle);
                        foreach (GXx509Certificate it in settings.Cipher.Certificates)
                        {
                            if ((it.KeyUsage & KeyUsage.DigitalSignature) != 0 && it.Subject == subject)
                            {
                                pk = it.PublicKey;
                                break;
                            }
                        }
                        if (pk == null) //TODO:|| !GXSecure.ValidateEphemeralPublicKeySignature(data2.Array(), sign.Array(), pk))
                        {
                            e.Error = ErrorCode.InconsistentClass;
                            settings.TargetEphemeralKey = null;
                        }
                        else
                        {
                            settings.TargetEphemeralKey = GXPublicKey.FromRawBytes(data2.SubArray(1, 64));
                            // Generate ephemeral keys.
                            KeyValuePair <GXPrivateKey, GXPublicKey> eKpS = settings.Cipher.EphemeralKeyPair;
                            if (eKpS.Key == null)
                            {
                                eKpS = GXEcdsa.GenerateKeyPair(GetEcc(SecuritySuite));
                                settings.Cipher.EphemeralKeyPair = eKpS;
                            }
                            // Generate shared secret.
                            return(null);
                        }
                    }
                }
                catch (Exception)
                {
                    e.Error = ErrorCode.InconsistentClass;
                }
            }
            else if (e.Index == 4)
            {
                // generate_key_pair
                CertificateType key = (CertificateType)(int)e.Parameters;
                KeyValuePair <GXPrivateKey, GXPublicKey> value = GXEcdsa.GenerateKeyPair(GetEcc(SecuritySuite));
                switch (key)
                {
                case CertificateType.DigitalSignature:
                    settings.Cipher.SigningKeyPair = value;
                    break;

                case CertificateType.KeyAgreement:
                    settings.Cipher.KeyAgreementKeyPair = value;
                    break;

                default:
                    e.Error = ErrorCode.InconsistentClass;
                    break;
                }
            }
            else if (e.Index == 5)
            {
                // generate_certificate_request
                CertificateType key = (CertificateType)(int)e.Parameters;
                try
                {
                    KeyValuePair <GXPrivateKey, GXPublicKey> kp = default(KeyValuePair <GXPrivateKey, GXPublicKey>);
                    switch (key)
                    {
                    case CertificateType.DigitalSignature:
                        kp = settings.Cipher.SigningKeyPair;
                        break;

                    case CertificateType.KeyAgreement:
                        kp = settings.Cipher.KeyAgreementKeyPair;
                        break;

                    default:
                        break;
                    }
                    if (kp.Key != null)
                    {
                        GXPkcs10 pkc10 = GXPkcs10.CreateCertificateSigningRequest(kp, SystemTitleToSubject(settings.Cipher.SystemTitle));
                        return(pkc10.Encoded);
                    }
                    else
                    {
                        e.Error = ErrorCode.ReadWriteDenied;
                    }
                }
                catch (Exception)
                {
                    e.Error = ErrorCode.ReadWriteDenied;
                }
            }
            else if (e.Index == 6)
            {
                // import_certificate
                GXx509Certificate cert = new GXx509Certificate((byte[])e.Parameters);
                if (cert.KeyUsage == 0)
                {
                    // At least one bit must be used.
                    e.Error = ErrorCode.InconsistentClass;
                }
                else
                {
                    settings.Cipher.Certificates.Add(cert);
                }
            }
            else if (e.Index == 7)
            {
                // export_certificate
                List <Object>     tmp  = (List <Object>)e.Parameters;
                short             type = (short)tmp[0];
                GXx509Certificate cert = null;
                lock (settings.Cipher.Certificates)
                {
                    if (type == 0)
                    {
                        tmp  = (List <Object>)tmp[1];
                        cert = FindCertificateByEntity(settings, (CertificateEntity)tmp[0], (CertificateType)tmp[1], (byte[])tmp[2]);
                    }
                    else if (type == 1)
                    {
                        tmp  = (List <Object>)tmp[1];
                        cert = FindCertificateBySerial(settings, (byte[])tmp[1], ASCIIEncoding.ASCII.GetString((byte[])tmp[2]));
                    }
                    if (cert == null)
                    {
                        e.Error = ErrorCode.InconsistentClass;
                    }
                    else
                    {
                        return(cert.Encoded);
                    }
                }
            }
            else if (e.Index == 8)
            {
                // remove_certificate
                List <Object>     tmp  = (List <Object>)((List <object>)e.Parameters)[0];
                short             type = (short)tmp[0];
                GXx509Certificate cert = null;
                lock (settings.Cipher.Certificates)
                {
                    if (type == 0)
                    {
                        cert = FindCertificateByEntity(settings, (CertificateEntity)tmp[1], (CertificateType)tmp[2], (byte[])tmp[3]);
                    }
                    else if (type == 1)
                    {
                        cert = FindCertificateBySerial(settings, (byte[])tmp[1], ASCIIEncoding.ASCII.GetString((byte[])tmp[2]));
                    }
                    if (cert == null)
                    {
                        e.Error = ErrorCode.InconsistentClass;
                    }
                    else
                    {
                        settings.Cipher.Certificates.Remove(cert);
                    }
                }
            }
            else
            {
                e.Error = ErrorCode.ReadWriteDenied;
            }
            //Return standard reply.
            return(null);
        }