1 (edited by gquere 2012-09-17 04:33:15)

Topic: Modify CyaSSL embedded SSL random data signing (client authentication)

Hello,

I'm trying to modify the CyaSSL embedded SSL library. I wish to change the portion where the random data sent by the server is signed by the client using the client's private key, thus completing the client authentication.
I've spent some time trying to find the functions doing that but there's just too much code and I'm running in circles.

Could someone point me to the correct file/function ?
Thanks

Edit: right now i'm in  "int SendCertificateVerify(CYASSL* ssl)" of internal.c
Still would appreciate pointers smile

Share

Re: Modify CyaSSL embedded SSL random data signing (client authentication)

This is where I'm at now. I'm progressing step by step and still need help.
I could have used some comments in the code -_-

/**
 * SendCertificate: receives ssl connection parameters (it's a huge structure defined in ...)
 *        - get RSA private key of client (using what key ?)
 *         - build SHA-1 hash of certificate
 *        - encode digest (using what key ?)
 *        - sign it using RSA private key
**/


int SendCertificateVerify(CYASSL* ssl)
{
    byte              *output;
    int                sendSz = 0, length, ret;
    word32             idx = 0;
    word32             sigOutSz = 0;
    RsaKey             key;
    int                usingEcc = 0;
    int                     var = 0;

    // proof that this code is executed by the client
    printf(">> I AM A %d AND CLIENT_END IS %d\n", ssl->options.side, CLIENT_END);

    if (ssl->options.sendVerify == SEND_BLANK_CERT)
        return 0;  /* sent blank cert, can't verify */

    /* check for avalaible size */
    if ((ret = CheckAvalaibleSize(ssl, MAX_CERT_VERIFY_SZ)) != 0)
        return ret;

    /* get ouput buffer */        // output buffer of what ???
    output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length;

    // BuildCertHashes => Does this build the certificate hash ?
    BuildCertHashes(ssl, &ssl->certHashes);

    // Looks like we prepare room for the RSA key inside the ssl structure (since so far "key" is empty)
    InitRsaKey(&key, ssl->heap);

    // Decode RSA Private key from ssl structure and put it into key   <= what key do we use to do so ?
    ret = RsaPrivateKeyDecode(ssl->buffers.key.buffer, &idx, &key, ssl->buffers.key.length);

    if (ret == 0)
        sigOutSz = RsaEncryptSize(&key);
    else 
        {
        }
    if (ret == 0) 
        {
        byte*  verify = (byte*)&output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ];
        byte*  signBuffer = ssl->certHashes.md5;
        word32 signSz = sizeof(Hashes);
        byte   encodedSig[MAX_ENCODED_SIG_SZ];
        word32 extraSz = 0;  /* tls 1.2 hash/sig */

        length = sigOutSz;
        if (IsAtLeastTLSv1_2(ssl))
            {
            verify[0] = sha_mac;
            verify[1] = usingEcc ? ecc_dsa_sa_algo : rsa_sa_algo;
            extraSz = HASH_SIG_SIZE;
            }
        c16toa((word16)length, verify + extraSz); /* prepend verify header*/

        if (usingEcc) 
            {
            }
        else 
            {
            if (IsAtLeastTLSv1_2(ssl)) 
                {
                byte* digest;
                int   typeH;
                int   digestSz;

                /* sha1 for now */
                digest   = ssl->certHashes.sha;
                typeH    = SHAh;
                digestSz = SHA_DIGEST_SIZE;

                printf(">> This is my SHA-1 hash, which size is %d:\n", SHA_DIGEST_SIZE);
                for(var=0; var<SHA_DIGEST_SIZE; var++)
                    printf("%d ", digest[var]); 
                printf("\n");

                // encode signature: input digest and size and type of hash, output signature and size
                signSz = EncodeSignature(encodedSig, digest, digestSz, typeH);
                signBuffer = encodedSig;

                printf(">> This is my encoded hash, which size is %d:\n", signSz);
                for(var=0; var<signSz; var++)
                    printf("%d ", encodedSig[var]); 
                printf("\n");
                }

            // sign the encoded signature: 
                // input index in a buffer, private RSA key, encrypt len (512)
                // output is in signBuffer, probably rng (random number genrator ??)
            ret = RsaSSL_Sign(signBuffer, signSz, verify + extraSz + VERIFY_HEADER, ENCRYPT_LEN, &key, &ssl->rng);

            printf(">> This is my signed encoded hash, which size is %d:\n", ENCRYPT_LEN);
            for(var=0; var<ENCRYPT_LEN; var++)
                printf("%d ", signBuffer[var]); 
            printf("\n");

            if (ret > 0)
                ret = 0;  /* RSA reset */
            }
        
        if (ret == 0) 
            {
            // add header to certificate ??
            AddHeaders(output, length + extraSz + VERIFY_HEADER, certificate_verify, ssl);
            sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length + extraSz + VERIFY_HEADER;
            HashOutput(ssl, output, sendSz, 0);
            }
        }

    // delete object
    FreeRsaKey(&key);

    if (ret == 0) 
        {
        ssl->buffers.outputBuffer.length += sendSz;
        if (ssl->options.groupMessages)
            return 0;
        else
            return SendBuffered(ssl);
        }
    else
        return ret;
}

