/*============================================================================
 * OpcUa_MemoryStream_Read
 *===========================================================================*/
OpcUa_StatusCode OpcUa_MemoryStream_Read(
    struct _OpcUa_InputStream*     istrm,
    OpcUa_Byte*                    buffer,
    OpcUa_UInt32*                  count,
    OpcUa_Stream_PfnOnReadyToRead* callback,
    OpcUa_Void*                    callbackData)
{
    OpcUa_MemoryStream* handle = OpcUa_Null;

    OpcUa_DeclareErrorTraceModule(OpcUa_Module_MemoryStream);

    OpcUa_ReturnErrorIfArgumentNull(istrm);
    OpcUa_ReturnErrorIfArgumentNull(buffer);
    OpcUa_ReturnErrorIfArgumentNull(count);
    OpcUa_ReturnErrorIfInvalidStream(istrm, Read);
    OpcUa_ReferenceParameter(callback);
    OpcUa_ReferenceParameter(callbackData);

    handle = (OpcUa_MemoryStream*)istrm->Handle;

    if (handle->Closed)
    {
        return OpcUa_BadInvalidState;
    }

    return OpcUa_Buffer_Read(handle->pBuffer, buffer, count);
}
OpcUa_Void OPCUA_DLLCALL OpcUa_P_Trace(
#if OPCUA_TRACE_FILE_LINE_INFO
                                        OpcUa_UInt32 level,
                                        OpcUa_CharA* sFile,
                                        OpcUa_UInt32 line,
#endif
                                        OpcUa_CharA* a_sMessage)
{
#if OPCUA_TRACE_FILE_LINE_INFO
    OpcUa_ReferenceParameter(level);
    OpcUa_ReferenceParameter(sFile);
    OpcUa_ReferenceParameter(line);
#endif

    /* send to tracehook if registered */
    if(g_OpcUa_P_TraceHook != OpcUa_Null)
    {
        g_OpcUa_P_TraceHook(a_sMessage);
    }
    else /* send to console */
    {
        char dtbuffer[25];
        OpcUa_DateTime timestamp;

        timestamp = OpcUa_P_DateTime_UtcNow();
        OpcUa_P_DateTime_GetStringFromDateTime(timestamp, dtbuffer, 25);

        printf("|%ld| %s %s", OpcUa_P_Thread_GetCurrentThreadId(), &dtbuffer[11], a_sMessage);
    }
}
/*
 * 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;
}
/*
ToDo: problems with RSA_PKCS1_OAEP_PADDING -> find solution
*/
OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Public_Verify(
    OpcUa_CryptoProvider* a_pProvider,
    OpcUa_ByteString      a_data,
    OpcUa_Key*            a_publicKey,
    OpcUa_Int16           a_padding,
    OpcUa_ByteString*     a_pSignature)
{
    EVP_PKEY*       pPublicKey      = OpcUa_Null;
    OpcUa_Int32     keySize         = 0;
    const unsigned char *pData;

    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Public_Verify");

    OpcUa_ReferenceParameter(a_pProvider);
    OpcUa_ReferenceParameter(a_padding);

    OpcUa_ReturnErrorIfArgumentNull(a_data.Data);
    OpcUa_ReturnErrorIfArgumentNull(a_publicKey);
    OpcUa_ReturnErrorIfArgumentNull(a_publicKey->Key.Data);
    OpcUa_ReturnErrorIfArgumentNull(a_pSignature);

    if(a_publicKey->Type != OpcUa_Crypto_KeyType_Rsa_Public)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument);
    }

    pData = a_publicKey->Key.Data;
    pPublicKey = d2i_PublicKey(EVP_PKEY_RSA,OpcUa_Null, &pData, a_publicKey->Key.Length);

    if(pPublicKey == OpcUa_Null)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument);
    }

    keySize = RSA_size(pPublicKey->pkey.rsa);

    if((a_pSignature->Length%keySize) != 0)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_Bad);
    }

    if (RSA_verify(NID_sha1, a_data.Data, a_data.Length, a_pSignature->Data, a_pSignature->Length, pPublicKey->pkey.rsa) != 1)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_Bad);
    }

    EVP_PKEY_free(pPublicKey);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

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

