title: How to use API and to initialize openssl properly?
body: <h1>how to use API and to initialize openssl properly?</h1>
  
  <p>I got to make opevpn work with Russian cryptostandard called GOST. 
  I know that there are existing products by <a href="http://www.cryptocom.ru/opensource/openvpn.html" rel="nofollow">cryptocom</a> which provides this opportunity. I've looked through their site and find out that they used openssl version 0.9.8 in demo version. I've tried demo. It works, but with shared libraries and outdated openssl and opevpn versions.</p>
  
  <p>Actual openssl version is <a href="http://www.openssl.org/source/openssl-1.0.1c.tar.gz" rel="nofollow">1.0.1c</a> by now and I want to use static libssl and libcripto (if possible). As I read in openssl <a href="http://www.openssl.org/news/changelog.html" rel="nofollow">changelog</a>, starting from version 1.0.0 library supports GOST crypto, (<strong>fyi</strong> implemented by cryptocom).</p>
  
  <hr>
  
  <h2>What I've done</h2>
  
  <p>I've downloaded and compiled openssl-1.0.1c like this:</p>
  
  <pre><code>mkdir ~/test
  cd ~/test
  wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
  ...
  tar xzf openssl-1.0.1c.tar.gz
  cd openssl-1.0.1c
  ./config enable-gost -fPIC no-shared
  ...
  make
  ...
  </code></pre>
  
  <p>I've wrote config file to enable GOST crypto algorithm <strong>~/test/openssl.cnf</strong></p>
  
  <pre><code>openssl_conf = openssl_def
  [openssl_def]
  engines = engine_section
  
  [engine_section]
  gost = gost_section
  
  [gost_section]
  engine_id = gost
  default_algorithms = ALL
  CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
  
  # man ca(1SSL)
  [ ca ]
  default_ca  = CA_default
  
  # man ca(1SSL)
  [ CA_default ]
  dir             = ./CA                    # 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.
  new_certs_dir   = $dir/newcerts           # default place for new certs.
  certificate     = $dir/ca.pem             # The CA certificate
  serial          = $dir/serial             # The current serial number
  crlnumber       = $dir/crlnumber          # the current crl number
  crl             = $dir/crl.pem            # The current CRL
  private_key     = $dir/private/cakey.pem  # The private key
  RANDFILE        = $dir/private/.rand      # private random number file
  x509_extensions = usr_cert                # The extentions to add to the cert
  name_opt        = ca_default              # Subject Name options
  cert_opt        = ca_default              # Certificate field options
  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
  policy          = policy_match
  
  # man ca(1SSL)
  [ policy_match ]
  countryName             = match
  stateOrProvinceName     = match
  organizationName        = match
  organizationalUnitName  = optional
  commonName              = supplied
  emailAddress            = optional
  
  # man req(1SSL)
  [ req ]
  default_bits        = 1024
  distinguished_name  = req_distinguished_name
  attributes          = req_attributes
  x509_extensions     = v3_ca 
  string_mask         = utf8only
  
  # man req(1SSL)
  [ req_distinguished_name ] 
  countryName                     = Country Name (2 letter code)
  countryName_default             = RU
  countryName_min                 = 2
  countryName_max                 = 2
  stateOrProvinceName             = State or Province Name (full name)
  stateOrProvinceName_default     = Moscow
  localityName                    = Locality Name (eg, city)
  localityName_default            = Moscow
  0.organizationName              = Organization Name (eg, company)
  0.organizationName_default      = Company Ltd
  organizationalUnitName          = Organizational Unit Name (eg, section)
  organizationalUnitName_default  = Organisation Unit
  commonName                      = Common Name (e.g. server FQDN or YOUR name)
  commonName_max                  = 64
  emailAddress                    = Email Address
  emailAddress_max                = 64
  
  # man req(1SSL)
  [ req_attributes ]
  challengePassword     = A challenge password
  challengePassword_min = 4
  challengePassword_max = 20
  unstructuredName      = An optional company name
  
  # man x509v3_config(5SSL)
  [ usr_cert ]
  basicConstraints       = CA:FALSE
  nsCertType             = client, email, objsign
  keyUsage               = nonRepudiation, digitalSignature, keyEncipherment
  nsComment              = "Some company OpenSSL Generated Certificate"
  subjectKeyIdentifier   = hash
  authorityKeyIdentifier = keyid,issuer
  
  # man x509v3_config(5SSL)
  [ v3_ca ]
  subjectKeyIdentifier=hash
  authorityKeyIdentifier=keyid:always,issuer
  basicConstraints = CA:true
  </code></pre>
  
  <p>Then I've looked through supported TLS ciphers:</p>
  
  <pre><code>OPENSSL_CONF=~/test/openssl.cnf ./apps/openssl ciphers -tls1
  WARNING: can't open config file: /usr/local/ssl/openssl.cnf
  ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:SRP-DSS-AES-256-CBC-SHA:SRP-RSA-AES-256-CBC-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:GOST2001-GOST89-GOST89:GOST94-GOST89-GOST89:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA:PSK-AES256-CBC-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:SRP-DSS-3DES-EDE-CBC-SHA:SRP-RSA-3DES-EDE-CBC-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA:PSK-3DES-EDE-CBC-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:SRP-DSS-AES-128-CBC-SHA:SRP-RSA-AES-128-CBC-SHA:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:DHE-RSA-SEED-SHA:DHE-DSS-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:SEED-SHA:CAMELLIA128-SHA:IDEA-CBC-SHA:PSK-AES128-CBC-SHA:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5:PSK-RC4-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC4-MD5
  </code></pre>
  
  <p>and found GOST. </p>
  
  <hr>
  
  <h2>What is my question is about :</h2>
  
  <p>I want to get TLS ciphers list using openssl API (I mean libcripto and libssl). I've wrote a small program which outputs TLS ciphers that openssl provides <strong>~/test/test.c</strong>:</p>
  
  <pre><code>#include &lt;openssl/ssl.h&gt;
  #include &lt;openssl/err.h&gt;
  #include &lt;stdio.h&gt;
  
  void show_available_tls_ciphers (void)
  {
    SSL_CTX *ctx;
    SSL *ssl;
    int i;
    const char *cipher_name;
    int priority = 0;
  
    ctx = SSL_CTX_new(TLSv1_method());
    if (!ctx) {
      ERR_print_errors_fp(stderr);    
      return;
    }
  
    ssl = SSL_new (ctx);
    if (!ssl) {
      ERR_print_errors_fp(stderr);
      SSL_CTX_free(ctx);
    }
  
    STACK_OF(SSL_CIPHER) *sk = SSL_get_ciphers(ssl);
    if(!sk) {
      ERR_print_errors_fp(stderr);
      SSL_CTX_free(ctx);
      SSL_free(ssl);
      return;
    }
  
    for(i=0; i&lt; sk_SSL_CIPHER_num(sk); ++i) {
      printf("%s\n",sk_SSL_CIPHER_value(sk,i)-&gt;name);
    }
  
    printf ("\n");
  
    SSL_free (ssl);
    SSL_CTX_free (ctx);
  }
  
  
  int main(void) {
    CRYPTO_malloc_init();
    SSL_library_init();
    ERR_load_crypto_strings();
  
    OpenSSL_add_all_algorithms();
    ENGINE_load_builtin_engines();
    OpenSSL_add_ssl_algorithms();
  
    SSL_load_error_strings();
    show_available_tls_ciphers();
    return 0;
  }
  </code></pre>
  
  <p>Compiled like that </p>
  
  <pre><code>cd ~/test
  gcc test.c  -g -O0 -I~/test/openssl-1.0.1c/include -L~/test/openssl-1.0.1c -lssl -lcrypto -ldl
  </code></pre>
  
  <p>But my result differs from <code>OPENSSL_CONF=~/test/openssl.cnf ./apps/openssl ciphers -tls11</code> output above and doesn't include GOST:</p>
  
  <pre><code>OPENSSL_CONF=~/test/openssl.cnf ./a.out
  ECDHE-RSA-AES256-GCM-SHA384
  ECDHE-ECDSA-AES256-GCM-SHA384
  ECDHE-RSA-AES256-SHA384
  ECDHE-ECDSA-AES256-SHA384
  ECDHE-RSA-AES256-SHA
  ECDHE-ECDSA-AES256-SHA
  SRP-DSS-AES-256-CBC-SHA
  SRP-RSA-AES-256-CBC-SHA
  DHE-DSS-AES256-GCM-SHA384
  DHE-RSA-AES256-GCM-SHA384
  DHE-RSA-AES256-SHA256
  DHE-DSS-AES256-SHA256
  DHE-RSA-AES256-SHA
  DHE-DSS-AES256-SHA
  DHE-RSA-CAMELLIA256-SHA
  DHE-DSS-CAMELLIA256-SHA
  ECDH-RSA-AES256-GCM-SHA384
  ECDH-ECDSA-AES256-GCM-SHA384
  ECDH-RSA-AES256-SHA384
  ECDH-ECDSA-AES256-SHA384
  ECDH-RSA-AES256-SHA
  ECDH-ECDSA-AES256-SHA
  AES256-GCM-SHA384
  AES256-SHA256
  AES256-SHA
  CAMELLIA256-SHA
  PSK-AES256-CBC-SHA
  ECDHE-RSA-DES-CBC3-SHA
  ECDHE-ECDSA-DES-CBC3-SHA
  SRP-DSS-3DES-EDE-CBC-SHA
  SRP-RSA-3DES-EDE-CBC-SHA
  EDH-RSA-DES-CBC3-SHA
  EDH-DSS-DES-CBC3-SHA
  ECDH-RSA-DES-CBC3-SHA
  ECDH-ECDSA-DES-CBC3-SHA
  DES-CBC3-SHA
  PSK-3DES-EDE-CBC-SHA
  ECDHE-RSA-AES128-GCM-SHA256
  ECDHE-ECDSA-AES128-GCM-SHA256
  ECDHE-RSA-AES128-SHA256
  ECDHE-ECDSA-AES128-SHA256
  ECDHE-RSA-AES128-SHA
  ECDHE-ECDSA-AES128-SHA
  SRP-DSS-AES-128-CBC-SHA
  SRP-RSA-AES-128-CBC-SHA
  DHE-DSS-AES128-GCM-SHA256
  DHE-RSA-AES128-GCM-SHA256
  DHE-RSA-AES128-SHA256
  DHE-DSS-AES128-SHA256
  DHE-RSA-AES128-SHA
  DHE-DSS-AES128-SHA
  DHE-RSA-SEED-SHA
  DHE-DSS-SEED-SHA
  DHE-RSA-CAMELLIA128-SHA
  DHE-DSS-CAMELLIA128-SHA
  ECDH-RSA-AES128-GCM-SHA256
  ECDH-ECDSA-AES128-GCM-SHA256
  ECDH-RSA-AES128-SHA256
  ECDH-ECDSA-AES128-SHA256
  ECDH-RSA-AES128-SHA
  ECDH-ECDSA-AES128-SHA
  AES128-GCM-SHA256
  AES128-SHA256
  AES128-SHA
  SEED-SHA
  CAMELLIA128-SHA
  IDEA-CBC-SHA
  PSK-AES128-CBC-SHA
  ECDHE-RSA-RC4-SHA
  ECDHE-ECDSA-RC4-SHA
  ECDH-RSA-RC4-SHA
  ECDH-ECDSA-RC4-SHA
  RC4-SHA
  RC4-MD5
  PSK-RC4-SHA
  EDH-RSA-DES-CBC-SHA
  EDH-DSS-DES-CBC-SHA
  DES-CBC-SHA
  EXP-EDH-RSA-DES-CBC-SHA
  EXP-EDH-DSS-DES-CBC-SHA
  EXP-DES-CBC-SHA
  EXP-RC2-CBC-MD5
  EXP-RC4-MD5
  </code></pre>
  
  <p>To write this, I've used code and openssl initialization order from openssl-1.0.1c/apps/ciphers.c file.</p>
  
  <p>Why can't I see GOST in <code>a.out</code> output, what have I done wrong? How should I write my code, to work with openssl properly to see GOST in output of my test program?</p>