Topic: [SOLVED] STM32F401 - Create ECC key and CSR

Hello,
I downloaded the package and try to evaluate it. My target is ST Nucleo F401RE, I'm using a STM32F401 with Freertos and I want to generate an ECC private key and a CSR based on it.
There is no RNG on the 401.
What is the minimum set of sources I need for that?
Is there any close example to this need?
Thanks,
Eyal

Share

Re: [SOLVED] STM32F401 - Create ECC key and CSR

Hi Eyal,

Thanks for evaluating wolfSSL! We have many customers using the STM32F4 with FreeRTOS. That is a great question!

To generate an ECC key:
1.  Make sure you have the `HAVE_ECC` defined.
2. Call:

ecc_key eccKey;
wc_ecc_make_key(rng, keySize, & eccKey);

Example: https://github.com/wolfSSL/wolfssl/blob … t.c#L11231

To create a CSR based on this ECC key:
1. Make sure you have `WOLFSSL_CERT_GEN` and `WOLFSSL_CERT_REQ` defined.
2. Call:

Cert req;
wc_MakeCertReq(&req, der, derSz, NULL, &eccKey);

Example: https://github.com/wolfSSL/wolfssl/blob … st.c#L8953

For an embedded system I find it best to put all my build options into a `user_settings.h` file (somewhere in your include path) and define `WOLFSSL_USER_SETTINGS`. You can find a good example for this here:

https://github.com/wolfSSL/wolfssl/blob … settings.h

Let me know if you have any issues or further questions.

Thanks,
David Garske, wolfSSL

Share

Re: [SOLVED] STM32F401 - Create ECC key and CSR

Thank you David for your answer,

I added wolfcrypt files to my stm32401 project and after straggling with the defines I finally succeed to build the project.

Since I don't have HW RGN on the 401 I have to use an alternative function, I'm missing the definition of custom_rand_generate_block(unsigned char* output, unsigned int sz);

Where is the description of it? Does it return a block of random numbers of size sz?
Do you have an example of such implementation?

Thanks,

Eyal

Share

Re: [SOLVED] STM32F401 - Create ECC key and CSR

Hi Eyal,

If you are only using the wolfCrypt portion of the library you can:
1. define `WOLFCRYPT_ONLY`.
2. Include relevant source files in /wolfcrypt/src/*.c
3. Include relevant headers in /wolfssl/wolfcrypt/*.h

For the build options you are using the only files you would to include are: asn.c, ecc.c, sha256.c and random.c. However I would recommend pulling in all the files/headers and letting the linker optimize out any used functions. This should the same code size, but allow you to expand your use.

If you do not have a hardware RNG, then you should use the pseudo DBRG based on SHA256. To seed the DRBG you'll need to find some random source such as a microsecond counter or ADC noise.

Here are the defines and code example for doing this:

#define HAVE_HASHDRBG

#define CUSTOM_RAND_TYPE      unsigned int
extern unsigned int custom_rand_generate(void);
#define CUSTOM_RAND_GENERATE  custom_rand_generate

unsigned int custom_rand_generate(void)
{
    /* TODO: build 32-bits of RNG and return */
    return myRng;
}

Thanks,
David Garske, wolfSSL

Share

Re: [SOLVED] STM32F401 - Create ECC key and CSR

Thank again David,

Your detailed answers brought me very fast to a stage where my project is built with wolfcrypt and I'm able to create the ECC key I needed.

I'm not sure about the output but when I used openssl to create the key on my Windows machine I used this command:

OpenSSL ecparam -out my_ec_key.pem -name prime256v1 –genkey

And I got keys that look like this:

-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIO1rlKJE/b1DDQsi6ESqePmNjxrqbc7Dg/GlJtZviz+EoAoGCCqGSM49
AwEHoUQDQgAE/DuVorKIGfByjKMiT+SJtRRMHwnsh5jofFtIBIm4J0VnR3hjw4Fw
CeYOQBdDIGpuDr8y2IvJWeLTz51gz0pWwQ==
-----END EC PRIVATE KEY-----

With wolfcrypt I use this:

ecc_key key;
wc_ecc_init(&key);

