Topic: Error on wolfSSL_connect: "ASN no signer error to confirm failure"
Hi,
I am trying to build a simple client-server application with mutual authentication.
I want to use self-generated certificate for both client and server authentication, without having to rely on CA or third party certificates.
First, I generate my self-signed certificate.
This is the certificate to be used by both server and client, for TLS and peer verification.
To do this, I generate a RSA key, then a certificate, using wc_MakeSelfCert().
// ________________________________________________
//
//  GenerateCert
//
//  PURPOSE: 
//  Generate certificate with public & private key.
//
//  PARAMETERS:
//  None
//
//  RETURN VALUE:
//  SSL_SUCCESS If successful the call will return.
//  BAD_MUTEX_E is an error that may be returned.
//  WC_INIT_E wolfCrypt initialization error returned.
// ________________________________________________
//
Export BOOL GenerateCert()
{
    /* Generate RSA Key */
    RsaKey    genKey;
    RNG        rng;
    int     ret;
    BOOL    bRet = FALSE;
    byte    derKey[4096];
    byte    pemKey[4096];
    int        derSize;
    int        pemSize;
    HANDLE hFile;
    DWORD    dwBytesWritten;
    wc_InitRng(&rng);
    wc_InitRsaKey(&genKey, NULL);
    ret = wc_MakeRsaKey(&genKey, 2048, 65537, &rng);
    if (ret != 0) {
        /* ret contains error */;
        return FALSE;
    }
    derSize = wc_RsaKeyToDer(&genKey, derKey, sizeof(derKey));
    if (derSize < 0) {
        /* derSz contains error */;
        MessageBoxA(0, "ERROR: failed to get DER RSA Key", "", MB_ICONERROR);
        return FALSE;
    }
    pemSize = wc_DerToPem(derKey, derSize, pemKey, sizeof(pemKey), PRIVATEKEY_TYPE);
    if (pemSize < 0) {
        /* pemCertSz contains error */;
        MessageBoxA(0, "ERROR: failed to get PEM RSA Key", "", MB_ICONERROR);
        return FALSE;
    }
    /* Write Key file  */
    hFile = CreateFile(L"key.key",                // name of the write
        GENERIC_WRITE,          // open for writing
        0,                      // do not share
        NULL,                   // default security
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,  // normal file
        NULL);
    bRet = WriteFile(
        hFile,           // open file handle
        pemKey,      // start of data to write
        pemSize,  // number of bytes to write
        &dwBytesWritten, // number of bytes that were written
        NULL);            // no overlapped structure
    CloseHandle(hFile);
    /* Generate Certificate */
    Cert myCert;
    byte derCert[4096];
    byte pemCert[4096];
    wc_InitCert(&myCert);
    derSize = wc_MakeSelfCert(&myCert, derCert, sizeof(derCert), &genKey, &rng);
    if (derSize < 0) {
        /* certSz contains the error */;
        return FALSE;
    }
    pemSize = wc_DerToPem(derCert, derSize, pemCert, sizeof(pemCert), CERT_TYPE);
    if (pemSize < 0) {
        /* pemCertSz contains error */;
        return FALSE;
    }
    /* Write Certificate file  */
    hFile = CreateFile(L"certificate.crt",                // name of the write
        GENERIC_WRITE,          // open for writing
        0,                      // do not share
        NULL,                   // default security
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,  // normal file
        NULL);
    bRet = WriteFile(
        hFile,           // open file handle
        pemCert,      // start of data to write
        pemSize,  // number of bytes to write
        &dwBytesWritten, // number of bytes that were written
        NULL);            // no overlapped structure
    CloseHandle(hFile);
    return bRet;
}I start my TLS server, with wolfSSL_CTX_set_verify(SSL_VERIFY_PEER) to enable peer authentication.
I also use wolfSSL_CTX_trust_peer_cert() with my self-signed certificate, so that no CA will be needed for client authentication.
// ________________________________________________
//
//    InitTLS_Server
//
//  PURPOSE: 
//  Initialize TLS Server settings:
//  + Select Cipher Suite
//  + Enable Client Authentication
//    + Load RSA Key
//
//  PARAMETERS:
//  None
//
//  RETURN VALUE:
//  Pointer to WOLFSSL_CTX on success
//  NULL on failure
// ________________________________________________
//
Export WOLFSSL_CTX* InitTLS_Server()
{
    WOLFSSL_CTX*    ctx;
    /* Create and initialize WOLFSSL_CTX */
    if ((ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method())) == NULL) {
        MessageBoxA(0, "ERROR: failed to create WOLFSSL_CTX", "", MB_ICONERROR);
        //fprintf(stderr, "ERROR: failed to create WOLFSSL_CTX\n");
        return NULL;
    }
    /* Select cipher list to use */
    if (wolfSSL_CTX_set_cipher_list(ctx, "TLS_AES_128_GCM_SHA256") != SSL_SUCCESS)
    {
        MessageBoxA(0, "ERROR: failed to set cipher list.", "", MB_ICONERROR);
        wolfSSL_CTX_free(ctx);  /* Free the wolfSSL context object   */
        return NULL;
    }
    /* Load CA certificates into WOLFSSL_CTX */
    if (wolfSSL_CTX_load_verify_locations(ctx, CERT_FILE, NULL) != SSL_SUCCESS)
    {
        MessageBoxA(0, "ERROR: failed to load certificate.", "", MB_ICONERROR);
        wolfSSL_CTX_free(ctx);  // Free the wolfSSL context object
        return NULL;
    }
    /* Load server certificates into WOLFSSL_CTX */
    if (wolfSSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM) != SSL_SUCCESS)
    {
        MessageBoxA(0, "ERROR: failed to load server certificate.", "", MB_ICONERROR);
        wolfSSL_CTX_free(ctx);  /* Free the wolfSSL context object   */
        return NULL;
    }
    /* Load server key into WOLFSSL_CTX */
    if (wolfSSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, SSL_FILETYPE_PEM)
        != SSL_SUCCESS) {
        //fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", KEY_FILE);
        MessageBoxA(0, "ERROR: failed to load keyfile.", "", MB_ICONERROR);
        wolfSSL_CTX_free(ctx);
        return NULL;
    }
    /* Use trusted certificate to verify a peer when performing a TLS handshake (instead of CA certificate). */
    if (wolfSSL_CTX_trust_peer_cert(ctx, CERT_FILE, SSL_FILETYPE_PEM) != SSL_SUCCESS)
    {
        MessageBoxA(0, "ERROR: failed to load trusted peer certificate.", "", MB_ICONERROR);
        wolfSSL_CTX_free(ctx);  /* Free the wolfSSL context object   */
        return NULL;
    }
    /* Enable client authentication */
    wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0);
    return ctx;
}In my client side,
I load the same self-signed certificate generated earlier, using wolfSSL_CTX_use_certificate_buffer().
I use wolfSSL_CTX_trust_peer_buffer() so that no CA will be needed for server authentication.
// ________________________________________________
//
//  InitializeTLS (Client Side)
//
//  PURPOSE: 
//  One-time initialization of TLS.
//  Must be called just once at application start.
//
//  PARAMETERS:
//  Client Certificate buffer
//
//  RETURN VALUE:
//  TRUE on Success
//  FALSE on Failure
// ________________________________________________
//
bool CConnection::InitializeTLS(PBYTE pCert, int lenCert)
{
    int ret;
    /* Initialize wolfSSL */
    if ((ret = wolfSSL_Init()) != WOLFSSL_SUCCESS) {
        PrintEvent("[ERROR]", "Failed to initialize TLS");
        return false;
    }
    /* Create and initialize WOLFSSL_CTX */
    if ((ctxTLS = wolfSSL_CTX_new(wolfTLSv1_3_client_method())) == NULL) {
        PrintEvent("[ERROR]", "Failed to initialize TLS context");
        ret = -1;
        return false;
    }
    /* Load client certificates into WOLFSSL_CTX */
    if ((ret = wolfSSL_CTX_use_certificate_buffer(ctxTLS, pCert, lenCert, SSL_FILETYPE_ASN1))
        != SSL_SUCCESS) {
        PrintEvent("[ERROR]", "Failed to load TLS certificate");
        return false;
    }
    /* Select cipher list to use */
    if (wolfSSL_CTX_set_cipher_list(ctxTLS, "TLS_AES_128_GCM_SHA256") != SSL_SUCCESS)
    {
        PrintEvent("[ERROR]", "Failed to set cipher list");
        return false;
    }
    /* Use trusted certificate to verify a peer when performing a TLS handshake (instead of CA certificate). */
    if (wolfSSL_CTX_trust_peer_buffer(ctxTLS, pCert, lenCert, SSL_FILETYPE_ASN1) != SSL_SUCCESS)
    {
        PrintEvent("[ERROR]", "Failed to set peer certificate");
        return false;
    }
    bUseTLS = true;
    return true;
}After the aforementioned initialization code (which succeeds without errors),
I connect to server using wolfSSL_connect() and I get an error on this function.
The error is: ASN no signer error to confirm failure
which seem to indicate an error regarding invalid CA certificate.
I am confused on why that happens:
both client and server are instructed with wolfSSL_CTX_trust_peer_buffer and wolfSSL_CTX_trust_peer_cert to use a custom certificate for verification.
The certificate used by the server and client is the same one, which was self-generated using the above code.
I would greatly appreciate if you can point me to the right direction.
Thank you in advance,
and Best Regards