OpcUa_FinishErrorHandling;
}
/*============================================================================
 * OpcUa_P_OpenSSL_PKI_NoSecurity_CloseCertificateStore
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_NoSecurity_CloseCertificateStore(
    OpcUa_PKIProvider*          a_pProvider,
    OpcUa_Void**                a_ppCertificateStore)
{
    OpcUa_ReferenceParameter(a_pProvider);
    OpcUa_ReferenceParameter(a_ppCertificateStore);

    return OpcUa_BadNotSupported;
}
/*============================================================================
 * OpcUa_P_OpenSSL_PKI_NoSecurity_LoadCertificate
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_NoSecurity_LoadPrivateKeyFromFile(
    OpcUa_StringA               a_privateKeyFile,
    OpcUa_P_FileFormat          a_fileFormat,
    OpcUa_StringA               a_password,
    OpcUa_ByteString*           a_pPrivateKey)
{
    OpcUa_ReferenceParameter(a_privateKeyFile);
    OpcUa_ReferenceParameter(a_fileFormat);
    OpcUa_ReferenceParameter(a_password);
    OpcUa_ReferenceParameter(a_pPrivateKey);

    return OpcUa_BadNotSupported;
}
/*============================================================================
 * OpcUa_P_OpenSSL_PKI_ValidateCertificate
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_NoSecurity_ValidateCertificate(
    OpcUa_PKIProvider*          a_pProvider,
    OpcUa_ByteString*           a_pCertificate,
    OpcUa_Void*                 a_pCertificateStore,
    OpcUa_Int*                  a_pValidationCode)
{
    OpcUa_ReferenceParameter(a_pProvider);
    OpcUa_ReferenceParameter(a_pCertificateStore);
    OpcUa_ReferenceParameter(a_pCertificate);
    OpcUa_ReferenceParameter(a_pValidationCode);

    return OpcUa_BadNotSupported;
}
/*============================================================================
 * OpcUa_P_OpenSSL_PKI_NoSecurity_LoadCertificate
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_NoSecurity_LoadCertificate(
    OpcUa_PKIProvider*          a_pProvider,
    OpcUa_Void*                 a_pLoadHandle,
    OpcUa_Void*                 a_pCertificateStore,
    OpcUa_ByteString*           a_pCertificate)
{
    OpcUa_ReferenceParameter(a_pProvider);
    OpcUa_ReferenceParameter(a_pCertificateStore);
    OpcUa_ReferenceParameter(a_pCertificate);
    OpcUa_ReferenceParameter(a_pLoadHandle);

    return OpcUa_BadNotSupported;
}
/*============================================================================
 * OpcUa_P_OpenSSL_AES_CBC_Encrypt
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_AES_CBC_Encrypt(
    OpcUa_CryptoProvider*   a_pProvider,
    OpcUa_Byte*             a_pPlainText,
    OpcUa_UInt32            a_plainTextLen,
    OpcUa_Key*              a_key,
    OpcUa_Byte*             a_pInitalVector,
    OpcUa_Byte*             a_pCipherText,
    OpcUa_UInt32*           a_pCipherTextLen)
{
    AES_KEY         key;

    OpcUa_Byte      pInitalVector[16];

    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "AES_CBC_Encrypt");

    OpcUa_ReferenceParameter(a_pProvider);

    OpcUa_ReturnErrorIfArgumentNull(a_pPlainText);
    OpcUa_ReturnErrorIfArgumentNull(a_key);
    OpcUa_ReturnErrorIfArgumentNull(a_key->Key.Data);
    OpcUa_ReturnErrorIfArgumentNull(a_pInitalVector);
    OpcUa_ReturnErrorIfArgumentNull(a_pCipherTextLen);

    if(a_plainTextLen % 16 != 0)
    {
        uStatus = OpcUa_BadInvalidArgument;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    *a_pCipherTextLen = a_plainTextLen;

    /* if just the output length is needed for the caller of this function */
    if(a_pCipherText == OpcUa_Null)
    {
        OpcUa_ReturnStatusCode;
    }

    /* we have to pass the key length in bits instead of bytes */
    if(AES_set_encrypt_key(a_key->Key.Data, a_key->Key.Length * 8, &key) < 0)
    {
        uStatus = OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* copy the IV because the AES_cbc_encrypt function overwrites it. */
    OpcUa_P_Memory_MemCpy(pInitalVector, 16, a_pInitalVector, 16);

    /* encrypt data */
    AES_cbc_encrypt(    a_pPlainText,
                        a_pCipherText,
                        a_plainTextLen,
                        &key,
                        pInitalVector,
                        AES_ENCRYPT);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

OpcUa_FinishErrorHandling;
}
Beispiel #10
0
OpcUa_Boolean OPCUA_DLLCALL OpcUa_Trace_Nop(OpcUa_UInt32     a_uTraceLevel,
#if OPCUA_TRACE_FILE_LINE_INFO
                                            OpcUa_CharA*     a_sFile,
                                            OpcUa_UInt32     a_sLine,
#endif /* OPCUA_TRACE_FILE_LINE_INFO */
                                            OpcUa_CharA*     a_sFormat,
                                            ...)
{
    OpcUa_ReferenceParameter(a_uTraceLevel);
    OpcUa_ReferenceParameter(a_sFormat);
#if OPCUA_TRACE_FILE_LINE_INFO
    OpcUa_ReferenceParameter(a_sFile);
    OpcUa_ReferenceParameter(a_sLine);
#endif /* OPCUA_TRACE_FILE_LINE_INFO */

    return OpcUa_False;
}
/*============================================================================
 * OpcUa_P_OpenSSL_RSA_GenerateKeys
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_GenerateKeys(
    OpcUa_CryptoProvider*   a_pProvider,
    OpcUa_UInt32            a_bits,
    OpcUa_Key*              a_pPublicKey,
    OpcUa_Key*              a_pPrivateKey)
{
    RSA*            pRsa;
    unsigned char*  pData;

    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_GenerateKeys");

    OpcUa_ReturnErrorIfArgumentNull(a_pProvider);
    OpcUa_ReturnErrorIfArgumentNull(a_pPublicKey);
    OpcUa_ReturnErrorIfArgumentNull(a_pPrivateKey);

    OpcUa_ReferenceParameter(a_pProvider);

    /* Just 1024 or 2048 bits should be allowed for compatibility reasons */
    if ((a_bits != 1024) && (a_bits != 2048) && (a_bits != 3072) && (a_bits != 4096))
    {
        uStatus = OpcUa_BadInvalidArgument;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(a_pPublicKey->Key.Data == OpcUa_Null)
    {
       a_pPublicKey->Key.Length = a_bits;
       OpcUa_ReturnStatusCode;
    }

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

    pRsa = RSA_generate_key(a_bits, RSA_F4, NULL, OpcUa_Null);

    pData = a_pPublicKey->Key.Data;
    a_pPublicKey->Key.Length = i2d_RSAPublicKey(pRsa, &pData);

    pData = a_pPrivateKey->Key.Data;
    a_pPrivateKey->Key.Length = i2d_RSAPrivateKey(pRsa, &pData);

    /* clean up */
    if(pRsa != OpcUa_Null)
    {
       RSA_free(pRsa);
    }

    a_pPublicKey->Type = OpcUa_Crypto_Rsa_Alg_Id;
    a_pPrivateKey->Type = OpcUa_Crypto_Rsa_Alg_Id;

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

OpcUa_FinishErrorHandling;
}
/*============================================================================
 * OpcUa_P_OpenSSL_X509_GetSignature
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_X509_GetSignature(
    OpcUa_CryptoProvider*       a_pProvider,
    OpcUa_ByteString*           a_pCertificate,
    OpcUa_Signature*            a_pSignature)
{
    X509*                   pX509Certificate    = OpcUa_Null;
    const unsigned char*    pTemp               = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_GetSignature");

    OpcUa_ReferenceParameter(a_pProvider);

    OpcUa_ReturnErrorIfArgumentNull(a_pProvider);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificate);
    OpcUa_ReturnErrorIfArgumentNull(a_pSignature);

    /* d2i_X509 modifies the given pointer -> use local replacement */
    pTemp = a_pCertificate->Data;

    d2i_X509(&pX509Certificate, &pTemp, a_pCertificate->Length);

    if(pX509Certificate == OpcUa_Null)
    {
        uStatus = OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    a_pSignature->Signature.Length = pX509Certificate->signature->length;

    a_pSignature->Algorithm = OBJ_obj2nid(pX509Certificate->sig_alg->algorithm);

    if(a_pSignature->Algorithm == NID_undef)
    {
        uStatus = OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(a_pSignature->Signature.Data != OpcUa_Null)
    {
        uStatus = OpcUa_P_Memory_MemCpy(a_pSignature->Signature.Data,
                                        a_pSignature->Signature.Length,
                                        pX509Certificate->signature->data,
                                        pX509Certificate->signature->length);

    }

    X509_free(pX509Certificate);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

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

OpcUa_FinishErrorHandling;
}
/*============================================================================
 * OpcUa_P_OpenSSL_Random_Key_Generate
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_Random_Key_Generate(
    OpcUa_CryptoProvider* a_pProvider,
    OpcUa_Int32           a_keyLen,
    OpcUa_Key*            a_pKey)
{
    OpcUa_CryptoProviderConfig* pConfig = OpcUa_Null;
    OpcUa_Int32                 keyLen  = 0;

    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "Random_Key_Generate");

    OpcUa_ReturnErrorIfArgumentNull(a_pProvider);
    OpcUa_ReturnErrorIfArgumentNull(a_pKey);

    OpcUa_ReferenceParameter(a_pProvider);

    keyLen = a_keyLen;

    if(keyLen < 0)
    {
        if(a_pProvider->Handle != OpcUa_Null)
        {
            /* get default configuration */
            pConfig = (OpcUa_CryptoProviderConfig*)a_pProvider->Handle;
            keyLen = pConfig->SymmetricKeyLength;
        }
        else
        {
            uStatus = OpcUa_BadInvalidArgument;
            OpcUa_GotoErrorIfBad(uStatus);
        }
    }
    else if(keyLen > MAX_GENERATED_OUTPUT_LEN)
    {
            uStatus = OpcUa_BadInvalidArgument;
            OpcUa_GotoErrorIfBad(uStatus);
    }

    a_pKey->Key.Length = keyLen;
    a_pKey->Type = OpcUa_Crypto_KeyType_Random;

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

    if(RAND_bytes(a_pKey->Key.Data, a_pKey->Key.Length) == 0)
    {
        uStatus = OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;


OpcUa_FinishErrorHandling;
}
/*============================================================================
 * Get last socket error.
 *===========================================================================*/
