1

(2 replies, posted in wolfSSL)

So, I have this solved for my silicon, and I'm posting it here for anyone else who runs into this.

Going down the list:

  • NTP isn't an option.

  • Using WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY allows the CA to load, but the verify still gives an error -150 because the time is still outside the Certificate window.

  • Overriding the verify until the server tells the device what time it is opens up to allowing anything to validate, because the CA won't load, unless the above step is also done.

  • Setting NO_ASN_TIME_CHECK opens it up for all time, since it's a build setting

The time functions used by this build of WolfSSL are mapped from "time()", which is the "Unix" function.  To set that, the C function clock_settime() is supposed to be used.

In the environment I am using, it is TI SYSBIOS on Sitara chip (which TI has completely walked away from any support including baremetal...  "Sucks to be you" is their attitude), the clock_settime() library is not present. The header is there, but no lib to link to.

Also the Unix C function "time()" doesn't get or set by the RTC functions that their SYSBIOS/RTOS/XDC API environment has. Nor does setting the Unix time do anything to the RTC registers.  So the RTC registers in the CPU are never in line with the Unix time.  The RTC registers power up as 01 Jan 2000, while the Unix time() is still 01 Jan 1970.

I don't know what is incrementing the Unix time, since it's not coupled to the RTC registers or to any timer interrupt I am aware of.

Regardless,  I discovered that I can set the Unix time with Seconds_set(now) which is a SYSBIOS/XDC function, where "now" is a time_t value.  Although it still remains different from the RTC registers that the CPU uses. 

Then when the Wolf library calls time(), it gets the value I injected into it.  So I can forcibly set it to a value which is within the CA validity window and it loads.  And it can also make the first connection to the server and not have any issue with the certificate time either. 

Then the server tells the device what time it really is, so I can set both the RTC registers as well as the Unix time, and everyone is happy.

-Scotty

2

(2 replies, posted in wolfSSL)

I am getting an error -150 when attempting to call "wolfSSL_CTX_load_verify_buffer()"

But only in my embedded project.  Not on my PC.

The issue:   The SERVER tells the unit what the time is. There is no battery backed RTC.   
We can't get to the server to tell us the time because the CAs cannot be loaded.

The CAs I am testing are from DigiCert
       Validity
            Not Before: Mar 30 00:00:00 2021 GMT
            Not After : Mar 29 23:59:59 2031 GMT
        Validity
            Not Before: Aug  1 12:00:00 2013 GMT
            Not After : Jan 15 12:00:00 2038 GMT

I tried setting our internal clock to 2022 01 01 00 00 00 001  (Jan1 2022) BEFORE even calling

m_sslCtx = wolfSSL_CTX_new(meth);

But it is still failing to load the CAs.

And to verify it is set, I display the time immediately AFTER calling

wolfSSL_CTX_load_verify_buffer()  

and getting a failure.

So, how/where is the Wolf lib getting the time that it decides to reject the CA's?

How can I force it to load the CA file before the time is set?

3

(4 replies, posted in wolfSSL)

noblekeon:

Don't expect any assistance from WolfSSL on this.  I didn't get any (as you can see by the thread dying).

And the RFC's are written in a very obfuscated and confusing manner (IMO).

There is a statement that it "now supports SNMPv3" but I find nothing that explains that.  Because all that it needed is to compute some hashes and do DES en/decryption.  So I just implemented the packet authentication and ciphers using regular functions that have been around for years.

I implemented SNMPv3 in our device (although the project was abandoned), so I figured out a lot of it.

I started with this, as it's the best description I found.  And it explains version 1
https://www.ranecommercial.com/legacy/note161.html

I then reverse engineered a lot of code from a project net-snmp-5.9.1. The first thing I did was create a project that responds to SNMPv1 messages (low level Ethernet protocol).

I also picked up the book "SNMP, SNMPv2, SNMPv3 and RMON1 and 2" - William Stallings Pearson books.
Specifically, part 5, chapter 14-16 let me take my development code testing from V1 to V3 with the authentication requirements.

I spun up a Linux box, and used the SNMP package to send SNMP OID requests to my test app, in order to verify correct operation.  Using the command line tools in Linux as the requester, I could send in requests for specific OIDs, blocks of them, or even lists.

A fun little web page that lets you examine OIDs is http://oid-info.com/

Hope this helps.

