Beispiel #1
0
/*============================================================================
 * Allocate the mutex.
 *===========================================================================*/
OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_Mutex_Create(OpcUa_Mutex* phMutex)
{
    OpcUa_StatusCode uStatus        = OpcUa_Good;
    pthread_mutex_t* pPosixMutex    = OpcUa_Null;

    if(phMutex == OpcUa_Null)
    {
        return OpcUa_BadInvalidArgument;
    }

    pPosixMutex = OpcUa_P_Memory_Alloc(sizeof(pthread_mutex_t));
    OpcUa_ReturnErrorIfAllocFailed(pPosixMutex);

    uStatus = OpcUa_P_Mutex_Initialize((OpcUa_Mutex)pPosixMutex);
    if(OpcUa_IsBad(uStatus))
    {
        OpcUa_P_Mutex_Delete((OpcUa_Mutex*)&pPosixMutex);
    }
    else
    {
        *phMutex = (OpcUa_Mutex)pPosixMutex;
    }

    return uStatus;
}
/*============================================================================
 * Create a UDP sender socket
 *===========================================================================*/
OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_SocketUdp_CreateSender(  OpcUa_StringA    a_LocalIpAddress,
                                                                OpcUa_StringA    a_RemoteIpAddress,
                                                                OpcUa_Int16      a_RemotePort,
                                                                OpcUa_Byte       a_TimeToLive,
                                                                OpcUa_Socket*    a_pSocket)
{
    OpcUa_InternalUdpSocket* pInternalSocket = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_Socket, "CreateUdpSender");

    OpcUa_ReturnErrorIfArgumentNull(a_pSocket);

    *a_pSocket = OpcUa_Null;

    OpcUa_GotoErrorIfArgumentNull(a_RemoteIpAddress);

    if(a_RemotePort == 0)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument);
    }

    pInternalSocket = (OpcUa_InternalUdpSocket*)OpcUa_P_Memory_Alloc(sizeof(OpcUa_InternalUdpSocket));
    OpcUa_GotoErrorIfAllocFailed(pInternalSocket);

    pInternalSocket->pSocketServiceTable      = &OpcUa_UdpSocketServiceTable;

    if(strchr(a_RemoteIpAddress, ':'))
    {
        uStatus = OpcUa_P_RawSocket_CreateUdpV6(&pInternalSocket->rawSocket,
                                                OpcUa_True,
                                                a_LocalIpAddress,
                                                a_RemoteIpAddress,
                                                a_RemotePort,
                                                a_TimeToLive);
        OpcUa_GotoErrorIfBad(uStatus);
    }
    else
    {
        uStatus = OpcUa_P_RawSocket_CreateUdp(&pInternalSocket->rawSocket,
                                              OpcUa_True,
                                              a_LocalIpAddress,
                                              a_RemoteIpAddress,
                                              a_RemotePort,
                                              a_TimeToLive);
        OpcUa_GotoErrorIfBad(uStatus);
    }

    *a_pSocket = pInternalSocket;

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

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

OpcUa_FinishErrorHandling;
}
Beispiel #3
0
/*============================================================================
 * Allocate the mutex.
 *===========================================================================*/
OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_Mutex_CreateImp(OpcUa_Mutex* phMutex, char* file, int line)
{
    OpcUa_StatusCode uStatus = OpcUa_Good;
    CRITICAL_SECTION *pCS;
    OpcUa_P_InternalMutex* pInternalMutex = OpcUa_Null;

    if(phMutex == OpcUa_Null)
    {
        printf("Invalid Argument Error in: OpcUa_P_Mutex_Create!\n");
        return OpcUa_BadInvalidArgument;
    }

    pCS = OpcUa_P_Memory_Alloc(sizeof(CRITICAL_SECTION));
    if(pCS == NULL)
    {
        printf("Out of memory Error in: OpcUa_P_Mutex_Create!\n");
        return OpcUa_BadOutOfMemory;
    }

    pInternalMutex = (OpcUa_P_InternalMutex*)OpcUa_P_Memory_Alloc(sizeof(OpcUa_P_InternalMutex));
    if(pInternalMutex == NULL)
    {
        printf("Out of memory Error in: OpcUa_P_Mutex_Create!\n");
        return OpcUa_BadOutOfMemory;
    }

    g_nMutexId++;

    pInternalMutex->pSystemMutex = pCS;
    pInternalMutex->nLockCount = 0;
    pInternalMutex->uThreadId  = 0;
    pInternalMutex->nMutexId   = g_nMutexId;

    InitializeCriticalSection(pCS);

    *phMutex = (OpcUa_Mutex)pInternalMutex;

    /* printf("Created  Mutex%d, File: %s, Line: %d\n", pInternalMutex->nMutexId, file, line); */

    return uStatus;
}
Beispiel #4
0
/*============================================================================
 * Allocate the mutex.
 *===========================================================================*/
OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_Mutex_CreateImp(OpcUa_Mutex* a_phMutex)
{
    OpcUa_StatusCode uStatus = OpcUa_Good;
    LPCRITICAL_SECTION lpCriticalSection = NULL;

#if OPCUA_MUTEX_USE_SPINCOUNT
    BOOL bRet;
    LONG hr;
#endif

    if(a_phMutex == OpcUa_Null)
    {
        return OpcUa_BadInvalidArgument;
    }

    if(*a_phMutex != OpcUa_Null)
    {
        *a_phMutex = OpcUa_Null;
    }

    lpCriticalSection = OpcUa_P_Memory_Alloc(sizeof(CRITICAL_SECTION));

    if(lpCriticalSection == NULL)
    {
        return OpcUa_BadOutOfMemory;
    }

#if OPCUA_MUTEX_USE_SPINCOUNT
    bRet = InitializeCriticalSectionAndSpinCount(   lpCriticalSection,
                                                    0x00000400) ;
    if (bRet == 0)
    {
        hr = GetLastError();
        OpcUa_P_Memory_Free(lpCriticalSection);
        return OpcUa_Bad;
    }

#else
    InitializeCriticalSection(lpCriticalSection);
#endif

    *a_phMutex = (OpcUa_Mutex)lpCriticalSection;

    return uStatus;
}
/*============================================================================
 * Create a platform thread
 *===========================================================================*/
OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_Thread_Create(OpcUa_RawThread* pRawThread)
{
    OpcUa_StatusCode   uStatus     = OpcUa_Good;
    OpcUa_P_ThreadArg* pThreadArgs = OpcUa_Null;

    *pRawThread = OpcUa_Null;

    pThreadArgs = (OpcUa_P_ThreadArg*)OpcUa_P_Memory_Alloc(sizeof(OpcUa_P_ThreadArg));
    OpcUa_ReturnErrorIfAllocFailed(pThreadArgs);

    pThreadArgs->hThread                = INVALID_HANDLE_VALUE;
    pThreadArgs->pfnInternalThreadMain  = OpcUa_Null;
    pThreadArgs->ThreadArgs             = OpcUa_Null;

    *pRawThread = (OpcUa_RawThread)pThreadArgs;

    return uStatus;
}
/* internal function */
OpcUa_P_OpenSSL_PSHA256_Ctx* OpcUa_P_OpenSSL_PSHA256_Context_Create(
    OpcUa_Byte*     a_pSecret,
    OpcUa_UInt32    a_secretLen,
    OpcUa_Byte*     a_pSeed,
    OpcUa_Int32     a_seedLen)
{
    OpcUa_P_OpenSSL_PSHA256_Ctx*  pCtx;
    OpcUa_Int                   size;

    if(a_pSecret == OpcUa_Null || a_pSeed   == OpcUa_Null)
        return OpcUa_Null;

    pCtx = OpcUa_Null;
    size = sizeof(OpcUa_P_OpenSSL_PSHA256_Ctx) + a_secretLen + a_seedLen;

    pCtx = (OpcUa_P_OpenSSL_PSHA256_Ctx*) OpcUa_P_Memory_Alloc(size);

    if (pCtx == OpcUa_Null)
        return OpcUa_Null;

    pCtx->secret_len = a_secretLen;
    pCtx->seed_len = a_seedLen;

    OpcUa_P_Memory_MemCpy(OpcUa_P_OpenSSL_PSHA256_SECRET(pCtx), a_secretLen, a_pSecret, a_secretLen);
    OpcUa_P_Memory_MemCpy(OpcUa_P_OpenSSL_PSHA256_SEED(pCtx), a_seedLen, a_pSeed, a_seedLen);

    /* A(0) = seed */
    /* A(i) = HMAC_SHA256(secret, A(i-1)) */
    /* Calculate A(1) = HMAC_SHA256(secret, seed) */
    HMAC(EVP_sha256(), a_pSecret, a_secretLen, a_pSeed, a_seedLen, (unsigned char*)pCtx->A, (unsigned int*)OpcUa_Null);

    if(pCtx == OpcUa_Null)
        return OpcUa_Null;

    return pCtx;
}
/*============================================================================
 * 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;
}
/*============================================================================
 * OpcUa_P_ParseUrl
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_ParseUrl(  OpcUa_StringA   a_psUrl,
                                    OpcUa_StringA*  a_psIpAdress,
                                    OpcUa_UInt16*   a_puPort)
{
    OpcUa_UInt32    uUrlLength        = 0;

    OpcUa_StringA   sHostName         = OpcUa_Null;
    OpcUa_UInt32    uHostNameLength   = 0;

    OpcUa_CharA*    pcCursor          = OpcUa_Null;

    OpcUa_Int       nIndex1           = 0;
    OpcUa_Int       nIpStart          = 0;

    struct hostent* pHostEnt          = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_Utilities, "P_ParseUrl");

    OpcUa_ReturnErrorIfArgumentNull(a_psUrl);
    OpcUa_ReturnErrorIfArgumentNull(a_psIpAdress);
    OpcUa_ReturnErrorIfArgumentNull(a_puPort);

    *a_psIpAdress = OpcUa_Null;

    uUrlLength = (OpcUa_UInt32)strlen(a_psUrl);

    /* check for // (end of protocol header) */
    pcCursor = strstr(a_psUrl, "//");

    if(pcCursor != OpcUa_Null)
    {
        /* begin of host address */
        pcCursor += 2;
        nIndex1 = (OpcUa_Int)(pcCursor - a_psUrl);
    }
    else
    {
        uStatus = OpcUa_BadSyntaxError;
        OpcUa_ReturnStatusCode;
    }

    /* skip protocol prefix and store beginning of ip adress */
    nIpStart = nIndex1;

    /* skip host address */
    while(      a_psUrl[nIndex1] != ':'
            &&  a_psUrl[nIndex1] != '/'
            &&  a_psUrl[nIndex1] != 0
            &&  nIndex1          <  (OpcUa_Int32)uUrlLength)
    {
        nIndex1++;
    }

    uHostNameLength = nIndex1 - nIpStart;
    sHostName       = (OpcUa_StringA)malloc(uHostNameLength + 1);
    if(sHostName == NULL)
    {
        return OpcUa_BadOutOfMemory;
    }

    memcpy(sHostName, &a_psUrl[nIpStart], uHostNameLength);
    sHostName[uHostNameLength] = '\0';

    pHostEnt = gethostbyname(sHostName);

    free(sHostName);

    if(pHostEnt == NULL)
    {
        /* hostname could not be resolved */
        return OpcUa_BadHostUnknown;
    }

    nIpStart = 0;
    *a_psIpAdress = (OpcUa_StringA)OpcUa_P_Memory_Alloc(16);
    memset(*a_psIpAdress, 0, 16);

