Topic: verifying DER certificates

Hello! I would like to use wolfSSL to authenticate embedded firmware which has a single DER encoded certificate built into it. I am a little lost trying to figure out which APIs to use to accomplish this. Could you please guide me in the right direction?

Share

Re: verifying DER certificates

Hi @agoswam,

Have you seen the wolfSSL secure boot solution, wolfBoot? If not could you read the overview in the README, is that along the lines of what you are seeking? https://github.com/wolfSSL/wolfBoot/blo … /README.md

IE a way to verify a firmware update or is your use-case something else? If the use case is something else please briefly describe the use-case and what/who is driving the effort.

Warm Regards,

K

3 (edited by agoswam 2019-08-08 11:55:05)

Re: verifying DER certificates

Hello! Thank you for your reply. I am not looking for a bootloader at this point, although it is good to know about wolfBoot. The use case I am working on is 'secure boot'. Ensuring that only legitimate firmware is booted when the device is powered. I am the one working on this. Firmware update is also a legitimate use case for this.

I have had some luck [since my initial post on this forum] using the wolfSSL APIs but as of now, I am seeing a -229 (SIG_VERIFY_E) error upon calling wc_SignatureVerify(..).

The issue I see is quite similar to the one described here -
https://www.wolfssl.com/forums/topic891 … alues.html

Could you please tell me what the final resolution to the problem [that thomas.cornu reported] was? I haven't compared the bytes in the two hashes but I do see that the return value from wc_RsaSSL_Verify() call is 51 (vs. 32 for the hash it is being compared against).

Below is a close representation of what the code looks like....

    ret = wolfSSL_Init();
    if (ret != SSL_SUCCESS) {
            /*failed to initialize wolfSSL library*/
            while(1);
    }

    /* open and read DER-formatted cert into buffer */
    file = fopen("./cert.der", "rb");
    if (!file)
    {
        while(1); // error reading certificate file
    }

    derCertSz = fread(derCert, 1, sizeof(derCert), file);
    fclose(file);

    wolfSSL_X509_d2i(&certificate, derCert, derCertSz); //wolfSSL_X509_load_certificate_file(CERT_FILE, SSL_FILETYPE_ASN1);
    pubKeyTmp = wolfSSL_X509_get_pubkey(certificate);

    if (certificate != NULL) {
        wolfSSL_X509_free(certificate);
    } else {
        return 0;
    }

    /* initialize DecodedCert with DER cert */
    InitDecodedCert(&cert, derCert, derCertSz, 0);
    ret = ParseCert(&cert, RSA_PUBLICKEY_TYPE /*RSA_PUBLICKEY_TYPE*/, NO_VERIFY, 0);
    if (ret != 0)
    {
        while(1); // ParseCert failed
    }

    /* extract the public key from the cert */
    wc_InitRsaKey(&pubKey, NULL);
    ret = wc_RsaPublicKeyDecode((byte*)pubKeyTmp->pkey.ptr, &idx, &pubKey, pubKeyTmp->pkey_sz);

    if (ret != 0)
    {
        while(1); //  RsaPublicKeyDecode failed
    }

    /* Copy the binary into a buffer */
    appFilePtr = fopen("./app.bin", "rb");
    fseek(appFilePtr,0,SEEK_END);
    filelen = ftell(appFilePtr);
    rewind(appFilePtr);
    buffer = (char *)malloc((filelen)*sizeof(char));
    fread(buffer,1,filelen,appFilePtr);
    fclose(appFilePtr);

    /* Verify signature */
    ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA, buffer, filelen, cert.signature,   cert.sigLength, &pubKey, sizeof(pubKey));
    if (ret == 0)
    {
        printf("PASS: %d", ret);
    }
    else{
        printf("FAIL: %d", ret);
    }

The result I see is - FAIL: -229

What might I need to do differently?

Share

Re: verifying DER certificates

I wanted to post an update and re-request help on this issue.

Using 'WC_SIGNATURE_TYPE_RSA_W_ENC' signature type helps. Both hashes are now 51 bytes long, however the bytes themselves do not match, which ultimately causes failure during verification of the two hashes (the decrypted signature hash vs. hash calculated based on the raw binary data).

Share

Re: verifying DER certificates

Hi agoswam,

Both hashes are now 51 bytes long

You indicated the digest size is 51 which may be the source of the issue. You are passing WC_HASH_TYPE_SHA256 which has a digest of only 32-bytes not 51.

A SHA256 digest is 32-bytes long,
A SHA384 digest is 48-bytes long,
and
A SHA512 digest is 64-bytes long.

There are no digests that are 51 bytes long. Can you double check the digest length?


Warm Regards,

K

6 (edited by agoswam 2019-08-13 11:56:07)

Re: verifying DER certificates

A. The sha256 hash that is calculated on the binary data is 32 bytes long. What I am seeing is that 19 bytes of DER encoded header is added to this 32 byte hash once wc_SignatureDerEncode(..) is called, i.e. only if the signature type is defined as WC_SIGNATURE_TYPE_RSA_W_ENC. If the signature type is defined as WC_SIGNATURE_TYPE_RSA then this hash is 32 bytes long which is in line with what you are saying. 

B. The cert.signature (RSA encrypted hash) + cert.sigLength (512) when decrypted using the RSA public key [ this is done by the wc_RsaSSL_Verify(..) function ] results in a hash that is 51 bytes long.

The top 19 bytes (which I think is some kind of header) of both hashes match; the remaining 32 bytes do not.

I only experimented with using the ..._W_ENC signature type when I looked at the bottom of this exchange - https://www.wolfssl.com/forums/topic891 … alues.html

Share

Re: verifying DER certificates

agoswam,

Can you tell us where the signature came from and how it was generated initially? If there is DER encoding in front of the signature is it possibly PKCS8 encoded? Can you try calling wc_GetPkcs8TraditionalOffset on the signature first and check the return code of that function? If wc_GetPkcs8TraditionalOffset returns a zero (success) can you try stripping off the PKCS8 header before verifying the signature?

If it is not a PKCS8 encoded signature do you know how it was encoded initially?

Warm Regards,

K

Re: verifying DER certificates

Hi Kaleb,
Thank you. I have sent you an email and a test case for further follow up.

Share