/*
 * ToDo: problems with RSA_PKCS1_OAEP_PADDING -> RSA_PKCS1_PSS_PADDING is
 * needed (Version 0.9.9); RSA_PKCS1_OAEP_PADDING is just for encryption
 */
OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Private_Sign(
    OpcUa_CryptoProvider* a_pProvider,
    OpcUa_ByteString      a_data,
    OpcUa_Key*            a_privateKey,
    OpcUa_Int16           a_padding,          /* e.g. RSA_PKCS1_PADDING */
    OpcUa_ByteString*     a_pSignature)       /* output length >= key length */
{
    EVP_PKEY*               pSSLPrivateKey  = OpcUa_Null;
    const unsigned char*    pData           = OpcUa_Null;
    int                     iErr            = 0;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Private_Sign");

    /* unused parameters */
    OpcUa_ReferenceParameter(a_pProvider);
    OpcUa_ReferenceParameter(a_padding);

    /* check parameters */
    OpcUa_ReturnErrorIfArgumentNull(a_privateKey);
    OpcUa_ReturnErrorIfArgumentNull(a_pSignature);
    pData = a_privateKey->Key.Data;
    OpcUa_ReturnErrorIfArgumentNull(pData);
    OpcUa_ReturnErrorIfTrue((a_privateKey->Type != OpcUa_Crypto_KeyType_Rsa_Private), OpcUa_BadInvalidArgument);

    /* convert private key and check key length against buffer length */
    pSSLPrivateKey = d2i_PrivateKey(EVP_PKEY_RSA, OpcUa_Null, &pData, a_privateKey->Key.Length);
    OpcUa_GotoErrorIfTrue((pSSLPrivateKey == OpcUa_Null), OpcUa_BadUnexpectedError);
    OpcUa_GotoErrorIfTrue((a_pSignature->Length < RSA_size(pSSLPrivateKey->pkey.rsa)), OpcUa_BadInvalidArgument);

    /* sign data */
    iErr = RSA_sign(NID_sha1, a_data.Data, a_data.Length, a_pSignature->Data, (unsigned int*)&a_pSignature->Length, pSSLPrivateKey->pkey.rsa);
    OpcUa_GotoErrorIfTrue((iErr != 1), OpcUa_BadUnexpectedError);

    /* free internal key representation */
    EVP_PKEY_free(pSSLPrivateKey);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(OpcUa_IsEqual(OpcUa_BadUnexpectedError))
    {
        long    lErr    = ERR_get_error();
        char*   szErr   = ERR_error_string(lErr, 0);

        if(szErr != OpcUa_Null)
        {
            OpcUa_P_Trace("*** RSA_Private_Sign: ");
            OpcUa_P_Trace(szErr);
            OpcUa_P_Trace(" ***\n");
        }
    }

    if(pSSLPrivateKey != OpcUa_Null)
    {
        EVP_PKEY_free(pSSLPrivateKey);
    }

OpcUa_FinishErrorHandling;
}
示例#2
0
/*============================================================================
 * Get address information about the peer
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_RawSocket_GetPeerInfo( OpcUa_Socket    a_RawSocket,
                                                OpcUa_CharA*    a_achPeerInfoBuffer,
                                                OpcUa_UInt32    a_uiPeerInfoBufferSize)
{
    int                 apiResult       = 0;
    struct sockaddr_in  sockAddrIn;
    size_t              TempLen         = sizeof(struct sockaddr_in);
    SOCKET              winSocket       = (SOCKET)OPCUA_P_SOCKET_INVALID;
    char*               pchAddrBuf      = OpcUa_Null;
    OpcUa_UInt16        usPort          = 0;

OpcUa_InitializeStatus(OpcUa_Module_Socket, "GetPeerInfo");

    /* initial parameter check */
    OpcUa_ReturnErrorIfTrue((a_RawSocket == (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID), OpcUa_BadInvalidArgument);
    OpcUa_ReturnErrorIfTrue((a_uiPeerInfoBufferSize < OPCUA_P_PEERINFO_MIN_SIZE), OpcUa_BadInvalidArgument);
    OpcUa_ReturnErrorIfArgumentNull(a_achPeerInfoBuffer);

    winSocket = (SOCKET)a_RawSocket;
    apiResult = getpeername(winSocket, (struct sockaddr*)&sockAddrIn, (int*)&TempLen);

    OpcUa_ReturnErrorIfTrue((apiResult != 0), OpcUa_BadInternalError);

    /* IP */
    pchAddrBuf = inet_ntoa(sockAddrIn.sin_addr);
    OpcUa_GotoErrorIfTrue(pchAddrBuf == OpcUa_Null, OpcUa_BadInternalError);

    /* Port */
    usPort = OpcUa_P_RawSocket_NToHS((OpcUa_UInt16)sockAddrIn.sin_port);

    /* build result string */
    TempLen = strlen(pchAddrBuf);

#if OPCUA_USE_SAFE_FUNCTIONS
    OpcUa_GotoErrorIfTrue((strncpy_s(a_achPeerInfoBuffer, a_uiPeerInfoBufferSize + 1, pchAddrBuf, TempLen) != 0), OpcUa_Bad);
    a_achPeerInfoBuffer[TempLen] = ':';
    TempLen++;
    sprintf_s(&a_achPeerInfoBuffer[TempLen], a_uiPeerInfoBufferSize - TempLen, "%u", usPort);
#else /* OPCUA_USE_SAFE_FUNCTIONS */
    OpcUa_GotoErrorIfTrue((strncpy(a_achPeerInfoBuffer, pchAddrBuf, TempLen) != a_achPeerInfoBuffer), OpcUa_Bad);
    a_achPeerInfoBuffer[TempLen] = ':';
    sprintf(&a_achPeerInfoBuffer[TempLen + 1], "%u", usPort);
#endif /* OPCUA_USE_SAFE_FUNCTIONS */

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
/*============================================================================
 * OpcUa_EnumeratedType_FindValue
 *===========================================================================*/
OPCUA_EXPORT OpcUa_StatusCode OpcUa_EnumeratedType_FindValue(
    OpcUa_EnumeratedType* a_pType,
    OpcUa_StringA         a_sName,
    OpcUa_Int32*          a_pValue)
{
    OpcUa_UInt32 ii = 0;

    OpcUa_InitializeStatus(OpcUa_Module_Serializer, "EnumeratedType_FindValue");

    OpcUa_ReturnErrorIfArgumentNull(a_pType);
    OpcUa_ReturnErrorIfArgumentNull(a_sName);
    OpcUa_ReturnErrorIfArgumentNull(a_pValue);

    *a_pValue = 0;

    for (ii = 0; a_pType->Values[ii].Name != OpcUa_Null; ii++)
    {
        if (OpcUa_StrCmpA(a_pType->Values[ii].Name, a_sName) == 0)
        {
            *a_pValue = a_pType->Values[ii].Value;
            break;
        }
    }

    OpcUa_GotoErrorIfTrue(a_pType->Values[ii].Name == OpcUa_Null, OpcUa_BadInvalidArgument);

    OpcUa_ReturnStatusCode;
    OpcUa_BeginErrorHandling;

    /* nothing to do */

    OpcUa_FinishErrorHandling;
}
/*============================================================================
 * OpcUa_P_OpenSSL_RSA_LoadPrivateKeyFromFile
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_LoadPrivateKeyFromFile(
    OpcUa_StringA           a_privateKeyFile,
    OpcUa_P_FileFormat      a_fileFormat,
    OpcUa_StringA           a_password,         /* optional: just needed encrypted PEM */
    OpcUa_ByteString*       a_pPrivateKey)
{
    BIO*            pPrivateKeyFile     = OpcUa_Null;
    RSA*            pRsaPrivateKey      = OpcUa_Null;
    EVP_PKEY*       pEvpKey             = OpcUa_Null;
    unsigned char*  pData;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_LoadPrivateKeyFromFile");

    /* check parameters */
    OpcUa_ReturnErrorIfArgumentNull(a_privateKeyFile);
    OpcUa_ReturnErrorIfArgumentNull(a_pPrivateKey);

    if(a_fileFormat == OpcUa_Crypto_Encoding_Invalid)
    {
        return OpcUa_BadInvalidArgument;
    }

    OpcUa_ReferenceParameter(a_password);

    /* open file */
    pPrivateKeyFile = BIO_new_file((const char*)a_privateKeyFile, "rb");
    OpcUa_ReturnErrorIfArgumentNull(pPrivateKeyFile);

    /* read and convert file */
    switch(a_fileFormat)
    {
    case OpcUa_Crypto_Encoding_PEM:
        {
            /* read from file */
            pEvpKey = PEM_read_bio_PrivateKey(  pPrivateKeyFile,    /* file                 */
                                                NULL,               /* key struct           */
                                                0,                  /* password callback    */
                                                a_password);        /* default passphrase or arbitrary handle */
            OpcUa_GotoErrorIfNull(pEvpKey, OpcUa_Bad);
            break;
        }
    case OpcUa_Crypto_Encoding_PKCS12:
        {
            int iResult = 0;

            /* read from file. */
            PKCS12* pPkcs12 = d2i_PKCS12_bio(pPrivateKeyFile, NULL);

            if (pPkcs12 == 0)
            {
                OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError);
            }

            /*  parse the certificate. */
            iResult = PKCS12_parse(pPkcs12, a_password, &pEvpKey, NULL, NULL);

            if (iResult == 0)
            {
                OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError);
            }

            /*  free certificate. */
            PKCS12_free(pPkcs12);
            pPkcs12 = NULL;
            break;
        }
    case OpcUa_Crypto_Encoding_DER:
    default:
        {
            uStatus = OpcUa_BadNotSupported;
            OpcUa_GotoError;
        }
    }

    /* convert to intermediary openssl struct */
    pRsaPrivateKey = EVP_PKEY_get1_RSA(pEvpKey);
    EVP_PKEY_free(pEvpKey);
    OpcUa_GotoErrorIfNull(pRsaPrivateKey, OpcUa_Bad);

    /* get required length */
    a_pPrivateKey->Length = i2d_RSAPrivateKey(pRsaPrivateKey, OpcUa_Null);
    OpcUa_GotoErrorIfTrue((a_pPrivateKey->Length <= 0), OpcUa_Bad);

    /* allocate target buffer */
    a_pPrivateKey->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pPrivateKey->Length);
    OpcUa_GotoErrorIfAllocFailed(a_pPrivateKey->Data);

    /* do real conversion */
    pData = a_pPrivateKey->Data;
    a_pPrivateKey->Length = i2d_RSAPrivateKey(pRsaPrivateKey, &pData);
    OpcUa_GotoErrorIfTrue((a_pPrivateKey->Length <= 0), OpcUa_Bad);

    RSA_free(pRsaPrivateKey);
    BIO_free(pPrivateKeyFile);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(pEvpKey)
    {
        EVP_PKEY_free(pEvpKey);
    }

    if(a_pPrivateKey != OpcUa_Null)
    {
        if(a_pPrivateKey->Data != OpcUa_Null)
        {
            OpcUa_P_Memory_Free(a_pPrivateKey->Data);
            a_pPrivateKey->Data = OpcUa_Null;
            a_pPrivateKey->Length = -1;
        }
    }

    if(pPrivateKeyFile != NULL)
    {
        BIO_free(pPrivateKeyFile);
    }

    if(pRsaPrivateKey != NULL)
    {
        RSA_free(pRsaPrivateKey);
    }