WC_RNG rng;
wc_InitRng(&rng);

wc_ecc_make_key(&rng, 32, &key); // initialize 32 byte ecc key
#define FOURK_BUF 4096
byte  der[FOURK_BUF];
int  derSz = wc_EccKeyToDer(&key, der, FOURK_BUF);
byte pem[4096];
int  pemSz = wc_DerToPem(der, derSz, pem, sizeof(pem),ECC_PRIVATEKEY_TYPE);

And I get a key that look like this:

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIG1ceBb5bj3YhpfCuxBB+tW8x/L1OK852gN5EijIoRHDoAoGCCqGSM49
AwEHoUQDQgAEwH2T6dZ6N+Vim7EKGRorUSZb+GIPXRDpXHPHJV+qxp7i7gOClDvg
oQagUCoB/llEaXTFzOzmmGVM+sakTYsByA==
-----END EC PRIVATE KEY-----

I see that the EC PARAMETERS part is missing, how can I produce it?
Also, does the prime256v1 is the same as calling wc_ecc_make_key with 32?

Thanks
Eyal

Share

Re: [SOLVED] STM32F401 - Create ECC key and CSR

Hi Eyal,

I'm happy to hear you got it working!

The `-----BEGIN EC PARAMETERS-----\nBggqhkjOPQMBBw==\n-----END EC PARAMETERS-----` part is static. Meaning for a prime256v1 256-bit key its always the same and you can always pre-pend it to the generated key if its required. This is just a base 64 encoded ASN1 object id, which indicates prime256v1. I've added this to our feature request list. It would be good for us to have the ability to generate these ECC parameters.

The default curve type is the NIST prime curves, so when calling wc_ecc_make_key with 32 you get a NIST prime256v1 curve. If you use the wc_ecc_make_key_ex function you can provide a curve_id such as `ECC_SECP256R1`.

You can see all the ECC build options here:
https://github.com/wolfSSL/wolfssl/blob … /ecc.c#L32

You can see a list of all supported curves here:
https://github.com/wolfSSL/wolfssl/blob … ecc.c#L456

If you would like to save code space you can define `ECC_USER_CURVES`, which allows you to define specific curve sizes manually using the 'HAVE_ECC###`defines (256-bit is on by default).

Thanks,
David Garske, wolfSSL

Share

Re: [SOLVED] STM32F401 - Create ECC key and CSR

Hi David,

I have now a full working code that creat the ECC key and a CSR based on it, but, the CSR looks broken, when I try to use it it is identify as corrupted or as an incorrect format.

I do this in the code:

    ecc_key key;
    wc_ecc_init(&key);

    WC_RNG rng;
    wc_InitRng(&rng);

//    wc_ecc_make_key(&rng, 32, &key); // initialize 32 byte ecc key
    wc_ecc_make_key_ex(&rng, 32, &key,ECC_SECP256R1); // initialize 32 byte ecc key
    #define FOURK_BUF 4096
    byte  der[FOURK_BUF];
    int  derSz = wc_EccKeyToDer(&key, der, FOURK_BUF);
    byte pem[4096];
    memset(pem,0,sizeof(pem));
    int  pemSz = wc_DerToPem(der, derSz, pem, sizeof(pem),ECC_PRIVATEKEY_TYPE);
    printf("%s",pem);
    Cert req;
    wc_InitCert(&req);
    strncpy(req.subject.country, "US", CTC_NAME_SIZE);
    strncpy(req.subject.state, "OR", CTC_NAME_SIZE);
    strncpy(req.subject.locality, "Portland", CTC_NAME_SIZE);
    strncpy(req.subject.org, "yaSSL", CTC_NAME_SIZE);
    strncpy(req.subject.unit, "Development", CTC_NAME_SIZE);
    strncpy(req.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE);
    strncpy(req.subject.email, "info@wolfssl.com", CTC_NAME_SIZE);
    derSz = wc_MakeCertReq(&req, der, FOURK_BUF, NULL, &key);
    pemSz = wc_DerToPem(der, derSz, pem, sizeof(pem),CERTREQ_TYPE);
    printf("%s",pem);