OpcUa_Int32 OpcUa_P_RawSocket_GetLastError( OpcUa_RawSocket a_RawSocket)
{
    int lastError = 0;
    OpcUa_ReferenceParameter(a_RawSocket); /* Not needed in this implementation. */

    lastError = WSAGetLastError();

    return (OpcUa_Int32)lastError;
}
/*============================================================================
 * Quick Sort
 *===========================================================================*/
OpcUa_Void OPCUA_DLLCALL OpcUa_P_QSort( OpcUa_Void*       pElements,
                                        OpcUa_UInt32      nElementCount,
                                        OpcUa_UInt32      nElementSize,
                                        OpcUa_PfnCompare* pfnCompare,
                                        OpcUa_Void*       pContext)
{
    /*qsort_s(pElements, nElementCount, nElementSize, pfnCompare, pContext);*/
    OpcUa_ReferenceParameter(pContext);
    qsort(pElements, nElementCount, nElementSize, pfnCompare);
}
Beispiel #16
0
/**
  @brief Unlocks the internal mutex and allows other threads to enter the list.

  Takes no action if a_pList is null
  Takes no action if the mutex is null

  @param a_pList    [in]    Location of the list to leave
*/
OpcUa_Void OpcUa_List_Leave(OpcUa_List* a_pList)
{
#if OPCUA_USE_SYNCHRONISATION
    if(a_pList != OpcUa_Null && a_pList->pMutex != OpcUa_Null)
    {
        OPCUA_P_MUTEX_UNLOCK(a_pList->pMutex);
    }
#else /* OPCUA_USE_SYNCHRONISATION */
    OpcUa_ReferenceParameter(a_pList);
#endif /* OPCUA_USE_SYNCHRONISATION */
}
/*============================================================================
 * Binary Search on sorted array
 *===========================================================================*/
