2r2w
2r2w

Reputation: 1509

How to use API and to initialize openssl properly?

how to use API and to initialize openssl properly?

I got to make opevpn work with Russian cryptostandard called GOST. I know that there are existing products by cryptocom 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.

Actual openssl version is 1.0.1c by now and I want to use static libssl and libcripto (if possible). As I read in openssl changelog, starting from version 1.0.0 library supports GOST crypto, (fyi implemented by cryptocom).


What I've done

I've downloaded and compiled openssl-1.0.1c like this:

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
...

I've wrote config file to enable GOST crypto algorithm ~/test/openssl.cnf

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

Then I've looked through supported TLS ciphers:

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

and found GOST.


What is my question is about :

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 ~/test/test.c:

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <stdio.h>

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< sk_SSL_CIPHER_num(sk); ++i) {
    printf("%s\n",sk_SSL_CIPHER_value(sk,i)->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;
}

Compiled like that

cd ~/test
gcc test.c  -g -O0 -I~/test/openssl-1.0.1c/include -L~/test/openssl-1.0.1c -lssl -lcrypto -ldl

But my result differs from OPENSSL_CONF=~/test/openssl.cnf ./apps/openssl ciphers -tls11 output above and doesn't include GOST:

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

To write this, I've used code and openssl initialization order from openssl-1.0.1c/apps/ciphers.c file.

Why can't I see GOST in a.out 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?

Upvotes: 1

Views: 7116

Answers (2)

Dmitry
Dmitry

Reputation: 11

You should call this at the first instruction to load default config:

OPENSSL_config(NULL);

All ciphers will be loaded including gost from config. Also you may set this after loading config:

'#define CIPHER_LIST "GOST2001-NULL-GOST94"//GOST2001-GOST89-GOST89 (chose one)

SSL_CTX_set_cipher_list(ctx, CIPHER_LIST)

and you will get only this chipher.

Upvotes: 1

Dirk-Willem van Gulik
Dirk-Willem van Gulik

Reputation: 7704

In short - you're not calling the stuff that sets up the config.

Have a look at the source of apps/open ssl.c in the openssl package you fetched (chipers.c is the code linked against it based on $0 which you ran in 'openssl ciphers').

Note the bit that goes:

    p=getenv("OPENSSL_CONF");
    if (p == NULL)
            p=getenv("SSLEAY_CONF");
    if (p == NULL)
            p=to_free=make_config_name();

    default_config_file=p;

and then further down:

    config=NCONF_new(NULL);
    i=NCONF_load(config,p,&errline);
    if (i == 0) ...

which is how it sucks in the configs.

Dw.

Upvotes: 3

Related Questions