-Scott

4

(4 replies, posted in wolfSSL)

Kareem,
Is there any support under our contract for how to implement SNMPv3?

It's bad enough that I can't find any useful documentation for the PDU packet in earlier versions.

My wireshark trace of an SNMPv3 message has a bunch of additional fields in it which I cannot find anything documenting that either.  They all appear to be cipher related.

5

(4 replies, posted in wolfSSL)

Hello,
The following page
https://www.wolfssl.com/wolfssl-support-added-net-snmp/
announces that SNMP support is now avaialble.

Except the "follow the instructions " link  is to a repository page with a couple of diff files.  No instructions at all.

And we don't use patch/diff tools.

I am looking into adding a SNMPv3 agent to our embedded product.  While I have deciphered enough to the protocol to "be dangerous", I am looking for support writing and integrating an agent into the device running an RTOS, which already uses WolfSSL extensively.

(Off topic...  I've never seen such a kludge and poorly documented protocol in my 30+ years of network coding... requires 15+ RFCs and a PhD in some custom MIB files and how to BER them... and still no details about the protocol on the wire)

6

(2 replies, posted in wolfSSL)

Update...
The questions still stand, but I realize the CA is loaded in the

X509_Store_new();  

And it not necessary to load into

SSL_user_certificate_ASN1();

That was already occurring in another part of my code.

So that portion of my post changes. However the behavior of the certVertify callback remains not understood.

7

(2 replies, posted in wolfSSL)

Hello,
I am writing a 802.1X handshake client and need to verify the cert chain.  If I leave the ssl_set_verify() as NULL, it fails due to a date issue, since the embedded device has no RTC.

So I need to verify that the signer for the server certificate matches the CA which I have on the client device.  And ignore if the cert date is not valid, because we can't get the time until after the 802.1X authentication occurs.

Here's my test process

  • A CA where we are acting as our own Certification Authority (call it "CA1")

  • A fabricated cert on the server which is signed by CA1  (call it "certificate")

  • A fabricated different CA which doesn't apply to anything (call it "CA2")

(CA2 is to mimic someone attaching the device to a different 802.1X network where the server sends a cert that we don't have the correct CA for)

My goal is to ignore the errors related to the time validity, but reject if the server certificate was issued by CA "company1", while the client is using a CA from "company2"

Loading the PEM/DER data is not a problem. 
But am I loading it for the correct usage, and using the correct API calls?

I registered the callback using

SSL_set_verify(ssl, SSL_VERIFY_NONE, certVertify);

I load the CA using

SSL_user_certificate_ASN1(ssl, cabuffer, calength);

I also load the clients cert and key since the server needs peer authentication

SSL_user_certificate_ASN1(ssl, clientbuffer, clientlength);
SSL_user_certificate_ASN1(ssl, keybuffer, keylength);

If I completely ignore any errors on the client side, the 802.1X validation occurs fine, and it lets the device into the network.

But I need to be able to verify in the client that the server certificate is signed by the CA that is on the client.

The callback code is:

static int certVertify(int preverify_ok, X509_STORE_CTX *x509_ctx) {
        X509 *err_cert;
        int err, depth;
        char buf[256];
        const char *err_str;

        printf("------------------\nVerify Called\n");
        err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);

        err = X509_STORE_CTX_get_error(x509_ctx);
        depth = X509_STORE_CTX_get_error_depth(x509_ctx);

        err_str = X509_verify_cert_error_string(err);
        printf("The error is: %ds  Depth: %d \n",err_str , depth);
        X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
        printf("Cert is %s\n", buf);
        ...

Here's what happens and in some of these case, I don't understand what it's doing or why:
When I load the CA1 (the real one) and the time is correct, the callback gets called twice.  I am logging each time the verification callback occurs, and getting the error code, the depth, and certificate that the callback is referring to.

Error: 0  Depth: 1  Cert is CA1
Error: 0  Depth: 0  Cert is the certificate

That's fine. Makes sense.  Except we won't have the correct time in real life.

When I load the CA1 (the real one) and the time is INCORRECT, the callback gets called four times:

Error: certificate is not yet valid   Depth: 1   Cert is CA1
Error: certificate is not yet valid   Depth: 1   Cert is CA1
Error: certificate is not yet valid   Depth: 0   Cert is the certificate
Error: certificate is not yet valid   Depth: 0   Cert is the certificate

The "not yet valid makes sense", but why is it called 4 times?  Twice for each depth?

Next, when I load the CA2, which is the incorrect certification authority. This would a use where the device is attached to a network who has the incorrect CA.  And with the correct time, I get the following:

Error: Self Signed cert in chain  Depth: 1   Cert is CA1
Error: Self Signed cert in chain  Depth: 1   Cert is CA1
Error: Self Signed cert in chain  Depth: 0   Cert is the certificate

Okay, why is the callback handing me the CA from the server, and yet saying nothing about the certificate not being signed by the CA2 that I loaded?

Why is it telling me that CA1 (the actual signer of the certificate) is self signed?

Why is it calling the depth 1 twice?

Next, when I load the CA2, which is the incorrect certification authority, and the time is INCORRECT, I get the following:

Error: Self Signed cert in chain  Depth: 1   Cert is CA1
Error: certificate not yet valid    Depth: 1   Cert is CA1
Error: certificate not yet valid    Depth: 1   Cert is CA1
Error: certificate not yet valid    Depth: 0   Cert is the certificate
Error: certificate not yet valid    Depth: 0   Cert is the certificate

Now why are there 5 calls to the callback?

Any explanation about this would be greatly appreciated.

-Scott

Jacob,
I got emails asking to create an account... is this new?

I've gotten support last year and the year before with our Digital Check account.  Dealing with you, Sean, Eric directly.

I'll try those other settings in a the next day or two.

Thanks.

We have a support contract already in place.

Also, how is it that OpenSSL on a Windows i7 PC takes upwards of 15 seconds to create a new 2048 Public Private key pair  (and substantially longer for a 4096 pair), but you said this can do it in under a second on an Pi?

In fact, here is the full list:

#ifndef WOLF_USER_SETTINGS_H_
#define WOLF_USER_SETTINGS_H_

#define USE_FAST_MATH
#define TFM_TIMING_RESISTANT
#define WC_RSA_BLINDING
#define ECC_TIMING_RESISTANT

#define ALT_ECC_SIZE

#define OPENSSL_EXTRA        /*   */

#define WOLFSSL_KEY_GEN        //  Needed to generate KEYS, CERTS, and alternate names
#define WOLFSSL_CERT_GEN
#define WOLFSSL_ALT_NAMES        //  Needed for altername subject names in cert generation

//  From the "settings.h"

    #define SIZEOF_LONG_LONG 8
    #define NO_ERROR_STRINGS
    #define FP_MAX_BITS 8192        /*  Increase for 4096 bit key */
    #define HAVE_ECC
    #define HAVE_ALPN
    #define USE_WOLF_STRTOK /* use with HAVE_ALPN */
    #define HAVE_TLS_EXTENSIONS
    #define HAVE_AESGCM

//  Speed up tests
#define WOLFSSL_SP_DH
#define WOLFSSL_HAVE_SP_ECC
#define WOLFSSL_SP_4096


//  New settings, trying to get client to connect
#define    WOLFSSL_AES_256

#define WOLFSSL_SHA384
#define WOLFSSL_SHA512

#define NO_PSK
#define HAVE_AESGCM
#define ECC_USER_CURVES
#define ECC_SHAMIR
#define WOLFSSL_RIPEMD
#define HAVE_EXTENDED_MASTER
#define WOLFSSL_CERT_EXT

USE_FAST_MATH was already defined.  And tfm.c is already being compiled in.

The others were not.  However it made no difference.
This is trying to create a new keypair.   
And it taking anywhere between 20 seconds and 75 seconds at a time, during the 15+ tests I've run.

Specifically this: 

result = wc_InitRng(&rng);

result = wc_InitRsaKey(&genKey,0);
result = wc_MakeRsaKey(&genKey, 2048, 65537, &rng);

Running in a task in TI RTOS.

And how do I enable "--enable-fastmath" using a #define in the user_settings.h ?

Because we don't use the build scripts, as they are notoriously broken in CCS trying to build for platforms which are untested.

Got it. Thanks.

Any experience running wc_MakeRsaKey() on a AM3352 chip?  It runs at about 1Gig.

It seems to be taking a long time to create a 2048 key pair.  What would be an expected time?  10 Seconds? 30 seconds? 60 seconds?

I know it's generating random numbers and trying some things.  So it will vary.

Jacob,
Simply added these lines to set the before and after date.  And now it makes a cert that fails...

    /*  Create a CERT */
    Cert testcert;
    wc_InitCert(&testcert);

    memcpy(testcert.beforeDate,"20220215060001Z",15);
    testcert.beforeDateSz = 15;
    memcpy(testcert.afterDate, "20240215060001Z",15);
    testcert.afterDateSz = 15;
    testcert.daysValid = 365*2;

    strcpy(testcert.subject.country, "US");
    strcpy(testcert.subject.state, "IL");

I stored of the PEM, and I get this:

openssl x509 -in Dated.pem -noout -text
WARNING: can't open config file: c:\source\lib\openssl-1.0.1g/ssl/openssl.cnf
unable to load certificate
18176:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:.\crypto\asn1\asn1_lib.c:142:
18176:error:0D068066:asn1 encoding routines:ASN1_CHECK_TLEN:bad object header:.\crypto\asn1\tasn_dec.c:1306:
18176:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:.\crypto\asn1\tasn_dec.c:210:Type=ASN1_TIME
18176:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:.\crypto\asn1\tasn_dec.c:751:Field=notBefore, Type=X509_VAL
18176:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:.\crypto\asn1\tasn_dec.c:751:Field=validity, Type=X509_CINF
18176:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:.\crypto\asn1\tasn_dec.c:751:Field=cert_info, Type=X509
18176:error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib:.\crypto\pem\pem_oth.c:83:

So, what's the secret?

Jacob,
Thanks.
BUT I also see fields for the size.  And my digging indicates that the OID for the fields are type 18 and defined as YYYYMMDDHHMMSSZ   (15 chars long)
Isn't this an implied and fixed size?

Also, what is the point of "daysValid" if we have a start and stop field already?   
What takes priority?  beforeDate + daysvalid?  Or afterDate to beforeDate  ?

typedef struct Cert {
    int      version;                   /* x509 version  */
    byte     serial[CTC_SERIAL_SIZE];   /* serial number */
    int      serialSz;                  /* serial size */
    int      sigType;                   /* signature algo type */
    CertName issuer;                    /* issuer info */
    int      daysValid;                 /* validity days */
    int      selfSigned;                /* self signed flag */
    CertName subject;                   /* subject info */
    int      isCA;                      /* is this going to be a CA */
    /* internal use only */
    int      bodySz;                    /* pre sign total size */
    int      keyType;                   /* public key type of subject */
#ifdef WOLFSSL_ALT_NAMES
    byte     altNames[CTC_MAX_ALT_SIZE]; /* altNames copy */
    int      altNamesSz;                 /* altNames size in bytes */
    byte     beforeDate[CTC_DATE_SIZE];  /* before date copy */
    int      beforeDateSz;               /* size of copy */
    byte     afterDate[CTC_DATE_SIZE];   /* after date copy */
    int      afterDateSz;                /* size of copy */
#endif

-------------------------------------------
As an aside, where do I find this documented?
1. This site: https://luca.ntop.org/Teaching/Appunti/asn1.html   shows a Generalize date as tag 17, but the cert uses 18

2. A DER Cert decoder I found shows everything,  http://lapo.it/asn1js/

But how does a cert KNOW which fields are what?  SOME of the entries have OID, and some don't.
There are OIDs that define the signature algorithm, but the DER sequence which contains two generalized time entries has no OID associated with it...  Does that just imply that two generalized time values are ALWAYS "NotValidBefore" and "NotValidAfter".

Is any of this actually defined somewhere?  Because every resource I've found just gives vague descriptions of ASN.1, BER, DER, etc...  Nothing that says "Here's a expected structure of a real cert needs to be".

Hello,
Here is some background:
We are using our own internal CA.  And we need a device to generate and sign a certificate using the CA.

I have all this working fine. Modeling off of OpenSSL is how I started.
However OpenSSL uses a CNF file for those settings. No such option appears to exist.

I did find this:

https://wolfssl.com/doxygen/group__ASN. … 130e2c6563

WOLFSSL_API int wc_SetDatesBuffer    (Cert *, const byte * , int )
Which is one of the more useless explainations of how to function is used I've come across.

The example code is:

 Cert myCert;
 // initialize myCert
 byte* der;
 der = (byte*)malloc(FOURK_BUF);
 // initialize der
 if(wc_SetDatesBuffer(&myCert, der, FOURK_BUF) != 0) {
     // error setting subject
 }

Which only tells me I need a DER to use as a source for the dates...  Kind of a "circular" goal... 

Functionally, this all works, except the date is bad (dec 1969 as expected)
I need to be able to control the issue date and duration.

The (simplified) steps are:

    wc_MakeRsaKey()
    ...
    wc_InitCert(&testcert);
    strcpy(testcert.subject.country, "US");
    strcpy(testcert.subject.state, "IL");
    ... //  Yeah, a request is created, all fields good, and ready to be signed...

    caCertLength = LoadCACert();    //  Load the CA from storage
    wc_SetIssuerBuffer(testcert,m_caCert, caCertLength);
     ???  
    certsize = wc_MakeCert(&testcert, dercert, 4096, &genKey, NULL, &rng);
    caKeyLength = LoadCAKey();      //  Load the private key from storage
    result = wc_RsaPrivateKeyDecode((const byte *)m_caKey, &idx, &cakey, caKeyLength);
    ????
    certsize = wc_SignCert(testcert.bodySz, testcert.sigType, dercert, 4096, &cakey, NULL, &rng);

I am suspecting somewhere after "wc_SetIssueBuffer" or just before "wc_SignCert" is where the issue date and expiration date are set.
But there are no examples or explanations.

Can someone advise?

Thanks.

18

(2 replies, posted in wolfSSL)

dgarske wrote:

Hi Scott,

Did you see this example?
https://github.com/wolfSSL/wolfssl-exam … mes.c#L145

No, none of my searching came up with that.

This one worked: 

                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:localhost, DNS:example.com, DNS:127.0.0.1, IP Address:127.0.0.1
    Signature Algorithm: sha1WithRSAEncryption
         a3:2f:fb:a5:0c:55:68:51:e5:da:a6:6f:4d:3d:f0:1d:9c:77:
        ....  

dgarske wrote:

I will have another engineer provide some additional examples. For reference the test case I was using for Scott is posted here:
https://drive.google.com/file/d/15QOGFB … sp=sharing

Thanks,
David Garske, wolfSSL

Yeah, that's my test program I am working with.  All I needed at this stage was to be able to add a Subject Alternative Name

What's different between "myAltNames" in those two posts??
https://www.wolfssl.com/forums/topic140 … l-api.html
and
https://github.com/wolfSSL/wolfssl-exam … mes.c#L145

From what I can determine now, the opening sequence which includes the OID is NOT required in the second one.  But that opening sequence has a length requirement...  I guess internally it just adds 7 extra byte to it??  (The 5 byte OID identifier, and 2 byte STRING identifier plus the length)?

The DER/BER doc is spaghetti, and I can't tell when something is nested and when something isn't.  Nor can I find any definitions for those DNS (x2), IP (x7) IDs that are nested under other stuff... that I still can't figure out...
Since when is x08 an identifier for a string?  It's supposed to be x04...
The 0x08 data type isn't defined anywhere I can find in the DER/BER/ASN.1.

And when did a data type designators move to the upper nibble?

Somewhere, which I have yet to locate, there must be a definition of the sub sequences and their layouts for OID 2.5.29.17  (the Subject Alternative Name).

RFC 5280 specifies that an IP address in a Alternative name is designated as numeric, but the comment in the last entry of the "myAltNames" says it's a string, then uses 0x08 which is an undefined datatype (but uses it for both string and numbers...? )

        /* This is a string 0x08, it denotes an IP Address 0x07 -> 0x87 */
        /* This strings length is 4 (0x04) */
        0x87, 0x04,
        /* The IP address is 127 (0x7F), 0 (0x00), 0, (0x00), 1 (0x01) ->
        *  127.0.0.1
        */
        0x7F, 0x00, 0x00, 0x01

Well, this gives me something to work with, even if there isn't aren't definitions beyond the inline comments.

Thanks.

-Scott

19

(2 replies, posted in wolfSSL)

Hello,
See subject line...

I am creating a certificate, and signing it with an internal CA.  All is fine.  Except I need to also include alternate subject names.

I am using 4.7

This post:
https://www.wolfssl.com/forums/topic140 … l-api.html
Does not work.
The code block

char myAltNames[] = {
                                 // SEQUENCE (2 elements)
                                 0x30, 0x14,
                                 // OBJECT IDENTIFIEER: 2.5.29.17 subjectAltName
                                 // (X.509 extension)
                                 0x06, 0x03, 0x55, 0x1D, 0x11,
                                 // OCTET STRING (1 element) 
.....

Is building the DER sequence structure for a single name.
And when this is copied in the CERT structure:

    memcpy(testcert.altNames, myAltNames, sizeof(myAltNames) );
    testcert.altNamesSz = (int) sizeof(myAltNames) ;

The cert has garbage (actually the DER OID information) in the Alternate Subject Name

                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Alternative Name:
0...localhost   0...U...
    Signature Algorithm: sha1WithRSAEncryption
         c0:2b:4b:4d:b9:fd:1e:47:7b:0b:39:d9:17:72:6c:65:24:4e:

So the REAL solution appears to be something like

    memcpy(testcert.altNames,"DNS:LocalHost", sizeof("DNS:LocalHost") - 1);
    testcert.altNamesSz = (int) sizeof("DNS:LocalHost") - 1;

(the -1 is to remove the trailing null terminator)
Because now the certificate dump is

               Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:LocalHost.
    Signature Algorithm: sha1WithRSAEncryption
         83:bd:77:cd:3a:6a:f6:dc:ec:ab:63:cb:1c:3b:d4:39:02:4b:

Which pretty much "looks" correct, but I haven't tried it yet.

On the other hand, this doesn't work at all

    strcpy(testcert.subject.commonName, "www.whatever.com");
    strcpy(testcert.subject.email, "Info@whatever.com");
    wc_SetAltNames(&testcert, "localhost");

When I dump the generated and signed certificate, there is no X509 Extension Subject Alternative Name.

My question:
What is the correct way to set alternate names?
What is the correct way to set MULTIPLE alternate names?
What is the correct way to also set an IP address in the Subject Alternative Name field?

Short of studying the DER OID structures and mastering them (which I have done yet but I'm getting close to having to do), how can this field be set with multiple values and field types?

Scott

20

(3 replies, posted in wolfSSL)

dgarske wrote:

Hi Scott,

Thanks for your feedback on Doxygen quality and will bring up with the team. We strive to keep things well documented, provide timely support and quality examples.

David Garske, wolfSSL

David,
I am trying to figure out how to set an alternate name in a certificate...

The doc for "wc_SetAltNames"...
https://www.wolfssl.com/doxygen/group__ … e4fe7e3626
gives this example...

// initialize myCert
if(wc_SetSubject(&myCert, ”./path/to/ca-cert.pem”) != 0) {
    // error setting alt names
}

Subject is NOT Alternate name

21

(3 replies, posted in wolfSSL)

Thanks.
As I look for answers, troubleshooting issues, examples, etc...  I can show lots of issues.

I could constantly post things, but I don't want to just come across as antagonistic.

I've also though the best example was the MSDN (from about 15 years ago).  No one seems willing to put effort into following that model anymore.

Not just in WolfSSL...  literally everywhere I see these shortcut tools used, the content is horrid.

22

(4 replies, posted in wolfSSL)

Found it...
It doesn't generate a new buffer from the existing cert.  You feed it the existing cert.

    //  Now we can make the certificate 
    certsize = wc_MakeCert(&testcert, dercert, 4096, &genKey, NULL, &rng);
...
...
    //  Now we sign the certificate  
    //   byte signedcert[4096];
    //    certsize = wc_SignCert(testcert.bodySz, testcert.sigType, signedcert, 4096, &cakey, NULL, &rng);
    certsize = wc_SignCert(testcert.bodySz, testcert.sigType, dercert, 4096, &cakey, NULL, &rng);

And yet, you have to feed it the Cert object fields (testcert in this example), but the DER structured certificate.  But they both represent the same thing.

By the way... regarding doxygen, you know that wc_KeyPemToDer isn't anywhere to be found?

23

(4 replies, posted in wolfSSL)

Hello,

See subject line.
I am trying to create and sign a certificate on the fly.  I've gone through the examples (some with bugs), dug through API doc, debugged over and over... and managed to piece together this sequence.

The code, and a dummy CA cert/key are attached.

The code below simply does (or is supposed to)

  • [1]Create a 2048 key pair
    [2]Convert it to DER
    [3]Then convert it to PEM
    [4]Save the private key.pem
    [5]Create a Cert
    [6]Load a CA
    [7]Set the issuer
    [8]Make the cert
    [9]Load the CA Key
    [10]Decode the CA key
    [11]Sign the Cert
    [12]Convert the Cert to PEM
    [13]Save the Cert.pem

It gives a corrupted PEM file.

I've gone as far as creating a self signed and it works.  Adding the steps to load the CA, set issuer, signed it are creating the bad PEM.  I can't remove any of those individual steps to see what is breaking.

This is a Windows based build as a first development concept.
Since this will ultimately be embedded without a file system, the code loads the ca/key and runs from memory buffers.

The last half of the PEM is simply uninitialized memory.

-----BEGIN CERTIFICATE-----
MIICeKADAgECAhAIA+FO9NCldJWF6ua77BzkMA0GCSqGSIb3DQEBBQUAMHsxCzAJ
BgNVBAYTAlhYMQswCQYDVQQIDAJYWDEQMA4GA1UEBwwHQW55Q2l0eTENMAsGA1UE
CgwERGVtbzENMAsGA1UECwwERGVtbzERMA8GA1UEAwwIZGVtby5jb20xHDAaBgkq
hkiG9w0BCQEWDWluZm9ARGVtby5jb20wIhgPMjAyMTA2MDMxMzAxMzVaGA8yMDIy
MTAxNzEzMDEzNVowgYgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJaWjESMBAGA1UE
BwwJVGhpcyBDaXR5MQ0wCwYDVQQKDARZYWRhMQwwCgYDVQQLDANEZXYxGTAXBgNV
BAMMEHd3dy53aGF0ZXZlci5jb20xIDAeBgkqhkiG9w0BCQEWEUluZm9Ad2hhdGV2
ZXIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Ilzmeb9p6h0
fB5uNXkxNbuFvPP3lXVoOqM9wpz+yD/I/tL7EmWjgGkrjC0EBFPp6GwGbeWMR8Ui
4nQNTSYuCSJXUv/W/q4pvyEcx4CM+Of5GxUNRnDrQeVbHoiWfum2TGqPngzJVGiO
7ji6j3xlGUqQowS3CNQVAmKcXdVXaWJWyFfzbl5AjBlRjUgX08YsXc1bP7Wg291Z
88U7aY2skIgv1TJiftZrlxvPHa+uRMql5OS6cQkQ2psXRvEHurvwkij4MMUJaoCs
0uRmX8qDy1tXX/GwN6kGFcuoPJwNH7tP3adTFFrmWeevLL5n1xZmWovor15CxpXC
BsxPwKdclwIDAQABzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM
zMzMzMzMzMzMzMzMzMzMzMzMzMw=
-----END CERTIFICATE-----

This is the code being used.  ALL the return codes are good (even though they are not tested, they are good as I step through with the debugger)

#include <stdio.h>

#include "wolfssl\ssl.h"
#include "wolfssl/wolfcrypt\asn_public.h"    /*  Used for cert generation */
#include "wolfssl/wolfcrypt/rsa.h"        /*  Used for RNG and RSA Key */


int main() {
    RsaKey genKey;
    int result;
    RNG rng;
    FILE *fp;
    wc_InitRng(&rng);

    wc_InitRsaKey(&genKey,0);

    wc_MakeRsaKey(&genKey, 2048, 65537, &rng);
    /*  Save off the private key we are going to use  */
    byte keyDer[4096];
    int keysize, keypemsize;
    keysize = wc_RsaKeyToDer(&genKey, keyDer, 4096);

    byte keypem[4096];
    keypemsize = wc_DerToPem(keyDer, keysize, keypem, 4096, PRIVATEKEY_TYPE);

    /*  Save the new private key */
    fp = fopen("TestprivateKey.pem", "w+");
    fwrite(keypem, 1, keypemsize, fp);
    fclose(fp);

    /*  Create a CERT */
    Cert testcert;
    wc_InitCert(&testcert);

    strcpy(testcert.subject.country, "US");
    strcpy(testcert.subject.state, "ZZ");
    strcpy(testcert.subject.locality, "This City");
    strcpy(testcert.subject.org, "Yada");
    strcpy(testcert.subject.unit, "Dev");
    strcpy(testcert.subject.commonName, "www.whatever.com");
    strcpy(testcert.subject.email, "Info@whatever.com");
    byte dercert[4096];
    int certsize, certpemsize;
    /*  Use for SELF SIGNED */
    //certsize = wc_MakeSelfCert(&testcert, dercert, 4096, &genKey, &rng);

    /*  Use to sign it */
    /*  Load the CA cert to use */
    int cacertbufsize;
    unsigned char cacertbuf[4096];
    byte cacertder[4096];
    fp = fopen("sampleCA.pem", "r");
    cacertbufsize = fread(cacertbuf, 1, 4096, fp);
    fclose(fp);
        /*  Need to convert it to DER  */
    cacertbufsize = wc_CertPemToDer(cacertbuf, cacertbufsize, cacertder, 4096, CERT_TYPE);
    result = wc_SetIssuerBuffer(&testcert, cacertder, cacertbufsize);

    /*  Now we can make the certificate */
    certsize = wc_MakeCert(&testcert, dercert, 4096, &genKey, NULL, &rng);

    /*  Now load the CA key  */
    RsaKey cakey;
    int cakeybufsize;
    unsigned char cakeybuf[4096];
    word32 idx = 0;
    fp = fopen("sampleCAkey.pem", "r");
    cakeybufsize = fread(cakeybuf, 1, 4096, fp);
    fclose(fp);
    unsigned char caderkey[4096];
    /*  Need to conver it to DER  */
    wc_InitRsaKey(&cakey, 0);
    cakeybufsize = wc_KeyPemToDer(cakeybuf, cakeybufsize, caderkey, 4096, "ByteMe");
    result = wc_RsaPrivateKeyDecode((const byte *)caderkey, &idx,&cakey, cakeybufsize);

    /*  Now we sign the certificate  */
    byte signedcert[4096];
    certsize = wc_SignCert(testcert.bodySz, testcert.sigType, signedcert, 4096, &cakey, NULL, &rng);

    /* Convert the DER to PEM  */
    byte pemcert[4096];
    certpemsize = wc_DerToPem(dercert, certsize, pemcert, 4096, CERT_TYPE);

    /*  Save the signed signed cert  */
    fp = fopen("TestprivateCert.pem", "w+");
    fwrite(pemcert, 1, certpemsize, fp);
    fclose(fp);
    return 0;
}

24

(6 replies, posted in wolfSSL)

Sean,
Updated to what?

Just "grabbing the latest" is not a solution. It takes months of integrating and regression testing.  I can't just drop a new package in during the middle of that process.

I added my own definition in the user_settings.h file because the limits.h file that GCC Linaro uses (which TI distributes) is broken.  It doesn't have ANY definition for ULLONG_MAX under the C++, while it does under C

Both C and C++ do, however, have a definition for __UINT64_MAX__ , so I used it to define ULLONG_MAX

Of course, the TI 17.3 compiler freaks out at that...  Sheesh.
(we are trying to migrate off the TI unsupported compiler to GCC)

25

(3 replies, posted in wolfSSL)

Hello,
Not a question... a complaint.

It has always been my conclusion that anyone who uses "Doxygen" is demonstrating how lacks their work effort it... The output from it is virtually useless.  Developers spend more time in headers formatting, commenting, etc...  then just writing good doc.  Because it spits out header comments as it's source.

Bereft of examples, lacking cross references, one has to know exactly what one is looking for in order to find it.  A serious "cart before the horse" situation.

But developers slap some comments in the headers, let it spit out useless HTML, and they think the job is done.
Then it remains untouched, out of date from enhancements, broken information when something is changed... Because it's forgotten.

If a real document was part of the package, then a real task of updating it would exist.
(The only "real" doc I can find on this product is a PDF from version 3)

From here:
https://www.wolfssl.com/doxygen/group__ … eca15af4c5

" Certificate file type found in asn_public.h enum CertType. "

Go ahead... click it.  It takes you here
https://www.wolfssl.com/doxygen/asn__public_8h.html

There isn't any "CertType" defined anywhere on that page.
Try typing CertType into the search box...  Nothing.

Now start aimlessly wandering through it's useless menu system hoping to stumble on what you are looking for.

Don't think this is just the first incident where I can't find something, and now left wandering aimlessly.  Nor the second time.  Nor the tenth time...  It gets old really fast.

Broken documentation.  Created by an inferior system.