OpcUa_FinishErrorHandling;
}
示例#5
0
/*
    ToDo:   Create Access to OpenSSL certificate store
            => Only API to In-Memory-Store is available for version 0.9.8x
            => Wait until Directory- and/or File-Store is available
*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_LoadCertificate(
    OpcUa_PKIProvider*          a_pProvider,
    OpcUa_Void*                 a_pLoadHandle,
    OpcUa_Void*                 a_pCertificateStore,
    OpcUa_ByteString*           a_pCertificate)
{
    OpcUa_Byte*     buf                 = OpcUa_Null;
    OpcUa_Byte*     p                   = OpcUa_Null;
    FILE*           pCertificateFile    = OpcUa_Null;
    X509*           pTmpCert            = OpcUa_Null;

    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_LoadCertificate");

    OpcUa_ReturnErrorIfArgumentNull(a_pProvider);
    OpcUa_ReturnErrorIfArgumentNull(a_pProvider->Handle);
    OpcUa_ReturnErrorIfArgumentNull(a_pLoadHandle);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificateStore);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificate);

    /* read DER certificates */
    pCertificateFile = fopen((const char*)a_pLoadHandle, "r");

    /* check for valid file handle */
    OpcUa_GotoErrorIfTrue((pCertificateFile == OpcUa_Null), OpcUa_BadInvalidArgument);

    if(!(pTmpCert = d2i_X509_fp(pCertificateFile, (X509**)OpcUa_Null)))
    {
        uStatus = OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    a_pCertificate->Length = i2d_X509(pTmpCert, NULL);
    buf = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertificate->Length);
    OpcUa_GotoErrorIfAllocFailed(buf);
    p = buf;
    for (;;)
    {
        i2d_X509(pTmpCert, &p);
        X509_free(pTmpCert);
        if(!(pTmpCert = d2i_X509_fp(pCertificateFile, (X509**)OpcUa_Null)))
        {
            break;
        }
        p = OpcUa_P_Memory_ReAlloc(buf, a_pCertificate->Length + i2d_X509(pTmpCert, NULL));
        OpcUa_GotoErrorIfAllocFailed(p);
        buf = p;
        p = buf + a_pCertificate->Length;
        a_pCertificate->Length += i2d_X509(pTmpCert, NULL);
    }

    if(fclose(pCertificateFile) != 0)
    {
        pCertificateFile = OpcUa_Null;
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    a_pCertificate->Data = buf;

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(pCertificateFile != OpcUa_Null)
    {
        fclose(pCertificateFile);
    }

    if(pTmpCert != OpcUa_Null)
    {
        X509_free(pTmpCert);
    }

    if(buf != OpcUa_Null)
    {
        OpcUa_P_Memory_Free(buf);
    }

OpcUa_FinishErrorHandling;
}
示例#6
0
/*
    ToDo:   Create Access to OpenSSL certificate store
            => Only API to In-Memory-Store is available for version 0.9.8x
            => Wait until Directory- and/or File-Store is available
*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_SaveCertificate(
    OpcUa_PKIProvider*          a_pProvider,
    OpcUa_ByteString*           a_pCertificate,
    OpcUa_Void*                 a_pCertificateStore,
    OpcUa_Void*                 a_pSaveHandle)      /* Index or number within store/destination filepath */
{
    X509*                                       pX509Certificate        = OpcUa_Null;
    FILE*                                       pCertificateFile        = OpcUa_Null;

    const unsigned char*                        p;

    OpcUa_UInt32                                i;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_SaveCertificate");


    OpcUa_ReturnErrorIfArgumentNull(a_pProvider);
    OpcUa_ReturnErrorIfArgumentNull(a_pProvider->Handle);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificate);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificateStore);
    OpcUa_ReturnErrorIfArgumentNull(a_pSaveHandle);

    /* save DER certificate */
    pCertificateFile = fopen((const char*)a_pSaveHandle, "w");

    /* check for valid file handle */
    OpcUa_GotoErrorIfTrue((pCertificateFile == OpcUa_Null), OpcUa_BadInvalidArgument);

    /* convert openssl X509 certificate to DER encoded bytestring certificate */
    p = a_pCertificate->Data;
    while (p < a_pCertificate->Data + a_pCertificate->Length)
    {
        if(!(pX509Certificate = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Data + a_pCertificate->Length - p)))
        {
            fclose(pCertificateFile);
            uStatus = OpcUa_Bad;
            OpcUa_GotoErrorIfBad(uStatus);
        }

        i = i2d_X509_fp(pCertificateFile, pX509Certificate);

        if(i < 1)
        {
            fclose(pCertificateFile);
            uStatus =  OpcUa_Bad;
            OpcUa_GotoErrorIfBad(uStatus);
        }

        X509_free(pX509Certificate);
        pX509Certificate = OpcUa_Null;
    }

    if(fclose(pCertificateFile) != 0)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if (pX509Certificate != OpcUa_Null)
    {
        X509_free(pX509Certificate);
    }