And this is the key\csr pair I get:

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIG1ceBb5bj3YhpfCuxBB+tW8x/L1OK852gN5EijIoRHDoAoGCCqGSM49
AwEHoUQDQgAEwH2T6dZ6N+Vim7EKGRorUSZb+GIPXRDpXHPHJV+qxp7i7gOClDvg
oQagUCoB/llEaXTFzOzmmGVM+sakTYsByA==
-----END EC PRIVATE KEY-----

-----BEGIN CERTIFICATE REQUEST-----
MIHxAgECMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECAwCT1IxETAPBgNVBAcMCFBv
cnRsYW5kMQ4wDAYDVQQKDAV5YVNTTDEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxGDAW
BgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm
c3NsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMB9k+nWejflYpuxChka
K1EmW/hiD10Q6VxzxyVfqsae4u4DgpQ74KEGoFAqAf5ZRGl0xczs5phlTPrGpE2L
AcigAA==
-----END CERTIFICATE REQUEST-----

I tested it both on my target server that refuse the CSR and on https://www.sslshopper.com/csr-decoder.html the gave an error message -

We were unable to decode this CSR. It may be corrupt or in an incorrect format.

When I took the above key and used openssl like this:

OpenSSL req -new -config my_config.cnf -key wolf_ecc_key.pem -out wolf_ecc.csr

The wolf_ecc.csr format was OK in both cases, that is, on my target server and the csr-decoder.

Any idea what I did wrong?

Thanks,

Eyal

Share

Re: [SOLVED] STM32F401 - Create ECC key and CSR

Hi Eyal,

What you have is an incomplete CSR, which is missing the signature. When comparing the one you generated with one from openssl the only difference was the missing signature at the bottom:

openssl asn1parse -inform der -in mycsr.der -dump
...
  248:d=1  hl=2 l=   9 cons: SEQUENCE          
  250:d=2  hl=2 l=   7 prim: OBJECT            :ecdsa-with-SHA1
  259:d=1  hl=2 l=  72 prim: BIT STRING        

Here is a complete code example for creating a valid CSR.

#include <wolfssl/options.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/asn_public.h>

#define MAX_TEMP_SIZE 1024

/* Build using:
gcc -lwolfssl -o makecsr makecsr.c
*/

int main(void)
{
    ecc_key key;
    WC_RNG rng;
    Cert req;
    byte der[MAX_TEMP_SIZE], pem[MAX_TEMP_SIZE];
    int  derSz, pemSz;

    wc_ecc_init(&key);
    wc_InitRng(&rng);

    wc_ecc_make_key_ex(&rng, 32, &key, ECC_SECP256R1);

    derSz = wc_EccKeyToDer(&key, der, sizeof(der));

    memset(pem, 0, sizeof(pem));
    pemSz = wc_DerToPem(der, derSz, pem, sizeof(pem), ECC_PRIVATEKEY_TYPE);
    printf("%s", pem);

    wc_InitCert(&req);
    strncpy(req.subject.country, "US", CTC_NAME_SIZE);
    strncpy(req.subject.state, "OR", CTC_NAME_SIZE);
    strncpy(req.subject.locality, "Portland", CTC_NAME_SIZE);
    strncpy(req.subject.org, "yaSSL", CTC_NAME_SIZE);
    strncpy(req.subject.unit, "Development", CTC_NAME_SIZE);
    strncpy(req.subject.commonName, "www.wolfssl.com", CTC_NAME_SIZE);
    strncpy(req.subject.email, "info@wolfssl.com", CTC_NAME_SIZE);
    derSz = wc_MakeCertReq(&req, der, sizeof(der), NULL, &key);

    req.sigType = CTC_SHA256wECDSA;
    derSz = wc_SignCert(req.bodySz, req.sigType, der, sizeof(der), NULL, &key, &rng);

    pemSz = wc_DerToPem(der, derSz, pem, sizeof(pem), CERTREQ_TYPE);
    printf("%s", pem);

    wc_ecc_free(&key);
    wc_FreeRng(&rng);

    return 0;
}
gcc -lwolfssl -o makecsr makecsr.c
./makecsr > mycsr.csr