#if OPCUA_USE_SAFE_FUNCTIONS
    nIpStart += sprintf_s(&(*a_psIpAdress)[0],         16,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[0]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf_s(&(*a_psIpAdress)[nIpStart],  12,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[1]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf_s(&(*a_psIpAdress)[nIpStart],   8,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[2]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf_s(&(*a_psIpAdress)[nIpStart],   4,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[3]);
#else /* OPCUA_USE_SAFE_FUNCTIONS */

    nIpStart += sprintf(&(*a_psIpAdress)[0], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[0]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf(&(*a_psIpAdress)[nIpStart], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[1]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf(&(*a_psIpAdress)[nIpStart], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[2]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf(&(*a_psIpAdress)[nIpStart], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[3]);
#endif /* OPCUA_USE_SAFE_FUNCTIONS */

    /* scan port */
    if(a_psUrl[nIndex1] == ':')
    {
        OpcUa_Int       nIndex2 = 0;
        OpcUa_CharA*    sPort   = OpcUa_Null;
        OpcUa_CharA sBuffer[MAX_PORT_LENGTH];

        /* skip delimiter */
        nIndex1++;

        /* store beginning of port */
        sPort = &a_psUrl[nIndex1];

        /* search for end of port */
        while(      a_psUrl[nIndex1] != '/'
                &&  a_psUrl[nIndex1] != 0
                &&  nIndex2          <  6)
        {
            nIndex1++;
            nIndex2++;
        }

        /* convert port */
        OpcUa_P_Memory_MemCpy(sBuffer, MAX_PORT_LENGTH-1, sPort, nIndex2);
        sBuffer[nIndex2] = 0;
        *a_puPort = (OpcUa_UInt16)OpcUa_P_CharAToInt(sBuffer);
    }
    else
    {
        /* return default port */
        if (strncmp(a_psUrl, "http:", 5) != 0)
        {
            *a_puPort = OPCUA_TCP_DEFAULT_PORT;
        }
        else
        {
            *a_puPort = OPCUA_HTTP_DEFAULT_PORT;
        }
    }

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
/**
  @brief Extracts data from a certificate store object.

  @param pCertificate          [in] The certificate to examine.
  @param pIssuer               [out, optional] The issuer name of the certificate.
  @param pSubject              [out, optional] The subject name of the certificate.
  @param pSubjectUri           [out, optional] The subject's URI of the certificate.
  @param pSubjectIP            [out, optional] The subject's IP of the certificate.
  @param pSubjectDNS           [out, optional] The subject's DNS name of the certificate.
  @param pCertThumbprint       [out, optional] The thumbprint of the certificate.
  @param pSubjectHash          [out, optional] The hash code of the certificate.
  @param pCertRawLength        [out, optional] The length of the DER encoded data.
                               can be smaller than the total length of pCertificate in case of chain certificate or garbage follow.
*/
OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_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)
{
    X509*                       pX509Cert = OpcUa_Null;
    char*                       pName = OpcUa_Null;
    GENERAL_NAMES*              pNames = OpcUa_Null;
    const unsigned char*        p;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_ExtractCertificateData");

    OpcUa_ReturnErrorIfArgumentNull(a_pCertificate);

    if(a_pIssuer != OpcUa_Null)
    {
        a_pIssuer->Data = OpcUa_Null;
        a_pIssuer->Length = 0;
    }

    if(a_pSubject != OpcUa_Null)
    {
        a_pSubject->Data = OpcUa_Null;
        a_pSubject->Length = 0;
    }

    if(a_pSubjectUri != OpcUa_Null)
    {
        a_pSubjectUri->Data = OpcUa_Null;
        a_pSubjectUri->Length = 0;
    }

    if(a_pSubjectIP != OpcUa_Null)
    {
        a_pSubjectIP->Data = OpcUa_Null;
        a_pSubjectIP->Length = 0;
    }

    if(a_pSubjectDNS != OpcUa_Null)
    {
        a_pSubjectDNS->Data = OpcUa_Null;
        a_pSubjectDNS->Length = 0;
    }

    if(a_pCertThumbprint != OpcUa_Null)
    {
        a_pCertThumbprint->Data = OpcUa_Null;
        a_pCertThumbprint->Length = 0;
    }

    if(a_pSubjectHash != OpcUa_Null)
    {
        *a_pSubjectHash = 0;
    }

    if(a_pCertRawLength != OpcUa_Null)
    {
        *a_pCertRawLength = 0;
    }

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

    if(a_pIssuer != OpcUa_Null)
    {
        pName = X509_NAME_oneline(X509_get_issuer_name(pX509Cert), NULL, 0);
        OpcUa_GotoErrorIfAllocFailed(pName);
        a_pIssuer->Length = strlen(pName)+1;
        a_pIssuer->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pIssuer->Length*sizeof(OpcUa_Byte));
        OpcUa_GotoErrorIfAllocFailed(a_pIssuer->Data);
        uStatus = OpcUa_P_Memory_MemCpy(a_pIssuer->Data, a_pIssuer->Length, pName, a_pIssuer->Length);
        OpcUa_GotoErrorIfBad(uStatus);
        OPENSSL_free(pName);
        pName = OpcUa_Null;
    }

    if(a_pSubject != OpcUa_Null)
    {
        pName = X509_NAME_oneline(X509_get_subject_name(pX509Cert), NULL, 0);
        OpcUa_GotoErrorIfAllocFailed(pName);
        a_pSubject->Length = strlen(pName)+1;
        a_pSubject->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubject->Length*sizeof(OpcUa_Byte));
        OpcUa_GotoErrorIfAllocFailed(a_pSubject->Data);
        uStatus = OpcUa_P_Memory_MemCpy(a_pSubject->Data, a_pSubject->Length, pName, a_pSubject->Length);
        OpcUa_GotoErrorIfBad(uStatus);
        OPENSSL_free(pName);
        pName = OpcUa_Null;
    }

    if(a_pSubjectUri != OpcUa_Null || a_pSubjectIP != OpcUa_Null || a_pSubjectDNS != OpcUa_Null)
    {
        pNames = X509_get_ext_d2i(pX509Cert, NID_subject_alt_name, OpcUa_Null, OpcUa_Null);
        if (pNames != OpcUa_Null)
        {
            int num;
            for (num = 0; num < sk_GENERAL_NAME_num(pNames); num++)
            {
                GENERAL_NAME *value = sk_GENERAL_NAME_value(pNames, num);
                switch (value->type)
                {
                case GEN_URI:
                    if (a_pSubjectUri != OpcUa_Null && a_pSubjectUri->Data == OpcUa_Null)
                    {
                        a_pSubjectUri->Length = value->d.ia5->length+1;
                        a_pSubjectUri->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectUri->Length*sizeof(OpcUa_Byte));
                        OpcUa_GotoErrorIfAllocFailed(a_pSubjectUri->Data);
                        uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectUri->Data, a_pSubjectUri->Length, value->d.ia5->data, a_pSubjectUri->Length);
                        OpcUa_GotoErrorIfBad(uStatus);
                    }
                break;

                case GEN_IPADD:
                    if (a_pSubjectIP != OpcUa_Null && a_pSubjectIP->Data == OpcUa_Null)
                    {
                        a_pSubjectIP->Length = value->d.ip->length;
                        a_pSubjectIP->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectIP->Length*sizeof(OpcUa_Byte));
                        OpcUa_GotoErrorIfAllocFailed(a_pSubjectIP->Data);
                        uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectIP->Data, a_pSubjectIP->Length, value->d.ip->data, a_pSubjectIP->Length);
                        OpcUa_GotoErrorIfBad(uStatus);
                    }
                break;

                case GEN_DNS:
                    if (a_pSubjectDNS != OpcUa_Null && a_pSubjectDNS->Data == OpcUa_Null)
                    {
                        a_pSubjectDNS->Length = value->d.ia5->length+1;
                        a_pSubjectDNS->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectDNS->Length*sizeof(OpcUa_Byte));
                        OpcUa_GotoErrorIfAllocFailed(a_pSubjectDNS->Data);
                        uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectDNS->Data, a_pSubjectDNS->Length, value->d.ia5->data, a_pSubjectDNS->Length);
                        OpcUa_GotoErrorIfBad(uStatus);
                    }
                break;
                }
            }
            sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free);
            pNames = OpcUa_Null;
        }
    }

    if(a_pCertThumbprint != OpcUa_Null)
    {
        /* update pX509Cert->sha1_hash */
        X509_check_purpose(pX509Cert, -1, 0);
        a_pCertThumbprint->Length = sizeof(pX509Cert->sha1_hash);
        a_pCertThumbprint->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertThumbprint->Length*sizeof(OpcUa_Byte));
        OpcUa_GotoErrorIfAllocFailed(a_pCertThumbprint->Data);
        uStatus = OpcUa_P_Memory_MemCpy(a_pCertThumbprint->Data, a_pCertThumbprint->Length, pX509Cert->sha1_hash, a_pCertThumbprint->Length);
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(a_pSubjectHash != OpcUa_Null)
    {
        *a_pSubjectHash = X509_NAME_hash(X509_get_subject_name(pX509Cert));
    }

    if(a_pCertRawLength != OpcUa_Null)
    {
        *a_pCertRawLength = (OpcUa_UInt32)(p - a_pCertificate->Data);
    }

    X509_free(pX509Cert);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(a_pIssuer != OpcUa_Null && a_pIssuer->Data != OpcUa_Null)
    {
        OpcUa_P_Memory_Free(a_pIssuer->Data);
        a_pIssuer->Data = OpcUa_Null;
        a_pIssuer->Length = 0;
    }

    if(a_pSubject != OpcUa_Null && a_pSubject->Data != OpcUa_Null)
    {
        OpcUa_P_Memory_Free(a_pSubject->Data);
        a_pSubject->Data = OpcUa_Null;
        a_pSubject->Length = 0;
    }

    if(a_pSubjectUri != OpcUa_Null && a_pSubjectUri->Data != OpcUa_Null)
    {
        OpcUa_P_Memory_Free(a_pSubjectUri->Data);
        a_pSubjectUri->Data = OpcUa_Null;
        a_pSubjectUri->Length = 0;
    }

    if(a_pSubjectIP != OpcUa_Null && a_pSubjectIP->Data != OpcUa_Null)
    {
        OpcUa_P_Memory_Free(a_pSubjectIP->Data);
        a_pSubjectIP->Data = OpcUa_Null;
        a_pSubjectIP->Length = 0;
    }

    if(a_pSubjectDNS != OpcUa_Null && a_pSubjectDNS->Data != OpcUa_Null)
    {
        OpcUa_P_Memory_Free(a_pSubjectDNS->Data);
        a_pSubjectDNS->Data = OpcUa_Null;
        a_pSubjectDNS->Length = 0;
    }

    if(a_pCertThumbprint != OpcUa_Null && a_pCertThumbprint->Data != OpcUa_Null)
    {
        OpcUa_P_Memory_Free(a_pCertThumbprint->Data);
        a_pCertThumbprint->Data = OpcUa_Null;
        a_pCertThumbprint->Length = 0;
    }

    if (pName != OpcUa_Null)
    {
        OPENSSL_free(pName);
    }

    if (pNames != OpcUa_Null)
    {
        sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free);
    }

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

