MicrochipTech/cryptoauth-openssl-engine

Integration issues

jimpnet opened this issue · 8 comments

I'm having issues getting basic client cert authentication to work. I'm working with a device that was provided with the cryptoquth-openssl-engine already integrated by the vendor so I'm not doing the compilation/integration myself. I've attempted to make a test as basic as possible based on the scripts in this project. The file ec-params.pem as the prime256v1 params, the file my-ca.crt is a self-signed CA cert, and my-ca.key is it's key. I use these commands to generate my client key and certificate:

openssl req -keygen_engine ateccx08 -newkey ec:ec-params.pem -subj "/O=Example/CN=11000308" -sha256 -keyout client.key -out device-csr.pem -verify

openssl x509 -req -in device-csr.pem -days 2000000 -CA my-ca.crt -CAcreateserial -CAkey my-ca.key -out client.crt

openssl ec -in client.key -out client.key

I get this output:

ATECCX08: bind_fn()
ATECCX08: ECCX08 bind_helper()
ATECCX08: eccx08_rand_init()
ATECCX08: eccx08_pkey_meth_init()
ATECCX08: eccx08_pkey_meth_init()
ATECCX08: eccx08_ecdh_init() - HW
ATECCX08: eccx08_cmd_defn_init()
ATECCX08: returned normally()
ATECCX08: eccx08_init()
ATECCX08: eccx08_pkey_meth_f()
ATECCX08: eccx08_pkey_ec_init() - hw
ATECCX08: eccx08_pkey_ec_keygen_init()
Generating a 256 bit EC private key
ATECCX08: eccx08_pkey_ec_keygen() - HW
ATECCX08: eccx08_finish()
writing new private key to '/opt/ext/etc/keys/client.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
ATECCX08: eccx08_item_sign() - HW
ATECCX08: ECDSA_eccx08_do_sign(): int eckey HW
verify OK
ATECCX08: eccx08_int_ec_free()
ATECCX08: eccx08_pkey_meth_f()
ATECCX08: eccx08_pkey_asn1_meth_f()
ATECCX08: eccx08_destroy()
Signature ok
subject=/O=Example/CN=11000308
Getting CA Private Key
read EC key
Enter PEM pass phrase:
writing EC key

I have a server.crt and server.key that are also signed by my-ca.crt. I run a server that does not integrate with the ecc508A using this command:

openssl s_server -CAfile my-ca.crt -cert server.crt -key server.key -Verify 2

Finally, I run a client like this:

openssl s_client -engine ateccx08 -connect localhost:4433 -CAfile my-ca.crt -cert client.crt -key client.key

with this output

ATECCX08: bind_fn()
ATECCX08: ECCX08 bind_helper()
ATECCX08: eccx08_rand_init()
ATECCX08: eccx08_pkey_meth_init()
ATECCX08: eccx08_pkey_meth_init()
ATECCX08: eccx08_ecdh_init() - HW
ATECCX08: eccx08_cmd_defn_init()
ATECCX08: returned normally()
ATECCX08: eccx08_ctrl()
ATECCX08: eccx08_init()
ATECCX08: eccx08_pkey_meth_f()
ATECCX08: eccx08_pkey_asn1_meth_f()
engine "ateccx08" set.
ATECCX08: RAND_eccx08_rand_bytes() -  hw
CONNECTED(00000003)
ATECCX08: eccx08_rsa_init()
depth=1 C = US, ST = ..., L = ..., O = ..., CN = ...
verify return:1
ATECCX08: eccx08_rsa_init()
depth=0 C = US, ST = ..., L = ..., O = ..., CN = ...
verify return:1
ATECCX08: ECDH_eccx08_compute_key(): HW 
ATECCX08: ECDH_eccx08_get_pubkey() - hw
ATECCX08: ECDSA_eccx08_do_sign(): ERROR dgst_len
1995924688:error:14099006:SSL routines:ssl3_send_client_verify:EVP lib:s3_clnt.c:3286:
---
Certificate chain
 0 s:/C=US/ST=.../L=.../O=.../CN=...
   i:/C=US/ST=.../L=.../O=.../CN=...
 1 s:/C=US/ST=.../L=.../O=.../CN=...
   i:/C=US/ST=.../L=.../O=.../CN=...
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject=/C=US/ST=.../L=.../O=.../CN=...
issuer=/C=US/ST=.../L=.../O=.../CN=...
---
Acceptable client certificate CA names
/C=US/ST=.../L=.../O=.../CN=...
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Shared Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:ECDSA+SHA512:RSA+SHA384:DSA+SHA384:ECDSA+SHA384:RSA+SHA256:DSA+SHA256:ECDSA+SHA256:RSA+SHA224:DSA+SHA224:ECDSA+SHA224:RSA+SHA1:DSA+SHA1:ECDSA+SHA1
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 2297 bytes and written 1560 bytes
---
New, (NONE), Cipher is (NONE)
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: ED8D7DFD9ADCF5F896DE93D6AF2B581D217809AFA12EA7FA396A85D174FB2B5849DFFBA3AB5284981D33BFE9257B7F7A
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1498848897
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
ATECCX08: eccx08_finish()
ATECCX08: eccx08_pkey_meth_f()
ATECCX08: eccx08_pkey_asn1_meth_f()
ATECCX08: eccx08_destroy()

