Dear Dmitry, Thank you very much for the help. Appreciate it. Regards, Shariful Alam
On Thu, Aug 26, 2021 at 12:01 PM Dmitry Belyavsky <beld...@gmail.com> wrote: > Dear Shariful, > > You can build your engine when it's feasible. > You can install it to the engine folder and get rid of dynamic_path, but > it's not necessary. > > I prefer explicitly loading the engine via the config file. > > > On Thu, Aug 26, 2021 at 7:56 PM Shariful Alam <dipto...@gmail.com> wrote: > >> Dear Dmitry, >> Thank you very much. After moving the above section at the end of the >> configuration file and add the dynamic path to the shared library like the >> following, >> ================== >> [rsa_section] >> engine_id = rsa-engine-new >> dynamic_path = /opt/openssl/lib/engines-1.1/rsa-engine-new.so >> ================== >> >> My engine load without any error. Thanks. >> One more question, Do I need to compile and install my engine >> with Openssl source code in-order for it to work with mod_ssl? >> >> Regards, >> Shariful Alam >> >> >> >> >> >> On Thu, Aug 26, 2021 at 10:30 AM Dmitry Belyavsky <beld...@gmail.com> >> wrote: >> >>> As I suspected, you have the remnants of main openssl config just after >>> your only directive in the [rsa_section] >>> >>> I'd suggest you moving the following lines >>> >>> ========= >>> [openssl_def] >>> engines = engine_section >>> >>> [engine_section] >>> rsa-engine-new = rsa_section >>> >>> [rsa_section] >>> engine_id = rsa-engine-new >>> ========== >>> to the end of your openssl.cnf >>> >>> On Thu, Aug 26, 2021 at 6:20 PM Shariful Alam <dipto...@gmail.com> >>> wrote: >>> >>>> Dmitry, >>>> Thank you for your response. >>>> >>>> As you have suggested, I have changed my engine name to maintain with >>>> the configuration file >>>> >>>> /* Engine Id and Name */ >>>> static const char *engine_rsa_id = "rsa-engine-new"; >>>> static const char *engine_rsa_name = "Dummy RSA engine for testing"; >>>> >>>> Here is my whole *openssl.cnf* file content >>>> >>>> ============================================================================================================================= >>>> >>>> # >>>> # OpenSSL example configuration file. >>>> # This is mostly being used for generation of certificate requests. >>>> # >>>> >>>> # Note that you can include other files from the main configuration >>>> # file using the .include directive. >>>> #.include filename >>>> >>>> # This definition stops the following lines choking if HOME isn't >>>> # defined. >>>> HOME = . >>>> >>>> openssl_conf = openssl_def >>>> >>>> [openssl_def] >>>> engines = engine_section >>>> >>>> [engine_section] >>>> rsa-engine-new = rsa_section >>>> >>>> [rsa_section] >>>> engine_id = rsa-engine-new >>>> >>>> # Extra OBJECT IDENTIFIER info: >>>> #oid_file = $ENV::HOME/.oid >>>> oid_section = new_oids >>>> >>>> # To use this configuration file with the "-extfile" option of the >>>> # "openssl x509" utility, name here the section containing the >>>> # X.509v3 extensions to use: >>>> # extensions = >>>> # (Alternatively, use a configuration file that has only >>>> # X.509v3 extensions in its main [= default] section.) >>>> >>>> [ new_oids ] >>>> >>>> # We can add new OIDs in here for use by 'ca', 'req' and 'ts'. >>>> # Add a simple OID like this: >>>> # testoid1=1.2.3.4 >>>> # Or use config file substitution like this: >>>> # testoid2=${testoid1}.5.6 >>>> >>>> # Policies used by the TSA examples. >>>> tsa_policy1 = 1.2.3.4.1 >>>> tsa_policy2 = 1.2.3.4.5.6 >>>> tsa_policy3 = 1.2.3.4.5.7 >>>> >>>> #################################################################### >>>> [ ca ] >>>> default_ca = CA_default # The default ca section >>>> >>>> #################################################################### >>>> [ CA_default ] >>>> >>>> dir = ./demoCA # Where everything is kept >>>> certs = $dir/certs # Where the issued certs are kept >>>> crl_dir = $dir/crl # Where the issued crl are kept >>>> database = $dir/index.txt # database index file. >>>> #unique_subject = no # Set to 'no' to allow creation of >>>> # several certs with same subject. >>>> new_certs_dir = $dir/newcerts # default place for new certs. >>>> >>>> certificate = $dir/cacert.pem # The CA certificate >>>> serial = $dir/serial # The current serial number >>>> crlnumber = $dir/crlnumber # the current crl number >>>> # must be commented out to leave a V1 CRL >>>> crl = $dir/crl.pem # The current CRL >>>> private_key = $dir/private/cakey.pem# The private key >>>> >>>> x509_extensions = usr_cert # The extensions to add to the cert >>>> >>>> # Comment out the following two lines for the "traditional" >>>> # (and highly broken) format. >>>> name_opt = ca_default # Subject Name options >>>> cert_opt = ca_default # Certificate field options >>>> >>>> # Extension copying option: use with caution. >>>> # copy_extensions = copy >>>> >>>> # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 >>>> CRLs >>>> # so this is commented out by default to leave a V1 CRL. >>>> # crlnumber must also be commented out to leave a V1 CRL. >>>> # crl_extensions = crl_ext >>>> >>>> default_days = 365 # how long to certify for >>>> default_crl_days= 30 # how long before next CRL >>>> default_md = default # use public key default MD >>>> preserve = no # keep passed DN ordering >>>> >>>> # A few difference way of specifying how similar the request should look >>>> # For type CA, the listed attributes must be the same, and the optional >>>> # and supplied fields are just that :-) >>>> policy = policy_match >>>> >>>> # For the CA policy >>>> [ policy_match ] >>>> countryName = match >>>> stateOrProvinceName = optional >>>> organizationName = optional >>>> organizationalUnitName = optional >>>> commonName = supplied >>>> emailAddress = optional >>>> >>>> # For the 'anything' policy >>>> # At this point in time, you must list all acceptable 'object' >>>> # types. >>>> [ policy_anything ] >>>> countryName = optional >>>> stateOrProvinceName = optional >>>> localityName = optional >>>> organizationName = optional >>>> organizationalUnitName = optional >>>> commonName = supplied >>>> emailAddress = optional >>>> >>>> #################################################################### >>>> [ req ] >>>> default_bits = 2048 >>>> default_keyfile = privkey.pem >>>> distinguished_name = req_distinguished_name >>>> attributes = req_attributes >>>> x509_extensions = v3_ca # The extensions to add to the self signed cert >>>> >>>> # Passwords for private keys if not present they will be prompted for >>>> # input_password = secret >>>> # output_password = secret >>>> >>>> # This sets a mask for permitted string types. There are several >>>> options. >>>> # default: PrintableString, T61String, BMPString. >>>> # pkix : PrintableString, BMPString (PKIX recommendation before 2004) >>>> # utf8only: only UTF8Strings (PKIX recommendation after 2004). >>>> # nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). >>>> # MASK:XXXX a literal mask value. >>>> # WARNING: ancient versions of Netscape crash on BMPStrings or >>>> UTF8Strings. >>>> string_mask = utf8only >>>> >>>> # req_extensions = v3_req # The extensions to add to a certificate >>>> request >>>> >>>> [ req_distinguished_name ] >>>> countryName = Country Name (2 letter code) >>>> countryName_default = AU >>>> countryName_min = 2 >>>> countryName_max = 2 >>>> >>>> stateOrProvinceName = State or Province Name (full name) >>>> stateOrProvinceName_default = Some-State >>>> >>>> localityName = Locality Name (eg, city) >>>> >>>> 0.organizationName = Organization Name (eg, company) >>>> 0.organizationName_default = Internet Widgits Pty Ltd >>>> >>>> # we can do this but it is not needed normally :-) >>>> #1.organizationName = Second Organization Name (eg, company) >>>> #1.organizationName_default = World Wide Web Pty Ltd >>>> >>>> organizationalUnitName = Organizational Unit Name (eg, section) >>>> #organizationalUnitName_default = >>>> >>>> commonName = Common Name (e.g. server FQDN or YOUR name) >>>> commonName_max = 64 >>>> >>>> emailAddress = Email Address >>>> emailAddress_max = 64 >>>> >>>> # SET-ex3 = SET extension number 3 >>>> >>>> [ req_attributes ] >>>> challengePassword = A challenge password >>>> challengePassword_min = 4 >>>> challengePassword_max = 20 >>>> >>>> unstructuredName = An optional company name >>>> >>>> [ usr_cert ] >>>> >>>> # These extensions are added when 'ca' signs a request. >>>> >>>> # This goes against PKIX guidelines but some CAs do it and some software >>>> # requires this to avoid interpreting an end user certificate as a CA. >>>> >>>> basicConstraints=CA:FALSE >>>> >>>> # Here are some examples of the usage of nsCertType. If it is omitted >>>> # the certificate can be used for anything *except* object signing. >>>> >>>> # This is OK for an SSL server. >>>> # nsCertType = server >>>> >>>> # For an object signing certificate this would be used. >>>> # nsCertType = objsign >>>> >>>> # For normal client use this is typical >>>> # nsCertType = client, email >>>> >>>> # and for everything including object signing: >>>> # nsCertType = client, email, objsign >>>> >>>> # This is typical in keyUsage for a client certificate. >>>> # keyUsage = nonRepudiation, digitalSignature, keyEncipherment >>>> >>>> # This will be displayed in Netscape's comment listbox. >>>> nsComment = "OpenSSL Generated Certificate" >>>> >>>> # PKIX recommendations harmless if included in all certificates. >>>> subjectKeyIdentifier=hash >>>> authorityKeyIdentifier=keyid,issuer >>>> >>>> # This stuff is for subjectAltName and issuerAltname. >>>> # Import the email address. >>>> # subjectAltName=email:copy >>>> # An alternative to produce certificates that aren't >>>> # deprecated according to PKIX. >>>> # subjectAltName=email:move >>>> >>>> # Copy subject details >>>> # issuerAltName=issuer:copy >>>> >>>> #nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem >>>> #nsBaseUrl >>>> #nsRevocationUrl >>>> #nsRenewalUrl >>>> #nsCaPolicyUrl >>>> #nsSslServerName >>>> >>>> # This is required for TSA certificates. >>>> # extendedKeyUsage = critical,timeStamping >>>> >>>> [ v3_req ] >>>> >>>> # Extensions to add to a certificate request >>>> >>>> basicConstraints = CA:FALSE >>>> keyUsage = nonRepudiation, digitalSignature, keyEncipherment >>>> >>>> [ v3_ca ] >>>> >>>> >>>> # Extensions for a typical CA >>>> >>>> >>>> # PKIX recommendation. >>>> >>>> subjectKeyIdentifier=hash >>>> >>>> authorityKeyIdentifier=keyid:always,issuer >>>> >>>> basicConstraints = critical,CA:true >>>> >>>> # Key usage: this is typical for a CA certificate. However since it will >>>> # prevent it being used as an test self-signed certificate it is best >>>> # left out by default. >>>> # keyUsage = cRLSign, keyCertSign >>>> >>>> # Some might want this also >>>> # nsCertType = sslCA, emailCA >>>> >>>> # Include email address in subject alt name: another PKIX recommendation >>>> # subjectAltName=email:copy >>>> # Copy issuer details >>>> # issuerAltName=issuer:copy >>>> >>>> # DER hex encoding of an extension: beware experts only! >>>> # obj=DER:02:03 >>>> # Where 'obj' is a standard or added object >>>> # You can even override a supported extension: >>>> # basicConstraints= critical, DER:30:03:01:01:FF >>>> >>>> [ crl_ext ] >>>> >>>> # CRL extensions. >>>> # Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. >>>> >>>> # issuerAltName=issuer:copy >>>> authorityKeyIdentifier=keyid:always >>>> >>>> [ proxy_cert_ext ] >>>> # These extensions should be added when creating a proxy certificate >>>> >>>> # This goes against PKIX guidelines but some CAs do it and some software >>>> # requires this to avoid interpreting an end user certificate as a CA. >>>> >>>> basicConstraints=CA:FALSE >>>> >>>> # Here are some examples of the usage of nsCertType. If it is omitted >>>> # the certificate can be used for anything *except* object signing. >>>> >>>> # This is OK for an SSL server. >>>> # nsCertType = server >>>> >>>> # For an object signing certificate this would be used. >>>> # nsCertType = objsign >>>> >>>> # For normal client use this is typical >>>> # nsCertType = client, email >>>> >>>> # and for everything including object signing: >>>> # nsCertType = client, email, objsign >>>> >>>> # This is typical in keyUsage for a client certificate. >>>> # keyUsage = nonRepudiation, digitalSignature, keyEncipherment >>>> >>>> # This will be displayed in Netscape's comment listbox. >>>> nsComment = "OpenSSL Generated Certificate" >>>> >>>> # PKIX recommendations harmless if included in all certificates. >>>> subjectKeyIdentifier=hash >>>> authorityKeyIdentifier=keyid,issuer >>>> >>>> # This stuff is for subjectAltName and issuerAltname. >>>> # Import the email address. >>>> # subjectAltName=email:copy >>>> # An alternative to produce certificates that aren't >>>> # deprecated according to PKIX. >>>> # subjectAltName=email:move >>>> >>>> # Copy subject details >>>> # issuerAltName=issuer:copy >>>> >>>> #nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem >>>> #nsBaseUrl >>>> #nsRevocationUrl >>>> #nsRenewalUrl >>>> #nsCaPolicyUrl >>>> #nsSslServerName >>>> >>>> # This really needs to be in place for it to be a proxy certificate. >>>> proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo >>>> >>>> #################################################################### >>>> [ tsa ] >>>> >>>> default_tsa = tsa_config1 # the default TSA section >>>> >>>> [ tsa_config1 ] >>>> >>>> # These are used by the TSA reply generation only. >>>> dir = ./demoCA # TSA root directory >>>> serial = $dir/tsaserial # The current serial number (mandatory) >>>> crypto_device = builtin # OpenSSL engine to use for signing >>>> signer_cert = $dir/tsacert.pem # The TSA signing certificate >>>> # (optional) >>>> certs = $dir/cacert.pem # Certificate chain to include in reply >>>> # (optional) >>>> signer_key = $dir/private/tsakey.pem # The TSA private key (optional) >>>> signer_digest = sha256 # Signing digest to use. (Optional) >>>> default_policy = tsa_policy1 # Policy if request did not specify it >>>> # (optional) >>>> other_policies = tsa_policy2, tsa_policy3 # acceptable policies >>>> (optional) >>>> digests = sha1, sha256, sha384, sha512 # Acceptable message >>>> digests (mandatory) >>>> accuracy = secs:1, millisecs:500, microsecs:100 # (optional) >>>> clock_precision_digits = 0 # number of digits after dot. (optional) >>>> ordering = yes # Is ordering defined for timestamps? >>>> # (optional, default: no) >>>> tsa_name = yes # Must the TSA name be included in the reply? >>>> # (optional, default: no) >>>> ess_cert_id_chain = no # Must the ESS cert id chain be included? >>>> # (optional, default: no) >>>> ess_cert_id_alg = sha1 # algorithm to compute certificate >>>> # identifier (optional, default: sha1) >>>> >>>> >>>> On Thu, Aug 26, 2021 at 7:39 AM Dmitry Belyavsky <beld...@gmail.com> >>>> wrote: >>>> >>>>> Dear Shariful, >>>>> >>>>> 1. Don't hurry :) >>>>> 2. It looks like there are some more configuration options in your >>>>> openssl.cnf [rsa_section] >>>>> I think they came from the standard configuration. So if I am wrong, >>>>> please provide the whole file. >>>>> 3. I'd recommend you also update the lines >>>>> ` >>>>> static const char *engine_dasync_id = "dasync"; >>>>> static const char *engine_dasync_name = "Dummy Async engine support"; >>>>> ` >>>>> To be consistent with your engine name >>>>> >>>>> On Thu, Aug 26, 2021 at 3:24 PM Shariful Alam <dipto...@gmail.com> >>>>> wrote: >>>>> >>>>>> Any help regarding this matter?? >>>>>> >>>>>> Regards, >>>>>> Shariful >>>>>> >>>>>> On Thu, Aug 26, 2021, 12:06 AM Shariful Alam <dipto...@gmail.com> >>>>>> wrote: >>>>>> >>>>>>> Hello, >>>>>>> >>>>>>> I have a simple rsa engine code (from engines/e_dasync.c). My code >>>>>>> compiles. Command "*$openssl engine -t -c*" shows the following, >>>>>>> >>>>>>> >>>>>>> openssl engine -t -c >>>>>>> >>>>>>> (rdrand) Intel RDRAND engine >>>>>>> >>>>>>> [RAND] >>>>>>> >>>>>>> [ available ] >>>>>>> >>>>>>> (dynamic) Dynamic engine loading support >>>>>>> >>>>>>> [ unavailable ] >>>>>>> >>>>>>> (dasync) Dummy Async engine support >>>>>>> >>>>>>> [RSA] >>>>>>> >>>>>>> [ available ] >>>>>>> >>>>>>> >>>>>>> I also modify *openssl.cnf* configuration as following to load this >>>>>>> engine, >>>>>>> >>>>>>> >>>>>>> openssl_conf = openssl_def >>>>>>> >>>>>>> >>>>>>> [openssl_def] >>>>>>> >>>>>>> engines = engine_section >>>>>>> >>>>>>> >>>>>>> [engine_section] >>>>>>> >>>>>>> rsa-engine-new = rsa_section >>>>>>> >>>>>>> >>>>>>> [rsa_section] >>>>>>> >>>>>>> engine_id = rsa-engine-new >>>>>>> >>>>>>> >>>>>>> Then when I run the command "$*openssl engine*", I get the >>>>>>> following error, >>>>>>> >>>>>>> $openssl engine >>>>>>> >>>>>>> (rdrand) Intel RDRAND engine >>>>>>> >>>>>>> (dynamic) Dynamic engine loading support >>>>>>> >>>>>>> (dasync) Dummy Async engine support >>>>>>> >>>>>>> 139633213376256:error:260AB089:engine >>>>>>> routines:ENGINE_ctrl_cmd_string:invalid cmd >>>>>>> name:crypto/engine/eng_ctrl.c:255: >>>>>>> >>>>>>> 139633213376256:error:260BC066:engine >>>>>>> routines:int_engine_configure:engine configuration >>>>>>> error:crypto/engine/eng_cnf.c:141:section=rsa_section, name=oid_section, >>>>>>> value=new_oids >>>>>>> >>>>>>> 139633213376256:error:0E07606D:configuration file >>>>>>> routines:module_run:module initialization >>>>>>> error:crypto/conf/conf_mod.c:177:module=engines, value=engine_section, >>>>>>> retcode=-1 >>>>>>> >>>>>>> >>>>>>> Any help why is this happening? How can I fix this? >>>>>>> >>>>>>> My goal is to use my OpenSSL engine with Apache for mod_ssl. Do I >>>>>>> have to compile my engine with the OpenSSL source code to do that? >>>>>>> >>>>>>> >>>>>>> Here is the complete source code of my sample engine, >>>>>>> >>>>>>> ============================================== >>>>>>> >>>>>>> >>>>>>> #include <stdio.h> >>>>>>> >>>>>>> #include <string.h> >>>>>>> >>>>>>> >>>>>>> #include <openssl/engine.h> >>>>>>> >>>>>>> #include <openssl/sha.h> >>>>>>> >>>>>>> #include <openssl/aes.h> >>>>>>> >>>>>>> #include <openssl/rsa.h> >>>>>>> >>>>>>> #include <openssl/evp.h> >>>>>>> >>>>>>> #include <openssl/async.h> >>>>>>> >>>>>>> #include <openssl/bn.h> >>>>>>> >>>>>>> #include <openssl/crypto.h> >>>>>>> >>>>>>> #include <openssl/ssl.h> >>>>>>> >>>>>>> #include <openssl/modes.h> >>>>>>> >>>>>>> >>>>>>> /* Engine Id and Name */ >>>>>>> >>>>>>> static const char *engine_dasync_id = "dasync"; >>>>>>> >>>>>>> static const char *engine_dasync_name = "Dummy Async engine support"; >>>>>>> >>>>>>> >>>>>>> static int dasync_pub_enc(int flen, const unsigned char *from, >>>>>>> >>>>>>> unsigned char *to, RSA *rsa, int padding) { >>>>>>> >>>>>>> printf("dasync_pub_enc\n"); >>>>>>> >>>>>>> >>>>>>> >>>>>>> return 0; >>>>>>> >>>>>>> } >>>>>>> >>>>>>> >>>>>>> static int dasync_pub_dec(int flen, const unsigned char *from, >>>>>>> >>>>>>> unsigned char *to, RSA *rsa, int padding) { >>>>>>> >>>>>>> printf("dasync_pub_dec\n"); >>>>>>> >>>>>>> >>>>>>> >>>>>>> return 0; >>>>>>> >>>>>>> } >>>>>>> >>>>>>> >>>>>>> static int dasync_rsa_priv_enc(int flen, const unsigned char *from, >>>>>>> unsigned char *to, RSA *rsa, int padding){ >>>>>>> >>>>>>> printf("dasync_rsa_priv_enc\n"); >>>>>>> >>>>>>> return 0; >>>>>>> >>>>>>> } >>>>>>> >>>>>>> >>>>>>> static int dasync_rsa_priv_dec(int flen, const unsigned char *from, >>>>>>> unsigned char *to, RSA *rsa, int padding){ >>>>>>> >>>>>>> printf("dasync_rsa_priv_dec\n"); >>>>>>> >>>>>>> return 0; >>>>>>> >>>>>>> } >>>>>>> >>>>>>> >>>>>>> >>>>>>> static RSA_METHOD *dasync_rsa_method = NULL; >>>>>>> >>>>>>> >>>>>>> >>>>>>> static int bind_dasync(ENGINE *e){ >>>>>>> >>>>>>> /* Setup RSA_METHOD */ >>>>>>> >>>>>>> if ((dasync_rsa_method = RSA_meth_new("Dummy Async RSA method", >>>>>>> 0)) == NULL >>>>>>> >>>>>>> || RSA_meth_set_pub_enc(dasync_rsa_method, dasync_pub_enc) >>>>>>> == 0 >>>>>>> >>>>>>> || RSA_meth_set_pub_dec(dasync_rsa_method, dasync_pub_dec) >>>>>>> == 0 >>>>>>> >>>>>>> || RSA_meth_set_priv_enc(dasync_rsa_method, >>>>>>> dasync_rsa_priv_enc) == 0 >>>>>>> >>>>>>> || RSA_meth_set_priv_dec(dasync_rsa_method, >>>>>>> dasync_rsa_priv_dec) == 0 >>>>>>> >>>>>>> ) { >>>>>>> >>>>>>> >>>>>>> return 0; >>>>>>> >>>>>>> } >>>>>>> >>>>>>> >>>>>>> /* Ensure the dasync error handling is set up */ >>>>>>> >>>>>>> >>>>>>> >>>>>>> if (!ENGINE_set_id(e, engine_dasync_id) >>>>>>> >>>>>>> || !ENGINE_set_name(e, engine_dasync_name) >>>>>>> >>>>>>> || !ENGINE_set_RSA(e, dasync_rsa_method) >>>>>>> >>>>>>> ) { >>>>>>> >>>>>>> return 0; >>>>>>> >>>>>>> } >>>>>>> >>>>>>> return 1; >>>>>>> >>>>>>> } >>>>>>> >>>>>>> >>>>>>> static int bind_helper(ENGINE *e, const char *id){ >>>>>>> >>>>>>> if (!bind_dasync(e)){ >>>>>>> >>>>>>> printf("2_Error: Inside Bind helper\n"); >>>>>>> >>>>>>> return 0; >>>>>>> >>>>>>> } >>>>>>> >>>>>>> return 1; >>>>>>> >>>>>>> } >>>>>>> >>>>>>> >>>>>>> IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) >>>>>>> >>>>>>> IMPLEMENT_DYNAMIC_CHECK_FN() >>>>>>> >>>>>>> >>>>>>> ============================================= >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> Thanks, >>>>>>> >>>>>>> Shariful >>>>>>> >>>>>>> >>>>> >>>>> -- >>>>> SY, Dmitry Belyavsky >>>>> >>>> >>> >>> -- >>> SY, Dmitry Belyavsky >>> >> > > -- > SY, Dmitry Belyavsky >