OpcUa_FinishErrorHandling;
}
Beispiel #10
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;
}
/*============================================================================
 * Create a new socket manager or initialize the global one (OpcUa_Null first).
 *===========================================================================*/
OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_SocketManager_Create(OpcUa_SocketManager*    a_pSocketManager,
                                                            OpcUa_UInt32            a_nSockets,
                                                            OpcUa_UInt32            a_nFlags)
{
    OpcUa_InternalSocketManager*    pInternalSocketManager   = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_Socket, "SocketManager_Create");

    if(a_nFlags & 0xFFFFFFF8)
    {
        return OpcUa_BadInvalidArgument;
    }

    if(a_nSockets > OPCUA_P_SOCKETMANAGER_NUMBEROFSOCKETS)
    {
        return OpcUa_BadInvalidArgument;
    }

    /* set number of socket to maximum */
    if(a_nSockets == 0)
    {
        a_nSockets = OPCUA_P_SOCKETMANAGER_NUMBEROFSOCKETS;
    }

    a_nSockets += 1; /* add signal socket to requested sockets */

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

    if(a_pSocketManager == OpcUa_Null)
    {
        return OpcUa_BadInvalidArgument;
    }

    *a_pSocketManager = OpcUa_SocketManager_Alloc();
    OpcUa_GotoErrorIfAllocFailed(*a_pSocketManager);

    pInternalSocketManager = (OpcUa_InternalSocketManager*)*a_pSocketManager;

    OpcUa_SocketManager_Initialize(pInternalSocketManager);