OpcUa_FinishErrorHandling;
}
/*============================================================================
 * Create a client socket
 *===========================================================================*/
OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_SocketManager_CreateClient(  OpcUa_SocketManager         a_hSocketManager,
                                                                    OpcUa_StringA               a_sRemoteAddress,
                                                                    OpcUa_UInt16                a_uLocalPort,
                                                                    OpcUa_Socket_EventCallback  a_pfnSocketCallBack,
                                                                    OpcUa_Void*                 a_pCallbackData,
                                                                    OpcUa_Socket*               a_pSocket)
{
    OpcUa_InternalSocket*        pNewClientSocket       = OpcUa_Null;
    OpcUa_InternalSocketManager* pInternalSocketManager = OpcUa_Null;
    OpcUa_UInt16                 uPort                  = 0;
    OpcUa_StringA                sRemoteAdress          = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_Socket, "CreateClient");

#if !OPCUA_MULTITHREADED
    if(a_hSocketManager == OpcUa_Null)
    {
        a_hSocketManager = OpcUa_Socket_g_SocketManager;
    }
#endif

    OpcUa_ReturnErrorIfArgumentNull(a_hSocketManager);
    OpcUa_ReturnErrorIfArgumentNull(a_pSocket);
    OpcUa_ReturnErrorIfArgumentNull(a_sRemoteAddress);

    /* parse address */
    uStatus = OpcUa_P_ParseUrl( a_sRemoteAddress,
                                &sRemoteAdress,
                                &uPort);
    OpcUa_ReturnErrorIfBad(uStatus);

    pInternalSocketManager = (OpcUa_InternalSocketManager*)a_hSocketManager;

    pNewClientSocket = (OpcUa_InternalSocket*)OpcUa_SocketManager_FindFreeSocket(   (OpcUa_SocketManager)pInternalSocketManager,
                                                                                    OpcUa_False);
    if (pNewClientSocket == OpcUa_Null)
    {
        OpcUa_P_Memory_Free(sRemoteAdress);
        uStatus = OpcUa_BadMaxConnectionsReached; /* no socket left in the list. */
        goto Error;
    }

    /* Create client socket. */
    pNewClientSocket->rawSocket = OpcUa_P_Socket_CreateClient(  a_uLocalPort,
                                                                uPort,
                                                                sRemoteAdress,
                                                                &uStatus);

    OpcUa_P_Memory_Free(sRemoteAdress);

    OpcUa_GotoErrorIfTrue(  pNewClientSocket->rawSocket == (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID,
                            OpcUa_BadCommunicationError);

    pNewClientSocket->pfnEventCallback       = a_pfnSocketCallBack;
    pNewClientSocket->pvUserData             = a_pCallbackData;
    pNewClientSocket->Flags.bOwnThread       = OpcUa_False;
    pNewClientSocket->Flags.EventMask        = OPCUA_SOCKET_READ_EVENT
                                             | OPCUA_SOCKET_EXCEPT_EVENT
                                             | OPCUA_SOCKET_CONNECT_EVENT
                                             | OPCUA_SOCKET_TIMEOUT_EVENT;

    OPCUA_SOCKET_SETVALID(pNewClientSocket);

    /* return the new client socket */
    *a_pSocket = pNewClientSocket;

    /* break loop to add new socket into eventing */
    uStatus = OpcUa_P_SocketManager_InterruptLoop(  a_hSocketManager,
                                                    OPCUA_SOCKET_RENEWLOOP_EVENT,
                                                    OpcUa_False);
    OpcUa_GotoErrorIfBad(uStatus);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(pNewClientSocket != OpcUa_Null)
    {
        if(pNewClientSocket->rawSocket != (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID)
        {
            OpcUa_P_RawSocket_Close(pNewClientSocket->rawSocket);
            pNewClientSocket->rawSocket = (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID;
        }
        OPCUA_SOCKET_INVALIDATE(pNewClientSocket);
    }

OpcUa_FinishErrorHandling;
}
示例#8
0
/*============================================================================
 * OpcUa_P_OpenSSL_X509_GetPrivateKey
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_X509_GetPrivateKey(
    OpcUa_CryptoProvider*       a_pProvider,
    OpcUa_StringA               a_certificateFileName,
    OpcUa_StringA               a_password,             /* this is optional */
    OpcUa_Key*                  a_pPrivateKey)
{
    BIO*            pCertFile       = OpcUa_Null;
    PKCS12*         pPKCS12Cert     = OpcUa_Null;
    EVP_PKEY*       pPrivateKey     = OpcUa_Null;
    RSA*            pRsaPrivateKey  = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_GetPrivateKey");

    OpcUa_ReferenceParameter(a_pProvider);

    OpcUa_ReturnErrorIfArgumentNull(a_pProvider);
    OpcUa_ReturnErrorIfArgumentNull(a_certificateFileName);
    OpcUa_ReturnErrorIfArgumentNull(a_pPrivateKey);

    /* import certificate from file by the given encoding type */
    pCertFile = BIO_new_file((const char*)a_certificateFileName, "r");
    OpcUa_ReturnErrorIfArgumentNull(pCertFile);

    /* convert certificate file handle to PKCS12 structure */
    d2i_PKCS12_bio(pCertFile, &pPKCS12Cert);

    /* close certificat file handle */
    BIO_free(pCertFile);

    if(pPKCS12Cert != OpcUa_Null)
    {
        /* get the private key from the PKCS12 structure*/
        PKCS12_parse(pPKCS12Cert, a_password, &pPrivateKey, OpcUa_Null, OpcUa_Null);
    }
    else
    {
        uStatus = OpcUa_Bad;
        OpcUa_ReturnStatusCode;
    }

    if(pPKCS12Cert != OpcUa_Null)
    {
        PKCS12_free(pPKCS12Cert);
        pPKCS12Cert = OpcUa_Null;
    }

    switch(EVP_PKEY_type(pPrivateKey->type))
    {
    case EVP_PKEY_RSA:
        {
            /* convert to intermediary openssl struct */
            pRsaPrivateKey = EVP_PKEY_get1_RSA(pPrivateKey);
            EVP_PKEY_free(pPrivateKey);
            OpcUa_GotoErrorIfNull(pRsaPrivateKey, OpcUa_Bad);

            /* get required length */
            a_pPrivateKey->Key.Length = i2d_RSAPrivateKey(pRsaPrivateKey, OpcUa_Null);
            OpcUa_GotoErrorIfTrue(a_pPrivateKey->Key.Length <= 0, OpcUa_Bad);

            if(a_pPrivateKey->Key.Data == OpcUa_Null)
            {
                OpcUa_ReturnStatusCode;
            }

            /* do real conversion */
            a_pPrivateKey->Key.Length = i2d_RSAPrivateKey(  pRsaPrivateKey,
                                                            &a_pPrivateKey->Key.Data);
            OpcUa_GotoErrorIfTrue(a_pPrivateKey->Key.Length <= 0, OpcUa_Bad);

            if(pRsaPrivateKey != OpcUa_Null)
            {
                RSA_free(pRsaPrivateKey);
                pRsaPrivateKey = OpcUa_Null;
            }

            /* correct buffer pointer */
            a_pPrivateKey->Key.Data -= a_pPrivateKey->Key.Length;

            a_pPrivateKey->Type = OpcUa_Crypto_KeyType_Rsa_Private;

            break;
        }
    case EVP_PKEY_EC:
    case EVP_PKEY_DSA:
    case EVP_PKEY_DH:
    default:
        {
            uStatus =  OpcUa_BadNotSupported;
            OpcUa_GotoErrorIfBad(uStatus);
        }
    }

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(pRsaPrivateKey != OpcUa_Null)
    {
        RSA_free(pRsaPrivateKey);
    }

    if(pPrivateKey != OpcUa_Null)
    {
        EVP_PKEY_free(pPrivateKey);
    }

OpcUa_FinishErrorHandling;
}