cat mycsr.csr 
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJEIx4rTDoZFi7lsCiOX7XyTXnXOvj4VPDoQDGeD4p8woAoGCCqGSM49
AwEHoUQDQgAEMZygsN1xZH/QRxMszDej8bL84by+XQ4sziXUT83HGkTUx9puoNeI
UxlctiaTT1IgwCg9GCpC52SXU/e/NtvoUw==
-----END EC PRIVATE KEY-----
-----BEGIN CERTIFICATE REQUEST-----
MIIBSTCB8QIBAjCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk9SMREwDwYDVQQH
DAhQb3J0bGFuZDEOMAwGA1UECgwFeWFTU0wxFDASBgNVBAsMC0RldmVsb3BtZW50
MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9A
d29sZnNzbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQxnKCw3XFkf9BH
EyzMN6PxsvzhvL5dDizOJdRPzccaRNTH2m6g14hTGVy2JpNPUiDAKD0YKkLnZJdT
97822+hToAAwCgYIKoZIzj0EAwIDRwAwRAIgMdviSP9zLvYaNm1hcCVqG8jOvJz2
T34DlP3XXKI3cZ4CIFsNEquqCPbIkKGC8pOW9fUcmf6sWlgrra6uedL+PaCF
-----END CERTIFICATE REQUEST-----

openssl req -in mycsr.csr -text -noout
Certificate Request:
    Data:
        Version: 2 (0x2)
        Subject: C=US, ST=OR, L=Portland, O=yaSSL, OU=Development, CN=www.wolfssl.com/emailAddress=info@wolfssl.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
            EC Public Key: 
                pub: 
                    04:31:9c:a0:b0:dd:71:64:7f:d0:47:13:2c:cc:37:
                    a3:f1:b2:fc:e1:bc:be:5d:0e:2c:ce:25:d4:4f:cd:
                    c7:1a:44:d4:c7:da:6e:a0:d7:88:53:19:5c:b6:26:
                    93:4f:52:20:c0:28:3d:18:2a:42:e7:64:97:53:f7:
                    bf:36:db:e8:53
                ASN1 OID: prime256v1
        Attributes:
            a0:00
    Signature Algorithm: ecdsa-with-SHA256
        30:44:02:20:31:db:e2:48:ff:73:2e:f6:1a:36:6d:61:70:25:
        6a:1b:c8:ce:bc:9c:f6:4f:7e:03:94:fd:d7:5c:a2:37:71:9e:
        02:20:5b:0d:12:ab:aa:08:f6:c8:90:a1:82:f2:93:96:f5:f5:
        1c:99:fe:ac:5a:58:2b:ad:ae:ae:79:d2:fe:3d:a0:85

Let me know if you have any questions.

Thanks,
David Garske, wolfSSL

Share

Re: [SOLVED] STM32F401 - Create ECC key and CSR

Thank you again David, now all the elements seems to fit to each other and I was able to upload the CSR to AWS IOT and signing a cert for my key.

But, from some reason I'm not succeed to establish a TLS connection with the AWS thing while when I use the openssl pair I am.

I try to run openssl req -in wolf_ecc.csr -text -noout and compare the csr-s with no significant differences.

I'll try again tomorrow from fresh but I wanted to ask you if you can think of any thing I'm doing wrong here that can cause that different behavior?

Thanks,

Eyal

Share

Re: [SOLVED] STM32F401 - Create ECC key and CSR

OK, I retest all the process and now I can say that the case is solved for me!

I found out that on my device, if the cert is too big then there is some memory problems that cause the TLS to fail.

I created a shorter cert by removing some of the DN elements and make the others shorter (Like it actually was created with the openssl in the first time - no email and CN with only 2 letters) and with this wolf cert and key the device was able to establish a TLS connection with AWS IOT.

Thanks for the responsive support,

Eyal

Share

Re: [SOLVED] STM32F401 - Create ECC key and CSR

Hi Eyal,

That's wonderful! Very happy you got it all working.
Let me know if you have any other questions or issues.

Cheers,
David Garske

Share