#if OPCUA_USE_SYNCHRONISATION
    uStatus = OpcUa_P_Mutex_Create(&pInternalSocketManager->pMutex);
    OpcUa_GotoErrorIfBad(uStatus);
#endif /* OPCUA_USE_SYNCHRONISATION */

    /* preallocate socket structures for all possible sockets (maxsockets) */
    uStatus = OpcUa_SocketManager_CreateSockets((OpcUa_SocketManager)pInternalSocketManager, a_nSockets);
    OpcUa_GotoErrorIfBad(uStatus);

    pInternalSocketManager->uintLastExternalEvent  = OPCUA_SOCKET_NO_EVENT;

    /* set the behaviour flags */
    if((a_nFlags & OPCUA_SOCKET_SPAWN_THREAD_ON_ACCEPT)    != OPCUA_SOCKET_NO_FLAG)
    {
        pInternalSocketManager->Flags.bSpawnThreadOnAccept      = OpcUa_True;
    }

    if((a_nFlags & OPCUA_SOCKET_REJECT_ON_NO_THREAD)       != OPCUA_SOCKET_NO_FLAG)
    {
        pInternalSocketManager->Flags.bRejectOnThreadFail       = OpcUa_True;
    }

    if((a_nFlags & OPCUA_SOCKET_DONT_CLOSE_ON_EXCEPT)      != OPCUA_SOCKET_NO_FLAG)
    {
        pInternalSocketManager->Flags.bDontCloseOnExcept        = OpcUa_True;
    }

    uStatus = OpcUa_P_SocketManager_NewSignalSocket(pInternalSocketManager);
    OpcUa_GotoErrorIfBad(uStatus);

#if OPCUA_MULTITHREADED
    if (pInternalSocketManager->Flags.bSpawnThreadOnAccept)
    {
        /* create a semaphore with no free resources for which a host can wait to be signalled. */
        uStatus = OpcUa_P_Semaphore_Create(&pInternalSocketManager->pStartupSemaphore, 0, 1);
        OpcUa_GotoErrorIfBad(uStatus);

        pInternalSocketManager->pSocketManagers = OpcUa_P_Memory_Alloc(sizeof(OpcUa_InternalSocketManager*) * OPCUA_SOCKET_MAXMANAGERS);
        OpcUa_GotoErrorIfAllocFailed(pInternalSocketManager->pSocketManagers);
        OpcUa_MemSet(pInternalSocketManager->pSocketManagers, 0, sizeof(OpcUa_InternalSocketManager*) * OPCUA_SOCKET_MAXMANAGERS);
    }

    /* if multithreaded, create and start the server thread if the list is not the global list. */
    uStatus = OpcUa_P_Thread_Create(&pInternalSocketManager->pThread); /* make raw thread */
    OpcUa_GotoErrorIfBad(uStatus);

    uStatus = OpcUa_P_Thread_Start( pInternalSocketManager->pThread,
                                    OpcUa_P_SocketManager_ServerLoopThread,
                                    (OpcUa_Void*)pInternalSocketManager);
    OpcUa_GotoErrorIfBad(uStatus);