As you can see I get this error ATECCX08: ECDSA_eccx08_do_sign(): ERROR dgst_len. I'm not sure why there is a key file when the key is stored in the hardware but your scripts included it so I kept it.

I should also note that if I omit the -keygen ateccx08 and -engine ateccx08 this all works fine.

I'd greatly appreciate any help you can provide.

Thanks.

Thank you so much. I will do that. Can you answer a couple more questions for me please:

How do I tell whether it's using SHA-512 or SHA-256?

What do I need to do to use this in code? I have something like this presently:

ENGINE_load_dynamic();
ENGINE *engine =  = ENGINE_by_id("ateccx08");
ENGINE_set_default_ECDH(engine) ;
ENGINE_set_default_RAND(engine);
ENGINE_set_default_pkey_asn1_meths(engine) ;
ENGINE_set_default_ECDSA(engine) ;
ENGINE_set_default_RSA(engine) ;
ENGINE_set_default_pkey_meths(engine) ;
ENGINE_set_default_ciphers(engine) ;
ENGINE_set_default_digests(engine) ;
ENGINE_set_default_DH(engine) ;
ENGINE_set_default_DSA(engine) ;
SSL_CTX_use_PrivateKey_file(ctx, keyfile, SSL_FILETYPE_PEM);

Should I have calls I am missing or remove any I have? I just called all the ENGINE_set_default_... functions. Do I still need to use the key? I'm not clear why that is.

Does the patch affect libraries or just the openssl executable?

Thanks again. You've been extremely helpful.

Also, is this a problem when I'm generating the keys/certs or just when I'm trying to connect?

I was able to get it to work by adding -client_sigalgs ECDSA+SHA256 to my openssl s_client ... command.

I'm still having issues getting it to work programatically though. Do you have an example of what I need to do as far as loading the engine, context settings, etc? The load and set default call in one of the comments above is all the farther I've gotten.

Thank you for all the help.

Jim, I assume you've probably already found what you need for programmatic use of an engine but for documentation and those encountering this issue later the general order of controlling the engine for all features would follow this pattern. The sigalgs and cipher sections are more generically applicable as they are how to restrict negotiation to just what is supported and can be used/tested without the engine being used.

    OpenSSL_add_all_algorithms();
    ERR_load_BIO_strings();
    ERR_load_crypto_strings();
    SSL_load_error_strings();

#ifdef USE_ENGINE
    ENGINE_load_dynamic();
    if (!CONF_modules_load_file(NULL, NULL, CONF_MFLAGS_DEFAULT_SECTION))
    {
        ERROR("Config failed to load");
    }

    /* Load the engine for testing */
    engine = ENGINE_by_id("ateccx08");

    if (engine == NULL)
    {
        ERROR("Engine failed to load");
    }

    if (!ENGINE_init(engine))
    {
        ERROR("Engine failed to initialize");
    }

    /* Register all engine functionality with OpenSSL */
    if (!ENGINE_register_complete(engine))
    {
        ERROR("Engine register failed");
    }
#endif

    if (SSL_library_init() < 0) {
        ret_val = SSL_INIT_ERROR;
    }

    method = TLSv1_2_method();

     if ((pSSLContext = SSL_CTX_new(method)) == NULL) {
          ERROR(" SSL INIT Failed - Unable to create SSL Context");
          ret_val = SSL_INIT_ERROR;
     }

#ifdef USE_ENGINE
     if(!SSL_CTX_set_client_cert_engine(pSSLContext, engine))
     {
          ERROR(" Error setting client cert engine");
     }
     ENGINE_free(engine);
#endif

     if(!SSL_CTX_set_cipher_list(pSSLContext, "ECDHE-ECDSA-AES128-GCM-SHA256"))
     {
          ERROR(" Unable to set cipher suite");
     }

     if(!SSL_CTX_set1_sigalgs_list(pSSLContext, "ECDSA+SHA256"))
     {
          ERROR(" Unable to set sigalgs");
     }
	
     if(!SSL_CTX_set1_client_sigalgs_list(pSSLContext, "ECDSA+SHA256"))
     {
          ERROR(" Unable to set client sigalgs");
     }