Share

Re: Modify CyaSSL embedded SSL random data signing (client authentication)

Hi gquere,

You mention that you want to "change the portion where the random data sent by the server is signed by the client using the client's private key."  Can you elaborate on what you are trying to change?

Thanks,
Chris

4 (edited by gquere 2012-09-26 00:42:18)

Re: Modify CyaSSL embedded SSL random data signing (client authentication)

Hello,

Well, the thing is I want to change the default SSL provider on Android. Now, CyaSSL looks like something I could use, but on x86 (I'm simulating the behavior first), I cannot make the examples work with my server.

The binaries client/server will communicate just fine, but client/apache always fails when the server verifies the identity of the client. So the communication is fine, but the content is not.
Using wireshark I can see something like this:

...
TLSv1.2  Application data
TLSv1.2  Encrypted Handshake Message
TLSv1.2  Encrypted Alert
...

Looking at the content of the last frame, I can see the alert is 21. Looking at the TLS RFC, this alert means "decryption_failed(21)". So basically, the encryption client side always fails.
I've taken a look at the code but I don't see anything too strange. Not sure why it wouldn't work.

My setup:
Tried my own certs (which work with browser or java code)
Tried yassl certs from certs folder
Apache 2.4.3 with openSSL 1.0.1c
(before I was using Apache 2.x/OSSL 0.9.8k but upgraded just in case OSSL was the failure)


Edit: also, I confirm that I was looking at the right function from internal.c. But scratch my early comments from this function, they're mostly wrong smile

Share

Re: Modify CyaSSL embedded SSL random data signing (client authentication)

Well, the thing is I want to change the default SSL provider on Android. Now, CyaSSL looks like something I could use, but on x86 (I'm simulating the behavior first), I cannot make the examples work with my server.

Are you using the example client from the CyaSSL download (./examples/clilent/client), or are you using the example SSLClient.java from our CyaSSL Java Provider bundle?

Using wireshark I can see something like this ...

Would you be able to attach your wireshark trace, or PM it to me?

Thanks,
Chris

6 (edited by gquere 2012-09-27 05:17:19)

Re: Modify CyaSSL embedded SSL random data signing (client authentication)

Hello,

I'm using the CyaSSL download example for now.

Attached you'll find a proper wireshark capture.
The first part is  "./examples/client/client -h 127.0.0.1 -p 443 -g" and apache option "SSLInsecureRenegotiation on"
The second part is same client command but with "SSLInsecureRenegotiation off".

Thanks for the help

Edit:
That's the apache log for a failed connection with "SSLInsecureRenegotiation on":

==> access_log <==
127.0.0.1 - - [27/Sep/2012:14:15:28 +0200] "GET / HTTP/1.0" 403 202

==> error_log <==
[Thu Sep 27 14:15:28.354289 2012] [ssl:error] [pid 1251:tid 2987457392] [client 127.0.0.1:60150] AH02259: insecure SSL re-negotiation required, but a pipelined request is present; keepalive disabled
[Thu Sep 27 14:15:28.354582 2012] [ssl:error] [pid 1251:tid 2987457392] [client 127.0.0.1:60150] AH02261: Re-negotiation handshake failed: Not accepted by client!?

==> ssl_request_log <==
[27/Sep/2012:14:15:28 +0200] 127.0.0.1 - - "GET / HTTP/1.0" 202

Post's attachments

ws_capture 9 kb, 1 downloads since 2012-09-27 

You don't have the permssions to download the attachments of this post.

Share

Re: Modify CyaSSL embedded SSL random data signing (client authentication)

Thanks for the wireshark trace.  Keep in mind that CyaSSL doesn't currently support renegotiation because we've always felt that it is an insecure feature.  This will explain the failure when renegotiation is turned on in your Apache server configuration.

For the trace without renegotiation enabled, are you able to turn on CyaSSL's debugging output and see if it reveals any additional information about the connection?  You can enable debugging when building CyaSSL with "./configure --enable-debug" or by defining DEBUG_CYASSL.

Thanks,
Chris