#endif /* OPCUA_MULTITHREADED */

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(pInternalSocketManager != OpcUa_Null)
    {
#if OPCUA_MULTITHREADED
        if(pInternalSocketManager->pThread != OpcUa_Null)
        {
            OpcUa_P_Thread_Delete(&pInternalSocketManager->pThread);
        }
        if(pInternalSocketManager->pSocketManagers != OpcUa_Null)
        {
            OpcUa_P_Memory_Free(pInternalSocketManager->pSocketManagers);
        }
        if(pInternalSocketManager->pStartupSemaphore != OpcUa_Null)
        {
            OpcUa_P_Semaphore_Delete(&pInternalSocketManager->pStartupSemaphore);
        }
#endif /* OPCUA_MULTITHREADED */
        if(pInternalSocketManager->pCookie != (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID)
        {
            OpcUa_P_RawSocket_Close(pInternalSocketManager->pCookie);
        }
        if(pInternalSocketManager->pSockets != OpcUa_Null)
        {
            if(pInternalSocketManager->pSockets[0].rawSocket != (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID)
            {
                OpcUa_P_RawSocket_Close(pInternalSocketManager->pSockets[0].rawSocket);
            }
            OpcUa_P_Memory_Free(pInternalSocketManager->pSockets);
        }
#if OPCUA_USE_SYNCHRONISATION
        if(pInternalSocketManager->pMutex != OpcUa_Null)
        {
            OpcUa_P_Mutex_Delete(&pInternalSocketManager->pMutex);
        }
#endif /* OPCUA_USE_SYNCHRONISATION */
        OpcUa_P_Memory_Free(pInternalSocketManager);
    }

    *a_pSocketManager = OpcUa_Null;

OpcUa_FinishErrorHandling;
}
/*============================================================================
 * OpcUa_P_OpenSSL_Random_Key_PSHA256_Derive
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_Random_Key_PSHA256_Derive(
    OpcUa_CryptoProvider* a_pProvider,
    OpcUa_ByteString      a_secret, /* clientnonce | servernonce, servernonce | clientnonce */
    OpcUa_ByteString      a_seed,
    OpcUa_Int32           a_keyLen, /* output len */
    OpcUa_Key*            a_pKey)
{
    OpcUa_P_OpenSSL_PSHA256_Ctx*pCtx            = OpcUa_Null;
    OpcUa_Byte*                 pBuffer         = OpcUa_Null;

    OpcUa_Int                   bufferlength;
    OpcUa_Int                   i;
    OpcUa_Int                   iterations;

    OpcUa_CryptoProviderConfig* pConfig         = OpcUa_Null;
    OpcUa_Int32                 keyLen          = 0;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "Random_Key_PSHA256_Derive");

    OpcUa_ReferenceParameter(a_pProvider);

    OpcUa_ReturnErrorIfArgumentNull(a_pProvider);
    OpcUa_ReturnErrorIfArgumentNull(a_secret.Data);
    OpcUa_ReturnErrorIfArgumentNull(a_seed.Data);
    OpcUa_ReturnErrorIfArgumentNull(a_pKey);

    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_DERIVED_OUTPUT_LEN)
    {
            uStatus = OpcUa_BadInvalidArgument;
            OpcUa_GotoErrorIfBad(uStatus);
    }

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

    a_pKey->Type = OpcUa_Crypto_KeyType_Random;

    /** start creating key **/

    pCtx = (OpcUa_P_OpenSSL_PSHA256_Ctx*)OpcUa_Null;

    iterations = keyLen/32 + (keyLen%32?1:0);
    bufferlength = iterations*32;

    pBuffer = (OpcUa_Byte *)OpcUa_P_Memory_Alloc(bufferlength * sizeof(OpcUa_Byte));

    pCtx = OpcUa_P_OpenSSL_PSHA256_Context_Create(a_secret.Data, a_secret.Length, a_seed.Data, a_seed.Length);

    for(i=0; i<iterations; i++)
    {
        /* SHA256 produces 32 Bytes of output for every iteration */
        uStatus = OpcUa_P_OpenSSL_PSHA256_Hash_Generate(pCtx, pBuffer + (i*32));
        OpcUa_GotoErrorIfBad(uStatus);
    }

    OpcUa_P_Memory_MemCpy(a_pKey->Key.Data, a_pKey->Key.Length, pBuffer, keyLen);

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

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

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

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

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