OpcUa_Void* OPCUA_DLLCALL OpcUa_P_BSearch(  OpcUa_Void*       pKey,
                                            OpcUa_Void*       pElements,
                                            OpcUa_UInt32      nElementCount,
                                            OpcUa_UInt32      nElementSize,
                                            OpcUa_PfnCompare* pfnCompare,
                                            OpcUa_Void*       pContext)
{
    /*return bsearch_s(pKey, pElements, nElementCount, nElementSize, pfnCompare, pContext);*/
    OpcUa_ReferenceParameter(pContext);
    return bsearch(pKey, pElements, nElementCount, nElementSize, pfnCompare);
}
/*============================================================================
 * Set socket user data
 *===========================================================================*/
static OpcUa_StatusCode OpcUa_P_SocketService_UdpSetUserData(OpcUa_Socket a_pSocket,
                                                             OpcUa_Void*  a_pvUserData)
{
OpcUa_InitializeStatus(OpcUa_Module_Socket, "UdpSetUserData");

    OpcUa_GotoErrorIfArgumentNull(a_pSocket);
    OpcUa_ReferenceParameter(a_pvUserData);

    OpcUa_GotoErrorWithStatus(OpcUa_BadNotImplemented);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
/*============================================================================
 * Select usable socket. (maxfds ignored in win32)
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_RawSocket_Select(  OpcUa_RawSocket         a_MaxFds,
                                            OpcUa_P_Socket_Array*   a_pFdSetRead,
                                            OpcUa_P_Socket_Array*   a_pFdSetWrite,
                                            OpcUa_P_Socket_Array*   a_pFdSetException,
                                            OpcUa_TimeVal*          a_pTimeout)
{
    int                 apiResult  = 0;
    struct timeval      timeout;

OpcUa_InitializeStatus(OpcUa_Module_Socket, "P_Select");

    OpcUa_ReferenceParameter(a_MaxFds);

    OpcUa_GotoErrorIfArgumentNull(a_pFdSetRead);
    OpcUa_GotoErrorIfArgumentNull(a_pFdSetWrite);
    OpcUa_GotoErrorIfArgumentNull(a_pFdSetException);

    timeout.tv_sec  = a_pTimeout->uintSeconds;
    timeout.tv_usec = a_pTimeout->uintMicroSeconds;

    apiResult = select( 0,
                        (fd_set*)a_pFdSetRead,
                        (fd_set*)a_pFdSetWrite,
                        (fd_set*)a_pFdSetException,
                        &timeout);

    if(apiResult == OPCUA_P_SOCKET_SOCKETERROR)
    {
        apiResult = WSAGetLastError();

        switch(apiResult)
        {
        case WSAENOTSOCK:
            {
                uStatus = OpcUa_BadInvalidArgument;
                break;
            }
        default:
            {
                uStatus = OpcUa_BadCommunicationError;
            }
        }
    }

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
/*============================================================================
 * Get IP Address and Port Number of the Peer
 *===========================================================================*/
static OpcUa_StatusCode OpcUa_P_SocketService_UdpGetPeerInfo(  OpcUa_Socket  a_pSocket,
                                                               OpcUa_CharA*  a_achPeerInfoBuffer,
                                                               OpcUa_UInt32  a_uiPeerInfoBufferSize)
{
OpcUa_InitializeStatus(OpcUa_Module_Socket, "UdpGetPeerInfo");

    OpcUa_GotoErrorIfArgumentNull(a_pSocket);
    OpcUa_GotoErrorIfArgumentNull(a_achPeerInfoBuffer);
    OpcUa_ReferenceParameter(a_uiPeerInfoBufferSize);

    OpcUa_GotoErrorWithStatus(OpcUa_BadNotImplemented);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
/* returns number of bytes written to the socket */
static OpcUa_Int32 OpcUa_P_SocketService_UdpWrite( OpcUa_Socket    a_pSocket,
                                                   OpcUa_Byte*     a_pBuffer,
                                                   OpcUa_UInt32    a_uBufferSize,
                                                   OpcUa_Boolean   a_bBlock)
{
    OpcUa_InternalUdpSocket*    pInternalSocket     = (OpcUa_InternalUdpSocket*)a_pSocket;
    OpcUa_Int32                 result;

    OpcUa_ReturnErrorIfNull(a_pSocket, OPCUA_SOCKET_ERROR);
    OpcUa_ReturnErrorIfNull(a_pBuffer, OPCUA_SOCKET_ERROR);
    OpcUa_ReferenceParameter(a_bBlock);

    result = OpcUa_P_RawSocket_Write (pInternalSocket->rawSocket, a_pBuffer, a_uBufferSize);

    return result;
}
/*============================================================================
 * OpcUa_TcpSecureChannel_ReleaseSecuritySet
 *===========================================================================*/
OpcUa_StatusCode OpcUa_TcpSecureChannel_ReleaseSecuritySet( OpcUa_SecureChannel*    a_pSecureChannel,
                                                            OpcUa_UInt32            a_uTokenId)
{
OpcUa_InitializeStatus(OpcUa_Module_SecureChannel, "ReleaseSecuritySet");

    OpcUa_ReturnErrorIfArgumentNull(a_pSecureChannel);

    OpcUa_ReferenceParameter(a_uTokenId);

    OpcUa_Trace(OPCUA_TRACE_LEVEL_DEBUG, "ReleaseSecurityKeyset: Keyset for token %u released.\n", a_uTokenId);

    OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
/*============================================================================
 * OpcUa_P_OpenSSL_PKI_NoSecurity_ExtractCertificateData
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_NoSecurity_ExtractCertificateData(
    OpcUa_ByteString*           a_pCertificate,
    OpcUa_ByteString*           a_pIssuer,
    OpcUa_ByteString*           a_pSubject,
    OpcUa_ByteString*           a_pSubjectUri,
    OpcUa_ByteString*           a_pSubjectIP,
    OpcUa_ByteString*           a_pSubjectDNS,
    OpcUa_ByteString*           a_pCertThumbprint,
    OpcUa_UInt32*               a_pSubjectHash,
    OpcUa_UInt32*               a_pCertRawLength)
{
    OpcUa_ReferenceParameter(a_pCertificate);
    OpcUa_ReferenceParameter(a_pIssuer);
    OpcUa_ReferenceParameter(a_pSubject);
    OpcUa_ReferenceParameter(a_pSubjectUri);
    OpcUa_ReferenceParameter(a_pSubjectIP);
    OpcUa_ReferenceParameter(a_pSubjectDNS);
    OpcUa_ReferenceParameter(a_pCertThumbprint);
    OpcUa_ReferenceParameter(a_pSubjectHash);
    OpcUa_ReferenceParameter(a_pCertRawLength);

    return OpcUa_BadNotSupported;
}
/*===========================================================================*
OpcUa_P_OpenSSL_RSA_Public_GetKeyLength
*===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Public_GetKeyLength(
    OpcUa_CryptoProvider*   a_pProvider,
    OpcUa_Key               a_publicKey,
    OpcUa_UInt32*           a_pKeyLen)
{
    EVP_PKEY*       pPublicKey      = OpcUa_Null;
    const unsigned char *pData;

    OpcUa_UInt32    uKeySize            = 0;

    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Public_GetKeyLength");

    OpcUa_ReferenceParameter(a_pProvider);

    OpcUa_ReturnErrorIfArgumentNull(a_publicKey.Key.Data);
    OpcUa_ReturnErrorIfArgumentNull(a_pKeyLen);

    *a_pKeyLen = 0;

    if(a_publicKey.Type != OpcUa_Crypto_KeyType_Rsa_Public)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument);
    }

    pData = a_publicKey.Key.Data;
    pPublicKey = d2i_PublicKey(EVP_PKEY_RSA, OpcUa_Null, &pData, a_publicKey.Key.Length);

    uKeySize = RSA_size(pPublicKey->pkey.rsa);

    *a_pKeyLen = uKeySize*8;

    EVP_PKEY_free(pPublicKey);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

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

    *a_pKeyLen = (OpcUa_UInt32)-1;

OpcUa_FinishErrorHandling;
}
Beispiel #25
0
/*============================================================================
 * OpcUa_P_OpenSSL_CertificateStore_Close
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_CloseCertificateStore(
    OpcUa_PKIProvider*          a_pProvider,
    OpcUa_Void**                a_ppCertificateStore) /* type depends on store implementation */
{
OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_CloseCertificateStore");

    OpcUa_ReferenceParameter(a_pProvider);

    if(*a_ppCertificateStore != OpcUa_Null)
    {
        X509_STORE_free((X509_STORE*)*a_ppCertificateStore);
        *a_ppCertificateStore = OpcUa_Null;
    }

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
/*============================================================================
 * OpcUa_MemoryStream_Flush
 *===========================================================================*/
static
OpcUa_StatusCode OpcUa_MemoryStream_Flush(
    OpcUa_OutputStream* ostrm,
    OpcUa_Boolean       lastCall)
{
    OpcUa_MemoryStream* handle = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_MemoryStream, "Flush");

    OpcUa_ReturnErrorIfArgumentNull(ostrm);
    OpcUa_ReturnErrorIfInvalidStream(ostrm, Flush);
    OpcUa_ReferenceParameter(lastCall);

    handle = (OpcUa_MemoryStream*)ostrm->Handle;

    if(handle->Closed)
    {
        return OpcUa_BadInvalidState;
    }

    if(!OpcUa_Buffer_IsEmpty((OpcUa_Buffer *)handle->pBuffer))
    {
        OpcUa_Byte*  pData          = OpcUa_Null;
        OpcUa_UInt32 uDataLength    = 0;

        uStatus = OpcUa_Buffer_GetData(handle->pBuffer, &pData, &uDataLength);

        if (OpcUa_IsBad(uStatus))
        {
            OpcUa_Trace(OPCUA_TRACE_LEVEL_ERROR, "Flush: FAILED with 0x%X\n", uStatus);
            OpcUa_GotoError;
        }
    }

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
Beispiel #27
0
/* SHA-2: 256 Bits output */
OpcUa_StatusCode OpcUa_P_OpenSSL_SHA2_256_Generate(
    OpcUa_CryptoProvider*         a_pProvider,
    OpcUa_Byte*                   a_pData,
    OpcUa_UInt32                  a_dataLen,
    OpcUa_Byte*                   a_pMessageDigest)
{
    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "SHA2_256_Generate");

    OpcUa_ReferenceParameter(a_pProvider);

    OpcUa_ReturnErrorIfArgumentNull(a_pData);
    OpcUa_ReturnErrorIfArgumentNull(a_pMessageDigest);

    if(SHA256(a_pData, a_dataLen, a_pMessageDigest) == OpcUa_Null)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_Bad);
    }

OpcUa_ReturnStatusCode;

OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
/*============================================================================
 * OpcUa_P_OpenSSL_RSA_Private_Decrypt
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Private_Decrypt(
    OpcUa_CryptoProvider*   a_pProvider,
    OpcUa_Byte*             a_pCipherText,
    OpcUa_UInt32            a_cipherTextLen,
    OpcUa_Key*              a_privateKey,
    OpcUa_Int16             a_padding,
    OpcUa_Byte*             a_pPlainText,
    OpcUa_UInt32*           a_pPlainTextLen)
{
    EVP_PKEY*       pPrivateKey     = OpcUa_Null;

    OpcUa_UInt32    keySize         = 0;
    OpcUa_Int32     decryptedBytes  = 0;
    OpcUa_UInt32    iCipherText     = 0;
    /* OpcUa_UInt32 iPlainTextLen   = 0; */
    OpcUa_UInt32    decDataSize     = 0;

    const char*     sError          = OpcUa_Null;
    const unsigned char *pData;

    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Private_Decrypt");

    OpcUa_ReferenceParameter(a_pProvider);

    OpcUa_ReturnErrorIfArgumentNull(a_pCipherText);
    OpcUa_ReturnErrorIfArgumentNull(a_privateKey);
    OpcUa_ReturnErrorIfArgumentNull(a_privateKey->Key.Data);
    OpcUa_ReturnErrorIfArgumentNull(a_pPlainTextLen);

    *a_pPlainTextLen = 0;

    if(a_privateKey->Type != OpcUa_Crypto_KeyType_Rsa_Private)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument);
    }

    pData = a_privateKey->Key.Data;
    pPrivateKey = d2i_PrivateKey(EVP_PKEY_RSA,OpcUa_Null, &pData, a_privateKey->Key.Length);

    if (pPrivateKey == OpcUa_Null)
    {
        long lErr = ERR_get_error();
        char *szErr = ERR_error_string(lErr, 0);
        OpcUa_ReferenceParameter(szErr);
        return OpcUa_BadInvalidArgument;
    }

    keySize = RSA_size(pPrivateKey->pkey.rsa);

    if((a_cipherTextLen%keySize) != 0)
    {
        uStatus = OpcUa_BadInvalidArgument;
        OpcUa_GotoError;
    }

    /* check padding type */
    switch(a_padding)
    {
    case RSA_PKCS1_PADDING:
        {
            decDataSize = keySize - 11;
            break;
        }
    case RSA_PKCS1_OAEP_PADDING:
        {
            decDataSize = keySize - 42;
            break;
        }
    case RSA_NO_PADDING:
        {
            decDataSize = keySize;
            break;
        }
    default:
        {
            OpcUa_GotoErrorWithStatus(OpcUa_BadNotSupported);
        }
    }

    while(iCipherText < a_cipherTextLen)
    {
        if(a_pPlainText != OpcUa_Null)
        {
            decryptedBytes = RSA_private_decrypt(   keySize,                            /* how much to decrypt  */
                                                    a_pCipherText + iCipherText,        /* what to decrypt      */
                                                    a_pPlainText + (*a_pPlainTextLen),  /* where to decrypt     */
                                                    pPrivateKey->pkey.rsa,              /* private key          */
                                                    a_padding);                         /* padding mode         */

            /* goto error block, if decryption fails */
            if(decryptedBytes == -1)
            {
                /* const char* serror = NULL; */
                unsigned long error = ERR_get_error();

                ERR_load_crypto_strings();

                sError = ERR_reason_error_string(error);
                sError = ERR_func_error_string(error);
                sError = ERR_lib_error_string(error);

                uStatus = OpcUa_Bad;
                OpcUa_GotoError;
            }

        }
        else
        {
            decryptedBytes = decDataSize;
        }

        *a_pPlainTextLen = *a_pPlainTextLen + decryptedBytes;
        iCipherText = iCipherText + keySize;
    }


    EVP_PKEY_free(pPrivateKey);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

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

    *a_pPlainTextLen = (OpcUa_UInt32)-1;

