TLS Certificates

Discussion to talk about software related topics only.
SeeCwriter
Posts: 605
Joined: Mon May 12, 2008 10:55 am

Re: TLS Certificates

Post by SeeCwriter »

Yes, the co-worker used support, #37042, dated Oct 2020.

Regarding auto-generated certificates, I deleted the auto-generated certificate I was using, and tried to make a secure connection. It failed to connect, and didn't generate a new certificate. Using wireshark, the process was:
1. PC initiates a TCP connection.
2. Module ACKs with its own SYN.
3. PC ACKs the module's ACK.
4. PC sends TLS1.2 Hello Client packet.
5. Module ACKs hello client packet with no data.
6. Module closes connection.
7. PC ACKs and closes its connection.

It all takes .5 seconds.
User avatar
Jon
Posts: 79
Joined: Mon Feb 05, 2018 10:54 am

Re: TLS Certificates

Post by Jon »

Hi SeeCWriter,

I have to correct my previous statement, it seems. Sorry about the confusion here. When SSL_accept() is called, it will check the status of the certificate the first time as part of the server initialization (specifically in SslInitServer()). Future calls to SSL_accept() will not trigger this check.

That said, we recently added a check in the SSL task that will look to see if the auto-generated cert is expired, and if it is, it will trigger the auto-generation process again (though it hasn't been released yet). If you open <nndk_install>\libraries\crypto\NetBurner\NbWolfSsl.cpp and look at the end of SslCallBackTask(), add the following under the line wait_interval = Is2ndTickEarlier(now, lowest_next) ? 1 : (lowest_next - now);:

Code: Select all

        // Check to see if we have an auto-generated cert that needs to be renewed
        if( SSL_CreateNewCert && ( !HalDeviceCertValid() || gCertGenData.m_certExpTimeSet ))
        {
            time_t now = time(nullptr);
            if( difftime(gCertGenData.m_certExpTime, now) < 0 )
            {
                if( SSL_CreateNewCert(gCertGenData.m_commonName, gCertGenData.m_yrsValid, gCertGenData.m_altNames, gCertGenData.m_altNameCnt) == CERT_GEN_RETURN_SUCCESS )
                {
                    WOLFSSL_CTX* curCtx = (gServerCtx != nullptr) ? gServerCtx : gClientCtx;
                    SSL_ReadyCert( curCtx, HalGetDeviceCert(), HalGetDeviceCertLen(), HalGetDeviceKey(), HalGetDeviceKeyLen(), HalGetDeviceFormat() );
                }
                else
                {
                    SSL_DEBUG_IPRINTF("Unable to create certificates due to expiration time reached.\r\n");
                }
            }
        }
This will periodically check the status of the self-generated cert, and recreate it if it's not valid. This will happen outside of the context of a connection, though, so you won't get the stall you might if it were to happen when someone was trying to connect to the server. That said, you also get less control over when will happen as the device will try to fix this as soon as it detects it's a problem.

For the issue with the dates, it looks like those changes were added into the repo after 2.9.5 was released as well. In the same file, if you replace the function SSL_IsCertExpired() with the following, it should fix the date issues:

Code: Select all

bool SSL_GetTimeToExpire( unsigned char* certBuff, int certLen, uint16_t certBuffFormat, time_t& timeToExp )
{
    uint16_t expBufLen = 64;
    unsigned char expBuf[expBufLen] = {0};
    if( SSL_GetExpirationDate(certBuff, certLen, expBuf, expBufLen, certBuffFormat))
    {
        // Two date formats are possible based on the year of expiration according to RFC 5280:
        // 1) A 12 digit value in the format of YYMMDDHHMMSSZ when the expiration year falls before 2050 which follows
        // the following conventions:
        //    - Where YY is greater than or equal to 50, the year SHALL be interpreted as 19YY
        //    - Where YY is less than 50, the year SHALL be interpreted as 20YY
        // 2) A 14 digit value in the format of YYYYMMDDHHMMSSZ when the expiration year falls on or after 2050

        // Test for 14 Digit Format
        int bufIndMod = 0;
        if(expBuf[14] != 'Z')
        {
            bufIndMod = 2;
        }

        struct tm ExpTime;
        char tempBuf[4] = {0};
        sniprintf(tempBuf, 3, "%s", &expBuf[4 + bufIndMod]);
        ExpTime.tm_mon = atoi(tempBuf)  - 1; // Month is 0 - 11

        sniprintf(tempBuf, 3, "%s", &expBuf[6 + bufIndMod]);
        ExpTime.tm_mday = atoi(tempBuf);

        sniprintf(tempBuf, (3 + bufIndMod), "%s", &expBuf[2]);
        ExpTime.tm_year = atoi(tempBuf);
        // If we're using the 12 digit format, we need to modify the year based on the rules above,
        // but minus 1900 for the time conversion.
        if( bufIndMod == 0 )
        {
            ExpTime.tm_year += (ExpTime.tm_year >= 50) ? 0 : 100;
        }
        else
        {
            ExpTime.tm_year = ExpTime.tm_year - 1900;
        }

        sniprintf(tempBuf, 3, "%s", &expBuf[8 + bufIndMod]);
        ExpTime.tm_hour = atoi(tempBuf);

        sniprintf(tempBuf, 3, "%s", &expBuf[10 + bufIndMod]);
        ExpTime.tm_min = atoi(tempBuf);

        sniprintf(tempBuf, 3, "%s", &expBuf[12 + bufIndMod]);
        ExpTime.tm_sec = atoi(tempBuf);

        timeToExp = mktime(&ExpTime);
        return true;
    }
    return false;
}

ExpireRetCodes SSL_IsCertExpired( unsigned char* certBuff, int certLen, uint16_t certBuffFormat /*= SSL_FILETYPE_PEM*/ )
{
    // Make sure we have system time, and have it ready to compare to the expiration date
    time_t now = time(nullptr);
    struct tm tmStruct;
    localtime_r( &now, &tmStruct);
    if( (tmStruct.tm_year + 1900) == 1970 )
    {
        SSL_DEBUG_IPRINTF("System time not set.\r\n");
        return ExpireRetCodes::E_NO_SYSTEM_TIME;
    }

    // Get current time and compare it to expiration date
    time_t timeToExpire = 0;
    if( SSL_GetTimeToExpire(certBuff, certLen, certBuffFormat, timeToExpire) )
    {
        time_t now = time(nullptr);
        return (difftime(timeToExpire, now) < 0) ? ExpireRetCodes::E_CERT_EXPIRED : ExpireRetCodes::E_CERT_VALID;
    }

    return ExpireRetCodes::E_BAD_EXPIRATION_VALUE;
}
Please let me know if there are any other questions, and if these changes fix the issues you're experiencing.
SeeCwriter
Posts: 605
Joined: Mon May 12, 2008 10:55 am

Re: TLS Certificates

Post by SeeCwriter »

Since I am unable to build the system libraries (long story), will these updates be in the next release of the 2.9.x tools?

Also, does, or will, the TLS implementation use JSON Web Tokens and x.509 certificates?
User avatar
Jon
Posts: 79
Joined: Mon Feb 05, 2018 10:54 am

Re: TLS Certificates

Post by Jon »

Hi SeeCwriter,

All the changes mentioned above are pushed into our repo and will be integrated into the next release for 2.x.

The library does support x.509 certificates, which is the standard used to dictate how SSL/TLS certificates are structured. The formats accepted for these certificates are DER and PEM.

We currently have all the tools that you would need to implement JSON Web Tokens, but it's not currently part of the native library. That's a really interesting feature, though, and I'll talk to our team about implementing it.

Please feel free to let me know if you have any other issues at all.

Kind Regards,
Jon
SeeCwriter
Posts: 605
Joined: Mon May 12, 2008 10:55 am

Re: TLS Certificates

Post by SeeCwriter »

I found another PC to install v2.9.5, and it appears to be able to build the system libs. At least it went a long time and didn't throw a Cywin fault. But I am getting an error about variable gCertGenData being undefined in the code you said to add to NbWolfSsl.cpp.

I searched all the include and system files and didn't find it either.
Post Reply