OpcUa_FinishErrorHandling;
}
/*============================================================================
 * OpcUa_P_OpenSSL_X509_LoadFromFile
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_X509_LoadFromFile(
    OpcUa_StringA               a_fileName,
    OpcUa_P_FileFormat          a_fileFormat,
    OpcUa_StringA               a_sPassword,        /* optional: just for OpcUa_PKCS12 */
    OpcUa_ByteString*           a_pCertificate)
{
    BIO*            pCertFile       = OpcUa_Null;
    X509*           pCertX509       = OpcUa_Null;
    PKCS12*         pPKCS12Cert     = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_LoadFromFile");

    /* check filename */
    if(OpcUa_P_String_strlen(a_fileName) < 1)
    {
        uStatus = OpcUa_BadInvalidArgument;
        OpcUa_GotoErrorIfBad(uStatus);
    }

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

    switch(a_fileFormat)
    {
    case OpcUa_Crypto_Encoding_DER:
        {

            pCertX509 = d2i_X509_bio(pCertFile,      /* sourcefile */
                                     (X509**)NULL);  /* target (if preallocated) */
            break;
        }
    case OpcUa_Crypto_Encoding_PEM:
        {

            pCertX509 = PEM_read_bio_X509(  pCertFile,          /* sourcefile */
                                            (X509**)OpcUa_Null, /* target (if preallocated) */
                                            OpcUa_Null,         /* password callback function */
                                            OpcUa_Null);        /* passphrase or callback data */
            break;
        }
    case OpcUa_Crypto_Encoding_PKCS12:
        {
            d2i_PKCS12_bio(pCertFile, &pPKCS12Cert);

            PKCS12_parse(pPKCS12Cert, a_sPassword, OpcUa_Null, &pCertX509, OpcUa_Null);

            if(pPKCS12Cert != OpcUa_Null)
            {
                PKCS12_free(pPKCS12Cert);
                /*OPENSSL_free(pPKCS12Cert);*/
            }

            break;
        }
    default:
        {
            BIO_free(pCertFile);
            return OpcUa_BadNotSupported;
        }
    }

    BIO_free(pCertFile);
    pCertFile = OpcUa_Null;

    if(pCertX509 == OpcUa_Null)
    {
        /* error in OpenSSL - maybe certificate file was corrupt */
        return OpcUa_Bad;
    }

    /* prepare container */
    memset(a_pCertificate, 0, sizeof(OpcUa_ByteString));

    /* get required length for conversion target buffer */
    a_pCertificate->Length = i2d_X509(  pCertX509,
                                            NULL);

    if(a_pCertificate->Length <= 0)
    {
        /* conversion to DER not possible */
        uStatus = OpcUa_Bad;
    }

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

    /* convert into DER */
    a_pCertificate->Length = i2d_X509(  pCertX509,
                                            &(a_pCertificate->Data));
    if(a_pCertificate->Length <= 0)
    {
        /* conversion to DER not possible */
        uStatus = OpcUa_Bad;
    }
    else
    {
        /* correct pointer incrementation by i2d_X509() */
        a_pCertificate->Data -= a_pCertificate->Length;
    }

    X509_free(pCertX509);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

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

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

    if(a_pCertificate->Data != OpcUa_Null)
    {
        OpcUa_P_Memory_Free(a_pCertificate->Data);
        a_pCertificate->Data = OpcUa_Null;
    }

    if(pCertFile != OpcUa_Null)
    {
        BIO_free(pCertFile);
    }

OpcUa_FinishErrorHandling;
}
/*============================================================================
 * OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create(
    OpcUa_CryptoProvider*       a_pProvider,
    OpcUa_Int32                 a_serialNumber,
    OpcUa_UInt32                a_validToInSec,
    OpcUa_Crypto_NameEntry*     a_pNameEntries,      /* will be used for issuer and subject thus it's selfigned cert */
    OpcUa_UInt                  a_nameEntriesCount,  /* will be used for issuer and subject thus it's selfigned cert */
    OpcUa_Key                   a_pSubjectPublicKey, /* EVP_PKEY* - type defines also public key algorithm */
    OpcUa_Crypto_Extension*     a_pExtensions,
    OpcUa_UInt                  a_extensionsCount,
    OpcUa_UInt                  a_signatureHashAlgorithm, /* EVP_sha1(),... */
    OpcUa_Key                   a_pIssuerPrivateKey, /* EVP_PKEY* - type defines also signature algorithm */
    OpcUa_ByteString*           a_pCertificate)
{
    OpcUa_UInt          i;

    X509_NAME*          pSubj               = OpcUa_Null;
    X509V3_CTX          ctx;
    const EVP_MD*       pDigest             = OpcUa_Null;

    X509*               pCert               = OpcUa_Null;
    EVP_PKEY*           pSubjectPublicKey   = OpcUa_Null;
    EVP_PKEY*           pIssuerPrivateKey   = OpcUa_Null;

    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_SelfSigned_Custom_Create");

    OpcUa_ReferenceParameter(a_pProvider);

    OpcUa_ReturnErrorIfArgumentNull(a_pNameEntries);
    OpcUa_ReturnErrorIfArgumentNull(a_pExtensions);
    OpcUa_ReturnErrorIfArgumentNull(a_pIssuerPrivateKey.Key.Data);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificate);

    if(a_pSubjectPublicKey.Type != OpcUa_Crypto_KeyType_Rsa_Public)
    {
        uStatus =  OpcUa_BadInvalidArgument;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(a_pIssuerPrivateKey.Type != OpcUa_Crypto_KeyType_Rsa_Private)
    {
        uStatus =  OpcUa_BadInvalidArgument;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    pSubjectPublicKey = d2i_PublicKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pSubjectPublicKey.Key.Data)),a_pSubjectPublicKey.Key.Length);
    if(pSubjectPublicKey == OpcUa_Null)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    pIssuerPrivateKey = d2i_PrivateKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pIssuerPrivateKey.Key.Data)),a_pIssuerPrivateKey.Key.Length);
    if(pIssuerPrivateKey == OpcUa_Null)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* create new certificate object */
    pCert = X509_new();
    if(pCert == OpcUa_Null)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set version of certificate (V3 since internal representation starts versioning from 0) */
    if(X509_set_version(pCert, 2L) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* generate a unique number for a serial number if none provided. */
    if(a_serialNumber == 0)
    {
        ASN1_INTEGER* pSerialNumber = X509_get_serialNumber(pCert);

        pSerialNumber->type   = V_ASN1_INTEGER;
        pSerialNumber->data   = OPENSSL_realloc(pSerialNumber->data, 16);
        pSerialNumber->length = 16;

        if(pSerialNumber->data == NULL || OpcUa_P_Guid_Create((OpcUa_Guid*)pSerialNumber->data) == NULL)
        {
            uStatus =  OpcUa_Bad;
            OpcUa_GotoErrorIfBad(uStatus);
        }
    }

    /* use the integer passed in - note the API should not be using a 32-bit integer - must fix sometime */
    else if(ASN1_INTEGER_set(X509_get_serialNumber(pCert), a_serialNumber) == 0)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* add key to the request */
    if(X509_set_pubkey(pCert, pSubjectPublicKey) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

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

    /* assign the subject name */
    pSubj = X509_NAME_new();
    if(!pSubj)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* create and add entries to subject name */
    for(i=0; i<a_nameEntriesCount; i++)
    {
        uStatus = OpcUa_P_OpenSSL_X509_Name_AddEntry(&pSubj, a_pNameEntries + i);
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set subject name in request */
    if(X509_set_subject_name(pCert, pSubj) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set name of issuer (CA) */
    if(X509_set_issuer_name(pCert, pSubj) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(!(X509_gmtime_adj(X509_get_notBefore(pCert), 0)))
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set ending time of the certificate */
    if(!(X509_gmtime_adj(X509_get_notAfter(pCert), a_validToInSec)))
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* add x509v3 extensions */
    X509V3_set_ctx(&ctx, pCert, pCert, OpcUa_Null, OpcUa_Null, 0);

    for(i=0; i<a_extensionsCount; i++)
    {
        uStatus = OpcUa_P_OpenSSL_X509_AddCustomExtension(&pCert, a_pExtensions+i, &ctx);
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* sign certificate with the CA private key */
    switch(a_signatureHashAlgorithm)
    {
    case OPCUA_P_SHA_160:
        pDigest = EVP_sha1();
        break;
    case OPCUA_P_SHA_224:
        pDigest = EVP_sha224();
        break;
    case OPCUA_P_SHA_256:
        pDigest = EVP_sha256();
        break;
    case OPCUA_P_SHA_384:
        pDigest = EVP_sha384();
        break;
    case OPCUA_P_SHA_512:
        pDigest = EVP_sha512();
        break;
    default:
        uStatus =  OpcUa_BadNotSupported;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(!(X509_sign(pCert, pIssuerPrivateKey, pDigest)))
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(X509_verify(pCert, pIssuerPrivateKey) <= 0)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

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

    if(pSubj != OpcUa_Null)
    {
        X509_NAME_free(pSubj);
        pSubj = OpcUa_Null;
    }

    /* prepare container */
    memset(a_pCertificate, 0, sizeof(OpcUa_ByteString));

    /* get required length for conversion target buffer */
    a_pCertificate->Length = i2d_X509(pCert, NULL);

    if(a_pCertificate->Length <= 0)
    {
        /* conversion to DER not possible */
        uStatus = OpcUa_Bad;
    }

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

    /* convert into DER */
    a_pCertificate->Length = i2d_X509(pCert, &(a_pCertificate->Data));
    if(a_pCertificate->Length <= 0)
    {
        /* conversion to DER not possible */
        uStatus = OpcUa_Bad;
    }
    else
    {
        /* correct pointer incrementation by i2d_X509() */
        a_pCertificate->Data -= a_pCertificate->Length;
    }

    X509_free(pCert);

OpcUa_ReturnStatusCode;

OpcUa_BeginErrorHandling;

    X509_free(pCert);

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

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

    if(pSubj != OpcUa_Null)
    {
        X509_NAME_free(pSubj);
    }

OpcUa_FinishErrorHandling;
}
Beispiel #15
0
/*============================================================================
 * OpcUa_P_ParseUrl
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_ParseUrl(  OpcUa_StringA   a_psUrl,
                                    OpcUa_StringA*  a_psIpAddress,
                                    OpcUa_UInt16*   a_puPort)
{
    OpcUa_StringA       sHostName         = OpcUa_Null;
    OpcUa_UInt32        uHostNameLength   = 0;

    OpcUa_CharA*        sPort             = OpcUa_Null;

    OpcUa_CharA*        pcCursor;

    OpcUa_Int           nIndex1           = 0;
    OpcUa_Int           nIpStart;

    struct addrinfo*    pAddrInfo         = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_Utilities, "P_ParseUrl");

    OpcUa_ReturnErrorIfArgumentNull(a_psUrl);
    OpcUa_ReturnErrorIfArgumentNull(a_psIpAddress);
    OpcUa_ReturnErrorIfArgumentNull(a_puPort);


    *a_psIpAddress = OpcUa_Null;

    /* check for // (end of protocol header) */
    pcCursor = strstr(a_psUrl, "//");

    if(pcCursor != OpcUa_Null)
    {
        /* begin of host address */
        pcCursor += 2;
        nIndex1 = (OpcUa_Int)(pcCursor - a_psUrl);
    }

    /* skip protocol prefix and store beginning of ip adress */
    nIpStart = nIndex1;

    /* skip host address (IPv6 address can contain colons!) */
    while(a_psUrl[nIndex1] != '/' && a_psUrl[nIndex1] != 0)
    {
        if(a_psUrl[nIndex1] == ':')
        {
            sPort = &a_psUrl[nIndex1 + 1];
            uHostNameLength = nIndex1 - nIpStart;
        }
        /* handle "opc.tcp://[::1]:4880/" */
        if(a_psUrl[nIndex1] == ']' && sPort != OpcUa_Null && a_psUrl[nIpStart] == '[')
        {
            nIpStart++;
            uHostNameLength = nIndex1 - nIpStart;
            sPort = OpcUa_Null;
            if(a_psUrl[nIndex1 + 1] == ':')
            {
                sPort = &a_psUrl[nIndex1 + 2];
            }
            break;
        }
        nIndex1++;
    }

    if(uHostNameLength == 0)
    {
        uHostNameLength = nIndex1 - nIpStart;
    }

    /* scan port */
    if(sPort != OpcUa_Null)
    {
        /* convert port */
        *a_puPort = (OpcUa_UInt16)OpcUa_P_CharAToInt(sPort);
    }
    else
    {
        /* return default port */
        *a_puPort = OPCUA_TCP_DEFAULT_PORT;
    }

    sHostName = (OpcUa_StringA)OpcUa_P_Memory_Alloc(uHostNameLength + 1);

    if(sHostName == NULL)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);
    }

    memcpy(sHostName, &a_psUrl[nIpStart], uHostNameLength);
    sHostName[uHostNameLength] = '\0';

    if(getaddrinfo(sHostName, NULL, NULL, &pAddrInfo))
    {
        /* hostname could not be resolved */
        pAddrInfo = NULL;
        OpcUa_GotoErrorWithStatus(OpcUa_BadHostUnknown);
    }

    if(pAddrInfo->ai_family == AF_INET)
    {
        struct sockaddr_in* pAddr = (struct sockaddr_in*)pAddrInfo->ai_addr;
        OpcUa_P_Memory_Free(sHostName);
        sHostName = OpcUa_P_Memory_Alloc(INET_ADDRSTRLEN);
        OpcUa_GotoErrorIfAllocFailed(sHostName);
        if(inet_ntop(AF_INET, (void*)&pAddr->sin_addr,
                     sHostName, INET_ADDRSTRLEN) == NULL)
        {
            OpcUa_GotoErrorWithStatus(OpcUa_BadInternalError);
        }
    }
    else if(pAddrInfo->ai_family == AF_INET6)
    {
        struct sockaddr_in6* pAddr = (struct sockaddr_in6*)pAddrInfo->ai_addr;
        OpcUa_P_Memory_Free(sHostName);
        sHostName = OpcUa_P_Memory_Alloc(INET6_ADDRSTRLEN);
        OpcUa_GotoErrorIfAllocFailed(sHostName);
        if(inet_ntop(AF_INET6, (void*)&pAddr->sin6_addr,
                     sHostName, INET6_ADDRSTRLEN) == NULL)
        {
            OpcUa_GotoErrorWithStatus(OpcUa_BadInternalError);
        }
        if(pAddr->sin6_scope_id)
        {
            char *pScopeAddress = OpcUa_P_Memory_Alloc(strlen(sHostName) + 12);
            OpcUa_GotoErrorIfAllocFailed(pScopeAddress);
            sprintf(pScopeAddress, "%s%%%u", sHostName, pAddr->sin6_scope_id);
            OpcUa_P_Memory_Free(sHostName);
            sHostName = pScopeAddress;
        }
    }
    else
    {
        OpcUa_GotoErrorWithStatus(OpcUa_BadInternalError);
    }

    *a_psIpAddress = sHostName;
    freeaddrinfo(pAddrInfo);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

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

    if(pAddrInfo != NULL)
    {
        freeaddrinfo(pAddrInfo);
    }

OpcUa_FinishErrorHandling;
}