OpcUa_FinishErrorHandling;
}
/*===========================================================================*
OpcUa_P_OpenSSL_RSA_Public_Encrypt
*===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_Public_Encrypt(
    OpcUa_CryptoProvider*   a_pProvider,
    OpcUa_Byte*             a_pPlainText,
    OpcUa_UInt32            a_plainTextLen,
    OpcUa_Key*              a_publicKey,
    OpcUa_Int16             a_padding,
    OpcUa_Byte*             a_pCipherText,
    OpcUa_UInt32*           a_pCipherTextLen)
{
    EVP_PKEY*       pPublicKey      = OpcUa_Null;

    OpcUa_UInt32    uKeySize            = 0;
    OpcUa_UInt32    uEncryptedDataSize  = 0;
    OpcUa_UInt32    uPlainTextPosition  = 0;
    OpcUa_UInt32    uCipherTextPosition = 0;
    OpcUa_UInt32    uBytesToEncrypt     = 0;
    OpcUa_Int32     iEncryptedBytes     = 0;
    const unsigned char *pData;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_Public_Encrypt");

    OpcUa_ReferenceParameter(a_pProvider);

    OpcUa_ReturnErrorIfArgumentNull(a_publicKey);
    OpcUa_ReturnErrorIfArgumentNull(a_publicKey->Key.Data);
    OpcUa_ReturnErrorIfArgumentNull(a_pCipherTextLen);

    *a_pCipherTextLen = 0;

    if((OpcUa_Int32)a_plainTextLen < 1)
    {
        uStatus = OpcUa_BadInvalidArgument;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(a_publicKey->Type != OpcUa_Crypto_KeyType_Rsa_Public)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument);
    }

    pData = a_publicKey->Key.Data;
    pPublicKey = d2i_PublicKey(EVP_PKEY_RSA, OpcUa_Null, &pData, a_publicKey->Key.Length);

    if ( pPublicKey != OpcUa_Null )
    {
        uKeySize = RSA_size(pPublicKey->pkey.rsa);
    }
    else
    {
        OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument);
    }

    /* check padding type */
    switch(a_padding)
    {
    case RSA_PKCS1_PADDING:
        {
            uEncryptedDataSize = uKeySize - 11;
            break;
        }
    case RSA_PKCS1_OAEP_PADDING:
        {
            uEncryptedDataSize = uKeySize - 42;
            break;
        }
    case RSA_NO_PADDING:
        {
            uEncryptedDataSize = uKeySize;
            break;
        }
    default:
        {
            OpcUa_GotoErrorWithStatus(OpcUa_BadNotSupported);
        }
    }

    if(a_plainTextLen < uEncryptedDataSize)
    {
        uBytesToEncrypt = a_plainTextLen;
    }
    else
    {
        uBytesToEncrypt = uEncryptedDataSize;
    }

    while(uPlainTextPosition < a_plainTextLen)
    {

        /* the last part could be smaller */
        if((a_plainTextLen >= uEncryptedDataSize) && ((a_plainTextLen - uPlainTextPosition) < uEncryptedDataSize))
        {
            uBytesToEncrypt = a_plainTextLen - uPlainTextPosition;
        }

        if((a_pCipherText != OpcUa_Null) && (a_pPlainText != OpcUa_Null))
        {
            iEncryptedBytes = RSA_public_encrypt(   uBytesToEncrypt,      /* how much to encrypt  */
                                                    a_pPlainText + uPlainTextPosition,      /* what to encrypt      */
                                                    a_pCipherText + uCipherTextPosition,/* where to encrypt     */
                                                    pPublicKey->pkey.rsa,                  /* public key           */
                                                    a_padding);        /* padding mode         */
            if(iEncryptedBytes < 0)
            {
                const char*     sError          = OpcUa_Null;
                unsigned long   error           = 0;

                error = ERR_get_error();

                ERR_load_crypto_strings();

                sError = ERR_reason_error_string(error);
                sError = ERR_func_error_string(error);
                sError = ERR_lib_error_string(error);

                uStatus = OpcUa_Bad;
                OpcUa_GotoError;
            }

        }
        else
        {
            iEncryptedBytes = uKeySize;
        }

        *a_pCipherTextLen = *a_pCipherTextLen + iEncryptedBytes;
        uCipherTextPosition += uKeySize;
        uPlainTextPosition  += uBytesToEncrypt;
    }

    EVP_PKEY_free(pPublicKey);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

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

    *a_pCipherTextLen = (OpcUa_UInt32)-1;

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;
}